]> git.sesse.net Git - bcachefs-tools-debian/commitdiff
Update bcachefs sources to 9d554fa16d bcachefs: Add .to_text() methods for all superb...
authorKent Overstreet <kent.overstreet@gmail.com>
Mon, 21 Feb 2022 10:38:44 +0000 (05:38 -0500)
committerKent Overstreet <kent.overstreet@gmail.com>
Mon, 21 Feb 2022 10:38:44 +0000 (05:38 -0500)
19 files changed:
.bcachefs_revision
libbcachefs/alloc_background.c
libbcachefs/dirent.c
libbcachefs/disk_groups.c
libbcachefs/disk_groups.h
libbcachefs/extents.c
libbcachefs/journal_io.c
libbcachefs/journal_reclaim.c
libbcachefs/journal_seq_blacklist.c
libbcachefs/quota.c
libbcachefs/recovery.c
libbcachefs/replicas.c
libbcachefs/replicas.h
libbcachefs/super-io.c
libbcachefs/super-io.h
libbcachefs/sysfs.c
libbcachefs/util.c
libbcachefs/util.h
libbcachefs/xattr.c

index 5165b9d2b99308532358b131aa9a4df176dc4769..b537d89b7b1633070c9676a4453fbf34ccc4f62a 100644 (file)
@@ -1 +1 @@
-7d0925084b6927ad8c631bde92fb1c41cc6270c2
+9d554fa16def4f6310d2df74092c5568419e69e3
index 023db6219ad878f8106b439895adf7d8f362a358..4afb2d457fb09cbf92a1f078f5e64fe3c7d1bfc1 100644 (file)
@@ -794,7 +794,8 @@ static int push_invalidated_bucket(struct bch_fs *c, struct bch_dev *ca, u64 b)
 
 static void discard_one_bucket(struct bch_fs *c, struct bch_dev *ca, u64 b)
 {
-       if (ca->mi.discard &&
+       if (!c->opts.nochanges &&
+           ca->mi.discard &&
            blk_queue_discard(bdev_get_queue(ca->disk_sb.bdev)))
                blkdev_issue_discard(ca->disk_sb.bdev, bucket_to_sector(ca, b),
                                     ca->mi.bucket_size, GFP_NOFS, 0);
index 6f699b736b348e366b6c1e43567cf7a65c78b8a4..a43a24409d37d627c8f0214acb87157519717de9 100644 (file)
@@ -122,9 +122,9 @@ void bch2_dirent_to_text(struct printbuf *out, struct bch_fs *c,
 {
        struct bkey_s_c_dirent d = bkey_s_c_to_dirent(k);
 
-       bch_scnmemcpy(out, d.v->d_name,
-                     bch2_dirent_name_bytes(d));
-       pr_buf(out, " -> %llu type %s",
+       pr_buf(out, "%.*s -> %llu type %s",
+              bch2_dirent_name_bytes(d),
+              d.v->d_name,
               d.v->d_type != DT_SUBVOL
               ? le64_to_cpu(d.v->d_inum)
               : le32_to_cpu(d.v->d_child_subvol),
index 6c84297ef265f0810f71f3288a8d8fbab69e936e..19698e504b3cb9fb27c673ef36e11cd2491a49ea 100644 (file)
@@ -76,8 +76,9 @@ static int bch2_sb_disk_groups_validate(struct bch_sb *sb,
        for (g = sorted; g + 1 < sorted + nr_groups; g++)
                if (!BCH_GROUP_DELETED(g) &&
                    !group_cmp(&g[0], &g[1])) {
-                       pr_buf(err, "duplicate label %llu.", BCH_GROUP_PARENT(g));
-                       bch_scnmemcpy(err, g->label, strnlen(g->label, sizeof(g->label)));
+                       pr_buf(err, "duplicate label %llu.%.*s",
+                              BCH_GROUP_PARENT(g),
+                              (int) sizeof(g->label), g->label);
                        goto err;
                }
 
@@ -342,12 +343,10 @@ int bch2_disk_path_find_or_create(struct bch_sb_handle *sb, const char *name)
        return v;
 }
 
-void bch2_disk_path_to_text(struct printbuf *out,
-                           struct bch_sb_handle *sb,
-                           unsigned v)
+void bch2_disk_path_to_text(struct printbuf *out, struct bch_sb *sb, unsigned v)
 {
        struct bch_sb_field_disk_groups *groups =
-               bch2_sb_get_disk_groups(sb->sb);
+               bch2_sb_get_disk_groups(sb);
        struct bch_disk_group *g;
        unsigned nr = 0;
        u16 path[32];
@@ -376,15 +375,13 @@ void bch2_disk_path_to_text(struct printbuf *out,
                v = path[--nr];
                g = groups->entries + v;
 
-               bch_scnmemcpy(out, g->label,
-                             strnlen(g->label, sizeof(g->label)));
-
+               pr_buf(out, "%.*s", (int) sizeof(g->label), g->label);
                if (nr)
                        pr_buf(out, ".");
        }
        return;
 inval:
-       pr_buf(out, "invalid group %u", v);
+       pr_buf(out, "invalid label %u", v);
 }
 
 int bch2_dev_group_set(struct bch_fs *c, struct bch_dev *ca, const char *name)
@@ -448,6 +445,36 @@ int bch2_opt_target_parse(struct bch_fs *c, const char *buf, u64 *v)
        return -EINVAL;
 }
 
+void bch2_sb_target_to_text(struct printbuf *out, struct bch_sb *sb, u64 v)
+{
+       struct target t = target_decode(v);
+
+       switch (t.type) {
+       case TARGET_NULL:
+               pr_buf(out, "none");
+               break;
+       case TARGET_DEV: {
+               struct bch_sb_field_members *mi = bch2_sb_get_members(sb);
+               struct bch_member *m = mi->members + t.dev;
+
+               if (bch2_dev_exists(sb, mi, t.dev)) {
+                       pr_buf(out, "Device ");
+                       pr_uuid(out, m->uuid.b);
+                       pr_buf(out, " (%u)", t.dev);
+               } else {
+                       pr_buf(out, "Bad device %u", t.dev);
+               }
+
+               break;
+       }
+       case TARGET_GROUP:
+               bch2_disk_path_to_text(out, sb, t.group);
+               break;
+       default:
+               BUG();
+       }
+}
+
 void bch2_opt_target_to_text(struct printbuf *out, struct bch_fs *c, u64 v)
 {
        struct target t = target_decode(v);
@@ -481,7 +508,7 @@ void bch2_opt_target_to_text(struct printbuf *out, struct bch_fs *c, u64 v)
        }
        case TARGET_GROUP:
                mutex_lock(&c->sb_lock);
-               bch2_disk_path_to_text(out, &c->disk_sb, t.group);
+               bch2_disk_path_to_text(out, c->disk_sb.sb, t.group);
                mutex_unlock(&c->sb_lock);
                break;
        default:
index 3d84f23c34ed42ab2b13e7be4beafddceb3f7fbd..a274aacbdf921e5360aca39227f93488d49e5aa8 100644 (file)
@@ -75,8 +75,9 @@ int bch2_disk_path_find(struct bch_sb_handle *, const char *);
 /* Exported for userspace bcachefs-tools: */
 int bch2_disk_path_find_or_create(struct bch_sb_handle *, const char *);
 
-void bch2_disk_path_to_text(struct printbuf *, struct bch_sb_handle *,
-                           unsigned);
+void bch2_disk_path_to_text(struct printbuf *, struct bch_sb *, unsigned);
+
+void bch2_sb_target_to_text(struct printbuf *, struct bch_sb *, u64);
 
 int bch2_opt_target_parse(struct bch_fs *, const char *, u64 *);
 void bch2_opt_target_to_text(struct printbuf *, struct bch_fs *, u64);
index 44c584e9adaa8691a6335e10b70dab66e9a2bd0d..cc50e4b28882c703c5a80ab58e545e4e41aeeb40 100644 (file)
@@ -954,15 +954,19 @@ void bch2_bkey_ptrs_to_text(struct printbuf *out, struct bch_fs *c,
                switch (__extent_entry_type(entry)) {
                case BCH_EXTENT_ENTRY_ptr:
                        ptr = entry_to_ptr(entry);
-                       ca = ptr->dev < c->sb.nr_devices && c->devs[ptr->dev]
-                               ? bch_dev_bkey_exists(c, ptr->dev)
-                               : NULL;
 
-                       pr_buf(out, "ptr: %u:%llu gen %u%s%s", ptr->dev,
+                       pr_buf(out, "ptr: %u:%llu gen %u%s", ptr->dev,
                               (u64) ptr->offset, ptr->gen,
-                              ptr->cached ? " cached" : "",
-                              ca && ptr_stale(ca, ptr)
-                              ? " stale" : "");
+                              ptr->cached ? " cached" : "");
+
+                       if (c) {
+                               ca = ptr->dev < c->sb.nr_devices && c->devs[ptr->dev]
+                                       ? bch_dev_bkey_exists(c, ptr->dev)
+                                       : NULL;
+
+                               if (ca && ptr_stale(ca, ptr))
+                                       pr_buf(out, " stale");
+                       }
                        break;
                case BCH_EXTENT_ENTRY_crc32:
                case BCH_EXTENT_ENTRY_crc64:
index 901e346684fb27ff9a2a82b728288dd2eb2fc496..05c1092620498c81bb42b07211bf1ecbec0d0f70 100644 (file)
@@ -303,7 +303,7 @@ static void journal_entry_btree_keys_to_text(struct printbuf *out, struct bch_fs
 
        vstruct_for_each(entry, k) {
                if (!first) {
-                       printbuf_newline(out);
+                       pr_newline(out);
                        pr_buf(out, "%s: ", bch2_jset_entry_types[entry->type]);
                }
                pr_buf(out, "btree=%s l=%u ", bch2_btree_ids[entry->btree_id], entry->level);
@@ -596,7 +596,7 @@ static void journal_entry_log_to_text(struct printbuf *out, struct bch_fs *c,
        struct jset_entry_log *l = container_of(entry, struct jset_entry_log, entry);
        unsigned bytes = vstruct_bytes(entry) - offsetof(struct jset_entry_log, d);
 
-       bch_scnmemcpy(out, l->d, strnlen(l->d, bytes));
+       pr_buf(out, "%.*s", bytes, l->d);
 }
 
 struct jset_entry_ops {
index 52a3935cff530748ce5d5adb55ed55411b1d80cb..9467191e182e6ff2e09625b54a2be11d8251630f 100644 (file)
@@ -286,7 +286,8 @@ void bch2_journal_do_discards(struct journal *j)
                struct journal_device *ja = &ca->journal;
 
                while (should_discard_bucket(j, ja)) {
-                       if (ca->mi.discard &&
+                       if (!c->opts.nochanges &&
+                           ca->mi.discard &&
                            blk_queue_discard(bdev_get_queue(ca->disk_sb.bdev)))
                                blkdev_issue_discard(ca->disk_sb.bdev,
                                        bucket_to_sector(ca,
index 3cc63fc202ab4cbc83017cb6cad4412720e03797..3140c8731431ea7d5966b7ab38e4c71dda8a1fe7 100644 (file)
@@ -235,6 +235,7 @@ static void bch2_sb_journal_seq_blacklist_to_text(struct printbuf *out,
                       le64_to_cpu(i->start),
                       le64_to_cpu(i->end));
        }
+       pr_newline(out);
 }
 
 const struct bch_sb_field_ops bch_sb_field_ops_journal_seq_blacklist = {
index 6fb8224f565e3a00a2960a5dde41f2182a0dbe5a..b7ef8fa7bbc98356db0a274b3b89e294c8206b9d 100644 (file)
@@ -6,7 +6,18 @@
 #include "subvolume.h"
 #include "super-io.h"
 
-static int bch2_sb_validate_quota(struct bch_sb *sb, struct bch_sb_field *f,
+static const char * const bch2_quota_types[] = {
+       "user",
+       "group",
+       "project",
+};
+
+static const char * const bch2_quota_counters[] = {
+       "space",
+       "inodes",
+};
+
+static int bch2_sb_quota_validate(struct bch_sb *sb, struct bch_sb_field *f,
                                  struct printbuf *err)
 {
        struct bch_sb_field_quota *q = field_to_type(f, quota);
@@ -14,13 +25,36 @@ static int bch2_sb_validate_quota(struct bch_sb *sb, struct bch_sb_field *f,
        if (vstruct_bytes(&q->field) < sizeof(*q)) {
                pr_buf(err, "wrong size (got %llu should be %zu)",
                       vstruct_bytes(&q->field), sizeof(*q));
+               return -EINVAL;
        }
 
        return 0;
 }
 
+static void bch2_sb_quota_to_text(struct printbuf *out, struct bch_sb *sb,
+                                 struct bch_sb_field *f)
+{
+       struct bch_sb_field_quota *q = field_to_type(f, quota);
+       unsigned qtyp, counter;
+
+       for (qtyp = 0; qtyp < ARRAY_SIZE(q->q); qtyp++) {
+               pr_buf(out, "%s: flags %llx",
+                      bch2_quota_types[qtyp],
+                      le64_to_cpu(q->q[qtyp].flags));
+
+               for (counter = 0; counter < Q_COUNTERS; counter++)
+                       pr_buf(out, " %s timelimit %u warnlimit %u",
+                              bch2_quota_counters[counter],
+                              le32_to_cpu(q->q[qtyp].c[counter].timelimit),
+                              le32_to_cpu(q->q[qtyp].c[counter].warnlimit));
+
+               pr_newline(out);
+       }
+}
+
 const struct bch_sb_field_ops bch_sb_field_ops_quota = {
-       .validate       = bch2_sb_validate_quota,
+       .validate       = bch2_sb_quota_validate,
+       .to_text        = bch2_sb_quota_to_text,
 };
 
 const char *bch2_quota_invalid(const struct bch_fs *c, struct bkey_s_c k)
@@ -34,11 +68,6 @@ const char *bch2_quota_invalid(const struct bch_fs *c, struct bkey_s_c k)
        return NULL;
 }
 
-static const char * const bch2_quota_counters[] = {
-       "space",
-       "inodes",
-};
-
 void bch2_quota_to_text(struct printbuf *out, struct bch_fs *c,
                        struct bkey_s_c k)
 {
index 96f13f2e7a9ae063579b4218ee4477d05f373fc5..ed25595275fcb05e6f4e0d312d7276ed56c3660e 100644 (file)
@@ -803,7 +803,7 @@ static struct bch_sb_field_clean *read_superblock_clean(struct bch_fs *c)
                return ERR_PTR(-ENOMEM);
        }
 
-       ret = bch2_sb_clean_validate(c, clean, READ);
+       ret = bch2_sb_clean_validate_late(c, clean, READ);
        if (ret) {
                mutex_unlock(&c->sb_lock);
                return ERR_PTR(ret);
index 96994b7a75a555699fc0aa2c2745f8353cdeeaba..6c1d42f1c92c0b5ced7a1c3d4204b266c1adfb7e 100644 (file)
@@ -36,6 +36,22 @@ static void bch2_cpu_replicas_sort(struct bch_replicas_cpu *r)
        eytzinger0_sort(r->entries, r->nr, r->entry_size, memcmp, NULL);
 }
 
+void bch2_replicas_entry_v0_to_text(struct printbuf *out,
+                                   struct bch_replicas_entry_v0 *e)
+{
+       unsigned i;
+
+       if (e->data_type < BCH_DATA_NR)
+               pr_buf(out, "%s", bch2_data_types[e->data_type]);
+       else
+               pr_buf(out, "(invalid data type %u)", e->data_type);
+
+       pr_buf(out, ": %u [", e->nr_devs);
+       for (i = 0; i < e->nr_devs; i++)
+               pr_buf(out, i ? " %u" : "%u", e->devs[i]);
+       pr_buf(out, "]");
+}
+
 void bch2_replicas_entry_to_text(struct printbuf *out,
                                 struct bch_replicas_entry *e)
 {
@@ -860,7 +876,7 @@ static int bch2_cpu_replicas_validate(struct bch_replicas_cpu *cpu_r,
        return 0;
 }
 
-static int bch2_sb_validate_replicas(struct bch_sb *sb, struct bch_sb_field *f,
+static int bch2_sb_replicas_validate(struct bch_sb *sb, struct bch_sb_field *f,
                                     struct printbuf *err)
 {
        struct bch_sb_field_replicas *sb_r = field_to_type(f, replicas);
@@ -890,14 +906,15 @@ static void bch2_sb_replicas_to_text(struct printbuf *out,
 
                bch2_replicas_entry_to_text(out, e);
        }
+       pr_newline(out);
 }
 
 const struct bch_sb_field_ops bch_sb_field_ops_replicas = {
-       .validate       = bch2_sb_validate_replicas,
+       .validate       = bch2_sb_replicas_validate,
        .to_text        = bch2_sb_replicas_to_text,
 };
 
-static int bch2_sb_validate_replicas_v0(struct bch_sb *sb, struct bch_sb_field *f,
+static int bch2_sb_replicas_v0_validate(struct bch_sb *sb, struct bch_sb_field *f,
                                        struct printbuf *err)
 {
        struct bch_sb_field_replicas_v0 *sb_r = field_to_type(f, replicas_v0);
@@ -912,8 +929,27 @@ static int bch2_sb_validate_replicas_v0(struct bch_sb *sb, struct bch_sb_field *
        return ret;
 }
 
+static void bch2_sb_replicas_v0_to_text(struct printbuf *out,
+                                       struct bch_sb *sb,
+                                       struct bch_sb_field *f)
+{
+       struct bch_sb_field_replicas_v0 *sb_r = field_to_type(f, replicas_v0);
+       struct bch_replicas_entry_v0 *e;
+       bool first = true;
+
+       for_each_replicas_entry(sb_r, e) {
+               if (!first)
+                       pr_buf(out, " ");
+               first = false;
+
+               bch2_replicas_entry_v0_to_text(out, e);
+       }
+       pr_newline(out);
+}
+
 const struct bch_sb_field_ops bch_sb_field_ops_replicas_v0 = {
-       .validate       = bch2_sb_validate_replicas_v0,
+       .validate       = bch2_sb_replicas_v0_validate,
+       .to_text        = bch2_sb_replicas_v0_to_text,
 };
 
 /* Query replicas: */
@@ -970,19 +1006,42 @@ bool bch2_have_enough_devs(struct bch_fs *c, struct bch_devs_mask devs,
        return ret;
 }
 
-unsigned bch2_dev_has_data(struct bch_fs *c, struct bch_dev *ca)
+unsigned bch2_sb_dev_has_data(struct bch_sb *sb, unsigned dev)
 {
-       struct bch_replicas_entry *e;
-       unsigned i, ret = 0;
+       struct bch_sb_field_replicas *replicas;
+       struct bch_sb_field_replicas_v0 *replicas_v0;
+       unsigned i, data_has = 0;
+
+       replicas = bch2_sb_get_replicas(sb);
+       replicas_v0 = bch2_sb_get_replicas_v0(sb);
+
+       if (replicas) {
+               struct bch_replicas_entry *r;
+
+               for_each_replicas_entry(replicas, r)
+                       for (i = 0; i < r->nr_devs; i++)
+                               if (r->devs[i] == dev)
+                                       data_has |= 1 << r->data_type;
+       } else if (replicas_v0) {
+               struct bch_replicas_entry_v0 *r;
+
+               for_each_replicas_entry_v0(replicas_v0, r)
+                       for (i = 0; i < r->nr_devs; i++)
+                               if (r->devs[i] == dev)
+                                       data_has |= 1 << r->data_type;
+       }
 
-       percpu_down_read(&c->mark_lock);
 
-       for_each_cpu_replicas_entry(&c->replicas, e)
-               for (i = 0; i < e->nr_devs; i++)
-                       if (e->devs[i] == ca->dev_idx)
-                               ret |= 1 << e->data_type;
+       return data_has;
+}
 
-       percpu_up_read(&c->mark_lock);
+unsigned bch2_dev_has_data(struct bch_fs *c, struct bch_dev *ca)
+{
+       unsigned ret;
+
+       mutex_lock(&c->sb_lock);
+       ret = bch2_sb_dev_has_data(c->disk_sb.sb, ca->dev_idx);
+       mutex_unlock(&c->sb_lock);
 
        return ret;
 }
index d237d7c51ccb9b9faa771e72ba123fb505914c16..87820b2e1ad3e1322216aba57da1e083d6d49d37 100644 (file)
@@ -64,6 +64,7 @@ static inline void bch2_replicas_entry_cached(struct bch_replicas_entry *e,
 bool bch2_have_enough_devs(struct bch_fs *, struct bch_devs_mask,
                           unsigned, bool);
 
+unsigned bch2_sb_dev_has_data(struct bch_sb *, unsigned);
 unsigned bch2_dev_has_data(struct bch_fs *, struct bch_dev *);
 
 int bch2_replicas_gc_end(struct bch_fs *, int);
index eae63184ead2330cd36e60eedbc401b3a0aade3d..08613a73cb54a43338d2ab051d3e9d06e25b36ac 100644 (file)
@@ -918,7 +918,7 @@ static int u64_cmp(const void *_l, const void *_r)
        return l < r ? -1 : l > r ? 1 : 0;
 }
 
-static int bch2_sb_validate_journal(struct bch_sb *sb,
+static int bch2_sb_journal_validate(struct bch_sb *sb,
                                    struct bch_sb_field *f,
                                    struct printbuf *err)
 {
@@ -971,13 +971,26 @@ err:
        return ret;
 }
 
+static void bch2_sb_journal_to_text(struct printbuf *out, struct bch_sb *sb,
+                                   struct bch_sb_field *f)
+{
+       struct bch_sb_field_journal *journal = field_to_type(f, journal);
+       unsigned i, nr = bch2_nr_journal_buckets(journal);
+
+       pr_buf(out, "Buckets: ");
+       for (i = 0; i < nr; i++)
+               pr_buf(out, " %llu", le64_to_cpu(journal->buckets[i]));
+       pr_newline(out);
+}
+
 static const struct bch_sb_field_ops bch_sb_field_ops_journal = {
-       .validate       = bch2_sb_validate_journal,
+       .validate       = bch2_sb_journal_validate,
+       .to_text        = bch2_sb_journal_to_text,
 };
 
 /* BCH_SB_FIELD_members: */
 
-static int bch2_sb_validate_members(struct bch_sb *sb,
+static int bch2_sb_members_validate(struct bch_sb *sb,
                                    struct bch_sb_field *f,
                                    struct printbuf *err)
 {
@@ -1027,13 +1040,105 @@ static int bch2_sb_validate_members(struct bch_sb *sb,
        return 0;
 }
 
+static void bch2_sb_members_to_text(struct printbuf *out, struct bch_sb *sb,
+                                   struct bch_sb_field *f)
+{
+       struct bch_sb_field_members *mi = field_to_type(f, members);
+       struct bch_sb_field_disk_groups *gi = bch2_sb_get_disk_groups(sb);
+       unsigned i;
+
+       for (i = 0; i < sb->nr_devices; i++) {
+               struct bch_member *m = mi->members + i;
+               unsigned data_have = bch2_sb_dev_has_data(sb, i);
+               u64 bucket_size = le16_to_cpu(m->bucket_size);
+               u64 device_size = le64_to_cpu(m->nbuckets) * bucket_size;
+
+               if (!bch2_member_exists(m))
+                       continue;
+
+               pr_buf(out, "Device:                  %u", i);
+               pr_newline(out);
+
+               printbuf_indent_push(out, 2);
+
+               pr_buf(out, "UUID:                  ");
+               pr_uuid(out, m->uuid.b);
+               pr_newline(out);
+
+               pr_buf(out, "Size:                  ");
+               pr_units(out, device_size, device_size << 9);
+               pr_newline(out);
+
+               pr_buf(out, "Bucket size:           ");
+               pr_units(out, bucket_size, bucket_size << 9);
+               pr_newline(out);
+
+               pr_buf(out, "First bucket:          %u",
+                      le16_to_cpu(m->first_bucket));
+               pr_newline(out);
+
+               pr_buf(out, "Buckets:               %llu",
+                      le64_to_cpu(m->nbuckets));
+               pr_newline(out);
+
+               pr_buf(out, "Last mount:            ");
+               if (m->last_mount)
+                       pr_time(out, le64_to_cpu(m->last_mount));
+               else
+                       pr_buf(out, "(never)");
+               pr_newline(out);
+
+               pr_buf(out, "State:                 %s",
+                      BCH_MEMBER_STATE(m) < BCH_MEMBER_STATE_NR
+                      ? bch2_member_states[BCH_MEMBER_STATE(m)]
+                      : "unknown");
+               pr_newline(out);
+
+               pr_buf(out, "Group:                 ");
+               if (BCH_MEMBER_GROUP(m)) {
+                       unsigned idx = BCH_MEMBER_GROUP(m) - 1;
+
+                       if (idx < disk_groups_nr(gi))
+                               pr_buf(out, "%s (%u)",
+                                      gi->entries[idx].label, idx);
+                       else
+                               pr_buf(out, "(bad disk labels section)");
+               } else {
+                       pr_buf(out, "(none)");
+               }
+               pr_newline(out);
+
+               pr_buf(out, "Data allowed:          ");
+               if (BCH_MEMBER_DATA_ALLOWED(m))
+                       bch2_flags_to_text(out, bch2_data_types,
+                                          BCH_MEMBER_DATA_ALLOWED(m));
+               else
+                       pr_buf(out, "(none)");
+               pr_newline(out);
+
+               pr_buf(out, "Has data:              ");
+               if (data_have)
+                       bch2_flags_to_text(out, bch2_data_types, data_have);
+               else
+                       pr_buf(out, "(none)");
+               pr_newline(out);
+
+               pr_buf(out, "Discard:               %llu",
+                      BCH_MEMBER_DISCARD(m));
+               pr_newline(out);
+
+               printbuf_indent_pop(out, 2);
+       }
+}
+
 static const struct bch_sb_field_ops bch_sb_field_ops_members = {
-       .validate       = bch2_sb_validate_members,
+       .validate       = bch2_sb_members_validate,
+       .to_text        = bch2_sb_members_to_text,
 };
 
 /* BCH_SB_FIELD_crypt: */
 
-static int bch2_sb_validate_crypt(struct bch_sb *sb,
+static int bch2_sb_crypt_validate(struct bch_sb *sb,
                                  struct bch_sb_field *f,
                                  struct printbuf *err)
 {
@@ -1053,13 +1158,29 @@ static int bch2_sb_validate_crypt(struct bch_sb *sb,
        return 0;
 }
 
+static void bch2_sb_crypt_to_text(struct printbuf *out, struct bch_sb *sb,
+                                 struct bch_sb_field *f)
+{
+       struct bch_sb_field_crypt *crypt = field_to_type(f, crypt);
+
+       pr_buf(out, "KFD:               %llu", BCH_CRYPT_KDF_TYPE(crypt));
+       pr_newline(out);
+       pr_buf(out, "scrypt n:          %llu", BCH_KDF_SCRYPT_N(crypt));
+       pr_newline(out);
+       pr_buf(out, "scrypt r:          %llu", BCH_KDF_SCRYPT_R(crypt));
+       pr_newline(out);
+       pr_buf(out, "scrypt p:          %llu", BCH_KDF_SCRYPT_P(crypt));
+       pr_newline(out);
+}
+
 static const struct bch_sb_field_ops bch_sb_field_ops_crypt = {
-       .validate       = bch2_sb_validate_crypt,
+       .validate       = bch2_sb_crypt_validate,
+       .to_text        = bch2_sb_crypt_to_text,
 };
 
 /* BCH_SB_FIELD_clean: */
 
-int bch2_sb_clean_validate(struct bch_fs *c, struct bch_sb_field_clean *clean, int write)
+int bch2_sb_clean_validate_late(struct bch_fs *c, struct bch_sb_field_clean *clean, int write)
 {
        struct jset_entry *entry;
        int ret;
@@ -1248,7 +1369,7 @@ void bch2_fs_mark_clean(struct bch_fs *c)
         * this should be in the write path, and we should be validating every
         * superblock section:
         */
-       ret = bch2_sb_clean_validate(c, sb_clean, WRITE);
+       ret = bch2_sb_clean_validate_late(c, sb_clean, WRITE);
        if (ret) {
                bch_err(c, "error writing marking filesystem clean: validate error");
                goto out;
@@ -1259,7 +1380,7 @@ out:
        mutex_unlock(&c->sb_lock);
 }
 
-static int bch2_sb_validate_clean(struct bch_sb *sb,
+static int bch2_sb_clean_validate(struct bch_sb *sb,
                                  struct bch_sb_field *f,
                                  struct printbuf *err)
 {
@@ -1274,8 +1395,32 @@ static int bch2_sb_validate_clean(struct bch_sb *sb,
        return 0;
 }
 
+static void bch2_sb_clean_to_text(struct printbuf *out, struct bch_sb *sb,
+                                 struct bch_sb_field *f)
+{
+       struct bch_sb_field_clean *clean = field_to_type(f, clean);
+       struct jset_entry *entry;
+
+       pr_buf(out, "flags:          %x",       le32_to_cpu(clean->flags));
+       pr_newline(out);
+       pr_buf(out, "journal_seq:    %llu",     le64_to_cpu(clean->journal_seq));
+       pr_newline(out);
+
+       for (entry = clean->start;
+            entry != vstruct_end(&clean->field);
+            entry = vstruct_next(entry)) {
+               if (entry->type == BCH_JSET_ENTRY_btree_keys &&
+                   !entry->u64s)
+                       continue;
+
+               bch2_journal_entry_to_text(out, NULL, entry);
+               pr_newline(out);
+       }
+}
+
 static const struct bch_sb_field_ops bch_sb_field_ops_clean = {
-       .validate       = bch2_sb_validate_clean,
+       .validate       = bch2_sb_clean_validate,
+       .to_text        = bch2_sb_clean_to_text,
 };
 
 static const struct bch_sb_field_ops *bch2_sb_field_ops[] = {
@@ -1299,7 +1444,7 @@ static int bch2_sb_field_validate(struct bch_sb *sb, struct bch_sb_field *f,
 
        ret = bch2_sb_field_ops[type]->validate(sb, f, &err);
        if (ret) {
-               pr_buf(&err, "\n");
+               pr_newline(&err);
                bch2_sb_field_to_text(&err, sb, f);
                *orig_err = err;
        }
@@ -1320,7 +1465,202 @@ void bch2_sb_field_to_text(struct printbuf *out, struct bch_sb *sb,
                pr_buf(out, "(unknown field %u)", type);
 
        pr_buf(out, " (size %llu):", vstruct_bytes(f));
+       pr_newline(out);
 
-       if (ops && ops->to_text)
+       if (ops && ops->to_text) {
+               printbuf_indent_push(out, 2);
                bch2_sb_field_ops[type]->to_text(out, sb, f);
+               printbuf_indent_pop(out, 2);
+       }
+}
+
+void bch2_sb_layout_to_text(struct printbuf *out, struct bch_sb_layout *l)
+{
+       unsigned i;
+
+       pr_buf(out, "Type:                    %u", l->layout_type);
+       pr_newline(out);
+
+       pr_buf(out, "Superblock max size:     ");
+       pr_units(out,
+                1 << l->sb_max_size_bits,
+                512 << l->sb_max_size_bits);
+       pr_newline(out);
+
+       pr_buf(out, "Nr superblocks:          %u", l->nr_superblocks);
+       pr_newline(out);
+
+       pr_buf(out, "Offsets:                 ");
+       for (i = 0; i < l->nr_superblocks; i++) {
+               if (i)
+                       pr_buf(out, ", ");
+               pr_buf(out, "%llu", le64_to_cpu(l->sb_offset[i]));
+       }
+       pr_newline(out);
+}
+
+void bch2_sb_to_text(struct printbuf *out, struct bch_sb *sb,
+                    bool print_layout, unsigned fields)
+{
+       struct bch_sb_field_members *mi;
+       struct bch_sb_field *f;
+       u64 fields_have = 0;
+       unsigned nr_devices = 0;
+
+       mi = bch2_sb_get_members(sb);
+       if (mi) {
+               struct bch_member *m;
+
+               for (m = mi->members;
+                    m < mi->members + sb->nr_devices;
+                    m++)
+                       nr_devices += bch2_member_exists(m);
+       }
+
+       pr_buf(out, "External UUID:             ");
+       pr_uuid(out, sb->user_uuid.b);
+       pr_newline(out);
+
+       pr_buf(out, "Internal UUID:             ");
+       pr_uuid(out, sb->uuid.b);
+       pr_newline(out);
+
+       pr_buf(out, "Device index:              %u", sb->dev_idx);
+       pr_newline(out);
+
+       pr_buf(out, "Label:                     ");
+       pr_buf(out, "%.*s", (int) sizeof(sb->label), sb->label);
+       pr_newline(out);
+
+       pr_buf(out, "Version:                   %u", le16_to_cpu(sb->version));
+       pr_newline(out);
+
+       pr_buf(out, "Oldest version on disk:    %u", le16_to_cpu(sb->version_min));
+       pr_newline(out);
+
+       pr_buf(out, "Created:                   ");
+       if (sb->time_base_lo)
+               pr_time(out, le64_to_cpu(sb->time_base_lo) / NSEC_PER_SEC);
+       else
+               pr_buf(out, "(not set)");
+       pr_newline(out);
+
+       pr_buf(out, "Squence number:            %llu", le64_to_cpu(sb->seq));
+       pr_newline(out);
+
+       pr_buf(out, "Block_size:                ");
+       pr_units(out, le16_to_cpu(sb->block_size),
+                (u32) le16_to_cpu(sb->block_size) << 9);
+       pr_newline(out);
+
+       pr_buf(out, "Btree node size:           ");
+       pr_units(out, BCH_SB_BTREE_NODE_SIZE(sb),
+                BCH_SB_BTREE_NODE_SIZE(sb) << 9);
+       pr_newline(out);
+
+       pr_buf(out, "Error action:              %s",
+              BCH_SB_ERROR_ACTION(sb) < BCH_ON_ERROR_NR
+              ? bch2_error_actions[BCH_SB_ERROR_ACTION(sb)]
+              : "unknown");
+       pr_newline(out);
+
+       pr_buf(out, "Clean:                     %llu", BCH_SB_CLEAN(sb));
+       pr_newline(out);
+
+       pr_buf(out, "Features:                  ");
+       bch2_flags_to_text(out, bch2_sb_features,
+                          le64_to_cpu(sb->features[0]));
+       pr_newline(out);
+
+       pr_buf(out, "Compat features:           ");
+       bch2_flags_to_text(out, bch2_sb_compat,
+                          le64_to_cpu(sb->compat[0]));
+       pr_newline(out);
+
+       pr_buf(out, "Metadata replicas:         %llu", BCH_SB_META_REPLICAS_WANT(sb));
+       pr_newline(out);
+
+       pr_buf(out, "Data replicas:             %llu", BCH_SB_DATA_REPLICAS_WANT(sb));
+       pr_newline(out);
+
+       pr_buf(out, "Metadata checksum type:    %s (%llu)",
+              BCH_SB_META_CSUM_TYPE(sb) < BCH_CSUM_OPT_NR
+              ? bch2_csum_opts[BCH_SB_META_CSUM_TYPE(sb)]
+              : "unknown",
+              BCH_SB_META_CSUM_TYPE(sb));
+       pr_newline(out);
+
+       pr_buf(out, "Data checksum type:        %s (%llu)",
+              BCH_SB_DATA_CSUM_TYPE(sb) < BCH_CSUM_OPT_NR
+              ? bch2_csum_opts[BCH_SB_DATA_CSUM_TYPE(sb)]
+              : "unknown",
+              BCH_SB_DATA_CSUM_TYPE(sb));
+       pr_newline(out);
+
+       pr_buf(out, "Compression type:          %s (%llu)",
+              BCH_SB_COMPRESSION_TYPE(sb) < BCH_COMPRESSION_OPT_NR
+              ? bch2_compression_opts[BCH_SB_COMPRESSION_TYPE(sb)]
+              : "unknown",
+              BCH_SB_COMPRESSION_TYPE(sb));
+       pr_newline(out);
+
+       pr_buf(out, "Foreground write target:   ");
+       bch2_sb_target_to_text(out, sb, BCH_SB_FOREGROUND_TARGET(sb));
+       pr_newline(out);
+
+       pr_buf(out, "Background write target:   ");
+       bch2_sb_target_to_text(out, sb, BCH_SB_BACKGROUND_TARGET(sb));
+       pr_newline(out);
+
+       pr_buf(out, "Promote target:            ");
+       bch2_sb_target_to_text(out, sb, BCH_SB_PROMOTE_TARGET(sb));
+       pr_newline(out);
+
+       pr_buf(out, "Metadata target:           ");
+       bch2_sb_target_to_text(out, sb, BCH_SB_METADATA_TARGET(sb));
+       pr_newline(out);
+
+       pr_buf(out, "String hash type:          %s (%llu)",
+              BCH_SB_STR_HASH_TYPE(sb) < BCH_STR_HASH_NR
+              ? bch2_str_hash_types[BCH_SB_STR_HASH_TYPE(sb)]
+              : "unknown",
+              BCH_SB_STR_HASH_TYPE(sb));
+       pr_newline(out);
+
+       pr_buf(out, "32 bit inodes:             %llu", BCH_SB_INODE_32BIT(sb));
+       pr_newline(out);
+
+       pr_buf(out, "GC reserve percentage:     %llu%%", BCH_SB_GC_RESERVE(sb));
+       pr_newline(out);
+
+       pr_buf(out, "Root reserve percentage:   %llu%%", BCH_SB_ROOT_RESERVE(sb));
+       pr_newline(out);
+
+       pr_buf(out, "Devices:                   %u live, %u total",
+              nr_devices, sb->nr_devices);
+       pr_newline(out);
+
+       pr_buf(out, "Sections:                  ");
+       vstruct_for_each(sb, f)
+               fields_have |= 1 << le32_to_cpu(f->type);
+       bch2_flags_to_text(out, bch2_sb_fields, fields_have);
+       pr_newline(out);
+
+       pr_buf(out, "Superblock size:           %llu", vstruct_bytes(sb));
+       pr_newline(out);
+
+       if (print_layout) {
+               pr_newline(out);
+               pr_buf(out, "layout:");
+               pr_newline(out);
+               printbuf_indent_push(out, 2);
+               bch2_sb_layout_to_text(out, &sb->layout);
+               printbuf_indent_pop(out, 2);
+       }
+
+       vstruct_for_each(sb, f)
+               if (fields & (1 << le32_to_cpu(f->type))) {
+                       pr_newline(out);
+                       bch2_sb_field_to_text(out, sb, f);
+               }
 }
index 3b425bed17c48c51a552ae0e2b8e73bde01a91c3..50f31a3b9b1845208a23921f32f2db9a71389006 100644 (file)
@@ -121,12 +121,14 @@ static inline struct bch_member_cpu bch2_mi_to_cpu(struct bch_member *mi)
 void bch2_journal_super_entries_add_common(struct bch_fs *,
                                           struct jset_entry **, u64);
 
-int bch2_sb_clean_validate(struct bch_fs *, struct bch_sb_field_clean *, int);
+int bch2_sb_clean_validate_late(struct bch_fs *, struct bch_sb_field_clean *, int);
 
 int bch2_fs_mark_dirty(struct bch_fs *);
 void bch2_fs_mark_clean(struct bch_fs *);
 
 void bch2_sb_field_to_text(struct printbuf *, struct bch_sb *,
                           struct bch_sb_field *);
+void bch2_sb_layout_to_text(struct printbuf *, struct bch_sb_layout *);
+void bch2_sb_to_text(struct printbuf *, struct bch_sb *, bool, unsigned);
 
 #endif /* _BCACHEFS_SUPER_IO_H */
index b727845dd64b73d4ea51fe8842c9f03ca899ad23..1a3068f658a1ffd5eea1bd850a3ffe419fe1fbed 100644 (file)
@@ -825,7 +825,7 @@ SHOW(bch2_dev)
        if (attr == &sysfs_label) {
                if (ca->mi.group) {
                        mutex_lock(&c->sb_lock);
-                       bch2_disk_path_to_text(&out, &c->disk_sb,
+                       bch2_disk_path_to_text(&out, c->disk_sb.sb,
                                               ca->mi.group - 1);
                        mutex_unlock(&c->sb_lock);
                }
index 0bbea332fcaaf7cecc6ce62695fe0367c011bab2..ab808fe4d64dbf4f393f69fbbcda01db8071a217 100644 (file)
@@ -120,6 +120,27 @@ void bch2_hprint(struct printbuf *buf, s64 v)
                pr_buf(buf, "%c", si_units[u]);
 }
 
+void bch2_pr_units(struct printbuf *out, s64 raw, s64 bytes)
+{
+       if (raw < 0) {
+               pr_buf(out, "-");
+               raw     = -raw;
+               bytes   = -bytes;
+       }
+
+       switch (out->units) {
+       case PRINTBUF_UNITS_RAW:
+               pr_buf(out, "%llu", raw);
+               break;
+       case PRINTBUF_UNITS_BYTES:
+               pr_buf(out, "%llu", bytes);
+               break;
+       case PRINTBUF_UNITS_HUMAN_READABLE:
+               bch2_hprint(out, bytes);
+               break;
+       }
+}
+
 void bch2_string_opt_to_text(struct printbuf *out,
                             const char * const list[],
                             size_t selected)
@@ -579,19 +600,6 @@ void memcpy_from_bio(void *dst, struct bio *src, struct bvec_iter src_iter)
        }
 }
 
-void bch_scnmemcpy(struct printbuf *out,
-                  const char *src, size_t len)
-{
-       size_t n = printbuf_remaining(out);
-
-       if (n) {
-               n = min(n - 1, len);
-               memcpy(out->pos, src, n);
-               out->pos += n;
-               *out->pos = '\0';
-       }
-}
-
 #include "eytzinger.h"
 
 static int alignment_ok(const void *base, size_t align)
index e55407dc53249d1a93106cd9e4b37c9df74b523e..b43c195381f89c8b1a03805a07653a19d0a4a170 100644 (file)
@@ -235,10 +235,17 @@ do {                                                                      \
 #define ANYSINT_MAX(t)                                                 \
        ((((t) 1 << (sizeof(t) * 8 - 2)) - (t) 1) * (t) 2 + (t) 1)
 
+enum printbuf_units {
+       PRINTBUF_UNITS_RAW,
+       PRINTBUF_UNITS_BYTES,
+       PRINTBUF_UNITS_HUMAN_READABLE,
+};
+
 struct printbuf {
-       char            *pos;
-       char            *end;
-       unsigned        indent;
+       char                    *pos;
+       char                    *end;
+       unsigned                indent;
+       enum printbuf_units     units;
 };
 
 static inline size_t printbuf_remaining(struct printbuf *buf)
@@ -272,7 +279,7 @@ static inline void printbuf_indent_pop(struct printbuf *buf, unsigned spaces)
        buf->indent -= spaces;
 }
 
-static inline void printbuf_newline(struct printbuf *buf)
+static inline void pr_newline(struct printbuf *buf)
 {
        unsigned i;
 
@@ -281,7 +288,45 @@ static inline void printbuf_newline(struct printbuf *buf)
                pr_buf(buf, " ");
 }
 
-void bch_scnmemcpy(struct printbuf *, const char *, size_t);
+void bch2_pr_units(struct printbuf *, s64, s64);
+#define pr_units(...) bch2_pr_units(__VA_ARGS__)
+
+#ifdef __KERNEL__
+static inline void pr_time(struct printbuf *out, u64 time)
+{
+       pr_buf(out, "%llu", time);
+}
+#else
+#include <time.h>
+static inline void pr_time(struct printbuf *out, u64 _time)
+{
+       char time_str[64];
+       time_t time = _time;
+       struct tm *tm = localtime(&time);
+       size_t err = strftime(time_str, sizeof(time_str), "%c", tm);
+       if (!err)
+               pr_buf(out, "(formatting error)");
+       else
+               pr_buf(out, "%s", time_str);
+}
+#endif
+
+#ifdef __KERNEL__
+static inline void uuid_unparse_lower(u8 *uuid, char *out)
+{
+       sprintf(out, "%plU", uuid);
+}
+#else
+#include <uuid/uuid.h>
+#endif
+
+static inline void pr_uuid(struct printbuf *out, u8 *uuid)
+{
+       char uuid_str[40];
+
+       uuid_unparse_lower(uuid, uuid_str);
+       pr_buf(out, uuid_str);
+}
 
 int bch2_strtoint_h(const char *, int *);
 int bch2_strtouint_h(const char *, unsigned int *);
@@ -768,13 +813,4 @@ static inline int u8_cmp(u8 l, u8 r)
        return cmp_int(l, r);
 }
 
-#ifdef __KERNEL__
-static inline void uuid_unparse_lower(u8 *uuid, char *out)
-{
-       sprintf(out, "%plU", uuid);
-}
-#else
-#include <uuid/uuid.h>
-#endif
-
 #endif /* _BCACHEFS_UTIL_H */
index 4d7db64e3ef3085602c7017618b411f281a06b6b..1673654fff3e8490244871a5bc5ce99845dce145 100644 (file)
@@ -111,11 +111,11 @@ void bch2_xattr_to_text(struct printbuf *out, struct bch_fs *c,
        else
                pr_buf(out, "(unknown type %u)", xattr.v->x_type);
 
-       bch_scnmemcpy(out, xattr.v->x_name,
-                     xattr.v->x_name_len);
-       pr_buf(out, ":");
-       bch_scnmemcpy(out, xattr_val(xattr.v),
-                     le16_to_cpu(xattr.v->x_val_len));
+       pr_buf(out, "%.*s:%.*s",
+              xattr.v->x_name_len,
+              xattr.v->x_name,
+              le16_to_cpu(xattr.v->x_val_len),
+              (char *) xattr_val(xattr.v));
 }
 
 static int bch2_xattr_get_trans(struct btree_trans *trans, struct bch_inode_info *inode,