Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

s390/dasd: fix endless loop after read unit address configuration

After getting a storage server event that causes the DASD device driver
to update its unit address configuration during a device shutdown there is
the possibility of an endless loop in the device driver.

In the system log there will be ongoing DASD error messages with RC: -19.

The reason is that the loop starting the ruac request only terminates when
the retry counter is decreased to 0. But in the sleep_on function there are
early exit paths that do not decrease the retry counter.

Prevent an endless loop by handling those cases separately.

Remove the unnecessary do..while loop since the sleep_on function takes
care of retries by itself.

Fixes: 8e09f21574ea ("[S390] dasd: add hyper PAV support to DASD device driver, part 1")
Cc: stable@vger.kernel.org # 2.6.25+
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Stefan Haberland and committed by
Jens Axboe
41995342 0eb6ddfb

+16 -6
+16 -6
drivers/s390/block/dasd_alias.c
··· 383 383 char msg_format; 384 384 char msg_no; 385 385 386 + /* 387 + * intrc values ENODEV, ENOLINK and EPERM 388 + * will be optained from sleep_on to indicate that no 389 + * IO operation can be started 390 + */ 391 + if (cqr->intrc == -ENODEV) 392 + return 1; 393 + 394 + if (cqr->intrc == -ENOLINK) 395 + return 1; 396 + 397 + if (cqr->intrc == -EPERM) 398 + return 1; 399 + 386 400 sense = dasd_get_sense(&cqr->irb); 387 401 if (!sense) 388 402 return 0; ··· 461 447 lcu->flags &= ~NEED_UAC_UPDATE; 462 448 spin_unlock_irqrestore(&lcu->lock, flags); 463 449 464 - do { 465 - rc = dasd_sleep_on(cqr); 466 - if (rc && suborder_not_supported(cqr)) 467 - return -EOPNOTSUPP; 468 - } while (rc && (cqr->retries > 0)); 469 - if (rc) { 450 + rc = dasd_sleep_on(cqr); 451 + if (rc && !suborder_not_supported(cqr)) { 470 452 spin_lock_irqsave(&lcu->lock, flags); 471 453 lcu->flags |= NEED_UAC_UPDATE; 472 454 spin_unlock_irqrestore(&lcu->lock, flags);