diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-06-16 14:17:01 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-07-10 23:40:28 -0400 |
commit | 4bef61ff7514396419563ca54fd42ef846485b06 (patch) | |
tree | 5ea7eca032557a8ae307661b8c2b887fac257476 /net | |
parent | 6529eba08fe7297852391a468d95322913de73fa (diff) |
SUNRPC: Add a per-rpc_clnt spinlock
Use that to protect the rpc_clnt->cl_tasks list instead of using a global
lock.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/clnt.c | 2 | ||||
-rw-r--r-- | net/sunrpc/sched.c | 47 |
2 files changed, 29 insertions, 20 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 6631ece14983..424dfdc6862c 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -149,6 +149,7 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
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 | INIT_LIST_HEAD(&clnt->cl_tasks); |
152 | spin_lock_init(&clnt->cl_lock); | ||
152 | 153 | ||
153 | if (!xprt_bound(clnt->cl_xprt)) | 154 | if (!xprt_bound(clnt->cl_xprt)) |
154 | clnt->cl_autobind = 1; | 155 | clnt->cl_autobind = 1; |
@@ -286,6 +287,7 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
286 | new->cl_oneshot = 0; | 287 | new->cl_oneshot = 0; |
287 | new->cl_dead = 0; | 288 | new->cl_dead = 0; |
288 | INIT_LIST_HEAD(&new->cl_tasks); | 289 | INIT_LIST_HEAD(&new->cl_tasks); |
290 | spin_lock_init(&new->cl_lock); | ||
289 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); | 291 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); |
290 | if (new->cl_auth) | 292 | if (new->cl_auth) |
291 | atomic_inc(&new->cl_auth->au_count); | 293 | atomic_inc(&new->cl_auth->au_count); |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 6309f3b52c53..f56ebc5a08f7 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -270,17 +270,22 @@ static int rpc_wait_bit_interruptible(void *word) | |||
270 | 270 | ||
271 | static void rpc_set_active(struct rpc_task *task) | 271 | static void rpc_set_active(struct rpc_task *task) |
272 | { | 272 | { |
273 | struct rpc_clnt *clnt; | ||
273 | if (test_and_set_bit(RPC_TASK_ACTIVE, &task->tk_runstate) != 0) | 274 | if (test_and_set_bit(RPC_TASK_ACTIVE, &task->tk_runstate) != 0) |
274 | return; | 275 | return; |
275 | spin_lock(&rpc_sched_lock); | ||
276 | #ifdef RPC_DEBUG | 276 | #ifdef RPC_DEBUG |
277 | task->tk_magic = RPC_TASK_MAGIC_ID; | 277 | task->tk_magic = RPC_TASK_MAGIC_ID; |
278 | spin_lock(&rpc_sched_lock); | ||
278 | task->tk_pid = rpc_task_id++; | 279 | task->tk_pid = rpc_task_id++; |
280 | spin_unlock(&rpc_sched_lock); | ||
279 | #endif | 281 | #endif |
280 | /* Add to global list of all tasks */ | 282 | /* Add to global list of all tasks */ |
281 | if (task->tk_client) | 283 | clnt = task->tk_client; |
282 | list_add_tail(&task->tk_task, &task->tk_client->cl_tasks); | 284 | if (clnt != NULL) { |
283 | spin_unlock(&rpc_sched_lock); | 285 | spin_lock(&clnt->cl_lock); |
286 | list_add_tail(&task->tk_task, &clnt->cl_tasks); | ||
287 | spin_unlock(&clnt->cl_lock); | ||
288 | } | ||
284 | } | 289 | } |
285 | 290 | ||
286 | /* | 291 | /* |
@@ -924,10 +929,11 @@ static void rpc_release_task(struct rpc_task *task) | |||
924 | dprintk("RPC: %5u release task\n", task->tk_pid); | 929 | dprintk("RPC: %5u release task\n", task->tk_pid); |
925 | 930 | ||
926 | if (!list_empty(&task->tk_task)) { | 931 | if (!list_empty(&task->tk_task)) { |
932 | struct rpc_clnt *clnt = task->tk_client; | ||
927 | /* Remove from client task list */ | 933 | /* Remove from client task list */ |
928 | spin_lock(&rpc_sched_lock); | 934 | spin_lock(&clnt->cl_lock); |
929 | list_del(&task->tk_task); | 935 | list_del(&task->tk_task); |
930 | spin_unlock(&rpc_sched_lock); | 936 | spin_unlock(&clnt->cl_lock); |
931 | } | 937 | } |
932 | BUG_ON (RPC_IS_QUEUED(task)); | 938 | BUG_ON (RPC_IS_QUEUED(task)); |
933 | 939 | ||
@@ -970,12 +976,19 @@ EXPORT_SYMBOL(rpc_run_task); | |||
970 | * Kill all tasks for the given client. | 976 | * Kill all tasks for the given client. |
971 | * XXX: kill their descendants as well? | 977 | * XXX: kill their descendants as well? |
972 | */ | 978 | */ |
973 | static void rpc_killall_tasks_locked(struct list_head *head) | 979 | void rpc_killall_tasks(struct rpc_clnt *clnt) |
974 | { | 980 | { |
975 | struct rpc_task *rovr; | 981 | struct rpc_task *rovr; |
976 | 982 | ||
977 | 983 | ||
978 | list_for_each_entry(rovr, head, tk_task) { | 984 | if (list_empty(&clnt->cl_tasks)) |
985 | return; | ||
986 | dprintk("RPC: killing all tasks for client %p\n", clnt); | ||
987 | /* | ||
988 | * Spin lock all_tasks to prevent changes... | ||
989 | */ | ||
990 | spin_lock(&clnt->cl_lock); | ||
991 | list_for_each_entry(rovr, &clnt->cl_tasks, tk_task) { | ||
979 | if (! RPC_IS_ACTIVATED(rovr)) | 992 | if (! RPC_IS_ACTIVATED(rovr)) |
980 | continue; | 993 | continue; |
981 | if (!(rovr->tk_flags & RPC_TASK_KILLED)) { | 994 | if (!(rovr->tk_flags & RPC_TASK_KILLED)) { |
@@ -984,17 +997,7 @@ static void rpc_killall_tasks_locked(struct list_head *head) | |||
984 | rpc_wake_up_task(rovr); | 997 | rpc_wake_up_task(rovr); |
985 | } | 998 | } |
986 | } | 999 | } |
987 | } | 1000 | spin_unlock(&clnt->cl_lock); |
988 | |||
989 | void 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); | ||
997 | spin_unlock(&rpc_sched_lock); | ||
998 | } | 1001 | } |
999 | 1002 | ||
1000 | static void rpciod_killall(void) | 1003 | static void rpciod_killall(void) |
@@ -1007,7 +1010,7 @@ static void rpciod_killall(void) | |||
1007 | 1010 | ||
1008 | spin_lock(&rpc_sched_lock); | 1011 | spin_lock(&rpc_sched_lock); |
1009 | list_for_each_entry(clnt, &all_clients, cl_clients) | 1012 | list_for_each_entry(clnt, &all_clients, cl_clients) |
1010 | rpc_killall_tasks_locked(&clnt->cl_tasks); | 1013 | rpc_killall_tasks(clnt); |
1011 | spin_unlock(&rpc_sched_lock); | 1014 | spin_unlock(&rpc_sched_lock); |
1012 | flush_workqueue(rpciod_workqueue); | 1015 | flush_workqueue(rpciod_workqueue); |
1013 | if (!list_empty(&all_clients)) | 1016 | if (!list_empty(&all_clients)) |
@@ -1110,6 +1113,9 @@ void rpc_show_tasks(void) | |||
1110 | printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout " | 1113 | printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout " |
1111 | "-rpcwait -action- ---ops--\n"); | 1114 | "-rpcwait -action- ---ops--\n"); |
1112 | list_for_each_entry(clnt, &all_clients, cl_clients) { | 1115 | list_for_each_entry(clnt, &all_clients, cl_clients) { |
1116 | if (list_empty(&clnt->cl_tasks)) | ||
1117 | continue; | ||
1118 | spin_lock(&clnt->cl_lock); | ||
1113 | list_for_each_entry(t, &clnt->cl_tasks, tk_task) { | 1119 | list_for_each_entry(t, &clnt->cl_tasks, tk_task) { |
1114 | const char *rpc_waitq = "none"; | 1120 | const char *rpc_waitq = "none"; |
1115 | 1121 | ||
@@ -1126,6 +1132,7 @@ void rpc_show_tasks(void) | |||
1126 | rpc_waitq, | 1132 | rpc_waitq, |
1127 | t->tk_action, t->tk_ops); | 1133 | t->tk_action, t->tk_ops); |
1128 | } | 1134 | } |
1135 | spin_unlock(&clnt->cl_lock); | ||
1129 | } | 1136 | } |
1130 | out: | 1137 | out: |
1131 | spin_unlock(&rpc_sched_lock); | 1138 | spin_unlock(&rpc_sched_lock); |