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: Trond Myklebust <trond.myklebust@hammerspace.com>
This commit is contained in:
parent
cf9946cd61
commit
359c48c04a
|
@ -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,
|
||||||
|
|
|
@ -440,14 +440,28 @@ 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) {
|
||||||
__rpc_do_wake_up_task_on_wq(wq, queue, task);
|
if (action == NULL || action(task, data)) {
|
||||||
|
__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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue