Skip to content

Commit 531724a

Browse files
Christoph Hellwigaxboe
authored andcommitted
block: avoid extra bio reference for async O_DIRECT
The bio referencing has a trick that doesn't do any actual atomic inc/dec on the reference count until we have to elevator to > 1. For the async IO O_DIRECT case, we can't use the simple DIO variants, so we use __blkdev_direct_IO(). It always grabs an extra reference to the bio after allocation, which means we then enter the slower path of actually having to do atomic_inc/dec on the count. We don't need to do that for the async case, unless we end up going multi-bio, in which case we're already doing huge amounts of IO. For the smaller IO case (< BIO_MAX_PAGES), we can do without the extra ref. Based on an earlier patch (and commit log) from Jens Axboe. Signed-off-by: Christoph Hellwig <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 27fae42 commit 531724a

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

fs/block_dev.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,8 @@ static void blkdev_bio_end_io(struct bio *bio)
302302
}
303303

304304
dio->iocb->ki_complete(iocb, ret, 0);
305-
bio_put(&dio->bio);
305+
if (dio->multi_bio)
306+
bio_put(&dio->bio);
306307
} else {
307308
struct task_struct *waiter = dio->waiter;
308309

@@ -343,14 +344,15 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
343344
return -EINVAL;
344345

345346
bio = bio_alloc_bioset(GFP_KERNEL, nr_pages, &blkdev_dio_pool);
346-
bio_get(bio); /* extra ref for the completion handler */
347347

348348
dio = container_of(bio, struct blkdev_dio, bio);
349349
dio->is_sync = is_sync = is_sync_kiocb(iocb);
350-
if (dio->is_sync)
350+
if (dio->is_sync) {
351351
dio->waiter = current;
352-
else
352+
bio_get(bio);
353+
} else {
353354
dio->iocb = iocb;
355+
}
354356

355357
dio->size = 0;
356358
dio->multi_bio = false;
@@ -400,6 +402,13 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
400402
}
401403

402404
if (!dio->multi_bio) {
405+
/*
406+
* AIO needs an extra reference to ensure the dio
407+
* structure which is embedded into the first bio
408+
* stays around.
409+
*/
410+
if (!is_sync)
411+
bio_get(bio);
403412
dio->multi_bio = true;
404413
atomic_set(&dio->ref, 2);
405414
} else {

0 commit comments

Comments
 (0)