diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-07 16:19:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-08-07 16:19:36 -0400 |
commit | 5df6b8e65ad0f2eaee202ff002ac00d1ac605315 (patch) | |
tree | 2eff6606f8e39dc1fd7eb8a05feb2a9927151805 /net/sunrpc | |
parent | fe21ea18c742ab0eb8f6f8ebc543374839a02a87 (diff) | |
parent | 3dce9a5c3a39a664e372886ea86c42ae7ae33dfc (diff) |
Merge branch 'nfs-for-2.6.36' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
* 'nfs-for-2.6.36' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6: (42 commits)
NFS: NFSv4.1 is no longer a "developer only" feature
NFS: NFS_V4 is no longer an EXPERIMENTAL feature
NFS: Fix /proc/mount for legacy binary interface
NFS: Fix the locking in nfs4_callback_getattr
SUNRPC: Defer deleting the security context until gss_do_free_ctx()
SUNRPC: prevent task_cleanup running on freed xprt
SUNRPC: Reduce asynchronous RPC task stack usage
SUNRPC: Move the bound cred to struct rpc_rqst
SUNRPC: Clean up of rpc_bindcred()
SUNRPC: Move remaining RPC client related task initialisation into clnt.c
SUNRPC: Ensure that rpc_exit() always wakes up a sleeping task
SUNRPC: Make the credential cache hashtable size configurable
SUNRPC: Store the hashtable size in struct rpc_cred_cache
NFS: Ensure the AUTH_UNIX credcache is allocated dynamically
NFS: Fix the NFS users of rpc_restart_call()
SUNRPC: The function rpc_restart_call() should return success/failure
NFSv4: Get rid of the bogus RPC_ASSASSINATED(task) checks
NFSv4: Clean up the process of renewing the NFSv4 lease
NFSv4.1: Handle NFS4ERR_DELAY on SEQUENCE correctly
NFS: nfs_rename() should not have to flush out writebacks
...
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/auth.c | 157 | ||||
-rw-r--r-- | net/sunrpc/auth_generic.c | 23 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 29 | ||||
-rw-r--r-- | net/sunrpc/auth_null.c | 2 | ||||
-rw-r--r-- | net/sunrpc/auth_unix.c | 21 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 182 | ||||
-rw-r--r-- | net/sunrpc/sched.c | 104 | ||||
-rw-r--r-- | net/sunrpc/sunrpc_syms.c | 15 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 3 |
9 files changed, 301 insertions, 235 deletions
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 8dc47f1d0001..880d0de3f50f 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -19,6 +19,15 @@ | |||
19 | # define RPCDBG_FACILITY RPCDBG_AUTH | 19 | # define RPCDBG_FACILITY RPCDBG_AUTH |
20 | #endif | 20 | #endif |
21 | 21 | ||
22 | #define RPC_CREDCACHE_DEFAULT_HASHBITS (4) | ||
23 | struct rpc_cred_cache { | ||
24 | struct hlist_head *hashtable; | ||
25 | unsigned int hashbits; | ||
26 | spinlock_t lock; | ||
27 | }; | ||
28 | |||
29 | static unsigned int auth_hashbits = RPC_CREDCACHE_DEFAULT_HASHBITS; | ||
30 | |||
22 | static DEFINE_SPINLOCK(rpc_authflavor_lock); | 31 | static DEFINE_SPINLOCK(rpc_authflavor_lock); |
23 | static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { | 32 | static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { |
24 | &authnull_ops, /* AUTH_NULL */ | 33 | &authnull_ops, /* AUTH_NULL */ |
@@ -29,6 +38,42 @@ static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { | |||
29 | static LIST_HEAD(cred_unused); | 38 | static LIST_HEAD(cred_unused); |
30 | static unsigned long number_cred_unused; | 39 | static unsigned long number_cred_unused; |
31 | 40 | ||
41 | #define MAX_HASHTABLE_BITS (10) | ||
42 | static int param_set_hashtbl_sz(const char *val, struct kernel_param *kp) | ||
43 | { | ||
44 | unsigned long num; | ||
45 | unsigned int nbits; | ||
46 | int ret; | ||
47 | |||
48 | if (!val) | ||
49 | goto out_inval; | ||
50 | ret = strict_strtoul(val, 0, &num); | ||
51 | if (ret == -EINVAL) | ||
52 | goto out_inval; | ||
53 | nbits = fls(num); | ||
54 | if (num > (1U << nbits)) | ||
55 | nbits++; | ||
56 | if (nbits > MAX_HASHTABLE_BITS || nbits < 2) | ||
57 | goto out_inval; | ||
58 | *(unsigned int *)kp->arg = nbits; | ||
59 | return 0; | ||
60 | out_inval: | ||
61 | return -EINVAL; | ||
62 | } | ||
63 | |||
64 | static int param_get_hashtbl_sz(char *buffer, struct kernel_param *kp) | ||
65 | { | ||
66 | unsigned int nbits; | ||
67 | |||
68 | nbits = *(unsigned int *)kp->arg; | ||
69 | return sprintf(buffer, "%u", 1U << nbits); | ||
70 | } | ||
71 | |||
72 | #define param_check_hashtbl_sz(name, p) __param_check(name, p, unsigned int); | ||
73 | |||
74 | module_param_named(auth_hashtable_size, auth_hashbits, hashtbl_sz, 0644); | ||
75 | MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size"); | ||
76 | |||
32 | static u32 | 77 | static u32 |
33 | pseudoflavor_to_flavor(u32 flavor) { | 78 | pseudoflavor_to_flavor(u32 flavor) { |
34 | if (flavor >= RPC_AUTH_MAXFLAVOR) | 79 | if (flavor >= RPC_AUTH_MAXFLAVOR) |
@@ -145,16 +190,23 @@ int | |||
145 | rpcauth_init_credcache(struct rpc_auth *auth) | 190 | rpcauth_init_credcache(struct rpc_auth *auth) |
146 | { | 191 | { |
147 | struct rpc_cred_cache *new; | 192 | struct rpc_cred_cache *new; |
148 | int i; | 193 | unsigned int hashsize; |
149 | 194 | ||
150 | new = kmalloc(sizeof(*new), GFP_KERNEL); | 195 | new = kmalloc(sizeof(*new), GFP_KERNEL); |
151 | if (!new) | 196 | if (!new) |
152 | return -ENOMEM; | 197 | goto out_nocache; |
153 | for (i = 0; i < RPC_CREDCACHE_NR; i++) | 198 | new->hashbits = auth_hashbits; |
154 | INIT_HLIST_HEAD(&new->hashtable[i]); | 199 | hashsize = 1U << new->hashbits; |
200 | new->hashtable = kcalloc(hashsize, sizeof(new->hashtable[0]), GFP_KERNEL); | ||
201 | if (!new->hashtable) | ||
202 | goto out_nohashtbl; | ||
155 | spin_lock_init(&new->lock); | 203 | spin_lock_init(&new->lock); |
156 | auth->au_credcache = new; | 204 | auth->au_credcache = new; |
157 | return 0; | 205 | return 0; |
206 | out_nohashtbl: | ||
207 | kfree(new); | ||
208 | out_nocache: | ||
209 | return -ENOMEM; | ||
158 | } | 210 | } |
159 | EXPORT_SYMBOL_GPL(rpcauth_init_credcache); | 211 | EXPORT_SYMBOL_GPL(rpcauth_init_credcache); |
160 | 212 | ||
@@ -183,11 +235,12 @@ rpcauth_clear_credcache(struct rpc_cred_cache *cache) | |||
183 | LIST_HEAD(free); | 235 | LIST_HEAD(free); |
184 | struct hlist_head *head; | 236 | struct hlist_head *head; |
185 | struct rpc_cred *cred; | 237 | struct rpc_cred *cred; |
238 | unsigned int hashsize = 1U << cache->hashbits; | ||
186 | int i; | 239 | int i; |
187 | 240 | ||
188 | spin_lock(&rpc_credcache_lock); | 241 | spin_lock(&rpc_credcache_lock); |
189 | spin_lock(&cache->lock); | 242 | spin_lock(&cache->lock); |
190 | for (i = 0; i < RPC_CREDCACHE_NR; i++) { | 243 | for (i = 0; i < hashsize; i++) { |
191 | head = &cache->hashtable[i]; | 244 | head = &cache->hashtable[i]; |
192 | while (!hlist_empty(head)) { | 245 | while (!hlist_empty(head)) { |
193 | cred = hlist_entry(head->first, struct rpc_cred, cr_hash); | 246 | cred = hlist_entry(head->first, struct rpc_cred, cr_hash); |
@@ -216,6 +269,7 @@ rpcauth_destroy_credcache(struct rpc_auth *auth) | |||
216 | if (cache) { | 269 | if (cache) { |
217 | auth->au_credcache = NULL; | 270 | auth->au_credcache = NULL; |
218 | rpcauth_clear_credcache(cache); | 271 | rpcauth_clear_credcache(cache); |
272 | kfree(cache->hashtable); | ||
219 | kfree(cache); | 273 | kfree(cache); |
220 | } | 274 | } |
221 | } | 275 | } |
@@ -297,7 +351,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, | |||
297 | *entry, *new; | 351 | *entry, *new; |
298 | unsigned int nr; | 352 | unsigned int nr; |
299 | 353 | ||
300 | nr = hash_long(acred->uid, RPC_CREDCACHE_HASHBITS); | 354 | nr = hash_long(acred->uid, cache->hashbits); |
301 | 355 | ||
302 | rcu_read_lock(); | 356 | rcu_read_lock(); |
303 | hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) { | 357 | hlist_for_each_entry_rcu(entry, pos, &cache->hashtable[nr], cr_hash) { |
@@ -390,16 +444,16 @@ rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred, | |||
390 | } | 444 | } |
391 | EXPORT_SYMBOL_GPL(rpcauth_init_cred); | 445 | EXPORT_SYMBOL_GPL(rpcauth_init_cred); |
392 | 446 | ||
393 | void | 447 | struct rpc_cred * |
394 | rpcauth_generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred, int lookupflags) | 448 | rpcauth_generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred, int lookupflags) |
395 | { | 449 | { |
396 | task->tk_msg.rpc_cred = get_rpccred(cred); | ||
397 | dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid, | 450 | dprintk("RPC: %5u holding %s cred %p\n", task->tk_pid, |
398 | cred->cr_auth->au_ops->au_name, cred); | 451 | cred->cr_auth->au_ops->au_name, cred); |
452 | return get_rpccred(cred); | ||
399 | } | 453 | } |
400 | EXPORT_SYMBOL_GPL(rpcauth_generic_bind_cred); | 454 | EXPORT_SYMBOL_GPL(rpcauth_generic_bind_cred); |
401 | 455 | ||
402 | static void | 456 | static struct rpc_cred * |
403 | rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags) | 457 | rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags) |
404 | { | 458 | { |
405 | struct rpc_auth *auth = task->tk_client->cl_auth; | 459 | struct rpc_auth *auth = task->tk_client->cl_auth; |
@@ -407,45 +461,43 @@ rpcauth_bind_root_cred(struct rpc_task *task, int lookupflags) | |||
407 | .uid = 0, | 461 | .uid = 0, |
408 | .gid = 0, | 462 | .gid = 0, |
409 | }; | 463 | }; |
410 | struct rpc_cred *ret; | ||
411 | 464 | ||
412 | dprintk("RPC: %5u looking up %s cred\n", | 465 | dprintk("RPC: %5u looking up %s cred\n", |
413 | task->tk_pid, task->tk_client->cl_auth->au_ops->au_name); | 466 | task->tk_pid, task->tk_client->cl_auth->au_ops->au_name); |
414 | ret = auth->au_ops->lookup_cred(auth, &acred, lookupflags); | 467 | return auth->au_ops->lookup_cred(auth, &acred, lookupflags); |
415 | if (!IS_ERR(ret)) | ||
416 | task->tk_msg.rpc_cred = ret; | ||
417 | else | ||
418 | task->tk_status = PTR_ERR(ret); | ||
419 | } | 468 | } |
420 | 469 | ||
421 | static void | 470 | static struct rpc_cred * |
422 | rpcauth_bind_new_cred(struct rpc_task *task, int lookupflags) | 471 | rpcauth_bind_new_cred(struct rpc_task *task, int lookupflags) |
423 | { | 472 | { |
424 | struct rpc_auth *auth = task->tk_client->cl_auth; | 473 | struct rpc_auth *auth = task->tk_client->cl_auth; |
425 | struct rpc_cred *ret; | ||
426 | 474 | ||
427 | dprintk("RPC: %5u looking up %s cred\n", | 475 | dprintk("RPC: %5u looking up %s cred\n", |
428 | task->tk_pid, auth->au_ops->au_name); | 476 | task->tk_pid, auth->au_ops->au_name); |
429 | ret = rpcauth_lookupcred(auth, lookupflags); | 477 | return rpcauth_lookupcred(auth, lookupflags); |
430 | if (!IS_ERR(ret)) | ||
431 | task->tk_msg.rpc_cred = ret; | ||
432 | else | ||
433 | task->tk_status = PTR_ERR(ret); | ||
434 | } | 478 | } |
435 | 479 | ||
436 | void | 480 | static int |
437 | rpcauth_bindcred(struct rpc_task *task, struct rpc_cred *cred, int flags) | 481 | rpcauth_bindcred(struct rpc_task *task, struct rpc_cred *cred, int flags) |
438 | { | 482 | { |
483 | struct rpc_rqst *req = task->tk_rqstp; | ||
484 | struct rpc_cred *new; | ||
439 | int lookupflags = 0; | 485 | int lookupflags = 0; |
440 | 486 | ||
441 | if (flags & RPC_TASK_ASYNC) | 487 | if (flags & RPC_TASK_ASYNC) |
442 | lookupflags |= RPCAUTH_LOOKUP_NEW; | 488 | lookupflags |= RPCAUTH_LOOKUP_NEW; |
443 | if (cred != NULL) | 489 | if (cred != NULL) |
444 | cred->cr_ops->crbind(task, cred, lookupflags); | 490 | new = cred->cr_ops->crbind(task, cred, lookupflags); |
445 | else if (flags & RPC_TASK_ROOTCREDS) | 491 | else if (flags & RPC_TASK_ROOTCREDS) |
446 | rpcauth_bind_root_cred(task, lookupflags); | 492 | new = rpcauth_bind_root_cred(task, lookupflags); |
447 | else | 493 | else |
448 | rpcauth_bind_new_cred(task, lookupflags); | 494 | new = rpcauth_bind_new_cred(task, lookupflags); |
495 | if (IS_ERR(new)) | ||
496 | return PTR_ERR(new); | ||
497 | if (req->rq_cred != NULL) | ||
498 | put_rpccred(req->rq_cred); | ||
499 | req->rq_cred = new; | ||
500 | return 0; | ||
449 | } | 501 | } |
450 | 502 | ||
451 | void | 503 | void |
@@ -484,22 +536,10 @@ out_nodestroy: | |||
484 | } | 536 | } |
485 | EXPORT_SYMBOL_GPL(put_rpccred); | 537 | EXPORT_SYMBOL_GPL(put_rpccred); |
486 | 538 | ||
487 | void | ||
488 | rpcauth_unbindcred(struct rpc_task *task) | ||
489 | { | ||
490 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | ||
491 | |||
492 | dprintk("RPC: %5u releasing %s cred %p\n", | ||
493 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); | ||
494 | |||
495 | put_rpccred(cred); | ||
496 | task->tk_msg.rpc_cred = NULL; | ||
497 | } | ||
498 | |||
499 | __be32 * | 539 | __be32 * |
500 | rpcauth_marshcred(struct rpc_task *task, __be32 *p) | 540 | rpcauth_marshcred(struct rpc_task *task, __be32 *p) |
501 | { | 541 | { |
502 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 542 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
503 | 543 | ||
504 | dprintk("RPC: %5u marshaling %s cred %p\n", | 544 | dprintk("RPC: %5u marshaling %s cred %p\n", |
505 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); | 545 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); |
@@ -510,7 +550,7 @@ rpcauth_marshcred(struct rpc_task *task, __be32 *p) | |||
510 | __be32 * | 550 | __be32 * |
511 | rpcauth_checkverf(struct rpc_task *task, __be32 *p) | 551 | rpcauth_checkverf(struct rpc_task *task, __be32 *p) |
512 | { | 552 | { |
513 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 553 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
514 | 554 | ||
515 | dprintk("RPC: %5u validating %s cred %p\n", | 555 | dprintk("RPC: %5u validating %s cred %p\n", |
516 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); | 556 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); |
@@ -522,7 +562,7 @@ int | |||
522 | rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp, | 562 | rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp, |
523 | __be32 *data, void *obj) | 563 | __be32 *data, void *obj) |
524 | { | 564 | { |
525 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 565 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
526 | 566 | ||
527 | dprintk("RPC: %5u using %s cred %p to wrap rpc data\n", | 567 | dprintk("RPC: %5u using %s cred %p to wrap rpc data\n", |
528 | task->tk_pid, cred->cr_ops->cr_name, cred); | 568 | task->tk_pid, cred->cr_ops->cr_name, cred); |
@@ -536,7 +576,7 @@ int | |||
536 | rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, | 576 | rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, |
537 | __be32 *data, void *obj) | 577 | __be32 *data, void *obj) |
538 | { | 578 | { |
539 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 579 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
540 | 580 | ||
541 | dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n", | 581 | dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n", |
542 | task->tk_pid, cred->cr_ops->cr_name, cred); | 582 | task->tk_pid, cred->cr_ops->cr_name, cred); |
@@ -550,13 +590,21 @@ rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, | |||
550 | int | 590 | int |
551 | rpcauth_refreshcred(struct rpc_task *task) | 591 | rpcauth_refreshcred(struct rpc_task *task) |
552 | { | 592 | { |
553 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 593 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
554 | int err; | 594 | int err; |
555 | 595 | ||
596 | cred = task->tk_rqstp->rq_cred; | ||
597 | if (cred == NULL) { | ||
598 | err = rpcauth_bindcred(task, task->tk_msg.rpc_cred, task->tk_flags); | ||
599 | if (err < 0) | ||
600 | goto out; | ||
601 | cred = task->tk_rqstp->rq_cred; | ||
602 | }; | ||
556 | dprintk("RPC: %5u refreshing %s cred %p\n", | 603 | dprintk("RPC: %5u refreshing %s cred %p\n", |
557 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); | 604 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); |
558 | 605 | ||
559 | err = cred->cr_ops->crrefresh(task); | 606 | err = cred->cr_ops->crrefresh(task); |
607 | out: | ||
560 | if (err < 0) | 608 | if (err < 0) |
561 | task->tk_status = err; | 609 | task->tk_status = err; |
562 | return err; | 610 | return err; |
@@ -565,7 +613,7 @@ rpcauth_refreshcred(struct rpc_task *task) | |||
565 | void | 613 | void |
566 | rpcauth_invalcred(struct rpc_task *task) | 614 | rpcauth_invalcred(struct rpc_task *task) |
567 | { | 615 | { |
568 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 616 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
569 | 617 | ||
570 | dprintk("RPC: %5u invalidating %s cred %p\n", | 618 | dprintk("RPC: %5u invalidating %s cred %p\n", |
571 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); | 619 | task->tk_pid, cred->cr_auth->au_ops->au_name, cred); |
@@ -576,7 +624,7 @@ rpcauth_invalcred(struct rpc_task *task) | |||
576 | int | 624 | int |
577 | rpcauth_uptodatecred(struct rpc_task *task) | 625 | rpcauth_uptodatecred(struct rpc_task *task) |
578 | { | 626 | { |
579 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 627 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
580 | 628 | ||
581 | return cred == NULL || | 629 | return cred == NULL || |
582 | test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0; | 630 | test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0; |
@@ -587,14 +635,27 @@ static struct shrinker rpc_cred_shrinker = { | |||
587 | .seeks = DEFAULT_SEEKS, | 635 | .seeks = DEFAULT_SEEKS, |
588 | }; | 636 | }; |
589 | 637 | ||
590 | void __init rpcauth_init_module(void) | 638 | int __init rpcauth_init_module(void) |
591 | { | 639 | { |
592 | rpc_init_authunix(); | 640 | int err; |
593 | rpc_init_generic_auth(); | 641 | |
642 | err = rpc_init_authunix(); | ||
643 | if (err < 0) | ||
644 | goto out1; | ||
645 | err = rpc_init_generic_auth(); | ||
646 | if (err < 0) | ||
647 | goto out2; | ||
594 | register_shrinker(&rpc_cred_shrinker); | 648 | register_shrinker(&rpc_cred_shrinker); |
649 | return 0; | ||
650 | out2: | ||
651 | rpc_destroy_authunix(); | ||
652 | out1: | ||
653 | return err; | ||
595 | } | 654 | } |
596 | 655 | ||
597 | void __exit rpcauth_remove_module(void) | 656 | void __exit rpcauth_remove_module(void) |
598 | { | 657 | { |
658 | rpc_destroy_authunix(); | ||
659 | rpc_destroy_generic_auth(); | ||
599 | unregister_shrinker(&rpc_cred_shrinker); | 660 | unregister_shrinker(&rpc_cred_shrinker); |
600 | } | 661 | } |
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index 8f623b0f03dd..43162bb3b78f 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c | |||
@@ -27,7 +27,6 @@ struct generic_cred { | |||
27 | }; | 27 | }; |
28 | 28 | ||
29 | static struct rpc_auth generic_auth; | 29 | static struct rpc_auth generic_auth; |
30 | static struct rpc_cred_cache generic_cred_cache; | ||
31 | static const struct rpc_credops generic_credops; | 30 | static const struct rpc_credops generic_credops; |
32 | 31 | ||
33 | /* | 32 | /* |
@@ -55,18 +54,13 @@ struct rpc_cred *rpc_lookup_machine_cred(void) | |||
55 | } | 54 | } |
56 | EXPORT_SYMBOL_GPL(rpc_lookup_machine_cred); | 55 | EXPORT_SYMBOL_GPL(rpc_lookup_machine_cred); |
57 | 56 | ||
58 | static void | 57 | static struct rpc_cred *generic_bind_cred(struct rpc_task *task, |
59 | generic_bind_cred(struct rpc_task *task, struct rpc_cred *cred, int lookupflags) | 58 | struct rpc_cred *cred, int lookupflags) |
60 | { | 59 | { |
61 | struct rpc_auth *auth = task->tk_client->cl_auth; | 60 | struct rpc_auth *auth = task->tk_client->cl_auth; |
62 | struct auth_cred *acred = &container_of(cred, struct generic_cred, gc_base)->acred; | 61 | struct auth_cred *acred = &container_of(cred, struct generic_cred, gc_base)->acred; |
63 | struct rpc_cred *ret; | ||
64 | 62 | ||
65 | ret = auth->au_ops->lookup_cred(auth, acred, lookupflags); | 63 | return auth->au_ops->lookup_cred(auth, acred, lookupflags); |
66 | if (!IS_ERR(ret)) | ||
67 | task->tk_msg.rpc_cred = ret; | ||
68 | else | ||
69 | task->tk_status = PTR_ERR(ret); | ||
70 | } | 64 | } |
71 | 65 | ||
72 | /* | 66 | /* |
@@ -159,20 +153,16 @@ out_nomatch: | |||
159 | return 0; | 153 | return 0; |
160 | } | 154 | } |
161 | 155 | ||
162 | void __init rpc_init_generic_auth(void) | 156 | int __init rpc_init_generic_auth(void) |
163 | { | 157 | { |
164 | spin_lock_init(&generic_cred_cache.lock); | 158 | return rpcauth_init_credcache(&generic_auth); |
165 | } | 159 | } |
166 | 160 | ||
167 | void __exit rpc_destroy_generic_auth(void) | 161 | void __exit rpc_destroy_generic_auth(void) |
168 | { | 162 | { |
169 | rpcauth_clear_credcache(&generic_cred_cache); | 163 | rpcauth_destroy_credcache(&generic_auth); |
170 | } | 164 | } |
171 | 165 | ||
172 | static struct rpc_cred_cache generic_cred_cache = { | ||
173 | {{ NULL, },}, | ||
174 | }; | ||
175 | |||
176 | static const struct rpc_authops generic_auth_ops = { | 166 | static const struct rpc_authops generic_auth_ops = { |
177 | .owner = THIS_MODULE, | 167 | .owner = THIS_MODULE, |
178 | .au_name = "Generic", | 168 | .au_name = "Generic", |
@@ -183,7 +173,6 @@ static const struct rpc_authops generic_auth_ops = { | |||
183 | static struct rpc_auth generic_auth = { | 173 | static struct rpc_auth generic_auth = { |
184 | .au_ops = &generic_auth_ops, | 174 | .au_ops = &generic_auth_ops, |
185 | .au_count = ATOMIC_INIT(0), | 175 | .au_count = ATOMIC_INIT(0), |
186 | .au_credcache = &generic_cred_cache, | ||
187 | }; | 176 | }; |
188 | 177 | ||
189 | static const struct rpc_credops generic_credops = { | 178 | static const struct rpc_credops generic_credops = { |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 8da2a0e68574..dcfc66bab2bb 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -373,7 +373,7 @@ gss_handle_downcall_result(struct gss_cred *gss_cred, struct gss_upcall_msg *gss | |||
373 | static void | 373 | static void |
374 | gss_upcall_callback(struct rpc_task *task) | 374 | gss_upcall_callback(struct rpc_task *task) |
375 | { | 375 | { |
376 | struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred, | 376 | struct gss_cred *gss_cred = container_of(task->tk_rqstp->rq_cred, |
377 | struct gss_cred, gc_base); | 377 | struct gss_cred, gc_base); |
378 | struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall; | 378 | struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall; |
379 | struct inode *inode = &gss_msg->inode->vfs_inode; | 379 | struct inode *inode = &gss_msg->inode->vfs_inode; |
@@ -502,7 +502,7 @@ static void warn_gssd(void) | |||
502 | static inline int | 502 | static inline int |
503 | gss_refresh_upcall(struct rpc_task *task) | 503 | gss_refresh_upcall(struct rpc_task *task) |
504 | { | 504 | { |
505 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 505 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
506 | struct gss_auth *gss_auth = container_of(cred->cr_auth, | 506 | struct gss_auth *gss_auth = container_of(cred->cr_auth, |
507 | struct gss_auth, rpc_auth); | 507 | struct gss_auth, rpc_auth); |
508 | struct gss_cred *gss_cred = container_of(cred, | 508 | struct gss_cred *gss_cred = container_of(cred, |
@@ -928,6 +928,7 @@ gss_do_free_ctx(struct gss_cl_ctx *ctx) | |||
928 | { | 928 | { |
929 | dprintk("RPC: gss_free_ctx\n"); | 929 | dprintk("RPC: gss_free_ctx\n"); |
930 | 930 | ||
931 | gss_delete_sec_context(&ctx->gc_gss_ctx); | ||
931 | kfree(ctx->gc_wire_ctx.data); | 932 | kfree(ctx->gc_wire_ctx.data); |
932 | kfree(ctx); | 933 | kfree(ctx); |
933 | } | 934 | } |
@@ -942,13 +943,7 @@ gss_free_ctx_callback(struct rcu_head *head) | |||
942 | static void | 943 | static void |
943 | gss_free_ctx(struct gss_cl_ctx *ctx) | 944 | gss_free_ctx(struct gss_cl_ctx *ctx) |
944 | { | 945 | { |
945 | struct gss_ctx *gc_gss_ctx; | ||
946 | |||
947 | gc_gss_ctx = rcu_dereference(ctx->gc_gss_ctx); | ||
948 | rcu_assign_pointer(ctx->gc_gss_ctx, NULL); | ||
949 | call_rcu(&ctx->gc_rcu, gss_free_ctx_callback); | 946 | call_rcu(&ctx->gc_rcu, gss_free_ctx_callback); |
950 | if (gc_gss_ctx) | ||
951 | gss_delete_sec_context(&gc_gss_ctx); | ||
952 | } | 947 | } |
953 | 948 | ||
954 | static void | 949 | static void |
@@ -1064,12 +1059,12 @@ out: | |||
1064 | static __be32 * | 1059 | static __be32 * |
1065 | gss_marshal(struct rpc_task *task, __be32 *p) | 1060 | gss_marshal(struct rpc_task *task, __be32 *p) |
1066 | { | 1061 | { |
1067 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 1062 | struct rpc_rqst *req = task->tk_rqstp; |
1063 | struct rpc_cred *cred = req->rq_cred; | ||
1068 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, | 1064 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, |
1069 | gc_base); | 1065 | gc_base); |
1070 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); | 1066 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
1071 | __be32 *cred_len; | 1067 | __be32 *cred_len; |
1072 | struct rpc_rqst *req = task->tk_rqstp; | ||
1073 | u32 maj_stat = 0; | 1068 | u32 maj_stat = 0; |
1074 | struct xdr_netobj mic; | 1069 | struct xdr_netobj mic; |
1075 | struct kvec iov; | 1070 | struct kvec iov; |
@@ -1119,7 +1114,7 @@ out_put_ctx: | |||
1119 | 1114 | ||
1120 | static int gss_renew_cred(struct rpc_task *task) | 1115 | static int gss_renew_cred(struct rpc_task *task) |
1121 | { | 1116 | { |
1122 | struct rpc_cred *oldcred = task->tk_msg.rpc_cred; | 1117 | struct rpc_cred *oldcred = task->tk_rqstp->rq_cred; |
1123 | struct gss_cred *gss_cred = container_of(oldcred, | 1118 | struct gss_cred *gss_cred = container_of(oldcred, |
1124 | struct gss_cred, | 1119 | struct gss_cred, |
1125 | gc_base); | 1120 | gc_base); |
@@ -1133,7 +1128,7 @@ static int gss_renew_cred(struct rpc_task *task) | |||
1133 | new = gss_lookup_cred(auth, &acred, RPCAUTH_LOOKUP_NEW); | 1128 | new = gss_lookup_cred(auth, &acred, RPCAUTH_LOOKUP_NEW); |
1134 | if (IS_ERR(new)) | 1129 | if (IS_ERR(new)) |
1135 | return PTR_ERR(new); | 1130 | return PTR_ERR(new); |
1136 | task->tk_msg.rpc_cred = new; | 1131 | task->tk_rqstp->rq_cred = new; |
1137 | put_rpccred(oldcred); | 1132 | put_rpccred(oldcred); |
1138 | return 0; | 1133 | return 0; |
1139 | } | 1134 | } |
@@ -1161,7 +1156,7 @@ static int gss_cred_is_negative_entry(struct rpc_cred *cred) | |||
1161 | static int | 1156 | static int |
1162 | gss_refresh(struct rpc_task *task) | 1157 | gss_refresh(struct rpc_task *task) |
1163 | { | 1158 | { |
1164 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 1159 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
1165 | int ret = 0; | 1160 | int ret = 0; |
1166 | 1161 | ||
1167 | if (gss_cred_is_negative_entry(cred)) | 1162 | if (gss_cred_is_negative_entry(cred)) |
@@ -1172,7 +1167,7 @@ gss_refresh(struct rpc_task *task) | |||
1172 | ret = gss_renew_cred(task); | 1167 | ret = gss_renew_cred(task); |
1173 | if (ret < 0) | 1168 | if (ret < 0) |
1174 | goto out; | 1169 | goto out; |
1175 | cred = task->tk_msg.rpc_cred; | 1170 | cred = task->tk_rqstp->rq_cred; |
1176 | } | 1171 | } |
1177 | 1172 | ||
1178 | if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)) | 1173 | if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)) |
@@ -1191,7 +1186,7 @@ gss_refresh_null(struct rpc_task *task) | |||
1191 | static __be32 * | 1186 | static __be32 * |
1192 | gss_validate(struct rpc_task *task, __be32 *p) | 1187 | gss_validate(struct rpc_task *task, __be32 *p) |
1193 | { | 1188 | { |
1194 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 1189 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
1195 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); | 1190 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
1196 | __be32 seq; | 1191 | __be32 seq; |
1197 | struct kvec iov; | 1192 | struct kvec iov; |
@@ -1400,7 +1395,7 @@ static int | |||
1400 | gss_wrap_req(struct rpc_task *task, | 1395 | gss_wrap_req(struct rpc_task *task, |
1401 | kxdrproc_t encode, void *rqstp, __be32 *p, void *obj) | 1396 | kxdrproc_t encode, void *rqstp, __be32 *p, void *obj) |
1402 | { | 1397 | { |
1403 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 1398 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
1404 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, | 1399 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, |
1405 | gc_base); | 1400 | gc_base); |
1406 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); | 1401 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
@@ -1503,7 +1498,7 @@ static int | |||
1503 | gss_unwrap_resp(struct rpc_task *task, | 1498 | gss_unwrap_resp(struct rpc_task *task, |
1504 | kxdrproc_t decode, void *rqstp, __be32 *p, void *obj) | 1499 | kxdrproc_t decode, void *rqstp, __be32 *p, void *obj) |
1505 | { | 1500 | { |
1506 | struct rpc_cred *cred = task->tk_msg.rpc_cred; | 1501 | struct rpc_cred *cred = task->tk_rqstp->rq_cred; |
1507 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, | 1502 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, |
1508 | gc_base); | 1503 | gc_base); |
1509 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); | 1504 | struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); |
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c index 1db618f56ecb..a5c36c01707b 100644 --- a/net/sunrpc/auth_null.c +++ b/net/sunrpc/auth_null.c | |||
@@ -75,7 +75,7 @@ nul_marshal(struct rpc_task *task, __be32 *p) | |||
75 | static int | 75 | static int |
76 | nul_refresh(struct rpc_task *task) | 76 | nul_refresh(struct rpc_task *task) |
77 | { | 77 | { |
78 | set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags); | 78 | set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_rqstp->rq_cred->cr_flags); |
79 | return 0; | 79 | return 0; |
80 | } | 80 | } |
81 | 81 | ||
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index aac2f8b4ee21..4cb70dc6e7ad 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c | |||
@@ -29,7 +29,6 @@ struct unx_cred { | |||
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | static struct rpc_auth unix_auth; | 31 | static struct rpc_auth unix_auth; |
32 | static struct rpc_cred_cache unix_cred_cache; | ||
33 | static const struct rpc_credops unix_credops; | 32 | static const struct rpc_credops unix_credops; |
34 | 33 | ||
35 | static struct rpc_auth * | 34 | static struct rpc_auth * |
@@ -141,7 +140,7 @@ static __be32 * | |||
141 | unx_marshal(struct rpc_task *task, __be32 *p) | 140 | unx_marshal(struct rpc_task *task, __be32 *p) |
142 | { | 141 | { |
143 | struct rpc_clnt *clnt = task->tk_client; | 142 | struct rpc_clnt *clnt = task->tk_client; |
144 | struct unx_cred *cred = container_of(task->tk_msg.rpc_cred, struct unx_cred, uc_base); | 143 | struct unx_cred *cred = container_of(task->tk_rqstp->rq_cred, struct unx_cred, uc_base); |
145 | __be32 *base, *hold; | 144 | __be32 *base, *hold; |
146 | int i; | 145 | int i; |
147 | 146 | ||
@@ -174,7 +173,7 @@ unx_marshal(struct rpc_task *task, __be32 *p) | |||
174 | static int | 173 | static int |
175 | unx_refresh(struct rpc_task *task) | 174 | unx_refresh(struct rpc_task *task) |
176 | { | 175 | { |
177 | set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags); | 176 | set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_rqstp->rq_cred->cr_flags); |
178 | return 0; | 177 | return 0; |
179 | } | 178 | } |
180 | 179 | ||
@@ -197,15 +196,20 @@ unx_validate(struct rpc_task *task, __be32 *p) | |||
197 | printk("RPC: giant verf size: %u\n", size); | 196 | printk("RPC: giant verf size: %u\n", size); |
198 | return NULL; | 197 | return NULL; |
199 | } | 198 | } |
200 | task->tk_msg.rpc_cred->cr_auth->au_rslack = (size >> 2) + 2; | 199 | task->tk_rqstp->rq_cred->cr_auth->au_rslack = (size >> 2) + 2; |
201 | p += (size >> 2); | 200 | p += (size >> 2); |
202 | 201 | ||
203 | return p; | 202 | return p; |
204 | } | 203 | } |
205 | 204 | ||
206 | void __init rpc_init_authunix(void) | 205 | int __init rpc_init_authunix(void) |
207 | { | 206 | { |
208 | spin_lock_init(&unix_cred_cache.lock); | 207 | return rpcauth_init_credcache(&unix_auth); |
208 | } | ||
209 | |||
210 | void rpc_destroy_authunix(void) | ||
211 | { | ||
212 | rpcauth_destroy_credcache(&unix_auth); | ||
209 | } | 213 | } |
210 | 214 | ||
211 | const struct rpc_authops authunix_ops = { | 215 | const struct rpc_authops authunix_ops = { |
@@ -219,17 +223,12 @@ const struct rpc_authops authunix_ops = { | |||
219 | }; | 223 | }; |
220 | 224 | ||
221 | static | 225 | static |
222 | struct rpc_cred_cache unix_cred_cache = { | ||
223 | }; | ||
224 | |||
225 | static | ||
226 | struct rpc_auth unix_auth = { | 226 | struct rpc_auth unix_auth = { |
227 | .au_cslack = UNX_WRITESLACK, | 227 | .au_cslack = UNX_WRITESLACK, |
228 | .au_rslack = 2, /* assume AUTH_NULL verf */ | 228 | .au_rslack = 2, /* assume AUTH_NULL verf */ |
229 | .au_ops = &authunix_ops, | 229 | .au_ops = &authunix_ops, |
230 | .au_flavor = RPC_AUTH_UNIX, | 230 | .au_flavor = RPC_AUTH_UNIX, |
231 | .au_count = ATOMIC_INIT(0), | 231 | .au_count = ATOMIC_INIT(0), |
232 | .au_credcache = &unix_cred_cache, | ||
233 | }; | 232 | }; |
234 | 233 | ||
235 | static | 234 | static |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 756fc324db9e..2388d83b68ff 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -414,6 +414,35 @@ out_no_clnt: | |||
414 | EXPORT_SYMBOL_GPL(rpc_clone_client); | 414 | EXPORT_SYMBOL_GPL(rpc_clone_client); |
415 | 415 | ||
416 | /* | 416 | /* |
417 | * Kill all tasks for the given client. | ||
418 | * XXX: kill their descendants as well? | ||
419 | */ | ||
420 | void rpc_killall_tasks(struct rpc_clnt *clnt) | ||
421 | { | ||
422 | struct rpc_task *rovr; | ||
423 | |||
424 | |||
425 | if (list_empty(&clnt->cl_tasks)) | ||
426 | return; | ||
427 | dprintk("RPC: killing all tasks for client %p\n", clnt); | ||
428 | /* | ||
429 | * Spin lock all_tasks to prevent changes... | ||
430 | */ | ||
431 | spin_lock(&clnt->cl_lock); | ||
432 | list_for_each_entry(rovr, &clnt->cl_tasks, tk_task) { | ||
433 | if (!RPC_IS_ACTIVATED(rovr)) | ||
434 | continue; | ||
435 | if (!(rovr->tk_flags & RPC_TASK_KILLED)) { | ||
436 | rovr->tk_flags |= RPC_TASK_KILLED; | ||
437 | rpc_exit(rovr, -EIO); | ||
438 | rpc_wake_up_queued_task(rovr->tk_waitqueue, rovr); | ||
439 | } | ||
440 | } | ||
441 | spin_unlock(&clnt->cl_lock); | ||
442 | } | ||
443 | EXPORT_SYMBOL_GPL(rpc_killall_tasks); | ||
444 | |||
445 | /* | ||
417 | * Properly shut down an RPC client, terminating all outstanding | 446 | * Properly shut down an RPC client, terminating all outstanding |
418 | * requests. | 447 | * requests. |
419 | */ | 448 | */ |
@@ -538,6 +567,49 @@ out: | |||
538 | } | 567 | } |
539 | EXPORT_SYMBOL_GPL(rpc_bind_new_program); | 568 | EXPORT_SYMBOL_GPL(rpc_bind_new_program); |
540 | 569 | ||
570 | void rpc_task_release_client(struct rpc_task *task) | ||
571 | { | ||
572 | struct rpc_clnt *clnt = task->tk_client; | ||
573 | |||
574 | if (clnt != NULL) { | ||
575 | /* Remove from client task list */ | ||
576 | spin_lock(&clnt->cl_lock); | ||
577 | list_del(&task->tk_task); | ||
578 | spin_unlock(&clnt->cl_lock); | ||
579 | task->tk_client = NULL; | ||
580 | |||
581 | rpc_release_client(clnt); | ||
582 | } | ||
583 | } | ||
584 | |||
585 | static | ||
586 | void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) | ||
587 | { | ||
588 | if (clnt != NULL) { | ||
589 | rpc_task_release_client(task); | ||
590 | task->tk_client = clnt; | ||
591 | kref_get(&clnt->cl_kref); | ||
592 | if (clnt->cl_softrtry) | ||
593 | task->tk_flags |= RPC_TASK_SOFT; | ||
594 | /* Add to the client's list of all tasks */ | ||
595 | spin_lock(&clnt->cl_lock); | ||
596 | list_add_tail(&task->tk_task, &clnt->cl_tasks); | ||
597 | spin_unlock(&clnt->cl_lock); | ||
598 | } | ||
599 | } | ||
600 | |||
601 | static void | ||
602 | rpc_task_set_rpc_message(struct rpc_task *task, const struct rpc_message *msg) | ||
603 | { | ||
604 | if (msg != NULL) { | ||
605 | task->tk_msg.rpc_proc = msg->rpc_proc; | ||
606 | task->tk_msg.rpc_argp = msg->rpc_argp; | ||
607 | task->tk_msg.rpc_resp = msg->rpc_resp; | ||
608 | if (msg->rpc_cred != NULL) | ||
609 | task->tk_msg.rpc_cred = get_rpccred(msg->rpc_cred); | ||
610 | } | ||
611 | } | ||
612 | |||
541 | /* | 613 | /* |
542 | * Default callback for async RPC calls | 614 | * Default callback for async RPC calls |
543 | */ | 615 | */ |
@@ -562,6 +634,18 @@ struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data) | |||
562 | if (IS_ERR(task)) | 634 | if (IS_ERR(task)) |
563 | goto out; | 635 | goto out; |
564 | 636 | ||
637 | rpc_task_set_client(task, task_setup_data->rpc_client); | ||
638 | rpc_task_set_rpc_message(task, task_setup_data->rpc_message); | ||
639 | |||
640 | if (task->tk_status != 0) { | ||
641 | int ret = task->tk_status; | ||
642 | rpc_put_task(task); | ||
643 | return ERR_PTR(ret); | ||
644 | } | ||
645 | |||
646 | if (task->tk_action == NULL) | ||
647 | rpc_call_start(task); | ||
648 | |||
565 | atomic_inc(&task->tk_count); | 649 | atomic_inc(&task->tk_count); |
566 | rpc_execute(task); | 650 | rpc_execute(task); |
567 | out: | 651 | out: |
@@ -756,12 +840,13 @@ EXPORT_SYMBOL_GPL(rpc_force_rebind); | |||
756 | * Restart an (async) RPC call from the call_prepare state. | 840 | * Restart an (async) RPC call from the call_prepare state. |
757 | * Usually called from within the exit handler. | 841 | * Usually called from within the exit handler. |
758 | */ | 842 | */ |
759 | void | 843 | int |
760 | rpc_restart_call_prepare(struct rpc_task *task) | 844 | rpc_restart_call_prepare(struct rpc_task *task) |
761 | { | 845 | { |
762 | if (RPC_ASSASSINATED(task)) | 846 | if (RPC_ASSASSINATED(task)) |
763 | return; | 847 | return 0; |
764 | task->tk_action = rpc_prepare_task; | 848 | task->tk_action = rpc_prepare_task; |
849 | return 1; | ||
765 | } | 850 | } |
766 | EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); | 851 | EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); |
767 | 852 | ||
@@ -769,13 +854,13 @@ EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); | |||
769 | * Restart an (async) RPC call. Usually called from within the | 854 | * Restart an (async) RPC call. Usually called from within the |
770 | * exit handler. | 855 | * exit handler. |
771 | */ | 856 | */ |
772 | void | 857 | int |
773 | rpc_restart_call(struct rpc_task *task) | 858 | rpc_restart_call(struct rpc_task *task) |
774 | { | 859 | { |
775 | if (RPC_ASSASSINATED(task)) | 860 | if (RPC_ASSASSINATED(task)) |
776 | return; | 861 | return 0; |
777 | |||
778 | task->tk_action = call_start; | 862 | task->tk_action = call_start; |
863 | return 1; | ||
779 | } | 864 | } |
780 | EXPORT_SYMBOL_GPL(rpc_restart_call); | 865 | EXPORT_SYMBOL_GPL(rpc_restart_call); |
781 | 866 | ||
@@ -824,11 +909,6 @@ call_reserve(struct rpc_task *task) | |||
824 | { | 909 | { |
825 | dprint_status(task); | 910 | dprint_status(task); |
826 | 911 | ||
827 | if (!rpcauth_uptodatecred(task)) { | ||
828 | task->tk_action = call_refresh; | ||
829 | return; | ||
830 | } | ||
831 | |||
832 | task->tk_status = 0; | 912 | task->tk_status = 0; |
833 | task->tk_action = call_reserveresult; | 913 | task->tk_action = call_reserveresult; |
834 | xprt_reserve(task); | 914 | xprt_reserve(task); |
@@ -892,7 +972,7 @@ call_reserveresult(struct rpc_task *task) | |||
892 | static void | 972 | static void |
893 | call_allocate(struct rpc_task *task) | 973 | call_allocate(struct rpc_task *task) |
894 | { | 974 | { |
895 | unsigned int slack = task->tk_msg.rpc_cred->cr_auth->au_cslack; | 975 | unsigned int slack = task->tk_client->cl_auth->au_cslack; |
896 | struct rpc_rqst *req = task->tk_rqstp; | 976 | struct rpc_rqst *req = task->tk_rqstp; |
897 | struct rpc_xprt *xprt = task->tk_xprt; | 977 | struct rpc_xprt *xprt = task->tk_xprt; |
898 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; | 978 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; |
@@ -900,7 +980,7 @@ call_allocate(struct rpc_task *task) | |||
900 | dprint_status(task); | 980 | dprint_status(task); |
901 | 981 | ||
902 | task->tk_status = 0; | 982 | task->tk_status = 0; |
903 | task->tk_action = call_bind; | 983 | task->tk_action = call_refresh; |
904 | 984 | ||
905 | if (req->rq_buffer) | 985 | if (req->rq_buffer) |
906 | return; | 986 | return; |
@@ -937,6 +1017,47 @@ call_allocate(struct rpc_task *task) | |||
937 | rpc_exit(task, -ERESTARTSYS); | 1017 | rpc_exit(task, -ERESTARTSYS); |
938 | } | 1018 | } |
939 | 1019 | ||
1020 | /* | ||
1021 | * 2a. Bind and/or refresh the credentials | ||
1022 | */ | ||
1023 | static void | ||
1024 | call_refresh(struct rpc_task *task) | ||
1025 | { | ||
1026 | dprint_status(task); | ||
1027 | |||
1028 | task->tk_action = call_refreshresult; | ||
1029 | task->tk_status = 0; | ||
1030 | task->tk_client->cl_stats->rpcauthrefresh++; | ||
1031 | rpcauth_refreshcred(task); | ||
1032 | } | ||
1033 | |||
1034 | /* | ||
1035 | * 2b. Process the results of a credential refresh | ||
1036 | */ | ||
1037 | static void | ||
1038 | call_refreshresult(struct rpc_task *task) | ||
1039 | { | ||
1040 | int status = task->tk_status; | ||
1041 | |||
1042 | dprint_status(task); | ||
1043 | |||
1044 | task->tk_status = 0; | ||
1045 | task->tk_action = call_bind; | ||
1046 | if (status >= 0 && rpcauth_uptodatecred(task)) | ||
1047 | return; | ||
1048 | switch (status) { | ||
1049 | case -EACCES: | ||
1050 | rpc_exit(task, -EACCES); | ||
1051 | return; | ||
1052 | case -ENOMEM: | ||
1053 | rpc_exit(task, -ENOMEM); | ||
1054 | return; | ||
1055 | case -ETIMEDOUT: | ||
1056 | rpc_delay(task, 3*HZ); | ||
1057 | } | ||
1058 | task->tk_action = call_refresh; | ||
1059 | } | ||
1060 | |||
940 | static inline int | 1061 | static inline int |
941 | rpc_task_need_encode(struct rpc_task *task) | 1062 | rpc_task_need_encode(struct rpc_task *task) |
942 | { | 1063 | { |
@@ -1472,43 +1593,6 @@ out_retry: | |||
1472 | } | 1593 | } |
1473 | } | 1594 | } |
1474 | 1595 | ||
1475 | /* | ||
1476 | * 8. Refresh the credentials if rejected by the server | ||
1477 | */ | ||
1478 | static void | ||
1479 | call_refresh(struct rpc_task *task) | ||
1480 | { | ||
1481 | dprint_status(task); | ||
1482 | |||
1483 | task->tk_action = call_refreshresult; | ||
1484 | task->tk_status = 0; | ||
1485 | task->tk_client->cl_stats->rpcauthrefresh++; | ||
1486 | rpcauth_refreshcred(task); | ||
1487 | } | ||
1488 | |||
1489 | /* | ||
1490 | * 8a. Process the results of a credential refresh | ||
1491 | */ | ||
1492 | static void | ||
1493 | call_refreshresult(struct rpc_task *task) | ||
1494 | { | ||
1495 | int status = task->tk_status; | ||
1496 | |||
1497 | dprint_status(task); | ||
1498 | |||
1499 | task->tk_status = 0; | ||
1500 | task->tk_action = call_reserve; | ||
1501 | if (status >= 0 && rpcauth_uptodatecred(task)) | ||
1502 | return; | ||
1503 | if (status == -EACCES) { | ||
1504 | rpc_exit(task, -EACCES); | ||
1505 | return; | ||
1506 | } | ||
1507 | task->tk_action = call_refresh; | ||
1508 | if (status != -ETIMEDOUT) | ||
1509 | rpc_delay(task, 3*HZ); | ||
1510 | } | ||
1511 | |||
1512 | static __be32 * | 1596 | static __be32 * |
1513 | rpc_encode_header(struct rpc_task *task) | 1597 | rpc_encode_header(struct rpc_task *task) |
1514 | { | 1598 | { |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 4a843b883b89..cace6049e4a5 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -246,17 +246,8 @@ static inline void rpc_task_set_debuginfo(struct rpc_task *task) | |||
246 | 246 | ||
247 | static void rpc_set_active(struct rpc_task *task) | 247 | static void rpc_set_active(struct rpc_task *task) |
248 | { | 248 | { |
249 | struct rpc_clnt *clnt; | ||
250 | if (test_and_set_bit(RPC_TASK_ACTIVE, &task->tk_runstate) != 0) | ||
251 | return; | ||
252 | rpc_task_set_debuginfo(task); | 249 | rpc_task_set_debuginfo(task); |
253 | /* Add to global list of all tasks */ | 250 | set_bit(RPC_TASK_ACTIVE, &task->tk_runstate); |
254 | clnt = task->tk_client; | ||
255 | if (clnt != NULL) { | ||
256 | spin_lock(&clnt->cl_lock); | ||
257 | list_add_tail(&task->tk_task, &clnt->cl_tasks); | ||
258 | spin_unlock(&clnt->cl_lock); | ||
259 | } | ||
260 | } | 251 | } |
261 | 252 | ||
262 | /* | 253 | /* |
@@ -319,11 +310,6 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, | |||
319 | dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n", | 310 | dprintk("RPC: %5u sleep_on(queue \"%s\" time %lu)\n", |
320 | task->tk_pid, rpc_qname(q), jiffies); | 311 | task->tk_pid, rpc_qname(q), jiffies); |
321 | 312 | ||
322 | if (!RPC_IS_ASYNC(task) && !RPC_IS_ACTIVATED(task)) { | ||
323 | printk(KERN_ERR "RPC: Inactive synchronous task put to sleep!\n"); | ||
324 | return; | ||
325 | } | ||
326 | |||
327 | __rpc_add_wait_queue(q, task); | 313 | __rpc_add_wait_queue(q, task); |
328 | 314 | ||
329 | BUG_ON(task->tk_callback != NULL); | 315 | BUG_ON(task->tk_callback != NULL); |
@@ -334,8 +320,8 @@ static void __rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, | |||
334 | void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, | 320 | void rpc_sleep_on(struct rpc_wait_queue *q, struct rpc_task *task, |
335 | rpc_action action) | 321 | rpc_action action) |
336 | { | 322 | { |
337 | /* Mark the task as being activated if so needed */ | 323 | /* We shouldn't ever put an inactive task to sleep */ |
338 | rpc_set_active(task); | 324 | BUG_ON(!RPC_IS_ACTIVATED(task)); |
339 | 325 | ||
340 | /* | 326 | /* |
341 | * Protect the queue operations. | 327 | * Protect the queue operations. |
@@ -406,14 +392,6 @@ void rpc_wake_up_queued_task(struct rpc_wait_queue *queue, struct rpc_task *task | |||
406 | EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task); | 392 | EXPORT_SYMBOL_GPL(rpc_wake_up_queued_task); |
407 | 393 | ||
408 | /* | 394 | /* |
409 | * Wake up the specified task | ||
410 | */ | ||
411 | static void rpc_wake_up_task(struct rpc_task *task) | ||
412 | { | ||
413 | rpc_wake_up_queued_task(task->tk_waitqueue, task); | ||
414 | } | ||
415 | |||
416 | /* | ||
417 | * Wake up the next task on a priority queue. | 395 | * Wake up the next task on a priority queue. |
418 | */ | 396 | */ |
419 | static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queue) | 397 | static struct rpc_task * __rpc_wake_up_next_priority(struct rpc_wait_queue *queue) |
@@ -600,7 +578,15 @@ void rpc_exit_task(struct rpc_task *task) | |||
600 | } | 578 | } |
601 | } | 579 | } |
602 | } | 580 | } |
603 | EXPORT_SYMBOL_GPL(rpc_exit_task); | 581 | |
582 | void rpc_exit(struct rpc_task *task, int status) | ||
583 | { | ||
584 | task->tk_status = status; | ||
585 | task->tk_action = rpc_exit_task; | ||
586 | if (RPC_IS_QUEUED(task)) | ||
587 | rpc_wake_up_queued_task(task->tk_waitqueue, task); | ||
588 | } | ||
589 | EXPORT_SYMBOL_GPL(rpc_exit); | ||
604 | 590 | ||
605 | void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata) | 591 | void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata) |
606 | { | 592 | { |
@@ -690,7 +676,6 @@ static void __rpc_execute(struct rpc_task *task) | |||
690 | dprintk("RPC: %5u got signal\n", task->tk_pid); | 676 | dprintk("RPC: %5u got signal\n", task->tk_pid); |
691 | task->tk_flags |= RPC_TASK_KILLED; | 677 | task->tk_flags |= RPC_TASK_KILLED; |
692 | rpc_exit(task, -ERESTARTSYS); | 678 | rpc_exit(task, -ERESTARTSYS); |
693 | rpc_wake_up_task(task); | ||
694 | } | 679 | } |
695 | rpc_set_running(task); | 680 | rpc_set_running(task); |
696 | dprintk("RPC: %5u sync task resuming\n", task->tk_pid); | 681 | dprintk("RPC: %5u sync task resuming\n", task->tk_pid); |
@@ -714,8 +699,9 @@ static void __rpc_execute(struct rpc_task *task) | |||
714 | void rpc_execute(struct rpc_task *task) | 699 | void rpc_execute(struct rpc_task *task) |
715 | { | 700 | { |
716 | rpc_set_active(task); | 701 | rpc_set_active(task); |
717 | rpc_set_running(task); | 702 | rpc_make_runnable(task); |
718 | __rpc_execute(task); | 703 | if (!RPC_IS_ASYNC(task)) |
704 | __rpc_execute(task); | ||
719 | } | 705 | } |
720 | 706 | ||
721 | static void rpc_async_schedule(struct work_struct *work) | 707 | static void rpc_async_schedule(struct work_struct *work) |
@@ -808,26 +794,9 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta | |||
808 | /* Initialize workqueue for async tasks */ | 794 | /* Initialize workqueue for async tasks */ |
809 | task->tk_workqueue = task_setup_data->workqueue; | 795 | task->tk_workqueue = task_setup_data->workqueue; |
810 | 796 | ||
811 | task->tk_client = task_setup_data->rpc_client; | ||
812 | if (task->tk_client != NULL) { | ||
813 | kref_get(&task->tk_client->cl_kref); | ||
814 | if (task->tk_client->cl_softrtry) | ||
815 | task->tk_flags |= RPC_TASK_SOFT; | ||
816 | } | ||
817 | |||
818 | if (task->tk_ops->rpc_call_prepare != NULL) | 797 | if (task->tk_ops->rpc_call_prepare != NULL) |
819 | task->tk_action = rpc_prepare_task; | 798 | task->tk_action = rpc_prepare_task; |
820 | 799 | ||
821 | if (task_setup_data->rpc_message != NULL) { | ||
822 | task->tk_msg.rpc_proc = task_setup_data->rpc_message->rpc_proc; | ||
823 | task->tk_msg.rpc_argp = task_setup_data->rpc_message->rpc_argp; | ||
824 | task->tk_msg.rpc_resp = task_setup_data->rpc_message->rpc_resp; | ||
825 | /* Bind the user cred */ | ||
826 | rpcauth_bindcred(task, task_setup_data->rpc_message->rpc_cred, task_setup_data->flags); | ||
827 | if (task->tk_action == NULL) | ||
828 | rpc_call_start(task); | ||
829 | } | ||
830 | |||
831 | /* starting timestamp */ | 800 | /* starting timestamp */ |
832 | task->tk_start = ktime_get(); | 801 | task->tk_start = ktime_get(); |
833 | 802 | ||
@@ -896,11 +865,8 @@ void rpc_put_task(struct rpc_task *task) | |||
896 | if (task->tk_rqstp) | 865 | if (task->tk_rqstp) |
897 | xprt_release(task); | 866 | xprt_release(task); |
898 | if (task->tk_msg.rpc_cred) | 867 | if (task->tk_msg.rpc_cred) |
899 | rpcauth_unbindcred(task); | 868 | put_rpccred(task->tk_msg.rpc_cred); |
900 | if (task->tk_client) { | 869 | rpc_task_release_client(task); |
901 | rpc_release_client(task->tk_client); | ||
902 | task->tk_client = NULL; | ||
903 | } | ||
904 | if (task->tk_workqueue != NULL) { | 870 | if (task->tk_workqueue != NULL) { |
905 | INIT_WORK(&task->u.tk_work, rpc_async_release); | 871 | INIT_WORK(&task->u.tk_work, rpc_async_release); |
906 | queue_work(task->tk_workqueue, &task->u.tk_work); | 872 | queue_work(task->tk_workqueue, &task->u.tk_work); |
@@ -913,13 +879,6 @@ static void rpc_release_task(struct rpc_task *task) | |||
913 | { | 879 | { |
914 | dprintk("RPC: %5u release task\n", task->tk_pid); | 880 | dprintk("RPC: %5u release task\n", task->tk_pid); |
915 | 881 | ||
916 | if (!list_empty(&task->tk_task)) { | ||
917 | struct rpc_clnt *clnt = task->tk_client; | ||
918 | /* Remove from client task list */ | ||
919 | spin_lock(&clnt->cl_lock); | ||
920 | list_del(&task->tk_task); | ||
921 | spin_unlock(&clnt->cl_lock); | ||
922 | } | ||
923 | BUG_ON (RPC_IS_QUEUED(task)); | 882 | BUG_ON (RPC_IS_QUEUED(task)); |
924 | 883 | ||
925 | /* Wake up anyone who is waiting for task completion */ | 884 | /* Wake up anyone who is waiting for task completion */ |
@@ -928,35 +887,6 @@ static void rpc_release_task(struct rpc_task *task) | |||
928 | rpc_put_task(task); | 887 | rpc_put_task(task); |
929 | } | 888 | } |
930 | 889 | ||
931 | /* | ||
932 | * Kill all tasks for the given client. | ||
933 | * XXX: kill their descendants as well? | ||
934 | */ | ||
935 | void rpc_killall_tasks(struct rpc_clnt *clnt) | ||
936 | { | ||
937 | struct rpc_task *rovr; | ||
938 | |||
939 | |||
940 | if (list_empty(&clnt->cl_tasks)) | ||
941 | return; | ||
942 | dprintk("RPC: killing all tasks for client %p\n", clnt); | ||
943 | /* | ||
944 | * Spin lock all_tasks to prevent changes... | ||
945 | */ | ||
946 | spin_lock(&clnt->cl_lock); | ||
947 | list_for_each_entry(rovr, &clnt->cl_tasks, tk_task) { | ||
948 | if (! RPC_IS_ACTIVATED(rovr)) | ||
949 | continue; | ||
950 | if (!(rovr->tk_flags & RPC_TASK_KILLED)) { | ||
951 | rovr->tk_flags |= RPC_TASK_KILLED; | ||
952 | rpc_exit(rovr, -EIO); | ||
953 | rpc_wake_up_task(rovr); | ||
954 | } | ||
955 | } | ||
956 | spin_unlock(&clnt->cl_lock); | ||
957 | } | ||
958 | EXPORT_SYMBOL_GPL(rpc_killall_tasks); | ||
959 | |||
960 | int rpciod_up(void) | 890 | int rpciod_up(void) |
961 | { | 891 | { |
962 | return try_module_get(THIS_MODULE) ? 0 : -EINVAL; | 892 | return try_module_get(THIS_MODULE) ? 0 : -EINVAL; |
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index f438347d817b..34b58f9e704a 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c | |||
@@ -33,10 +33,11 @@ init_sunrpc(void) | |||
33 | if (err) | 33 | if (err) |
34 | goto out; | 34 | goto out; |
35 | err = rpc_init_mempool(); | 35 | err = rpc_init_mempool(); |
36 | if (err) { | 36 | if (err) |
37 | unregister_rpc_pipefs(); | 37 | goto out2; |
38 | goto out; | 38 | err = rpcauth_init_module(); |
39 | } | 39 | if (err) |
40 | goto out3; | ||
40 | #ifdef RPC_DEBUG | 41 | #ifdef RPC_DEBUG |
41 | rpc_register_sysctl(); | 42 | rpc_register_sysctl(); |
42 | #endif | 43 | #endif |
@@ -47,7 +48,11 @@ init_sunrpc(void) | |||
47 | cache_register(&unix_gid_cache); | 48 | cache_register(&unix_gid_cache); |
48 | svc_init_xprt_sock(); /* svc sock transport */ | 49 | svc_init_xprt_sock(); /* svc sock transport */ |
49 | init_socket_xprt(); /* clnt sock transport */ | 50 | init_socket_xprt(); /* clnt sock transport */ |
50 | rpcauth_init_module(); | 51 | return 0; |
52 | out3: | ||
53 | rpc_destroy_mempool(); | ||
54 | out2: | ||
55 | unregister_rpc_pipefs(); | ||
51 | out: | 56 | out: |
52 | return err; | 57 | return err; |
53 | } | 58 | } |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index dcd0132396ba..970fb00f388c 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -1032,6 +1032,8 @@ void xprt_release(struct rpc_task *task) | |||
1032 | spin_unlock_bh(&xprt->transport_lock); | 1032 | spin_unlock_bh(&xprt->transport_lock); |
1033 | if (req->rq_buffer) | 1033 | if (req->rq_buffer) |
1034 | xprt->ops->buf_free(req->rq_buffer); | 1034 | xprt->ops->buf_free(req->rq_buffer); |
1035 | if (req->rq_cred != NULL) | ||
1036 | put_rpccred(req->rq_cred); | ||
1035 | task->tk_rqstp = NULL; | 1037 | task->tk_rqstp = NULL; |
1036 | if (req->rq_release_snd_buf) | 1038 | if (req->rq_release_snd_buf) |
1037 | req->rq_release_snd_buf(req); | 1039 | req->rq_release_snd_buf(req); |
@@ -1129,6 +1131,7 @@ static void xprt_destroy(struct kref *kref) | |||
1129 | rpc_destroy_wait_queue(&xprt->sending); | 1131 | rpc_destroy_wait_queue(&xprt->sending); |
1130 | rpc_destroy_wait_queue(&xprt->resend); | 1132 | rpc_destroy_wait_queue(&xprt->resend); |
1131 | rpc_destroy_wait_queue(&xprt->backlog); | 1133 | rpc_destroy_wait_queue(&xprt->backlog); |
1134 | cancel_work_sync(&xprt->task_cleanup); | ||
1132 | /* | 1135 | /* |
1133 | * Tear down transport state and free the rpc_xprt | 1136 | * Tear down transport state and free the rpc_xprt |
1134 | */ | 1137 | */ |