aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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)