mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-07 13:53:24 +00:00
SUNRPC: Add a helper to allow pNFS drivers to selectively cancel RPC calls
Add the helper rpc_cancel_tasks(), which uses a caller-defined selection function to define a set of in-flight RPC calls to cancel. This is mainly intended for pNFS drivers which are subject to a layout recall, and which may therefore want to cancel all pending I/O using that layout in order to redrive it after the layout recall has been satisfied. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
parent
39494194f9
commit
f8423909ec
@ -210,11 +210,16 @@ struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req);
|
||||
void rpc_put_task(struct rpc_task *);
|
||||
void rpc_put_task_async(struct rpc_task *);
|
||||
bool rpc_task_set_rpc_status(struct rpc_task *task, int rpc_status);
|
||||
void rpc_task_try_cancel(struct rpc_task *task, int error);
|
||||
void rpc_signal_task(struct rpc_task *);
|
||||
void rpc_exit_task(struct rpc_task *);
|
||||
void rpc_exit(struct rpc_task *, int);
|
||||
void rpc_release_calldata(const struct rpc_call_ops *, void *);
|
||||
void rpc_killall_tasks(struct rpc_clnt *);
|
||||
unsigned long rpc_cancel_tasks(struct rpc_clnt *clnt, int error,
|
||||
bool (*fnmatch)(const struct rpc_task *,
|
||||
const void *),
|
||||
const void *data);
|
||||
void rpc_execute(struct rpc_task *);
|
||||
void rpc_init_priority_wait_queue(struct rpc_wait_queue *, const char *);
|
||||
void rpc_init_wait_queue(struct rpc_wait_queue *, const char *);
|
||||
|
@ -873,6 +873,43 @@ void rpc_killall_tasks(struct rpc_clnt *clnt)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rpc_killall_tasks);
|
||||
|
||||
/**
|
||||
* rpc_cancel_tasks - try to cancel a set of RPC tasks
|
||||
* @clnt: Pointer to RPC client
|
||||
* @error: RPC task error value to set
|
||||
* @fnmatch: Pointer to selector function
|
||||
* @data: User data
|
||||
*
|
||||
* Uses @fnmatch to define a set of RPC tasks that are to be cancelled.
|
||||
* The argument @error must be a negative error value.
|
||||
*/
|
||||
unsigned long rpc_cancel_tasks(struct rpc_clnt *clnt, int error,
|
||||
bool (*fnmatch)(const struct rpc_task *,
|
||||
const void *),
|
||||
const void *data)
|
||||
{
|
||||
struct rpc_task *task;
|
||||
unsigned long count = 0;
|
||||
|
||||
if (list_empty(&clnt->cl_tasks))
|
||||
return 0;
|
||||
/*
|
||||
* Spin lock all_tasks to prevent changes...
|
||||
*/
|
||||
spin_lock(&clnt->cl_lock);
|
||||
list_for_each_entry(task, &clnt->cl_tasks, tk_task) {
|
||||
if (!RPC_IS_ACTIVATED(task))
|
||||
continue;
|
||||
if (!fnmatch(task, data))
|
||||
continue;
|
||||
rpc_task_try_cancel(task, error);
|
||||
count++;
|
||||
}
|
||||
spin_unlock(&clnt->cl_lock);
|
||||
return count;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rpc_cancel_tasks);
|
||||
|
||||
/*
|
||||
* Properly shut down an RPC client, terminating all outstanding
|
||||
* requests.
|
||||
|
@ -872,6 +872,17 @@ void rpc_signal_task(struct rpc_task *task)
|
||||
rpc_wake_up_queued_task(queue, task);
|
||||
}
|
||||
|
||||
void rpc_task_try_cancel(struct rpc_task *task, int error)
|
||||
{
|
||||
struct rpc_wait_queue *queue;
|
||||
|
||||
if (!rpc_task_set_rpc_status(task, error))
|
||||
return;
|
||||
queue = READ_ONCE(task->tk_waitqueue);
|
||||
if (queue)
|
||||
rpc_wake_up_queued_task(queue, task);
|
||||
}
|
||||
|
||||
void rpc_exit(struct rpc_task *task, int status)
|
||||
{
|
||||
task->tk_status = status;
|
||||
|
Loading…
Reference in New Issue
Block a user