|
@@ -94,6 +94,12 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
|
|
err = follow_down(&path);
|
|
err = follow_down(&path);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
goto out;
|
|
goto out;
|
|
|
|
+ if (path.mnt == exp->ex_path.mnt && path.dentry == dentry &&
|
|
|
|
+ nfsd_mountpoint(dentry, exp) == 2) {
|
|
|
|
+ /* This is only a mountpoint in some other namespace */
|
|
|
|
+ path_put(&path);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
|
|
exp2 = rqst_exp_get_by_name(rqstp, &path);
|
|
exp2 = rqst_exp_get_by_name(rqstp, &path);
|
|
if (IS_ERR(exp2)) {
|
|
if (IS_ERR(exp2)) {
|
|
@@ -167,16 +173,26 @@ static int nfsd_lookup_parent(struct svc_rqst *rqstp, struct dentry *dparent, st
|
|
/*
|
|
/*
|
|
* For nfsd purposes, we treat V4ROOT exports as though there was an
|
|
* For nfsd purposes, we treat V4ROOT exports as though there was an
|
|
* export at *every* directory.
|
|
* export at *every* directory.
|
|
|
|
+ * We return:
|
|
|
|
+ * '1' if this dentry *must* be an export point,
|
|
|
|
+ * '2' if it might be, if there is really a mount here, and
|
|
|
|
+ * '0' if there is no chance of an export point here.
|
|
*/
|
|
*/
|
|
int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp)
|
|
int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp)
|
|
{
|
|
{
|
|
- if (d_mountpoint(dentry))
|
|
|
|
|
|
+ if (!d_inode(dentry))
|
|
|
|
+ return 0;
|
|
|
|
+ if (exp->ex_flags & NFSEXP_V4ROOT)
|
|
return 1;
|
|
return 1;
|
|
if (nfsd4_is_junction(dentry))
|
|
if (nfsd4_is_junction(dentry))
|
|
return 1;
|
|
return 1;
|
|
- if (!(exp->ex_flags & NFSEXP_V4ROOT))
|
|
|
|
- return 0;
|
|
|
|
- return d_inode(dentry) != NULL;
|
|
|
|
|
|
+ if (d_mountpoint(dentry))
|
|
|
|
+ /*
|
|
|
|
+ * Might only be a mountpoint in a different namespace,
|
|
|
|
+ * but we need to check.
|
|
|
|
+ */
|
|
|
|
+ return 2;
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
__be32
|
|
__be32
|