Commit c21c3ad0 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] convert direct-io to use bio_add_page()

From Badari Pavlati.

Use bio_add_page() in direct-io.c.
parent 7b88e5e0
...@@ -23,12 +23,6 @@ ...@@ -23,12 +23,6 @@
#include <linux/rwsem.h> #include <linux/rwsem.h>
#include <asm/atomic.h> #include <asm/atomic.h>
/*
* The largest-sized BIO which this code will assemble, in bytes. Set this
* to PAGE_SIZE if your drivers are broken.
*/
#define DIO_BIO_MAX_SIZE (16*1024)
/* /*
* How many user pages to map in one call to get_user_pages(). This determines * How many user pages to map in one call to get_user_pages(). This determines
* the size of a structure on the stack. * the size of a structure on the stack.
...@@ -38,7 +32,6 @@ ...@@ -38,7 +32,6 @@
struct dio { struct dio {
/* BIO submission state */ /* BIO submission state */
struct bio *bio; /* bio under assembly */ struct bio *bio; /* bio under assembly */
struct bio_vec *bvec; /* current bvec in that bio */
struct inode *inode; struct inode *inode;
int rw; int rw;
unsigned blkbits; /* doesn't change */ unsigned blkbits; /* doesn't change */
...@@ -180,15 +173,10 @@ dio_bio_alloc(struct dio *dio, struct block_device *bdev, ...@@ -180,15 +173,10 @@ dio_bio_alloc(struct dio *dio, struct block_device *bdev,
return -ENOMEM; return -ENOMEM;
bio->bi_bdev = bdev; bio->bi_bdev = bdev;
bio->bi_vcnt = nr_vecs;
bio->bi_idx = 0;
bio->bi_size = 0;
bio->bi_sector = first_sector; bio->bi_sector = first_sector;
bio->bi_io_vec[0].bv_page = NULL;
bio->bi_end_io = dio_bio_end_io; bio->bi_end_io = dio_bio_end_io;
dio->bio = bio; dio->bio = bio;
dio->bvec = NULL; /* debug */
return 0; return 0;
} }
...@@ -196,14 +184,11 @@ static void dio_bio_submit(struct dio *dio) ...@@ -196,14 +184,11 @@ static void dio_bio_submit(struct dio *dio)
{ {
struct bio *bio = dio->bio; struct bio *bio = dio->bio;
bio->bi_vcnt = bio->bi_idx;
bio->bi_idx = 0;
bio->bi_private = dio; bio->bi_private = dio;
atomic_inc(&dio->bio_count); atomic_inc(&dio->bio_count);
submit_bio(dio->rw, bio); submit_bio(dio->rw, bio);
dio->bio = NULL; dio->bio = NULL;
dio->bvec = NULL;
dio->boundary = 0; dio->boundary = 0;
} }
...@@ -394,8 +379,7 @@ static void dio_prep_bio(struct dio *dio) ...@@ -394,8 +379,7 @@ static void dio_prep_bio(struct dio *dio)
if (dio->bio == NULL) if (dio->bio == NULL)
return; return;
if (dio->bio->bi_idx == dio->bio->bi_vcnt || if (dio->boundary ||
dio->boundary ||
dio->last_block_in_bio != dio->next_block_in_bio - 1) dio->last_block_in_bio != dio->next_block_in_bio - 1)
dio_bio_submit(dio); dio_bio_submit(dio);
} }
...@@ -406,19 +390,44 @@ static void dio_prep_bio(struct dio *dio) ...@@ -406,19 +390,44 @@ static void dio_prep_bio(struct dio *dio)
static int dio_new_bio(struct dio *dio) static int dio_new_bio(struct dio *dio)
{ {
sector_t sector; sector_t sector;
int ret; int ret, nr_pages;
ret = dio_bio_reap(dio); ret = dio_bio_reap(dio);
if (ret) if (ret)
goto out; goto out;
sector = dio->next_block_in_bio << (dio->blkbits - 9); sector = dio->next_block_in_bio << (dio->blkbits - 9);
ret = dio_bio_alloc(dio, dio->map_bh.b_bdev, sector, nr_pages = min(dio->total_pages, BIO_MAX_PAGES);
DIO_BIO_MAX_SIZE / PAGE_SIZE); ret = dio_bio_alloc(dio, dio->map_bh.b_bdev, sector, nr_pages);
dio->boundary = 0; dio->boundary = 0;
out: out:
return ret; return ret;
} }
static int
dio_bio_add_page(struct dio *dio, struct page *page,
unsigned int bv_len, unsigned int bv_offset)
{
int ret = 0;
if (bv_len == 0)
goto out;
page_cache_get(page);
if (bio_add_page(dio->bio, page, bv_len, bv_offset)) {
dio_bio_submit(dio);
ret = dio_new_bio(dio);
if (ret == 0) {
ret = bio_add_page(dio->bio, page, bv_len, bv_offset);
BUG_ON(ret != 0);
}
}
page_cache_release(page);
out:
return ret;
}
/* /*
* Walk the user pages, and the file, mapping blocks to disk and emitting BIOs. * Walk the user pages, and the file, mapping blocks to disk and emitting BIOs.
* *
...@@ -439,13 +448,15 @@ int do_direct_IO(struct dio *dio) ...@@ -439,13 +448,15 @@ int do_direct_IO(struct dio *dio)
const unsigned blocks_per_page = PAGE_SIZE >> blkbits; const unsigned blocks_per_page = PAGE_SIZE >> blkbits;
struct page *page; struct page *page;
unsigned block_in_page; unsigned block_in_page;
int ret; int ret = 0;
/* The I/O can start at any block offset within the first page */ /* The I/O can start at any block offset within the first page */
block_in_page = dio->first_block_in_page; block_in_page = dio->first_block_in_page;
while (dio->block_in_file < dio->final_block_in_request) { while (dio->block_in_file < dio->final_block_in_request) {
int new_page; /* Need to insert this page into the BIO? */ int new_page; /* Need to insert this page into the BIO? */
unsigned int bv_offset;
unsigned int bv_len;
page = dio_get_page(dio); page = dio_get_page(dio);
if (IS_ERR(page)) { if (IS_ERR(page)) {
...@@ -454,15 +465,16 @@ int do_direct_IO(struct dio *dio) ...@@ -454,15 +465,16 @@ int do_direct_IO(struct dio *dio)
} }
new_page = 1; new_page = 1;
bv_offset = 0;
bv_len = 0;
while (block_in_page < blocks_per_page) { while (block_in_page < blocks_per_page) {
struct bio *bio;
unsigned this_chunk_bytes; /* # of bytes mapped */ unsigned this_chunk_bytes; /* # of bytes mapped */
unsigned this_chunk_blocks; /* # of blocks */ unsigned this_chunk_blocks; /* # of blocks */
unsigned u; unsigned u;
ret = get_more_blocks(dio); ret = get_more_blocks(dio);
if (ret) if (ret)
goto fail_release; goto out;
/* Handle holes */ /* Handle holes */
if (!buffer_mapped(&dio->map_bh)) { if (!buffer_mapped(&dio->map_bh)) {
...@@ -481,24 +493,19 @@ int do_direct_IO(struct dio *dio) ...@@ -481,24 +493,19 @@ int do_direct_IO(struct dio *dio)
if (dio->bio == NULL) { if (dio->bio == NULL) {
ret = dio_new_bio(dio); ret = dio_new_bio(dio);
if (ret) if (ret)
goto fail_release; goto out;
new_page = 1; new_page = 1;
} }
bio = dio->bio;
if (new_page) { if (new_page) {
dio->bvec = &bio->bi_io_vec[bio->bi_idx]; bv_len = 0;
page_cache_get(page); bv_offset = block_in_page << blkbits;
dio->bvec->bv_page = page;
dio->bvec->bv_len = 0;
dio->bvec->bv_offset = block_in_page << blkbits;
bio->bi_idx++;
new_page = 0; new_page = 0;
} }
/* Work out how much disk we can add to this page */ /* Work out how much disk we can add to this page */
this_chunk_blocks = dio->blocks_available; this_chunk_blocks = dio->blocks_available;
u = (PAGE_SIZE - (dio->bvec->bv_offset + dio->bvec->bv_len)) >> blkbits; u = (PAGE_SIZE - (bv_len + bv_offset)) >> blkbits;
if (this_chunk_blocks > u) if (this_chunk_blocks > u)
this_chunk_blocks = u; this_chunk_blocks = u;
u = dio->final_block_in_request - dio->block_in_file; u = dio->final_block_in_request - dio->block_in_file;
...@@ -507,8 +514,7 @@ int do_direct_IO(struct dio *dio) ...@@ -507,8 +514,7 @@ int do_direct_IO(struct dio *dio)
this_chunk_bytes = this_chunk_blocks << blkbits; this_chunk_bytes = this_chunk_blocks << blkbits;
BUG_ON(this_chunk_bytes == 0); BUG_ON(this_chunk_bytes == 0);
dio->bvec->bv_len += this_chunk_bytes; bv_len += this_chunk_bytes;
bio->bi_size += this_chunk_bytes;
dio->next_block_in_bio += this_chunk_blocks; dio->next_block_in_bio += this_chunk_blocks;
dio->last_block_in_bio = dio->next_block_in_bio - 1; dio->last_block_in_bio = dio->next_block_in_bio - 1;
dio->boundary = buffer_boundary(&dio->map_bh); dio->boundary = buffer_boundary(&dio->map_bh);
...@@ -521,13 +527,11 @@ int do_direct_IO(struct dio *dio) ...@@ -521,13 +527,11 @@ int do_direct_IO(struct dio *dio)
if (dio->block_in_file == dio->final_block_in_request) if (dio->block_in_file == dio->final_block_in_request)
break; break;
} }
ret = dio_bio_add_page(dio, page, bv_len, bv_offset);
if (ret)
goto out;
block_in_page = 0; block_in_page = 0;
page_cache_release(page);
} }
ret = 0;
goto out;
fail_release:
page_cache_release(page);
out: out:
return ret; return ret;
} }
...@@ -543,7 +547,6 @@ direct_io_worker(int rw, struct inode *inode, const struct iovec *iov, ...@@ -543,7 +547,6 @@ direct_io_worker(int rw, struct inode *inode, const struct iovec *iov,
size_t bytes, tot_bytes = 0; size_t bytes, tot_bytes = 0;
dio.bio = NULL; dio.bio = NULL;
dio.bvec = NULL;
dio.inode = inode; dio.inode = inode;
dio.rw = rw; dio.rw = rw;
dio.blkbits = blkbits; dio.blkbits = blkbits;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment