]>
Commit | Line | Data |
---|---|---|
00e5a55c BS |
1 | From: Gerald Schaefer <geraldsc@de.ibm.com> |
2 | Subject: zfcp: Fix oops when port disappears | |
3 | References: bnc#487755,LTC#52844 | |
4 | ||
5 | Symptom: Kernel oops when port disappears. | |
6 | Problem: The zfcp_port might have been removed, while the FC | |
7 | fast_io_fail timer is still running and could trigger | |
8 | the terminate_rport_io callback. | |
9 | Solution: Set the pointer to the zfcp_port to NULL and check | |
10 | accordingly before using it. | |
11 | ||
12 | Acked-by: John Jolly <jjolly@suse.de> | |
13 | --- | |
14 | drivers/s390/scsi/zfcp_aux.c | 3 +-- | |
15 | drivers/s390/scsi/zfcp_fsf.c | 4 ++++ | |
16 | drivers/s390/scsi/zfcp_scsi.c | 25 +++++++++++++++++++------ | |
17 | 3 files changed, 24 insertions(+), 8 deletions(-) | |
18 | ||
19 | --- a/drivers/s390/scsi/zfcp_aux.c | |
20 | +++ b/drivers/s390/scsi/zfcp_aux.c | |
21 | @@ -677,8 +677,7 @@ void zfcp_port_dequeue(struct zfcp_port | |
22 | list_del(&port->list); | |
23 | write_unlock_irq(&zfcp_data.config_lock); | |
24 | if (port->rport) | |
25 | - fc_remote_port_delete(port->rport); | |
26 | - port->rport = NULL; | |
27 | + port->rport->dd_data = NULL; | |
28 | zfcp_adapter_put(port->adapter); | |
29 | sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs); | |
30 | device_unregister(&port->sysfs_device); | |
31 | --- a/drivers/s390/scsi/zfcp_fsf.c | |
32 | +++ b/drivers/s390/scsi/zfcp_fsf.c | |
33 | @@ -175,12 +175,16 @@ static void zfcp_fsf_link_down_info_eval | |
34 | struct fsf_link_down_info *link_down) | |
35 | { | |
36 | struct zfcp_adapter *adapter = req->adapter; | |
37 | + unsigned long flags; | |
38 | ||
39 | if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED) | |
40 | return; | |
41 | ||
42 | atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); | |
43 | + | |
44 | + read_lock_irqsave(&zfcp_data.config_lock, flags); | |
45 | zfcp_scsi_schedule_rports_block(adapter); | |
46 | + read_unlock_irqrestore(&zfcp_data.config_lock, flags); | |
47 | ||
48 | if (!link_down) | |
49 | goto out; | |
50 | --- a/drivers/s390/scsi/zfcp_scsi.c | |
51 | +++ b/drivers/s390/scsi/zfcp_scsi.c | |
52 | @@ -491,10 +491,12 @@ static void zfcp_set_rport_dev_loss_tmo( | |
53 | */ | |
54 | static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport) | |
55 | { | |
56 | - struct zfcp_port *port = rport->dd_data; | |
57 | + struct zfcp_port *port; | |
58 | ||
59 | write_lock_irq(&zfcp_data.config_lock); | |
60 | - port->rport = NULL; | |
61 | + port = rport->dd_data; | |
62 | + if (port) | |
63 | + port->rport = NULL; | |
64 | write_unlock_irq(&zfcp_data.config_lock); | |
65 | } | |
66 | ||
67 | @@ -508,9 +510,18 @@ static void zfcp_scsi_dev_loss_tmo_callb | |
68 | */ | |
69 | static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport) | |
70 | { | |
71 | - struct zfcp_port *port = rport->dd_data; | |
72 | + struct zfcp_port *port; | |
73 | ||
74 | - zfcp_erp_port_reopen(port, 0, 152, NULL); | |
75 | + write_lock_irq(&zfcp_data.config_lock); | |
76 | + port = rport->dd_data; | |
77 | + if (port) | |
78 | + zfcp_port_get(port); | |
79 | + write_unlock_irq(&zfcp_data.config_lock); | |
80 | + | |
81 | + if (port) { | |
82 | + zfcp_erp_port_reopen(port, 0, 152, NULL); | |
83 | + zfcp_port_put(port); | |
84 | + } | |
85 | } | |
86 | ||
87 | static void zfcp_scsi_rport_register(struct zfcp_port *port) | |
88 | @@ -539,8 +550,10 @@ static void zfcp_scsi_rport_register(str | |
89 | ||
90 | static void zfcp_scsi_rport_block(struct zfcp_port *port) | |
91 | { | |
92 | - if (port->rport) | |
93 | - fc_remote_port_delete(port->rport); | |
94 | + struct fc_rport *rport = port->rport; | |
95 | + | |
96 | + if (rport) | |
97 | + fc_remote_port_delete(rport); | |
98 | } | |
99 | ||
100 | void zfcp_scsi_schedule_rport_register(struct zfcp_port *port) |