md: Export preferred I/O sizes and physical alignment For each of the RAID levels set the preferred I/O hints according to chunk size and stripe width. Signed-off-by: Martin K. Petersen --- diff --git a/drivers/md/linear.c b/drivers/md/linear.c --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -135,6 +135,17 @@ static linear_conf_t *linear_conf(mddev_ blk_queue_stack_limits(mddev->queue, rdev->bdev->bd_disk->queue); + + if (rdev->raid_disk == 0) { + disk_topology_set(mddev->gendisk, 0, IOT_PHYS_OFFSET, + bdev_phys_offset(rdev->bdev) + + rdev->data_offset); + disk_topology_set(mddev->gendisk, 0, IOT_OPT_BLOCK_SIZE, + bdev_optimal_io_block(rdev->bdev)); + disk_topology_set(mddev->gendisk, 0, IOT_OPT_IO_LENGTH, + bdev_optimal_io_length(rdev->bdev)); + } + /* as we don't honour merge_bvec_fn, we must never risk * violating it, so limit ->max_sector to one PAGE, as * a one page request is never in violation. diff --git a/drivers/md/md.c b/drivers/md/md.c --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3325,6 +3325,7 @@ static struct kobject *md_probe(dev_t de disk->private_data = mddev; disk->queue = mddev->queue; add_disk(disk); + disk_topology_register(disk); mddev->gendisk = disk; mutex_unlock(&disks_mutex); error = kobject_init_and_add(&mddev->kobj, &md_ktype, &disk->dev.kobj, @@ -6181,6 +6182,7 @@ static __exit void md_exit(void) if (!disk) continue; export_array(mddev); + disk_topology_unregister(disk); del_gendisk(disk); put_disk(disk); mddev->gendisk = NULL; diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -140,6 +140,17 @@ static int create_strip_zones (mddev_t * blk_queue_stack_limits(mddev->queue, rdev1->bdev->bd_disk->queue); + + if (rdev1->raid_disk == 0) { + disk_set_io_hints(mddev->gendisk, + bdev_phys_offset(rdev1->bdev) + + rdev1->data_offset, + mddev->chunk_size, + mddev->chunk_size * mddev->raid_disks); + printk(KERN_ERR "raid0: chunk_size=%u, disks=%u\n", + mddev->chunk_size, mddev->raid_disks); + } + /* as we don't honour merge_bvec_fn, we must never risk * violating it, so limit ->max_sector to one PAGE, as * a one page request is never in violation. diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1970,6 +1970,14 @@ static int run(mddev_t *mddev) blk_queue_stack_limits(mddev->queue, rdev->bdev->bd_disk->queue); + + if (rdev->raid_disk == 0) + disk_set_io_hints(mddev->gendisk, + bdev_phys_offset(rdev->bdev) + + rdev->data_offset, + bdev_optimal_io_block(rdev->bdev), + bdev_optimal_io_length(rdev->bdev)); + /* as we don't honour merge_bvec_fn, we must never risk * violating it, so limit ->max_sector to one PAGE, as * a one page request is never in violation. diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -2106,6 +2106,15 @@ static int run(mddev_t *mddev) blk_queue_stack_limits(mddev->queue, rdev->bdev->bd_disk->queue); + + if (rdev->raid_disk == 0) + disk_set_io_hints(mddev->gendisk, + bdev_phys_offset(rdev->bdev) + + rdev->data_offset, + mddev->chunk_size, + (mddev->chunk_size * mddev->raid_disks) + >> 1); + /* as we don't honour merge_bvec_fn, we must never risk * violating it, so limit ->max_sector to one PAGE, as * a one page request is never in violation. diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4368,6 +4368,19 @@ static int run(mddev_t *mddev) mdname(mddev)); goto abort; } + + if (rdev->raid_disk == 0) { + int disks = mddev->raid_disks - 1; + + if (mddev->level == 6) + disks--; + + disk_set_io_hints(mddev->gendisk, + bdev_phys_offset(rdev->bdev) + + rdev->data_offset, + mddev->chunk_size, + mddev->chunk_size * disks); + } } {