Пример #1
0
struct iscsi_conn *iscsi_rx_thread_pre_handler(struct iscsi_thread_set *ts)
{
	int ret;

	spin_lock_bh(&ts->ts_state_lock);
	if (ts->create_threads) {
		spin_unlock_bh(&ts->ts_state_lock);
		goto sleep;
	}

	flush_signals(current);

	if (ts->delay_inactive && (--ts->thread_count == 0)) {
		spin_unlock_bh(&ts->ts_state_lock);
		iscsi_del_ts_from_active_list(ts);

		if (!iscsit_global->in_shutdown)
			iscsi_deallocate_extra_thread_sets();

		iscsi_add_ts_to_inactive_list(ts);
		spin_lock_bh(&ts->ts_state_lock);
	}

	if ((ts->status == ISCSI_THREAD_SET_RESET) &&
	    (ts->thread_clear & ISCSI_CLEAR_RX_THREAD))
		complete(&ts->rx_restart_comp);

	ts->thread_clear &= ~ISCSI_CLEAR_RX_THREAD;
	spin_unlock_bh(&ts->ts_state_lock);
sleep:
	ret = wait_for_completion_interruptible(&ts->rx_start_comp);
	pr_info("%s: %s/%d (thread set %d) got %d waiting for rx_start_comp\n",
		__func__, current->comm, task_pid_nr(current), ts->thread_id, ret);
	if (ret != 0)
		return NULL;

	if (iscsi_signal_thread_pre_handler(ts) < 0)
		return NULL;

	if (!ts->conn) {
		pr_err("struct iscsi_thread_set->conn is NULL for"
			" thread_id: %d, going back to sleep\n", ts->thread_id);
		goto sleep;
	}
	iscsi_check_to_add_additional_sets();
	/*
	 * The RX Thread starts up the TX Thread and sleeps.
	 */
	spin_lock_bh(&ts->ts_state_lock);
	ts->thread_clear |= ISCSI_CLEAR_RX_THREAD;
	spin_unlock_bh(&ts->ts_state_lock);
	complete(&ts->tx_start_comp);
	wait_for_completion(&ts->tx_post_start_comp);

	pr_info("%s/%d: returning connection %p for rx thread\n",
		current->comm, task_pid_nr(current), ts->conn);

	return ts->conn;
}
struct iscsi_conn *iscsi_tx_thread_pre_handler(struct iscsi_thread_set *ts)
{
	int ret;

	spin_lock_bh(&ts->ts_state_lock);
	if (ts->create_threads) {
		spin_unlock_bh(&ts->ts_state_lock);
		goto sleep;
	}

	flush_signals(current);

	if (ts->delay_inactive && (--ts->thread_count == 0)) {
		spin_unlock_bh(&ts->ts_state_lock);
		iscsi_del_ts_from_active_list(ts);

		if (!iscsit_global->in_shutdown)
			iscsi_deallocate_extra_thread_sets();

		iscsi_add_ts_to_inactive_list(ts);
		spin_lock_bh(&ts->ts_state_lock);
	}
	if ((ts->status == ISCSI_THREAD_SET_RESET) &&
	    (ts->thread_clear & ISCSI_CLEAR_TX_THREAD))
		complete(&ts->tx_restart_comp);

	ts->thread_clear &= ~ISCSI_CLEAR_TX_THREAD;
	spin_unlock_bh(&ts->ts_state_lock);
sleep:
	ret = wait_for_completion_interruptible(&ts->tx_start_comp);
	if (ret != 0)
		return NULL;

	if (iscsi_signal_thread_pre_handler(ts) < 0)
		return NULL;

	if (!ts->conn) {
		pr_err("struct iscsi_thread_set->conn is NULL for "
			" thread_id: %d, going back to sleep\n",
			ts->thread_id);
		goto sleep;
	}

	iscsi_check_to_add_additional_sets();
	/*
	 * From the TX thread, up the tx_post_start_comp that the RX Thread is
	 * sleeping on in iscsi_rx_thread_pre_handler(), then up the
	 * rx_post_start_comp that iscsi_activate_thread_set() is sleeping on.
	 */
	ts->thread_clear |= ISCSI_CLEAR_TX_THREAD;
	complete(&ts->tx_post_start_comp);
	complete(&ts->rx_post_start_comp);

	spin_lock_bh(&ts->ts_state_lock);
	ts->status = ISCSI_THREAD_SET_ACTIVE;
	spin_unlock_bh(&ts->ts_state_lock);

	return ts->conn;
}