From 7455abd4f2f037796127a8f92f2c5dd4dcc6770e Mon Sep 17 00:00:00 2001 From: Kent Overstreet Date: Mon, 2 Dec 2013 21:42:05 -0800 Subject: dio: use submit_io() for block zeroing --- fs/direct-io.c | 64 ++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 20 deletions(-) diff --git a/fs/direct-io.c b/fs/direct-io.c index fb24ae4057b7..1c7b78e85241 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -309,6 +309,22 @@ static int get_blocks(struct dio *dio, loff_t offset, size_t size, return ret; } +static void __dio_bio_submit(struct dio *dio, struct bio *bio, + loff_t offset, dio_submit_t *submit_io) +{ + /* + * Read accounting is performed in submit_bio() + */ + if (dio->rw & WRITE) + task_io_account_write(bio->bi_iter.bi_size); + + if (submit_io) + submit_io(dio->rw, bio, dio->inode, + offset >> dio->i_blkbits); + else + submit_bio(dio->rw, bio); +} + /* * For reads we speculatively dirty the pages before starting IO. During IO * completion, any of these pages which happen to have been written back will be @@ -335,24 +351,15 @@ static int dio_bio_submit(struct dio *dio, struct bio *bio, dio->result += map->size; - /* - * Read accounting is performed in submit_bio() - */ - if (dio->rw & WRITE) - task_io_account_write(split->bi_iter.bi_size); - - if (submit_io) - submit_io(dio->rw, split, dio->inode, - offset >> dio->i_blkbits); - else - submit_bio(dio->rw, split); + __dio_bio_submit(dio, bio, offset, submit_io); return split == bio; } static void dio_write_zeroes(struct dio *dio, struct bio *parent, struct block_device *bdev, - sector_t sector, size_t size) + sector_t sector, size_t size, + loff_t offset, dio_submit_t *submit_io) { unsigned pages = DIV_ROUND_UP(size, PAGE_SIZE); struct bio *bio = bio_alloc(GFP_KERNEL, pages); @@ -368,26 +375,35 @@ static void dio_write_zeroes(struct dio *dio, struct bio *parent, bio->bi_iter.bi_size = size; bio_chain(bio, parent); - submit_bio(WRITE, bio); + __dio_bio_submit(dio, bio, offset, submit_io); } -static void dio_zero_partial_block(struct dio *dio, struct bio *bio, - struct dio_mapping *map, loff_t offset) +static void dio_zero_partial_block_front(struct dio *dio, struct bio *bio, + struct dio_mapping *map, loff_t offset, + dio_submit_t *submit_io) { unsigned blksize = 1 << dio->i_blkbits; unsigned blkmask = blksize - 1; unsigned front = offset & blkmask; - unsigned back = (offset + map->size) & blkmask; if (front) dio_write_zeroes(dio, bio, map->bdev, (map->offset - front) >> 9, - front); + front, offset, submit_io); +} + +static void dio_zero_partial_block_back(struct dio *dio, struct bio *bio, + struct dio_mapping *map, loff_t offset, + dio_submit_t *submit_io) +{ + unsigned blksize = 1 << dio->i_blkbits; + unsigned blkmask = blksize - 1; + unsigned back = (offset + map->size) & blkmask; if (back) dio_write_zeroes(dio, bio, map->bdev, (map->offset + map->size) >> 9, - blksize - back); + blksize - back, offset, submit_io); } static int dio_read_zeroes(struct dio *dio, struct bio *bio, @@ -422,6 +438,7 @@ static int dio_send_bio(struct dio *dio, struct bio *bio, loff_t offset, { struct dio_mapping map; int ret = 0, rw = dio->rw & WRITE; + bool done; if (rw == READ) bio_set_pages_dirty(bio); @@ -458,10 +475,17 @@ static int dio_send_bio(struct dio *dio, struct bio *bio, loff_t offset, goto out; } - dio_zero_partial_block(dio, bio, &map, offset); + dio_zero_partial_block_front(dio, bio, &map, + offset, submit_io); - if (dio_bio_submit(dio, bio, &map, offset, submit_io)) + done = dio_bio_submit(dio, bio, &map, offset, submit_io); + + dio_zero_partial_block_back(dio, bio, &map, + offset, submit_io); + + if (done) goto out; + break; case MAP_UNMAPPED|WRITE: /* AKPM: eargh, -ENOTBLK is a hack */ -- cgit v1.2.3