summaryrefslogtreecommitdiff
path: root/fs/smb/client/smb2inode.c
diff options
context:
space:
mode:
authorPaulo Alcantara <pc@manguebit.com>2023-11-25 23:55:07 -0300
committerSteve French <stfrench@microsoft.com>2024-01-07 15:46:06 -0600
commit5408990aa662bcfd6ba894734023a023a16e8729 (patch)
tree926738354eaea0c27e823c560fa78920973f9e08 /fs/smb/client/smb2inode.c
parent7435d51b7ea2ab7801279c43ecd72063e9d5c92f (diff)
smb: client: fix hardlinking of reparse points
The client was sending an SMB2_CREATE request without setting OPEN_REPARSE_POINT flag thus failing the entire hardlink 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.c33
1 files changed, 21 insertions, 12 deletions
diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
index 2d9cdc194403..919f778be84d 100644
--- a/fs/smb/client/smb2inode.c
+++ b/fs/smb/client/smb2inode.c
@@ -44,6 +44,18 @@ static struct reparse_data_buffer *reparse_buf_ptr(struct kvec *iov)
return buf;
}
+static inline __u32 file_create_options(struct dentry *dentry)
+{
+ struct cifsInodeInfo *ci;
+
+ if (dentry) {
+ ci = CIFS_I(d_inode(dentry));
+ if (ci->cifsAttrs & ATTR_REPARSE)
+ return OPEN_REPARSE_POINT;
+ }
+ return 0;
+}
+
/*
* note: If cfile is passed, the reference to it is dropped here.
* So make sure that you do not reuse cfile after return from this func.
@@ -920,15 +932,9 @@ int smb2_rename_path(const unsigned int xid,
const char *from_name, const char *to_name,
struct cifs_sb_info *cifs_sb)
{
- struct cifsInodeInfo *ci;
struct cifsFileInfo *cfile;
- __u32 co = 0;
+ __u32 co = file_create_options(source_dentry);
- 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);
@@ -936,13 +942,16 @@ int smb2_rename_path(const unsigned int xid,
co, DELETE, SMB2_OP_RENAME, cfile);
}
-int
-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)
+int smb2_create_hardlink(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)
{
+ __u32 co = file_create_options(source_dentry);
+
return smb2_set_path_attr(xid, tcon, from_name, to_name,
- cifs_sb, 0, FILE_READ_ATTRIBUTES,
+ cifs_sb, co, FILE_READ_ATTRIBUTES,
SMB2_OP_HARDLINK, NULL);
}