Commit 6529eba0 authored by Trond Myklebust's avatar Trond Myklebust

SUNRPC: Move rpc_task->tk_task list into struct rpc_clnt

Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent c6d00e63
...@@ -26,6 +26,8 @@ struct rpc_inode; ...@@ -26,6 +26,8 @@ struct rpc_inode;
struct rpc_clnt { struct rpc_clnt {
atomic_t cl_count; /* Number of clones */ atomic_t cl_count; /* Number of clones */
atomic_t cl_users; /* number of references */ atomic_t cl_users; /* number of references */
struct list_head cl_clients; /* Global list of clients */
struct list_head cl_tasks; /* List of tasks */
struct rpc_xprt * cl_xprt; /* transport */ struct rpc_xprt * cl_xprt; /* transport */
struct rpc_procinfo * cl_procinfo; /* procedure info */ struct rpc_procinfo * cl_procinfo; /* procedure info */
u32 cl_prog, /* RPC program number */ u32 cl_prog, /* RPC program number */
...@@ -122,6 +124,8 @@ struct rpc_clnt *rpc_clone_client(struct rpc_clnt *); ...@@ -122,6 +124,8 @@ struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
int rpc_shutdown_client(struct rpc_clnt *); int rpc_shutdown_client(struct rpc_clnt *);
int rpc_destroy_client(struct rpc_clnt *); int rpc_destroy_client(struct rpc_clnt *);
void rpc_release_client(struct rpc_clnt *); void rpc_release_client(struct rpc_clnt *);
void rpc_register_client(struct rpc_clnt *);
void rpc_unregister_client(struct rpc_clnt *);
int rpcb_register(u32, u32, int, unsigned short, int *); int rpcb_register(u32, u32, int, unsigned short, int *);
void rpcb_getport(struct rpc_task *); void rpcb_getport(struct rpc_task *);
......
...@@ -110,11 +110,6 @@ struct rpc_task { ...@@ -110,11 +110,6 @@ struct rpc_task {
if (!list_empty(head) && \ if (!list_empty(head) && \
((task=list_entry((head)->next, struct rpc_task, u.tk_wait.list)),1)) ((task=list_entry((head)->next, struct rpc_task, u.tk_wait.list)),1))
/* .. and walking list of all tasks */
#define alltask_for_each(task, pos, head) \
list_for_each(pos, head) \
if ((task=list_entry(pos, struct rpc_task, tk_task)),1)
typedef void (*rpc_action)(struct rpc_task *); typedef void (*rpc_action)(struct rpc_task *);
struct rpc_call_ops { struct rpc_call_ops {
......
...@@ -148,6 +148,7 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s ...@@ -148,6 +148,7 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
if (clnt->cl_metrics == NULL) if (clnt->cl_metrics == NULL)
goto out_no_stats; goto out_no_stats;
clnt->cl_program = program; clnt->cl_program = program;
INIT_LIST_HEAD(&clnt->cl_tasks);
if (!xprt_bound(clnt->cl_xprt)) if (!xprt_bound(clnt->cl_xprt))
clnt->cl_autobind = 1; clnt->cl_autobind = 1;
...@@ -172,6 +173,7 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s ...@@ -172,6 +173,7 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
if (clnt->cl_nodelen > UNX_MAXNODENAME) if (clnt->cl_nodelen > UNX_MAXNODENAME)
clnt->cl_nodelen = UNX_MAXNODENAME; clnt->cl_nodelen = UNX_MAXNODENAME;
memcpy(clnt->cl_nodename, utsname()->nodename, clnt->cl_nodelen); memcpy(clnt->cl_nodename, utsname()->nodename, clnt->cl_nodelen);
rpc_register_client(clnt);
return clnt; return clnt;
out_no_auth: out_no_auth:
...@@ -283,9 +285,11 @@ rpc_clone_client(struct rpc_clnt *clnt) ...@@ -283,9 +285,11 @@ rpc_clone_client(struct rpc_clnt *clnt)
new->cl_autobind = 0; new->cl_autobind = 0;
new->cl_oneshot = 0; new->cl_oneshot = 0;
new->cl_dead = 0; new->cl_dead = 0;
INIT_LIST_HEAD(&new->cl_tasks);
rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
if (new->cl_auth) if (new->cl_auth)
atomic_inc(&new->cl_auth->au_count); atomic_inc(&new->cl_auth->au_count);
rpc_register_client(new);
return new; return new;
out_no_path: out_no_path:
rpc_free_iostats(new->cl_metrics); rpc_free_iostats(new->cl_metrics);
...@@ -357,6 +361,7 @@ rpc_destroy_client(struct rpc_clnt *clnt) ...@@ -357,6 +361,7 @@ rpc_destroy_client(struct rpc_clnt *clnt)
if (clnt->cl_server != clnt->cl_inline_name) if (clnt->cl_server != clnt->cl_inline_name)
kfree(clnt->cl_server); kfree(clnt->cl_server);
out_free: out_free:
rpc_unregister_client(clnt);
rpc_free_iostats(clnt->cl_metrics); rpc_free_iostats(clnt->cl_metrics);
clnt->cl_metrics = NULL; clnt->cl_metrics = NULL;
xprt_put(clnt->cl_xprt); xprt_put(clnt->cl_xprt);
......
...@@ -50,9 +50,10 @@ static void rpc_release_task(struct rpc_task *task); ...@@ -50,9 +50,10 @@ static void rpc_release_task(struct rpc_task *task);
static RPC_WAITQ(delay_queue, "delayq"); static RPC_WAITQ(delay_queue, "delayq");
/* /*
* All RPC tasks are linked into this list * All RPC clients are linked into this list
*/ */
static LIST_HEAD(all_tasks); static LIST_HEAD(all_clients);
static DECLARE_WAIT_QUEUE_HEAD(client_kill_wait);
/* /*
* rpciod-related stuff * rpciod-related stuff
...@@ -277,7 +278,8 @@ static void rpc_set_active(struct rpc_task *task) ...@@ -277,7 +278,8 @@ static void rpc_set_active(struct rpc_task *task)
task->tk_pid = rpc_task_id++; task->tk_pid = rpc_task_id++;
#endif #endif
/* Add to global list of all tasks */ /* Add to global list of all tasks */
list_add_tail(&task->tk_task, &all_tasks); if (task->tk_client)
list_add_tail(&task->tk_task, &task->tk_client->cl_tasks);
spin_unlock(&rpc_sched_lock); spin_unlock(&rpc_sched_lock);
} }
...@@ -818,6 +820,7 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons ...@@ -818,6 +820,7 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons
if (tk_ops->rpc_call_prepare != NULL) if (tk_ops->rpc_call_prepare != NULL)
task->tk_action = rpc_prepare_task; task->tk_action = rpc_prepare_task;
task->tk_calldata = calldata; task->tk_calldata = calldata;
INIT_LIST_HEAD(&task->tk_task);
/* Initialize retry counters */ /* Initialize retry counters */
task->tk_garb_retry = 2; task->tk_garb_retry = 2;
...@@ -920,11 +923,12 @@ static void rpc_release_task(struct rpc_task *task) ...@@ -920,11 +923,12 @@ static void rpc_release_task(struct rpc_task *task)
#endif #endif
dprintk("RPC: %5u release task\n", task->tk_pid); dprintk("RPC: %5u release task\n", task->tk_pid);
/* Remove from global task list */ if (!list_empty(&task->tk_task)) {
/* Remove from client task list */
spin_lock(&rpc_sched_lock); spin_lock(&rpc_sched_lock);
list_del(&task->tk_task); list_del(&task->tk_task);
spin_unlock(&rpc_sched_lock); spin_unlock(&rpc_sched_lock);
}
BUG_ON (RPC_IS_QUEUED(task)); BUG_ON (RPC_IS_QUEUED(task));
/* Synchronously delete any running timer */ /* Synchronously delete any running timer */
...@@ -966,42 +970,52 @@ EXPORT_SYMBOL(rpc_run_task); ...@@ -966,42 +970,52 @@ EXPORT_SYMBOL(rpc_run_task);
* Kill all tasks for the given client. * Kill all tasks for the given client.
* XXX: kill their descendants as well? * XXX: kill their descendants as well?
*/ */
void rpc_killall_tasks(struct rpc_clnt *clnt) static void rpc_killall_tasks_locked(struct list_head *head)
{ {
struct rpc_task *rovr; struct rpc_task *rovr;
struct list_head *le;
dprintk("RPC: killing all tasks for client %p\n", clnt);
/* list_for_each_entry(rovr, head, tk_task) {
* Spin lock all_tasks to prevent changes...
*/
spin_lock(&rpc_sched_lock);
alltask_for_each(rovr, le, &all_tasks) {
if (! RPC_IS_ACTIVATED(rovr)) if (! RPC_IS_ACTIVATED(rovr))
continue; continue;
if (!clnt || rovr->tk_client == clnt) { if (!(rovr->tk_flags & RPC_TASK_KILLED)) {
rovr->tk_flags |= RPC_TASK_KILLED; rovr->tk_flags |= RPC_TASK_KILLED;
rpc_exit(rovr, -EIO); rpc_exit(rovr, -EIO);
rpc_wake_up_task(rovr); rpc_wake_up_task(rovr);
} }
} }
}
void rpc_killall_tasks(struct rpc_clnt *clnt)
{
dprintk("RPC: killing all tasks for client %p\n", clnt);
/*
* Spin lock all_tasks to prevent changes...
*/
spin_lock(&rpc_sched_lock);
rpc_killall_tasks_locked(&clnt->cl_tasks);
spin_unlock(&rpc_sched_lock); spin_unlock(&rpc_sched_lock);
} }
static void rpciod_killall(void) static void rpciod_killall(void)
{ {
struct rpc_clnt *clnt;
unsigned long flags; unsigned long flags;
while (!list_empty(&all_tasks)) { for(;;) {
clear_thread_flag(TIF_SIGPENDING); clear_thread_flag(TIF_SIGPENDING);
rpc_killall_tasks(NULL);
spin_lock(&rpc_sched_lock);
list_for_each_entry(clnt, &all_clients, cl_clients)
rpc_killall_tasks_locked(&clnt->cl_tasks);
spin_unlock(&rpc_sched_lock);
flush_workqueue(rpciod_workqueue); flush_workqueue(rpciod_workqueue);
if (!list_empty(&all_tasks)) { if (!list_empty(&all_clients))
break;
dprintk("RPC: rpciod_killall: waiting for tasks " dprintk("RPC: rpciod_killall: waiting for tasks "
"to exit\n"); "to exit\n");
yield(); wait_event_timeout(client_kill_wait,
} list_empty(&all_clients), 1*HZ);
} }
spin_lock_irqsave(&current->sighand->siglock, flags); spin_lock_irqsave(&current->sighand->siglock, flags);
...@@ -1009,6 +1023,22 @@ static void rpciod_killall(void) ...@@ -1009,6 +1023,22 @@ static void rpciod_killall(void)
spin_unlock_irqrestore(&current->sighand->siglock, flags); spin_unlock_irqrestore(&current->sighand->siglock, flags);
} }
void rpc_register_client(struct rpc_clnt *clnt)
{
spin_lock(&rpc_sched_lock);
list_add(&clnt->cl_clients, &all_clients);
spin_unlock(&rpc_sched_lock);
}
void rpc_unregister_client(struct rpc_clnt *clnt)
{
spin_lock(&rpc_sched_lock);
list_del(&clnt->cl_clients);
if (list_empty(&all_clients))
wake_up(&client_kill_wait);
spin_unlock(&rpc_sched_lock);
}
/* /*
* Start up the rpciod process if it's not already running. * Start up the rpciod process if it's not already running.
*/ */
...@@ -1071,17 +1101,16 @@ rpciod_down(void) ...@@ -1071,17 +1101,16 @@ rpciod_down(void)
#ifdef RPC_DEBUG #ifdef RPC_DEBUG
void rpc_show_tasks(void) void rpc_show_tasks(void)
{ {
struct list_head *le; struct rpc_clnt *clnt;
struct rpc_task *t; struct rpc_task *t;
spin_lock(&rpc_sched_lock); spin_lock(&rpc_sched_lock);
if (list_empty(&all_tasks)) { if (list_empty(&all_clients))
spin_unlock(&rpc_sched_lock); goto out;
return;
}
printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout " printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
"-rpcwait -action- ---ops--\n"); "-rpcwait -action- ---ops--\n");
alltask_for_each(t, le, &all_tasks) { list_for_each_entry(clnt, &all_clients, cl_clients) {
list_for_each_entry(t, &clnt->cl_tasks, tk_task) {
const char *rpc_waitq = "none"; const char *rpc_waitq = "none";
if (RPC_IS_QUEUED(t)) if (RPC_IS_QUEUED(t))
...@@ -1097,6 +1126,8 @@ void rpc_show_tasks(void) ...@@ -1097,6 +1126,8 @@ void rpc_show_tasks(void)
rpc_waitq, rpc_waitq,
t->tk_action, t->tk_ops); t->tk_action, t->tk_ops);
} }
}
out:
spin_unlock(&rpc_sched_lock); spin_unlock(&rpc_sched_lock);
} }
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment