aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/clnt.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-06-14 16:40:31 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-07-10 23:40:28 -0400
commit34f52e3591f241b825353ba27def956d8487c400 (patch)
tree9f7f0cd52f206095217bd2469e31c2531cbae0a4 /net/sunrpc/clnt.c
parentc44fe705530ff9ea5e563bf9b65bdd29defe682b (diff)
SUNRPC: Convert rpc_clnt->cl_users to a kref
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/clnt.c')
-rw-r--r--net/sunrpc/clnt.c57
1 files changed, 28 insertions, 29 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 424dfdc6862c..254a6e1a5770 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -121,7 +121,6 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
121 clnt = kzalloc(sizeof(*clnt), GFP_KERNEL); 121 clnt = kzalloc(sizeof(*clnt), GFP_KERNEL);
122 if (!clnt) 122 if (!clnt)
123 goto out_err; 123 goto out_err;
124 atomic_set(&clnt->cl_users, 0);
125 atomic_set(&clnt->cl_count, 1); 124 atomic_set(&clnt->cl_count, 1);
126 clnt->cl_parent = clnt; 125 clnt->cl_parent = clnt;
127 126
@@ -157,6 +156,8 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s
157 clnt->cl_rtt = &clnt->cl_rtt_default; 156 clnt->cl_rtt = &clnt->cl_rtt_default;
158 rpc_init_rtt(&clnt->cl_rtt_default, xprt->timeout.to_initval); 157 rpc_init_rtt(&clnt->cl_rtt_default, xprt->timeout.to_initval);
159 158
159 kref_init(&clnt->cl_kref);
160
160 err = rpc_setup_pipedir(clnt, program->pipe_dir_name); 161 err = rpc_setup_pipedir(clnt, program->pipe_dir_name);
161 if (err < 0) 162 if (err < 0)
162 goto out_no_path; 163 goto out_no_path;
@@ -272,10 +273,10 @@ rpc_clone_client(struct rpc_clnt *clnt)
272 if (!new) 273 if (!new)
273 goto out_no_clnt; 274 goto out_no_clnt;
274 atomic_set(&new->cl_count, 1); 275 atomic_set(&new->cl_count, 1);
275 atomic_set(&new->cl_users, 0);
276 new->cl_metrics = rpc_alloc_iostats(clnt); 276 new->cl_metrics = rpc_alloc_iostats(clnt);
277 if (new->cl_metrics == NULL) 277 if (new->cl_metrics == NULL)
278 goto out_no_stats; 278 goto out_no_stats;
279 kref_init(&new->cl_kref);
279 err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); 280 err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name);
280 if (err != 0) 281 if (err != 0)
281 goto out_no_path; 282 goto out_no_path;
@@ -311,40 +312,28 @@ out_no_clnt:
311int 312int
312rpc_shutdown_client(struct rpc_clnt *clnt) 313rpc_shutdown_client(struct rpc_clnt *clnt)
313{ 314{
314 dprintk("RPC: shutting down %s client for %s, tasks=%d\n", 315 dprintk("RPC: shutting down %s client for %s\n",
315 clnt->cl_protname, clnt->cl_server, 316 clnt->cl_protname, clnt->cl_server);
316 atomic_read(&clnt->cl_users));
317 317
318 while (atomic_read(&clnt->cl_users) > 0) { 318 while (!list_empty(&clnt->cl_tasks)) {
319 /* Don't let rpc_release_client destroy us */ 319 /* Don't let rpc_release_client destroy us */
320 clnt->cl_oneshot = 0; 320 clnt->cl_oneshot = 0;
321 clnt->cl_dead = 0; 321 clnt->cl_dead = 0;
322 rpc_killall_tasks(clnt); 322 rpc_killall_tasks(clnt);
323 wait_event_timeout(destroy_wait, 323 wait_event_timeout(destroy_wait,
324 !atomic_read(&clnt->cl_users), 1*HZ); 324 list_empty(&clnt->cl_tasks), 1*HZ);
325 }
326
327 if (atomic_read(&clnt->cl_users) < 0) {
328 printk(KERN_ERR "RPC: rpc_shutdown_client clnt %p tasks=%d\n",
329 clnt, atomic_read(&clnt->cl_users));
330#ifdef RPC_DEBUG
331 rpc_show_tasks();
332#endif
333 BUG();
334 } 325 }
335 326
336 return rpc_destroy_client(clnt); 327 return rpc_destroy_client(clnt);
337} 328}
338 329
339/* 330/*
340 * Delete an RPC client 331 * Free an RPC client
341 */ 332 */
342int 333static void
343rpc_destroy_client(struct rpc_clnt *clnt) 334rpc_free_client(struct kref *kref)
344{ 335{
345 if (!atomic_dec_and_test(&clnt->cl_count)) 336 struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref);
346 return 1;
347 BUG_ON(atomic_read(&clnt->cl_users) != 0);
348 337
349 dprintk("RPC: destroying %s client for %s\n", 338 dprintk("RPC: destroying %s client for %s\n",
350 clnt->cl_protname, clnt->cl_server); 339 clnt->cl_protname, clnt->cl_server);
@@ -368,23 +357,33 @@ out_free:
368 clnt->cl_metrics = NULL; 357 clnt->cl_metrics = NULL;
369 xprt_put(clnt->cl_xprt); 358 xprt_put(clnt->cl_xprt);
370 kfree(clnt); 359 kfree(clnt);
371 return 0;
372} 360}
373 361
374/* 362/*
375 * Release an RPC client 363 * Release reference to the RPC client
376 */ 364 */
377void 365void
378rpc_release_client(struct rpc_clnt *clnt) 366rpc_release_client(struct rpc_clnt *clnt)
379{ 367{
380 dprintk("RPC: rpc_release_client(%p, %d)\n", 368 dprintk("RPC: rpc_release_client(%p)\n", clnt);
381 clnt, atomic_read(&clnt->cl_users));
382 369
383 if (!atomic_dec_and_test(&clnt->cl_users)) 370 if (list_empty(&clnt->cl_tasks))
384 return; 371 wake_up(&destroy_wait);
385 wake_up(&destroy_wait);
386 if (clnt->cl_oneshot || clnt->cl_dead) 372 if (clnt->cl_oneshot || clnt->cl_dead)
387 rpc_destroy_client(clnt); 373 rpc_destroy_client(clnt);
374 kref_put(&clnt->cl_kref, rpc_free_client);
375}
376
377/*
378 * Delete an RPC client
379 */
380int
381rpc_destroy_client(struct rpc_clnt *clnt)
382{
383 if (!atomic_dec_and_test(&clnt->cl_count))
384 return 1;
385 kref_put(&clnt->cl_kref, rpc_free_client);
386 return 0;
388} 387}
389 388
390/** 389/**