mirror of
https://github.com/koverstreet/bcachefs-tools.git
synced 2025-02-22 00:00:03 +03:00
Give make-bcache the ability to format multiple devices at once
This commit is contained in:
parent
c798b43ade
commit
02614b5c81
63
bcache.h
63
bcache.h
@ -5,55 +5,40 @@ static const char bcache_magic[] = {
|
||||
0xc6, 0x85, 0x73, 0xf6, 0x4e, 0x1a, 0x45, 0xca,
|
||||
0x82, 0x65, 0xf5, 0x7f, 0x48, 0xba, 0x6d, 0x81 };
|
||||
|
||||
#define SB_LABEL_SIZE 32
|
||||
#define SB_SECTOR 8
|
||||
#define SB_LABEL_SIZE 32
|
||||
|
||||
struct cache_sb {
|
||||
uint64_t csum;
|
||||
uint64_t offset_this_sb;
|
||||
uint64_t version;
|
||||
uint64_t csum;
|
||||
uint64_t offset; /* sector where this sb was written */
|
||||
uint64_t version;
|
||||
#define CACHE_BACKING_DEV 1
|
||||
|
||||
uint8_t magic[16];
|
||||
uint8_t magic[16];
|
||||
|
||||
uint8_t uuid[16];
|
||||
uint8_t set_uuid[16];
|
||||
uint8_t label[SB_LABEL_SIZE];
|
||||
uint8_t uuid[16];
|
||||
union {
|
||||
uint8_t set_uuid[16];
|
||||
uint64_t set_magic;
|
||||
};
|
||||
uint8_t label[SB_LABEL_SIZE];
|
||||
|
||||
#define CACHE_SYNC (1U << 0)
|
||||
uint64_t flags;
|
||||
uint64_t seq;
|
||||
uint64_t pad[8];
|
||||
|
||||
#define BDEV_WRITEBACK_BIT 0U
|
||||
uint64_t nbuckets; /* device size */
|
||||
uint16_t block_size; /* sectors */
|
||||
uint16_t bucket_size; /* sectors */
|
||||
|
||||
#define BDEV_STATE_NONE 0U
|
||||
#define BDEV_STATE_CLEAN 1U
|
||||
#define BDEV_STATE_DIRTY 2U
|
||||
#define BDEV_STATE_STALE 3U
|
||||
uint64_t flags;
|
||||
uint64_t sequence;
|
||||
uint64_t pad[8];
|
||||
uint16_t nr_in_set;
|
||||
uint16_t nr_this_dev;
|
||||
|
||||
uint64_t nbuckets; /* device size */
|
||||
uint16_t block_size; /* sectors */
|
||||
uint16_t bucket_size; /* sectors */
|
||||
uint32_t last_mount; /* time_t */
|
||||
|
||||
uint16_t nr_in_set;
|
||||
uint16_t nr_this_dev;
|
||||
|
||||
uint32_t last_mount; /* time_t */
|
||||
|
||||
uint16_t first_bucket;
|
||||
uint16_t njournal_buckets;
|
||||
uint64_t journal_buckets[];
|
||||
uint16_t first_bucket;
|
||||
uint16_t keys; /* number of journal buckets */
|
||||
uint64_t d[512]; /* journal buckets */
|
||||
};
|
||||
|
||||
struct bkey {
|
||||
uint64_t header;
|
||||
uint64_t key;
|
||||
uint64_t ptr[];
|
||||
};
|
||||
|
||||
struct bucket_disk {
|
||||
uint16_t priority;
|
||||
uint8_t generation;
|
||||
} __attribute((packed));
|
||||
|
||||
#endif
|
||||
|
156
make-bcache.c
156
make-bcache.c
@ -71,26 +71,94 @@ void usage()
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void write_sb(char *dev, struct cache_sb *sb)
|
||||
{
|
||||
int fd;
|
||||
char uuid[40], set_uuid[40];
|
||||
|
||||
if (sb->version > 1) {
|
||||
printf("Must specify one of -C or -B\n");
|
||||
usage();
|
||||
}
|
||||
|
||||
if ((sb->bucket_size & (sb->bucket_size - 1)) ||
|
||||
(sb->block_size & (sb->block_size - 1))) {
|
||||
printf("Block and bucket sizes must be powers of two\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (sb->bucket_size < sb->block_size) {
|
||||
printf("Bad bucket size %i\n", sb->bucket_size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if ((fd = open(dev, O_RDWR)) == -1) {
|
||||
printf("Can't open dev %s: %s\n", dev, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
sb->offset = SB_SECTOR;
|
||||
memcpy(sb->magic, bcache_magic, 16);
|
||||
sb->nbuckets = getblocks(fd) / sb->bucket_size;
|
||||
sb->nr_in_set = 1;
|
||||
sb->first_bucket = (23 / sb->bucket_size) + 1;
|
||||
uuid_unparse(sb->uuid, uuid);
|
||||
uuid_unparse(sb->set_uuid, set_uuid);
|
||||
|
||||
if (sb->nbuckets < 1 << 7) {
|
||||
printf("Not enough buckets: %ju, need %u\n",
|
||||
sb->nbuckets, 1 << 7);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("UUID: %s\n"
|
||||
"Set UUID: %s\n"
|
||||
"nbuckets: %ju\n"
|
||||
"block_size: %u\n"
|
||||
"bucket_size: %u\n"
|
||||
"nr_in_set: %u\n"
|
||||
"nr_this_dev: %u\n"
|
||||
"first_bucket: %u\n",
|
||||
uuid, set_uuid,
|
||||
sb->nbuckets,
|
||||
sb->block_size,
|
||||
sb->bucket_size,
|
||||
sb->nr_in_set,
|
||||
sb->nr_this_dev,
|
||||
sb->first_bucket);
|
||||
|
||||
if (pwrite(fd, sb, sizeof(*sb), SB_SECTOR << 9) != sizeof(*sb)) {
|
||||
perror("write error\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fsync(fd);
|
||||
close(fd);
|
||||
|
||||
uuid_generate(sb->uuid);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
bool cache = false, backingdev = false;
|
||||
int fd, c;
|
||||
int64_t nblocks;
|
||||
char uuid[40], set_uuid[40], *dev;
|
||||
bool written = false;
|
||||
int c;
|
||||
struct cache_sb sb;
|
||||
|
||||
memset(&sb, 0, sizeof(struct cache_sb));
|
||||
sb.version = 2;
|
||||
sb.block_size = 8;
|
||||
sb.bucket_size = 1024;
|
||||
|
||||
uuid_generate(sb.uuid);
|
||||
uuid_generate(sb.set_uuid);
|
||||
|
||||
while ((c = getopt(argc, argv, "CBU:w:b:j:")) != -1)
|
||||
while ((c = getopt(argc, argv, "-CBU:w:b:")) != -1)
|
||||
switch (c) {
|
||||
case 'C':
|
||||
cache = true;
|
||||
sb.version = 0;
|
||||
break;
|
||||
case 'B':
|
||||
backingdev = true;
|
||||
sb.version = CACHE_BACKING_DEV;
|
||||
break;
|
||||
case 'b':
|
||||
sb.bucket_size = hatoi(optarg) / 512;
|
||||
@ -104,80 +172,16 @@ int main(int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
case 'S':
|
||||
if (uuid_parse(optarg, sb.set_uuid)) {
|
||||
printf("Bad uuid\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
case 1:
|
||||
write_sb(optarg, &sb);
|
||||
written = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!sb.block_size)
|
||||
sb.block_size = 4;
|
||||
|
||||
if (!sb.bucket_size)
|
||||
sb.bucket_size = cache ? 256 : 8192;
|
||||
|
||||
if (cache == backingdev) {
|
||||
printf("Must specify one of -C or -B\n");
|
||||
usage();
|
||||
}
|
||||
|
||||
if (argc <= optind) {
|
||||
if (!written) {
|
||||
printf("Please supply a device\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
dev = argv[optind];
|
||||
fd = open(dev, O_RDWR);
|
||||
if (fd == -1) {
|
||||
printf("Can't open dev %s: %s\n", dev, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
nblocks = getblocks(fd);
|
||||
printf("device is %ju sectors\n", nblocks);
|
||||
|
||||
sb.offset_this_sb = 8;
|
||||
memcpy(sb.magic, bcache_magic, 16);
|
||||
sb.version = backingdev ? CACHE_BACKING_DEV : 0;
|
||||
sb.nbuckets = nblocks / sb.bucket_size;
|
||||
sb.nr_in_set = 1;
|
||||
uuid_unparse(sb.uuid, uuid);
|
||||
uuid_unparse(sb.set_uuid, set_uuid);
|
||||
|
||||
sb.first_bucket = (23 / sb.bucket_size) + 1;
|
||||
|
||||
if (cache)
|
||||
if (sb.bucket_size < sb.block_size ||
|
||||
sb.bucket_size > nblocks / 8) {
|
||||
printf("Bad bucket size %i\n", sb.bucket_size);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("UUID: %s\n"
|
||||
"Set UUID: %s\n"
|
||||
"nbuckets: %ju\n"
|
||||
"block_size: %u\n"
|
||||
"bucket_size: %u\n"
|
||||
"nr_in_set: %u\n"
|
||||
"nr_this_dev: %u\n"
|
||||
"first_bucket: %u\n"
|
||||
"sizeof sb: %lu\n",
|
||||
uuid, set_uuid,
|
||||
sb.nbuckets,
|
||||
sb.block_size,
|
||||
sb.bucket_size,
|
||||
sb.nr_in_set,
|
||||
sb.nr_this_dev,
|
||||
sb.first_bucket,
|
||||
sizeof(sb));
|
||||
|
||||
if (pwrite(fd, &sb, sizeof(sb), 4096) != sizeof(sb))
|
||||
goto err;
|
||||
|
||||
fsync(fd);
|
||||
exit(EXIT_SUCCESS);
|
||||
err:
|
||||
perror("write error\n");
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user