bcachefs: ec: zero_out_rest_of_ec_bucket()
authorKent Overstreet <kent.overstreet@linux.dev>
Sun, 26 Feb 2023 22:12:36 +0000 (17:12 -0500)
committerKent Overstreet <kent.overstreet@linux.dev>
Sun, 22 Oct 2023 21:09:55 +0000 (17:09 -0400)
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>
fs/bcachefs/ec.c

index 473f1c0..88f3199 100644 (file)
@@ -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);
 }