summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Haberland <stefan.haberland@de.ibm.com>2014-10-01 13:04:54 +0200
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2014-10-09 09:13:51 +0200
commit362ce84f43aac61589a8b60e5bb3fcfae9801b13 (patch)
treec3417eb18b62b843922c56947842ca3c318d3930
parentcfb0b24143b4f587ff3e3bd829f9f471285d097b (diff)
downloadlinux-362ce84f43aac61589a8b60e5bb3fcfae9801b13.tar.bz2
s390/dasd: fix infinite loop during format
Error recovery requests may not be cleaned up correctly so that other needed erp requests can not be build because of insufficient memory. This would lead to an infinite loop trying to build erp requests. Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--drivers/s390/block/dasd.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 5df05f26b7d9..f0895f49d4f9 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -2261,8 +2261,8 @@ static inline int _wait_for_wakeup_queue(struct list_head *ccw_queue)
static int _dasd_sleep_on_queue(struct list_head *ccw_queue, int interruptible)
{
struct dasd_device *device;
- int rc;
struct dasd_ccw_req *cqr, *n;
+ int rc;
retry:
list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) {
@@ -2310,21 +2310,26 @@ retry:
/*
* for alias devices simplify error recovery and
* return to upper layer
+ * do not skip ERP requests
*/
- if (cqr->startdev != cqr->basedev &&
+ if (cqr->startdev != cqr->basedev && !cqr->refers &&
(cqr->status == DASD_CQR_TERMINATED ||
cqr->status == DASD_CQR_NEED_ERP))
return -EAGAIN;
- else {
- /* normal recovery for basedev IO */
- if (__dasd_sleep_on_erp(cqr)) {
- if (!cqr->status == DASD_CQR_TERMINATED &&
- !cqr->status == DASD_CQR_NEED_ERP)
- break;
- rc = 1;
- }
+
+ /* normal recovery for basedev IO */
+ if (__dasd_sleep_on_erp(cqr)) {
+ goto retry;
+ /* remember that ERP was needed */
+ rc = 1;
+ /* skip processing for active cqr */
+ if (cqr->status != DASD_CQR_TERMINATED &&
+ cqr->status != DASD_CQR_NEED_ERP)
+ break;
}
}
+
+ /* start ERP requests in upper loop */
if (rc)
goto retry;