Skip to content

Commit

Permalink
[SCSI] libfc: tune fc_exch_em_alloc() to be O(2)
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Hillf Danton authored and James Bottomley committed Dec 21, 2010
1 parent 8236554 commit 2034c19
Showing 1 changed file with 33 additions and 3 deletions.
36 changes: 33 additions & 3 deletions drivers/scsi/libfc/fc_exch.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,11 @@ struct workqueue_struct *fc_exch_workqueue;
struct fc_exch_pool {
u16 next_index;
u16 total_exches;

/* two cache of free slot in exch array */
u16 left;
u16 right;

spinlock_t lock;
struct list_head ex_list;
};
Expand Down Expand Up @@ -396,13 +401,23 @@ static inline void fc_exch_ptr_set(struct fc_exch_pool *pool, u16 index,
static void fc_exch_delete(struct fc_exch *ep)
{
struct fc_exch_pool *pool;
u16 index;

pool = ep->pool;
spin_lock_bh(&pool->lock);
WARN_ON(pool->total_exches <= 0);
pool->total_exches--;
fc_exch_ptr_set(pool, (ep->xid - ep->em->min_xid) >> fc_cpu_order,
NULL);

/* update cache of free slot */
index = (ep->xid - ep->em->min_xid) >> fc_cpu_order;
if (pool->left == FC_XID_UNKNOWN)
pool->left = index;
else if (pool->right == FC_XID_UNKNOWN)
pool->right = index;
else
pool->next_index = index;

fc_exch_ptr_set(pool, index, NULL);
list_del(&ep->ex_list);
spin_unlock_bh(&pool->lock);
fc_exch_release(ep); /* drop hold for exch in mp */
Expand Down Expand Up @@ -678,6 +693,19 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
pool = per_cpu_ptr(mp->pool, cpu);
spin_lock_bh(&pool->lock);
put_cpu();

/* peek cache of free slot */
if (pool->left != FC_XID_UNKNOWN) {
index = pool->left;
pool->left = FC_XID_UNKNOWN;
goto hit;
}
if (pool->right != FC_XID_UNKNOWN) {
index = pool->right;
pool->right = FC_XID_UNKNOWN;
goto hit;
}

index = pool->next_index;
/* allocate new exch from pool */
while (fc_exch_ptr_get(pool, index)) {
Expand All @@ -686,7 +714,7 @@ static struct fc_exch *fc_exch_em_alloc(struct fc_lport *lport,
goto err;
}
pool->next_index = index == mp->pool_max_index ? 0 : index + 1;

hit:
fc_exch_hold(ep); /* hold for exch in mp */
spin_lock_init(&ep->ex_lock);
/*
Expand Down Expand Up @@ -2180,6 +2208,8 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lport,
goto free_mempool;
for_each_possible_cpu(cpu) {
pool = per_cpu_ptr(mp->pool, cpu);
pool->left = FC_XID_UNKNOWN;
pool->right = FC_XID_UNKNOWN;
spin_lock_init(&pool->lock);
INIT_LIST_HEAD(&pool->ex_list);
}
Expand Down

0 comments on commit 2034c19

Please sign in to comment.