bcachefs: bch2_write_inode() now checks for changing rebalance options
authorKent Overstreet <kent.overstreet@linux.dev>
Mon, 21 Oct 2024 00:53:53 +0000 (20:53 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sat, 21 Dec 2024 06:36:16 +0000 (01:36 -0500)
Previously, BCHFS_IOC_REINHERIT_ATTRS didn't trigger rebalance scans
when changing rebalance options - it had been missed, only the xattr
interface triggered them.

Ideally they'd be done by the transactional trigger, but unpacking the
inode to get the options is too heavy to be done in the low level
trigger - the inode trigger is run on every extent update, since the
bch_inode.bi_journal_seq has to be updated for fsync.

bch2_write_inode() is a good compromise, it already unpacks and repacks
and is not run in any super-fast paths.

Additionally, creating the new rebalance entry to trigger the scan is
now done in the same transaction as the inode update that changed the
options.

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

index 646b74494a3f3514102fa1f45bcb16f32d9e9401..e0ffe4648bb87777843e52a20272994629d16d80 100644 (file)
@@ -23,6 +23,7 @@
 #include "journal.h"
 #include "keylist.h"
 #include "quota.h"
+#include "rebalance.h"
 #include "snapshot.h"
 #include "super.h"
 #include "xattr.h"
@@ -89,10 +90,25 @@ int __must_check bch2_write_inode(struct bch_fs *c,
 retry:
        bch2_trans_begin(trans);
 
-       ret   = bch2_inode_peek(trans, &iter, &inode_u, inode_inum(inode),
-                               BTREE_ITER_intent) ?:
-               (set ? set(trans, inode, &inode_u, p) : 0) ?:
-               bch2_inode_write(trans, &iter, &inode_u) ?:
+       ret = bch2_inode_peek(trans, &iter, &inode_u, inode_inum(inode), BTREE_ITER_intent);
+       if (ret)
+               goto err;
+
+       struct bch_extent_rebalance old_r = bch2_inode_rebalance_opts_get(c, &inode_u);
+
+       ret = (set ? set(trans, inode, &inode_u, p) : 0);
+       if (ret)
+               goto err;
+
+       struct bch_extent_rebalance new_r = bch2_inode_rebalance_opts_get(c, &inode_u);
+
+       if (memcmp(&old_r, &new_r, sizeof(new_r))) {
+               ret = bch2_set_rebalance_needs_scan_trans(trans, inode_u.bi_inum);
+               if (ret)
+                       goto err;
+       }
+
+       ret   = bch2_inode_write(trans, &iter, &inode_u) ?:
                bch2_trans_commit(trans, NULL, NULL, BCH_TRANS_COMMIT_no_enospc);
 
        /*
@@ -101,7 +117,7 @@ retry:
         */
        if (!ret)
                bch2_inode_update_after_write(trans, inode, &inode_u, fields);
-
+err:
        bch2_trans_iter_exit(trans, &iter);
 
        if (bch2_err_matches(ret, BCH_ERR_transaction_restart))
index bdeb6be76038ab907f7f79f275874b3fabe170fa..f52336cb298f5e1de16ea41deaae9fd4fe860652 100644 (file)
@@ -262,6 +262,14 @@ void bch2_inode_opts_get(struct bch_io_opts *, struct bch_fs *,
                         struct bch_inode_unpacked *);
 int bch2_inum_opts_get(struct btree_trans*, subvol_inum, struct bch_io_opts *);
 
+static inline struct bch_extent_rebalance
+bch2_inode_rebalance_opts_get(struct bch_fs *c, struct bch_inode_unpacked *inode)
+{
+       struct bch_io_opts io_opts;
+       bch2_inode_opts_get(&io_opts, c, inode);
+       return io_opts_to_rebalance_opts(&io_opts);
+}
+
 int bch2_inode_rm_snapshot(struct btree_trans *, u64, u32);
 int bch2_delete_dead_inodes(struct bch_fs *);
 
index d8cb346ac138d4a0ff761e7dbcf67cf9406e0466..926b9d5eba4562cd853bb774a7cd934a250494d9 100644 (file)
@@ -33,7 +33,7 @@ static const char * const bch2_rebalance_state_strs[] = {
 #undef x
 };
 
-static int __bch2_set_rebalance_needs_scan(struct btree_trans *trans, u64 inum)
+int bch2_set_rebalance_needs_scan_trans(struct btree_trans *trans, u64 inum)
 {
        struct btree_iter iter;
        struct bkey_s_c k;
@@ -73,7 +73,7 @@ int bch2_set_rebalance_needs_scan(struct bch_fs *c, u64 inum)
        int ret = bch2_trans_commit_do(c, NULL, NULL,
                                       BCH_TRANS_COMMIT_no_enospc|
                                       BCH_TRANS_COMMIT_lazy_rw,
-                           __bch2_set_rebalance_needs_scan(trans, inum));
+                           bch2_set_rebalance_needs_scan_trans(trans, inum));
        rebalance_wakeup(c);
        return ret;
 }
index 28a52638f16cc113848cf3925758e12d510dc247..791649c04ff5de2a1013655893eff15abe7c860c 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "rebalance_types.h"
 
+int bch2_set_rebalance_needs_scan_trans(struct btree_trans *, u64);
 int bch2_set_rebalance_needs_scan(struct bch_fs *, u64 inum);
 int bch2_set_fs_needs_rebalance(struct bch_fs *);
 
index bf3c6bb5049562f8588f2eb7c09ffa19ab2d240d..ed418a747cddebabd17231c58c566a1b18ec0b29 100644 (file)
@@ -565,13 +565,6 @@ static int bch2_xattr_bcachefs_set(const struct xattr_handler *handler,
        ret = bch2_write_inode(c, inode, inode_opt_set_fn, &s, 0);
 err:
        mutex_unlock(&inode->ei_update_lock);
-
-       if (value &&
-           (opt_id == Opt_background_target ||
-            opt_id == Opt_background_compression ||
-            (opt_id == Opt_compression && !inode_opt_get(c, &inode->ei_inode, background_compression))))
-               bch2_set_rebalance_needs_scan(c, inode->ei_inode.bi_inum);
-
 err_class_exit:
        return bch2_err_class(ret);
 }