Skip to content

Commit 5517554

Browse files
Ronnie Sahlbergsmfrench
Ronnie Sahlberg
authored andcommitted
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 <[email protected]> Signed-off-by: Steve French <[email protected]> Reviewed-by: Pavel Shilovsky <[email protected]>
1 parent 95907fe commit 5517554

File tree

7 files changed

+79
-4
lines changed

7 files changed

+79
-4
lines changed

fs/cifs/cifsglob.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ struct smb_version_operations {
421421
size_t, struct cifs_sb_info *);
422422
int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
423423
const char *, const void *, const __u16,
424-
const struct nls_table *, int);
424+
const struct nls_table *, struct cifs_sb_info *);
425425
struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *,
426426
const char *, u32 *);
427427
struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *,

fs/cifs/cifsproto.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,8 @@ extern ssize_t CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
484484
extern int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
485485
const char *fileName, const char *ea_name,
486486
const void *ea_value, const __u16 ea_value_len,
487-
const struct nls_table *nls_codepage, int remap_special_chars);
487+
const struct nls_table *nls_codepage,
488+
struct cifs_sb_info *cifs_sb);
488489
extern int CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon,
489490
__u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen);
490491
extern int CIFSSMBSetCIFSACL(const unsigned int, struct cifs_tcon *, __u16,

fs/cifs/cifssmb.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6264,7 +6264,7 @@ int
62646264
CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
62656265
const char *fileName, const char *ea_name, const void *ea_value,
62666266
const __u16 ea_value_len, const struct nls_table *nls_codepage,
6267-
int remap)
6267+
struct cifs_sb_info *cifs_sb)
62686268
{
62696269
struct smb_com_transaction2_spi_req *pSMB = NULL;
62706270
struct smb_com_transaction2_spi_rsp *pSMBr = NULL;
@@ -6273,6 +6273,7 @@ CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
62736273
int rc = 0;
62746274
int bytes_returned = 0;
62756275
__u16 params, param_offset, byte_count, offset, count;
6276+
int remap = cifs_remap(cifs_sb);
62766277

62776278
cifs_dbg(FYI, "In SetEA\n");
62786279
SetEARetry:

fs/cifs/smb2ops.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,62 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
558558
return rc;
559559
}
560560

561+
562+
static int
563+
smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
564+
const char *path, const char *ea_name, const void *ea_value,
565+
const __u16 ea_value_len, const struct nls_table *nls_codepage,
566+
struct cifs_sb_info *cifs_sb)
567+
{
568+
int rc;
569+
__le16 *utf16_path;
570+
__u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
571+
struct cifs_open_parms oparms;
572+
struct cifs_fid fid;
573+
struct smb2_file_full_ea_info *ea;
574+
int ea_name_len = strlen(ea_name);
575+
int len;
576+
577+
if (ea_name_len > 255)
578+
return -EINVAL;
579+
580+
utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
581+
if (!utf16_path)
582+
return -ENOMEM;
583+
584+
oparms.tcon = tcon;
585+
oparms.desired_access = FILE_WRITE_EA;
586+
oparms.disposition = FILE_OPEN;
587+
oparms.create_options = 0;
588+
oparms.fid = &fid;
589+
oparms.reconnect = false;
590+
591+
rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
592+
kfree(utf16_path);
593+
if (rc) {
594+
cifs_dbg(FYI, "open failed rc=%d\n", rc);
595+
return rc;
596+
}
597+
598+
len = sizeof(ea) + ea_name_len + ea_value_len + 1;
599+
ea = kzalloc(len, GFP_KERNEL);
600+
if (ea == NULL) {
601+
SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
602+
return -ENOMEM;
603+
}
604+
605+
ea->ea_name_length = ea_name_len;
606+
ea->ea_value_length = cpu_to_le16(ea_value_len);
607+
memcpy(ea->ea_data, ea_name, ea_name_len + 1);
608+
memcpy(ea->ea_data + ea_name_len + 1, ea_value, ea_value_len);
609+
610+
rc = SMB2_set_ea(xid, tcon, fid.persistent_fid, fid.volatile_fid, ea,
611+
len);
612+
SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
613+
614+
return rc;
615+
}
616+
561617
static bool
562618
smb2_can_echo(struct TCP_Server_Info *server)
563619
{
@@ -2706,6 +2762,7 @@ struct smb_version_operations smb20_operations = {
27062762
.select_sectype = smb2_select_sectype,
27072763
#ifdef CONFIG_CIFS_XATTR
27082764
.query_all_EAs = smb2_query_eas,
2765+
.set_EA = smb2_set_ea,
27092766
#endif /* CIFS_XATTR */
27102767
#ifdef CONFIG_CIFS_ACL
27112768
.get_acl = get_smb2_acl,
@@ -2799,6 +2856,7 @@ struct smb_version_operations smb21_operations = {
27992856
.select_sectype = smb2_select_sectype,
28002857
#ifdef CONFIG_CIFS_XATTR
28012858
.query_all_EAs = smb2_query_eas,
2859+
.set_EA = smb2_set_ea,
28022860
#endif /* CIFS_XATTR */
28032861
#ifdef CONFIG_CIFS_ACL
28042862
.get_acl = get_smb2_acl,
@@ -2902,6 +2960,7 @@ struct smb_version_operations smb30_operations = {
29022960
.select_sectype = smb2_select_sectype,
29032961
#ifdef CONFIG_CIFS_XATTR
29042962
.query_all_EAs = smb2_query_eas,
2963+
.set_EA = smb2_set_ea,
29052964
#endif /* CIFS_XATTR */
29062965
#ifdef CONFIG_CIFS_ACL
29072966
.get_acl = get_smb2_acl,
@@ -3006,6 +3065,7 @@ struct smb_version_operations smb311_operations = {
30063065
.select_sectype = smb2_select_sectype,
30073066
#ifdef CONFIG_CIFS_XATTR
30083067
.query_all_EAs = smb2_query_eas,
3068+
.set_EA = smb2_set_ea,
30093069
#endif /* CIFS_XATTR */
30103070
};
30113071
#endif /* CIFS_SMB311 */

fs/cifs/smb2pdu.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3196,6 +3196,16 @@ SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
31963196
1, (void **)&pnntsd, &pacllen);
31973197
}
31983198

3199+
int
3200+
SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
3201+
u64 persistent_fid, u64 volatile_fid,
3202+
struct smb2_file_full_ea_info *buf, int len)
3203+
{
3204+
return send_set_info(xid, tcon, persistent_fid, volatile_fid,
3205+
current->tgid, FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE,
3206+
0, 1, (void **)&buf, &len);
3207+
}
3208+
31993209
int
32003210
SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
32013211
const u64 persistent_fid, const u64 volatile_fid,

fs/cifs/smb2proto.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,9 @@ extern int SMB2_set_info(const unsigned int xid, struct cifs_tcon *tcon,
172172
extern int SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon,
173173
u64 persistent_fid, u64 volatile_fid,
174174
struct cifs_ntsd *pnntsd, int pacllen, int aclflag);
175+
extern int SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
176+
u64 persistent_fid, u64 volatile_fid,
177+
struct smb2_file_full_ea_info *buf, int len);
175178
extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
176179
u64 persistent_fid, u64 volatile_fid);
177180
extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,

fs/cifs/xattr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler,
8484
if (pTcon->ses->server->ops->set_EA)
8585
rc = pTcon->ses->server->ops->set_EA(xid, pTcon,
8686
full_path, name, value, (__u16)size,
87-
cifs_sb->local_nls, cifs_remap(cifs_sb));
87+
cifs_sb->local_nls, cifs_sb);
8888
break;
8989

9090
case XATTR_CIFS_ACL: {

0 commit comments

Comments
 (0)