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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag '5.3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
"Two fixes for stable, one that had dependency on earlier patch in this
merge window and can now go in, and a perf improvement in SMB3 open"

* tag '5.3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
cifs: update internal module number
cifs: flush before set-info if we have writeable handles
smb3: optimize open to not send query file internal info
cifs: copy_file_range needs to strip setuid bits and update timestamps
CIFS: fix deadlock in cached root handling

+126 -31
+8 -3
fs/cifs/cifsfs.c
··· 1104 1104 goto out; 1105 1105 } 1106 1106 1107 + rc = -EOPNOTSUPP; 1108 + if (!target_tcon->ses->server->ops->copychunk_range) 1109 + goto out; 1110 + 1107 1111 /* 1108 1112 * Note: cifs case is easier than btrfs since server responsible for 1109 1113 * checks for proper open modes and file type and if it wants ··· 1119 1115 /* should we flush first and last page first */ 1120 1116 truncate_inode_pages(&target_inode->i_data, 0); 1121 1117 1122 - if (target_tcon->ses->server->ops->copychunk_range) 1118 + rc = file_modified(dst_file); 1119 + if (!rc) 1123 1120 rc = target_tcon->ses->server->ops->copychunk_range(xid, 1124 1121 smb_file_src, smb_file_target, off, len, destoff); 1125 - else 1126 - rc = -EOPNOTSUPP; 1122 + 1123 + file_accessed(src_file); 1127 1124 1128 1125 /* force revalidate of size and timestamps of target file now 1129 1126 * that target is updated on the server
+1 -1
fs/cifs/cifsfs.h
··· 152 152 extern const struct export_operations cifs_export_ops; 153 153 #endif /* CONFIG_CIFS_NFSD_EXPORT */ 154 154 155 - #define CIFS_VERSION "2.20" 155 + #define CIFS_VERSION "2.21" 156 156 #endif /* _CIFSFS_H */
+16
fs/cifs/inode.c
··· 2406 2406 struct inode *inode = d_inode(direntry); 2407 2407 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 2408 2408 struct cifsInodeInfo *cifsInode = CIFS_I(inode); 2409 + struct cifsFileInfo *wfile; 2410 + struct cifs_tcon *tcon; 2409 2411 char *full_path = NULL; 2410 2412 int rc = -EACCES; 2411 2413 __u32 dosattr = 0; ··· 2453 2451 2454 2452 mapping_set_error(inode->i_mapping, rc); 2455 2453 rc = 0; 2454 + 2455 + if (attrs->ia_valid & ATTR_MTIME) { 2456 + rc = cifs_get_writable_file(cifsInode, false, &wfile); 2457 + if (!rc) { 2458 + tcon = tlink_tcon(wfile->tlink); 2459 + rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid); 2460 + cifsFileInfo_put(wfile); 2461 + if (rc) 2462 + return rc; 2463 + } else if (rc != -EBADF) 2464 + return rc; 2465 + else 2466 + rc = 0; 2467 + } 2456 2468 2457 2469 if (attrs->ia_valid & ATTR_SIZE) { 2458 2470 rc = cifs_set_file_size(inode, attrs, xid, full_path);
+12 -6
fs/cifs/smb2file.c
··· 88 88 } 89 89 90 90 if (buf) { 91 - /* open response does not have IndexNumber field - get it */ 92 - rc = SMB2_get_srv_num(xid, oparms->tcon, fid->persistent_fid, 91 + /* if open response does not have IndexNumber field - get it */ 92 + if (smb2_data->IndexNumber == 0) { 93 + rc = SMB2_get_srv_num(xid, oparms->tcon, 94 + fid->persistent_fid, 93 95 fid->volatile_fid, 94 96 &smb2_data->IndexNumber); 95 - if (rc) { 96 - /* let get_inode_info disable server inode numbers */ 97 - smb2_data->IndexNumber = 0; 98 - rc = 0; 97 + if (rc) { 98 + /* 99 + * let get_inode_info disable server inode 100 + * numbers 101 + */ 102 + smb2_data->IndexNumber = 0; 103 + rc = 0; 104 + } 99 105 } 100 106 move_smb2_info_to_cifs(buf, smb2_data); 101 107 }
+49 -4
fs/cifs/smb2ops.c
··· 694 694 695 695 smb2_set_related(&rqst[1]); 696 696 697 + /* 698 + * We do not hold the lock for the open because in case 699 + * SMB2_open needs to reconnect, it will end up calling 700 + * cifs_mark_open_files_invalid() which takes the lock again 701 + * thus causing a deadlock 702 + */ 703 + 704 + mutex_unlock(&tcon->crfid.fid_mutex); 697 705 rc = compound_send_recv(xid, ses, flags, 2, rqst, 698 706 resp_buftype, rsp_iov); 707 + mutex_lock(&tcon->crfid.fid_mutex); 708 + 709 + /* 710 + * Now we need to check again as the cached root might have 711 + * been successfully re-opened from a concurrent process 712 + */ 713 + 714 + if (tcon->crfid.is_valid) { 715 + /* work was already done */ 716 + 717 + /* stash fids for close() later */ 718 + struct cifs_fid fid = { 719 + .persistent_fid = pfid->persistent_fid, 720 + .volatile_fid = pfid->volatile_fid, 721 + }; 722 + 723 + /* 724 + * caller expects this func to set pfid to a valid 725 + * cached root, so we copy the existing one and get a 726 + * reference. 727 + */ 728 + memcpy(pfid, tcon->crfid.fid, sizeof(*pfid)); 729 + kref_get(&tcon->crfid.refcount); 730 + 731 + mutex_unlock(&tcon->crfid.fid_mutex); 732 + 733 + if (rc == 0) { 734 + /* close extra handle outside of crit sec */ 735 + SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid); 736 + } 737 + goto oshr_free; 738 + } 739 + 740 + /* Cached root is still invalid, continue normaly */ 741 + 699 742 if (rc) 700 743 goto oshr_exit; 701 744 ··· 754 711 tcon->crfid.is_valid = true; 755 712 kref_init(&tcon->crfid.refcount); 756 713 714 + /* BB TBD check to see if oplock level check can be removed below */ 757 715 if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) { 758 716 kref_get(&tcon->crfid.refcount); 759 - oplock = smb2_parse_lease_state(server, o_rsp, 760 - &oparms.fid->epoch, 761 - oparms.fid->lease_key); 717 + smb2_parse_contexts(server, o_rsp, 718 + &oparms.fid->epoch, 719 + oparms.fid->lease_key, &oplock, NULL); 762 720 } else 763 721 goto oshr_exit; 764 722 ··· 773 729 (char *)&tcon->crfid.file_all_info)) 774 730 tcon->crfid.file_all_info_is_valid = 1; 775 731 776 - oshr_exit: 732 + oshr_exit: 777 733 mutex_unlock(&tcon->crfid.fid_mutex); 734 + oshr_free: 778 735 SMB2_open_free(&rqst[0]); 779 736 SMB2_query_info_free(&rqst[1]); 780 737 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
+33 -13
fs/cifs/smb2pdu.c
··· 1873 1873 return buf; 1874 1874 } 1875 1875 1876 - __u8 1877 - smb2_parse_lease_state(struct TCP_Server_Info *server, 1876 + static void 1877 + parse_query_id_ctxt(struct create_context *cc, struct smb2_file_all_info *buf) 1878 + { 1879 + struct create_on_disk_id *pdisk_id = (struct create_on_disk_id *)cc; 1880 + 1881 + cifs_dbg(FYI, "parse query id context 0x%llx 0x%llx\n", 1882 + pdisk_id->DiskFileId, pdisk_id->VolumeId); 1883 + buf->IndexNumber = pdisk_id->DiskFileId; 1884 + } 1885 + 1886 + void 1887 + smb2_parse_contexts(struct TCP_Server_Info *server, 1878 1888 struct smb2_create_rsp *rsp, 1879 - unsigned int *epoch, char *lease_key) 1889 + unsigned int *epoch, char *lease_key, __u8 *oplock, 1890 + struct smb2_file_all_info *buf) 1880 1891 { 1881 1892 char *data_offset; 1882 1893 struct create_context *cc; ··· 1895 1884 unsigned int remaining; 1896 1885 char *name; 1897 1886 1887 + *oplock = 0; 1898 1888 data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset); 1899 1889 remaining = le32_to_cpu(rsp->CreateContextsLength); 1900 1890 cc = (struct create_context *)data_offset; 1891 + 1892 + /* Initialize inode number to 0 in case no valid data in qfid context */ 1893 + if (buf) 1894 + buf->IndexNumber = 0; 1895 + 1901 1896 while (remaining >= sizeof(struct create_context)) { 1902 1897 name = le16_to_cpu(cc->NameOffset) + (char *)cc; 1903 1898 if (le16_to_cpu(cc->NameLength) == 4 && 1904 - strncmp(name, "RqLs", 4) == 0) 1905 - return server->ops->parse_lease_buf(cc, epoch, 1906 - lease_key); 1899 + strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4) == 0) 1900 + *oplock = server->ops->parse_lease_buf(cc, epoch, 1901 + lease_key); 1902 + else if (buf && (le16_to_cpu(cc->NameLength) == 4) && 1903 + strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4) == 0) 1904 + parse_query_id_ctxt(cc, buf); 1907 1905 1908 1906 next = le32_to_cpu(cc->Next); 1909 1907 if (!next) ··· 1921 1901 cc = (struct create_context *)((char *)cc + next); 1922 1902 } 1923 1903 1924 - return 0; 1904 + if (rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE) 1905 + *oplock = rsp->OplockLevel; 1906 + 1907 + return; 1925 1908 } 1926 1909 1927 1910 static int ··· 2611 2588 buf->DeletePending = 0; 2612 2589 } 2613 2590 2614 - if (rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) 2615 - *oplock = smb2_parse_lease_state(server, rsp, 2616 - &oparms->fid->epoch, 2617 - oparms->fid->lease_key); 2618 - else 2619 - *oplock = rsp->OplockLevel; 2591 + 2592 + smb2_parse_contexts(server, rsp, &oparms->fid->epoch, 2593 + oparms->fid->lease_key, oplock, buf); 2620 2594 creat_exit: 2621 2595 SMB2_open_free(&rqst); 2622 2596 free_rsp_buf(resp_buftype, rsp);
+3 -1
fs/cifs/smb2pdu.h
··· 818 818 } __packed; 819 819 820 820 /* See MS-SMB2 2.2.14.2.9 */ 821 - struct on_disk_id { 821 + struct create_on_disk_id { 822 + struct create_context ccontext; 823 + __u8 Name[8]; 822 824 __le64 DiskFileId; 823 825 __le64 VolumeId; 824 826 __u32 Reserved[4];
+4 -3
fs/cifs/smb2proto.h
··· 228 228 229 229 extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *, 230 230 enum securityEnum); 231 - extern __u8 smb2_parse_lease_state(struct TCP_Server_Info *server, 232 - struct smb2_create_rsp *rsp, 233 - unsigned int *epoch, char *lease_key); 231 + extern void smb2_parse_contexts(struct TCP_Server_Info *server, 232 + struct smb2_create_rsp *rsp, 233 + unsigned int *epoch, char *lease_key, 234 + __u8 *oplock, struct smb2_file_all_info *buf); 234 235 extern int smb3_encryption_required(const struct cifs_tcon *tcon); 235 236 extern int smb2_validate_iov(unsigned int offset, unsigned int buffer_length, 236 237 struct kvec *iov, unsigned int min_buf_size);