Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

nfsd: make expkey cache allocated per network namespace context

This patch also changes svcauth_unix_purge() function: added network namespace
as a parameter and thus loop over all networks was replaced by only one call
for ip map cache purge.

Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>

authored by

Stanislav Kinsbursky and committed by
J. Bruce Fields
e5f06f72 b3853e0e

+25 -24
+17 -11
fs/nfsd/export.c
··· 40 40 #define EXPKEY_HASHBITS 8 41 41 #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS) 42 42 #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) 43 - static struct cache_head *expkey_table[EXPKEY_HASHMAX]; 44 43 45 44 static void expkey_put(struct kref *ref) 46 45 { ··· 240 241 return NULL; 241 242 } 242 243 243 - static struct cache_detail svc_expkey_cache = { 244 + static struct cache_detail svc_expkey_cache_template = { 244 245 .owner = THIS_MODULE, 245 246 .hash_size = EXPKEY_HASHMAX, 246 - .hash_table = expkey_table, 247 247 .name = "nfsd.fh", 248 248 .cache_put = expkey_put, 249 249 .cache_upcall = expkey_upcall, ··· 881 883 u32 *fsidv, struct cache_req *reqp) 882 884 { 883 885 struct svc_export *exp; 884 - struct svc_expkey *ek = exp_find_key(&svc_expkey_cache, clp, fsid_type, fsidv, reqp); 886 + struct nfsd_net *nn = net_generic(cd->net, nfsd_net_id); 887 + struct svc_expkey *ek = exp_find_key(nn->svc_expkey_cache, clp, fsid_type, fsidv, reqp); 885 888 if (IS_ERR(ek)) 886 889 return ERR_CAST(ek); 887 890 888 891 exp = exp_get_by_name(cd, clp, &ek->ek_path, reqp); 889 - cache_put(&ek->h, &svc_expkey_cache); 892 + cache_put(&ek->h, nn->svc_expkey_cache); 890 893 891 894 if (IS_ERR(exp)) 892 895 return ERR_CAST(exp); ··· 1231 1232 .show = e_show, 1232 1233 }; 1233 1234 1234 - 1235 1235 /* 1236 1236 * Initialize the exports module. 1237 1237 */ ··· 1249 1251 if (rv) 1250 1252 goto destroy_export_cache; 1251 1253 1252 - rv = cache_register_net(&svc_expkey_cache, net); 1253 - if (rv) 1254 + nn->svc_expkey_cache = cache_create_net(&svc_expkey_cache_template, net); 1255 + if (IS_ERR(nn->svc_expkey_cache)) { 1256 + rv = PTR_ERR(nn->svc_expkey_cache); 1254 1257 goto unregister_export_cache; 1258 + } 1259 + rv = cache_register_net(nn->svc_expkey_cache, net); 1260 + if (rv) 1261 + goto destroy_expkey_cache; 1255 1262 return 0; 1256 1263 1264 + destroy_expkey_cache: 1265 + cache_destroy_net(nn->svc_expkey_cache, net); 1257 1266 unregister_export_cache: 1258 1267 cache_unregister_net(nn->svc_export_cache, net); 1259 1268 destroy_export_cache: ··· 1276 1271 { 1277 1272 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1278 1273 1279 - cache_purge(&svc_expkey_cache); 1274 + cache_purge(nn->svc_expkey_cache); 1280 1275 cache_purge(nn->svc_export_cache); 1281 1276 } 1282 1277 ··· 1290 1285 1291 1286 dprintk("nfsd: shutting down export module (net: %p).\n", net); 1292 1287 1293 - cache_unregister_net(&svc_expkey_cache, net); 1288 + cache_unregister_net(nn->svc_expkey_cache, net); 1294 1289 cache_unregister_net(nn->svc_export_cache, net); 1290 + cache_destroy_net(nn->svc_expkey_cache, net); 1295 1291 cache_destroy_net(nn->svc_export_cache, net); 1296 - svcauth_unix_purge(); 1292 + svcauth_unix_purge(net); 1297 1293 1298 1294 dprintk("nfsd: export shutdown complete (net: %p).\n", net); 1299 1295 }
+1
fs/nfsd/netns.h
··· 29 29 struct nfsd_net { 30 30 struct cld_net *cld_net; 31 31 32 + struct cache_detail *svc_expkey_cache; 32 33 struct cache_detail *svc_export_cache; 33 34 }; 34 35
+2 -1
fs/nfsd/nfsctl.c
··· 129 129 { 130 130 int err; 131 131 struct seq_file *seq; 132 + struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 132 133 133 134 err = seq_open(file, &nfs_exports_op); 134 135 if (err) 135 136 return err; 136 137 137 138 seq = file->private_data; 138 - seq->private = &svc_export_cache; 139 + seq->private = nn->svc_export_cache; 139 140 return 0; 140 141 } 141 142
-2
include/linux/nfsd/export.h
··· 143 143 __be32 exp_pseudoroot(struct svc_rqst *, struct svc_fh *); 144 144 __be32 nfserrno(int errno); 145 145 146 - extern struct cache_detail svc_export_cache; 147 - 148 146 static inline void exp_put(struct svc_export *exp) 149 147 { 150 148 cache_put(&exp->h, exp->cd);
+1 -1
include/linux/sunrpc/svcauth.h
··· 130 130 extern struct auth_domain *auth_domain_find(char *name); 131 131 extern struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr); 132 132 extern int auth_unix_forget_old(struct auth_domain *dom); 133 - extern void svcauth_unix_purge(void); 133 + extern void svcauth_unix_purge(struct net *net); 134 134 extern void svcauth_unix_info_release(struct svc_xprt *xpt); 135 135 extern int svcauth_unix_set_client(struct svc_rqst *rqstp); 136 136
+4 -9
net/sunrpc/svcauth_unix.c
··· 346 346 return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry); 347 347 } 348 348 349 - 350 - void svcauth_unix_purge(void) 349 + void svcauth_unix_purge(struct net *net) 351 350 { 352 - struct net *net; 351 + struct sunrpc_net *sn; 353 352 354 - for_each_net(net) { 355 - struct sunrpc_net *sn; 356 - 357 - sn = net_generic(net, sunrpc_net_id); 358 - cache_purge(sn->ip_map_cache); 359 - } 353 + sn = net_generic(net, sunrpc_net_id); 354 + cache_purge(sn->ip_map_cache); 360 355 } 361 356 EXPORT_SYMBOL_GPL(svcauth_unix_purge); 362 357