]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
repart: Rescan disk on failure if we create blkpg partitions on the fly
authorValentin David <me@valentindavid.com>
Thu, 12 Mar 2026 22:14:39 +0000 (23:14 +0100)
committerValentin David <me@valentindavid.com>
Tue, 12 May 2026 16:31:23 +0000 (18:31 +0200)
Since we did not write the partition table, then the created partitions
should get removed on error.

src/repart/repart.c

index 854ca644f7573adbc93d59ad0fa8119f8871989d..0e5ba58af2a697a8237b91742a88427cc6853787 100644 (file)
@@ -568,6 +568,8 @@ struct Context {
         bool defer_partitions_factory_reset;
 
         sd_varlink *link; /* If 'more' is used on the Varlink call, we'll send progress info over this link */
+
+        bool needs_rescan;
 };
 
 static const char *empty_mode_table[_EMPTY_MODE_MAX] = {
@@ -5132,6 +5134,8 @@ static int partition_target_prepare(
                         if (r < 0)
                                 return log_error_errno(r, "Failed to create new partition '%s': %m", part_node);
 
+                        context->needs_rescan = true;
+
                         dev_fd = open(part_node, O_RDWR|O_CLOEXEC|O_NOCTTY);
                         if (dev_fd < 0) {
                                 r = -errno;
@@ -8244,9 +8248,34 @@ static int context_find_esp_offset(Context *context, uint64_t *ret) {
         return 0;
 }
 
+static int context_partscan(Context *context) {
+        int capable, r;
+
+        assert(context);
+
+        context->needs_rescan = false;
+
+        capable = blockdev_partscan_enabled_fd(sym_fdisk_get_devfd(context->fdisk_context));
+        if (capable == -ENOTBLK)
+                log_debug("Not telling kernel to reread partition table, since we are not operating on a block device.");
+        else if (capable < 0)
+                return log_error_errno(capable, "Failed to check if block device supports partition scanning: %m");
+        else if (capable > 0) {
+                log_info("Informing kernel about changed partitions...");
+                (void) context_notify(context, PROGRESS_REREADING_TABLE, /* object= */ NULL, UINT_MAX);
+
+                r = reread_partition_table_fd(sym_fdisk_get_devfd(context->fdisk_context), /* flags= */ 0);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to reread partition table: %m");
+        } else
+                log_notice("Not telling kernel to reread partition table, because selected image does not support kernel partition block devices.");
+
+        return 0;
+}
+
 static int context_write_partition_table(Context *context) {
         _cleanup_(fdisk_unref_tablep) struct fdisk_table *original_table = NULL;
-        int capable, r;
+        int r;
 
         assert(context);
 
@@ -8292,46 +8321,43 @@ static int context_write_partition_table(Context *context) {
          * gaps between partitions, just to be sure. */
         r = context_wipe_and_discard(context);
         if (r < 0)
-                return r;
+                goto error;
 
         r = context_copy_blocks(context);
         if (r < 0)
-                return r;
+                goto error;
 
         r = context_mkfs(context);
         if (r < 0)
-                return r;
+                goto error;
 
         r = context_mangle_partitions(context);
         if (r < 0)
-                return r;
+                goto error;
 
         log_info("Writing new partition table.");
 
         (void) context_notify(context, PROGRESS_WRITING_TABLE, /* object= */ NULL, UINT_MAX);
 
         r = sym_fdisk_write_disklabel(context->fdisk_context);
-        if (r < 0)
-                return log_error_errno(r, "Failed to write partition table: %m");
-
-        capable = blockdev_partscan_enabled_fd(sym_fdisk_get_devfd(context->fdisk_context));
-        if (capable == -ENOTBLK)
-                log_debug("Not telling kernel to reread partition table, since we are not operating on a block device.");
-        else if (capable < 0)
-                return log_error_errno(capable, "Failed to check if block device supports partition scanning: %m");
-        else if (capable > 0) {
-                log_info("Informing kernel about changed partitions...");
-                (void) context_notify(context, PROGRESS_REREADING_TABLE, /* object= */ NULL, UINT_MAX);
+        if (r < 0) {
+                r = log_error_errno(r, "Failed to write partition table: %m");
+                goto error;
+        }
 
-                r = reread_partition_table_fd(sym_fdisk_get_devfd(context->fdisk_context), /* flags= */ 0);
-                if (r < 0)
-                        return log_error_errno(r, "Failed to reread partition table: %m");
-        } else
-                log_notice("Not telling kernel to reread partition table, because selected image does not support kernel partition block devices.");
+        r = context_partscan(context);
+        if (r < 0)
+                return r;
 
         log_info("Partition table written.");
 
         return 0;
+
+ error:
+        if (context->needs_rescan)
+                (void) context_partscan(context);
+
+        return r;
 }
 
 static int context_write_eltorito(Context *context) {