diff options
Diffstat (limited to 'make-bcache.c')
-rw-r--r-- | make-bcache.c | 77 |
1 files changed, 55 insertions, 22 deletions
diff --git a/make-bcache.c b/make-bcache.c index 30b49638..9e55fac1 100644 --- a/make-bcache.c +++ b/make-bcache.c @@ -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,18 +168,42 @@ 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, uint16_t nr_in_set, uint16_t nr_this_dev) { 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); } @@ -223,7 +249,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); } @@ -252,7 +278,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); } @@ -313,7 +345,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; @@ -326,6 +358,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' }, @@ -353,7 +386,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; @@ -365,14 +398,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; @@ -381,7 +414,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); } @@ -393,12 +426,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); } @@ -414,15 +447,15 @@ 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, - data_offset, set_uuid, false, - ncache_devices, i); + writeback, discard, wipe_bcache, + cache_replacement_policy, data_offset, + set_uuid, false, ncache_devices, i); for (i = 0; i < nbacking_devices; i++) write_sb(backing_devices[i], block_size, bucket_size, - writeback, discard, cache_replacement_policy, - data_offset, set_uuid, true, - nbacking_devices, i); + writeback, discard, wipe_bcache, + cache_replacement_policy, data_offset, + set_uuid, true, nbacking_devices, i); return 0; } |