]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
make-bcache: Prevent stray superblocks
authorGabriel <g2p.code@gmail.com>
Sat, 17 Aug 2013 16:56:50 +0000 (18:56 +0200)
committerGabriel <g2p.code@gmail.com>
Sun, 1 Sep 2013 10:38:11 +0000 (12:38 +0200)
Fail if the device has any leftover superblock or partition table label.

Add a --wipe-bcache flag to overwrite bcache superblocks and recommend
wipefs for non-bcache superblocks.

Once the device is safe to write, always zero immediately before the
bcache superblock.

Make sure errors go to stderr.  Use pkg-config.

Makefile
make-bcache.c
probe-bcache.c

index 10ec79c64e8740bb2ef2154881619ece099c5d2a..edb4133a319d0422870ce78226824c0b7c6833e0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -16,9 +16,10 @@ install: make-bcache probe-bcache bcache-super-show
 clean:
        $(RM) -f make-bcache probe-bcache bcache-super-show bcache-test *.o
 
-bcache-test: LDLIBS += -lm -lssl -lcrypto
-make-bcache: LDLIBS += -luuid
+bcache-test: LDLIBS += `pkg-config --libs openssl`
+make-bcache: LDLIBS += `pkg-config --libs uuid blkid`
+make-bcache: CFLAGS += `pkg-config --cflags uuid blkid`
 make-bcache: bcache.o
-probe-bcache: LDLIBS += -luuid
-bcache-super-show: LDLIBS += -luuid
+probe-bcache: LDLIBS += `pkg-config --libs uuid`
+bcache-super-show: LDLIBS += `pkg-config --libs uuid`
 bcache-super-show: bcache.o
index 9c038a8958dfc6cc8f6bbce9059c1a8e94e3ddbd..27d49eb90b9ed40b4a53dcab12b120a6cf64fecd 100644 (file)
@@ -8,6 +8,7 @@
 #define __USE_FILE_OFFSET64
 #define _XOPEN_SOURCE 600
 
+#include <blkid.h>
 #include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -76,19 +77,19 @@ unsigned hatoi_validate(const char *s, const char *msg)
        uint64_t v = hatoi(s);
 
        if (v & (v - 1)) {
-               printf("%s must be a power of two\n", msg);
+               fprintf(stderr, "%s must be a power of two\n", msg);
                exit(EXIT_FAILURE);
        }
 
        v /= 512;
 
        if (v > USHRT_MAX) {
-               printf("%s too large\n", msg);
+               fprintf(stderr, "%s too large\n", msg);
                exit(EXIT_FAILURE);
        }
 
        if (!v) {
-               printf("%s too small\n", msg);
+               fprintf(stderr, "%s too small\n", msg);
                exit(EXIT_FAILURE);
        }
 
@@ -143,7 +144,8 @@ ssize_t read_string_list(const char *buf, const char * const list[])
 
 void usage()
 {
-       printf("Usage: make-bcache [options] device\n"
+       fprintf(stderr,
+                  "Usage: make-bcache [options] device\n"
               "        -C, --cache             Format a cache device\n"
               "        -B, --bdev              Format a backing device\n"
               "        -b, --bucket            bucket size\n"
@@ -166,17 +168,41 @@ const char * const cache_replacement_policies[] = {
 };
 
 static void write_sb(char *dev, unsigned block_size, unsigned bucket_size,
-                    bool writeback, bool discard,
+                    bool writeback, bool discard, bool wipe_bcache,
                     unsigned cache_replacement_policy,
                     uint64_t data_offset,
                     uuid_t set_uuid, bool bdev)
 {
        int fd;
-       char uuid_str[40], set_uuid_str[40];
+       char uuid_str[40], set_uuid_str[40], zeroes[SB_START] = {0};
        struct cache_sb sb;
+       blkid_probe pr;
 
        if ((fd = open(dev, O_RDWR|O_EXCL)) == -1) {
-               printf("Can't open dev %s: %s\n", dev, strerror(errno));
+               fprintf(stderr, "Can't open dev %s: %s\n", dev, strerror(errno));
+               exit(EXIT_FAILURE);
+       }
+
+       if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb))
+               exit(EXIT_FAILURE);
+
+       if (!memcmp(sb.magic, bcache_magic, 16) && !wipe_bcache) {
+               fprintf(stderr, "Already a bcache device on %s, "
+                       "overwrite with --wipe-bcache\n", dev);
+               exit(EXIT_FAILURE);
+       }
+
+       if (!(pr = blkid_new_probe()))
+               exit(EXIT_FAILURE);
+       if (blkid_probe_set_device(pr, fd, 0, 0))
+               exit(EXIT_FAILURE);
+       /* enable ptable probing; superblock probing is enabled by default */
+       if (blkid_probe_enable_partitions(pr, true))
+               exit(EXIT_FAILURE);
+       if (!blkid_do_probe(pr)) {
+               /* XXX wipefs doesn't know how to remove partition tables */
+               fprintf(stderr, "Device %s already has a non-bcache superblock, "
+                               "remove it using wipefs and wipefs -a\n", dev);
                exit(EXIT_FAILURE);
        }
 
@@ -221,7 +247,7 @@ static void write_sb(char *dev, unsigned block_size, unsigned bucket_size,
                sb.first_bucket         = (23 / sb.bucket_size) + 1;
 
                if (sb.nbuckets < 1 << 7) {
-                       printf("Not enough buckets: %ju, need %u\n",
+                       fprintf(stderr, "Not enough buckets: %ju, need %u\n",
                               sb.nbuckets, 1 << 7);
                        exit(EXIT_FAILURE);
                }
@@ -250,7 +276,13 @@ static void write_sb(char *dev, unsigned block_size, unsigned bucket_size,
 
        sb.csum = csum_set(&sb);
 
-       if (pwrite(fd, &sb, sizeof(sb), SB_SECTOR << 9) != sizeof(sb)) {
+       /* Zero start of disk */
+       if (pwrite(fd, zeroes, SB_START, 0) != SB_START) {
+               perror("write error\n");
+               exit(EXIT_FAILURE);
+       }
+       /* Write superblock */
+       if (pwrite(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) {
                perror("write error\n");
                exit(EXIT_FAILURE);
        }
@@ -311,7 +343,7 @@ int main(int argc, char **argv)
        char *backing_devices[argc];
 
        unsigned block_size = 0, bucket_size = 1024;
-       int writeback = 0, discard = 0;
+       int writeback = 0, discard = 0, wipe_bcache = 0;
        unsigned cache_replacement_policy = 0;
        uint64_t data_offset = BDEV_DATA_START_DEFAULT;
        uuid_t set_uuid;
@@ -324,6 +356,7 @@ int main(int argc, char **argv)
                { "bucket",             1, NULL,        'b' },
                { "block",              1, NULL,        'w' },
                { "writeback",          0, &writeback,  1 },
+               { "wipe-bcache",        0, &wipe_bcache,        1 },
                { "discard",            0, &discard,    1 },
                { "cache_replacement_policy", 1, NULL, 'p' },
                { "data_offset",        1, NULL,        'o' },
@@ -351,7 +384,7 @@ int main(int argc, char **argv)
 #if 0
                case 'U':
                        if (uuid_parse(optarg, sb.uuid)) {
-                               printf("Bad uuid\n");
+                               fprintf(stderr, "Bad uuid\n");
                                exit(EXIT_FAILURE);
                        }
                        break;
@@ -363,14 +396,14 @@ int main(int argc, char **argv)
                case 'o':
                        data_offset = atoll(optarg);
                        if (data_offset < BDEV_DATA_START_DEFAULT) {
-                               printf("Bad data offset; minimum %d sectors\n",
+                               fprintf(stderr, "Bad data offset; minimum %d sectors\n",
                                       BDEV_DATA_START_DEFAULT);
                                exit(EXIT_FAILURE);
                        }
                        break;
                case 'u':
                        if (uuid_parse(optarg, set_uuid)) {
-                               printf("Bad uuid\n");
+                               fprintf(stderr, "Bad uuid\n");
                                exit(EXIT_FAILURE);
                        }
                        break;
@@ -379,7 +412,7 @@ int main(int argc, char **argv)
                        break;
                case 1:
                        if (bdev == -1) {
-                               printf("Please specify -C or -B\n");
+                               fprintf(stderr, "Please specify -C or -B\n");
                                exit(EXIT_FAILURE);
                        }
 
@@ -391,12 +424,12 @@ int main(int argc, char **argv)
                }
 
        if (!ncache_devices && !nbacking_devices) {
-               printf("Please supply a device\n");
+               fprintf(stderr, "Please supply a device\n");
                usage();
        }
 
        if (bucket_size < block_size) {
-               printf("Bucket size cannot be smaller than block size\n");
+               fprintf(stderr, "Bucket size cannot be smaller than block size\n");
                exit(EXIT_FAILURE);
        }
 
@@ -412,12 +445,14 @@ int main(int argc, char **argv)
 
        for (i = 0; i < ncache_devices; i++)
                write_sb(cache_devices[i], block_size, bucket_size,
-                        writeback, discard, cache_replacement_policy,
+                        writeback, discard, wipe_bcache,
+                        cache_replacement_policy,
                         data_offset, set_uuid, false);
 
        for (i = 0; i < nbacking_devices; i++)
                write_sb(backing_devices[i], block_size, bucket_size,
-                        writeback, discard, cache_replacement_policy,
+                        writeback, discard, wipe_bcache,
+                        cache_replacement_policy,
                         data_offset, set_uuid, true);
 
        return 0;
index caff7b6522a8a6337c4e00e4ce3714b48d0bd8c4..e1ad61467c0acf54035b4134633f009ec4530281 100644 (file)
@@ -52,7 +52,7 @@ int main(int argc, char **argv)
                        continue;
 
 
-               if (pread(fd, &sb, sizeof(sb), 4096) != sizeof(sb))
+               if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb))
                        continue;
 
                if (memcmp(sb.magic, bcache_magic, 16))