aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libfc/fc_exch.c
diff options
context:
space:
mode:
authorVasu Dev <vasu.dev@intel.com>2009-11-03 14:50:10 -0500
committerJames Bottomley <James.Bottomley@suse.de>2009-12-04 13:01:26 -0500
commit4ae1e19f251335a24ce6cd13f08b4af560ed8765 (patch)
tree2a22a5722e3e6740f9dfad1d59f92cac7229c988 /drivers/scsi/libfc/fc_exch.c
parent18fa11efc279c20af5eefff2bbe814ca067e51ae (diff)
[SCSI] libfc: fix an issue of pending exch/es after i/f destroyed or rmmod fcoe
All exches must be freed before its EM mempool destroyed in this case but currently some exches could be still pending in their scheduled delayed work after EM mempool is destroyed causing this issue discussed and reported in this latest email thread:- http://www.open-fcoe.org/pipermail/devel/2009-October/004788.html This patch fixes this issue by adding dedicated work queue thread fc_exch_workqueue for exch delayed work and then flush this work queue before destroying EM mempool. The cancel_delayed_work_sync cannot be called during final fc_exch_reset due to lport and exch locking ordering, so removes related comment block not relevant any more with this patch. Reported-by: Joe Eykholt <jeykholt@cisco.com> Signed-off-by: Vasu Dev <vasu.dev@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/libfc/fc_exch.c')
-rw-r--r--drivers/scsi/libfc/fc_exch.c16
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 0f45bb8521f1..19d711cb938c 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -38,6 +38,7 @@ u16 fc_cpu_mask; /* cpu mask for possible cpus */
38EXPORT_SYMBOL(fc_cpu_mask); 38EXPORT_SYMBOL(fc_cpu_mask);
39static u16 fc_cpu_order; /* 2's power to represent total possible cpus */ 39static u16 fc_cpu_order; /* 2's power to represent total possible cpus */
40static struct kmem_cache *fc_em_cachep; /* cache for exchanges */ 40static struct kmem_cache *fc_em_cachep; /* cache for exchanges */
41struct workqueue_struct *fc_exch_workqueue;
41 42
42/* 43/*
43 * Structure and function definitions for managing Fibre Channel Exchanges 44 * Structure and function definitions for managing Fibre Channel Exchanges
@@ -427,8 +428,8 @@ static inline void fc_exch_timer_set_locked(struct fc_exch *ep,
427 428
428 FC_EXCH_DBG(ep, "Exchange timer armed\n"); 429 FC_EXCH_DBG(ep, "Exchange timer armed\n");
429 430
430 if (schedule_delayed_work(&ep->timeout_work, 431 if (queue_delayed_work(fc_exch_workqueue, &ep->timeout_work,
431 msecs_to_jiffies(timer_msec))) 432 msecs_to_jiffies(timer_msec)))
432 fc_exch_hold(ep); /* hold for timer */ 433 fc_exch_hold(ep); /* hold for timer */
433} 434}
434 435
@@ -1619,12 +1620,6 @@ static void fc_exch_reset(struct fc_exch *ep)
1619 1620
1620 spin_lock_bh(&ep->ex_lock); 1621 spin_lock_bh(&ep->ex_lock);
1621 ep->state |= FC_EX_RST_CLEANUP; 1622 ep->state |= FC_EX_RST_CLEANUP;
1622 /*
1623 * we really want to call del_timer_sync, but cannot due
1624 * to the lport calling with the lport lock held (some resp
1625 * functions can also grab the lport lock which could cause
1626 * a deadlock).
1627 */
1628 if (cancel_delayed_work(&ep->timeout_work)) 1623 if (cancel_delayed_work(&ep->timeout_work))
1629 atomic_dec(&ep->ex_refcnt); /* drop hold for timer */ 1624 atomic_dec(&ep->ex_refcnt); /* drop hold for timer */
1630 resp = ep->resp; 1625 resp = ep->resp;
@@ -2203,6 +2198,7 @@ void fc_exch_mgr_free(struct fc_lport *lport)
2203{ 2198{
2204 struct fc_exch_mgr_anchor *ema, *next; 2199 struct fc_exch_mgr_anchor *ema, *next;
2205 2200
2201 flush_workqueue(fc_exch_workqueue);
2206 list_for_each_entry_safe(ema, next, &lport->ema_list, ema_list) 2202 list_for_each_entry_safe(ema, next, &lport->ema_list, ema_list)
2207 fc_exch_mgr_del(ema); 2203 fc_exch_mgr_del(ema);
2208} 2204}
@@ -2338,6 +2334,9 @@ int fc_setup_exch_mgr()
2338 } 2334 }
2339 fc_cpu_mask--; 2335 fc_cpu_mask--;
2340 2336
2337 fc_exch_workqueue = create_singlethread_workqueue("fc_exch_workqueue");
2338 if (!fc_exch_workqueue)
2339 return -ENOMEM;
2341 return 0; 2340 return 0;
2342} 2341}
2343 2342
@@ -2346,5 +2345,6 @@ int fc_setup_exch_mgr()
2346 */ 2345 */
2347void fc_destroy_exch_mgr() 2346void fc_destroy_exch_mgr()
2348{ 2347{
2348 destroy_workqueue(fc_exch_workqueue);
2349 kmem_cache_destroy(fc_em_cachep); 2349 kmem_cache_destroy(fc_em_cachep);
2350} 2350}