Commit ac77810c authored by Kent Overstreet's avatar Kent Overstreet

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: default avatarKent Overstreet <kent.overstreet@linux.dev>
parent abab7609
...@@ -1481,7 +1481,7 @@ static void bch2_nocow_write(struct bch_write_op *op) ...@@ -1481,7 +1481,7 @@ static void bch2_nocow_write(struct bch_write_op *op)
struct btree_iter iter; struct btree_iter iter;
struct bkey_s_c k; struct bkey_s_c k;
struct bkey_ptrs_c ptrs; struct bkey_ptrs_c ptrs;
const struct bch_extent_ptr *ptr, *ptr2; const struct bch_extent_ptr *ptr;
struct { struct {
struct bpos b; struct bpos b;
unsigned gen; unsigned gen;
...@@ -1536,11 +1536,12 @@ static void bch2_nocow_write(struct bch_write_op *op) ...@@ -1536,11 +1536,12 @@ static void bch2_nocow_write(struct bch_write_op *op)
bucket_to_u64(buckets[nr_buckets].b)); bucket_to_u64(buckets[nr_buckets].b));
prefetch(buckets[nr_buckets].l); prefetch(buckets[nr_buckets].l);
nr_buckets++;
if (unlikely(!bch2_dev_get_ioref(bch_dev_bkey_exists(c, ptr->dev), WRITE))) if (unlikely(!bch2_dev_get_ioref(bch_dev_bkey_exists(c, ptr->dev), WRITE)))
goto err_get_ioref; goto err_get_ioref;
nr_buckets++;
if (ptr->unwritten) if (ptr->unwritten)
op->flags |= BCH_WRITE_CONVERT_UNWRITTEN; op->flags |= BCH_WRITE_CONVERT_UNWRITTEN;
} }
...@@ -1631,12 +1632,8 @@ static void bch2_nocow_write(struct bch_write_op *op) ...@@ -1631,12 +1632,8 @@ static void bch2_nocow_write(struct bch_write_op *op)
} }
return; return;
err_get_ioref: err_get_ioref:
bkey_for_each_ptr(ptrs, ptr2) { for (i = 0; i < nr_buckets; i++)
if (ptr2 == ptr) percpu_ref_put(&bch_dev_bkey_exists(c, buckets[i].b.inode)->io_ref);
break;
percpu_ref_put(&bch_dev_bkey_exists(c, ptr2->dev)->io_ref);
}
/* Fall back to COW path: */ /* Fall back to COW path: */
goto out; goto out;
...@@ -1645,9 +1642,8 @@ static void bch2_nocow_write(struct bch_write_op *op) ...@@ -1645,9 +1642,8 @@ static void bch2_nocow_write(struct bch_write_op *op)
bch2_bucket_nocow_unlock(&c->nocow_locks, bch2_bucket_nocow_unlock(&c->nocow_locks,
buckets[i].b, buckets[i].b,
BUCKET_NOCOW_LOCK_UPDATE); BUCKET_NOCOW_LOCK_UPDATE);
for (i = 0; i < nr_buckets; i++)
bkey_for_each_ptr(ptrs, ptr2) percpu_ref_put(&bch_dev_bkey_exists(c, buckets[i].b.inode)->io_ref);
percpu_ref_put(&bch_dev_bkey_exists(c, ptr2->dev)->io_ref);
/* We can retry this: */ /* We can retry this: */
ret = BCH_ERR_transaction_restart; ret = BCH_ERR_transaction_restart;
......
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