diff options
Diffstat (limited to 'net/sunrpc/clnt.c')
-rw-r--r-- | net/sunrpc/clnt.c | 371 |
1 files changed, 241 insertions, 130 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index d8fbee40a19c..52429b1ffcc1 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -44,6 +44,12 @@ | |||
44 | dprintk("RPC: %5u %s (status %d)\n", t->tk_pid, \ | 44 | dprintk("RPC: %5u %s (status %d)\n", t->tk_pid, \ |
45 | __FUNCTION__, t->tk_status) | 45 | __FUNCTION__, t->tk_status) |
46 | 46 | ||
47 | /* | ||
48 | * All RPC clients are linked into this list | ||
49 | */ | ||
50 | static LIST_HEAD(all_clients); | ||
51 | static DEFINE_SPINLOCK(rpc_client_lock); | ||
52 | |||
47 | static DECLARE_WAIT_QUEUE_HEAD(destroy_wait); | 53 | static DECLARE_WAIT_QUEUE_HEAD(destroy_wait); |
48 | 54 | ||
49 | 55 | ||
@@ -66,6 +72,21 @@ static void call_connect_status(struct rpc_task *task); | |||
66 | static __be32 * call_header(struct rpc_task *task); | 72 | static __be32 * call_header(struct rpc_task *task); |
67 | static __be32 * call_verify(struct rpc_task *task); | 73 | static __be32 * call_verify(struct rpc_task *task); |
68 | 74 | ||
75 | static int rpc_ping(struct rpc_clnt *clnt, int flags); | ||
76 | |||
77 | static void rpc_register_client(struct rpc_clnt *clnt) | ||
78 | { | ||
79 | spin_lock(&rpc_client_lock); | ||
80 | list_add(&clnt->cl_clients, &all_clients); | ||
81 | spin_unlock(&rpc_client_lock); | ||
82 | } | ||
83 | |||
84 | static void rpc_unregister_client(struct rpc_clnt *clnt) | ||
85 | { | ||
86 | spin_lock(&rpc_client_lock); | ||
87 | list_del(&clnt->cl_clients); | ||
88 | spin_unlock(&rpc_client_lock); | ||
89 | } | ||
69 | 90 | ||
70 | static int | 91 | static int |
71 | rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) | 92 | rpc_setup_pipedir(struct rpc_clnt *clnt, char *dir_name) |
@@ -111,6 +132,9 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
111 | dprintk("RPC: creating %s client for %s (xprt %p)\n", | 132 | dprintk("RPC: creating %s client for %s (xprt %p)\n", |
112 | program->name, servname, xprt); | 133 | program->name, servname, xprt); |
113 | 134 | ||
135 | err = rpciod_up(); | ||
136 | if (err) | ||
137 | goto out_no_rpciod; | ||
114 | err = -EINVAL; | 138 | err = -EINVAL; |
115 | if (!xprt) | 139 | if (!xprt) |
116 | goto out_no_xprt; | 140 | goto out_no_xprt; |
@@ -121,8 +145,6 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
121 | clnt = kzalloc(sizeof(*clnt), GFP_KERNEL); | 145 | clnt = kzalloc(sizeof(*clnt), GFP_KERNEL); |
122 | if (!clnt) | 146 | if (!clnt) |
123 | goto out_err; | 147 | goto out_err; |
124 | atomic_set(&clnt->cl_users, 0); | ||
125 | atomic_set(&clnt->cl_count, 1); | ||
126 | clnt->cl_parent = clnt; | 148 | clnt->cl_parent = clnt; |
127 | 149 | ||
128 | clnt->cl_server = clnt->cl_inline_name; | 150 | clnt->cl_server = clnt->cl_inline_name; |
@@ -148,6 +170,8 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
148 | if (clnt->cl_metrics == NULL) | 170 | if (clnt->cl_metrics == NULL) |
149 | goto out_no_stats; | 171 | goto out_no_stats; |
150 | clnt->cl_program = program; | 172 | clnt->cl_program = program; |
173 | INIT_LIST_HEAD(&clnt->cl_tasks); | ||
174 | spin_lock_init(&clnt->cl_lock); | ||
151 | 175 | ||
152 | if (!xprt_bound(clnt->cl_xprt)) | 176 | if (!xprt_bound(clnt->cl_xprt)) |
153 | clnt->cl_autobind = 1; | 177 | clnt->cl_autobind = 1; |
@@ -155,6 +179,8 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
155 | clnt->cl_rtt = &clnt->cl_rtt_default; | 179 | clnt->cl_rtt = &clnt->cl_rtt_default; |
156 | rpc_init_rtt(&clnt->cl_rtt_default, xprt->timeout.to_initval); | 180 | rpc_init_rtt(&clnt->cl_rtt_default, xprt->timeout.to_initval); |
157 | 181 | ||
182 | kref_init(&clnt->cl_kref); | ||
183 | |||
158 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); | 184 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); |
159 | if (err < 0) | 185 | if (err < 0) |
160 | goto out_no_path; | 186 | goto out_no_path; |
@@ -172,6 +198,7 @@ static struct rpc_clnt * rpc_new_client(struct rpc_xprt *xprt, char *servname, s | |||
172 | if (clnt->cl_nodelen > UNX_MAXNODENAME) | 198 | if (clnt->cl_nodelen > UNX_MAXNODENAME) |
173 | clnt->cl_nodelen = UNX_MAXNODENAME; | 199 | clnt->cl_nodelen = UNX_MAXNODENAME; |
174 | memcpy(clnt->cl_nodename, utsname()->nodename, clnt->cl_nodelen); | 200 | memcpy(clnt->cl_nodename, utsname()->nodename, clnt->cl_nodelen); |
201 | rpc_register_client(clnt); | ||
175 | return clnt; | 202 | return clnt; |
176 | 203 | ||
177 | out_no_auth: | 204 | out_no_auth: |
@@ -188,6 +215,8 @@ out_no_stats: | |||
188 | out_err: | 215 | out_err: |
189 | xprt_put(xprt); | 216 | xprt_put(xprt); |
190 | out_no_xprt: | 217 | out_no_xprt: |
218 | rpciod_down(); | ||
219 | out_no_rpciod: | ||
191 | return ERR_PTR(err); | 220 | return ERR_PTR(err); |
192 | } | 221 | } |
193 | 222 | ||
@@ -205,13 +234,32 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
205 | { | 234 | { |
206 | struct rpc_xprt *xprt; | 235 | struct rpc_xprt *xprt; |
207 | struct rpc_clnt *clnt; | 236 | struct rpc_clnt *clnt; |
237 | struct rpc_xprtsock_create xprtargs = { | ||
238 | .proto = args->protocol, | ||
239 | .srcaddr = args->saddress, | ||
240 | .dstaddr = args->address, | ||
241 | .addrlen = args->addrsize, | ||
242 | .timeout = args->timeout | ||
243 | }; | ||
244 | char servername[20]; | ||
208 | 245 | ||
209 | xprt = xprt_create_transport(args->protocol, args->address, | 246 | xprt = xprt_create_transport(&xprtargs); |
210 | args->addrsize, args->timeout); | ||
211 | if (IS_ERR(xprt)) | 247 | if (IS_ERR(xprt)) |
212 | return (struct rpc_clnt *)xprt; | 248 | return (struct rpc_clnt *)xprt; |
213 | 249 | ||
214 | /* | 250 | /* |
251 | * If the caller chooses not to specify a hostname, whip | ||
252 | * up a string representation of the passed-in address. | ||
253 | */ | ||
254 | if (args->servername == NULL) { | ||
255 | struct sockaddr_in *addr = | ||
256 | (struct sockaddr_in *) &args->address; | ||
257 | snprintf(servername, sizeof(servername), NIPQUAD_FMT, | ||
258 | NIPQUAD(addr->sin_addr.s_addr)); | ||
259 | args->servername = servername; | ||
260 | } | ||
261 | |||
262 | /* | ||
215 | * By default, kernel RPC client connects from a reserved port. | 263 | * By default, kernel RPC client connects from a reserved port. |
216 | * CAP_NET_BIND_SERVICE will not be set for unprivileged requesters, | 264 | * CAP_NET_BIND_SERVICE will not be set for unprivileged requesters, |
217 | * but it is always enabled for rpciod, which handles the connect | 265 | * but it is always enabled for rpciod, which handles the connect |
@@ -245,8 +293,6 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
245 | clnt->cl_intr = 1; | 293 | clnt->cl_intr = 1; |
246 | if (args->flags & RPC_CLNT_CREATE_AUTOBIND) | 294 | if (args->flags & RPC_CLNT_CREATE_AUTOBIND) |
247 | clnt->cl_autobind = 1; | 295 | clnt->cl_autobind = 1; |
248 | if (args->flags & RPC_CLNT_CREATE_ONESHOT) | ||
249 | clnt->cl_oneshot = 1; | ||
250 | if (args->flags & RPC_CLNT_CREATE_DISCRTRY) | 296 | if (args->flags & RPC_CLNT_CREATE_DISCRTRY) |
251 | clnt->cl_discrtry = 1; | 297 | clnt->cl_discrtry = 1; |
252 | 298 | ||
@@ -268,24 +314,25 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
268 | new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); | 314 | new = kmemdup(clnt, sizeof(*new), GFP_KERNEL); |
269 | if (!new) | 315 | if (!new) |
270 | goto out_no_clnt; | 316 | goto out_no_clnt; |
271 | atomic_set(&new->cl_count, 1); | 317 | new->cl_parent = clnt; |
272 | atomic_set(&new->cl_users, 0); | 318 | /* Turn off autobind on clones */ |
319 | new->cl_autobind = 0; | ||
320 | INIT_LIST_HEAD(&new->cl_tasks); | ||
321 | spin_lock_init(&new->cl_lock); | ||
322 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); | ||
273 | new->cl_metrics = rpc_alloc_iostats(clnt); | 323 | new->cl_metrics = rpc_alloc_iostats(clnt); |
274 | if (new->cl_metrics == NULL) | 324 | if (new->cl_metrics == NULL) |
275 | goto out_no_stats; | 325 | goto out_no_stats; |
326 | kref_init(&new->cl_kref); | ||
276 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); | 327 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); |
277 | if (err != 0) | 328 | if (err != 0) |
278 | goto out_no_path; | 329 | goto out_no_path; |
279 | new->cl_parent = clnt; | ||
280 | atomic_inc(&clnt->cl_count); | ||
281 | new->cl_xprt = xprt_get(clnt->cl_xprt); | ||
282 | /* Turn off autobind on clones */ | ||
283 | new->cl_autobind = 0; | ||
284 | new->cl_oneshot = 0; | ||
285 | new->cl_dead = 0; | ||
286 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); | ||
287 | if (new->cl_auth) | 330 | if (new->cl_auth) |
288 | atomic_inc(&new->cl_auth->au_count); | 331 | atomic_inc(&new->cl_auth->au_count); |
332 | xprt_get(clnt->cl_xprt); | ||
333 | kref_get(&clnt->cl_kref); | ||
334 | rpc_register_client(new); | ||
335 | rpciod_up(); | ||
289 | return new; | 336 | return new; |
290 | out_no_path: | 337 | out_no_path: |
291 | rpc_free_iostats(new->cl_metrics); | 338 | rpc_free_iostats(new->cl_metrics); |
@@ -298,86 +345,86 @@ out_no_clnt: | |||
298 | 345 | ||
299 | /* | 346 | /* |
300 | * Properly shut down an RPC client, terminating all outstanding | 347 | * Properly shut down an RPC client, terminating all outstanding |
301 | * requests. Note that we must be certain that cl_oneshot and | 348 | * requests. |
302 | * cl_dead are cleared, or else the client would be destroyed | ||
303 | * when the last task releases it. | ||
304 | */ | 349 | */ |
305 | int | 350 | void rpc_shutdown_client(struct rpc_clnt *clnt) |
306 | rpc_shutdown_client(struct rpc_clnt *clnt) | ||
307 | { | 351 | { |
308 | dprintk("RPC: shutting down %s client for %s, tasks=%d\n", | 352 | dprintk("RPC: shutting down %s client for %s\n", |
309 | clnt->cl_protname, clnt->cl_server, | 353 | clnt->cl_protname, clnt->cl_server); |
310 | atomic_read(&clnt->cl_users)); | 354 | |
311 | 355 | while (!list_empty(&clnt->cl_tasks)) { | |
312 | while (atomic_read(&clnt->cl_users) > 0) { | ||
313 | /* Don't let rpc_release_client destroy us */ | ||
314 | clnt->cl_oneshot = 0; | ||
315 | clnt->cl_dead = 0; | ||
316 | rpc_killall_tasks(clnt); | 356 | rpc_killall_tasks(clnt); |
317 | wait_event_timeout(destroy_wait, | 357 | wait_event_timeout(destroy_wait, |
318 | !atomic_read(&clnt->cl_users), 1*HZ); | 358 | list_empty(&clnt->cl_tasks), 1*HZ); |
319 | } | ||
320 | |||
321 | if (atomic_read(&clnt->cl_users) < 0) { | ||
322 | printk(KERN_ERR "RPC: rpc_shutdown_client clnt %p tasks=%d\n", | ||
323 | clnt, atomic_read(&clnt->cl_users)); | ||
324 | #ifdef RPC_DEBUG | ||
325 | rpc_show_tasks(); | ||
326 | #endif | ||
327 | BUG(); | ||
328 | } | 359 | } |
329 | 360 | ||
330 | return rpc_destroy_client(clnt); | 361 | rpc_release_client(clnt); |
331 | } | 362 | } |
332 | 363 | ||
333 | /* | 364 | /* |
334 | * Delete an RPC client | 365 | * Free an RPC client |
335 | */ | 366 | */ |
336 | int | 367 | static void |
337 | rpc_destroy_client(struct rpc_clnt *clnt) | 368 | rpc_free_client(struct kref *kref) |
338 | { | 369 | { |
339 | if (!atomic_dec_and_test(&clnt->cl_count)) | 370 | struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); |
340 | return 1; | ||
341 | BUG_ON(atomic_read(&clnt->cl_users) != 0); | ||
342 | 371 | ||
343 | dprintk("RPC: destroying %s client for %s\n", | 372 | dprintk("RPC: destroying %s client for %s\n", |
344 | clnt->cl_protname, clnt->cl_server); | 373 | clnt->cl_protname, clnt->cl_server); |
345 | if (clnt->cl_auth) { | ||
346 | rpcauth_destroy(clnt->cl_auth); | ||
347 | clnt->cl_auth = NULL; | ||
348 | } | ||
349 | if (!IS_ERR(clnt->cl_dentry)) { | 374 | if (!IS_ERR(clnt->cl_dentry)) { |
350 | rpc_rmdir(clnt->cl_dentry); | 375 | rpc_rmdir(clnt->cl_dentry); |
351 | rpc_put_mount(); | 376 | rpc_put_mount(); |
352 | } | 377 | } |
353 | if (clnt->cl_parent != clnt) { | 378 | if (clnt->cl_parent != clnt) { |
354 | rpc_destroy_client(clnt->cl_parent); | 379 | rpc_release_client(clnt->cl_parent); |
355 | goto out_free; | 380 | goto out_free; |
356 | } | 381 | } |
357 | if (clnt->cl_server != clnt->cl_inline_name) | 382 | if (clnt->cl_server != clnt->cl_inline_name) |
358 | kfree(clnt->cl_server); | 383 | kfree(clnt->cl_server); |
359 | out_free: | 384 | out_free: |
385 | rpc_unregister_client(clnt); | ||
360 | rpc_free_iostats(clnt->cl_metrics); | 386 | rpc_free_iostats(clnt->cl_metrics); |
361 | clnt->cl_metrics = NULL; | 387 | clnt->cl_metrics = NULL; |
362 | xprt_put(clnt->cl_xprt); | 388 | xprt_put(clnt->cl_xprt); |
389 | rpciod_down(); | ||
363 | kfree(clnt); | 390 | kfree(clnt); |
364 | return 0; | ||
365 | } | 391 | } |
366 | 392 | ||
367 | /* | 393 | /* |
368 | * Release an RPC client | 394 | * Free an RPC client |
395 | */ | ||
396 | static void | ||
397 | rpc_free_auth(struct kref *kref) | ||
398 | { | ||
399 | struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); | ||
400 | |||
401 | if (clnt->cl_auth == NULL) { | ||
402 | rpc_free_client(kref); | ||
403 | return; | ||
404 | } | ||
405 | |||
406 | /* | ||
407 | * Note: RPCSEC_GSS may need to send NULL RPC calls in order to | ||
408 | * release remaining GSS contexts. This mechanism ensures | ||
409 | * that it can do so safely. | ||
410 | */ | ||
411 | kref_init(kref); | ||
412 | rpcauth_release(clnt->cl_auth); | ||
413 | clnt->cl_auth = NULL; | ||
414 | kref_put(kref, rpc_free_client); | ||
415 | } | ||
416 | |||
417 | /* | ||
418 | * Release reference to the RPC client | ||
369 | */ | 419 | */ |
370 | void | 420 | void |
371 | rpc_release_client(struct rpc_clnt *clnt) | 421 | rpc_release_client(struct rpc_clnt *clnt) |
372 | { | 422 | { |
373 | dprintk("RPC: rpc_release_client(%p, %d)\n", | 423 | dprintk("RPC: rpc_release_client(%p)\n", clnt); |
374 | clnt, atomic_read(&clnt->cl_users)); | ||
375 | 424 | ||
376 | if (!atomic_dec_and_test(&clnt->cl_users)) | 425 | if (list_empty(&clnt->cl_tasks)) |
377 | return; | 426 | wake_up(&destroy_wait); |
378 | wake_up(&destroy_wait); | 427 | kref_put(&clnt->cl_kref, rpc_free_auth); |
379 | if (clnt->cl_oneshot || clnt->cl_dead) | ||
380 | rpc_destroy_client(clnt); | ||
381 | } | 428 | } |
382 | 429 | ||
383 | /** | 430 | /** |
@@ -468,82 +515,96 @@ void rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset) | |||
468 | rpc_restore_sigmask(oldset); | 515 | rpc_restore_sigmask(oldset); |
469 | } | 516 | } |
470 | 517 | ||
471 | /* | 518 | static |
472 | * New rpc_call implementation | 519 | struct rpc_task *rpc_do_run_task(struct rpc_clnt *clnt, |
520 | struct rpc_message *msg, | ||
521 | int flags, | ||
522 | const struct rpc_call_ops *ops, | ||
523 | void *data) | ||
524 | { | ||
525 | struct rpc_task *task, *ret; | ||
526 | sigset_t oldset; | ||
527 | |||
528 | task = rpc_new_task(clnt, flags, ops, data); | ||
529 | if (task == NULL) { | ||
530 | rpc_release_calldata(ops, data); | ||
531 | return ERR_PTR(-ENOMEM); | ||
532 | } | ||
533 | |||
534 | /* Mask signals on synchronous RPC calls and RPCSEC_GSS upcalls */ | ||
535 | rpc_task_sigmask(task, &oldset); | ||
536 | if (msg != NULL) { | ||
537 | rpc_call_setup(task, msg, 0); | ||
538 | if (task->tk_status != 0) { | ||
539 | ret = ERR_PTR(task->tk_status); | ||
540 | rpc_put_task(task); | ||
541 | goto out; | ||
542 | } | ||
543 | } | ||
544 | atomic_inc(&task->tk_count); | ||
545 | rpc_execute(task); | ||
546 | ret = task; | ||
547 | out: | ||
548 | rpc_restore_sigmask(&oldset); | ||
549 | return ret; | ||
550 | } | ||
551 | |||
552 | /** | ||
553 | * rpc_call_sync - Perform a synchronous RPC call | ||
554 | * @clnt: pointer to RPC client | ||
555 | * @msg: RPC call parameters | ||
556 | * @flags: RPC call flags | ||
473 | */ | 557 | */ |
474 | int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) | 558 | int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) |
475 | { | 559 | { |
476 | struct rpc_task *task; | 560 | struct rpc_task *task; |
477 | sigset_t oldset; | 561 | int status; |
478 | int status; | ||
479 | |||
480 | /* If this client is slain all further I/O fails */ | ||
481 | if (clnt->cl_dead) | ||
482 | return -EIO; | ||
483 | 562 | ||
484 | BUG_ON(flags & RPC_TASK_ASYNC); | 563 | BUG_ON(flags & RPC_TASK_ASYNC); |
485 | 564 | ||
486 | task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL); | 565 | task = rpc_do_run_task(clnt, msg, flags, &rpc_default_ops, NULL); |
487 | if (task == NULL) | 566 | if (IS_ERR(task)) |
488 | return -ENOMEM; | 567 | return PTR_ERR(task); |
489 | |||
490 | /* Mask signals on RPC calls _and_ GSS_AUTH upcalls */ | ||
491 | rpc_task_sigmask(task, &oldset); | ||
492 | |||
493 | /* Set up the call info struct and execute the task */ | ||
494 | rpc_call_setup(task, msg, 0); | ||
495 | if (task->tk_status == 0) { | ||
496 | atomic_inc(&task->tk_count); | ||
497 | rpc_execute(task); | ||
498 | } | ||
499 | status = task->tk_status; | 568 | status = task->tk_status; |
500 | rpc_put_task(task); | 569 | rpc_put_task(task); |
501 | rpc_restore_sigmask(&oldset); | ||
502 | return status; | 570 | return status; |
503 | } | 571 | } |
504 | 572 | ||
505 | /* | 573 | /** |
506 | * New rpc_call implementation | 574 | * rpc_call_async - Perform an asynchronous RPC call |
575 | * @clnt: pointer to RPC client | ||
576 | * @msg: RPC call parameters | ||
577 | * @flags: RPC call flags | ||
578 | * @ops: RPC call ops | ||
579 | * @data: user call data | ||
507 | */ | 580 | */ |
508 | int | 581 | int |
509 | rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, | 582 | rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, |
510 | const struct rpc_call_ops *tk_ops, void *data) | 583 | const struct rpc_call_ops *tk_ops, void *data) |
511 | { | 584 | { |
512 | struct rpc_task *task; | 585 | struct rpc_task *task; |
513 | sigset_t oldset; | ||
514 | int status; | ||
515 | |||
516 | /* If this client is slain all further I/O fails */ | ||
517 | status = -EIO; | ||
518 | if (clnt->cl_dead) | ||
519 | goto out_release; | ||
520 | |||
521 | flags |= RPC_TASK_ASYNC; | ||
522 | |||
523 | /* Create/initialize a new RPC task */ | ||
524 | status = -ENOMEM; | ||
525 | if (!(task = rpc_new_task(clnt, flags, tk_ops, data))) | ||
526 | goto out_release; | ||
527 | |||
528 | /* Mask signals on GSS_AUTH upcalls */ | ||
529 | rpc_task_sigmask(task, &oldset); | ||
530 | 586 | ||
531 | rpc_call_setup(task, msg, 0); | 587 | task = rpc_do_run_task(clnt, msg, flags|RPC_TASK_ASYNC, tk_ops, data); |
532 | 588 | if (IS_ERR(task)) | |
533 | /* Set up the call info struct and execute the task */ | 589 | return PTR_ERR(task); |
534 | status = task->tk_status; | 590 | rpc_put_task(task); |
535 | if (status == 0) | 591 | return 0; |
536 | rpc_execute(task); | ||
537 | else | ||
538 | rpc_put_task(task); | ||
539 | |||
540 | rpc_restore_sigmask(&oldset); | ||
541 | return status; | ||
542 | out_release: | ||
543 | rpc_release_calldata(tk_ops, data); | ||
544 | return status; | ||
545 | } | 592 | } |
546 | 593 | ||
594 | /** | ||
595 | * rpc_run_task - Allocate a new RPC task, then run rpc_execute against it | ||
596 | * @clnt: pointer to RPC client | ||
597 | * @flags: RPC flags | ||
598 | * @ops: RPC call ops | ||
599 | * @data: user call data | ||
600 | */ | ||
601 | struct rpc_task *rpc_run_task(struct rpc_clnt *clnt, int flags, | ||
602 | const struct rpc_call_ops *tk_ops, | ||
603 | void *data) | ||
604 | { | ||
605 | return rpc_do_run_task(clnt, NULL, flags, tk_ops, data); | ||
606 | } | ||
607 | EXPORT_SYMBOL(rpc_run_task); | ||
547 | 608 | ||
548 | void | 609 | void |
549 | rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags) | 610 | rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags) |
@@ -745,7 +806,7 @@ call_reserveresult(struct rpc_task *task) | |||
745 | static void | 806 | static void |
746 | call_allocate(struct rpc_task *task) | 807 | call_allocate(struct rpc_task *task) |
747 | { | 808 | { |
748 | unsigned int slack = task->tk_auth->au_cslack; | 809 | unsigned int slack = task->tk_msg.rpc_cred->cr_auth->au_cslack; |
749 | struct rpc_rqst *req = task->tk_rqstp; | 810 | struct rpc_rqst *req = task->tk_rqstp; |
750 | struct rpc_xprt *xprt = task->tk_xprt; | 811 | struct rpc_xprt *xprt = task->tk_xprt; |
751 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; | 812 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; |
@@ -843,10 +904,8 @@ call_encode(struct rpc_task *task) | |||
843 | if (encode == NULL) | 904 | if (encode == NULL) |
844 | return; | 905 | return; |
845 | 906 | ||
846 | lock_kernel(); | ||
847 | task->tk_status = rpcauth_wrap_req(task, encode, req, p, | 907 | task->tk_status = rpcauth_wrap_req(task, encode, req, p, |
848 | task->tk_msg.rpc_argp); | 908 | task->tk_msg.rpc_argp); |
849 | unlock_kernel(); | ||
850 | if (task->tk_status == -ENOMEM) { | 909 | if (task->tk_status == -ENOMEM) { |
851 | /* XXX: Is this sane? */ | 910 | /* XXX: Is this sane? */ |
852 | rpc_delay(task, 3*HZ); | 911 | rpc_delay(task, 3*HZ); |
@@ -1177,10 +1236,8 @@ call_decode(struct rpc_task *task) | |||
1177 | task->tk_action = rpc_exit_task; | 1236 | task->tk_action = rpc_exit_task; |
1178 | 1237 | ||
1179 | if (decode) { | 1238 | if (decode) { |
1180 | lock_kernel(); | ||
1181 | task->tk_status = rpcauth_unwrap_resp(task, decode, req, p, | 1239 | task->tk_status = rpcauth_unwrap_resp(task, decode, req, p, |
1182 | task->tk_msg.rpc_resp); | 1240 | task->tk_msg.rpc_resp); |
1183 | unlock_kernel(); | ||
1184 | } | 1241 | } |
1185 | dprintk("RPC: %5u call_decode result %d\n", task->tk_pid, | 1242 | dprintk("RPC: %5u call_decode result %d\n", task->tk_pid, |
1186 | task->tk_status); | 1243 | task->tk_status); |
@@ -1273,9 +1330,9 @@ call_verify(struct rpc_task *task) | |||
1273 | * - if it isn't pointer subtraction in the NFS client may give | 1330 | * - if it isn't pointer subtraction in the NFS client may give |
1274 | * undefined results | 1331 | * undefined results |
1275 | */ | 1332 | */ |
1276 | printk(KERN_WARNING | 1333 | dprintk("RPC: %5u %s: XDR representation not a multiple of" |
1277 | "call_verify: XDR representation not a multiple of" | 1334 | " 4 bytes: 0x%x\n", task->tk_pid, __FUNCTION__, |
1278 | " 4 bytes: 0x%x\n", task->tk_rqstp->rq_rcv_buf.len); | 1335 | task->tk_rqstp->rq_rcv_buf.len); |
1279 | goto out_eio; | 1336 | goto out_eio; |
1280 | } | 1337 | } |
1281 | if ((len -= 3) < 0) | 1338 | if ((len -= 3) < 0) |
@@ -1283,7 +1340,8 @@ call_verify(struct rpc_task *task) | |||
1283 | p += 1; /* skip XID */ | 1340 | p += 1; /* skip XID */ |
1284 | 1341 | ||
1285 | if ((n = ntohl(*p++)) != RPC_REPLY) { | 1342 | if ((n = ntohl(*p++)) != RPC_REPLY) { |
1286 | printk(KERN_WARNING "call_verify: not an RPC reply: %x\n", n); | 1343 | dprintk("RPC: %5u %s: not an RPC reply: %x\n", |
1344 | task->tk_pid, __FUNCTION__, n); | ||
1287 | goto out_garbage; | 1345 | goto out_garbage; |
1288 | } | 1346 | } |
1289 | if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { | 1347 | if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { |
@@ -1334,7 +1392,8 @@ call_verify(struct rpc_task *task) | |||
1334 | "authentication.\n", task->tk_client->cl_server); | 1392 | "authentication.\n", task->tk_client->cl_server); |
1335 | break; | 1393 | break; |
1336 | default: | 1394 | default: |
1337 | printk(KERN_WARNING "call_verify: unknown auth error: %x\n", n); | 1395 | dprintk("RPC: %5u %s: unknown auth error: %x\n", |
1396 | task->tk_pid, __FUNCTION__, n); | ||
1338 | error = -EIO; | 1397 | error = -EIO; |
1339 | } | 1398 | } |
1340 | dprintk("RPC: %5u %s: call rejected %d\n", | 1399 | dprintk("RPC: %5u %s: call rejected %d\n", |
@@ -1342,7 +1401,8 @@ call_verify(struct rpc_task *task) | |||
1342 | goto out_err; | 1401 | goto out_err; |
1343 | } | 1402 | } |
1344 | if (!(p = rpcauth_checkverf(task, p))) { | 1403 | if (!(p = rpcauth_checkverf(task, p))) { |
1345 | printk(KERN_WARNING "call_verify: auth check failed\n"); | 1404 | dprintk("RPC: %5u %s: auth check failed\n", |
1405 | task->tk_pid, __FUNCTION__); | ||
1346 | goto out_garbage; /* bad verifier, retry */ | 1406 | goto out_garbage; /* bad verifier, retry */ |
1347 | } | 1407 | } |
1348 | len = p - (__be32 *)iov->iov_base - 1; | 1408 | len = p - (__be32 *)iov->iov_base - 1; |
@@ -1381,7 +1441,8 @@ call_verify(struct rpc_task *task) | |||
1381 | task->tk_pid, __FUNCTION__); | 1441 | task->tk_pid, __FUNCTION__); |
1382 | break; /* retry */ | 1442 | break; /* retry */ |
1383 | default: | 1443 | default: |
1384 | printk(KERN_WARNING "call_verify: server accept status: %x\n", n); | 1444 | dprintk("RPC: %5u %s: server accept status: %x\n", |
1445 | task->tk_pid, __FUNCTION__, n); | ||
1385 | /* Also retry */ | 1446 | /* Also retry */ |
1386 | } | 1447 | } |
1387 | 1448 | ||
@@ -1395,14 +1456,16 @@ out_garbage: | |||
1395 | out_retry: | 1456 | out_retry: |
1396 | return ERR_PTR(-EAGAIN); | 1457 | return ERR_PTR(-EAGAIN); |
1397 | } | 1458 | } |
1398 | printk(KERN_WARNING "RPC %s: retry failed, exit EIO\n", __FUNCTION__); | ||
1399 | out_eio: | 1459 | out_eio: |
1400 | error = -EIO; | 1460 | error = -EIO; |
1401 | out_err: | 1461 | out_err: |
1402 | rpc_exit(task, error); | 1462 | rpc_exit(task, error); |
1463 | dprintk("RPC: %5u %s: call failed with error %d\n", task->tk_pid, | ||
1464 | __FUNCTION__, error); | ||
1403 | return ERR_PTR(error); | 1465 | return ERR_PTR(error); |
1404 | out_overflow: | 1466 | out_overflow: |
1405 | printk(KERN_WARNING "RPC %s: server reply was truncated.\n", __FUNCTION__); | 1467 | dprintk("RPC: %5u %s: server reply was truncated.\n", task->tk_pid, |
1468 | __FUNCTION__); | ||
1406 | goto out_garbage; | 1469 | goto out_garbage; |
1407 | } | 1470 | } |
1408 | 1471 | ||
@@ -1421,7 +1484,7 @@ static struct rpc_procinfo rpcproc_null = { | |||
1421 | .p_decode = rpcproc_decode_null, | 1484 | .p_decode = rpcproc_decode_null, |
1422 | }; | 1485 | }; |
1423 | 1486 | ||
1424 | int rpc_ping(struct rpc_clnt *clnt, int flags) | 1487 | static int rpc_ping(struct rpc_clnt *clnt, int flags) |
1425 | { | 1488 | { |
1426 | struct rpc_message msg = { | 1489 | struct rpc_message msg = { |
1427 | .rpc_proc = &rpcproc_null, | 1490 | .rpc_proc = &rpcproc_null, |
@@ -1432,3 +1495,51 @@ int rpc_ping(struct rpc_clnt *clnt, int flags) | |||
1432 | put_rpccred(msg.rpc_cred); | 1495 | put_rpccred(msg.rpc_cred); |
1433 | return err; | 1496 | return err; |
1434 | } | 1497 | } |
1498 | |||
1499 | struct rpc_task *rpc_call_null(struct rpc_clnt *clnt, struct rpc_cred *cred, int flags) | ||
1500 | { | ||
1501 | struct rpc_message msg = { | ||
1502 | .rpc_proc = &rpcproc_null, | ||
1503 | .rpc_cred = cred, | ||
1504 | }; | ||
1505 | return rpc_do_run_task(clnt, &msg, flags, &rpc_default_ops, NULL); | ||
1506 | } | ||
1507 | EXPORT_SYMBOL(rpc_call_null); | ||
1508 | |||
1509 | #ifdef RPC_DEBUG | ||
1510 | void rpc_show_tasks(void) | ||
1511 | { | ||
1512 | struct rpc_clnt *clnt; | ||
1513 | struct rpc_task *t; | ||
1514 | |||
1515 | spin_lock(&rpc_client_lock); | ||
1516 | if (list_empty(&all_clients)) | ||
1517 | goto out; | ||
1518 | printk("-pid- proc flgs status -client- -prog- --rqstp- -timeout " | ||
1519 | "-rpcwait -action- ---ops--\n"); | ||
1520 | list_for_each_entry(clnt, &all_clients, cl_clients) { | ||
1521 | if (list_empty(&clnt->cl_tasks)) | ||
1522 | continue; | ||
1523 | spin_lock(&clnt->cl_lock); | ||
1524 | list_for_each_entry(t, &clnt->cl_tasks, tk_task) { | ||
1525 | const char *rpc_waitq = "none"; | ||
1526 | |||
1527 | if (RPC_IS_QUEUED(t)) | ||
1528 | rpc_waitq = rpc_qname(t->u.tk_wait.rpc_waitq); | ||
1529 | |||
1530 | printk("%5u %04d %04x %6d %8p %6d %8p %8ld %8s %8p %8p\n", | ||
1531 | t->tk_pid, | ||
1532 | (t->tk_msg.rpc_proc ? t->tk_msg.rpc_proc->p_proc : -1), | ||
1533 | t->tk_flags, t->tk_status, | ||
1534 | t->tk_client, | ||
1535 | (t->tk_client ? t->tk_client->cl_prog : 0), | ||
1536 | t->tk_rqstp, t->tk_timeout, | ||
1537 | rpc_waitq, | ||
1538 | t->tk_action, t->tk_ops); | ||
1539 | } | ||
1540 | spin_unlock(&clnt->cl_lock); | ||
1541 | } | ||
1542 | out: | ||
1543 | spin_unlock(&rpc_client_lock); | ||
1544 | } | ||
1545 | #endif | ||