bcachefs: Put open_buckets in a hashtable
authorKent Overstreet <kent.overstreet@gmail.com>
Sun, 26 Dec 2021 02:43:29 +0000 (21:43 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:20 +0000 (17:09 -0400)
This is so that the copygc code doesn't have to refer to
bucket_mark.owned_by_allocator - assisting in getting rid of the in
memory bucket array.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
fs/bcachefs/alloc_foreground.c
fs/bcachefs/alloc_foreground.h
fs/bcachefs/alloc_types.h
fs/bcachefs/bcachefs.h

index 35a2683d88076a3fceb476a3eef0e16c9162c441..7506d54c854b9dd0f90ff9b4b94c840b5e8a08bd 100644 (file)
  * reference _after_ doing the index update that makes its allocation reachable.
  */
 
+static void bch2_open_bucket_hash_add(struct bch_fs *c, struct open_bucket *ob)
+{
+       open_bucket_idx_t idx = ob - c->open_buckets;
+       open_bucket_idx_t *slot = open_bucket_hashslot(c, ob->dev, ob->bucket);
+
+       ob->hash = *slot;
+       *slot = idx;
+}
+
+static void bch2_open_bucket_hash_remove(struct bch_fs *c, struct open_bucket *ob)
+{
+       open_bucket_idx_t idx = ob - c->open_buckets;
+       open_bucket_idx_t *slot = open_bucket_hashslot(c, ob->dev, ob->bucket);
+
+       while (*slot != idx) {
+               BUG_ON(!*slot);
+               slot = &c->open_buckets[*slot].hash;
+       }
+
+       *slot = ob->hash;
+       ob->hash = 0;
+}
+
 void __bch2_open_bucket_put(struct bch_fs *c, struct open_bucket *ob)
 {
        struct bch_dev *ca = bch_dev_bkey_exists(c, ob->dev);
@@ -63,6 +86,8 @@ void __bch2_open_bucket_put(struct bch_fs *c, struct open_bucket *ob)
        percpu_up_read(&c->mark_lock);
 
        spin_lock(&c->freelist_lock);
+       bch2_open_bucket_hash_remove(c, ob);
+
        ob->freelist = c->open_buckets_freelist;
        c->open_buckets_freelist = ob - c->open_buckets;
 
@@ -100,7 +125,6 @@ static struct open_bucket *bch2_open_bucket_alloc(struct bch_fs *c)
        return ob;
 }
 
-
 static void open_bucket_free_unused(struct bch_fs *c,
                                    struct write_point *wp,
                                    struct open_bucket *ob)
@@ -253,6 +277,9 @@ out:
        ob->bucket      = b;
        spin_unlock(&ob->lock);
 
+       ca->nr_open_buckets++;
+       bch2_open_bucket_hash_add(c, ob);
+
        if (c->blocked_allocate_open_bucket) {
                bch2_time_stats_update(
                        &c->times[BCH_TIME_blocked_allocate_open_bucket],
@@ -267,7 +294,6 @@ out:
                c->blocked_allocate = 0;
        }
 
-       ca->nr_open_buckets++;
        spin_unlock(&c->freelist_lock);
 
        bch2_wake_allocator(ca);
index 39d8ae5bbb96921384261ca6c476fce1baa3a1b5..d466bda9afc8fdddb49f7b353c8c571b12f1fcf6 100644 (file)
@@ -91,6 +91,30 @@ static inline void bch2_open_bucket_get(struct bch_fs *c,
        }
 }
 
+static inline open_bucket_idx_t *open_bucket_hashslot(struct bch_fs *c,
+                                                 unsigned dev, u64 bucket)
+{
+       return c->open_buckets_hash +
+               (jhash_3words(dev, bucket, bucket >> 32, 0) &
+                (OPEN_BUCKETS_COUNT - 1));
+}
+
+static inline bool bch2_bucket_is_open(struct bch_fs *c, unsigned dev, u64 bucket)
+{
+       open_bucket_idx_t slot = *open_bucket_hashslot(c, dev, bucket);
+
+       while (slot) {
+               struct open_bucket *ob = &c->open_buckets[slot];
+
+               if (ob->dev == dev && ob->bucket == bucket)
+                       return true;
+
+               slot = ob->hash;
+       }
+
+       return false;
+}
+
 int bch2_bucket_alloc_set(struct bch_fs *, struct open_buckets *,
                      struct dev_stripe_state *, struct bch_devs_mask *,
                      unsigned, unsigned *, bool *, enum alloc_reserve,
index bd173c7c334b462126a8cd176b400887cc059de9..409232e3d99800ef652ce6fcd8b2cf0a2e6476b9 100644 (file)
@@ -37,12 +37,16 @@ typedef FIFO(long)  alloc_fifo;
 #define WRITE_POINT_HASH_NR    32
 #define WRITE_POINT_MAX                32
 
+/*
+ * 0 is never a valid open_bucket_idx_t:
+ */
 typedef u16                    open_bucket_idx_t;
 
 struct open_bucket {
        spinlock_t              lock;
        atomic_t                pin;
        open_bucket_idx_t       freelist;
+       open_bucket_idx_t       hash;
 
        /*
         * When an open bucket has an ec_stripe attached, this is the index of
index f41d9b3ac4831057428a19e79be0ef29532cc9ad..6c686be28b39a6650be468e37956f59a4ed66f84 100644 (file)
@@ -756,10 +756,12 @@ struct bch_fs {
        struct closure_waitlist freelist_wait;
        u64                     blocked_allocate;
        u64                     blocked_allocate_open_bucket;
+
        open_bucket_idx_t       open_buckets_freelist;
        open_bucket_idx_t       open_buckets_nr_free;
        struct closure_waitlist open_buckets_wait;
        struct open_bucket      open_buckets[OPEN_BUCKETS_COUNT];
+       open_bucket_idx_t       open_buckets_hash[OPEN_BUCKETS_COUNT];
 
        struct write_point      btree_write_point;
        struct write_point      rebalance_write_point;