aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_transport_fc.c
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2007-05-24 19:04:44 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2007-05-26 12:47:58 -0400
commit9ef3e4a4527e1f65b8776287c6d4fd1fca5ba98f (patch)
tree21352d4d676ada59ec83aa39963ddf0423ff6a72 /drivers/scsi/scsi_transport_fc.c
parentbee4fe8e63ea1985f3955323dbc98b6d6bd5c6f8 (diff)
[SCSI] fc_transport: fix sysfs deadlock on vport delete
When the vport attribute "delete" is used to delete the vport, sysfs deadlocks waiting for the write to complete, which is waiting for the sysfs teardown to complete. Moved this effort to a work_q element. Took the opportunity to make some other cosmetic changes: - removed tabs in Doc file - replaced with expanded spaces - minor copyright text and author text updates - removed a bunch of trailing whitespace Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/scsi_transport_fc.c')
-rw-r--r--drivers/scsi/scsi_transport_fc.c59
1 files changed, 35 insertions, 24 deletions
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 217651468115..4953f0dca029 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -1,4 +1,4 @@
1/* 1/*
2 * FiberChannel transport specific attributes exported to sysfs. 2 * FiberChannel transport specific attributes exported to sysfs.
3 * 3 *
4 * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved. 4 * Copyright (c) 2003 Silicon Graphics, Inc. All rights reserved.
@@ -22,6 +22,7 @@
22 * Copyright (C) 2004-2007 James Smart, Emulex Corporation 22 * Copyright (C) 2004-2007 James Smart, Emulex Corporation
23 * Rewrite for host, target, device, and remote port attributes, 23 * Rewrite for host, target, device, and remote port attributes,
24 * statistics, and service functions... 24 * statistics, and service functions...
25 * Add vports, etc
25 * 26 *
26 */ 27 */
27#include <linux/module.h> 28#include <linux/module.h>
@@ -37,6 +38,7 @@
37#include "scsi_priv.h" 38#include "scsi_priv.h"
38 39
39static int fc_queue_work(struct Scsi_Host *, struct work_struct *); 40static int fc_queue_work(struct Scsi_Host *, struct work_struct *);
41static void fc_vport_sched_delete(struct work_struct *work);
40 42
41/* 43/*
42 * This is a temporary carrier for creating a vport. It will eventually 44 * This is a temporary carrier for creating a vport. It will eventually
@@ -377,7 +379,7 @@ static int fc_host_setup(struct transport_container *tc, struct device *dev,
377 struct Scsi_Host *shost = dev_to_shost(dev); 379 struct Scsi_Host *shost = dev_to_shost(dev);
378 struct fc_host_attrs *fc_host = shost_to_fc_host(shost); 380 struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
379 381
380 /* 382 /*
381 * Set default values easily detected by the midlayer as 383 * Set default values easily detected by the midlayer as
382 * failure cases. The scsi lldd is responsible for initializing 384 * failure cases. The scsi lldd is responsible for initializing
383 * all transport attributes to valid values per host. 385 * all transport attributes to valid values per host.
@@ -1198,12 +1200,9 @@ store_fc_vport_delete(struct class_device *cdev, const char *buf,
1198 size_t count) 1200 size_t count)
1199{ 1201{
1200 struct fc_vport *vport = transport_class_to_vport(cdev); 1202 struct fc_vport *vport = transport_class_to_vport(cdev);
1201 int stat; 1203 struct Scsi_Host *shost = vport_to_shost(vport);
1202
1203 stat = fc_vport_terminate(vport);
1204 if (stat)
1205 return stat;
1206 1204
1205 fc_queue_work(shost, &vport->vport_delete_work);
1207 return count; 1206 return count;
1208} 1207}
1209static FC_CLASS_DEVICE_ATTR(vport, vport_delete, S_IWUSR, 1208static FC_CLASS_DEVICE_ATTR(vport, vport_delete, S_IWUSR,
@@ -1996,7 +1995,7 @@ fc_attach_transport(struct fc_function_template *ft)
1996 i->t.eh_timed_out = fc_timed_out; 1995 i->t.eh_timed_out = fc_timed_out;
1997 1996
1998 i->t.user_scan = fc_user_scan; 1997 i->t.user_scan = fc_user_scan;
1999 1998
2000 /* 1999 /*
2001 * Setup SCSI Target Attributes. 2000 * Setup SCSI Target Attributes.
2002 */ 2001 */
@@ -2215,23 +2214,12 @@ fc_remove_host(struct Scsi_Host *shost)
2215 struct workqueue_struct *work_q; 2214 struct workqueue_struct *work_q;
2216 struct fc_host_attrs *fc_host = shost_to_fc_host(shost); 2215 struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
2217 unsigned long flags; 2216 unsigned long flags;
2218 int stat;
2219 2217
2220 spin_lock_irqsave(shost->host_lock, flags); 2218 spin_lock_irqsave(shost->host_lock, flags);
2221 2219
2222 /* Remove any vports */ 2220 /* Remove any vports */
2223 list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers) { 2221 list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers)
2224 spin_unlock_irqrestore(shost->host_lock, flags); 2222 fc_queue_work(shost, &vport->vport_delete_work);
2225 /* this must be called synchronously */
2226 stat = fc_vport_terminate(vport);
2227 spin_lock_irqsave(shost->host_lock, flags);
2228 if (stat)
2229 dev_printk(KERN_ERR, vport->dev.parent,
2230 "%s: %s could not be deleted created via "
2231 "shost%d channel %d\n", __FUNCTION__,
2232 vport->dev.bus_id, vport->shost->host_no,
2233 vport->channel);
2234 }
2235 2223
2236 /* Remove any remote ports */ 2224 /* Remove any remote ports */
2237 list_for_each_entry_safe(rport, next_rport, 2225 list_for_each_entry_safe(rport, next_rport,
@@ -2308,7 +2296,7 @@ fc_rport_final_delete(struct work_struct *work)
2308 unsigned long flags; 2296 unsigned long flags;
2309 2297
2310 /* 2298 /*
2311 * if a scan is pending, flush the SCSI Host work_q so that 2299 * if a scan is pending, flush the SCSI Host work_q so that
2312 * that we can reclaim the rport scan work element. 2300 * that we can reclaim the rport scan work element.
2313 */ 2301 */
2314 if (rport->flags & FC_RPORT_SCAN_PENDING) 2302 if (rport->flags & FC_RPORT_SCAN_PENDING)
@@ -2858,7 +2846,7 @@ EXPORT_SYMBOL(fc_remote_port_rolechg);
2858 * fc_timeout_deleted_rport - Timeout handler for a deleted remote port, 2846 * fc_timeout_deleted_rport - Timeout handler for a deleted remote port,
2859 * which we blocked, and has now failed to return 2847 * which we blocked, and has now failed to return
2860 * in the allotted time. 2848 * in the allotted time.
2861 * 2849 *
2862 * @work: rport target that failed to reappear in the allotted time. 2850 * @work: rport target that failed to reappear in the allotted time.
2863 **/ 2851 **/
2864static void 2852static void
@@ -3061,6 +3049,7 @@ fc_vport_create(struct Scsi_Host *shost, int channel, struct device *pdev,
3061 vport->shost = shost; 3049 vport->shost = shost;
3062 vport->channel = channel; 3050 vport->channel = channel;
3063 vport->flags = FC_VPORT_CREATING; 3051 vport->flags = FC_VPORT_CREATING;
3052 INIT_WORK(&vport->vport_delete_work, fc_vport_sched_delete);
3064 3053
3065 spin_lock_irqsave(shost->host_lock, flags); 3054 spin_lock_irqsave(shost->host_lock, flags);
3066 3055
@@ -3207,8 +3196,30 @@ fc_vport_terminate(struct fc_vport *vport)
3207} 3196}
3208EXPORT_SYMBOL(fc_vport_terminate); 3197EXPORT_SYMBOL(fc_vport_terminate);
3209 3198
3199/**
3200 * fc_vport_sched_delete - workq-based delete request for a vport
3201 *
3202 * @work: vport to be deleted.
3203 **/
3204static void
3205fc_vport_sched_delete(struct work_struct *work)
3206{
3207 struct fc_vport *vport =
3208 container_of(work, struct fc_vport, vport_delete_work);
3209 int stat;
3210
3211 stat = fc_vport_terminate(vport);
3212 if (stat)
3213 dev_printk(KERN_ERR, vport->dev.parent,
3214 "%s: %s could not be deleted created via "
3215 "shost%d channel %d - error %d\n", __FUNCTION__,
3216 vport->dev.bus_id, vport->shost->host_no,
3217 vport->channel, stat);
3218}
3219
3210 3220
3211MODULE_AUTHOR("Martin Hicks"); 3221/* Original Author: Martin Hicks */
3222MODULE_AUTHOR("James Smart");
3212MODULE_DESCRIPTION("FC Transport Attributes"); 3223MODULE_DESCRIPTION("FC Transport Attributes");
3213MODULE_LICENSE("GPL"); 3224MODULE_LICENSE("GPL");
3214 3225