diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-07-31 14:29:08 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-08-04 08:54:06 -0400 |
| commit | 241269bd0b580faae71575443d9ab38df7469126 (patch) | |
| tree | b438cf34fd67b2b96b0a28be3241fd8d0c43fbca /net/sunrpc | |
| parent | 988664a0f6bbfc356e6ce55f7a87b8594050012f (diff) | |
SUNRPC: Make the credential cache hashtable size configurable
This patch allows the user to configure the credential cache hashtable size
using a new module parameter: auth_hashtable_size
When set, this parameter will be rounded up to the nearest power of two,
with a maximum allowed value of 1024 elements.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc')
| -rw-r--r-- | net/sunrpc/auth.c | 60 |
1 files changed, 55 insertions, 5 deletions
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 | } |
