diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2019-10-04 20:40:47 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:08:28 -0400 |
commit | 63fbf458cb7d7df6b58f982df7496f79ee9e6863 (patch) | |
tree | 3745246903357f2a29751e4f28e68f4ff1d74fa0 /fs | |
parent | 0741d378216054145c9fd2c316924e1d403c8266 (diff) |
bcachefs: Can't be holding read locks while taking write locks
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bcachefs/btree_update_leaf.c | 9 | ||||
-rw-r--r-- | fs/bcachefs/dirent.c | 7 | ||||
-rw-r--r-- | fs/bcachefs/dirent.h | 2 | ||||
-rw-r--r-- | fs/bcachefs/fs-common.c | 25 | ||||
-rw-r--r-- | fs/bcachefs/fs-common.h | 3 | ||||
-rw-r--r-- | fs/bcachefs/reflink.c | 12 |
6 files changed, 33 insertions, 25 deletions
diff --git a/fs/bcachefs/btree_update_leaf.c b/fs/bcachefs/btree_update_leaf.c index 05b9c0d2e893..fd50f51943c3 100644 --- a/fs/bcachefs/btree_update_leaf.c +++ b/fs/bcachefs/btree_update_leaf.c @@ -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); diff --git a/fs/bcachefs/dirent.c b/fs/bcachefs/dirent.c index 304128d7251f..2a3e830ebf50 100644 --- a/fs/bcachefs/dirent.c +++ b/fs/bcachefs/dirent.c @@ -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; diff --git a/fs/bcachefs/dirent.h b/fs/bcachefs/dirent.h index 9a57ad005468..e6184dc796d3 100644 --- a/fs/bcachefs/dirent.h +++ b/fs/bcachefs/dirent.h @@ -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 *); diff --git a/fs/bcachefs/fs-common.c b/fs/bcachefs/fs-common.c index fdd2b9b6716f..a4497eeb1f1b 100644 --- a/fs/bcachefs/fs-common.c +++ b/fs/bcachefs/fs-common.c @@ -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); diff --git a/fs/bcachefs/fs-common.h b/fs/bcachefs/fs-common.h index 7adcfcf92aec..c1621485a526 100644 --- a/fs/bcachefs/fs-common.h +++ b/fs/bcachefs/fs-common.h @@ -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 *); diff --git a/fs/bcachefs/reflink.c b/fs/bcachefs/reflink.c index ad526d280a14..f1b0e7fc8487 100644 --- a/fs/bcachefs/reflink.c +++ b/fs/bcachefs/reflink.c @@ -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, |