summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2021-05-18 23:53:43 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2021-05-19 15:33:48 -0400
commit27f102a94aaedcc338773141fb7a17c301804376 (patch)
treedcb8391fafca938eec0d4aecba88909b710394a9
parent13419c3d1ed72e0e661a36a322350f4d22818eca (diff)
bcachefs: Move io_in_flight ratelimiting to fs-io.c
This fixes a bug where an async O_DIRECT write that required multiple bch2_write calls could deadlock, because bch2_write runs out of the same workqueue used for index updates and would block on the io_in_flight semaphore. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/fs-io.c7
-rw-r--r--fs/bcachefs/io.c9
2 files changed, 7 insertions, 9 deletions
diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c
index d707cabd7536..33c8ac17703d 100644
--- a/fs/bcachefs/fs-io.c
+++ b/fs/bcachefs/fs-io.c
@@ -1018,6 +1018,8 @@ static void bch2_writepage_io_done(struct closure *cl)
struct bio_vec *bvec;
unsigned i;
+ up(&io->op.c->io_in_flight);
+
if (io->op.error) {
set_bit(EI_INODE_ERROR, &io->inode->ei_flags);
@@ -1080,6 +1082,8 @@ static void bch2_writepage_do_io(struct bch_writepage_state *w)
{
struct bch_writepage_io *io = w->io;
+ down(&io->op.c->io_in_flight);
+
w->io = NULL;
closure_call(&io->op.cl, bch2_write, NULL, &io->cl);
continue_at(&io->cl, bch2_writepage_io_done, NULL);
@@ -1819,6 +1823,8 @@ static long bch2_dio_write_loop(struct dio_write *dio)
if (dio->loop)
goto loop;
+ down(&c->io_in_flight);
+
while (1) {
iter_count = dio->iter.count;
@@ -1949,6 +1955,7 @@ loop:
ret = dio->op.error ?: ((long) dio->written << 9);
err:
+ up(&c->io_in_flight);
bch2_pagecache_block_put(&inode->ei_pagecache_lock);
bch2_quota_reservation_put(c, inode, &dio->quota_res);
diff --git a/fs/bcachefs/io.c b/fs/bcachefs/io.c
index 677d354343b7..b2e80722c77e 100644
--- a/fs/bcachefs/io.c
+++ b/fs/bcachefs/io.c
@@ -537,9 +537,6 @@ static void bch2_write_done(struct closure *cl)
bch2_time_stats_update(&c->times[BCH_TIME_data_write], op->start_time);
- if (!(op->flags & BCH_WRITE_FROM_INTERNAL))
- up(&c->io_in_flight);
-
if (op->end_io) {
EBUG_ON(cl->parent);
closure_debug_destroy(cl);
@@ -1323,12 +1320,6 @@ void bch2_write(struct closure *cl)
goto err;
}
- /*
- * Can't ratelimit copygc - we'd deadlock:
- */
- if (!(op->flags & BCH_WRITE_FROM_INTERNAL))
- down(&c->io_in_flight);
-
bch2_increment_clock(c, bio_sectors(bio), WRITE);
data_len = min_t(u64, bio->bi_iter.bi_size,