Re: [PATCH AUTOSEL 6.12 25/28] cifs: Treat unhandled directory name surrogate reparse points as mount directory nodes

Pali Rohár
2025-02-24T17:53:05Z

This patch depends on cad3fc0a4c8cef07b07ceddc137f582267577250 ("cifs:
Throw -EOPNOTSUPP error on unsupported reparse point type from
parse_reparse_point()". Please ensure that this dependency is included.

On Monday 24 February 2025 06:17:56 Sasha Levin wrote:
> From: Pali Rohár <pali@kernel.org>
>
> [ Upstream commit b587fd128660d48cd2122f870f720ff8e2b4abb3 ]
>
> If the reparse point was not handled (indicated by the -EOPNOTSUPP from
> ops->parse_reparse_point() call) but reparse tag is of type name surrogate
> directory type, then treat is as a new mount point.
>
> Name surrogate reparse point represents another named entity in the system.
>
> From SMB client point of view, this another entity is resolved on the SMB
> server, and server serves its content automatically. Therefore from Linux
> client point of view, this name surrogate reparse point of directory type
> crosses mount point.
>
> Signed-off-by: Pali Rohár <pali@kernel.org>
> Signed-off-by: Steve French <stfrench@microsoft.com>
> Signed-off-by: Sasha Levin <sashal@kernel.org>
> ---
> fs/smb/client/inode.c | 13 +++++++++++++
> fs/smb/common/smbfsctl.h | 3 +++
> 2 files changed, 16 insertions(+)
>
> diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
> index fafc07e38663c..295afb73fcdd6 100644
> --- a/fs/smb/client/inode.c
> +++ b/fs/smb/client/inode.c
> @@ -1193,6 +1193,19 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
> rc = server->ops->parse_reparse_point(cifs_sb,
> full_path,
> iov, data);
> + /*
> + * If the reparse point was not handled but it is the
> + * name surrogate which points to directory, then treat
> + * is as a new mount point. Name surrogate reparse point
> + * represents another named entity in the system.
> + */
> + if (rc == -EOPNOTSUPP &&
> + IS_REPARSE_TAG_NAME_SURROGATE(data->reparse.tag) &&
> + (le32_to_cpu(data->fi.Attributes) & ATTR_DIRECTORY)) {
> + rc = 0;
> + cifs_create_junction_fattr(fattr, sb);
> + goto out;
> + }
> }
> break;
> }
> diff --git a/fs/smb/common/smbfsctl.h b/fs/smb/common/smbfsctl.h
> index 4b379e84c46b9..3253a18ecb5cb 100644
> --- a/fs/smb/common/smbfsctl.h
> +++ b/fs/smb/common/smbfsctl.h
> @@ -159,6 +159,9 @@
> #define IO_REPARSE_TAG_LX_CHR 0x80000025
> #define IO_REPARSE_TAG_LX_BLK 0x80000026
>
> +/* If Name Surrogate Bit is set, the file or directory represents another named entity in the system. */
> +#define IS_REPARSE_TAG_NAME_SURROGATE(tag) (!!((tag) & 0x20000000))
> +
> /* fsctl flags */
> /* If Flags is set to this value, the request is an FSCTL not ioctl request */
> #define SMB2_0_IOCTL_IS_FSCTL 0x00000001
> --
> 2.39.5
>