Skip to content

Commit ecf0c77

Browse files
sswenJames Bottomley
authored andcommitted
[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>
1 parent 0a55256 commit ecf0c77

File tree

8 files changed

+199
-200
lines changed

8 files changed

+199
-200
lines changed

drivers/s390/scsi/zfcp_aux.c

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,6 @@ static int __init zfcp_module_init(void)
187187
goto out_gid_cache;
188188

189189
mutex_init(&zfcp_data.config_mutex);
190-
rwlock_init(&zfcp_data.config_lock);
191190

192191
zfcp_data.scsi_transport_template =
193192
fc_attach_transport(&zfcp_transport_functions);
@@ -238,12 +237,18 @@ module_init(zfcp_module_init);
238237
*/
239238
struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun)
240239
{
240+
unsigned long flags;
241241
struct zfcp_unit *unit;
242242

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)
244245
if ((unit->fcp_lun == fcp_lun) &&
245-
!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_REMOVE))
246-
return unit;
246+
!(atomic_read(&unit->status) & ZFCP_STATUS_COMMON_REMOVE)) {
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);
247252
return NULL;
248253
}
249254

@@ -257,12 +262,18 @@ struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *port, u64 fcp_lun)
257262
struct zfcp_port *zfcp_get_port_by_wwpn(struct zfcp_adapter *adapter,
258263
u64 wwpn)
259264
{
265+
unsigned long flags;
260266
struct zfcp_port *port;
261267

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)
263270
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);
265274
return port;
275+
}
276+
read_unlock_irqrestore(&adapter->port_list_lock, flags);
266277
return NULL;
267278
}
268279

@@ -284,12 +295,11 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
284295
{
285296
struct zfcp_unit *unit;
286297

287-
read_lock_irq(&zfcp_data.config_lock);
288-
if (zfcp_get_unit_by_lun(port, fcp_lun)) {
289-
read_unlock_irq(&zfcp_data.config_lock);
298+
unit = zfcp_get_unit_by_lun(port, fcp_lun);
299+
if (unit) {
300+
zfcp_unit_put(unit);
290301
return ERR_PTR(-EINVAL);
291302
}
292-
read_unlock_irq(&zfcp_data.config_lock);
293303

294304
unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
295305
if (!unit)
@@ -335,13 +345,13 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
335345

336346
zfcp_unit_get(unit);
337347

338-
write_lock_irq(&zfcp_data.config_lock);
339-
list_add_tail(&unit->list, &port->unit_list_head);
348+
write_lock_irq(&port->unit_list_lock);
349+
list_add_tail(&unit->list, &port->unit_list);
350+
write_unlock_irq(&port->unit_list_lock);
351+
340352
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
341353
atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status);
342354

343-
write_unlock_irq(&zfcp_data.config_lock);
344-
345355
zfcp_port_get(port);
346356

347357
return unit;
@@ -356,11 +366,11 @@ struct zfcp_unit *zfcp_unit_enqueue(struct zfcp_port *port, u64 fcp_lun)
356366
*/
357367
void zfcp_unit_dequeue(struct zfcp_unit *unit)
358368
{
369+
struct zfcp_port *port = unit->port;
370+
359371
wait_event(unit->remove_wq, atomic_read(&unit->refcount) == 0);
360-
write_lock_irq(&zfcp_data.config_lock);
361-
list_del(&unit->list);
362-
write_unlock_irq(&zfcp_data.config_lock);
363-
zfcp_port_put(unit->port);
372+
list_del(&unit->list); /* no list locking required */
373+
zfcp_port_put(port);
364374
sysfs_remove_group(&unit->sysfs_device.kobj, &zfcp_sysfs_unit_attrs);
365375
device_unregister(&unit->sysfs_device);
366376
}
@@ -539,11 +549,13 @@ int zfcp_adapter_enqueue(struct ccw_device *ccw_device)
539549
if (zfcp_fc_gs_setup(adapter))
540550
goto generic_services_failed;
541551

552+
rwlock_init(&adapter->port_list_lock);
553+
INIT_LIST_HEAD(&adapter->port_list);
554+
542555
init_waitqueue_head(&adapter->remove_wq);
543556
init_waitqueue_head(&adapter->erp_ready_wq);
544557
init_waitqueue_head(&adapter->erp_done_wqh);
545558

546-
INIT_LIST_HEAD(&adapter->port_list_head);
547559
INIT_LIST_HEAD(&adapter->erp_ready_head);
548560
INIT_LIST_HEAD(&adapter->erp_running_head);
549561

@@ -650,19 +662,20 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
650662
{
651663
struct zfcp_port *port;
652664

653-
read_lock_irq(&zfcp_data.config_lock);
654-
if (zfcp_get_port_by_wwpn(adapter, wwpn)) {
655-
read_unlock_irq(&zfcp_data.config_lock);
656-
return ERR_PTR(-EINVAL);
665+
port = zfcp_get_port_by_wwpn(adapter, wwpn);
666+
if (port) {
667+
zfcp_port_put(port);
668+
return ERR_PTR(-EEXIST);
657669
}
658-
read_unlock_irq(&zfcp_data.config_lock);
659670

660671
port = kzalloc(sizeof(struct zfcp_port), GFP_KERNEL);
661672
if (!port)
662673
return ERR_PTR(-ENOMEM);
663674

675+
rwlock_init(&port->unit_list_lock);
676+
INIT_LIST_HEAD(&port->unit_list);
677+
664678
init_waitqueue_head(&port->remove_wq);
665-
INIT_LIST_HEAD(&port->unit_list_head);
666679
INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup);
667680
INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work);
668681
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,
698711

699712
zfcp_port_get(port);
700713

701-
write_lock_irq(&zfcp_data.config_lock);
702-
list_add_tail(&port->list, &adapter->port_list_head);
714+
write_lock_irq(&adapter->port_list_lock);
715+
list_add_tail(&port->list, &adapter->port_list);
716+
write_unlock_irq(&adapter->port_list_lock);
717+
703718
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
704719
atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &port->status);
705720

706-
write_unlock_irq(&zfcp_data.config_lock);
707-
708721
zfcp_adapter_get(adapter);
709722
return port;
710723
}
@@ -715,12 +728,11 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
715728
*/
716729
void zfcp_port_dequeue(struct zfcp_port *port)
717730
{
718-
write_lock_irq(&zfcp_data.config_lock);
719-
list_del(&port->list);
720-
write_unlock_irq(&zfcp_data.config_lock);
731+
struct zfcp_adapter *adapter = port->adapter;
732+
733+
list_del(&port->list); /* no list locking required here */
721734
wait_event(port->remove_wq, atomic_read(&port->refcount) == 0);
722-
cancel_work_sync(&port->rport_work); /* usually not necessary */
723-
zfcp_adapter_put(port->adapter);
735+
zfcp_adapter_put(adapter);
724736
sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs);
725737
device_unregister(&port->sysfs_device);
726738
}

drivers/s390/scsi/zfcp_ccw.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,29 +100,33 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
100100

101101
mutex_lock(&zfcp_data.config_mutex);
102102
adapter = dev_get_drvdata(&ccw_device->dev);
103-
if (!adapter)
104-
goto out;
105103
mutex_unlock(&zfcp_data.config_mutex);
106104

105+
if (!adapter)
106+
return;
107+
107108
cancel_work_sync(&adapter->scan_work);
108109

109110
mutex_lock(&zfcp_data.config_mutex);
110111

111112
/* this also removes the scsi devices, so call it first */
112113
zfcp_adapter_scsi_unregister(adapter);
113114

114-
write_lock_irq(&zfcp_data.config_lock);
115-
list_for_each_entry_safe(port, p, &adapter->port_list_head, list) {
116-
list_for_each_entry_safe(unit, u, &port->unit_list_head, list) {
117-
list_move(&unit->list, &unit_remove_lh);
115+
write_lock_irq(&adapter->port_list_lock);
116+
list_for_each_entry_safe(port, p, &adapter->port_list, list) {
117+
write_lock(&port->unit_list_lock);
118+
list_for_each_entry_safe(unit, u, &port->unit_list, list) {
118119
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE,
119120
&unit->status);
121+
list_move(&unit->list, &unit_remove_lh);
120122
}
121-
list_move(&port->list, &port_remove_lh);
123+
write_unlock(&port->unit_list_lock);
122124
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &port->status);
125+
list_move(&port->list, &port_remove_lh);
123126
}
124127
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
125-
write_unlock_irq(&zfcp_data.config_lock);
128+
write_unlock_irq(&adapter->port_list_lock);
129+
mutex_unlock(&zfcp_data.config_mutex);
126130

127131
list_for_each_entry_safe(port, p, &port_remove_lh, list) {
128132
list_for_each_entry_safe(unit, u, &unit_remove_lh, list)
@@ -131,9 +135,6 @@ static void zfcp_ccw_remove(struct ccw_device *ccw_device)
131135
}
132136
wait_event(adapter->remove_wq, atomic_read(&adapter->refcount) == 0);
133137
zfcp_adapter_dequeue(adapter);
134-
135-
out:
136-
mutex_unlock(&zfcp_data.config_mutex);
137138
}
138139

139140
/**

drivers/s390/scsi/zfcp_def.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,8 @@ struct zfcp_adapter {
461461
u32 hardware_version; /* of FCP channel */
462462
u16 timer_ticks; /* time int for a tick */
463463
struct Scsi_Host *scsi_host; /* Pointer to mid-layer */
464-
struct list_head port_list_head; /* remote port list */
464+
struct list_head port_list; /* remote port list */
465+
rwlock_t port_list_lock; /* port list lock */
465466
unsigned long req_no; /* unique FSF req number */
466467
struct list_head *req_list; /* list of pending reqs */
467468
spinlock_t req_list_lock; /* request list lock */
@@ -504,7 +505,8 @@ struct zfcp_port {
504505
wait_queue_head_t remove_wq; /* can be used to wait for
505506
refcount drop to zero */
506507
struct zfcp_adapter *adapter; /* adapter used to access port */
507-
struct list_head unit_list_head; /* head of logical unit list */
508+
struct list_head unit_list; /* head of logical unit list */
509+
rwlock_t unit_list_lock; /* unit list lock */
508510
atomic_t status; /* status of this remote port */
509511
u64 wwnn; /* WWNN if known */
510512
u64 wwpn; /* WWPN */
@@ -601,9 +603,6 @@ struct zfcp_fsf_req {
601603
struct zfcp_data {
602604
struct scsi_host_template scsi_host_template;
603605
struct scsi_transport_template *scsi_transport_template;
604-
rwlock_t config_lock; /* serialises changes
605-
to adapter/port/unit
606-
lists */
607606
struct mutex config_mutex;
608607
struct kmem_cache *gpn_ft_cache;
609608
struct kmem_cache *qtcb_cache;

0 commit comments

Comments
 (0)