diff options
| author | Neil Brown <neilb@cse.unsw.edu.au> | 2002-09-12 01:42:25 -0700 |
|---|---|---|
| committer | David S. Miller <davem@nuts.ninka.net> | 2002-09-12 01:42:25 -0700 |
| commit | 37dbeea3430745f4c062e8681f594bae33f7be73 (patch) | |
| tree | 45e3edb62cd1e1335fa9ea9cd65effcb85379422 | |
| parent | 0414681697d939f8853ce12c804f12834a2bc6c1 (diff) | |
[PATCH] kNFSd 12: Change exp_parent to talk directory tree, not hash table.
Currently get_parent (needed to find the exportpoint
above a given dentry) walks the hash table of export points
checking each with is_subdir. Now it walks up the d_parent
link checking each for membership in the hashtable.
nfsd_lookup currently does that walk too (when crossing
a mountpoint backwards) so the code gets unified.
This approach makes more sense as we move towards a cache
for export information that can be filled on demand.
It also assumes less about the hash table (which will change).
| -rw-r--r-- | fs/nfsd/export.c | 29 | ||||
| -rw-r--r-- | fs/nfsd/vfs.c | 16 | ||||
| -rw-r--r-- | include/linux/nfsd/export.h | 2 |
3 files changed, 22 insertions, 25 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 79fbbf3fd1bc..4e4bcce160b0 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -35,8 +35,6 @@ typedef struct svc_client svc_client; typedef struct svc_export svc_export; -static svc_export * exp_parent(svc_client *clp, struct super_block *sb, - struct dentry *dentry); static void exp_unexport_all(svc_client *clp); static void exp_do_unexport(svc_export *unexp); static svc_client * exp_getclientbyname(char *name); @@ -124,24 +122,21 @@ exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry) } /* - * Find the export entry for a given dentry. <gam3@acm.org> + * Find the export entry for a given dentry. */ -static svc_export * -exp_parent(svc_client *clp, struct super_block *sb, struct dentry *dentry) +struct svc_export * +exp_parent(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry) { - struct list_head *head = &clp->cl_export[EXPORT_HASH(sb->s_dev)]; - struct list_head *p; + svc_export *exp; - spin_lock(&dcache_lock); - list_for_each(p, head) { - svc_export *exp = list_entry(p, svc_export, ex_hash); - if (is_subdir(dentry, exp->ex_dentry)) { - spin_unlock(&dcache_lock); - return exp; - } + read_lock(&dparent_lock); + exp = exp_get_by_name(clp, mnt, dentry); + while (exp == NULL && dentry != dentry->d_parent) { + dentry = dentry->d_parent; + exp = exp_get_by_name(clp, mnt, dentry); } - spin_unlock(&dcache_lock); - return NULL; + read_unlock(&dparent_lock); + return exp; } /* @@ -415,7 +410,7 @@ exp_rootfh(struct svc_client *clp, char *path, struct knfsd_fh *f, int maxsize) dprintk("nfsd: exp_rootfh(%s [%p] %s:%s/%ld)\n", path, nd.dentry, clp->cl_ident, inode->i_sb->s_id, inode->i_ino); - exp = exp_parent(clp, inode->i_sb, nd.dentry); + exp = exp_parent(clp, nd.mnt, nd.dentry); if (!exp) { dprintk("nfsd: exp_rootfh export not found.\n"); goto out; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 219c03bc8eed..61c7bd03d3f0 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -119,24 +119,24 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, else { /* checking mountpoint crossing is very different when stepping up */ struct svc_export *exp2 = NULL; - struct dentry *dp, *old; + struct dentry *dp; struct vfsmount *mnt = mntget(exp->ex_mnt); dentry = dget(dparent); while(follow_up(&mnt, &dentry)) ; - old = dentry; read_lock(&dparent_lock); - dp = dentry->d_parent; - for ( ; !exp2 && dp->d_parent != dp; dp=dp->d_parent) - exp2 = exp_get_by_name(exp->ex_client, mnt, dp); + dp = dget(dentry->d_parent); + read_unlock(&dparent_lock); + dput(dentry); + dentry = dp; + + exp2 = exp_parent(exp->ex_client, mnt, dentry); if (!exp2) { + dput(dentry); dentry = dget(dparent); } else { - dget(dentry->d_parent); exp = exp2; } - read_unlock(&dparent_lock); - dput(old); mntput(mnt); } } else { diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h index 4b3f7b1bfd74..d3bd2a796716 100644 --- a/include/linux/nfsd/export.h +++ b/include/linux/nfsd/export.h @@ -91,6 +91,8 @@ struct svc_export * exp_get_fsid(struct svc_client *clp, int fsid); struct svc_export * exp_get_by_name(struct svc_client *clp, struct vfsmount *mnt, struct dentry *dentry); +struct svc_export * exp_parent(struct svc_client *clp, struct vfsmount *mnt, + struct dentry *dentry); int exp_rootfh(struct svc_client *, char *path, struct knfsd_fh *, int maxsize); int nfserrno(int errno); |
