@@ -2768,22 +2768,6 @@ static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *bmval2, u32
return 0;
}
-
-static int get_parent_attributes(struct svc_export *exp, struct kstat *stat)
-{
- struct path path = exp->ex_path;
- int err;
-
- path_get(&path);
- while (follow_up(&path)) {
- if (path.dentry != path.mnt->mnt_root)
- break;
- }
- err = vfs_getattr(&path, stat, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
- path_put(&path);
- return err;
-}
-
static __be32
nfsd4_encode_bitmap(struct xdr_stream *xdr, u32 bmval0, u32 bmval1, u32 bmval2)
{
@@ -3269,8 +3253,7 @@ 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) {
- struct kstat parent_stat;
- u64 ino = stat.ino;
+ u64 ino;
p = xdr_reserve_space(xdr, 8);
if (!p)
@@ -3279,12 +3262,10 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
* 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) {
- err = get_parent_attributes(exp, &parent_stat);
- if (err)
- goto out_nfserr;
- ino = parent_stat.ino;
- }
+ 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);
}
#ifdef CONFIG_NFSD_PNFS
@@ -2445,3 +2445,21 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
return err? nfserrno(err) : 0;
}
+
+unsigned long nfsd_get_mounted_on(struct vfsmount *mnt)
+{
+ struct kstat stat;
+ struct path path = { .mnt = mnt, .dentry = mnt->mnt_root };
+ int err;
+
+ path_get(&path);
+ while (follow_up(&path)) {
+ if (path.dentry != path.mnt->mnt_root)
+ break;
+ }
+ err = vfs_getattr(&path, &stat, STATX_INO, AT_STATX_DONT_SYNC);
+ path_put(&path);
+ if (err)
+ return 0;
+ return stat.ino;
+}
@@ -132,6 +132,8 @@ __be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *,
__be32 nfsd_permission(struct svc_rqst *, struct svc_export *,
struct dentry *, int);
+unsigned long nfsd_get_mounted_on(struct vfsmount *mnt);
+
static inline int fh_want_write(struct svc_fh *fh)
{
int ret;
get_parent_attributes() is only used to get the inode number of the mounted-on directory. So change it to only do that and call it nfsd_get_mounted_on(). It will eventually be use by nfs3 as well as nfs4, so move it to vfs.c. Signed-off-by: NeilBrown <neilb@suse.de> --- fs/nfsd/nfs4xdr.c | 29 +++++------------------------ fs/nfsd/vfs.c | 18 ++++++++++++++++++ fs/nfsd/vfs.h | 2 ++ 3 files changed, 25 insertions(+), 24 deletions(-)