aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSwen Schillig <swen@vnet.ibm.com>2009-11-24 10:54:06 -0500
committerJames Bottomley <James.Bottomley@suse.de>2009-12-04 13:02:08 -0500
commit9eae07ef6bb5988163d8bb82cd952905db47b721 (patch)
tree97a7f5c98c760b6232e5cdb60e5da58414079981
parent6b183334c23969d52d4d9f775da554480d05ca4d (diff)
[SCSI] zfcp: Assign scheduled work to driver queue
The port_scan work was scheduled to the work_queue provided by the kernel. This resulted on SMP systems to a likely situation that more than one scan_work were processed in parallel. This is not required and openes the possibility of race conditions between the removal of invalid ports and the enqueue of just scanned ports. This patch synchronizes the scan_work tasks by scheduling them to adapter local work_queue. 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@suse.de>
-rw-r--r--drivers/s390/scsi/zfcp_aux.c2
-rw-r--r--drivers/s390/scsi/zfcp_erp.c2
-rw-r--r--drivers/s390/scsi/zfcp_ext.h3
-rw-r--r--drivers/s390/scsi/zfcp_fc.c25
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c2
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c7
6 files changed, 17 insertions, 24 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 6b94f8d0609c..107d3f2b6e94 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -522,7 +522,7 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
522 adapter->ccw_device = ccw_device; 522 adapter->ccw_device = ccw_device;
523 523
524 INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler); 524 INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
525 INIT_WORK(&adapter->scan_work, _zfcp_fc_scan_ports_later); 525 INIT_WORK(&adapter->scan_work, zfcp_fc_scan_ports);
526 526
527 if (zfcp_qdio_setup(adapter)) 527 if (zfcp_qdio_setup(adapter))
528 goto failed; 528 goto failed;
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 3454c2a3b6b1..b51a11a82e63 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -1197,7 +1197,7 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
1197 case ZFCP_ERP_ACTION_REOPEN_ADAPTER: 1197 case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
1198 if (result == ZFCP_ERP_SUCCEEDED) { 1198 if (result == ZFCP_ERP_SUCCEEDED) {
1199 register_service_level(&adapter->service_level); 1199 register_service_level(&adapter->service_level);
1200 schedule_work(&adapter->scan_work); 1200 queue_work(adapter->work_queue, &adapter->scan_work);
1201 } else 1201 } else
1202 unregister_service_level(&adapter->service_level); 1202 unregister_service_level(&adapter->service_level);
1203 kref_put(&adapter->ref, zfcp_adapter_release); 1203 kref_put(&adapter->ref, zfcp_adapter_release);
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 5f205f85e6f9..d372146af38d 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -94,8 +94,7 @@ extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *, char *,
94extern void zfcp_erp_timeout_handler(unsigned long); 94extern void zfcp_erp_timeout_handler(unsigned long);
95 95
96/* zfcp_fc.c */ 96/* zfcp_fc.c */
97extern int zfcp_fc_scan_ports(struct zfcp_adapter *); 97extern void zfcp_fc_scan_ports(struct work_struct *);
98extern void _zfcp_fc_scan_ports_later(struct work_struct *);
99extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *); 98extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *);
100extern void zfcp_fc_port_did_lookup(struct work_struct *); 99extern void zfcp_fc_port_did_lookup(struct work_struct *);
101extern void zfcp_fc_trigger_did_lookup(struct zfcp_port *); 100extern void zfcp_fc_trigger_did_lookup(struct zfcp_port *);
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 9252b65a13a5..7d6b3cadfb73 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -184,7 +184,7 @@ static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req)
184 range_mask = rscn_range_mask[fcp_rscn_element->addr_format]; 184 range_mask = rscn_range_mask[fcp_rscn_element->addr_format];
185 _zfcp_fc_incoming_rscn(fsf_req, range_mask, fcp_rscn_element); 185 _zfcp_fc_incoming_rscn(fsf_req, range_mask, fcp_rscn_element);
186 } 186 }
187 schedule_work(&fsf_req->adapter->scan_work); 187 queue_work(fsf_req->adapter->work_queue, &fsf_req->adapter->scan_work);
188} 188}
189 189
190static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn) 190static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn)
@@ -664,10 +664,12 @@ static int zfcp_fc_eval_gpn_ft(struct zfcp_gpn_ft *gpn_ft, int max_entries)
664 664
665/** 665/**
666 * zfcp_fc_scan_ports - scan remote ports and attach new ports 666 * zfcp_fc_scan_ports - scan remote ports and attach new ports
667 * @adapter: pointer to struct zfcp_adapter 667 * @work: reference to scheduled work
668 */ 668 */
669int zfcp_fc_scan_ports(struct zfcp_adapter *adapter) 669void zfcp_fc_scan_ports(struct work_struct *work)
670{ 670{
671 struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter,
672 scan_work);
671 int ret, i; 673 int ret, i;
672 struct zfcp_gpn_ft *gpn_ft; 674 struct zfcp_gpn_ft *gpn_ft;
673 int chain, max_entries, buf_num, max_bytes; 675 int chain, max_entries, buf_num, max_bytes;
@@ -679,17 +681,14 @@ int zfcp_fc_scan_ports(struct zfcp_adapter *adapter)
679 681
680 if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT && 682 if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT &&
681 fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV) 683 fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV)
682 return 0; 684 return;
683 685
684 ret = zfcp_fc_wka_port_get(&adapter->gs->ds); 686 if (zfcp_fc_wka_port_get(&adapter->gs->ds))
685 if (ret) 687 return;
686 return ret;
687 688
688 gpn_ft = zfcp_alloc_sg_env(buf_num); 689 gpn_ft = zfcp_alloc_sg_env(buf_num);
689 if (!gpn_ft) { 690 if (!gpn_ft)
690 ret = -ENOMEM;
691 goto out; 691 goto out;
692 }
693 692
694 for (i = 0; i < 3; i++) { 693 for (i = 0; i < 3; i++) {
695 ret = zfcp_fc_send_gpn_ft(gpn_ft, adapter, max_bytes); 694 ret = zfcp_fc_send_gpn_ft(gpn_ft, adapter, max_bytes);
@@ -704,15 +703,9 @@ int zfcp_fc_scan_ports(struct zfcp_adapter *adapter)
704 zfcp_free_sg_env(gpn_ft, buf_num); 703 zfcp_free_sg_env(gpn_ft, buf_num);
705out: 704out:
706 zfcp_fc_wka_port_put(&adapter->gs->ds); 705 zfcp_fc_wka_port_put(&adapter->gs->ds);
707 return ret;
708} 706}
709 707
710 708
711void _zfcp_fc_scan_ports_later(struct work_struct *work)
712{
713 zfcp_fc_scan_ports(container_of(work, struct zfcp_adapter, scan_work));
714}
715
716struct zfcp_els_fc_job { 709struct zfcp_els_fc_job {
717 struct zfcp_send_els els; 710 struct zfcp_send_els els;
718 struct fc_bsg_job *job; 711 struct fc_bsg_job *job;
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 5eb96052941a..b6f12c826b79 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -287,7 +287,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
287 zfcp_erp_adapter_access_changed(adapter, "fssrh_3", 287 zfcp_erp_adapter_access_changed(adapter, "fssrh_3",
288 req); 288 req);
289 if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS) 289 if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
290 schedule_work(&adapter->scan_work); 290 queue_work(adapter->work_queue, &adapter->scan_work);
291 break; 291 break;
292 case FSF_STATUS_READ_CFDC_UPDATED: 292 case FSF_STATUS_READ_CFDC_UPDATED:
293 zfcp_erp_adapter_access_changed(adapter, "fssrh_4", req); 293 zfcp_erp_adapter_access_changed(adapter, "fssrh_4", req);
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index 35e920b4fd8a..f539e006683c 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -184,15 +184,16 @@ static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
184{ 184{
185 struct ccw_device *cdev = to_ccwdev(dev); 185 struct ccw_device *cdev = to_ccwdev(dev);
186 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); 186 struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
187 int ret;
188 187
189 if (!adapter) 188 if (!adapter)
190 return -ENODEV; 189 return -ENODEV;
191 190
192 ret = zfcp_fc_scan_ports(adapter); 191 /* sync the user-space- with the kernel-invocation of scan_work */
192 queue_work(adapter->work_queue, &adapter->scan_work);
193 flush_work(&adapter->scan_work);
193 zfcp_ccw_adapter_put(adapter); 194 zfcp_ccw_adapter_put(adapter);
194 195
195 return ret ? ret : (ssize_t) count; 196 return (ssize_t) count;
196} 197}
197static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL, 198static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
198 zfcp_sysfs_port_rescan_store); 199 zfcp_sysfs_port_rescan_store);