diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2023-03-19 12:50:05 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:09:58 -0400 |
commit | ac77810cb4ffd16976487d787e2f81ba9cb5fd0c (patch) | |
tree | a71ffe84c50508fe578f2eb9e8b2168b9bc91556 /fs | |
parent | abab7609de92c973bfa3ad069a622c0a107b6386 (diff) | |
download | lwn-ac77810cb4ffd16976487d787e2f81ba9cb5fd0c.tar.gz lwn-ac77810cb4ffd16976487d787e2f81ba9cb5fd0c.zip |
bcachefs: Nocow write error path fix
The nocow write error path was iterating over pointers in an extent,
aftre we'd dropped btree locks - oops.
Fortunately we'd already stashed what we need in nocow_lock_bucket, so
use that instead.
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/bcachefs/io.c | 18 |
1 files changed, 7 insertions, 11 deletions
diff --git a/fs/bcachefs/io.c b/fs/bcachefs/io.c index 0c2d42eaba56..ad22557197a6 100644 --- a/fs/bcachefs/io.c +++ b/fs/bcachefs/io.c @@ -1481,7 +1481,7 @@ static void bch2_nocow_write(struct bch_write_op *op) struct btree_iter iter; struct bkey_s_c k; struct bkey_ptrs_c ptrs; - const struct bch_extent_ptr *ptr, *ptr2; + const struct bch_extent_ptr *ptr; struct { struct bpos b; unsigned gen; @@ -1536,11 +1536,12 @@ retry: bucket_to_u64(buckets[nr_buckets].b)); prefetch(buckets[nr_buckets].l); - nr_buckets++; if (unlikely(!bch2_dev_get_ioref(bch_dev_bkey_exists(c, ptr->dev), WRITE))) goto err_get_ioref; + nr_buckets++; + if (ptr->unwritten) op->flags |= BCH_WRITE_CONVERT_UNWRITTEN; } @@ -1631,12 +1632,8 @@ err: } return; err_get_ioref: - bkey_for_each_ptr(ptrs, ptr2) { - if (ptr2 == ptr) - break; - - percpu_ref_put(&bch_dev_bkey_exists(c, ptr2->dev)->io_ref); - } + for (i = 0; i < nr_buckets; i++) + percpu_ref_put(&bch_dev_bkey_exists(c, buckets[i].b.inode)->io_ref); /* Fall back to COW path: */ goto out; @@ -1645,9 +1642,8 @@ err_bucket_stale: bch2_bucket_nocow_unlock(&c->nocow_locks, buckets[i].b, BUCKET_NOCOW_LOCK_UPDATE); - - bkey_for_each_ptr(ptrs, ptr2) - percpu_ref_put(&bch_dev_bkey_exists(c, ptr2->dev)->io_ref); + for (i = 0; i < nr_buckets; i++) + percpu_ref_put(&bch_dev_bkey_exists(c, buckets[i].b.inode)->io_ref); /* We can retry this: */ ret = BCH_ERR_transaction_restart; |