diff options
| author | Kent Overstreet <kent.overstreet@gmail.com> | 2019-11-01 21:16:51 -0400 |
|---|---|---|
| committer | Kent Overstreet <kent.overstreet@linux.dev> | 2023-10-22 17:08:31 -0400 |
| commit | f8f30863382c0d905196ea7606c14524d1f21fd0 (patch) | |
| tree | ec911c3eb1a12c6c309661214250cb03e6e4db4e /fs/bcachefs/fs-io.c | |
| parent | f7f63211a4e7ecc4c56e3bc1062a4f9711dfd0aa (diff) | |
| download | linux-f8f30863382c0d905196ea7606c14524d1f21fd0.tar.gz linux-f8f30863382c0d905196ea7606c14524d1f21fd0.tar.bz2 linux-f8f30863382c0d905196ea7606c14524d1f21fd0.zip | |
bcachefs: Avoid atomics in write fast path
This adds some horrible hacks, but the atomic ops for closures were
getting to be a pretty expensive part of the write path. We don't want
to rip out closures entirely from the write path, because they're used
for e.g. waiting on the allocator, or waiting on the journal flush, and
that stuff would get really ugly without closures.
Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Diffstat (limited to 'fs/bcachefs/fs-io.c')
| -rw-r--r-- | fs/bcachefs/fs-io.c | 38 |
1 files changed, 18 insertions, 20 deletions
diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c index 93f6cdbbf7c7..436676f4fa2a 100644 --- a/fs/bcachefs/fs-io.c +++ b/fs/bcachefs/fs-io.c @@ -54,7 +54,7 @@ struct bch_writepage_io { }; struct dio_write { - struct closure cl; + struct completion done; struct kiocb *req; struct mm_struct *mm; unsigned loop:1, @@ -1755,8 +1755,6 @@ static noinline int bch2_dio_write_copy_iov(struct dio_write *dio) return 0; } -static void bch2_dio_write_loop_async(struct closure *); - static long bch2_dio_write_loop(struct dio_write *dio) { bool kthread = (current->flags & PF_KTHREAD) != 0; @@ -1830,23 +1828,20 @@ static long bch2_dio_write_loop(struct dio_write *dio) task_io_account_write(bio->bi_iter.bi_size); - closure_call(&dio->op.cl, bch2_write, NULL, &dio->cl); - if (!dio->sync && !dio->loop && dio->iter.count) { if (bch2_dio_write_copy_iov(dio)) { - dio->op.error = -ENOMEM; - goto err_wait_io; + dio->sync = true; + goto do_io; } } -err_wait_io: +do_io: dio->loop = true; + closure_call(&dio->op.cl, bch2_write, NULL, NULL); - if (!dio->sync) { - continue_at(&dio->cl, bch2_dio_write_loop_async, NULL); + if (dio->sync) + wait_for_completion(&dio->done); + else return -EIOCBQUEUED; - } - - closure_sync(&dio->cl); loop: i_sectors_acct(c, inode, &dio->quota_res, dio->op.i_sectors_delta); @@ -1863,7 +1858,9 @@ loop: put_page(bv->bv_page); if (!dio->iter.count || dio->op.error) break; + bio_reset(bio, NULL, REQ_OP_WRITE); + reinit_completion(&dio->done); } ret = dio->op.error ?: ((long) dio->op.written << 9); @@ -1875,8 +1872,6 @@ err: if (dio->free_iov) kfree(dio->iter.__iov); - closure_debug_destroy(&dio->cl); - sync = dio->sync; bio_put(bio); @@ -1890,11 +1885,14 @@ err: return ret; } -static void bch2_dio_write_loop_async(struct closure *cl) +static void bch2_dio_write_loop_async(struct bch_write_op *op) { - struct dio_write *dio = container_of(cl, struct dio_write, cl); + struct dio_write *dio = container_of(op, struct dio_write, op); - bch2_dio_write_loop(dio); + if (dio->sync) + complete(&dio->done); + else + bch2_dio_write_loop(dio); } static noinline @@ -1922,7 +1920,7 @@ ssize_t bch2_direct_write(struct kiocb *req, struct iov_iter *iter) GFP_KERNEL, &c->dio_write_bioset); dio = container_of(bio, struct dio_write, op.wbio.bio); - closure_init(&dio->cl, NULL); + init_completion(&dio->done); dio->req = req; dio->mm = current->mm; dio->loop = false; @@ -1933,6 +1931,7 @@ ssize_t bch2_direct_write(struct kiocb *req, struct iov_iter *iter) dio->iter = *iter; bch2_write_op_init(&dio->op, c, opts); + dio->op.end_io = bch2_dio_write_loop_async; dio->op.target = opts.foreground_target; op_journal_seq_set(&dio->op, &inode->ei_journal_seq); dio->op.write_point = writepoint_hashed((unsigned long) current); @@ -1962,7 +1961,6 @@ ssize_t bch2_direct_write(struct kiocb *req, struct iov_iter *iter) err: bch2_disk_reservation_put(c, &dio->op.res); bch2_quota_reservation_put(c, inode, &dio->quota_res); - closure_debug_destroy(&dio->cl); bio_put(bio); return ret; } |
