diff options
-rw-r--r-- | include/linux/sunrpc/auth.h | 9 | ||||
-rw-r--r-- | net/sunrpc/auth.c | 60 |
2 files changed, 56 insertions, 13 deletions
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index 84d64b6926a9..d2737625a247 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h | |||
@@ -61,14 +61,7 @@ struct rpc_cred { | |||
61 | /* | 61 | /* |
62 | * Client authentication handle | 62 | * Client authentication handle |
63 | */ | 63 | */ |
64 | #define RPC_CREDCACHE_HASHBITS 4 | 64 | struct rpc_cred_cache; |
65 | #define RPC_CREDCACHE_NR (1 << RPC_CREDCACHE_HASHBITS) | ||
66 | struct rpc_cred_cache { | ||
67 | struct hlist_head hashtable[RPC_CREDCACHE_NR]; | ||
68 | unsigned int hashbits; | ||
69 | spinlock_t lock; | ||
70 | }; | ||
71 | |||
72 | struct rpc_authops; | 65 | struct rpc_authops; |
73 | struct rpc_auth { | 66 | struct rpc_auth { |
74 | unsigned int au_cslack; /* call cred size estimate */ | 67 | unsigned int au_cslack; /* call cred size estimate */ |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index eef76a1f1dd6..d80f01725fc2 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -19,6 +19,15 @@ | |||
19 | # define RPCDBG_FACILITY RPCDBG_AUTH | 19 | # define RPCDBG_FACILITY RPCDBG_AUTH |
20 | #endif | 20 | #endif |
21 | 21 | ||
22 | #define RPC_CREDCACHE_DEFAULT_HASHBITS (4) | ||
23 | struct rpc_cred_cache { | ||
24 | struct hlist_head *hashtable; | ||
25 | unsigned int hashbits; | ||
26 | spinlock_t lock; | ||
27 | }; | ||
28 | |||
29 | static unsigned int auth_hashbits = RPC_CREDCACHE_DEFAULT_HASHBITS; | ||
30 | |||
22 | static DEFINE_SPINLOCK(rpc_authflavor_lock); | 31 | static DEFINE_SPINLOCK(rpc_authflavor_lock); |
23 | static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { | 32 | static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { |
24 | &authnull_ops, /* AUTH_NULL */ | 33 | &authnull_ops, /* AUTH_NULL */ |
@@ -29,6 +38,42 @@ static const struct rpc_authops *auth_flavors[RPC_AUTH_MAXFLAVOR] = { | |||
29 | static LIST_HEAD(cred_unused); | 38 | static LIST_HEAD(cred_unused); |
30 | static unsigned long number_cred_unused; | 39 | static unsigned long number_cred_unused; |
31 | 40 | ||
41 | #define MAX_HASHTABLE_BITS (10) | ||
42 | static int param_set_hashtbl_sz(const char *val, struct kernel_param *kp) | ||
43 | { | ||
44 | unsigned long num; | ||
45 | unsigned int nbits; | ||
46 | int ret; | ||
47 | |||
48 | if (!val) | ||
49 | goto out_inval; | ||
50 | ret = strict_strtoul(val, 0, &num); | ||
51 | if (ret == -EINVAL) | ||
52 | goto out_inval; | ||
53 | nbits = fls(num); | ||
54 | if (num > (1U << nbits)) | ||
55 | nbits++; | ||
56 | if (nbits > MAX_HASHTABLE_BITS || nbits < 2) | ||
57 | goto out_inval; | ||
58 | *(unsigned int *)kp->arg = nbits; | ||
59 | return 0; | ||
60 | out_inval: | ||
61 | return -EINVAL; | ||
62 | } | ||
63 | |||
64 | static int param_get_hashtbl_sz(char *buffer, struct kernel_param *kp) | ||
65 | { | ||
66 | unsigned int nbits; | ||
67 | |||
68 | nbits = *(unsigned int *)kp->arg; | ||
69 | return sprintf(buffer, "%u", 1U << nbits); | ||
70 | } | ||
71 | |||
72 | #define param_check_hashtbl_sz(name, p) __param_check(name, p, unsigned int); | ||
73 | |||
74 | module_param_named(auth_hashtable_size, auth_hashbits, hashtbl_sz, 0644); | ||
75 | MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size"); | ||
76 | |||
32 | static u32 | 77 | static u32 |
33 | pseudoflavor_to_flavor(u32 flavor) { | 78 | pseudoflavor_to_flavor(u32 flavor) { |
34 | if (flavor >= RPC_AUTH_MAXFLAVOR) | 79 | if (flavor >= RPC_AUTH_MAXFLAVOR) |
@@ -146,18 +191,22 @@ rpcauth_init_credcache(struct rpc_auth *auth) | |||
146 | { | 191 | { |
147 | struct rpc_cred_cache *new; | 192 | struct rpc_cred_cache *new; |
148 | unsigned int hashsize; | 193 | unsigned int hashsize; |
149 | int i; | ||
150 | 194 | ||
151 | new = kmalloc(sizeof(*new), GFP_KERNEL); | 195 | new = kmalloc(sizeof(*new), GFP_KERNEL); |
152 | if (!new) | 196 | if (!new) |
153 | return -ENOMEM; | 197 | goto out_nocache; |
154 | new->hashbits = RPC_CREDCACHE_HASHBITS; | 198 | new->hashbits = auth_hashbits; |
155 | hashsize = 1U << new->hashbits; | 199 | hashsize = 1U << new->hashbits; |
156 | for (i = 0; i < hashsize; i++) | 200 | new->hashtable = kcalloc(hashsize, sizeof(new->hashtable[0]), GFP_KERNEL); |
157 | INIT_HLIST_HEAD(&new->hashtable[i]); | 201 | if (!new->hashtable) |
202 | goto out_nohashtbl; | ||
158 | spin_lock_init(&new->lock); | 203 | spin_lock_init(&new->lock); |
159 | auth->au_credcache = new; | 204 | auth->au_credcache = new; |
160 | return 0; | 205 | return 0; |
206 | out_nohashtbl: | ||
207 | kfree(new); | ||
208 | out_nocache: | ||
209 | return -ENOMEM; | ||
161 | } | 210 | } |
162 | EXPORT_SYMBOL_GPL(rpcauth_init_credcache); | 211 | EXPORT_SYMBOL_GPL(rpcauth_init_credcache); |
163 | 212 | ||
@@ -220,6 +269,7 @@ rpcauth_destroy_credcache(struct rpc_auth *auth) | |||
220 | if (cache) { | 269 | if (cache) { |
221 | auth->au_credcache = NULL; | 270 | auth->au_credcache = NULL; |
222 | rpcauth_clear_credcache(cache); | 271 | rpcauth_clear_credcache(cache); |
272 | kfree(cache->hashtable); | ||
223 | kfree(cache); | 273 | kfree(cache); |
224 | } | 274 | } |
225 | } | 275 | } |