summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-02-26 17:12:36 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-10-22 17:09:55 -0400
commit94bc95c468344d6a329dd87ab4461532584a7b71 (patch)
tree3106b439bbbbf9658513c909580c66e30aeb7f94
parent039c45feef4f9a46aa0ee0b5ecfafdfd4c0dde76 (diff)
downloadlwn-94bc95c468344d6a329dd87ab4461532584a7b71.tar.gz
lwn-94bc95c468344d6a329dd87ab4461532584a7b71.zip
bcachefs: ec: zero_out_rest_of_ec_bucket()
Occasionally, we won't write to an entire bucket. This fixes the EC code to handle this case, zeroing out the rest of the bucket as needed. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--fs/bcachefs/ec.c40
1 files changed, 37 insertions, 3 deletions
diff --git a/fs/bcachefs/ec.c b/fs/bcachefs/ec.c
index 473f1c09e106..88f319992c37 100644
--- a/fs/bcachefs/ec.c
+++ b/fs/bcachefs/ec.c
@@ -1003,6 +1003,35 @@ err:
return ret;
}
+static void zero_out_rest_of_ec_bucket(struct bch_fs *c,
+ struct ec_stripe_new *s,
+ unsigned block,
+ struct open_bucket *ob)
+{
+ struct bch_dev *ca = bch_dev_bkey_exists(c, ob->dev);
+ unsigned offset = ca->mi.bucket_size - ob->sectors_free;
+ int ret;
+
+ if (!bch2_dev_get_ioref(ca, WRITE)) {
+ s->err = -EROFS;
+ return;
+ }
+
+ memset(s->new_stripe.data[block] + (offset << 9),
+ 0,
+ ob->sectors_free << 9);
+
+ ret = blkdev_issue_zeroout(ca->disk_sb.bdev,
+ ob->bucket * ca->mi.bucket_size + offset,
+ ob->sectors_free,
+ GFP_KERNEL, 0);
+
+ percpu_ref_put(&ca->io_ref);
+
+ if (ret)
+ s->err = ret;
+}
+
/*
* data buckets of new stripe all written: create the stripe
*/
@@ -1018,6 +1047,14 @@ static void ec_stripe_create(struct ec_stripe_new *s)
closure_sync(&s->iodone);
+ for (i = 0; i < nr_data; i++)
+ if (s->blocks[i]) {
+ ob = c->open_buckets + s->blocks[i];
+
+ if (ob->sectors_free)
+ zero_out_rest_of_ec_bucket(c, s, i, ob);
+ }
+
if (s->err) {
if (!bch2_err_matches(s->err, EROFS))
bch_err(c, "error creating stripe: error writing data buckets");
@@ -1159,9 +1196,6 @@ void bch2_ec_bucket_written(struct bch_fs *c, struct open_bucket *ob)
{
struct ec_stripe_new *s = ob->ec;
- if (ob->sectors_free)
- s->err = -1;
-
ec_stripe_new_put(c, s);
}