]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: bch2_move_data_phys()
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 28 Dec 2024 15:40:11 +0000 (10:40 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 15 Mar 2025 01:02:12 +0000 (21:02 -0400)
Add a more general version of bch2_evacuate_bucket - to be used for
scrub.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/chardev.c
fs/bcachefs/move.c
fs/bcachefs/move_types.h
fs/bcachefs/trace.h

index bab49d5ee598536d89f20322bc6eb2e231db3654..bc1f91bf3e16e2dce00d2f971b126c62de7246c8 100644 (file)
@@ -313,7 +313,7 @@ static int bch2_data_thread(void *arg)
        struct bch_data_ctx *ctx = container_of(arg, struct bch_data_ctx, thr);
 
        ctx->thr.ret = bch2_data_job(ctx->c, &ctx->stats, ctx->arg);
-       ctx->stats.data_type = U8_MAX;
+       ctx->stats.done = true;
        return 0;
 }
 
@@ -333,7 +333,7 @@ static ssize_t bch2_data_job_read(struct file *file, char __user *buf,
        struct bch_fs *c = ctx->c;
        struct bch_ioctl_data_event e = {
                .type                   = BCH_DATA_EVENT_PROGRESS,
-               .p.data_type            = ctx->stats.data_type,
+               .p.data_type            = ctx->stats.done ? U8_MAX : ctx->stats.data_type,
                .p.btree_id             = ctx->stats.pos.btree,
                .p.pos                  = ctx->stats.pos.pos,
                .p.sectors_done         = atomic64_read(&ctx->stats.sectors_seen),
index d825493cac25935608fa558a9fa0cc1bd3fe417e..cfcde0e33177c21cf33b50f5cb0ba7551e19d3a1 100644 (file)
@@ -655,21 +655,21 @@ int bch2_move_data(struct bch_fs *c,
                   bool wait_on_copygc,
                   move_pred_fn pred, void *arg)
 {
-
        struct moving_context ctxt;
-       int ret;
 
        bch2_moving_ctxt_init(&ctxt, c, rate, stats, wp, wait_on_copygc);
-       ret = __bch2_move_data(&ctxt, start, end, pred, arg);
+       int ret = __bch2_move_data(&ctxt, start, end, pred, arg);
        bch2_moving_ctxt_exit(&ctxt);
 
        return ret;
 }
 
-int bch2_evacuate_bucket(struct moving_context *ctxt,
-                          struct move_bucket_in_flight *bucket_in_flight,
-                          struct bpos bucket, int gen,
-                          struct data_update_opts _data_opts)
+static int __bch2_move_data_phys(struct moving_context *ctxt,
+                       struct move_bucket_in_flight *bucket_in_flight,
+                       unsigned dev,
+                       u64 bucket_start,
+                       u64 bucket_end,
+                       move_pred_fn pred, void *arg)
 {
        struct btree_trans *trans = ctxt->trans;
        struct bch_fs *c = trans->c;
@@ -678,16 +678,20 @@ int bch2_evacuate_bucket(struct moving_context *ctxt,
        struct btree_iter iter = {}, bp_iter = {};
        struct bkey_buf sk;
        struct bkey_s_c k;
-       struct data_update_opts data_opts;
        unsigned sectors_moved = 0;
        struct bkey_buf last_flushed;
        int ret = 0;
 
-       struct bch_dev *ca = bch2_dev_tryget(c, bucket.inode);
+       struct bch_dev *ca = bch2_dev_tryget(c, dev);
        if (!ca)
                return 0;
 
-       trace_bucket_evacuate(c, &bucket);
+       bucket_end = min(bucket_end, ca->mi.nbuckets);
+
+       struct bpos bp_start    = bucket_pos_to_bp_start(ca, POS(dev, bucket_start));
+       struct bpos bp_end      = bucket_pos_to_bp_end(ca, POS(dev, bucket_end));
+       bch2_dev_put(ca);
+       ca = NULL;
 
        bch2_bkey_buf_init(&last_flushed);
        bkey_init(&last_flushed.k->k);
@@ -698,8 +702,7 @@ int bch2_evacuate_bucket(struct moving_context *ctxt,
         */
        bch2_trans_begin(trans);
 
-       bch2_trans_iter_init(trans, &bp_iter, BTREE_ID_backpointers,
-                            bucket_pos_to_bp_start(ca, bucket), 0);
+       bch2_trans_iter_init(trans, &bp_iter, BTREE_ID_backpointers, bp_start, 0);
 
        bch_err_msg(c, ret, "looking up alloc key");
        if (ret)
@@ -723,7 +726,7 @@ int bch2_evacuate_bucket(struct moving_context *ctxt,
                if (ret)
                        goto err;
 
-               if (!k.k || bkey_gt(k.k->p, bucket_pos_to_bp_end(ca, bucket)))
+               if (!k.k || bkey_gt(k.k->p, bp_end))
                        break;
 
                if (k.k->type != KEY_TYPE_backpointer)
@@ -731,6 +734,10 @@ int bch2_evacuate_bucket(struct moving_context *ctxt,
 
                struct bkey_s_c_backpointer bp = bkey_s_c_to_backpointer(k);
 
+               if (ctxt->stats)
+                       ctxt->stats->offset =
+                               bp.k->p.offset >> MAX_EXTENT_COMPRESS_RATIO_SHIFT;
+
                if (!bp.v->level) {
                        k = bch2_backpointer_get_key(trans, bp, &iter, 0, &last_flushed);
                        ret = bkey_err(k);
@@ -741,34 +748,22 @@ int bch2_evacuate_bucket(struct moving_context *ctxt,
                        if (!k.k)
                                goto next;
 
-                       bch2_bkey_buf_reassemble(&sk, c, k);
-                       k = bkey_i_to_s_c(sk.k);
-
                        ret = bch2_move_get_io_opts_one(trans, &io_opts, &iter, k);
                        if (ret) {
                                bch2_trans_iter_exit(trans, &iter);
                                continue;
                        }
 
-                       data_opts = _data_opts;
-                       data_opts.target        = io_opts.background_target;
-                       data_opts.rewrite_ptrs = 0;
+                       struct data_update_opts data_opts = {};
+                       if (!pred(c, arg, k, &io_opts, &data_opts)) {
+                               bch2_trans_iter_exit(trans, &iter);
+                               goto next;
+                       }
+
+                       bch2_bkey_buf_reassemble(&sk, c, k);
+                       k = bkey_i_to_s_c(sk.k);
 
                        unsigned sectors = bp.v->bucket_len; /* move_extent will drop locks */
-                       unsigned i = 0;
-                       const union bch_extent_entry *entry;
-                       struct extent_ptr_decoded p;
-                       bkey_for_each_ptr_decode(k.k, bch2_bkey_ptrs_c(k), p, entry) {
-                               if (p.ptr.dev == bucket.inode) {
-                                       if (p.ptr.cached) {
-                                               bch2_trans_iter_exit(trans, &iter);
-                                               goto next;
-                                       }
-                                       data_opts.rewrite_ptrs |= 1U << i;
-                                       break;
-                               }
-                               i++;
-                       }
 
                        ret = bch2_move_extent(ctxt, bucket_in_flight,
                                               &iter, k, io_opts, data_opts);
@@ -801,6 +796,12 @@ int bch2_evacuate_bucket(struct moving_context *ctxt,
                        if (!b)
                                goto next;
 
+                       struct data_update_opts data_opts = {};
+                       if (!pred(c, arg, bkey_i_to_s_c(&b->key), &io_opts, &data_opts)) {
+                               bch2_trans_iter_exit(trans, &iter);
+                               goto next;
+                       }
+
                        unsigned sectors = btree_ptr_sectors_written(bkey_i_to_s_c(&b->key));
 
                        ret = bch2_btree_node_rewrite(trans, &iter, b, 0);
@@ -817,21 +818,58 @@ int bch2_evacuate_bucket(struct moving_context *ctxt,
                                atomic64_add(sectors, &ctxt->stats->sectors_seen);
                                atomic64_add(sectors, &ctxt->stats->sectors_moved);
                        }
-                       sectors_moved += btree_sectors(c);
+                       sectors_moved += sectors;
                }
 next:
                bch2_btree_iter_advance(&bp_iter);
        }
-
-       trace_evacuate_bucket(c, &bucket, sectors_moved, ca->mi.bucket_size, ret);
 err:
        bch2_trans_iter_exit(trans, &bp_iter);
-       bch2_dev_put(ca);
        bch2_bkey_buf_exit(&sk, c);
        bch2_bkey_buf_exit(&last_flushed, c);
        return ret;
 }
 
+struct evacuate_bucket_arg {
+       struct bpos             bucket;
+       int                     gen;
+       struct data_update_opts data_opts;
+};
+
+static bool evacuate_bucket_pred(struct bch_fs *c, void *_arg, struct bkey_s_c k,
+                                struct bch_io_opts *io_opts,
+                                struct data_update_opts *data_opts)
+{
+       struct evacuate_bucket_arg *arg = _arg;
+
+       *data_opts = arg->data_opts;
+
+       unsigned i = 0;
+       bkey_for_each_ptr(bch2_bkey_ptrs_c(k), ptr) {
+               if (ptr->dev == arg->bucket.inode &&
+                   (arg->gen < 0 || arg->gen == ptr->gen) &&
+                   !ptr->cached)
+                       data_opts->rewrite_ptrs |= BIT(i);
+               i++;
+       }
+
+       return data_opts->rewrite_ptrs != 0;
+}
+
+int bch2_evacuate_bucket(struct moving_context *ctxt,
+                          struct move_bucket_in_flight *bucket_in_flight,
+                          struct bpos bucket, int gen,
+                          struct data_update_opts data_opts)
+{
+       struct evacuate_bucket_arg arg = { bucket, gen, data_opts, };
+
+       return __bch2_move_data_phys(ctxt, bucket_in_flight,
+                                  bucket.inode,
+                                  bucket.offset,
+                                  bucket.offset + 1,
+                                  evacuate_bucket_pred, &arg);
+}
+
 typedef bool (*move_btree_pred)(struct bch_fs *, void *,
                                struct btree *, struct bch_io_opts *,
                                struct data_update_opts *);
index e22841ef31e475fdfa11d8dcc7d48adb8d333897..15d1f7f3d1dc64ca8162d9f55e523f1cd202f81f 100644 (file)
@@ -5,9 +5,20 @@
 #include "bbpos_types.h"
 
 struct bch_move_stats {
-       enum bch_data_type      data_type;
-       struct bbpos            pos;
        char                    name[32];
+       bool                    phys;
+       bool                    done;
+
+       union {
+       struct {
+               enum bch_data_type      data_type;
+               struct bbpos            pos;
+       };
+       struct {
+               unsigned                dev;
+               u64                     offset;
+       };
+       };
 
        atomic64_t              keys_moved;
        atomic64_t              keys_raced;
index c1b51009edf6b17e85d6c42b4ef8150c0788099a..2f25dcfc0e25bde24730c862579b53988d7d285e 100644 (file)
@@ -797,27 +797,6 @@ TRACE_EVENT(bucket_invalidate,
 
 /* Moving IO */
 
-TRACE_EVENT(bucket_evacuate,
-       TP_PROTO(struct bch_fs *c, struct bpos *bucket),
-       TP_ARGS(c, bucket),
-
-       TP_STRUCT__entry(
-               __field(dev_t,          dev                     )
-               __field(u32,            dev_idx                 )
-               __field(u64,            bucket                  )
-       ),
-
-       TP_fast_assign(
-               __entry->dev            = c->dev;
-               __entry->dev_idx        = bucket->inode;
-               __entry->bucket         = bucket->offset;
-       ),
-
-       TP_printk("%d:%d %u:%llu",
-                 MAJOR(__entry->dev), MINOR(__entry->dev),
-                 __entry->dev_idx, __entry->bucket)
-);
-
 DEFINE_EVENT(fs_str, move_extent,
        TP_PROTO(struct bch_fs *c, const char *str),
        TP_ARGS(c, str)
@@ -881,37 +860,6 @@ TRACE_EVENT(move_data,
                  __entry->sectors_raced)
 );
 
-TRACE_EVENT(evacuate_bucket,
-       TP_PROTO(struct bch_fs *c, struct bpos *bucket,
-                unsigned sectors, unsigned bucket_size,
-                int ret),
-       TP_ARGS(c, bucket, sectors, bucket_size, ret),
-
-       TP_STRUCT__entry(
-               __field(dev_t,          dev             )
-               __field(u64,            member          )
-               __field(u64,            bucket          )
-               __field(u32,            sectors         )
-               __field(u32,            bucket_size     )
-               __field(int,            ret             )
-       ),
-
-       TP_fast_assign(
-               __entry->dev                    = c->dev;
-               __entry->member                 = bucket->inode;
-               __entry->bucket                 = bucket->offset;
-               __entry->sectors                = sectors;
-               __entry->bucket_size            = bucket_size;
-               __entry->ret                    = ret;
-       ),
-
-       TP_printk("%d,%d %llu:%llu sectors %u/%u ret %i",
-                 MAJOR(__entry->dev), MINOR(__entry->dev),
-                 __entry->member, __entry->bucket,
-                 __entry->sectors, __entry->bucket_size,
-                 __entry->ret)
-);
-
 TRACE_EVENT(copygc,
        TP_PROTO(struct bch_fs *c,
                 u64 buckets,