Commit eab7e2e647c348b418e8715ecaca0177e1b473c7

Authored by NeilBrown
Committed by Linus Torvalds
1 parent efc36aa560

[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

... ... @@ -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