smb: client: fix hardlinking of reparse points
[ Upstream commit 5408990aa662bcfd6ba894734023a023a16e8729 ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
c586b0c746
commit
8c944f8a41
@ -405,9 +405,11 @@ struct smb_version_operations {
|
||||
const char *from_name, const char *to_name,
|
||||
struct cifs_sb_info *cifs_sb);
|
||||
/* send create hardlink request */
|
||||
int (*create_hardlink)(const unsigned int, struct cifs_tcon *,
|
||||
const char *, const char *,
|
||||
struct cifs_sb_info *);
|
||||
int (*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);
|
||||
/* query symlink target */
|
||||
int (*query_symlink)(const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
|
@ -443,9 +443,11 @@ extern int CIFSSMBRenameOpenFile(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
int netfid, const char *target_name,
|
||||
const struct nls_table *nls_codepage,
|
||||
int remap_special_chars);
|
||||
extern int CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *from_name, const char *to_name,
|
||||
struct cifs_sb_info *cifs_sb);
|
||||
int CIFSCreateHardLink(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);
|
||||
extern int CIFSUnixCreateHardLink(const unsigned int xid,
|
||||
struct cifs_tcon *tcon,
|
||||
const char *fromName, const char *toName,
|
||||
|
@ -2530,10 +2530,11 @@ createHardLinkRetry:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
CIFSCreateHardLink(const unsigned int xid, struct cifs_tcon *tcon,
|
||||
const char *from_name, const char *to_name,
|
||||
struct cifs_sb_info *cifs_sb)
|
||||
int CIFSCreateHardLink(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)
|
||||
{
|
||||
int rc = 0;
|
||||
NT_RENAME_REQ *pSMB = NULL;
|
||||
|
@ -522,8 +522,8 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
|
||||
rc = -ENOSYS;
|
||||
goto cifs_hl_exit;
|
||||
}
|
||||
rc = server->ops->create_hardlink(xid, tcon, from_name, to_name,
|
||||
cifs_sb);
|
||||
rc = server->ops->create_hardlink(xid, tcon, old_file,
|
||||
from_name, to_name, cifs_sb);
|
||||
if ((rc == -EIO) || (rc == -EINVAL))
|
||||
rc = -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -35,6 +35,18 @@ free_set_inf_compound(struct smb_rqst *rqst)
|
||||
SMB2_close_free(&rqst[2]);
|
||||
}
|
||||
|
||||
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.
|
||||
@ -809,15 +821,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);
|
||||
|
||||
@ -825,13 +831,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);
|
||||
}
|
||||
|
||||
|
@ -85,9 +85,11 @@ int smb2_rename_path(const unsigned int xid,
|
||||
struct dentry *source_dentry,
|
||||
const char *from_name, const char *to_name,
|
||||
struct cifs_sb_info *cifs_sb);
|
||||
extern 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);
|
||||
extern int smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
|
||||
struct cifs_sb_info *cifs_sb, const unsigned char *path,
|
||||
char *pbuf, unsigned int *pbytes_written);
|
||||
|
Loading…
x
Reference in New Issue
Block a user