daemon: Call wipefs before mkfs to work around pathological behaviour in btrfs.

See: RHBZ#907554, http://www.spinics.net/lists/linux-btrfs/msg21197.html
This commit is contained in:
Richard W.M. Jones
2013-02-04 19:43:25 +00:00
parent 7e25e0780e
commit 72dd398679
6 changed files with 53 additions and 0 deletions

View File

@@ -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);

View File

@@ -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));

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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
*/
}