diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-07 19:06:14 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-07 19:06:14 -0400 |
commit | 8dc5b3a6cb2fc5d4f751bda56a378589202a118b (patch) | |
tree | cae239c16625ecb15ebc4b94535f46ea064bfd47 | |
parent | 2500e287bca1beb313aa298f2d36be1257cbb483 (diff) | |
parent | 76e752701a8af4404bbd9c45723f7cbd6e4a251e (diff) |
Merge tag '4.14-smb3-xattr-enable' of git://git.samba.org/sfrench/cifs-2.6
Pull cifs update from Steve French:
"Enable xattr support for smb3 and also a bugfix"
* tag '4.14-smb3-xattr-enable' of git://git.samba.org/sfrench/cifs-2.6:
cifs: Check for timeout on Negotiate stage
cifs: Add support for writing attributes on SMB2+
cifs: Add support for reading attributes on SMB2+
-rw-r--r-- | fs/cifs/cifsglob.h | 2 | ||||
-rw-r--r-- | fs/cifs/cifsproto.h | 3 | ||||
-rw-r--r-- | fs/cifs/cifssmb.c | 15 | ||||
-rw-r--r-- | fs/cifs/connect.c | 3 | ||||
-rw-r--r-- | fs/cifs/smb2ops.c | 204 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.c | 34 | ||||
-rw-r--r-- | fs/cifs/smb2pdu.h | 10 | ||||
-rw-r--r-- | fs/cifs/smb2proto.h | 6 | ||||
-rw-r--r-- | fs/cifs/xattr.c | 2 |
9 files changed, 274 insertions, 5 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 221693fe49ec..808486c29f0d 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
@@ -421,7 +421,7 @@ struct smb_version_operations { | |||
421 | size_t, struct cifs_sb_info *); | 421 | size_t, struct cifs_sb_info *); |
422 | int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *, | 422 | int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *, |
423 | const char *, const void *, const __u16, | 423 | const char *, const void *, const __u16, |
424 | const struct nls_table *, int); | 424 | const struct nls_table *, struct cifs_sb_info *); |
425 | struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *, | 425 | struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *, |
426 | const char *, u32 *); | 426 | const char *, u32 *); |
427 | struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *, | 427 | struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *, |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 6eb3147132e3..4143c9dec463 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
@@ -484,7 +484,8 @@ extern ssize_t CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon, | |||
484 | extern int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon, | 484 | extern int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon, |
485 | const char *fileName, const char *ea_name, | 485 | const char *fileName, const char *ea_name, |
486 | const void *ea_value, const __u16 ea_value_len, | 486 | 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); | ||
488 | extern int CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, | 489 | extern int CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, |
489 | __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen); | 490 | __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen); |
490 | extern int CIFSSMBSetCIFSACL(const unsigned int, struct cifs_tcon *, __u16, | 491 | extern int CIFSSMBSetCIFSACL(const unsigned int, struct cifs_tcon *, __u16, |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 118a63e7e221..35dc5bf01ee2 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -178,6 +178,18 @@ cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) | |||
178 | * reconnect the same SMB session | 178 | * reconnect the same SMB session |
179 | */ | 179 | */ |
180 | mutex_lock(&ses->session_mutex); | 180 | mutex_lock(&ses->session_mutex); |
181 | |||
182 | /* | ||
183 | * Recheck after acquire mutex. If another thread is negotiating | ||
184 | * and the server never sends an answer the socket will be closed | ||
185 | * and tcpStatus set to reconnect. | ||
186 | */ | ||
187 | if (server->tcpStatus == CifsNeedReconnect) { | ||
188 | rc = -EHOSTDOWN; | ||
189 | mutex_unlock(&ses->session_mutex); | ||
190 | goto out; | ||
191 | } | ||
192 | |||
181 | rc = cifs_negotiate_protocol(0, ses); | 193 | rc = cifs_negotiate_protocol(0, ses); |
182 | if (rc == 0 && ses->need_reconnect) | 194 | if (rc == 0 && ses->need_reconnect) |
183 | rc = cifs_setup_session(0, ses, nls_codepage); | 195 | rc = cifs_setup_session(0, ses, nls_codepage); |
@@ -6264,7 +6276,7 @@ int | |||
6264 | CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon, | 6276 | CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon, |
6265 | const char *fileName, const char *ea_name, const void *ea_value, | 6277 | const char *fileName, const char *ea_name, const void *ea_value, |
6266 | const __u16 ea_value_len, const struct nls_table *nls_codepage, | 6278 | const __u16 ea_value_len, const struct nls_table *nls_codepage, |
6267 | int remap) | 6279 | struct cifs_sb_info *cifs_sb) |
6268 | { | 6280 | { |
6269 | struct smb_com_transaction2_spi_req *pSMB = NULL; | 6281 | struct smb_com_transaction2_spi_req *pSMB = NULL; |
6270 | struct smb_com_transaction2_spi_rsp *pSMBr = NULL; | 6282 | struct smb_com_transaction2_spi_rsp *pSMBr = NULL; |
@@ -6273,6 +6285,7 @@ CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon, | |||
6273 | int rc = 0; | 6285 | int rc = 0; |
6274 | int bytes_returned = 0; | 6286 | int bytes_returned = 0; |
6275 | __u16 params, param_offset, byte_count, offset, count; | 6287 | __u16 params, param_offset, byte_count, offset, count; |
6288 | int remap = cifs_remap(cifs_sb); | ||
6276 | 6289 | ||
6277 | cifs_dbg(FYI, "In SetEA\n"); | 6290 | cifs_dbg(FYI, "In SetEA\n"); |
6278 | SetEARetry: | 6291 | SetEARetry: |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 83a8f52cd879..5aa2d278ca84 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
@@ -509,7 +509,8 @@ server_unresponsive(struct TCP_Server_Info *server) | |||
509 | * 65s kernel_recvmsg times out, and we see that we haven't gotten | 509 | * 65s kernel_recvmsg times out, and we see that we haven't gotten |
510 | * a response in >60s. | 510 | * a response in >60s. |
511 | */ | 511 | */ |
512 | if (server->tcpStatus == CifsGood && | 512 | if ((server->tcpStatus == CifsGood || |
513 | server->tcpStatus == CifsNeedNegotiate) && | ||
513 | time_after(jiffies, server->lstrp + 2 * server->echo_interval)) { | 514 | time_after(jiffies, server->lstrp + 2 * server->echo_interval)) { |
514 | cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n", | 515 | cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n", |
515 | server->hostname, (2 * server->echo_interval) / HZ); | 516 | server->hostname, (2 * server->echo_interval) / HZ); |
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index cfacf2c97e94..fb2934b9b97c 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c | |||
@@ -426,6 +426,194 @@ smb2_query_file_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
426 | return rc; | 426 | return rc; |
427 | } | 427 | } |
428 | 428 | ||
429 | static ssize_t | ||
430 | move_smb2_ea_to_cifs(char *dst, size_t dst_size, | ||
431 | struct smb2_file_full_ea_info *src, size_t src_size, | ||
432 | const unsigned char *ea_name) | ||
433 | { | ||
434 | int rc = 0; | ||
435 | unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0; | ||
436 | char *name, *value; | ||
437 | size_t name_len, value_len, user_name_len; | ||
438 | |||
439 | while (src_size > 0) { | ||
440 | name = &src->ea_data[0]; | ||
441 | name_len = (size_t)src->ea_name_length; | ||
442 | value = &src->ea_data[src->ea_name_length + 1]; | ||
443 | value_len = (size_t)le16_to_cpu(src->ea_value_length); | ||
444 | |||
445 | if (name_len == 0) { | ||
446 | break; | ||
447 | } | ||
448 | |||
449 | if (src_size < 8 + name_len + 1 + value_len) { | ||
450 | cifs_dbg(FYI, "EA entry goes beyond length of list\n"); | ||
451 | rc = -EIO; | ||
452 | goto out; | ||
453 | } | ||
454 | |||
455 | if (ea_name) { | ||
456 | if (ea_name_len == name_len && | ||
457 | memcmp(ea_name, name, name_len) == 0) { | ||
458 | rc = value_len; | ||
459 | if (dst_size == 0) | ||
460 | goto out; | ||
461 | if (dst_size < value_len) { | ||
462 | rc = -ERANGE; | ||
463 | goto out; | ||
464 | } | ||
465 | memcpy(dst, value, value_len); | ||
466 | goto out; | ||
467 | } | ||
468 | } else { | ||
469 | /* 'user.' plus a terminating null */ | ||
470 | user_name_len = 5 + 1 + name_len; | ||
471 | |||
472 | rc += user_name_len; | ||
473 | |||
474 | if (dst_size >= user_name_len) { | ||
475 | dst_size -= user_name_len; | ||
476 | memcpy(dst, "user.", 5); | ||
477 | dst += 5; | ||
478 | memcpy(dst, src->ea_data, name_len); | ||
479 | dst += name_len; | ||
480 | *dst = 0; | ||
481 | ++dst; | ||
482 | } else if (dst_size == 0) { | ||
483 | /* skip copy - calc size only */ | ||
484 | } else { | ||
485 | /* stop before overrun buffer */ | ||
486 | rc = -ERANGE; | ||
487 | break; | ||
488 | } | ||
489 | } | ||
490 | |||
491 | if (!src->next_entry_offset) | ||
492 | break; | ||
493 | |||
494 | if (src_size < le32_to_cpu(src->next_entry_offset)) { | ||
495 | /* stop before overrun buffer */ | ||
496 | rc = -ERANGE; | ||
497 | break; | ||
498 | } | ||
499 | src_size -= le32_to_cpu(src->next_entry_offset); | ||
500 | src = (void *)((char *)src + | ||
501 | le32_to_cpu(src->next_entry_offset)); | ||
502 | } | ||
503 | |||
504 | /* didn't find the named attribute */ | ||
505 | if (ea_name) | ||
506 | rc = -ENODATA; | ||
507 | |||
508 | out: | ||
509 | return (ssize_t)rc; | ||
510 | } | ||
511 | |||
512 | static ssize_t | ||
513 | smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, | ||
514 | const unsigned char *path, const unsigned char *ea_name, | ||
515 | char *ea_data, size_t buf_size, | ||
516 | struct cifs_sb_info *cifs_sb) | ||
517 | { | ||
518 | int rc; | ||
519 | __le16 *utf16_path; | ||
520 | __u8 oplock = SMB2_OPLOCK_LEVEL_NONE; | ||
521 | struct cifs_open_parms oparms; | ||
522 | struct cifs_fid fid; | ||
523 | struct smb2_file_full_ea_info *smb2_data; | ||
524 | |||
525 | utf16_path = cifs_convert_path_to_utf16(path, cifs_sb); | ||
526 | if (!utf16_path) | ||
527 | return -ENOMEM; | ||
528 | |||
529 | oparms.tcon = tcon; | ||
530 | oparms.desired_access = FILE_READ_EA; | ||
531 | oparms.disposition = FILE_OPEN; | ||
532 | oparms.create_options = 0; | ||
533 | oparms.fid = &fid; | ||
534 | oparms.reconnect = false; | ||
535 | |||
536 | rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL); | ||
537 | kfree(utf16_path); | ||
538 | if (rc) { | ||
539 | cifs_dbg(FYI, "open failed rc=%d\n", rc); | ||
540 | return rc; | ||
541 | } | ||
542 | |||
543 | smb2_data = kzalloc(SMB2_MAX_EA_BUF, GFP_KERNEL); | ||
544 | if (smb2_data == NULL) { | ||
545 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | ||
546 | return -ENOMEM; | ||
547 | } | ||
548 | |||
549 | rc = SMB2_query_eas(xid, tcon, fid.persistent_fid, fid.volatile_fid, | ||
550 | smb2_data); | ||
551 | SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); | ||
552 | |||
553 | if (!rc) | ||
554 | rc = move_smb2_ea_to_cifs(ea_data, buf_size, smb2_data, | ||
555 | SMB2_MAX_EA_BUF, ea_name); | ||
556 | |||
557 | kfree(smb2_data); | ||
558 | return rc; | ||
559 | } | ||
560 | |||
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 | |||
429 | static bool | 617 | static bool |
430 | smb2_can_echo(struct TCP_Server_Info *server) | 618 | smb2_can_echo(struct TCP_Server_Info *server) |
431 | { | 619 | { |
@@ -2572,6 +2760,10 @@ struct smb_version_operations smb20_operations = { | |||
2572 | .dir_needs_close = smb2_dir_needs_close, | 2760 | .dir_needs_close = smb2_dir_needs_close, |
2573 | .get_dfs_refer = smb2_get_dfs_refer, | 2761 | .get_dfs_refer = smb2_get_dfs_refer, |
2574 | .select_sectype = smb2_select_sectype, | 2762 | .select_sectype = smb2_select_sectype, |
2763 | #ifdef CONFIG_CIFS_XATTR | ||
2764 | .query_all_EAs = smb2_query_eas, | ||
2765 | .set_EA = smb2_set_ea, | ||
2766 | #endif /* CIFS_XATTR */ | ||
2575 | #ifdef CONFIG_CIFS_ACL | 2767 | #ifdef CONFIG_CIFS_ACL |
2576 | .get_acl = get_smb2_acl, | 2768 | .get_acl = get_smb2_acl, |
2577 | .get_acl_by_fid = get_smb2_acl_by_fid, | 2769 | .get_acl_by_fid = get_smb2_acl_by_fid, |
@@ -2662,6 +2854,10 @@ struct smb_version_operations smb21_operations = { | |||
2662 | .enum_snapshots = smb3_enum_snapshots, | 2854 | .enum_snapshots = smb3_enum_snapshots, |
2663 | .get_dfs_refer = smb2_get_dfs_refer, | 2855 | .get_dfs_refer = smb2_get_dfs_refer, |
2664 | .select_sectype = smb2_select_sectype, | 2856 | .select_sectype = smb2_select_sectype, |
2857 | #ifdef CONFIG_CIFS_XATTR | ||
2858 | .query_all_EAs = smb2_query_eas, | ||
2859 | .set_EA = smb2_set_ea, | ||
2860 | #endif /* CIFS_XATTR */ | ||
2665 | #ifdef CONFIG_CIFS_ACL | 2861 | #ifdef CONFIG_CIFS_ACL |
2666 | .get_acl = get_smb2_acl, | 2862 | .get_acl = get_smb2_acl, |
2667 | .get_acl_by_fid = get_smb2_acl_by_fid, | 2863 | .get_acl_by_fid = get_smb2_acl_by_fid, |
@@ -2762,6 +2958,10 @@ struct smb_version_operations smb30_operations = { | |||
2762 | .receive_transform = smb3_receive_transform, | 2958 | .receive_transform = smb3_receive_transform, |
2763 | .get_dfs_refer = smb2_get_dfs_refer, | 2959 | .get_dfs_refer = smb2_get_dfs_refer, |
2764 | .select_sectype = smb2_select_sectype, | 2960 | .select_sectype = smb2_select_sectype, |
2961 | #ifdef CONFIG_CIFS_XATTR | ||
2962 | .query_all_EAs = smb2_query_eas, | ||
2963 | .set_EA = smb2_set_ea, | ||
2964 | #endif /* CIFS_XATTR */ | ||
2765 | #ifdef CONFIG_CIFS_ACL | 2965 | #ifdef CONFIG_CIFS_ACL |
2766 | .get_acl = get_smb2_acl, | 2966 | .get_acl = get_smb2_acl, |
2767 | .get_acl_by_fid = get_smb2_acl_by_fid, | 2967 | .get_acl_by_fid = get_smb2_acl_by_fid, |
@@ -2863,6 +3063,10 @@ struct smb_version_operations smb311_operations = { | |||
2863 | .receive_transform = smb3_receive_transform, | 3063 | .receive_transform = smb3_receive_transform, |
2864 | .get_dfs_refer = smb2_get_dfs_refer, | 3064 | .get_dfs_refer = smb2_get_dfs_refer, |
2865 | .select_sectype = smb2_select_sectype, | 3065 | .select_sectype = smb2_select_sectype, |
3066 | #ifdef CONFIG_CIFS_XATTR | ||
3067 | .query_all_EAs = smb2_query_eas, | ||
3068 | .set_EA = smb2_set_ea, | ||
3069 | #endif /* CIFS_XATTR */ | ||
2866 | }; | 3070 | }; |
2867 | #endif /* CIFS_SMB311 */ | 3071 | #endif /* CIFS_SMB311 */ |
2868 | 3072 | ||
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 7aa67206f6da..5531e7ee1210 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c | |||
@@ -238,6 +238,18 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon) | |||
238 | * the same SMB session | 238 | * the same SMB session |
239 | */ | 239 | */ |
240 | mutex_lock(&tcon->ses->session_mutex); | 240 | mutex_lock(&tcon->ses->session_mutex); |
241 | |||
242 | /* | ||
243 | * Recheck after acquire mutex. If another thread is negotiating | ||
244 | * and the server never sends an answer the socket will be closed | ||
245 | * and tcpStatus set to reconnect. | ||
246 | */ | ||
247 | if (server->tcpStatus == CifsNeedReconnect) { | ||
248 | rc = -EHOSTDOWN; | ||
249 | mutex_unlock(&tcon->ses->session_mutex); | ||
250 | goto out; | ||
251 | } | ||
252 | |||
241 | rc = cifs_negotiate_protocol(0, tcon->ses); | 253 | rc = cifs_negotiate_protocol(0, tcon->ses); |
242 | if (!rc && tcon->ses->need_reconnect) | 254 | if (!rc && tcon->ses->need_reconnect) |
243 | rc = cifs_setup_session(0, tcon->ses, nls_codepage); | 255 | rc = cifs_setup_session(0, tcon->ses, nls_codepage); |
@@ -2145,6 +2157,18 @@ qinf_exit: | |||
2145 | return rc; | 2157 | return rc; |
2146 | } | 2158 | } |
2147 | 2159 | ||
2160 | int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, | ||
2161 | u64 persistent_fid, u64 volatile_fid, | ||
2162 | struct smb2_file_full_ea_info *data) | ||
2163 | { | ||
2164 | return query_info(xid, tcon, persistent_fid, volatile_fid, | ||
2165 | FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 0, | ||
2166 | SMB2_MAX_EA_BUF, | ||
2167 | sizeof(struct smb2_file_full_ea_info), | ||
2168 | (void **)&data, | ||
2169 | NULL); | ||
2170 | } | ||
2171 | |||
2148 | int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, | 2172 | int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, |
2149 | u64 persistent_fid, u64 volatile_fid, struct smb2_file_all_info *data) | 2173 | u64 persistent_fid, u64 volatile_fid, struct smb2_file_all_info *data) |
2150 | { | 2174 | { |
@@ -3185,6 +3209,16 @@ SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon, | |||
3185 | } | 3209 | } |
3186 | 3210 | ||
3187 | int | 3211 | int |
3212 | SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, | ||
3213 | u64 persistent_fid, u64 volatile_fid, | ||
3214 | struct smb2_file_full_ea_info *buf, int len) | ||
3215 | { | ||
3216 | return send_set_info(xid, tcon, persistent_fid, volatile_fid, | ||
3217 | current->tgid, FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, | ||
3218 | 0, 1, (void **)&buf, &len); | ||
3219 | } | ||
3220 | |||
3221 | int | ||
3188 | SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, | 3222 | SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, |
3189 | const u64 persistent_fid, const u64 volatile_fid, | 3223 | const u64 persistent_fid, const u64 volatile_fid, |
3190 | __u8 oplock_level) | 3224 | __u8 oplock_level) |
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h index 2826882c81d1..393ed5f4e1b6 100644 --- a/fs/cifs/smb2pdu.h +++ b/fs/cifs/smb2pdu.h | |||
@@ -1178,6 +1178,16 @@ struct smb2_file_link_info { /* encoding of request for level 11 */ | |||
1178 | char FileName[0]; /* Name to be assigned to new link */ | 1178 | char FileName[0]; /* Name to be assigned to new link */ |
1179 | } __packed; /* level 11 Set */ | 1179 | } __packed; /* level 11 Set */ |
1180 | 1180 | ||
1181 | #define SMB2_MAX_EA_BUF 2048 | ||
1182 | |||
1183 | struct smb2_file_full_ea_info { /* encoding of response for level 15 */ | ||
1184 | __le32 next_entry_offset; | ||
1185 | __u8 flags; | ||
1186 | __u8 ea_name_length; | ||
1187 | __le16 ea_value_length; | ||
1188 | char ea_data[0]; /* \0 terminated name plus value */ | ||
1189 | } __packed; /* level 15 Set */ | ||
1190 | |||
1181 | /* | 1191 | /* |
1182 | * This level 18, although with struct with same name is different from cifs | 1192 | * This level 18, although with struct with same name is different from cifs |
1183 | * level 0x107. Level 0x107 has an extra u64 between AccessFlags and | 1193 | * level 0x107. Level 0x107 has an extra u64 between AccessFlags and |
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h index 1cadaf9f3c58..003217099ef3 100644 --- a/fs/cifs/smb2proto.h +++ b/fs/cifs/smb2proto.h | |||
@@ -132,6 +132,9 @@ extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, | |||
132 | u64 persistent_file_id, u64 volatile_file_id); | 132 | u64 persistent_file_id, u64 volatile_file_id); |
133 | extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, | 133 | extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, |
134 | u64 persistent_file_id, u64 volatile_file_id); | 134 | u64 persistent_file_id, u64 volatile_file_id); |
135 | extern int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, | ||
136 | u64 persistent_file_id, u64 volatile_file_id, | ||
137 | struct smb2_file_full_ea_info *data); | ||
135 | extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, | 138 | extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, |
136 | u64 persistent_file_id, u64 volatile_file_id, | 139 | u64 persistent_file_id, u64 volatile_file_id, |
137 | struct smb2_file_all_info *data); | 140 | struct smb2_file_all_info *data); |
@@ -169,6 +172,9 @@ extern int SMB2_set_info(const unsigned int xid, struct cifs_tcon *tcon, | |||
169 | extern int SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon, | 172 | extern int SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon, |
170 | u64 persistent_fid, u64 volatile_fid, | 173 | u64 persistent_fid, u64 volatile_fid, |
171 | struct cifs_ntsd *pnntsd, int pacllen, int aclflag); | 174 | 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); | ||
172 | extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, | 178 | extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, |
173 | u64 persistent_fid, u64 volatile_fid); | 179 | u64 persistent_fid, u64 volatile_fid); |
174 | extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, | 180 | extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, |
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index de50e749ff05..52f975d848a0 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
@@ -84,7 +84,7 @@ static int cifs_xattr_set(const struct xattr_handler *handler, | |||
84 | if (pTcon->ses->server->ops->set_EA) | 84 | if (pTcon->ses->server->ops->set_EA) |
85 | rc = pTcon->ses->server->ops->set_EA(xid, pTcon, | 85 | rc = pTcon->ses->server->ops->set_EA(xid, pTcon, |
86 | full_path, name, value, (__u16)size, | 86 | full_path, name, value, (__u16)size, |
87 | cifs_sb->local_nls, cifs_remap(cifs_sb)); | 87 | cifs_sb->local_nls, cifs_sb); |
88 | break; | 88 | break; |
89 | 89 | ||
90 | case XATTR_CIFS_ACL: { | 90 | case XATTR_CIFS_ACL: { |