fs/block_dev.c: remove #if 0'ed code
Commit b2e895dbd8
#if 0'ed this code stating:
<-- snip -->
[PATCH] revert blockdev direct io back to 2.6.19 version
Andrew Vasquez is reporting as-iosched oopses and a 65% throughput
slowdown due to the recent special-casing of direct-io against
blockdevs. We don't know why either of these things are occurring.
The patch minimally reverts us back to the 2.6.19 code for a 2.6.20
release.
<-- snip -->
It has since been dead code, and unless someone wants to revive it now
it's time to remove it.
This patch also makes bio_release_pages() static again and removes the
ki_bio_count member from struct kiocb, reverting changes that had been
done for this dead code.
Signed-off-by: Adrian Bunk <bunk@kernel.org>
Signed-off-by: Jens Axboe <axboe@carl.home.kernel.dk>
This commit is contained in:
parent
4c54ac62dc
commit
86b6c7a7f7
2
fs/bio.c
2
fs/bio.c
|
@ -903,7 +903,7 @@ void bio_set_pages_dirty(struct bio *bio)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bio_release_pages(struct bio *bio)
|
static void bio_release_pages(struct bio *bio)
|
||||||
{
|
{
|
||||||
struct bio_vec *bvec = bio->bi_io_vec;
|
struct bio_vec *bvec = bio->bi_io_vec;
|
||||||
int i;
|
int i;
|
||||||
|
|
197
fs/block_dev.c
197
fs/block_dev.c
|
@ -173,203 +173,6 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
|
||||||
iov, offset, nr_segs, blkdev_get_blocks, NULL);
|
iov, offset, nr_segs, blkdev_get_blocks, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void blk_end_aio(struct bio *bio, int error)
|
|
||||||
{
|
|
||||||
struct kiocb *iocb = bio->bi_private;
|
|
||||||
atomic_t *bio_count = &iocb->ki_bio_count;
|
|
||||||
|
|
||||||
if (bio_data_dir(bio) == READ)
|
|
||||||
bio_check_pages_dirty(bio);
|
|
||||||
else {
|
|
||||||
bio_release_pages(bio);
|
|
||||||
bio_put(bio);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* iocb->ki_nbytes stores error code from LLDD */
|
|
||||||
if (error)
|
|
||||||
iocb->ki_nbytes = -EIO;
|
|
||||||
|
|
||||||
if (atomic_dec_and_test(bio_count)) {
|
|
||||||
if ((long)iocb->ki_nbytes < 0)
|
|
||||||
aio_complete(iocb, iocb->ki_nbytes, 0);
|
|
||||||
else
|
|
||||||
aio_complete(iocb, iocb->ki_left, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define VEC_SIZE 16
|
|
||||||
struct pvec {
|
|
||||||
unsigned short nr;
|
|
||||||
unsigned short idx;
|
|
||||||
struct page *page[VEC_SIZE];
|
|
||||||
};
|
|
||||||
|
|
||||||
#define PAGES_SPANNED(addr, len) \
|
|
||||||
(DIV_ROUND_UP((addr) + (len), PAGE_SIZE) - (addr) / PAGE_SIZE);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* get page pointer for user addr, we internally cache struct page array for
|
|
||||||
* (addr, count) range in pvec to avoid frequent call to get_user_pages. If
|
|
||||||
* internal page list is exhausted, a batch count of up to VEC_SIZE is used
|
|
||||||
* to get next set of page struct.
|
|
||||||
*/
|
|
||||||
static struct page *blk_get_page(unsigned long addr, size_t count, int rw,
|
|
||||||
struct pvec *pvec)
|
|
||||||
{
|
|
||||||
int ret, nr_pages;
|
|
||||||
if (pvec->idx == pvec->nr) {
|
|
||||||
nr_pages = PAGES_SPANNED(addr, count);
|
|
||||||
nr_pages = min(nr_pages, VEC_SIZE);
|
|
||||||
down_read(¤t->mm->mmap_sem);
|
|
||||||
ret = get_user_pages(current, current->mm, addr, nr_pages,
|
|
||||||
rw == READ, 0, pvec->page, NULL);
|
|
||||||
up_read(¤t->mm->mmap_sem);
|
|
||||||
if (ret < 0)
|
|
||||||
return ERR_PTR(ret);
|
|
||||||
pvec->nr = ret;
|
|
||||||
pvec->idx = 0;
|
|
||||||
}
|
|
||||||
return pvec->page[pvec->idx++];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return a page back to pvec array */
|
|
||||||
static void blk_unget_page(struct page *page, struct pvec *pvec)
|
|
||||||
{
|
|
||||||
pvec->page[--pvec->idx] = page;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t
|
|
||||||
blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
|
|
||||||
loff_t pos, unsigned long nr_segs)
|
|
||||||
{
|
|
||||||
struct inode *inode = iocb->ki_filp->f_mapping->host;
|
|
||||||
unsigned blkbits = blksize_bits(bdev_hardsect_size(I_BDEV(inode)));
|
|
||||||
unsigned blocksize_mask = (1 << blkbits) - 1;
|
|
||||||
unsigned long seg = 0; /* iov segment iterator */
|
|
||||||
unsigned long nvec; /* number of bio vec needed */
|
|
||||||
unsigned long cur_off; /* offset into current page */
|
|
||||||
unsigned long cur_len; /* I/O len of current page, up to PAGE_SIZE */
|
|
||||||
|
|
||||||
unsigned long addr; /* user iovec address */
|
|
||||||
size_t count; /* user iovec len */
|
|
||||||
size_t nbytes = iocb->ki_nbytes = iocb->ki_left; /* total xfer size */
|
|
||||||
loff_t size; /* size of block device */
|
|
||||||
struct bio *bio;
|
|
||||||
atomic_t *bio_count = &iocb->ki_bio_count;
|
|
||||||
struct page *page;
|
|
||||||
struct pvec pvec;
|
|
||||||
|
|
||||||
pvec.nr = 0;
|
|
||||||
pvec.idx = 0;
|
|
||||||
|
|
||||||
if (pos & blocksize_mask)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
size = i_size_read(inode);
|
|
||||||
if (pos + nbytes > size) {
|
|
||||||
nbytes = size - pos;
|
|
||||||
iocb->ki_left = nbytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* check first non-zero iov alignment, the remaining
|
|
||||||
* iov alignment is checked inside bio loop below.
|
|
||||||
*/
|
|
||||||
do {
|
|
||||||
addr = (unsigned long) iov[seg].iov_base;
|
|
||||||
count = min(iov[seg].iov_len, nbytes);
|
|
||||||
if (addr & blocksize_mask || count & blocksize_mask)
|
|
||||||
return -EINVAL;
|
|
||||||
} while (!count && ++seg < nr_segs);
|
|
||||||
atomic_set(bio_count, 1);
|
|
||||||
|
|
||||||
while (nbytes) {
|
|
||||||
/* roughly estimate number of bio vec needed */
|
|
||||||
nvec = (nbytes + PAGE_SIZE - 1) / PAGE_SIZE;
|
|
||||||
nvec = max(nvec, nr_segs - seg);
|
|
||||||
nvec = min(nvec, (unsigned long) BIO_MAX_PAGES);
|
|
||||||
|
|
||||||
/* bio_alloc should not fail with GFP_KERNEL flag */
|
|
||||||
bio = bio_alloc(GFP_KERNEL, nvec);
|
|
||||||
bio->bi_bdev = I_BDEV(inode);
|
|
||||||
bio->bi_end_io = blk_end_aio;
|
|
||||||
bio->bi_private = iocb;
|
|
||||||
bio->bi_sector = pos >> blkbits;
|
|
||||||
same_bio:
|
|
||||||
cur_off = addr & ~PAGE_MASK;
|
|
||||||
cur_len = PAGE_SIZE - cur_off;
|
|
||||||
if (count < cur_len)
|
|
||||||
cur_len = count;
|
|
||||||
|
|
||||||
page = blk_get_page(addr, count, rw, &pvec);
|
|
||||||
if (unlikely(IS_ERR(page)))
|
|
||||||
goto backout;
|
|
||||||
|
|
||||||
if (bio_add_page(bio, page, cur_len, cur_off)) {
|
|
||||||
pos += cur_len;
|
|
||||||
addr += cur_len;
|
|
||||||
count -= cur_len;
|
|
||||||
nbytes -= cur_len;
|
|
||||||
|
|
||||||
if (count)
|
|
||||||
goto same_bio;
|
|
||||||
while (++seg < nr_segs) {
|
|
||||||
addr = (unsigned long) iov[seg].iov_base;
|
|
||||||
count = iov[seg].iov_len;
|
|
||||||
if (!count)
|
|
||||||
continue;
|
|
||||||
if (unlikely(addr & blocksize_mask ||
|
|
||||||
count & blocksize_mask)) {
|
|
||||||
page = ERR_PTR(-EINVAL);
|
|
||||||
goto backout;
|
|
||||||
}
|
|
||||||
count = min(count, nbytes);
|
|
||||||
goto same_bio;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
blk_unget_page(page, &pvec);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* bio is ready, submit it */
|
|
||||||
if (rw == READ)
|
|
||||||
bio_set_pages_dirty(bio);
|
|
||||||
atomic_inc(bio_count);
|
|
||||||
submit_bio(rw, bio);
|
|
||||||
}
|
|
||||||
|
|
||||||
completion:
|
|
||||||
iocb->ki_left -= nbytes;
|
|
||||||
nbytes = iocb->ki_left;
|
|
||||||
iocb->ki_pos += nbytes;
|
|
||||||
|
|
||||||
blk_run_address_space(inode->i_mapping);
|
|
||||||
if (atomic_dec_and_test(bio_count))
|
|
||||||
aio_complete(iocb, nbytes, 0);
|
|
||||||
|
|
||||||
return -EIOCBQUEUED;
|
|
||||||
|
|
||||||
backout:
|
|
||||||
/*
|
|
||||||
* back out nbytes count constructed so far for this bio,
|
|
||||||
* we will throw away current bio.
|
|
||||||
*/
|
|
||||||
nbytes += bio->bi_size;
|
|
||||||
bio_release_pages(bio);
|
|
||||||
bio_put(bio);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* if no bio was submmitted, return the error code.
|
|
||||||
* otherwise, proceed with pending I/O completion.
|
|
||||||
*/
|
|
||||||
if (atomic_read(bio_count) == 1)
|
|
||||||
return PTR_ERR(page);
|
|
||||||
goto completion;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int blkdev_writepage(struct page *page, struct writeback_control *wbc)
|
static int blkdev_writepage(struct page *page, struct writeback_control *wbc)
|
||||||
{
|
{
|
||||||
return block_write_full_page(page, blkdev_get_block, wbc);
|
return block_write_full_page(page, blkdev_get_block, wbc);
|
||||||
|
|
|
@ -105,7 +105,6 @@ struct kiocb {
|
||||||
wait_queue_t ki_wait;
|
wait_queue_t ki_wait;
|
||||||
loff_t ki_pos;
|
loff_t ki_pos;
|
||||||
|
|
||||||
atomic_t ki_bio_count; /* num bio used for this iocb */
|
|
||||||
void *private;
|
void *private;
|
||||||
/* State that we remember to be able to restart/retry */
|
/* State that we remember to be able to restart/retry */
|
||||||
unsigned short ki_opcode;
|
unsigned short ki_opcode;
|
||||||
|
|
|
@ -326,7 +326,6 @@ extern struct bio *bio_map_kern(struct request_queue *, void *, unsigned int,
|
||||||
gfp_t);
|
gfp_t);
|
||||||
extern void bio_set_pages_dirty(struct bio *bio);
|
extern void bio_set_pages_dirty(struct bio *bio);
|
||||||
extern void bio_check_pages_dirty(struct bio *bio);
|
extern void bio_check_pages_dirty(struct bio *bio);
|
||||||
extern void bio_release_pages(struct bio *bio);
|
|
||||||
extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int);
|
extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int);
|
||||||
extern int bio_uncopy_user(struct bio *);
|
extern int bio_uncopy_user(struct bio *);
|
||||||
void zero_fill_bio(struct bio *bio);
|
void zero_fill_bio(struct bio *bio);
|
||||||
|
|
Loading…
Reference in New Issue