]> git.hungrycats.org Git - linux/commitdiff
[PATCH] kNFSd 12: Change exp_parent to talk directory tree, not hash table.
authorNeil Brown <neilb@cse.unsw.edu.au>
Thu, 12 Sep 2002 08:42:25 +0000 (01:42 -0700)
committerDavid S. Miller <davem@nuts.ninka.net>
Thu, 12 Sep 2002 08:42:25 +0000 (01:42 -0700)
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).

fs/nfsd/export.c
fs/nfsd/vfs.c
include/linux/nfsd/export.h

index 79fbbf3fd1bcf322462ee26261e55e63365b18e3..4e4bcce160b0c55e284d152e31ef0c9b5244efe1 100644 (file)
@@ -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;
index 219c03bc8eed8972d301cd1e529e7a06c496c430..61c7bd03d3f0e5ad02a56360b2c54ac164fd848a 100644 (file)
@@ -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 {
index 4b3f7b1bfd746d8a90a3e070cfe4a276e5d5cff5..d3bd2a796716f2d8f8341db83133df1940d6fe0c 100644 (file)
@@ -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);