[Parted-commits] GNU Parted Official Repository: Changes to 'master'
Jim Meyering
meyering at alioth.debian.org
Fri Apr 30 14:33:00 UTC 2010
bootstrap.conf | 1
libparted/arch/linux.c | 81 ++++++++++++++--------------------
tests/t4100-dvh-partition-limits.sh | 7 ++
tests/t4100-msdos-partition-limits.sh | 10 +++-
4 files changed, 51 insertions(+), 48 deletions(-)
New commits:
commit 1611f6e9c09d0168f36939e8d22f404cfd9a1f2e
Author: Jim Meyering <meyering at redhat.com>
Date: Fri Apr 30 15:59:14 2010 +0200
tests: avoid root-only/XFS limit test failure on 32-bit system
* tests/t4100-msdos-partition-limits.sh: Due to an inherent XFS
limitation on 32-bit systems, this test would fail a set-up
file creation step for simulated sector sizes of 4K and up.
Skip this test in those cases.
Upon dd failure, propagate its diagnostic to output, to make this
sort of problem easier to diagnose.
* tests/t4100-dvh-partition-limits.sh: Likewise.
diff --git a/tests/t4100-dvh-partition-limits.sh b/tests/t4100-dvh-partition-limits.sh
index bf269e7..1016077 100755
--- a/tests/t4100-dvh-partition-limits.sh
+++ b/tests/t4100-dvh-partition-limits.sh
@@ -25,6 +25,13 @@ privileges_required_=1
require_xfs_
ss=$sector_size_
+# On a 32-bit system, we must skip this test when $ss >= 4096.
+# Otherwise, due to an inherent 32-bit-XFS limit, dd would fail to
+# create the file of size > 16TiB
+if test $(uname -m) != x86_64; then
+ test $ss -le 2048 || exit 77
+fi
+
####################################################
# Create and mount a file system capable of dealing with >=2TB files.
# We must be able to create a file with an apparent length of 2TB or larger.
diff --git a/tests/t4100-msdos-partition-limits.sh b/tests/t4100-msdos-partition-limits.sh
index b63a534..db98f2e 100755
--- a/tests/t4100-msdos-partition-limits.sh
+++ b/tests/t4100-msdos-partition-limits.sh
@@ -25,6 +25,13 @@ privileges_required_=1
require_xfs_
ss=$sector_size_
+# On a 32-bit system, we must skip this test when $ss >= 4096.
+# Otherwise, due to an inherent 32-bit-XFS limit, dd would fail to
+# create the file of size > 16TiB
+if test $(uname -m) != x86_64; then
+ test $ss -le 2048 || exit 77
+fi
+
####################################################
# Create and mount a file system capable of dealing with >=2TB files.
# We must be able to create a file with an apparent length of 2TB or larger.
@@ -59,7 +66,8 @@ do_mkpart()
start_sector=$1
end_sector=$2
# echo '********' $(echo $end_sector - $start_sector + 1 |bc)
- dd if=/dev/zero of=$dev bs=$ss count=2k seek=$end_sector 2> /dev/null &&
+ dd if=/dev/zero of=$dev bs=$ss count=2k seek=$end_sector 2> dd-err ||
+ { cat dd-err 1>&2; return 1; }
parted -s $dev mklabel $table_type &&
parted -s $dev mkpart p xfs ${start_sector}s ${end_sector}s
}
commit 0f850220b3f26bb969a1a7ff78dc550691a89566
Author: Jim Meyering <meyering at redhat.com>
Date: Fri Apr 30 12:28:16 2010 +0200
libparted: avoid race in informing the kernel of partition table changes
When sync'ing a partition table change using the latest
code, sometimes we'd get an unwarranted failure like this:
Warning: Partition(s) 1 on /dev/sdd have been written, but we
have been unable to inform the kernel of the change, probably because
it/they are in use. As a result, the old partition(s) will remain in
use. You should reboot now before making further changes.
To be precise, when running the partition-resizing root-only test
in a loop:
for i in $(seq 240); do make -C tests check VERBOSE=yes \
TESTS=t3000-resize-fs.sh >& log.$i && printf . || echo $i $?; done
I would typically see about 50% of them fail on a Fedora 13 system.
It was obvious that this was due to a race condition when I found that
modifying that tests' parted...resize invocation to go via strace changed
the timing enough to make the test pass every time.
The fix is to retry the partition-removal step upon any EBUSY failure,
currently for up to 1 second (retrying up to 100 times, sleeping 10ms
after each failure).
* libparted/arch/linux.c (_disk_sync_part_table): Allocate "ok" using
calloc, now that its initial values matter.
Retry each removal upon EBUSY-failure.
* bootstrap.conf (gnulib_modules): Use gnulib's usleep module.
diff --git a/bootstrap.conf b/bootstrap.conf
index 6c9287d..4ca51a7 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -58,6 +58,7 @@ gnulib_modules="
unlink
update-copyright
useless-if-before-free
+ usleep
vc-list-files
version-etc-fsf
warnings
diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
index 8116c76..73a8e6f 100644
--- a/libparted/arch/linux.c
+++ b/libparted/arch/linux.c
@@ -2452,17 +2452,35 @@ _disk_sync_part_table (PedDisk* disk)
if (lpn < 0)
return 0;
int ret = 0;
- int *ok = ped_malloc(sizeof(int) * lpn);
+ int *ok = calloc (lpn, sizeof *ok);
if (!ok)
return 0;
int *errnums = ped_malloc(sizeof(int) * lpn);
if (!errnums)
goto cleanup;
- int i;
- for (i = 1; i <= lpn; i++) {
- ok[i - 1] = _blkpg_remove_partition (disk, i);
- errnums[i - 1] = errno;
+ /* Attempt to remove each and every partition, retrying for
+ up to max_sleep_seconds upon any failure due to EBUSY. */
+ unsigned int sleep_microseconds = 10000;
+ unsigned int max_sleep_seconds = 1;
+ unsigned int n_sleep = (max_sleep_seconds
+ * 1000000 / sleep_microseconds);
+ int i;
+ for (i = 0; i < n_sleep; i++) {
+ if (i)
+ usleep (sleep_microseconds);
+ bool busy = false;
+ int j;
+ for (j = 0; j < lpn; j++) {
+ if (!ok[j]) {
+ ok[j] = _blkpg_remove_partition (disk, j + 1);
+ errnums[j] = errno;
+ if (!ok[j] && errnums[j] == EBUSY)
+ busy = true;
+ }
+ }
+ if (!busy)
+ break;
}
for (i = 1; i <= lpn; i++) {
commit 9acc5869985c8616066af4825f52fb6c474f63dd
Author: Jim Meyering <meyering at redhat.com>
Date: Fri Apr 30 12:01:08 2010 +0200
libparted: variable renaming, minor "goto" reorg
* libparted/arch/linux.c (_disk_sync_part_table): Rename local array:
s/rets/ok/, for readability.
Use only a single label, "cleanup:", rather than two: free_rets
and free_errnums.
diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
index d8f3393..8116c76 100644
--- a/libparted/arch/linux.c
+++ b/libparted/arch/linux.c
@@ -2452,29 +2452,29 @@ _disk_sync_part_table (PedDisk* disk)
if (lpn < 0)
return 0;
int ret = 0;
- int *rets = ped_malloc(sizeof(int) * lpn);
- if (!rets)
+ int *ok = ped_malloc(sizeof(int) * lpn);
+ if (!ok)
return 0;
int *errnums = ped_malloc(sizeof(int) * lpn);
if (!errnums)
- goto free_rets;
+ goto cleanup;
int i;
for (i = 1; i <= lpn; i++) {
- rets[i - 1] = _blkpg_remove_partition (disk, i);
+ ok[i - 1] = _blkpg_remove_partition (disk, i);
errnums[i - 1] = errno;
}
for (i = 1; i <= lpn; i++) {
const PedPartition *part = ped_disk_get_partition (disk, i);
if (part) {
- if (!rets[i - 1] && errnums[i - 1] == EBUSY) {
+ if (!ok[i - 1] && errnums[i - 1] == EBUSY) {
struct hd_geometry geom;
unsigned long long length = 0;
/* get start and length of existing partition */
char *dev_name = _device_get_part_path (disk->dev, i);
if (!dev_name)
- goto free_errnums;
+ goto cleanup;
int fd = open (dev_name, O_RDONLY);
if (fd == -1
|| ioctl (fd, HDIO_GETGEO, &geom)
@@ -2487,14 +2487,14 @@ _disk_sync_part_table (PedDisk* disk)
if (fd != -1)
close (fd);
free (dev_name);
- goto free_errnums;
+ goto cleanup;
}
free (dev_name);
length /= disk->dev->sector_size;
close (fd);
if (geom.start == part->geom.start
&& length == part->geom.length)
- rets[i - 1] = 1;
+ ok[i - 1] = 1;
/* If the new partition is unchanged and the
existing one was not removed because it was
in use, then reset the error flag and do not
@@ -2509,7 +2509,7 @@ _disk_sync_part_table (PedDisk* disk)
PED_EXCEPTION_RETRY_CANCEL,
_("Failed to add partition %d (%s)"),
i, strerror (errno));
- goto free_errnums;
+ goto cleanup;
}
}
}
@@ -2517,12 +2517,12 @@ _disk_sync_part_table (PedDisk* disk)
char *bad_part_list = NULL;
/* now warn about any errors */
for (i = 1; i <= lpn; i++) {
- if (rets[i - 1] || errnums[i - 1] == ENXIO)
+ if (ok[i - 1] || errnums[i - 1] == ENXIO)
continue;
if (bad_part_list == NULL) {
bad_part_list = malloc (lpn * 5);
if (!bad_part_list)
- goto free_errnums;
+ goto cleanup;
bad_part_list[0] = 0;
}
sprintf (bad_part_list + strlen (bad_part_list), "%d, ", i);
@@ -2543,10 +2543,9 @@ _disk_sync_part_table (PedDisk* disk)
ret = 1;
free (bad_part_list);
}
- free_errnums:
+ cleanup:
free (errnums);
- free_rets:
- free (rets);
+ free (ok);
return ret;
}
commit 1223b9fc07859cb619c80dc057bd05458f9b5669
Author: Jim Meyering <meyering at redhat.com>
Date: Fri Apr 30 11:45:51 2010 +0200
libparted: remove now-worse-than-useless _kernel_reread_part_table
Now that we're using BLKPG properly, there's no point in using the
less-functional BLKRRPART ioctl to make the kernel reread the partition
table.
More importantly, this function would fail when any partition is in
use, in spite of our having carefully vetted them via BLKPG ioctls.
* libparted/arch/linux.c (_kernel_reread_part_table): Remove function.
(linux_disk_commit): Don't call it.
diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
index 988fde7..d8f3393 100644
--- a/libparted/arch/linux.c
+++ b/libparted/arch/linux.c
@@ -2760,34 +2760,6 @@ _dm_reread_part_table (PedDisk* disk)
#endif
static int
-_kernel_reread_part_table (PedDevice* dev)
-{
- LinuxSpecific* arch_specific = LINUX_SPECIFIC (dev);
- int retry_count = 9;
-
- sync();
- while (ioctl (arch_specific->fd, BLKRRPART)) {
- retry_count--;
- sync();
- if (retry_count == 3)
- sleep(1); /* Pause to allow system to settle */
-
- if (!retry_count) {
- ped_exception_throw (
- PED_EXCEPTION_WARNING,
- PED_EXCEPTION_IGNORE,
- _("WARNING: the kernel failed to re-read the partition "
- "table on %s (%s). As a result, it may not "
- "reflect all of your changes until after reboot."),
- dev->path, strerror (errno));
- return 0;
- }
- }
-
- return 1;
-}
-
-static int
_have_blkpg ()
{
static int have_blkpg = -1;
@@ -2825,8 +2797,6 @@ linux_disk_commit (PedDisk* disk)
ok = 0;
}
- if (!_kernel_reread_part_table (disk->dev))
- ok = 0;
return ok;
}
More information about the Parted-commits
mailing list