bcachefs: Don't write bucket IO time lazily
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 17 Oct 2020 01:39:16 +0000 (21:39 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:50 +0000 (17:08 -0400)
With the btree key cache code, we don't need to update the alloc btree
lazily - and this will mean we can remove the bch2_alloc_write() call in
the shutdown path.

Future work: we really need to expend the bucket IO clocks from 16 to 64
bits, so that we don't have to rescale them.

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/alloc_background.c
fs/bcachefs/alloc_background.h
fs/bcachefs/alloc_foreground.c
fs/bcachefs/buckets.h
fs/bcachefs/fs-io.c
fs/bcachefs/io.c
fs/bcachefs/io.h
fs/bcachefs/move.c

index 078968f30175b1e6292a3b32031b00050bda469e..1ef695acc7d6bca46eb04bf77a92b1ca113ba71f 100644 (file)
@@ -489,6 +489,54 @@ static void bch2_bucket_clock_init(struct bch_fs *c, int rw)
        mutex_init(&clock->lock);
 }
 
+int bch2_bucket_io_time_reset(struct btree_trans *trans, unsigned dev,
+                             size_t bucket_nr, int rw)
+{
+       struct bch_fs *c = trans->c;
+       struct bch_dev *ca = bch_dev_bkey_exists(c, dev);
+       struct btree_iter *iter;
+       struct bucket *g;
+       struct bkey_i_alloc *a;
+       struct bkey_alloc_unpacked u;
+       u16 *time;
+       int ret = 0;
+
+       iter = bch2_trans_get_iter(trans, BTREE_ID_ALLOC, POS(dev, bucket_nr),
+                                  BTREE_ITER_CACHED|
+                                  BTREE_ITER_CACHED_NOFILL|
+                                  BTREE_ITER_INTENT);
+       ret = bch2_btree_iter_traverse(iter);
+       if (ret)
+               goto out;
+
+       a = bch2_trans_kmalloc(trans, BKEY_ALLOC_U64s_MAX * 8);
+       ret = PTR_ERR_OR_ZERO(a);
+       if (ret)
+               goto out;
+
+       percpu_down_read(&c->mark_lock);
+       g = bucket(ca, bucket_nr);
+       u = alloc_mem_to_key(g, READ_ONCE(g->mark));
+       percpu_up_read(&c->mark_lock);
+
+       bkey_alloc_init(&a->k_i);
+       a->k.p = iter->pos;
+
+       time = rw == READ ? &u.read_time : &u.write_time;
+       if (*time == c->bucket_clock[rw].hand)
+               goto out;
+
+       *time = c->bucket_clock[rw].hand;
+
+       bch2_alloc_pack(a, u);
+
+       ret   = bch2_trans_update(trans, iter, &a->k_i, 0) ?:
+               bch2_trans_commit(trans, NULL, NULL, 0);
+out:
+       bch2_trans_iter_put(trans, iter);
+       return ret;
+}
+
 /* Background allocator thread: */
 
 /*
index 8e3abb89dfb7de2af313be62dba46a7ce31aca8f..d10ff56e4de169fc5bbb63823f4a5c49cfa8fe1d 100644 (file)
@@ -31,6 +31,8 @@ struct bkey_alloc_unpacked bch2_alloc_unpack(struct bkey_s_c);
 void bch2_alloc_pack(struct bkey_i_alloc *,
                     const struct bkey_alloc_unpacked);
 
+int bch2_bucket_io_time_reset(struct btree_trans *, unsigned, size_t, int);
+
 static inline struct bkey_alloc_unpacked
 alloc_mem_to_key(struct bucket *g, struct bucket_mark m)
 {
index 169ddfad7ea04c35d8d5dc3416d1747545a22b9d..82a49831afb759bbcedb98b086a850ea22ecc0b2 100644 (file)
@@ -309,8 +309,6 @@ out:
                .dev    = ca->dev_idx,
        };
 
-       bucket_io_clock_reset(c, ca, bucket, READ);
-       bucket_io_clock_reset(c, ca, bucket, WRITE);
        spin_unlock(&ob->lock);
 
        if (c->blocked_allocate_open_bucket) {
index 7ee63413f83c018fbf9bbcbf4af87ee4a46010a9..2e9c4e46c61c07a25183850fe1d8ca5a0a057a17 100644 (file)
@@ -58,12 +58,6 @@ static inline struct bucket *bucket(struct bch_dev *ca, size_t b)
        return __bucket(ca, b, false);
 }
 
-static inline void bucket_io_clock_reset(struct bch_fs *c, struct bch_dev *ca,
-                                        size_t b, int rw)
-{
-       bucket(ca, b)->io_time[rw] = c->bucket_clock[rw].hand;
-}
-
 static inline u16 bucket_last_io(struct bch_fs *c, struct bucket *g, int rw)
 {
        return c->bucket_clock[rw].hand - g->io_time[rw];
index 2d31547446ace60d15fbf719442b91f8660c6274..4f270b6cdf6616d74324c62ab3bf8acd32dd1068 100644 (file)
@@ -826,7 +826,7 @@ retry:
                if (bkey_extent_is_allocation(k.k))
                        bch2_add_page_sectors(&rbio->bio, k);
 
-               bch2_read_extent(c, rbio, k, offset_into_extent, flags);
+               bch2_read_extent(trans, rbio, k, offset_into_extent, flags);
 
                if (flags & BCH_READ_LAST_FRAGMENT)
                        break;
index 2b381fc960097127c46daa8bc239d2ffed6bbb35..a67bd18f6b8cc74227e917be3b7b9449a508e34b 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include "bcachefs.h"
+#include "alloc_background.h"
 #include "alloc_foreground.h"
 #include "bkey_on_stack.h"
 #include "bset.h"
@@ -1640,7 +1641,7 @@ retry:
                goto out;
        }
 
-       ret = __bch2_read_extent(c, rbio, bvec_iter, k, 0, failed, flags);
+       ret = __bch2_read_extent(&trans, rbio, bvec_iter, k, 0, failed, flags);
        if (ret == READ_RETRY)
                goto retry;
        if (ret)
@@ -1698,7 +1699,7 @@ retry:
                bytes = min(sectors, bvec_iter_sectors(bvec_iter)) << 9;
                swap(bvec_iter.bi_size, bytes);
 
-               ret = __bch2_read_extent(c, rbio, bvec_iter, k,
+               ret = __bch2_read_extent(&trans, rbio, bvec_iter, k,
                                offset_into_extent, failed, flags);
                switch (ret) {
                case READ_RETRY:
@@ -2026,11 +2027,12 @@ err:
        return ret;
 }
 
-int __bch2_read_extent(struct bch_fs *c, struct bch_read_bio *orig,
+int __bch2_read_extent(struct btree_trans *trans, struct bch_read_bio *orig,
                       struct bvec_iter iter, struct bkey_s_c k,
                       unsigned offset_into_extent,
                       struct bch_io_failures *failed, unsigned flags)
 {
+       struct bch_fs *c = trans->c;
        struct extent_ptr_decoded pick;
        struct bch_read_bio *rbio = NULL;
        struct bch_dev *ca;
@@ -2200,9 +2202,9 @@ get_bio:
 
        bch2_increment_clock(c, bio_sectors(&rbio->bio), READ);
 
-       rcu_read_lock();
-       bucket_io_clock_reset(c, ca, PTR_BUCKET_NR(ca, &pick.ptr), READ);
-       rcu_read_unlock();
+       if (pick.ptr.cached)
+               bch2_bucket_io_time_reset(trans, pick.ptr.dev,
+                       PTR_BUCKET_NR(ca, &pick.ptr), READ);
 
        if (!(flags & (BCH_READ_IN_RETRY|BCH_READ_LAST_FRAGMENT))) {
                bio_inc_remaining(&orig->bio);
@@ -2351,7 +2353,7 @@ retry:
                if (rbio->bio.bi_iter.bi_size == bytes)
                        flags |= BCH_READ_LAST_FRAGMENT;
 
-               bch2_read_extent(c, rbio, k, offset_into_extent, flags);
+               bch2_read_extent(&trans, rbio, k, offset_into_extent, flags);
 
                if (flags & BCH_READ_LAST_FRAGMENT)
                        break;
index be4aa3875360d0fe0764521e09499e6a0fe36682..379263a935fab99bb88c11a5da129235eb533309 100644 (file)
@@ -140,17 +140,17 @@ enum bch_read_flags {
        BCH_READ_IN_RETRY               = 1 << 7,
 };
 
-int __bch2_read_extent(struct bch_fs *, struct bch_read_bio *,
+int __bch2_read_extent(struct btree_trans *, struct bch_read_bio *,
                       struct bvec_iter, struct bkey_s_c, unsigned,
                       struct bch_io_failures *, unsigned);
 
-static inline void bch2_read_extent(struct bch_fs *c,
+static inline void bch2_read_extent(struct btree_trans *trans,
                                    struct bch_read_bio *rbio,
                                    struct bkey_s_c k,
                                    unsigned offset_into_extent,
                                    unsigned flags)
 {
-       __bch2_read_extent(c, rbio, rbio->bio.bi_iter, k,
+       __bch2_read_extent(trans, rbio, rbio->bio.bi_iter, k,
                           offset_into_extent, NULL, flags);
 }
 
index 9d190ae4f3915ee3c58ef7c061fd9b236e9f43f3..62a6bbd676ae995065d046b60eb0aad6476b836d 100644 (file)
@@ -414,7 +414,7 @@ static void bch2_move_ctxt_wait_for_io(struct moving_context *ctxt)
                atomic_read(&ctxt->write_sectors) != sectors_pending);
 }
 
-static int bch2_move_extent(struct bch_fs *c,
+static int bch2_move_extent(struct btree_trans *trans,
                            struct moving_context *ctxt,
                            struct write_point_specifier wp,
                            struct bch_io_opts io_opts,
@@ -423,6 +423,7 @@ static int bch2_move_extent(struct bch_fs *c,
                            enum data_cmd data_cmd,
                            struct data_opts data_opts)
 {
+       struct bch_fs *c = trans->c;
        struct bkey_ptrs_c ptrs = bch2_bkey_ptrs_c(k);
        struct moving_io *io;
        const union bch_extent_entry *entry;
@@ -489,7 +490,7 @@ static int bch2_move_extent(struct bch_fs *c,
         * ctxt when doing wakeup
         */
        closure_get(&ctxt->cl);
-       bch2_read_extent(c, &io->rbio, k, 0,
+       bch2_read_extent(trans, &io->rbio, k, 0,
                         BCH_READ_NODECODE|
                         BCH_READ_LAST_FRAGMENT);
        return 0;
@@ -607,7 +608,7 @@ peek:
                k = bkey_i_to_s_c(sk.k);
                bch2_trans_unlock(&trans);
 
-               ret2 = bch2_move_extent(c, ctxt, wp, io_opts, btree_id, k,
+               ret2 = bch2_move_extent(&trans, ctxt, wp, io_opts, btree_id, k,
                                        data_cmd, data_opts);
                if (ret2) {
                        if (ret2 == -ENOMEM) {