aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorHillf Danton <dhillf@gmail.com>2010-11-30 19:18:17 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-12-21 13:24:19 -0500
commit2034c19ce8f8503aa14cb1e763fbfe60316aaa8e (patch)
treea041e219fe6342d6268d71581d94c02073f681f6 /drivers/scsi
parent8236554a27af870ecd1cd588d9558ccdc212037b (diff)
[SCSI] libfc: tune fc_exch_em_alloc() to be O(2)
For allocating new exch from pool, scanning for free slot in exch array fluctuates when exch pool is close to exhaustion. The fluctuation is smoothed, and the scan looks to be O(2). Signed-off-by: Hillf Danton <dhillf@gmail.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')
-rw-r--r--drivers/scsi/libfc/fc_exch.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index d0df1b2faf25..46973d6618d0 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -67,6 +67,11 @@ struct workqueue_struct *fc_exch_workqueue;
67struct fc_exch_pool { 67struct fc_exch_pool {
68 u16 next_index; 68 u16 next_index;
69 u16 total_exches; 69 u16 total_exches;
70
71 /* two cache of free slot in exch array */
72 u16 left;
73 u16 right;
74
70 spinlock_t lock; 75 spinlock_t lock;
71 struct list_head ex_list; 76 struct list_head ex_list;
72}; 77};
@@ -396,13 +401,23 @@ static inline void fc_exch_ptr_set(struct fc_exch_pool *pool, u16 index,
396static void fc_exch_delete(struct fc_exch *ep) 401static void fc_exch_delete(struct fc_exch *ep)
397{ 402{
398 struct fc_exch_pool *pool; 403 struct fc_exch_pool *pool;
404 u16 index;
399 405
400 pool = ep->pool; 406 pool = ep->pool;
401 spin_lock_bh(&pool->lock); 407 spin_lock_bh(&pool->lock);
402 WARN_ON(pool->total_exches <= 0); 408 WARN_ON(pool->total_exches <= 0);
403 pool->total_exches--; 409 pool->total_exches--;
404 fc_exch_ptr_set(pool, (ep->xid - ep->em->min_xid) >> fc_cpu_order, 410
405 NULL); 411 /* update cache of free slot */
412 index = (ep->xid - ep->em->min_xid) >> fc_cpu_order;
413 if (pool->left == FC_XID_UNKNOWN)
414 pool->left = index;
415 else if (pool->right == FC_XID_UNKNOWN)
416 pool->right = index;
417 else
418 pool->next_index = index;
419
420 fc_exch_ptr_set(pool, index, NULL);
406 list_del(&ep->ex_list); 421 list_del(&ep->ex_list);
407 spin_unlock_bh(&pool->lock); 422 spin_unlock_bh(&pool->lock);
408 fc_exch_release(ep); /* drop hold for exch in mp */ 423 fc_exch_release(ep); /* drop hold for exch in mp */
@@ -678,6 +693,19 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
678 pool = per_cpu_ptr(mp->pool, cpu); 693 pool = per_cpu_ptr(mp->pool, cpu);
679 spin_lock_bh(&pool->lock); 694 spin_lock_bh(&pool->lock);
680 put_cpu(); 695 put_cpu();
696
697 /* peek cache of free slot */
698 if (pool->left != FC_XID_UNKNOWN) {
699 index = pool->left;
700 pool->left = FC_XID_UNKNOWN;
701 goto hit;
702 }
703 if (pool->right != FC_XID_UNKNOWN) {
704 index = pool->right;
705 pool->right = FC_XID_UNKNOWN;
706 goto hit;
707 }
708
681 index = pool->next_index; 709 index = pool->next_index;
682 /* allocate new exch from pool */ 710 /* allocate new exch from pool */
683 while (fc_exch_ptr_get(pool, index)) { 711 while (fc_exch_ptr_get(pool, index)) {
@@ -686,7 +714,7 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
686 goto err; 714 goto err;
687 } 715 }
688 pool->next_index = index == mp->pool_max_index ? 0 : index + 1; 716 pool->next_index = index == mp->pool_max_index ? 0 : index + 1;
689 717hit:
690 fc_exch_hold(ep); /* hold for exch in mp */ 718 fc_exch_hold(ep); /* hold for exch in mp */
691 spin_lock_init(&ep->ex_lock); 719 spin_lock_init(&ep->ex_lock);
692 /* 720 /*
@@ -2180,6 +2208,8 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lport,
2180 goto free_mempool; 2208 goto free_mempool;
2181 for_each_possible_cpu(cpu) { 2209 for_each_possible_cpu(cpu) {
2182 pool = per_cpu_ptr(mp->pool, cpu); 2210 pool = per_cpu_ptr(mp->pool, cpu);
2211 pool->left = FC_XID_UNKNOWN;
2212 pool->right = FC_XID_UNKNOWN;
2183 spin_lock_init(&pool->lock); 2213 spin_lock_init(&pool->lock);
2184 INIT_LIST_HEAD(&pool->ex_list); 2214 INIT_LIST_HEAD(&pool->ex_list);
2185 } 2215 }