bcache device_show now dumps superblocks

This commit is contained in:
Kent Overstreet 2016-10-04 01:10:24 -08:00
parent 837a476cc1
commit f3a8d54837
10 changed files with 312 additions and 104 deletions

View File

@ -6,7 +6,7 @@ LDFLAGS+=-static
PKGCONFIG_LIBS="blkid uuid libnih"
CFLAGS+=`pkg-config --cflags ${PKGCONFIG_LIBS}`
LDLIBS+=`pkg-config --libs ${PKGCONFIG_LIBS}` -lscrypt -lsodium -lkeyutils
LDLIBS+=`pkg-config --libs ${PKGCONFIG_LIBS}` -lscrypt -lsodium -lkeyutils -lm
ifeq ($(PREFIX),/usr)
ROOT_SBINDIR=/sbin

View File

@ -16,6 +16,10 @@
#include <nih/option.h>
#include "bcache.h"
#include "libbcache.h"
/* This code belongs under show_fs */
#if 0
struct bcache_dev {
unsigned nr;
@ -162,6 +166,20 @@ int cmd_device_show(int argc, char *argv[])
return 0;
}
#endif
int cmd_device_show(int argc, char *argv[])
{
struct cache_sb *sb;
if (argc != 2)
die("please supply a single device");
sb = bcache_super_read(argv[1]);
bcache_super_print(sb, HUMAN_READABLE);
return 0;
}
int cmd_device_add(int argc, char *argv[])
{

View File

@ -18,7 +18,7 @@ int cmd_unlock(int argc, char *argv[])
struct bcache_disk_key disk_key;
struct bcache_key key;
struct cache_sb sb;
struct cache_sb *sb;
char *passphrase;
char uuid[40];
char description[60];
@ -26,12 +26,12 @@ int cmd_unlock(int argc, char *argv[])
if (!args[0] || args[1])
die("please supply a single device");
bcache_super_read(args[0], &sb);
sb = bcache_super_read(args[0]);
if (!CACHE_SET_ENCRYPTION_KEY(&sb))
if (!CACHE_SET_ENCRYPTION_KEY(sb))
die("filesystem is not encrypted");
memcpy(&disk_key, sb.encryption_key, sizeof(disk_key));
memcpy(&disk_key, sb->encryption_key, sizeof(disk_key));
if (!memcmp(&disk_key, bch_key_header, sizeof(bch_key_header)))
die("filesystem does not have encryption key");
@ -39,12 +39,12 @@ int cmd_unlock(int argc, char *argv[])
passphrase = read_passphrase("Enter passphrase: ");
derive_passphrase(&key, passphrase);
disk_key_encrypt(&sb, &disk_key, &key);
disk_key_encrypt(sb, &disk_key, &key);
if (memcmp(&disk_key, bch_key_header, sizeof(bch_key_header)))
die("incorrect passphrase");
uuid_unparse_lower(sb.user_uuid.b, uuid);
uuid_unparse_lower(sb->user_uuid.b, uuid);
sprintf(description, "bcache:%s", uuid);
if (add_key("logon", description, &key, sizeof(key),

View File

@ -670,6 +670,7 @@ LE64_BITMASK(CACHE_STATE, struct cache_member, f1, 0, 4)
#define CACHE_RO 1U
#define CACHE_FAILED 2U
#define CACHE_SPARE 3U
#define CACHE_STATE_NR 4U
LE64_BITMASK(CACHE_TIER, struct cache_member, f1, 4, 8)
#define CACHE_TIERS 4U
@ -683,6 +684,7 @@ LE64_BITMASK(CACHE_REPLACEMENT, struct cache_member, f1, 26, 30)
#define CACHE_REPLACEMENT_LRU 0U
#define CACHE_REPLACEMENT_FIFO 1U
#define CACHE_REPLACEMENT_RANDOM 2U
#define CACHE_REPLACEMENT_NR 3U
LE64_BITMASK(CACHE_DISCARD, struct cache_member, f1, 30, 31);
@ -770,18 +772,7 @@ LE64_BITMASK(CACHE_SET_META_CSUM_TYPE,struct cache_sb, flags, 16, 20);
#define BCH_CSUM_NONE 0U
#define BCH_CSUM_CRC32C 1U
#define BCH_CSUM_CRC64 2U
#define BCH_CSUM_CHACHA20_POLY1305 3U
#define BCH_CSUM_NR 4U
static inline _Bool bch_csum_type_is_encryption(unsigned type)
{
switch (type) {
case BCH_CSUM_CHACHA20_POLY1305:
return 1;
default:
return 0;
}
}
#define BCH_CSUM_NR 3U
LE64_BITMASK(CACHE_SET_BTREE_NODE_SIZE, struct cache_sb, flags, 20, 36);
@ -816,6 +807,12 @@ LE64_BITMASK(CACHE_SET_GC_RESERVE, struct cache_sb, flags, 57, 63);
LE64_BITMASK(CACHE_SET_ROOT_RESERVE, struct cache_sb, flags2, 0, 6);
/*
* Did we shut down cleanly? Just a hint, doesn't affect behaviour of
* mount/recovery path:
*/
LE64_BITMASK(CACHE_SET_CLEAN, struct cache_sb, flags2, 6, 7);
/*
* If nonzero, encryption is enabled; overrides DATA/META_CSUM_TYPE. Also
* indicates encryption algorithm in use, if/when we get more than one:

View File

@ -23,58 +23,6 @@
#include "bcache.h"
const char * const cache_state[] = {
"active",
"ro",
"failed",
"spare",
NULL
};
const char * const replacement_policies[] = {
"lru",
"fifo",
"random",
NULL
};
const char * const csum_types[] = {
"none",
"crc32c",
"crc64",
NULL
};
const char * const compression_types[] = {
"none",
"lz4",
"gzip",
NULL
};
const char * const error_actions[] = {
"continue",
"readonly",
"panic",
NULL
};
const char * const bdev_cache_mode[] = {
"writethrough",
"writeback",
"writearound",
"none",
NULL
};
const char * const bdev_state[] = {
"detached",
"clean",
"dirty",
"inconsistent",
NULL
};
static void usage(void)
{
puts("bcache - tool for managing bcache volumes/filesystems\n"

View File

@ -9,14 +9,6 @@
#include "util.h"
extern const char * const cache_state[];
extern const char * const replacement_policies[];
extern const char * const csum_types[];
extern const char * const compression_types[];
extern const char * const error_actions[];
extern const char * const bdev_cache_mode[];
extern const char * const bdev_state[];
int cmd_format(int argc, char *argv[]);
int cmd_unlock(int argc, char *argv[]);

View File

@ -17,6 +17,74 @@
#include "libbcache.h"
#include "crypto.h"
const char * const cache_state[] = {
"active",
"ro",
"failed",
"spare",
NULL
};
const char * const replacement_policies[] = {
"lru",
"fifo",
"random",
NULL
};
const char * const csum_types[] = {
"none",
"crc32c",
"crc64",
NULL
};
const char * const compression_types[] = {
"none",
"lz4",
"gzip",
NULL
};
const char * const str_hash_types[] = {
"crc32c",
"crc64",
"siphash",
"sha1",
NULL
};
const char * const error_actions[] = {
"continue",
"readonly",
"panic",
NULL
};
const char * const member_states[] = {
"active",
"ro",
"failed",
"spare",
NULL
};
const char * const bdev_cache_mode[] = {
"writethrough",
"writeback",
"writearound",
"none",
NULL
};
const char * const bdev_state[] = {
"detached",
"clean",
"dirty",
"inconsistent",
NULL
};
#define BCH_MIN_NR_NBUCKETS (1 << 10)
/* first bucket should start 1 mb in, in sectors: */
@ -187,48 +255,155 @@ void bcache_format(struct dev_opts *devs, size_t nr_devs,
for (i = devs; i < devs + nr_devs; i++) {
struct cache_member *m = sb->members + (i - devs);
char uuid_str[40], set_uuid_str[40];
sb->disk_uuid = m->uuid;
sb->nr_this_dev = i - devs;
sb->csum = __cpu_to_le64(__csum_set(sb, __le16_to_cpu(sb->u64s),
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,
__le64_to_cpu(m->nbuckets),
__le16_to_cpu(sb->block_size),
__le16_to_cpu(m->bucket_size),
sb->nr_in_set,
sb->nr_this_dev,
__le16_to_cpu(m->first_bucket));
do_write_sb(i->fd, sb);
}
bcache_super_print(sb, HUMAN_READABLE);
free(sb);
}
void bcache_super_read(const char *path, struct cache_sb *sb)
void bcache_super_print(struct cache_sb *sb, int units)
{
unsigned i;
char user_uuid_str[40], internal_uuid_str[40], member_uuid_str[40];
char label[SB_LABEL_SIZE + 1];
memset(label, 0, sizeof(label));
memcpy(label, sb->label, sizeof(sb->label));
uuid_unparse(sb->user_uuid.b, user_uuid_str);
uuid_unparse(sb->set_uuid.b, internal_uuid_str);
printf("External UUID: %s\n"
"Internal UUID: %s\n"
"Label: %s\n"
"Version: %llu\n"
"Block_size: %s\n"
"Btree node size: %s\n"
"Error action: %s\n"
"Clean: %llu\n"
"Metadata replicas: have %llu, want %llu\n"
"Data replicas: have %llu, want %llu\n"
"Metadata checksum type: %s\n"
"Data checksum type: %s\n"
"Compression type: %s\n"
"String hash type: %s\n"
"32 bit inodes: %llu\n"
"GC reserve percentage: %llu%%\n"
"Root reserve percentage: %llu%%\n"
"Devices: %u\n",
user_uuid_str,
internal_uuid_str,
label,
le64_to_cpu(sb->version),
pr_units(le16_to_cpu(sb->block_size), units).b,
pr_units(CACHE_SET_BTREE_NODE_SIZE(sb), units).b,
CACHE_SET_ERROR_ACTION(sb) < BCH_NR_ERROR_ACTIONS
? error_actions[CACHE_SET_ERROR_ACTION(sb)]
: "unknown",
CACHE_SET_CLEAN(sb),
CACHE_SET_META_REPLICAS_HAVE(sb),
CACHE_SET_META_REPLICAS_WANT(sb),
CACHE_SET_DATA_REPLICAS_HAVE(sb),
CACHE_SET_DATA_REPLICAS_WANT(sb),
CACHE_SET_META_CSUM_TYPE(sb) < BCH_CSUM_NR
? csum_types[CACHE_SET_META_CSUM_TYPE(sb)]
: "unknown",
CACHE_SET_DATA_CSUM_TYPE(sb) < BCH_CSUM_NR
? csum_types[CACHE_SET_DATA_CSUM_TYPE(sb)]
: "unknown",
CACHE_SET_COMPRESSION_TYPE(sb) < BCH_COMPRESSION_NR
? compression_types[CACHE_SET_COMPRESSION_TYPE(sb)]
: "unknown",
CACHE_SET_STR_HASH_TYPE(sb) < BCH_STR_HASH_NR
? str_hash_types[CACHE_SET_STR_HASH_TYPE(sb)]
: "unknown",
CACHE_INODE_32BIT(sb),
CACHE_SET_GC_RESERVE(sb),
CACHE_SET_ROOT_RESERVE(sb),
sb->nr_in_set);
for (i = 0; i < sb->nr_in_set; i++) {
struct cache_member *m = sb->members + i;
time_t last_mount = le64_to_cpu(m->last_mount);
uuid_unparse(m->uuid.b, member_uuid_str);
printf("\n"
"Device %u:\n"
" UUID: %s\n"
" bucket_size: %s\n"
" first_bucket: %u\n"
" nbuckets: %llu\n"
" Last mount: %s\n"
" State: %s\n"
" Tier: %llu\n"
" Has metadata: %llu\n"
" Has data: %llu\n"
" Replacement policy: %s\n"
" Discard: %llu\n",
i, member_uuid_str,
pr_units(le16_to_cpu(m->bucket_size), units).b,
le16_to_cpu(m->first_bucket),
le64_to_cpu(m->nbuckets),
last_mount ? ctime(&last_mount) : "(never)",
CACHE_STATE(m) < CACHE_STATE_NR
? member_states[CACHE_STATE(m)]
: "unknown",
CACHE_TIER(m),
CACHE_HAS_METADATA(m),
CACHE_HAS_DATA(m),
CACHE_REPLACEMENT(m) < CACHE_REPLACEMENT_NR
? replacement_policies[CACHE_REPLACEMENT(m)]
: "unknown",
CACHE_DISCARD(m));
}
}
struct cache_sb *bcache_super_read(const char *path)
{
struct cache_sb sb, *ret;
size_t bytes;
int fd = open(path, O_RDONLY);
if (fd < 0)
die("couldn't open %s", path);
if (pread(fd, sb, sizeof(*sb), SB_SECTOR << 9) != sizeof(*sb))
if (pread(fd, &sb, sizeof(sb), SB_SECTOR << 9) != sizeof(sb))
die("error reading superblock");
if (memcmp(&sb->magic, &BCACHE_MAGIC, sizeof(sb->magic)))
if (memcmp(&sb.magic, &BCACHE_MAGIC, sizeof(sb.magic)))
die("not a bcache superblock");
bytes = sizeof(sb) + le16_to_cpu(sb.u64s) * sizeof(u64);
ret = calloc(1, bytes);
if (pread(fd, ret, bytes, SB_SECTOR << 9) != bytes)
die("error reading superblock");
return ret;
}

View File

@ -4,6 +4,15 @@
#include "util.h"
#include "stdbool.h"
extern const char * const cache_state[];
extern const char * const replacement_policies[];
extern const char * const csum_types[];
extern const char * const compression_types[];
extern const char * const str_hash_types[];
extern const char * const error_actions[];
extern const char * const bdev_cache_mode[];
extern const char * const bdev_state[];
struct dev_opts {
int fd;
const char *path;
@ -29,6 +38,8 @@ void bcache_format(struct dev_opts *devs, size_t nr_devs,
char *label,
uuid_le uuid);
void bcache_super_read(const char *, struct cache_sb *);
void bcache_super_print(struct cache_sb *, int);
struct cache_sb *bcache_super_read(const char *);
#endif /* _LIBBCACHE_H */

30
util.c
View File

@ -4,6 +4,7 @@
#include <fcntl.h>
#include <limits.h>
#include <linux/fs.h>
#include <math.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
@ -69,6 +70,35 @@ char *strim(char *s)
return s;
}
struct units_buf pr_units(u64 v, enum units units)
{
struct units_buf ret;
switch (units) {
case BYTES:
snprintf(ret.b, sizeof(ret.b), "%llu", v << 9);
break;
case SECTORS:
snprintf(ret.b, sizeof(ret.b), "%llu", v);
break;
case HUMAN_READABLE:
v <<= 9;
if (v >= 1024) {
int exp = log(v) / log(1024);
snprintf(ret.b, sizeof(ret.b), "%.1f%c",
v / pow(1024, exp),
"KMGTPE"[exp-1]);
} else {
snprintf(ret.b, sizeof(ret.b), "%llu", v);
}
break;
}
return ret;
}
/* Argument parsing stuff: */
long strtoul_or_die(const char *p, size_t max, const char *msg)

37
util.h
View File

@ -9,6 +9,7 @@
/* linux kernel style types: */
#include <asm/types.h>
#include <asm/byteorder.h>
typedef __u8 u8;
typedef __u16 u16;
@ -20,6 +21,29 @@ typedef __s16 s16;
typedef __s32 s32;
typedef __s64 s64;
#define cpu_to_le16 __cpu_to_le16
#define cpu_to_le32 __cpu_to_le32
#define cpu_to_le64 __cpu_to_le64
#define le16_to_cpu __le16_to_cpu
#define le32_to_cpu __le32_to_cpu
#define le64_to_cpu __le64_to_cpu
static inline void le16_add_cpu(__le16 *var, u16 val)
{
*var = cpu_to_le16(le16_to_cpu(*var) + val);
}
static inline void le32_add_cpu(__le32 *var, u32 val)
{
*var = cpu_to_le32(le32_to_cpu(*var) + val);
}
static inline void le64_add_cpu(__le64 *var, u64 val)
{
*var = cpu_to_le64(le64_to_cpu(*var) + val);
}
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
#define min(x, y) ({ \
@ -46,7 +70,20 @@ unsigned ilog2(u64);
char *skip_spaces(const char *str);
char *strim(char *s);
enum units {
BYTES,
SECTORS,
HUMAN_READABLE,
};
struct units_buf pr_units(u64, enum units);
struct units_buf {
char b[20];
};
long strtoul_or_die(const char *, size_t, const char *);
u64 hatoi(const char *);
unsigned hatoi_validate(const char *, const char *);
unsigned nr_args(char * const *);