summaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd_genhd.c
diff options
context:
space:
mode:
authorStefan Weinhuber <wein@de.ibm.com>2008-01-26 14:11:23 +0100
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2008-01-26 14:11:28 +0100
commit8e09f21574ea3028d5629e5de759e0b196c690c5 (patch)
treeced4feb1847ee6c2a7b7b4cec8f3118f83d3a386 /drivers/s390/block/dasd_genhd.c
parent[S390] single-step cleanup (diff)
downloadlinux-8e09f21574ea3028d5629e5de759e0b196c690c5.tar.xz
linux-8e09f21574ea3028d5629e5de759e0b196c690c5.zip
[S390] dasd: add hyper PAV support to DASD device driver, part 1
Parallel access volumes (PAV) is a storage server feature, that allows to start multiple channel programs on the same DASD in parallel. It defines alias devices which can be used as alternative paths to the same disk. With the old base PAV support we only needed rudimentary functionality in the DASD device driver. As the mapping between base and alias devices was static, we just had to export an identifier (uid) and could leave the combining of devices to external layers like a device mapper multipath. Now hyper PAV removes the requirement to dedicate alias devices to specific base devices. Instead each alias devices can be combined with multiple base device on a per request basis. This requires full support by the DASD device driver as now each channel program itself has to identify the target base device. The changes to the dasd device driver and the ECKD discipline are: - Separate subchannel device representation (dasd_device) from block device representation (dasd_block). Only base devices are block devices. - Gather information about base and alias devices and possible combinations. - For each request decide which dasd_device should be used (base or alias) and build specific channel program. - Support summary unit checks, which allow the storage server to upgrade / downgrade between base and hyper PAV at runtime (support is mandatory). Signed-off-by: Stefan Weinhuber <wein@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/block/dasd_genhd.c')
-rw-r--r--drivers/s390/block/dasd_genhd.c76
1 files changed, 36 insertions, 40 deletions
diff --git a/drivers/s390/block/dasd_genhd.c b/drivers/s390/block/dasd_genhd.c
index 47ba4462708d..aee6565aaf98 100644
--- a/drivers/s390/block/dasd_genhd.c
+++ b/drivers/s390/block/dasd_genhd.c
@@ -25,14 +25,15 @@
/*
* Allocate and register gendisk structure for device.
*/
-int
-dasd_gendisk_alloc(struct dasd_device *device)
+int dasd_gendisk_alloc(struct dasd_block *block)
{
struct gendisk *gdp;
+ struct dasd_device *base;
int len;
/* Make sure the minor for this device exists. */
- if (device->devindex >= DASD_PER_MAJOR)
+ base = block->base;
+ if (base->devindex >= DASD_PER_MAJOR)
return -EBUSY;
gdp = alloc_disk(1 << DASD_PARTN_BITS);
@@ -41,9 +42,9 @@ dasd_gendisk_alloc(struct dasd_device *device)
/* Initialize gendisk structure. */
gdp->major = DASD_MAJOR;
- gdp->first_minor = device->devindex << DASD_PARTN_BITS;
+ gdp->first_minor = base->devindex << DASD_PARTN_BITS;
gdp->fops = &dasd_device_operations;
- gdp->driverfs_dev = &device->cdev->dev;
+ gdp->driverfs_dev = &base->cdev->dev;
/*
* Set device name.
@@ -53,53 +54,51 @@ dasd_gendisk_alloc(struct dasd_device *device)
* dasdaaaa - dasdzzzz : 456976 devices, added up = 475252
*/
len = sprintf(gdp->disk_name, "dasd");
- if (device->devindex > 25) {
- if (device->devindex > 701) {
- if (device->devindex > 18277)
+ if (base->devindex > 25) {
+ if (base->devindex > 701) {
+ if (base->devindex > 18277)
len += sprintf(gdp->disk_name + len, "%c",
- 'a'+(((device->devindex-18278)
+ 'a'+(((base->devindex-18278)
/17576)%26));
len += sprintf(gdp->disk_name + len, "%c",
- 'a'+(((device->devindex-702)/676)%26));
+ 'a'+(((base->devindex-702)/676)%26));
}
len += sprintf(gdp->disk_name + len, "%c",
- 'a'+(((device->devindex-26)/26)%26));
+ 'a'+(((base->devindex-26)/26)%26));
}
- len += sprintf(gdp->disk_name + len, "%c", 'a'+(device->devindex%26));
+ len += sprintf(gdp->disk_name + len, "%c", 'a'+(base->devindex%26));
- if (device->features & DASD_FEATURE_READONLY)
+ if (block->base->features & DASD_FEATURE_READONLY)
set_disk_ro(gdp, 1);
- gdp->private_data = device;
- gdp->queue = device->request_queue;
- device->gdp = gdp;
- set_capacity(device->gdp, 0);
- add_disk(device->gdp);
+ gdp->private_data = block;
+ gdp->queue = block->request_queue;
+ block->gdp = gdp;
+ set_capacity(block->gdp, 0);
+ add_disk(block->gdp);
return 0;
}
/*
* Unregister and free gendisk structure for device.
*/
-void
-dasd_gendisk_free(struct dasd_device *device)
+void dasd_gendisk_free(struct dasd_block *block)
{
- if (device->gdp) {
- del_gendisk(device->gdp);
- device->gdp->queue = NULL;
- put_disk(device->gdp);
- device->gdp = NULL;
+ if (block->gdp) {
+ del_gendisk(block->gdp);
+ block->gdp->queue = NULL;
+ put_disk(block->gdp);
+ block->gdp = NULL;
}
}
/*
* Trigger a partition detection.
*/
-int
-dasd_scan_partitions(struct dasd_device * device)
+int dasd_scan_partitions(struct dasd_block *block)
{
struct block_device *bdev;
- bdev = bdget_disk(device->gdp, 0);
+ bdev = bdget_disk(block->gdp, 0);
if (!bdev || blkdev_get(bdev, FMODE_READ, 1) < 0)
return -ENODEV;
/*
@@ -117,7 +116,7 @@ dasd_scan_partitions(struct dasd_device * device)
* is why the assignment to device->bdev is done AFTER
* the BLKRRPART ioctl.
*/
- device->bdev = bdev;
+ block->bdev = bdev;
return 0;
}
@@ -125,8 +124,7 @@ dasd_scan_partitions(struct dasd_device * device)
* Remove all inodes in the system for a device, delete the
* partitions and make device unusable by setting its size to zero.
*/
-void
-dasd_destroy_partitions(struct dasd_device * device)
+void dasd_destroy_partitions(struct dasd_block *block)
{
/* The two structs have 168/176 byte on 31/64 bit. */
struct blkpg_partition bpart;
@@ -137,8 +135,8 @@ dasd_destroy_partitions(struct dasd_device * device)
* Get the bdev pointer from the device structure and clear
* device->bdev to lower the offline open_count limit again.
*/
- bdev = device->bdev;
- device->bdev = NULL;
+ bdev = block->bdev;
+ block->bdev = NULL;
/*
* See fs/partition/check.c:delete_partition
@@ -149,17 +147,16 @@ dasd_destroy_partitions(struct dasd_device * device)
memset(&barg, 0, sizeof(struct blkpg_ioctl_arg));
barg.data = (void __force __user *) &bpart;
barg.op = BLKPG_DEL_PARTITION;
- for (bpart.pno = device->gdp->minors - 1; bpart.pno > 0; bpart.pno--)
+ for (bpart.pno = block->gdp->minors - 1; bpart.pno > 0; bpart.pno--)
ioctl_by_bdev(bdev, BLKPG, (unsigned long) &barg);
- invalidate_partition(device->gdp, 0);
+ invalidate_partition(block->gdp, 0);
/* Matching blkdev_put to the blkdev_get in dasd_scan_partitions. */
blkdev_put(bdev);
- set_capacity(device->gdp, 0);
+ set_capacity(block->gdp, 0);
}
-int
-dasd_gendisk_init(void)
+int dasd_gendisk_init(void)
{
int rc;
@@ -174,8 +171,7 @@ dasd_gendisk_init(void)
return 0;
}
-void
-dasd_gendisk_exit(void)
+void dasd_gendisk_exit(void)
{
unregister_blkdev(DASD_MAJOR, "dasd");
}