[parted-devel] [PATCH] arch: Fix race between systemd and parted command

Gulam Mohamed gulam.mohamed at oracle.com
Thu Sep 26 21:33:59 BST 2024


When parted commands like print, delete and others along with create
command, are run continuously, at some point of time a race has been
noticed between the create command and systemd.

The parted create command when tries to sync the partition table by calling
"_disk_sync_part_table()" function, it will try to fetch the start and
length of the partition. For this, it will try to open the sysfs entry
of the partition (for example /sys/block/loop0/loop0p1/start).

At the same time, if systemd calls rescan_partitions, then the sysfs
entries will disapper as these partitions will be removed and added.

Now, since the parted create command is trying to open the same sysfs
entry to get the start and length, it will fail when systemd removes the
partition  and hence the parted command thinks that this is a new
partition and will try to add the existing partition again by calling
BLKPG_ADD_PARTITION ioctl. At kernel level, the kernel ioctl code will
check for the overlap. As the partition was already existing, it will
return EBUSY to the userspace.

This is causing the parted command to throw the below exception:

"Error: Partition(s) 1 on /dev/loop276070 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."

This can be fixed by retrying to open the sysfs entry of the partition
device with few retries, if the open call fails.

Signed-off-by: Gulam Mohamed <gulam.mohamed at oracle.com>
---
 libparted/arch/linux.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c
index ccbba8656bc7..375e36cdd5d0 100644
--- a/libparted/arch/linux.c
+++ b/libparted/arch/linux.c
@@ -2735,6 +2735,12 @@ _sysfs_ull_entry_from_part(PedPartition const* part, const char *entry,
 {
         char path[128];
         char *part_name = _device_get_part_path (part->disk->dev, part->num);
+        bool ok = false;
+        FILE *fp = NULL;
+        unsigned int sleep_microseconds = 10000;
+        unsigned int max_sleep_seconds = 1;
+        unsigned int n_sleep = (max_sleep_seconds
+                                * 1000000 / sleep_microseconds);
         if (!part_name)
                 return false;
 
@@ -2744,12 +2750,16 @@ _sysfs_ull_entry_from_part(PedPartition const* part, const char *entry,
         free(part_name);
         if (r < 0 || r >= sizeof(path))
                 return false;
-
-        FILE *fp = fopen(path, "r");
+        do {
+                fp = fopen(path, "r");
+                if (fp)
+                        break;
+                usleep (sleep_microseconds);
+        } while(n_sleep--);
         if (!fp)
                 return false;
 
-        bool ok = fscanf(fp, "%llu", val) == 1;
+        ok = fscanf(fp, "%llu", val) == 1;
         fclose(fp);
 
         return ok;
-- 
2.43.5




More information about the parted-devel mailing list