[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#933511: partman-base: reformatting md raid 0.90 metadata does not delete metadata



The patch attached to this mail is better.

On Wed, 31 Jul 2019 at 14:12, Michael Hudson-Doyle <michael.hudson@ubuntu.com> wrote:
Source: partman-base
Severity: normal
Tags: d-i patch

Dear Maintainer,

As reported in

    https://bugs.launchpad.net/ubuntu/+source/partman-base/+bug/1828558

installing over a drive previously used as a md raid can leave a system
that does not boot.  I tried and failed to convince parted upstream this
was their bug (https://debbugs.gnu.org/cgi/bugreport.cgi?bug=36853) so
it probably makes sense to fix it in parted_server instead.

I'm attaching a WIP patch to this report. I'll probably upload something
like this to Ubuntu once I've tested it a bit.

Cheers,
mwh

-- System Information:
Debian Release: buster/sid
  APT prefers bionic-updates
  APT policy: (500, 'bionic-updates'), (500, 'bionic-security'), (500, 'bionic'), (400, 'bionic-proposed'), (100, 'bionic-backports')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.15.0-55-generic (SMP w/4 CPU cores)
Locale: LANG=en_NZ.UTF-8, LC_CTYPE=en_NZ.UTF-8 (charmap=UTF-8), LANGUAGE=en_NZ.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
diff --git a/Makefile.am b/Makefile.am
index f93bf8e..e8027ba 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -2,7 +2,8 @@ bin_PROGRAMS = parted_server parted_devices partmap
 bin_SCRIPTS = partman partman-command partman-commit
 
 parted_server_SOURCES = parted_server.c
-parted_server_LDADD = $(libparted_fs_resize_LIBS) $(libparted_LIBS)
+parted_server_CPPFLAGS = $(blkid_CFLAGS)
+parted_server_LDADD = $(libparted_fs_resize_LIBS) $(libparted_LIBS) $(blkid_LIBS)
 
 parted_devices_SOURCES = parted_devices.c
 parted_devices_LDADD = $(libparted_LIBS)
diff --git a/configure.ac b/configure.ac
index 987cc4d..3d081ff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,6 +7,7 @@ AC_DEFINE([_POSIX_C_SOURCE], [200809L], [Define the POSIX version])
 AC_PROG_CC
 
 PKG_CHECK_MODULES([libparted], [libparted])
+PKG_CHECK_MODULES([blkid], [blkid])
 
 AC_ARG_VAR([libparted_fs_resize_LIBS], [linker flags for libparted-fs-resize])
 AC_MSG_CHECKING([for libparted >= 3.1])
diff --git a/parted_server.c b/parted_server.c
index 41784b7..5c75684 100644
--- a/parted_server.c
+++ b/parted_server.c
@@ -15,6 +15,7 @@
 #include <ctype.h>
 #include <signal.h>
 #include <stdarg.h>
+#include <blkid.h>
 
 /**********************************************************************
    Logging
@@ -1360,6 +1361,61 @@ is_system_with_firmware_on_disk()
         return result;
 }
 
+/*
+ * wipe all superblocks libblkid knows about from a device
+ * (condensed from wipefs in util-linux)
+ */
+static int
+do_wipe(char *devname)
+{
+        blkid_probe pr = NULL;
+        int fd = -1;
+        int r = -1;
+
+        fd = open(devname, O_RDWR);
+
+        if (fd < 0) {
+                log("open(%s) failed errno %d", devname, errno);
+                goto error;
+        }
+
+        log("do_wipe open(%s), %d", devname, fd);
+
+
+        pr = blkid_new_probe();
+        if (!pr || blkid_probe_set_device(pr, fd, 0, 0) != 0) {
+                log("setting up probe failed");
+                goto error;
+        }
+
+        blkid_probe_enable_superblocks(pr, 1);
+        blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC |      /* return magic string and offset */
+                                          BLKID_SUBLKS_TYPE |           /* return superblock type */
+                                          BLKID_SUBLKS_BADCSUM);        /* accept bad checksums */
+
+        blkid_probe_enable_partitions(pr, 1);
+        blkid_probe_set_partitions_flags(pr, BLKID_PARTS_MAGIC |
+                                         BLKID_PARTS_FORCE_GPT);
+
+        while (blkid_do_probe(pr) == 0) {
+                char *type = "unknown";
+                if (blkid_probe_lookup_value(pr, "TYPE", &type, NULL) < 0)
+                        blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL);
+                log("wiping superblock of type %s", type);
+                if (blkid_do_wipe(pr, 0) != 0) {
+                        log("wiping failed");
+                }
+        }
+
+        fsync(fd);
+        r = 0;
+      error:
+        if (fd >= 0)
+                close(fd);
+        blkid_free_probe(pr);
+        return r;
+}
+
 void
 command_commit()
 {
@@ -1382,8 +1438,25 @@ command_commit()
         }
 
         open_out();
-        if (disk != NULL && named_is_changed(device_name))
-                ped_disk_commit(disk);
+        if (disk != NULL) {
+                /* ped_disk_clobber does not remove all superblock information
+                 * -- in particular it does not wipe mdraid 0.90 metadata,
+                 * which can lead to an unbootable system as in
+                 * https://bugs.launchpad.net/ubuntu/+source/partman-base/+bug/1828558.
+                 * parted upstream didn't think this was a bug so here we give
+                 * it a helping hand by using libblkid to wipe all superblocks. */
+                if (disk->needs_clobber) {
+                        log("command_commit: wiping superblocks from %s", dev->path);
+                        if (do_wipe(dev->path) != 0) {
+                                log("wiping superblocks from %s failed", dev->path);
+                        } else {
+                                log("wiping superblocks from %s succeeded", dev->path);
+                        }
+                }
+                if (named_is_changed(device_name)) {
+                        ped_disk_commit(disk);
+                }
+        }
         unchange_named(device_name);
         oprintf("OK\n");
 }

Reply to: