[PATCH 2/2] Improve BLKPG error checking

Phillip Susi psusi at cfl.rr.com
Tue Mar 30 19:11:53 UTC 2010


This patch cleans up the BLKPG code that the previous patch put back
to perform proper error checking and in the event that some partitions
are in use, they can not be modified in the running kernel using BLKPG.
Warn the user that this is the case and advise them to reboot, just like
we do when BLKRRPART fails for the same reason, unless the partition in
question is unchanged.
---
 libparted/arch/linux.c |   85 +++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 73 insertions(+), 12 deletions(-)

diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
index 0344a99..db7f841 100644
--- a/libparted/arch/linux.c
+++ b/libparted/arch/linux.c
@@ -2415,7 +2415,9 @@ _device_get_partition_range(PedDevice* dev)
  * Sync the partition table in two step process:
  * 1. Remove all of the partitions from the kernel's tables, but do not attempt
  *    removal of any partition for which the corresponding ioctl call fails.
- * 2. Add all the partitions that we hold in disk.
+ * 2. Add all the partitions that we hold in disk, throwing a warning
+ *    if we cannot because step 1 failed to remove it and it is not being
+ *    added back with the same start and length.
  *
  * To achieve this two step process we must calculate the minimum number of
  * maximum possible partitions between what linux supports and what the label
@@ -2441,10 +2443,13 @@ _disk_sync_part_table (PedDisk* disk)
          * */
         if(lpn < 0)
                 return 0;
-
+        int ret = 0;
         int *rets = ped_malloc(sizeof(int) * lpn);
+        if (!rets)
+                return 0;
         int *errnums = ped_malloc(sizeof(int) * lpn);
-        int ret = 1;
+        if (!errnums)
+                goto free_rets;
         int i;
 
         for (i = 1; i <= lpn; i++) {
@@ -2455,21 +2460,77 @@ _disk_sync_part_table (PedDisk* disk)
         for (i = 1; i <= lpn; i++) {
                 const PedPartition *part = ped_disk_get_partition (disk, i);
                 if (part) {
-                        /* busy... so we won't (can't!) disturb ;)  Prolly
-                         * doesn't matter anyway, because users shouldn't be
-                         * changing mounted partitions anyway...
-                         */
-                        if (!rets[i - 1] && errnums[i - 1] == EBUSY)
-                                        continue;
+                        if (!rets[i - 1] && errnums[i - 1] == EBUSY) {
+                                struct hd_geometry geom;
+                                int fd;
+                                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;
+                                fd = open (dev_name, O_RDONLY);
+                                free (dev_name);
+                                if (fd == -1 ||
+                                    ioctl (fd, HDIO_GETGEO, &geom) ||
+                                    ioctl (fd, BLKGETSIZE64, &length)) {
+                                        ped_exception_throw (
+                                                             PED_EXCEPTION_BUG,
+                                                             PED_EXCEPTION_CANCEL,
+                                                             _("Unable to determine the size and length of %s."),
+                                                             dev_name);
+                                        if( fd != -1 )
+                                                close (fd);
+                                        goto free_errnums;
+                                }
+                                length /= disk->dev->sector_size;
+                                close (fd);
+                                if (geom.start == part->geom.start &&
+                                    length == part->geom.length)
+                                        rets[i - 1] = 1;
+                                /* if the new partition is unchanged and the exiting
+                                   one was not removed because it was in use, then
+                                   reset the error flag and skip adding it
+                                   since it is already there */
+                                continue;
+                        }
 
                         /* add the (possibly modified or new) partition */
-                        if (!_blkpg_add_partition (disk, part))
-                                ret = 0;
+                        if (!_blkpg_add_partition (disk, part)) {
+                                ped_exception_throw (
+                                        PED_EXCEPTION_ERROR,
+                                        PED_EXCEPTION_RETRY_CANCEL,
+                                        _("Failed to add partition %i (%s)"),
+                                        i, strerror (errno));
+                                goto free_errnums;
+                        }
                 }
         }
 
-        free (rets);
+        char *parts = ped_malloc (lpn * 5);
+        if (!parts)
+                goto free_errnums;
+        parts[0] = 0;
+        /* now warn about any errors */
+        for (i = 1; i <= lpn; i++)
+                if (!rets[i - 1] && errnums[i - 1] != ENXIO)
+                        sprintf (parts + strlen (parts), "%i, ", i);
+        if (parts[0]) {
+                parts[strlen (parts) - 2] = 0;
+                ped_exception_throw (
+                        PED_EXCEPTION_WARNING,
+                        PED_EXCEPTION_IGNORE,
+                        _("Partition(s) %s on %s could not be modified, probably "
+                          "because it/they is/are in use.  As a result, the old partition(s) "
+                          "will remain in use until after reboot. You should reboot "
+                          "now before making further changes."),
+                        parts, disk->dev->path);
+        }
+        free (parts);
+        ret = 1;
+ free_errnums:
         free (errnums);
+ free_rets:
+        free (rets);
         return ret;
 }
 
-- 
1.6.3.3


--------------070105040404010604020208
Content-Type: text/x-patch; name="0001-Put-back-BLKPG-ioctls.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="0001-Put-back-BLKPG-ioctls.patch"



More information about the parted-devel mailing list