summaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd_ioctl.c
diff options
context:
space:
mode:
authorStefan Haberland <stefan.haberland@de.ibm.com>2014-07-18 14:26:01 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2014-07-22 09:26:23 +0200
commit29b8dd9d4274bca6526e4bb8d4f46dec1f4c15c9 (patch)
tree631cb92a24223b571ea534f28ea7ec0a2950480b /drivers/s390/block/dasd_ioctl.c
parentdasd: fix list_del corruption during format (diff)
downloadlinux-29b8dd9d4274bca6526e4bb8d4f46dec1f4c15c9.tar.xz
linux-29b8dd9d4274bca6526e4bb8d4f46dec1f4c15c9.zip
dasd: fix error recovery for alias devices during format
Kernel panic or a hanging device during format if an alias device is set offline or I/O errors occur. Omit the error recovery procedure for alias devices and do retries on the base device with full erp. Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/block/dasd_ioctl.c')
-rw-r--r--drivers/s390/block/dasd_ioctl.c33
1 files changed, 27 insertions, 6 deletions
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 25a0f2f8b0b9..ad62608e4175 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -203,7 +203,9 @@ static int
dasd_format(struct dasd_block *block, struct format_data_t *fdata)
{
struct dasd_device *base;
- int rc;
+ int enable_PAV = 1;
+ int rc, retries;
+ int start, stop;
base = block->base;
if (base->discipline->format_device == NULL)
@@ -231,11 +233,30 @@ dasd_format(struct dasd_block *block, struct format_data_t *fdata)
bdput(bdev);
}
- rc = base->discipline->format_device(base, fdata);
- if (rc)
- return rc;
-
- return 0;
+ retries = 255;
+ /* backup start- and endtrack for retries */
+ start = fdata->start_unit;
+ stop = fdata->stop_unit;
+ do {
+ rc = base->discipline->format_device(base, fdata, enable_PAV);
+ if (rc) {
+ if (rc == -EAGAIN) {
+ retries--;
+ /* disable PAV in case of errors */
+ enable_PAV = 0;
+ fdata->start_unit = start;
+ fdata->stop_unit = stop;
+ } else
+ return rc;
+ } else
+ /* success */
+ break;
+ } while (retries);
+
+ if (!retries)
+ return -EIO;
+ else
+ return 0;
}
/*