cifs: Add support for writing attributes on SMB2+
This adds support for writing extended attributes on SMB2+ shares. Attributes can be written using the setfattr command. RH-bz: 1110709 Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <smfrench@gmail.com> Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
This commit is contained in:
parent
95907fea4f
commit
5517554e43
@ -421,7 +421,7 @@ struct smb_version_operations {
|
|||||||
size_t, struct cifs_sb_info *);
|
size_t, struct cifs_sb_info *);
|
||||||
int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
|
int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
|
||||||
const char *, const void *, const __u16,
|
const char *, const void *, const __u16,
|
||||||
const struct nls_table *, int);
|
const struct nls_table *, struct cifs_sb_info *);
|
||||||
struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *,
|
struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *,
|
||||||
const char *, u32 *);
|
const char *, u32 *);
|
||||||
struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *,
|
struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *,
|
||||||
|
@ -484,7 +484,8 @@ extern ssize_t CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
extern int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
const char *fileName, const char *ea_name,
|
const char *fileName, const char *ea_name,
|
||||||
const void *ea_value, const __u16 ea_value_len,
|
const void *ea_value, const __u16 ea_value_len,
|
||||||
const struct nls_table *nls_codepage, int remap_special_chars);
|
const struct nls_table *nls_codepage,
|
||||||
|
struct cifs_sb_info *cifs_sb);
|
||||||
extern int CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
__u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen);
|
__u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen);
|
||||||
extern int CIFSSMBSetCIFSACL(const unsigned int, struct cifs_tcon *, __u16,
|
extern int CIFSSMBSetCIFSACL(const unsigned int, struct cifs_tcon *, __u16,
|
||||||
|
@ -6264,7 +6264,7 @@ int
|
|||||||
CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
|
CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
const char *fileName, const char *ea_name, const void *ea_value,
|
const char *fileName, const char *ea_name, const void *ea_value,
|
||||||
const __u16 ea_value_len, const struct nls_table *nls_codepage,
|
const __u16 ea_value_len, const struct nls_table *nls_codepage,
|
||||||
int remap)
|
struct cifs_sb_info *cifs_sb)
|
||||||
{
|
{
|
||||||
struct smb_com_transaction2_spi_req *pSMB = NULL;
|
struct smb_com_transaction2_spi_req *pSMB = NULL;
|
||||||
struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
|
struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
|
||||||
@ -6273,6 +6273,7 @@ CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
int bytes_returned = 0;
|
int bytes_returned = 0;
|
||||||
__u16 params, param_offset, byte_count, offset, count;
|
__u16 params, param_offset, byte_count, offset, count;
|
||||||
|
int remap = cifs_remap(cifs_sb);
|
||||||
|
|
||||||
cifs_dbg(FYI, "In SetEA\n");
|
cifs_dbg(FYI, "In SetEA\n");
|
||||||
SetEARetry:
|
SetEARetry:
|
||||||
|
@ -558,6 +558,62 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
const char *path, const char *ea_name, const void *ea_value,
|
||||||
|
const __u16 ea_value_len, const struct nls_table *nls_codepage,
|
||||||
|
struct cifs_sb_info *cifs_sb)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
__le16 *utf16_path;
|
||||||
|
__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
|
||||||
|
struct cifs_open_parms oparms;
|
||||||
|
struct cifs_fid fid;
|
||||||
|
struct smb2_file_full_ea_info *ea;
|
||||||
|
int ea_name_len = strlen(ea_name);
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (ea_name_len > 255)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
|
||||||
|
if (!utf16_path)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
oparms.tcon = tcon;
|
||||||
|
oparms.desired_access = FILE_WRITE_EA;
|
||||||
|
oparms.disposition = FILE_OPEN;
|
||||||
|
oparms.create_options = 0;
|
||||||
|
oparms.fid = &fid;
|
||||||
|
oparms.reconnect = false;
|
||||||
|
|
||||||
|
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
|
||||||
|
kfree(utf16_path);
|
||||||
|
if (rc) {
|
||||||
|
cifs_dbg(FYI, "open failed rc=%d\n", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = sizeof(ea) + ea_name_len + ea_value_len + 1;
|
||||||
|
ea = kzalloc(len, GFP_KERNEL);
|
||||||
|
if (ea == NULL) {
|
||||||
|
SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
ea->ea_name_length = ea_name_len;
|
||||||
|
ea->ea_value_length = cpu_to_le16(ea_value_len);
|
||||||
|
memcpy(ea->ea_data, ea_name, ea_name_len + 1);
|
||||||
|
memcpy(ea->ea_data + ea_name_len + 1, ea_value, ea_value_len);
|
||||||
|
|
||||||
|
rc = SMB2_set_ea(xid, tcon, fid.persistent_fid, fid.volatile_fid, ea,
|
||||||
|
len);
|
||||||
|
SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
smb2_can_echo(struct TCP_Server_Info *server)
|
smb2_can_echo(struct TCP_Server_Info *server)
|
||||||
{
|
{
|
||||||
@ -2706,6 +2762,7 @@ struct smb_version_operations smb20_operations = {
|
|||||||
.select_sectype = smb2_select_sectype,
|
.select_sectype = smb2_select_sectype,
|
||||||
#ifdef CONFIG_CIFS_XATTR
|
#ifdef CONFIG_CIFS_XATTR
|
||||||
.query_all_EAs = smb2_query_eas,
|
.query_all_EAs = smb2_query_eas,
|
||||||
|
.set_EA = smb2_set_ea,
|
||||||
#endif /* CIFS_XATTR */
|
#endif /* CIFS_XATTR */
|
||||||
#ifdef CONFIG_CIFS_ACL
|
#ifdef CONFIG_CIFS_ACL
|
||||||
.get_acl = get_smb2_acl,
|
.get_acl = get_smb2_acl,
|
||||||
@ -2799,6 +2856,7 @@ struct smb_version_operations smb21_operations = {
|
|||||||
.select_sectype = smb2_select_sectype,
|
.select_sectype = smb2_select_sectype,
|
||||||
#ifdef CONFIG_CIFS_XATTR
|
#ifdef CONFIG_CIFS_XATTR
|
||||||
.query_all_EAs = smb2_query_eas,
|
.query_all_EAs = smb2_query_eas,
|
||||||
|
.set_EA = smb2_set_ea,
|
||||||
#endif /* CIFS_XATTR */
|
#endif /* CIFS_XATTR */
|
||||||
#ifdef CONFIG_CIFS_ACL
|
#ifdef CONFIG_CIFS_ACL
|
||||||
.get_acl = get_smb2_acl,
|
.get_acl = get_smb2_acl,
|
||||||
@ -2902,6 +2960,7 @@ struct smb_version_operations smb30_operations = {
|
|||||||
.select_sectype = smb2_select_sectype,
|
.select_sectype = smb2_select_sectype,
|
||||||
#ifdef CONFIG_CIFS_XATTR
|
#ifdef CONFIG_CIFS_XATTR
|
||||||
.query_all_EAs = smb2_query_eas,
|
.query_all_EAs = smb2_query_eas,
|
||||||
|
.set_EA = smb2_set_ea,
|
||||||
#endif /* CIFS_XATTR */
|
#endif /* CIFS_XATTR */
|
||||||
#ifdef CONFIG_CIFS_ACL
|
#ifdef CONFIG_CIFS_ACL
|
||||||
.get_acl = get_smb2_acl,
|
.get_acl = get_smb2_acl,
|
||||||
@ -3006,6 +3065,7 @@ struct smb_version_operations smb311_operations = {
|
|||||||
.select_sectype = smb2_select_sectype,
|
.select_sectype = smb2_select_sectype,
|
||||||
#ifdef CONFIG_CIFS_XATTR
|
#ifdef CONFIG_CIFS_XATTR
|
||||||
.query_all_EAs = smb2_query_eas,
|
.query_all_EAs = smb2_query_eas,
|
||||||
|
.set_EA = smb2_set_ea,
|
||||||
#endif /* CIFS_XATTR */
|
#endif /* CIFS_XATTR */
|
||||||
};
|
};
|
||||||
#endif /* CIFS_SMB311 */
|
#endif /* CIFS_SMB311 */
|
||||||
|
@ -3196,6 +3196,16 @@ SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
1, (void **)&pnntsd, &pacllen);
|
1, (void **)&pnntsd, &pacllen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
u64 persistent_fid, u64 volatile_fid,
|
||||||
|
struct smb2_file_full_ea_info *buf, int len)
|
||||||
|
{
|
||||||
|
return send_set_info(xid, tcon, persistent_fid, volatile_fid,
|
||||||
|
current->tgid, FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE,
|
||||||
|
0, 1, (void **)&buf, &len);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
|
SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
const u64 persistent_fid, const u64 volatile_fid,
|
const u64 persistent_fid, const u64 volatile_fid,
|
||||||
|
@ -172,6 +172,9 @@ extern int SMB2_set_info(const unsigned int xid, struct cifs_tcon *tcon,
|
|||||||
extern int SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
u64 persistent_fid, u64 volatile_fid,
|
u64 persistent_fid, u64 volatile_fid,
|
||||||
struct cifs_ntsd *pnntsd, int pacllen, int aclflag);
|
struct cifs_ntsd *pnntsd, int pacllen, int aclflag);
|
||||||
|
extern int SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
u64 persistent_fid, u64 volatile_fid,
|
||||||
|
struct smb2_file_full_ea_info *buf, int len);
|
||||||
extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
u64 persistent_fid, u64 volatile_fid);
|
u64 persistent_fid, u64 volatile_fid);
|
||||||
extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
|
extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
|
||||||
|
@ -84,7 +84,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
|
|||||||
if (pTcon->ses->server->ops->set_EA)
|
if (pTcon->ses->server->ops->set_EA)
|
||||||
rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
|
rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
|
||||||
full_path, name, value, (__u16)size,
|
full_path, name, value, (__u16)size,
|
||||||
cifs_sb->local_nls, cifs_remap(cifs_sb));
|
cifs_sb->local_nls, cifs_sb);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XATTR_CIFS_ACL: {
|
case XATTR_CIFS_ACL: {
|
||||||
|
Loading…
Reference in New Issue
Block a user