]> www.infradead.org Git - nvme.git/commitdiff
bcachefs: dev_usage updated by new accounting
authorKent Overstreet <kent.overstreet@linux.dev>
Tue, 2 Jan 2024 00:42:37 +0000 (19:42 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 14 Jul 2024 23:00:13 +0000 (19:00 -0400)
Reading disk accounting now requires an eytzinger lookup (see:
bch2_accounting_mem_read()), but the per-device counters are used
frequently enough that we'd like to still be able to read them with just
a percpu sum, as in the old code.

This patch special cases the device counters; when we update in-memory
accounting we also update the old style percpu counters if it's a deice
counter update.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/bcachefs.h
fs/bcachefs/btree_gc.c
fs/bcachefs/buckets.c
fs/bcachefs/buckets_types.h
fs/bcachefs/disk_accounting.c
fs/bcachefs/disk_accounting.h
fs/bcachefs/recovery.c
fs/bcachefs/sb-clean.c

index 03e4f15f34f5ebe3d83dd82211da6bf2e89370c1..8ffb683c368ab384dbbd5ada93100d7ec2506257 100644 (file)
@@ -545,8 +545,7 @@ struct bch_dev {
        unsigned long           *buckets_nouse;
        struct rw_semaphore     bucket_lock;
 
-       struct bch_dev_usage            *usage_base;
-       struct bch_dev_usage __percpu   *usage[JOURNAL_BUF_NR];
+       struct bch_dev_usage __percpu   *usage;
        struct bch_dev_usage __percpu   *usage_gc;
 
        /* Allocator: */
index b5fe6785d3e40a5a8cb14f386d57a3d367b2fa2b..fe7293166e3724646fa84076ce824ca8f40930e0 100644 (file)
@@ -773,7 +773,7 @@ static int bch2_gc_done(struct bch_fs *c)
                bch2_fs_usage_acc_to_base(c, i);
 
        __for_each_member_device(c, ca) {
-               struct bch_dev_usage *dst = ca->usage_base;
+               struct bch_dev_usage *dst = this_cpu_ptr(ca->usage);
                struct bch_dev_usage *src = (void *)
                        bch2_acc_percpu_u64s((u64 __percpu *) ca->usage_gc,
                                             dev_usage_u64s());
index c3dac9d1c45bffbaa74c08b6ad68a4418a93a444..37347159ef4d053d2269b6d4b59577bc7bea8152 100644 (file)
@@ -69,15 +69,8 @@ void bch2_fs_usage_initialize(struct bch_fs *c)
 
 void bch2_dev_usage_read_fast(struct bch_dev *ca, struct bch_dev_usage *usage)
 {
-       struct bch_fs *c = ca->fs;
-       unsigned seq, i, u64s = dev_usage_u64s();
-
-       do {
-               seq = read_seqcount_begin(&c->usage_lock);
-               memcpy(usage, ca->usage_base, u64s * sizeof(u64));
-               for (i = 0; i < ARRAY_SIZE(ca->usage); i++)
-                       acc_u64s_percpu((u64 *) usage, (u64 __percpu *) ca->usage[i], u64s);
-       } while (read_seqcount_retry(&c->usage_lock, seq));
+       memset(usage, 0, sizeof(*usage));
+       acc_u64s_percpu((u64 *) usage, (u64 __percpu *) ca->usage, dev_usage_u64s());
 }
 
 u64 bch2_fs_usage_read_one(struct bch_fs *c, u64 *v)
@@ -147,16 +140,6 @@ void bch2_fs_usage_acc_to_base(struct bch_fs *c, unsigned idx)
                        (u64 __percpu *) c->usage[idx], u64s);
        percpu_memset(c->usage[idx], 0, u64s * sizeof(u64));
 
-       rcu_read_lock();
-       for_each_member_device_rcu(c, ca, NULL) {
-               u64s = dev_usage_u64s();
-
-               acc_u64s_percpu((u64 *) ca->usage_base,
-                               (u64 __percpu *) ca->usage[idx], u64s);
-               percpu_memset(ca->usage[idx], 0, u64s * sizeof(u64));
-       }
-       rcu_read_unlock();
-
        write_seqcount_end(&c->usage_lock);
        preempt_enable();
 }
@@ -1488,23 +1471,14 @@ void bch2_dev_buckets_free(struct bch_dev *ca)
 {
        kvfree(ca->buckets_nouse);
        kvfree(rcu_dereference_protected(ca->bucket_gens, 1));
-
-       for (unsigned i = 0; i < ARRAY_SIZE(ca->usage); i++)
-               free_percpu(ca->usage[i]);
-       kfree(ca->usage_base);
+       free_percpu(ca->usage);
 }
 
 int bch2_dev_buckets_alloc(struct bch_fs *c, struct bch_dev *ca)
 {
-       ca->usage_base = kzalloc(sizeof(struct bch_dev_usage), GFP_KERNEL);
-       if (!ca->usage_base)
+       ca->usage = alloc_percpu(struct bch_dev_usage);
+       if (!ca->usage)
                return -BCH_ERR_ENOMEM_usage_init;
 
-       for (unsigned i = 0; i < ARRAY_SIZE(ca->usage); i++) {
-               ca->usage[i] = alloc_percpu(struct bch_dev_usage);
-               if (!ca->usage[i])
-                       return -BCH_ERR_ENOMEM_usage_init;
-       }
-
        return bch2_dev_buckets_resize(c, ca, ca->mi.nbuckets);
 }
index 6c4ee3163d0f3bdabc70c89bd06e33c72557ee20..a15e3f79b9cb3d539b044878d24696dd4a5c6a99 100644 (file)
@@ -36,7 +36,7 @@ struct bucket_gens {
 };
 
 struct bch_dev_usage {
-       struct {
+       struct bch_dev_usage_type {
                u64             buckets;
                u64             sectors; /* _compressed_ sectors: */
                /*
index dbdc16f2fc1c857660e341ee27c3f1146b7e2fa9..ccd3f8d878d1122033f0007a98f604baddb7c250 100644 (file)
@@ -400,6 +400,21 @@ int bch2_accounting_read(struct bch_fs *c)
                case BCH_DISK_ACCOUNTING_replicas:
                        fs_usage_data_type_to_base(usage, k.replicas.data_type, v[0]);
                        break;
+               case BCH_DISK_ACCOUNTING_dev_data_type:
+                       rcu_read_lock();
+                       struct bch_dev *ca = bch2_dev_rcu(c, k.dev_data_type.dev);
+                       if (ca) {
+                               struct bch_dev_usage_type __percpu *d = &ca->usage->d[k.dev_data_type.data_type];
+                               percpu_u64_set(&d->buckets,     v[0]);
+                               percpu_u64_set(&d->sectors,     v[1]);
+                               percpu_u64_set(&d->fragmented,  v[2]);
+
+                               if (k.dev_data_type.data_type == BCH_DATA_sb ||
+                                   k.dev_data_type.data_type == BCH_DATA_journal)
+                                       usage->hidden += v[0] * ca->mi.bucket_size;
+                       }
+                       rcu_read_unlock();
+                       break;
                }
        }
        preempt_enable();
index ec1b8ae2aeee542921abb152d59926663866e93f..9f2078c970f3ca2616571694d2113d0cd3b91ffe 100644 (file)
@@ -3,6 +3,7 @@
 #define _BCACHEFS_DISK_ACCOUNTING_H
 
 #include "eytzinger.h"
+#include "sb-members.h"
 
 static inline void bch2_u64s_neg(u64 *v, unsigned nr)
 {
@@ -131,6 +132,7 @@ static inline int __bch2_accounting_mem_mod(struct bch_fs *c, struct bkey_s_c_ac
 static inline int bch2_accounting_mem_mod(struct btree_trans *trans, struct
                                          bkey_s_c_accounting a)
 {
+       struct bch_fs *c = trans->c;
        struct disk_accounting_pos acc_k;
        bpos_to_disk_accounting_pos(&acc_k, a.k->p);
 
@@ -141,8 +143,18 @@ static inline int bch2_accounting_mem_mod(struct btree_trans *trans, struct
        case BCH_DISK_ACCOUNTING_replicas:
                fs_usage_data_type_to_base(&trans->fs_usage_delta, acc_k.replicas.data_type, a.v->d[0]);
                break;
+       case BCH_DISK_ACCOUNTING_dev_data_type:
+               rcu_read_lock();
+               struct bch_dev *ca = bch2_dev_rcu(c, acc_k.dev_data_type.dev);
+               if (ca) {
+                       this_cpu_add(ca->usage->d[acc_k.dev_data_type.data_type].buckets, a.v->d[0]);
+                       this_cpu_add(ca->usage->d[acc_k.dev_data_type.data_type].sectors, a.v->d[1]);
+                       this_cpu_add(ca->usage->d[acc_k.dev_data_type.data_type].fragmented, a.v->d[2]);
+               }
+               rcu_read_unlock();
+               break;
        }
-       return __bch2_accounting_mem_mod(trans->c, a);
+       return __bch2_accounting_mem_mod(c, a);
 }
 
 static inline void bch2_accounting_mem_read_counters(struct bch_fs *c,
index 2d03b4ff31ddf86bad5d556b94b024e3a762ad70..fcc8d5bc6c2f5281db79328c1d4c9015e79a2b3d 100644 (file)
@@ -451,23 +451,6 @@ static int journal_replay_entry_early(struct bch_fs *c,
                                              le64_to_cpu(u->v));
                break;
        }
-       case BCH_JSET_ENTRY_dev_usage: {
-               struct jset_entry_dev_usage *u =
-                       container_of(entry, struct jset_entry_dev_usage, entry);
-               unsigned nr_types = jset_entry_dev_usage_nr_types(u);
-
-               rcu_read_lock();
-               struct bch_dev *ca = bch2_dev_rcu(c, le32_to_cpu(u->dev));
-               if (ca)
-                       for (unsigned i = 0; i < min_t(unsigned, nr_types, BCH_DATA_NR); i++) {
-                               ca->usage_base->d[i].buckets    = le64_to_cpu(u->d[i].buckets);
-                               ca->usage_base->d[i].sectors    = le64_to_cpu(u->d[i].sectors);
-                               ca->usage_base->d[i].fragmented = le64_to_cpu(u->d[i].fragmented);
-                       }
-               rcu_read_unlock();
-
-               break;
-       }
        case BCH_JSET_ENTRY_blacklist: {
                struct jset_entry_blacklist *bl_entry =
                        container_of(entry, struct jset_entry_blacklist, entry);
index 47f10ab57f40c3773d329d9d3f407efe0b3467ca..57fd744b71e723d98fe798d0586adec82939c58d 100644 (file)
@@ -236,23 +236,6 @@ void bch2_journal_super_entries_add_common(struct bch_fs *c,
                              "embedded variable length struct");
        }
 
-       for_each_member_device(c, ca) {
-               unsigned b = sizeof(struct jset_entry_dev_usage) +
-                       sizeof(struct jset_entry_dev_usage_type) * BCH_DATA_NR;
-               struct jset_entry_dev_usage *u =
-                       container_of(jset_entry_init(end, b),
-                                    struct jset_entry_dev_usage, entry);
-
-               u->entry.type = BCH_JSET_ENTRY_dev_usage;
-               u->dev = cpu_to_le32(ca->dev_idx);
-
-               for (unsigned i = 0; i < BCH_DATA_NR; i++) {
-                       u->d[i].buckets = cpu_to_le64(ca->usage_base->d[i].buckets);
-                       u->d[i].sectors = cpu_to_le64(ca->usage_base->d[i].sectors);
-                       u->d[i].fragmented = cpu_to_le64(ca->usage_base->d[i].fragmented);
-               }
-       }
-
        percpu_up_read(&c->mark_lock);
 
        for (unsigned i = 0; i < 2; i++) {