diff options
-rw-r--r-- | fs/lockd/clntproc.c | 11 | ||||
-rw-r--r-- | fs/nfs/direct.c | 2 | ||||
-rw-r--r-- | include/linux/lockd/lockd.h | 2 | ||||
-rw-r--r-- | include/linux/sunrpc/auth.h | 10 | ||||
-rw-r--r-- | net/sunrpc/auth.c | 25 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 40 | ||||
-rw-r--r-- | net/sunrpc/auth_unix.c | 6 | ||||
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 102 |
8 files changed, 127 insertions, 71 deletions
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 145524039577..220058d8616d 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
@@ -22,12 +22,14 @@ | |||
22 | #define NLMDBG_FACILITY NLMDBG_CLIENT | 22 | #define NLMDBG_FACILITY NLMDBG_CLIENT |
23 | #define NLMCLNT_GRACE_WAIT (5*HZ) | 23 | #define NLMCLNT_GRACE_WAIT (5*HZ) |
24 | #define NLMCLNT_POLL_TIMEOUT (30*HZ) | 24 | #define NLMCLNT_POLL_TIMEOUT (30*HZ) |
25 | #define NLMCLNT_MAX_RETRIES 3 | ||
25 | 26 | ||
26 | static int nlmclnt_test(struct nlm_rqst *, struct file_lock *); | 27 | static int nlmclnt_test(struct nlm_rqst *, struct file_lock *); |
27 | static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *); | 28 | static int nlmclnt_lock(struct nlm_rqst *, struct file_lock *); |
28 | static int nlmclnt_unlock(struct nlm_rqst *, struct file_lock *); | 29 | static int nlmclnt_unlock(struct nlm_rqst *, struct file_lock *); |
29 | static int nlm_stat_to_errno(u32 stat); | 30 | static int nlm_stat_to_errno(u32 stat); |
30 | static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host); | 31 | static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *host); |
32 | static int nlmclnt_cancel(struct nlm_host *, int , struct file_lock *); | ||
31 | 33 | ||
32 | static const struct rpc_call_ops nlmclnt_unlock_ops; | 34 | static const struct rpc_call_ops nlmclnt_unlock_ops; |
33 | static const struct rpc_call_ops nlmclnt_cancel_ops; | 35 | static const struct rpc_call_ops nlmclnt_cancel_ops; |
@@ -598,7 +600,7 @@ out_unblock: | |||
598 | nlmclnt_finish_block(req); | 600 | nlmclnt_finish_block(req); |
599 | /* Cancel the blocked request if it is still pending */ | 601 | /* Cancel the blocked request if it is still pending */ |
600 | if (resp->status == NLM_LCK_BLOCKED) | 602 | if (resp->status == NLM_LCK_BLOCKED) |
601 | nlmclnt_cancel(host, fl); | 603 | nlmclnt_cancel(host, req->a_args.block, fl); |
602 | out: | 604 | out: |
603 | nlmclnt_release_lockargs(req); | 605 | nlmclnt_release_lockargs(req); |
604 | return status; | 606 | return status; |
@@ -728,8 +730,7 @@ static const struct rpc_call_ops nlmclnt_unlock_ops = { | |||
728 | * We always use an async RPC call for this in order not to hang a | 730 | * We always use an async RPC call for this in order not to hang a |
729 | * process that has been Ctrl-C'ed. | 731 | * process that has been Ctrl-C'ed. |
730 | */ | 732 | */ |
731 | int | 733 | static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl) |
732 | nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl) | ||
733 | { | 734 | { |
734 | struct nlm_rqst *req; | 735 | struct nlm_rqst *req; |
735 | unsigned long flags; | 736 | unsigned long flags; |
@@ -750,6 +751,7 @@ nlmclnt_cancel(struct nlm_host *host, struct file_lock *fl) | |||
750 | req->a_flags = RPC_TASK_ASYNC; | 751 | req->a_flags = RPC_TASK_ASYNC; |
751 | 752 | ||
752 | nlmclnt_setlockargs(req, fl); | 753 | nlmclnt_setlockargs(req, fl); |
754 | req->a_args.block = block; | ||
753 | 755 | ||
754 | status = nlmclnt_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops); | 756 | status = nlmclnt_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops); |
755 | if (status < 0) { | 757 | if (status < 0) { |
@@ -801,6 +803,9 @@ die: | |||
801 | return; | 803 | return; |
802 | 804 | ||
803 | retry_cancel: | 805 | retry_cancel: |
806 | /* Don't ever retry more than 3 times */ | ||
807 | if (req->a_retries++ >= NLMCLNT_MAX_RETRIES) | ||
808 | goto die; | ||
804 | nlm_rebind_host(req->a_host); | 809 | nlm_rebind_host(req->a_host); |
805 | rpc_restart_call(task); | 810 | rpc_restart_call(task); |
806 | rpc_delay(task, 30 * HZ); | 811 | rpc_delay(task, 30 * HZ); |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 10ae377e68ff..04ab2fc360e7 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -481,7 +481,7 @@ retry: | |||
481 | if (wdata->verf.committed != NFS_FILE_SYNC) { | 481 | if (wdata->verf.committed != NFS_FILE_SYNC) { |
482 | need_commit = 1; | 482 | need_commit = 1; |
483 | if (memcmp(&first_verf.verifier, &wdata->verf.verifier, | 483 | if (memcmp(&first_verf.verifier, &wdata->verf.verifier, |
484 | sizeof(first_verf.verifier))); | 484 | sizeof(first_verf.verifier))) |
485 | goto sync_retry; | 485 | goto sync_retry; |
486 | } | 486 | } |
487 | 487 | ||
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index 95c8fea293ba..920766cea79c 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h | |||
@@ -84,6 +84,7 @@ struct nlm_rqst { | |||
84 | struct nlm_args a_args; /* arguments */ | 84 | struct nlm_args a_args; /* arguments */ |
85 | struct nlm_res a_res; /* result */ | 85 | struct nlm_res a_res; /* result */ |
86 | struct nlm_wait * a_block; | 86 | struct nlm_wait * a_block; |
87 | unsigned int a_retries; /* Retry count */ | ||
87 | char a_owner[NLMCLNT_OHSIZE]; | 88 | char a_owner[NLMCLNT_OHSIZE]; |
88 | }; | 89 | }; |
89 | 90 | ||
@@ -148,7 +149,6 @@ struct nlm_rqst * nlmclnt_alloc_call(void); | |||
148 | int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl); | 149 | int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl); |
149 | void nlmclnt_finish_block(struct nlm_rqst *req); | 150 | void nlmclnt_finish_block(struct nlm_rqst *req); |
150 | long nlmclnt_block(struct nlm_rqst *req, long timeout); | 151 | long nlmclnt_block(struct nlm_rqst *req, long timeout); |
151 | int nlmclnt_cancel(struct nlm_host *, struct file_lock *); | ||
152 | u32 nlmclnt_grant(struct nlm_lock *); | 152 | u32 nlmclnt_grant(struct nlm_lock *); |
153 | void nlmclnt_recovery(struct nlm_host *, u32); | 153 | void nlmclnt_recovery(struct nlm_host *, u32); |
154 | int nlmclnt_reclaim(struct nlm_host *, struct file_lock *); | 154 | int nlmclnt_reclaim(struct nlm_host *, struct file_lock *); |
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index b68c11a2d6dd..be4772ed43c0 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h | |||
@@ -48,7 +48,7 @@ struct rpc_cred { | |||
48 | 48 | ||
49 | /* per-flavor data */ | 49 | /* per-flavor data */ |
50 | }; | 50 | }; |
51 | #define RPCAUTH_CRED_LOCKED 0x0001 | 51 | #define RPCAUTH_CRED_NEW 0x0001 |
52 | #define RPCAUTH_CRED_UPTODATE 0x0002 | 52 | #define RPCAUTH_CRED_UPTODATE 0x0002 |
53 | 53 | ||
54 | #define RPCAUTH_CRED_MAGIC 0x0f4aa4f0 | 54 | #define RPCAUTH_CRED_MAGIC 0x0f4aa4f0 |
@@ -83,9 +83,10 @@ struct rpc_auth { | |||
83 | struct rpc_cred_cache * au_credcache; | 83 | struct rpc_cred_cache * au_credcache; |
84 | /* per-flavor data */ | 84 | /* per-flavor data */ |
85 | }; | 85 | }; |
86 | #define RPC_AUTH_PROC_CREDS 0x0010 /* process creds (including | 86 | |
87 | * uid/gid, fs[ug]id, gids) | 87 | /* Flags for rpcauth_lookupcred() */ |
88 | */ | 88 | #define RPCAUTH_LOOKUP_NEW 0x01 /* Accept an uninitialised cred */ |
89 | #define RPCAUTH_LOOKUP_ROOTCREDS 0x02 /* This really ought to go! */ | ||
89 | 90 | ||
90 | /* | 91 | /* |
91 | * Client authentication ops | 92 | * Client authentication ops |
@@ -105,6 +106,7 @@ struct rpc_authops { | |||
105 | 106 | ||
106 | struct rpc_credops { | 107 | struct rpc_credops { |
107 | const char * cr_name; /* Name of the auth flavour */ | 108 | const char * cr_name; /* Name of the auth flavour */ |
109 | int (*cr_init)(struct rpc_auth *, struct rpc_cred *); | ||
108 | void (*crdestroy)(struct rpc_cred *); | 110 | void (*crdestroy)(struct rpc_cred *); |
109 | 111 | ||
110 | int (*crmatch)(struct auth_cred *, struct rpc_cred *, int); | 112 | int (*crmatch)(struct auth_cred *, struct rpc_cred *, int); |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 9ac1b8c26c01..8d6f1a176b15 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -184,7 +184,7 @@ rpcauth_gc_credcache(struct rpc_auth *auth, struct hlist_head *free) | |||
184 | */ | 184 | */ |
185 | struct rpc_cred * | 185 | struct rpc_cred * |
186 | rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, | 186 | rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, |
187 | int taskflags) | 187 | int flags) |
188 | { | 188 | { |
189 | struct rpc_cred_cache *cache = auth->au_credcache; | 189 | struct rpc_cred_cache *cache = auth->au_credcache; |
190 | HLIST_HEAD(free); | 190 | HLIST_HEAD(free); |
@@ -193,7 +193,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, | |||
193 | *cred = NULL; | 193 | *cred = NULL; |
194 | int nr = 0; | 194 | int nr = 0; |
195 | 195 | ||
196 | if (!(taskflags & RPC_TASK_ROOTCREDS)) | 196 | if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) |
197 | nr = acred->uid & RPC_CREDCACHE_MASK; | 197 | nr = acred->uid & RPC_CREDCACHE_MASK; |
198 | retry: | 198 | retry: |
199 | spin_lock(&rpc_credcache_lock); | 199 | spin_lock(&rpc_credcache_lock); |
@@ -202,7 +202,7 @@ retry: | |||
202 | hlist_for_each_safe(pos, next, &cache->hashtable[nr]) { | 202 | hlist_for_each_safe(pos, next, &cache->hashtable[nr]) { |
203 | struct rpc_cred *entry; | 203 | struct rpc_cred *entry; |
204 | entry = hlist_entry(pos, struct rpc_cred, cr_hash); | 204 | entry = hlist_entry(pos, struct rpc_cred, cr_hash); |
205 | if (entry->cr_ops->crmatch(acred, entry, taskflags)) { | 205 | if (entry->cr_ops->crmatch(acred, entry, flags)) { |
206 | hlist_del(&entry->cr_hash); | 206 | hlist_del(&entry->cr_hash); |
207 | cred = entry; | 207 | cred = entry; |
208 | break; | 208 | break; |
@@ -224,7 +224,7 @@ retry: | |||
224 | rpcauth_destroy_credlist(&free); | 224 | rpcauth_destroy_credlist(&free); |
225 | 225 | ||
226 | if (!cred) { | 226 | if (!cred) { |
227 | new = auth->au_ops->crcreate(auth, acred, taskflags); | 227 | new = auth->au_ops->crcreate(auth, acred, flags); |
228 | if (!IS_ERR(new)) { | 228 | if (!IS_ERR(new)) { |
229 | #ifdef RPC_DEBUG | 229 | #ifdef RPC_DEBUG |
230 | new->cr_magic = RPCAUTH_CRED_MAGIC; | 230 | new->cr_magic = RPCAUTH_CRED_MAGIC; |
@@ -232,13 +232,21 @@ retry: | |||
232 | goto retry; | 232 | goto retry; |
233 | } else | 233 | } else |
234 | cred = new; | 234 | cred = new; |
235 | } else if ((cred->cr_flags & RPCAUTH_CRED_NEW) | ||
236 | && cred->cr_ops->cr_init != NULL | ||
237 | && !(flags & RPCAUTH_LOOKUP_NEW)) { | ||
238 | int res = cred->cr_ops->cr_init(auth, cred); | ||
239 | if (res < 0) { | ||
240 | put_rpccred(cred); | ||
241 | cred = ERR_PTR(res); | ||
242 | } | ||
235 | } | 243 | } |
236 | 244 | ||
237 | return (struct rpc_cred *) cred; | 245 | return (struct rpc_cred *) cred; |
238 | } | 246 | } |
239 | 247 | ||
240 | struct rpc_cred * | 248 | struct rpc_cred * |
241 | rpcauth_lookupcred(struct rpc_auth *auth, int taskflags) | 249 | rpcauth_lookupcred(struct rpc_auth *auth, int flags) |
242 | { | 250 | { |
243 | struct auth_cred acred = { | 251 | struct auth_cred acred = { |
244 | .uid = current->fsuid, | 252 | .uid = current->fsuid, |
@@ -250,7 +258,7 @@ rpcauth_lookupcred(struct rpc_auth *auth, int taskflags) | |||
250 | dprintk("RPC: looking up %s cred\n", | 258 | dprintk("RPC: looking up %s cred\n", |
251 | auth->au_ops->au_name); | 259 | auth->au_ops->au_name); |
252 | get_group_info(acred.group_info); | 260 | get_group_info(acred.group_info); |
253 | ret = auth->au_ops->lookup_cred(auth, &acred, taskflags); | 261 | ret = auth->au_ops->lookup_cred(auth, &acred, flags); |
254 | put_group_info(acred.group_info); | 262 | put_group_info(acred.group_info); |
255 | return ret; | 263 | return ret; |
256 | } | 264 | } |
@@ -265,11 +273,14 @@ rpcauth_bindcred(struct rpc_task *task) | |||
265 | .group_info = current->group_info, | 273 | .group_info = current->group_info, |
266 | }; | 274 | }; |
267 | struct rpc_cred *ret; | 275 | struct rpc_cred *ret; |
276 | int flags = 0; | ||
268 | 277 | ||
269 | dprintk("RPC: %4d looking up %s cred\n", | 278 | dprintk("RPC: %4d looking up %s cred\n", |
270 | task->tk_pid, task->tk_auth->au_ops->au_name); | 279 | task->tk_pid, task->tk_auth->au_ops->au_name); |
271 | get_group_info(acred.group_info); | 280 | get_group_info(acred.group_info); |
272 | ret = auth->au_ops->lookup_cred(auth, &acred, task->tk_flags); | 281 | if (task->tk_flags & RPC_TASK_ROOTCREDS) |
282 | flags |= RPCAUTH_LOOKUP_ROOTCREDS; | ||
283 | ret = auth->au_ops->lookup_cred(auth, &acred, flags); | ||
273 | if (!IS_ERR(ret)) | 284 | if (!IS_ERR(ret)) |
274 | task->tk_msg.rpc_cred = ret; | 285 | task->tk_msg.rpc_cred = ret; |
275 | else | 286 | else |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 8d782282ec19..bb46efd92e57 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -158,6 +158,7 @@ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx) | |||
158 | old = gss_cred->gc_ctx; | 158 | old = gss_cred->gc_ctx; |
159 | gss_cred->gc_ctx = ctx; | 159 | gss_cred->gc_ctx = ctx; |
160 | cred->cr_flags |= RPCAUTH_CRED_UPTODATE; | 160 | cred->cr_flags |= RPCAUTH_CRED_UPTODATE; |
161 | cred->cr_flags &= ~RPCAUTH_CRED_NEW; | ||
161 | write_unlock(&gss_ctx_lock); | 162 | write_unlock(&gss_ctx_lock); |
162 | if (old) | 163 | if (old) |
163 | gss_put_ctx(old); | 164 | gss_put_ctx(old); |
@@ -580,7 +581,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) | |||
580 | } else { | 581 | } else { |
581 | struct auth_cred acred = { .uid = uid }; | 582 | struct auth_cred acred = { .uid = uid }; |
582 | spin_unlock(&gss_auth->lock); | 583 | spin_unlock(&gss_auth->lock); |
583 | cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, 0); | 584 | cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, RPCAUTH_LOOKUP_NEW); |
584 | if (IS_ERR(cred)) { | 585 | if (IS_ERR(cred)) { |
585 | err = PTR_ERR(cred); | 586 | err = PTR_ERR(cred); |
586 | goto err_put_ctx; | 587 | goto err_put_ctx; |
@@ -758,13 +759,13 @@ gss_destroy_cred(struct rpc_cred *rc) | |||
758 | * Lookup RPCSEC_GSS cred for the current process | 759 | * Lookup RPCSEC_GSS cred for the current process |
759 | */ | 760 | */ |
760 | static struct rpc_cred * | 761 | static struct rpc_cred * |
761 | gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags) | 762 | gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) |
762 | { | 763 | { |
763 | return rpcauth_lookup_credcache(auth, acred, taskflags); | 764 | return rpcauth_lookup_credcache(auth, acred, flags); |
764 | } | 765 | } |
765 | 766 | ||
766 | static struct rpc_cred * | 767 | static struct rpc_cred * |
767 | gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags) | 768 | gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) |
768 | { | 769 | { |
769 | struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth); | 770 | struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth); |
770 | struct gss_cred *cred = NULL; | 771 | struct gss_cred *cred = NULL; |
@@ -785,13 +786,8 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags) | |||
785 | */ | 786 | */ |
786 | cred->gc_flags = 0; | 787 | cred->gc_flags = 0; |
787 | cred->gc_base.cr_ops = &gss_credops; | 788 | cred->gc_base.cr_ops = &gss_credops; |
789 | cred->gc_base.cr_flags = RPCAUTH_CRED_NEW; | ||
788 | cred->gc_service = gss_auth->service; | 790 | cred->gc_service = gss_auth->service; |
789 | do { | ||
790 | err = gss_create_upcall(gss_auth, cred); | ||
791 | } while (err == -EAGAIN); | ||
792 | if (err < 0) | ||
793 | goto out_err; | ||
794 | |||
795 | return &cred->gc_base; | 791 | return &cred->gc_base; |
796 | 792 | ||
797 | out_err: | 793 | out_err: |
@@ -801,13 +797,34 @@ out_err: | |||
801 | } | 797 | } |
802 | 798 | ||
803 | static int | 799 | static int |
804 | gss_match(struct auth_cred *acred, struct rpc_cred *rc, int taskflags) | 800 | gss_cred_init(struct rpc_auth *auth, struct rpc_cred *cred) |
801 | { | ||
802 | struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth); | ||
803 | struct gss_cred *gss_cred = container_of(cred,struct gss_cred, gc_base); | ||
804 | int err; | ||
805 | |||
806 | do { | ||
807 | err = gss_create_upcall(gss_auth, gss_cred); | ||
808 | } while (err == -EAGAIN); | ||
809 | return err; | ||
810 | } | ||
811 | |||
812 | static int | ||
813 | gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) | ||
805 | { | 814 | { |
806 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); | 815 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); |
807 | 816 | ||
817 | /* | ||
818 | * If the searchflags have set RPCAUTH_LOOKUP_NEW, then | ||
819 | * we don't really care if the credential has expired or not, | ||
820 | * since the caller should be prepared to reinitialise it. | ||
821 | */ | ||
822 | if ((flags & RPCAUTH_LOOKUP_NEW) && (rc->cr_flags & RPCAUTH_CRED_NEW)) | ||
823 | goto out; | ||
808 | /* Don't match with creds that have expired. */ | 824 | /* Don't match with creds that have expired. */ |
809 | if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry)) | 825 | if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry)) |
810 | return 0; | 826 | return 0; |
827 | out: | ||
811 | return (rc->cr_uid == acred->uid); | 828 | return (rc->cr_uid == acred->uid); |
812 | } | 829 | } |
813 | 830 | ||
@@ -1241,6 +1258,7 @@ static struct rpc_authops authgss_ops = { | |||
1241 | static struct rpc_credops gss_credops = { | 1258 | static struct rpc_credops gss_credops = { |
1242 | .cr_name = "AUTH_GSS", | 1259 | .cr_name = "AUTH_GSS", |
1243 | .crdestroy = gss_destroy_cred, | 1260 | .crdestroy = gss_destroy_cred, |
1261 | .cr_init = gss_cred_init, | ||
1244 | .crmatch = gss_match, | 1262 | .crmatch = gss_match, |
1245 | .crmarshal = gss_marshal, | 1263 | .crmarshal = gss_marshal, |
1246 | .crrefresh = gss_refresh, | 1264 | .crrefresh = gss_refresh, |
diff --git a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c index 1b3ed4fd1987..df14b6bfbf10 100644 --- a/net/sunrpc/auth_unix.c +++ b/net/sunrpc/auth_unix.c | |||
@@ -75,7 +75,7 @@ unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | |||
75 | 75 | ||
76 | atomic_set(&cred->uc_count, 1); | 76 | atomic_set(&cred->uc_count, 1); |
77 | cred->uc_flags = RPCAUTH_CRED_UPTODATE; | 77 | cred->uc_flags = RPCAUTH_CRED_UPTODATE; |
78 | if (flags & RPC_TASK_ROOTCREDS) { | 78 | if (flags & RPCAUTH_LOOKUP_ROOTCREDS) { |
79 | cred->uc_uid = 0; | 79 | cred->uc_uid = 0; |
80 | cred->uc_gid = 0; | 80 | cred->uc_gid = 0; |
81 | cred->uc_gids[0] = NOGROUP; | 81 | cred->uc_gids[0] = NOGROUP; |
@@ -108,12 +108,12 @@ unx_destroy_cred(struct rpc_cred *cred) | |||
108 | * request root creds (e.g. for NFS swapping). | 108 | * request root creds (e.g. for NFS swapping). |
109 | */ | 109 | */ |
110 | static int | 110 | static int |
111 | unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int taskflags) | 111 | unx_match(struct auth_cred *acred, struct rpc_cred *rcred, int flags) |
112 | { | 112 | { |
113 | struct unx_cred *cred = (struct unx_cred *) rcred; | 113 | struct unx_cred *cred = (struct unx_cred *) rcred; |
114 | int i; | 114 | int i; |
115 | 115 | ||
116 | if (!(taskflags & RPC_TASK_ROOTCREDS)) { | 116 | if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) { |
117 | int groups; | 117 | int groups; |
118 | 118 | ||
119 | if (cred->uc_uid != acred->uid | 119 | if (cred->uc_uid != acred->uid |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 9764c80ab0b2..a5c0c7b6e151 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -38,44 +38,42 @@ static kmem_cache_t *rpc_inode_cachep __read_mostly; | |||
38 | 38 | ||
39 | #define RPC_UPCALL_TIMEOUT (30*HZ) | 39 | #define RPC_UPCALL_TIMEOUT (30*HZ) |
40 | 40 | ||
41 | static void | 41 | static void rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, |
42 | __rpc_purge_list(struct rpc_inode *rpci, struct list_head *head, int err) | 42 | void (*destroy_msg)(struct rpc_pipe_msg *), int err) |
43 | { | 43 | { |
44 | struct rpc_pipe_msg *msg; | 44 | struct rpc_pipe_msg *msg; |
45 | void (*destroy_msg)(struct rpc_pipe_msg *); | ||
46 | 45 | ||
47 | destroy_msg = rpci->ops->destroy_msg; | 46 | if (list_empty(head)) |
48 | while (!list_empty(head)) { | 47 | return; |
48 | do { | ||
49 | msg = list_entry(head->next, struct rpc_pipe_msg, list); | 49 | msg = list_entry(head->next, struct rpc_pipe_msg, list); |
50 | list_del_init(&msg->list); | 50 | list_del(&msg->list); |
51 | msg->errno = err; | 51 | msg->errno = err; |
52 | destroy_msg(msg); | 52 | destroy_msg(msg); |
53 | } | 53 | } while (!list_empty(head)); |
54 | } | ||
55 | |||
56 | static void | ||
57 | __rpc_purge_upcall(struct inode *inode, int err) | ||
58 | { | ||
59 | struct rpc_inode *rpci = RPC_I(inode); | ||
60 | |||
61 | __rpc_purge_list(rpci, &rpci->pipe, err); | ||
62 | rpci->pipelen = 0; | ||
63 | wake_up(&rpci->waitq); | 54 | wake_up(&rpci->waitq); |
64 | } | 55 | } |
65 | 56 | ||
66 | static void | 57 | static void |
67 | rpc_timeout_upcall_queue(void *data) | 58 | rpc_timeout_upcall_queue(void *data) |
68 | { | 59 | { |
60 | LIST_HEAD(free_list); | ||
69 | struct rpc_inode *rpci = (struct rpc_inode *)data; | 61 | struct rpc_inode *rpci = (struct rpc_inode *)data; |
70 | struct inode *inode = &rpci->vfs_inode; | 62 | struct inode *inode = &rpci->vfs_inode; |
63 | void (*destroy_msg)(struct rpc_pipe_msg *); | ||
71 | 64 | ||
72 | mutex_lock(&inode->i_mutex); | 65 | spin_lock(&inode->i_lock); |
73 | if (rpci->ops == NULL) | 66 | if (rpci->ops == NULL) { |
74 | goto out; | 67 | spin_unlock(&inode->i_lock); |
75 | if (rpci->nreaders == 0 && !list_empty(&rpci->pipe)) | 68 | return; |
76 | __rpc_purge_upcall(inode, -ETIMEDOUT); | 69 | } |
77 | out: | 70 | destroy_msg = rpci->ops->destroy_msg; |
78 | mutex_unlock(&inode->i_mutex); | 71 | if (rpci->nreaders == 0) { |
72 | list_splice_init(&rpci->pipe, &free_list); | ||
73 | rpci->pipelen = 0; | ||
74 | } | ||
75 | spin_unlock(&inode->i_lock); | ||
76 | rpc_purge_list(rpci, &free_list, destroy_msg, -ETIMEDOUT); | ||
79 | } | 77 | } |
80 | 78 | ||
81 | int | 79 | int |
@@ -84,7 +82,7 @@ rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) | |||
84 | struct rpc_inode *rpci = RPC_I(inode); | 82 | struct rpc_inode *rpci = RPC_I(inode); |
85 | int res = -EPIPE; | 83 | int res = -EPIPE; |
86 | 84 | ||
87 | mutex_lock(&inode->i_mutex); | 85 | spin_lock(&inode->i_lock); |
88 | if (rpci->ops == NULL) | 86 | if (rpci->ops == NULL) |
89 | goto out; | 87 | goto out; |
90 | if (rpci->nreaders) { | 88 | if (rpci->nreaders) { |
@@ -100,7 +98,7 @@ rpc_queue_upcall(struct inode *inode, struct rpc_pipe_msg *msg) | |||
100 | res = 0; | 98 | res = 0; |
101 | } | 99 | } |
102 | out: | 100 | out: |
103 | mutex_unlock(&inode->i_mutex); | 101 | spin_unlock(&inode->i_lock); |
104 | wake_up(&rpci->waitq); | 102 | wake_up(&rpci->waitq); |
105 | return res; | 103 | return res; |
106 | } | 104 | } |
@@ -115,21 +113,29 @@ static void | |||
115 | rpc_close_pipes(struct inode *inode) | 113 | rpc_close_pipes(struct inode *inode) |
116 | { | 114 | { |
117 | struct rpc_inode *rpci = RPC_I(inode); | 115 | struct rpc_inode *rpci = RPC_I(inode); |
116 | struct rpc_pipe_ops *ops; | ||
118 | 117 | ||
119 | mutex_lock(&inode->i_mutex); | 118 | mutex_lock(&inode->i_mutex); |
120 | if (rpci->ops != NULL) { | 119 | ops = rpci->ops; |
120 | if (ops != NULL) { | ||
121 | LIST_HEAD(free_list); | ||
122 | |||
123 | spin_lock(&inode->i_lock); | ||
121 | rpci->nreaders = 0; | 124 | rpci->nreaders = 0; |
122 | __rpc_purge_list(rpci, &rpci->in_upcall, -EPIPE); | 125 | list_splice_init(&rpci->in_upcall, &free_list); |
123 | __rpc_purge_upcall(inode, -EPIPE); | 126 | list_splice_init(&rpci->pipe, &free_list); |
124 | rpci->nwriters = 0; | 127 | rpci->pipelen = 0; |
125 | if (rpci->ops->release_pipe) | ||
126 | rpci->ops->release_pipe(inode); | ||
127 | rpci->ops = NULL; | 128 | rpci->ops = NULL; |
129 | spin_unlock(&inode->i_lock); | ||
130 | rpc_purge_list(rpci, &free_list, ops->destroy_msg, -EPIPE); | ||
131 | rpci->nwriters = 0; | ||
132 | if (ops->release_pipe) | ||
133 | ops->release_pipe(inode); | ||
134 | cancel_delayed_work(&rpci->queue_timeout); | ||
135 | flush_scheduled_work(); | ||
128 | } | 136 | } |
129 | rpc_inode_setowner(inode, NULL); | 137 | rpc_inode_setowner(inode, NULL); |
130 | mutex_unlock(&inode->i_mutex); | 138 | mutex_unlock(&inode->i_mutex); |
131 | cancel_delayed_work(&rpci->queue_timeout); | ||
132 | flush_scheduled_work(); | ||
133 | } | 139 | } |
134 | 140 | ||
135 | static struct inode * | 141 | static struct inode * |
@@ -177,16 +183,26 @@ rpc_pipe_release(struct inode *inode, struct file *filp) | |||
177 | goto out; | 183 | goto out; |
178 | msg = (struct rpc_pipe_msg *)filp->private_data; | 184 | msg = (struct rpc_pipe_msg *)filp->private_data; |
179 | if (msg != NULL) { | 185 | if (msg != NULL) { |
186 | spin_lock(&inode->i_lock); | ||
180 | msg->errno = -EAGAIN; | 187 | msg->errno = -EAGAIN; |
181 | list_del_init(&msg->list); | 188 | list_del(&msg->list); |
189 | spin_unlock(&inode->i_lock); | ||
182 | rpci->ops->destroy_msg(msg); | 190 | rpci->ops->destroy_msg(msg); |
183 | } | 191 | } |
184 | if (filp->f_mode & FMODE_WRITE) | 192 | if (filp->f_mode & FMODE_WRITE) |
185 | rpci->nwriters --; | 193 | rpci->nwriters --; |
186 | if (filp->f_mode & FMODE_READ) | 194 | if (filp->f_mode & FMODE_READ) { |
187 | rpci->nreaders --; | 195 | rpci->nreaders --; |
188 | if (!rpci->nreaders) | 196 | if (rpci->nreaders == 0) { |
189 | __rpc_purge_upcall(inode, -EAGAIN); | 197 | LIST_HEAD(free_list); |
198 | spin_lock(&inode->i_lock); | ||
199 | list_splice_init(&rpci->pipe, &free_list); | ||
200 | rpci->pipelen = 0; | ||
201 | spin_unlock(&inode->i_lock); | ||
202 | rpc_purge_list(rpci, &free_list, | ||
203 | rpci->ops->destroy_msg, -EAGAIN); | ||
204 | } | ||
205 | } | ||
190 | if (rpci->ops->release_pipe) | 206 | if (rpci->ops->release_pipe) |
191 | rpci->ops->release_pipe(inode); | 207 | rpci->ops->release_pipe(inode); |
192 | out: | 208 | out: |
@@ -209,6 +225,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) | |||
209 | } | 225 | } |
210 | msg = filp->private_data; | 226 | msg = filp->private_data; |
211 | if (msg == NULL) { | 227 | if (msg == NULL) { |
228 | spin_lock(&inode->i_lock); | ||
212 | if (!list_empty(&rpci->pipe)) { | 229 | if (!list_empty(&rpci->pipe)) { |
213 | msg = list_entry(rpci->pipe.next, | 230 | msg = list_entry(rpci->pipe.next, |
214 | struct rpc_pipe_msg, | 231 | struct rpc_pipe_msg, |
@@ -218,6 +235,7 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) | |||
218 | filp->private_data = msg; | 235 | filp->private_data = msg; |
219 | msg->copied = 0; | 236 | msg->copied = 0; |
220 | } | 237 | } |
238 | spin_unlock(&inode->i_lock); | ||
221 | if (msg == NULL) | 239 | if (msg == NULL) |
222 | goto out_unlock; | 240 | goto out_unlock; |
223 | } | 241 | } |
@@ -225,7 +243,9 @@ rpc_pipe_read(struct file *filp, char __user *buf, size_t len, loff_t *offset) | |||
225 | res = rpci->ops->upcall(filp, msg, buf, len); | 243 | res = rpci->ops->upcall(filp, msg, buf, len); |
226 | if (res < 0 || msg->len == msg->copied) { | 244 | if (res < 0 || msg->len == msg->copied) { |
227 | filp->private_data = NULL; | 245 | filp->private_data = NULL; |
228 | list_del_init(&msg->list); | 246 | spin_lock(&inode->i_lock); |
247 | list_del(&msg->list); | ||
248 | spin_unlock(&inode->i_lock); | ||
229 | rpci->ops->destroy_msg(msg); | 249 | rpci->ops->destroy_msg(msg); |
230 | } | 250 | } |
231 | out_unlock: | 251 | out_unlock: |
@@ -610,7 +630,7 @@ rpc_lookup_negative(char *path, struct nameidata *nd) | |||
610 | return ERR_PTR(error); | 630 | return ERR_PTR(error); |
611 | dir = nd->dentry->d_inode; | 631 | dir = nd->dentry->d_inode; |
612 | mutex_lock(&dir->i_mutex); | 632 | mutex_lock(&dir->i_mutex); |
613 | dentry = lookup_hash(nd); | 633 | dentry = lookup_one_len(nd->last.name, nd->dentry, nd->last.len); |
614 | if (IS_ERR(dentry)) | 634 | if (IS_ERR(dentry)) |
615 | goto out_err; | 635 | goto out_err; |
616 | if (dentry->d_inode) { | 636 | if (dentry->d_inode) { |
@@ -672,7 +692,7 @@ rpc_rmdir(char *path) | |||
672 | return error; | 692 | return error; |
673 | dir = nd.dentry->d_inode; | 693 | dir = nd.dentry->d_inode; |
674 | mutex_lock(&dir->i_mutex); | 694 | mutex_lock(&dir->i_mutex); |
675 | dentry = lookup_hash(&nd); | 695 | dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len); |
676 | if (IS_ERR(dentry)) { | 696 | if (IS_ERR(dentry)) { |
677 | error = PTR_ERR(dentry); | 697 | error = PTR_ERR(dentry); |
678 | goto out_release; | 698 | goto out_release; |
@@ -733,7 +753,7 @@ rpc_unlink(char *path) | |||
733 | return error; | 753 | return error; |
734 | dir = nd.dentry->d_inode; | 754 | dir = nd.dentry->d_inode; |
735 | mutex_lock(&dir->i_mutex); | 755 | mutex_lock(&dir->i_mutex); |
736 | dentry = lookup_hash(&nd); | 756 | dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len); |
737 | if (IS_ERR(dentry)) { | 757 | if (IS_ERR(dentry)) { |
738 | error = PTR_ERR(dentry); | 758 | error = PTR_ERR(dentry); |
739 | goto out_release; | 759 | goto out_release; |