* [PATCH 1/3] cifs: Remove declaration of dead CIFSSMBQuerySymLink function
@ 2024-12-27 17:40 Pali Rohár
2024-12-27 17:40 ` [PATCH 2/3] cifs: Fix validation of SMB1 query reparse point response Pali Rohár
2024-12-27 17:40 ` [PATCH 3/3] cifs: Add support for creating reparse points over SMB1 Pali Rohár
0 siblings, 2 replies; 4+ messages in thread
From: Pali Rohár @ 2024-12-27 17:40 UTC (permalink / raw)
To: Steve French, Paulo Alcantara; +Cc: linux-cifs, linux-kernel
Function CIFSSMBQuerySymLink() was renamed to cifs_query_reparse_point() in
commit ed3e0a149b58 ("smb: client: implement ->query_reparse_point() for
SMB1"). Remove its dead declaration from header file too.
Signed-off-by: Pali Rohár <pali@kernel.org>
---
fs/smb/client/cifsproto.h | 3 ---
1 file changed, 3 deletions(-)
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index f0ca99e6090c..9833837c6299 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -477,9 +477,6 @@ extern int cifs_query_reparse_point(const unsigned int xid,
const char *full_path,
u32 *tag, struct kvec *rsp,
int *rsp_buftype);
-extern int CIFSSMBQuerySymLink(const unsigned int xid, struct cifs_tcon *tcon,
- __u16 fid, char **symlinkinfo,
- const struct nls_table *nls_codepage);
extern int CIFSSMB_set_compression(const unsigned int xid,
struct cifs_tcon *tcon, __u16 fid);
extern int CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms,
--
2.20.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/3] cifs: Fix validation of SMB1 query reparse point response
2024-12-27 17:40 [PATCH 1/3] cifs: Remove declaration of dead CIFSSMBQuerySymLink function Pali Rohár
@ 2024-12-27 17:40 ` Pali Rohár
2024-12-27 17:40 ` [PATCH 3/3] cifs: Add support for creating reparse points over SMB1 Pali Rohár
1 sibling, 0 replies; 4+ messages in thread
From: Pali Rohár @ 2024-12-27 17:40 UTC (permalink / raw)
To: Steve French, Paulo Alcantara; +Cc: linux-cifs, linux-kernel
NT_TRANSACT_IOCTL response contains one word long setup data after which is
ByteCount member. So check that SetupCount is 1 before trying to read and
use ByteCount member.
Output setup data contains ReturnedDataLen member which is the output
length of executed IOCTL command by remote system. So check that output was
not truncated before transferring over network.
Change MaxSetupCount of NT_TRANSACT_IOCTL request from 4 to 1 as io_rsp
structure already expects one word long output setup data. This should
prevent server sending incompatible structure (in case it would be extended
in future, which is unlikely).
Change MaxParameterCount of NT_TRANSACT_IOCTL request from 2 to 0 as
NT IOCTL does not have any documented output parameters and this function
does not parse any output parameters at all.
Fixes: ed3e0a149b58 ("smb: client: implement ->query_reparse_point() for SMB1")
Signed-off-by: Pali Rohár <pali@kernel.org>
---
fs/smb/client/cifssmb.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c
index 83365861a99c..ff8633fde85c 100644
--- a/fs/smb/client/cifssmb.c
+++ b/fs/smb/client/cifssmb.c
@@ -2720,10 +2720,10 @@ int cifs_query_reparse_point(const unsigned int xid,
io_req->TotalParameterCount = 0;
io_req->TotalDataCount = 0;
- io_req->MaxParameterCount = cpu_to_le32(2);
+ io_req->MaxParameterCount = cpu_to_le32(0);
/* BB find exact data count max from sess structure BB */
io_req->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00);
- io_req->MaxSetupCount = 4;
+ io_req->MaxSetupCount = 1;
io_req->Reserved = 0;
io_req->ParameterOffset = 0;
io_req->DataCount = 0;
@@ -2750,6 +2750,22 @@ int cifs_query_reparse_point(const unsigned int xid,
goto error;
}
+ /* SetupCount must be 1, otherwise offset to ByteCount is incorrect. */
+ if (io_rsp->SetupCount != 1) {
+ rc = -EIO;
+ goto error;
+ }
+
+ /*
+ * ReturnedDataLen is output length of executed IOCTL.
+ * DataCount is output length transferred over network.
+ * Check that we have full FSCTL_GET_REPARSE_POINT buffer.
+ */
+ if (data_count != le16_to_cpu(io_rsp->ReturnedDataLen)) {
+ rc = -EIO;
+ goto error;
+ }
+
end = 2 + get_bcc(&io_rsp->hdr) + (__u8 *)&io_rsp->ByteCount;
start = (__u8 *)&io_rsp->hdr.Protocol + data_offset;
if (start >= end) {
--
2.20.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/3] cifs: Add support for creating reparse points over SMB1
2024-12-27 17:40 [PATCH 1/3] cifs: Remove declaration of dead CIFSSMBQuerySymLink function Pali Rohár
2024-12-27 17:40 ` [PATCH 2/3] cifs: Fix validation of SMB1 query reparse point response Pali Rohár
@ 2024-12-27 17:40 ` Pali Rohár
2025-01-01 13:14 ` Pali Rohár
1 sibling, 1 reply; 4+ messages in thread
From: Pali Rohár @ 2024-12-27 17:40 UTC (permalink / raw)
To: Steve French, Paulo Alcantara; +Cc: linux-cifs, linux-kernel
SMB1 already supports querying reparse points and detecting types of
symlink, fifo, socket, block and char.
This change implements the missing part - ability to create a new reparse
points over SMB1. This includes everything which SMB2+ already supports:
- native SMB symlinks and sockets
- NFS style of special files (symlinks, fifos, sockets, char/block devs)
- WSL style of special files (symlinks, fifos, sockets, char/block devs)
Attaching a reparse point to an existing file or directory is done via
SMB1 SMB_COM_NT_TRANSACT/NT_TRANSACT_IOCTL/FSCTL_SET_REPARSE_POINT command
and implemented in a new cifs_create_reparse_inode() function.
This change introduce a new callback ->create_reparse_inode() which creates
a new reperse point file or directory and returns inode. For SMB1 it is
provided via that new cifs_create_reparse_inode() function.
Existing reparse.c code was only slightly updated to call new protocol
callback ->create_reparse_inode() instead of hardcoded SMB2+ function.
This make the whole reparse.c code to work with every SMB dialect.
The original callback ->create_reparse_symlink() is not needed anymore as
the implementation of new create_reparse_symlink() function is dialect
agnostic too. So the link.c code was updated to call that function directly
(and not via callback).
Signed-off-by: Pali Rohár <pali@kernel.org>
---
fs/smb/client/cifsglob.h | 14 +++--
fs/smb/client/cifsproto.h | 8 +++
fs/smb/client/cifssmb.c | 128 ++++++++++++++++++++++++++++++++++++++
fs/smb/client/link.c | 13 ++--
fs/smb/client/reparse.c | 16 +++--
fs/smb/client/reparse.h | 4 +-
fs/smb/client/smb1ops.c | 31 ++++++---
fs/smb/client/smb2inode.c | 2 +-
fs/smb/client/smb2ops.c | 10 +--
fs/smb/client/smb2proto.h | 5 +-
10 files changed, 188 insertions(+), 43 deletions(-)
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index e1deb5f6209d..06ad727e824b 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -625,12 +625,14 @@ struct smb_version_operations {
bool (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv);
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,
- struct cifs_tcon *tcon,
- const char *full_path,
- const char *symname);
+ struct inode * (*create_reparse_inode)(struct cifs_open_info_data *data,
+ struct super_block *sb,
+ const unsigned int xid,
+ struct cifs_tcon *tcon,
+ const char *full_path,
+ bool directory,
+ struct kvec *reparse_iov,
+ struct kvec *xattr_iov);
};
struct smb_version_values {
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index 9833837c6299..ea8a0ecce9dc 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -477,6 +477,14 @@ extern int cifs_query_reparse_point(const unsigned int xid,
const char *full_path,
u32 *tag, struct kvec *rsp,
int *rsp_buftype);
+extern struct inode *cifs_create_reparse_inode(struct cifs_open_info_data *data,
+ struct super_block *sb,
+ const unsigned int xid,
+ struct cifs_tcon *tcon,
+ const char *full_path,
+ bool directory,
+ struct kvec *reparse_iov,
+ struct kvec *xattr_iov);
extern int CIFSSMB_set_compression(const unsigned int xid,
struct cifs_tcon *tcon, __u16 fid);
extern int CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms,
diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c
index ff8633fde85c..dd71c4c8f776 100644
--- a/fs/smb/client/cifssmb.c
+++ b/fs/smb/client/cifssmb.c
@@ -2795,6 +2795,134 @@ int cifs_query_reparse_point(const unsigned int xid,
return rc;
}
+struct inode *cifs_create_reparse_inode(struct cifs_open_info_data *data,
+ struct super_block *sb,
+ const unsigned int xid,
+ struct cifs_tcon *tcon,
+ const char *full_path,
+ bool directory,
+ struct kvec *reparse_iov,
+ struct kvec *xattr_iov)
+{
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ struct cifs_open_parms oparms;
+ TRANSACT_IOCTL_REQ *io_req;
+ struct inode *new = NULL;
+ struct kvec in_iov[2];
+ struct kvec out_iov;
+ struct cifs_fid fid;
+ int io_req_len;
+ int oplock = 0;
+ int buf_type = 0;
+ int rc;
+
+ cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
+
+ /*
+ * 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);
+
+#ifndef CONFIG_CIFS_XATTR
+ if (xattr_iov)
+ return ERR_PTR(-EOPNOTSUPP);
+#endif
+
+ oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
+ FILE_READ_ATTRIBUTES | FILE_WRITE_DATA | FILE_WRITE_EA,
+ FILE_CREATE,
+ (directory ? CREATE_NOT_FILE : CREATE_NOT_DIR) | OPEN_REPARSE_POINT,
+ ACL_NO_MODE);
+ oparms.fid = &fid;
+
+ rc = CIFS_open(xid, &oparms, &oplock, NULL);
+ if (rc)
+ return ERR_PTR(rc);
+
+#ifdef CONFIG_CIFS_XATTR
+ if (xattr_iov) {
+ struct smb2_file_full_ea_info *ea;
+
+ ea = &((struct smb2_create_ea_ctx *)xattr_iov->iov_base)->ea;
+ while (1) {
+ rc = CIFSSMBSetEA(xid,
+ tcon,
+ full_path,
+ &ea->ea_data[0],
+ &ea->ea_data[ea->ea_name_length+1],
+ le16_to_cpu(ea->ea_value_length),
+ cifs_sb->local_nls,
+ cifs_sb);
+ if (rc)
+ goto out_close;
+ if (le32_to_cpu(ea->next_entry_offset) == 0)
+ break;
+ ea = (struct smb2_file_full_ea_info *)((u8 *)ea +
+ le32_to_cpu(ea->next_entry_offset));
+ }
+ }
+#endif
+
+ rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **)&io_req, NULL);
+ if (rc)
+ goto out_close;
+
+ inc_rfc1001_len(io_req, sizeof(io_req->Pad));
+
+ io_req_len = be32_to_cpu(io_req->hdr.smb_buf_length) + sizeof(io_req->hdr.smb_buf_length);
+
+ /* NT IOCTL response contains one-word long output setup buffer with size of output data. */
+ io_req->MaxSetupCount = 1;
+ /* NT IOCTL response does not contain output parameters. */
+ io_req->MaxParameterCount = cpu_to_le32(0);
+ /* FSCTL_SET_REPARSE_POINT response contains empty output data. */
+ io_req->MaxDataCount = cpu_to_le32(0);
+
+ io_req->TotalParameterCount = cpu_to_le32(0);
+ io_req->TotalDataCount = cpu_to_le32(reparse_iov->iov_len);
+ io_req->ParameterCount = io_req->TotalParameterCount;
+ io_req->ParameterOffset = cpu_to_le32(0);
+ io_req->DataCount = io_req->TotalDataCount;
+ io_req->DataOffset = cpu_to_le32(offsetof(typeof(*io_req), Data) -
+ sizeof(io_req->hdr.smb_buf_length));
+ io_req->SetupCount = 4;
+ io_req->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
+ io_req->FunctionCode = cpu_to_le32(FSCTL_SET_REPARSE_POINT);
+ io_req->Fid = fid.netfid;
+ io_req->IsFsctl = 1;
+ io_req->IsRootFlag = 0;
+ io_req->ByteCount = cpu_to_le32(le32_to_cpu(io_req->DataCount) + sizeof(io_req->Pad));
+
+ inc_rfc1001_len(io_req, reparse_iov->iov_len);
+
+ in_iov[0].iov_base = (char *)io_req;
+ in_iov[0].iov_len = io_req_len;
+ in_iov[1] = *reparse_iov;
+ rc = SendReceive2(xid, tcon->ses, in_iov, ARRAY_SIZE(in_iov), &buf_type,
+ CIFS_NO_RSP_BUF, &out_iov);
+
+ cifs_buf_release(io_req);
+
+ if (!rc)
+ rc = cifs_get_inode_info(&new, full_path, data, sb, xid, NULL);
+
+out_close:
+ CIFSSMBClose(xid, tcon, fid.netfid);
+
+ /*
+ * If CREATE was successful but FSCTL_SET_REPARSE_POINT failed then
+ * remove the intermediate object created by CREATE. Otherwise
+ * empty object stay on the server when reparse call failed.
+ */
+ if (rc)
+ CIFSSMBDelFile(xid, tcon, full_path, cifs_sb, NULL);
+
+ return rc ? ERR_PTR(rc) : new;
+}
+
int
CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
__u16 fid)
diff --git a/fs/smb/client/link.c b/fs/smb/client/link.c
index a88253668286..b1a346e20b07 100644
--- a/fs/smb/client/link.c
+++ b/fs/smb/client/link.c
@@ -19,6 +19,7 @@
#include "smb2proto.h"
#include "cifs_ioctl.h"
#include "fs_context.h"
+#include "reparse.h"
/*
* M-F Symlink Functions - Begin
@@ -570,7 +571,6 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
int rc = -EOPNOTSUPP;
unsigned int xid;
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
- struct TCP_Server_Info *server;
struct tcon_link *tlink;
struct cifs_tcon *pTcon;
const char *full_path;
@@ -593,7 +593,6 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
goto symlink_exit;
}
pTcon = tlink_tcon(tlink);
- server = cifs_pick_channel(pTcon->ses);
full_path = build_path_from_dentry(direntry, page);
if (IS_ERR(full_path)) {
@@ -643,13 +642,9 @@ 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 &&
- (le32_to_cpu(pTcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS)) {
- rc = server->ops->create_reparse_symlink(xid, inode,
- direntry,
- pTcon,
- full_path,
- symname);
+ if (le32_to_cpu(pTcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) {
+ rc = create_reparse_symlink(xid, inode, direntry, pTcon,
+ full_path, symname);
goto symlink_exit;
}
break;
diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
index 9e40f5709c7f..69efbcae6683 100644
--- a/fs/smb/client/reparse.c
+++ b/fs/smb/client/reparse.c
@@ -34,7 +34,7 @@ static int detect_directory_symlink_target(struct cifs_sb_info *cifs_sb,
const char *symname,
bool *directory);
-int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
+int create_reparse_symlink(const unsigned int xid, struct inode *inode,
struct dentry *dentry, struct cifs_tcon *tcon,
const char *full_path, const char *symname)
{
@@ -225,7 +225,8 @@ static int create_native_symlink(const unsigned int xid, struct inode *inode,
iov.iov_base = buf;
iov.iov_len = len;
- new = smb2_get_reparse_inode(&data, inode->i_sb, xid,
+ new = tcon->ses->server->ops->create_reparse_inode(
+ &data, inode->i_sb, xid,
tcon, full_path, directory,
&iov, NULL);
if (!IS_ERR(new))
@@ -397,7 +398,8 @@ static int create_native_socket(const unsigned int xid, struct inode *inode,
struct inode *new;
int rc = 0;
- new = smb2_get_reparse_inode(&data, inode->i_sb, xid,
+ new = tcon->ses->server->ops->create_reparse_inode(
+ &data, inode->i_sb, xid,
tcon, full_path, false, &iov, NULL);
if (!IS_ERR(new))
d_instantiate(dentry, new);
@@ -490,7 +492,8 @@ static int mknod_nfs(unsigned int xid, struct inode *inode,
.symlink_target = kstrdup(symname, GFP_KERNEL),
};
- new = smb2_get_reparse_inode(&data, inode->i_sb, xid,
+ new = tcon->ses->server->ops->create_reparse_inode(
+ &data, inode->i_sb, xid,
tcon, full_path, false, &iov, NULL);
if (!IS_ERR(new))
d_instantiate(dentry, new);
@@ -683,7 +686,8 @@ static int mknod_wsl(unsigned int xid, struct inode *inode,
memcpy(data.wsl.eas, &cc->ea, len);
data.wsl.eas_len = len;
- new = smb2_get_reparse_inode(&data, inode->i_sb,
+ new = tcon->ses->server->ops->create_reparse_inode(
+ &data, inode->i_sb,
xid, tcon, full_path, false,
&reparse_iov, &xattr_iov);
if (!IS_ERR(new))
@@ -696,7 +700,7 @@ static int mknod_wsl(unsigned int xid, struct inode *inode,
return rc;
}
-int smb2_mknod_reparse(unsigned int xid, struct inode *inode,
+int 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)
{
diff --git a/fs/smb/client/reparse.h b/fs/smb/client/reparse.h
index c17130657def..8cb11db076a7 100644
--- a/fs/smb/client/reparse.h
+++ b/fs/smb/client/reparse.h
@@ -113,10 +113,10 @@ static inline bool cifs_open_data_reparse(struct cifs_open_info_data *data)
bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
struct cifs_fattr *fattr,
struct cifs_open_info_data *data);
-int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
+int create_reparse_symlink(const unsigned int xid, struct inode *inode,
struct dentry *dentry, struct cifs_tcon *tcon,
const char *full_path, const char *symname);
-int smb2_mknod_reparse(unsigned int xid, struct inode *inode,
+int 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);
struct reparse_data_buffer *smb2_get_reparse_point_buffer(const struct kvec *rsp_iov, u32 *len);
diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
index c52fc4c1557c..a0a15dda0949 100644
--- a/fs/smb/client/smb1ops.c
+++ b/fs/smb/client/smb1ops.c
@@ -16,6 +16,7 @@
#include "fs_context.h"
#include "nterr.h"
#include "smberr.h"
+#include "reparse.h"
/*
* An NT cancel request header looks just like the original request except:
@@ -1076,17 +1077,26 @@ cifs_make_node(unsigned int xid, struct inode *inode,
if (rc == 0)
d_instantiate(dentry, newinode);
return rc;
+ } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
+ /*
+ * Check if mounted with mount parm 'sfu' mount parm.
+ * SFU emulation should work with all servers
+ * and was used by default in earlier versions of Windows.
+ */
+ return cifs_sfu_make_node(xid, inode, dentry, tcon,
+ full_path, mode, dev);
+ } else if (le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) {
+ /*
+ * mknod via reparse points requires server support for
+ * storing reparse points, which is available since
+ * Windows 2000, but was not widely used until release
+ * of Windows Server 2012 by the Windows NFS server.
+ */
+ return mknod_reparse(xid, inode, dentry, tcon,
+ full_path, mode, dev);
+ } else {
+ return -EOPNOTSUPP;
}
- /*
- * Check if mounted with mount parm 'sfu' mount parm.
- * SFU emulation should work with all servers, but only
- * supports block and char device, socket & fifo,
- * and was used by default in earlier versions of Windows
- */
- if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
- return -EPERM;
- return cifs_sfu_make_node(xid, inode, dentry, tcon,
- full_path, mode, dev);
}
static bool
@@ -1183,6 +1193,7 @@ struct smb_version_operations smb1_operations = {
.create_hardlink = CIFSCreateHardLink,
.query_symlink = cifs_query_symlink,
.get_reparse_point_buffer = cifs_get_reparse_point_buffer,
+ .create_reparse_inode = cifs_create_reparse_inode,
.open = cifs_open_file,
.set_fid = cifs_set_fid,
.close = cifs_close_file,
diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
index 426dbaff270a..0b8d6d8f724d 100644
--- a/fs/smb/client/smb2inode.c
+++ b/fs/smb/client/smb2inode.c
@@ -1305,7 +1305,7 @@ smb2_set_file_info(struct inode *inode, const char *full_path,
return rc;
}
-struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
+struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data,
struct super_block *sb,
const unsigned int xid,
struct cifs_tcon *tcon,
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index ba81b662f5c7..4aa9f3ac4c34 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -5232,7 +5232,7 @@ static int smb2_make_node(unsigned int xid, struct inode *inode,
rc = cifs_sfu_make_node(xid, inode, dentry, tcon,
full_path, mode, dev);
} else if (le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) {
- rc = smb2_mknod_reparse(xid, inode, dentry, tcon,
+ rc = mknod_reparse(xid, inode, dentry, tcon,
full_path, mode, dev);
}
return rc;
@@ -5291,7 +5291,7 @@ struct smb_version_operations smb20_operations = {
.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,
+ .create_reparse_inode = smb2_create_reparse_inode,
.open = smb2_open_file,
.set_fid = smb2_set_fid,
.close = smb2_close_file,
@@ -5394,7 +5394,7 @@ struct smb_version_operations smb21_operations = {
.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,
+ .create_reparse_inode = smb2_create_reparse_inode,
.open = smb2_open_file,
.set_fid = smb2_set_fid,
.close = smb2_close_file,
@@ -5501,7 +5501,7 @@ struct smb_version_operations smb30_operations = {
.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,
+ .create_reparse_inode = smb2_create_reparse_inode,
.open = smb2_open_file,
.set_fid = smb2_set_fid,
.close = smb2_close_file,
@@ -5617,7 +5617,7 @@ struct smb_version_operations smb311_operations = {
.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,
+ .create_reparse_inode = smb2_create_reparse_inode,
.open = smb2_open_file,
.set_fid = smb2_set_fid,
.close = smb2_close_file,
diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h
index 2336dfb23f36..cec5921bfdd2 100644
--- a/fs/smb/client/smb2proto.h
+++ b/fs/smb/client/smb2proto.h
@@ -54,7 +54,7 @@ extern int smb3_handle_read_data(struct TCP_Server_Info *server,
extern int smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb, const char *path,
__u32 *reparse_tag);
-struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
+struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data,
struct super_block *sb,
const unsigned int xid,
struct cifs_tcon *tcon,
@@ -317,9 +317,6 @@ int smb311_posix_query_path_info(const unsigned int xid,
int posix_info_parse(const void *beg, const void *end,
struct smb2_posix_info_parsed *out);
int posix_info_sid_size(const void *beg, const void *end);
-int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
- struct dentry *dentry, struct cifs_tcon *tcon,
- const char *full_path, const char *symname);
int smb2_make_nfs_node(unsigned int xid, struct inode *inode,
struct dentry *dentry, struct cifs_tcon *tcon,
const char *full_path, umode_t mode, dev_t dev);
--
2.20.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 3/3] cifs: Add support for creating reparse points over SMB1
2024-12-27 17:40 ` [PATCH 3/3] cifs: Add support for creating reparse points over SMB1 Pali Rohár
@ 2025-01-01 13:14 ` Pali Rohár
0 siblings, 0 replies; 4+ messages in thread
From: Pali Rohár @ 2025-01-01 13:14 UTC (permalink / raw)
To: Steve French, Paulo Alcantara; +Cc: linux-cifs, linux-kernel
On Friday 27 December 2024 18:40:47 Pali Rohár wrote:
> SMB1 already supports querying reparse points and detecting types of
> symlink, fifo, socket, block and char.
>
> This change implements the missing part - ability to create a new reparse
> points over SMB1. This includes everything which SMB2+ already supports:
> - native SMB symlinks and sockets
> - NFS style of special files (symlinks, fifos, sockets, char/block devs)
> - WSL style of special files (symlinks, fifos, sockets, char/block devs)
>
> Attaching a reparse point to an existing file or directory is done via
> SMB1 SMB_COM_NT_TRANSACT/NT_TRANSACT_IOCTL/FSCTL_SET_REPARSE_POINT command
> and implemented in a new cifs_create_reparse_inode() function.
>
> This change introduce a new callback ->create_reparse_inode() which creates
> a new reperse point file or directory and returns inode. For SMB1 it is
> provided via that new cifs_create_reparse_inode() function.
>
> Existing reparse.c code was only slightly updated to call new protocol
> callback ->create_reparse_inode() instead of hardcoded SMB2+ function.
> This make the whole reparse.c code to work with every SMB dialect.
>
> The original callback ->create_reparse_symlink() is not needed anymore as
> the implementation of new create_reparse_symlink() function is dialect
> agnostic too. So the link.c code was updated to call that function directly
> (and not via callback).
>
> Signed-off-by: Pali Rohár <pali@kernel.org>
> ---
> fs/smb/client/cifsglob.h | 14 +++--
> fs/smb/client/cifsproto.h | 8 +++
> fs/smb/client/cifssmb.c | 128 ++++++++++++++++++++++++++++++++++++++
> fs/smb/client/link.c | 13 ++--
> fs/smb/client/reparse.c | 16 +++--
> fs/smb/client/reparse.h | 4 +-
> fs/smb/client/smb1ops.c | 31 ++++++---
> fs/smb/client/smb2inode.c | 2 +-
> fs/smb/client/smb2ops.c | 10 +--
> fs/smb/client/smb2proto.h | 5 +-
> 10 files changed, 188 insertions(+), 43 deletions(-)
>
> diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
> index e1deb5f6209d..06ad727e824b 100644
> --- a/fs/smb/client/cifsglob.h
> +++ b/fs/smb/client/cifsglob.h
> @@ -625,12 +625,14 @@ struct smb_version_operations {
> bool (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv);
> 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,
> - struct cifs_tcon *tcon,
> - const char *full_path,
> - const char *symname);
> + struct inode * (*create_reparse_inode)(struct cifs_open_info_data *data,
> + struct super_block *sb,
> + const unsigned int xid,
> + struct cifs_tcon *tcon,
> + const char *full_path,
> + bool directory,
> + struct kvec *reparse_iov,
> + struct kvec *xattr_iov);
> };
>
> struct smb_version_values {
> diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
> index 9833837c6299..ea8a0ecce9dc 100644
> --- a/fs/smb/client/cifsproto.h
> +++ b/fs/smb/client/cifsproto.h
> @@ -477,6 +477,14 @@ extern int cifs_query_reparse_point(const unsigned int xid,
> const char *full_path,
> u32 *tag, struct kvec *rsp,
> int *rsp_buftype);
> +extern struct inode *cifs_create_reparse_inode(struct cifs_open_info_data *data,
> + struct super_block *sb,
> + const unsigned int xid,
> + struct cifs_tcon *tcon,
> + const char *full_path,
> + bool directory,
> + struct kvec *reparse_iov,
> + struct kvec *xattr_iov);
> extern int CIFSSMB_set_compression(const unsigned int xid,
> struct cifs_tcon *tcon, __u16 fid);
> extern int CIFS_open(const unsigned int xid, struct cifs_open_parms *oparms,
> diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c
> index ff8633fde85c..dd71c4c8f776 100644
> --- a/fs/smb/client/cifssmb.c
> +++ b/fs/smb/client/cifssmb.c
> @@ -2795,6 +2795,134 @@ int cifs_query_reparse_point(const unsigned int xid,
> return rc;
> }
>
> +struct inode *cifs_create_reparse_inode(struct cifs_open_info_data *data,
> + struct super_block *sb,
> + const unsigned int xid,
> + struct cifs_tcon *tcon,
> + const char *full_path,
> + bool directory,
> + struct kvec *reparse_iov,
> + struct kvec *xattr_iov)
> +{
> + struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
> + struct cifs_open_parms oparms;
> + TRANSACT_IOCTL_REQ *io_req;
> + struct inode *new = NULL;
> + struct kvec in_iov[2];
> + struct kvec out_iov;
> + struct cifs_fid fid;
> + int io_req_len;
> + int oplock = 0;
> + int buf_type = 0;
> + int rc;
> +
> + cifs_tcon_dbg(FYI, "%s: path=%s\n", __func__, full_path);
> +
> + /*
> + * 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);
> +
> +#ifndef CONFIG_CIFS_XATTR
> + if (xattr_iov)
> + return ERR_PTR(-EOPNOTSUPP);
> +#endif
> +
> + oparms = CIFS_OPARMS(cifs_sb, tcon, full_path,
> + FILE_READ_ATTRIBUTES | FILE_WRITE_DATA | FILE_WRITE_EA,
> + FILE_CREATE,
> + (directory ? CREATE_NOT_FILE : CREATE_NOT_DIR) | OPEN_REPARSE_POINT,
> + ACL_NO_MODE);
> + oparms.fid = &fid;
> +
> + rc = CIFS_open(xid, &oparms, &oplock, NULL);
> + if (rc)
> + return ERR_PTR(rc);
> +
> +#ifdef CONFIG_CIFS_XATTR
> + if (xattr_iov) {
> + struct smb2_file_full_ea_info *ea;
> +
> + ea = &((struct smb2_create_ea_ctx *)xattr_iov->iov_base)->ea;
> + while (1) {
> + rc = CIFSSMBSetEA(xid,
> + tcon,
> + full_path,
> + &ea->ea_data[0],
> + &ea->ea_data[ea->ea_name_length+1],
> + le16_to_cpu(ea->ea_value_length),
> + cifs_sb->local_nls,
> + cifs_sb);
> + if (rc)
> + goto out_close;
> + if (le32_to_cpu(ea->next_entry_offset) == 0)
> + break;
> + ea = (struct smb2_file_full_ea_info *)((u8 *)ea +
> + le32_to_cpu(ea->next_entry_offset));
> + }
> + }
> +#endif
> +
> + rc = smb_init(SMB_COM_NT_TRANSACT, 23, tcon, (void **)&io_req, NULL);
> + if (rc)
> + goto out_close;
> +
> + inc_rfc1001_len(io_req, sizeof(io_req->Pad));
> +
> + io_req_len = be32_to_cpu(io_req->hdr.smb_buf_length) + sizeof(io_req->hdr.smb_buf_length);
> +
> + /* NT IOCTL response contains one-word long output setup buffer with size of output data. */
> + io_req->MaxSetupCount = 1;
> + /* NT IOCTL response does not contain output parameters. */
> + io_req->MaxParameterCount = cpu_to_le32(0);
> + /* FSCTL_SET_REPARSE_POINT response contains empty output data. */
> + io_req->MaxDataCount = cpu_to_le32(0);
> +
> + io_req->TotalParameterCount = cpu_to_le32(0);
> + io_req->TotalDataCount = cpu_to_le32(reparse_iov->iov_len);
> + io_req->ParameterCount = io_req->TotalParameterCount;
> + io_req->ParameterOffset = cpu_to_le32(0);
> + io_req->DataCount = io_req->TotalDataCount;
> + io_req->DataOffset = cpu_to_le32(offsetof(typeof(*io_req), Data) -
> + sizeof(io_req->hdr.smb_buf_length));
> + io_req->SetupCount = 4;
> + io_req->SubCommand = cpu_to_le16(NT_TRANSACT_IOCTL);
> + io_req->FunctionCode = cpu_to_le32(FSCTL_SET_REPARSE_POINT);
> + io_req->Fid = fid.netfid;
> + io_req->IsFsctl = 1;
> + io_req->IsRootFlag = 0;
> + io_req->ByteCount = cpu_to_le32(le32_to_cpu(io_req->DataCount) + sizeof(io_req->Pad));
Robot found there endianity issue. ByteCount is only 16-bit LE, so
cpu_to_le16() needs to be used.
> +
> + inc_rfc1001_len(io_req, reparse_iov->iov_len);
> +
> + in_iov[0].iov_base = (char *)io_req;
> + in_iov[0].iov_len = io_req_len;
> + in_iov[1] = *reparse_iov;
> + rc = SendReceive2(xid, tcon->ses, in_iov, ARRAY_SIZE(in_iov), &buf_type,
> + CIFS_NO_RSP_BUF, &out_iov);
> +
> + cifs_buf_release(io_req);
> +
> + if (!rc)
> + rc = cifs_get_inode_info(&new, full_path, data, sb, xid, NULL);
> +
> +out_close:
> + CIFSSMBClose(xid, tcon, fid.netfid);
> +
> + /*
> + * If CREATE was successful but FSCTL_SET_REPARSE_POINT failed then
> + * remove the intermediate object created by CREATE. Otherwise
> + * empty object stay on the server when reparse call failed.
> + */
> + if (rc)
> + CIFSSMBDelFile(xid, tcon, full_path, cifs_sb, NULL);
> +
> + return rc ? ERR_PTR(rc) : new;
> +}
> +
> int
> CIFSSMB_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
> __u16 fid)
> diff --git a/fs/smb/client/link.c b/fs/smb/client/link.c
> index a88253668286..b1a346e20b07 100644
> --- a/fs/smb/client/link.c
> +++ b/fs/smb/client/link.c
> @@ -19,6 +19,7 @@
> #include "smb2proto.h"
> #include "cifs_ioctl.h"
> #include "fs_context.h"
> +#include "reparse.h"
>
> /*
> * M-F Symlink Functions - Begin
> @@ -570,7 +571,6 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
> int rc = -EOPNOTSUPP;
> unsigned int xid;
> struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
> - struct TCP_Server_Info *server;
> struct tcon_link *tlink;
> struct cifs_tcon *pTcon;
> const char *full_path;
> @@ -593,7 +593,6 @@ cifs_symlink(struct mnt_idmap *idmap, struct inode *inode,
> goto symlink_exit;
> }
> pTcon = tlink_tcon(tlink);
> - server = cifs_pick_channel(pTcon->ses);
>
> full_path = build_path_from_dentry(direntry, page);
> if (IS_ERR(full_path)) {
> @@ -643,13 +642,9 @@ 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 &&
> - (le32_to_cpu(pTcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS)) {
> - rc = server->ops->create_reparse_symlink(xid, inode,
> - direntry,
> - pTcon,
> - full_path,
> - symname);
> + if (le32_to_cpu(pTcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) {
> + rc = create_reparse_symlink(xid, inode, direntry, pTcon,
> + full_path, symname);
> goto symlink_exit;
> }
> break;
> diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
> index 9e40f5709c7f..69efbcae6683 100644
> --- a/fs/smb/client/reparse.c
> +++ b/fs/smb/client/reparse.c
> @@ -34,7 +34,7 @@ static int detect_directory_symlink_target(struct cifs_sb_info *cifs_sb,
> const char *symname,
> bool *directory);
>
> -int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
> +int create_reparse_symlink(const unsigned int xid, struct inode *inode,
> struct dentry *dentry, struct cifs_tcon *tcon,
> const char *full_path, const char *symname)
> {
> @@ -225,7 +225,8 @@ static int create_native_symlink(const unsigned int xid, struct inode *inode,
>
> iov.iov_base = buf;
> iov.iov_len = len;
> - new = smb2_get_reparse_inode(&data, inode->i_sb, xid,
> + new = tcon->ses->server->ops->create_reparse_inode(
> + &data, inode->i_sb, xid,
> tcon, full_path, directory,
> &iov, NULL);
> if (!IS_ERR(new))
> @@ -397,7 +398,8 @@ static int create_native_socket(const unsigned int xid, struct inode *inode,
> struct inode *new;
> int rc = 0;
>
> - new = smb2_get_reparse_inode(&data, inode->i_sb, xid,
> + new = tcon->ses->server->ops->create_reparse_inode(
> + &data, inode->i_sb, xid,
> tcon, full_path, false, &iov, NULL);
> if (!IS_ERR(new))
> d_instantiate(dentry, new);
> @@ -490,7 +492,8 @@ static int mknod_nfs(unsigned int xid, struct inode *inode,
> .symlink_target = kstrdup(symname, GFP_KERNEL),
> };
>
> - new = smb2_get_reparse_inode(&data, inode->i_sb, xid,
> + new = tcon->ses->server->ops->create_reparse_inode(
> + &data, inode->i_sb, xid,
> tcon, full_path, false, &iov, NULL);
> if (!IS_ERR(new))
> d_instantiate(dentry, new);
> @@ -683,7 +686,8 @@ static int mknod_wsl(unsigned int xid, struct inode *inode,
> memcpy(data.wsl.eas, &cc->ea, len);
> data.wsl.eas_len = len;
>
> - new = smb2_get_reparse_inode(&data, inode->i_sb,
> + new = tcon->ses->server->ops->create_reparse_inode(
> + &data, inode->i_sb,
> xid, tcon, full_path, false,
> &reparse_iov, &xattr_iov);
> if (!IS_ERR(new))
> @@ -696,7 +700,7 @@ static int mknod_wsl(unsigned int xid, struct inode *inode,
> return rc;
> }
>
> -int smb2_mknod_reparse(unsigned int xid, struct inode *inode,
> +int 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)
> {
> diff --git a/fs/smb/client/reparse.h b/fs/smb/client/reparse.h
> index c17130657def..8cb11db076a7 100644
> --- a/fs/smb/client/reparse.h
> +++ b/fs/smb/client/reparse.h
> @@ -113,10 +113,10 @@ static inline bool cifs_open_data_reparse(struct cifs_open_info_data *data)
> bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
> struct cifs_fattr *fattr,
> struct cifs_open_info_data *data);
> -int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
> +int create_reparse_symlink(const unsigned int xid, struct inode *inode,
> struct dentry *dentry, struct cifs_tcon *tcon,
> const char *full_path, const char *symname);
> -int smb2_mknod_reparse(unsigned int xid, struct inode *inode,
> +int 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);
> struct reparse_data_buffer *smb2_get_reparse_point_buffer(const struct kvec *rsp_iov, u32 *len);
> diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
> index c52fc4c1557c..a0a15dda0949 100644
> --- a/fs/smb/client/smb1ops.c
> +++ b/fs/smb/client/smb1ops.c
> @@ -16,6 +16,7 @@
> #include "fs_context.h"
> #include "nterr.h"
> #include "smberr.h"
> +#include "reparse.h"
>
> /*
> * An NT cancel request header looks just like the original request except:
> @@ -1076,17 +1077,26 @@ cifs_make_node(unsigned int xid, struct inode *inode,
> if (rc == 0)
> d_instantiate(dentry, newinode);
> return rc;
> + } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
> + /*
> + * Check if mounted with mount parm 'sfu' mount parm.
> + * SFU emulation should work with all servers
> + * and was used by default in earlier versions of Windows.
> + */
> + return cifs_sfu_make_node(xid, inode, dentry, tcon,
> + full_path, mode, dev);
> + } else if (le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) {
> + /*
> + * mknod via reparse points requires server support for
> + * storing reparse points, which is available since
> + * Windows 2000, but was not widely used until release
> + * of Windows Server 2012 by the Windows NFS server.
> + */
> + return mknod_reparse(xid, inode, dentry, tcon,
> + full_path, mode, dev);
> + } else {
> + return -EOPNOTSUPP;
> }
> - /*
> - * Check if mounted with mount parm 'sfu' mount parm.
> - * SFU emulation should work with all servers, but only
> - * supports block and char device, socket & fifo,
> - * and was used by default in earlier versions of Windows
> - */
> - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL))
> - return -EPERM;
> - return cifs_sfu_make_node(xid, inode, dentry, tcon,
> - full_path, mode, dev);
> }
>
> static bool
> @@ -1183,6 +1193,7 @@ struct smb_version_operations smb1_operations = {
> .create_hardlink = CIFSCreateHardLink,
> .query_symlink = cifs_query_symlink,
> .get_reparse_point_buffer = cifs_get_reparse_point_buffer,
> + .create_reparse_inode = cifs_create_reparse_inode,
> .open = cifs_open_file,
> .set_fid = cifs_set_fid,
> .close = cifs_close_file,
> diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
> index 426dbaff270a..0b8d6d8f724d 100644
> --- a/fs/smb/client/smb2inode.c
> +++ b/fs/smb/client/smb2inode.c
> @@ -1305,7 +1305,7 @@ smb2_set_file_info(struct inode *inode, const char *full_path,
> return rc;
> }
>
> -struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
> +struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data,
> struct super_block *sb,
> const unsigned int xid,
> struct cifs_tcon *tcon,
> diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
> index ba81b662f5c7..4aa9f3ac4c34 100644
> --- a/fs/smb/client/smb2ops.c
> +++ b/fs/smb/client/smb2ops.c
> @@ -5232,7 +5232,7 @@ static int smb2_make_node(unsigned int xid, struct inode *inode,
> rc = cifs_sfu_make_node(xid, inode, dentry, tcon,
> full_path, mode, dev);
> } else if (le32_to_cpu(tcon->fsAttrInfo.Attributes) & FILE_SUPPORTS_REPARSE_POINTS) {
> - rc = smb2_mknod_reparse(xid, inode, dentry, tcon,
> + rc = mknod_reparse(xid, inode, dentry, tcon,
> full_path, mode, dev);
> }
> return rc;
> @@ -5291,7 +5291,7 @@ struct smb_version_operations smb20_operations = {
> .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,
> + .create_reparse_inode = smb2_create_reparse_inode,
> .open = smb2_open_file,
> .set_fid = smb2_set_fid,
> .close = smb2_close_file,
> @@ -5394,7 +5394,7 @@ struct smb_version_operations smb21_operations = {
> .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,
> + .create_reparse_inode = smb2_create_reparse_inode,
> .open = smb2_open_file,
> .set_fid = smb2_set_fid,
> .close = smb2_close_file,
> @@ -5501,7 +5501,7 @@ struct smb_version_operations smb30_operations = {
> .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,
> + .create_reparse_inode = smb2_create_reparse_inode,
> .open = smb2_open_file,
> .set_fid = smb2_set_fid,
> .close = smb2_close_file,
> @@ -5617,7 +5617,7 @@ struct smb_version_operations smb311_operations = {
> .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,
> + .create_reparse_inode = smb2_create_reparse_inode,
> .open = smb2_open_file,
> .set_fid = smb2_set_fid,
> .close = smb2_close_file,
> diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h
> index 2336dfb23f36..cec5921bfdd2 100644
> --- a/fs/smb/client/smb2proto.h
> +++ b/fs/smb/client/smb2proto.h
> @@ -54,7 +54,7 @@ extern int smb3_handle_read_data(struct TCP_Server_Info *server,
> extern int smb2_query_reparse_tag(const unsigned int xid, struct cifs_tcon *tcon,
> struct cifs_sb_info *cifs_sb, const char *path,
> __u32 *reparse_tag);
> -struct inode *smb2_get_reparse_inode(struct cifs_open_info_data *data,
> +struct inode *smb2_create_reparse_inode(struct cifs_open_info_data *data,
> struct super_block *sb,
> const unsigned int xid,
> struct cifs_tcon *tcon,
> @@ -317,9 +317,6 @@ int smb311_posix_query_path_info(const unsigned int xid,
> int posix_info_parse(const void *beg, const void *end,
> struct smb2_posix_info_parsed *out);
> int posix_info_sid_size(const void *beg, const void *end);
> -int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
> - struct dentry *dentry, struct cifs_tcon *tcon,
> - const char *full_path, const char *symname);
> int smb2_make_nfs_node(unsigned int xid, struct inode *inode,
> struct dentry *dentry, struct cifs_tcon *tcon,
> const char *full_path, umode_t mode, dev_t dev);
> --
> 2.20.1
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-01-01 13:14 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-27 17:40 [PATCH 1/3] cifs: Remove declaration of dead CIFSSMBQuerySymLink function Pali Rohár
2024-12-27 17:40 ` [PATCH 2/3] cifs: Fix validation of SMB1 query reparse point response Pali Rohár
2024-12-27 17:40 ` [PATCH 3/3] cifs: Add support for creating reparse points over SMB1 Pali Rohár
2025-01-01 13:14 ` 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