Commit e092bdcd939416ef911090890096fe07d0281a5e

Authored by Trond Myklebust
1 parent fc432dd907

SUNRPC: cleanup rpc credential cache garbage collection

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

Showing 3 changed files with 74 additions and 49 deletions Inline Diff

include/linux/sunrpc/auth.h
1 /* 1 /*
2 * linux/include/linux/sunrpc/auth.h 2 * linux/include/linux/sunrpc/auth.h
3 * 3 *
4 * Declarations for the RPC client authentication machinery. 4 * Declarations for the RPC client authentication machinery.
5 * 5 *
6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> 6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
7 */ 7 */
8 8
9 #ifndef _LINUX_SUNRPC_AUTH_H 9 #ifndef _LINUX_SUNRPC_AUTH_H
10 #define _LINUX_SUNRPC_AUTH_H 10 #define _LINUX_SUNRPC_AUTH_H
11 11
12 #ifdef __KERNEL__ 12 #ifdef __KERNEL__
13 13
14 #include <linux/sunrpc/sched.h> 14 #include <linux/sunrpc/sched.h>
15 #include <linux/sunrpc/msg_prot.h> 15 #include <linux/sunrpc/msg_prot.h>
16 #include <linux/sunrpc/xdr.h> 16 #include <linux/sunrpc/xdr.h>
17 17
18 #include <asm/atomic.h> 18 #include <asm/atomic.h>
19 19
20 /* size of the nodename buffer */ 20 /* size of the nodename buffer */
21 #define UNX_MAXNODENAME 32 21 #define UNX_MAXNODENAME 32
22 22
23 /* Work around the lack of a VFS credential */ 23 /* Work around the lack of a VFS credential */
24 struct auth_cred { 24 struct auth_cred {
25 uid_t uid; 25 uid_t uid;
26 gid_t gid; 26 gid_t gid;
27 struct group_info *group_info; 27 struct group_info *group_info;
28 }; 28 };
29 29
30 /* 30 /*
31 * Client user credentials 31 * Client user credentials
32 */ 32 */
33 struct rpc_auth; 33 struct rpc_auth;
34 struct rpc_credops; 34 struct rpc_credops;
35 struct rpc_cred { 35 struct rpc_cred {
36 struct hlist_node cr_hash; /* hash chain */ 36 struct hlist_node cr_hash; /* hash chain */
37 struct list_head cr_lru; /* lru garbage collection */
37 struct rpc_auth * cr_auth; 38 struct rpc_auth * cr_auth;
38 const struct rpc_credops *cr_ops; 39 const struct rpc_credops *cr_ops;
39 #ifdef RPC_DEBUG 40 #ifdef RPC_DEBUG
40 unsigned long cr_magic; /* 0x0f4aa4f0 */ 41 unsigned long cr_magic; /* 0x0f4aa4f0 */
41 #endif 42 #endif
42 unsigned long cr_expire; /* when to gc */ 43 unsigned long cr_expire; /* when to gc */
43 unsigned long cr_flags; /* various flags */ 44 unsigned long cr_flags; /* various flags */
44 atomic_t cr_count; /* ref count */ 45 atomic_t cr_count; /* ref count */
45 46
46 uid_t cr_uid; 47 uid_t cr_uid;
47 48
48 /* per-flavor data */ 49 /* per-flavor data */
49 }; 50 };
50 #define RPCAUTH_CRED_NEW 0 51 #define RPCAUTH_CRED_NEW 0
51 #define RPCAUTH_CRED_UPTODATE 1 52 #define RPCAUTH_CRED_UPTODATE 1
52 53
53 #define RPCAUTH_CRED_MAGIC 0x0f4aa4f0 54 #define RPCAUTH_CRED_MAGIC 0x0f4aa4f0
54 55
55 /* 56 /*
56 * Client authentication handle 57 * Client authentication handle
57 */ 58 */
58 #define RPC_CREDCACHE_NR 8 59 #define RPC_CREDCACHE_NR 8
59 #define RPC_CREDCACHE_MASK (RPC_CREDCACHE_NR - 1) 60 #define RPC_CREDCACHE_MASK (RPC_CREDCACHE_NR - 1)
60 struct rpc_cred_cache { 61 struct rpc_cred_cache {
61 struct hlist_head hashtable[RPC_CREDCACHE_NR]; 62 struct hlist_head hashtable[RPC_CREDCACHE_NR];
62 unsigned long nextgc; /* next garbage collection */ 63 unsigned long nextgc; /* next garbage collection */
63 unsigned long expire; /* cache expiry interval */ 64 unsigned long expire; /* cache expiry interval */
64 }; 65 };
65 66
66 struct rpc_authops; 67 struct rpc_authops;
67 struct rpc_auth { 68 struct rpc_auth {
68 unsigned int au_cslack; /* call cred size estimate */ 69 unsigned int au_cslack; /* call cred size estimate */
69 /* guess at number of u32's auth adds before 70 /* guess at number of u32's auth adds before
70 * reply data; normally the verifier size: */ 71 * reply data; normally the verifier size: */
71 unsigned int au_rslack; 72 unsigned int au_rslack;
72 /* for gss, used to calculate au_rslack: */ 73 /* for gss, used to calculate au_rslack: */
73 unsigned int au_verfsize; 74 unsigned int au_verfsize;
74 75
75 unsigned int au_flags; /* various flags */ 76 unsigned int au_flags; /* various flags */
76 const struct rpc_authops *au_ops; /* operations */ 77 const struct rpc_authops *au_ops; /* operations */
77 rpc_authflavor_t au_flavor; /* pseudoflavor (note may 78 rpc_authflavor_t au_flavor; /* pseudoflavor (note may
78 * differ from the flavor in 79 * differ from the flavor in
79 * au_ops->au_flavor in gss 80 * au_ops->au_flavor in gss
80 * case) */ 81 * case) */
81 atomic_t au_count; /* Reference counter */ 82 atomic_t au_count; /* Reference counter */
82 83
83 struct rpc_cred_cache * au_credcache; 84 struct rpc_cred_cache * au_credcache;
84 /* per-flavor data */ 85 /* per-flavor data */
85 }; 86 };
86 87
87 /* Flags for rpcauth_lookupcred() */ 88 /* Flags for rpcauth_lookupcred() */
88 #define RPCAUTH_LOOKUP_NEW 0x01 /* Accept an uninitialised cred */ 89 #define RPCAUTH_LOOKUP_NEW 0x01 /* Accept an uninitialised cred */
89 #define RPCAUTH_LOOKUP_ROOTCREDS 0x02 /* This really ought to go! */ 90 #define RPCAUTH_LOOKUP_ROOTCREDS 0x02 /* This really ought to go! */
90 91
91 /* 92 /*
92 * Client authentication ops 93 * Client authentication ops
93 */ 94 */
94 struct rpc_authops { 95 struct rpc_authops {
95 struct module *owner; 96 struct module *owner;
96 rpc_authflavor_t au_flavor; /* flavor (RPC_AUTH_*) */ 97 rpc_authflavor_t au_flavor; /* flavor (RPC_AUTH_*) */
97 #ifdef RPC_DEBUG 98 #ifdef RPC_DEBUG
98 char * au_name; 99 char * au_name;
99 #endif 100 #endif
100 struct rpc_auth * (*create)(struct rpc_clnt *, rpc_authflavor_t); 101 struct rpc_auth * (*create)(struct rpc_clnt *, rpc_authflavor_t);
101 void (*destroy)(struct rpc_auth *); 102 void (*destroy)(struct rpc_auth *);
102 103
103 struct rpc_cred * (*lookup_cred)(struct rpc_auth *, struct auth_cred *, int); 104 struct rpc_cred * (*lookup_cred)(struct rpc_auth *, struct auth_cred *, int);
104 struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int); 105 struct rpc_cred * (*crcreate)(struct rpc_auth*, struct auth_cred *, int);
105 }; 106 };
106 107
107 struct rpc_credops { 108 struct rpc_credops {
108 const char * cr_name; /* Name of the auth flavour */ 109 const char * cr_name; /* Name of the auth flavour */
109 int (*cr_init)(struct rpc_auth *, struct rpc_cred *); 110 int (*cr_init)(struct rpc_auth *, struct rpc_cred *);
110 void (*crdestroy)(struct rpc_cred *); 111 void (*crdestroy)(struct rpc_cred *);
111 112
112 int (*crmatch)(struct auth_cred *, struct rpc_cred *, int); 113 int (*crmatch)(struct auth_cred *, struct rpc_cred *, int);
113 __be32 * (*crmarshal)(struct rpc_task *, __be32 *); 114 __be32 * (*crmarshal)(struct rpc_task *, __be32 *);
114 int (*crrefresh)(struct rpc_task *); 115 int (*crrefresh)(struct rpc_task *);
115 __be32 * (*crvalidate)(struct rpc_task *, __be32 *); 116 __be32 * (*crvalidate)(struct rpc_task *, __be32 *);
116 int (*crwrap_req)(struct rpc_task *, kxdrproc_t, 117 int (*crwrap_req)(struct rpc_task *, kxdrproc_t,
117 void *, __be32 *, void *); 118 void *, __be32 *, void *);
118 int (*crunwrap_resp)(struct rpc_task *, kxdrproc_t, 119 int (*crunwrap_resp)(struct rpc_task *, kxdrproc_t,
119 void *, __be32 *, void *); 120 void *, __be32 *, void *);
120 }; 121 };
121 122
122 extern const struct rpc_authops authunix_ops; 123 extern const struct rpc_authops authunix_ops;
123 extern const struct rpc_authops authnull_ops; 124 extern const struct rpc_authops authnull_ops;
124 125
125 int rpcauth_register(const struct rpc_authops *); 126 int rpcauth_register(const struct rpc_authops *);
126 int rpcauth_unregister(const struct rpc_authops *); 127 int rpcauth_unregister(const struct rpc_authops *);
127 struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *); 128 struct rpc_auth * rpcauth_create(rpc_authflavor_t, struct rpc_clnt *);
128 void rpcauth_release(struct rpc_auth *); 129 void rpcauth_release(struct rpc_auth *);
129 struct rpc_cred * rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int); 130 struct rpc_cred * rpcauth_lookup_credcache(struct rpc_auth *, struct auth_cred *, int);
130 void rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *); 131 void rpcauth_init_cred(struct rpc_cred *, const struct auth_cred *, struct rpc_auth *, const struct rpc_credops *);
131 struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int); 132 struct rpc_cred * rpcauth_lookupcred(struct rpc_auth *, int);
132 struct rpc_cred * rpcauth_bindcred(struct rpc_task *); 133 struct rpc_cred * rpcauth_bindcred(struct rpc_task *);
133 void rpcauth_holdcred(struct rpc_task *); 134 void rpcauth_holdcred(struct rpc_task *);
134 void put_rpccred(struct rpc_cred *); 135 void put_rpccred(struct rpc_cred *);
135 void rpcauth_unbindcred(struct rpc_task *); 136 void rpcauth_unbindcred(struct rpc_task *);
136 __be32 * rpcauth_marshcred(struct rpc_task *, __be32 *); 137 __be32 * rpcauth_marshcred(struct rpc_task *, __be32 *);
137 __be32 * rpcauth_checkverf(struct rpc_task *, __be32 *); 138 __be32 * rpcauth_checkverf(struct rpc_task *, __be32 *);
138 int rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp, __be32 *data, void *obj); 139 int rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp, __be32 *data, void *obj);
139 int rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, __be32 *data, void *obj); 140 int rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, __be32 *data, void *obj);
140 int rpcauth_refreshcred(struct rpc_task *); 141 int rpcauth_refreshcred(struct rpc_task *);
141 void rpcauth_invalcred(struct rpc_task *); 142 void rpcauth_invalcred(struct rpc_task *);
142 int rpcauth_uptodatecred(struct rpc_task *); 143 int rpcauth_uptodatecred(struct rpc_task *);
143 int rpcauth_init_credcache(struct rpc_auth *, unsigned long); 144 int rpcauth_init_credcache(struct rpc_auth *, unsigned long);
144 void rpcauth_destroy_credcache(struct rpc_auth *); 145 void rpcauth_destroy_credcache(struct rpc_auth *);
145 void rpcauth_clear_credcache(struct rpc_cred_cache *); 146 void rpcauth_clear_credcache(struct rpc_cred_cache *);
146 147
147 static inline 148 static inline
148 struct rpc_cred * get_rpccred(struct rpc_cred *cred) 149 struct rpc_cred * get_rpccred(struct rpc_cred *cred)
149 { 150 {
150 atomic_inc(&cred->cr_count); 151 atomic_inc(&cred->cr_count);
151 return cred; 152 return cred;
152 } 153 }
153 154
154 #endif /* __KERNEL__ */ 155 #endif /* __KERNEL__ */
155 #endif /* _LINUX_SUNRPC_AUTH_H */ 156 #endif /* _LINUX_SUNRPC_AUTH_H */
156 157
1 /* 1 /*
2 * linux/net/sunrpc/auth.c 2 * linux/net/sunrpc/auth.c
3 * 3 *
4 * Generic RPC client authentication API. 4 * Generic RPC client authentication API.
5 * 5 *
6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> 6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
7 */ 7 */
8 8
9 #include <linux/types.h> 9 #include <linux/types.h>
10 #include <linux/sched.h> 10 #include <linux/sched.h>
11 #include <linux/module.h> 11 #include <linux/module.h>
12 #include <linux/slab.h> 12 #include <linux/slab.h>
13 #include <linux/errno.h> 13 #include <linux/errno.h>
14 #include <linux/sunrpc/clnt.h> 14 #include <linux/sunrpc/clnt.h>
15 #include <linux/spinlock.h> 15 #include <linux/spinlock.h>
16 16
17 #ifdef RPC_DEBUG 17 #ifdef RPC_DEBUG
18 # define RPCDBG_FACILITY RPCDBG_AUTH 18 # define RPCDBG_FACILITY RPCDBG_AUTH
19 #endif 19 #endif
20 20
21 static DEFINE_SPINLOCK(rpc_authflavor_lock); 21 static DEFINE_SPINLOCK(rpc_authflavor_lock);
22 static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { 22 static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = {
23 &authnull_ops, /* AUTH_NULL */ 23 &authnull_ops, /* AUTH_NULL */
24 &authunix_ops, /* AUTH_UNIX */ 24 &authunix_ops, /* AUTH_UNIX */
25 NULL, /* others can be loadable modules */ 25 NULL, /* others can be loadable modules */
26 }; 26 };
27 27
28 static LIST_HEAD(cred_unused);
29
28 static u32 30 static u32
29 pseudoflavor_to_flavor(u32 flavor) { 31 pseudoflavor_to_flavor(u32 flavor) {
30 if (flavor >= RPC_AUTH_MAXFLAVOR) 32 if (flavor >= RPC_AUTH_MAXFLAVOR)
31 return RPC_AUTH_GSS; 33 return RPC_AUTH_GSS;
32 return flavor; 34 return flavor;
33 } 35 }
34 36
35 int 37 int
36 rpcauth_register(const struct rpc_authops *ops) 38 rpcauth_register(const struct rpc_authops *ops)
37 { 39 {
38 rpc_authflavor_t flavor; 40 rpc_authflavor_t flavor;
39 int ret = -EPERM; 41 int ret = -EPERM;
40 42
41 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR) 43 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
42 return -EINVAL; 44 return -EINVAL;
43 spin_lock(&rpc_authflavor_lock); 45 spin_lock(&rpc_authflavor_lock);
44 if (auth_flavors[flavor] == NULL) { 46 if (auth_flavors[flavor] == NULL) {
45 auth_flavors[flavor] = ops; 47 auth_flavors[flavor] = ops;
46 ret = 0; 48 ret = 0;
47 } 49 }
48 spin_unlock(&rpc_authflavor_lock); 50 spin_unlock(&rpc_authflavor_lock);
49 return ret; 51 return ret;
50 } 52 }
51 53
52 int 54 int
53 rpcauth_unregister(const struct rpc_authops *ops) 55 rpcauth_unregister(const struct rpc_authops *ops)
54 { 56 {
55 rpc_authflavor_t flavor; 57 rpc_authflavor_t flavor;
56 int ret = -EPERM; 58 int ret = -EPERM;
57 59
58 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR) 60 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
59 return -EINVAL; 61 return -EINVAL;
60 spin_lock(&rpc_authflavor_lock); 62 spin_lock(&rpc_authflavor_lock);
61 if (auth_flavors[flavor] == ops) { 63 if (auth_flavors[flavor] == ops) {
62 auth_flavors[flavor] = NULL; 64 auth_flavors[flavor] = NULL;
63 ret = 0; 65 ret = 0;
64 } 66 }
65 spin_unlock(&rpc_authflavor_lock); 67 spin_unlock(&rpc_authflavor_lock);
66 return ret; 68 return ret;
67 } 69 }
68 70
69 struct rpc_auth * 71 struct rpc_auth *
70 rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt) 72 rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
71 { 73 {
72 struct rpc_auth *auth; 74 struct rpc_auth *auth;
73 const struct rpc_authops *ops; 75 const struct rpc_authops *ops;
74 u32 flavor = pseudoflavor_to_flavor(pseudoflavor); 76 u32 flavor = pseudoflavor_to_flavor(pseudoflavor);
75 77
76 auth = ERR_PTR(-EINVAL); 78 auth = ERR_PTR(-EINVAL);
77 if (flavor >= RPC_AUTH_MAXFLAVOR) 79 if (flavor >= RPC_AUTH_MAXFLAVOR)
78 goto out; 80 goto out;
79 81
80 #ifdef CONFIG_KMOD 82 #ifdef CONFIG_KMOD
81 if ((ops = auth_flavors[flavor]) == NULL) 83 if ((ops = auth_flavors[flavor]) == NULL)
82 request_module("rpc-auth-%u", flavor); 84 request_module("rpc-auth-%u", flavor);
83 #endif 85 #endif
84 spin_lock(&rpc_authflavor_lock); 86 spin_lock(&rpc_authflavor_lock);
85 ops = auth_flavors[flavor]; 87 ops = auth_flavors[flavor];
86 if (ops == NULL || !try_module_get(ops->owner)) { 88 if (ops == NULL || !try_module_get(ops->owner)) {
87 spin_unlock(&rpc_authflavor_lock); 89 spin_unlock(&rpc_authflavor_lock);
88 goto out; 90 goto out;
89 } 91 }
90 spin_unlock(&rpc_authflavor_lock); 92 spin_unlock(&rpc_authflavor_lock);
91 auth = ops->create(clnt, pseudoflavor); 93 auth = ops->create(clnt, pseudoflavor);
92 module_put(ops->owner); 94 module_put(ops->owner);
93 if (IS_ERR(auth)) 95 if (IS_ERR(auth))
94 return auth; 96 return auth;
95 if (clnt->cl_auth) 97 if (clnt->cl_auth)
96 rpcauth_release(clnt->cl_auth); 98 rpcauth_release(clnt->cl_auth);
97 clnt->cl_auth = auth; 99 clnt->cl_auth = auth;
98 100
99 out: 101 out:
100 return auth; 102 return auth;
101 } 103 }
102 104
103 void 105 void
104 rpcauth_release(struct rpc_auth *auth) 106 rpcauth_release(struct rpc_auth *auth)
105 { 107 {
106 if (!atomic_dec_and_test(&auth->au_count)) 108 if (!atomic_dec_and_test(&auth->au_count))
107 return; 109 return;
108 auth->au_ops->destroy(auth); 110 auth->au_ops->destroy(auth);
109 } 111 }
110 112
111 static DEFINE_SPINLOCK(rpc_credcache_lock); 113 static DEFINE_SPINLOCK(rpc_credcache_lock);
112 114
113 /* 115 /*
114 * Initialize RPC credential cache 116 * Initialize RPC credential cache
115 */ 117 */
116 int 118 int
117 rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire) 119 rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
118 { 120 {
119 struct rpc_cred_cache *new; 121 struct rpc_cred_cache *new;
120 int i; 122 int i;
121 123
122 new = kmalloc(sizeof(*new), GFP_KERNEL); 124 new = kmalloc(sizeof(*new), GFP_KERNEL);
123 if (!new) 125 if (!new)
124 return -ENOMEM; 126 return -ENOMEM;
125 for (i = 0; i < RPC_CREDCACHE_NR; i++) 127 for (i = 0; i < RPC_CREDCACHE_NR; i++)
126 INIT_HLIST_HEAD(&new->hashtable[i]); 128 INIT_HLIST_HEAD(&new->hashtable[i]);
127 new->expire = expire; 129 new->expire = expire;
128 new->nextgc = jiffies + (expire >> 1); 130 new->nextgc = jiffies + (expire >> 1);
129 auth->au_credcache = new; 131 auth->au_credcache = new;
130 return 0; 132 return 0;
131 } 133 }
132 134
133 /* 135 /*
134 * Destroy a list of credentials 136 * Destroy a list of credentials
135 */ 137 */
136 static inline 138 static inline
137 void rpcauth_destroy_credlist(struct hlist_head *head) 139 void rpcauth_destroy_credlist(struct list_head *head)
138 { 140 {
139 struct rpc_cred *cred; 141 struct rpc_cred *cred;
140 142
141 while (!hlist_empty(head)) { 143 while (!list_empty(head)) {
142 cred = hlist_entry(head->first, struct rpc_cred, cr_hash); 144 cred = list_entry(head->next, struct rpc_cred, cr_lru);
143 hlist_del_init(&cred->cr_hash); 145 list_del_init(&cred->cr_lru);
144 put_rpccred(cred); 146 put_rpccred(cred);
145 } 147 }
146 } 148 }
147 149
148 /* 150 /*
149 * Clear the RPC credential cache, and delete those credentials 151 * Clear the RPC credential cache, and delete those credentials
150 * that are not referenced. 152 * that are not referenced.
151 */ 153 */
152 void 154 void
153 rpcauth_clear_credcache(struct rpc_cred_cache *cache) 155 rpcauth_clear_credcache(struct rpc_cred_cache *cache)
154 { 156 {
155 HLIST_HEAD(free); 157 LIST_HEAD(free);
156 struct hlist_node *pos, *next; 158 struct hlist_head *head;
157 struct rpc_cred *cred; 159 struct rpc_cred *cred;
158 int i; 160 int i;
159 161
160 spin_lock(&rpc_credcache_lock); 162 spin_lock(&rpc_credcache_lock);
161 for (i = 0; i < RPC_CREDCACHE_NR; i++) { 163 for (i = 0; i < RPC_CREDCACHE_NR; i++) {
162 hlist_for_each_safe(pos, next, &cache->hashtable[i]) { 164 head = &cache->hashtable[i];
163 cred = hlist_entry(pos, struct rpc_cred, cr_hash); 165 while (!hlist_empty(head)) {
164 __hlist_del(&cred->cr_hash); 166 cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
165 hlist_add_head(&cred->cr_hash, &free); 167 get_rpccred(cred);
168 list_move_tail(&cred->cr_lru, &free);
169 smp_wmb();
170 hlist_del_init(&cred->cr_hash);
166 } 171 }
167 } 172 }
168 spin_unlock(&rpc_credcache_lock); 173 spin_unlock(&rpc_credcache_lock);
169 rpcauth_destroy_credlist(&free); 174 rpcauth_destroy_credlist(&free);
170 } 175 }
171 176
172 /* 177 /*
173 * Destroy the RPC credential cache 178 * Destroy the RPC credential cache
174 */ 179 */
175 void 180 void
176 rpcauth_destroy_credcache(struct rpc_auth *auth) 181 rpcauth_destroy_credcache(struct rpc_auth *auth)
177 { 182 {
178 struct rpc_cred_cache *cache = auth->au_credcache; 183 struct rpc_cred_cache *cache = auth->au_credcache;
179 184
180 if (cache) { 185 if (cache) {
181 auth->au_credcache = NULL; 186 auth->au_credcache = NULL;
182 rpcauth_clear_credcache(cache); 187 rpcauth_clear_credcache(cache);
183 kfree(cache); 188 kfree(cache);
184 } 189 }
185 } 190 }
186 191
192 /*
193 * Remove stale credentials. Avoid sleeping inside the loop.
194 */
187 static void 195 static void
188 rpcauth_prune_expired(struct rpc_auth *auth, struct rpc_cred *cred, struct hlist_head *free) 196 rpcauth_prune_expired(struct list_head *free)
189 { 197 {
190 if (atomic_read(&cred->cr_count) != 1) 198 struct rpc_cred *cred;
191 return; 199
192 if (time_after(jiffies, cred->cr_expire + auth->au_credcache->expire)) 200 while (!list_empty(&cred_unused)) {
193 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); 201 cred = list_entry(cred_unused.next, struct rpc_cred, cr_lru);
194 if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) { 202 if (time_after(jiffies, cred->cr_expire +
195 __hlist_del(&cred->cr_hash); 203 cred->cr_auth->au_credcache->expire))
196 hlist_add_head(&cred->cr_hash, free); 204 break;
205 list_del_init(&cred->cr_lru);
206 if (atomic_read(&cred->cr_count) != 0)
207 continue;
208 get_rpccred(cred);
209 list_add_tail(&cred->cr_lru, free);
210 smp_wmb();
211 hlist_del_init(&cred->cr_hash);
197 } 212 }
198 } 213 }
199 214
200 /* 215 /*
201 * Remove stale credentials. Avoid sleeping inside the loop. 216 * Run garbage collector.
202 */ 217 */
203 static void 218 static void
204 rpcauth_gc_credcache(struct rpc_auth *auth, struct hlist_head *free) 219 rpcauth_gc_credcache(struct rpc_cred_cache *cache, struct list_head *free)
205 { 220 {
206 struct rpc_cred_cache *cache = auth->au_credcache; 221 if (time_before(jiffies, cache->nextgc))
207 struct hlist_node *pos, *next; 222 return;
208 struct rpc_cred *cred;
209 int i;
210
211 dprintk("RPC: gc'ing RPC credentials for auth %p\n", auth);
212 for (i = 0; i < RPC_CREDCACHE_NR; i++) {
213 hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
214 cred = hlist_entry(pos, struct rpc_cred, cr_hash);
215 rpcauth_prune_expired(auth, cred, free);
216 }
217 }
218 cache->nextgc = jiffies + cache->expire; 223 cache->nextgc = jiffies + cache->expire;
224 rpcauth_prune_expired(free);
219 } 225 }
220 226
221 /* 227 /*
222 * Look up a process' credentials in the authentication cache 228 * Look up a process' credentials in the authentication cache
223 */ 229 */
224 struct rpc_cred * 230 struct rpc_cred *
225 rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, 231 rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
226 int flags) 232 int flags)
227 { 233 {
234 LIST_HEAD(free);
228 struct rpc_cred_cache *cache = auth->au_credcache; 235 struct rpc_cred_cache *cache = auth->au_credcache;
229 HLIST_HEAD(free); 236 struct hlist_node *pos;
230 struct hlist_node *pos, *next;
231 struct rpc_cred *new = NULL, 237 struct rpc_cred *new = NULL,
232 *cred = NULL; 238 *cred = NULL,
239 *entry;
233 int nr = 0; 240 int nr = 0;
234 241
235 if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS)) 242 if (!(flags & RPCAUTH_LOOKUP_ROOTCREDS))
236 nr = acred->uid & RPC_CREDCACHE_MASK; 243 nr = acred->uid & RPC_CREDCACHE_MASK;
237 retry: 244 retry:
238 spin_lock(&rpc_credcache_lock); 245 spin_lock(&rpc_credcache_lock);
239 if (time_before(cache->nextgc, jiffies)) 246 hlist_for_each_entry(entry, pos, &cache->hashtable[nr], cr_hash) {
240 rpcauth_gc_credcache(auth, &free); 247 if (!entry->cr_ops->crmatch(acred, entry, flags))
241 hlist_for_each_safe(pos, next, &cache->hashtable[nr]) { 248 continue;
242 struct rpc_cred *entry; 249 cred = get_rpccred(entry);
243 entry = hlist_entry(pos, struct rpc_cred, cr_hash); 250 hlist_del(&entry->cr_hash);
244 if (entry->cr_ops->crmatch(acred, entry, flags)) { 251 break;
245 hlist_del(&entry->cr_hash);
246 cred = entry;
247 break;
248 }
249 rpcauth_prune_expired(auth, entry, &free);
250 } 252 }
251 if (new) { 253 if (new) {
252 if (cred) 254 if (cred)
253 hlist_add_head(&new->cr_hash, &free); 255 list_add_tail(&new->cr_lru, &free);
254 else 256 else
255 cred = new; 257 cred = new;
256 } 258 }
257 if (cred) { 259 if (cred) {
258 hlist_add_head(&cred->cr_hash, &cache->hashtable[nr]); 260 hlist_add_head(&cred->cr_hash, &cache->hashtable[nr]);
259 get_rpccred(cred);
260 } 261 }
262 rpcauth_gc_credcache(cache, &free);
261 spin_unlock(&rpc_credcache_lock); 263 spin_unlock(&rpc_credcache_lock);
262 264
263 rpcauth_destroy_credlist(&free); 265 rpcauth_destroy_credlist(&free);
264 266
265 if (!cred) { 267 if (!cred) {
266 new = auth->au_ops->crcreate(auth, acred, flags); 268 new = auth->au_ops->crcreate(auth, acred, flags);
267 if (!IS_ERR(new)) 269 if (!IS_ERR(new))
268 goto retry; 270 goto retry;
269 cred = new; 271 cred = new;
270 } else if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) 272 } else if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags)
271 && cred->cr_ops->cr_init != NULL 273 && cred->cr_ops->cr_init != NULL
272 && !(flags & RPCAUTH_LOOKUP_NEW)) { 274 && !(flags & RPCAUTH_LOOKUP_NEW)) {
273 int res = cred->cr_ops->cr_init(auth, cred); 275 int res = cred->cr_ops->cr_init(auth, cred);
274 if (res < 0) { 276 if (res < 0) {
275 put_rpccred(cred); 277 put_rpccred(cred);
276 cred = ERR_PTR(res); 278 cred = ERR_PTR(res);
277 } 279 }
278 } 280 }
279 281
280 return (struct rpc_cred *) cred; 282 return (struct rpc_cred *) cred;
281 } 283 }
282 284
283 struct rpc_cred * 285 struct rpc_cred *
284 rpcauth_lookupcred(struct rpc_auth *auth, int flags) 286 rpcauth_lookupcred(struct rpc_auth *auth, int flags)
285 { 287 {
286 struct auth_cred acred = { 288 struct auth_cred acred = {
287 .uid = current->fsuid, 289 .uid = current->fsuid,
288 .gid = current->fsgid, 290 .gid = current->fsgid,
289 .group_info = current->group_info, 291 .group_info = current->group_info,
290 }; 292 };
291 struct rpc_cred *ret; 293 struct rpc_cred *ret;
292 294
293 dprintk("RPC: looking up %s cred\n", 295 dprintk("RPC: looking up %s cred\n",
294 auth->au_ops->au_name); 296 auth->au_ops->au_name);
295 get_group_info(acred.group_info); 297 get_group_info(acred.group_info);
296 ret = auth->au_ops->lookup_cred(auth, &acred, flags); 298 ret = auth->au_ops->lookup_cred(auth, &acred, flags);
297 put_group_info(acred.group_info); 299 put_group_info(acred.group_info);
298 return ret; 300 return ret;
299 } 301 }
300 302
301 void 303 void
302 rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred, 304 rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
303 struct rpc_auth *auth, const struct rpc_credops *ops) 305 struct rpc_auth *auth, const struct rpc_credops *ops)
304 { 306 {
305 INIT_HLIST_NODE(&cred->cr_hash); 307 INIT_HLIST_NODE(&cred->cr_hash);
308 INIT_LIST_HEAD(&cred->cr_lru);
306 atomic_set(&cred->cr_count, 1); 309 atomic_set(&cred->cr_count, 1);
307 cred->cr_auth = auth; 310 cred->cr_auth = auth;
308 cred->cr_ops = ops; 311 cred->cr_ops = ops;
309 cred->cr_expire = jiffies; 312 cred->cr_expire = jiffies;
310 #ifdef RPC_DEBUG 313 #ifdef RPC_DEBUG
311 cred->cr_magic = RPCAUTH_CRED_MAGIC; 314 cred->cr_magic = RPCAUTH_CRED_MAGIC;
312 #endif 315 #endif
313 cred->cr_uid = acred->uid; 316 cred->cr_uid = acred->uid;
314 } 317 }
315 EXPORT_SYMBOL(rpcauth_init_cred); 318 EXPORT_SYMBOL(rpcauth_init_cred);
316 319
317 struct rpc_cred * 320 struct rpc_cred *
318 rpcauth_bindcred(struct rpc_task *task) 321 rpcauth_bindcred(struct rpc_task *task)
319 { 322 {
320 struct rpc_auth *auth = task->tk_auth; 323 struct rpc_auth *auth = task->tk_auth;
321 struct auth_cred acred = { 324 struct auth_cred acred = {
322 .uid = current->fsuid, 325 .uid = current->fsuid,
323 .gid = current->fsgid, 326 .gid = current->fsgid,
324 .group_info = current->group_info, 327 .group_info = current->group_info,
325 }; 328 };
326 struct rpc_cred *ret; 329 struct rpc_cred *ret;
327 int flags = 0; 330 int flags = 0;
328 331
329 dprintk("RPC: %5u looking up %s cred\n", 332 dprintk("RPC: %5u looking up %s cred\n",
330 task->tk_pid, task->tk_auth->au_ops->au_name); 333 task->tk_pid, task->tk_auth->au_ops->au_name);
331 get_group_info(acred.group_info); 334 get_group_info(acred.group_info);
332 if (task->tk_flags & RPC_TASK_ROOTCREDS) 335 if (task->tk_flags & RPC_TASK_ROOTCREDS)
333 flags |= RPCAUTH_LOOKUP_ROOTCREDS; 336 flags |= RPCAUTH_LOOKUP_ROOTCREDS;
334 ret = auth->au_ops->lookup_cred(auth, &acred, flags); 337 ret = auth->au_ops->lookup_cred(auth, &acred, flags);
335 if (!IS_ERR(ret)) 338 if (!IS_ERR(ret))
336 task->tk_msg.rpc_cred = ret; 339 task->tk_msg.rpc_cred = ret;
337 else 340 else
338 task->tk_status = PTR_ERR(ret); 341 task->tk_status = PTR_ERR(ret);
339 put_group_info(acred.group_info); 342 put_group_info(acred.group_info);
340 return ret; 343 return ret;
341 } 344 }
342 345
343 void 346 void
344 rpcauth_holdcred(struct rpc_task *task) 347 rpcauth_holdcred(struct rpc_task *task)
345 { 348 {
346 dprintk("RPC: %5u holding %s cred %p\n", 349 dprintk("RPC: %5u holding %s cred %p\n",
347 task->tk_pid, task->tk_auth->au_ops->au_name, 350 task->tk_pid, task->tk_auth->au_ops->au_name,
348 task->tk_msg.rpc_cred); 351 task->tk_msg.rpc_cred);
349 if (task->tk_msg.rpc_cred) 352 if (task->tk_msg.rpc_cred)
350 get_rpccred(task->tk_msg.rpc_cred); 353 get_rpccred(task->tk_msg.rpc_cred);
351 } 354 }
352 355
353 void 356 void
354 put_rpccred(struct rpc_cred *cred) 357 put_rpccred(struct rpc_cred *cred)
355 { 358 {
356 cred->cr_expire = jiffies; 359 /* Fast path for unhashed credentials */
360 if (!hlist_unhashed(&cred->cr_hash))
361 goto need_lock;
362
357 if (!atomic_dec_and_test(&cred->cr_count)) 363 if (!atomic_dec_and_test(&cred->cr_count))
358 return; 364 return;
365 goto out_destroy;
366
367 need_lock:
368 if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
369 return;
370 if (!list_empty(&cred->cr_lru))
371 list_del_init(&cred->cr_lru);
372 if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
373 hlist_del(&cred->cr_hash);
374 else if (!hlist_unhashed(&cred->cr_hash)) {
375 cred->cr_expire = jiffies;
376 list_add_tail(&cred->cr_lru, &cred_unused);
377 spin_unlock(&rpc_credcache_lock);
378 return;
379 }
380 spin_unlock(&rpc_credcache_lock);
381 out_destroy:
359 cred->cr_ops->crdestroy(cred); 382 cred->cr_ops->crdestroy(cred);
360 } 383 }
361 384
362 void 385 void
363 rpcauth_unbindcred(struct rpc_task *task) 386 rpcauth_unbindcred(struct rpc_task *task)
364 { 387 {
365 struct rpc_cred *cred = task->tk_msg.rpc_cred; 388 struct rpc_cred *cred = task->tk_msg.rpc_cred;
366 389
367 dprintk("RPC: %5u releasing %s cred %p\n", 390 dprintk("RPC: %5u releasing %s cred %p\n",
368 task->tk_pid, task->tk_auth->au_ops->au_name, cred); 391 task->tk_pid, task->tk_auth->au_ops->au_name, cred);
369 392
370 put_rpccred(cred); 393 put_rpccred(cred);
371 task->tk_msg.rpc_cred = NULL; 394 task->tk_msg.rpc_cred = NULL;
372 } 395 }
373 396
374 __be32 * 397 __be32 *
375 rpcauth_marshcred(struct rpc_task *task, __be32 *p) 398 rpcauth_marshcred(struct rpc_task *task, __be32 *p)
376 { 399 {
377 struct rpc_cred *cred = task->tk_msg.rpc_cred; 400 struct rpc_cred *cred = task->tk_msg.rpc_cred;
378 401
379 dprintk("RPC: %5u marshaling %s cred %p\n", 402 dprintk("RPC: %5u marshaling %s cred %p\n",
380 task->tk_pid, task->tk_auth->au_ops->au_name, cred); 403 task->tk_pid, task->tk_auth->au_ops->au_name, cred);
381 404
382 return cred->cr_ops->crmarshal(task, p); 405 return cred->cr_ops->crmarshal(task, p);
383 } 406 }
384 407
385 __be32 * 408 __be32 *
386 rpcauth_checkverf(struct rpc_task *task, __be32 *p) 409 rpcauth_checkverf(struct rpc_task *task, __be32 *p)
387 { 410 {
388 struct rpc_cred *cred = task->tk_msg.rpc_cred; 411 struct rpc_cred *cred = task->tk_msg.rpc_cred;
389 412
390 dprintk("RPC: %5u validating %s cred %p\n", 413 dprintk("RPC: %5u validating %s cred %p\n",
391 task->tk_pid, task->tk_auth->au_ops->au_name, cred); 414 task->tk_pid, task->tk_auth->au_ops->au_name, cred);
392 415
393 return cred->cr_ops->crvalidate(task, p); 416 return cred->cr_ops->crvalidate(task, p);
394 } 417 }
395 418
396 int 419 int
397 rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp, 420 rpcauth_wrap_req(struct rpc_task *task, kxdrproc_t encode, void *rqstp,
398 __be32 *data, void *obj) 421 __be32 *data, void *obj)
399 { 422 {
400 struct rpc_cred *cred = task->tk_msg.rpc_cred; 423 struct rpc_cred *cred = task->tk_msg.rpc_cred;
401 424
402 dprintk("RPC: %5u using %s cred %p to wrap rpc data\n", 425 dprintk("RPC: %5u using %s cred %p to wrap rpc data\n",
403 task->tk_pid, cred->cr_ops->cr_name, cred); 426 task->tk_pid, cred->cr_ops->cr_name, cred);
404 if (cred->cr_ops->crwrap_req) 427 if (cred->cr_ops->crwrap_req)
405 return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj); 428 return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj);
406 /* By default, we encode the arguments normally. */ 429 /* By default, we encode the arguments normally. */
407 return encode(rqstp, data, obj); 430 return encode(rqstp, data, obj);
408 } 431 }
409 432
410 int 433 int
411 rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp, 434 rpcauth_unwrap_resp(struct rpc_task *task, kxdrproc_t decode, void *rqstp,
412 __be32 *data, void *obj) 435 __be32 *data, void *obj)
413 { 436 {
414 struct rpc_cred *cred = task->tk_msg.rpc_cred; 437 struct rpc_cred *cred = task->tk_msg.rpc_cred;
415 438
416 dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n", 439 dprintk("RPC: %5u using %s cred %p to unwrap rpc data\n",
417 task->tk_pid, cred->cr_ops->cr_name, cred); 440 task->tk_pid, cred->cr_ops->cr_name, cred);
418 if (cred->cr_ops->crunwrap_resp) 441 if (cred->cr_ops->crunwrap_resp)
419 return cred->cr_ops->crunwrap_resp(task, decode, rqstp, 442 return cred->cr_ops->crunwrap_resp(task, decode, rqstp,
420 data, obj); 443 data, obj);
421 /* By default, we decode the arguments normally. */ 444 /* By default, we decode the arguments normally. */
422 return decode(rqstp, data, obj); 445 return decode(rqstp, data, obj);
423 } 446 }
424 447
425 int 448 int
426 rpcauth_refreshcred(struct rpc_task *task) 449 rpcauth_refreshcred(struct rpc_task *task)
427 { 450 {
428 struct rpc_cred *cred = task->tk_msg.rpc_cred; 451 struct rpc_cred *cred = task->tk_msg.rpc_cred;
429 int err; 452 int err;
430 453
431 dprintk("RPC: %5u refreshing %s cred %p\n", 454 dprintk("RPC: %5u refreshing %s cred %p\n",
432 task->tk_pid, task->tk_auth->au_ops->au_name, cred); 455 task->tk_pid, task->tk_auth->au_ops->au_name, cred);
433 456
434 err = cred->cr_ops->crrefresh(task); 457 err = cred->cr_ops->crrefresh(task);
435 if (err < 0) 458 if (err < 0)
436 task->tk_status = err; 459 task->tk_status = err;
437 return err; 460 return err;
438 } 461 }
439 462
440 void 463 void
441 rpcauth_invalcred(struct rpc_task *task) 464 rpcauth_invalcred(struct rpc_task *task)
442 { 465 {
net/sunrpc/auth_null.c
1 /* 1 /*
2 * linux/net/sunrpc/auth_null.c 2 * linux/net/sunrpc/auth_null.c
3 * 3 *
4 * AUTH_NULL authentication. Really :-) 4 * AUTH_NULL authentication. Really :-)
5 * 5 *
6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> 6 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
7 */ 7 */
8 8
9 #include <linux/types.h> 9 #include <linux/types.h>
10 #include <linux/module.h> 10 #include <linux/module.h>
11 #include <linux/utsname.h> 11 #include <linux/utsname.h>
12 #include <linux/sunrpc/clnt.h> 12 #include <linux/sunrpc/clnt.h>
13 13
14 #ifdef RPC_DEBUG 14 #ifdef RPC_DEBUG
15 # define RPCDBG_FACILITY RPCDBG_AUTH 15 # define RPCDBG_FACILITY RPCDBG_AUTH
16 #endif 16 #endif
17 17
18 static struct rpc_auth null_auth; 18 static struct rpc_auth null_auth;
19 static struct rpc_cred null_cred; 19 static struct rpc_cred null_cred;
20 20
21 static struct rpc_auth * 21 static struct rpc_auth *
22 nul_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor) 22 nul_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
23 { 23 {
24 atomic_inc(&null_auth.au_count); 24 atomic_inc(&null_auth.au_count);
25 return &null_auth; 25 return &null_auth;
26 } 26 }
27 27
28 static void 28 static void
29 nul_destroy(struct rpc_auth *auth) 29 nul_destroy(struct rpc_auth *auth)
30 { 30 {
31 } 31 }
32 32
33 /* 33 /*
34 * Lookup NULL creds for current process 34 * Lookup NULL creds for current process
35 */ 35 */
36 static struct rpc_cred * 36 static struct rpc_cred *
37 nul_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) 37 nul_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
38 { 38 {
39 return get_rpccred(&null_cred); 39 return get_rpccred(&null_cred);
40 } 40 }
41 41
42 /* 42 /*
43 * Destroy cred handle. 43 * Destroy cred handle.
44 */ 44 */
45 static void 45 static void
46 nul_destroy_cred(struct rpc_cred *cred) 46 nul_destroy_cred(struct rpc_cred *cred)
47 { 47 {
48 } 48 }
49 49
50 /* 50 /*
51 * Match cred handle against current process 51 * Match cred handle against current process
52 */ 52 */
53 static int 53 static int
54 nul_match(struct auth_cred *acred, struct rpc_cred *cred, int taskflags) 54 nul_match(struct auth_cred *acred, struct rpc_cred *cred, int taskflags)
55 { 55 {
56 return 1; 56 return 1;
57 } 57 }
58 58
59 /* 59 /*
60 * Marshal credential. 60 * Marshal credential.
61 */ 61 */
62 static __be32 * 62 static __be32 *
63 nul_marshal(struct rpc_task *task, __be32 *p) 63 nul_marshal(struct rpc_task *task, __be32 *p)
64 { 64 {
65 *p++ = htonl(RPC_AUTH_NULL); 65 *p++ = htonl(RPC_AUTH_NULL);
66 *p++ = 0; 66 *p++ = 0;
67 *p++ = htonl(RPC_AUTH_NULL); 67 *p++ = htonl(RPC_AUTH_NULL);
68 *p++ = 0; 68 *p++ = 0;
69 69
70 return p; 70 return p;
71 } 71 }
72 72
73 /* 73 /*
74 * Refresh credential. This is a no-op for AUTH_NULL 74 * Refresh credential. This is a no-op for AUTH_NULL
75 */ 75 */
76 static int 76 static int
77 nul_refresh(struct rpc_task *task) 77 nul_refresh(struct rpc_task *task)
78 { 78 {
79 set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags); 79 set_bit(RPCAUTH_CRED_UPTODATE, &task->tk_msg.rpc_cred->cr_flags);
80 return 0; 80 return 0;
81 } 81 }
82 82
83 static __be32 * 83 static __be32 *
84 nul_validate(struct rpc_task *task, __be32 *p) 84 nul_validate(struct rpc_task *task, __be32 *p)
85 { 85 {
86 rpc_authflavor_t flavor; 86 rpc_authflavor_t flavor;
87 u32 size; 87 u32 size;
88 88
89 flavor = ntohl(*p++); 89 flavor = ntohl(*p++);
90 if (flavor != RPC_AUTH_NULL) { 90 if (flavor != RPC_AUTH_NULL) {
91 printk("RPC: bad verf flavor: %u\n", flavor); 91 printk("RPC: bad verf flavor: %u\n", flavor);
92 return NULL; 92 return NULL;
93 } 93 }
94 94
95 size = ntohl(*p++); 95 size = ntohl(*p++);
96 if (size != 0) { 96 if (size != 0) {
97 printk("RPC: bad verf size: %u\n", size); 97 printk("RPC: bad verf size: %u\n", size);
98 return NULL; 98 return NULL;
99 } 99 }
100 100
101 return p; 101 return p;
102 } 102 }
103 103
104 const struct rpc_authops authnull_ops = { 104 const struct rpc_authops authnull_ops = {
105 .owner = THIS_MODULE, 105 .owner = THIS_MODULE,
106 .au_flavor = RPC_AUTH_NULL, 106 .au_flavor = RPC_AUTH_NULL,
107 #ifdef RPC_DEBUG 107 #ifdef RPC_DEBUG
108 .au_name = "NULL", 108 .au_name = "NULL",
109 #endif 109 #endif
110 .create = nul_create, 110 .create = nul_create,
111 .destroy = nul_destroy, 111 .destroy = nul_destroy,
112 .lookup_cred = nul_lookup_cred, 112 .lookup_cred = nul_lookup_cred,
113 }; 113 };
114 114
115 static 115 static
116 struct rpc_auth null_auth = { 116 struct rpc_auth null_auth = {
117 .au_cslack = 4, 117 .au_cslack = 4,
118 .au_rslack = 2, 118 .au_rslack = 2,
119 .au_ops = &authnull_ops, 119 .au_ops = &authnull_ops,
120 .au_flavor = RPC_AUTH_NULL, 120 .au_flavor = RPC_AUTH_NULL,
121 .au_count = ATOMIC_INIT(0), 121 .au_count = ATOMIC_INIT(0),
122 }; 122 };
123 123
124 static 124 static
125 const struct rpc_credops null_credops = { 125 const struct rpc_credops null_credops = {
126 .cr_name = "AUTH_NULL", 126 .cr_name = "AUTH_NULL",
127 .crdestroy = nul_destroy_cred, 127 .crdestroy = nul_destroy_cred,
128 .crmatch = nul_match, 128 .crmatch = nul_match,
129 .crmarshal = nul_marshal, 129 .crmarshal = nul_marshal,
130 .crrefresh = nul_refresh, 130 .crrefresh = nul_refresh,
131 .crvalidate = nul_validate, 131 .crvalidate = nul_validate,
132 }; 132 };
133 133
134 static 134 static
135 struct rpc_cred null_cred = { 135 struct rpc_cred null_cred = {
136 .cr_lru = LIST_HEAD_INIT(null_cred.cr_lru),
136 .cr_auth = &null_auth, 137 .cr_auth = &null_auth,
137 .cr_ops = &null_credops, 138 .cr_ops = &null_credops,
138 .cr_count = ATOMIC_INIT(1), 139 .cr_count = ATOMIC_INIT(1),
139 .cr_flags = 1UL << RPCAUTH_CRED_UPTODATE, 140 .cr_flags = 1UL << RPCAUTH_CRED_UPTODATE,
140 #ifdef RPC_DEBUG 141 #ifdef RPC_DEBUG
141 .cr_magic = RPCAUTH_CRED_MAGIC, 142 .cr_magic = RPCAUTH_CRED_MAGIC,
142 #endif 143 #endif
143 }; 144 };
144 145