Skip to content

Commit 5408990

Browse files
Paulo Alcantarasmfrench
authored andcommitted
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>
1 parent 7435d51 commit 5408990

6 files changed

Lines changed: 43 additions & 27 deletions

File tree

fs/smb/client/cifsglob.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -405,9 +405,11 @@ struct smb_version_operations {
405405
const char *from_name, const char *to_name,
406406
struct cifs_sb_info *cifs_sb);
407407
/* send create hardlink request */
408-
int (*create_hardlink)(const unsigned int, struct cifs_tcon *,
409-
const char *, const char *,
410-
struct cifs_sb_info *);
408+
int (*create_hardlink)(const unsigned int xid,
409+
struct cifs_tcon *tcon,
410+
struct dentry *source_dentry,
411+
const char *from_name, const char *to_name,
412+
struct cifs_sb_info *cifs_sb);
411413
/* query symlink target */
412414
int (*query_symlink)(const unsigned int xid,
413415
struct cifs_tcon *tcon,

fs/smb/client/cifsproto.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -447,9 +447,11 @@ extern int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *tcon,
447447
int netfid, const char *target_name,
448448
const struct nls_table *nls_codepage,
449449
int remap_special_chars);
450-
extern int CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
451-
const char *from_name, const char *to_name,
452-
struct cifs_sb_info *cifs_sb);
450+
int CIFSCreateHardLink(const unsigned int xid,
451+
struct cifs_tcon *tcon,
452+
struct dentry *source_dentry,
453+
const char *from_name, const char *to_name,
454+
struct cifs_sb_info *cifs_sb);
453455
extern int CIFSUnixCreateHardLink(const unsigned int xid,
454456
struct cifs_tcon *tcon,
455457
const char *fromName, const char *toName,

fs/smb/client/cifssmb.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2530,10 +2530,11 @@ CIFSUnixCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
25302530
return rc;
25312531
}
25322532

2533-
int
2534-
CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
2535-
const char *from_name, const char *to_name,
2536-
struct cifs_sb_info *cifs_sb)
2533+
int CIFSCreateHardLink(const unsigned int xid,
2534+
struct cifs_tcon *tcon,
2535+
struct dentry *source_dentry,
2536+
const char *from_name, const char *to_name,
2537+
struct cifs_sb_info *cifs_sb)
25372538
{
25382539
int rc = 0;
25392540
NT_RENAME_REQ *pSMB = NULL;

fs/smb/client/link.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -510,8 +510,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
510510
rc = -ENOSYS;
511511
goto cifs_hl_exit;
512512
}
513-
rc = server->ops->create_hardlink(xid, tcon, from_name, to_name,
514-
cifs_sb);
513+
rc = server->ops->create_hardlink(xid, tcon, old_file,
514+
from_name, to_name, cifs_sb);
515515
if ((rc == -EIO) || (rc == -EINVAL))
516516
rc = -EOPNOTSUPP;
517517
}

fs/smb/client/smb2inode.c

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@ static struct reparse_data_buffer *reparse_buf_ptr(struct kvec *iov)
4444
return buf;
4545
}
4646

47+
static inline __u32 file_create_options(struct dentry *dentry)
48+
{
49+
struct cifsInodeInfo *ci;
50+
51+
if (dentry) {
52+
ci = CIFS_I(d_inode(dentry));
53+
if (ci->cifsAttrs & ATTR_REPARSE)
54+
return OPEN_REPARSE_POINT;
55+
}
56+
return 0;
57+
}
58+
4759
/*
4860
* note: If cfile is passed, the reference to it is dropped here.
4961
* So make sure that you do not reuse cfile after return from this func.
@@ -920,29 +932,26 @@ int smb2_rename_path(const unsigned int xid,
920932
const char *from_name, const char *to_name,
921933
struct cifs_sb_info *cifs_sb)
922934
{
923-
struct cifsInodeInfo *ci;
924935
struct cifsFileInfo *cfile;
925-
__u32 co = 0;
936+
__u32 co = file_create_options(source_dentry);
926937

927-
if (source_dentry) {
928-
ci = CIFS_I(d_inode(source_dentry));
929-
if (ci->cifsAttrs & ATTR_REPARSE)
930-
co |= OPEN_REPARSE_POINT;
931-
}
932938
drop_cached_dir_by_name(xid, tcon, from_name, cifs_sb);
933939
cifs_get_writable_path(tcon, from_name, FIND_WR_WITH_DELETE, &cfile);
934940

935941
return smb2_set_path_attr(xid, tcon, from_name, to_name, cifs_sb,
936942
co, DELETE, SMB2_OP_RENAME, cfile);
937943
}
938944

939-
int
940-
smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
941-
const char *from_name, const char *to_name,
942-
struct cifs_sb_info *cifs_sb)
945+
int smb2_create_hardlink(const unsigned int xid,
946+
struct cifs_tcon *tcon,
947+
struct dentry *source_dentry,
948+
const char *from_name, const char *to_name,
949+
struct cifs_sb_info *cifs_sb)
943950
{
951+
__u32 co = file_create_options(source_dentry);
952+
944953
return smb2_set_path_attr(xid, tcon, from_name, to_name,
945-
cifs_sb, 0, FILE_READ_ATTRIBUTES,
954+
cifs_sb, co, FILE_READ_ATTRIBUTES,
946955
SMB2_OP_HARDLINK, NULL);
947956
}
948957

fs/smb/client/smb2proto.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,11 @@ int smb2_rename_path(const unsigned int xid,
9191
struct dentry *source_dentry,
9292
const char *from_name, const char *to_name,
9393
struct cifs_sb_info *cifs_sb);
94-
extern int smb2_create_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
95-
const char *from_name, const char *to_name,
96-
struct cifs_sb_info *cifs_sb);
94+
int smb2_create_hardlink(const unsigned int xid,
95+
struct cifs_tcon *tcon,
96+
struct dentry *source_dentry,
97+
const char *from_name, const char *to_name,
98+
struct cifs_sb_info *cifs_sb);
9799
extern int smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
98100
struct cifs_sb_info *cifs_sb, const unsigned char *path,
99101
char *pbuf, unsigned int *pbytes_written);

0 commit comments

Comments
 (0)