Skip to content

Commit

Permalink
Keep data offset in the superblock.
Browse files Browse the repository at this point in the history
Consolidate superblock version defines, update related comments,
pick a free version number, and enable the --data-offset option.

Also make sure to copy more than sizeof(sb) so that current bdev
and cdev formats pass checksumming.  Print all known formats in
bcache-super-show.
  • Loading branch information
g2p committed Apr 7, 2013
1 parent 445032e commit e524e29
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 64 deletions.
71 changes: 42 additions & 29 deletions bcache-super-show.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ int main(int argc, char **argv)
bool force_csum = false;
int o;
extern char *optarg;
struct cache_sb sb;
struct cache_sb *sb = calloc(1, SB_SIZE);
char uuid[40];
uint64_t expected_csum;

Expand Down Expand Up @@ -60,32 +60,32 @@ int main(int argc, char **argv)
exit(2);
}

if (pread(fd, &sb, sizeof(sb), 4096) != sizeof(sb)) {
if (pread(fd, sb, SB_SIZE, SB_START) != SB_SIZE) {
fprintf(stderr, "Couldn't read\n");
exit(2);
}

printf("sb.magic\t\t");
if (! memcmp(sb.magic, bcache_magic, 16)) {
if (! memcmp(sb->magic, bcache_magic, 16)) {
printf("ok\n");
} else {
printf("bad magic\n");
fprintf(stderr, "Invalid superblock (bad magic)\n");
exit(2);
}

printf("sb.first_sector\t\t%" PRIu64, sb.offset);
if (sb.offset == SB_SECTOR) {
printf("sb.first_sector\t\t%" PRIu64, sb->offset);
if (sb->offset == SB_SECTOR) {
printf(" [match]\n");
} else {
printf(" [expected %ds]\n", SB_SECTOR);
fprintf(stderr, "Invalid superblock (bad sector)\n");
exit(2);
}

printf("sb.csum\t\t\t%" PRIX64, sb.csum);
expected_csum = csum_set(&sb);
if (sb.csum == expected_csum) {
printf("sb.csum\t\t\t%" PRIX64, sb->csum);
expected_csum = csum_set(sb);
if (sb->csum == expected_csum) {
printf(" [match]\n");
} else {
printf(" [expected %" PRIX64 "]\n", expected_csum);
Expand All @@ -95,18 +95,24 @@ int main(int argc, char **argv)
}
}

printf("sb.version\t\t%" PRIu64, sb.version);
switch (sb.version) {
case 0:
printf("sb.version\t\t%" PRIu64, sb->version);
switch (sb->version) {
case BCACHE_SB_VERSION_CDEV:
printf(" [cache device]\n");
break;

// SB_BDEV macro says bdev iff version is odd; only 0 and 1
// seem to be fully implemented however.
case CACHE_BACKING_DEV: // 1
case BCACHE_SB_VERSION_CDEV_WITH_UUID:
printf(" [cache device (new UUID format)]\n");
break;

case BCACHE_SB_VERSION_BDEV: // 1
printf(" [backing device]\n");
break;

case BCACHE_SB_VERSION_BDEV_WITH_OFFSET: // 4
printf(" [backing device with data offset]\n");
break;

default:
printf(" [unknown]\n");
// exit code?
Expand All @@ -115,40 +121,47 @@ int main(int argc, char **argv)

putchar('\n');

uuid_unparse(sb.uuid, uuid);
uuid_unparse(sb->uuid, uuid);
printf("dev.uuid\t\t%s\n", uuid);

printf(
"dev.sectors_per_block\t%u\n"
"dev.sectors_per_bucket\t%u\n"
"dev.bucket_count\t%ju\n"
"dev.cache_count\t\t%u\n", // expect version == 0 ? 1 : 0
sb.block_size,
sb.bucket_size,
sb.nbuckets,
sb.nr_this_dev);
"dev.cache_count\t\t%u\n", // expect SB_IS_BDEV(version) ? 0 : 1
sb->block_size,
sb->bucket_size,
sb->nbuckets,
sb->nr_this_dev);

if (sb.version == 0) {
if (sb->version == 0) {
printf(
"dev.cache.first_bucket\t%u\n"
"dev.cache.first_sector\t%u\n"
"dev.cache.discard\t%s\n",
sb.first_bucket,
sb.bucket_size * sb.first_bucket,
CACHE_DISCARD(&sb) ? "yes" : "no");
} else if (sb.version == CACHE_BACKING_DEV) {
sb->first_bucket,
sb->bucket_size * sb->first_bucket,
CACHE_DISCARD(sb) ? "yes" : "no");
} else if (sb->version == BCACHE_SB_VERSION_BDEV) {
printf(
"dev.data.first_sector\t%u\n"
"dev.data.writeback\t%s\n",
BDEV_DATA_START,
BDEV_WRITEBACK(&sb) ? "yes" : "no");
BDEV_DATA_START_DEFAULT,
BDEV_WRITEBACK(sb) ? "yes" : "no");
} else if (sb->version == BCACHE_SB_VERSION_BDEV_WITH_OFFSET) {
printf(
"dev.data.first_sector\t%lu\n"
"dev.data.writeback\t%s\n",
sb->d[0],
BDEV_WRITEBACK(sb) ? "yes" : "no");
}
putchar('\n');

uuid_unparse(sb.set_uuid, uuid);
uuid_unparse(sb->set_uuid, uuid);
printf("cset.uuid\t\t%s\n", uuid);

printf("cset.cache_count\t%u\n\n", sb.nr_in_set);
printf("cset.cache_count\t%u\n\n", sb->nr_in_set);

free(sb);
return 0;
}
24 changes: 16 additions & 8 deletions bcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,29 @@ static const char bcache_magic[] = {
0xc6, 0x85, 0x73, 0xf6, 0x4e, 0x1a, 0x45, 0xca,
0x82, 0x65, 0xf5, 0x7f, 0x48, 0xba, 0x6d, 0x81 };

/* Version 1: Backing dev
/* Version 0: Cache device
* Version 1: Backing device
* Version 2: Seed pointer into btree node checksum
* Version 3: Backing dev superblock has offset of start of data
* Version 3: Cache device with new UUID format
* Version 4: Backing device with data offset
*/

#define BCACHE_SB_BDEV_VERSION 3
#define BCACHE_SB_MAX_VERSION 3
#define BCACHE_SB_VERSION_CDEV 0
#define BCACHE_SB_VERSION_BDEV 1
#define BCACHE_SB_VERSION_CDEV_WITH_UUID 3
#define BCACHE_SB_VERSION_BDEV_WITH_OFFSET 4
#define BCACHE_SB_MAX_VERSION 4

#define SB_SECTOR 8
#define SB_LABEL_SIZE 32
#define BDEV_DATA_START 16 /* sectors */
#define BDEV_DATA_START_DEFAULT 16 /* sectors */
#define SB_START (SB_SECTOR * 512)
#define SB_SIZE 4096


struct cache_sb {
uint64_t csum;
uint64_t offset; /* sector where this sb was written */
uint64_t version;
#define CACHE_BACKING_DEV 1

uint8_t magic[16];

Expand Down Expand Up @@ -61,7 +66,10 @@ struct cache_sb {
uint64_t d[]; /* journal buckets */
};

BITMASK(SB_BDEV, struct cache_sb, version, 0, 1);
static inline bool SB_IS_BDEV(const struct cache_sb *sb) {
return sb->version == BCACHE_SB_VERSION_BDEV
|| sb->version == BCACHE_SB_VERSION_BDEV_WITH_OFFSET;
}

BITMASK(BDEV_WRITEBACK, struct cache_sb, flags, 0, 1);

Expand Down
47 changes: 25 additions & 22 deletions make-bcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ void usage()
" -B, --bdev Format a backing device\n"
" -b, --bucket bucket size\n"
" -w, --block block size (hard sector size of SSD, often 2k)\n"
" -o, --data-offset data offset in sectors\n"
" -U UUID\n"
" --writeback enable writeback\n"
" --discard enable discards\n"
Expand All @@ -154,7 +155,7 @@ const char * const cache_replacement_policies[] = {
int writeback;
int discard;
unsigned cache_replacement_policy;
uint64_t data_offset = BDEV_DATA_START;
uint64_t data_offset = BDEV_DATA_START_DEFAULT;

struct option opts[] = {
{ "cache", 0, NULL, 'C' },
Expand All @@ -164,7 +165,7 @@ struct option opts[] = {
{ "writeback", 0, &writeback, 1 },
{ "discard", 0, &discard, 1 },
{ "cache_replacement_policy", 1, NULL, 'p' },
// { "data_offset", 1, NULL, 'o' },
{ "data-offset", 1, NULL, 'o' },
{ "help", 0, NULL, 'h' },
{ NULL, 0, NULL, 0 },
};
Expand All @@ -191,13 +192,15 @@ void write_sb(char *dev, struct cache_sb *sb)

sb->flags = 0;

if (SB_BDEV(sb)) {
if (SB_IS_BDEV(sb)) {
SET_BDEV_WRITEBACK(sb, writeback);

if (data_offset != BDEV_DATA_START) {
sb->version = BCACHE_SB_BDEV_VERSION;
if (data_offset != BDEV_DATA_START_DEFAULT) {
sb->version = BCACHE_SB_VERSION_BDEV_WITH_OFFSET;
sb->keys = 1;
sb->d[0] = data_offset;
} else {
sb->version = BCACHE_SB_VERSION_BDEV;
}
} else {
SET_CACHE_DISCARD(sb, discard);
Expand Down Expand Up @@ -235,7 +238,7 @@ void write_sb(char *dev, struct cache_sb *sb)
sb->nr_this_dev,
sb->first_bucket);

if (pwrite(fd, sb, sizeof(*sb), SB_SECTOR << 9) != sizeof(*sb)) {
if (pwrite(fd, sb, SB_SIZE, SB_START) != SB_SIZE) {
perror("write error\n");
exit(EXIT_FAILURE);
}
Expand All @@ -250,34 +253,33 @@ int main(int argc, char **argv)
{
bool written = false;
int c;
struct cache_sb sb;
struct cache_sb *sb = calloc(1, SB_SIZE);

memset(&sb, 0, sizeof(struct cache_sb));
sb.version = -1;
sb.block_size = 1;
sb.bucket_size = 1024;
sb->version = -1;
sb->block_size = 1;
sb->bucket_size = 1024;

uuid_generate(sb.uuid);
uuid_generate(sb.set_uuid);
uuid_generate(sb->uuid);
uuid_generate(sb->set_uuid);

while ((c = getopt_long(argc, argv,
"-hCBU:w:b:",
"-hoCBU:w:b:",
opts, NULL)) != -1)
switch (c) {
case 'C':
sb.version = 0;
sb->version = 0;
break;
case 'B':
sb.version = CACHE_BACKING_DEV;
sb->version = BCACHE_SB_VERSION_BDEV;
break;
case 'b':
sb.bucket_size = hatoi_validate(optarg, "bucket size");
sb->bucket_size = hatoi_validate(optarg, "bucket size");
break;
case 'w':
sb.block_size = hatoi_validate(optarg, "block size");
sb->block_size = hatoi_validate(optarg, "block size");
break;
case 'U':
if (uuid_parse(optarg, sb.uuid)) {
if (uuid_parse(optarg, sb->uuid)) {
printf("Bad uuid\n");
exit(EXIT_FAILURE);
}
Expand All @@ -288,16 +290,16 @@ int main(int argc, char **argv)
break;
case 'o':
data_offset = atoll(optarg);
if (sb.d[0] < BDEV_DATA_START) {
printf("Bad data offset; minimum %d sectors\n", BDEV_DATA_START);
if (data_offset < BDEV_DATA_START_DEFAULT) {
printf("Bad data offset; minimum %d sectors\n", BDEV_DATA_START_DEFAULT);
exit(EXIT_FAILURE);
}
break;
case 'h':
usage();
break;
case 1:
write_sb(optarg, &sb);
write_sb(optarg, sb);
written = true;
break;
}
Expand All @@ -307,5 +309,6 @@ int main(int argc, char **argv)
usage();
}

free(sb);
return 0;
}
10 changes: 5 additions & 5 deletions probe-bcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ int main(int argc, char **argv)
bool udev = false;
int i, o;
extern char *optarg;
struct cache_sb sb;
struct cache_sb *sb = calloc(1, SB_SIZE);
char uuid[40];

while ((o = getopt(argc, argv, "o:")) != EOF)
Expand All @@ -45,14 +45,13 @@ int main(int argc, char **argv)
if (fd == -1)
continue;


if (pread(fd, &sb, sizeof(sb), 4096) != sizeof(sb))
if (pread(fd, sb, SB_SIZE, SB_START) != SB_SIZE)
continue;

if (memcmp(sb.magic, bcache_magic, 16))
if (memcmp(sb->magic, bcache_magic, 16))
continue;

uuid_unparse(sb.uuid, uuid);
uuid_unparse(sb->uuid, uuid);

if (udev)
printf("ID_FS_UUID=%s\n"
Expand All @@ -63,5 +62,6 @@ int main(int argc, char **argv)
printf("%s: UUID=\"\" TYPE=\"bcache\"\n", uuid);
}

free(sb);
return 0;
}

0 comments on commit e524e29

Please sign in to comment.