Skip to content

Commit

Permalink
Merge branch 'for-jens' of http://evilpiepirate.org/git/linux-bcache
Browse files Browse the repository at this point in the history
…into for-3.10/core

This contains Kents prep work for the immutable bio_vecs.
  • Loading branch information
Jens Axboe committed Mar 25, 2013
2 parents c815881 + 29ed781 commit 705cd0e
Show file tree
Hide file tree
Showing 39 changed files with 645 additions and 630 deletions.
82 changes: 13 additions & 69 deletions block/blk-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,20 +159,10 @@ static void req_bio_endio(struct request *rq, struct bio *bio,
else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
error = -EIO;

if (unlikely(nbytes > bio->bi_size)) {
printk(KERN_ERR "%s: want %u bytes done, %u left\n",
__func__, nbytes, bio->bi_size);
nbytes = bio->bi_size;
}

if (unlikely(rq->cmd_flags & REQ_QUIET))
set_bit(BIO_QUIET, &bio->bi_flags);

bio->bi_size -= nbytes;
bio->bi_sector += (nbytes >> 9);

if (bio_integrity(bio))
bio_integrity_advance(bio, nbytes);
bio_advance(bio, nbytes);

/* don't actually finish bio if it's part of flush sequence */
if (bio->bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ))
Expand Down Expand Up @@ -1609,7 +1599,7 @@ static void handle_bad_sector(struct bio *bio)
printk(KERN_INFO "%s: rw=%ld, want=%Lu, limit=%Lu\n",
bdevname(bio->bi_bdev, b),
bio->bi_rw,
(unsigned long long)bio->bi_sector + bio_sectors(bio),
(unsigned long long)bio_end_sector(bio),
(long long)(i_size_read(bio->bi_bdev->bd_inode) >> 9));

set_bit(BIO_EOF, &bio->bi_flags);
Expand Down Expand Up @@ -2292,8 +2282,7 @@ EXPORT_SYMBOL(blk_fetch_request);
**/
bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
{
int total_bytes, bio_nbytes, next_idx = 0;
struct bio *bio;
int total_bytes;

if (!req->bio)
return false;
Expand Down Expand Up @@ -2339,56 +2328,21 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)

blk_account_io_completion(req, nr_bytes);

total_bytes = bio_nbytes = 0;
while ((bio = req->bio) != NULL) {
int nbytes;
total_bytes = 0;
while (req->bio) {
struct bio *bio = req->bio;
unsigned bio_bytes = min(bio->bi_size, nr_bytes);

if (nr_bytes >= bio->bi_size) {
if (bio_bytes == bio->bi_size)
req->bio = bio->bi_next;
nbytes = bio->bi_size;
req_bio_endio(req, bio, nbytes, error);
next_idx = 0;
bio_nbytes = 0;
} else {
int idx = bio->bi_idx + next_idx;

if (unlikely(idx >= bio->bi_vcnt)) {
blk_dump_rq_flags(req, "__end_that");
printk(KERN_ERR "%s: bio idx %d >= vcnt %d\n",
__func__, idx, bio->bi_vcnt);
break;
}

nbytes = bio_iovec_idx(bio, idx)->bv_len;
BIO_BUG_ON(nbytes > bio->bi_size);

/*
* not a complete bvec done
*/
if (unlikely(nbytes > nr_bytes)) {
bio_nbytes += nr_bytes;
total_bytes += nr_bytes;
break;
}

/*
* advance to the next vector
*/
next_idx++;
bio_nbytes += nbytes;
}
req_bio_endio(req, bio, bio_bytes, error);

total_bytes += nbytes;
nr_bytes -= nbytes;
total_bytes += bio_bytes;
nr_bytes -= bio_bytes;

bio = req->bio;
if (bio) {
/*
* end more in this run, or just return 'not-done'
*/
if (unlikely(nr_bytes <= 0))
break;
}
if (!nr_bytes)
break;
}

/*
Expand All @@ -2404,16 +2358,6 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
return false;
}

/*
* if the request wasn't completed, update state
*/
if (bio_nbytes) {
req_bio_endio(req, bio, bio_nbytes, error);
bio->bi_idx += next_idx;
bio_iovec(bio)->bv_offset += nr_bytes;
bio_iovec(bio)->bv_len -= nr_bytes;
}

req->__data_len -= total_bytes;
req->buffer = bio_data(req->bio);

Expand Down
7 changes: 2 additions & 5 deletions block/cfq-iosched.c
Original file line number Diff line number Diff line change
Expand Up @@ -2270,11 +2270,8 @@ cfq_find_rq_fmerge(struct cfq_data *cfqd, struct bio *bio)
return NULL;

cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio));
if (cfqq) {
sector_t sector = bio->bi_sector + bio_sectors(bio);

return elv_rb_find(&cfqq->sort_list, sector);
}
if (cfqq)
return elv_rb_find(&cfqq->sort_list, bio_end_sector(bio));

return NULL;
}
Expand Down
2 changes: 1 addition & 1 deletion block/deadline-iosched.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ deadline_merge(struct request_queue *q, struct request **req, struct bio *bio)
* check for front merge
*/
if (dd->front_merges) {
sector_t sector = bio->bi_sector + bio_sectors(bio);
sector_t sector = bio_end_sector(bio);

__rq = elv_rb_find(&dd->sort_list[bio_data_dir(bio)], sector);
if (__rq) {
Expand Down
2 changes: 1 addition & 1 deletion drivers/block/aoe/aoecmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,7 @@ bufinit(struct buf *buf, struct request *rq, struct bio *bio)
buf->resid = bio->bi_size;
buf->sector = bio->bi_sector;
bio_pageinc(bio);
buf->bv = bv = &bio->bi_io_vec[bio->bi_idx];
buf->bv = bio_iovec(bio);
buf->bv_resid = bv->bv_len;
WARN_ON(buf->bv_resid == 0);
}
Expand Down
3 changes: 1 addition & 2 deletions drivers/block/brd.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,8 +334,7 @@ static void brd_make_request(struct request_queue *q, struct bio *bio)
int err = -EIO;

sector = bio->bi_sector;
if (sector + (bio->bi_size >> SECTOR_SHIFT) >
get_capacity(bdev->bd_disk))
if (bio_end_sector(bio) > get_capacity(bdev->bd_disk))
goto out;

if (unlikely(bio->bi_rw & REQ_DISCARD)) {
Expand Down
1 change: 0 additions & 1 deletion drivers/block/floppy.c
Original file line number Diff line number Diff line change
Expand Up @@ -3777,7 +3777,6 @@ static int __floppy_read_block_0(struct block_device *bdev)
bio_vec.bv_len = size;
bio_vec.bv_offset = 0;
bio.bi_vcnt = 1;
bio.bi_idx = 0;
bio.bi_size = size;
bio.bi_bdev = bdev;
bio.bi_sector = 0;
Expand Down
102 changes: 23 additions & 79 deletions drivers/block/pktcdvd.c
Original file line number Diff line number Diff line change
Expand Up @@ -901,7 +901,7 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
pd->iosched.successive_reads += bio->bi_size >> 10;
else {
pd->iosched.successive_reads = 0;
pd->iosched.last_write = bio->bi_sector + bio_sectors(bio);
pd->iosched.last_write = bio_end_sector(bio);
}
if (pd->iosched.successive_reads >= HI_SPEED_SWITCH) {
if (pd->read_speed == pd->write_speed) {
Expand Down Expand Up @@ -947,31 +947,6 @@ static int pkt_set_segment_merging(struct pktcdvd_device *pd, struct request_que
}
}

/*
* Copy CD_FRAMESIZE bytes from src_bio into a destination page
*/
static void pkt_copy_bio_data(struct bio *src_bio, int seg, int offs, struct page *dst_page, int dst_offs)
{
unsigned int copy_size = CD_FRAMESIZE;

while (copy_size > 0) {
struct bio_vec *src_bvl = bio_iovec_idx(src_bio, seg);
void *vfrom = kmap_atomic(src_bvl->bv_page) +
src_bvl->bv_offset + offs;
void *vto = page_address(dst_page) + dst_offs;
int len = min_t(int, copy_size, src_bvl->bv_len - offs);

BUG_ON(len < 0);
memcpy(vto, vfrom, len);
kunmap_atomic(vfrom);

seg++;
offs = 0;
dst_offs += len;
copy_size -= len;
}
}

/*
* Copy all data for this packet to pkt->pages[], so that
* a) The number of required segments for the write bio is minimized, which
Expand Down Expand Up @@ -1181,16 +1156,15 @@ static int pkt_start_recovery(struct packet_data *pkt)
new_sector = new_block * (CD_FRAMESIZE >> 9);
pkt->sector = new_sector;

bio_reset(pkt->bio);
pkt->bio->bi_bdev = pd->bdev;
pkt->bio->bi_rw = REQ_WRITE;
pkt->bio->bi_sector = new_sector;
pkt->bio->bi_next = NULL;
pkt->bio->bi_flags = 1 << BIO_UPTODATE;
pkt->bio->bi_idx = 0;
pkt->bio->bi_size = pkt->frames * CD_FRAMESIZE;
pkt->bio->bi_vcnt = pkt->frames;

BUG_ON(pkt->bio->bi_rw != REQ_WRITE);
BUG_ON(pkt->bio->bi_vcnt != pkt->frames);
BUG_ON(pkt->bio->bi_size != pkt->frames * CD_FRAMESIZE);
BUG_ON(pkt->bio->bi_end_io != pkt_end_io_packet_write);
BUG_ON(pkt->bio->bi_private != pkt);
pkt->bio->bi_end_io = pkt_end_io_packet_write;
pkt->bio->bi_private = pkt;

drop_super(sb);
return 1;
Expand Down Expand Up @@ -1325,55 +1299,35 @@ static int pkt_handle_queue(struct pktcdvd_device *pd)
*/
static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
{
struct bio *bio;
int f;
int frames_write;
struct bio_vec *bvec = pkt->w_bio->bi_io_vec;

bio_reset(pkt->w_bio);
pkt->w_bio->bi_sector = pkt->sector;
pkt->w_bio->bi_bdev = pd->bdev;
pkt->w_bio->bi_end_io = pkt_end_io_packet_write;
pkt->w_bio->bi_private = pkt;

/* XXX: locking? */
for (f = 0; f < pkt->frames; f++) {
bvec[f].bv_page = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE];
bvec[f].bv_offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset))
BUG();
}
VPRINTK(DRIVER_NAME": vcnt=%d\n", pkt->w_bio->bi_vcnt);

/*
* Fill-in bvec with data from orig_bios.
*/
frames_write = 0;
spin_lock(&pkt->lock);
bio_list_for_each(bio, &pkt->orig_bios) {
int segment = bio->bi_idx;
int src_offs = 0;
int first_frame = (bio->bi_sector - pkt->sector) / (CD_FRAMESIZE >> 9);
int num_frames = bio->bi_size / CD_FRAMESIZE;
BUG_ON(first_frame < 0);
BUG_ON(first_frame + num_frames > pkt->frames);
for (f = first_frame; f < first_frame + num_frames; f++) {
struct bio_vec *src_bvl = bio_iovec_idx(bio, segment);

while (src_offs >= src_bvl->bv_len) {
src_offs -= src_bvl->bv_len;
segment++;
BUG_ON(segment >= bio->bi_vcnt);
src_bvl = bio_iovec_idx(bio, segment);
}
bio_copy_data(pkt->w_bio, pkt->orig_bios.head);

if (src_bvl->bv_len - src_offs >= CD_FRAMESIZE) {
bvec[f].bv_page = src_bvl->bv_page;
bvec[f].bv_offset = src_bvl->bv_offset + src_offs;
} else {
pkt_copy_bio_data(bio, segment, src_offs,
bvec[f].bv_page, bvec[f].bv_offset);
}
src_offs += CD_FRAMESIZE;
frames_write++;
}
}
pkt_set_state(pkt, PACKET_WRITE_WAIT_STATE);
spin_unlock(&pkt->lock);

VPRINTK("pkt_start_write: Writing %d frames for zone %llx\n",
frames_write, (unsigned long long)pkt->sector);
BUG_ON(frames_write != pkt->write_size);
pkt->write_size, (unsigned long long)pkt->sector);

if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames)) {
pkt_make_local_copy(pkt, bvec);
Expand All @@ -1383,16 +1337,6 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
}

/* Start the write request */
bio_reset(pkt->w_bio);
pkt->w_bio->bi_sector = pkt->sector;
pkt->w_bio->bi_bdev = pd->bdev;
pkt->w_bio->bi_end_io = pkt_end_io_packet_write;
pkt->w_bio->bi_private = pkt;
for (f = 0; f < pkt->frames; f++)
if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset))
BUG();
VPRINTK(DRIVER_NAME": vcnt=%d\n", pkt->w_bio->bi_vcnt);

atomic_set(&pkt->io_wait, 1);
pkt->w_bio->bi_rw = WRITE;
pkt_queue_bio(pd, pkt->w_bio);
Expand Down Expand Up @@ -2433,7 +2377,7 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio)
cloned_bio->bi_bdev = pd->bdev;
cloned_bio->bi_private = psd;
cloned_bio->bi_end_io = pkt_end_io_read_cloned;
pd->stats.secs_r += bio->bi_size >> 9;
pd->stats.secs_r += bio_sectors(bio);
pkt_queue_bio(pd, cloned_bio);
return;
}
Expand All @@ -2454,15 +2398,15 @@ static void pkt_make_request(struct request_queue *q, struct bio *bio)
zone = ZONE(bio->bi_sector, pd);
VPRINTK("pkt_make_request: start = %6llx stop = %6llx\n",
(unsigned long long)bio->bi_sector,
(unsigned long long)(bio->bi_sector + bio_sectors(bio)));
(unsigned long long)bio_end_sector(bio));

/* Check if we have to split the bio */
{
struct bio_pair *bp;
sector_t last_zone;
int first_sectors;

last_zone = ZONE(bio->bi_sector + bio_sectors(bio) - 1, pd);
last_zone = ZONE(bio_end_sector(bio) - 1, pd);
if (last_zone != zone) {
BUG_ON(last_zone != zone + pd->settings.size);
first_sectors = last_zone - bio->bi_sector;
Expand Down
2 changes: 1 addition & 1 deletion drivers/block/rbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -952,7 +952,7 @@ static struct bio *bio_clone_range(struct bio *bio_src,
/* Find first affected segment... */

resid = offset;
__bio_for_each_segment(bv, bio_src, idx, 0) {
bio_for_each_segment(bv, bio_src, idx) {
if (resid < bv->bv_len)
break;
resid -= bv->bv_len;
Expand Down
3 changes: 1 addition & 2 deletions drivers/md/dm-crypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -858,8 +858,7 @@ static void crypt_free_buffer_pages(struct crypt_config *cc, struct bio *clone)
unsigned int i;
struct bio_vec *bv;

for (i = 0; i < clone->bi_vcnt; i++) {
bv = bio_iovec_idx(clone, i);
bio_for_each_segment_all(bv, clone, i) {
BUG_ON(!bv->bv_page);
mempool_free(bv->bv_page, cc->page_pool);
bv->bv_page = NULL;
Expand Down
2 changes: 1 addition & 1 deletion drivers/md/dm-raid1.c
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ static void map_region(struct dm_io_region *io, struct mirror *m,
{
io->bdev = m->dev->bdev;
io->sector = map_sector(m, bio);
io->count = bio->bi_size >> 9;
io->count = bio_sectors(bio);
}

static void hold_bio(struct mirror_set *ms, struct bio *bio)
Expand Down
2 changes: 1 addition & 1 deletion drivers/md/dm-stripe.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ static int stripe_map_range(struct stripe_c *sc, struct bio *bio,
sector_t begin, end;

stripe_map_range_sector(sc, bio->bi_sector, target_stripe, &begin);
stripe_map_range_sector(sc, bio->bi_sector + bio_sectors(bio),
stripe_map_range_sector(sc, bio_end_sector(bio),
target_stripe, &end);
if (begin < end) {
bio->bi_bdev = sc->stripe[target_stripe].dev->bdev;
Expand Down
Loading

0 comments on commit 705cd0e

Please sign in to comment.