Commit eab7e2e647c348b418e8715ecaca0177e1b473c7
Committed by
Linus Torvalds
1 parent
efc36aa560
Exists in
master
and in
4 other branches
[PATCH] knfsd: Break the hard linkage from svc_expkey to svc_export
Current svc_expkey holds a pointer to the svc_export structure, so updates to that structure have to be in-place, which is a wart on the whole cache infrastruct. So we break that linkage and just do a second lookup. If this became a performance issue, it would be possible to put a direct link back in which was only used conditionally. i.e. when an object is replaced in the cache, we set a flag in the old object. When dereferencing the link from svc_expkey, if the flag is set, we drop the reference and do a fresh lookup. Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 2 changed files with 44 additions and 36 deletions Side-by-side Diff
fs/nfsd/export.c
... | ... | @@ -73,8 +73,10 @@ |
73 | 73 | if (cache_put(item, cd)) { |
74 | 74 | struct svc_expkey *key = container_of(item, struct svc_expkey, h); |
75 | 75 | if (test_bit(CACHE_VALID, &item->flags) && |
76 | - !test_bit(CACHE_NEGATIVE, &item->flags)) | |
77 | - exp_put(key->ek_export); | |
76 | + !test_bit(CACHE_NEGATIVE, &item->flags)) { | |
77 | + dput(key->ek_dentry); | |
78 | + mntput(key->ek_mnt); | |
79 | + } | |
78 | 80 | auth_domain_put(key->ek_client); |
79 | 81 | kfree(key); |
80 | 82 | } |
81 | 83 | |
82 | 84 | |
83 | 85 | |
... | ... | @@ -164,26 +166,18 @@ |
164 | 166 | } else { |
165 | 167 | struct nameidata nd; |
166 | 168 | struct svc_expkey *ek; |
167 | - struct svc_export *exp; | |
168 | 169 | err = path_lookup(buf, 0, &nd); |
169 | 170 | if (err) |
170 | 171 | goto out; |
171 | 172 | |
172 | 173 | dprintk("Found the path %s\n", buf); |
173 | - exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL); | |
174 | - | |
175 | - err = -ENOENT; | |
176 | - if (!exp) | |
177 | - goto out_nd; | |
178 | - key.ek_export = exp; | |
179 | - dprintk("And found export\n"); | |
174 | + key.ek_mnt = nd.mnt; | |
175 | + key.ek_dentry = nd.dentry; | |
180 | 176 | |
181 | 177 | ek = svc_expkey_lookup(&key, 1); |
182 | 178 | if (ek) |
183 | 179 | expkey_put(&ek->h, &svc_expkey_cache); |
184 | - exp_put(exp); | |
185 | 180 | err = 0; |
186 | - out_nd: | |
187 | 181 | path_release(&nd); |
188 | 182 | } |
189 | 183 | cache_flush(); |
... | ... | @@ -214,7 +208,7 @@ |
214 | 208 | if (test_bit(CACHE_VALID, &h->flags) && |
215 | 209 | !test_bit(CACHE_NEGATIVE, &h->flags)) { |
216 | 210 | seq_printf(m, " "); |
217 | - seq_path(m, ek->ek_export->ex_mnt, ek->ek_export->ex_dentry, "\ \t\n"); | |
211 | + seq_path(m, ek->ek_mnt, ek->ek_dentry, "\ \t\n"); | |
218 | 212 | } |
219 | 213 | seq_printf(m, "\n"); |
220 | 214 | return 0; |
... | ... | @@ -252,8 +246,8 @@ |
252 | 246 | |
253 | 247 | static inline void svc_expkey_update(struct svc_expkey *new, struct svc_expkey *item) |
254 | 248 | { |
255 | - cache_get(&item->ek_export->h); | |
256 | - new->ek_export = item->ek_export; | |
249 | + new->ek_mnt = mntget(item->ek_mnt); | |
250 | + new->ek_dentry = dget(item->ek_dentry); | |
257 | 251 | } |
258 | 252 | |
259 | 253 | static DefineSimpleCacheLookup(svc_expkey,0) /* no inplace updates */ |
... | ... | @@ -519,7 +513,8 @@ |
519 | 513 | key.ek_client = clp; |
520 | 514 | key.ek_fsidtype = fsid_type; |
521 | 515 | memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); |
522 | - key.ek_export = exp; | |
516 | + key.ek_mnt = exp->ex_mnt; | |
517 | + key.ek_dentry = exp->ex_dentry; | |
523 | 518 | key.h.expiry_time = NEVER; |
524 | 519 | key.h.flags = 0; |
525 | 520 | |
... | ... | @@ -741,8 +736,8 @@ |
741 | 736 | if ((nxp->ex_flags & NFSEXP_FSID) && |
742 | 737 | (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) && |
743 | 738 | !IS_ERR(fsid_key) && |
744 | - fsid_key->ek_export && | |
745 | - fsid_key->ek_export != exp) | |
739 | + fsid_key->ek_mnt && | |
740 | + (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) ) | |
746 | 741 | goto finish; |
747 | 742 | |
748 | 743 | if (exp) { |
... | ... | @@ -912,6 +907,24 @@ |
912 | 907 | return err; |
913 | 908 | } |
914 | 909 | |
910 | +struct svc_export * | |
911 | +exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, | |
912 | + struct cache_req *reqp) | |
913 | +{ | |
914 | + struct svc_export *exp; | |
915 | + struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp); | |
916 | + if (!ek || IS_ERR(ek)) | |
917 | + return ERR_PTR(PTR_ERR(ek)); | |
918 | + | |
919 | + exp = exp_get_by_name(clp, ek->ek_mnt, ek->ek_dentry, reqp); | |
920 | + expkey_put(&ek->h, &svc_expkey_cache); | |
921 | + | |
922 | + if (!exp || IS_ERR(exp)) | |
923 | + return ERR_PTR(PTR_ERR(exp)); | |
924 | + return exp; | |
925 | +} | |
926 | + | |
927 | + | |
915 | 928 | /* |
916 | 929 | * Called when we need the filehandle for the root of the pseudofs, |
917 | 930 | * for a given NFSv4 client. The root is defined to be the |
... | ... | @@ -922,6 +935,7 @@ |
922 | 935 | struct cache_req *creq) |
923 | 936 | { |
924 | 937 | struct svc_expkey *fsid_key; |
938 | + struct svc_export *exp; | |
925 | 939 | int rv; |
926 | 940 | u32 fsidv[2]; |
927 | 941 | |
... | ... | @@ -933,8 +947,14 @@ |
933 | 947 | if (!fsid_key || IS_ERR(fsid_key)) |
934 | 948 | return nfserr_perm; |
935 | 949 | |
936 | - rv = fh_compose(fhp, fsid_key->ek_export, | |
937 | - fsid_key->ek_export->ex_dentry, NULL); | |
950 | + exp = exp_get_by_name(clp, fsid_key->ek_mnt, fsid_key->ek_dentry, creq); | |
951 | + if (exp == NULL) | |
952 | + rv = nfserr_perm; | |
953 | + else if (IS_ERR(exp)) | |
954 | + rv = nfserrno(PTR_ERR(exp)); | |
955 | + else | |
956 | + rv = fh_compose(fhp, exp, | |
957 | + fsid_key->ek_dentry, NULL); | |
938 | 958 | expkey_put(&fsid_key->h, &svc_expkey_cache); |
939 | 959 | return rv; |
940 | 960 | } |
include/linux/nfsd/export.h
... | ... | @@ -67,7 +67,8 @@ |
67 | 67 | int ek_fsidtype; |
68 | 68 | u32 ek_fsid[3]; |
69 | 69 | |
70 | - struct svc_export * ek_export; | |
70 | + struct vfsmount * ek_mnt; | |
71 | + struct dentry * ek_dentry; | |
71 | 72 | }; |
72 | 73 | |
73 | 74 | #define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT)) |
74 | 75 | |
... | ... | @@ -114,22 +115,9 @@ |
114 | 115 | { |
115 | 116 | cache_get(&exp->h); |
116 | 117 | } |
117 | -static inline struct svc_export * | |
118 | +extern struct svc_export * | |
118 | 119 | exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, |
119 | - struct cache_req *reqp) | |
120 | -{ | |
121 | - struct svc_expkey *ek = exp_find_key(clp, fsid_type, fsidv, reqp); | |
122 | - if (ek && !IS_ERR(ek)) { | |
123 | - struct svc_export *exp = ek->ek_export; | |
124 | - int err; | |
125 | - exp_get(exp); | |
126 | - expkey_put(&ek->h, &svc_expkey_cache); | |
127 | - if ((err = cache_check(&svc_export_cache, &exp->h, reqp))) | |
128 | - exp = ERR_PTR(err); | |
129 | - return exp; | |
130 | - } else | |
131 | - return ERR_PTR(PTR_ERR(ek)); | |
132 | -} | |
120 | + struct cache_req *reqp); | |
133 | 121 | |
134 | 122 | #endif /* __KERNEL__ */ |
135 | 123 |