]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bcachefs: Can't be holding read locks while taking write locks
authorKent Overstreet <kent.overstreet@gmail.com>
Sat, 5 Oct 2019 00:40:47 +0000 (20:40 -0400)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:08:28 +0000 (17:08 -0400)
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
fs/bcachefs/btree_update_leaf.c
fs/bcachefs/dirent.c
fs/bcachefs/dirent.h
fs/bcachefs/fs-common.c
fs/bcachefs/fs-common.h
fs/bcachefs/reflink.c

index 05b9c0d2e8935650c671303476837de33448f2c4..fd50f51943c3a595535920ef04ea748c0b7906e0 100644 (file)
@@ -451,6 +451,7 @@ static inline int do_btree_insert_at(struct btree_trans *trans,
        struct bch_fs *c = trans->c;
        struct bch_fs_usage_online *fs_usage = NULL;
        struct btree_insert_entry *i;
+       struct btree_iter *iter;
        unsigned mark_flags = trans->flags & BTREE_INSERT_BUCKET_INVALIDATE
                ? BCH_BUCKET_MARK_BUCKET_INVALIDATE
                : 0;
@@ -473,6 +474,14 @@ static inline int do_btree_insert_at(struct btree_trans *trans,
                                goto out_clear_replicas;
                }
 
+       trans_for_each_iter(trans, iter) {
+               if (iter->nodes_locked != iter->nodes_intent_locked) {
+                       BUG_ON(iter->flags & BTREE_ITER_KEEP_UNTIL_COMMIT);
+                       BUG_ON(trans->iters_live & (1ULL << iter->idx));
+                       __bch2_btree_iter_unlock(iter);
+               }
+       }
+
        if (IS_ENABLED(CONFIG_BCACHEFS_DEBUG))
                trans_for_each_update(trans, i)
                        btree_insert_entry_checks(trans, i);
index 304128d7251fd7850b51163e6268b7d4d7bce414..2a3e830ebf500a39015ec1d154d09beaadca926b 100644 (file)
@@ -296,10 +296,10 @@ int bch2_dirent_delete(struct bch_fs *c, u64 dir_inum,
 struct btree_iter *
 __bch2_dirent_lookup_trans(struct btree_trans *trans, u64 dir_inum,
                           const struct bch_hash_info *hash_info,
-                          const struct qstr *name)
+                          const struct qstr *name, unsigned flags)
 {
        return bch2_hash_lookup(trans, bch2_dirent_hash_desc,
-                               hash_info, dir_inum, name, 0);
+                               hash_info, dir_inum, name, flags);
 }
 
 u64 bch2_dirent_lookup(struct bch_fs *c, u64 dir_inum,
@@ -313,7 +313,8 @@ u64 bch2_dirent_lookup(struct bch_fs *c, u64 dir_inum,
 
        bch2_trans_init(&trans, c, 0, 0);
 
-       iter = __bch2_dirent_lookup_trans(&trans, dir_inum, hash_info, name);
+       iter = __bch2_dirent_lookup_trans(&trans, dir_inum,
+                                         hash_info, name, 0);
        if (IS_ERR(iter)) {
                BUG_ON(PTR_ERR(iter) == -EINTR);
                goto out;
index 9a57ad005468d3538941e4c4847d6c9ecf8f3c17..e6184dc796d38e634bf60fce3d14b379b956424a 100644 (file)
@@ -55,7 +55,7 @@ int bch2_dirent_rename(struct btree_trans *,
 struct btree_iter *
 __bch2_dirent_lookup_trans(struct btree_trans *, u64,
                           const struct bch_hash_info *,
-                          const struct qstr *);
+                          const struct qstr *, unsigned);
 u64 bch2_dirent_lookup(struct bch_fs *, u64, const struct bch_hash_info *,
                       const struct qstr *);
 
index fdd2b9b6716f571e270758de2a237df3419db480..a4497eeb1f1bb7d2747199877702089818a50739 100644 (file)
@@ -24,8 +24,7 @@ int bch2_create_trans(struct btree_trans *trans, u64 dir_inum,
        u64 now = bch2_current_time(trans->c);
        int ret;
 
-       dir_iter = bch2_inode_peek(trans, dir_u, dir_inum,
-                                  name ? BTREE_ITER_INTENT : 0);
+       dir_iter = bch2_inode_peek(trans, dir_u, dir_inum, BTREE_ITER_INTENT);
        if (IS_ERR(dir_iter))
                return PTR_ERR(dir_iter);
 
@@ -76,8 +75,7 @@ int bch2_create_trans(struct btree_trans *trans, u64 dir_inum,
        return 0;
 }
 
-int bch2_link_trans(struct btree_trans *trans,
-                   u64 dir_inum,
+int bch2_link_trans(struct btree_trans *trans, u64 dir_inum,
                    u64 inum, struct bch_inode_unpacked *inode_u,
                    const struct qstr *name)
 {
@@ -86,19 +84,22 @@ int bch2_link_trans(struct btree_trans *trans,
        struct bch_hash_info dir_hash;
        u64 now = bch2_current_time(trans->c);
 
-       dir_iter = bch2_inode_peek(trans, &dir_u, dir_inum, 0);
-       if (IS_ERR(dir_iter))
-               return PTR_ERR(dir_iter);
-
        inode_iter = bch2_inode_peek(trans, inode_u, inum, BTREE_ITER_INTENT);
        if (IS_ERR(inode_iter))
                return PTR_ERR(inode_iter);
 
-       dir_hash = bch2_hash_info_init(trans->c, &dir_u);
-
        inode_u->bi_ctime = now;
        bch2_inode_nlink_inc(inode_u);
 
+       dir_iter = bch2_inode_peek(trans, &dir_u, dir_inum, 0);
+       if (IS_ERR(dir_iter))
+               return PTR_ERR(dir_iter);
+
+       /* XXX: shouldn't we be updating mtime/ctime on the directory? */
+
+       dir_hash = bch2_hash_info_init(trans->c, &dir_u);
+       bch2_trans_iter_put(trans, dir_iter);
+
        return bch2_dirent_create(trans, dir_inum, &dir_hash,
                                  mode_to_type(inode_u->bi_mode),
                                  name, inum, BCH_HASH_SET_MUST_CREATE) ?:
@@ -121,8 +122,8 @@ int bch2_unlink_trans(struct btree_trans *trans,
 
        dir_hash = bch2_hash_info_init(trans->c, dir_u);
 
-       dirent_iter = __bch2_dirent_lookup_trans(trans, dir_inum,
-                                                &dir_hash, name);
+       dirent_iter = __bch2_dirent_lookup_trans(trans, dir_inum, &dir_hash,
+                                                name, BTREE_ITER_INTENT);
        if (IS_ERR(dirent_iter))
                return PTR_ERR(dirent_iter);
 
index 7adcfcf92aec5b8892559cba4af06a328454ad6d..c1621485a526b7e77a7ec802de9b850e6b69c82e 100644 (file)
@@ -12,8 +12,7 @@ int bch2_create_trans(struct btree_trans *, u64,
                      struct posix_acl *,
                      struct posix_acl *);
 
-int bch2_link_trans(struct btree_trans *,
-                   u64,
+int bch2_link_trans(struct btree_trans *, u64,
                    u64, struct bch_inode_unpacked *,
                    const struct qstr *);
 
index ad526d280a145cb5f80c57739717f6c27c359cbd..f1b0e7fc8487a1143d5546650bb762f81a9422e5 100644 (file)
@@ -144,20 +144,18 @@ err:
 static struct bkey_s_c get_next_src(struct btree_iter *iter, struct bpos end)
 {
        struct bkey_s_c k = bch2_btree_iter_peek(iter);
+       int ret;
 
-       while (1) {
-               if (bkey_err(k))
-                       return k;
-
+       for_each_btree_key_continue(iter, 0, k, ret) {
                if (bkey_cmp(iter->pos, end) >= 0)
                        return bkey_s_c_null;
 
                if (k.k->type == KEY_TYPE_extent ||
                    k.k->type == KEY_TYPE_reflink_p)
-                       return k;
-
-               k = bch2_btree_iter_next(iter);
+                       break;
        }
+
+       return k;
 }
 
 s64 bch2_remap_range(struct bch_fs *c,