aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2012-10-20 23:17:27 -0400
committerAlex Elder <elder@inktank.com>2012-10-26 18:18:08 -0400
commite5cfeed281a842a37c9da84bad2911c9b470347e (patch)
tree9d03793d01f30a5d86f182a98a9cae1c45cb6947 /drivers/block
parentd4b125e9eb43babd14538ba61718e3db71a98d29 (diff)
rbd: simplify rbd_merge_bvec()
The aim of this patch is to make what's going on rbd_merge_bvec() a bit more obvious than it was before. This was an issue when a recent btrfs bug led us to question whether the merge function was working correctly. Use "obj" rather than "chunk" to indicate the units whose boundaries we care about we call (rados) "objects". Signed-off-by: Alex Elder <elder@inktank.com> Reviewed-by: Dan Mick <dan.mick@inktank.com>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/rbd.c51
1 files changed, 35 insertions, 16 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 4858d925b95e..76fbfa120064 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -1566,22 +1566,41 @@ static int rbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bmd,
1566 struct bio_vec *bvec) 1566 struct bio_vec *bvec)
1567{ 1567{
1568 struct rbd_device *rbd_dev = q->queuedata; 1568 struct rbd_device *rbd_dev = q->queuedata;
1569 unsigned int chunk_sectors; 1569 sector_t sector_offset;
1570 sector_t sector; 1570 sector_t sectors_per_obj;
1571 unsigned int bio_sectors; 1571 sector_t obj_sector_offset;
1572 int max; 1572 int ret;
1573 1573
1574 chunk_sectors = 1 << (rbd_dev->header.obj_order - SECTOR_SHIFT); 1574 /*
1575 sector = bmd->bi_sector + get_start_sect(bmd->bi_bdev); 1575 * Find how far into its rbd object the partition-relative
1576 bio_sectors = bmd->bi_size >> SECTOR_SHIFT; 1576 * bio start sector is to offset relative to the enclosing
1577 1577 * device.
1578 max = (chunk_sectors - ((sector & (chunk_sectors - 1)) 1578 */
1579 + bio_sectors)) << SECTOR_SHIFT; 1579 sector_offset = get_start_sect(bmd->bi_bdev) + bmd->bi_sector;
1580 if (max < 0) 1580 sectors_per_obj = 1 << (rbd_dev->header.obj_order - SECTOR_SHIFT);
1581 max = 0; /* bio_add cannot handle a negative return */ 1581 obj_sector_offset = sector_offset & (sectors_per_obj - 1);
1582 if (max <= bvec->bv_len && bio_sectors == 0) 1582
1583 return bvec->bv_len; 1583 /*
1584 return max; 1584 * Compute the number of bytes from that offset to the end
1585 * of the object. Account for what's already used by the bio.
1586 */
1587 ret = (int) (sectors_per_obj - obj_sector_offset) << SECTOR_SHIFT;
1588 if (ret > bmd->bi_size)
1589 ret -= bmd->bi_size;
1590 else
1591 ret = 0;
1592
1593 /*
1594 * Don't send back more than was asked for. And if the bio
1595 * was empty, let the whole thing through because: "Note
1596 * that a block device *must* allow a single page to be
1597 * added to an empty bio."
1598 */
1599 rbd_assert(bvec->bv_len <= PAGE_SIZE);
1600 if (ret > (int) bvec->bv_len || !bmd->bi_size)
1601 ret = (int) bvec->bv_len;
1602
1603 return ret;
1585} 1604}
1586 1605
1587static void rbd_free_disk(struct rbd_device *rbd_dev) 1606static void rbd_free_disk(struct rbd_device *rbd_dev)