diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-09-14 20:04:48 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-09-14 20:04:48 -0400 |
| commit | de8d4f5d758786a2cbcfa54a6a85ce747e5637e3 (patch) | |
| tree | a09c0a4f8fe995bea2dde0ea4fa5dbdd32cf3fd4 | |
| parent | 75e1c70fc31490ef8a373ea2a4bea2524099b478 (diff) | |
| parent | 827e3457022d0bb0b1bb8a0eb88501876fe7dcf0 (diff) | |
Merge branch 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6
* 'bugfixes' of git://git.linux-nfs.org/projects/trondmy/nfs-2.6:
SUNRPC: Fix the NFSv4 and RPCSEC_GSS Kconfig dependencies
statfs() gives ESTALE error
NFS: Fix a typo in nfs_sockaddr_match_ipaddr6
sunrpc: increase MAX_HASHTABLE_BITS to 14
gss:spkm3 miss returning error to caller when import security context
gss:krb5 miss returning error to caller when import security context
Remove incorrect do_vfs_lock message
SUNRPC: cleanup state-machine ordering
SUNRPC: Fix a race in rpc_info_open
SUNRPC: Fix race corrupting rpc upcall
Fix null dereference in call_allocate
| -rw-r--r-- | fs/nfs/Kconfig | 1 | ||||
| -rw-r--r-- | fs/nfs/client.c | 2 | ||||
| -rw-r--r-- | fs/nfs/file.c | 4 | ||||
| -rw-r--r-- | fs/nfs/super.c | 8 | ||||
| -rw-r--r-- | fs/nfsd/Kconfig | 1 | ||||
| -rw-r--r-- | include/linux/sunrpc/clnt.h | 2 | ||||
| -rw-r--r-- | net/sunrpc/auth.c | 2 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 9 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_mech.c | 10 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/gss_spkm3_mech.c | 5 | ||||
| -rw-r--r-- | net/sunrpc/clnt.c | 116 | ||||
| -rw-r--r-- | net/sunrpc/rpc_pipe.c | 20 |
12 files changed, 98 insertions, 82 deletions
diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 6c2aad49d731..f7e13db613cb 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig | |||
| @@ -63,6 +63,7 @@ config NFS_V3_ACL | |||
| 63 | config NFS_V4 | 63 | config NFS_V4 |
| 64 | bool "NFS client support for NFS version 4" | 64 | bool "NFS client support for NFS version 4" |
| 65 | depends on NFS_FS | 65 | depends on NFS_FS |
| 66 | select SUNRPC_GSS | ||
| 66 | help | 67 | help |
| 67 | This option enables support for version 4 of the NFS protocol | 68 | This option enables support for version 4 of the NFS protocol |
| 68 | (RFC 3530) in the kernel's NFS client. | 69 | (RFC 3530) in the kernel's NFS client. |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 4e7df2adb212..e7340729af89 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -275,7 +275,7 @@ static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, | |||
| 275 | sin1->sin6_scope_id != sin2->sin6_scope_id) | 275 | sin1->sin6_scope_id != sin2->sin6_scope_id) |
| 276 | return 0; | 276 | return 0; |
| 277 | 277 | ||
| 278 | return ipv6_addr_equal(&sin1->sin6_addr, &sin1->sin6_addr); | 278 | return ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr); |
| 279 | } | 279 | } |
| 280 | #else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */ | 280 | #else /* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */ |
| 281 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, | 281 | static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1, |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index eb51bd6201da..05bf3c0dc751 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
| @@ -723,10 +723,6 @@ static int do_vfs_lock(struct file *file, struct file_lock *fl) | |||
| 723 | default: | 723 | default: |
| 724 | BUG(); | 724 | BUG(); |
| 725 | } | 725 | } |
| 726 | if (res < 0) | ||
| 727 | dprintk(KERN_WARNING "%s: VFS is out of sync with lock manager" | ||
| 728 | " - error %d!\n", | ||
| 729 | __func__, res); | ||
| 730 | return res; | 726 | return res; |
| 731 | } | 727 | } |
| 732 | 728 | ||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index ec3966e4706b..f4cbf0c306c6 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
| @@ -431,7 +431,15 @@ static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 431 | goto out_err; | 431 | goto out_err; |
| 432 | 432 | ||
| 433 | error = server->nfs_client->rpc_ops->statfs(server, fh, &res); | 433 | error = server->nfs_client->rpc_ops->statfs(server, fh, &res); |
| 434 | if (unlikely(error == -ESTALE)) { | ||
| 435 | struct dentry *pd_dentry; | ||
| 434 | 436 | ||
| 437 | pd_dentry = dget_parent(dentry); | ||
| 438 | if (pd_dentry != NULL) { | ||
| 439 | nfs_zap_caches(pd_dentry->d_inode); | ||
| 440 | dput(pd_dentry); | ||
| 441 | } | ||
| 442 | } | ||
| 435 | nfs_free_fattr(res.fattr); | 443 | nfs_free_fattr(res.fattr); |
| 436 | if (error < 0) | 444 | if (error < 0) |
| 437 | goto out_err; | 445 | goto out_err; |
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig index 95932f523aef..4264377552e2 100644 --- a/fs/nfsd/Kconfig +++ b/fs/nfsd/Kconfig | |||
| @@ -69,6 +69,7 @@ config NFSD_V4 | |||
| 69 | depends on NFSD && PROC_FS && EXPERIMENTAL | 69 | depends on NFSD && PROC_FS && EXPERIMENTAL |
| 70 | select NFSD_V3 | 70 | select NFSD_V3 |
| 71 | select FS_POSIX_ACL | 71 | select FS_POSIX_ACL |
| 72 | select SUNRPC_GSS | ||
| 72 | help | 73 | help |
| 73 | This option enables support in your system's NFS server for | 74 | This option enables support in your system's NFS server for |
| 74 | version 4 of the NFS protocol (RFC 3530). | 75 | version 4 of the NFS protocol (RFC 3530). |
diff --git a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h index 569dc722a600..85f38a63f098 100644 --- a/include/linux/sunrpc/clnt.h +++ b/include/linux/sunrpc/clnt.h | |||
| @@ -30,7 +30,7 @@ struct rpc_inode; | |||
| 30 | * The high-level client handle | 30 | * The high-level client handle |
| 31 | */ | 31 | */ |
| 32 | struct rpc_clnt { | 32 | struct rpc_clnt { |
| 33 | struct kref cl_kref; /* Number of references */ | 33 | atomic_t cl_count; /* Number of references */ |
| 34 | struct list_head cl_clients; /* Global list of clients */ | 34 | struct list_head cl_clients; /* Global list of clients */ |
| 35 | struct list_head cl_tasks; /* List of tasks */ | 35 | struct list_head cl_tasks; /* List of tasks */ |
| 36 | spinlock_t cl_lock; /* spinlock */ | 36 | spinlock_t cl_lock; /* spinlock */ |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 36cb66022a27..e9eaaf7d43c1 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
| @@ -38,7 +38,7 @@ static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { | |||
| 38 | static LIST_HEAD(cred_unused); | 38 | static LIST_HEAD(cred_unused); |
| 39 | static unsigned long number_cred_unused; | 39 | static unsigned long number_cred_unused; |
| 40 | 40 | ||
| 41 | #define MAX_HASHTABLE_BITS (10) | 41 | #define MAX_HASHTABLE_BITS (14) |
| 42 | static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) | 42 | static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) |
| 43 | { | 43 | { |
| 44 | unsigned long num; | 44 | unsigned long num; |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index dcfc66bab2bb..12c485982814 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
| @@ -745,17 +745,18 @@ gss_pipe_release(struct inode *inode) | |||
| 745 | struct rpc_inode *rpci = RPC_I(inode); | 745 | struct rpc_inode *rpci = RPC_I(inode); |
| 746 | struct gss_upcall_msg *gss_msg; | 746 | struct gss_upcall_msg *gss_msg; |
| 747 | 747 | ||
| 748 | restart: | ||
| 748 | spin_lock(&inode->i_lock); | 749 | spin_lock(&inode->i_lock); |
| 749 | while (!list_empty(&rpci->in_downcall)) { | 750 | list_for_each_entry(gss_msg, &rpci->in_downcall, list) { |
| 750 | 751 | ||
| 751 | gss_msg = list_entry(rpci->in_downcall.next, | 752 | if (!list_empty(&gss_msg->msg.list)) |
| 752 | struct gss_upcall_msg, list); | 753 | continue; |
| 753 | gss_msg->msg.errno = -EPIPE; | 754 | gss_msg->msg.errno = -EPIPE; |
| 754 | atomic_inc(&gss_msg->count); | 755 | atomic_inc(&gss_msg->count); |
| 755 | __gss_unhash_msg(gss_msg); | 756 | __gss_unhash_msg(gss_msg); |
| 756 | spin_unlock(&inode->i_lock); | 757 | spin_unlock(&inode->i_lock); |
| 757 | gss_release_msg(gss_msg); | 758 | gss_release_msg(gss_msg); |
| 758 | spin_lock(&inode->i_lock); | 759 | goto restart; |
| 759 | } | 760 | } |
| 760 | spin_unlock(&inode->i_lock); | 761 | spin_unlock(&inode->i_lock); |
| 761 | 762 | ||
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 032644610524..778e5dfc5144 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c | |||
| @@ -237,6 +237,7 @@ get_key(const void *p, const void *end, | |||
| 237 | if (!supported_gss_krb5_enctype(alg)) { | 237 | if (!supported_gss_krb5_enctype(alg)) { |
| 238 | printk(KERN_WARNING "gss_kerberos_mech: unsupported " | 238 | printk(KERN_WARNING "gss_kerberos_mech: unsupported " |
| 239 | "encryption key algorithm %d\n", alg); | 239 | "encryption key algorithm %d\n", alg); |
| 240 | p = ERR_PTR(-EINVAL); | ||
| 240 | goto out_err; | 241 | goto out_err; |
| 241 | } | 242 | } |
| 242 | p = simple_get_netobj(p, end, &key); | 243 | p = simple_get_netobj(p, end, &key); |
| @@ -282,15 +283,19 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) | |||
| 282 | ctx->enctype = ENCTYPE_DES_CBC_RAW; | 283 | ctx->enctype = ENCTYPE_DES_CBC_RAW; |
| 283 | 284 | ||
| 284 | ctx->gk5e = get_gss_krb5_enctype(ctx->enctype); | 285 | ctx->gk5e = get_gss_krb5_enctype(ctx->enctype); |
| 285 | if (ctx->gk5e == NULL) | 286 | if (ctx->gk5e == NULL) { |
| 287 | p = ERR_PTR(-EINVAL); | ||
| 286 | goto out_err; | 288 | goto out_err; |
| 289 | } | ||
| 287 | 290 | ||
| 288 | /* The downcall format was designed before we completely understood | 291 | /* The downcall format was designed before we completely understood |
| 289 | * the uses of the context fields; so it includes some stuff we | 292 | * the uses of the context fields; so it includes some stuff we |
| 290 | * just give some minimal sanity-checking, and some we ignore | 293 | * just give some minimal sanity-checking, and some we ignore |
| 291 | * completely (like the next twenty bytes): */ | 294 | * completely (like the next twenty bytes): */ |
| 292 | if (unlikely(p + 20 > end || p + 20 < p)) | 295 | if (unlikely(p + 20 > end || p + 20 < p)) { |
| 296 | p = ERR_PTR(-EFAULT); | ||
| 293 | goto out_err; | 297 | goto out_err; |
| 298 | } | ||
| 294 | p += 20; | 299 | p += 20; |
| 295 | p = simple_get_bytes(p, end, &tmp, sizeof(tmp)); | 300 | p = simple_get_bytes(p, end, &tmp, sizeof(tmp)); |
| 296 | if (IS_ERR(p)) | 301 | if (IS_ERR(p)) |
| @@ -619,6 +624,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, | |||
| 619 | if (ctx->seq_send64 != ctx->seq_send) { | 624 | if (ctx->seq_send64 != ctx->seq_send) { |
| 620 | dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__, | 625 | dprintk("%s: seq_send64 %lx, seq_send %x overflow?\n", __func__, |
| 621 | (long unsigned)ctx->seq_send64, ctx->seq_send); | 626 | (long unsigned)ctx->seq_send64, ctx->seq_send); |
| 627 | p = ERR_PTR(-EINVAL); | ||
| 622 | goto out_err; | 628 | goto out_err; |
| 623 | } | 629 | } |
| 624 | p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype)); | 630 | p = simple_get_bytes(p, end, &ctx->enctype, sizeof(ctx->enctype)); |
diff --git a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c index dc3f1f5ed865..adade3d313f2 100644 --- a/net/sunrpc/auth_gss/gss_spkm3_mech.c +++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c | |||
| @@ -100,6 +100,7 @@ gss_import_sec_context_spkm3(const void *p, size_t len, | |||
| 100 | if (version != 1) { | 100 | if (version != 1) { |
| 101 | dprintk("RPC: unknown spkm3 token format: " | 101 | dprintk("RPC: unknown spkm3 token format: " |
| 102 | "obsolete nfs-utils?\n"); | 102 | "obsolete nfs-utils?\n"); |
| 103 | p = ERR_PTR(-EINVAL); | ||
| 103 | goto out_err_free_ctx; | 104 | goto out_err_free_ctx; |
| 104 | } | 105 | } |
| 105 | 106 | ||
| @@ -135,8 +136,10 @@ gss_import_sec_context_spkm3(const void *p, size_t len, | |||
| 135 | if (IS_ERR(p)) | 136 | if (IS_ERR(p)) |
| 136 | goto out_err_free_intg_alg; | 137 | goto out_err_free_intg_alg; |
| 137 | 138 | ||
| 138 | if (p != end) | 139 | if (p != end) { |
| 140 | p = ERR_PTR(-EFAULT); | ||
| 139 | goto out_err_free_intg_key; | 141 | goto out_err_free_intg_key; |
| 142 | } | ||
| 140 | 143 | ||
| 141 | ctx_id->internal_ctx_id = ctx; | 144 | ctx_id->internal_ctx_id = ctx; |
| 142 | 145 | ||
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 2388d83b68ff..fa5549079d79 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -226,7 +226,7 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, stru | |||
| 226 | goto out_no_principal; | 226 | goto out_no_principal; |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | kref_init(&clnt->cl_kref); | 229 | atomic_set(&clnt->cl_count, 1); |
| 230 | 230 | ||
| 231 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); | 231 | err = rpc_setup_pipedir(clnt, program->pipe_dir_name); |
| 232 | if (err < 0) | 232 | if (err < 0) |
| @@ -390,14 +390,14 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
| 390 | if (new->cl_principal == NULL) | 390 | if (new->cl_principal == NULL) |
| 391 | goto out_no_principal; | 391 | goto out_no_principal; |
| 392 | } | 392 | } |
| 393 | kref_init(&new->cl_kref); | 393 | atomic_set(&new->cl_count, 1); |
| 394 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); | 394 | err = rpc_setup_pipedir(new, clnt->cl_program->pipe_dir_name); |
| 395 | if (err != 0) | 395 | if (err != 0) |
| 396 | goto out_no_path; | 396 | goto out_no_path; |
| 397 | if (new->cl_auth) | 397 | if (new->cl_auth) |
| 398 | atomic_inc(&new->cl_auth->au_count); | 398 | atomic_inc(&new->cl_auth->au_count); |
| 399 | xprt_get(clnt->cl_xprt); | 399 | xprt_get(clnt->cl_xprt); |
| 400 | kref_get(&clnt->cl_kref); | 400 | atomic_inc(&clnt->cl_count); |
| 401 | rpc_register_client(new); | 401 | rpc_register_client(new); |
| 402 | rpciod_up(); | 402 | rpciod_up(); |
| 403 | return new; | 403 | return new; |
| @@ -465,10 +465,8 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client); | |||
| 465 | * Free an RPC client | 465 | * Free an RPC client |
| 466 | */ | 466 | */ |
| 467 | static void | 467 | static void |
| 468 | rpc_free_client(struct kref *kref) | 468 | rpc_free_client(struct rpc_clnt *clnt) |
| 469 | { | 469 | { |
| 470 | struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); | ||
| 471 | |||
| 472 | dprintk("RPC: destroying %s client for %s\n", | 470 | dprintk("RPC: destroying %s client for %s\n", |
| 473 | clnt->cl_protname, clnt->cl_server); | 471 | clnt->cl_protname, clnt->cl_server); |
| 474 | if (!IS_ERR(clnt->cl_path.dentry)) { | 472 | if (!IS_ERR(clnt->cl_path.dentry)) { |
| @@ -495,12 +493,10 @@ out_free: | |||
| 495 | * Free an RPC client | 493 | * Free an RPC client |
| 496 | */ | 494 | */ |
| 497 | static void | 495 | static void |
| 498 | rpc_free_auth(struct kref *kref) | 496 | rpc_free_auth(struct rpc_clnt *clnt) |
| 499 | { | 497 | { |
| 500 | struct rpc_clnt *clnt = container_of(kref, struct rpc_clnt, cl_kref); | ||
| 501 | |||
| 502 | if (clnt->cl_auth == NULL) { | 498 | if (clnt->cl_auth == NULL) { |
| 503 | rpc_free_client(kref); | 499 | rpc_free_client(clnt); |
| 504 | return; | 500 | return; |
| 505 | } | 501 | } |
| 506 | 502 | ||
| @@ -509,10 +505,11 @@ rpc_free_auth(struct kref *kref) | |||
| 509 | * release remaining GSS contexts. This mechanism ensures | 505 | * release remaining GSS contexts. This mechanism ensures |
| 510 | * that it can do so safely. | 506 | * that it can do so safely. |
| 511 | */ | 507 | */ |
| 512 | kref_init(kref); | 508 | atomic_inc(&clnt->cl_count); |
| 513 | rpcauth_release(clnt->cl_auth); | 509 | rpcauth_release(clnt->cl_auth); |
| 514 | clnt->cl_auth = NULL; | 510 | clnt->cl_auth = NULL; |
| 515 | kref_put(kref, rpc_free_client); | 511 | if (atomic_dec_and_test(&clnt->cl_count)) |
| 512 | rpc_free_client(clnt); | ||
| 516 | } | 513 | } |
| 517 | 514 | ||
| 518 | /* | 515 | /* |
| @@ -525,7 +522,8 @@ rpc_release_client(struct rpc_clnt *clnt) | |||
| 525 | 522 | ||
| 526 | if (list_empty(&clnt->cl_tasks)) | 523 | if (list_empty(&clnt->cl_tasks)) |
| 527 | wake_up(&destroy_wait); | 524 | wake_up(&destroy_wait); |
| 528 | kref_put(&clnt->cl_kref, rpc_free_auth); | 525 | if (atomic_dec_and_test(&clnt->cl_count)) |
| 526 | rpc_free_auth(clnt); | ||
| 529 | } | 527 | } |
| 530 | 528 | ||
| 531 | /** | 529 | /** |
| @@ -588,7 +586,7 @@ void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) | |||
| 588 | if (clnt != NULL) { | 586 | if (clnt != NULL) { |
| 589 | rpc_task_release_client(task); | 587 | rpc_task_release_client(task); |
| 590 | task->tk_client = clnt; | 588 | task->tk_client = clnt; |
| 591 | kref_get(&clnt->cl_kref); | 589 | atomic_inc(&clnt->cl_count); |
| 592 | if (clnt->cl_softrtry) | 590 | if (clnt->cl_softrtry) |
| 593 | task->tk_flags |= RPC_TASK_SOFT; | 591 | task->tk_flags |= RPC_TASK_SOFT; |
| 594 | /* Add to the client's list of all tasks */ | 592 | /* Add to the client's list of all tasks */ |
| @@ -931,7 +929,7 @@ call_reserveresult(struct rpc_task *task) | |||
| 931 | task->tk_status = 0; | 929 | task->tk_status = 0; |
| 932 | if (status >= 0) { | 930 | if (status >= 0) { |
| 933 | if (task->tk_rqstp) { | 931 | if (task->tk_rqstp) { |
| 934 | task->tk_action = call_allocate; | 932 | task->tk_action = call_refresh; |
| 935 | return; | 933 | return; |
| 936 | } | 934 | } |
| 937 | 935 | ||
| @@ -966,13 +964,54 @@ call_reserveresult(struct rpc_task *task) | |||
| 966 | } | 964 | } |
| 967 | 965 | ||
| 968 | /* | 966 | /* |
| 969 | * 2. Allocate the buffer. For details, see sched.c:rpc_malloc. | 967 | * 2. Bind and/or refresh the credentials |
| 968 | */ | ||
| 969 | static void | ||
| 970 | call_refresh(struct rpc_task *task) | ||
| 971 | { | ||
| 972 | dprint_status(task); | ||
| 973 | |||
| 974 | task->tk_action = call_refreshresult; | ||
| 975 | task->tk_status = 0; | ||
| 976 | task->tk_client->cl_stats->rpcauthrefresh++; | ||
| 977 | rpcauth_refreshcred(task); | ||
| 978 | } | ||
| 979 | |||
| 980 | /* | ||
| 981 | * 2a. Process the results of a credential refresh | ||
| 982 | */ | ||
| 983 | static void | ||
| 984 | call_refreshresult(struct rpc_task *task) | ||
| 985 | { | ||
| 986 | int status = task->tk_status; | ||
| 987 | |||
| 988 | dprint_status(task); | ||
| 989 | |||
| 990 | task->tk_status = 0; | ||
| 991 | task->tk_action = call_allocate; | ||
| 992 | if (status >= 0 && rpcauth_uptodatecred(task)) | ||
| 993 | return; | ||
| 994 | switch (status) { | ||
| 995 | case -EACCES: | ||
| 996 | rpc_exit(task, -EACCES); | ||
| 997 | return; | ||
| 998 | case -ENOMEM: | ||
| 999 | rpc_exit(task, -ENOMEM); | ||
| 1000 | return; | ||
| 1001 | case -ETIMEDOUT: | ||
| 1002 | rpc_delay(task, 3*HZ); | ||
| 1003 | } | ||
| 1004 | task->tk_action = call_refresh; | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | /* | ||
| 1008 | * 2b. Allocate the buffer. For details, see sched.c:rpc_malloc. | ||
| 970 | * (Note: buffer memory is freed in xprt_release). | 1009 | * (Note: buffer memory is freed in xprt_release). |
| 971 | */ | 1010 | */ |
| 972 | static void | 1011 | static void |
| 973 | call_allocate(struct rpc_task *task) | 1012 | call_allocate(struct rpc_task *task) |
| 974 | { | 1013 | { |
| 975 | unsigned int slack = task->tk_client->cl_auth->au_cslack; | 1014 | unsigned int slack = task->tk_rqstp->rq_cred->cr_auth->au_cslack; |
| 976 | struct rpc_rqst *req = task->tk_rqstp; | 1015 | struct rpc_rqst *req = task->tk_rqstp; |
| 977 | struct rpc_xprt *xprt = task->tk_xprt; | 1016 | struct rpc_xprt *xprt = task->tk_xprt; |
| 978 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; | 1017 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; |
| @@ -980,7 +1019,7 @@ call_allocate(struct rpc_task *task) | |||
| 980 | dprint_status(task); | 1019 | dprint_status(task); |
| 981 | 1020 | ||
| 982 | task->tk_status = 0; | 1021 | task->tk_status = 0; |
| 983 | task->tk_action = call_refresh; | 1022 | task->tk_action = call_bind; |
| 984 | 1023 | ||
| 985 | if (req->rq_buffer) | 1024 | if (req->rq_buffer) |
| 986 | return; | 1025 | return; |
| @@ -1017,47 +1056,6 @@ call_allocate(struct rpc_task *task) | |||
| 1017 | rpc_exit(task, -ERESTARTSYS); | 1056 | rpc_exit(task, -ERESTARTSYS); |
| 1018 | } | 1057 | } |
| 1019 | 1058 | ||
| 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 | |||
| 1061 | static inline int | 1059 | static inline int |
| 1062 | rpc_task_need_encode(struct rpc_task *task) | 1060 | rpc_task_need_encode(struct rpc_task *task) |
| 1063 | { | 1061 | { |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 95ccbcf45d3e..8c8eef2b8f26 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
| @@ -48,7 +48,7 @@ static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, | |||
| 48 | return; | 48 | return; |
| 49 | do { | 49 | do { |
| 50 | msg = list_entry(head->next, struct rpc_pipe_msg, list); | 50 | msg = list_entry(head->next, struct rpc_pipe_msg, list); |
| 51 | list_del(&msg->list); | 51 | list_del_init(&msg->list); |
| 52 | msg->errno = err; | 52 | msg->errno = err; |
| 53 | destroy_msg(msg); | 53 | destroy_msg(msg); |
| 54 | } while (!list_empty(head)); | 54 | } while (!list_empty(head)); |
| @@ -208,7 +208,7 @@ rpc_pipe_release(struct inode *inode, struct file *filp) | |||
| 208 | if (msg != NULL) { | 208 | if (msg != NULL) { |
| 209 | spin_lock(&inode->i_lock); | 209 | spin_lock(&inode->i_lock); |
| 210 | msg->errno = -EAGAIN; | 210 | msg->errno = -EAGAIN; |
| 211 | list_del(&msg->list); | 211 | list_del_init(&msg->list); |
| 212 | spin_unlock(&inode->i_lock); | 212 | spin_unlock(&inode->i_lock); |
| 213 | rpci->ops->destroy_msg(msg); | 213 | rpci->ops->destroy_msg(msg); |
| 214 | } | 214 | } |
| @@ -268,7 +268,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) | |||
| 268 | if (res < 0 || msg->len == msg->copied) { | 268 | if (res < 0 || msg->len == msg->copied) { |
| 269 | filp->private_data = NULL; | 269 | filp->private_data = NULL; |
| 270 | spin_lock(&inode->i_lock); | 270 | spin_lock(&inode->i_lock); |
| 271 | list_del(&msg->list); | 271 | list_del_init(&msg->list); |
| 272 | spin_unlock(&inode->i_lock); | 272 | spin_unlock(&inode->i_lock); |
| 273 | rpci->ops->destroy_msg(msg); | 273 | rpci->ops->destroy_msg(msg); |
| 274 | } | 274 | } |
| @@ -371,21 +371,23 @@ rpc_show_info(struct seq_file *m, void *v) | |||
| 371 | static int | 371 | static int |
| 372 | rpc_info_open(struct inode *inode, struct file *file) | 372 | rpc_info_open(struct inode *inode, struct file *file) |
| 373 | { | 373 | { |
| 374 | struct rpc_clnt *clnt; | 374 | struct rpc_clnt *clnt = NULL; |
| 375 | int ret = single_open(file, rpc_show_info, NULL); | 375 | int ret = single_open(file, rpc_show_info, NULL); |
| 376 | 376 | ||
| 377 | if (!ret) { | 377 | if (!ret) { |
| 378 | struct seq_file *m = file->private_data; | 378 | struct seq_file *m = file->private_data; |
| 379 | mutex_lock(&inode->i_mutex); | 379 | |
| 380 | clnt = RPC_I(inode)->private; | 380 | spin_lock(&file->f_path.dentry->d_lock); |
| 381 | if (clnt) { | 381 | if (!d_unhashed(file->f_path.dentry)) |
| 382 | kref_get(&clnt->cl_kref); | 382 | clnt = RPC_I(inode)->private; |
| 383 | if (clnt != NULL && atomic_inc_not_zero(&clnt->cl_count)) { | ||
| 384 | spin_unlock(&file->f_path.dentry->d_lock); | ||
| 383 | m->private = clnt; | 385 | m->private = clnt; |
| 384 | } else { | 386 | } else { |
| 387 | spin_unlock(&file->f_path.dentry->d_lock); | ||
| 385 | single_release(inode, file); | 388 | single_release(inode, file); |
| 386 | ret = -EINVAL; | 389 | ret = -EINVAL; |
| 387 | } | 390 | } |
| 388 | mutex_unlock(&inode->i_mutex); | ||
| 389 | } | 391 | } |
| 390 | return ret; | 392 | return ret; |
| 391 | } | 393 | } |
