Skip to content

Commit 10157b1

Browse files
Martin Wilckmartinkpetersen
authored andcommitted
scsi: core: alua: I/O errors for ALUA state transitions
When a host is configured with a few LUNs and I/O is running, injecting FC faults repeatedly leads to path recovery problems. The LUNs have 4 paths each and 3 of them come back active after say an FC fault which makes 2 of the paths go down, instead of all 4. This happens after several iterations of continuous FC faults. Reason here is that we're returning an I/O error whenever we're encountering sense code 06/04/0a (LOGICAL UNIT NOT ACCESSIBLE, ASYMMETRIC ACCESS STATE TRANSITION) instead of retrying. [mwilck: The original patch was developed by Rajashekhar M A and Hannes Reinecke. I moved the code to alua_check_sense() as suggested by Mike Christie [1]. Evan Milne had raised the question whether pg->state should be set to transitioning in the UA case [2]. I believe that doing this is correct. SCSI_ACCESS_STATE_TRANSITIONING by itself doesn't cause I/O errors. Our handler schedules an RTPG, which will only result in an I/O error condition if the transitioning timeout expires.] [1] https://lore.kernel.org/all/[email protected]/ [2] https://lore.kernel.org/all/CAGtn9r=kicnTDE2o7Gt5Y=yoidHYD7tG8XdMHEBJTBraVEoOCw@mail.gmail.com/ Co-developed-by: Rajashekhar M A <[email protected]> Co-developed-by: Hannes Reinecke <[email protected]> Signed-off-by: Hannes Reinecke <[email protected]> Signed-off-by: Martin Wilck <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Damien Le Moal <[email protected]> Reviewed-by: Christoph Hellwig <[email protected]> Reviewed-by: Mike Christie <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 9f365cb commit 10157b1

File tree

1 file changed

+22
-9
lines changed

1 file changed

+22
-9
lines changed

drivers/scsi/device_handler/scsi_dh_alua.c

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -414,28 +414,40 @@ static char print_alua_state(unsigned char state)
414414
}
415415
}
416416

417-
static enum scsi_disposition alua_check_sense(struct scsi_device *sdev,
418-
struct scsi_sense_hdr *sense_hdr)
417+
static void alua_handle_state_transition(struct scsi_device *sdev)
419418
{
420419
struct alua_dh_data *h = sdev->handler_data;
421420
struct alua_port_group *pg;
422421

422+
rcu_read_lock();
423+
pg = rcu_dereference(h->pg);
424+
if (pg)
425+
pg->state = SCSI_ACCESS_STATE_TRANSITIONING;
426+
rcu_read_unlock();
427+
alua_check(sdev, false);
428+
}
429+
430+
static enum scsi_disposition alua_check_sense(struct scsi_device *sdev,
431+
struct scsi_sense_hdr *sense_hdr)
432+
{
423433
switch (sense_hdr->sense_key) {
424434
case NOT_READY:
425435
if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0a) {
426436
/*
427437
* LUN Not Accessible - ALUA state transition
428438
*/
429-
rcu_read_lock();
430-
pg = rcu_dereference(h->pg);
431-
if (pg)
432-
pg->state = SCSI_ACCESS_STATE_TRANSITIONING;
433-
rcu_read_unlock();
434-
alua_check(sdev, false);
439+
alua_handle_state_transition(sdev);
435440
return NEEDS_RETRY;
436441
}
437442
break;
438443
case UNIT_ATTENTION:
444+
if (sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x0a) {
445+
/*
446+
* LUN Not Accessible - ALUA state transition
447+
*/
448+
alua_handle_state_transition(sdev);
449+
return NEEDS_RETRY;
450+
}
439451
if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00) {
440452
/*
441453
* Power On, Reset, or Bus Device Reset.
@@ -502,7 +514,8 @@ static int alua_tur(struct scsi_device *sdev)
502514

503515
retval = scsi_test_unit_ready(sdev, ALUA_FAILOVER_TIMEOUT * HZ,
504516
ALUA_FAILOVER_RETRIES, &sense_hdr);
505-
if (sense_hdr.sense_key == NOT_READY &&
517+
if ((sense_hdr.sense_key == NOT_READY ||
518+
sense_hdr.sense_key == UNIT_ATTENTION) &&
506519
sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x0a)
507520
return SCSI_DH_RETRY;
508521
else if (retval)

0 commit comments

Comments
 (0)