1a5bbec03f3e2389c764202a2ab1109b27a4a32f
[firefly-linux-kernel-4.4.55.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(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);
34
35 static void iscsi_add_ts_to_active_list(struct iscsi_thread_set *ts)
36 {
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);
41 }
42
43 static void iscsi_add_ts_to_inactive_list(struct iscsi_thread_set *ts)
44 {
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);
49 }
50
51 static void iscsi_del_ts_from_active_list(struct iscsi_thread_set *ts)
52 {
53         spin_lock(&active_ts_lock);
54         list_del(&ts->ts_list);
55         iscsit_global->active_ts--;
56         spin_unlock(&active_ts_lock);
57 }
58
59 static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void)
60 {
61         struct iscsi_thread_set *ts;
62
63         spin_lock(&inactive_ts_lock);
64         if (list_empty(&inactive_ts_list)) {
65                 spin_unlock(&inactive_ts_lock);
66                 return NULL;
67         }
68
69         ts = list_first_entry(&inactive_ts_list, struct iscsi_thread_set, ts_list);
70
71         list_del(&ts->ts_list);
72         iscsit_global->inactive_ts--;
73         spin_unlock(&inactive_ts_lock);
74
75         return ts;
76 }
77
78 int iscsi_allocate_thread_sets(u32 thread_pair_count)
79 {
80         int allocated_thread_pair_count = 0, i, thread_id;
81         struct iscsi_thread_set *ts = NULL;
82
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;
89                 }
90                 /*
91                  * Locate the next available regision in the thread_set_bitmap
92                  */
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;
102                 }
103
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);
114
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;
122                 }
123
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;
130                 }
131                 ts->create_threads = 0;
132
133                 iscsi_add_ts_to_inactive_list(ts);
134                 allocated_thread_pair_count++;
135         }
136
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;
140 }
141
142 void iscsi_deallocate_thread_sets(void)
143 {
144         u32 released_count = 0;
145         struct iscsi_thread_set *ts = NULL;
146
147         while ((ts = iscsi_get_ts_from_inactive_list())) {
148
149                 spin_lock_bh(&ts->ts_state_lock);
150                 ts->status = ISCSI_THREAD_SET_DIE;
151                 spin_unlock_bh(&ts->ts_state_lock);
152
153                 if (ts->rx_thread) {
154                         send_sig(SIGINT, ts->rx_thread, 1);
155                         kthread_stop(ts->rx_thread);
156                 }
157                 if (ts->tx_thread) {
158                         send_sig(SIGINT, ts->tx_thread, 1);
159                         kthread_stop(ts->tx_thread);
160                 }
161                 /*
162                  * Release this thread_id in the thread_set_bitmap
163                  */
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);
168
169                 released_count++;
170                 kfree(ts);
171         }
172
173         if (released_count)
174                 pr_debug("Stopped %d thread set(s) (%d total threads)."
175                         "\n", released_count, released_count * 2);
176 }
177
178 static void iscsi_deallocate_extra_thread_sets(void)
179 {
180         u32 orig_count, released_count = 0;
181         struct iscsi_thread_set *ts = NULL;
182
183         orig_count = TARGET_THREAD_SET_COUNT;
184
185         while ((iscsit_global->inactive_ts + 1) > orig_count) {
186                 ts = iscsi_get_ts_from_inactive_list();
187                 if (!ts)
188                         break;
189
190                 spin_lock_bh(&ts->ts_state_lock);
191                 ts->status = ISCSI_THREAD_SET_DIE;
192
193                 if (ts->rx_thread) {
194                         complete(&ts->rx_start_comp);
195                         spin_unlock_bh(&ts->ts_state_lock);
196                         kthread_stop(ts->rx_thread);
197                         spin_lock_bh(&ts->ts_state_lock);
198                 }
199                 if (ts->tx_thread) {
200                         complete(&ts->tx_start_comp);
201                         spin_unlock_bh(&ts->ts_state_lock);
202                         kthread_stop(ts->tx_thread);
203                         spin_lock_bh(&ts->ts_state_lock);
204                 }
205                 spin_unlock_bh(&ts->ts_state_lock);
206                 /*
207                  * Release this thread_id in the thread_set_bitmap
208                  */
209                 spin_lock(&ts_bitmap_lock);
210                 bitmap_release_region(iscsit_global->ts_bitmap,
211                                 ts->thread_id, get_order(1));
212                 spin_unlock(&ts_bitmap_lock);
213
214                 released_count++;
215                 kfree(ts);
216         }
217
218         if (released_count) {
219                 pr_debug("Stopped %d thread set(s) (%d total threads)."
220                         "\n", released_count, released_count * 2);
221         }
222 }
223
224 void iscsi_activate_thread_set(struct iscsi_conn *conn, struct iscsi_thread_set *ts)
225 {
226         iscsi_add_ts_to_active_list(ts);
227
228         spin_lock_bh(&ts->ts_state_lock);
229         conn->thread_set = ts;
230         ts->conn = conn;
231         spin_unlock_bh(&ts->ts_state_lock);
232         /*
233          * Start up the RX thread and wait on rx_post_start_comp.  The RX
234          * Thread will then do the same for the TX Thread in
235          * iscsi_rx_thread_pre_handler().
236          */
237         complete(&ts->rx_start_comp);
238         wait_for_completion(&ts->rx_post_start_comp);
239 }
240
241 struct iscsi_thread_set *iscsi_get_thread_set(void)
242 {
243         int allocate_ts = 0;
244         struct completion comp;
245         struct iscsi_thread_set *ts = NULL;
246         /*
247          * If no inactive thread set is available on the first call to
248          * iscsi_get_ts_from_inactive_list(), sleep for a second and
249          * try again.  If still none are available after two attempts,
250          * allocate a set ourselves.
251          */
252 get_set:
253         ts = iscsi_get_ts_from_inactive_list();
254         if (!ts) {
255                 if (allocate_ts == 2)
256                         iscsi_allocate_thread_sets(1);
257
258                 init_completion(&comp);
259                 wait_for_completion_timeout(&comp, 1 * HZ);
260
261                 allocate_ts++;
262                 goto get_set;
263         }
264
265         ts->delay_inactive = 1;
266         ts->signal_sent = 0;
267         ts->thread_count = 2;
268         init_completion(&ts->rx_restart_comp);
269         init_completion(&ts->tx_restart_comp);
270
271         return ts;
272 }
273
274 void iscsi_set_thread_clear(struct iscsi_conn *conn, u8 thread_clear)
275 {
276         struct iscsi_thread_set *ts = NULL;
277
278         if (!conn->thread_set) {
279                 pr_err("struct iscsi_conn->thread_set is NULL\n");
280                 return;
281         }
282         ts = conn->thread_set;
283
284         spin_lock_bh(&ts->ts_state_lock);
285         ts->thread_clear &= ~thread_clear;
286
287         if ((thread_clear & ISCSI_CLEAR_RX_THREAD) &&
288             (ts->blocked_threads & ISCSI_BLOCK_RX_THREAD))
289                 complete(&ts->rx_restart_comp);
290         else if ((thread_clear & ISCSI_CLEAR_TX_THREAD) &&
291                  (ts->blocked_threads & ISCSI_BLOCK_TX_THREAD))
292                 complete(&ts->tx_restart_comp);
293         spin_unlock_bh(&ts->ts_state_lock);
294 }
295
296 void iscsi_set_thread_set_signal(struct iscsi_conn *conn, u8 signal_sent)
297 {
298         struct iscsi_thread_set *ts = NULL;
299
300         if (!conn->thread_set) {
301                 pr_err("struct iscsi_conn->thread_set is NULL\n");
302                 return;
303         }
304         ts = conn->thread_set;
305
306         spin_lock_bh(&ts->ts_state_lock);
307         ts->signal_sent |= signal_sent;
308         spin_unlock_bh(&ts->ts_state_lock);
309 }
310
311 int iscsi_release_thread_set(struct iscsi_conn *conn)
312 {
313         int thread_called = 0;
314         struct iscsi_thread_set *ts = NULL;
315
316         if (!conn || !conn->thread_set) {
317                 pr_err("connection or thread set pointer is NULL\n");
318                 BUG();
319         }
320         ts = conn->thread_set;
321
322         spin_lock_bh(&ts->ts_state_lock);
323         ts->status = ISCSI_THREAD_SET_RESET;
324
325         if (!strncmp(current->comm, ISCSI_RX_THREAD_NAME,
326                         strlen(ISCSI_RX_THREAD_NAME)))
327                 thread_called = ISCSI_RX_THREAD;
328         else if (!strncmp(current->comm, ISCSI_TX_THREAD_NAME,
329                         strlen(ISCSI_TX_THREAD_NAME)))
330                 thread_called = ISCSI_TX_THREAD;
331
332         if (ts->rx_thread && (thread_called == ISCSI_TX_THREAD) &&
333            (ts->thread_clear & ISCSI_CLEAR_RX_THREAD)) {
334
335                 if (!(ts->signal_sent & ISCSI_SIGNAL_RX_THREAD)) {
336                         send_sig(SIGINT, ts->rx_thread, 1);
337                         ts->signal_sent |= ISCSI_SIGNAL_RX_THREAD;
338                 }
339                 ts->blocked_threads |= ISCSI_BLOCK_RX_THREAD;
340                 spin_unlock_bh(&ts->ts_state_lock);
341                 wait_for_completion(&ts->rx_restart_comp);
342                 spin_lock_bh(&ts->ts_state_lock);
343                 ts->blocked_threads &= ~ISCSI_BLOCK_RX_THREAD;
344         }
345         if (ts->tx_thread && (thread_called == ISCSI_RX_THREAD) &&
346            (ts->thread_clear & ISCSI_CLEAR_TX_THREAD)) {
347
348                 if (!(ts->signal_sent & ISCSI_SIGNAL_TX_THREAD)) {
349                         send_sig(SIGINT, ts->tx_thread, 1);
350                         ts->signal_sent |= ISCSI_SIGNAL_TX_THREAD;
351                 }
352                 ts->blocked_threads |= ISCSI_BLOCK_TX_THREAD;
353                 spin_unlock_bh(&ts->ts_state_lock);
354                 wait_for_completion(&ts->tx_restart_comp);
355                 spin_lock_bh(&ts->ts_state_lock);
356                 ts->blocked_threads &= ~ISCSI_BLOCK_TX_THREAD;
357         }
358
359         ts->conn = NULL;
360         ts->status = ISCSI_THREAD_SET_FREE;
361         spin_unlock_bh(&ts->ts_state_lock);
362
363         return 0;
364 }
365
366 int iscsi_thread_set_force_reinstatement(struct iscsi_conn *conn)
367 {
368         struct iscsi_thread_set *ts;
369
370         if (!conn->thread_set)
371                 return -1;
372         ts = conn->thread_set;
373
374         spin_lock_bh(&ts->ts_state_lock);
375         if (ts->status != ISCSI_THREAD_SET_ACTIVE) {
376                 spin_unlock_bh(&ts->ts_state_lock);
377                 return -1;
378         }
379
380         if (ts->tx_thread && (!(ts->signal_sent & ISCSI_SIGNAL_TX_THREAD))) {
381                 send_sig(SIGINT, ts->tx_thread, 1);
382                 ts->signal_sent |= ISCSI_SIGNAL_TX_THREAD;
383         }
384         if (ts->rx_thread && (!(ts->signal_sent & ISCSI_SIGNAL_RX_THREAD))) {
385                 send_sig(SIGINT, ts->rx_thread, 1);
386                 ts->signal_sent |= ISCSI_SIGNAL_RX_THREAD;
387         }
388         spin_unlock_bh(&ts->ts_state_lock);
389
390         return 0;
391 }
392
393 static void iscsi_check_to_add_additional_sets(void)
394 {
395         int thread_sets_add;
396
397         spin_lock(&inactive_ts_lock);
398         thread_sets_add = iscsit_global->inactive_ts;
399         spin_unlock(&inactive_ts_lock);
400         if (thread_sets_add == 1)
401                 iscsi_allocate_thread_sets(1);
402 }
403
404 static int iscsi_signal_thread_pre_handler(struct iscsi_thread_set *ts)
405 {
406         spin_lock_bh(&ts->ts_state_lock);
407         if (ts->status == ISCSI_THREAD_SET_DIE || kthread_should_stop() ||
408             signal_pending(current)) {
409                 spin_unlock_bh(&ts->ts_state_lock);
410                 return -1;
411         }
412         spin_unlock_bh(&ts->ts_state_lock);
413
414         return 0;
415 }
416
417 struct iscsi_conn *iscsi_rx_thread_pre_handler(struct iscsi_thread_set *ts)
418 {
419         int ret;
420
421         spin_lock_bh(&ts->ts_state_lock);
422         if (ts->create_threads) {
423                 spin_unlock_bh(&ts->ts_state_lock);
424                 goto sleep;
425         }
426
427         if (ts->status != ISCSI_THREAD_SET_DIE)
428                 flush_signals(current);
429
430         if (ts->delay_inactive && (--ts->thread_count == 0)) {
431                 spin_unlock_bh(&ts->ts_state_lock);
432                 iscsi_del_ts_from_active_list(ts);
433
434                 if (!iscsit_global->in_shutdown)
435                         iscsi_deallocate_extra_thread_sets();
436
437                 iscsi_add_ts_to_inactive_list(ts);
438                 spin_lock_bh(&ts->ts_state_lock);
439         }
440
441         if ((ts->status == ISCSI_THREAD_SET_RESET) &&
442             (ts->thread_clear & ISCSI_CLEAR_RX_THREAD))
443                 complete(&ts->rx_restart_comp);
444
445         ts->thread_clear &= ~ISCSI_CLEAR_RX_THREAD;
446         spin_unlock_bh(&ts->ts_state_lock);
447 sleep:
448         ret = wait_for_completion_interruptible(&ts->rx_start_comp);
449         if (ret != 0)
450                 return NULL;
451
452         if (iscsi_signal_thread_pre_handler(ts) < 0)
453                 return NULL;
454
455         if (!ts->conn) {
456                 pr_err("struct iscsi_thread_set->conn is NULL for"
457                         " thread_id: %d, going back to sleep\n", ts->thread_id);
458                 goto sleep;
459         }
460         iscsi_check_to_add_additional_sets();
461         /*
462          * The RX Thread starts up the TX Thread and sleeps.
463          */
464         ts->thread_clear |= ISCSI_CLEAR_RX_THREAD;
465         complete(&ts->tx_start_comp);
466         wait_for_completion(&ts->tx_post_start_comp);
467
468         return ts->conn;
469 }
470
471 struct iscsi_conn *iscsi_tx_thread_pre_handler(struct iscsi_thread_set *ts)
472 {
473         int ret;
474
475         spin_lock_bh(&ts->ts_state_lock);
476         if (ts->create_threads) {
477                 spin_unlock_bh(&ts->ts_state_lock);
478                 goto sleep;
479         }
480
481         if (ts->status != ISCSI_THREAD_SET_DIE)
482                 flush_signals(current);
483
484         if (ts->delay_inactive && (--ts->thread_count == 0)) {
485                 spin_unlock_bh(&ts->ts_state_lock);
486                 iscsi_del_ts_from_active_list(ts);
487
488                 if (!iscsit_global->in_shutdown)
489                         iscsi_deallocate_extra_thread_sets();
490
491                 iscsi_add_ts_to_inactive_list(ts);
492                 spin_lock_bh(&ts->ts_state_lock);
493         }
494         if ((ts->status == ISCSI_THREAD_SET_RESET) &&
495             (ts->thread_clear & ISCSI_CLEAR_TX_THREAD))
496                 complete(&ts->tx_restart_comp);
497
498         ts->thread_clear &= ~ISCSI_CLEAR_TX_THREAD;
499         spin_unlock_bh(&ts->ts_state_lock);
500 sleep:
501         ret = wait_for_completion_interruptible(&ts->tx_start_comp);
502         if (ret != 0)
503                 return NULL;
504
505         if (iscsi_signal_thread_pre_handler(ts) < 0)
506                 return NULL;
507
508         if (!ts->conn) {
509                 pr_err("struct iscsi_thread_set->conn is NULL for "
510                         " thread_id: %d, going back to sleep\n",
511                         ts->thread_id);
512                 goto sleep;
513         }
514
515         iscsi_check_to_add_additional_sets();
516         /*
517          * From the TX thread, up the tx_post_start_comp that the RX Thread is
518          * sleeping on in iscsi_rx_thread_pre_handler(), then up the
519          * rx_post_start_comp that iscsi_activate_thread_set() is sleeping on.
520          */
521         ts->thread_clear |= ISCSI_CLEAR_TX_THREAD;
522         complete(&ts->tx_post_start_comp);
523         complete(&ts->rx_post_start_comp);
524
525         spin_lock_bh(&ts->ts_state_lock);
526         ts->status = ISCSI_THREAD_SET_ACTIVE;
527         spin_unlock_bh(&ts->ts_state_lock);
528
529         return ts->conn;
530 }
531
532 int iscsi_thread_set_init(void)
533 {
534         int size;
535
536         iscsit_global->ts_bitmap_count = ISCSI_TS_BITMAP_BITS;
537
538         size = BITS_TO_LONGS(iscsit_global->ts_bitmap_count) * sizeof(long);
539         iscsit_global->ts_bitmap = kzalloc(size, GFP_KERNEL);
540         if (!iscsit_global->ts_bitmap) {
541                 pr_err("Unable to allocate iscsit_global->ts_bitmap\n");
542                 return -ENOMEM;
543         }
544
545         return 0;
546 }
547
548 void iscsi_thread_set_free(void)
549 {
550         kfree(iscsit_global->ts_bitmap);
551 }