aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_fc.c
diff options
context:
space:
mode:
authorSwen Schillig <swen@vnet.ibm.com>2008-10-01 06:42:17 -0400
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-10-03 13:11:53 -0400
commit5ab944f97e09a3d52951fe903eed9a7b88d810b2 (patch)
tree266171323bd7c5dfc433efd70ca19aafc891598c /drivers/s390/scsi/zfcp_fc.c
parent44cc76f2d154aa24340354b4711a0fe7f8f08adc (diff)
[SCSI] zfcp: attach and release SAN nameserver port on demand
Changing the zfcp behaviour from always having the nameserver port open to an on-demand strategy. This strategy reduces the use of limited resources like port connections. The patch provides a common infrastructure which could be used for all WKA ports in future. Also reduce the number of nameserver lookups by changing the zfcp behaviour of always querying the nameserver for the corresponding destination ID of the remote port. If the destination ID has changed during the reopen process we will be informed and then trigger a nameserver query on demand. Signed-off-by: Swen Schillig <swen@vnet.ibm.com> Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/s390/scsi/zfcp_fc.c')
-rw-r--r--drivers/s390/scsi/zfcp_fc.c215
1 files changed, 151 insertions, 64 deletions
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 44456f74a12d..899e45b9e60b 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -39,6 +39,84 @@ struct zfcp_gpn_ft {
39 struct scatterlist sg_resp[ZFCP_GPN_FT_BUFFERS]; 39 struct scatterlist sg_resp[ZFCP_GPN_FT_BUFFERS];
40}; 40};
41 41
42struct zfcp_fc_ns_handler_data {
43 struct completion done;
44 void (*handler)(unsigned long);
45 unsigned long handler_data;
46};
47
48static int zfcp_wka_port_get(struct zfcp_wka_port *wka_port)
49{
50 if (mutex_lock_interruptible(&wka_port->mutex))
51 return -ERESTARTSYS;
52
53 if (wka_port->status != ZFCP_WKA_PORT_ONLINE) {
54 wka_port->status = ZFCP_WKA_PORT_OPENING;
55 if (zfcp_fsf_open_wka_port(wka_port))
56 wka_port->status = ZFCP_WKA_PORT_OFFLINE;
57 }
58
59 mutex_unlock(&wka_port->mutex);
60
61 wait_event_timeout(
62 wka_port->completion_wq,
63 wka_port->status == ZFCP_WKA_PORT_ONLINE ||
64 wka_port->status == ZFCP_WKA_PORT_OFFLINE,
65 HZ >> 1);
66
67 if (wka_port->status == ZFCP_WKA_PORT_ONLINE) {
68 atomic_inc(&wka_port->refcount);
69 return 0;
70 }
71 return -EIO;
72}
73
74static void zfcp_wka_port_offline(struct work_struct *work)
75{
76 struct delayed_work *dw = container_of(work, struct delayed_work, work);
77 struct zfcp_wka_port *wka_port =
78 container_of(dw, struct zfcp_wka_port, work);
79
80 wait_event(wka_port->completion_wq,
81 atomic_read(&wka_port->refcount) == 0);
82
83 mutex_lock(&wka_port->mutex);
84 if ((atomic_read(&wka_port->refcount) != 0) ||
85 (wka_port->status != ZFCP_WKA_PORT_ONLINE))
86 goto out;
87
88 wka_port->status = ZFCP_WKA_PORT_CLOSING;
89 if (zfcp_fsf_close_wka_port(wka_port)) {
90 wka_port->status = ZFCP_WKA_PORT_OFFLINE;
91 wake_up(&wka_port->completion_wq);
92 }
93out:
94 mutex_unlock(&wka_port->mutex);
95}
96
97static void zfcp_wka_port_put(struct zfcp_wka_port *wka_port)
98{
99 if (atomic_dec_return(&wka_port->refcount) != 0)
100 return;
101 /* wait 10 miliseconds, other reqs might pop in */
102 schedule_delayed_work(&wka_port->work, HZ / 100);
103}
104
105void zfcp_fc_nameserver_init(struct zfcp_adapter *adapter)
106{
107 struct zfcp_wka_port *wka_port = &adapter->nsp;
108
109 init_waitqueue_head(&wka_port->completion_wq);
110
111 wka_port->adapter = adapter;
112 wka_port->d_id = ZFCP_DID_DIRECTORY_SERVICE;
113
114 wka_port->status = ZFCP_WKA_PORT_OFFLINE;
115 atomic_set(&wka_port->refcount, 0);
116 mutex_init(&wka_port->mutex);
117 INIT_DELAYED_WORK(&wka_port->work, zfcp_wka_port_offline);
118}
119
42static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range, 120static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
43 struct fcp_rscn_element *elem) 121 struct fcp_rscn_element *elem)
44{ 122{
@@ -47,9 +125,6 @@ static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
47 125
48 read_lock_irqsave(&zfcp_data.config_lock, flags); 126 read_lock_irqsave(&zfcp_data.config_lock, flags);
49 list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) { 127 list_for_each_entry(port, &fsf_req->adapter->port_list_head, list) {
50 if ((atomic_read(&port->status) & ZFCP_STATUS_PORT_WKA) ==
51 ZFCP_STATUS_PORT_WKA)
52 continue;
53 /* FIXME: ZFCP_STATUS_PORT_DID_DID check is racy */ 128 /* FIXME: ZFCP_STATUS_PORT_DID_DID check is racy */
54 if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_DID_DID)) 129 if (!(atomic_read(&port->status) & ZFCP_STATUS_PORT_DID_DID))
55 /* Try to connect to unused ports anyway. */ 130 /* Try to connect to unused ports anyway. */
@@ -158,7 +233,18 @@ void zfcp_fc_incoming_els(struct zfcp_fsf_req *fsf_req)
158 zfcp_fc_incoming_rscn(fsf_req); 233 zfcp_fc_incoming_rscn(fsf_req);
159} 234}
160 235
161static void zfcp_ns_gid_pn_handler(unsigned long data) 236static void zfcp_fc_ns_handler(unsigned long data)
237{
238 struct zfcp_fc_ns_handler_data *compl_rec =
239 (struct zfcp_fc_ns_handler_data *) data;
240
241 if (compl_rec->handler)
242 compl_rec->handler(compl_rec->handler_data);
243
244 complete(&compl_rec->done);
245}
246
247static void zfcp_fc_ns_gid_pn_eval(unsigned long data)
162{ 248{
163 struct zfcp_gid_pn_data *gid_pn = (struct zfcp_gid_pn_data *) data; 249 struct zfcp_gid_pn_data *gid_pn = (struct zfcp_gid_pn_data *) data;
164 struct zfcp_send_ct *ct = &gid_pn->ct; 250 struct zfcp_send_ct *ct = &gid_pn->ct;
@@ -167,43 +253,31 @@ static void zfcp_ns_gid_pn_handler(unsigned long data)
167 struct zfcp_port *port = gid_pn->port; 253 struct zfcp_port *port = gid_pn->port;
168 254
169 if (ct->status) 255 if (ct->status)
170 goto out; 256 return;
171 if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) { 257 if (ct_iu_resp->header.cmd_rsp_code != ZFCP_CT_ACCEPT) {
172 atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status); 258 atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status);
173 goto out; 259 return;
174 } 260 }
175 /* paranoia */ 261 /* paranoia */
176 if (ct_iu_req->wwpn != port->wwpn) 262 if (ct_iu_req->wwpn != port->wwpn)
177 goto out; 263 return;
178 /* looks like a valid d_id */ 264 /* looks like a valid d_id */
179 port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK; 265 port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK;
180 atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status); 266 atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status);
181out:
182 mempool_free(gid_pn, port->adapter->pool.data_gid_pn);
183} 267}
184 268
185/** 269int static zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action,
186 * zfcp_fc_ns_gid_pn_request - initiate GID_PN nameserver request 270 struct zfcp_gid_pn_data *gid_pn)
187 * @erp_action: pointer to zfcp_erp_action where GID_PN request is needed
188 * return: -ENOMEM on error, 0 otherwise
189 */
190int zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action)
191{ 271{
192 int ret;
193 struct zfcp_gid_pn_data *gid_pn;
194 struct zfcp_adapter *adapter = erp_action->adapter; 272 struct zfcp_adapter *adapter = erp_action->adapter;
195 273 struct zfcp_fc_ns_handler_data compl_rec;
196 gid_pn = mempool_alloc(adapter->pool.data_gid_pn, GFP_ATOMIC); 274 int ret;
197 if (!gid_pn)
198 return -ENOMEM;
199
200 memset(gid_pn, 0, sizeof(*gid_pn));
201 275
202 /* setup parameters for send generic command */ 276 /* setup parameters for send generic command */
203 gid_pn->port = erp_action->port; 277 gid_pn->port = erp_action->port;
204 gid_pn->ct.port = adapter->nameserver_port; 278 gid_pn->ct.wka_port = &adapter->nsp;
205 gid_pn->ct.handler = zfcp_ns_gid_pn_handler; 279 gid_pn->ct.handler = zfcp_fc_ns_handler;
206 gid_pn->ct.handler_data = (unsigned long) gid_pn; 280 gid_pn->ct.handler_data = (unsigned long) &compl_rec;
207 gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT; 281 gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT;
208 gid_pn->ct.req = &gid_pn->req; 282 gid_pn->ct.req = &gid_pn->req;
209 gid_pn->ct.resp = &gid_pn->resp; 283 gid_pn->ct.resp = &gid_pn->resp;
@@ -223,10 +297,42 @@ int zfcp_fc_ns_gid_pn_request(struct zfcp_erp_action *erp_action)
223 gid_pn->ct_iu_req.header.max_res_size = ZFCP_CT_MAX_SIZE; 297 gid_pn->ct_iu_req.header.max_res_size = ZFCP_CT_MAX_SIZE;
224 gid_pn->ct_iu_req.wwpn = erp_action->port->wwpn; 298 gid_pn->ct_iu_req.wwpn = erp_action->port->wwpn;
225 299
300 init_completion(&compl_rec.done);
301 compl_rec.handler = zfcp_fc_ns_gid_pn_eval;
302 compl_rec.handler_data = (unsigned long) gid_pn;
226 ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.fsf_req_erp, 303 ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.fsf_req_erp,
227 erp_action); 304 erp_action);
305 if (!ret)
306 wait_for_completion(&compl_rec.done);
307 return ret;
308}
309
310/**
311 * zfcp_fc_ns_gid_pn_request - initiate GID_PN nameserver request
312 * @erp_action: pointer to zfcp_erp_action where GID_PN request is needed
313 * return: -ENOMEM on error, 0 otherwise
314 */
315int zfcp_fc_ns_gid_pn(struct zfcp_erp_action *erp_action)
316{
317 int ret;
318 struct zfcp_gid_pn_data *gid_pn;
319 struct zfcp_adapter *adapter = erp_action->adapter;
320
321 gid_pn = mempool_alloc(adapter->pool.data_gid_pn, GFP_ATOMIC);
322 if (!gid_pn)
323 return -ENOMEM;
324
325 memset(gid_pn, 0, sizeof(*gid_pn));
326
327 ret = zfcp_wka_port_get(&adapter->nsp);
228 if (ret) 328 if (ret)
229 mempool_free(gid_pn, adapter->pool.data_gid_pn); 329 goto out;
330
331 ret = zfcp_fc_ns_gid_pn_request(erp_action, gid_pn);
332
333 zfcp_wka_port_put(&adapter->nsp);
334out:
335 mempool_free(gid_pn, adapter->pool.data_gid_pn);
230 return ret; 336 return ret;
231} 337}
232 338
@@ -339,30 +445,6 @@ void zfcp_test_link(struct zfcp_port *port)
339 zfcp_erp_port_forced_reopen(port, 0, 65, NULL); 445 zfcp_erp_port_forced_reopen(port, 0, 65, NULL);
340} 446}
341 447
342static int zfcp_scan_get_nameserver(struct zfcp_adapter *adapter)
343{
344 int ret;
345
346 if (!adapter->nameserver_port)
347 return -EINTR;
348
349 if (!(atomic_read(&adapter->nameserver_port->status) &
350 ZFCP_STATUS_COMMON_UNBLOCKED)) {
351 ret = zfcp_erp_port_reopen(adapter->nameserver_port, 0, 148,
352 NULL);
353 if (ret)
354 return ret;
355 zfcp_erp_wait(adapter);
356 }
357 return !(atomic_read(&adapter->nameserver_port->status) &
358 ZFCP_STATUS_COMMON_UNBLOCKED);
359}
360
361static void zfcp_gpn_ft_handler(unsigned long _done)
362{
363 complete((struct completion *)_done);
364}
365
366static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft) 448static void zfcp_free_sg_env(struct zfcp_gpn_ft *gpn_ft)
367{ 449{
368 struct scatterlist *sg = &gpn_ft->sg_req; 450 struct scatterlist *sg = &gpn_ft->sg_req;
@@ -404,7 +486,7 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
404{ 486{
405 struct zfcp_send_ct *ct = &gpn_ft->ct; 487 struct zfcp_send_ct *ct = &gpn_ft->ct;
406 struct ct_iu_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req); 488 struct ct_iu_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req);
407 struct completion done; 489 struct zfcp_fc_ns_handler_data compl_rec;
408 int ret; 490 int ret;
409 491
410 /* prepare CT IU for GPN_FT */ 492 /* prepare CT IU for GPN_FT */
@@ -421,19 +503,20 @@ static int zfcp_scan_issue_gpn_ft(struct zfcp_gpn_ft *gpn_ft,
421 req->fc4_type = ZFCP_CT_SCSI_FCP; 503 req->fc4_type = ZFCP_CT_SCSI_FCP;
422 504
423 /* prepare zfcp_send_ct */ 505 /* prepare zfcp_send_ct */
424 ct->port = adapter->nameserver_port; 506 ct->wka_port = &adapter->nsp;
425 ct->handler = zfcp_gpn_ft_handler; 507 ct->handler = zfcp_fc_ns_handler;
426 ct->handler_data = (unsigned long)&done; 508 ct->handler_data = (unsigned long)&compl_rec;
427 ct->timeout = 10; 509 ct->timeout = 10;
428 ct->req = &gpn_ft->sg_req; 510 ct->req = &gpn_ft->sg_req;
429 ct->resp = gpn_ft->sg_resp; 511 ct->resp = gpn_ft->sg_resp;
430 ct->req_count = 1; 512 ct->req_count = 1;
431 ct->resp_count = ZFCP_GPN_FT_BUFFERS; 513 ct->resp_count = ZFCP_GPN_FT_BUFFERS;
432 514
433 init_completion(&done); 515 init_completion(&compl_rec.done);
516 compl_rec.handler = NULL;
434 ret = zfcp_fsf_send_ct(ct, NULL, NULL); 517 ret = zfcp_fsf_send_ct(ct, NULL, NULL);
435 if (!ret) 518 if (!ret)
436 wait_for_completion(&done); 519 wait_for_completion(&compl_rec.done);
437 return ret; 520 return ret;
438} 521}
439 522
@@ -443,8 +526,6 @@ static void zfcp_validate_port(struct zfcp_port *port)
443 526
444 atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status); 527 atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status);
445 528
446 if (port == adapter->nameserver_port)
447 return;
448 if ((port->supported_classes != 0) || (port->units != 0)) { 529 if ((port->supported_classes != 0) || (port->units != 0)) {
449 zfcp_port_put(port); 530 zfcp_port_put(port);
450 return; 531 return;
@@ -461,7 +542,7 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft)
461 struct scatterlist *sg = gpn_ft->sg_resp; 542 struct scatterlist *sg = gpn_ft->sg_resp;
462 struct ct_hdr *hdr = sg_virt(sg); 543 struct ct_hdr *hdr = sg_virt(sg);
463 struct gpn_ft_resp_acc *acc = sg_virt(sg); 544 struct gpn_ft_resp_acc *acc = sg_virt(sg);
464 struct zfcp_adapter *adapter = ct->port->adapter; 545 struct zfcp_adapter *adapter = ct->wka_port->adapter;
465 struct zfcp_port *port, *tmp; 546 struct zfcp_port *port, *tmp;
466 u32 d_id; 547 u32 d_id;
467 int ret = 0, x, last = 0; 548 int ret = 0, x, last = 0;
@@ -491,6 +572,9 @@ static int zfcp_scan_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft)
491 d_id = acc->port_id[0] << 16 | acc->port_id[1] << 8 | 572 d_id = acc->port_id[0] << 16 | acc->port_id[1] << 8 |
492 acc->port_id[2]; 573 acc->port_id[2];
493 574
575 /* don't attach ports with a well known address */
576 if ((d_id & ZFCP_DID_WKA) == ZFCP_DID_WKA)
577 continue;
494 /* skip the adapter's port and known remote ports */ 578 /* skip the adapter's port and known remote ports */
495 if (acc->wwpn == fc_host_port_name(adapter->scsi_host)) 579 if (acc->wwpn == fc_host_port_name(adapter->scsi_host))
496 continue; 580 continue;
@@ -529,13 +613,15 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
529 if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT) 613 if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT)
530 return 0; 614 return 0;
531 615
532 ret = zfcp_scan_get_nameserver(adapter); 616 ret = zfcp_wka_port_get(&adapter->nsp);
533 if (ret) 617 if (ret)
534 return ret; 618 return ret;
535 619
536 gpn_ft = zfcp_alloc_sg_env(); 620 gpn_ft = zfcp_alloc_sg_env();
537 if (!gpn_ft) 621 if (!gpn_ft) {
538 return -ENOMEM; 622 ret = -ENOMEM;
623 goto out;
624 }
539 625
540 for (i = 0; i < 3; i++) { 626 for (i = 0; i < 3; i++) {
541 ret = zfcp_scan_issue_gpn_ft(gpn_ft, adapter); 627 ret = zfcp_scan_issue_gpn_ft(gpn_ft, adapter);
@@ -548,7 +634,8 @@ int zfcp_scan_ports(struct zfcp_adapter *adapter)
548 } 634 }
549 } 635 }
550 zfcp_free_sg_env(gpn_ft); 636 zfcp_free_sg_env(gpn_ft);
551 637out:
638 zfcp_wka_port_put(&adapter->nsp);
552 return ret; 639 return ret;
553} 640}
554 641