From e13d21ade75401f944cbbb7438f3e569bdfaf247 Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Sat, 28 Mar 2015 23:21:33 -0700 Subject: [PATCH] Major refactoring, add new settings to bcacheadm format --- .gitignore | 2 +- Makefile | 2 +- bcache.c | 236 ++++++---------------------- bcache.h | 17 +- bcacheadm-format.c | 376 +++++++++++++++++++++++++++++++++++++++++++++ bcacheadm.c | 270 +------------------------------- bcacheadm.h | 7 + 7 files changed, 443 insertions(+), 467 deletions(-) create mode 100644 bcacheadm-format.c create mode 100644 bcacheadm.h diff --git a/.gitignore b/.gitignore index 7dcf732..427b03e 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,4 @@ install-sh ltmain.sh m4 missing -.Apple* +include diff --git a/Makefile b/Makefile index 60abbd8..7d022cb 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ bcache.o: CFLAGS += `pkg-config --cflags uuid blkid` bcacheadm.o: CFLAGS += `pkg-config --cflags uuid blkid libnih` bcacheadm: LDLIBS += `pkg-config --libs uuid blkid libnih` -bcacheadm: bcache.o +bcacheadm: bcacheadm.o bcacheadm-format.o bcache.o probe-bcache.o: CFLAGS += `pkg-config --cflags uuid blkid` probe-bcache: LDLIBS += `pkg-config --libs uuid blkid` diff --git a/bcache.c b/bcache.c index e84771d..e2de70b 100644 --- a/bcache.c +++ b/bcache.c @@ -48,6 +48,13 @@ const char * const csum_types[] = { NULL }; +const char * const error_actions[] = { + "continue", + "readonly", + "panic", + NULL +}; + const char * const bdev_cache_mode[] = { "writethrough", "writeback", @@ -150,11 +157,8 @@ ssize_t read_string_list_or_die(const char *opt, const char * const list[], const char *msg) { ssize_t v = read_string_list(opt, list); - if (v < 0) { - fprintf(stderr, "Bad %s %s\n", msg, opt); - exit(EXIT_FAILURE); - - } + if (v < 0) + die("Bad %s %s", msg, opt); return v; } @@ -391,8 +395,7 @@ static uint64_t bch_checksum_update(unsigned type, uint64_t crc, const void *dat case BCH_CSUM_CRC64: return bch_crc64_update(crc, data, len); default: - fprintf(stderr, "Unknown checksum type %u\n", type); - exit(EXIT_FAILURE); + die("Unknown checksum type %u", type); } } @@ -447,27 +450,21 @@ unsigned hatoi_validate(const char *s, const char *msg) { uint64_t v = hatoi(s); - if (v & (v - 1)) { - fprintf(stderr, "%s must be a power of two\n", msg); - exit(EXIT_FAILURE); - } + if (v & (v - 1)) + die("%s must be a power of two", msg); v /= 512; - if (v > USHRT_MAX) { - fprintf(stderr, "%s too large\n", msg); - exit(EXIT_FAILURE); - } + if (v > USHRT_MAX) + die("%s too large\n", msg); - if (!v) { - fprintf(stderr, "%s too small\n", msg); - exit(EXIT_FAILURE); - } + if (!v) + die("%s too small\n", msg); return v; } -static void do_write_sb(int fd, struct cache_sb *sb) +void do_write_sb(int fd, struct cache_sb *sb) { char zeroes[SB_START] = {0}; size_t bytes = ((void *) __bset_bkey_last(sb)) - (void *) sb; @@ -487,8 +484,8 @@ static void do_write_sb(int fd, struct cache_sb *sb) close(fd); } -void write_backingdev_sb(int fd, unsigned block_size, unsigned *bucket_sizes, - unsigned mode, uint64_t data_offset, const char *label, +void write_backingdev_sb(int fd, unsigned block_size, unsigned mode, + uint64_t data_offset, const char *label, uuid_le user_uuid, uuid_le set_uuid) { char uuid_str[40], set_uuid_str[40]; @@ -531,170 +528,37 @@ void write_backingdev_sb(int fd, unsigned block_size, unsigned *bucket_sizes, do_write_sb(fd, &sb); } -int dev_open(const char *dev, bool wipe_bcache) +int dev_open(const char *dev) { - struct cache_sb sb; blkid_probe pr; int fd; - char err[MAX_PATH]; - if ((fd = open(dev, O_RDWR|O_EXCL)) == -1) { - sprintf(err, "Can't open dev %s: %s\n", dev, strerror(errno)); - goto err; - } - - if (pread(fd, &sb, sizeof(sb), SB_START) != sizeof(sb)) { - sprintf(err, "Failed to read superblock"); - goto err; - } + if ((fd = open(dev, O_RDWR|O_EXCL)) == -1) + die("Can't open dev %s: %s\n", dev, strerror(errno)); - if (!memcmp(&sb.magic, &BCACHE_MAGIC, 16) && !wipe_bcache) { - sprintf(err, "Already a bcache device on %s, " - "overwrite with --wipe-bcache\n", dev); - goto err; - } + if (!(pr = blkid_new_probe())) + die("Failed to create a new probe"); + if (blkid_probe_set_device(pr, fd, 0, 0)) + die("failed to set probe to device"); - if (!(pr = blkid_new_probe())) { - sprintf(err, "Failed to create a new probe"); - goto err; - } - if (blkid_probe_set_device(pr, fd, 0, 0)) { - sprintf(err, "failed to set probe to device"); - goto err; - } /* enable ptable probing; superblock probing is enabled by default */ - if (blkid_probe_enable_partitions(pr, true)) { - sprintf(err, "Failed to enable partitions on probe"); - goto err; - } - if (!blkid_do_probe(pr)) { + if (blkid_probe_enable_partitions(pr, true)) + die("Failed to enable partitions on probe"); + + if (!blkid_do_probe(pr)) /* XXX wipefs doesn't know how to remove partition tables */ - sprintf(err, "Device %s already has a non-bcache superblock, " - "remove it using wipefs and wipefs -a\n", dev); - goto err; - } + die("Device %s already has a non-bcache superblock, " + "remove it using wipefs and wipefs -a\n", dev); return fd; - - err: - fprintf(stderr, "dev_open failed with: %s", err); - exit(EXIT_FAILURE); } -void write_cache_sbs(int *fds, struct cache_sb *sb, - unsigned block_size, unsigned *bucket_sizes, - int num_bucket_sizes, unsigned btree_node_size) -{ - char uuid_str[40], set_uuid_str[40]; - size_t i; - - if (!btree_node_size) { - btree_node_size = 512; - - for (i = 0; i < num_bucket_sizes; i++) - btree_node_size = min(btree_node_size, - bucket_sizes[i]); - } - - sb->offset = SB_SECTOR; - sb->version = BCACHE_SB_VERSION_CDEV_V3; - sb->magic = BCACHE_MAGIC; - sb->block_size = block_size; - sb->u64s = bch_journal_buckets_offset(sb); - - /* - * don't have a userspace crc32c implementation handy, just always use - * crc64 - */ - SET_CACHE_SB_CSUM_TYPE(sb, BCH_CSUM_CRC64); - - for (i = 0; i < sb->nr_in_set; i++) { - struct cache_member *m = sb->members + i; - - if (num_bucket_sizes <= 1) { - m->bucket_size = bucket_sizes[0]; - } else { - if (!bucket_sizes[i]) { - printf("No bucket size specified for cache %zu," - " using the default of %u", - i, bucket_sizes[0]); - m->bucket_size = bucket_sizes[0]; - } else { - m->bucket_size = bucket_sizes[i]; - } - } - - m->nbuckets = getblocks(fds[i]) / m->bucket_size; - m->first_bucket = (23 / m->bucket_size) + 1; - - if (m->nbuckets < 1 << 7) { - fprintf(stderr, "Not enough buckets: %llu, need %u\n", - m->nbuckets, 1 << 7); - exit(EXIT_FAILURE); - } - } - - for (i = 0; i < sb->nr_in_set; i++) { - struct cache_member *m = sb->members + i; - - SET_CACHE_BTREE_NODE_SIZE(sb, btree_node_size); - - - sb->disk_uuid = m->uuid; - sb->nr_this_dev = i; - - sb->csum = csum_set(sb, CACHE_SB_CSUM_TYPE(sb)); - - uuid_unparse(sb->disk_uuid.b, uuid_str); - uuid_unparse(sb->user_uuid.b, set_uuid_str); - printf("UUID: %s\n" - "Set UUID: %s\n" - "version: %u\n" - "nbuckets: %llu\n" - "block_size: %u\n" - "bucket_size: %u\n" - "nr_in_set: %u\n" - "nr_this_dev: %u\n" - "first_bucket: %u\n", - uuid_str, set_uuid_str, - (unsigned) sb->version, - m->nbuckets, - sb->block_size, - m->bucket_size, - sb->nr_in_set, - sb->nr_this_dev, - m->first_bucket); - - do_write_sb(fds[i], sb); - } -} - -void next_cache_device(struct cache_sb *sb, - unsigned replication_set, - int tier, - unsigned replacement_policy, - bool discard) -{ - struct cache_member *m = sb->members + sb->nr_in_set; - - SET_CACHE_REPLICATION_SET(m, replication_set); - SET_CACHE_TIER(m, tier); - SET_CACHE_REPLACEMENT(m, replacement_policy); - SET_CACHE_DISCARD(m, discard); - uuid_generate(m->uuid.b); - - sb->nr_in_set++; -} - -unsigned get_blocksize(const char *path) +unsigned get_blocksize(const char *path, int fd) { struct stat statbuf; - if (stat(path, &statbuf)) { - fprintf(stderr, "Error statting %s: %s\n", - path, strerror(errno)); - exit(EXIT_FAILURE); - } + if (fstat(fd, &statbuf)) + die("Error statting %s: %s", path, strerror(errno)); if (S_ISBLK(statbuf.st_mode)) { /* check IO limits: @@ -710,17 +574,9 @@ unsigned get_blocksize(const char *path) * we want to use logical_block_size. */ unsigned int logical_block_size; - int fd = open(path, O_RDONLY); + if (ioctl(fd, BLKSSZGET, &logical_block_size)) + die("ioctl(%s, BLKSSZGET) failed: %m", path); - if (fd < 0) { - fprintf(stderr, "open(%s) failed: %m\n", path); - exit(EXIT_FAILURE); - } - if (ioctl(fd, BLKSSZGET, &logical_block_size)) { - fprintf(stderr, "ioctl(%s, BLKSSZGET) failed: %m\n", path); - exit(EXIT_FAILURE); - } - close(fd); return logical_block_size / 512; } @@ -734,10 +590,8 @@ long strtoul_or_die(const char *p, size_t max, const char *msg) { errno = 0; long v = strtol(p, NULL, 10); - if (errno || v < 0 || v >= max) { - fprintf(stderr, "Invalid %s %zi\n", msg, v); - exit(EXIT_FAILURE); - } + if (errno || v < 0 || v >= max) + die("Invalid %s %zi", msg, v); return v; } @@ -767,8 +621,7 @@ static void show_super_common(struct cache_sb *sb, bool force_csum) printf("ok\n"); } else { printf("bad magic\n"); - fprintf(stderr, "Invalid superblock (bad magic)\n"); - exit(2); + die("Invalid superblock (bad magic)"); } printf("sb.first_sector\t\t%ju", (uint64_t) sb->offset); @@ -776,8 +629,7 @@ static void show_super_common(struct cache_sb *sb, bool force_csum) printf(" [match]\n"); } else { printf(" [expected %ds]\n", SB_SECTOR); - fprintf(stderr, "Invalid superblock (bad sector)\n"); - exit(2); + die("Invalid superblock (bad sector)"); } printf("sb.csum\t\t\t%ju", (uint64_t) sb->csum); @@ -789,10 +641,8 @@ static void show_super_common(struct cache_sb *sb, bool force_csum) printf(" [match]\n"); } else { printf(" [expected %" PRIX64 "]\n", expected_csum); - if (force_csum) { - fprintf(stderr, "Corrupt superblock (bad csum)\n"); - exit(2); - } + if (force_csum) + die("Corrupt superblock (bad csum)"); } printf("sb.version\t\t%ju", (uint64_t) sb->version); diff --git a/bcache.h b/bcache.h index 597bcee..e5ab8ae 100644 --- a/bcache.h +++ b/bcache.h @@ -54,6 +54,7 @@ typedef __s64 s64; extern const char * const cache_state[]; extern const char * const replacement_policies[]; extern const char * const csum_types[]; +extern const char * const error_actions[]; extern const char * const bdev_cache_mode[]; extern const char * const bdev_state[]; extern const char * const set_attr[]; @@ -70,13 +71,11 @@ uint64_t bch_checksum(unsigned, const void *, size_t); uint64_t getblocks(int); uint64_t hatoi(const char *); unsigned hatoi_validate(const char *, const char *); -void write_backingdev_sb(int, unsigned, unsigned *, unsigned, uint64_t, +void do_write_sb(int, struct cache_sb *); +void write_backingdev_sb(int, unsigned, unsigned, uint64_t, const char *, uuid_le, uuid_le); -int dev_open(const char *, bool); -void write_cache_sbs(int *, struct cache_sb *, unsigned, - unsigned *, int, unsigned); -void next_cache_device(struct cache_sb *, unsigned, int, unsigned, bool); -unsigned get_blocksize(const char *); +int dev_open(const char *); +unsigned get_blocksize(const char *, int); long strtoul_or_die(const char *, size_t, const char *); void show_super_backingdev(struct cache_sb *, bool); @@ -109,4 +108,10 @@ char *device_set_failed(const char *dev_uuid); bch_checksum(type, start, end - start); \ }) +#define die(arg, ...) \ +do { \ + fprintf(stderr, arg "\n", ##__VA_ARGS__); \ + exit(EXIT_FAILURE); \ +} while (0) + #endif diff --git a/bcacheadm-format.c b/bcacheadm-format.c new file mode 100644 index 0000000..e2bc425 --- /dev/null +++ b/bcacheadm-format.c @@ -0,0 +1,376 @@ +/* + * Authors: Kent Overstreet + * Gabriel de Perthuis + * Jacob Malevich + * + * GPLv2 + */ + +#if 0 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "bcache.h" +#include "bcacheadm.h" + +static struct cache_opts { + int fd; + const char *dev; + unsigned bucket_size; + unsigned tier; + unsigned replacement_policy; + unsigned replication_set; + uint64_t filesystem_size; +} cache_devices[MAX_DEVS]; + +static struct backingdev_opts { + int fd; + const char *dev; + const char *label; +} backing_devices[MAX_DEVS]; + +static size_t nr_backing_devices = 0, nr_cache_devices = 0; + +static char *label = NULL; + +/* All in units of 512 byte sectors */ +static unsigned block_size; +static unsigned bucket_size = 2048; +static unsigned btree_node_size; +static uint64_t filesystem_size; +static unsigned tier, replacement_policy; + +static uuid_t cache_set_uuid; +static unsigned csum_type = BCH_CSUM_CRC32C; +static unsigned replication_set, meta_replicas = 1, data_replicas = 1; +static unsigned on_error_action; +static int discard; + +static uint64_t data_offset = BDEV_DATA_START_DEFAULT; +static unsigned cache_mode = CACHE_MODE_WRITEBACK; + +static int set_cache(NihOption *option, const char *arg) +{ + cache_devices[nr_cache_devices++] = (struct cache_opts) { + .dev = strdup(arg), + .bucket_size = bucket_size, + .tier = tier, + .replacement_policy = replacement_policy, + .replication_set = replication_set, + .filesystem_size = filesystem_size, + }; + return 0; +} + +static int set_bdev(NihOption *option, const char *arg) +{ + backing_devices[nr_backing_devices++] = (struct backingdev_opts) { + .dev = strdup(arg), + .label = strdup(label), + }; + return 0; +} + +static int set_cache_set_uuid(NihOption *option, const char *arg) +{ + if (uuid_parse(arg, cache_set_uuid)) + die("Bad uuid"); + return 0; +} + +static int set_block_size(NihOption *option, const char *arg) +{ + block_size = hatoi_validate(arg, "block size"); + return 0; +} + +static int set_bucket_sizes(NihOption *option, const char *arg) +{ + bucket_size = hatoi_validate(arg, "bucket size"); + return 0; +} + +static int set_btree_node_size(NihOption *option, const char *arg) +{ + btree_node_size = hatoi_validate(arg, "btree node size"); + return 0; +} + +static int set_filesystem_size(NihOption *option, const char *arg) +{ + filesystem_size = hatoi(arg) >> 9; + return 0; +} + +static int set_replacement_policy(NihOption *option, const char *arg) +{ + replacement_policy = read_string_list_or_die(arg, replacement_policies, + "replacement policy"); + return 0; +} + +static int set_csum_type(NihOption *option, const char *arg) +{ + csum_type = read_string_list_or_die(arg, csum_types, "checksum type"); + return 0; +} + +static int set_on_error_action(NihOption *option, const char *arg) +{ + on_error_action = read_string_list_or_die(arg, error_actions, + "error action"); + return 0; +} + +static int set_tier(NihOption *option, const char *arg) +{ + tier = strtoul_or_die(arg, CACHE_TIERS, "tier"); + return 0; +} + +static int set_replication_set(NihOption *option, const char *arg) +{ + replication_set = strtoul_or_die(arg, CACHE_REPLICATION_SET_MAX, + "replication set"); + return 0; +} + +static int set_meta_replicas(NihOption *option, const char *arg) +{ + meta_replicas = strtoul_or_die(arg, CACHE_SET_META_REPLICAS_WANT_MAX, + "meta_replicas"); + return 0; +} + +static int set_data_replicas(NihOption *option, const char *arg) +{ + data_replicas = strtoul_or_die(arg, CACHE_SET_DATA_REPLICAS_WANT_MAX, + "data_replicas"); + return 0; +} + +static int set_cache_mode(NihOption *option, const char *arg) +{ + cache_mode = read_string_list_or_die(arg, bdev_cache_mode, + "cache mode"); + return 0; +} + +NihOption bcacheadm_format_options[] = { +// { int shortoption, char *longoption, char *help, NihOptionGroup, char *argname, void *value, NihOptionSetter} + + { 'C', "cache", N_("Format a cache device"), + NULL, "dev", NULL, set_cache }, + { 'B', "bdev", N_("Format a backing device"), + NULL, "dev", NULL, set_bdev }, + + { 'l', "label", N_("label"), + NULL, "label", &label, NULL}, + { 0, "cset_uuid", N_("UUID for the cache set"), + NULL, "uuid", NULL, set_cache_set_uuid }, + + { 'w', "block", N_("block size (hard sector size of SSD, often 2k"), + NULL, "size", NULL, set_block_size }, + { 'b', "bucket", N_("bucket size"), + NULL, "size", NULL, set_bucket_sizes }, + { 'n', "btree-node", N_("Btree node size, default 256k"), + NULL, "size", NULL, set_btree_node_size }, + { 0, "fs-size", N_("Size of filesystem on device" ), + NULL, "size", NULL, set_filesystem_size }, + + { 'p', "cache_replacement_policy", NULL, + NULL, "(lru|fifo|random)", NULL, set_replacement_policy }, + + { 0, "csum-type", N_("Checksum type"), + NULL, "(none|crc32c|crc64)", NULL, set_csum_type }, + + { 0, "on-error", N_("Action to take on filesystem error"), + NULL, "(continue|readonly|panic)", NULL, set_on_error_action }, + + { 0, "discard", N_("Enable discards"), + NULL, NULL, &discard, NULL }, + + { 't', "tier", N_("tier of subsequent devices"), + NULL, "#", NULL, set_tier }, + + { 0, "replication_set", N_("replication set of subsequent devices"), + NULL, "#", NULL, set_replication_set }, + + { 0, "meta-replicas", N_("number of metadata replicas"), + NULL, "#", NULL, set_meta_replicas }, + + { 0, "data-replicas", N_("number of data replicas"), + NULL, "#", NULL, set_data_replicas }, + + { 0, "cache_mode", N_("Cache mode (for backing devices)"), + NULL, "(writethrough|writeback|writearound", NULL, set_cache_mode }, + + { 'o', "data_offset", N_("data offset in sectors"), + NULL, "offset", &data_offset, NULL}, + + NIH_OPTION_LAST +}; + +int bcacheadm_format(NihCommand *command, char *const *args) +{ + struct cache_sb *cache_set_sb; + + if (!nr_cache_devices && !nr_backing_devices) + die("Please supply a device"); + + for (struct cache_opts *i = cache_devices; + i < cache_devices + nr_cache_devices; + i++) + i->fd = dev_open(i->dev); + + for (struct backingdev_opts *i = backing_devices; + i < backing_devices + nr_backing_devices; + i++) + i->fd = dev_open(i->dev); + + if (!block_size) { + for (struct cache_opts *i = cache_devices; + i < cache_devices + nr_cache_devices; + i++) + block_size = max(block_size, get_blocksize(i->dev, i->fd)); + + for (struct backingdev_opts *i = backing_devices; + i < backing_devices + nr_backing_devices; + i++) + block_size = max(block_size, get_blocksize(i->dev, i->fd)); + } + + if (!btree_node_size) { + btree_node_size = 512; + + for (struct cache_opts *i = cache_devices; + i < cache_devices + nr_cache_devices; + i++) + btree_node_size = min(btree_node_size, i->bucket_size); + } + + cache_set_sb = calloc(1, sizeof(*cache_set_sb) + + sizeof(struct cache_member) * nr_cache_devices); + + cache_set_sb->offset = SB_SECTOR; + cache_set_sb->version = BCACHE_SB_VERSION_CDEV_V3; + cache_set_sb->magic = BCACHE_MAGIC; + cache_set_sb->block_size = block_size; + uuid_generate(cache_set_sb->set_uuid.b); + + if (uuid_is_null(cache_set_uuid)) + uuid_generate(cache_set_sb->user_uuid.b); + else + memcpy(cache_set_sb->user_uuid.b, cache_set_uuid, + sizeof(cache_set_sb->user_uuid)); + + if (label) + memcpy(cache_set_sb->label, label, sizeof(cache_set_sb->label)); + + /* + * don't have a userspace crc32c implementation handy, just always use + * crc64 + */ + SET_CACHE_SB_CSUM_TYPE(cache_set_sb, BCH_CSUM_CRC64); + SET_CACHE_PREFERRED_CSUM_TYPE(cache_set_sb, csum_type); + + SET_CACHE_BTREE_NODE_SIZE(cache_set_sb, btree_node_size); + SET_CACHE_SET_META_REPLICAS_WANT(cache_set_sb, meta_replicas); + SET_CACHE_SET_META_REPLICAS_HAVE(cache_set_sb, meta_replicas); + SET_CACHE_SET_DATA_REPLICAS_WANT(cache_set_sb, data_replicas); + SET_CACHE_SET_DATA_REPLICAS_HAVE(cache_set_sb, data_replicas); + SET_CACHE_ERROR_ACTION(cache_set_sb, on_error_action); + + for (struct cache_opts *i = cache_devices; + i < cache_devices + nr_cache_devices; + i++) { + if (i->bucket_size < block_size) + die("Bucket size cannot be smaller than block size"); + + struct cache_member *m = cache_set_sb->members + cache_set_sb->nr_in_set++; + + uuid_generate(m->uuid.b); + m->nbuckets = (i->filesystem_size ?: + getblocks(i->fd)) / i->bucket_size; + m->first_bucket = (23 / i->bucket_size) + 3; + m->bucket_size = i->bucket_size; + + if (m->nbuckets < 1 << 7) + die("Not enough buckets: %llu, need %u", + m->nbuckets, 1 << 7); + + SET_CACHE_TIER(m, i->tier); + SET_CACHE_REPLICATION_SET(m, i->replication_set); + SET_CACHE_REPLACEMENT(m, i->replacement_policy); + SET_CACHE_DISCARD(m, discard); + } + + cache_set_sb->u64s = bch_journal_buckets_offset(cache_set_sb); + + for (unsigned i = 0; i < cache_set_sb->nr_in_set; i++) { + char uuid_str[40], set_uuid_str[40]; + struct cache_member *m = cache_set_sb->members + i; + + cache_set_sb->disk_uuid = m->uuid; + cache_set_sb->nr_this_dev = i; + cache_set_sb->csum = csum_set(cache_set_sb, + CACHE_SB_CSUM_TYPE(cache_set_sb)); + + uuid_unparse(cache_set_sb->disk_uuid.b, uuid_str); + uuid_unparse(cache_set_sb->user_uuid.b, set_uuid_str); + printf("UUID: %s\n" + "Set UUID: %s\n" + "version: %u\n" + "nbuckets: %llu\n" + "block_size: %u\n" + "bucket_size: %u\n" + "nr_in_set: %u\n" + "nr_this_dev: %u\n" + "first_bucket: %u\n", + uuid_str, set_uuid_str, + (unsigned) cache_set_sb->version, + m->nbuckets, + cache_set_sb->block_size, + m->bucket_size, + cache_set_sb->nr_in_set, + cache_set_sb->nr_this_dev, + m->first_bucket); + + do_write_sb(cache_devices[i].fd, cache_set_sb); + } + + for (struct backingdev_opts *i = backing_devices; + i < backing_devices + nr_backing_devices; + i++) + write_backingdev_sb(i->fd, block_size, cache_mode, + data_offset, i->label, + cache_set_sb->user_uuid, + cache_set_sb->set_uuid); + + + return 0; +} diff --git a/bcacheadm.c b/bcacheadm.c index 792b5b7..6fd3173 100644 --- a/bcacheadm.c +++ b/bcacheadm.c @@ -27,39 +27,14 @@ #include #include #include -#include "bcache.h" //libbcache + +#include "bcache.h" +#include "bcacheadm.h" #define PACKAGE_NAME "bcacheadm" #define PACKAGE_VERSION "1.0" #define PACKAGE_BUGREPORT "bugreport" - - -/* make-bcache globals */ -int bdev = -1; -int devs = 0; -char *cache_devices[MAX_DEVS]; -int tier_mapping[MAX_DEVS]; -unsigned replacement_policy_mapping[MAX_DEVS]; -char *backing_devices[MAX_DEVS]; -char *backing_dev_labels[MAX_DEVS]; -size_t i, nr_backing_devices = 0, nr_cache_devices = 0; -unsigned block_size = 0; -unsigned btree_node_size = 0; -unsigned bucket_sizes[MAX_DEVS]; -int num_bucket_sizes = 0; -int writeback = 0, writearound = 0, discard = 0, wipe_bcache = 0; -unsigned replication_set = 0; -char *replacement_policy = 0; -uint64_t data_offset = BDEV_DATA_START_DEFAULT; -char *label = NULL; -struct cache_sb *cache_set_sb = NULL; -const char *cache_set_uuid = 0; -const char *csum_type = 0; -char *metadata_replicas = 0; -char *data_replicas = 0; -char *tier = 0; - /* rm-dev globals */ bool force_remove = false; @@ -102,80 +77,6 @@ bool stats_total = false; /* set_failed globals */ static const char *dev_failed_uuid = NULL; -/* make-bcache option setters */ -static int set_block_size(NihOption *option, const char *arg) -{ - block_size = hatoi_validate(arg, "block size"); - return 0; -} - -static int set_btree_node_size(NihOption *option, const char *arg) -{ - btree_node_size = hatoi_validate(arg, "btree node size"); - return 0; -} - -static int set_cache(NihOption *option, const char *arg) -{ - bdev = 0; - cache_devices[nr_cache_devices] = strdup(arg); - if(!tier) - tier_mapping[nr_cache_devices] = 0; - else { - int ntier = atoi(tier); - if(ntier == 0 || ntier == 1) - tier_mapping[nr_cache_devices] = ntier; - else - printf("Invalid tier %s\n", tier); - } - - if (!replacement_policy) - replacement_policy_mapping[nr_cache_devices] = 0; - else { - int i = 0; - - while (replacement_policies[i] != NULL) { - if (!strcmp(replacement_policy, - replacement_policies[i])) { - replacement_policy_mapping[nr_cache_devices] = i; - break; - } - i++; - } - - if (replacement_policies[i] == NULL) - printf("Invalid replacement policy: %s\n", - replacement_policy); - } - - devs++; - nr_cache_devices++; - - return 0; -} - -static int set_bdev(NihOption *option, const char *arg) -{ - bdev = 1; - - if(label) - backing_dev_labels[nr_backing_devices] = strdup(label); - - backing_devices[nr_backing_devices] = strdup(arg); - - nr_backing_devices++; - devs++; - - return 0; -} - -static int set_bucket_sizes(NihOption *option, const char *arg) -{ - bucket_sizes[num_bucket_sizes]=hatoi_validate(arg, "bucket size"); - num_bucket_sizes++; - return 0; -} - /* probe setters */ static int set_udev(NihOption *option, const char *arg) { @@ -187,38 +88,7 @@ static int set_udev(NihOption *option, const char *arg) return 0; } - /* options */ -static NihOption make_bcache_options[] = { -// {int shortoption, char* longoption, char* help, NihOptionGroup, char* argname, void *value, NihOptionSetter} - {'C', "cache", N_("Format a cache device"), NULL, "dev", NULL, set_cache}, - {'B', "bdev", N_("Format a backing device"), NULL, "dev", NULL, set_bdev}, - {'l', "label", N_("label"), NULL, "label", &label, NULL}, - //Only one bucket_size supported until a list of bucket sizes is parsed correctly - {'b', "bucket", N_("bucket size"), NULL, "size", NULL, set_bucket_sizes}, - //Does the default setter automatically convert strings to an int? - {'w', "block", N_("block size (hard sector size of SSD, often 2k"), NULL, "size", NULL, set_block_size}, - - {'n', "btree-node", N_("Btree node size, default 256k"), NULL, "size", NULL, set_btree_node_size}, - - {'t', "tier", N_("tier of subsequent devices"), NULL,"#", &tier, NULL}, - {'p', "cache_replacement_policy", N_("one of (lru|fifo|random)"), NULL,"policy", &replacement_policy, NULL}, - {'o', "data_offset", N_("data offset in sectors"), NULL,"offset", &data_offset, NULL}, - - {0, "cset-uuid", N_("UUID for the cache set"), NULL, "uuid", &cache_set_uuid, NULL}, - {0, "csum-type", N_("One of (none|crc32c|crc64)"), NULL, "type", &csum_type, NULL }, - {0, "replication-set",N_("replication set of subsequent devices"), NULL, NULL, &replication_set, NULL }, - {0, "meta-replicas",N_("number of metadata replicas"), NULL, "#", &metadata_replicas, NULL}, - {0, "data-replicas",N_("number of data replicas"), NULL, "#", &data_replicas, NULL }, - - {0, "wipe-bcache", N_("destroy existing bcache data if present"), NULL, NULL, &wipe_bcache, NULL}, - {0, "discard", N_("enable discards"), NULL, NULL, &discard, NULL}, - {0, "writeback", N_("enable writeback"), NULL, NULL, &writeback, NULL}, - {0, "writearound", N_("enable writearound"), NULL, NULL, &writearound, NULL}, - - NIH_OPTION_LAST -}; - static NihOption probe_bcache_options[] = { {'o', "udev", N_("udev"), NULL, NULL, NULL, set_udev}, NIH_OPTION_LAST @@ -295,138 +165,7 @@ static NihOption options[] = { NIH_OPTION_LAST }; - /* commands */ -int make_bcache(NihCommand *command, char *const *args) -{ - int cache_dev_fd[devs]; - int data_replicas_num, metadata_replicas_num; - - int backing_dev_fd[devs]; - - unsigned cache_mode; - - cache_set_sb = calloc(1, sizeof(*cache_set_sb) + - sizeof(struct cache_member) * devs); - - uuid_generate(cache_set_sb->set_uuid.b); - - if (cache_set_uuid) { - if(uuid_parse(cache_set_uuid, cache_set_sb->user_uuid.b)) { - fprintf(stderr, "Bad uuid\n"); - return -1; - } - } else { - uuid_generate(cache_set_sb->user_uuid.b); - } - - if (label) - memcpy(cache_set_sb->label, label, sizeof(cache_set_sb->label)); - - if (csum_type) { - SET_CACHE_PREFERRED_CSUM_TYPE(cache_set_sb, - read_string_list_or_die(csum_type, csum_types, - "csum type")); - } else { - SET_CACHE_PREFERRED_CSUM_TYPE(cache_set_sb, BCH_CSUM_CRC32C); - } - - if (metadata_replicas) { - metadata_replicas_num = - strtoul_or_die(metadata_replicas, - CACHE_SET_META_REPLICAS_WANT_MAX, - "meta replicas"); - } else { - metadata_replicas_num = 1; - } - - SET_CACHE_SET_META_REPLICAS_WANT(cache_set_sb, - metadata_replicas_num); - SET_CACHE_SET_META_REPLICAS_HAVE(cache_set_sb, - metadata_replicas_num); - - if (data_replicas) { - data_replicas_num = - strtoul_or_die(data_replicas, - CACHE_SET_DATA_REPLICAS_WANT_MAX, - "data replicas"); - } else { - data_replicas_num = 1; - } - - SET_CACHE_SET_DATA_REPLICAS_WANT(cache_set_sb, - data_replicas_num); - SET_CACHE_SET_DATA_REPLICAS_HAVE(cache_set_sb, - data_replicas_num); - - if (bdev == -1) { - fprintf(stderr, "Please specify -C or -B\n"); - exit(EXIT_FAILURE); - } - - if (!bucket_sizes[0]) - bucket_sizes[0] = 1024; - - for (i = 0; i < nr_cache_devices; i++) - next_cache_device(cache_set_sb, - replication_set, - tier_mapping[i], - replacement_policy_mapping[i], - discard); - - if (!cache_set_sb->nr_in_set && !nr_backing_devices) { - fprintf(stderr, "Please supply a device\n"); - exit(EXIT_FAILURE); - } - - i = 0; - do { - if (bucket_sizes[i] < block_size) { - fprintf(stderr, - "Bucket size cannot be smaller than block size\n"); - exit(EXIT_FAILURE); - } - i++; - } while (i < num_bucket_sizes); - - if (!block_size) { - for (i = 0; i < cache_set_sb->nr_in_set; i++) - block_size = max(block_size, - get_blocksize(cache_devices[i])); - - for (i = 0; i < nr_backing_devices; i++) - block_size = max(block_size, - get_blocksize(backing_devices[i])); - } - - for (i = 0; i < cache_set_sb->nr_in_set; i++) - cache_dev_fd[i] = dev_open(cache_devices[i], wipe_bcache); - - for (i = 0; i < nr_backing_devices; i++) - backing_dev_fd[i] = dev_open(backing_devices[i], wipe_bcache); - - write_cache_sbs(cache_dev_fd, cache_set_sb, block_size, - bucket_sizes, num_bucket_sizes, btree_node_size); - - if (writeback) - cache_mode = CACHE_MODE_WRITEBACK; - else if (writearound) - cache_mode = CACHE_MODE_WRITEAROUND; - else - cache_mode = CACHE_MODE_WRITETHROUGH; - - for (i = 0; i < nr_backing_devices; i++) - write_backingdev_sb(backing_dev_fd[i], - block_size, bucket_sizes, - cache_mode, data_offset, - backing_dev_labels[i], - cache_set_sb->user_uuid, - cache_set_sb->set_uuid); - - - return 0; -} - int probe_bcache(NihCommand *command, char *const *args) { int i; @@ -889,7 +628,7 @@ static NihCommand commands[] = { "Format one or a list of devices with bcache datastructures." " You need to do this before you create a volume", N_("format drive[s] with bcache"), - NULL, make_bcache_options, make_bcache}, + NULL, bcacheadm_format_options, bcacheadm_format}, {"probe", N_("probe "), "Does a blkid_probe on a device", N_("Does a blkid_probe on a device"), @@ -941,7 +680,6 @@ static NihCommand commands[] = { NIH_COMMAND_LAST }; - int main(int argc, char *argv[]) { int ret = 0; diff --git a/bcacheadm.h b/bcacheadm.h new file mode 100644 index 0000000..7a31ee9 --- /dev/null +++ b/bcacheadm.h @@ -0,0 +1,7 @@ +#ifndef _BCACHEADM_H +#define _BCACHEADM_H + +extern NihOption bcacheadm_format_options[]; +int bcacheadm_format(NihCommand *, char * const *); + +#endif /* _BCACHEADM_H */ -- 2.39.2