* [PATCH 09/11] nfsd: Allow filehandle lookup to cross internal mount points.
2021-07-27 22:37 [PATCH/RFC 00/11] expose btrfs subvols in mount table correctly NeilBrown
@ 2021-07-27 22:37 ` NeilBrown
2021-07-28 19:15 ` J. Bruce Fields
2021-07-30 0:42 ` Al Viro
0 siblings, 2 replies; 6+ messages in thread
From: NeilBrown @ 2021-07-27 22:37 UTC (permalink / raw
To: Christoph Hellwig, Josef Bacik, J. Bruce Fields, Chuck Lever,
Chris Mason, David Sterba, Alexander Viro
Cc: linux-fsdevel, linux-nfs, linux-btrfs
Enhance nfsd to detect internal mounts and to cross them without
requiring a new export.
Also ensure the fsid reported is different for different submounts. We
do this by xoring in the ino of the mounted-on directory. This makes
sense for btrfs at least.
Signed-off-by: NeilBrown <neilb@suse.de>
---
fs/nfsd/nfs3xdr.c | 28 +++++++++++++++++++++-------
fs/nfsd/nfs4xdr.c | 34 +++++++++++++++++++++++-----------
fs/nfsd/nfsfh.c | 7 ++++++-
fs/nfsd/vfs.c | 11 +++++++++--
4 files changed, 59 insertions(+), 21 deletions(-)
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 67af0c5c1543..80b1cc0334fa 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -370,6 +370,8 @@ svcxdr_encode_fattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
case FSIDSOURCE_UUID:
fsid = ((u64 *)fhp->fh_export->ex_uuid)[0];
fsid ^= ((u64 *)fhp->fh_export->ex_uuid)[1];
+ if (fhp->fh_mnt != fhp->fh_export->ex_path.mnt)
+ fsid ^= nfsd_get_mounted_on(fhp->fh_mnt);
break;
default:
fsid = (u64)huge_encode_dev(fhp->fh_dentry->d_sb->s_dev);
@@ -1094,8 +1096,8 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
__be32 rv = nfserr_noent;
dparent = cd->fh.fh_dentry;
- exp = cd->fh.fh_export;
- child.mnt = cd->fh.fh_mnt;
+ exp = exp_get(cd->fh.fh_export);
+ child.mnt = mntget(cd->fh.fh_mnt);
if (isdotent(name, namlen)) {
if (namlen == 2) {
@@ -1112,15 +1114,27 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
child.dentry = dget(dparent);
} else
child.dentry = lookup_positive_unlocked(name, dparent, namlen);
- if (IS_ERR(child.dentry))
+ if (IS_ERR(child.dentry)) {
+ mntput(child.mnt);
+ exp_put(exp);
return rv;
- if (d_mountpoint(child.dentry))
- goto out;
- if (child.dentry->d_inode->i_ino != ino)
+ }
+ /* If child is a mountpoint, then we want to expose the fact
+ * so client can create a mountpoint. If not, then a different
+ * ino number probably means a race with rename, so avoid providing
+ * too much detail.
+ */
+ if (nfsd_mountpoint(child.dentry, exp)) {
+ int err;
+ err = nfsd_cross_mnt(cd->rqstp, &child, &exp);
+ if (err)
+ goto out;
+ } else if (child.dentry->d_inode->i_ino != ino)
goto out;
rv = fh_compose(fhp, exp, &child, &cd->fh);
out:
- dput(child.dentry);
+ path_put(&child);
+ exp_put(exp);
return rv;
}
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index d5683b6a74b2..4dbc99ed2c8b 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2817,6 +2817,8 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
struct kstat stat;
struct svc_fh *tempfh = NULL;
struct kstatfs statfs;
+ u64 mounted_on_ino;
+ u64 sub_fsid;
__be32 *p;
int starting_len = xdr->buf->len;
int attrlen_offset;
@@ -2871,6 +2873,24 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
goto out;
fhp = tempfh;
}
+ if ((bmval0 & FATTR4_WORD0_FSID) ||
+ (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID)) {
+ mounted_on_ino = stat.ino;
+ sub_fsid = 0;
+ /*
+ * The inode number that the current mnt is mounted on is
+ * used for MOUNTED_ON_FILED if we are at the root,
+ * and for sub_fsid if mnt is not the export mnt.
+ */
+ if (ignore_crossmnt == 0) {
+ u64 moi = nfsd_get_mounted_on(mnt);
+
+ if (dentry == mnt->mnt_root && moi)
+ mounted_on_ino = moi;
+ if (mnt != exp->ex_path.mnt)
+ sub_fsid = moi;
+ }
+ }
if (bmval0 & FATTR4_WORD0_ACL) {
err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
if (err == -EOPNOTSUPP)
@@ -3008,6 +3028,8 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
case FSIDSOURCE_UUID:
p = xdr_encode_opaque_fixed(p, exp->ex_uuid,
EX_UUID_LEN);
+ if (mnt != exp->ex_path.mnt)
+ *(u64*)(p-2) ^= sub_fsid;
break;
}
}
@@ -3253,20 +3275,10 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
*p++ = cpu_to_be32(stat.mtime.tv_nsec);
}
if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
- u64 ino;
-
p = xdr_reserve_space(xdr, 8);
if (!p)
goto out_resource;
- /*
- * Get parent's attributes if not ignoring crossmount
- * and this is the root of a cross-mounted filesystem.
- */
- if (ignore_crossmnt == 0 && dentry == mnt->mnt_root)
- ino = nfsd_get_mounted_on(mnt);
- if (!ino)
- ino = stat.ino;
- p = xdr_encode_hyper(p, ino);
+ p = xdr_encode_hyper(p, mounted_on_ino);
}
#ifdef CONFIG_NFSD_PNFS
if (bmval1 & FATTR4_WORD1_FS_LAYOUT_TYPES) {
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 4023046f63e2..4b53838bca89 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -9,7 +9,7 @@
*/
#include <linux/exportfs.h>
-
+#include <linux/namei.h>
#include <linux/sunrpc/svcauth_gss.h>
#include "nfsd.h"
#include "vfs.h"
@@ -285,6 +285,11 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
default:
dentry = ERR_PTR(-ESTALE);
}
+ } else if (nfsd_mountpoint(dentry, exp)) {
+ struct path path = { .mnt = mnt, .dentry = dentry };
+ follow_down(&path, LOOKUP_AUTOMOUNT);
+ mnt = path.mnt;
+ dentry = path.dentry;
}
}
if (dentry == NULL)
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index baa12ac36ece..22523e1cd478 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -64,7 +64,7 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct path *path_parent,
.dentry = dget(path_parent->dentry)};
int err = 0;
- err = follow_down(&path, 0);
+ err = follow_down(&path, LOOKUP_AUTOMOUNT);
if (err < 0)
goto out;
if (path.mnt == path_parent->mnt && path.dentry == path_parent->dentry &&
@@ -73,6 +73,13 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct path *path_parent,
path_put(&path);
goto out;
}
+ if (mount_is_internal(path.mnt)) {
+ /* Use the new path, but don't look for a new export */
+ /* FIXME should I check NOHIDE in this case?? */
+ path_put(path_parent);
+ *path_parent = path;
+ goto out;
+ }
exp2 = rqst_exp_get_by_name(rqstp, &path);
if (IS_ERR(exp2)) {
@@ -157,7 +164,7 @@ int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp)
return 1;
if (nfsd4_is_junction(dentry))
return 1;
- if (d_mountpoint(dentry))
+ if (d_managed(dentry))
/*
* Might only be a mountpoint in a different namespace,
* but we need to check.
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 09/11] nfsd: Allow filehandle lookup to cross internal mount points.
2021-07-27 22:37 ` [PATCH 09/11] nfsd: Allow filehandle lookup to cross internal mount points NeilBrown
@ 2021-07-28 19:15 ` J. Bruce Fields
2021-07-28 22:29 ` NeilBrown
2021-07-30 0:42 ` Al Viro
1 sibling, 1 reply; 6+ messages in thread
From: J. Bruce Fields @ 2021-07-28 19:15 UTC (permalink / raw
To: NeilBrown
Cc: Christoph Hellwig, Josef Bacik, Chuck Lever, Chris Mason,
David Sterba, Alexander Viro, linux-fsdevel, linux-nfs,
linux-btrfs
On Wed, Jul 28, 2021 at 08:37:45AM +1000, NeilBrown wrote:
> Enhance nfsd to detect internal mounts and to cross them without
> requiring a new export.
Why don't we want a new export?
(Honest question, it's not obvious to me what the best behavior is.)
--b.
>
> Also ensure the fsid reported is different for different submounts. We
> do this by xoring in the ino of the mounted-on directory. This makes
> sense for btrfs at least.
>
> Signed-off-by: NeilBrown <neilb@suse.de>
> ---
> fs/nfsd/nfs3xdr.c | 28 +++++++++++++++++++++-------
> fs/nfsd/nfs4xdr.c | 34 +++++++++++++++++++++++-----------
> fs/nfsd/nfsfh.c | 7 ++++++-
> fs/nfsd/vfs.c | 11 +++++++++--
> 4 files changed, 59 insertions(+), 21 deletions(-)
>
> diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
> index 67af0c5c1543..80b1cc0334fa 100644
> --- a/fs/nfsd/nfs3xdr.c
> +++ b/fs/nfsd/nfs3xdr.c
> @@ -370,6 +370,8 @@ svcxdr_encode_fattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
> case FSIDSOURCE_UUID:
> fsid = ((u64 *)fhp->fh_export->ex_uuid)[0];
> fsid ^= ((u64 *)fhp->fh_export->ex_uuid)[1];
> + if (fhp->fh_mnt != fhp->fh_export->ex_path.mnt)
> + fsid ^= nfsd_get_mounted_on(fhp->fh_mnt);
> break;
> default:
> fsid = (u64)huge_encode_dev(fhp->fh_dentry->d_sb->s_dev);
> @@ -1094,8 +1096,8 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
> __be32 rv = nfserr_noent;
>
> dparent = cd->fh.fh_dentry;
> - exp = cd->fh.fh_export;
> - child.mnt = cd->fh.fh_mnt;
> + exp = exp_get(cd->fh.fh_export);
> + child.mnt = mntget(cd->fh.fh_mnt);
>
> if (isdotent(name, namlen)) {
> if (namlen == 2) {
> @@ -1112,15 +1114,27 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
> child.dentry = dget(dparent);
> } else
> child.dentry = lookup_positive_unlocked(name, dparent, namlen);
> - if (IS_ERR(child.dentry))
> + if (IS_ERR(child.dentry)) {
> + mntput(child.mnt);
> + exp_put(exp);
> return rv;
> - if (d_mountpoint(child.dentry))
> - goto out;
> - if (child.dentry->d_inode->i_ino != ino)
> + }
> + /* If child is a mountpoint, then we want to expose the fact
> + * so client can create a mountpoint. If not, then a different
> + * ino number probably means a race with rename, so avoid providing
> + * too much detail.
> + */
> + if (nfsd_mountpoint(child.dentry, exp)) {
> + int err;
> + err = nfsd_cross_mnt(cd->rqstp, &child, &exp);
> + if (err)
> + goto out;
> + } else if (child.dentry->d_inode->i_ino != ino)
> goto out;
> rv = fh_compose(fhp, exp, &child, &cd->fh);
> out:
> - dput(child.dentry);
> + path_put(&child);
> + exp_put(exp);
> return rv;
> }
>
> diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
> index d5683b6a74b2..4dbc99ed2c8b 100644
> --- a/fs/nfsd/nfs4xdr.c
> +++ b/fs/nfsd/nfs4xdr.c
> @@ -2817,6 +2817,8 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
> struct kstat stat;
> struct svc_fh *tempfh = NULL;
> struct kstatfs statfs;
> + u64 mounted_on_ino;
> + u64 sub_fsid;
> __be32 *p;
> int starting_len = xdr->buf->len;
> int attrlen_offset;
> @@ -2871,6 +2873,24 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
> goto out;
> fhp = tempfh;
> }
> + if ((bmval0 & FATTR4_WORD0_FSID) ||
> + (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID)) {
> + mounted_on_ino = stat.ino;
> + sub_fsid = 0;
> + /*
> + * The inode number that the current mnt is mounted on is
> + * used for MOUNTED_ON_FILED if we are at the root,
> + * and for sub_fsid if mnt is not the export mnt.
> + */
> + if (ignore_crossmnt == 0) {
> + u64 moi = nfsd_get_mounted_on(mnt);
> +
> + if (dentry == mnt->mnt_root && moi)
> + mounted_on_ino = moi;
> + if (mnt != exp->ex_path.mnt)
> + sub_fsid = moi;
> + }
> + }
> if (bmval0 & FATTR4_WORD0_ACL) {
> err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
> if (err == -EOPNOTSUPP)
> @@ -3008,6 +3028,8 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
> case FSIDSOURCE_UUID:
> p = xdr_encode_opaque_fixed(p, exp->ex_uuid,
> EX_UUID_LEN);
> + if (mnt != exp->ex_path.mnt)
> + *(u64*)(p-2) ^= sub_fsid;
> break;
> }
> }
> @@ -3253,20 +3275,10 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
> *p++ = cpu_to_be32(stat.mtime.tv_nsec);
> }
> if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
> - u64 ino;
> -
> p = xdr_reserve_space(xdr, 8);
> if (!p)
> goto out_resource;
> - /*
> - * Get parent's attributes if not ignoring crossmount
> - * and this is the root of a cross-mounted filesystem.
> - */
> - if (ignore_crossmnt == 0 && dentry == mnt->mnt_root)
> - ino = nfsd_get_mounted_on(mnt);
> - if (!ino)
> - ino = stat.ino;
> - p = xdr_encode_hyper(p, ino);
> + p = xdr_encode_hyper(p, mounted_on_ino);
> }
> #ifdef CONFIG_NFSD_PNFS
> if (bmval1 & FATTR4_WORD1_FS_LAYOUT_TYPES) {
> diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
> index 4023046f63e2..4b53838bca89 100644
> --- a/fs/nfsd/nfsfh.c
> +++ b/fs/nfsd/nfsfh.c
> @@ -9,7 +9,7 @@
> */
>
> #include <linux/exportfs.h>
> -
> +#include <linux/namei.h>
> #include <linux/sunrpc/svcauth_gss.h>
> #include "nfsd.h"
> #include "vfs.h"
> @@ -285,6 +285,11 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct svc_fh *fhp)
> default:
> dentry = ERR_PTR(-ESTALE);
> }
> + } else if (nfsd_mountpoint(dentry, exp)) {
> + struct path path = { .mnt = mnt, .dentry = dentry };
> + follow_down(&path, LOOKUP_AUTOMOUNT);
> + mnt = path.mnt;
> + dentry = path.dentry;
> }
> }
> if (dentry == NULL)
> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> index baa12ac36ece..22523e1cd478 100644
> --- a/fs/nfsd/vfs.c
> +++ b/fs/nfsd/vfs.c
> @@ -64,7 +64,7 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct path *path_parent,
> .dentry = dget(path_parent->dentry)};
> int err = 0;
>
> - err = follow_down(&path, 0);
> + err = follow_down(&path, LOOKUP_AUTOMOUNT);
> if (err < 0)
> goto out;
> if (path.mnt == path_parent->mnt && path.dentry == path_parent->dentry &&
> @@ -73,6 +73,13 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct path *path_parent,
> path_put(&path);
> goto out;
> }
> + if (mount_is_internal(path.mnt)) {
> + /* Use the new path, but don't look for a new export */
> + /* FIXME should I check NOHIDE in this case?? */
> + path_put(path_parent);
> + *path_parent = path;
> + goto out;
> + }
>
> exp2 = rqst_exp_get_by_name(rqstp, &path);
> if (IS_ERR(exp2)) {
> @@ -157,7 +164,7 @@ int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp)
> return 1;
> if (nfsd4_is_junction(dentry))
> return 1;
> - if (d_mountpoint(dentry))
> + if (d_managed(dentry))
> /*
> * Might only be a mountpoint in a different namespace,
> * but we need to check.
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 09/11] nfsd: Allow filehandle lookup to cross internal mount points.
@ 2021-07-28 22:12 kernel test robot
0 siblings, 0 replies; 6+ messages in thread
From: kernel test robot @ 2021-07-28 22:12 UTC (permalink / raw
To: kbuild
[-- Attachment #1: Type: text/plain, Size: 33761 bytes --]
CC: kbuild-all(a)lists.01.org
In-Reply-To: <162742546556.32498.16708762469227881912.stgit@noble.brown>
References: <162742546556.32498.16708762469227881912.stgit@noble.brown>
TO: NeilBrown <neilb@suse.de>
TO: Christoph Hellwig <hch@infradead.org>
TO: Josef Bacik <josef@toxicpanda.com>
TO: "J. Bruce Fields" <bfields@fieldses.org>
TO: Chuck Lever <chuck.lever@oracle.com>
TO: Chris Mason <chris.mason@fusionio.com>
TO: David Sterba <dsterba@suse.com>
TO: Alexander Viro <viro@zeniv.linux.org.uk>
CC: linux-fsdevel(a)vger.kernel.org
CC: linux-nfs(a)vger.kernel.org
CC: linux-btrfs(a)vger.kernel.org
Hi NeilBrown,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on nfsd/nfsd-next]
[also build test WARNING on kdave/for-next hch-configfs/for-next linus/master v5.14-rc3 next-20210727]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]
url: https://github.com/0day-ci/linux/commits/NeilBrown/expose-btrfs-subvols-in-mount-table-correctly/20210728-064502
base: git://linux-nfs.org/~bfields/linux.git nfsd-next
:::::: branch date: 23 hours ago
:::::: commit date: 23 hours ago
config: mips-randconfig-m031-20210728 (attached as .config)
compiler: mips-linux-gcc (GCC) 10.3.0
If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
New smatch warnings:
fs/nfsd/nfs4xdr.c:3032 nfsd4_encode_fattr() error: uninitialized symbol 'sub_fsid'.
fs/nfsd/nfs4xdr.c:3281 nfsd4_encode_fattr() error: uninitialized symbol 'mounted_on_ino'.
Old smatch warnings:
fs/nfsd/nfs4xdr.c:3319 nfsd4_encode_fattr() error: uninitialized symbol 'contextlen'.
fs/nfsd/nfs4xdr.c:4803 nfsd4_encode_read_plus_hole() warn: inconsistent indenting
vim +/sub_fsid +3032 fs/nfsd/nfs4xdr.c
18032ca062e621e David Quigley 2013-05-02 2922
75976de6556f593 Kinglong Mee 2015-07-30 2923 status = nfsd4_encode_bitmap(xdr, bmval0, bmval1, bmval2);
75976de6556f593 Kinglong Mee 2015-07-30 2924 if (status)
75976de6556f593 Kinglong Mee 2015-07-30 2925 goto out;
082d4bd72a4527c J. Bruce Fields 2013-08-29 2926
082d4bd72a4527c J. Bruce Fields 2013-08-29 2927 attrlen_offset = xdr->buf->len;
ddd1ea56367202f J. Bruce Fields 2013-08-27 2928 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 2929 if (!p)
ddd1ea56367202f J. Bruce Fields 2013-08-27 2930 goto out_resource;
082d4bd72a4527c J. Bruce Fields 2013-08-29 2931 p++; /* to be backfilled later */
^1da177e4c3f415 Linus Torvalds 2005-04-16 2932
^1da177e4c3f415 Linus Torvalds 2005-04-16 2933 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
dcd208697707b12 J. Bruce Fields 2017-01-11 2934 u32 supp[3];
dcd208697707b12 J. Bruce Fields 2017-01-11 2935
dcd208697707b12 J. Bruce Fields 2017-01-11 2936 memcpy(supp, nfsd_suppattrs[minorversion], sizeof(supp));
7e7057064782734 Andy Adamson 2009-04-03 2937
0c9d65e76a19ad7 Andreas Gruenbacher 2015-04-24 2938 if (!IS_POSIXACL(dentry->d_inode))
916d2d844afd09d J. Bruce Fields 2016-10-18 2939 supp[0] &= ~FATTR4_WORD0_ACL;
18032ca062e621e David Quigley 2013-05-02 2940 if (!contextsupport)
916d2d844afd09d J. Bruce Fields 2016-10-18 2941 supp[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
916d2d844afd09d J. Bruce Fields 2016-10-18 2942 if (!supp[2]) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 2943 p = xdr_reserve_space(xdr, 12);
ddd1ea56367202f J. Bruce Fields 2013-08-27 2944 if (!p)
2b44f1ba4091477 Benny Halevy 2010-09-30 2945 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 2946 *p++ = cpu_to_be32(2);
916d2d844afd09d J. Bruce Fields 2016-10-18 2947 *p++ = cpu_to_be32(supp[0]);
916d2d844afd09d J. Bruce Fields 2016-10-18 2948 *p++ = cpu_to_be32(supp[1]);
7e7057064782734 Andy Adamson 2009-04-03 2949 } else {
ddd1ea56367202f J. Bruce Fields 2013-08-27 2950 p = xdr_reserve_space(xdr, 16);
ddd1ea56367202f J. Bruce Fields 2013-08-27 2951 if (!p)
2b44f1ba4091477 Benny Halevy 2010-09-30 2952 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 2953 *p++ = cpu_to_be32(3);
916d2d844afd09d J. Bruce Fields 2016-10-18 2954 *p++ = cpu_to_be32(supp[0]);
916d2d844afd09d J. Bruce Fields 2016-10-18 2955 *p++ = cpu_to_be32(supp[1]);
916d2d844afd09d J. Bruce Fields 2016-10-18 2956 *p++ = cpu_to_be32(supp[2]);
7e7057064782734 Andy Adamson 2009-04-03 2957 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 2958 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 2959 if (bmval0 & FATTR4_WORD0_TYPE) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 2960 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 2961 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 2962 goto out_resource;
3d2544b1e4909b6 J. Bruce Fields 2011-08-15 2963 dummy = nfs4_file_type(stat.mode);
6b6d8137f1d3fc7 J. Bruce Fields 2013-01-16 2964 if (dummy == NF4BAD) {
6b6d8137f1d3fc7 J. Bruce Fields 2013-01-16 2965 status = nfserr_serverfault;
6b6d8137f1d3fc7 J. Bruce Fields 2013-01-16 2966 goto out;
6b6d8137f1d3fc7 J. Bruce Fields 2013-01-16 2967 }
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 2968 *p++ = cpu_to_be32(dummy);
^1da177e4c3f415 Linus Torvalds 2005-04-16 2969 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 2970 if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 2971 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 2972 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 2973 goto out_resource;
496400014f22c4d NeilBrown 2005-06-23 2974 if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 2975 *p++ = cpu_to_be32(NFS4_FH_PERSISTENT);
496400014f22c4d NeilBrown 2005-06-23 2976 else
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 2977 *p++ = cpu_to_be32(NFS4_FH_PERSISTENT|
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 2978 NFS4_FH_VOL_RENAME);
^1da177e4c3f415 Linus Torvalds 2005-04-16 2979 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 2980 if (bmval0 & FATTR4_WORD0_CHANGE) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 2981 p = xdr_reserve_space(xdr, 8);
ddd1ea56367202f J. Bruce Fields 2013-08-27 2982 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 2983 goto out_resource;
b880092109323d1 NeilBrown 2017-01-30 2984 p = encode_change(p, &stat, d_inode(dentry), exp);
^1da177e4c3f415 Linus Torvalds 2005-04-16 2985 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 2986 if (bmval0 & FATTR4_WORD0_SIZE) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 2987 p = xdr_reserve_space(xdr, 8);
ddd1ea56367202f J. Bruce Fields 2013-08-27 2988 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 2989 goto out_resource;
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 2990 p = xdr_encode_hyper(p, stat.size);
^1da177e4c3f415 Linus Torvalds 2005-04-16 2991 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 2992 if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 2993 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 2994 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 2995 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 2996 *p++ = cpu_to_be32(1);
^1da177e4c3f415 Linus Torvalds 2005-04-16 2997 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 2998 if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 2999 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3000 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3001 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3002 *p++ = cpu_to_be32(1);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3003 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3004 if (bmval0 & FATTR4_WORD0_NAMED_ATTR) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3005 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3006 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3007 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3008 *p++ = cpu_to_be32(0);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3009 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3010 if (bmval0 & FATTR4_WORD0_FSID) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3011 p = xdr_reserve_space(xdr, 16);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3012 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3013 goto out_resource;
42ca09938157105 J.Bruce Fields 2006-10-04 3014 if (exp->ex_fslocs.migrated) {
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3015 p = xdr_encode_hyper(p, NFS4_REFERRAL_FSID_MAJOR);
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3016 p = xdr_encode_hyper(p, NFS4_REFERRAL_FSID_MINOR);
af6a4e280e3ff45 NeilBrown 2007-02-14 3017 } else switch(fsid_source(fhp)) {
af6a4e280e3ff45 NeilBrown 2007-02-14 3018 case FSIDSOURCE_FSID:
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3019 p = xdr_encode_hyper(p, (u64)exp->ex_fsid);
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3020 p = xdr_encode_hyper(p, (u64)0);
af6a4e280e3ff45 NeilBrown 2007-02-14 3021 break;
af6a4e280e3ff45 NeilBrown 2007-02-14 3022 case FSIDSOURCE_DEV:
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3023 *p++ = cpu_to_be32(0);
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3024 *p++ = cpu_to_be32(MAJOR(stat.dev));
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3025 *p++ = cpu_to_be32(0);
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3026 *p++ = cpu_to_be32(MINOR(stat.dev));
af6a4e280e3ff45 NeilBrown 2007-02-14 3027 break;
af6a4e280e3ff45 NeilBrown 2007-02-14 3028 case FSIDSOURCE_UUID:
94eb36892d72714 Kinglong Mee 2014-05-23 3029 p = xdr_encode_opaque_fixed(p, exp->ex_uuid,
94eb36892d72714 Kinglong Mee 2014-05-23 3030 EX_UUID_LEN);
5caed3f714c903d NeilBrown 2021-07-28 3031 if (mnt != exp->ex_path.mnt)
5caed3f714c903d NeilBrown 2021-07-28 @3032 *(u64*)(p-2) ^= sub_fsid;
af6a4e280e3ff45 NeilBrown 2007-02-14 3033 break;
^1da177e4c3f415 Linus Torvalds 2005-04-16 3034 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3035 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3036 if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3037 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3038 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3039 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3040 *p++ = cpu_to_be32(0);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3041 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3042 if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3043 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3044 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3045 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3046 *p++ = cpu_to_be32(nn->nfsd4_lease);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3047 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3048 if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3049 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3050 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3051 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3052 *p++ = cpu_to_be32(rdattr_err);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3053 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3054 if (bmval0 & FATTR4_WORD0_ACL) {
^1da177e4c3f415 Linus Torvalds 2005-04-16 3055 struct nfs4_ace *ace;
^1da177e4c3f415 Linus Torvalds 2005-04-16 3056
^1da177e4c3f415 Linus Torvalds 2005-04-16 3057 if (acl == NULL) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3058 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3059 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3060 goto out_resource;
^1da177e4c3f415 Linus Torvalds 2005-04-16 3061
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3062 *p++ = cpu_to_be32(0);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3063 goto out_acl;
^1da177e4c3f415 Linus Torvalds 2005-04-16 3064 }
ddd1ea56367202f J. Bruce Fields 2013-08-27 3065 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3066 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3067 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3068 *p++ = cpu_to_be32(acl->naces);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3069
28e05dd8457c7a7 J. Bruce Fields 2007-02-16 3070 for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3071 p = xdr_reserve_space(xdr, 4*3);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3072 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3073 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3074 *p++ = cpu_to_be32(ace->type);
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3075 *p++ = cpu_to_be32(ace->flag);
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3076 *p++ = cpu_to_be32(ace->access_mask &
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3077 NFS4_ACE_MASK_ALL);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3078 status = nfsd4_encode_aclname(xdr, rqstp, ace);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3079 if (status)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3080 goto out;
^1da177e4c3f415 Linus Torvalds 2005-04-16 3081 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3082 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3083 out_acl:
^1da177e4c3f415 Linus Torvalds 2005-04-16 3084 if (bmval0 & FATTR4_WORD0_ACLSUPPORT) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3085 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3086 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3087 goto out_resource;
0c9d65e76a19ad7 Andreas Gruenbacher 2015-04-24 3088 *p++ = cpu_to_be32(IS_POSIXACL(dentry->d_inode) ?
^1da177e4c3f415 Linus Torvalds 2005-04-16 3089 ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3090 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3091 if (bmval0 & FATTR4_WORD0_CANSETTIME) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3092 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3093 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3094 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3095 *p++ = cpu_to_be32(1);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3096 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3097 if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3098 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3099 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3100 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3101 *p++ = cpu_to_be32(0);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3102 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3103 if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3104 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3105 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3106 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3107 *p++ = cpu_to_be32(1);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3108 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3109 if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3110 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3111 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3112 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3113 *p++ = cpu_to_be32(1);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3114 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3115 if (bmval0 & FATTR4_WORD0_FILEHANDLE) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3116 p = xdr_reserve_space(xdr, fhp->fh_handle.fh_size + 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3117 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3118 goto out_resource;
0c0c267ba96f606 J. Bruce Fields 2014-03-22 3119 p = xdr_encode_opaque(p, &fhp->fh_handle.fh_base,
0c0c267ba96f606 J. Bruce Fields 2014-03-22 3120 fhp->fh_handle.fh_size);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3121 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3122 if (bmval0 & FATTR4_WORD0_FILEID) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3123 p = xdr_reserve_space(xdr, 8);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3124 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3125 goto out_resource;
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3126 p = xdr_encode_hyper(p, stat.ino);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3127 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3128 if (bmval0 & FATTR4_WORD0_FILES_AVAIL) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3129 p = xdr_reserve_space(xdr, 8);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3130 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3131 goto out_resource;
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3132 p = xdr_encode_hyper(p, (u64) statfs.f_ffree);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3133 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3134 if (bmval0 & FATTR4_WORD0_FILES_FREE) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3135 p = xdr_reserve_space(xdr, 8);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3136 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3137 goto out_resource;
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3138 p = xdr_encode_hyper(p, (u64) statfs.f_ffree);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3139 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3140 if (bmval0 & FATTR4_WORD0_FILES_TOTAL) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3141 p = xdr_reserve_space(xdr, 8);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3142 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3143 goto out_resource;
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3144 p = xdr_encode_hyper(p, (u64) statfs.f_files);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3145 }
81c3f4130202a1d J.Bruce Fields 2006-10-04 3146 if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3147 status = nfsd4_encode_fs_locations(xdr, rqstp, exp);
81c3f4130202a1d J.Bruce Fields 2006-10-04 3148 if (status)
81c3f4130202a1d J.Bruce Fields 2006-10-04 3149 goto out;
81c3f4130202a1d J.Bruce Fields 2006-10-04 3150 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3151 if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3152 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3153 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3154 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3155 *p++ = cpu_to_be32(1);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3156 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3157 if (bmval0 & FATTR4_WORD0_MAXFILESIZE) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3158 p = xdr_reserve_space(xdr, 8);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3159 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3160 goto out_resource;
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3161 p = xdr_encode_hyper(p, exp->ex_path.mnt->mnt_sb->s_maxbytes);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3162 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3163 if (bmval0 & FATTR4_WORD0_MAXLINK) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3164 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3165 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3166 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3167 *p++ = cpu_to_be32(255);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3168 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3169 if (bmval0 & FATTR4_WORD0_MAXNAME) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3170 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3171 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3172 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3173 *p++ = cpu_to_be32(statfs.f_namelen);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3174 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3175 if (bmval0 & FATTR4_WORD0_MAXREAD) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3176 p = xdr_reserve_space(xdr, 8);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3177 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3178 goto out_resource;
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3179 p = xdr_encode_hyper(p, (u64) svc_max_payload(rqstp));
^1da177e4c3f415 Linus Torvalds 2005-04-16 3180 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3181 if (bmval0 & FATTR4_WORD0_MAXWRITE) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3182 p = xdr_reserve_space(xdr, 8);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3183 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3184 goto out_resource;
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3185 p = xdr_encode_hyper(p, (u64) svc_max_payload(rqstp));
^1da177e4c3f415 Linus Torvalds 2005-04-16 3186 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3187 if (bmval1 & FATTR4_WORD1_MODE) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3188 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3189 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3190 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3191 *p++ = cpu_to_be32(stat.mode & S_IALLUGO);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3192 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3193 if (bmval1 & FATTR4_WORD1_NO_TRUNC) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3194 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3195 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3196 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3197 *p++ = cpu_to_be32(1);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3198 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3199 if (bmval1 & FATTR4_WORD1_NUMLINKS) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3200 p = xdr_reserve_space(xdr, 4);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3201 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3202 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3203 *p++ = cpu_to_be32(stat.nlink);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3204 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3205 if (bmval1 & FATTR4_WORD1_OWNER) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3206 status = nfsd4_encode_user(xdr, rqstp, stat.uid);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3207 if (status)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3208 goto out;
^1da177e4c3f415 Linus Torvalds 2005-04-16 3209 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3210 if (bmval1 & FATTR4_WORD1_OWNER_GROUP) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3211 status = nfsd4_encode_group(xdr, rqstp, stat.gid);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3212 if (status)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3213 goto out;
^1da177e4c3f415 Linus Torvalds 2005-04-16 3214 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3215 if (bmval1 & FATTR4_WORD1_RAWDEV) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3216 p = xdr_reserve_space(xdr, 8);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3217 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3218 goto out_resource;
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3219 *p++ = cpu_to_be32((u32) MAJOR(stat.rdev));
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3220 *p++ = cpu_to_be32((u32) MINOR(stat.rdev));
^1da177e4c3f415 Linus Torvalds 2005-04-16 3221 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3222 if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3223 p = xdr_reserve_space(xdr, 8);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3224 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3225 goto out_resource;
^1da177e4c3f415 Linus Torvalds 2005-04-16 3226 dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize;
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3227 p = xdr_encode_hyper(p, dummy64);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3228 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3229 if (bmval1 & FATTR4_WORD1_SPACE_FREE) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3230 p = xdr_reserve_space(xdr, 8);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3231 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3232 goto out_resource;
^1da177e4c3f415 Linus Torvalds 2005-04-16 3233 dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize;
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3234 p = xdr_encode_hyper(p, dummy64);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3235 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3236 if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3237 p = xdr_reserve_space(xdr, 8);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3238 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3239 goto out_resource;
^1da177e4c3f415 Linus Torvalds 2005-04-16 3240 dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize;
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3241 p = xdr_encode_hyper(p, dummy64);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3242 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3243 if (bmval1 & FATTR4_WORD1_SPACE_USED) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3244 p = xdr_reserve_space(xdr, 8);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3245 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3246 goto out_resource;
^1da177e4c3f415 Linus Torvalds 2005-04-16 3247 dummy64 = (u64)stat.blocks << 9;
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3248 p = xdr_encode_hyper(p, dummy64);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3249 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3250 if (bmval1 & FATTR4_WORD1_TIME_ACCESS) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3251 p = xdr_reserve_space(xdr, 12);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3252 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3253 goto out_resource;
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3254 p = xdr_encode_hyper(p, (s64)stat.atime.tv_sec);
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3255 *p++ = cpu_to_be32(stat.atime.tv_nsec);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3256 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3257 if (bmval1 & FATTR4_WORD1_TIME_DELTA) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3258 p = xdr_reserve_space(xdr, 12);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3259 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3260 goto out_resource;
16945141c3567bb J. Bruce Fields 2018-04-25 3261 p = encode_time_delta(p, d_inode(dentry));
^1da177e4c3f415 Linus Torvalds 2005-04-16 3262 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3263 if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3264 p = xdr_reserve_space(xdr, 12);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3265 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3266 goto out_resource;
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3267 p = xdr_encode_hyper(p, (s64)stat.ctime.tv_sec);
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3268 *p++ = cpu_to_be32(stat.ctime.tv_nsec);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3269 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3270 if (bmval1 & FATTR4_WORD1_TIME_MODIFY) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3271 p = xdr_reserve_space(xdr, 12);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3272 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3273 goto out_resource;
b64c7f3bdfbb468 J. Bruce Fields 2014-03-22 3274 p = xdr_encode_hyper(p, (s64)stat.mtime.tv_sec);
c373b0a4289ebf1 J. Bruce Fields 2014-03-22 3275 *p++ = cpu_to_be32(stat.mtime.tv_nsec);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3276 }
^1da177e4c3f415 Linus Torvalds 2005-04-16 3277 if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
ddd1ea56367202f J. Bruce Fields 2013-08-27 3278 p = xdr_reserve_space(xdr, 8);
ddd1ea56367202f J. Bruce Fields 2013-08-27 3279 if (!p)
^1da177e4c3f415 Linus Torvalds 2005-04-16 3280 goto out_resource;
5caed3f714c903d NeilBrown 2021-07-28 3281 p = xdr_encode_hyper(p, mounted_on_ino);
^1da177e4c3f415 Linus Torvalds 2005-04-16 3282 }
9cf514ccfacb301 Christoph Hellwig 2014-05-05 3283 #ifdef CONFIG_NFSD_PNFS
6896f15aabde505 Kinglong Mee 2015-07-30 3284 if (bmval1 & FATTR4_WORD1_FS_LAYOUT_TYPES) {
8a4c3926889e7bf Jeff Layton 2016-07-10 3285 status = nfsd4_encode_layout_types(xdr, exp->ex_layout_types);
6896f15aabde505 Kinglong Mee 2015-07-30 3286 if (status)
6896f15aabde505 Kinglong Mee 2015-07-30 3287 goto out;
9cf514ccfacb301 Christoph Hellwig 2014-05-05 3288 }
6896f15aabde505 Kinglong Mee 2015-07-30 3289
6896f15aabde505 Kinglong Mee 2015-07-30 3290 if (bmval2 & FATTR4_WORD2_LAYOUT_TYPES) {
8a4c3926889e7bf Jeff Layton 2016-07-10 3291 status = nfsd4_encode_layout_types(xdr, exp->ex_layout_types);
6896f15aabde505 Kinglong Mee 2015-07-30 3292 if (status)
6896f15aabde505 Kinglong Mee 2015-07-30 3293 goto out;
9cf514ccfacb301 Christoph Hellwig 2014-05-05 3294 }
9cf514ccfacb301 Christoph Hellwig 2014-05-05 3295
9cf514ccfacb301 Christoph Hellwig 2014-05-05 3296 if (bmval2 & FATTR4_WORD2_LAYOUT_BLKSIZE) {
9cf514ccfacb301 Christoph Hellwig 2014-05-05 3297 p = xdr_reserve_space(xdr, 4);
9cf514ccfacb301 Christoph Hellwig 2014-05-05 3298 if (!p)
9cf514ccfacb301 Christoph Hellwig 2014-05-05 3299 goto out_resource;
9cf514ccfacb301 Christoph Hellwig 2014-05-05 3300 *p++ = cpu_to_be32(stat.blksize);
9cf514ccfacb301 Christoph Hellwig 2014-05-05 3301 }
9cf514ccfacb301 Christoph Hellwig 2014-05-05 3302 #endif /* CONFIG_NFSD_PNFS */
8c18f2052e756e7 Benny Halevy 2009-04-03 3303 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
b26b78cb7260075 Trond Myklebust 2017-05-09 3304 u32 supp[3];
b26b78cb7260075 Trond Myklebust 2017-05-09 3305
b26b78cb7260075 Trond Myklebust 2017-05-09 3306 memcpy(supp, nfsd_suppattrs[minorversion], sizeof(supp));
b26b78cb7260075 Trond Myklebust 2017-05-09 3307 supp[0] &= NFSD_SUPPATTR_EXCLCREAT_WORD0;
b26b78cb7260075 Trond Myklebust 2017-05-09 3308 supp[1] &= NFSD_SUPPATTR_EXCLCREAT_WORD1;
b26b78cb7260075 Trond Myklebust 2017-05-09 3309 supp[2] &= NFSD_SUPPATTR_EXCLCREAT_WORD2;
b26b78cb7260075 Trond Myklebust 2017-05-09 3310
b26b78cb7260075 Trond Myklebust 2017-05-09 3311 status = nfsd4_encode_bitmap(xdr, supp[0], supp[1], supp[2]);
75976de6556f593 Kinglong Mee 2015-07-30 3312 if (status)
75976de6556f593 Kinglong Mee 2015-07-30 3313 goto out;
8c18f2052e756e7 Benny Halevy 2009-04-03 3314 }
7e7057064782734 Andy Adamson 2009-04-03 3315
---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 37347 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 09/11] nfsd: Allow filehandle lookup to cross internal mount points.
2021-07-28 19:15 ` J. Bruce Fields
@ 2021-07-28 22:29 ` NeilBrown
0 siblings, 0 replies; 6+ messages in thread
From: NeilBrown @ 2021-07-28 22:29 UTC (permalink / raw
To: J. Bruce Fields
Cc: Christoph Hellwig, Josef Bacik, Chuck Lever, Chris Mason,
David Sterba, Alexander Viro, linux-fsdevel, linux-nfs,
linux-btrfs
On Thu, 29 Jul 2021, J. Bruce Fields wrote:
> On Wed, Jul 28, 2021 at 08:37:45AM +1000, NeilBrown wrote:
> > Enhance nfsd to detect internal mounts and to cross them without
> > requiring a new export.
>
> Why don't we want a new export?
>
> (Honest question, it's not obvious to me what the best behavior is.)
Because a new export means asking user-space to determine if the mount
is exported and to provide a filehandle-prefix for it. A large part of
the point of this it to avoid using a different filehandle-prefix.
I haven't yet thought deeply about how the 'crossmnt' flag (for v3)
should affect crossing these internal mounts. My current feeling is
that it shouldn't as it really is just one big filesystem being
exported, which happens to internally have different inode-number
spaces.
Unfortuantely this technically violates the RFC as the fsid is not meant
to change when you do a LOOKUP ...
NeilBrown
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 09/11] nfsd: Allow filehandle lookup to cross internal mount points.
2021-07-27 22:37 ` [PATCH 09/11] nfsd: Allow filehandle lookup to cross internal mount points NeilBrown
2021-07-28 19:15 ` J. Bruce Fields
@ 2021-07-30 0:42 ` Al Viro
2021-07-30 5:43 ` NeilBrown
1 sibling, 1 reply; 6+ messages in thread
From: Al Viro @ 2021-07-30 0:42 UTC (permalink / raw
To: NeilBrown
Cc: Christoph Hellwig, Josef Bacik, J. Bruce Fields, Chuck Lever,
Chris Mason, David Sterba, linux-fsdevel, linux-nfs, linux-btrfs
On Wed, Jul 28, 2021 at 08:37:45AM +1000, NeilBrown wrote:
> diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> index baa12ac36ece..22523e1cd478 100644
> --- a/fs/nfsd/vfs.c
> +++ b/fs/nfsd/vfs.c
> @@ -64,7 +64,7 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct path *path_parent,
> .dentry = dget(path_parent->dentry)};
> int err = 0;
>
> - err = follow_down(&path, 0);
> + err = follow_down(&path, LOOKUP_AUTOMOUNT);
> if (err < 0)
> goto out;
> if (path.mnt == path_parent->mnt && path.dentry == path_parent->dentry &&
> @@ -73,6 +73,13 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct path *path_parent,
> path_put(&path);
> goto out;
> }
> + if (mount_is_internal(path.mnt)) {
> + /* Use the new path, but don't look for a new export */
> + /* FIXME should I check NOHIDE in this case?? */
> + path_put(path_parent);
> + *path_parent = path;
> + goto out;
> + }
... IOW, mount_is_internal() is called with no exclusion whatsoever. What's there
to
* keep its return value valid?
* prevent fetching ->mnt_mountpoint, getting preempted away, having
the mount moved *and* what used to be ->mnt_mountpoint evicted from dcache,
now that it's no longer pinned, then mount_is_internal() regaining CPU and
dereferencing ->mnt_mountpoint, which now points to hell knows what?
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH 09/11] nfsd: Allow filehandle lookup to cross internal mount points.
2021-07-30 0:42 ` Al Viro
@ 2021-07-30 5:43 ` NeilBrown
0 siblings, 0 replies; 6+ messages in thread
From: NeilBrown @ 2021-07-30 5:43 UTC (permalink / raw
To: Al Viro
Cc: Christoph Hellwig, Josef Bacik, J. Bruce Fields, Chuck Lever,
Chris Mason, David Sterba, linux-fsdevel, linux-nfs, linux-btrfs
On Fri, 30 Jul 2021, Al Viro wrote:
> On Wed, Jul 28, 2021 at 08:37:45AM +1000, NeilBrown wrote:
>
> > diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> > index baa12ac36ece..22523e1cd478 100644
> > --- a/fs/nfsd/vfs.c
> > +++ b/fs/nfsd/vfs.c
> > @@ -64,7 +64,7 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct path *path_parent,
> > .dentry = dget(path_parent->dentry)};
> > int err = 0;
> >
> > - err = follow_down(&path, 0);
> > + err = follow_down(&path, LOOKUP_AUTOMOUNT);
> > if (err < 0)
> > goto out;
> > if (path.mnt == path_parent->mnt && path.dentry == path_parent->dentry &&
> > @@ -73,6 +73,13 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct path *path_parent,
> > path_put(&path);
> > goto out;
> > }
> > + if (mount_is_internal(path.mnt)) {
> > + /* Use the new path, but don't look for a new export */
> > + /* FIXME should I check NOHIDE in this case?? */
> > + path_put(path_parent);
> > + *path_parent = path;
> > + goto out;
> > + }
>
> ... IOW, mount_is_internal() is called with no exclusion whatsoever. What's there
> to
> * keep its return value valid?
> * prevent fetching ->mnt_mountpoint, getting preempted away, having
> the mount moved *and* what used to be ->mnt_mountpoint evicted from dcache,
> now that it's no longer pinned, then mount_is_internal() regaining CPU and
> dereferencing ->mnt_mountpoint, which now points to hell knows what?
>
Yes, mount_is_internal needs to same mount_lock protection that
lookup_mnt() has. Thanks.
I don't think it matter how long the result remains valid. The only
realistic transtion is from True to False, but the fact that it *was*
True means that it is acceptable for the lookup to have succeeded.
i.e. If the mountpoint was moved which a request was being processed it
will either cause the same result as if it happened before the request
started, or after it finished. Either seems OK.
Thanks,
NeilBrown
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2021-07-30 5:43 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-07-28 22:12 [PATCH 09/11] nfsd: Allow filehandle lookup to cross internal mount points kernel test robot
-- strict thread matches above, loose matches on Subject: below --
2021-07-27 22:37 [PATCH/RFC 00/11] expose btrfs subvols in mount table correctly NeilBrown
2021-07-27 22:37 ` [PATCH 09/11] nfsd: Allow filehandle lookup to cross internal mount points NeilBrown
2021-07-28 19:15 ` J. Bruce Fields
2021-07-28 22:29 ` NeilBrown
2021-07-30 0:42 ` Al Viro
2021-07-30 5:43 ` NeilBrown
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.