summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2019-10-04 20:40:47 -0400
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:08:28 -0400
commit63fbf458cb7d7df6b58f982df7496f79ee9e6863 (patch)
tree3745246903357f2a29751e4f28e68f4ff1d74fa0 /fs
parent0741d378216054145c9fd2c316924e1d403c8266 (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.c9
-rw-r--r--fs/bcachefs/dirent.c7
-rw-r--r--fs/bcachefs/dirent.h2
-rw-r--r--fs/bcachefs/fs-common.c25
-rw-r--r--fs/bcachefs/fs-common.h3
-rw-r--r--fs/bcachefs/reflink.c12
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,