struct iscsi_thread_set *iscsi_get_thread_set(void) { int allocate_ts = 0; struct completion comp; struct iscsi_thread_set *ts = NULL; /* * If no inactive thread set is available on the first call to * iscsi_get_ts_from_inactive_list(), sleep for a second and * try again. If still none are available after two attempts, * allocate a set ourselves. */ get_set: ts = iscsi_get_ts_from_inactive_list(); if (!ts) { if (allocate_ts == 2) iscsi_allocate_thread_sets(1); init_completion(&comp); wait_for_completion_timeout(&comp, 1 * HZ); allocate_ts++; goto get_set; } ts->delay_inactive = 1; ts->signal_sent = 0; ts->thread_count = 3; init_completion(&ts->rx_restart_comp); init_completion(&ts->tx_restart_comp); init_completion(&ts->deferred_restart_comp); return ts; }
struct iscsi_thread_set *iscsi_get_thread_set(void) { int allocate_ts = 0; struct completion comp; struct iscsi_thread_set *ts = NULL; /* */ get_set: ts = iscsi_get_ts_from_inactive_list(); if (!ts) { if (allocate_ts == 2) iscsi_allocate_thread_sets(1); init_completion(&comp); wait_for_completion_timeout(&comp, 1 * HZ); allocate_ts++; goto get_set; } ts->delay_inactive = 1; ts->signal_sent = 0; ts->thread_count = 2; init_completion(&ts->rx_restart_comp); init_completion(&ts->tx_restart_comp); return ts; }
void iscsi_deallocate_thread_sets(void) { u32 released_count = 0; struct iscsi_thread_set *ts = NULL; while ((ts = iscsi_get_ts_from_inactive_list())) { spin_lock_bh(&ts->ts_state_lock); ts->status = ISCSI_THREAD_SET_DIE; spin_unlock_bh(&ts->ts_state_lock); if (ts->rx_thread) { send_sig(SIGINT, ts->rx_thread, 1); kthread_stop(ts->rx_thread); } if (ts->tx_thread) { send_sig(SIGINT, ts->tx_thread, 1); kthread_stop(ts->tx_thread); } /* * Release this thread_id in the thread_set_bitmap */ spin_lock(&ts_bitmap_lock); bitmap_release_region(iscsit_global->ts_bitmap, ts->thread_id, get_order(1)); spin_unlock(&ts_bitmap_lock); released_count++; kfree(ts); } if (released_count) pr_debug("Stopped %d thread set(s) (%d total threads)." "\n", released_count, released_count * 2); }
static void iscsi_deallocate_extra_thread_sets(void) { u32 orig_count, released_count = 0; struct iscsi_thread_set *ts = NULL; orig_count = TARGET_THREAD_SET_COUNT; while ((iscsit_global->inactive_ts + 1) > orig_count) { ts = iscsi_get_ts_from_inactive_list(); if (!ts) break; spin_lock_bh(&ts->ts_state_lock); ts->status = ISCSI_THREAD_SET_DIE; spin_unlock_bh(&ts->ts_state_lock); if (ts->rx_thread) { send_sig(SIGINT, ts->rx_thread, 1); kthread_stop(ts->rx_thread); } if (ts->tx_thread) { send_sig(SIGINT, ts->tx_thread, 1); kthread_stop(ts->tx_thread); } /* */ spin_lock(&ts_bitmap_lock); bitmap_release_region(iscsit_global->ts_bitmap, ts->thread_id, get_order(1)); spin_unlock(&ts_bitmap_lock); released_count++; kfree(ts); } if (released_count) { pr_debug("Stopped %d thread set(s) (%d total threads)." "\n", released_count, released_count * 2); } }