btrfs-progs: handle errors in btrfs_wipe_existing_sb
authorDavid Sterba <dsterba@suse.com>
Tue, 1 Sep 2015 14:00:12 +0000 (16:00 +0200)
committerDavid Sterba <dsterba@suse.com>
Wed, 2 Sep 2015 16:56:52 +0000 (18:56 +0200)
Failure during superblock wiping is not always a hard error as we're
going to overwrite it anyway but it may catch some errors earlier. The
error message is not very descriptive though, because we don't get back
much information from blkid.

Signed-off-by: David Sterba <dsterba@suse.com>
utils.c

diff --git a/utils.c b/utils.c
index 220c7d8..52791b5 100644 (file)
--- a/utils.c
+++ b/utils.c
@@ -798,40 +798,52 @@ err_nomem:
        return -ENOMEM;
 }
 
-static void btrfs_wipe_existing_sb(int fd)
+static int btrfs_wipe_existing_sb(int fd)
 {
        const char *off = NULL;
        size_t len = 0;
        loff_t offset;
        char buf[BUFSIZ];
-       int rc = 0;
+       int ret = 0;
        blkid_probe pr = NULL;
 
        pr = blkid_new_probe();
        if (!pr)
-               return;
+               return -1;
 
-       if (blkid_probe_set_device(pr, fd, 0, 0))
+       if (blkid_probe_set_device(pr, fd, 0, 0)) {
+               ret = -1;
                goto out;
+       }
 
-       rc = blkid_probe_lookup_value(pr, "SBMAGIC_OFFSET", &off, NULL);
-       if (!rc)
-               rc = blkid_probe_lookup_value(pr, "SBMAGIC", NULL, &len);
+       ret = blkid_probe_lookup_value(pr, "SBMAGIC_OFFSET", &off, NULL);
+       if (!ret)
+               ret = blkid_probe_lookup_value(pr, "SBMAGIC", NULL, &len);
 
-       if (rc || len == 0 || off == NULL)
+       if (ret || len == 0 || off == NULL) {
+               /*
+                * If lookup fails, the probe did not find any values, eg. for
+                * a file image or a loop device. Soft error.
+                */
+               ret = 1;
                goto out;
+       }
 
        offset = strtoll(off, NULL, 10);
        if (len > sizeof(buf))
                len = sizeof(buf);
 
        memset(buf, 0, len);
-       rc = pwrite(fd, buf, len, offset);
+       ret = pwrite(fd, buf, len, offset);
+       if (ret != len) {
+               fprintf(stderr, "ERROR: cannot wipe existing superblock\n");
+               ret = -1;
+       }
        fsync(fd);
 
 out:
        blkid_free_probe(pr);
-       return;
+       return ret;
 }
 
 int btrfs_prepare_device(int fd, char *file, int zero_end, u64 *block_count_ret,
@@ -885,7 +897,12 @@ int btrfs_prepare_device(int fd, char *file, int zero_end, u64 *block_count_ret,
                return 1;
        }
 
-       btrfs_wipe_existing_sb(fd);
+       ret = btrfs_wipe_existing_sb(fd);
+       if (ret < 0) {
+               fprintf(stderr, "ERROR: cannot wipe superblocks on '%s'\n",
+                               file);
+               return 1;
+       }
 
        *block_count_ret = block_count;
        return 0;