summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kmo@daterainc.com>2013-12-02 21:42:05 -0800
committerKent Overstreet <kmo@daterainc.com>2014-06-17 18:25:55 -0700
commit7455abd4f2f037796127a8f92f2c5dd4dcc6770e (patch)
treec2c929d96396634f7c68d317b98608c47200d1de
parentcb80bbe80c45a713a6c884e6568615329e233e4f (diff)
dio: use submit_io() for block zeroingdio
-rw-r--r--fs/direct-io.c64
1 files 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 */