Commit fca1223c authored by Kent Overstreet's avatar Kent Overstreet Committed by Kent Overstreet

bcachefs: Avoid write lock on mark_lock

mark_lock is a frequently taken lock, and there's also potential for
deadlocks since currently bch2_clear_page_bits which is called from
memory reclaim has to take it to drop disk reservations.

The disk reservation get path takes it when it recalculates the number
of sectors known to be available, but it's not really needed for
consistency.  We just want to make sure we only have one thread updating
the sectors_available count, which we can do with a dedicated mutex.
Signed-off-by: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent 33eb63e5
...@@ -640,6 +640,7 @@ struct bch_fs { ...@@ -640,6 +640,7 @@ struct bch_fs {
unsigned bucket_size_max; unsigned bucket_size_max;
atomic64_t sectors_available; atomic64_t sectors_available;
struct mutex sectors_available_lock;
struct bch_fs_pcpu __percpu *pcpu; struct bch_fs_pcpu __percpu *pcpu;
......
...@@ -1182,13 +1182,6 @@ void bch2_trans_fs_usage_apply(struct btree_trans *trans, ...@@ -1182,13 +1182,6 @@ void bch2_trans_fs_usage_apply(struct btree_trans *trans,
/* Disk reservations: */ /* Disk reservations: */
static u64 bch2_recalc_sectors_available(struct bch_fs *c)
{
percpu_u64_set(&c->pcpu->sectors_available, 0);
return avail_factor(__bch2_fs_usage_read_short(c).free);
}
void __bch2_disk_reservation_put(struct bch_fs *c, struct disk_reservation *res) void __bch2_disk_reservation_put(struct bch_fs *c, struct disk_reservation *res)
{ {
percpu_down_read(&c->mark_lock); percpu_down_read(&c->mark_lock);
...@@ -1222,7 +1215,6 @@ int bch2_disk_reservation_add(struct bch_fs *c, struct disk_reservation *res, ...@@ -1222,7 +1215,6 @@ int bch2_disk_reservation_add(struct bch_fs *c, struct disk_reservation *res,
if (get < sectors) { if (get < sectors) {
preempt_enable(); preempt_enable();
percpu_up_read(&c->mark_lock);
goto recalculate; goto recalculate;
} }
} while ((v = atomic64_cmpxchg(&c->sectors_available, } while ((v = atomic64_cmpxchg(&c->sectors_available,
...@@ -1240,9 +1232,10 @@ int bch2_disk_reservation_add(struct bch_fs *c, struct disk_reservation *res, ...@@ -1240,9 +1232,10 @@ int bch2_disk_reservation_add(struct bch_fs *c, struct disk_reservation *res,
return 0; return 0;
recalculate: recalculate:
percpu_down_write(&c->mark_lock); mutex_lock(&c->sectors_available_lock);
sectors_available = bch2_recalc_sectors_available(c); percpu_u64_set(&c->pcpu->sectors_available, 0);
sectors_available = avail_factor(__bch2_fs_usage_read_short(c).free);
if (sectors <= sectors_available || if (sectors <= sectors_available ||
(flags & BCH_DISK_RESERVATION_NOFAIL)) { (flags & BCH_DISK_RESERVATION_NOFAIL)) {
...@@ -1256,7 +1249,8 @@ int bch2_disk_reservation_add(struct bch_fs *c, struct disk_reservation *res, ...@@ -1256,7 +1249,8 @@ int bch2_disk_reservation_add(struct bch_fs *c, struct disk_reservation *res,
ret = -ENOSPC; ret = -ENOSPC;
} }
percpu_up_write(&c->mark_lock); mutex_unlock(&c->sectors_available_lock);
percpu_up_read(&c->mark_lock);
return ret; return ret;
} }
......
...@@ -669,6 +669,8 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts) ...@@ -669,6 +669,8 @@ static struct bch_fs *bch2_fs_alloc(struct bch_sb *sb, struct bch_opts opts)
bch2_fs_btree_cache_init_early(&c->btree_cache); bch2_fs_btree_cache_init_early(&c->btree_cache);
mutex_init(&c->sectors_available_lock);
if (percpu_init_rwsem(&c->mark_lock)) if (percpu_init_rwsem(&c->mark_lock))
goto err; goto err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment