]> www.infradead.org Git - users/willy/pagecache.git/commitdiff
cifs: Treat unhandled directory name surrogate reparse points as mount directory...
authorPali Rohár <pali@kernel.org>
Tue, 17 Sep 2024 22:28:25 +0000 (00:28 +0200)
committerSteve French <stfrench@microsoft.com>
Wed, 19 Feb 2025 16:42:27 +0000 (10:42 -0600)
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>
fs/smb/client/inode.c
fs/smb/common/smbfsctl.h

index 3261190e6f9032058a1a5f5ed4a445d65fd8b1cf..616149c7f0a5411a2433b6e62a418a652b0aadc8 100644 (file)
@@ -1215,6 +1215,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;
+                       }
                }
 
                if (data->reparse.tag == IO_REPARSE_TAG_SYMLINK && !rc) {
index 4b379e84c46b945382a5f6a03e62172946ca0ce8..3253a18ecb5cbc36d17a7fa6eed217097322f245 100644 (file)
 #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