iscsi-target: Drop problematic active_ts_list usage
[pandora-kernel.git] / drivers / target / iscsi / iscsi_target_tq.c
1 /*******************************************************************************
2  * This file contains the iSCSI Login Thread and Thread Queue functions.
3  *
4  * \u00a9 Copyright 2007-2011 RisingTide Systems LLC.
5  *
6  * Licensed to the Linux Foundation under the General Public License (GPL) version 2.
7  *
8  * Author: Nicholas A. Bellinger <nab@linux-iscsi.org>
9  *
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.
14  *
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  ******************************************************************************/
20
21 #include <linux/kthread.h>
22 #include <linux/list.h>
23 #include <linux/bitmap.h>
24
25 #include "iscsi_target_core.h"
26 #include "iscsi_target_tq.h"
27 #include "iscsi_target.h"
28
29 static LIST_HEAD(inactive_ts_list);
30 static DEFINE_SPINLOCK(inactive_ts_lock);
31 static DEFINE_SPINLOCK(ts_bitmap_lock);
32
33 extern void iscsi_add_ts_to_inactive_list(struct iscsi_thread_set *ts)
34 {
35         if (!list_empty(&ts->ts_list)) {
36                 WARN_ON(1);
37                 return;
38         }
39         spin_lock(&inactive_ts_lock);
40         list_add_tail(&ts->ts_list, &inactive_ts_list);
41         iscsit_global->inactive_ts++;
42         spin_unlock(&inactive_ts_lock);
43 }
44
45 static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void)
46 {
47         struct iscsi_thread_set *ts;
48
49         spin_lock(&inactive_ts_lock);
50         if (list_empty(&inactive_ts_list)) {
51                 spin_unlock(&inactive_ts_lock);
52                 return NULL;
53         }
54
55         list_for_each_entry(ts, &inactive_ts_list, ts_list)
56                 break;
57
58         list_del_init(&ts->ts_list);
59         iscsit_global->inactive_ts--;
60         spin_unlock(&inactive_ts_lock);
61
62         return ts;
63 }
64
65 extern int iscsi_allocate_thread_sets(u32 thread_pair_count)
66 {
67         int allocated_thread_pair_count = 0, i, thread_id;
68         struct iscsi_thread_set *ts = NULL;
69
70         for (i = 0; i < thread_pair_count; i++) {
71                 ts = kzalloc(sizeof(struct iscsi_thread_set), GFP_KERNEL);
72                 if (!ts) {
73                         pr_err("Unable to allocate memory for"
74                                         " thread set.\n");
75                         return allocated_thread_pair_count;
76                 }
77                 /*
78                  * Locate the next available regision in the thread_set_bitmap
79                  */
80                 spin_lock(&ts_bitmap_lock);
81                 thread_id = bitmap_find_free_region(iscsit_global->ts_bitmap,
82                                 iscsit_global->ts_bitmap_count, get_order(1));
83                 spin_unlock(&ts_bitmap_lock);
84                 if (thread_id < 0) {
85                         pr_err("bitmap_find_free_region() failed for"
86                                 " thread_set_bitmap\n");
87                         kfree(ts);
88                         return allocated_thread_pair_count;
89                 }
90
91                 ts->thread_id = thread_id;
92                 ts->status = ISCSI_THREAD_SET_FREE;
93                 INIT_LIST_HEAD(&ts->ts_list);
94                 spin_lock_init(&ts->ts_state_lock);
95                 init_completion(&ts->rx_post_start_comp);
96                 init_completion(&ts->tx_post_start_comp);
97                 init_completion(&ts->rx_restart_comp);
98                 init_completion(&ts->tx_restart_comp);
99                 init_completion(&ts->rx_start_comp);
100                 init_completion(&ts->tx_start_comp);
101
102                 ts->create_threads = 1;
103                 ts->tx_thread = kthread_run(iscsi_target_tx_thread, ts, "%s",
104                                         ISCSI_TX_THREAD_NAME);
105                 if (IS_ERR(ts->tx_thread)) {
106                         dump_stack();
107                         pr_err("Unable to start iscsi_target_tx_thread\n");
108                         break;
109                 }
110
111                 ts->rx_thread = kthread_run(iscsi_target_rx_thread, ts, "%s",
112                                         ISCSI_RX_THREAD_NAME);
113                 if (IS_ERR(ts->rx_thread)) {
114                         kthread_stop(ts->tx_thread);
115                         pr_err("Unable to start iscsi_target_rx_thread\n");
116                         break;
117                 }
118                 ts->create_threads = 0;
119
120                 iscsi_add_ts_to_inactive_list(ts);
121                 allocated_thread_pair_count++;
122         }
123
124         pr_debug("Spawned %d thread set(s) (%d total threads).\n",
125                 allocated_thread_pair_count, allocated_thread_pair_count * 2);
126         return allocated_thread_pair_count;
127 }
128
129 extern void iscsi_deallocate_thread_sets(void)
130 {
131         u32 released_count = 0;
132         struct iscsi_thread_set *ts = NULL;
133
134         while ((ts = iscsi_get_ts_from_inactive_list())) {
135
136                 spin_lock_bh(&ts->ts_state_lock);
137                 ts->status = ISCSI_THREAD_SET_DIE;
138                 spin_unlock_bh(&ts->ts_state_lock);
139
140                 if (ts->rx_thread) {
141                         send_sig(SIGINT, ts->rx_thread, 1);
142                         kthread_stop(ts->rx_thread);
143                 }
144                 if (ts->tx_thread) {
145                         send_sig(SIGINT, ts->tx_thread, 1);
146                         kthread_stop(ts->tx_thread);
147                 }
148                 /*
149                  * Release this thread_id in the thread_set_bitmap
150                  */
151                 spin_lock(&ts_bitmap_lock);
152                 bitmap_release_region(iscsit_global->ts_bitmap,
153                                 ts->thread_id, get_order(1));
154                 spin_unlock(&ts_bitmap_lock);
155
156                 released_count++;
157                 kfree(ts);
158         }
159
160         if (released_count)
161                 pr_debug("Stopped %d thread set(s) (%d total threads)."
162                         "\n", released_count, released_count * 2);
163 }
164
165 static void iscsi_deallocate_extra_thread_sets(void)
166 {
167         u32 orig_count, released_count = 0;
168         struct iscsi_thread_set *ts = NULL;
169
170         orig_count = TARGET_THREAD_SET_COUNT;
171
172         while ((iscsit_global->inactive_ts + 1) > orig_count) {
173                 ts = iscsi_get_ts_from_inactive_list();
174                 if (!ts)
175                         break;
176
177                 spin_lock_bh(&ts->ts_state_lock);
178                 ts->status = ISCSI_THREAD_SET_DIE;
179                 spin_unlock_bh(&ts->ts_state_lock);
180
181                 if (ts->rx_thread) {
182                         send_sig(SIGINT, ts->rx_thread, 1);
183                         kthread_stop(ts->rx_thread);
184                 }
185                 if (ts->tx_thread) {
186                         send_sig(SIGINT, ts->tx_thread, 1);
187                         kthread_stop(ts->tx_thread);
188                 }
189                 /*
190                  * Release this thread_id in the thread_set_bitmap
191                  */
192                 spin_lock(&ts_bitmap_lock);
193                 bitmap_release_region(iscsit_global->ts_bitmap,
194                                 ts->thread_id, get_order(1));
195                 spin_unlock(&ts_bitmap_lock);
196
197                 released_count++;
198                 kfree(ts);
199         }
200
201         if (released_count) {
202                 pr_debug("Stopped %d thread set(s) (%d total threads)."
203                         "\n", released_count, released_count * 2);
204         }
205 }
206
207 void iscsi_activate_thread_set(struct iscsi_conn *conn, struct iscsi_thread_set *ts)
208 {
209         spin_lock_bh(&ts->ts_state_lock);
210         conn->thread_set = ts;
211         ts->conn = conn;
212         spin_unlock_bh(&ts->ts_state_lock);
213         /*
214          * Start up the RX thread and wait on rx_post_start_comp.  The RX
215          * Thread will then do the same for the TX Thread in
216          * iscsi_rx_thread_pre_handler().
217          */
218         complete(&ts->rx_start_comp);
219         wait_for_completion(&ts->rx_post_start_comp);
220 }
221
222 struct iscsi_thread_set *iscsi_get_thread_set(void)
223 {
224         int allocate_ts = 0;
225         struct completion comp;
226         struct iscsi_thread_set *ts = NULL;
227         /*
228          * If no inactive thread set is available on the first call to
229          * iscsi_get_ts_from_inactive_list(), sleep for a second and
230          * try again.  If still none are available after two attempts,
231          * allocate a set ourselves.
232          */
233 get_set:
234         ts = iscsi_get_ts_from_inactive_list();
235         if (!ts) {
236                 if (allocate_ts == 2)
237                         iscsi_allocate_thread_sets(1);
238
239                 init_completion(&comp);
240                 wait_for_completion_timeout(&comp, 1 * HZ);
241
242                 allocate_ts++;
243                 goto get_set;
244         }
245
246         ts->delay_inactive = 1;
247         ts->signal_sent = 0;
248         ts->thread_count = 2;
249         init_completion(&ts->rx_restart_comp);
250         init_completion(&ts->tx_restart_comp);
251
252         return ts;
253 }
254
255 void iscsi_set_thread_clear(struct iscsi_conn *conn, u8 thread_clear)
256 {
257         struct iscsi_thread_set *ts = NULL;
258
259         if (!conn->thread_set) {
260                 pr_err("struct iscsi_conn->thread_set is NULL\n");
261                 return;
262         }
263         ts = conn->thread_set;
264
265         spin_lock_bh(&ts->ts_state_lock);
266         ts->thread_clear &= ~thread_clear;
267
268         if ((thread_clear & ISCSI_CLEAR_RX_THREAD) &&
269             (ts->blocked_threads & ISCSI_BLOCK_RX_THREAD))
270                 complete(&ts->rx_restart_comp);
271         else if ((thread_clear & ISCSI_CLEAR_TX_THREAD) &&
272                  (ts->blocked_threads & ISCSI_BLOCK_TX_THREAD))
273                 complete(&ts->tx_restart_comp);
274         spin_unlock_bh(&ts->ts_state_lock);
275 }
276
277 void iscsi_set_thread_set_signal(struct iscsi_conn *conn, u8 signal_sent)
278 {
279         struct iscsi_thread_set *ts = NULL;
280
281         if (!conn->thread_set) {
282                 pr_err("struct iscsi_conn->thread_set is NULL\n");
283                 return;
284         }
285         ts = conn->thread_set;
286
287         spin_lock_bh(&ts->ts_state_lock);
288         ts->signal_sent |= signal_sent;
289         spin_unlock_bh(&ts->ts_state_lock);
290 }
291
292 int iscsi_release_thread_set(struct iscsi_conn *conn)
293 {
294         int thread_called = 0;
295         struct iscsi_thread_set *ts = NULL;
296
297         if (!conn || !conn->thread_set) {
298                 pr_err("connection or thread set pointer is NULL\n");
299                 BUG();
300         }
301         ts = conn->thread_set;
302
303         spin_lock_bh(&ts->ts_state_lock);
304         ts->status = ISCSI_THREAD_SET_RESET;
305
306         if (!strncmp(current->comm, ISCSI_RX_THREAD_NAME,
307                         strlen(ISCSI_RX_THREAD_NAME)))
308                 thread_called = ISCSI_RX_THREAD;
309         else if (!strncmp(current->comm, ISCSI_TX_THREAD_NAME,
310                         strlen(ISCSI_TX_THREAD_NAME)))
311                 thread_called = ISCSI_TX_THREAD;
312
313         if (ts->rx_thread && (thread_called == ISCSI_TX_THREAD) &&
314            (ts->thread_clear & ISCSI_CLEAR_RX_THREAD)) {
315
316                 if (!(ts->signal_sent & ISCSI_SIGNAL_RX_THREAD)) {
317                         send_sig(SIGINT, ts->rx_thread, 1);
318                         ts->signal_sent |= ISCSI_SIGNAL_RX_THREAD;
319                 }
320                 ts->blocked_threads |= ISCSI_BLOCK_RX_THREAD;
321                 spin_unlock_bh(&ts->ts_state_lock);
322                 wait_for_completion(&ts->rx_restart_comp);
323                 spin_lock_bh(&ts->ts_state_lock);
324                 ts->blocked_threads &= ~ISCSI_BLOCK_RX_THREAD;
325         }
326         if (ts->tx_thread && (thread_called == ISCSI_RX_THREAD) &&
327            (ts->thread_clear & ISCSI_CLEAR_TX_THREAD)) {
328
329                 if (!(ts->signal_sent & ISCSI_SIGNAL_TX_THREAD)) {
330                         send_sig(SIGINT, ts->tx_thread, 1);
331                         ts->signal_sent |= ISCSI_SIGNAL_TX_THREAD;
332                 }
333                 ts->blocked_threads |= ISCSI_BLOCK_TX_THREAD;
334                 spin_unlock_bh(&ts->ts_state_lock);
335                 wait_for_completion(&ts->tx_restart_comp);
336                 spin_lock_bh(&ts->ts_state_lock);
337                 ts->blocked_threads &= ~ISCSI_BLOCK_TX_THREAD;
338         }
339
340         ts->conn = NULL;
341         ts->status = ISCSI_THREAD_SET_FREE;
342         spin_unlock_bh(&ts->ts_state_lock);
343
344         return 0;
345 }
346
347 int iscsi_thread_set_force_reinstatement(struct iscsi_conn *conn)
348 {
349         struct iscsi_thread_set *ts;
350
351         if (!conn->thread_set)
352                 return -1;
353         ts = conn->thread_set;
354
355         spin_lock_bh(&ts->ts_state_lock);
356         if (ts->status != ISCSI_THREAD_SET_ACTIVE) {
357                 spin_unlock_bh(&ts->ts_state_lock);
358                 return -1;
359         }
360
361         if (ts->tx_thread && (!(ts->signal_sent & ISCSI_SIGNAL_TX_THREAD))) {
362                 send_sig(SIGINT, ts->tx_thread, 1);
363                 ts->signal_sent |= ISCSI_SIGNAL_TX_THREAD;
364         }
365         if (ts->rx_thread && (!(ts->signal_sent & ISCSI_SIGNAL_RX_THREAD))) {
366                 send_sig(SIGINT, ts->rx_thread, 1);
367                 ts->signal_sent |= ISCSI_SIGNAL_RX_THREAD;
368         }
369         spin_unlock_bh(&ts->ts_state_lock);
370
371         return 0;
372 }
373
374 static void iscsi_check_to_add_additional_sets(void)
375 {
376         int thread_sets_add;
377
378         spin_lock(&inactive_ts_lock);
379         thread_sets_add = iscsit_global->inactive_ts;
380         spin_unlock(&inactive_ts_lock);
381         if (thread_sets_add == 1)
382                 iscsi_allocate_thread_sets(1);
383 }
384
385 static int iscsi_signal_thread_pre_handler(struct iscsi_thread_set *ts)
386 {
387         spin_lock_bh(&ts->ts_state_lock);
388         if ((ts->status == ISCSI_THREAD_SET_DIE) || signal_pending(current)) {
389                 spin_unlock_bh(&ts->ts_state_lock);
390                 return -1;
391         }
392         spin_unlock_bh(&ts->ts_state_lock);
393
394         return 0;
395 }
396
397 struct iscsi_conn *iscsi_rx_thread_pre_handler(struct iscsi_thread_set *ts)
398 {
399         int ret;
400
401         spin_lock_bh(&ts->ts_state_lock);
402         if (ts->create_threads) {
403                 spin_unlock_bh(&ts->ts_state_lock);
404                 goto sleep;
405         }
406
407         flush_signals(current);
408
409         if (ts->delay_inactive && (--ts->thread_count == 0)) {
410                 spin_unlock_bh(&ts->ts_state_lock);
411
412                 if (!iscsit_global->in_shutdown)
413                         iscsi_deallocate_extra_thread_sets();
414
415                 iscsi_add_ts_to_inactive_list(ts);
416                 spin_lock_bh(&ts->ts_state_lock);
417         }
418
419         if ((ts->status == ISCSI_THREAD_SET_RESET) &&
420             (ts->thread_clear & ISCSI_CLEAR_RX_THREAD))
421                 complete(&ts->rx_restart_comp);
422
423         ts->thread_clear &= ~ISCSI_CLEAR_RX_THREAD;
424         spin_unlock_bh(&ts->ts_state_lock);
425 sleep:
426         ret = wait_for_completion_interruptible(&ts->rx_start_comp);
427         if (ret != 0)
428                 return NULL;
429
430         if (iscsi_signal_thread_pre_handler(ts) < 0)
431                 return NULL;
432
433         if (!ts->conn) {
434                 pr_err("struct iscsi_thread_set->conn is NULL for"
435                         " thread_id: %d, going back to sleep\n", ts->thread_id);
436                 goto sleep;
437         }
438         iscsi_check_to_add_additional_sets();
439         /*
440          * The RX Thread starts up the TX Thread and sleeps.
441          */
442         ts->thread_clear |= ISCSI_CLEAR_RX_THREAD;
443         complete(&ts->tx_start_comp);
444         wait_for_completion(&ts->tx_post_start_comp);
445
446         return ts->conn;
447 }
448
449 struct iscsi_conn *iscsi_tx_thread_pre_handler(struct iscsi_thread_set *ts)
450 {
451         int ret;
452
453         spin_lock_bh(&ts->ts_state_lock);
454         if (ts->create_threads) {
455                 spin_unlock_bh(&ts->ts_state_lock);
456                 goto sleep;
457         }
458
459         flush_signals(current);
460
461         if (ts->delay_inactive && (--ts->thread_count == 0)) {
462                 spin_unlock_bh(&ts->ts_state_lock);
463
464                 if (!iscsit_global->in_shutdown)
465                         iscsi_deallocate_extra_thread_sets();
466
467                 iscsi_add_ts_to_inactive_list(ts);
468                 spin_lock_bh(&ts->ts_state_lock);
469         }
470         if ((ts->status == ISCSI_THREAD_SET_RESET) &&
471             (ts->thread_clear & ISCSI_CLEAR_TX_THREAD))
472                 complete(&ts->tx_restart_comp);
473
474         ts->thread_clear &= ~ISCSI_CLEAR_TX_THREAD;
475         spin_unlock_bh(&ts->ts_state_lock);
476 sleep:
477         ret = wait_for_completion_interruptible(&ts->tx_start_comp);
478         if (ret != 0)
479                 return NULL;
480
481         if (iscsi_signal_thread_pre_handler(ts) < 0)
482                 return NULL;
483
484         if (!ts->conn) {
485                 pr_err("struct iscsi_thread_set->conn is NULL for "
486                         " thread_id: %d, going back to sleep\n",
487                         ts->thread_id);
488                 goto sleep;
489         }
490
491         iscsi_check_to_add_additional_sets();
492         /*
493          * From the TX thread, up the tx_post_start_comp that the RX Thread is
494          * sleeping on in iscsi_rx_thread_pre_handler(), then up the
495          * rx_post_start_comp that iscsi_activate_thread_set() is sleeping on.
496          */
497         ts->thread_clear |= ISCSI_CLEAR_TX_THREAD;
498         complete(&ts->tx_post_start_comp);
499         complete(&ts->rx_post_start_comp);
500
501         spin_lock_bh(&ts->ts_state_lock);
502         ts->status = ISCSI_THREAD_SET_ACTIVE;
503         spin_unlock_bh(&ts->ts_state_lock);
504
505         return ts->conn;
506 }
507
508 int iscsi_thread_set_init(void)
509 {
510         int size;
511
512         iscsit_global->ts_bitmap_count = ISCSI_TS_BITMAP_BITS;
513
514         size = BITS_TO_LONGS(iscsit_global->ts_bitmap_count) * sizeof(long);
515         iscsit_global->ts_bitmap = kzalloc(size, GFP_KERNEL);
516         if (!iscsit_global->ts_bitmap) {
517                 pr_err("Unable to allocate iscsit_global->ts_bitmap\n");
518                 return -ENOMEM;
519         }
520
521         spin_lock_init(&inactive_ts_lock);
522         spin_lock_init(&ts_bitmap_lock);
523         INIT_LIST_HEAD(&inactive_ts_list);
524
525         return 0;
526 }
527
528 void iscsi_thread_set_free(void)
529 {
530         kfree(iscsit_global->ts_bitmap);
531 }