summaryrefslogtreecommitdiff
path: root/fs/smb/client/smb2inode.c
diff options
context:
space:
mode:
authorPaulo Alcantara <pc@manguebit.com>2023-11-25 23:55:06 -0300
committerSteve French <stfrench@microsoft.com>2024-01-07 15:46:06 -0600
commit7435d51b7ea2ab7801279c43ecd72063e9d5c92f (patch)
tree464f91149925132f710835da6b20aaadb48db0a1 /fs/smb/client/smb2inode.c
parent67ec9949b0dfe78c99e110dd975eb7dc5645630c (diff)
smb: client: fix renaming of reparse points
The client was sending an SMB2_CREATE request without setting OPEN_REPARSE_POINT flag thus failing the entire rename operation. Fix this by setting OPEN_REPARSE_POINT in create options for SMB2_CREATE request when the source inode is a repase point. Signed-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com> Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/smb/client/smb2inode.c')
-rw-r--r--fs/smb/client/smb2inode.c38
1 files changed, 23 insertions, 15 deletions
diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
index 0f096fb41b3e..2d9cdc194403 100644
--- a/fs/smb/client/smb2inode.c
+++ b/fs/smb/client/smb2inode.c
@@ -889,11 +889,11 @@ smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
NULL, NULL, NULL, NULL, NULL);
}
-static int
-smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
- const char *from_name, const char *to_name,
- struct cifs_sb_info *cifs_sb, __u32 access, int command,
- struct cifsFileInfo *cfile)
+static int smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
+ const char *from_name, const char *to_name,
+ struct cifs_sb_info *cifs_sb,
+ __u32 create_options, __u32 access,
+ int command, struct cifsFileInfo *cfile)
{
struct kvec in_iov;
__le16 *smb2_to_name = NULL;
@@ -907,25 +907,33 @@ smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
in_iov.iov_base = smb2_to_name;
in_iov.iov_len = 2 * UniStrnlen((wchar_t *)smb2_to_name, PATH_MAX);
rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access,
- FILE_OPEN, 0, ACL_NO_MODE, &in_iov,
+ FILE_OPEN, create_options, ACL_NO_MODE, &in_iov,
&command, 1, cfile, NULL, NULL, NULL, NULL);
smb2_rename_path:
kfree(smb2_to_name);
return rc;
}
-int
-smb2_rename_path(const unsigned int xid, struct cifs_tcon *tcon,
- const char *from_name, const char *to_name,
- struct cifs_sb_info *cifs_sb)
+int smb2_rename_path(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ struct dentry *source_dentry,
+ const char *from_name, const char *to_name,
+ struct cifs_sb_info *cifs_sb)
{
+ struct cifsInodeInfo *ci;
struct cifsFileInfo *cfile;
+ __u32 co = 0;
+ if (source_dentry) {
+ ci = CIFS_I(d_inode(source_dentry));
+ if (ci->cifsAttrs & ATTR_REPARSE)
+ co |= OPEN_REPARSE_POINT;
+ }
drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb);
cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile);
- return smb2_set_path_attr(xid, tcon, from_name, to_name,
- cifs_sb, DELETE, SMB2_OP_RENAME, cfile);
+ return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
+ co, DELETE, SMB2_OP_RENAME, cfile);
}
int
@@ -933,9 +941,9 @@ smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
const char *from_name, const char *to_name,
struct cifs_sb_info *cifs_sb)
{
- return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
- FILE_READ_ATTRIBUTES, SMB2_OP_HARDLINK,
- NULL);
+ return smb2_set_path_attr(xid, tcon, from_name, to_name,
+ cifs_sb, 0, FILE_READ_ATTRIBUTES,
+ SMB2_OP_HARDLINK, NULL);
}
int