From 3212b58cde7b4451ecc2f75f635d4760e19d4c70 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Sat, 26 Sep 2009 20:32:24 -0400 Subject: [PATCH] --- yaml --- r: 177171 b: refs/heads/master c: 289ede453e5a621de19c61e630302b1845cc1d59 h: refs/heads/master i: 177169: 88fb0f12b4b845355d452211dc7b84886f85ab13 177167: 894361259ea51eef86b27d7f4bc574b286f340cf v: v3 --- [refs] | 2 +- trunk/fs/nfsd/vfs.c | 60 +++++++++++++++++++++++++++------------------ 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/[refs] b/[refs] index d7a898a1e17f..a1f3f5203704 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: fed83811269d0f559d2da9139e12c5e5d9874d5c +refs/heads/master: 289ede453e5a621de19c61e630302b1845cc1d59 diff --git a/trunk/fs/nfsd/vfs.c b/trunk/fs/nfsd/vfs.c index b8ed58bab8b1..638573968dcf 100644 --- a/trunk/fs/nfsd/vfs.c +++ b/trunk/fs/nfsd/vfs.c @@ -141,6 +141,40 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, return err; } +static void follow_to_parent(struct path *path) +{ + struct dentry *dp; + + while (path->dentry == path->mnt->mnt_root && follow_up(path)) + ; + dp = dget_parent(path->dentry); + dput(path->dentry); + path->dentry = dp; +} + +static int nfsd_lookup_parent(struct svc_rqst *rqstp, struct dentry *dparent, struct svc_export **exp, struct dentry **dentryp) +{ + struct svc_export *exp2; + struct path path = {.mnt = mntget((*exp)->ex_path.mnt), + .dentry = dget(dparent)}; + + follow_to_parent(&path); + + exp2 = rqst_exp_parent(rqstp, &path); + if (PTR_ERR(exp2) == -ENOENT) { + *dentryp = dget(dparent); + } else if (IS_ERR(exp2)) { + path_put(&path); + return PTR_ERR(exp2); + } else { + *dentryp = dget(path.dentry); + exp_put(*exp); + *exp = exp2; + } + path_put(&path); + return 0; +} + __be32 nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name, unsigned int len, @@ -173,31 +207,9 @@ nfsd_lookup_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp, dentry = dget(dparent); /* .. == . just like at / */ else { /* checking mountpoint crossing is very different when stepping up */ - struct svc_export *exp2 = NULL; - struct dentry *dp; - struct path path = {.mnt = mntget(exp->ex_path.mnt), - .dentry = dget(dparent)}; - - while (path.dentry == path.mnt->mnt_root && - follow_up(&path)) - ; - dp = dget_parent(path.dentry); - dput(path.dentry); - path.dentry = dp; - - exp2 = rqst_exp_parent(rqstp, &path); - if (PTR_ERR(exp2) == -ENOENT) { - dentry = dget(dparent); - } else if (IS_ERR(exp2)) { - host_err = PTR_ERR(exp2); - path_put(&path); + host_err = nfsd_lookup_parent(rqstp, dparent, &exp, &dentry); + if (host_err) goto out_nfserr; - } else { - dentry = dget(path.dentry); - exp_put(exp); - exp = exp2; - } - path_put(&path); } } else { fh_lock(fhp);