summaryrefslogtreecommitdiff
path: root/libbcachefs/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'libbcachefs/io.c')
-rw-r--r--libbcachefs/io.c128
1 files changed, 62 insertions, 66 deletions
diff --git a/libbcachefs/io.c b/libbcachefs/io.c
index 0c41e411..3369a2ff 100644
--- a/libbcachefs/io.c
+++ b/libbcachefs/io.c
@@ -20,6 +20,7 @@
#include "journal.h"
#include "keylist.h"
#include "move.h"
+#include "super.h"
#include "super-io.h"
#include <linux/blkdev.h>
@@ -139,7 +140,6 @@ void bch2_submit_wbio_replicas(struct bch_write_bio *wbio, struct bch_fs *c,
const struct bch_extent_ptr *ptr;
struct bch_write_bio *n;
struct bch_dev *ca;
- unsigned ptr_idx = 0;
BUG_ON(c->opts.nochanges);
@@ -147,7 +147,7 @@ void bch2_submit_wbio_replicas(struct bch_write_bio *wbio, struct bch_fs *c,
BUG_ON(ptr->dev >= BCH_SB_MEMBERS_MAX ||
!c->devs[ptr->dev]);
- ca = c->devs[ptr->dev];
+ ca = bch_dev_bkey_exists(c, ptr->dev);
if (ptr + 1 < &extent_entry_last(e)->ptr) {
n = to_wbio(bio_clone_fast(&wbio->bio, GFP_NOIO,
@@ -168,7 +168,6 @@ void bch2_submit_wbio_replicas(struct bch_write_bio *wbio, struct bch_fs *c,
n->c = c;
n->ca = ca;
- n->ptr_idx = ptr_idx++;
n->submit_time_us = local_clock_us();
n->bio.bi_iter.bi_sector = ptr->offset;
@@ -184,7 +183,7 @@ void bch2_submit_wbio_replicas(struct bch_write_bio *wbio, struct bch_fs *c,
submit_bio(&n->bio);
} else {
n->have_io_ref = false;
- bcache_io_error(c, &n->bio, "device has been removed");
+ n->bio.bi_status = BLK_STS_REMOVED;
bio_endio(&n->bio);
}
}
@@ -201,9 +200,12 @@ static void bch2_write_done(struct closure *cl)
if (!op->error && (op->flags & BCH_WRITE_FLUSH))
op->error = bch2_journal_error(&op->c->journal);
- bch2_disk_reservation_put(op->c, &op->res);
+ if (!(op->flags & BCH_WRITE_NOPUT_RESERVATION))
+ bch2_disk_reservation_put(op->c, &op->res);
percpu_ref_put(&op->c->writes);
bch2_keylist_free(&op->insert_keys, op->inline_keys);
+ op->flags &= ~(BCH_WRITE_DONE|BCH_WRITE_LOOPED);
+
closure_return(cl);
}
@@ -244,9 +246,37 @@ static void bch2_write_index(struct closure *cl)
struct bch_write_op *op = container_of(cl, struct bch_write_op, cl);
struct bch_fs *c = op->c;
struct keylist *keys = &op->insert_keys;
+ struct bkey_s_extent e;
+ struct bch_extent_ptr *ptr;
+ struct bkey_i *src, *dst = keys->keys, *n;
+ int ret;
op->flags |= BCH_WRITE_LOOPED;
+ for (src = keys->keys; src != keys->top; src = n) {
+ n = bkey_next(src);
+ bkey_copy(dst, src);
+
+ e = bkey_i_to_s_extent(dst);
+ extent_for_each_ptr_backwards(e, ptr)
+ if (test_bit(ptr->dev, op->failed.d))
+ bch2_extent_drop_ptr(e, ptr);
+
+ ret = bch2_extent_nr_ptrs(e.c)
+ ? bch2_check_mark_super(c, e.c, BCH_DATA_USER)
+ : -EIO;
+ if (ret) {
+ keys->top = keys->keys;
+ op->error = ret;
+ op->flags |= BCH_WRITE_DONE;
+ goto err;
+ }
+
+ dst = bkey_next(dst);
+ }
+
+ keys->top = dst;
+
if (!bch2_keylist_empty(keys)) {
u64 sectors_start = keylist_sectors(keys);
int ret = op->index_update_fn(op);
@@ -260,7 +290,7 @@ static void bch2_write_index(struct closure *cl)
op->error = ret;
}
}
-
+err:
bch2_open_bucket_put_refs(c, &op->open_buckets_nr, op->open_buckets);
if (!(op->flags & BCH_WRITE_DONE))
@@ -276,43 +306,6 @@ static void bch2_write_index(struct closure *cl)
}
}
-static void bch2_write_io_error(struct closure *cl)
-{
- struct bch_write_op *op = container_of(cl, struct bch_write_op, cl);
- struct keylist *keys = &op->insert_keys;
- struct bch_fs *c = op->c;
- struct bch_extent_ptr *ptr;
- struct bkey_i *k;
- int ret;
-
- for_each_keylist_key(keys, k) {
- struct bkey_i *n = bkey_next(k);
- struct bkey_s_extent e = bkey_i_to_s_extent(k);
-
- extent_for_each_ptr_backwards(e, ptr)
- if (test_bit(ptr->dev, op->failed.d))
- bch2_extent_drop_ptr(e, ptr);
-
- memmove(bkey_next(k), n, (void *) keys->top - (void *) n);
- keys->top_p -= (u64 *) n - (u64 *) bkey_next(k);
-
- ret = bch2_extent_nr_ptrs(e.c)
- ? bch2_check_mark_super(c, e.c, BCH_DATA_USER)
- : -EIO;
- if (ret) {
- keys->top = keys->keys;
- op->error = ret;
- op->flags |= BCH_WRITE_DONE;
- break;
- }
- }
-
- memset(&op->failed, 0, sizeof(op->failed));
-
- bch2_write_index(cl);
- return;
-}
-
static void bch2_write_endio(struct bio *bio)
{
struct closure *cl = bio->bi_private;
@@ -324,10 +317,8 @@ static void bch2_write_endio(struct bio *bio)
bch2_latency_acct(ca, wbio->submit_time_us, WRITE);
- if (bch2_dev_io_err_on(bio->bi_error, ca, "data write")) {
+ if (bch2_dev_io_err_on(bio->bi_status, ca, "data write"))
set_bit(ca->dev_idx, op->failed.d);
- set_closure_fn(cl, bch2_write_io_error, index_update_wq(op));
- }
if (wbio->have_io_ref)
percpu_ref_put(&ca->io_ref);
@@ -706,11 +697,6 @@ do_write:
key_to_write = (void *) (op->insert_keys.keys_p + key_to_write_offset);
- ret = bch2_check_mark_super(c, bkey_i_to_s_c_extent(key_to_write),
- BCH_DATA_USER);
- if (ret)
- goto err;
-
dst->bi_end_io = bch2_write_endio;
dst->bi_private = &op->cl;
bio_set_op_attrs(dst, REQ_OP_WRITE, 0);
@@ -870,7 +856,8 @@ void bch2_write(struct closure *cl)
!percpu_ref_tryget(&c->writes)) {
__bcache_io_error(c, "read only");
op->error = -EROFS;
- bch2_disk_reservation_put(c, &op->res);
+ if (!(op->flags & BCH_WRITE_NOPUT_RESERVATION))
+ bch2_disk_reservation_put(c, &op->res);
closure_return(cl);
}
@@ -916,7 +903,10 @@ static void promote_start(struct promote_op *op, struct bch_read_bio *rbio)
swap(bio->bi_vcnt, rbio->bio.bi_vcnt);
rbio->promote = NULL;
- __bch2_write_op_init(&op->write.op, c);
+ bch2_write_op_init(&op->write.op, c);
+ op->write.op.csum_type = bch2_data_checksum_type(c, rbio->opts.data_checksum);
+ op->write.op.compression_type =
+ bch2_compression_opt_to_type(rbio->opts.compression);
op->write.move_dev = -1;
op->write.op.devs = c->fastest_devs;
@@ -1060,7 +1050,7 @@ static void bch2_rbio_retry(struct work_struct *work)
if (rbio->split)
rbio = bch2_rbio_free(rbio);
else
- rbio->bio.bi_error = 0;
+ rbio->bio.bi_status = 0;
if (!(flags & BCH_READ_NODECODE))
flags |= BCH_READ_MUST_CLONE;
@@ -1073,7 +1063,8 @@ static void bch2_rbio_retry(struct work_struct *work)
__bch2_read(c, rbio, iter, inode, &avoid, flags);
}
-static void bch2_rbio_error(struct bch_read_bio *rbio, int retry, int error)
+static void bch2_rbio_error(struct bch_read_bio *rbio, int retry,
+ blk_status_t error)
{
rbio->retry = retry;
@@ -1081,7 +1072,7 @@ static void bch2_rbio_error(struct bch_read_bio *rbio, int retry, int error)
return;
if (retry == READ_ERR) {
- bch2_rbio_parent(rbio)->bio.bi_error = error;
+ bch2_rbio_parent(rbio)->bio.bi_status = error;
bch2_rbio_done(rbio);
} else {
bch2_rbio_punt(rbio, bch2_rbio_retry,
@@ -1236,7 +1227,7 @@ csum_err:
*/
if (!rbio->bounce && (rbio->flags & BCH_READ_USER_MAPPED)) {
rbio->flags |= BCH_READ_MUST_BOUNCE;
- bch2_rbio_error(rbio, READ_RETRY, -EIO);
+ bch2_rbio_error(rbio, READ_RETRY, BLK_STS_IOERR);
return;
}
@@ -1245,13 +1236,13 @@ csum_err:
rbio->pos.inode, (u64) rbio->bvec_iter.bi_sector,
rbio->pick.crc.csum.hi, rbio->pick.crc.csum.lo,
csum.hi, csum.lo, crc.csum_type);
- bch2_rbio_error(rbio, READ_RETRY_AVOID, -EIO);
+ bch2_rbio_error(rbio, READ_RETRY_AVOID, BLK_STS_IOERR);
return;
decompression_err:
__bcache_io_error(c, "decompression error, inode %llu offset %llu",
rbio->pos.inode,
(u64) rbio->bvec_iter.bi_sector);
- bch2_rbio_error(rbio, READ_ERR, -EIO);
+ bch2_rbio_error(rbio, READ_ERR, BLK_STS_IOERR);
return;
}
@@ -1270,8 +1261,8 @@ static void bch2_read_endio(struct bio *bio)
if (!rbio->split)
rbio->bio.bi_end_io = rbio->end_io;
- if (bch2_dev_io_err_on(bio->bi_error, rbio->pick.ca, "data read")) {
- bch2_rbio_error(rbio, READ_RETRY_AVOID, bio->bi_error);
+ if (bch2_dev_io_err_on(bio->bi_status, rbio->pick.ca, "data read")) {
+ bch2_rbio_error(rbio, READ_RETRY_AVOID, bio->bi_status);
return;
}
@@ -1281,9 +1272,9 @@ static void bch2_read_endio(struct bio *bio)
atomic_long_inc(&c->read_realloc_races);
if (rbio->flags & BCH_READ_RETRY_IF_STALE)
- bch2_rbio_error(rbio, READ_RETRY, -EINTR);
+ bch2_rbio_error(rbio, READ_RETRY, BLK_STS_AGAIN);
else
- bch2_rbio_error(rbio, READ_ERR, -EINTR);
+ bch2_rbio_error(rbio, READ_ERR, BLK_STS_AGAIN);
return;
}
@@ -1360,7 +1351,8 @@ int __bch2_read_extent(struct bch_fs *c, struct bch_read_bio *orig,
rbio = rbio_init(bio_alloc_bioset(GFP_NOIO,
DIV_ROUND_UP(sectors, PAGE_SECTORS),
- &c->bio_read_split));
+ &c->bio_read_split),
+ orig->opts);
bch2_bio_alloc_pages_pool(c, &rbio->bio, sectors << 9);
split = true;
@@ -1374,7 +1366,8 @@ int __bch2_read_extent(struct bch_fs *c, struct bch_read_bio *orig,
* lose the error)
*/
rbio = rbio_init(bio_clone_fast(&orig->bio, GFP_NOIO,
- &c->bio_read_split));
+ &c->bio_read_split),
+ orig->opts);
rbio->bio.bi_iter = iter;
split = true;
} else {
@@ -1428,6 +1421,8 @@ noclone:
bch2_read_endio(&rbio->bio);
ret = rbio->retry;
+ if (rbio->split)
+ rbio = bch2_rbio_free(rbio);
if (!ret)
bch2_rbio_done(rbio);
}
@@ -1503,7 +1498,7 @@ err:
* possibly bigger than the memory that was
* originally allocated)
*/
- rbio->bio.bi_error = -EINTR;
+ rbio->bio.bi_status = BLK_STS_AGAIN;
bio_endio(&rbio->bio);
return;
}
@@ -1561,6 +1556,7 @@ retry:
case READ_RETRY:
goto retry;
case READ_ERR:
+ rbio->bio.bi_status = BLK_STS_IOERR;
bio_endio(&rbio->bio);
return;
};