Commit 359c48c0 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

SUNRPC: Add a helper to wake up a sleeping rpc_task and set its status



Add a helper that will wake up a task that is sleeping on a specific
queue, and will set the value of task->tk_status. This is mainly
intended for use by the transport layer to notify the task of an
error condition.

Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
parent cf9946cd
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -235,6 +235,9 @@ void rpc_wake_up_queued_task_on_wq(struct workqueue_struct *wq,
		struct rpc_task *task);
		struct rpc_task *task);
void		rpc_wake_up_queued_task(struct rpc_wait_queue *,
void		rpc_wake_up_queued_task(struct rpc_wait_queue *,
					struct rpc_task *);
					struct rpc_task *);
void		rpc_wake_up_queued_task_set_status(struct rpc_wait_queue *,
						   struct rpc_task *,
						   int);
void		rpc_wake_up(struct rpc_wait_queue *);
void		rpc_wake_up(struct rpc_wait_queue *);
struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *);
struct rpc_task *rpc_wake_up_next(struct rpc_wait_queue *);
struct rpc_task *rpc_wake_up_first_on_wq(struct workqueue_struct *wq,
struct rpc_task *rpc_wake_up_first_on_wq(struct workqueue_struct *wq,
+55 −10
Original line number Original line Diff line number Diff line
@@ -440,15 +440,29 @@ static void __rpc_do_wake_up_task_on_wq(struct workqueue_struct *wq,
/*
/*
 * Wake up a queued task while the queue lock is being held
 * Wake up a queued task while the queue lock is being held
 */
 */
static void rpc_wake_up_task_on_wq_queue_locked(struct workqueue_struct *wq,
static struct rpc_task *
		struct rpc_wait_queue *queue, struct rpc_task *task)
rpc_wake_up_task_on_wq_queue_action_locked(struct workqueue_struct *wq,
		struct rpc_wait_queue *queue, struct rpc_task *task,
		bool (*action)(struct rpc_task *, void *), void *data)
{
{
	if (RPC_IS_QUEUED(task)) {
	if (RPC_IS_QUEUED(task)) {
		smp_rmb();
		smp_rmb();
		if (task->tk_waitqueue == queue)
		if (task->tk_waitqueue == queue) {
			if (action == NULL || action(task, data)) {
				__rpc_do_wake_up_task_on_wq(wq, queue, task);
				__rpc_do_wake_up_task_on_wq(wq, queue, task);
				return task;
			}
			}
		}
		}
	}
	return NULL;
}

static void
rpc_wake_up_task_on_wq_queue_locked(struct workqueue_struct *wq,
		struct rpc_wait_queue *queue, struct rpc_task *task)
{
	rpc_wake_up_task_on_wq_queue_action_locked(wq, queue, task, NULL, NULL);
}


/*
/*
 * Wake up a queued task while the queue lock is being held
 * Wake up a queued task while the queue lock is being held
@@ -481,6 +495,40 @@ void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task
}
}
EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task);
EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task);


static bool rpc_task_action_set_status(struct rpc_task *task, void *status)
{
	task->tk_status = *(int *)status;
	return true;
}

static void
rpc_wake_up_task_queue_set_status_locked(struct rpc_wait_queue *queue,
		struct rpc_task *task, int status)
{
	rpc_wake_up_task_on_wq_queue_action_locked(rpciod_workqueue, queue,
			task, rpc_task_action_set_status, &status);
}

/**
 * rpc_wake_up_queued_task_set_status - wake up a task and set task->tk_status
 * @queue: pointer to rpc_wait_queue
 * @task: pointer to rpc_task
 * @status: integer error value
 *
 * If @task is queued on @queue, then it is woken up, and @task->tk_status is
 * set to the value of @status.
 */
void
rpc_wake_up_queued_task_set_status(struct rpc_wait_queue *queue,
		struct rpc_task *task, int status)
{
	if (!RPC_IS_QUEUED(task))
		return;
	spin_lock_bh(&queue->lock);
	rpc_wake_up_task_queue_set_status_locked(queue, task, status);
	spin_unlock_bh(&queue->lock);
}

/*
/*
 * Wake up the next task on a priority queue.
 * Wake up the next task on a priority queue.
 */
 */
@@ -553,12 +601,9 @@ struct rpc_task *rpc_wake_up_first_on_wq(struct workqueue_struct *wq,
			queue, rpc_qname(queue));
			queue, rpc_qname(queue));
	spin_lock_bh(&queue->lock);
	spin_lock_bh(&queue->lock);
	task = __rpc_find_next_queued(queue);
	task = __rpc_find_next_queued(queue);
	if (task != NULL) {
	if (task != NULL)
		if (func(task, data))
		task = rpc_wake_up_task_on_wq_queue_action_locked(wq, queue,
			rpc_wake_up_task_on_wq_queue_locked(wq, queue, task);
				task, func, data);
		else
			task = NULL;
	}
	spin_unlock_bh(&queue->lock);
	spin_unlock_bh(&queue->lock);


	return task;
	return task;