aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorGravatar Kent Overstreet <kent.overstreet@linux.dev> 2023-02-17 22:43:47 -0500
committerGravatar Kent Overstreet <kent.overstreet@linux.dev> 2023-10-22 17:09:53 -0400
commit73d86dfd888541fd85f7e4d03c898f2ad8486196 (patch)
tree8f8008259cbcb45eb752c1c6d5b820c580cdb64b /fs
parentbcachefs: Don't block on ec_stripe_head_lock with btree locks held (diff)
downloadlinux-73d86dfd888541fd85f7e4d03c898f2ad8486196.tar.gz
linux-73d86dfd888541fd85f7e4d03c898f2ad8486196.tar.bz2
linux-73d86dfd888541fd85f7e4d03c898f2ad8486196.zip
bcachefs: Fix erasure coding locking
This adds a new helper, bch2_trans_mutex_lock(), for locking a mutex - dropping and retaking btree locks as needed. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs')
-rw-r--r--fs/bcachefs/alloc_foreground.c10
-rw-r--r--fs/bcachefs/btree_iter.h9
-rw-r--r--fs/bcachefs/btree_locking.c13
-rw-r--r--fs/bcachefs/ec.c19
4 files changed, 34 insertions, 17 deletions
diff --git a/fs/bcachefs/alloc_foreground.c b/fs/bcachefs/alloc_foreground.c
index 2eab63b90664..0b0fe4fea6cc 100644
--- a/fs/bcachefs/alloc_foreground.c
+++ b/fs/bcachefs/alloc_foreground.c
@@ -1073,7 +1073,7 @@ static bool try_decrease_writepoints(struct bch_fs *c,
return true;
}
-static void bch2_trans_mutex_lock(struct btree_trans *trans,
+static void bch2_trans_mutex_lock_norelock(struct btree_trans *trans,
struct mutex *lock)
{
if (!mutex_trylock(lock)) {
@@ -1091,7 +1091,7 @@ static struct write_point *writepoint_find(struct btree_trans *trans,
if (!(write_point & 1UL)) {
wp = (struct write_point *) write_point;
- bch2_trans_mutex_lock(trans, &wp->lock);
+ bch2_trans_mutex_lock_norelock(trans, &wp->lock);
return wp;
}
@@ -1100,7 +1100,7 @@ restart_find:
wp = __writepoint_find(head, write_point);
if (wp) {
lock_wp:
- bch2_trans_mutex_lock(trans, &wp->lock);
+ bch2_trans_mutex_lock_norelock(trans, &wp->lock);
if (wp->write_point == write_point)
goto out;
mutex_unlock(&wp->lock);
@@ -1113,8 +1113,8 @@ restart_find_oldest:
if (!oldest || time_before64(wp->last_used, oldest->last_used))
oldest = wp;
- bch2_trans_mutex_lock(trans, &oldest->lock);
- bch2_trans_mutex_lock(trans, &c->write_points_hash_lock);
+ bch2_trans_mutex_lock_norelock(trans, &oldest->lock);
+ bch2_trans_mutex_lock_norelock(trans, &c->write_points_hash_lock);
if (oldest >= c->write_points + c->write_points_nr ||
try_increase_writepoints(c)) {
mutex_unlock(&c->write_points_hash_lock);
diff --git a/fs/bcachefs/btree_iter.h b/fs/bcachefs/btree_iter.h
index 4b1f993ea3fb..458c7f7dc5b7 100644
--- a/fs/bcachefs/btree_iter.h
+++ b/fs/bcachefs/btree_iter.h
@@ -197,6 +197,15 @@ struct bkey_i *bch2_btree_journal_peek_slot(struct btree_trans *,
void bch2_btree_path_level_init(struct btree_trans *, struct btree_path *, struct btree *);
+int __bch2_trans_mutex_lock(struct btree_trans *, struct mutex *);
+
+static inline int bch2_trans_mutex_lock(struct btree_trans *trans, struct mutex *lock)
+{
+ return mutex_trylock(lock)
+ ? 0
+ : __bch2_trans_mutex_lock(trans, lock);
+}
+
#ifdef CONFIG_BCACHEFS_DEBUG
void bch2_trans_verify_paths(struct btree_trans *);
void bch2_assert_pos_locked(struct btree_trans *, enum btree_id,
diff --git a/fs/bcachefs/btree_locking.c b/fs/bcachefs/btree_locking.c
index 49c7e94573c9..14a0614af436 100644
--- a/fs/bcachefs/btree_locking.c
+++ b/fs/bcachefs/btree_locking.c
@@ -725,6 +725,19 @@ bool bch2_trans_locked(struct btree_trans *trans)
return false;
}
+int __bch2_trans_mutex_lock(struct btree_trans *trans,
+ struct mutex *lock)
+{
+ int ret;
+
+ bch2_trans_unlock(trans);
+ mutex_lock(lock);
+ ret = bch2_trans_relock(trans);
+ if (ret)
+ mutex_unlock(lock);
+ return ret;
+}
+
/* Debug */
#ifdef CONFIG_BCACHEFS_DEBUG
diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c
index 236e1bef5f02..6d0a49000bef 100644
--- a/fs/bcachefs/ec.c
+++ b/fs/bcachefs/ec.c
@@ -1231,7 +1231,7 @@ ec_new_stripe_head_alloc(struct bch_fs *c, unsigned target,
return NULL;
mutex_init(&h->lock);
- mutex_lock(&h->lock);
+ BUG_ON(!mutex_trylock(&h->lock));
h->target = target;
h->algo = algo;
@@ -1280,23 +1280,18 @@ struct ec_stripe_head *__bch2_ec_stripe_head_get(struct btree_trans *trans,
if (!redundancy)
return NULL;
- if (!mutex_trylock(&c->ec_stripe_head_lock)) {
- bch2_trans_unlock(trans);
- mutex_lock(&c->ec_stripe_head_lock);
-
- ret = bch2_trans_relock(trans);
- if (ret) {
- mutex_unlock(&c->ec_stripe_head_lock);
- return ERR_PTR(ret);
- }
- }
+ ret = bch2_trans_mutex_lock(trans, &c->ec_stripe_head_lock);
+ if (ret)
+ return ERR_PTR(ret);
list_for_each_entry(h, &c->ec_stripe_head_list, list)
if (h->target == target &&
h->algo == algo &&
h->redundancy == redundancy &&
h->copygc == copygc) {
- mutex_lock(&h->lock);
+ ret = bch2_trans_mutex_lock(trans, &h->lock);
+ if (ret)
+ h = ERR_PTR(ret);
goto found;
}