]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | Subject: FC devloss callback not called when devloss timer fires |
2 | From: James Smart <james.smart@emulex.com> | |
3 | References: bnc#463289 | |
4 | ||
5 | When a SCSI target goes away for more than devloss timer the LLDD is not being | |
6 | called for dev_loss_tmo_callbk in the FC transport code. | |
7 | ||
8 | The correct fix is to call dev_loss_tmo_callbk() at the tail end of | |
9 | fc_timeout_deleted_rport() - but it has to be synchronized with the completion | |
10 | of fc_starget_delete() that is pushed to the work queue just prior to the | |
11 | routine exiting. | |
12 | ||
13 | Signed-off-by: James Smart <james.smart@emulex.com> | |
14 | Signed-off-by: Hannes Reinecke <hare@suse.de> | |
15 | ||
16 | --- | |
17 | ||
18 | drivers/scsi/scsi_transport_fc.c | 22 ++++++++++++++++++++-- | |
19 | include/scsi/scsi_transport_fc.h | 1 + | |
20 | 2 files changed, 21 insertions(+), 2 deletions(-) | |
21 | ||
22 | --- a/drivers/scsi/scsi_transport_fc.c 2008-12-19 13:50:10.000000000 -0500 | |
23 | +++ b/drivers/scsi/scsi_transport_fc.c 2008-12-19 13:50:06.000000000 -0500 | |
24 | @@ -2407,8 +2407,12 @@ fc_rport_final_delete(struct work_struct | |
25 | /* | |
26 | * Notify the driver that the rport is now dead. The LLDD will | |
27 | * also guarantee that any communication to the rport is terminated | |
28 | + * | |
29 | + * Avoid this call if we already called it when we preserved the | |
30 | + * rport for the binding. | |
31 | */ | |
32 | - if (i->f->dev_loss_tmo_callbk) | |
33 | + if (!(rport->flags & FC_RPORT_DEVLOSS_CALLBK_DONE) && | |
34 | + (i->f->dev_loss_tmo_callbk)) | |
35 | i->f->dev_loss_tmo_callbk(rport); | |
36 | ||
37 | transport_remove_device(dev); | |
38 | @@ -2647,7 +2651,8 @@ fc_remote_port_add(struct Scsi_Host *sho | |
39 | spin_lock_irqsave(shost->host_lock, flags); | |
40 | ||
41 | rport->flags &= ~(FC_RPORT_FAST_FAIL_TIMEDOUT | | |
42 | - FC_RPORT_DEVLOSS_PENDING); | |
43 | + FC_RPORT_DEVLOSS_PENDING | | |
44 | + FC_RPORT_DEVLOSS_CALLBK_DONE); | |
45 | ||
46 | /* if target, initiate a scan */ | |
47 | if (rport->scsi_target_id != -1) { | |
48 | @@ -2944,6 +2949,7 @@ fc_timeout_deleted_rport(struct work_str | |
49 | struct fc_rport *rport = | |
50 | container_of(work, struct fc_rport, dev_loss_work.work); | |
51 | struct Scsi_Host *shost = rport_to_shost(rport); | |
52 | + struct fc_internal *i = to_fc_internal(shost->transportt); | |
53 | struct fc_host_attrs *fc_host = shost_to_fc_host(shost); | |
54 | unsigned long flags; | |
55 | ||
56 | @@ -3030,6 +3036,8 @@ fc_timeout_deleted_rport(struct work_str | |
57 | break; | |
58 | } | |
59 | ||
60 | + rport->flags |= FC_RPORT_DEVLOSS_CALLBK_DONE; | |
61 | + | |
62 | /* | |
63 | * As this only occurs if the remote port (scsi target) | |
64 | * went away and didn't come back - we'll remove | |
65 | @@ -3039,8 +3047,18 @@ fc_timeout_deleted_rport(struct work_str | |
66 | ||
67 | scsi_target_unblock(&rport->dev); | |
68 | fc_queue_work(shost, &rport->stgt_delete_work); | |
69 | + | |
70 | + /* | |
71 | + * Notify the driver that the rport is now dead. The LLDD will | |
72 | + * also guarantee that any communication to the rport is terminated | |
73 | + * | |
74 | + * Note: we set the CALLBK_DONE flag above to correspond | |
75 | + */ | |
76 | + if (i->f->dev_loss_tmo_callbk) | |
77 | + i->f->dev_loss_tmo_callbk(rport); | |
78 | } | |
79 | ||
80 | + | |
81 | /** | |
82 | * fc_timeout_fail_rport_io - Timeout handler for a fast io failing on a disconnected SCSI target. | |
83 | * @work: rport to terminate io on. | |
84 | --- a/include/scsi/scsi_transport_fc.h 2008-12-19 11:20:30.000000000 -0500 | |
85 | +++ b/include/scsi/scsi_transport_fc.h 2008-12-19 11:21:24.000000000 -0500 | |
86 | @@ -358,6 +358,7 @@ struct fc_rport { /* aka fc_starget_attr | |
87 | #define FC_RPORT_DEVLOSS_PENDING 0x01 | |
88 | #define FC_RPORT_SCAN_PENDING 0x02 | |
89 | #define FC_RPORT_FAST_FAIL_TIMEDOUT 0x04 | |
90 | +#define FC_RPORT_DEVLOSS_CALLBK_DONE 0x08 | |
91 | ||
92 | #define dev_to_rport(d) \ | |
93 | container_of(d, struct fc_rport, dev) |