Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 347572
b: refs/heads/master
c: e5cfeed
h: refs/heads/master
v: v3
  • Loading branch information
Alex Elder committed Oct 26, 2012
1 parent 1cbdf12 commit e7dbddd
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 17 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d4b125e9eb43babd14538ba61718e3db71a98d29
refs/heads/master: e5cfeed281a842a37c9da84bad2911c9b470347e
51 changes: 35 additions & 16 deletions trunk/drivers/block/rbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1566,22 +1566,41 @@ static int rbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd,
struct bio_vec *bvec)
{
struct rbd_device *rbd_dev = q->queuedata;
unsigned int chunk_sectors;
sector_t sector;
unsigned int bio_sectors;
int max;

chunk_sectors = 1 << (rbd_dev->header.obj_order - SECTOR_SHIFT);
sector = bmd->bi_sector + get_start_sect(bmd->bi_bdev);
bio_sectors = bmd->bi_size >> SECTOR_SHIFT;

max = (chunk_sectors - ((sector & (chunk_sectors - 1))
+ bio_sectors)) << SECTOR_SHIFT;
if (max < 0)
max = 0; /* bio_add cannot handle a negative return */
if (max <= bvec->bv_len && bio_sectors == 0)
return bvec->bv_len;
return max;
sector_t sector_offset;
sector_t sectors_per_obj;
sector_t obj_sector_offset;
int ret;

/*
* Find how far into its rbd object the partition-relative
* bio start sector is to offset relative to the enclosing
* device.
*/
sector_offset = get_start_sect(bmd->bi_bdev) + bmd->bi_sector;
sectors_per_obj = 1 << (rbd_dev->header.obj_order - SECTOR_SHIFT);
obj_sector_offset = sector_offset & (sectors_per_obj - 1);

/*
* Compute the number of bytes from that offset to the end
* of the object. Account for what's already used by the bio.
*/
ret = (int) (sectors_per_obj - obj_sector_offset) << SECTOR_SHIFT;
if (ret > bmd->bi_size)
ret -= bmd->bi_size;
else
ret = 0;

/*
* Don't send back more than was asked for. And if the bio
* was empty, let the whole thing through because: "Note
* that a block device *must* allow a single page to be
* added to an empty bio."
*/
rbd_assert(bvec->bv_len <= PAGE_SIZE);
if (ret > (int) bvec->bv_len || !bmd->bi_size)
ret = (int) bvec->bv_len;

return ret;
}

static void rbd_free_disk(struct rbd_device *rbd_dev)
Expand Down

0 comments on commit e7dbddd

Please sign in to comment.