2 * Author: Kent Overstreet <kmo@daterainc.com>
7 #define _FILE_OFFSET_BITS 64
8 #define __USE_FILE_OFFSET 64
9 #define _XOPEN_SOURCE 600
22 #include <sys/ioctl.h>
23 #include <sys/types.h>
26 #include <uuid/uuid.h>
33 "Usage: make-bcache [options] device\n"
34 " -C, --cache Format a cache device\n"
35 " -B, --bdev Format a backing device\n"
36 " --wipe-bcache destroy existing bcache data if present\n"
37 " -l, --label label\n"
38 " --cset-uuid UUID for the cache set\n"
39 " --csum-type One of (none|crc32c|crc64)\n"
41 " -b, --bucket bucket size\n"
42 " -w, --block block size (hard sector size of SSD, often 2k)\n"
44 " --replication-set replication set of subsequent devices\n"
45 " --meta-replicas number of metadata replicas\n"
46 " --data-replicas number of data replicas\n"
47 " --tier tier of subsequent devices\n"
48 " --cache_replacement_policy one of (lru|fifo|random)\n"
49 " --discard enable discards\n"
51 " --writeback enable writeback\n"
52 " -o, --data-offset data offset in sectors\n"
53 " -h, --help display this help and exit\n");
57 int main(int argc, char **argv)
60 size_t i, nr_backing_devices = 0;
62 unsigned block_size = 0;
63 unsigned bucket_sizes[argc];
64 int num_bucket_sizes = 0;
65 int writeback = 0, discard = 0, wipe_bcache = 0;
66 unsigned replication_set = 0, tier = 0, replacement_policy = 0;
67 uint64_t data_offset = BDEV_DATA_START_DEFAULT;
70 const char *cache_devices[argc];
71 int cache_dev_fd[argc];
73 const char *backing_devices[argc];
74 int backing_dev_fd[argc];
75 const char *backing_dev_labels[argc];
85 const struct option opts[] = {
86 { "cache", 0, NULL, 'C' },
87 { "bdev", 0, NULL, 'B' },
88 { "wipe-bcache", 0, &wipe_bcache, 1 },
89 { "label", 1, NULL, 'l' },
90 { "cset-uuid", 1, NULL, CACHE_SET_UUID },
91 { "csum-type", 1, NULL, CSUM_TYPE },
93 { "bucket", 1, NULL, 'b' },
94 { "block", 1, NULL, 'w' },
96 { "replication-set", 1, NULL, REPLICATION_SET },
97 { "meta-replicas", 1, NULL, META_REPLICAS},
98 { "data-replicas", 1, NULL, DATA_REPLICAS },
99 { "tier", 1, NULL, 't' },
100 { "cache_replacement_policy", 1, NULL, 'p' },
101 { "discard", 0, &discard, 1 },
103 { "writeback", 0, &writeback, 1 },
104 { "data_offset", 1, NULL, 'o' },
106 { "help", 0, NULL, 'h' },
107 { NULL, 0, NULL, 0 },
110 struct cache_sb *cache_set_sb = calloc(1, sizeof(*cache_set_sb) +
111 sizeof(struct cache_member) * argc);
113 uuid_generate(cache_set_sb->set_uuid.b);
114 SET_CACHE_PREFERRED_CSUM_TYPE(cache_set_sb, BCH_CSUM_CRC32C);
115 SET_CACHE_SET_META_REPLICAS_WANT(cache_set_sb, 1);
116 SET_CACHE_SET_DATA_REPLICAS_WANT(cache_set_sb, 1);
117 bucket_sizes[0] = 1024;
119 while ((c = getopt_long(argc, argv,
121 opts, NULL)) != -1) {
132 memcpy(cache_set_sb->label, label,
133 sizeof(cache_set_sb->label));
136 if (uuid_parse(optarg, cache_set_sb->set_uuid.b)) {
137 fprintf(stderr, "Bad uuid\n");
142 SET_CACHE_PREFERRED_CSUM_TYPE(cache_set_sb,
143 read_string_list_or_die(optarg, csum_types,
148 bucket_sizes[num_bucket_sizes] = hatoi_validate(optarg, "bucket size");
152 block_size = hatoi_validate(optarg, "block size");
155 case REPLICATION_SET:
156 replication_set = strtoul_or_die(optarg,
157 CACHE_REPLICATION_SET_MAX,
161 SET_CACHE_SET_META_REPLICAS_WANT(cache_set_sb,
162 strtoul_or_die(optarg,
163 CACHE_SET_META_REPLICAS_WANT_MAX,
167 SET_CACHE_SET_DATA_REPLICAS_WANT(cache_set_sb,
168 strtoul_or_die(optarg,
169 CACHE_SET_DATA_REPLICAS_WANT_MAX,
173 tier = strtoul_or_die(optarg, CACHE_TIERS, "tier");
176 replacement_policy = read_string_list_or_die(optarg,
177 replacement_policies,
178 "cache replacement policy");
182 data_offset = atoll(optarg);
183 if (data_offset < BDEV_DATA_START_DEFAULT) {
184 fprintf(stderr, "Bad data offset; minimum %d sectors\n",
185 BDEV_DATA_START_DEFAULT);
194 fprintf(stderr, "Please specify -C or -B\n");
199 backing_dev_labels[nr_backing_devices] = label;
200 backing_devices[nr_backing_devices++] = optarg;
202 cache_devices[cache_set_sb->nr_in_set] = optarg;
203 next_cache_device(cache_set_sb,
214 if (!cache_set_sb->nr_in_set && !nr_backing_devices) {
215 fprintf(stderr, "Please supply a device\n");
221 if (bucket_sizes[i] < block_size) {
222 fprintf(stderr, "Bucket size cannot be smaller than block size\n");
226 } while (i < num_bucket_sizes);
229 for (i = 0; i < cache_set_sb->nr_in_set; i++)
230 block_size = max(block_size,
231 get_blocksize(cache_devices[i]));
233 for (i = 0; i < nr_backing_devices; i++)
234 block_size = max(block_size,
235 get_blocksize(backing_devices[i]));
238 for (i = 0; i < cache_set_sb->nr_in_set; i++)
239 cache_dev_fd[i] = dev_open(cache_devices[i], wipe_bcache);
241 for (i = 0; i < nr_backing_devices; i++)
242 backing_dev_fd[i] = dev_open(backing_devices[i], wipe_bcache);
244 write_cache_sbs(cache_dev_fd, cache_set_sb, block_size,
245 bucket_sizes, num_bucket_sizes);
247 for (i = 0; i < nr_backing_devices; i++)
248 write_backingdev_sb(backing_dev_fd[i],
249 block_size, bucket_sizes,
250 writeback, data_offset,
251 backing_dev_labels[i],
252 cache_set_sb->set_uuid);