Bug#933511: partman-base: reformatting md raid 0.90 metadata does not delete metadata
The patch attached to this mail is better.
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: