]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: Fix lost rebalance wakeups
authorKent Overstreet <kent.overstreet@linux.dev>
Sat, 24 May 2025 19:29:50 +0000 (15:29 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Tue, 27 May 2025 04:02:44 +0000 (00:02 -0400)
Fix a missing wakeup in

'bcachefs set-file-option' -> xattr option update -> inode_write

this was missing because the wakeup needs to happen after transaction
commit. Also, add a 'kick' counter, to make sure we don't miss a wakeup
that occured right after we finished checking the rebalance_work btree.

Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/fs.c
fs/bcachefs/rebalance.c
fs/bcachefs/rebalance.h
fs/bcachefs/rebalance_types.h

index ddfe89d8496660760af79798263b4a652cce0fbc..adae43223bce3dd6a3832c0d33ba3c7f4fc0fe2b 100644 (file)
@@ -124,8 +124,9 @@ retry:
                goto err;
 
        struct bch_extent_rebalance new_r = bch2_inode_rebalance_opts_get(c, &inode_u);
+       bool rebalance_changed = memcmp(&old_r, &new_r, sizeof(new_r));
 
-       if (memcmp(&old_r, &new_r, sizeof(new_r))) {
+       if (rebalance_changed) {
                ret = bch2_set_rebalance_needs_scan_trans(trans, inode_u.bi_inum);
                if (ret)
                        goto err;
@@ -146,6 +147,9 @@ err:
        if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
                goto retry;
 
+       if (rebalance_changed)
+               bch2_rebalance_wakeup(c);
+
        bch2_fs_fatal_err_on(bch2_err_matches(ret, ENOENT), c,
                             "%s: inode %llu:%llu not found when updating",
                             bch2_err_str(ret),
index de1ec9e0caa0f1791468e5e2efd7b4171d5eb24f..dbaabaad1986b6bf06093f742accd8d13d2ed300 100644 (file)
@@ -527,7 +527,7 @@ static void rebalance_wait(struct bch_fs *c)
                r->state                = BCH_REBALANCE_waiting;
        }
 
-       bch2_kthread_io_clock_wait(clock, r->wait_iotime_end, MAX_SCHEDULE_TIMEOUT);
+       bch2_kthread_io_clock_wait_once(clock, r->wait_iotime_end, MAX_SCHEDULE_TIMEOUT);
 }
 
 static bool bch2_rebalance_enabled(struct bch_fs *c)
@@ -544,6 +544,7 @@ static int do_rebalance(struct moving_context *ctxt)
        struct bch_fs_rebalance *r = &c->rebalance;
        struct btree_iter rebalance_work_iter, extent_iter = {};
        struct bkey_s_c k;
+       u32 kick = r->kick;
        int ret = 0;
 
        bch2_trans_begin(trans);
@@ -593,7 +594,8 @@ static int do_rebalance(struct moving_context *ctxt)
        if (!ret &&
            !kthread_should_stop() &&
            !atomic64_read(&r->work_stats.sectors_seen) &&
-           !atomic64_read(&r->scan_stats.sectors_seen)) {
+           !atomic64_read(&r->scan_stats.sectors_seen) &&
+           kick == r->kick) {
                bch2_moving_ctxt_flush_all(ctxt);
                bch2_trans_unlock_long(trans);
                rebalance_wait(c);
index 5d9214fe1a22b5534d54b0379f09cd37f605f506..7a565ea7dbfcc5b5256bdbfd980f28088c28bea5 100644 (file)
@@ -39,13 +39,11 @@ int bch2_set_fs_needs_rebalance(struct bch_fs *);
 
 static inline void bch2_rebalance_wakeup(struct bch_fs *c)
 {
-       struct task_struct *p;
-
-       rcu_read_lock();
-       p = rcu_dereference(c->rebalance.thread);
+       c->rebalance.kick++;
+       guard(rcu)();
+       struct task_struct *p = rcu_dereference(c->rebalance.thread);
        if (p)
                wake_up_process(p);
-       rcu_read_unlock();
 }
 
 void bch2_rebalance_status_to_text(struct printbuf *, struct bch_fs *);
index 33d77286f1d565c7a1f811e94805ff1670055c51..c659da149fa3c46781371ca9e6941b4f03b549ac 100644 (file)
@@ -18,6 +18,7 @@ enum bch_rebalance_states {
 
 struct bch_fs_rebalance {
        struct task_struct __rcu        *thread;
+       u32                             kick;
        struct bch_pd_controller pd;
 
        enum bch_rebalance_states       state;