diff --git a/daemon/btrfs.c b/daemon/btrfs.c index 2830509c1..c100d185f 100644 --- a/daemon/btrfs.c +++ b/daemon/btrfs.c @@ -193,6 +193,9 @@ do_mkfs_btrfs (char *const *devices, ADD_ARG (argv, i, NULL); + for (j = 0; j < nr_devices; ++j) + wipe_device_before_mkfs (devices[j]); + r = commandv (NULL, &err, argv); if (r == -1) { reply_with_error ("%s: %s", devices[0], err); diff --git a/daemon/daemon.h b/daemon/daemon.h index 5f095a168..44fb9abe8 100644 --- a/daemon/daemon.h +++ b/daemon/daemon.h @@ -186,6 +186,9 @@ extern int lv_canonical (const char *device, char **ret); /*-- in lvm-filter.c --*/ extern void copy_lvm (void); +/*-- in zero.c --*/ +extern void wipe_device_before_mkfs (const char *device); + /*-- in proto.c --*/ extern void main_loop (int sock) __attribute__((noreturn)); diff --git a/daemon/ext2.c b/daemon/ext2.c index 12bf856cd..e4548d6f6 100644 --- a/daemon/ext2.c +++ b/daemon/ext2.c @@ -306,6 +306,8 @@ do_mke2journal (int blocksize, const char *device) char blocksize_s[32]; snprintf (blocksize_s, sizeof blocksize_s, "%d", blocksize); + wipe_device_before_mkfs (device); + r = command (NULL, &err, str_mke2fs, "-F", "-O", "journal_dev", "-b", blocksize_s, device, NULL); @@ -332,6 +334,8 @@ do_mke2journal_L (int blocksize, const char *label, const char *device) char blocksize_s[32]; snprintf (blocksize_s, sizeof blocksize_s, "%d", blocksize); + wipe_device_before_mkfs (device); + r = command (NULL, &err, str_mke2fs, "-F", "-O", "journal_dev", "-b", blocksize_s, "-L", label, @@ -353,6 +357,8 @@ do_mke2journal_U (int blocksize, const char *uuid, const char *device) char blocksize_s[32]; snprintf (blocksize_s, sizeof blocksize_s, "%d", blocksize); + wipe_device_before_mkfs (device); + r = command (NULL, &err, str_mke2fs, "-F", "-O", "journal_dev", "-b", blocksize_s, "-U", uuid, @@ -379,6 +385,8 @@ do_mke2fs_J (const char *fstype, int blocksize, const char *device, char jdev[len+32]; snprintf (jdev, len+32, "device=%s", journal); + wipe_device_before_mkfs (device); + r = command (NULL, &err, str_mke2fs, "-F", "-t", fstype, "-J", jdev, "-b", blocksize_s, device, NULL); @@ -410,6 +418,8 @@ do_mke2fs_JL (const char *fstype, int blocksize, const char *device, char jdev[len+32]; snprintf (jdev, len+32, "device=LABEL=%s", label); + wipe_device_before_mkfs (device); + r = command (NULL, &err, str_mke2fs, "-F", "-t", fstype, "-J", jdev, "-b", blocksize_s, device, NULL); @@ -435,6 +445,8 @@ do_mke2fs_JU (const char *fstype, int blocksize, const char *device, char jdev[len+32]; snprintf (jdev, len+32, "device=UUID=%s", uuid); + wipe_device_before_mkfs (device); + r = command (NULL, &err, str_mke2fs, "-F", "-t", fstype, "-J", jdev, "-b", blocksize_s, device, NULL); @@ -1128,6 +1140,8 @@ do_mke2fs (const char *device, /* 0 */ ADD_ARG (argv, i, NULL); + wipe_device_before_mkfs (device); + r = commandv (NULL, &err, argv); if (r == -1) { reply_with_error ("%s: %s", device, err); diff --git a/daemon/mkfs.c b/daemon/mkfs.c index 1f8bcb2ed..ff0f2fc3d 100644 --- a/daemon/mkfs.c +++ b/daemon/mkfs.c @@ -184,6 +184,8 @@ do_mkfs (const char *fstype, const char *device, int blocksize, ADD_ARG (argv, i, device); ADD_ARG (argv, i, NULL); + wipe_device_before_mkfs (device); + r = commandv (NULL, &err, argv); if (r == -1) { reply_with_error ("%s: %s: %s", fstype, device, err); diff --git a/daemon/swap.c b/daemon/swap.c index bf57ab31b..83f4d7c4d 100644 --- a/daemon/swap.c +++ b/daemon/swap.c @@ -91,6 +91,8 @@ do_mkswap (const char *device, const char *label, const char *uuid) ADD_ARG (argv, i, device); ADD_ARG (argv, i, NULL); + wipe_device_before_mkfs (device); + r = commandv (NULL, &err, argv); if (r == -1) { reply_with_error ("%s: %s", device, err); diff --git a/daemon/zero.c b/daemon/zero.c index aaec7eb0d..6d3efa82e 100644 --- a/daemon/zero.c +++ b/daemon/zero.c @@ -337,3 +337,32 @@ do_zero_free_space (const char *dir) return 0; } + +/* Internal function used to wipe disks before we do 'mkfs'-type + * operations on them. For the rationale see RHBZ#889888 and + * RHBZ#907554. + * + * Note this is really destructive, so only call it just before doing + * the 'mkfs' operation (ie. after doing as much pre-checking as + * possible). Otherwise you could end up with a 'mkfs' operation + * failing with an error but still wiping data. + */ +void +wipe_device_before_mkfs (const char *device) +{ + int r; + + r = command (NULL, NULL, "wipefs", "-a", "--force", device, NULL); + if (r == 0) + return; + + r = command (NULL, NULL, "wipefs", "-a", device, NULL); + if (r == 0) + return; + + /* XXX We could fall back to overwriting bits of disk here, but if + * they don't have working wipefs, it seems unlikely they are using + * btrfs which is what mostly causes this problem. See: + * http://www.spinics.net/lists/linux-btrfs/msg21197.html + */ +}