Linux 3.11-rc3
[cris-mirror.git] / drivers / target / iscsi / iscsi_target_tq.c
blob81289520f96b3915bf1e4e8cfaf330ac27625566
1 /*******************************************************************************
2 * This file contains the iSCSI Login Thread and Thread Queue functions.
4 * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
6 * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
8 * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 ******************************************************************************/
21 #include <linux/kthread.h>
22 #include <linux/list.h>
23 #include <linux/bitmap.h>
25 #include "iscsi_target_core.h"
26 #include "iscsi_target_tq.h"
27 #include "iscsi_target.h"
29 static LIST_HEAD(active_ts_list);
30 static LIST_HEAD(inactive_ts_list);
31 static DEFINE_SPINLOCK(active_ts_lock);
32 static DEFINE_SPINLOCK(inactive_ts_lock);
33 static DEFINE_SPINLOCK(ts_bitmap_lock);
35 static void iscsi_add_ts_to_active_list(struct iscsi_thread_set *ts)
37 spin_lock(&active_ts_lock);
38 list_add_tail(&ts->ts_list, &active_ts_list);
39 iscsit_global->active_ts++;
40 spin_unlock(&active_ts_lock);
43 static void iscsi_add_ts_to_inactive_list(struct iscsi_thread_set *ts)
45 spin_lock(&inactive_ts_lock);
46 list_add_tail(&ts->ts_list, &inactive_ts_list);
47 iscsit_global->inactive_ts++;
48 spin_unlock(&inactive_ts_lock);
51 static void iscsi_del_ts_from_active_list(struct iscsi_thread_set *ts)
53 spin_lock(&active_ts_lock);
54 list_del(&ts->ts_list);
55 iscsit_global->active_ts--;
56 spin_unlock(&active_ts_lock);
59 static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void)
61 struct iscsi_thread_set *ts;
63 spin_lock(&inactive_ts_lock);
64 if (list_empty(&inactive_ts_list)) {
65 spin_unlock(&inactive_ts_lock);
66 return NULL;
69 ts = list_first_entry(&inactive_ts_list, struct iscsi_thread_set, ts_list);
71 list_del(&ts->ts_list);
72 iscsit_global->inactive_ts--;
73 spin_unlock(&inactive_ts_lock);
75 return ts;
78 int iscsi_allocate_thread_sets(u32 thread_pair_count)
80 int allocated_thread_pair_count = 0, i, thread_id;
81 struct iscsi_thread_set *ts = NULL;
83 for (i = 0; i < thread_pair_count; i++) {
84 ts = kzalloc(sizeof(struct iscsi_thread_set), GFP_KERNEL);
85 if (!ts) {
86 pr_err("Unable to allocate memory for"
87 " thread set.\n");
88 return allocated_thread_pair_count;
91 * Locate the next available regision in the thread_set_bitmap
93 spin_lock(&ts_bitmap_lock);
94 thread_id = bitmap_find_free_region(iscsit_global->ts_bitmap,
95 iscsit_global->ts_bitmap_count, get_order(1));
96 spin_unlock(&ts_bitmap_lock);
97 if (thread_id < 0) {
98 pr_err("bitmap_find_free_region() failed for"
99 " thread_set_bitmap\n");
100 kfree(ts);
101 return allocated_thread_pair_count;
104 ts->thread_id = thread_id;
105 ts->status = ISCSI_THREAD_SET_FREE;
106 INIT_LIST_HEAD(&ts->ts_list);
107 spin_lock_init(&ts->ts_state_lock);
108 init_completion(&ts->rx_post_start_comp);
109 init_completion(&ts->tx_post_start_comp);
110 init_completion(&ts->rx_restart_comp);
111 init_completion(&ts->tx_restart_comp);
112 init_completion(&ts->rx_start_comp);
113 init_completion(&ts->tx_start_comp);
115 ts->create_threads = 1;
116 ts->tx_thread = kthread_run(iscsi_target_tx_thread, ts, "%s",
117 ISCSI_TX_THREAD_NAME);
118 if (IS_ERR(ts->tx_thread)) {
119 dump_stack();
120 pr_err("Unable to start iscsi_target_tx_thread\n");
121 break;
124 ts->rx_thread = kthread_run(iscsi_target_rx_thread, ts, "%s",
125 ISCSI_RX_THREAD_NAME);
126 if (IS_ERR(ts->rx_thread)) {
127 kthread_stop(ts->tx_thread);
128 pr_err("Unable to start iscsi_target_rx_thread\n");
129 break;
131 ts->create_threads = 0;
133 iscsi_add_ts_to_inactive_list(ts);
134 allocated_thread_pair_count++;
137 pr_debug("Spawned %d thread set(s) (%d total threads).\n",
138 allocated_thread_pair_count, allocated_thread_pair_count * 2);
139 return allocated_thread_pair_count;
142 void iscsi_deallocate_thread_sets(void)
144 u32 released_count = 0;
145 struct iscsi_thread_set *ts = NULL;
147 while ((ts = iscsi_get_ts_from_inactive_list())) {
149 spin_lock_bh(&ts->ts_state_lock);
150 ts->status = ISCSI_THREAD_SET_DIE;
151 spin_unlock_bh(&ts->ts_state_lock);
153 if (ts->rx_thread) {
154 send_sig(SIGINT, ts->rx_thread, 1);
155 kthread_stop(ts->rx_thread);
157 if (ts->tx_thread) {
158 send_sig(SIGINT, ts->tx_thread, 1);
159 kthread_stop(ts->tx_thread);
162 * Release this thread_id in the thread_set_bitmap
164 spin_lock(&ts_bitmap_lock);
165 bitmap_release_region(iscsit_global->ts_bitmap,
166 ts->thread_id, get_order(1));
167 spin_unlock(&ts_bitmap_lock);
169 released_count++;
170 kfree(ts);
173 if (released_count)
174 pr_debug("Stopped %d thread set(s) (%d total threads)."
175 "\n", released_count, released_count * 2);
178 static void iscsi_deallocate_extra_thread_sets(void)
180 u32 orig_count, released_count = 0;
181 struct iscsi_thread_set *ts = NULL;
183 orig_count = TARGET_THREAD_SET_COUNT;
185 while ((iscsit_global->inactive_ts + 1) > orig_count) {
186 ts = iscsi_get_ts_from_inactive_list();
187 if (!ts)
188 break;
190 spin_lock_bh(&ts->ts_state_lock);
191 ts->status = ISCSI_THREAD_SET_DIE;
192 spin_unlock_bh(&ts->ts_state_lock);
194 if (ts->rx_thread) {
195 send_sig(SIGINT, ts->rx_thread, 1);
196 kthread_stop(ts->rx_thread);
198 if (ts->tx_thread) {
199 send_sig(SIGINT, ts->tx_thread, 1);
200 kthread_stop(ts->tx_thread);
203 * Release this thread_id in the thread_set_bitmap
205 spin_lock(&ts_bitmap_lock);
206 bitmap_release_region(iscsit_global->ts_bitmap,
207 ts->thread_id, get_order(1));
208 spin_unlock(&ts_bitmap_lock);
210 released_count++;
211 kfree(ts);
214 if (released_count) {
215 pr_debug("Stopped %d thread set(s) (%d total threads)."
216 "\n", released_count, released_count * 2);
220 void iscsi_activate_thread_set(struct iscsi_conn *conn, struct iscsi_thread_set *ts)
222 iscsi_add_ts_to_active_list(ts);
224 spin_lock_bh(&ts->ts_state_lock);
225 conn->thread_set = ts;
226 ts->conn = conn;
227 spin_unlock_bh(&ts->ts_state_lock);
229 * Start up the RX thread and wait on rx_post_start_comp. The RX
230 * Thread will then do the same for the TX Thread in
231 * iscsi_rx_thread_pre_handler().
233 complete(&ts->rx_start_comp);
234 wait_for_completion(&ts->rx_post_start_comp);
237 struct iscsi_thread_set *iscsi_get_thread_set(void)
239 int allocate_ts = 0;
240 struct completion comp;
241 struct iscsi_thread_set *ts = NULL;
243 * If no inactive thread set is available on the first call to
244 * iscsi_get_ts_from_inactive_list(), sleep for a second and
245 * try again. If still none are available after two attempts,
246 * allocate a set ourselves.
248 get_set:
249 ts = iscsi_get_ts_from_inactive_list();
250 if (!ts) {
251 if (allocate_ts == 2)
252 iscsi_allocate_thread_sets(1);
254 init_completion(&comp);
255 wait_for_completion_timeout(&comp, 1 * HZ);
257 allocate_ts++;
258 goto get_set;
261 ts->delay_inactive = 1;
262 ts->signal_sent = 0;
263 ts->thread_count = 2;
264 init_completion(&ts->rx_restart_comp);
265 init_completion(&ts->tx_restart_comp);
267 return ts;
270 void iscsi_set_thread_clear(struct iscsi_conn *conn, u8 thread_clear)
272 struct iscsi_thread_set *ts = NULL;
274 if (!conn->thread_set) {
275 pr_err("struct iscsi_conn->thread_set is NULL\n");
276 return;
278 ts = conn->thread_set;
280 spin_lock_bh(&ts->ts_state_lock);
281 ts->thread_clear &= ~thread_clear;
283 if ((thread_clear & ISCSI_CLEAR_RX_THREAD) &&
284 (ts->blocked_threads & ISCSI_BLOCK_RX_THREAD))
285 complete(&ts->rx_restart_comp);
286 else if ((thread_clear & ISCSI_CLEAR_TX_THREAD) &&
287 (ts->blocked_threads & ISCSI_BLOCK_TX_THREAD))
288 complete(&ts->tx_restart_comp);
289 spin_unlock_bh(&ts->ts_state_lock);
292 void iscsi_set_thread_set_signal(struct iscsi_conn *conn, u8 signal_sent)
294 struct iscsi_thread_set *ts = NULL;
296 if (!conn->thread_set) {
297 pr_err("struct iscsi_conn->thread_set is NULL\n");
298 return;
300 ts = conn->thread_set;
302 spin_lock_bh(&ts->ts_state_lock);
303 ts->signal_sent |= signal_sent;
304 spin_unlock_bh(&ts->ts_state_lock);
307 int iscsi_release_thread_set(struct iscsi_conn *conn)
309 int thread_called = 0;
310 struct iscsi_thread_set *ts = NULL;
312 if (!conn || !conn->thread_set) {
313 pr_err("connection or thread set pointer is NULL\n");
314 BUG();
316 ts = conn->thread_set;
318 spin_lock_bh(&ts->ts_state_lock);
319 ts->status = ISCSI_THREAD_SET_RESET;
321 if (!strncmp(current->comm, ISCSI_RX_THREAD_NAME,
322 strlen(ISCSI_RX_THREAD_NAME)))
323 thread_called = ISCSI_RX_THREAD;
324 else if (!strncmp(current->comm, ISCSI_TX_THREAD_NAME,
325 strlen(ISCSI_TX_THREAD_NAME)))
326 thread_called = ISCSI_TX_THREAD;
328 if (ts->rx_thread && (thread_called == ISCSI_TX_THREAD) &&
329 (ts->thread_clear & ISCSI_CLEAR_RX_THREAD)) {
331 if (!(ts->signal_sent & ISCSI_SIGNAL_RX_THREAD)) {
332 send_sig(SIGINT, ts->rx_thread, 1);
333 ts->signal_sent |= ISCSI_SIGNAL_RX_THREAD;
335 ts->blocked_threads |= ISCSI_BLOCK_RX_THREAD;
336 spin_unlock_bh(&ts->ts_state_lock);
337 wait_for_completion(&ts->rx_restart_comp);
338 spin_lock_bh(&ts->ts_state_lock);
339 ts->blocked_threads &= ~ISCSI_BLOCK_RX_THREAD;
341 if (ts->tx_thread && (thread_called == ISCSI_RX_THREAD) &&
342 (ts->thread_clear & ISCSI_CLEAR_TX_THREAD)) {
344 if (!(ts->signal_sent & ISCSI_SIGNAL_TX_THREAD)) {
345 send_sig(SIGINT, ts->tx_thread, 1);
346 ts->signal_sent |= ISCSI_SIGNAL_TX_THREAD;
348 ts->blocked_threads |= ISCSI_BLOCK_TX_THREAD;
349 spin_unlock_bh(&ts->ts_state_lock);
350 wait_for_completion(&ts->tx_restart_comp);
351 spin_lock_bh(&ts->ts_state_lock);
352 ts->blocked_threads &= ~ISCSI_BLOCK_TX_THREAD;
355 ts->conn = NULL;
356 ts->status = ISCSI_THREAD_SET_FREE;
357 spin_unlock_bh(&ts->ts_state_lock);
359 return 0;
362 int iscsi_thread_set_force_reinstatement(struct iscsi_conn *conn)
364 struct iscsi_thread_set *ts;
366 if (!conn->thread_set)
367 return -1;
368 ts = conn->thread_set;
370 spin_lock_bh(&ts->ts_state_lock);
371 if (ts->status != ISCSI_THREAD_SET_ACTIVE) {
372 spin_unlock_bh(&ts->ts_state_lock);
373 return -1;
376 if (ts->tx_thread && (!(ts->signal_sent & ISCSI_SIGNAL_TX_THREAD))) {
377 send_sig(SIGINT, ts->tx_thread, 1);
378 ts->signal_sent |= ISCSI_SIGNAL_TX_THREAD;
380 if (ts->rx_thread && (!(ts->signal_sent & ISCSI_SIGNAL_RX_THREAD))) {
381 send_sig(SIGINT, ts->rx_thread, 1);
382 ts->signal_sent |= ISCSI_SIGNAL_RX_THREAD;
384 spin_unlock_bh(&ts->ts_state_lock);
386 return 0;
389 static void iscsi_check_to_add_additional_sets(void)
391 int thread_sets_add;
393 spin_lock(&inactive_ts_lock);
394 thread_sets_add = iscsit_global->inactive_ts;
395 spin_unlock(&inactive_ts_lock);
396 if (thread_sets_add == 1)
397 iscsi_allocate_thread_sets(1);
400 static int iscsi_signal_thread_pre_handler(struct iscsi_thread_set *ts)
402 spin_lock_bh(&ts->ts_state_lock);
403 if ((ts->status == ISCSI_THREAD_SET_DIE) || signal_pending(current)) {
404 spin_unlock_bh(&ts->ts_state_lock);
405 return -1;
407 spin_unlock_bh(&ts->ts_state_lock);
409 return 0;
412 struct iscsi_conn *iscsi_rx_thread_pre_handler(struct iscsi_thread_set *ts)
414 int ret;
416 spin_lock_bh(&ts->ts_state_lock);
417 if (ts->create_threads) {
418 spin_unlock_bh(&ts->ts_state_lock);
419 goto sleep;
422 flush_signals(current);
424 if (ts->delay_inactive && (--ts->thread_count == 0)) {
425 spin_unlock_bh(&ts->ts_state_lock);
426 iscsi_del_ts_from_active_list(ts);
428 if (!iscsit_global->in_shutdown)
429 iscsi_deallocate_extra_thread_sets();
431 iscsi_add_ts_to_inactive_list(ts);
432 spin_lock_bh(&ts->ts_state_lock);
435 if ((ts->status == ISCSI_THREAD_SET_RESET) &&
436 (ts->thread_clear & ISCSI_CLEAR_RX_THREAD))
437 complete(&ts->rx_restart_comp);
439 ts->thread_clear &= ~ISCSI_CLEAR_RX_THREAD;
440 spin_unlock_bh(&ts->ts_state_lock);
441 sleep:
442 ret = wait_for_completion_interruptible(&ts->rx_start_comp);
443 if (ret != 0)
444 return NULL;
446 if (iscsi_signal_thread_pre_handler(ts) < 0)
447 return NULL;
449 if (!ts->conn) {
450 pr_err("struct iscsi_thread_set->conn is NULL for"
451 " thread_id: %d, going back to sleep\n", ts->thread_id);
452 goto sleep;
454 iscsi_check_to_add_additional_sets();
456 * The RX Thread starts up the TX Thread and sleeps.
458 ts->thread_clear |= ISCSI_CLEAR_RX_THREAD;
459 complete(&ts->tx_start_comp);
460 wait_for_completion(&ts->tx_post_start_comp);
462 return ts->conn;
465 struct iscsi_conn *iscsi_tx_thread_pre_handler(struct iscsi_thread_set *ts)
467 int ret;
469 spin_lock_bh(&ts->ts_state_lock);
470 if (ts->create_threads) {
471 spin_unlock_bh(&ts->ts_state_lock);
472 goto sleep;
475 flush_signals(current);
477 if (ts->delay_inactive && (--ts->thread_count == 0)) {
478 spin_unlock_bh(&ts->ts_state_lock);
479 iscsi_del_ts_from_active_list(ts);
481 if (!iscsit_global->in_shutdown)
482 iscsi_deallocate_extra_thread_sets();
484 iscsi_add_ts_to_inactive_list(ts);
485 spin_lock_bh(&ts->ts_state_lock);
487 if ((ts->status == ISCSI_THREAD_SET_RESET) &&
488 (ts->thread_clear & ISCSI_CLEAR_TX_THREAD))
489 complete(&ts->tx_restart_comp);
491 ts->thread_clear &= ~ISCSI_CLEAR_TX_THREAD;
492 spin_unlock_bh(&ts->ts_state_lock);
493 sleep:
494 ret = wait_for_completion_interruptible(&ts->tx_start_comp);
495 if (ret != 0)
496 return NULL;
498 if (iscsi_signal_thread_pre_handler(ts) < 0)
499 return NULL;
501 if (!ts->conn) {
502 pr_err("struct iscsi_thread_set->conn is NULL for "
503 " thread_id: %d, going back to sleep\n",
504 ts->thread_id);
505 goto sleep;
508 iscsi_check_to_add_additional_sets();
510 * From the TX thread, up the tx_post_start_comp that the RX Thread is
511 * sleeping on in iscsi_rx_thread_pre_handler(), then up the
512 * rx_post_start_comp that iscsi_activate_thread_set() is sleeping on.
514 ts->thread_clear |= ISCSI_CLEAR_TX_THREAD;
515 complete(&ts->tx_post_start_comp);
516 complete(&ts->rx_post_start_comp);
518 spin_lock_bh(&ts->ts_state_lock);
519 ts->status = ISCSI_THREAD_SET_ACTIVE;
520 spin_unlock_bh(&ts->ts_state_lock);
522 return ts->conn;
525 int iscsi_thread_set_init(void)
527 int size;
529 iscsit_global->ts_bitmap_count = ISCSI_TS_BITMAP_BITS;
531 size = BITS_TO_LONGS(iscsit_global->ts_bitmap_count) * sizeof(long);
532 iscsit_global->ts_bitmap = kzalloc(size, GFP_KERNEL);
533 if (!iscsit_global->ts_bitmap) {
534 pr_err("Unable to allocate iscsit_global->ts_bitmap\n");
535 return -ENOMEM;
538 return 0;
541 void iscsi_thread_set_free(void)
543 kfree(iscsit_global->ts_bitmap);