* [PATCH 0/4] cifs: Add support for querying reparse points from userspace
@ 2024-12-22 15:43 Pali Rohár
2024-12-22 15:43 ` [PATCH 1/4] cifs: Split parse_reparse_point callback to functions: get buffer and parse buffer Pali Rohár
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Pali Rohár @ 2024-12-22 15:43 UTC (permalink / raw)
To: Steve French, Paulo Alcantara, Ronnie Sahlberg; +Cc: linux-cifs, linux-kernel
This patch series add a new xattr system.reparse for querying reparse
point buffer from userspace, fixes errnos related to reparse points and
do not attempt to use reparse points when server does not support them.
Add new reparse point or changing/deleting existing reparse point is not
implemented yet, can be done in the future via setxattr()/removexattr().
Pali Rohár (4):
cifs: Split parse_reparse_point callback to functions: get buffer and
parse buffer
cifs: Add a new xattr system.reparse for querying repase point from
SMB server
cifs: Change translation of STATUS_NOT_A_REPARSE_POINT to -ENODATA
cifs: Check if server supports reparse points before using them
fs/smb/client/cifsglob.h | 6 ++---
fs/smb/client/cifssmb.c | 3 +++
fs/smb/client/inode.c | 11 +++++----
fs/smb/client/link.c | 3 ++-
fs/smb/client/netmisc.c | 7 ++++++
fs/smb/client/nterr.c | 1 +
fs/smb/client/nterr.h | 1 +
fs/smb/client/reparse.c | 15 ++++--------
fs/smb/client/reparse.h | 5 +---
fs/smb/client/smb1ops.c | 17 +++++--------
fs/smb/client/smb2inode.c | 8 +++++++
fs/smb/client/smb2maperror.c | 2 +-
fs/smb/client/smb2ops.c | 12 +++++-----
fs/smb/client/xattr.c | 46 ++++++++++++++++++++++++++++++++++++
14 files changed, 96 insertions(+), 41 deletions(-)
--
2.20.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/4] cifs: Split parse_reparse_point callback to functions: get buffer and parse buffer
2024-12-22 15:43 [PATCH 0/4] cifs: Add support for querying reparse points from userspace Pali Rohár
@ 2024-12-22 15:43 ` Pali Rohár
2024-12-22 15:43 ` [PATCH 2/4] cifs: Add a new xattr system.reparse for querying repase point from SMB server Pali Rohár
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Pali Rohár @ 2024-12-22 15:43 UTC (permalink / raw)
To: Steve French, Paulo Alcantara, Ronnie Sahlberg; +Cc: linux-cifs, linux-kernel
Parsing reparse point buffer is generic for all SMB versions and is already
implemented by global function parse_reparse_point().
Getting reparse point buffer from the SMB response is SMB version specific,
so introduce for it a new callback get_reparse_point_buffer.
This functionality split is needed for next change - getting reparse point
buffer without parsing it.
Signed-off-by: Pali Rohár <pali@kernel.org>
---
fs/smb/client/cifsglob.h | 6 ++----
fs/smb/client/inode.c | 11 +++++++----
fs/smb/client/reparse.c | 15 +++++----------
fs/smb/client/reparse.h | 5 +----
fs/smb/client/smb1ops.c | 17 ++++++-----------
fs/smb/client/smb2ops.c | 8 ++++----
6 files changed, 25 insertions(+), 37 deletions(-)
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index 369458d37f99..d4c60d85d7a4 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -629,10 +629,8 @@ struct smb_version_operations {
bool (*is_status_io_timeout)(char *buf);
/* Check for STATUS_NETWORK_NAME_DELETED */
bool (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv);
- int (*parse_reparse_point)(struct cifs_sb_info *cifs_sb,
- const char *full_path,
- struct kvec *rsp_iov,
- struct cifs_open_info_data *data);
+ struct reparse_data_buffer * (*get_reparse_point_buffer)(const struct kvec *rsp_iov,
+ u32 *plen);
int (*create_reparse_symlink)(const unsigned int xid,
struct inode *inode,
struct dentry *dentry,
diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
index ed32d78971f8..b295d161373c 100644
--- a/fs/smb/client/inode.c
+++ b/fs/smb/client/inode.c
@@ -1207,10 +1207,13 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
/* Check for cached reparse point data */
if (data->symlink_target || data->reparse.buf) {
rc = 0;
- } else if (iov && server->ops->parse_reparse_point) {
- rc = server->ops->parse_reparse_point(cifs_sb,
- full_path,
- iov, data);
+ } else if (iov && server->ops->get_reparse_point_buffer) {
+ struct reparse_data_buffer *reparse_buf;
+ u32 reparse_len;
+
+ reparse_buf = server->ops->get_reparse_point_buffer(iov, &reparse_len);
+ rc = parse_reparse_point(reparse_buf, reparse_len,
+ cifs_sb, full_path, data);
/*
* If the reparse point was not handled but it is the
* name surrogate which points to directory, then treat
diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
index 6ffda4455f9b..f01214d6c5d4 100644
--- a/fs/smb/client/reparse.c
+++ b/fs/smb/client/reparse.c
@@ -1096,18 +1096,13 @@ int parse_reparse_point(struct reparse_data_buffer *buf,
}
}
-int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb,
- const char *full_path,
- struct kvec *rsp_iov,
- struct cifs_open_info_data *data)
+struct reparse_data_buffer *smb2_get_reparse_point_buffer(const struct kvec *rsp_iov,
+ u32 *plen)
{
- struct reparse_data_buffer *buf;
struct smb2_ioctl_rsp *io = rsp_iov->iov_base;
- u32 plen = le32_to_cpu(io->OutputCount);
-
- buf = (struct reparse_data_buffer *)((u8 *)io +
- le32_to_cpu(io->OutputOffset));
- return parse_reparse_point(buf, plen, cifs_sb, full_path, data);
+ *plen = le32_to_cpu(io->OutputCount);
+ return (struct reparse_data_buffer *)((u8 *)io +
+ le32_to_cpu(io->OutputOffset));
}
static void wsl_to_fattr(struct cifs_open_info_data *data,
diff --git a/fs/smb/client/reparse.h b/fs/smb/client/reparse.h
index 5a753fec7e2c..c17130657def 100644
--- a/fs/smb/client/reparse.h
+++ b/fs/smb/client/reparse.h
@@ -119,9 +119,6 @@ int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
int smb2_mknod_reparse(unsigned int xid, struct inode *inode,
struct dentry *dentry, struct cifs_tcon *tcon,
const char *full_path, umode_t mode, dev_t dev);
-int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb,
- const char *full_path,
- struct kvec *rsp_iov,
- struct cifs_open_info_data *data);
+struct reparse_data_buffer *smb2_get_reparse_point_buffer(const struct kvec *rsp_iov, u32 *len);
#endif /* _CIFS_REPARSE_H */
diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
index 3667fb94cbf5..01a7d6b23c7e 100644
--- a/fs/smb/client/smb1ops.c
+++ b/fs/smb/client/smb1ops.c
@@ -993,18 +993,13 @@ static int cifs_query_symlink(const unsigned int xid,
return rc;
}
-static int cifs_parse_reparse_point(struct cifs_sb_info *cifs_sb,
- const char *full_path,
- struct kvec *rsp_iov,
- struct cifs_open_info_data *data)
+static struct reparse_data_buffer *cifs_get_reparse_point_buffer(const struct kvec *rsp_iov,
+ u32 *plen)
{
- struct reparse_data_buffer *buf;
TRANSACT_IOCTL_RSP *io = rsp_iov->iov_base;
- u32 plen = le16_to_cpu(io->ByteCount);
-
- buf = (struct reparse_data_buffer *)((__u8 *)&io->hdr.Protocol +
- le32_to_cpu(io->DataOffset));
- return parse_reparse_point(buf, plen, cifs_sb, full_path, data);
+ *plen = le16_to_cpu(io->ByteCount);
+ return (struct reparse_data_buffer *)((__u8 *)&io->hdr.Protocol +
+ le32_to_cpu(io->DataOffset));
}
static bool
@@ -1139,7 +1134,7 @@ struct smb_version_operations smb1_operations = {
.rename = CIFSSMBRename,
.create_hardlink = CIFSCreateHardLink,
.query_symlink = cifs_query_symlink,
- .parse_reparse_point = cifs_parse_reparse_point,
+ .get_reparse_point_buffer = cifs_get_reparse_point_buffer,
.open = cifs_open_file,
.set_fid = cifs_set_fid,
.close = cifs_close_file,
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 87cb1872db28..0a91f18d4a54 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -5270,7 +5270,7 @@ struct smb_version_operations smb20_operations = {
.unlink = smb2_unlink,
.rename = smb2_rename_path,
.create_hardlink = smb2_create_hardlink,
- .parse_reparse_point = smb2_parse_reparse_point,
+ .get_reparse_point_buffer = smb2_get_reparse_point_buffer,
.query_mf_symlink = smb3_query_mf_symlink,
.create_mf_symlink = smb3_create_mf_symlink,
.create_reparse_symlink = smb2_create_reparse_symlink,
@@ -5373,7 +5373,7 @@ struct smb_version_operations smb21_operations = {
.unlink = smb2_unlink,
.rename = smb2_rename_path,
.create_hardlink = smb2_create_hardlink,
- .parse_reparse_point = smb2_parse_reparse_point,
+ .get_reparse_point_buffer = smb2_get_reparse_point_buffer,
.query_mf_symlink = smb3_query_mf_symlink,
.create_mf_symlink = smb3_create_mf_symlink,
.create_reparse_symlink = smb2_create_reparse_symlink,
@@ -5480,7 +5480,7 @@ struct smb_version_operations smb30_operations = {
.unlink = smb2_unlink,
.rename = smb2_rename_path,
.create_hardlink = smb2_create_hardlink,
- .parse_reparse_point = smb2_parse_reparse_point,
+ .get_reparse_point_buffer = smb2_get_reparse_point_buffer,
.query_mf_symlink = smb3_query_mf_symlink,
.create_mf_symlink = smb3_create_mf_symlink,
.create_reparse_symlink = smb2_create_reparse_symlink,
@@ -5596,7 +5596,7 @@ struct smb_version_operations smb311_operations = {
.unlink = smb2_unlink,
.rename = smb2_rename_path,
.create_hardlink = smb2_create_hardlink,
- .parse_reparse_point = smb2_parse_reparse_point,
+ .get_reparse_point_buffer = smb2_get_reparse_point_buffer,
.query_mf_symlink = smb3_query_mf_symlink,
.create_mf_symlink = smb3_create_mf_symlink,
.create_reparse_symlink = smb2_create_reparse_symlink,
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/4] cifs: Add a new xattr system.reparse for querying repase point from SMB server
2024-12-22 15:43 [PATCH 0/4] cifs: Add support for querying reparse points from userspace Pali Rohár
2024-12-22 15:43 ` [PATCH 1/4] cifs: Split parse_reparse_point callback to functions: get buffer and parse buffer Pali Rohár
@ 2024-12-22 15:43 ` Pali Rohár
2024-12-22 15:43 ` [PATCH 3/4] cifs: Change translation of STATUS_NOT_A_REPARSE_POINT to -ENODATA Pali Rohár
2024-12-22 15:43 ` [PATCH 4/4] cifs: Check if server supports reparse points before using them Pali Rohár
3 siblings, 0 replies; 5+ messages in thread
From: Pali Rohár @ 2024-12-22 15:43 UTC (permalink / raw)
To: Steve French, Paulo Alcantara, Ronnie Sahlberg; +Cc: linux-cifs, linux-kernel
Currently SMB client fetches and parses only few reparse point types,
those which directly maps to Linux file types.
This change introduce a new xattr system.reparse which allows userspace
application to query reparse point buffer and then let application to parse
and handle it as needed.
Currently only get xattr is implemented. Setting new reparse point,
changing it or deleting via set xattr is not implemented yet.
Signed-off-by: Pali Rohár <pali@kernel.org>
---
fs/smb/client/xattr.c | 46 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/fs/smb/client/xattr.c b/fs/smb/client/xattr.c
index b88fa04f5792..7fb7662afaea 100644
--- a/fs/smb/client/xattr.c
+++ b/fs/smb/client/xattr.c
@@ -39,7 +39,10 @@
#define SMB3_XATTR_CREATETIME "smb3.creationtime" /* user.smb3.creationtime */
/* BB need to add server (Samba e.g) support for security and trusted prefix */
+#define SMB_XATTR_REPARSE "system.reparse"
+
enum { XATTR_USER, XATTR_CIFS_ACL, XATTR_ACL_ACCESS, XATTR_ACL_DEFAULT,
+ XATTR_REPARSE,
XATTR_CIFS_NTSD_SACL, XATTR_CIFS_NTSD_OWNER,
XATTR_CIFS_NTSD, XATTR_CIFS_NTSD_FULL };
@@ -162,6 +165,11 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
}
break;
+ case XATTR_REPARSE:
+ /* TODO: Implementing setting, changing and deleting reparse point */
+ rc = -EOPNOTSUPP;
+ break;
+
case XATTR_CIFS_ACL:
case XATTR_CIFS_NTSD_SACL:
case XATTR_CIFS_NTSD_OWNER:
@@ -319,6 +327,36 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
full_path, name, value, size, cifs_sb);
break;
+ case XATTR_REPARSE: {
+ struct reparse_data_buffer *reparse_buf;
+ int rsp_buftype = CIFS_NO_BUFFER;
+ struct kvec rsp_iov = {};
+ u32 reparse_len;
+ u32 tag;
+
+ if (!pTcon->ses->server->ops->query_reparse_point)
+ goto out;
+
+ rc = pTcon->ses->server->ops->query_reparse_point(xid, pTcon,
+ cifs_sb, full_path, &tag, &rsp_iov, &rsp_buftype);
+ if (rc)
+ goto out;
+
+ reparse_buf = pTcon->ses->server->ops->get_reparse_point_buffer(&rsp_iov,
+ &reparse_len);
+
+ if (value) {
+ if (reparse_len > size)
+ reparse_len = -ERANGE;
+ else
+ memcpy(value, reparse_buf, reparse_len);
+ }
+ rc = reparse_len;
+
+ free_rsp_buf(rsp_buftype, rsp_iov.iov_base);
+ break;
+ }
+
case XATTR_CIFS_ACL:
case XATTR_CIFS_NTSD_SACL:
case XATTR_CIFS_NTSD_OWNER:
@@ -448,6 +486,13 @@ static const struct xattr_handler cifs_os2_xattr_handler = {
.set = cifs_xattr_set,
};
+static const struct xattr_handler cifs_reparse_xattr_handler = {
+ .name = SMB_XATTR_REPARSE,
+ .flags = XATTR_REPARSE,
+ .get = cifs_xattr_get,
+ .set = cifs_xattr_set,
+};
+
static const struct xattr_handler cifs_cifs_acl_xattr_handler = {
.name = CIFS_XATTR_CIFS_ACL,
.flags = XATTR_CIFS_ACL,
@@ -525,6 +570,7 @@ static const struct xattr_handler smb3_ntsd_full_xattr_handler = {
const struct xattr_handler * const cifs_xattr_handlers[] = {
&cifs_user_xattr_handler,
&cifs_os2_xattr_handler,
+ &cifs_reparse_xattr_handler,
&cifs_cifs_acl_xattr_handler,
&smb3_acl_xattr_handler, /* alias for above since avoiding "cifs" */
&smb3_ntsd_sacl_xattr_handler,
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/4] cifs: Change translation of STATUS_NOT_A_REPARSE_POINT to -ENODATA
2024-12-22 15:43 [PATCH 0/4] cifs: Add support for querying reparse points from userspace Pali Rohár
2024-12-22 15:43 ` [PATCH 1/4] cifs: Split parse_reparse_point callback to functions: get buffer and parse buffer Pali Rohár
2024-12-22 15:43 ` [PATCH 2/4] cifs: Add a new xattr system.reparse for querying repase point from SMB server Pali Rohár
@ 2024-12-22 15:43 ` Pali Rohár
2024-12-22 15:43 ` [PATCH 4/4] cifs: Check if server supports reparse points before using them Pali Rohár
3 siblings, 0 replies; 5+ messages in thread
From: Pali Rohár @ 2024-12-22 15:43 UTC (permalink / raw)
To: Steve French, Paulo Alcantara, Ronnie Sahlberg; +Cc: linux-cifs, linux-kernel
STATUS_NOT_A_REPARSE_POINT indicates that object does not have repase point
buffer attached, for example returned by FSCTL_GET_REPARSE_POINT.
Currently STATUS_NOT_A_REPARSE_POINT is translated to -EIO. Change it to
-ENODATA which better describe the situation when no reparse point is set.
Signed-off-by: Pali Rohár <pali@kernel.org>
---
fs/smb/client/netmisc.c | 7 +++++++
fs/smb/client/nterr.c | 1 +
fs/smb/client/nterr.h | 1 +
fs/smb/client/smb2maperror.c | 2 +-
4 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/fs/smb/client/netmisc.c b/fs/smb/client/netmisc.c
index a2fb1ae14d41..0ff3ccc7a356 100644
--- a/fs/smb/client/netmisc.c
+++ b/fs/smb/client/netmisc.c
@@ -871,6 +871,13 @@ map_smb_to_linux_error(char *buf, bool logErr)
}
/* else ERRHRD class errors or junk - return EIO */
+ /* special cases for NT status codes which cannot be translated to DOS codes */
+ if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
+ __u32 err = le32_to_cpu(smb->Status.CifsError);
+ if (err == (NT_STATUS_NOT_A_REPARSE_POINT))
+ rc = -ENODATA;
+ }
+
cifs_dbg(FYI, "Mapping smb error code 0x%x to POSIX err %d\n",
le32_to_cpu(smb->Status.CifsError), rc);
diff --git a/fs/smb/client/nterr.c b/fs/smb/client/nterr.c
index 358a766375b4..777431912e64 100644
--- a/fs/smb/client/nterr.c
+++ b/fs/smb/client/nterr.c
@@ -667,6 +667,7 @@ const struct nt_err_code_struct nt_errs[] = {
{"NT_STATUS_QUOTA_LIST_INCONSISTENT",
NT_STATUS_QUOTA_LIST_INCONSISTENT},
{"NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE},
+ {"NT_STATUS_NOT_A_REPARSE_POINT", NT_STATUS_NOT_A_REPARSE_POINT},
{"NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES},
{"NT_STATUS_MORE_ENTRIES", NT_STATUS_MORE_ENTRIES},
{"NT_STATUS_SOME_UNMAPPED", NT_STATUS_SOME_UNMAPPED},
diff --git a/fs/smb/client/nterr.h b/fs/smb/client/nterr.h
index edd4741cab0a..180602c22355 100644
--- a/fs/smb/client/nterr.h
+++ b/fs/smb/client/nterr.h
@@ -546,6 +546,7 @@ extern const struct nt_err_code_struct nt_errs[];
#define NT_STATUS_TOO_MANY_LINKS 0xC0000000 | 0x0265
#define NT_STATUS_QUOTA_LIST_INCONSISTENT 0xC0000000 | 0x0266
#define NT_STATUS_FILE_IS_OFFLINE 0xC0000000 | 0x0267
+#define NT_STATUS_NOT_A_REPARSE_POINT 0xC0000000 | 0x0275
#define NT_STATUS_NO_SUCH_JOB 0xC0000000 | 0xEDE /* scheduler */
#endif /* _NTERR_H */
diff --git a/fs/smb/client/smb2maperror.c b/fs/smb/client/smb2maperror.c
index 00c0bd79c074..daa56b2a2a1a 100644
--- a/fs/smb/client/smb2maperror.c
+++ b/fs/smb/client/smb2maperror.c
@@ -871,7 +871,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
{STATUS_VALIDATE_CONTINUE, -EIO, "STATUS_VALIDATE_CONTINUE"},
{STATUS_NO_MATCH, -EIO, "STATUS_NO_MATCH"},
{STATUS_NO_MORE_MATCHES, -EIO, "STATUS_NO_MORE_MATCHES"},
- {STATUS_NOT_A_REPARSE_POINT, -EIO, "STATUS_NOT_A_REPARSE_POINT"},
+ {STATUS_NOT_A_REPARSE_POINT, -ENODATA, "STATUS_NOT_A_REPARSE_POINT"},
{STATUS_IO_REPARSE_TAG_INVALID, -EIO, "STATUS_IO_REPARSE_TAG_INVALID"},
{STATUS_IO_REPARSE_TAG_MISMATCH, -EIO,
"STATUS_IO_REPARSE_TAG_MISMATCH"},
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 4/4] cifs: Check if server supports reparse points before using them
2024-12-22 15:43 [PATCH 0/4] cifs: Add support for querying reparse points from userspace Pali Rohár
` (2 preceding siblings ...)
2024-12-22 15:43 ` [PATCH 3/4] cifs: Change translation of STATUS_NOT_A_REPARSE_POINT to -ENODATA Pali Rohár
@ 2024-12-22 15:43 ` Pali Rohár
3 siblings, 0 replies; 5+ messages in thread
From: Pali Rohár @ 2024-12-22 15:43 UTC (permalink / raw)
To: Steve French, Paulo Alcantara, Ronnie Sahlberg; +Cc: linux-cifs, linux-kernel
Do not attempt to query or create reparse point when server fs does not
support it. This will prevent creating unusable empty object on the server.
Signed-off-by: Pali Rohár <pali@kernel.org>
---
fs/smb/client/cifssmb.c | 3 +++
fs/smb/client/link.c | 3 ++-
fs/smb/client/smb2inode.c | 8 ++++++++
fs/smb/client/smb2ops.c | 4 ++--
4 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c
index 2763db49b155..83365861a99c 100644
--- a/fs/smb/client/cifssmb.c
+++ b/fs/smb/client/cifssmb.c
@@ -2695,6 +2695,9 @@ int cifs_query_reparse_point(const unsigned int xid,
if (cap_unix(tcon->ses))
return -EOPNOTSUPP;
+ if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS))
+ return -EOPNOTSUPP;
+
oparms = (struct cifs_open_parms) {
.tcon = tcon,
.cifs_sb = cifs_sb,
diff --git a/fs/smb/client/link.c b/fs/smb/client/link.c
index 6e6c09cc5ce7..a88253668286 100644
--- a/fs/smb/client/link.c
+++ b/fs/smb/client/link.c
@@ -643,7 +643,8 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
case CIFS_SYMLINK_TYPE_NATIVE:
case CIFS_SYMLINK_TYPE_NFS:
case CIFS_SYMLINK_TYPE_WSL:
- if (server->ops->create_reparse_symlink) {
+ if (server->ops->create_reparse_symlink &&
+ (le32_to_cpu(pTcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS)) {
rc = server->ops->create_reparse_symlink(xid, inode,
direntry,
pTcon,
diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
index 379ac3cbad1f..818537c83d41 100644
--- a/fs/smb/client/smb2inode.c
+++ b/fs/smb/client/smb2inode.c
@@ -1289,6 +1289,14 @@ struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
int rc;
int i;
+ /*
+ * If server filesystem does not support reparse points then do not
+ * attempt to create reparse point. This will prevent creating unusable
+ * empty object on the server.
+ */
+ if (!(le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS))
+ return ERR_PTR(-EOPNOTSUPP);
+
oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
SYNCHRONIZE | DELETE |
FILE_READ_ATTRIBUTES |
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 0a91f18d4a54..50adb5cdfce9 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -5202,7 +5202,7 @@ static int smb2_make_node(unsigned int xid, struct inode *inode,
const char *full_path, umode_t mode, dev_t dev)
{
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- int rc;
+ int rc = -EOPNOTSUPP;
/*
* Check if mounted with mount parm 'sfu' mount parm.
@@ -5213,7 +5213,7 @@ static int smb2_make_node(unsigned int xid, struct inode *inode,
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
rc = cifs_sfu_make_node(xid, inode, dentry, tcon,
full_path, mode, dev);
- } else {
+ } else if (le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) {
rc = smb2_mknod_reparse(xid, inode, dentry, tcon,
full_path, mode, dev);
}
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-12-22 15:44 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-22 15:43 [PATCH 0/4] cifs: Add support for querying reparse points from userspace Pali Rohár
2024-12-22 15:43 ` [PATCH 1/4] cifs: Split parse_reparse_point callback to functions: get buffer and parse buffer Pali Rohár
2024-12-22 15:43 ` [PATCH 2/4] cifs: Add a new xattr system.reparse for querying repase point from SMB server Pali Rohár
2024-12-22 15:43 ` [PATCH 3/4] cifs: Change translation of STATUS_NOT_A_REPARSE_POINT to -ENODATA Pali Rohár
2024-12-22 15:43 ` [PATCH 4/4] cifs: Check if server supports reparse points before using them Pali Rohár
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox