diff options
author | Kent Overstreet <kent.overstreet@gmail.com> | 2021-05-18 23:53:43 -0400 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@gmail.com> | 2021-05-19 15:33:48 -0400 |
commit | 27f102a94aaedcc338773141fb7a17c301804376 (patch) | |
tree | dcb8391fafca938eec0d4aecba88909b710394a9 | |
parent | 13419c3d1ed72e0e661a36a322350f4d22818eca (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.c | 7 | ||||
-rw-r--r-- | fs/bcachefs/io.c | 9 |
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, |