diff options
author | Swen Schillig <swen@vnet.ibm.com> | 2009-11-24 10:53:58 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2009-12-04 13:02:01 -0500 |
commit | ecf0c7721b104c0ce9c8ca534c911f6310cf92a8 (patch) | |
tree | 639032b36bcbbe905c98c6f0b3b521dc2f0b1806 /drivers/s390/scsi/zfcp_aux.c | |
parent | 0a55256d158c18e4821c248a295b7f8f4423660f (diff) |
[SCSI] zfcp: Replace global config_lock with local list locks
The global config_lock was used to protect the configuration organized
in independent lists. It is not necessary to have a lock on driver
level for this purpose. This patch replaces the global config_lock
with a set of local list locks.
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>
Diffstat (limited to 'drivers/s390/scsi/zfcp_aux.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_aux.c | 80 |
1 files changed, 46 insertions, 34 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 2889e5f2dfd3..883e13948ace 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -187,7 +187,6 @@ static int __init zfcp_module_init(void) | |||
187 | goto out_gid_cache; | 187 | goto out_gid_cache; |
188 | 188 | ||
189 | mutex_init(&zfcp_data.config_mutex); | 189 | mutex_init(&zfcp_data.config_mutex); |
190 | rwlock_init(&zfcp_data.config_lock); | ||
191 | 190 | ||
192 | zfcp_data.scsi_transport_template = | 191 | zfcp_data.scsi_transport_template = |
193 | fc_attach_transport(&zfcp_transport_functions); | 192 | fc_attach_transport(&zfcp_transport_functions); |
@@ -238,12 +237,18 @@ module_init(zfcp_module_init); | |||
238 | */ | 237 | */ |
239 | struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun) | 238 | struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun) |
240 | { | 239 | { |
240 | unsigned long flags; | ||
241 | struct zfcp_unit *unit; | 241 | struct zfcp_unit *unit; |
242 | 242 | ||
243 | list_for_each_entry(unit, &port->unit_list_head, list) | 243 | read_lock_irqsave(&port->unit_list_lock, flags); |
244 | list_for_each_entry(unit, &port->unit_list, list) | ||
244 | if ((unit->fcp_lun == fcp_lun) && | 245 | if ((unit->fcp_lun == fcp_lun) && |
245 | !(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_REMOVE)) | 246 | !(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_REMOVE)) { |
246 | return unit; | 247 | zfcp_unit_get(unit); |
248 | read_unlock_irqrestore(&port->unit_list_lock, flags); | ||
249 | return unit; | ||
250 | } | ||
251 | read_unlock_irqrestore(&port->unit_list_lock, flags); | ||
247 | return NULL; | 252 | return NULL; |
248 | } | 253 | } |
249 | 254 | ||
@@ -257,12 +262,18 @@ struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun) | |||
257 | struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, | 262 | struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter, |
258 | u64 wwpn) | 263 | u64 wwpn) |
259 | { | 264 | { |
265 | unsigned long flags; | ||
260 | struct zfcp_port *port; | 266 | struct zfcp_port *port; |
261 | 267 | ||
262 | list_for_each_entry(port, &adapter->port_list_head, list) | 268 | read_lock_irqsave(&adapter->port_list_lock, flags); |
269 | list_for_each_entry(port, &adapter->port_list, list) | ||
263 | if ((port->wwpn == wwpn) && | 270 | if ((port->wwpn == wwpn) && |
264 | !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE)) | 271 | !(atomic_read(&port->status) & ZFCP_STATUS_COMMON_REMOVE)) { |
272 | zfcp_port_get(port); | ||
273 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | ||
265 | return port; | 274 | return port; |
275 | } | ||
276 | read_unlock_irqrestore(&adapter->port_list_lock, flags); | ||
266 | return NULL; | 277 | return NULL; |
267 | } | 278 | } |
268 | 279 | ||
@@ -284,12 +295,11 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) | |||
284 | { | 295 | { |
285 | struct zfcp_unit *unit; | 296 | struct zfcp_unit *unit; |
286 | 297 | ||
287 | read_lock_irq(&zfcp_data.config_lock); | 298 | unit = zfcp_get_unit_by_lun(port, fcp_lun); |
288 | if (zfcp_get_unit_by_lun(port, fcp_lun)) { | 299 | if (unit) { |
289 | read_unlock_irq(&zfcp_data.config_lock); | 300 | zfcp_unit_put(unit); |
290 | return ERR_PTR(-EINVAL); | 301 | return ERR_PTR(-EINVAL); |
291 | } | 302 | } |
292 | read_unlock_irq(&zfcp_data.config_lock); | ||
293 | 303 | ||
294 | unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); | 304 | unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); |
295 | if (!unit) | 305 | if (!unit) |
@@ -335,13 +345,13 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) | |||
335 | 345 | ||
336 | zfcp_unit_get(unit); | 346 | zfcp_unit_get(unit); |
337 | 347 | ||
338 | write_lock_irq(&zfcp_data.config_lock); | 348 | write_lock_irq(&port->unit_list_lock); |
339 | list_add_tail(&unit->list, &port->unit_list_head); | 349 | list_add_tail(&unit->list, &port->unit_list); |
350 | write_unlock_irq(&port->unit_list_lock); | ||
351 | |||
340 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); | 352 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); |
341 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status); | 353 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status); |
342 | 354 | ||
343 | write_unlock_irq(&zfcp_data.config_lock); | ||
344 | |||
345 | zfcp_port_get(port); | 355 | zfcp_port_get(port); |
346 | 356 | ||
347 | return unit; | 357 | return unit; |
@@ -356,11 +366,11 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun) | |||
356 | */ | 366 | */ |
357 | void zfcp_unit_dequeue(struct zfcp_unit *unit) | 367 | void zfcp_unit_dequeue(struct zfcp_unit *unit) |
358 | { | 368 | { |
369 | struct zfcp_port *port = unit->port; | ||
370 | |||
359 | wait_event(unit->remove_wq, atomic_read(&unit->refcount) == 0); | 371 | wait_event(unit->remove_wq, atomic_read(&unit->refcount) == 0); |
360 | write_lock_irq(&zfcp_data.config_lock); | 372 | list_del(&unit->list); /* no list locking required */ |
361 | list_del(&unit->list); | 373 | zfcp_port_put(port); |
362 | write_unlock_irq(&zfcp_data.config_lock); | ||
363 | zfcp_port_put(unit->port); | ||
364 | sysfs_remove_group(&unit->sysfs_device.kobj, &zfcp_sysfs_unit_attrs); | 374 | sysfs_remove_group(&unit->sysfs_device.kobj, &zfcp_sysfs_unit_attrs); |
365 | device_unregister(&unit->sysfs_device); | 375 | device_unregister(&unit->sysfs_device); |
366 | } | 376 | } |
@@ -539,11 +549,13 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
539 | if (zfcp_fc_gs_setup(adapter)) | 549 | if (zfcp_fc_gs_setup(adapter)) |
540 | goto generic_services_failed; | 550 | goto generic_services_failed; |
541 | 551 | ||
552 | rwlock_init(&adapter->port_list_lock); | ||
553 | INIT_LIST_HEAD(&adapter->port_list); | ||
554 | |||
542 | init_waitqueue_head(&adapter->remove_wq); | 555 | init_waitqueue_head(&adapter->remove_wq); |
543 | init_waitqueue_head(&adapter->erp_ready_wq); | 556 | init_waitqueue_head(&adapter->erp_ready_wq); |
544 | init_waitqueue_head(&adapter->erp_done_wqh); | 557 | init_waitqueue_head(&adapter->erp_done_wqh); |
545 | 558 | ||
546 | INIT_LIST_HEAD(&adapter->port_list_head); | ||
547 | INIT_LIST_HEAD(&adapter->erp_ready_head); | 559 | INIT_LIST_HEAD(&adapter->erp_ready_head); |
548 | INIT_LIST_HEAD(&adapter->erp_running_head); | 560 | INIT_LIST_HEAD(&adapter->erp_running_head); |
549 | 561 | ||
@@ -650,19 +662,20 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, | |||
650 | { | 662 | { |
651 | struct zfcp_port *port; | 663 | struct zfcp_port *port; |
652 | 664 | ||
653 | read_lock_irq(&zfcp_data.config_lock); | 665 | port = zfcp_get_port_by_wwpn(adapter, wwpn); |
654 | if (zfcp_get_port_by_wwpn(adapter, wwpn)) { | 666 | if (port) { |
655 | read_unlock_irq(&zfcp_data.config_lock); | 667 | zfcp_port_put(port); |
656 | return ERR_PTR(-EINVAL); | 668 | return ERR_PTR(-EEXIST); |
657 | } | 669 | } |
658 | read_unlock_irq(&zfcp_data.config_lock); | ||
659 | 670 | ||
660 | port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL); | 671 | port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL); |
661 | if (!port) | 672 | if (!port) |
662 | return ERR_PTR(-ENOMEM); | 673 | return ERR_PTR(-ENOMEM); |
663 | 674 | ||
675 | rwlock_init(&port->unit_list_lock); | ||
676 | INIT_LIST_HEAD(&port->unit_list); | ||
677 | |||
664 | init_waitqueue_head(&port->remove_wq); | 678 | init_waitqueue_head(&port->remove_wq); |
665 | INIT_LIST_HEAD(&port->unit_list_head); | ||
666 | INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup); | 679 | INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup); |
667 | INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work); | 680 | INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work); |
668 | INIT_WORK(&port->rport_work, zfcp_scsi_rport_work); | 681 | INIT_WORK(&port->rport_work, zfcp_scsi_rport_work); |
@@ -698,13 +711,13 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, | |||
698 | 711 | ||
699 | zfcp_port_get(port); | 712 | zfcp_port_get(port); |
700 | 713 | ||
701 | write_lock_irq(&zfcp_data.config_lock); | 714 | write_lock_irq(&adapter->port_list_lock); |
702 | list_add_tail(&port->list, &adapter->port_list_head); | 715 | list_add_tail(&port->list, &adapter->port_list); |
716 | write_unlock_irq(&adapter->port_list_lock); | ||
717 | |||
703 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); | 718 | atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status); |
704 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status); | 719 | atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status); |
705 | 720 | ||
706 | write_unlock_irq(&zfcp_data.config_lock); | ||
707 | |||
708 | zfcp_adapter_get(adapter); | 721 | zfcp_adapter_get(adapter); |
709 | return port; | 722 | return port; |
710 | } | 723 | } |
@@ -715,12 +728,11 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, | |||
715 | */ | 728 | */ |
716 | void zfcp_port_dequeue(struct zfcp_port *port) | 729 | void zfcp_port_dequeue(struct zfcp_port *port) |
717 | { | 730 | { |
718 | write_lock_irq(&zfcp_data.config_lock); | 731 | struct zfcp_adapter *adapter = port->adapter; |
719 | list_del(&port->list); | 732 | |
720 | write_unlock_irq(&zfcp_data.config_lock); | 733 | list_del(&port->list); /* no list locking required here */ |
721 | wait_event(port->remove_wq, atomic_read(&port->refcount) == 0); | 734 | wait_event(port->remove_wq, atomic_read(&port->refcount) == 0); |
722 | cancel_work_sync(&port->rport_work); /* usually not necessary */ | 735 | zfcp_adapter_put(adapter); |
723 | zfcp_adapter_put(port->adapter); | ||
724 | sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs); | 736 | sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs); |
725 | device_unregister(&port->sysfs_device); | 737 | device_unregister(&port->sysfs_device); |
726 | } | 738 | } |