]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
bcache device_show now dumps superblocks
authorKent Overstreet <kent.overstreet@gmail.com>
Tue, 4 Oct 2016 09:10:24 +0000 (01:10 -0800)
committerKent Overstreet <kent.overstreet@gmail.com>
Thu, 6 Oct 2016 14:52:54 +0000 (06:52 -0800)
Makefile
bcache-device.c
bcache-key.c
bcache-ondisk.h
bcache.c
bcache.h
libbcache.c
libbcache.h
util.c
util.h

index 9f2773ec39c1609af40405826f48d2d88746d3f6..9b3bdcc2c3f55582b83e054c123a7051835831e3 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -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
index 1f6f15745db13c061ddc86ef21a83d320d124159..a349e7901332b09dfd9dc3418d4cc911dbb57eea 100644 (file)
 #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[])
 {
index 34005454a5273ea12f75ef32fe6f9cd7fe158d17..cac0948215fc28fc21ae3407ee30933cd6343735 100644 (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),
index 4ceb10bb2113bcf3c24bbc4ecbb7932a032af472..f737511fd6c6df73f2feb0044ea7e9f1badd539e 100644 (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:
index 532194d157b560c8bd83285734a4c9f7052e5013..04955b34c857c3d7cea8f27a5fb7e7471f726123 100644 (file)
--- a/bcache.c
+++ b/bcache.c
 
 #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"
index 69d3edc3da9de70b2bcab589ef05da9b5990cab7..949f60947b9e8f4e840f845da328948febf430a7 100644 (file)
--- a/bcache.h
+++ b/bcache.h
@@ -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[]);
index f17bd4ad4d677a373bbc15468847f4c542a0c4c1..865b780edad33364919e375ffaba0dc283324a2e 100644 (file)
 #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;
 }
index ccfa37cbb003ad6106f2bf93f566cd794c37293e..920a9c51c5a5186749e55735670210e64ac55ea6 100644 (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 */
diff --git a/util.c b/util.c
index bd332b5bda9ae63a51e02804ea6361d20c253a4e..d30693c15100d679a262157c57d48772d35a06c4 100644 (file)
--- a/util.c
+++ b/util.c
@@ -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)
diff --git a/util.h b/util.h
index 463416a9cf6c8a0baa2dbf3d81dc388048d804cf..a8e18f90b46c668713a90c8bb7e181576b121d29 100644 (file)
--- a/util.h
+++ b/util.h
@@ -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 *);