예제 #1
0
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);
	}
}