aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sunrpc/clnt.h4
-rw-r--r--include/linux/sunrpc/sched.h5
-rw-r--r--net/sunrpc/clnt.c5
-rw-r--r--net/sunrpc/sched.c117
4 files changed, 83 insertions, 48 deletions
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
index 66611423c8ee..0801ab5407ce 100644
--- a/include/linux/sunrpc/clnt.h
+++ b/include/linux/sunrpc/clnt.h
@@ -26,6 +26,8 @@ struct rpc_inode;
26struct rpc_clnt { 26struct rpc_clnt {
27 atomic_t cl_count; /* Number of clones */ 27 atomic_t cl_count; /* Number of clones */
28 atomic_t cl_users; /* number of references */ 28 atomic_t cl_users; /* number of references */
29 struct list_head cl_clients; /* Global list of clients */
30 struct list_head cl_tasks; /* List of tasks */
29 struct rpc_xprt * cl_xprt; /* transport */ 31 struct rpc_xprt * cl_xprt; /* transport */
30 struct rpc_procinfo * cl_procinfo; /* procedure info */ 32 struct rpc_procinfo * cl_procinfo; /* procedure info */
31 u32 cl_prog, /* RPC program number */ 33 u32 cl_prog, /* RPC program number */
@@ -122,6 +124,8 @@ struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
122int rpc_shutdown_client(struct rpc_clnt *); 124int rpc_shutdown_client(struct rpc_clnt *);
123int rpc_destroy_client(struct rpc_clnt *); 125int rpc_destroy_client(struct rpc_clnt *);
124void rpc_release_client(struct rpc_clnt *); 126void rpc_release_client(struct rpc_clnt *);
127void rpc_register_client(struct rpc_clnt *);
128void rpc_unregister_client(struct rpc_clnt *);
125int rpcb_register(u32, u32, int, unsigned short, int *); 129int rpcb_register(u32, u32, int, unsigned short, int *);
126void rpcb_getport(struct rpc_task *); 130void rpcb_getport(struct rpc_task *);
127 131
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 2047fb202a13..3387b008cdfc 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -110,11 +110,6 @@ struct rpc_task {
110 if (!list_empty(head) && \ 110 if (!list_empty(head) && \
111 ((task=list_entry((head)->next, struct rpc_task, u.tk_wait.list)),1)) 111 ((task=list_entry((head)->next, struct rpc_task, u.tk_wait.list)),1))
112 112
113/* .. and walking list of all tasks */
114#define alltask_for_each(task, pos, head) \
115 list_for_each(pos, head) \
116 if ((task=list_entry(pos, struct rpc_task, tk_task)),1)
117
118typedef void (*rpc_action)(struct rpc_task *); 113typedef void (*rpc_action)(struct rpc_task *);
119 114
120struct rpc_call_ops { 115struct rpc_call_ops {
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index d8fbee40a19c..6631ece14983 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -148,6 +148,7 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
148 if (clnt->cl_metrics == NULL) 148 if (clnt->cl_metrics == NULL)
149 goto out_no_stats; 149 goto out_no_stats;
150 clnt->cl_program = program; 150 clnt->cl_program = program;
151 INIT_LIST_HEAD(&clnt->cl_tasks);
151 152
152 if (!xprt_bound(clnt->cl_xprt)) 153 if (!xprt_bound(clnt->cl_xprt))
153 clnt->cl_autobind = 1; 154 clnt->cl_autobind = 1;
@@ -172,6 +173,7 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
172 if (clnt->cl_nodelen > UNX_MAXNODENAME) 173 if (clnt->cl_nodelen > UNX_MAXNODENAME)
173 clnt->cl_nodelen = UNX_MAXNODENAME; 174 clnt->cl_nodelen = UNX_MAXNODENAME;
174 memcpy(clnt->cl_nodename, utsname()->nodename, clnt->cl_nodelen); 175 memcpy(clnt->cl_nodename, utsname()->nodename, clnt->cl_nodelen);
176 rpc_register_client(clnt);
175 return clnt; 177 return clnt;
176 178
177out_no_auth: 179out_no_auth:
@@ -283,9 +285,11 @@ rpc_clone_client(struct rpc_clnt *clnt)
283 new->cl_autobind = 0; 285 new->cl_autobind = 0;
284 new->cl_oneshot = 0; 286 new->cl_oneshot = 0;
285 new->cl_dead = 0; 287 new->cl_dead = 0;
288 INIT_LIST_HEAD(&new->cl_tasks);
286 rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); 289 rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval);
287 if (new->cl_auth) 290 if (new->cl_auth)
288 atomic_inc(&new->cl_auth->au_count); 291 atomic_inc(&new->cl_auth->au_count);
292 rpc_register_client(new);
289 return new; 293 return new;
290out_no_path: 294out_no_path:
291 rpc_free_iostats(new->cl_metrics); 295 rpc_free_iostats(new->cl_metrics);
@@ -357,6 +361,7 @@ rpc_destroy_client(struct rpc_clnt *clnt)
357 if (clnt->cl_server != clnt->cl_inline_name) 361 if (clnt->cl_server != clnt->cl_inline_name)
358 kfree(clnt->cl_server); 362 kfree(clnt->cl_server);
359out_free: 363out_free:
364 rpc_unregister_client(clnt);
360 rpc_free_iostats(clnt->cl_metrics); 365 rpc_free_iostats(clnt->cl_metrics);
361 clnt->cl_metrics = NULL; 366 clnt->cl_metrics = NULL;
362 xprt_put(clnt->cl_xprt); 367 xprt_put(clnt->cl_xprt);
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 944d75396fb3..6309f3b52c53 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -50,9 +50,10 @@ static void rpc_release_task(struct rpc_task *task);
50static RPC_WAITQ(delay_queue, "delayq"); 50static RPC_WAITQ(delay_queue, "delayq");
51 51
52/* 52/*
53 * All RPC tasks are linked into this list 53 * All RPC clients are linked into this list
54 */ 54 */
55static LIST_HEAD(all_tasks); 55static LIST_HEAD(all_clients);
56static DECLARE_WAIT_QUEUE_HEAD(client_kill_wait);
56 57
57/* 58/*
58 * rpciod-related stuff 59 * rpciod-related stuff
@@ -277,7 +278,8 @@ static void rpc_set_active(struct rpc_task *task)
277 task->tk_pid = rpc_task_id++; 278 task->tk_pid = rpc_task_id++;
278#endif 279#endif
279 /* Add to global list of all tasks */ 280 /* Add to global list of all tasks */
280 list_add_tail(&task->tk_task, &all_tasks); 281 if (task->tk_client)
282 list_add_tail(&task->tk_task, &task->tk_client->cl_tasks);
281 spin_unlock(&rpc_sched_lock); 283 spin_unlock(&rpc_sched_lock);
282} 284}
283 285
@@ -818,6 +820,7 @@ void rpc_init_task(struct rpc_task *task, struct rpc_clnt *clnt, int flags, cons
818 if (tk_ops->rpc_call_prepare != NULL) 820 if (tk_ops->rpc_call_prepare != NULL)
819 task->tk_action = rpc_prepare_task; 821 task->tk_action = rpc_prepare_task;
820 task->tk_calldata = calldata; 822 task->tk_calldata = calldata;
823 INIT_LIST_HEAD(&task->tk_task);
821 824
822 /* Initialize retry counters */ 825 /* Initialize retry counters */
823 task->tk_garb_retry = 2; 826 task->tk_garb_retry = 2;
@@ -920,11 +923,12 @@ static void rpc_release_task(struct rpc_task *task)
920#endif 923#endif
921 dprintk("RPC: %5u release task\n", task->tk_pid); 924 dprintk("RPC: %5u release task\n", task->tk_pid);
922 925
923 /* Remove from global task list */ 926 if (!list_empty(&task->tk_task)) {
924 spin_lock(&rpc_sched_lock); 927 /* Remove from client task list */
925 list_del(&task->tk_task); 928 spin_lock(&rpc_sched_lock);
926 spin_unlock(&rpc_sched_lock); 929 list_del(&task->tk_task);
927 930 spin_unlock(&rpc_sched_lock);
931 }
928 BUG_ON (RPC_IS_QUEUED(task)); 932 BUG_ON (RPC_IS_QUEUED(task));
929 933
930 /* Synchronously delete any running timer */ 934 /* Synchronously delete any running timer */
@@ -966,42 +970,52 @@ EXPORT_SYMBOL(rpc_run_task);
966 * Kill all tasks for the given client. 970 * Kill all tasks for the given client.
967 * XXX: kill their descendants as well? 971 * XXX: kill their descendants as well?
968 */ 972 */
969void rpc_killall_tasks(struct rpc_clnt *clnt) 973static void rpc_killall_tasks_locked(struct list_head *head)
970{ 974{
971 struct rpc_task *rovr; 975 struct rpc_task *rovr;
972 struct list_head *le;
973 976
974 dprintk("RPC: killing all tasks for client %p\n", clnt);
975 977
976 /* 978 list_for_each_entry(rovr, head, tk_task) {
977 * Spin lock all_tasks to prevent changes...
978 */
979 spin_lock(&rpc_sched_lock);
980 alltask_for_each(rovr, le, &all_tasks) {
981 if (! RPC_IS_ACTIVATED(rovr)) 979 if (! RPC_IS_ACTIVATED(rovr))
982 continue; 980 continue;
983 if (!clnt || rovr->tk_client == clnt) { 981 if (!(rovr->tk_flags & RPC_TASK_KILLED)) {
984 rovr->tk_flags |= RPC_TASK_KILLED; 982 rovr->tk_flags |= RPC_TASK_KILLED;
985 rpc_exit(rovr, -EIO); 983 rpc_exit(rovr, -EIO);
986 rpc_wake_up_task(rovr); 984 rpc_wake_up_task(rovr);
987 } 985 }
988 } 986 }
987}
988
989void rpc_killall_tasks(struct rpc_clnt *clnt)
990{
991 dprintk("RPC: killing all tasks for client %p\n", clnt);
992 /*
993 * Spin lock all_tasks to prevent changes...
994 */
995 spin_lock(&rpc_sched_lock);
996 rpc_killall_tasks_locked(&clnt->cl_tasks);
989 spin_unlock(&rpc_sched_lock); 997 spin_unlock(&rpc_sched_lock);
990} 998}
991 999
992static void rpciod_killall(void) 1000static void rpciod_killall(void)
993{ 1001{
1002 struct rpc_clnt *clnt;
994 unsigned long flags; 1003 unsigned long flags;
995 1004
996 while (!list_empty(&all_tasks)) { 1005 for(;;) {
997 clear_thread_flag(TIF_SIGPENDING); 1006 clear_thread_flag(TIF_SIGPENDING);
998 rpc_killall_tasks(NULL); 1007
1008 spin_lock(&rpc_sched_lock);
1009 list_for_each_entry(clnt, &all_clients, cl_clients)
1010 rpc_killall_tasks_locked(&clnt->cl_tasks);
1011 spin_unlock(&rpc_sched_lock);
999 flush_workqueue(rpciod_workqueue); 1012 flush_workqueue(rpciod_workqueue);
1000 if (!list_empty(&all_tasks)) { 1013 if (!list_empty(&all_clients))
1001 dprintk("RPC: rpciod_killall: waiting for tasks " 1014 break;
1015 dprintk("RPC: rpciod_killall: waiting for tasks "
1002 "to exit\n"); 1016 "to exit\n");
1003 yield(); 1017 wait_event_timeout(client_kill_wait,
1004 } 1018 list_empty(&all_clients), 1*HZ);
1005 } 1019 }
1006 1020
1007 spin_lock_irqsave(&current->sighand->siglock, flags); 1021 spin_lock_irqsave(&current->sighand->siglock, flags);
@@ -1009,6 +1023,22 @@ static void rpciod_killall(void)
1009 spin_unlock_irqrestore(&current->sighand->siglock, flags); 1023 spin_unlock_irqrestore(&current->sighand->siglock, flags);
1010} 1024}
1011 1025
1026void rpc_register_client(struct rpc_clnt *clnt)
1027{
1028 spin_lock(&rpc_sched_lock);
1029 list_add(&clnt->cl_clients, &all_clients);
1030 spin_unlock(&rpc_sched_lock);
1031}
1032
1033void rpc_unregister_client(struct rpc_clnt *clnt)
1034{
1035 spin_lock(&rpc_sched_lock);
1036 list_del(&clnt->cl_clients);
1037 if (list_empty(&all_clients))
1038 wake_up(&client_kill_wait);
1039 spin_unlock(&rpc_sched_lock);
1040}
1041
1012/* 1042/*
1013 * Start up the rpciod process if it's not already running. 1043 * Start up the rpciod process if it's not already running.
1014 */ 1044 */
@@ -1071,32 +1101,33 @@ rpciod_down(void)
1071#ifdef RPC_DEBUG 1101#ifdef RPC_DEBUG
1072void rpc_show_tasks(void) 1102void rpc_show_tasks(void)
1073{ 1103{
1074 struct list_head *le; 1104 struct rpc_clnt *clnt;
1075 struct rpc_task *t; 1105 struct rpc_task *t;
1076 1106
1077 spin_lock(&rpc_sched_lock); 1107 spin_lock(&rpc_sched_lock);
1078 if (list_empty(&all_tasks)) { 1108 if (list_empty(&all_clients))
1079 spin_unlock(&rpc_sched_lock); 1109 goto out;
1080 return;
1081 }
1082 printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout " 1110 printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout "
1083 "-rpcwait -action- ---ops--\n"); 1111 "-rpcwait -action- ---ops--\n");
1084 alltask_for_each(t, le, &all_tasks) { 1112 list_for_each_entry(clnt, &all_clients, cl_clients) {
1085 const char *rpc_waitq = "none"; 1113 list_for_each_entry(t, &clnt->cl_tasks, tk_task) {
1086 1114 const char *rpc_waitq = "none";
1087 if (RPC_IS_QUEUED(t)) 1115
1088 rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq); 1116 if (RPC_IS_QUEUED(t))
1089 1117 rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq);
1090 printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n", 1118
1091 t->tk_pid, 1119 printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n",
1092 (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1), 1120 t->tk_pid,
1093 t->tk_flags, t->tk_status, 1121 (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1),
1094 t->tk_client, 1122 t->tk_flags, t->tk_status,
1095 (t->tk_client ? t->tk_client->cl_prog : 0), 1123 t->tk_client,
1096 t->tk_rqstp, t->tk_timeout, 1124 (t->tk_client ? t->tk_client->cl_prog : 0),
1097 rpc_waitq, 1125 t->tk_rqstp, t->tk_timeout,
1098 t->tk_action, t->tk_ops); 1126 rpc_waitq,
1127 t->tk_action, t->tk_ops);
1128 }
1099 } 1129 }
1130out:
1100 spin_unlock(&rpc_sched_lock); 1131 spin_unlock(&rpc_sched_lock);
1101} 1132}
1102#endif 1133#endif