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);
}
/*
- * 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;
}
/*
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;
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 {
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);