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

Merge branch 'for-3.5-take-2' of git://linux-nfs.org/~bfields/linux

Pull nfsd update from Bruce Fields.

* 'for-3.5-take-2' of git://linux-nfs.org/~bfields/linux: (23 commits)
nfsd: trivial: use SEEK_SET instead of 0 in vfs_llseek
SUNRPC: split upcall function to extract reusable parts
nfsd: allocate id-to-name and name-to-id caches in per-net operations.
nfsd: make name-to-id cache allocated per network namespace context
nfsd: make id-to-name cache allocated per network namespace context
nfsd: pass network context to idmap init/exit functions
nfsd: allocate export and expkey caches in per-net operations.
nfsd: make expkey cache allocated per network namespace context
nfsd: make export cache allocated per network namespace context
nfsd: pass pointer to export cache down to stack wherever possible.
nfsd: pass network context to export caches init/shutdown routines
Lockd: pass network namespace to creation and destruction routines
NFSd: remove hard-coded dereferences to name-to-id and id-to-name caches
nfsd: pass pointer to expkey cache down to stack wherever possible.
nfsd: use hash table from cache detail in nfsd export seq ops
nfsd: pass svc_export_cache pointer as private data to "exports" seq file ops
nfsd: use exp_put() for svc_export_cache put
nfsd: use cache detail pointer from svc_export structure on cache put
nfsd: add link to owner cache detail to svc_export structure
nfsd: use passed cache_detail pointer expkey_parse()
...

+327 -214
+8 -5
fs/lockd/clntlock.c
··· 56 56 u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4; 57 57 int status; 58 58 59 - status = lockd_up(); 59 + status = lockd_up(nlm_init->net); 60 60 if (status < 0) 61 61 return ERR_PTR(status); 62 62 ··· 65 65 nlm_init->hostname, nlm_init->noresvport, 66 66 nlm_init->net); 67 67 if (host == NULL) { 68 - lockd_down(); 68 + lockd_down(nlm_init->net); 69 69 return ERR_PTR(-ENOLCK); 70 70 } 71 71 ··· 80 80 */ 81 81 void nlmclnt_done(struct nlm_host *host) 82 82 { 83 + struct net *net = host->net; 84 + 83 85 nlmclnt_release_host(host); 84 - lockd_down(); 86 + lockd_down(net); 85 87 } 86 88 EXPORT_SYMBOL_GPL(nlmclnt_done); 87 89 ··· 222 220 struct nlm_wait *block; 223 221 struct file_lock *fl, *next; 224 222 u32 nsmstate; 223 + struct net *net = host->net; 225 224 226 225 allow_signal(SIGKILL); 227 226 228 227 down_write(&host->h_rwsem); 229 - lockd_up(); /* note: this cannot fail as lockd is already running */ 228 + lockd_up(net); /* note: this cannot fail as lockd is already running */ 230 229 231 230 dprintk("lockd: reclaiming locks for host %s\n", host->h_name); 232 231 ··· 278 275 279 276 /* Release host handle after use */ 280 277 nlmclnt_release_host(host); 281 - lockd_down(); 278 + lockd_down(net); 282 279 return 0; 283 280 }
+3 -4
fs/lockd/svc.c
··· 295 295 /* 296 296 * Bring up the lockd process if it's not already up. 297 297 */ 298 - int lockd_up(void) 298 + int lockd_up(struct net *net) 299 299 { 300 300 struct svc_serv *serv; 301 301 int error = 0; 302 - struct net *net = current->nsproxy->net_ns; 303 302 304 303 mutex_lock(&nlmsvc_mutex); 305 304 /* ··· 377 378 * Decrement the user count and bring down lockd if we're the last. 378 379 */ 379 380 void 380 - lockd_down(void) 381 + lockd_down(struct net *net) 381 382 { 382 383 mutex_lock(&nlmsvc_mutex); 383 384 if (nlmsvc_users) { 384 385 if (--nlmsvc_users) { 385 - lockd_down_net(current->nsproxy->net_ns); 386 + lockd_down_net(net); 386 387 goto out; 387 388 } 388 389 } else {
+106 -69
fs/nfsd/export.c
··· 15 15 #include <linux/namei.h> 16 16 #include <linux/module.h> 17 17 #include <linux/exportfs.h> 18 + #include <linux/sunrpc/svc_xprt.h> 18 19 19 20 #include <net/ipv6.h> 20 21 21 22 #include "nfsd.h" 22 23 #include "nfsfh.h" 24 + #include "netns.h" 23 25 24 26 #define NFSDDBG_FACILITY NFSDDBG_EXPORT 25 27 ··· 40 38 #define EXPKEY_HASHBITS 8 41 39 #define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS) 42 40 #define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1) 43 - static struct cache_head *expkey_table[EXPKEY_HASHMAX]; 44 41 45 42 static void expkey_put(struct kref *ref) 46 43 { ··· 72 71 return sunrpc_cache_pipe_upcall(cd, h, expkey_request); 73 72 } 74 73 75 - static struct svc_expkey *svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old); 76 - static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *); 77 - static struct cache_detail svc_expkey_cache; 74 + static struct svc_expkey *svc_expkey_update(struct cache_detail *cd, struct svc_expkey *new, 75 + struct svc_expkey *old); 76 + static struct svc_expkey *svc_expkey_lookup(struct cache_detail *cd, struct svc_expkey *); 78 77 79 78 static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen) 80 79 { ··· 132 131 key.ek_fsidtype = fsidtype; 133 132 memcpy(key.ek_fsid, buf, len); 134 133 135 - ek = svc_expkey_lookup(&key); 134 + ek = svc_expkey_lookup(cd, &key); 136 135 err = -ENOMEM; 137 136 if (!ek) 138 137 goto out; ··· 146 145 err = 0; 147 146 if (len == 0) { 148 147 set_bit(CACHE_NEGATIVE, &key.h.flags); 149 - ek = svc_expkey_update(&key, ek); 148 + ek = svc_expkey_update(cd, &key, ek); 150 149 if (!ek) 151 150 err = -ENOMEM; 152 151 } else { ··· 156 155 157 156 dprintk("Found the path %s\n", buf); 158 157 159 - ek = svc_expkey_update(&key, ek); 158 + ek = svc_expkey_update(cd, &key, ek); 160 159 if (!ek) 161 160 err = -ENOMEM; 162 161 path_put(&key.ek_path); ··· 164 163 cache_flush(); 165 164 out: 166 165 if (ek) 167 - cache_put(&ek->h, &svc_expkey_cache); 166 + cache_put(&ek->h, cd); 168 167 if (dom) 169 168 auth_domain_put(dom); 170 169 kfree(buf); ··· 240 239 return NULL; 241 240 } 242 241 243 - static struct cache_detail svc_expkey_cache = { 242 + static struct cache_detail svc_expkey_cache_template = { 244 243 .owner = THIS_MODULE, 245 244 .hash_size = EXPKEY_HASHMAX, 246 - .hash_table = expkey_table, 247 245 .name = "nfsd.fh", 248 246 .cache_put = expkey_put, 249 247 .cache_upcall = expkey_upcall, ··· 268 268 } 269 269 270 270 static struct svc_expkey * 271 - svc_expkey_lookup(struct svc_expkey *item) 271 + svc_expkey_lookup(struct cache_detail *cd, struct svc_expkey *item) 272 272 { 273 273 struct cache_head *ch; 274 274 int hash = svc_expkey_hash(item); 275 275 276 - ch = sunrpc_cache_lookup(&svc_expkey_cache, &item->h, 277 - hash); 276 + ch = sunrpc_cache_lookup(cd, &item->h, hash); 278 277 if (ch) 279 278 return container_of(ch, struct svc_expkey, h); 280 279 else ··· 281 282 } 282 283 283 284 static struct svc_expkey * 284 - svc_expkey_update(struct svc_expkey *new, struct svc_expkey *old) 285 + svc_expkey_update(struct cache_detail *cd, struct svc_expkey *new, 286 + struct svc_expkey *old) 285 287 { 286 288 struct cache_head *ch; 287 289 int hash = svc_expkey_hash(new); 288 290 289 - ch = sunrpc_cache_update(&svc_expkey_cache, &new->h, 290 - &old->h, hash); 291 + ch = sunrpc_cache_update(cd, &new->h, &old->h, hash); 291 292 if (ch) 292 293 return container_of(ch, struct svc_expkey, h); 293 294 else ··· 297 298 298 299 #define EXPORT_HASHBITS 8 299 300 #define EXPORT_HASHMAX (1<< EXPORT_HASHBITS) 300 - 301 - static struct cache_head *export_table[EXPORT_HASHMAX]; 302 301 303 302 static void nfsd4_fslocs_free(struct nfsd4_fs_locations *fsloc) 304 303 { ··· 522 525 goto out1; 523 526 524 527 exp.ex_client = dom; 528 + exp.cd = cd; 525 529 526 530 /* expiry */ 527 531 err = -EINVAL; ··· 670 672 new->ex_fslocs.locations = NULL; 671 673 new->ex_fslocs.locations_count = 0; 672 674 new->ex_fslocs.migrated = 0; 675 + new->cd = item->cd; 673 676 } 674 677 675 678 static void export_update(struct cache_head *cnew, struct cache_head *citem) ··· 706 707 return NULL; 707 708 } 708 709 709 - struct cache_detail svc_export_cache = { 710 + struct cache_detail svc_export_cache_template = { 710 711 .owner = THIS_MODULE, 711 712 .hash_size = EXPORT_HASHMAX, 712 - .hash_table = export_table, 713 713 .name = "nfsd.export", 714 714 .cache_put = svc_export_put, 715 715 .cache_upcall = svc_export_upcall, ··· 737 739 struct cache_head *ch; 738 740 int hash = svc_export_hash(exp); 739 741 740 - ch = sunrpc_cache_lookup(&svc_export_cache, &exp->h, 741 - hash); 742 + ch = sunrpc_cache_lookup(exp->cd, &exp->h, hash); 742 743 if (ch) 743 744 return container_of(ch, struct svc_export, h); 744 745 else ··· 750 753 struct cache_head *ch; 751 754 int hash = svc_export_hash(old); 752 755 753 - ch = sunrpc_cache_update(&svc_export_cache, &new->h, 754 - &old->h, 755 - hash); 756 + ch = sunrpc_cache_update(old->cd, &new->h, &old->h, hash); 756 757 if (ch) 757 758 return container_of(ch, struct svc_export, h); 758 759 else ··· 759 764 760 765 761 766 static struct svc_expkey * 762 - exp_find_key(svc_client *clp, int fsid_type, u32 *fsidv, struct cache_req *reqp) 767 + exp_find_key(struct cache_detail *cd, svc_client *clp, int fsid_type, 768 + u32 *fsidv, struct cache_req *reqp) 763 769 { 764 770 struct svc_expkey key, *ek; 765 771 int err; ··· 772 776 key.ek_fsidtype = fsid_type; 773 777 memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); 774 778 775 - ek = svc_expkey_lookup(&key); 779 + ek = svc_expkey_lookup(cd, &key); 776 780 if (ek == NULL) 777 781 return ERR_PTR(-ENOMEM); 778 - err = cache_check(&svc_expkey_cache, &ek->h, reqp); 782 + err = cache_check(cd, &ek->h, reqp); 779 783 if (err) 780 784 return ERR_PTR(err); 781 785 return ek; 782 786 } 783 787 784 788 785 - static svc_export *exp_get_by_name(svc_client *clp, const struct path *path, 786 - struct cache_req *reqp) 789 + static svc_export *exp_get_by_name(struct cache_detail *cd, svc_client *clp, 790 + const struct path *path, struct cache_req *reqp) 787 791 { 788 792 struct svc_export *exp, key; 789 793 int err; ··· 793 797 794 798 key.ex_client = clp; 795 799 key.ex_path = *path; 800 + key.cd = cd; 796 801 797 802 exp = svc_export_lookup(&key); 798 803 if (exp == NULL) 799 804 return ERR_PTR(-ENOMEM); 800 - err = cache_check(&svc_export_cache, &exp->h, reqp); 805 + err = cache_check(cd, &exp->h, reqp); 801 806 if (err) 802 807 return ERR_PTR(err); 803 808 return exp; ··· 807 810 /* 808 811 * Find the export entry for a given dentry. 809 812 */ 810 - static struct svc_export *exp_parent(svc_client *clp, struct path *path) 813 + static struct svc_export *exp_parent(struct cache_detail *cd, svc_client *clp, 814 + struct path *path) 811 815 { 812 816 struct dentry *saved = dget(path->dentry); 813 - svc_export *exp = exp_get_by_name(clp, path, NULL); 817 + svc_export *exp = exp_get_by_name(cd, clp, path, NULL); 814 818 815 819 while (PTR_ERR(exp) == -ENOENT && !IS_ROOT(path->dentry)) { 816 820 struct dentry *parent = dget_parent(path->dentry); 817 821 dput(path->dentry); 818 822 path->dentry = parent; 819 - exp = exp_get_by_name(clp, path, NULL); 823 + exp = exp_get_by_name(cd, clp, path, NULL); 820 824 } 821 825 dput(path->dentry); 822 826 path->dentry = saved; ··· 832 834 * since its harder to fool a kernel module than a user space program. 833 835 */ 834 836 int 835 - exp_rootfh(svc_client *clp, char *name, struct knfsd_fh *f, int maxsize) 837 + exp_rootfh(struct net *net, svc_client *clp, char *name, 838 + struct knfsd_fh *f, int maxsize) 836 839 { 837 840 struct svc_export *exp; 838 841 struct path path; 839 842 struct inode *inode; 840 843 struct svc_fh fh; 841 844 int err; 845 + struct nfsd_net *nn = net_generic(net, nfsd_net_id); 846 + struct cache_detail *cd = nn->svc_export_cache; 842 847 843 848 err = -EPERM; 844 849 /* NB: we probably ought to check that it's NUL-terminated */ ··· 854 853 dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n", 855 854 name, path.dentry, clp->name, 856 855 inode->i_sb->s_id, inode->i_ino); 857 - exp = exp_parent(clp, &path); 856 + exp = exp_parent(cd, clp, &path); 858 857 if (IS_ERR(exp)) { 859 858 err = PTR_ERR(exp); 860 859 goto out; ··· 876 875 return err; 877 876 } 878 877 879 - static struct svc_export *exp_find(struct auth_domain *clp, int fsid_type, 878 + static struct svc_export *exp_find(struct cache_detail *cd, 879 + struct auth_domain *clp, int fsid_type, 880 880 u32 *fsidv, struct cache_req *reqp) 881 881 { 882 882 struct svc_export *exp; 883 - struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp); 883 + struct nfsd_net *nn = net_generic(cd->net, nfsd_net_id); 884 + struct svc_expkey *ek = exp_find_key(nn->svc_expkey_cache, clp, fsid_type, fsidv, reqp); 884 885 if (IS_ERR(ek)) 885 886 return ERR_CAST(ek); 886 887 887 - exp = exp_get_by_name(clp, &ek->ek_path, reqp); 888 - cache_put(&ek->h, &svc_expkey_cache); 888 + exp = exp_get_by_name(cd, clp, &ek->ek_path, reqp); 889 + cache_put(&ek->h, nn->svc_expkey_cache); 889 890 890 891 if (IS_ERR(exp)) 891 892 return ERR_CAST(exp); ··· 929 926 rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path) 930 927 { 931 928 struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); 929 + struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); 930 + struct cache_detail *cd = nn->svc_export_cache; 932 931 933 932 if (rqstp->rq_client == NULL) 934 933 goto gss; 935 934 936 935 /* First try the auth_unix client: */ 937 - exp = exp_get_by_name(rqstp->rq_client, path, &rqstp->rq_chandle); 936 + exp = exp_get_by_name(cd, rqstp->rq_client, path, &rqstp->rq_chandle); 938 937 if (PTR_ERR(exp) == -ENOENT) 939 938 goto gss; 940 939 if (IS_ERR(exp)) ··· 948 943 /* Otherwise, try falling back on gss client */ 949 944 if (rqstp->rq_gssclient == NULL) 950 945 return exp; 951 - gssexp = exp_get_by_name(rqstp->rq_gssclient, path, &rqstp->rq_chandle); 946 + gssexp = exp_get_by_name(cd, rqstp->rq_gssclient, path, &rqstp->rq_chandle); 952 947 if (PTR_ERR(gssexp) == -ENOENT) 953 948 return exp; 954 949 if (!IS_ERR(exp)) ··· 960 955 rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv) 961 956 { 962 957 struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); 958 + struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); 959 + struct cache_detail *cd = nn->svc_export_cache; 963 960 964 961 if (rqstp->rq_client == NULL) 965 962 goto gss; 966 963 967 964 /* First try the auth_unix client: */ 968 - exp = exp_find(rqstp->rq_client, fsid_type, fsidv, &rqstp->rq_chandle); 965 + exp = exp_find(cd, rqstp->rq_client, fsid_type, 966 + fsidv, &rqstp->rq_chandle); 969 967 if (PTR_ERR(exp) == -ENOENT) 970 968 goto gss; 971 969 if (IS_ERR(exp)) ··· 980 972 /* Otherwise, try falling back on gss client */ 981 973 if (rqstp->rq_gssclient == NULL) 982 974 return exp; 983 - gssexp = exp_find(rqstp->rq_gssclient, fsid_type, fsidv, 975 + gssexp = exp_find(cd, rqstp->rq_gssclient, fsid_type, fsidv, 984 976 &rqstp->rq_chandle); 985 977 if (PTR_ERR(gssexp) == -ENOENT) 986 978 return exp; ··· 1037 1029 /* Iterator */ 1038 1030 1039 1031 static void *e_start(struct seq_file *m, loff_t *pos) 1040 - __acquires(svc_export_cache.hash_lock) 1032 + __acquires(((struct cache_detail *)m->private)->hash_lock) 1041 1033 { 1042 1034 loff_t n = *pos; 1043 1035 unsigned hash, export; 1044 1036 struct cache_head *ch; 1045 - 1046 - read_lock(&svc_export_cache.hash_lock); 1037 + struct cache_detail *cd = m->private; 1038 + struct cache_head **export_table = cd->hash_table; 1039 + 1040 + read_lock(&cd->hash_lock); 1047 1041 if (!n--) 1048 1042 return SEQ_START_TOKEN; 1049 1043 hash = n >> 32; ··· 1070 1060 { 1071 1061 struct cache_head *ch = p; 1072 1062 int hash = (*pos >> 32); 1063 + struct cache_detail *cd = m->private; 1064 + struct cache_head **export_table = cd->hash_table; 1073 1065 1074 1066 if (p == SEQ_START_TOKEN) 1075 1067 hash = 0; ··· 1094 1082 } 1095 1083 1096 1084 static void e_stop(struct seq_file *m, void *p) 1097 - __releases(svc_export_cache.hash_lock) 1085 + __releases(((struct cache_detail *)m->private)->hash_lock) 1098 1086 { 1099 - read_unlock(&svc_export_cache.hash_lock); 1087 + struct cache_detail *cd = m->private; 1088 + 1089 + read_unlock(&cd->hash_lock); 1100 1090 } 1101 1091 1102 1092 static struct flags { ··· 1209 1195 { 1210 1196 struct cache_head *cp = p; 1211 1197 struct svc_export *exp = container_of(cp, struct svc_export, h); 1198 + struct cache_detail *cd = m->private; 1212 1199 1213 1200 if (p == SEQ_START_TOKEN) { 1214 1201 seq_puts(m, "# Version 1.1\n"); ··· 1218 1203 } 1219 1204 1220 1205 cache_get(&exp->h); 1221 - if (cache_check(&svc_export_cache, &exp->h, NULL)) 1206 + if (cache_check(cd, &exp->h, NULL)) 1222 1207 return 0; 1223 - cache_put(&exp->h, &svc_export_cache); 1224 - return svc_export_show(m, &svc_export_cache, cp); 1208 + exp_put(exp); 1209 + return svc_export_show(m, cd, cp); 1225 1210 } 1226 1211 1227 1212 const struct seq_operations nfs_exports_op = { ··· 1231 1216 .show = e_show, 1232 1217 }; 1233 1218 1234 - 1235 1219 /* 1236 1220 * Initialize the exports module. 1237 1221 */ 1238 1222 int 1239 - nfsd_export_init(void) 1223 + nfsd_export_init(struct net *net) 1240 1224 { 1241 1225 int rv; 1242 - dprintk("nfsd: initializing export module.\n"); 1226 + struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1243 1227 1244 - rv = cache_register_net(&svc_export_cache, &init_net); 1228 + dprintk("nfsd: initializing export module (net: %p).\n", net); 1229 + 1230 + nn->svc_export_cache = cache_create_net(&svc_export_cache_template, net); 1231 + if (IS_ERR(nn->svc_export_cache)) 1232 + return PTR_ERR(nn->svc_export_cache); 1233 + rv = cache_register_net(nn->svc_export_cache, net); 1245 1234 if (rv) 1246 - return rv; 1247 - rv = cache_register_net(&svc_expkey_cache, &init_net); 1235 + goto destroy_export_cache; 1236 + 1237 + nn->svc_expkey_cache = cache_create_net(&svc_expkey_cache_template, net); 1238 + if (IS_ERR(nn->svc_expkey_cache)) { 1239 + rv = PTR_ERR(nn->svc_expkey_cache); 1240 + goto unregister_export_cache; 1241 + } 1242 + rv = cache_register_net(nn->svc_expkey_cache, net); 1248 1243 if (rv) 1249 - cache_unregister_net(&svc_export_cache, &init_net); 1244 + goto destroy_expkey_cache; 1245 + return 0; 1246 + 1247 + destroy_expkey_cache: 1248 + cache_destroy_net(nn->svc_expkey_cache, net); 1249 + unregister_export_cache: 1250 + cache_unregister_net(nn->svc_export_cache, net); 1251 + destroy_export_cache: 1252 + cache_destroy_net(nn->svc_export_cache, net); 1250 1253 return rv; 1251 - 1252 1254 } 1253 1255 1254 1256 /* 1255 1257 * Flush exports table - called when last nfsd thread is killed 1256 1258 */ 1257 1259 void 1258 - nfsd_export_flush(void) 1260 + nfsd_export_flush(struct net *net) 1259 1261 { 1260 - cache_purge(&svc_expkey_cache); 1261 - cache_purge(&svc_export_cache); 1262 + struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1263 + 1264 + cache_purge(nn->svc_expkey_cache); 1265 + cache_purge(nn->svc_export_cache); 1262 1266 } 1263 1267 1264 1268 /* 1265 1269 * Shutdown the exports module. 1266 1270 */ 1267 1271 void 1268 - nfsd_export_shutdown(void) 1272 + nfsd_export_shutdown(struct net *net) 1269 1273 { 1274 + struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1270 1275 1271 - dprintk("nfsd: shutting down export module.\n"); 1276 + dprintk("nfsd: shutting down export module (net: %p).\n", net); 1272 1277 1273 - cache_unregister_net(&svc_expkey_cache, &init_net); 1274 - cache_unregister_net(&svc_export_cache, &init_net); 1275 - svcauth_unix_purge(); 1278 + cache_unregister_net(nn->svc_expkey_cache, net); 1279 + cache_unregister_net(nn->svc_export_cache, net); 1280 + cache_destroy_net(nn->svc_expkey_cache, net); 1281 + cache_destroy_net(nn->svc_export_cache, net); 1282 + svcauth_unix_purge(net); 1276 1283 1277 - dprintk("nfsd: export shutdown complete.\n"); 1284 + dprintk("nfsd: export shutdown complete (net: %p).\n", net); 1278 1285 }
+4 -4
fs/nfsd/idmap.h
··· 42 42 #define IDMAP_NAMESZ 128 43 43 44 44 #ifdef CONFIG_NFSD_V4 45 - int nfsd_idmap_init(void); 46 - void nfsd_idmap_shutdown(void); 45 + int nfsd_idmap_init(struct net *); 46 + void nfsd_idmap_shutdown(struct net *); 47 47 #else 48 - static inline int nfsd_idmap_init(void) 48 + static inline int nfsd_idmap_init(struct net *net) 49 49 { 50 50 return 0; 51 51 } 52 - static inline void nfsd_idmap_shutdown(void) 52 + static inline void nfsd_idmap_shutdown(struct net *net) 53 53 { 54 54 } 55 55 #endif
+6
fs/nfsd/netns.h
··· 28 28 29 29 struct nfsd_net { 30 30 struct cld_net *cld_net; 31 + 32 + struct cache_detail *svc_expkey_cache; 33 + struct cache_detail *svc_export_cache; 34 + 35 + struct cache_detail *idtoname_cache; 36 + struct cache_detail *nametoid_cache; 31 37 }; 32 38 33 39 extern int nfsd_net_id;
+63 -46
fs/nfsd/nfs4idmap.c
··· 36 36 #include <linux/seq_file.h> 37 37 #include <linux/sched.h> 38 38 #include <linux/slab.h> 39 + #include <linux/sunrpc/svc_xprt.h> 39 40 #include <net/net_namespace.h> 40 41 #include "idmap.h" 41 42 #include "nfsd.h" 43 + #include "netns.h" 42 44 43 45 /* 44 46 * Turn off idmapping when using AUTH_SYS. ··· 108 106 /* 109 107 * ID -> Name cache 110 108 */ 111 - 112 - static struct cache_head *idtoname_table[ENT_HASHMAX]; 113 109 114 110 static uint32_t 115 111 idtoname_hash(struct ent *ent) ··· 183 183 184 184 185 185 static int idtoname_parse(struct cache_detail *, char *, int); 186 - static struct ent *idtoname_lookup(struct ent *); 187 - static struct ent *idtoname_update(struct ent *, struct ent *); 186 + static struct ent *idtoname_lookup(struct cache_detail *, struct ent *); 187 + static struct ent *idtoname_update(struct cache_detail *, struct ent *, 188 + struct ent *); 188 189 189 - static struct cache_detail idtoname_cache = { 190 + static struct cache_detail idtoname_cache_template = { 190 191 .owner = THIS_MODULE, 191 192 .hash_size = ENT_HASHMAX, 192 - .hash_table = idtoname_table, 193 193 .name = "nfs4.idtoname", 194 194 .cache_put = ent_put, 195 195 .cache_upcall = idtoname_upcall, ··· 244 244 goto out; 245 245 246 246 error = -ENOMEM; 247 - res = idtoname_lookup(&ent); 247 + res = idtoname_lookup(cd, &ent); 248 248 if (!res) 249 249 goto out; 250 250 ··· 260 260 else 261 261 memcpy(ent.name, buf1, sizeof(ent.name)); 262 262 error = -ENOMEM; 263 - res = idtoname_update(&ent, res); 263 + res = idtoname_update(cd, &ent, res); 264 264 if (res == NULL) 265 265 goto out; 266 266 267 - cache_put(&res->h, &idtoname_cache); 267 + cache_put(&res->h, cd); 268 268 269 269 error = 0; 270 270 out: ··· 275 275 276 276 277 277 static struct ent * 278 - idtoname_lookup(struct ent *item) 278 + idtoname_lookup(struct cache_detail *cd, struct ent *item) 279 279 { 280 - struct cache_head *ch = sunrpc_cache_lookup(&idtoname_cache, 281 - &item->h, 280 + struct cache_head *ch = sunrpc_cache_lookup(cd, &item->h, 282 281 idtoname_hash(item)); 283 282 if (ch) 284 283 return container_of(ch, struct ent, h); ··· 286 287 } 287 288 288 289 static struct ent * 289 - idtoname_update(struct ent *new, struct ent *old) 290 + idtoname_update(struct cache_detail *cd, struct ent *new, struct ent *old) 290 291 { 291 - struct cache_head *ch = sunrpc_cache_update(&idtoname_cache, 292 - &new->h, &old->h, 292 + struct cache_head *ch = sunrpc_cache_update(cd, &new->h, &old->h, 293 293 idtoname_hash(new)); 294 294 if (ch) 295 295 return container_of(ch, struct ent, h); ··· 300 302 /* 301 303 * Name -> ID cache 302 304 */ 303 - 304 - static struct cache_head *nametoid_table[ENT_HASHMAX]; 305 305 306 306 static inline int 307 307 nametoid_hash(struct ent *ent) ··· 355 359 return 0; 356 360 } 357 361 358 - static struct ent *nametoid_lookup(struct ent *); 359 - static struct ent *nametoid_update(struct ent *, struct ent *); 362 + static struct ent *nametoid_lookup(struct cache_detail *, struct ent *); 363 + static struct ent *nametoid_update(struct cache_detail *, struct ent *, 364 + struct ent *); 360 365 static int nametoid_parse(struct cache_detail *, char *, int); 361 366 362 - static struct cache_detail nametoid_cache = { 367 + static struct cache_detail nametoid_cache_template = { 363 368 .owner = THIS_MODULE, 364 369 .hash_size = ENT_HASHMAX, 365 - .hash_table = nametoid_table, 366 370 .name = "nfs4.nametoid", 367 371 .cache_put = ent_put, 368 372 .cache_upcall = nametoid_upcall, ··· 422 426 set_bit(CACHE_NEGATIVE, &ent.h.flags); 423 427 424 428 error = -ENOMEM; 425 - res = nametoid_lookup(&ent); 429 + res = nametoid_lookup(cd, &ent); 426 430 if (res == NULL) 427 431 goto out; 428 - res = nametoid_update(&ent, res); 432 + res = nametoid_update(cd, &ent, res); 429 433 if (res == NULL) 430 434 goto out; 431 435 432 - cache_put(&res->h, &nametoid_cache); 436 + cache_put(&res->h, cd); 433 437 error = 0; 434 438 out: 435 439 kfree(buf1); ··· 439 443 440 444 441 445 static struct ent * 442 - nametoid_lookup(struct ent *item) 446 + nametoid_lookup(struct cache_detail *cd, struct ent *item) 443 447 { 444 - struct cache_head *ch = sunrpc_cache_lookup(&nametoid_cache, 445 - &item->h, 448 + struct cache_head *ch = sunrpc_cache_lookup(cd, &item->h, 446 449 nametoid_hash(item)); 447 450 if (ch) 448 451 return container_of(ch, struct ent, h); ··· 450 455 } 451 456 452 457 static struct ent * 453 - nametoid_update(struct ent *new, struct ent *old) 458 + nametoid_update(struct cache_detail *cd, struct ent *new, struct ent *old) 454 459 { 455 - struct cache_head *ch = sunrpc_cache_update(&nametoid_cache, 456 - &new->h, &old->h, 460 + struct cache_head *ch = sunrpc_cache_update(cd, &new->h, &old->h, 457 461 nametoid_hash(new)); 458 462 if (ch) 459 463 return container_of(ch, struct ent, h); ··· 465 471 */ 466 472 467 473 int 468 - nfsd_idmap_init(void) 474 + nfsd_idmap_init(struct net *net) 469 475 { 470 476 int rv; 477 + struct nfsd_net *nn = net_generic(net, nfsd_net_id); 471 478 472 - rv = cache_register_net(&idtoname_cache, &init_net); 479 + nn->idtoname_cache = cache_create_net(&idtoname_cache_template, net); 480 + if (IS_ERR(nn->idtoname_cache)) 481 + return PTR_ERR(nn->idtoname_cache); 482 + rv = cache_register_net(nn->idtoname_cache, net); 473 483 if (rv) 474 - return rv; 475 - rv = cache_register_net(&nametoid_cache, &init_net); 484 + goto destroy_idtoname_cache; 485 + nn->nametoid_cache = cache_create_net(&nametoid_cache_template, net); 486 + if (IS_ERR(nn->nametoid_cache)) { 487 + rv = PTR_ERR(nn->idtoname_cache); 488 + goto unregister_idtoname_cache; 489 + } 490 + rv = cache_register_net(nn->nametoid_cache, net); 476 491 if (rv) 477 - cache_unregister_net(&idtoname_cache, &init_net); 492 + goto destroy_nametoid_cache; 493 + return 0; 494 + 495 + destroy_nametoid_cache: 496 + cache_destroy_net(nn->nametoid_cache, net); 497 + unregister_idtoname_cache: 498 + cache_unregister_net(nn->idtoname_cache, net); 499 + destroy_idtoname_cache: 500 + cache_destroy_net(nn->idtoname_cache, net); 478 501 return rv; 479 502 } 480 503 481 504 void 482 - nfsd_idmap_shutdown(void) 505 + nfsd_idmap_shutdown(struct net *net) 483 506 { 484 - cache_unregister_net(&idtoname_cache, &init_net); 485 - cache_unregister_net(&nametoid_cache, &init_net); 507 + struct nfsd_net *nn = net_generic(net, nfsd_net_id); 508 + 509 + cache_unregister_net(nn->idtoname_cache, net); 510 + cache_unregister_net(nn->nametoid_cache, net); 511 + cache_destroy_net(nn->idtoname_cache, net); 512 + cache_destroy_net(nn->nametoid_cache, net); 486 513 } 487 514 488 515 static int 489 516 idmap_lookup(struct svc_rqst *rqstp, 490 - struct ent *(*lookup_fn)(struct ent *), struct ent *key, 491 - struct cache_detail *detail, struct ent **item) 517 + struct ent *(*lookup_fn)(struct cache_detail *, struct ent *), 518 + struct ent *key, struct cache_detail *detail, struct ent **item) 492 519 { 493 520 int ret; 494 521 495 - *item = lookup_fn(key); 522 + *item = lookup_fn(detail, key); 496 523 if (!*item) 497 524 return -ENOMEM; 498 525 retry: ··· 521 506 522 507 if (ret == -ETIMEDOUT) { 523 508 struct ent *prev_item = *item; 524 - *item = lookup_fn(key); 509 + *item = lookup_fn(detail, key); 525 510 if (*item != prev_item) 526 511 goto retry; 527 512 cache_put(&(*item)->h, detail); ··· 546 531 .type = type, 547 532 }; 548 533 int ret; 534 + struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); 549 535 550 536 if (namelen + 1 > sizeof(key.name)) 551 537 return nfserr_badowner; 552 538 memcpy(key.name, name, namelen); 553 539 key.name[namelen] = '\0'; 554 540 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); 555 - ret = idmap_lookup(rqstp, nametoid_lookup, &key, &nametoid_cache, &item); 541 + ret = idmap_lookup(rqstp, nametoid_lookup, &key, nn->nametoid_cache, &item); 556 542 if (ret == -ENOENT) 557 543 return nfserr_badowner; 558 544 if (ret) 559 545 return nfserrno(ret); 560 546 *id = item->id; 561 - cache_put(&item->h, &nametoid_cache); 547 + cache_put(&item->h, nn->nametoid_cache); 562 548 return 0; 563 549 } 564 550 ··· 571 555 .type = type, 572 556 }; 573 557 int ret; 558 + struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); 574 559 575 560 strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); 576 - ret = idmap_lookup(rqstp, idtoname_lookup, &key, &idtoname_cache, &item); 561 + ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item); 577 562 if (ret == -ENOENT) 578 563 return sprintf(name, "%u", id); 579 564 if (ret) ··· 582 565 ret = strlen(item->name); 583 566 BUG_ON(ret > IDMAP_NAMESZ); 584 567 memcpy(name, item->name, ret); 585 - cache_put(&item->h, &idtoname_cache); 568 + cache_put(&item->h, nn->idtoname_cache); 586 569 return ret; 587 570 } 588 571
+9 -4
fs/nfsd/nfs4state.c
··· 3155 3155 static struct lock_manager nfsd4_manager = { 3156 3156 }; 3157 3157 3158 + static bool grace_ended; 3159 + 3158 3160 static void 3159 3161 nfsd4_end_grace(void) 3160 3162 { 3163 + /* do nothing if grace period already ended */ 3164 + if (grace_ended) 3165 + return; 3166 + 3161 3167 dprintk("NFSD: end of grace period\n"); 3168 + grace_ended = true; 3162 3169 nfsd4_record_grace_done(&init_net, boot_time); 3163 3170 locks_end_grace(&nfsd4_manager); 3164 3171 /* ··· 3190 3183 nfs4_lock_state(); 3191 3184 3192 3185 dprintk("NFSD: laundromat service - starting\n"); 3193 - if (locks_in_grace()) 3194 - nfsd4_end_grace(); 3186 + nfsd4_end_grace(); 3195 3187 INIT_LIST_HEAD(&reaplist); 3196 3188 spin_lock(&client_lock); 3197 3189 list_for_each_safe(pos, next, &client_lru) { ··· 4061 4055 struct nfs4_openowner *open_sop = NULL; 4062 4056 struct nfs4_lockowner *lock_sop = NULL; 4063 4057 struct nfs4_ol_stateid *lock_stp; 4064 - struct nfs4_file *fp; 4065 4058 struct file *filp = NULL; 4066 4059 struct file_lock file_lock; 4067 4060 struct file_lock conflock; ··· 4128 4123 goto out; 4129 4124 } 4130 4125 lock_sop = lockowner(lock_stp->st_stateowner); 4131 - fp = lock_stp->st_file; 4132 4126 4133 4127 lkflg = setlkflg(lock->lk_type); 4134 4128 status = nfs4_check_openmode(lock_stp, lkflg); ··· 4719 4715 nfsd4_client_tracking_init(&init_net); 4720 4716 boot_time = get_seconds(); 4721 4717 locks_start_grace(&nfsd4_manager); 4718 + grace_ended = false; 4722 4719 printk(KERN_INFO "NFSD: starting %ld-second grace period\n", 4723 4720 nfsd4_grace); 4724 4721 ret = set_callback_cred();
+40 -15
fs/nfsd/nfsctl.c
··· 127 127 128 128 static int exports_open(struct inode *inode, struct file *file) 129 129 { 130 - return seq_open(file, &nfs_exports_op); 130 + int err; 131 + struct seq_file *seq; 132 + struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 133 + 134 + err = seq_open(file, &nfs_exports_op); 135 + if (err) 136 + return err; 137 + 138 + seq = file->private_data; 139 + seq->private = nn->svc_export_cache; 140 + return 0; 131 141 } 132 142 133 143 static const struct file_operations exports_operations = { ··· 355 345 if (!dom) 356 346 return -ENOMEM; 357 347 358 - len = exp_rootfh(dom, path, &fh, maxsize); 348 + len = exp_rootfh(&init_net, dom, path, &fh, maxsize); 359 349 auth_domain_put(dom); 360 350 if (len) 361 351 return len; ··· 1137 1127 #endif 1138 1128 1139 1129 int nfsd_net_id; 1130 + 1131 + static __net_init int nfsd_init_net(struct net *net) 1132 + { 1133 + int retval; 1134 + 1135 + retval = nfsd_export_init(net); 1136 + if (retval) 1137 + goto out_export_error; 1138 + retval = nfsd_idmap_init(net); 1139 + if (retval) 1140 + goto out_idmap_error; 1141 + return 0; 1142 + 1143 + out_idmap_error: 1144 + nfsd_export_shutdown(net); 1145 + out_export_error: 1146 + return retval; 1147 + } 1148 + 1149 + static __net_exit void nfsd_exit_net(struct net *net) 1150 + { 1151 + nfsd_idmap_shutdown(net); 1152 + nfsd_export_shutdown(net); 1153 + } 1154 + 1140 1155 static struct pernet_operations nfsd_net_ops = { 1156 + .init = nfsd_init_net, 1157 + .exit = nfsd_exit_net, 1141 1158 .id = &nfsd_net_id, 1142 1159 .size = sizeof(struct nfsd_net), 1143 1160 }; ··· 1191 1154 retval = nfsd_reply_cache_init(); 1192 1155 if (retval) 1193 1156 goto out_free_stat; 1194 - retval = nfsd_export_init(); 1195 - if (retval) 1196 - goto out_free_cache; 1197 1157 nfsd_lockd_init(); /* lockd->nfsd callbacks */ 1198 - retval = nfsd_idmap_init(); 1199 - if (retval) 1200 - goto out_free_lockd; 1201 1158 retval = create_proc_exports_entry(); 1202 1159 if (retval) 1203 - goto out_free_idmap; 1160 + goto out_free_lockd; 1204 1161 retval = register_filesystem(&nfsd_fs_type); 1205 1162 if (retval) 1206 1163 goto out_free_all; ··· 1202 1171 out_free_all: 1203 1172 remove_proc_entry("fs/nfs/exports", NULL); 1204 1173 remove_proc_entry("fs/nfs", NULL); 1205 - out_free_idmap: 1206 - nfsd_idmap_shutdown(); 1207 1174 out_free_lockd: 1208 1175 nfsd_lockd_shutdown(); 1209 - nfsd_export_shutdown(); 1210 - out_free_cache: 1211 1176 nfsd_reply_cache_shutdown(); 1212 1177 out_free_stat: 1213 1178 nfsd_stat_shutdown(); ··· 1219 1192 1220 1193 static void __exit exit_nfsd(void) 1221 1194 { 1222 - nfsd_export_shutdown(); 1223 1195 nfsd_reply_cache_shutdown(); 1224 1196 remove_proc_entry("fs/nfs/exports", NULL); 1225 1197 remove_proc_entry("fs/nfs", NULL); 1226 1198 nfsd_stat_shutdown(); 1227 1199 nfsd_lockd_shutdown(); 1228 - nfsd_idmap_shutdown(); 1229 1200 nfsd4_free_slabs(); 1230 1201 nfsd_fault_inject_cleanup(); 1231 1202 unregister_filesystem(&nfsd_fs_type);
+1 -1
fs/nfsd/nfsfh.c
··· 636 636 #endif 637 637 } 638 638 if (exp) { 639 - cache_put(&exp->h, &svc_export_cache); 639 + exp_put(exp); 640 640 fhp->fh_export = NULL; 641 641 } 642 642 return;
+4 -4
fs/nfsd/nfssvc.c
··· 220 220 ret = nfsd_init_socks(port); 221 221 if (ret) 222 222 goto out_racache; 223 - ret = lockd_up(); 223 + ret = lockd_up(&init_net); 224 224 if (ret) 225 225 goto out_racache; 226 226 ret = nfs4_state_start(); ··· 229 229 nfsd_up = true; 230 230 return 0; 231 231 out_lockd: 232 - lockd_down(); 232 + lockd_down(&init_net); 233 233 out_racache: 234 234 nfsd_racache_shutdown(); 235 235 return ret; ··· 246 246 if (!nfsd_up) 247 247 return; 248 248 nfs4_state_shutdown(); 249 - lockd_down(); 249 + lockd_down(&init_net); 250 250 nfsd_racache_shutdown(); 251 251 nfsd_up = false; 252 252 } ··· 261 261 262 262 printk(KERN_WARNING "nfsd: last server has exited, flushing export " 263 263 "cache\n"); 264 - nfsd_export_flush(); 264 + nfsd_export_flush(net); 265 265 } 266 266 267 267 void nfsd_reset_versions(void)
+1 -1
fs/nfsd/vfs.c
··· 2039 2039 if (err) 2040 2040 goto out; 2041 2041 2042 - offset = vfs_llseek(file, offset, 0); 2042 + offset = vfs_llseek(file, offset, SEEK_SET); 2043 2043 if (offset < 0) { 2044 2044 err = nfserrno((int)offset); 2045 2045 goto out_close;
+2 -2
include/linux/lockd/bind.h
··· 54 54 55 55 extern int nlmclnt_proc(struct nlm_host *host, int cmd, 56 56 struct file_lock *fl); 57 - extern int lockd_up(void); 58 - extern void lockd_down(void); 57 + extern int lockd_up(struct net *net); 58 + extern void lockd_down(struct net *net); 59 59 60 60 #endif /* LINUX_LOCKD_BIND_H */
+6 -7
include/linux/nfsd/export.h
··· 103 103 struct nfsd4_fs_locations ex_fslocs; 104 104 int ex_nflavors; 105 105 struct exp_flavor_info ex_flavors[MAX_SECINFO_LIST]; 106 + struct cache_detail *cd; 106 107 }; 107 108 108 109 /* an "export key" (expkey) maps a filehandlefragement to an ··· 130 129 /* 131 130 * Function declarations 132 131 */ 133 - int nfsd_export_init(void); 134 - void nfsd_export_shutdown(void); 135 - void nfsd_export_flush(void); 132 + int nfsd_export_init(struct net *); 133 + void nfsd_export_shutdown(struct net *); 134 + void nfsd_export_flush(struct net *); 136 135 struct svc_export * rqst_exp_get_by_name(struct svc_rqst *, 137 136 struct path *); 138 137 struct svc_export * rqst_exp_parent(struct svc_rqst *, 139 138 struct path *); 140 139 struct svc_export * rqst_find_fsidzero_export(struct svc_rqst *); 141 - int exp_rootfh(struct auth_domain *, 140 + int exp_rootfh(struct net *, struct auth_domain *, 142 141 char *path, struct knfsd_fh *, int maxsize); 143 142 __be32 exp_pseudoroot(struct svc_rqst *, struct svc_fh *); 144 143 __be32 nfserrno(int errno); 145 144 146 - extern struct cache_detail svc_export_cache; 147 - 148 145 static inline void exp_put(struct svc_export *exp) 149 146 { 150 - cache_put(&exp->h, &svc_export_cache); 147 + cache_put(&exp->h, exp->cd); 151 148 } 152 149 153 150 static inline void exp_get(struct svc_export *exp)
+1 -2
include/linux/sunrpc/svcauth.h
··· 16 16 #include <linux/sunrpc/cache.h> 17 17 #include <linux/hash.h> 18 18 19 - #define SVC_CRED_NGROUPS 32 20 19 struct svc_cred { 21 20 uid_t cr_uid; 22 21 gid_t cr_gid; ··· 130 131 extern struct auth_domain *auth_domain_find(char *name); 131 132 extern struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr); 132 133 extern int auth_unix_forget_old(struct auth_domain *dom); 133 - extern void svcauth_unix_purge(void); 134 + extern void svcauth_unix_purge(struct net *net); 134 135 extern void svcauth_unix_info_release(struct svc_xprt *xpt); 135 136 extern int svcauth_unix_set_client(struct svc_rqst *rqstp); 136 137
+69 -41
net/sunrpc/auth_gss/svcauth_gss.c
··· 969 969 } 970 970 971 971 static inline int 972 - gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, struct rsi *rsip) 972 + gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp, 973 + struct xdr_netobj *out_handle, int *major_status) 973 974 { 974 975 struct rsc *rsci; 975 976 int rc; 976 977 977 - if (rsip->major_status != GSS_S_COMPLETE) 978 + if (*major_status != GSS_S_COMPLETE) 978 979 return gss_write_null_verf(rqstp); 979 - rsci = gss_svc_searchbyctx(cd, &rsip->out_handle); 980 + rsci = gss_svc_searchbyctx(cd, out_handle); 980 981 if (rsci == NULL) { 981 - rsip->major_status = GSS_S_NO_CONTEXT; 982 + *major_status = GSS_S_NO_CONTEXT; 982 983 return gss_write_null_verf(rqstp); 983 984 } 984 985 rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN); 985 986 cache_put(&rsci->h, cd); 986 987 return rc; 988 + } 989 + 990 + static inline int 991 + gss_read_verf(struct rpc_gss_wire_cred *gc, 992 + struct kvec *argv, __be32 *authp, 993 + struct xdr_netobj *in_handle, 994 + struct xdr_netobj *in_token) 995 + { 996 + struct xdr_netobj tmpobj; 997 + 998 + /* Read the verifier; should be NULL: */ 999 + *authp = rpc_autherr_badverf; 1000 + if (argv->iov_len < 2 * 4) 1001 + return SVC_DENIED; 1002 + if (svc_getnl(argv) != RPC_AUTH_NULL) 1003 + return SVC_DENIED; 1004 + if (svc_getnl(argv) != 0) 1005 + return SVC_DENIED; 1006 + /* Martial context handle and token for upcall: */ 1007 + *authp = rpc_autherr_badcred; 1008 + if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) 1009 + return SVC_DENIED; 1010 + if (dup_netobj(in_handle, &gc->gc_ctx)) 1011 + return SVC_CLOSE; 1012 + *authp = rpc_autherr_badverf; 1013 + if (svc_safe_getnetobj(argv, &tmpobj)) { 1014 + kfree(in_handle->data); 1015 + return SVC_DENIED; 1016 + } 1017 + if (dup_netobj(in_token, &tmpobj)) { 1018 + kfree(in_handle->data); 1019 + return SVC_CLOSE; 1020 + } 1021 + 1022 + return 0; 1023 + } 1024 + 1025 + static inline int 1026 + gss_write_resv(struct kvec *resv, size_t size_limit, 1027 + struct xdr_netobj *out_handle, struct xdr_netobj *out_token, 1028 + int major_status, int minor_status) 1029 + { 1030 + if (resv->iov_len + 4 > size_limit) 1031 + return -1; 1032 + svc_putnl(resv, RPC_SUCCESS); 1033 + if (svc_safe_putnetobj(resv, out_handle)) 1034 + return -1; 1035 + if (resv->iov_len + 3 * 4 > size_limit) 1036 + return -1; 1037 + svc_putnl(resv, major_status); 1038 + svc_putnl(resv, minor_status); 1039 + svc_putnl(resv, GSS_SEQ_WIN); 1040 + if (svc_safe_putnetobj(resv, out_token)) 1041 + return -1; 1042 + return 0; 987 1043 } 988 1044 989 1045 /* ··· 1054 998 { 1055 999 struct kvec *argv = &rqstp->rq_arg.head[0]; 1056 1000 struct kvec *resv = &rqstp->rq_res.head[0]; 1057 - struct xdr_netobj tmpobj; 1058 1001 struct rsi *rsip, rsikey; 1059 1002 int ret; 1060 1003 struct sunrpc_net *sn = net_generic(rqstp->rq_xprt->xpt_net, sunrpc_net_id); 1061 1004 1062 - /* Read the verifier; should be NULL: */ 1063 - *authp = rpc_autherr_badverf; 1064 - if (argv->iov_len < 2 * 4) 1065 - return SVC_DENIED; 1066 - if (svc_getnl(argv) != RPC_AUTH_NULL) 1067 - return SVC_DENIED; 1068 - if (svc_getnl(argv) != 0) 1069 - return SVC_DENIED; 1070 - 1071 - /* Martial context handle and token for upcall: */ 1072 - *authp = rpc_autherr_badcred; 1073 - if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) 1074 - return SVC_DENIED; 1075 1005 memset(&rsikey, 0, sizeof(rsikey)); 1076 - if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx)) 1077 - return SVC_CLOSE; 1078 - *authp = rpc_autherr_badverf; 1079 - if (svc_safe_getnetobj(argv, &tmpobj)) { 1080 - kfree(rsikey.in_handle.data); 1081 - return SVC_DENIED; 1082 - } 1083 - if (dup_netobj(&rsikey.in_token, &tmpobj)) { 1084 - kfree(rsikey.in_handle.data); 1085 - return SVC_CLOSE; 1086 - } 1006 + ret = gss_read_verf(gc, argv, authp, 1007 + &rsikey.in_handle, &rsikey.in_token); 1008 + if (ret) 1009 + return ret; 1087 1010 1088 1011 /* Perform upcall, or find upcall result: */ 1089 1012 rsip = rsi_lookup(sn->rsi_cache, &rsikey); ··· 1075 1040 1076 1041 ret = SVC_CLOSE; 1077 1042 /* Got an answer to the upcall; use it: */ 1078 - if (gss_write_init_verf(sn->rsc_cache, rqstp, rsip)) 1043 + if (gss_write_init_verf(sn->rsc_cache, rqstp, 1044 + &rsip->out_handle, &rsip->major_status)) 1079 1045 goto out; 1080 - if (resv->iov_len + 4 > PAGE_SIZE) 1081 - goto out; 1082 - svc_putnl(resv, RPC_SUCCESS); 1083 - if (svc_safe_putnetobj(resv, &rsip->out_handle)) 1084 - goto out; 1085 - if (resv->iov_len + 3 * 4 > PAGE_SIZE) 1086 - goto out; 1087 - svc_putnl(resv, rsip->major_status); 1088 - svc_putnl(resv, rsip->minor_status); 1089 - svc_putnl(resv, GSS_SEQ_WIN); 1090 - if (svc_safe_putnetobj(resv, &rsip->out_token)) 1046 + if (gss_write_resv(resv, PAGE_SIZE, 1047 + &rsip->out_handle, &rsip->out_token, 1048 + rsip->major_status, rsip->minor_status)) 1091 1049 goto out; 1092 1050 1093 1051 ret = SVC_COMPLETE;
+4 -9
net/sunrpc/svcauth_unix.c
··· 347 347 return __ip_map_update(sn->ip_map_cache, ipm, udom, expiry); 348 348 } 349 349 350 - 351 - void svcauth_unix_purge(void) 350 + void svcauth_unix_purge(struct net *net) 352 351 { 353 - struct net *net; 352 + struct sunrpc_net *sn; 354 353 355 - for_each_net(net) { 356 - struct sunrpc_net *sn; 357 - 358 - sn = net_generic(net, sunrpc_net_id); 359 - cache_purge(sn->ip_map_cache); 360 - } 354 + sn = net_generic(net, sunrpc_net_id); 355 + cache_purge(sn->ip_map_cache); 361 356 } 362 357 EXPORT_SYMBOL_GPL(svcauth_unix_purge); 363 358