]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.arch/s390-10-05-zfcp_remote_port_handling.patch
Updated xen patches taken from suse.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.arch / s390-10-05-zfcp_remote_port_handling.patch
1 From: Gerald Schaefer <geraldsc@de.ibm.com>
2 Subject: zfcp: Block remote ports (rports) early
3 References: bnc#482818,LTC#51961
4
5 Symptom: On path failover, the SCSI error recovery can set
6 SCSI devices offline.
7 Problem: For path failover to work correctly, the FC rports
8 in the Linux kernel have to be in the state BLOCKED.
9 This prevents SCSI timeouts from triggering the SCSI
10 error recovery.
11 Solution: On any problem (local link, remote port or any type
12 of error recovery) set the FC rports to BLOCKED early.
13
14 Acked-by: John Jolly <jjolly@suse.de>
15 ---
16 drivers/s390/scsi/zfcp_aux.c | 2
17 drivers/s390/scsi/zfcp_dbf.c | 1
18 drivers/s390/scsi/zfcp_def.h | 2
19 drivers/s390/scsi/zfcp_erp.c | 48 ++---------------
20 drivers/s390/scsi/zfcp_ext.h | 4 +
21 drivers/s390/scsi/zfcp_fc.c | 20 ++++++-
22 drivers/s390/scsi/zfcp_fsf.c | 1
23 drivers/s390/scsi/zfcp_scsi.c | 117 +++++++++++++++++++++++++++++++++++++++++-
24 8 files changed, 149 insertions(+), 46 deletions(-)
25
26 --- a/drivers/s390/scsi/zfcp_aux.c
27 +++ b/drivers/s390/scsi/zfcp_aux.c
28 @@ -612,10 +612,12 @@ struct zfcp_port *zfcp_port_enqueue(stru
29 INIT_LIST_HEAD(&port->unit_list_head);
30 INIT_WORK(&port->gid_pn_work, zfcp_erp_port_strategy_open_lookup);
31 INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work);
32 + INIT_WORK(&port->rport_work, zfcp_scsi_rport_work);
33
34 port->adapter = adapter;
35 port->d_id = d_id;
36 port->wwpn = wwpn;
37 + port->rport_task = RPORT_NONE;
38
39 /* mark port unusable as long as sysfs registration is not complete */
40 atomic_set_mask(status | ZFCP_STATUS_COMMON_REMOVE, &port->status);
41 --- a/drivers/s390/scsi/zfcp_dbf.c
42 +++ b/drivers/s390/scsi/zfcp_dbf.c
43 @@ -644,6 +644,7 @@ static const char *zfcp_rec_dbf_ids[] =
44 [149] = "port scan",
45 [150] = "ptp attach",
46 [151] = "port validation failed",
47 + [152] = "term rport io",
48 };
49
50 static int zfcp_rec_dbf_view_format(debug_info_t *id, struct debug_view *view,
51 --- a/drivers/s390/scsi/zfcp_def.h
52 +++ b/drivers/s390/scsi/zfcp_def.h
53 @@ -540,6 +540,8 @@ struct zfcp_port {
54 u32 supported_classes;
55 struct work_struct gid_pn_work;
56 struct work_struct test_link_work;
57 + struct work_struct rport_work;
58 + enum { RPORT_NONE, RPORT_ADD, RPORT_DEL } rport_task;
59 };
60
61 struct zfcp_unit {
62 --- a/drivers/s390/scsi/zfcp_erp.c
63 +++ b/drivers/s390/scsi/zfcp_erp.c
64 @@ -239,6 +239,7 @@ static int _zfcp_erp_adapter_reopen(stru
65 int clear_mask, u8 id, void *ref)
66 {
67 zfcp_erp_adapter_block(adapter, clear_mask);
68 + zfcp_scsi_schedule_rports_block(adapter);
69
70 /* ensure propagation of failed status to new devices */
71 if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
72 @@ -319,6 +320,7 @@ static void _zfcp_erp_port_forced_reopen
73 int clear, u8 id, void *ref)
74 {
75 zfcp_erp_port_block(port, clear);
76 + zfcp_scsi_schedule_rport_block(port);
77
78 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
79 return;
80 @@ -350,6 +352,7 @@ static int _zfcp_erp_port_reopen(struct
81 void *ref)
82 {
83 zfcp_erp_port_block(port, clear);
84 + zfcp_scsi_schedule_rport_block(port);
85
86 if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
87 /* ensure propagation of failed status to new devices */
88 @@ -1218,37 +1221,6 @@ static void zfcp_erp_schedule_work(struc
89 queue_work(zfcp_data.work_queue, &p->work);
90 }
91
92 -static void zfcp_erp_rport_register(struct zfcp_port *port)
93 -{
94 - struct fc_rport_identifiers ids;
95 - ids.node_name = port->wwnn;
96 - ids.port_name = port->wwpn;
97 - ids.port_id = port->d_id;
98 - ids.roles = FC_RPORT_ROLE_FCP_TARGET;
99 - port->rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids);
100 - if (!port->rport) {
101 - dev_err(&port->adapter->ccw_device->dev,
102 - "Registering port 0x%016Lx failed\n",
103 - (unsigned long long)port->wwpn);
104 - return;
105 - }
106 -
107 - scsi_target_unblock(&port->rport->dev);
108 - port->rport->maxframe_size = port->maxframe_size;
109 - port->rport->supported_classes = port->supported_classes;
110 -}
111 -
112 -static void zfcp_erp_rports_del(struct zfcp_adapter *adapter)
113 -{
114 - struct zfcp_port *port;
115 - list_for_each_entry(port, &adapter->port_list_head, list) {
116 - if (!port->rport)
117 - continue;
118 - fc_remote_port_delete(port->rport);
119 - port->rport = NULL;
120 - }
121 -}
122 -
123 static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
124 {
125 struct zfcp_adapter *adapter = act->adapter;
126 @@ -1257,8 +1229,8 @@ static void zfcp_erp_action_cleanup(stru
127
128 switch (act->action) {
129 case ZFCP_ERP_ACTION_REOPEN_UNIT:
130 - if ((result == ZFCP_ERP_SUCCEEDED) &&
131 - !unit->device && port->rport) {
132 + flush_work(&port->rport_work);
133 + if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) {
134 atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED,
135 &unit->status);
136 if (!(atomic_read(&unit->status) &
137 @@ -1274,18 +1246,12 @@ static void zfcp_erp_action_cleanup(stru
138 zfcp_port_put(port);
139 return;
140 }
141 - if ((result == ZFCP_ERP_SUCCEEDED) && !port->rport)
142 - zfcp_erp_rport_register(port);
143 - if ((result != ZFCP_ERP_SUCCEEDED) && port->rport) {
144 - fc_remote_port_delete(port->rport);
145 - port->rport = NULL;
146 - }
147 + if (result == ZFCP_ERP_SUCCEEDED)
148 + zfcp_scsi_schedule_rport_register(port);
149 zfcp_port_put(port);
150 break;
151
152 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
153 - if (result != ZFCP_ERP_SUCCEEDED)
154 - zfcp_erp_rports_del(adapter);
155 zfcp_adapter_put(adapter);
156 break;
157 }
158 --- a/drivers/s390/scsi/zfcp_ext.h
159 +++ b/drivers/s390/scsi/zfcp_ext.h
160 @@ -154,6 +154,10 @@ extern int zfcp_adapter_scsi_register(st
161 extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *);
162 extern char *zfcp_get_fcp_sns_info_ptr(struct fcp_rsp_iu *);
163 extern struct fc_function_template zfcp_transport_functions;
164 +extern void zfcp_scsi_rport_work(struct work_struct *);
165 +extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *);
166 +extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *);
167 +extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *);
168
169 /* zfcp_sysfs.c */
170 extern struct attribute_group zfcp_sysfs_unit_attrs;
171 --- a/drivers/s390/scsi/zfcp_fc.c
172 +++ b/drivers/s390/scsi/zfcp_fc.c
173 @@ -370,9 +370,14 @@ static void zfcp_fc_adisc_handler(unsign
174 port->wwnn = ls_adisc->wwnn;
175
176 if ((port->wwpn != ls_adisc->wwpn) ||
177 - !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN))
178 + !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)) {
179 zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED, 64,
180 NULL);
181 + goto out;
182 + }
183 +
184 + /* port is good, unblock rport without going through erp */
185 + zfcp_scsi_schedule_rport_register(port);
186
187 out:
188 zfcp_port_put(port);
189 @@ -417,14 +422,23 @@ void zfcp_fc_link_test_work(struct work_
190 container_of(work, struct zfcp_port, test_link_work);
191 int retval;
192
193 + if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_UNBLOCKED)) {
194 + zfcp_port_put(port);
195 + return; /* port erp is running and will update rport status */
196 + }
197 +
198 + zfcp_port_get(port);
199 + port->rport_task = RPORT_DEL;
200 + zfcp_scsi_rport_work(&port->rport_work);
201 +
202 retval = zfcp_fc_adisc(port);
203 if (retval == 0)
204 return;
205
206 /* send of ADISC was not possible */
207 + zfcp_erp_port_forced_reopen(port, 0, 65, NULL);
208 +
209 zfcp_port_put(port);
210 - if (retval != -EBUSY)
211 - zfcp_erp_port_forced_reopen(port, 0, 65, NULL);
212 }
213
214 /**
215 --- a/drivers/s390/scsi/zfcp_fsf.c
216 +++ b/drivers/s390/scsi/zfcp_fsf.c
217 @@ -180,6 +180,7 @@ static void zfcp_fsf_link_down_info_eval
218 return;
219
220 atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
221 + zfcp_scsi_schedule_rports_block(adapter);
222
223 if (!link_down)
224 goto out;
225 --- a/drivers/s390/scsi/zfcp_scsi.c
226 +++ b/drivers/s390/scsi/zfcp_scsi.c
227 @@ -57,8 +57,8 @@ static int zfcp_scsi_queuecommand(struct
228 {
229 struct zfcp_unit *unit;
230 struct zfcp_adapter *adapter;
231 - int status;
232 - int ret;
233 + int status, scsi_result, ret;
234 + struct fc_rport *rport = starget_to_rport(scsi_target(scpnt->device));
235
236 /* reset the status for this request */
237 scpnt->result = 0;
238 @@ -80,6 +80,14 @@ static int zfcp_scsi_queuecommand(struct
239 return 0;
240 }
241
242 + scsi_result = fc_remote_port_chkready(rport);
243 + if (unlikely(scsi_result)) {
244 + scpnt->result = scsi_result;
245 + zfcp_scsi_dbf_event_result("fail", 4, adapter, scpnt, NULL);
246 + scpnt->scsi_done(scpnt);
247 + return 0;
248 + }
249 +
250 status = atomic_read(&unit->status);
251 if (unlikely((status & ZFCP_STATUS_COMMON_ERP_FAILED) ||
252 !(status & ZFCP_STATUS_COMMON_RUNNING))) {
253 @@ -478,6 +486,109 @@ static void zfcp_set_rport_dev_loss_tmo(
254 rport->dev_loss_tmo = timeout;
255 }
256
257 +/**
258 + * zfcp_scsi_dev_loss_tmo_callbk - Free any reference to rport
259 + * @rport: The rport that is about to be deleted.
260 + */
261 +static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport)
262 +{
263 + struct zfcp_port *port = rport->dd_data;
264 +
265 + write_lock_irq(&zfcp_data.config_lock);
266 + port->rport = NULL;
267 + write_unlock_irq(&zfcp_data.config_lock);
268 +}
269 +
270 +/**
271 + * zfcp_scsi_terminate_rport_io - Terminate all I/O on a rport
272 + * @rport: The FC rport where to teminate I/O
273 + *
274 + * Abort all pending SCSI commands for a port by closing the
275 + * port. Using a reopen for avoids a conflict with a shutdown
276 + * overwriting a reopen.
277 + */
278 +static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
279 +{
280 + struct zfcp_port *port = rport->dd_data;
281 +
282 + zfcp_erp_port_reopen(port, 0, 152, NULL);
283 +}
284 +
285 +static void zfcp_scsi_rport_register(struct zfcp_port *port)
286 +{
287 + struct fc_rport_identifiers ids;
288 + struct fc_rport *rport;
289 +
290 + ids.node_name = port->wwnn;
291 + ids.port_name = port->wwpn;
292 + ids.port_id = port->d_id;
293 + ids.roles = FC_RPORT_ROLE_FCP_TARGET;
294 +
295 + rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids);
296 + if (!rport) {
297 + dev_err(&port->adapter->ccw_device->dev,
298 + "Registering port 0x%016Lx failed\n",
299 + (unsigned long long)port->wwpn);
300 + return;
301 + }
302 +
303 + rport->dd_data = port;
304 + rport->maxframe_size = port->maxframe_size;
305 + rport->supported_classes = port->supported_classes;
306 + port->rport = rport;
307 +}
308 +
309 +static void zfcp_scsi_rport_block(struct zfcp_port *port)
310 +{
311 + if (port->rport)
312 + fc_remote_port_delete(port->rport);
313 +}
314 +
315 +void zfcp_scsi_schedule_rport_register(struct zfcp_port *port)
316 +{
317 + zfcp_port_get(port);
318 + port->rport_task = RPORT_ADD;
319 +
320 + if (!queue_work(zfcp_data.work_queue, &port->rport_work))
321 + zfcp_port_put(port);
322 +}
323 +
324 +void zfcp_scsi_schedule_rport_block(struct zfcp_port *port)
325 +{
326 + zfcp_port_get(port);
327 + port->rport_task = RPORT_DEL;
328 +
329 + if (!queue_work(zfcp_data.work_queue, &port->rport_work))
330 + zfcp_port_put(port);
331 +}
332 +
333 +void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *adapter)
334 +{
335 + struct zfcp_port *port;
336 +
337 + list_for_each_entry(port, &adapter->port_list_head, list)
338 + zfcp_scsi_schedule_rport_block(port);
339 +}
340 +
341 +void zfcp_scsi_rport_work(struct work_struct *work)
342 +{
343 + struct zfcp_port *port = container_of(work, struct zfcp_port,
344 + rport_work);
345 +
346 + while (port->rport_task) {
347 + if (port->rport_task == RPORT_ADD) {
348 + port->rport_task = RPORT_NONE;
349 + zfcp_scsi_rport_register(port);
350 + } else {
351 + port->rport_task = RPORT_NONE;
352 + zfcp_scsi_rport_block(port);
353 + }
354 + }
355 +
356 + zfcp_port_put(port);
357 +}
358 +
359 +
360 struct fc_function_template zfcp_transport_functions = {
361 .show_starget_port_id = 1,
362 .show_starget_port_name = 1,
363 @@ -496,6 +607,8 @@ struct fc_function_template zfcp_transpo
364 .reset_fc_host_stats = zfcp_reset_fc_host_stats,
365 .set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo,
366 .get_host_port_state = zfcp_get_host_port_state,
367 + .dev_loss_tmo_callbk = zfcp_scsi_dev_loss_tmo_callbk,
368 + .terminate_rport_io = zfcp_scsi_terminate_rport_io,
369 .show_host_port_state = 1,
370 /* no functions registered for following dynamic attributes but
371 directly set by LLDD */