diff -Nru partman-base-192ubuntu1.1/debian/changelog partman-base-192ubuntu1.2/debian/changelog --- partman-base-192ubuntu1.1/debian/changelog 2019-07-29 22:18:37.000000000 +0000 +++ partman-base-192ubuntu1.2/debian/changelog 2019-08-06 00:04:16.000000000 +0000 @@ -1,3 +1,10 @@ +partman-base (192ubuntu1.2) bionic; urgency=medium + + * Move superblock wiping code from command_new_label to command_commit, as + the disk is not supposed to be written to until the latter is called. + + -- Michael Hudson-Doyle Tue, 06 Aug 2019 12:04:16 +1200 + partman-base (192ubuntu1.1) bionic; urgency=medium * parted_server.c: Wipe all known superblocks from device in diff -Nru partman-base-192ubuntu1.1/parted_server.c partman-base-192ubuntu1.2/parted_server.c --- partman-base-192ubuntu1.1/parted_server.c 2019-07-29 22:18:37.000000000 +0000 +++ partman-base-192ubuntu1.2/parted_server.c 2019-08-06 00:04:16.000000000 +0000 @@ -1361,6 +1361,61 @@ 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() { @@ -1383,8 +1438,25 @@ } 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"); } @@ -1865,61 +1937,6 @@ oprintf("OK\n"); } -/* - * 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 | O_EXCL); - - 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_new_label() { @@ -1943,12 +1960,6 @@ enough to change the partition table (i.e. `disk'). */ set_disk_named(device_name, NULL); set_device_named(device_name, NULL); - log("command_new_label: wiping %s", device); - if (do_wipe(device) != 0) { - log("wiping superblocks from %s failed", device); - } else { - log("wiping superblocks from %s succeeded", device); - } dev = ped_device_get(device); free(device); if (NULL == dev)