aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-03-27 04:15:00 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-27 11:44:41 -0500
commiteab7e2e647c348b418e8715ecaca0177e1b473c7 (patch)
tree91aa453d6313eee89c8b19eea48699b1143264aa
parentefc36aa5608f5717338747e152c23f2cfdb14697 (diff)
[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>
-rw-r--r--fs/nfsd/export.c60
-rw-r--r--include/linux/nfsd/export.h20
2 files changed, 44 insertions, 36 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index ac0997731fce..587829ed651c 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -73,8 +73,10 @@ void expkey_put(struct cache_head *item, struct cache_detail *cd)
73 if (cache_put(item, cd)) { 73 if (cache_put(item, cd)) {
74 struct svc_expkey *key = container_of(item, struct svc_expkey, h); 74 struct svc_expkey *key = container_of(item, struct svc_expkey, h);
75 if (test_bit(CACHE_VALID, &item->flags) && 75 if (test_bit(CACHE_VALID, &item->flags) &&
76 !test_bit(CACHE_NEGATIVE, &item->flags)) 76 !test_bit(CACHE_NEGATIVE, &item->flags)) {
77 exp_put(key->ek_export); 77 dput(key->ek_dentry);
78 mntput(key->ek_mnt);
79 }
78 auth_domain_put(key->ek_client); 80 auth_domain_put(key->ek_client);
79 kfree(key); 81 kfree(key);
80 } 82 }
@@ -164,26 +166,18 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
164 } else { 166 } else {
165 struct nameidata nd; 167 struct nameidata nd;
166 struct svc_expkey *ek; 168 struct svc_expkey *ek;
167 struct svc_export *exp;
168 err = path_lookup(buf, 0, &nd); 169 err = path_lookup(buf, 0, &nd);
169 if (err) 170 if (err)
170 goto out; 171 goto out;
171 172
172 dprintk("Found the path %s\n", buf); 173 dprintk("Found the path %s\n", buf);
173 exp = exp_get_by_name(dom, nd.mnt, nd.dentry, NULL); 174 key.ek_mnt = nd.mnt;
174 175 key.ek_dentry = nd.dentry;
175 err = -ENOENT;
176 if (!exp)
177 goto out_nd;
178 key.ek_export = exp;
179 dprintk("And found export\n");
180 176
181 ek = svc_expkey_lookup(&key, 1); 177 ek = svc_expkey_lookup(&key, 1);
182 if (ek) 178 if (ek)
183 expkey_put(&ek->h, &svc_expkey_cache); 179 expkey_put(&ek->h, &svc_expkey_cache);
184 exp_put(exp);
185 err = 0; 180 err = 0;
186 out_nd:
187 path_release(&nd); 181 path_release(&nd);
188 } 182 }
189 cache_flush(); 183 cache_flush();
@@ -214,7 +208,7 @@ static int expkey_show(struct seq_file *m,
214 if (test_bit(CACHE_VALID, &h->flags) && 208 if (test_bit(CACHE_VALID, &h->flags) &&
215 !test_bit(CACHE_NEGATIVE, &h->flags)) { 209 !test_bit(CACHE_NEGATIVE, &h->flags)) {
216 seq_printf(m, " "); 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 seq_printf(m, "\n"); 213 seq_printf(m, "\n");
220 return 0; 214 return 0;
@@ -252,8 +246,8 @@ static inline void svc_expkey_init(struct svc_expkey *new, struct svc_expkey *it
252 246
253static inline void svc_expkey_update(struct svc_expkey *new, struct svc_expkey *item) 247static inline void svc_expkey_update(struct svc_expkey *new, struct svc_expkey *item)
254{ 248{
255 cache_get(&item->ek_export->h); 249 new->ek_mnt = mntget(item->ek_mnt);
256 new->ek_export = item->ek_export; 250 new->ek_dentry = dget(item->ek_dentry);
257} 251}
258 252
259static DefineSimpleCacheLookup(svc_expkey,0) /* no inplace updates */ 253static DefineSimpleCacheLookup(svc_expkey,0) /* no inplace updates */
@@ -519,7 +513,8 @@ static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
519 key.ek_client = clp; 513 key.ek_client = clp;
520 key.ek_fsidtype = fsid_type; 514 key.ek_fsidtype = fsid_type;
521 memcpy(key.ek_fsid, fsidv, key_len(fsid_type)); 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 key.h.expiry_time = NEVER; 518 key.h.expiry_time = NEVER;
524 key.h.flags = 0; 519 key.h.flags = 0;
525 520
@@ -741,8 +736,8 @@ exp_export(struct nfsctl_export *nxp)
741 if ((nxp->ex_flags & NFSEXP_FSID) && 736 if ((nxp->ex_flags & NFSEXP_FSID) &&
742 (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) && 737 (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
743 !IS_ERR(fsid_key) && 738 !IS_ERR(fsid_key) &&
744 fsid_key->ek_export && 739 fsid_key->ek_mnt &&
745 fsid_key->ek_export != exp) 740 (fsid_key->ek_mnt != nd.mnt || fsid_key->ek_dentry != nd.dentry) )
746 goto finish; 741 goto finish;
747 742
748 if (exp) { 743 if (exp) {
@@ -912,6 +907,24 @@ out:
912 return err; 907 return err;
913} 908}
914 909
910struct svc_export *
911exp_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 * Called when we need the filehandle for the root of the pseudofs, 929 * Called when we need the filehandle for the root of the pseudofs,
917 * for a given NFSv4 client. The root is defined to be the 930 * for a given NFSv4 client. The root is defined to be the
@@ -922,6 +935,7 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
922 struct cache_req *creq) 935 struct cache_req *creq)
923{ 936{
924 struct svc_expkey *fsid_key; 937 struct svc_expkey *fsid_key;
938 struct svc_export *exp;
925 int rv; 939 int rv;
926 u32 fsidv[2]; 940 u32 fsidv[2];
927 941
@@ -933,8 +947,14 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp,
933 if (!fsid_key || IS_ERR(fsid_key)) 947 if (!fsid_key || IS_ERR(fsid_key))
934 return nfserr_perm; 948 return nfserr_perm;
935 949
936 rv = fh_compose(fhp, fsid_key->ek_export, 950 exp = exp_get_by_name(clp, fsid_key->ek_mnt, fsid_key->ek_dentry, creq);
937 fsid_key->ek_export->ex_dentry, NULL); 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 expkey_put(&fsid_key->h, &svc_expkey_cache); 958 expkey_put(&fsid_key->h, &svc_expkey_cache);
939 return rv; 959 return rv;
940} 960}
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index 6bad4766d3d9..d52e0b7ad37b 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -67,7 +67,8 @@ struct svc_expkey {
67 int ek_fsidtype; 67 int ek_fsidtype;
68 u32 ek_fsid[3]; 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#define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT)) 74#define EX_SECURE(exp) (!((exp)->ex_flags & NFSEXP_INSECURE_PORT))
@@ -114,22 +115,9 @@ static inline void exp_get(struct svc_export *exp)
114{ 115{
115 cache_get(&exp->h); 116 cache_get(&exp->h);
116} 117}
117static inline struct svc_export * 118extern struct svc_export *
118exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv, 119exp_find(struct auth_domain *clp, int fsid_type, u32 *fsidv,
119 struct cache_req *reqp) 120 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}
133 121
134#endif /* __KERNEL__ */ 122#endif /* __KERNEL__ */
135 123