summaryrefslogtreecommitdiffstats
path: root/drivers/target
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2018-11-29 19:36:41 -0500
committerJens Axboe <axboe@kernel.dk>2018-11-30 16:48:04 -0500
commit5d2ee7122c73be6a3b6bfe90d237e8aed737cfaa (patch)
treeada2bd06a0523a6ab8a9eae652034e2b0cb7b996 /drivers/target
parentea86ea2cdced20057da4d2c32965c1219c238197 (diff)
sbitmap: optimize wakeup check
Even if we have no waiters on any of the sbitmap_queue wait states, we still have to loop every entry to check. We do this for every IO, so the cost adds up. Shift a bit of the cost to the slow path, when we actually have waiters. Wrap prepare_to_wait_exclusive() and finish_wait(), so we can maintain an internal count of how many are currently active. Then we can simply check this count in sbq_wake_ptr() and not have to loop if we don't have any sleepers. Convert the two users of sbitmap with waiting, blk-mq-tag and iSCSI. Reviewed-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/target')
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index 36b742932c72..86987da86dd6 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -150,24 +150,26 @@ void iscsit_free_r2ts_from_list(struct iscsi_cmd *cmd)
150static int iscsit_wait_for_tag(struct se_session *se_sess, int state, int *cpup) 150static int iscsit_wait_for_tag(struct se_session *se_sess, int state, int *cpup)
151{ 151{
152 int tag = -1; 152 int tag = -1;
153 DEFINE_WAIT(wait); 153 DEFINE_SBQ_WAIT(wait);
154 struct sbq_wait_state *ws; 154 struct sbq_wait_state *ws;
155 struct sbitmap_queue *sbq;
155 156
156 if (state == TASK_RUNNING) 157 if (state == TASK_RUNNING)
157 return tag; 158 return tag;
158 159
159 ws = &se_sess->sess_tag_pool.ws[0]; 160 sbq = &se_sess->sess_tag_pool;
161 ws = &sbq->ws[0];
160 for (;;) { 162 for (;;) {
161 prepare_to_wait_exclusive(&ws->wait, &wait, state); 163 sbitmap_prepare_to_wait(sbq, ws, &wait, state);
162 if (signal_pending_state(state, current)) 164 if (signal_pending_state(state, current))
163 break; 165 break;
164 tag = sbitmap_queue_get(&se_sess->sess_tag_pool, cpup); 166 tag = sbitmap_queue_get(sbq, cpup);
165 if (tag >= 0) 167 if (tag >= 0)
166 break; 168 break;
167 schedule(); 169 schedule();
168 } 170 }
169 171
170 finish_wait(&ws->wait, &wait); 172 sbitmap_finish_wait(sbq, ws, &wait);
171 return tag; 173 return tag;
172} 174}
173 175