bcachefs: Track sectors of erasure coded data
authorKent Overstreet <kent.overstreet@gmail.com>
Fri, 19 Jun 2020 01:06:42 +0000 (21:06 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:42 +0000 (17:08 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/bcachefs_ioctl.h
fs/bcachefs/buckets.c
fs/bcachefs/buckets_types.h
fs/bcachefs/chardev.c
fs/bcachefs/sysfs.c

index d7f25e52dc719101f3d7af36660265d4c6336ff9..923001188a88ebe29d071c4708b11c89de8298a6 100644 (file)
@@ -275,9 +275,13 @@ struct bch_ioctl_dev_usage {
 
        __u32                   bucket_size;
        __u64                   nr_buckets;
+       __u64                   available_buckets;
 
        __u64                   buckets[BCH_DATA_NR];
        __u64                   sectors[BCH_DATA_NR];
+
+       __u64                   ec_buckets;
+       __u64                   ec_sectors;
 };
 
 /*
index 1ae9403847cae33a831505fae14c42d69901a817..1198c7bbeab9ceed29339c3e6b6cdacfa319626b 100644 (file)
@@ -374,6 +374,11 @@ static inline int is_fragmented_bucket(struct bucket_mark m,
        return 0;
 }
 
+static inline int bucket_stripe_sectors(struct bucket_mark m)
+{
+       return m.stripe ? m.dirty_sectors : 0;
+}
+
 static inline enum bch_data_type bucket_type(struct bucket_mark m)
 {
        return m.cached_sectors && !m.dirty_sectors
@@ -443,30 +448,33 @@ static void bch2_dev_usage_update(struct bch_fs *c, struct bch_dev *ca,
                                  struct bucket_mark old, struct bucket_mark new,
                                  bool gc)
 {
-       struct bch_dev_usage *dev_usage;
+       struct bch_dev_usage *u;
 
        percpu_rwsem_assert_held(&c->mark_lock);
 
        preempt_disable();
-       dev_usage = this_cpu_ptr(ca->usage[gc]);
+       u = this_cpu_ptr(ca->usage[gc]);
 
        if (bucket_type(old))
-               account_bucket(fs_usage, dev_usage, bucket_type(old),
+               account_bucket(fs_usage, u, bucket_type(old),
                               -1, -ca->mi.bucket_size);
 
        if (bucket_type(new))
-               account_bucket(fs_usage, dev_usage, bucket_type(new),
+               account_bucket(fs_usage, u, bucket_type(new),
                               1, ca->mi.bucket_size);
 
-       dev_usage->buckets_ec += (int) new.stripe - (int) old.stripe;
-       dev_usage->buckets_unavailable +=
+       u->buckets_unavailable +=
                is_unavailable_bucket(new) - is_unavailable_bucket(old);
 
-       dev_usage->sectors[old.data_type] -= old.dirty_sectors;
-       dev_usage->sectors[new.data_type] += new.dirty_sectors;
-       dev_usage->sectors[BCH_DATA_CACHED] +=
+       u->buckets_ec += (int) new.stripe - (int) old.stripe;
+       u->sectors_ec += bucket_stripe_sectors(new) -
+                        bucket_stripe_sectors(old);
+
+       u->sectors[old.data_type] -= old.dirty_sectors;
+       u->sectors[new.data_type] += new.dirty_sectors;
+       u->sectors[BCH_DATA_CACHED] +=
                (int) new.cached_sectors - (int) old.cached_sectors;
-       dev_usage->sectors_fragmented +=
+       u->sectors_fragmented +=
                is_fragmented_bucket(new, ca) - is_fragmented_bucket(old, ca);
        preempt_enable();
 
index 172b0ccf2b4fc75ef103186fd5bb818b924e40de..b64b2fc9a896c448dc2560f2e23eb05f8af71da6 100644 (file)
@@ -52,12 +52,14 @@ struct bucket_array {
 
 struct bch_dev_usage {
        u64                     buckets[BCH_DATA_NR];
-       u64                     buckets_ec;
        u64                     buckets_unavailable;
 
        /* _compressed_ sectors: */
        u64                     sectors[BCH_DATA_NR];
        u64                     sectors_fragmented;
+
+       u64                     buckets_ec;
+       u64                     sectors_ec;
 };
 
 struct bch_fs_usage {
index 084bef5e7997e1ce209591ac25b1ae627e758b70..b46d32db4b581590b8c22a03623a8f70663f2dad 100644 (file)
@@ -470,9 +470,12 @@ static long bch2_ioctl_dev_usage(struct bch_fs *c,
 
        src = bch2_dev_usage_read(c, ca);
 
-       arg.state       = ca->mi.state;
-       arg.bucket_size = ca->mi.bucket_size;
-       arg.nr_buckets  = ca->mi.nbuckets - ca->mi.first_bucket;
+       arg.state               = ca->mi.state;
+       arg.bucket_size         = ca->mi.bucket_size;
+       arg.nr_buckets          = ca->mi.nbuckets - ca->mi.first_bucket;
+       arg.available_buckets   = arg.nr_buckets - src.buckets_unavailable;
+       arg.ec_buckets          = src.buckets_ec;
+       arg.ec_sectors          = src.sectors_ec;
 
        for (i = 0; i < BCH_DATA_NR; i++) {
                arg.buckets[i] = src.buckets[i];
index 67c0f6d2b219ee51de9799e2eaff87ef05fd01c9..30be49eb5da6eba6653f7c448b39a42138a8cbfc 100644 (file)
@@ -845,6 +845,7 @@ static ssize_t show_dev_alloc_debug(struct bch_dev *ca, char *buf)
                "    meta:               %llu\n"
                "    user:               %llu\n"
                "    cached:             %llu\n"
+               "    erasure coded:      %llu\n"
                "    fragmented:         %llu\n"
                "    copygc threshold:   %llu\n"
                "freelist_wait:          %s\n"
@@ -870,6 +871,7 @@ static ssize_t show_dev_alloc_debug(struct bch_dev *ca, char *buf)
                stats.sectors[BCH_DATA_BTREE],
                stats.sectors[BCH_DATA_USER],
                stats.sectors[BCH_DATA_CACHED],
+               stats.sectors_ec,
                stats.sectors_fragmented,
                ca->copygc_threshold,
                c->freelist_wait.list.first             ? "waiting" : "empty",