Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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+

+274 -5
+1 -1
fs/cifs/cifsglob.h
··· 421 421 size_t, struct cifs_sb_info *); 422 422 int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *, 423 423 const char *, const void *, const __u16, 424 - const struct nls_table *, int); 424 + const struct nls_table *, struct cifs_sb_info *); 425 425 struct cifs_ntsd * (*get_acl)(struct cifs_sb_info *, struct inode *, 426 426 const char *, u32 *); 427 427 struct cifs_ntsd * (*get_acl_by_fid)(struct cifs_sb_info *,
+2 -1
fs/cifs/cifsproto.h
··· 484 484 extern int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon, 485 485 const char *fileName, const char *ea_name, 486 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 489 extern int CIFSSMBGetCIFSACL(const unsigned int xid, struct cifs_tcon *tcon, 489 490 __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen); 490 491 extern int CIFSSMBSetCIFSACL(const unsigned int, struct cifs_tcon *, __u16,
+14 -1
fs/cifs/cifssmb.c
··· 178 178 * reconnect the same SMB session 179 179 */ 180 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 193 rc = cifs_negotiate_protocol(0, ses); 182 194 if (rc == 0 && ses->need_reconnect) 183 195 rc = cifs_setup_session(0, ses, nls_codepage); ··· 6276 6264 CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon, 6277 6265 const char *fileName, const char *ea_name, const void *ea_value, 6278 6266 const __u16 ea_value_len, const struct nls_table *nls_codepage, 6279 - int remap) 6267 + struct cifs_sb_info *cifs_sb) 6280 6268 { 6281 6269 struct smb_com_transaction2_spi_req *pSMB = NULL; 6282 6270 struct smb_com_transaction2_spi_rsp *pSMBr = NULL; ··· 6285 6273 int rc = 0; 6286 6274 int bytes_returned = 0; 6287 6275 __u16 params, param_offset, byte_count, offset, count; 6276 + int remap = cifs_remap(cifs_sb); 6288 6277 6289 6278 cifs_dbg(FYI, "In SetEA\n"); 6290 6279 SetEARetry:
+2 -1
fs/cifs/connect.c
··· 509 509 * 65s kernel_recvmsg times out, and we see that we haven't gotten 510 510 * a response in >60s. 511 511 */ 512 - if (server->tcpStatus == CifsGood && 512 + if ((server->tcpStatus == CifsGood || 513 + server->tcpStatus == CifsNeedNegotiate) && 513 514 time_after(jiffies, server->lstrp + 2 * server->echo_interval)) { 514 515 cifs_dbg(VFS, "Server %s has not responded in %lu seconds. Reconnecting...\n", 515 516 server->hostname, (2 * server->echo_interval) / HZ);
+204
fs/cifs/smb2ops.c
··· 426 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 617 static bool 430 618 smb2_can_echo(struct TCP_Server_Info *server) 431 619 { ··· 2760 2572 .dir_needs_close = smb2_dir_needs_close, 2761 2573 .get_dfs_refer = smb2_get_dfs_refer, 2762 2574 .select_sectype = smb2_select_sectype, 2575 + #ifdef CONFIG_CIFS_XATTR 2576 + .query_all_EAs = smb2_query_eas, 2577 + .set_EA = smb2_set_ea, 2578 + #endif /* CIFS_XATTR */ 2763 2579 #ifdef CONFIG_CIFS_ACL 2764 2580 .get_acl = get_smb2_acl, 2765 2581 .get_acl_by_fid = get_smb2_acl_by_fid, ··· 2854 2662 .enum_snapshots = smb3_enum_snapshots, 2855 2663 .get_dfs_refer = smb2_get_dfs_refer, 2856 2664 .select_sectype = smb2_select_sectype, 2665 + #ifdef CONFIG_CIFS_XATTR 2666 + .query_all_EAs = smb2_query_eas, 2667 + .set_EA = smb2_set_ea, 2668 + #endif /* CIFS_XATTR */ 2857 2669 #ifdef CONFIG_CIFS_ACL 2858 2670 .get_acl = get_smb2_acl, 2859 2671 .get_acl_by_fid = get_smb2_acl_by_fid, ··· 2958 2762 .receive_transform = smb3_receive_transform, 2959 2763 .get_dfs_refer = smb2_get_dfs_refer, 2960 2764 .select_sectype = smb2_select_sectype, 2765 + #ifdef CONFIG_CIFS_XATTR 2766 + .query_all_EAs = smb2_query_eas, 2767 + .set_EA = smb2_set_ea, 2768 + #endif /* CIFS_XATTR */ 2961 2769 #ifdef CONFIG_CIFS_ACL 2962 2770 .get_acl = get_smb2_acl, 2963 2771 .get_acl_by_fid = get_smb2_acl_by_fid, ··· 3063 2863 .receive_transform = smb3_receive_transform, 3064 2864 .get_dfs_refer = smb2_get_dfs_refer, 3065 2865 .select_sectype = smb2_select_sectype, 2866 + #ifdef CONFIG_CIFS_XATTR 2867 + .query_all_EAs = smb2_query_eas, 2868 + .set_EA = smb2_set_ea, 2869 + #endif /* CIFS_XATTR */ 3066 2870 }; 3067 2871 #endif /* CIFS_SMB311 */ 3068 2872
+34
fs/cifs/smb2pdu.c
··· 238 238 * the same SMB session 239 239 */ 240 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 253 rc = cifs_negotiate_protocol(0, tcon->ses); 242 254 if (!rc && tcon->ses->need_reconnect) 243 255 rc = cifs_setup_session(0, tcon->ses, nls_codepage); ··· 2157 2145 return rc; 2158 2146 } 2159 2147 2148 + int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon, 2149 + u64 persistent_fid, u64 volatile_fid, 2150 + struct smb2_file_full_ea_info *data) 2151 + { 2152 + return query_info(xid, tcon, persistent_fid, volatile_fid, 2153 + FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 0, 2154 + SMB2_MAX_EA_BUF, 2155 + sizeof(struct smb2_file_full_ea_info), 2156 + (void **)&data, 2157 + NULL); 2158 + } 2159 + 2160 2160 int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, 2161 2161 u64 persistent_fid, u64 volatile_fid, struct smb2_file_all_info *data) 2162 2162 { ··· 3206 3182 return send_set_info(xid, tcon, persistent_fid, volatile_fid, 3207 3183 current->tgid, 0, SMB2_O_INFO_SECURITY, aclflag, 3208 3184 1, (void **)&pnntsd, &pacllen); 3185 + } 3186 + 3187 + int 3188 + SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, 3189 + u64 persistent_fid, u64 volatile_fid, 3190 + struct smb2_file_full_ea_info *buf, int len) 3191 + { 3192 + return send_set_info(xid, tcon, persistent_fid, volatile_fid, 3193 + current->tgid, FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 3194 + 0, 1, (void **)&buf, &len); 3209 3195 } 3210 3196 3211 3197 int
+10
fs/cifs/smb2pdu.h
··· 1178 1178 char FileName[0]; /* Name to be assigned to new link */ 1179 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 1192 * This level 18, although with struct with same name is different from cifs 1183 1193 * level 0x107. Level 0x107 has an extra u64 between AccessFlags and
+6
fs/cifs/smb2proto.h
··· 132 132 u64 persistent_file_id, u64 volatile_file_id); 133 133 extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, 134 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 138 extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon, 136 139 u64 persistent_file_id, u64 volatile_file_id, 137 140 struct smb2_file_all_info *data); ··· 172 169 extern int SMB2_set_acl(const unsigned int xid, struct cifs_tcon *tcon, 173 170 u64 persistent_fid, u64 volatile_fid, 174 171 struct cifs_ntsd *pnntsd, int pacllen, int aclflag); 172 + extern int SMB2_set_ea(const unsigned int xid, struct cifs_tcon *tcon, 173 + u64 persistent_fid, u64 volatile_fid, 174 + struct smb2_file_full_ea_info *buf, int len); 175 175 extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, 176 176 u64 persistent_fid, u64 volatile_fid); 177 177 extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
+1 -1
fs/cifs/xattr.c
··· 84 84 if (pTcon->ses->server->ops->set_EA) 85 85 rc = pTcon->ses->server->ops->set_EA(xid, pTcon, 86 86 full_path, name, value, (__u16)size, 87 - cifs_sb->local_nls, cifs_remap(cifs_sb)); 87 + cifs_sb->local_nls, cifs_sb); 88 88 break; 89 89 90 90 case XATTR_CIFS_ACL: {