diff options
-rw-r--r-- | drivers/block/rbd.c | 51 |
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 | ||
1587 | static void rbd_free_disk(struct rbd_device *rbd_dev) | 1606 | static void rbd_free_disk(struct rbd_device *rbd_dev) |