diff options
author | Daniel Hill <daniel@gluo.nz> | 2023-01-06 21:11:07 +1300 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-03-13 11:34:49 -0400 |
commit | ab30ea8e044beeab202e54bf67f16b4cef849ed1 (patch) | |
tree | 63932cf3e3fcb44c2b1de0f2bf4813835d1cd5a3 | |
parent | 05283fec05a4b01fb0befacfdfc1097d9219616f (diff) |
bcachefs: don't block reads if we're promoting
The promote path calls data_update_init() and now that we take locks here,
there's potential for promote to block our read path, just error
when we can't take the lock instead of blocking.
Signed-off-by: Daniel Hill <daniel@gluo.nz>
-rw-r--r-- | fs/bcachefs/data_update.c | 26 | ||||
-rw-r--r-- | fs/bcachefs/errcode.h | 1 | ||||
-rw-r--r-- | fs/bcachefs/io.c | 7 |
3 files changed, 25 insertions, 9 deletions
diff --git a/fs/bcachefs/data_update.c b/fs/bcachefs/data_update.c index d44fc1a3d622..9df958b43dfe 100644 --- a/fs/bcachefs/data_update.c +++ b/fs/bcachefs/data_update.c @@ -412,6 +412,7 @@ int bch2_data_update_init(struct btree_trans *trans, const union bch_extent_entry *entry; struct extent_ptr_decoded p; unsigned i, reserve_sectors = k.k->size * data_opts.extra_replicas; + unsigned int ptrs_locked = 0; int ret; bch2_bkey_buf_init(&m->k); @@ -437,6 +438,8 @@ int bch2_data_update_init(struct btree_trans *trans, i = 0; bkey_for_each_ptr_decode(k.k, ptrs, p, entry) { + bool locked; + if (((1U << i) & m->data_opts.rewrite_ptrs) && p.ptr.cached) BUG(); @@ -462,11 +465,7 @@ int bch2_data_update_init(struct btree_trans *trans, if (p.crc.compression_type == BCH_COMPRESSION_TYPE_incompressible) m->op.incompressible = true; - i++; - if (ctxt) { - bool locked; - move_ctxt_wait_event(ctxt, trans, (locked = bch2_bucket_nocow_trylock(&c->nocow_locks, PTR_BUCKET_POS(c, &p.ptr), 0)) || @@ -476,9 +475,14 @@ int bch2_data_update_init(struct btree_trans *trans, bch2_bucket_nocow_lock(&c->nocow_locks, PTR_BUCKET_POS(c, &p.ptr), 0); } else { - bch2_bucket_nocow_lock(&c->nocow_locks, - PTR_BUCKET_POS(c, &p.ptr), 0); + if (!bch2_bucket_nocow_trylock(&c->nocow_locks, + PTR_BUCKET_POS(c, &p.ptr), 0)) { + ret = -BCH_ERR_nocow_lock_blocked; + goto err; + } } + ptrs_locked |= (1U << i); + i++; } if (reserve_sectors) { @@ -500,9 +504,13 @@ int bch2_data_update_init(struct btree_trans *trans, return -BCH_ERR_unwritten_extent_update; return 0; err: - bkey_for_each_ptr_decode(k.k, ptrs, p, entry) - bch2_bucket_nocow_unlock(&c->nocow_locks, - PTR_BUCKET_POS(c, &p.ptr), 0); + i = 0; + bkey_for_each_ptr_decode(k.k, ptrs, p, entry) { + if ((1U << i) & ptrs_locked) + bch2_bucket_nocow_unlock(&c->nocow_locks, + PTR_BUCKET_POS(c, &p.ptr), 0); + i++; + } bch2_bkey_buf_exit(&m->k, c); bch2_bio_free_pages_pool(c, &m->op.wbio.bio); diff --git a/fs/bcachefs/errcode.h b/fs/bcachefs/errcode.h index 57f1d0a6a490..6129af6129c3 100644 --- a/fs/bcachefs/errcode.h +++ b/fs/bcachefs/errcode.h @@ -120,6 +120,7 @@ x(BCH_ERR_invalid_sb, invalid_sb_clean) \ x(BCH_ERR_invalid_sb, invalid_sb_quota) \ x(BCH_ERR_invalid, invalid_bkey) \ + x(BCH_ERR_operation_blocked, nocow_lock_blocked) \ enum bch_errcode { BCH_ERR_START = 2048, diff --git a/fs/bcachefs/io.c b/fs/bcachefs/io.c index 27159c646043..64925db22cdc 100644 --- a/fs/bcachefs/io.c +++ b/fs/bcachefs/io.c @@ -2024,6 +2024,13 @@ static struct promote_op *__promote_alloc(struct btree_trans *trans, .write_flags = BCH_WRITE_ALLOC_NOWAIT|BCH_WRITE_CACHED, }, btree_id, k); + if (ret == -BCH_ERR_nocow_lock_blocked) { + ret = rhashtable_remove_fast(&c->promote_table, &op->hash, + bch_promote_params); + BUG_ON(ret); + goto err; + } + BUG_ON(ret); op->write.op.end_io = promote_done; |