diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 01ed03a0c7ee..1dadb134e0bb 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -42,7 +42,7 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector) (void)sector_div(block, conf->hash_spacing); hash = conf->hash_table[block]; - while ((sector>>1) >= (hash->size + hash->offset)) + while (sector >= hash->num_sectors + hash->start_sector) hash++; return hash; } @@ -65,7 +65,7 @@ static int linear_mergeable_bvec(struct request_queue *q, sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev); dev0 = which_dev(mddev, sector); - maxsectors = (dev0->size << 1) - (sector - (dev0->offset<<1)); + maxsectors = dev0->num_sectors - (sector - dev0->start_sector); if (maxsectors < bio_sectors) maxsectors = 0; @@ -113,7 +113,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) mdk_rdev_t *rdev; int i, nb_zone, cnt; sector_t min_spacing; - sector_t curr_offset; + sector_t curr_sector; struct list_head *tmp; conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t), @@ -145,7 +145,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) mddev->queue->max_sectors > (PAGE_SIZE>>9)) blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); - disk->size = rdev->size; + disk->num_sectors = rdev->size * 2; conf->array_sectors += rdev->size * 2; cnt++; @@ -169,7 +169,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) sector_t sz = 0; int j; for (j = i; j < cnt - 1 && sz < min_spacing; j++) - sz += conf->disks[j].size; + sz += conf->disks[j].num_sectors / 2; if (sz >= min_spacing && sz < conf->hash_spacing) conf->hash_spacing = sz; } @@ -211,20 +211,20 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) * Here we generate the linear hash table * First calculate the device offsets. */ - conf->disks[0].offset = 0; + conf->disks[0].start_sector = 0; for (i = 1; i < raid_disks; i++) - conf->disks[i].offset = - conf->disks[i-1].offset + - conf->disks[i-1].size; + conf->disks[i].start_sector = + conf->disks[i-1].start_sector + + conf->disks[i-1].num_sectors; table = conf->hash_table; i = 0; - for (curr_offset = 0; - curr_offset < conf->array_sectors / 2; - curr_offset += conf->hash_spacing) { + for (curr_sector = 0; + curr_sector < conf->array_sectors; + curr_sector += conf->hash_spacing * 2) { while (i < raid_disks-1 && - curr_offset >= conf->disks[i+1].offset) + curr_sector >= conf->disks[i+1].start_sector) i++; *table ++ = conf->disks + i; @@ -316,7 +316,6 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) const int rw = bio_data_dir(bio); mddev_t *mddev = q->queuedata; dev_info_t *tmp_dev; - sector_t block; int cpu; if (unlikely(bio_barrier(bio))) { @@ -331,29 +330,33 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) part_stat_unlock(); tmp_dev = which_dev(mddev, bio->bi_sector); - block = bio->bi_sector >> 1; - if (unlikely(block >= (tmp_dev->size + tmp_dev->offset) - || block < tmp_dev->offset)) { + if (unlikely(bio->bi_sector >= (tmp_dev->num_sectors + + tmp_dev->start_sector) + || (bio->bi_sector < + tmp_dev->start_sector))) { char b[BDEVNAME_SIZE]; - printk("linear_make_request: Block %llu out of bounds on " - "dev %s size %llu offset %llu\n", - (unsigned long long)block, + printk("linear_make_request: Sector %llu out of bounds on " + "dev %s: %llu sectors, offset %llu\n", + (unsigned long long)bio->bi_sector, bdevname(tmp_dev->rdev->bdev, b), - (unsigned long long)tmp_dev->size, - (unsigned long long)tmp_dev->offset); + (unsigned long long)tmp_dev->num_sectors, + (unsigned long long)tmp_dev->start_sector); bio_io_error(bio); return 0; } if (unlikely(bio->bi_sector + (bio->bi_size >> 9) > - (tmp_dev->offset + tmp_dev->size)<<1)) { + tmp_dev->start_sector + tmp_dev->num_sectors)) { /* This bio crosses a device boundary, so we have to * split it. */ struct bio_pair *bp; + bp = bio_split(bio, - ((tmp_dev->offset + tmp_dev->size)<<1) - bio->bi_sector); + tmp_dev->start_sector + tmp_dev->num_sectors + - bio->bi_sector); + if (linear_make_request(q, &bp->bio1)) generic_make_request(&bp->bio1); if (linear_make_request(q, &bp->bio2)) @@ -363,7 +366,8 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) } bio->bi_bdev = tmp_dev->rdev->bdev; - bio->bi_sector = bio->bi_sector - (tmp_dev->offset << 1) + tmp_dev->rdev->data_offset; + bio->bi_sector = bio->bi_sector - tmp_dev->start_sector + + tmp_dev->rdev->data_offset; return 1; } diff --git a/include/linux/raid/linear.h b/include/linux/raid/linear.h index 7e375111d007..87090e98529f 100644 --- a/include/linux/raid/linear.h +++ b/include/linux/raid/linear.h @@ -5,8 +5,8 @@ struct dev_info { mdk_rdev_t *rdev; - sector_t size; - sector_t offset; + sector_t num_sectors; + sector_t start_sector; }; typedef struct dev_info dev_info_t;