bcachefs: Include summarized counts in fs_usage
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 1 Dec 2018 16:32:12 +0000 (11:32 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:13 +0000 (17:08 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_gc.c
fs/bcachefs/buckets.c
fs/bcachefs/buckets_types.h
fs/bcachefs/chardev.c
fs/bcachefs/sysfs.c

index 75ea243d4bbc04a7cc9e4b0cb24952450e260054..c353fbbed975ce0ade08c4a2dfff6a1606f71675 100644 (file)
@@ -482,6 +482,24 @@ static void bch2_gc_free(struct bch_fs *c)
        c->usage[1] = NULL;
 }
 
+static void fs_usage_reset(struct bch_fs_usage *fs_usage)
+{
+       unsigned offset = offsetof(typeof(*fs_usage), s.gc_start);
+
+       memset((void *) fs_usage + offset, 0,
+              sizeof(*fs_usage) - offset);
+}
+
+static void fs_usage_cpy(struct bch_fs_usage *dst,
+                        struct bch_fs_usage *src)
+{
+       unsigned offset = offsetof(typeof(*dst), s.gc_start);
+
+       memcpy((void *) dst + offset,
+              (void *) src + offset,
+              sizeof(*dst) - offset);
+}
+
 static void bch2_gc_done_nocheck(struct bch_fs *c)
 {
        struct bch_dev *ca;
@@ -530,17 +548,12 @@ static void bch2_gc_done_nocheck(struct bch_fs *c)
 
        {
                struct bch_fs_usage src = __bch2_fs_usage_read(c, 1);
-               struct bch_fs_usage *p;
 
-               for_each_possible_cpu(cpu) {
-                       p = per_cpu_ptr(c->usage[0], cpu);
-                       memset(p, 0, offsetof(typeof(*p), online_reserved));
-               }
+               for_each_possible_cpu(cpu)
+                       fs_usage_reset(per_cpu_ptr(c->usage[0], cpu));
 
                preempt_disable();
-               memcpy(this_cpu_ptr(c->usage[0]),
-                      &src,
-                      offsetof(typeof(*p), online_reserved));
+               fs_usage_cpy(this_cpu_ptr(c->usage[0]), &src);
                preempt_enable();
        }
 
@@ -668,9 +681,14 @@ static void bch2_gc_done(struct bch_fs *c, bool initial)
        {
                struct bch_fs_usage dst = __bch2_fs_usage_read(c, 0);
                struct bch_fs_usage src = __bch2_fs_usage_read(c, 1);
-               struct bch_fs_usage *p;
                unsigned r, b;
 
+               copy_fs_field(s.hidden,         "hidden");
+               copy_fs_field(s.data,           "data");
+               copy_fs_field(s.cached,         "cached");
+               copy_fs_field(s.reserved,       "reserved");
+               copy_fs_field(s.nr_inodes,      "nr_inodes");
+
                for (r = 0; r < BCH_REPLICAS_MAX; r++) {
                        for (b = 0; b < BCH_DATA_NR; b++)
                                copy_fs_field(replicas[r].data[b],
@@ -685,16 +703,12 @@ static void bch2_gc_done(struct bch_fs *c, bool initial)
                for (b = 0; b < BCH_DATA_NR; b++)
                        copy_fs_field(buckets[b],
                                      "buckets[%s]", bch2_data_types[b]);
-               copy_fs_field(nr_inodes, "nr_inodes");
 
-               for_each_possible_cpu(cpu) {
-                       p = per_cpu_ptr(c->usage[0], cpu);
-                       memset(p, 0, offsetof(typeof(*p), online_reserved));
-               }
+               for_each_possible_cpu(cpu)
+                       fs_usage_reset(per_cpu_ptr(c->usage[0], cpu));
 
                preempt_disable();
-               p = this_cpu_ptr(c->usage[0]);
-               memcpy(p, &dst, offsetof(typeof(*p), online_reserved));
+               fs_usage_cpy(this_cpu_ptr(c->usage[0]), &dst);
                preempt_enable();
        }
 out:
index c53d7a0308320717d402fa3f5267eab8efdcdcdb..16aafe8502a070dd2aa751d066cf060fd299a5bd 100644 (file)
@@ -106,9 +106,9 @@ static void bch2_fs_stats_verify(struct bch_fs *c)
                              bch_data_types[j],
                              stats.buckets[j]);
 
-       if ((s64) stats.online_reserved < 0)
+       if ((s64) stats.s.online_reserved < 0)
                panic("sectors_online_reserved underflow: %lli\n",
-                     stats.online_reserved);
+                     stats.s.online_reserved);
 }
 
 static void bch2_dev_stats_verify(struct bch_dev *ca)
@@ -228,38 +228,6 @@ struct bch_fs_usage bch2_fs_usage_read(struct bch_fs *c)
        return bch2_usage_read_raw(c->usage[0]);
 }
 
-struct fs_usage_sum {
-       u64     hidden;
-       u64     data;
-       u64     cached;
-       u64     reserved;
-};
-
-static inline struct fs_usage_sum __fs_usage_sum(struct bch_fs_usage stats)
-{
-       struct fs_usage_sum sum = { 0 };
-       unsigned i;
-
-       /*
-        * For superblock and journal we count bucket usage, not sector usage,
-        * because any internal fragmentation should _not_ be counted as
-        * free space:
-        */
-       sum.hidden += stats.buckets[BCH_DATA_SB];
-       sum.hidden += stats.buckets[BCH_DATA_JOURNAL];
-
-       for (i = 0; i < ARRAY_SIZE(stats.replicas); i++) {
-               sum.data        += stats.replicas[i].data[BCH_DATA_BTREE];
-               sum.data        += stats.replicas[i].data[BCH_DATA_USER];
-               sum.data        += stats.replicas[i].ec_data;
-               sum.cached      += stats.replicas[i].data[BCH_DATA_CACHED];
-               sum.reserved    += stats.replicas[i].persistent_reserved;
-       }
-
-       sum.reserved += stats.online_reserved;
-       return sum;
-}
-
 #define RESERVE_FACTOR 6
 
 static u64 reserve_factor(u64 r)
@@ -274,9 +242,10 @@ static u64 avail_factor(u64 r)
 
 static inline u64 __bch2_fs_sectors_used(struct bch_fs *c, struct bch_fs_usage fs_usage)
 {
-       struct fs_usage_sum sum = __fs_usage_sum(fs_usage);
-
-       return sum.hidden + sum.data + reserve_factor(sum.reserved);
+       return fs_usage.s.hidden +
+               fs_usage.s.data +
+               reserve_factor(fs_usage.s.reserved +
+                              fs_usage.s.online_reserved);
 }
 
 u64 bch2_fs_sectors_used(struct bch_fs *c, struct bch_fs_usage fs_usage)
@@ -287,13 +256,14 @@ u64 bch2_fs_sectors_used(struct bch_fs *c, struct bch_fs_usage fs_usage)
 struct bch_fs_usage_short
 bch2_fs_usage_read_short(struct bch_fs *c)
 {
-       struct bch_fs_usage usage = bch2_fs_usage_read(c);
-       struct fs_usage_sum sum = __fs_usage_sum(usage);
+       struct bch_fs_usage_summarized usage =
+               bch2_usage_read_raw(&c->usage[0]->s);
        struct bch_fs_usage_short ret;
 
-       ret.capacity    = READ_ONCE(c->capacity) - sum.hidden;
-       ret.used        = min(ret.capacity, sum.data +
-                             reserve_factor(sum.reserved));
+       ret.capacity    = READ_ONCE(c->capacity) - usage.hidden;
+       ret.used        = min(ret.capacity, usage.data +
+                             reserve_factor(usage.reserved +
+                                            usage.online_reserved));
        ret.nr_inodes   = usage.nr_inodes;
 
        return ret;
@@ -334,8 +304,7 @@ void bch2_fs_usage_apply(struct bch_fs *c,
                         struct disk_reservation *disk_res,
                         struct gc_pos gc_pos)
 {
-       struct fs_usage_sum sum = __fs_usage_sum(*fs_usage);
-       s64 added = sum.data + sum.reserved;
+       s64 added = fs_usage->s.data + fs_usage->s.reserved;
        s64 should_not_have_added;
 
        percpu_rwsem_assert_held(&c->mark_lock);
@@ -353,7 +322,7 @@ void bch2_fs_usage_apply(struct bch_fs *c,
 
        if (added > 0) {
                disk_res->sectors               -= added;
-               fs_usage->online_reserved       -= added;
+               fs_usage->s.online_reserved     -= added;
        }
 
        preempt_disable();
@@ -368,6 +337,18 @@ void bch2_fs_usage_apply(struct bch_fs *c,
        memset(fs_usage, 0, sizeof(*fs_usage));
 }
 
+static inline void account_bucket(struct bch_fs_usage *fs_usage,
+                                 struct bch_dev_usage *dev_usage,
+                                 enum bch_data_type type,
+                                 int nr, s64 size)
+{
+       if (type == BCH_DATA_SB || type == BCH_DATA_JOURNAL)
+               fs_usage->s.hidden      += size;
+
+       fs_usage->buckets[type]         += size;
+       dev_usage->buckets[type]        += nr;
+}
+
 static void bch2_dev_usage_update(struct bch_fs *c, struct bch_dev *ca,
                                  struct bch_fs_usage *fs_usage,
                                  struct bucket_mark old, struct bucket_mark new,
@@ -386,15 +367,13 @@ static void bch2_dev_usage_update(struct bch_fs *c, struct bch_dev *ca,
        preempt_disable();
        dev_usage = this_cpu_ptr(ca->usage[gc]);
 
-       if (bucket_type(old)) {
-               fs_usage->buckets[bucket_type(old)] -= ca->mi.bucket_size;
-               dev_usage->buckets[bucket_type(old)]--;
-       }
+       if (bucket_type(old))
+               account_bucket(fs_usage, dev_usage, bucket_type(old),
+                              -1, -ca->mi.bucket_size);
 
-       if (bucket_type(new)) {
-               fs_usage->buckets[bucket_type(new)] += ca->mi.bucket_size;
-               dev_usage->buckets[bucket_type(new)]++;
-       }
+       if (bucket_type(new))
+               account_bucket(fs_usage, dev_usage, bucket_type(new),
+                              1, ca->mi.bucket_size);
 
        dev_usage->buckets_alloc +=
                (int) new.owned_by_allocator - (int) old.owned_by_allocator;
@@ -460,7 +439,8 @@ static void __bch2_invalidate_bucket(struct bch_fs *c, struct bch_dev *ca,
                new.gen++;
        }));
 
-       fs_usage->replicas[0].data[BCH_DATA_CACHED] -= old->cached_sectors;
+       fs_usage->replicas[0].data[BCH_DATA_CACHED]     -= old->cached_sectors;
+       fs_usage->s.cached                              -= old->cached_sectors;
 }
 
 void bch2_invalidate_bucket(struct bch_fs *c, struct bch_dev *ca,
@@ -528,7 +508,10 @@ static void __bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
                checked_add(new.dirty_sectors, sectors);
        }));
 
-       fs_usage->replicas[0].data[type] += sectors;
+       if (type == BCH_DATA_BTREE ||
+           type == BCH_DATA_USER)
+               fs_usage->s.data                += sectors;
+       fs_usage->replicas[0].data[type]        += sectors;
 }
 
 void bch2_mark_metadata_bucket(struct bch_fs *c, struct bch_dev *ca,
@@ -755,8 +738,13 @@ static int bch2_mark_extent(struct bch_fs *c, struct bkey_s_c k,
        ec_redundancy   = clamp_t(unsigned,     ec_redundancy,
                                  1, ARRAY_SIZE(fs_usage->replicas));
 
+       fs_usage->s.cached                                      += cached_sectors;
        fs_usage->replicas[0].data[BCH_DATA_CACHED]             += cached_sectors;
+
+       fs_usage->s.data                                        += dirty_sectors;
        fs_usage->replicas[replicas - 1].data[data_type]        += dirty_sectors;
+
+       fs_usage->s.data                                        += ec_sectors;
        fs_usage->replicas[ec_redundancy - 1].ec_data           += ec_sectors;
 
        return 0;
@@ -866,9 +854,9 @@ static int __bch2_mark_key(struct bch_fs *c, struct bkey_s_c k,
                break;
        case KEY_TYPE_alloc:
                if (inserting)
-                       fs_usage->nr_inodes++;
+                       fs_usage->s.nr_inodes++;
                else
-                       fs_usage->nr_inodes--;
+                       fs_usage->s.nr_inodes--;
                break;
        case KEY_TYPE_reservation: {
                unsigned replicas = bkey_s_c_to_reservation(k).v->nr_replicas;
@@ -877,7 +865,8 @@ static int __bch2_mark_key(struct bch_fs *c, struct bkey_s_c k,
                replicas = clamp_t(unsigned, replicas,
                                   1, ARRAY_SIZE(fs_usage->replicas));
 
-               fs_usage->replicas[replicas - 1].persistent_reserved += sectors;
+               fs_usage->s.reserved                                    += sectors;
+               fs_usage->replicas[replicas - 1].persistent_reserved    += sectors;
                break;
        }
        default:
@@ -1021,8 +1010,7 @@ static u64 bch2_recalc_sectors_available(struct bch_fs *c)
 void __bch2_disk_reservation_put(struct bch_fs *c, struct disk_reservation *res)
 {
        percpu_down_read(&c->mark_lock);
-       this_cpu_sub(c->usage[0]->online_reserved,
-                    res->sectors);
+       this_cpu_sub(c->usage[0]->s.online_reserved, res->sectors);
 
        bch2_fs_stats_verify(c);
        percpu_up_read(&c->mark_lock);
@@ -1064,7 +1052,7 @@ int bch2_disk_reservation_add(struct bch_fs *c, struct disk_reservation *res,
 
 out:
        pcpu->sectors_available         -= sectors;
-       this_cpu_add(c->usage[0]->online_reserved, sectors);
+       this_cpu_add(c->usage[0]->s.online_reserved, sectors);
        res->sectors                    += sectors;
 
        bch2_disk_reservations_verify(c, flags);
@@ -1098,7 +1086,7 @@ recalculate:
            (flags & BCH_DISK_RESERVATION_NOFAIL)) {
                atomic64_set(&c->sectors_available,
                             max_t(s64, 0, sectors_available - sectors));
-               this_cpu_add(c->usage[0]->online_reserved, sectors);
+               this_cpu_add(c->usage[0]->s.online_reserved, sectors);
                res->sectors                    += sectors;
                ret = 0;
 
index f451a96f432c5d7bb254212e893a368bde334920..196f07f417286f9a184dd73e5919ff5e063ac108 100644 (file)
@@ -63,6 +63,21 @@ struct bch_dev_usage {
 struct bch_fs_usage {
        /* all fields are in units of 512 byte sectors: */
 
+       /* summarized: */
+       struct bch_fs_usage_summarized {
+               u64             online_reserved;
+
+               /* fields after online_reserved are cleared/recalculated by gc: */
+               u64             gc_start[0];
+
+               u64             hidden;
+               u64             data;
+               u64             cached;
+               u64             reserved;
+               u64             nr_inodes;
+       } s;
+
+       /* broken out: */
        struct {
                u64             data[BCH_DATA_NR];
                u64             ec_data;
@@ -70,10 +85,6 @@ struct bch_fs_usage {
        }                       replicas[BCH_REPLICAS_MAX];
 
        u64                     buckets[BCH_DATA_NR];
-
-       u64                     nr_inodes;
-
-       u64                     online_reserved;
 };
 
 struct bch_fs_usage_short {
index c11f8f4d24cf7d9a4421c81cfb1ac73c608e50c2..7f79f020d9041ac017f2db489a0950587f8355dc 100644 (file)
@@ -398,7 +398,7 @@ static long bch2_ioctl_usage(struct bch_fs *c,
                struct bch_ioctl_fs_usage dst = {
                        .capacity               = c->capacity,
                        .used                   = bch2_fs_sectors_used(c, src),
-                       .online_reserved        = src.online_reserved,
+                       .online_reserved        = src.s.online_reserved,
                };
 
                for (i = 0; i < BCH_REPLICAS_MAX; i++) {
index 7e46b254da38ad3395b185dc0c2b7e921504a0b1..a423159b6ed55a2ef4c6c8fa231fd6a552c77077 100644 (file)
@@ -259,7 +259,7 @@ static ssize_t show_fs_alloc_debug(struct bch_fs *c, char *buf)
                       stats.buckets[type]);
 
        pr_buf(&out, "online reserved:\t%llu\n",
-              stats.online_reserved);
+              stats.s.online_reserved);
 
        return out.pos - buf;
 }