Request for mode bits and nlink count in the nfs4_get_referral call and if server returns them use them instead of hard coded values. CC: stable@xxxxxxxxxxxxxxx Signed-off-by: Ashish Sangwan <ashishsangwan2@xxxxxxxxx> --- fs/nfs/nfs4proc.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 6e95c85fe395..efec05c5f535 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -266,7 +266,9 @@ const u32 nfs4_fs_locations_bitmap[3] = { | FATTR4_WORD0_FSID | FATTR4_WORD0_FILEID | FATTR4_WORD0_FS_LOCATIONS, - FATTR4_WORD1_OWNER + FATTR4_WORD1_MODE + | FATTR4_WORD1_NUMLINKS + | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP | FATTR4_WORD1_RAWDEV | FATTR4_WORD1_SPACE_USED @@ -7594,16 +7596,28 @@ nfs4_listxattr_nfs4_user(struct inode *inode, char *list, size_t list_len) */ static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr) { + bool fix_mode = true, fix_nlink = true; + if (!(((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) || (fattr->valid & NFS_ATTR_FATTR_FILEID)) && (fattr->valid & NFS_ATTR_FATTR_FSID) && (fattr->valid & NFS_ATTR_FATTR_V4_LOCATIONS))) return; + if (fattr->valid & NFS_ATTR_FATTR_MODE) + fix_mode = false; + if (fattr->valid & NFS_ATTR_FATTR_NLINK) + fix_nlink = false; fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | NFS_ATTR_FATTR_NLINK | NFS_ATTR_FATTR_V4_REFERRAL; - fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO; - fattr->nlink = 2; + + if (fix_mode) + fattr->mode = S_IFDIR | S_IRUGO | S_IXUGO; + else + fattr->mode |= S_IFDIR; + + if (fix_nlink) + fattr->nlink = 2; } static int _nfs4_proc_fs_locations(struct rpc_clnt *client, struct inode *dir, -- 2.22.0