summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeil Brown <neilb@cse.unsw.edu.au>2002-09-12 01:42:25 -0700
committerDavid S. Miller <davem@nuts.ninka.net>2002-09-12 01:42:25 -0700
commit37dbeea3430745f4c062e8681f594bae33f7be73 (patch)
tree45e3edb62cd1e1335fa9ea9cd65effcb85379422
parent0414681697d939f8853ce12c804f12834a2bc6c1 (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.c29
-rw-r--r--fs/nfsd/vfs.c16
-rw-r--r--include/linux/nfsd/export.h2
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);