From c55b18f0d85f82c6c554d17ab214a64f9564600c Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Mon, 24 Mar 2008 21:54:38 -0400 Subject: [PATCH] make libparted poke the kernel when adding/deleting partitions Turns out that libparted is already using the right ioctl's mentioned in commit 6a2a1f2b7cc7b52b277aa9788a3a0bb280227441. So now we can correctly add/delete partitions even when other partitions on the same disk are busy. --- src/devkit-disks-device.c | 17 +++------------ src/job-create-partition.c | 20 +++-------------- src/job-delete-partition.c | 19 ++--------------- src/partutil.c | 53 +++++++++++++++++++++++++++------------------- src/partutil.h | 15 ++++++++----- 5 files changed, 49 insertions(+), 75 deletions(-) diff --git a/src/devkit-disks-device.c b/src/devkit-disks-device.c index 3a9a716..04b58ce 100644 --- a/src/devkit-disks-device.c +++ b/src/devkit-disks-device.c @@ -2676,12 +2676,14 @@ devkit_disks_device_delete_partition (DevkitDisksDevice *device, goto out; } +#if 0 /* see rant in devkit_disks_device_create_partition() */ if (devkit_disks_device_local_partitions_are_busy (enclosing_device)) { throw_error (context, DEVKIT_DISKS_DEVICE_ERROR_IS_BUSY, "A sibling partition is busy (TODO: addpart/delpart/partx to the rescue!)"); goto out; } +#endif if (!devkit_disks_damon_local_check_auth (device->priv->daemon, pk_caller, @@ -3385,20 +3387,7 @@ devkit_disks_device_create_partition (DevkitDisksDevice *device, goto out; } - /* TODO: Fuck, the kernel is dumb and BLKRRPART won't work if any of the partitions - * are busy. The solution, I think, involves is judicious use of addpart(8) / - * delpart(8) / partx(8) to spoonfeed the kernel this information. - * - * Until this is fixed, for now bail out if any of the partitions on the disk are busy. - */ - if (devkit_disks_device_local_partitions_are_busy (device)) { - throw_error (context, DEVKIT_DISKS_DEVICE_ERROR_IS_BUSY, - "A partition on the device is busy (TODO: addpart/delpart/partx to the rescue!)"); - goto out; - } - - - /* TODO: check there are no partitions in the requested slice */ + /* partutil.c / libparted will check there are no partitions in the requested slice */ if (!devkit_disks_damon_local_check_auth (device->priv->daemon, pk_caller, diff --git a/src/job-create-partition.c b/src/job-create-partition.c index 3064096..f0c5c29 100644 --- a/src/job-create-partition.c +++ b/src/job-create-partition.c @@ -44,7 +44,6 @@ int main (int argc, char **argv) { int n; - int fd; int ret; const char *device; char **options; @@ -93,6 +92,7 @@ main (int argc, char **argv) g_print ("progress: %d %d -1 partitioning\n", 0, 2); + /* libparted will update the kernel's partition table map */ if (part_add_partition ((char *) device, offset, size, @@ -102,7 +102,8 @@ main (int argc, char **argv) strlen (label) > 0 ? label : NULL, flags, -1, - -1)) { + -1, + TRUE)) { /* now clear out file system signatures in the newly created * partition... Unless it's an extended partition! */ @@ -126,21 +127,6 @@ main (int argc, char **argv) g_printerr ("job-create-partition-size: %lld\n", out_size); } - /* either way, we've got this far.. signal the kernel to reread the partition table */ - fd = open (device, O_RDONLY); - if (fd < 0) { - g_printerr ("cannot open %s (for BLKRRPART): %m\n", device); - ret = 1; - goto out; - } - if (ioctl (fd, BLKRRPART) != 0) { - close (fd); - g_printerr ("BLKRRPART ioctl failed for %s: %m\n", device); - ret = 1; - goto out; - } - close (fd); - out: g_strfreev (flags); return ret; diff --git a/src/job-delete-partition.c b/src/job-delete-partition.c index 039aa48..2fd84ac 100644 --- a/src/job-delete-partition.c +++ b/src/job-delete-partition.c @@ -43,7 +43,6 @@ int main (int argc, char **argv) { - int fd; int ret; const char *device; const char *partition_device; @@ -94,7 +93,8 @@ main (int argc, char **argv) g_print ("progress: %d %d -1 partitioning\n", num_erase_passes, num_erase_passes + 2); - if (part_del_partition ((char *) device, offset)) { + /* libparted will update the kernel's partition table map */ + if (part_del_partition ((char *) device, offset, TRUE)) { /* zero the contents of what was the _partition_ * @@ -108,21 +108,6 @@ main (int argc, char **argv) } } - /* either way, we've got this far.. signal the kernel to reread the partition table */ - fd = open (device, O_RDONLY); - if (fd < 0) { - g_printerr ("cannot open %s (for BLKRRPART): %m\n", device); - ret = 1; - goto out; - } - if (ioctl (fd, BLKRRPART) != 0) { - close (fd); - g_printerr ("BLKRRPART ioctl failed for %s: %m\n", device); - ret = 1; - goto out; - } - close (fd); - out: g_free (erase); return ret; diff --git a/src/partutil.c b/src/partutil.c index 5b7ac6f..032d94c 100644 --- a/src/partutil.c +++ b/src/partutil.c @@ -1263,7 +1263,8 @@ part_add_change_partition (char *device_file, guint64 new_start, guint64 new_size, guint64 *out_start, guint64 *out_size, char *type, char *label, char **flags, - int geometry_hps, int geometry_spt) + int geometry_hps, int geometry_spt, + gboolean poke_kernel) { int n; gboolean is_change; @@ -1650,14 +1651,17 @@ try_change_again: */ part = NULL; - /* use commit_to_dev rather than just commit to avoid - * libparted sending BLKRRPART to the kernel - we want to do - * this ourselves... - */ - if (ped_disk_commit_to_dev (disk) == 0) { - DEBUG ("ped_disk_commit_to_dev() failed"); - goto out_ped_constraint; - } + if (poke_kernel) { + if (ped_disk_commit (disk) == 0) { + DEBUG ("ped_disk_commit() failed"); + goto out_ped_disk; + } + } else { + if (ped_disk_commit_to_dev (disk) == 0) { + DEBUG ("ped_disk_commit_to_dev() failed"); + goto out_ped_constraint; + } + } DEBUG ("committed to disk"); res = TRUE; @@ -1690,14 +1694,16 @@ part_add_partition (char *device_file, guint64 start, guint64 size, guint64 *out_start, guint64 *out_size, char *type, char *label, char **flags, - int geometry_hps, int geometry_spt) + int geometry_hps, int geometry_spt, + gboolean poke_kernel) { return part_add_change_partition (device_file, start, size, 0, 0, out_start, out_size, type, label, flags, - geometry_hps, geometry_spt); + geometry_hps, geometry_spt, + poke_kernel); } gboolean @@ -1713,11 +1719,12 @@ part_change_partition (char *device_file, new_start, new_size, out_start, out_size, type, label, flags, - geometry_hps, geometry_spt); + geometry_hps, geometry_spt, + FALSE); } gboolean -part_del_partition (char *device_file, guint64 offset) +part_del_partition (char *device_file, guint64 offset, gboolean poke_kernel) { gboolean ret; PedDevice *device; @@ -1797,15 +1804,17 @@ part_del_partition (char *device_file, guint64 offset) goto out_ped_disk; } - /* use commit_to_dev rather than just commit to avoid - * libparted sending BLKRRPART to the kernel - we want to do - * this ourselves... - */ - - if (ped_disk_commit_to_dev (disk) == 0) { - DEBUG ("ped_disk_commit_to_dev() failed"); - goto out_ped_disk; - } + if (poke_kernel) { + if (ped_disk_commit (disk) == 0) { + DEBUG ("ped_disk_commit() failed"); + goto out_ped_disk; + } + } else { + if (ped_disk_commit_to_dev (disk) == 0) { + DEBUG ("ped_disk_commit_to_dev() failed"); + goto out_ped_disk; + } + } DEBUG ("committed to disk"); ret = TRUE; diff --git a/src/partutil.h b/src/partutil.h index 88f0288..122ad9c 100644 --- a/src/partutil.h +++ b/src/partutil.h @@ -311,6 +311,8 @@ gboolean part_create_partition_table (char *device, PartitionScheme * @label: the partition label as defined in part_table_entry_get_label() * @geometry_hps: heads-per-sector used for LBA<->CHS conversions * @geometry_spt: sectors-per-track used for LBA<->CHS conversions + * @poke_kernel: whether to update the kernels in-memory representation of + * the partition table * * Adds a new partition to a disk. * @@ -342,9 +344,9 @@ gboolean part_create_partition_table (char *device, PartitionScheme * To create an MSDOS extended partition table in a MSDOS partition * table, simply pass 0x05, 0x0f or 0x85 as the partition type. * - * In order for changes to take effect, the caller needs to poke the - * OS kernel himself to make it reload the partition table. It is not - * automatically done by this function. + * Unless @poke_kernel is set to #TRUE, in order for changes to take + * effect, the caller needs to poke the OS kernel himself to make it + * reload the partition table. * * NOTE: After calling this function you need to discard any partition table * obtained with part_table_load_from_disk() since the in-memory data structure @@ -356,7 +358,8 @@ gboolean part_add_partition (char *device, guint64 start, guint64 size, guint64 *out_start, guint64 *out_size, char *type, char *label, char **flags, - int geometry_hps, int geometry_spt); + int geometry_hps, int geometry_spt, + gboolean poke_kernel); /** * part_change_partition: @@ -413,6 +416,8 @@ gboolean part_change_partition (char *device_file, * part_del_partition: * @device: name of device file for entire disk, e.g. /dev/sda * @offset: offset of somewhere within the partition to delete, in bytes + * @poke_kernel: whether to update the kernels in-memory representation of + * the partition table * * Deletes a partition. Just pass the offset of the partition. If you * delete an extended partition all logical partitions will be deleted @@ -424,7 +429,7 @@ gboolean part_change_partition (char *device_file, * * Returns: TRUE if the operation was succesful, otherwise FALSE */ -gboolean part_del_partition (char *device, guint64 offset); +gboolean part_del_partition (char *device, guint64 offset, gboolean poke_kernel); #endif /* PARTUTIL_H */ -- 2.7.4