diff options
author | Stefan Haberland <stefan.haberland@de.ibm.com> | 2014-07-18 14:26:01 +0200 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2014-07-22 09:26:23 +0200 |
commit | 29b8dd9d4274bca6526e4bb8d4f46dec1f4c15c9 (patch) | |
tree | 631cb92a24223b571ea534f28ea7ec0a2950480b /drivers/s390/block/dasd_ioctl.c | |
parent | dasd: fix list_del corruption during format (diff) | |
download | linux-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.c | 33 |
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; } /* |