New superblock format

This commit is contained in:
Kent Overstreet 2011-07-25 00:18:42 -07:00
parent d1404a0cf1
commit c798b43ade
2 changed files with 73 additions and 65 deletions

View File

@ -5,40 +5,52 @@ static const char bcache_magic[] = {
0xc6, 0x85, 0x73, 0xf6, 0x4e, 0x1a, 0x45, 0xca, 0xc6, 0x85, 0x73, 0xf6, 0x4e, 0x1a, 0x45, 0xca,
0x82, 0x65, 0xf5, 0x7f, 0x48, 0xba, 0x6d, 0x81 }; 0x82, 0x65, 0xf5, 0x7f, 0x48, 0xba, 0x6d, 0x81 };
#define SB_LABEL_SIZE 32
struct cache_sb {
uint64_t csum;
uint64_t offset_this_sb;
uint64_t version;
#define CACHE_BACKING_DEV 1
uint8_t magic[16];
uint8_t uuid[16];
uint8_t set_uuid[16];
uint8_t label[SB_LABEL_SIZE];
#define CACHE_SYNC (1U << 0)
#define BDEV_WRITEBACK_BIT 0U
#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];
uint64_t nbuckets; /* device size */
uint16_t block_size; /* sectors */
uint16_t bucket_size; /* sectors */
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[];
};
struct bkey { struct bkey {
uint64_t header; uint64_t header;
uint64_t key; uint64_t key;
uint64_t ptr[]; uint64_t ptr[];
}; };
struct cache_sb {
uint8_t magic[16];
uint8_t uuid[16];
uint8_t set_uuid[16];
uint64_t sequence;
#define CACHE_CLEAN 1
#define CACHE_SYNC 2
#define CACHE_BACKING_DEV 4
uint32_t version;
uint16_t block_size; /* sectors */
uint16_t bucket_size; /* sectors */
uint32_t journal_start; /* buckets */
uint32_t first_bucket; /* start of data */
uint64_t nbuckets; /* device size */
union {
struct bkey btree_root;
uint64_t _pad[8];
};
uint16_t btree_level;
uint16_t nr_in_set;
uint16_t nr_this_dev;
uint16_t _pad[1];
#define SB_LABEL_SIZE 32
uint8_t label[SB_LABEL_SIZE];
};
struct bucket_disk { struct bucket_disk {
uint16_t priority; uint16_t priority;
uint8_t generation; uint8_t generation;

View File

@ -2,6 +2,8 @@
#define __USE_FILE_OFFSET64 #define __USE_FILE_OFFSET64
#define _XOPEN_SOURCE 600 #define _XOPEN_SOURCE 600
#include <ctype.h>
#include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <stdbool.h> #include <stdbool.h>
@ -64,7 +66,6 @@ void usage()
" -B Format a backing device\n" " -B Format a backing device\n"
" -b bucket size\n" " -b bucket size\n"
" -w block size (hard sector size of SSD, often 2k)\n" " -w block size (hard sector size of SSD, often 2k)\n"
" -j journal size, in buckets\n"
" -U UUID\n" " -U UUID\n"
" -S Set UUID\n"); " -S Set UUID\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -73,9 +74,9 @@ void usage()
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
bool cache = false, backingdev = false; bool cache = false, backingdev = false;
int64_t nblocks, journal = 0; int fd, c;
int fd, i, c; int64_t nblocks;
char uuid[40], set_uuid[40]; char uuid[40], set_uuid[40], *dev;
struct cache_sb sb; struct cache_sb sb;
memset(&sb, 0, sizeof(struct cache_sb)); memset(&sb, 0, sizeof(struct cache_sb));
@ -97,9 +98,6 @@ int main(int argc, char **argv)
case 'w': case 'w':
sb.block_size = hatoi(optarg) / 512; sb.block_size = hatoi(optarg) / 512;
break; break;
case 'j':
journal = atoi(optarg);
break;
case 'U': case 'U':
if (uuid_parse(optarg, sb.uuid)) { if (uuid_parse(optarg, sb.uuid)) {
printf("Bad uuid\n"); printf("Bad uuid\n");
@ -130,51 +128,49 @@ int main(int argc, char **argv)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
fd = open(argv[optind], O_RDWR); dev = argv[optind];
fd = open(dev, O_RDWR);
if (fd == -1) { if (fd == -1) {
perror("Can't open dev\n"); printf("Can't open dev %s: %s\n", dev, strerror(errno));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
nblocks = getblocks(fd); nblocks = getblocks(fd);
printf("device is %ju sectors\n", nblocks); printf("device is %ju sectors\n", nblocks);
if (sb.bucket_size < sb.block_size || sb.offset_this_sb = 8;
sb.bucket_size > nblocks / 8) {
printf("Bad bucket size %i\n", sb.bucket_size);
exit(EXIT_FAILURE);
}
memcpy(sb.magic, bcache_magic, 16); memcpy(sb.magic, bcache_magic, 16);
sb.version = backingdev ? CACHE_BACKING_DEV : 0; sb.version = backingdev ? CACHE_BACKING_DEV : 0;
sb.nbuckets = nblocks / sb.bucket_size; sb.nbuckets = nblocks / sb.bucket_size;
sb.nr_in_set = 1; sb.nr_in_set = 1;
uuid_unparse(sb.uuid, uuid); uuid_unparse(sb.uuid, uuid);
uuid_unparse(sb.set_uuid, set_uuid); uuid_unparse(sb.set_uuid, set_uuid);
sb.journal_start = ((sb.nbuckets * sizeof(struct bucket_disk)) + (24 << 9)) / (sb.bucket_size << 9) + 1; sb.first_bucket = (23 / sb.bucket_size) + 1;
sb.first_bucket = sb.journal_start + journal;
printf("block_size: %u\n" if (cache)
"bucket_size: %u\n" if (sb.bucket_size < sb.block_size ||
"journal_start: %u\n" sb.bucket_size > nblocks / 8) {
"first_bucket: %u\n" printf("Bad bucket size %i\n", sb.bucket_size);
exit(EXIT_FAILURE);
}
printf("UUID: %s\n"
"Set UUID: %s\n"
"nbuckets: %ju\n" "nbuckets: %ju\n"
"UUID: %s\n" "block_size: %u\n"
"Set UUID: %s\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.block_size,
sb.bucket_size, sb.bucket_size,
sb.journal_start, sb.nr_in_set,
sb.nr_this_dev,
sb.first_bucket, sb.first_bucket,
sb.nbuckets, sizeof(sb));
uuid, set_uuid);
if (!backingdev) {
/* Zero out priorities */
lseek(fd, 4096, SEEK_SET);
for (i = 8; i < sb.first_bucket * sb.bucket_size; i++)
if (write(fd, zero, 512) != 512)
goto err;
}
if (pwrite(fd, &sb, sizeof(sb), 4096) != sizeof(sb)) if (pwrite(fd, &sb, sizeof(sb), 4096) != sizeof(sb))
goto err; goto err;