bcachefs: Use deferred btree updates for inode updates
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 21 Jul 2018 02:27:07 +0000 (22:27 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:17 +0000 (17:08 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_iter.h
fs/bcachefs/btree_locking.h
fs/bcachefs/fs-io.c
fs/bcachefs/fs.c
fs/bcachefs/fs.h

index 52e0e003153b5cd96e213bc8fa4daf671cce92a3..a64ed6d321754431de97b597336a84d8468eab36 100644 (file)
@@ -104,6 +104,7 @@ void bch2_btree_node_iter_fix(struct btree_iter *, struct btree *,
                              unsigned, unsigned);
 
 int bch2_btree_iter_unlock(struct btree_iter *);
+bool bch2_btree_iter_relock(struct btree_iter *);
 
 bool __bch2_btree_iter_upgrade(struct btree_iter *, unsigned);
 bool __bch2_btree_iter_upgrade_nounlock(struct btree_iter *, unsigned);
index 48b50e0661869526f046719c0eafe0263479475e..c036cd0458a4a35cf40c589cf5c9be06f7266b09 100644 (file)
@@ -203,8 +203,6 @@ static inline bool bch2_btree_node_relock(struct btree_iter *iter,
                __bch2_btree_node_relock(iter, level);
 }
 
-bool bch2_btree_iter_relock(struct btree_iter *);
-
 void bch2_btree_node_unlock_write(struct btree *, struct btree_iter *);
 
 void __bch2_btree_node_lock_write(struct btree *, struct btree_iter *);
index 7681cfbc6bed40710c67a8cb6b6e909e07bd03db..f8657baf0521025495fa6637d1434458e75e9f8c 100644 (file)
@@ -287,11 +287,11 @@ static int bch2_extent_update(struct btree_trans *trans,
                              bool direct,
                              s64 *total_delta)
 {
-       struct btree_iter *inode_iter = NULL;
        struct bch_inode_unpacked inode_u;
        struct bkey_inode_buf inode_p;
        bool allocating = false;
        bool extended = false;
+       bool inode_locked = false;
        s64 i_sectors_delta;
        int ret;
 
@@ -314,16 +314,20 @@ static int bch2_extent_update(struct btree_trans *trans,
        /* XXX: inode->i_size locking */
        if (i_sectors_delta ||
            new_i_size > inode->ei_inode.bi_size) {
-               inode_iter = bch2_trans_get_iter(trans,
-                       BTREE_ID_INODES,
-                       POS(k->k.p.inode, 0),
-                       BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
-               if (IS_ERR(inode_iter))
-                       return PTR_ERR(inode_iter);
+               bch2_btree_iter_unlock(extent_iter);
+               mutex_lock(&inode->ei_update_lock);
 
-               ret = bch2_btree_iter_traverse(inode_iter);
-               if (ret)
-                       goto err;
+               if (!bch2_btree_iter_relock(extent_iter)) {
+                       mutex_unlock(&inode->ei_update_lock);
+                       return -EINTR;
+               }
+
+               inode_locked = true;
+
+               if (!inode->ei_inode_update)
+                       inode->ei_inode_update =
+                               bch2_deferred_update_alloc(trans->c,
+                                                       BTREE_ID_INODES, 64);
 
                inode_u = inode->ei_inode;
                inode_u.bi_sectors += i_sectors_delta;
@@ -337,7 +341,8 @@ static int bch2_extent_update(struct btree_trans *trans,
 
                bch2_inode_pack(&inode_p, &inode_u);
                bch2_trans_update(trans,
-                       BTREE_INSERT_ENTRY(inode_iter, &inode_p.inode.k_i));
+                       BTREE_INSERT_DEFERRED(inode->ei_inode_update,
+                                             &inode_p.inode.k_i));
        }
 
        ret = bch2_trans_commit(trans, disk_res,
@@ -371,13 +376,15 @@ static int bch2_extent_update(struct btree_trans *trans,
        if (total_delta)
                *total_delta += i_sectors_delta;
 err:
-       if (!IS_ERR_OR_NULL(inode_iter))
-               bch2_trans_iter_put(trans, inode_iter);
+       if (inode_locked)
+               mutex_unlock(&inode->ei_update_lock);
+
        return ret;
 }
 
 static int bchfs_write_index_update(struct bch_write_op *wop)
 {
+       struct bch_fs *c = wop->c;
        struct bchfs_write_op *op = container_of(wop,
                                struct bchfs_write_op, op);
        struct quota_res *quota_res = op->is_dio
@@ -392,7 +399,7 @@ static int bchfs_write_index_update(struct bch_write_op *wop)
 
        BUG_ON(k->k.p.inode != inode->v.i_ino);
 
-       bch2_trans_init(&trans, wop->c);
+       bch2_trans_init(&trans, c);
        bch2_trans_preload_iters(&trans);
 
        iter = bch2_trans_get_iter(&trans,
index 02c7543e40c850a10931a2b88636572065140ef1..5f93ea76785f2652b697705634a0bcf5b96b80b1 100644 (file)
@@ -156,12 +156,18 @@ int __must_check bch2_write_inode_trans(struct btree_trans *trans,
                                inode_set_fn set,
                                void *p)
 {
+       struct bch_fs *c = trans->c;
        struct btree_iter *iter;
        struct bkey_inode_buf *inode_p;
        int ret;
 
        lockdep_assert_held(&inode->ei_update_lock);
 
+       /* XXX: Don't do this with btree locks held */
+       if (!inode->ei_inode_update)
+               inode->ei_inode_update =
+                       bch2_deferred_update_alloc(c, BTREE_ID_INODES, 64);
+#if 0
        iter = bch2_trans_get_iter(trans, BTREE_ID_INODES,
                        POS(inode->v.i_ino, 0),
                        BTREE_ITER_SLOTS|BTREE_ITER_INTENT);
@@ -172,7 +178,7 @@ int __must_check bch2_write_inode_trans(struct btree_trans *trans,
        ret = bch2_btree_iter_traverse(iter);
        if (ret)
                return ret;
-
+#endif
        *inode_u = inode->ei_inode;
 
        if (set) {
@@ -186,7 +192,15 @@ int __must_check bch2_write_inode_trans(struct btree_trans *trans,
                return PTR_ERR(inode_p);
 
        bch2_inode_pack(inode_p, inode_u);
-       bch2_trans_update(trans, BTREE_INSERT_ENTRY(iter, &inode_p->inode.k_i));
+
+       if (!inode->ei_inode_update)
+               bch2_trans_update(trans,
+                       BTREE_INSERT_ENTRY(iter, &inode_p->inode.k_i));
+       else
+               bch2_trans_update(trans,
+                       BTREE_INSERT_DEFERRED(inode->ei_inode_update,
+                                             &inode_p->inode.k_i));
+
        return 0;
 }
 
@@ -1431,6 +1445,7 @@ static struct inode *bch2_alloc_inode(struct super_block *sb)
        mutex_init(&inode->ei_update_lock);
        pagecache_lock_init(&inode->ei_pagecache_lock);
        mutex_init(&inode->ei_quota_lock);
+       inode->ei_inode_update = NULL;
        inode->ei_journal_seq = 0;
 
        return &inode->v;
@@ -1494,6 +1509,10 @@ static void bch2_evict_inode(struct inode *vinode)
 
        BUG_ON(!is_bad_inode(&inode->v) && inode->ei_quota_reserved);
 
+       if (inode->ei_inode_update)
+               bch2_deferred_update_free(c, inode->ei_inode_update);
+       inode->ei_inode_update = NULL;
+
        if (!inode->v.i_nlink && !is_bad_inode(&inode->v)) {
                bch2_quota_acct(c, inode->ei_qid, Q_SPC, -((s64) inode->v.i_blocks),
                                KEY_TYPE_QUOTA_WARN);
index f949cd0d2a68e94127d43eb51623950244f2eb29..b9a8a9bc3e90534bfa1fc72e6c29c2c5c7868ad1 100644 (file)
@@ -34,6 +34,7 @@ struct bch_inode_info {
        struct inode            v;
 
        struct mutex            ei_update_lock;
+       struct deferred_update  *ei_inode_update;
        u64                     ei_journal_seq;
        u64                     ei_quota_reserved;
        unsigned long           ei_last_dirtied;