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.1-rc-smb3' of git://git.samba.org/sfrench/cifs-2.6

Pull more smb3 updates from Steve French:
"Various tracing and debugging improvements, crediting fixes, some
cleanup, and important fallocate fix (fixes three xfstests) and lock
fix.

Summary:

- Various additional dynamic tracing tracepoints

- Debugging improvements (including ability to query the server via
SMB3 fsctl from userspace tools which can help with stats and
debugging)

- One minor performance improvement (root directory inode caching)

- Crediting (SMB3 flow control) fixes

- Some cleanup (docs and to mknod)

- Important fixes: one to smb3 implementation of fallocate zero range
(which fixes three xfstests) and a POSIX lock fix"

* tag '5.1-rc-smb3' of git://git.samba.org/sfrench/cifs-2.6: (22 commits)
CIFS: fix POSIX lock leak and invalid ptr deref
SMB3: Allow SMB3 FSCTL queries to be sent to server from tools
cifs: fix incorrect handling of smb2_set_sparse() return in smb3_simple_falloc
smb2: fix typo in definition of a few error flags
CIFS: make mknod() an smb_version_op
cifs: minor documentation updates
cifs: remove unused value pointed out by Coverity
SMB3: passthru query info doesn't check for SMB3 FSCTL passthru
smb3: add dynamic tracepoints for simple fallocate and zero range
cifs: fix smb3_zero_range so it can expand the file-size when required
cifs: add SMB2_ioctl_init/free helpers to be used with compounding
smb3: Add dynamic trace points for various compounded smb3 ops
cifs: cache FILE_ALL_INFO for the shared root handle
smb3: display volume serial number for shares in /proc/fs/cifs/DebugData
cifs: simplify how we handle credits in compound_send_recv()
smb3: add dynamic tracepoint for timeout waiting for credits
smb3: display security information in /proc/fs/cifs/DebugData more accurately
cifs: add a timeout argument to wait_for_free_credits
cifs: prevent starvation in wait_for_free_credits for multi-credit requests
cifs: wait_for_free_credits() make it possible to wait for >=1 credits
...

+979 -360
+2 -1
Documentation/filesystems/cifs/TODO
··· 111 111 112 112 5) Continue to extend the smb3 "buildbot" which does automated xfstesting 113 113 against Windows, Samba and Azure currently - to add additional tests and 114 - to allow the buildbot to execute the tests faster. 114 + to allow the buildbot to execute the tests faster. The URL for the 115 + buildbot is: http://smb3-test-rhel-75.southcentralus.cloudapp.azure.com 115 116 116 117 6) Address various coverity warnings (most are not bugs per-se, but 117 118 the more warnings are addressed, the easier it is to spot real
+22 -12
Documentation/filesystems/cifs/cifs.txt
··· 1 1 This is the client VFS module for the SMB3 NAS protocol as well 2 - older dialects such as the Common Internet File System (CIFS) 2 + as for older dialects such as the Common Internet File System (CIFS) 3 3 protocol which was the successor to the Server Message Block 4 4 (SMB) protocol, the native file sharing mechanism for most early 5 5 PC operating systems. New and improved versions of CIFS are now 6 - called SMB2 and SMB3. These dialects are also supported by the 7 - CIFS VFS module. CIFS is fully supported by network 8 - file servers such as Windows 2000, 2003, 2008, 2012 and 2016 9 - as well by Samba (which provides excellent CIFS 10 - server support for Linux and many other operating systems), Apple 11 - systems, as well as most Network Attached Storage vendors, so 12 - this network filesystem client can mount to a wide variety of 13 - servers. 6 + called SMB2 and SMB3. Use of SMB3 (and later, including SMB3.1.1) 7 + is strongly preferred over using older dialects like CIFS due to 8 + security reaasons. All modern dialects, including the most recent, 9 + SMB3.1.1 are supported by the CIFS VFS module. The SMB3 protocol 10 + is implemented and supported by all major file servers 11 + such as all modern versions of Windows (including Windows 2016 12 + Server), as well as by Samba (which provides excellent 13 + CIFS/SMB2/SMB3 server support and tools for Linux and many other 14 + operating systems). Apple systems also support SMB3 well, as 15 + do most Network Attached Storage vendors, so this network 16 + filesystem client can mount to a wide variety of systems. 17 + It also supports mounting to the cloud (for example 18 + Microsoft Azure), including the necessary security features. 14 19 15 20 The intent of this module is to provide the most advanced network 16 21 file system function for SMB3 compliant servers, including advanced ··· 29 24 cluster file systems for fileserving in some Linux to Linux environments, 30 25 not just in Linux to Windows (or Linux to Mac) environments. 31 26 32 - This filesystem has an mount utility (mount.cifs) that can be obtained from 27 + This filesystem has a mount utility (mount.cifs) and various user space 28 + tools (including smbinfo and setcifsacl) that can be obtained from 33 29 34 - https://ftp.samba.org/pub/linux-cifs/cifs-utils/ 30 + https://git.samba.org/?p=cifs-utils.git 31 + or 32 + git://git.samba.org/cifs-utils.git 35 33 36 - It must be installed in the directory with the other mount helpers. 34 + mount.cifs should be installed in the directory with the other mount helpers. 37 35 38 36 For more information on the module see the project wiki page at 39 37 38 + https://wiki.samba.org/index.php/LinuxCIFS 39 + and 40 40 https://wiki.samba.org/index.php/LinuxCIFS_utils
+10 -1
fs/cifs/cifs_debug.c
··· 115 115 seq_puts(m, " type: CDROM "); 116 116 else 117 117 seq_printf(m, " type: %d ", dev_type); 118 - if (tcon->seal) 118 + 119 + seq_printf(m, "Serial Number: 0x%x", tcon->vol_serial_number); 120 + 121 + if ((tcon->seal) || 122 + (tcon->ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) || 123 + (tcon->share_flags & SHI1005_FLAGS_ENCRYPT_DATA)) 119 124 seq_printf(m, " Encrypted"); 120 125 if (tcon->nocase) 121 126 seq_printf(m, " nocase"); ··· 376 371 atomic_read(&server->in_send), 377 372 atomic_read(&server->num_waiters)); 378 373 #endif 374 + if (ses->session_flags & SMB2_SESSION_FLAG_ENCRYPT_DATA) 375 + seq_puts(m, " encrypted"); 376 + if (ses->sign) 377 + seq_puts(m, " signed"); 379 378 380 379 seq_puts(m, "\n\tShares:"); 381 380 j = 0;
+3
fs/cifs/cifs_ioctl.h
··· 43 43 /* snapshots[]; */ 44 44 } __packed; 45 45 46 + /* query_info flags */ 47 + #define PASSTHRU_QUERY_INFO 0x00000000 48 + #define PASSTHRU_FSCTL 0x00000001 46 49 struct smb_query_info { 47 50 __u32 info_type; 48 51 __u32 file_info_class;
+14 -2
fs/cifs/cifsglob.h
··· 479 479 struct cifs_tcon *tcon, 480 480 __le16 *path, int is_dir, 481 481 unsigned long p); 482 + /* make unix special files (block, char, fifo, socket) */ 483 + int (*make_node)(unsigned int xid, 484 + struct inode *inode, 485 + struct dentry *dentry, 486 + struct cifs_tcon *tcon, 487 + char *full_path, 488 + umode_t mode, 489 + dev_t device_number); 482 490 }; 483 491 484 492 struct smb_version_values { ··· 743 735 } 744 736 745 737 static inline bool 746 - has_credits(struct TCP_Server_Info *server, int *credits) 738 + has_credits(struct TCP_Server_Info *server, int *credits, int num_credits) 747 739 { 748 740 int num; 749 741 spin_lock(&server->req_lock); 750 742 num = *credits; 751 743 spin_unlock(&server->req_lock); 752 - return num > 0; 744 + return num >= num_credits; 753 745 } 754 746 755 747 static inline void ··· 970 962 971 963 struct cached_fid { 972 964 bool is_valid:1; /* Do we have a useable root fid */ 965 + bool file_all_info_is_valid:1; 966 + 973 967 struct kref refcount; 974 968 struct cifs_fid *fid; 975 969 struct mutex fid_mutex; 976 970 struct cifs_tcon *tcon; 977 971 struct work_struct lease_break; 972 + struct smb2_file_all_info file_all_info; 978 973 }; 979 974 980 975 /* ··· 1746 1735 * GlobalMid_Lock protects: 1747 1736 * list operations on pending_mid_q and oplockQ 1748 1737 * updates to XID counters, multiplex id and SMB sequence numbers 1738 + * list operations on global DnotifyReqList 1749 1739 * tcp_ses_lock protects: 1750 1740 * list operations on tcp and SMB session lists 1751 1741 * tcon->open_file_lock protects the list of open files hanging off the tcon
-4
fs/cifs/connect.c
··· 1191 1191 continue; 1192 1192 } 1193 1193 1194 - if (server->large_buf) 1195 - buf = server->bigbuf; 1196 - 1197 - 1198 1194 server->lstrp = jiffies; 1199 1195 1200 1196 for (i = 0; i < num_mids; i++) {
+3 -104
fs/cifs/dir.c
··· 621 621 { 622 622 int rc = -EPERM; 623 623 unsigned int xid; 624 - int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL; 625 624 struct cifs_sb_info *cifs_sb; 626 625 struct tcon_link *tlink; 627 626 struct cifs_tcon *tcon; 628 - struct cifs_io_parms io_parms; 629 627 char *full_path = NULL; 630 - struct inode *newinode = NULL; 631 - __u32 oplock = 0; 632 - struct cifs_fid fid; 633 - struct cifs_open_parms oparms; 634 - FILE_ALL_INFO *buf = NULL; 635 - unsigned int bytes_written; 636 - struct win_dev *pdev; 637 - struct kvec iov[2]; 638 628 639 629 if (!old_valid_dev(device_number)) 640 630 return -EINVAL; ··· 644 654 goto mknod_out; 645 655 } 646 656 647 - if (tcon->unix_ext) { 648 - struct cifs_unix_set_info_args args = { 649 - .mode = mode & ~current_umask(), 650 - .ctime = NO_CHANGE_64, 651 - .atime = NO_CHANGE_64, 652 - .mtime = NO_CHANGE_64, 653 - .device = device_number, 654 - }; 655 - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 656 - args.uid = current_fsuid(); 657 - args.gid = current_fsgid(); 658 - } else { 659 - args.uid = INVALID_UID; /* no change */ 660 - args.gid = INVALID_GID; /* no change */ 661 - } 662 - rc = CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, 663 - cifs_sb->local_nls, 664 - cifs_remap(cifs_sb)); 665 - if (rc) 666 - goto mknod_out; 667 - 668 - rc = cifs_get_inode_info_unix(&newinode, full_path, 669 - inode->i_sb, xid); 670 - 671 - if (rc == 0) 672 - d_instantiate(direntry, newinode); 673 - goto mknod_out; 674 - } 675 - 676 - if (!S_ISCHR(mode) && !S_ISBLK(mode)) 677 - goto mknod_out; 678 - 679 - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) 680 - goto mknod_out; 681 - 682 - 683 - cifs_dbg(FYI, "sfu compat create special file\n"); 684 - 685 - buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); 686 - if (buf == NULL) { 687 - rc = -ENOMEM; 688 - goto mknod_out; 689 - } 690 - 691 - if (backup_cred(cifs_sb)) 692 - create_options |= CREATE_OPEN_BACKUP_INTENT; 693 - 694 - oparms.tcon = tcon; 695 - oparms.cifs_sb = cifs_sb; 696 - oparms.desired_access = GENERIC_WRITE; 697 - oparms.create_options = create_options; 698 - oparms.disposition = FILE_CREATE; 699 - oparms.path = full_path; 700 - oparms.fid = &fid; 701 - oparms.reconnect = false; 702 - 703 - if (tcon->ses->server->oplocks) 704 - oplock = REQ_OPLOCK; 705 - else 706 - oplock = 0; 707 - rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, buf); 708 - if (rc) 709 - goto mknod_out; 710 - 711 - /* 712 - * BB Do not bother to decode buf since no local inode yet to put 713 - * timestamps in, but we can reuse it safely. 714 - */ 715 - 716 - pdev = (struct win_dev *)buf; 717 - io_parms.pid = current->tgid; 718 - io_parms.tcon = tcon; 719 - io_parms.offset = 0; 720 - io_parms.length = sizeof(struct win_dev); 721 - iov[1].iov_base = buf; 722 - iov[1].iov_len = sizeof(struct win_dev); 723 - if (S_ISCHR(mode)) { 724 - memcpy(pdev->type, "IntxCHR", 8); 725 - pdev->major = cpu_to_le64(MAJOR(device_number)); 726 - pdev->minor = cpu_to_le64(MINOR(device_number)); 727 - rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, 728 - &bytes_written, iov, 1); 729 - } else if (S_ISBLK(mode)) { 730 - memcpy(pdev->type, "IntxBLK", 8); 731 - pdev->major = cpu_to_le64(MAJOR(device_number)); 732 - pdev->minor = cpu_to_le64(MINOR(device_number)); 733 - rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, 734 - &bytes_written, iov, 1); 735 - } 736 - tcon->ses->server->ops->close(xid, tcon, &fid); 737 - d_drop(direntry); 738 - 739 - /* FIXME: add code here to set EAs */ 657 + rc = tcon->ses->server->ops->make_node(xid, inode, direntry, tcon, 658 + full_path, mode, 659 + device_number); 740 660 741 661 mknod_out: 742 662 kfree(full_path); 743 - kfree(buf); 744 663 free_xid(xid); 745 664 cifs_put_tlink(tlink); 746 665 return rc;
+13 -1
fs/cifs/file.c
··· 1645 1645 rc = server->ops->mand_unlock_range(cfile, flock, xid); 1646 1646 1647 1647 out: 1648 - if (flock->fl_flags & FL_POSIX && !rc) 1648 + if (flock->fl_flags & FL_POSIX) { 1649 + /* 1650 + * If this is a request to remove all locks because we 1651 + * are closing the file, it doesn't matter if the 1652 + * unlocking failed as both cifs.ko and the SMB server 1653 + * remove the lock on file close 1654 + */ 1655 + if (rc) { 1656 + cifs_dbg(VFS, "%s failed rc=%d\n", __func__, rc); 1657 + if (!(flock->fl_flags & FL_CLOSE)) 1658 + return rc; 1659 + } 1649 1660 rc = locks_lock_file_wait(file, flock); 1661 + } 1650 1662 return rc; 1651 1663 } 1652 1664
+126
fs/cifs/smb1ops.c
··· 1027 1027 return false; 1028 1028 } 1029 1029 1030 + static int 1031 + cifs_make_node(unsigned int xid, struct inode *inode, 1032 + struct dentry *dentry, struct cifs_tcon *tcon, 1033 + char *full_path, umode_t mode, dev_t dev) 1034 + { 1035 + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 1036 + struct inode *newinode = NULL; 1037 + int rc = -EPERM; 1038 + int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL; 1039 + FILE_ALL_INFO *buf = NULL; 1040 + struct cifs_io_parms io_parms; 1041 + __u32 oplock = 0; 1042 + struct cifs_fid fid; 1043 + struct cifs_open_parms oparms; 1044 + unsigned int bytes_written; 1045 + struct win_dev *pdev; 1046 + struct kvec iov[2]; 1047 + 1048 + if (tcon->unix_ext) { 1049 + /* 1050 + * SMB1 Unix Extensions: requires server support but 1051 + * works with all special files 1052 + */ 1053 + struct cifs_unix_set_info_args args = { 1054 + .mode = mode & ~current_umask(), 1055 + .ctime = NO_CHANGE_64, 1056 + .atime = NO_CHANGE_64, 1057 + .mtime = NO_CHANGE_64, 1058 + .device = dev, 1059 + }; 1060 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { 1061 + args.uid = current_fsuid(); 1062 + args.gid = current_fsgid(); 1063 + } else { 1064 + args.uid = INVALID_UID; /* no change */ 1065 + args.gid = INVALID_GID; /* no change */ 1066 + } 1067 + rc = CIFSSMBUnixSetPathInfo(xid, tcon, full_path, &args, 1068 + cifs_sb->local_nls, 1069 + cifs_remap(cifs_sb)); 1070 + if (rc) 1071 + goto out; 1072 + 1073 + rc = cifs_get_inode_info_unix(&newinode, full_path, 1074 + inode->i_sb, xid); 1075 + 1076 + if (rc == 0) 1077 + d_instantiate(dentry, newinode); 1078 + goto out; 1079 + } 1080 + 1081 + /* 1082 + * SMB1 SFU emulation: should work with all servers, but only 1083 + * support block and char device (no socket & fifo) 1084 + */ 1085 + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) 1086 + goto out; 1087 + 1088 + if (!S_ISCHR(mode) && !S_ISBLK(mode)) 1089 + goto out; 1090 + 1091 + cifs_dbg(FYI, "sfu compat create special file\n"); 1092 + 1093 + buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); 1094 + if (buf == NULL) { 1095 + rc = -ENOMEM; 1096 + goto out; 1097 + } 1098 + 1099 + if (backup_cred(cifs_sb)) 1100 + create_options |= CREATE_OPEN_BACKUP_INTENT; 1101 + 1102 + oparms.tcon = tcon; 1103 + oparms.cifs_sb = cifs_sb; 1104 + oparms.desired_access = GENERIC_WRITE; 1105 + oparms.create_options = create_options; 1106 + oparms.disposition = FILE_CREATE; 1107 + oparms.path = full_path; 1108 + oparms.fid = &fid; 1109 + oparms.reconnect = false; 1110 + 1111 + if (tcon->ses->server->oplocks) 1112 + oplock = REQ_OPLOCK; 1113 + else 1114 + oplock = 0; 1115 + rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, buf); 1116 + if (rc) 1117 + goto out; 1118 + 1119 + /* 1120 + * BB Do not bother to decode buf since no local inode yet to put 1121 + * timestamps in, but we can reuse it safely. 1122 + */ 1123 + 1124 + pdev = (struct win_dev *)buf; 1125 + io_parms.pid = current->tgid; 1126 + io_parms.tcon = tcon; 1127 + io_parms.offset = 0; 1128 + io_parms.length = sizeof(struct win_dev); 1129 + iov[1].iov_base = buf; 1130 + iov[1].iov_len = sizeof(struct win_dev); 1131 + if (S_ISCHR(mode)) { 1132 + memcpy(pdev->type, "IntxCHR", 8); 1133 + pdev->major = cpu_to_le64(MAJOR(dev)); 1134 + pdev->minor = cpu_to_le64(MINOR(dev)); 1135 + rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, 1136 + &bytes_written, iov, 1); 1137 + } else if (S_ISBLK(mode)) { 1138 + memcpy(pdev->type, "IntxBLK", 8); 1139 + pdev->major = cpu_to_le64(MAJOR(dev)); 1140 + pdev->minor = cpu_to_le64(MINOR(dev)); 1141 + rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, 1142 + &bytes_written, iov, 1); 1143 + } 1144 + tcon->ses->server->ops->close(xid, tcon, &fid); 1145 + d_drop(dentry); 1146 + 1147 + /* FIXME: add code here to set EAs */ 1148 + out: 1149 + kfree(buf); 1150 + return rc; 1151 + } 1152 + 1153 + 1154 + 1030 1155 struct smb_version_operations smb1_operations = { 1031 1156 .send_cancel = send_nt_cancel, 1032 1157 .compare_fids = cifs_compare_fids, ··· 1235 1110 .get_acl_by_fid = get_cifs_acl_by_fid, 1236 1111 .set_acl = set_cifs_acl, 1237 1112 #endif /* CIFS_ACL */ 1113 + .make_node = cifs_make_node, 1238 1114 }; 1239 1115 1240 1116 struct smb_version_values smb1_values = {
+78 -9
fs/cifs/smb2inode.c
··· 37 37 #include "smb2pdu.h" 38 38 #include "smb2proto.h" 39 39 40 + static void 41 + free_set_inf_compound(struct smb_rqst *rqst) 42 + { 43 + if (rqst[1].rq_iov) 44 + SMB2_set_info_free(&rqst[1]); 45 + if (rqst[2].rq_iov) 46 + SMB2_close_free(&rqst[2]); 47 + } 48 + 49 + 40 50 static int 41 51 smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon, 42 52 struct cifs_sb_info *cifs_sb, const char *full_path, ··· 122 112 PATH_MAX * 2, 0, NULL); 123 113 smb2_set_next_command(tcon, &rqst[num_rqst]); 124 114 smb2_set_related(&rqst[num_rqst++]); 115 + trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid, 116 + full_path); 125 117 break; 126 118 case SMB2_OP_DELETE: 119 + trace_smb3_delete_enter(xid, ses->Suid, tcon->tid, full_path); 127 120 break; 128 121 case SMB2_OP_MKDIR: 129 122 /* 130 123 * Directories are created through parameters in the 131 124 * SMB2_open() call. 132 125 */ 126 + trace_smb3_mkdir_enter(xid, ses->Suid, tcon->tid, full_path); 133 127 break; 134 128 case SMB2_OP_RMDIR: 135 129 memset(&si_iov, 0, sizeof(si_iov)); ··· 149 135 SMB2_O_INFO_FILE, 0, data, size); 150 136 smb2_set_next_command(tcon, &rqst[num_rqst]); 151 137 smb2_set_related(&rqst[num_rqst++]); 138 + trace_smb3_rmdir_enter(xid, ses->Suid, tcon->tid, full_path); 152 139 break; 153 140 case SMB2_OP_SET_EOF: 154 141 memset(&si_iov, 0, sizeof(si_iov)); ··· 165 150 SMB2_O_INFO_FILE, 0, data, size); 166 151 smb2_set_next_command(tcon, &rqst[num_rqst]); 167 152 smb2_set_related(&rqst[num_rqst++]); 153 + trace_smb3_set_eof_enter(xid, ses->Suid, tcon->tid, full_path); 168 154 break; 169 155 case SMB2_OP_SET_INFO: 170 156 memset(&si_iov, 0, sizeof(si_iov)); ··· 182 166 SMB2_O_INFO_FILE, 0, data, size); 183 167 smb2_set_next_command(tcon, &rqst[num_rqst]); 184 168 smb2_set_related(&rqst[num_rqst++]); 169 + trace_smb3_set_info_compound_enter(xid, ses->Suid, tcon->tid, 170 + full_path); 185 171 break; 186 172 case SMB2_OP_RENAME: 187 173 memset(&si_iov, 0, sizeof(si_iov)); ··· 208 190 SMB2_O_INFO_FILE, 0, data, size); 209 191 smb2_set_next_command(tcon, &rqst[num_rqst]); 210 192 smb2_set_related(&rqst[num_rqst++]); 193 + trace_smb3_rename_enter(xid, ses->Suid, tcon->tid, full_path); 211 194 break; 212 195 case SMB2_OP_HARDLINK: 213 196 memset(&si_iov, 0, sizeof(si_iov)); ··· 233 214 SMB2_O_INFO_FILE, 0, data, size); 234 215 smb2_set_next_command(tcon, &rqst[num_rqst]); 235 216 smb2_set_related(&rqst[num_rqst++]); 217 + trace_smb3_hardlink_enter(xid, ses->Suid, tcon->tid, full_path); 236 218 break; 237 219 default: 238 220 cifs_dbg(VFS, "Invalid command\n"); ··· 272 252 SMB2_query_info_free(&rqst[1]); 273 253 if (rqst[2].rq_iov) 274 254 SMB2_close_free(&rqst[2]); 255 + if (rc) 256 + trace_smb3_query_info_compound_err(xid, ses->Suid, 257 + tcon->tid, rc); 258 + else 259 + trace_smb3_query_info_compound_done(xid, ses->Suid, 260 + tcon->tid); 275 261 break; 276 262 case SMB2_OP_DELETE: 263 + if (rc) 264 + trace_smb3_delete_err(xid, ses->Suid, tcon->tid, rc); 265 + else 266 + trace_smb3_delete_done(xid, ses->Suid, tcon->tid); 267 + if (rqst[1].rq_iov) 268 + SMB2_close_free(&rqst[1]); 269 + break; 277 270 case SMB2_OP_MKDIR: 271 + if (rc) 272 + trace_smb3_mkdir_err(xid, ses->Suid, tcon->tid, rc); 273 + else 274 + trace_smb3_mkdir_done(xid, ses->Suid, tcon->tid); 278 275 if (rqst[1].rq_iov) 279 276 SMB2_close_free(&rqst[1]); 280 277 break; 281 278 case SMB2_OP_HARDLINK: 279 + if (rc) 280 + trace_smb3_hardlink_err(xid, ses->Suid, tcon->tid, rc); 281 + else 282 + trace_smb3_hardlink_done(xid, ses->Suid, tcon->tid); 283 + free_set_inf_compound(rqst); 284 + break; 282 285 case SMB2_OP_RENAME: 286 + if (rc) 287 + trace_smb3_rename_err(xid, ses->Suid, tcon->tid, rc); 288 + else 289 + trace_smb3_rename_done(xid, ses->Suid, tcon->tid); 290 + free_set_inf_compound(rqst); 291 + break; 283 292 case SMB2_OP_RMDIR: 293 + if (rc) 294 + trace_smb3_rmdir_err(xid, ses->Suid, tcon->tid, rc); 295 + else 296 + trace_smb3_rmdir_done(xid, ses->Suid, tcon->tid); 297 + free_set_inf_compound(rqst); 298 + break; 284 299 case SMB2_OP_SET_EOF: 300 + if (rc) 301 + trace_smb3_set_eof_err(xid, ses->Suid, tcon->tid, rc); 302 + else 303 + trace_smb3_set_eof_done(xid, ses->Suid, tcon->tid); 304 + free_set_inf_compound(rqst); 305 + break; 285 306 case SMB2_OP_SET_INFO: 286 - if (rqst[1].rq_iov) 287 - SMB2_set_info_free(&rqst[1]); 288 - if (rqst[2].rq_iov) 289 - SMB2_close_free(&rqst[2]); 307 + if (rc) 308 + trace_smb3_set_info_compound_err(xid, ses->Suid, 309 + tcon->tid, rc); 310 + else 311 + trace_smb3_set_info_compound_done(xid, ses->Suid, 312 + tcon->tid); 313 + free_set_inf_compound(rqst); 290 314 break; 291 315 } 292 316 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); ··· 373 309 rc = open_shroot(xid, tcon, &fid); 374 310 if (rc) 375 311 goto out; 376 - rc = SMB2_query_info(xid, tcon, fid.persistent_fid, 377 - fid.volatile_fid, smb2_data); 312 + 313 + if (tcon->crfid.file_all_info_is_valid) { 314 + move_smb2_info_to_cifs(data, 315 + &tcon->crfid.file_all_info); 316 + } else { 317 + rc = SMB2_query_info(xid, tcon, fid.persistent_fid, 318 + fid.volatile_fid, smb2_data); 319 + if (!rc) 320 + move_smb2_info_to_cifs(data, smb2_data); 321 + } 378 322 close_shroot(&tcon->crfid); 379 - if (rc) 380 - goto out; 381 - move_smb2_info_to_cifs(data, smb2_data); 382 323 goto out; 383 324 } 384 325
+362 -57
fs/cifs/smb2ops.c
··· 185 185 spin_unlock(&server->req_lock); 186 186 cifs_num_waiters_inc(server); 187 187 rc = wait_event_killable(server->request_q, 188 - has_credits(server, &server->credits)); 188 + has_credits(server, &server->credits, 1)); 189 189 cifs_num_waiters_dec(server); 190 190 if (rc) 191 191 return rc; ··· 619 619 SMB2_close(0, cfid->tcon, cfid->fid->persistent_fid, 620 620 cfid->fid->volatile_fid); 621 621 cfid->is_valid = false; 622 + cfid->file_all_info_is_valid = false; 622 623 } 623 624 } 624 625 ··· 644 643 */ 645 644 int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid) 646 645 { 647 - struct cifs_open_parms oparams; 648 - int rc; 649 - __le16 srch_path = 0; /* Null - since an open of top of share */ 646 + struct cifs_ses *ses = tcon->ses; 647 + struct TCP_Server_Info *server = ses->server; 648 + struct cifs_open_parms oparms; 649 + struct smb2_create_rsp *o_rsp = NULL; 650 + struct smb2_query_info_rsp *qi_rsp = NULL; 651 + int resp_buftype[2]; 652 + struct smb_rqst rqst[2]; 653 + struct kvec rsp_iov[2]; 654 + struct kvec open_iov[SMB2_CREATE_IOV_SIZE]; 655 + struct kvec qi_iov[1]; 656 + int rc, flags = 0; 657 + __le16 utf16_path = 0; /* Null - since an open of top of share */ 650 658 u8 oplock = SMB2_OPLOCK_LEVEL_II; 651 659 652 660 mutex_lock(&tcon->crfid.fid_mutex); ··· 667 657 return 0; 668 658 } 669 659 670 - oparams.tcon = tcon; 671 - oparams.create_options = 0; 672 - oparams.desired_access = FILE_READ_ATTRIBUTES; 673 - oparams.disposition = FILE_OPEN; 674 - oparams.fid = pfid; 675 - oparams.reconnect = false; 660 + if (smb3_encryption_required(tcon)) 661 + flags |= CIFS_TRANSFORM_REQ; 676 662 677 - rc = SMB2_open(xid, &oparams, &srch_path, &oplock, NULL, NULL, NULL); 678 - if (rc == 0) { 679 - memcpy(tcon->crfid.fid, pfid, sizeof(struct cifs_fid)); 680 - tcon->crfid.tcon = tcon; 681 - tcon->crfid.is_valid = true; 682 - kref_init(&tcon->crfid.refcount); 683 - kref_get(&tcon->crfid.refcount); 684 - } 663 + memset(rqst, 0, sizeof(rqst)); 664 + resp_buftype[0] = resp_buftype[1] = CIFS_NO_BUFFER; 665 + memset(rsp_iov, 0, sizeof(rsp_iov)); 666 + 667 + /* Open */ 668 + memset(&open_iov, 0, sizeof(open_iov)); 669 + rqst[0].rq_iov = open_iov; 670 + rqst[0].rq_nvec = SMB2_CREATE_IOV_SIZE; 671 + 672 + oparms.tcon = tcon; 673 + oparms.create_options = 0; 674 + oparms.desired_access = FILE_READ_ATTRIBUTES; 675 + oparms.disposition = FILE_OPEN; 676 + oparms.fid = pfid; 677 + oparms.reconnect = false; 678 + 679 + rc = SMB2_open_init(tcon, &rqst[0], &oplock, &oparms, &utf16_path); 680 + if (rc) 681 + goto oshr_exit; 682 + smb2_set_next_command(tcon, &rqst[0]); 683 + 684 + memset(&qi_iov, 0, sizeof(qi_iov)); 685 + rqst[1].rq_iov = qi_iov; 686 + rqst[1].rq_nvec = 1; 687 + 688 + rc = SMB2_query_info_init(tcon, &rqst[1], COMPOUND_FID, 689 + COMPOUND_FID, FILE_ALL_INFORMATION, 690 + SMB2_O_INFO_FILE, 0, 691 + sizeof(struct smb2_file_all_info) + 692 + PATH_MAX * 2, 0, NULL); 693 + if (rc) 694 + goto oshr_exit; 695 + 696 + smb2_set_related(&rqst[1]); 697 + 698 + rc = compound_send_recv(xid, ses, flags, 2, rqst, 699 + resp_buftype, rsp_iov); 700 + if (rc) 701 + goto oshr_exit; 702 + 703 + o_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base; 704 + oparms.fid->persistent_fid = o_rsp->PersistentFileId; 705 + oparms.fid->volatile_fid = o_rsp->VolatileFileId; 706 + #ifdef CONFIG_CIFS_DEBUG2 707 + oparms.fid->mid = le64_to_cpu(o_rsp->sync_hdr.MessageId); 708 + #endif /* CIFS_DEBUG2 */ 709 + 710 + if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) 711 + oplock = smb2_parse_lease_state(server, o_rsp, 712 + &oparms.fid->epoch, 713 + oparms.fid->lease_key); 714 + else 715 + goto oshr_exit; 716 + 717 + 718 + memcpy(tcon->crfid.fid, pfid, sizeof(struct cifs_fid)); 719 + tcon->crfid.tcon = tcon; 720 + tcon->crfid.is_valid = true; 721 + kref_init(&tcon->crfid.refcount); 722 + kref_get(&tcon->crfid.refcount); 723 + 724 + 725 + qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base; 726 + if (le32_to_cpu(qi_rsp->OutputBufferLength) < sizeof(struct smb2_file_all_info)) 727 + goto oshr_exit; 728 + rc = smb2_validate_and_copy_iov( 729 + le16_to_cpu(qi_rsp->OutputBufferOffset), 730 + sizeof(struct smb2_file_all_info), 731 + &rsp_iov[1], sizeof(struct smb2_file_all_info), 732 + (char *)&tcon->crfid.file_all_info); 733 + if (rc) 734 + goto oshr_exit; 735 + tcon->crfid.file_all_info_is_valid = 1; 736 + 737 + oshr_exit: 685 738 mutex_unlock(&tcon->crfid.fid_mutex); 739 + SMB2_open_free(&rqst[0]); 740 + SMB2_query_info_free(&rqst[1]); 741 + free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); 742 + free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); 686 743 return rc; 687 744 } 688 745 ··· 1330 1253 struct smb_query_info __user *pqi; 1331 1254 int rc = 0; 1332 1255 int flags = 0; 1333 - struct smb2_query_info_rsp *rsp = NULL; 1256 + struct smb2_query_info_rsp *qi_rsp = NULL; 1257 + struct smb2_ioctl_rsp *io_rsp = NULL; 1334 1258 void *buffer = NULL; 1335 1259 struct smb_rqst rqst[3]; 1336 1260 int resp_buftype[3]; ··· 1341 1263 u8 oplock = SMB2_OPLOCK_LEVEL_NONE; 1342 1264 struct cifs_fid fid; 1343 1265 struct kvec qi_iov[1]; 1266 + struct kvec io_iov[SMB2_IOCTL_IOV_SIZE]; 1344 1267 struct kvec close_iov[1]; 1345 1268 1346 1269 memset(rqst, 0, sizeof(rqst)); ··· 1392 1313 smb2_set_next_command(tcon, &rqst[0]); 1393 1314 1394 1315 /* Query */ 1395 - memset(&qi_iov, 0, sizeof(qi_iov)); 1396 - rqst[1].rq_iov = qi_iov; 1397 - rqst[1].rq_nvec = 1; 1316 + if (qi.flags & PASSTHRU_FSCTL) { 1317 + /* Can eventually relax perm check since server enforces too */ 1318 + if (!capable(CAP_SYS_ADMIN)) 1319 + rc = -EPERM; 1320 + else { 1321 + memset(&io_iov, 0, sizeof(io_iov)); 1322 + rqst[1].rq_iov = io_iov; 1323 + rqst[1].rq_nvec = SMB2_IOCTL_IOV_SIZE; 1398 1324 1399 - rc = SMB2_query_info_init(tcon, &rqst[1], COMPOUND_FID, COMPOUND_FID, 1400 - qi.file_info_class, qi.info_type, 1401 - qi.additional_information, 1325 + rc = SMB2_ioctl_init(tcon, &rqst[1], 1326 + COMPOUND_FID, COMPOUND_FID, 1327 + qi.info_type, true, NULL, 1328 + 0); 1329 + } 1330 + } else if (qi.flags == PASSTHRU_QUERY_INFO) { 1331 + memset(&qi_iov, 0, sizeof(qi_iov)); 1332 + rqst[1].rq_iov = qi_iov; 1333 + rqst[1].rq_nvec = 1; 1334 + 1335 + rc = SMB2_query_info_init(tcon, &rqst[1], COMPOUND_FID, 1336 + COMPOUND_FID, qi.file_info_class, 1337 + qi.info_type, qi.additional_information, 1402 1338 qi.input_buffer_length, 1403 1339 qi.output_buffer_length, buffer); 1340 + } else { /* unknown flags */ 1341 + cifs_dbg(VFS, "invalid passthru query flags: 0x%x\n", qi.flags); 1342 + rc = -EINVAL; 1343 + } 1344 + 1404 1345 if (rc) 1405 1346 goto iqinf_exit; 1406 1347 smb2_set_next_command(tcon, &rqst[1]); ··· 1440 1341 resp_buftype, rsp_iov); 1441 1342 if (rc) 1442 1343 goto iqinf_exit; 1443 - pqi = (struct smb_query_info __user *)arg; 1444 - rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base; 1445 - if (le32_to_cpu(rsp->OutputBufferLength) < qi.input_buffer_length) 1446 - qi.input_buffer_length = le32_to_cpu(rsp->OutputBufferLength); 1447 - if (copy_to_user(&pqi->input_buffer_length, &qi.input_buffer_length, 1448 - sizeof(qi.input_buffer_length))) { 1449 - rc = -EFAULT; 1450 - goto iqinf_exit; 1451 - } 1452 - if (copy_to_user(pqi + 1, rsp->Buffer, qi.input_buffer_length)) { 1453 - rc = -EFAULT; 1454 - goto iqinf_exit; 1344 + if (qi.flags & PASSTHRU_FSCTL) { 1345 + pqi = (struct smb_query_info __user *)arg; 1346 + io_rsp = (struct smb2_ioctl_rsp *)rsp_iov[1].iov_base; 1347 + if (le32_to_cpu(io_rsp->OutputCount) < qi.input_buffer_length) 1348 + qi.input_buffer_length = le32_to_cpu(io_rsp->OutputCount); 1349 + if (copy_to_user(&pqi->input_buffer_length, &qi.input_buffer_length, 1350 + sizeof(qi.input_buffer_length))) { 1351 + rc = -EFAULT; 1352 + goto iqinf_exit; 1353 + } 1354 + if (copy_to_user(pqi + 1, &io_rsp[1], qi.input_buffer_length)) { 1355 + rc = -EFAULT; 1356 + goto iqinf_exit; 1357 + } 1358 + } else { 1359 + pqi = (struct smb_query_info __user *)arg; 1360 + qi_rsp = (struct smb2_query_info_rsp *)rsp_iov[1].iov_base; 1361 + if (le32_to_cpu(qi_rsp->OutputBufferLength) < qi.input_buffer_length) 1362 + qi.input_buffer_length = le32_to_cpu(qi_rsp->OutputBufferLength); 1363 + if (copy_to_user(&pqi->input_buffer_length, &qi.input_buffer_length, 1364 + sizeof(qi.input_buffer_length))) { 1365 + rc = -EFAULT; 1366 + goto iqinf_exit; 1367 + } 1368 + if (copy_to_user(pqi + 1, qi_rsp->Buffer, qi.input_buffer_length)) { 1369 + rc = -EFAULT; 1370 + goto iqinf_exit; 1371 + } 1455 1372 } 1456 1373 1457 1374 iqinf_exit: 1458 1375 kfree(buffer); 1459 1376 SMB2_open_free(&rqst[0]); 1460 - SMB2_query_info_free(&rqst[1]); 1377 + if (qi.flags & PASSTHRU_FSCTL) 1378 + SMB2_ioctl_free(&rqst[1]); 1379 + else 1380 + SMB2_query_info_free(&rqst[1]); 1381 + 1461 1382 SMB2_close_free(&rqst[2]); 1462 1383 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); 1463 1384 free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); ··· 2591 2472 static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, 2592 2473 loff_t offset, loff_t len, bool keep_size) 2593 2474 { 2475 + struct cifs_ses *ses = tcon->ses; 2594 2476 struct inode *inode; 2595 2477 struct cifsInodeInfo *cifsi; 2596 2478 struct cifsFileInfo *cfile = file->private_data; 2597 2479 struct file_zero_data_information fsctl_buf; 2480 + struct smb_rqst rqst[2]; 2481 + int resp_buftype[2]; 2482 + struct kvec rsp_iov[2]; 2483 + struct kvec io_iov[SMB2_IOCTL_IOV_SIZE]; 2484 + struct kvec si_iov[1]; 2485 + unsigned int size[1]; 2486 + void *data[1]; 2598 2487 long rc; 2599 2488 unsigned int xid; 2489 + int num = 0, flags = 0; 2490 + __le64 eof; 2600 2491 2601 2492 xid = get_xid(); 2602 2493 2603 2494 inode = d_inode(cfile->dentry); 2604 2495 cifsi = CIFS_I(inode); 2605 2496 2497 + trace_smb3_zero_enter(xid, cfile->fid.persistent_fid, tcon->tid, 2498 + ses->Suid, offset, len); 2499 + 2500 + 2606 2501 /* if file not oplocked can't be sure whether asking to extend size */ 2607 2502 if (!CIFS_CACHE_READ(cifsi)) 2608 2503 if (keep_size == false) { 2609 2504 rc = -EOPNOTSUPP; 2505 + trace_smb3_zero_err(xid, cfile->fid.persistent_fid, 2506 + tcon->tid, ses->Suid, offset, len, rc); 2610 2507 free_xid(xid); 2611 2508 return rc; 2612 2509 } ··· 2633 2498 */ 2634 2499 if (!(cifsi->cifsAttrs & FILE_ATTRIBUTE_SPARSE_FILE)) { 2635 2500 rc = -EOPNOTSUPP; 2501 + trace_smb3_zero_err(xid, cfile->fid.persistent_fid, tcon->tid, 2502 + ses->Suid, offset, len, rc); 2636 2503 free_xid(xid); 2637 2504 return rc; 2638 2505 } 2639 - 2640 - /* 2641 - * need to make sure we are not asked to extend the file since the SMB3 2642 - * fsctl does not change the file size. In the future we could change 2643 - * this to zero the first part of the range then set the file size 2644 - * which for a non sparse file would zero the newly extended range 2645 - */ 2646 - if (keep_size == false) 2647 - if (i_size_read(inode) < offset + len) { 2648 - rc = -EOPNOTSUPP; 2649 - free_xid(xid); 2650 - return rc; 2651 - } 2652 2506 2653 2507 cifs_dbg(FYI, "offset %lld len %lld", offset, len); 2654 2508 2655 2509 fsctl_buf.FileOffset = cpu_to_le64(offset); 2656 2510 fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len); 2657 2511 2658 - rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, 2659 - cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA, 2660 - true /* is_fctl */, (char *)&fsctl_buf, 2661 - sizeof(struct file_zero_data_information), NULL, NULL); 2512 + if (smb3_encryption_required(tcon)) 2513 + flags |= CIFS_TRANSFORM_REQ; 2514 + 2515 + memset(rqst, 0, sizeof(rqst)); 2516 + resp_buftype[0] = resp_buftype[1] = CIFS_NO_BUFFER; 2517 + memset(rsp_iov, 0, sizeof(rsp_iov)); 2518 + 2519 + 2520 + memset(&io_iov, 0, sizeof(io_iov)); 2521 + rqst[num].rq_iov = io_iov; 2522 + rqst[num].rq_nvec = SMB2_IOCTL_IOV_SIZE; 2523 + rc = SMB2_ioctl_init(tcon, &rqst[num++], cfile->fid.persistent_fid, 2524 + cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA, 2525 + true /* is_fctl */, (char *)&fsctl_buf, 2526 + sizeof(struct file_zero_data_information)); 2527 + if (rc) 2528 + goto zero_range_exit; 2529 + 2530 + /* 2531 + * do we also need to change the size of the file? 2532 + */ 2533 + if (keep_size == false && i_size_read(inode) < offset + len) { 2534 + smb2_set_next_command(tcon, &rqst[0]); 2535 + 2536 + memset(&si_iov, 0, sizeof(si_iov)); 2537 + rqst[num].rq_iov = si_iov; 2538 + rqst[num].rq_nvec = 1; 2539 + 2540 + eof = cpu_to_le64(offset + len); 2541 + size[0] = 8; /* sizeof __le64 */ 2542 + data[0] = &eof; 2543 + 2544 + rc = SMB2_set_info_init(tcon, &rqst[num++], 2545 + cfile->fid.persistent_fid, 2546 + cfile->fid.persistent_fid, 2547 + current->tgid, 2548 + FILE_END_OF_FILE_INFORMATION, 2549 + SMB2_O_INFO_FILE, 0, data, size); 2550 + smb2_set_related(&rqst[1]); 2551 + } 2552 + 2553 + rc = compound_send_recv(xid, ses, flags, num, rqst, 2554 + resp_buftype, rsp_iov); 2555 + 2556 + zero_range_exit: 2557 + SMB2_ioctl_free(&rqst[0]); 2558 + SMB2_set_info_free(&rqst[1]); 2559 + free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base); 2560 + free_rsp_buf(resp_buftype[1], rsp_iov[1].iov_base); 2662 2561 free_xid(xid); 2562 + if (rc) 2563 + trace_smb3_zero_err(xid, cfile->fid.persistent_fid, tcon->tid, 2564 + ses->Suid, offset, len, rc); 2565 + else 2566 + trace_smb3_zero_done(xid, cfile->fid.persistent_fid, tcon->tid, 2567 + ses->Suid, offset, len); 2663 2568 return rc; 2664 2569 } 2665 2570 ··· 2748 2573 struct cifsFileInfo *cfile = file->private_data; 2749 2574 long rc = -EOPNOTSUPP; 2750 2575 unsigned int xid; 2576 + __le64 eof; 2751 2577 2752 2578 xid = get_xid(); 2753 2579 2754 2580 inode = d_inode(cfile->dentry); 2755 2581 cifsi = CIFS_I(inode); 2756 2582 2583 + trace_smb3_falloc_enter(xid, cfile->fid.persistent_fid, tcon->tid, 2584 + tcon->ses->Suid, off, len); 2757 2585 /* if file not oplocked can't be sure whether asking to extend size */ 2758 2586 if (!CIFS_CACHE_READ(cifsi)) 2759 2587 if (keep_size == false) { 2588 + trace_smb3_falloc_err(xid, cfile->fid.persistent_fid, 2589 + tcon->tid, tcon->ses->Suid, off, len, rc); 2760 2590 free_xid(xid); 2761 2591 return rc; 2762 2592 } ··· 2781 2601 /* BB: in future add else clause to extend file */ 2782 2602 else 2783 2603 rc = -EOPNOTSUPP; 2604 + if (rc) 2605 + trace_smb3_falloc_err(xid, cfile->fid.persistent_fid, 2606 + tcon->tid, tcon->ses->Suid, off, len, rc); 2607 + else 2608 + trace_smb3_falloc_done(xid, cfile->fid.persistent_fid, 2609 + tcon->tid, tcon->ses->Suid, off, len); 2784 2610 free_xid(xid); 2785 2611 return rc; 2786 2612 } ··· 2802 2616 */ 2803 2617 if ((off > 8192) || (off + len + 8192 < i_size_read(inode))) { 2804 2618 rc = -EOPNOTSUPP; 2619 + trace_smb3_falloc_err(xid, cfile->fid.persistent_fid, 2620 + tcon->tid, tcon->ses->Suid, off, len, rc); 2805 2621 free_xid(xid); 2806 2622 return rc; 2807 2623 } 2808 2624 2809 - rc = smb2_set_sparse(xid, tcon, cfile, inode, false); 2625 + smb2_set_sparse(xid, tcon, cfile, inode, false); 2626 + rc = 0; 2627 + } else { 2628 + smb2_set_sparse(xid, tcon, cfile, inode, false); 2629 + rc = 0; 2630 + if (i_size_read(inode) < off + len) { 2631 + eof = cpu_to_le64(off + len); 2632 + rc = SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, 2633 + cfile->fid.volatile_fid, cfile->pid, 2634 + &eof); 2635 + } 2810 2636 } 2811 - /* BB: else ... in future add code to extend file and set sparse */ 2812 2637 2638 + if (rc) 2639 + trace_smb3_falloc_err(xid, cfile->fid.persistent_fid, tcon->tid, 2640 + tcon->ses->Suid, off, len, rc); 2641 + else 2642 + trace_smb3_falloc_done(xid, cfile->fid.persistent_fid, tcon->tid, 2643 + tcon->ses->Suid, off, len); 2813 2644 2814 2645 free_xid(xid); 2815 2646 return rc; ··· 3807 3604 return le32_to_cpu(hdr->NextCommand); 3808 3605 } 3809 3606 3607 + static int 3608 + smb2_make_node(unsigned int xid, struct inode *inode, 3609 + struct dentry *dentry, struct cifs_tcon *tcon, 3610 + char *full_path, umode_t mode, dev_t dev) 3611 + { 3612 + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 3613 + int rc = -EPERM; 3614 + int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL; 3615 + FILE_ALL_INFO *buf = NULL; 3616 + struct cifs_io_parms io_parms; 3617 + __u32 oplock = 0; 3618 + struct cifs_fid fid; 3619 + struct cifs_open_parms oparms; 3620 + unsigned int bytes_written; 3621 + struct win_dev *pdev; 3622 + struct kvec iov[2]; 3623 + 3624 + /* 3625 + * Check if mounted with mount parm 'sfu' mount parm. 3626 + * SFU emulation should work with all servers, but only 3627 + * supports block and char device (no socket & fifo), 3628 + * and was used by default in earlier versions of Windows 3629 + */ 3630 + if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL)) 3631 + goto out; 3632 + 3633 + /* 3634 + * TODO: Add ability to create instead via reparse point. Windows (e.g. 3635 + * their current NFS server) uses this approach to expose special files 3636 + * over SMB2/SMB3 and Samba will do this with SMB3.1.1 POSIX Extensions 3637 + */ 3638 + 3639 + if (!S_ISCHR(mode) && !S_ISBLK(mode)) 3640 + goto out; 3641 + 3642 + cifs_dbg(FYI, "sfu compat create special file\n"); 3643 + 3644 + buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); 3645 + if (buf == NULL) { 3646 + rc = -ENOMEM; 3647 + goto out; 3648 + } 3649 + 3650 + if (backup_cred(cifs_sb)) 3651 + create_options |= CREATE_OPEN_BACKUP_INTENT; 3652 + 3653 + oparms.tcon = tcon; 3654 + oparms.cifs_sb = cifs_sb; 3655 + oparms.desired_access = GENERIC_WRITE; 3656 + oparms.create_options = create_options; 3657 + oparms.disposition = FILE_CREATE; 3658 + oparms.path = full_path; 3659 + oparms.fid = &fid; 3660 + oparms.reconnect = false; 3661 + 3662 + if (tcon->ses->server->oplocks) 3663 + oplock = REQ_OPLOCK; 3664 + else 3665 + oplock = 0; 3666 + rc = tcon->ses->server->ops->open(xid, &oparms, &oplock, buf); 3667 + if (rc) 3668 + goto out; 3669 + 3670 + /* 3671 + * BB Do not bother to decode buf since no local inode yet to put 3672 + * timestamps in, but we can reuse it safely. 3673 + */ 3674 + 3675 + pdev = (struct win_dev *)buf; 3676 + io_parms.pid = current->tgid; 3677 + io_parms.tcon = tcon; 3678 + io_parms.offset = 0; 3679 + io_parms.length = sizeof(struct win_dev); 3680 + iov[1].iov_base = buf; 3681 + iov[1].iov_len = sizeof(struct win_dev); 3682 + if (S_ISCHR(mode)) { 3683 + memcpy(pdev->type, "IntxCHR", 8); 3684 + pdev->major = cpu_to_le64(MAJOR(dev)); 3685 + pdev->minor = cpu_to_le64(MINOR(dev)); 3686 + rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, 3687 + &bytes_written, iov, 1); 3688 + } else if (S_ISBLK(mode)) { 3689 + memcpy(pdev->type, "IntxBLK", 8); 3690 + pdev->major = cpu_to_le64(MAJOR(dev)); 3691 + pdev->minor = cpu_to_le64(MINOR(dev)); 3692 + rc = tcon->ses->server->ops->sync_write(xid, &fid, &io_parms, 3693 + &bytes_written, iov, 1); 3694 + } 3695 + tcon->ses->server->ops->close(xid, tcon, &fid); 3696 + d_drop(dentry); 3697 + 3698 + /* FIXME: add code here to set EAs */ 3699 + out: 3700 + kfree(buf); 3701 + return rc; 3702 + } 3703 + 3704 + 3810 3705 struct smb_version_operations smb20_operations = { 3811 3706 .compare_fids = smb2_compare_fids, 3812 3707 .setup_request = smb2_setup_request, ··· 3999 3698 #endif /* CIFS_ACL */ 4000 3699 .next_header = smb2_next_header, 4001 3700 .ioctl_query_info = smb2_ioctl_query_info, 3701 + .make_node = smb2_make_node, 4002 3702 }; 4003 3703 4004 3704 struct smb_version_operations smb21_operations = { ··· 4098 3796 #endif /* CIFS_ACL */ 4099 3797 .next_header = smb2_next_header, 4100 3798 .ioctl_query_info = smb2_ioctl_query_info, 3799 + .make_node = smb2_make_node, 4101 3800 }; 4102 3801 4103 3802 struct smb_version_operations smb30_operations = { ··· 4206 3903 #endif /* CIFS_ACL */ 4207 3904 .next_header = smb2_next_header, 4208 3905 .ioctl_query_info = smb2_ioctl_query_info, 3906 + .make_node = smb2_make_node, 4209 3907 }; 4210 3908 4211 3909 struct smb_version_operations smb311_operations = { ··· 4315 4011 #endif /* CIFS_ACL */ 4316 4012 .next_header = smb2_next_header, 4317 4013 .ioctl_query_info = smb2_ioctl_query_info, 4014 + .make_node = smb2_make_node, 4318 4015 }; 4319 4016 4320 4017 struct smb_version_values smb20_values = {
+83 -62
fs/cifs/smb2pdu.c
··· 1797 1797 return buf; 1798 1798 } 1799 1799 1800 - static __u8 1801 - parse_lease_state(struct TCP_Server_Info *server, struct smb2_create_rsp *rsp, 1802 - unsigned int *epoch, char *lease_key) 1800 + __u8 1801 + smb2_parse_lease_state(struct TCP_Server_Info *server, 1802 + struct smb2_create_rsp *rsp, 1803 + unsigned int *epoch, char *lease_key) 1803 1804 { 1804 1805 char *data_offset; 1805 1806 struct create_context *cc; ··· 2457 2456 } 2458 2457 2459 2458 if (rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) 2460 - *oplock = parse_lease_state(server, rsp, &oparms->fid->epoch, 2461 - oparms->fid->lease_key); 2459 + *oplock = smb2_parse_lease_state(server, rsp, 2460 + &oparms->fid->epoch, 2461 + oparms->fid->lease_key); 2462 2462 else 2463 2463 *oplock = rsp->OplockLevel; 2464 2464 creat_exit: ··· 2468 2466 return rc; 2469 2467 } 2470 2468 2471 - /* 2472 - * SMB2 IOCTL is used for both IOCTLs and FSCTLs 2473 - */ 2474 2469 int 2475 - SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, 2476 - u64 volatile_fid, u32 opcode, bool is_fsctl, 2477 - char *in_data, u32 indatalen, 2478 - char **out_data, u32 *plen /* returned data len */) 2470 + SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, 2471 + u64 persistent_fid, u64 volatile_fid, u32 opcode, 2472 + bool is_fsctl, char *in_data, u32 indatalen) 2479 2473 { 2480 - struct smb_rqst rqst; 2481 2474 struct smb2_ioctl_req *req; 2482 - struct smb2_ioctl_rsp *rsp; 2483 - struct cifs_ses *ses; 2484 - struct kvec iov[2]; 2485 - struct kvec rsp_iov; 2486 - int resp_buftype; 2487 - int n_iov; 2488 - int rc = 0; 2489 - int flags = 0; 2475 + struct kvec *iov = rqst->rq_iov; 2490 2476 unsigned int total_len; 2491 - 2492 - cifs_dbg(FYI, "SMB2 IOCTL\n"); 2493 - 2494 - if (out_data != NULL) 2495 - *out_data = NULL; 2496 - 2497 - /* zero out returned data len, in case of error */ 2498 - if (plen) 2499 - *plen = 0; 2500 - 2501 - if (tcon) 2502 - ses = tcon->ses; 2503 - else 2504 - return -EIO; 2505 - 2506 - if (!ses || !(ses->server)) 2507 - return -EIO; 2477 + int rc; 2508 2478 2509 2479 rc = smb2_plain_req_init(SMB2_IOCTL, tcon, (void **) &req, &total_len); 2510 2480 if (rc) 2511 2481 return rc; 2512 2482 2513 - if (smb3_encryption_required(tcon)) 2514 - flags |= CIFS_TRANSFORM_REQ; 2515 - 2516 2483 req->CtlCode = cpu_to_le32(opcode); 2517 2484 req->PersistentFileId = persistent_fid; 2518 2485 req->VolatileFileId = volatile_fid; 2519 2486 2487 + iov[0].iov_base = (char *)req; 2488 + /* 2489 + * If no input data, the size of ioctl struct in 2490 + * protocol spec still includes a 1 byte data buffer, 2491 + * but if input data passed to ioctl, we do not 2492 + * want to double count this, so we do not send 2493 + * the dummy one byte of data in iovec[0] if sending 2494 + * input data (in iovec[1]). 2495 + */ 2520 2496 if (indatalen) { 2521 2497 req->InputCount = cpu_to_le32(indatalen); 2522 2498 /* do not set InputOffset if no input data */ 2523 2499 req->InputOffset = 2524 2500 cpu_to_le32(offsetof(struct smb2_ioctl_req, Buffer)); 2501 + rqst->rq_nvec = 2; 2502 + iov[0].iov_len = total_len - 1; 2525 2503 iov[1].iov_base = in_data; 2526 2504 iov[1].iov_len = indatalen; 2527 - n_iov = 2; 2528 - } else 2529 - n_iov = 1; 2505 + } else { 2506 + rqst->rq_nvec = 1; 2507 + iov[0].iov_len = total_len; 2508 + } 2530 2509 2531 2510 req->OutputOffset = 0; 2532 2511 req->OutputCount = 0; /* MBZ */ ··· 2529 2546 else 2530 2547 req->Flags = 0; 2531 2548 2532 - iov[0].iov_base = (char *)req; 2533 - 2534 - /* 2535 - * If no input data, the size of ioctl struct in 2536 - * protocol spec still includes a 1 byte data buffer, 2537 - * but if input data passed to ioctl, we do not 2538 - * want to double count this, so we do not send 2539 - * the dummy one byte of data in iovec[0] if sending 2540 - * input data (in iovec[1]). 2541 - */ 2542 - 2543 - if (indatalen) { 2544 - iov[0].iov_len = total_len - 1; 2545 - } else 2546 - iov[0].iov_len = total_len; 2547 - 2548 2549 /* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */ 2549 2550 if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO) 2550 2551 req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED; 2551 2552 2553 + return 0; 2554 + } 2555 + 2556 + void 2557 + SMB2_ioctl_free(struct smb_rqst *rqst) 2558 + { 2559 + if (rqst && rqst->rq_iov) 2560 + cifs_small_buf_release(rqst->rq_iov[0].iov_base); /* request */ 2561 + } 2562 + 2563 + /* 2564 + * SMB2 IOCTL is used for both IOCTLs and FSCTLs 2565 + */ 2566 + int 2567 + SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, 2568 + u64 volatile_fid, u32 opcode, bool is_fsctl, 2569 + char *in_data, u32 indatalen, 2570 + char **out_data, u32 *plen /* returned data len */) 2571 + { 2572 + struct smb_rqst rqst; 2573 + struct smb2_ioctl_rsp *rsp = NULL; 2574 + struct cifs_ses *ses; 2575 + struct kvec iov[SMB2_IOCTL_IOV_SIZE]; 2576 + struct kvec rsp_iov = {NULL, 0}; 2577 + int resp_buftype = CIFS_NO_BUFFER; 2578 + int rc = 0; 2579 + int flags = 0; 2580 + 2581 + cifs_dbg(FYI, "SMB2 IOCTL\n"); 2582 + 2583 + if (out_data != NULL) 2584 + *out_data = NULL; 2585 + 2586 + /* zero out returned data len, in case of error */ 2587 + if (plen) 2588 + *plen = 0; 2589 + 2590 + if (tcon) 2591 + ses = tcon->ses; 2592 + else 2593 + return -EIO; 2594 + 2595 + if (!ses || !(ses->server)) 2596 + return -EIO; 2597 + 2598 + if (smb3_encryption_required(tcon)) 2599 + flags |= CIFS_TRANSFORM_REQ; 2600 + 2552 2601 memset(&rqst, 0, sizeof(struct smb_rqst)); 2602 + memset(&iov, 0, sizeof(iov)); 2553 2603 rqst.rq_iov = iov; 2554 - rqst.rq_nvec = n_iov; 2604 + rqst.rq_nvec = SMB2_IOCTL_IOV_SIZE; 2605 + 2606 + rc = SMB2_ioctl_init(tcon, &rqst, persistent_fid, volatile_fid, 2607 + opcode, is_fsctl, in_data, indatalen); 2608 + if (rc) 2609 + goto ioctl_exit; 2555 2610 2556 2611 rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, 2557 2612 &rsp_iov); 2558 - cifs_small_buf_release(req); 2559 2613 rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base; 2560 2614 2561 2615 if (rc != 0) ··· 2642 2622 } 2643 2623 2644 2624 ioctl_exit: 2625 + SMB2_ioctl_free(&rqst); 2645 2626 free_rsp_buf(resp_buftype, rsp); 2646 2627 return rc; 2647 2628 }
+7
fs/cifs/smb2pdu.h
··· 959 959 __le64 ByteCount; /* Bytes to be copied */ 960 960 } __packed; 961 961 962 + /* 963 + * Maximum number of iovs we need for an ioctl request. 964 + * [0] : struct smb2_ioctl_req 965 + * [1] : in_data 966 + */ 967 + #define SMB2_IOCTL_IOV_SIZE 2 968 + 962 969 struct smb2_ioctl_req { 963 970 struct smb2_sync_hdr sync_hdr; 964 971 __le16 StructureSize; /* Must be 57 */
+7
fs/cifs/smb2proto.h
··· 144 144 u64 persistent_fid, u64 volatile_fid, u32 opcode, 145 145 bool is_fsctl, char *in_data, u32 indatalen, 146 146 char **out_data, u32 *plen /* returned data len */); 147 + extern int SMB2_ioctl_init(struct cifs_tcon *tcon, struct smb_rqst *rqst, 148 + u64 persistent_fid, u64 volatile_fid, u32 opcode, 149 + bool is_fsctl, char *in_data, u32 indatalen); 150 + extern void SMB2_ioctl_free(struct smb_rqst *rqst); 147 151 extern int SMB2_close(const unsigned int xid, struct cifs_tcon *tcon, 148 152 u64 persistent_file_id, u64 volatile_file_id); 149 153 extern int SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon, ··· 227 223 228 224 extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *, 229 225 enum securityEnum); 226 + extern __u8 smb2_parse_lease_state(struct TCP_Server_Info *server, 227 + struct smb2_create_rsp *rsp, 228 + unsigned int *epoch, char *lease_key); 230 229 extern int smb3_encryption_required(const struct cifs_tcon *tcon); 231 230 extern int smb2_validate_iov(unsigned int offset, unsigned int buffer_length, 232 231 struct kvec *iov, unsigned int min_buf_size);
+3 -3
fs/cifs/smb2status.h
··· 30 30 */ 31 31 32 32 #define STATUS_SEVERITY_SUCCESS __constant_cpu_to_le32(0x0000) 33 - #define STATUS_SEVERITY_INFORMATIONAL __constanst_cpu_to_le32(0x0001) 34 - #define STATUS_SEVERITY_WARNING __constanst_cpu_to_le32(0x0002) 35 - #define STATUS_SEVERITY_ERROR __constanst_cpu_to_le32(0x0003) 33 + #define STATUS_SEVERITY_INFORMATIONAL cpu_to_le32(0x0001) 34 + #define STATUS_SEVERITY_WARNING cpu_to_le32(0x0002) 35 + #define STATUS_SEVERITY_ERROR cpu_to_le32(0x0003) 36 36 37 37 struct ntstatus { 38 38 /* Facility is the high 12 bits of the following field */
+124
fs/cifs/trace.h
··· 59 59 DEFINE_SMB3_RW_ERR_EVENT(write_err); 60 60 DEFINE_SMB3_RW_ERR_EVENT(read_err); 61 61 DEFINE_SMB3_RW_ERR_EVENT(query_dir_err); 62 + DEFINE_SMB3_RW_ERR_EVENT(zero_err); 63 + DEFINE_SMB3_RW_ERR_EVENT(falloc_err); 62 64 63 65 64 66 /* For logging successful read or write */ ··· 106 104 DEFINE_SMB3_RW_DONE_EVENT(write_enter); 107 105 DEFINE_SMB3_RW_DONE_EVENT(read_enter); 108 106 DEFINE_SMB3_RW_DONE_EVENT(query_dir_enter); 107 + DEFINE_SMB3_RW_DONE_EVENT(zero_enter); 108 + DEFINE_SMB3_RW_DONE_EVENT(falloc_enter); 109 109 DEFINE_SMB3_RW_DONE_EVENT(write_done); 110 110 DEFINE_SMB3_RW_DONE_EVENT(read_done); 111 111 DEFINE_SMB3_RW_DONE_EVENT(query_dir_done); 112 + DEFINE_SMB3_RW_DONE_EVENT(zero_done); 113 + DEFINE_SMB3_RW_DONE_EVENT(falloc_done); 112 114 113 115 /* 114 116 * For handle based calls other than read and write, and get/set info ··· 247 241 DEFINE_SMB3_INF_ERR_EVENT(query_info_err); 248 242 DEFINE_SMB3_INF_ERR_EVENT(set_info_err); 249 243 DEFINE_SMB3_INF_ERR_EVENT(fsctl_err); 244 + 245 + DECLARE_EVENT_CLASS(smb3_inf_compound_enter_class, 246 + TP_PROTO(unsigned int xid, 247 + __u32 tid, 248 + __u64 sesid, 249 + const char *full_path), 250 + TP_ARGS(xid, tid, sesid, full_path), 251 + TP_STRUCT__entry( 252 + __field(unsigned int, xid) 253 + __field(__u32, tid) 254 + __field(__u64, sesid) 255 + __string(path, full_path) 256 + ), 257 + TP_fast_assign( 258 + __entry->xid = xid; 259 + __entry->tid = tid; 260 + __entry->sesid = sesid; 261 + __assign_str(path, full_path); 262 + ), 263 + TP_printk("xid=%u sid=0x%llx tid=0x%x path=%s", 264 + __entry->xid, __entry->sesid, __entry->tid, 265 + __get_str(path)) 266 + ) 267 + 268 + #define DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(name) \ 269 + DEFINE_EVENT(smb3_inf_compound_enter_class, smb3_##name, \ 270 + TP_PROTO(unsigned int xid, \ 271 + __u32 tid, \ 272 + __u64 sesid, \ 273 + const char *full_path), \ 274 + TP_ARGS(xid, tid, sesid, full_path)) 275 + 276 + DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(query_info_compound_enter); 277 + DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(hardlink_enter); 278 + DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rename_enter); 279 + DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(rmdir_enter); 280 + DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_eof_enter); 281 + DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(set_info_compound_enter); 282 + DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(delete_enter); 283 + DEFINE_SMB3_INF_COMPOUND_ENTER_EVENT(mkdir_enter); 284 + 285 + 286 + DECLARE_EVENT_CLASS(smb3_inf_compound_done_class, 287 + TP_PROTO(unsigned int xid, 288 + __u32 tid, 289 + __u64 sesid), 290 + TP_ARGS(xid, tid, sesid), 291 + TP_STRUCT__entry( 292 + __field(unsigned int, xid) 293 + __field(__u32, tid) 294 + __field(__u64, sesid) 295 + ), 296 + TP_fast_assign( 297 + __entry->xid = xid; 298 + __entry->tid = tid; 299 + __entry->sesid = sesid; 300 + ), 301 + TP_printk("xid=%u sid=0x%llx tid=0x%x", 302 + __entry->xid, __entry->sesid, __entry->tid) 303 + ) 304 + 305 + #define DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(name) \ 306 + DEFINE_EVENT(smb3_inf_compound_done_class, smb3_##name, \ 307 + TP_PROTO(unsigned int xid, \ 308 + __u32 tid, \ 309 + __u64 sesid), \ 310 + TP_ARGS(xid, tid, sesid)) 311 + 312 + DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(query_info_compound_done); 313 + DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(hardlink_done); 314 + DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rename_done); 315 + DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(rmdir_done); 316 + DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_eof_done); 317 + DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(set_info_compound_done); 318 + DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(delete_done); 319 + DEFINE_SMB3_INF_COMPOUND_DONE_EVENT(mkdir_done); 320 + 321 + 322 + DECLARE_EVENT_CLASS(smb3_inf_compound_err_class, 323 + TP_PROTO(unsigned int xid, 324 + __u32 tid, 325 + __u64 sesid, 326 + int rc), 327 + TP_ARGS(xid, tid, sesid, rc), 328 + TP_STRUCT__entry( 329 + __field(unsigned int, xid) 330 + __field(__u32, tid) 331 + __field(__u64, sesid) 332 + __field(int, rc) 333 + ), 334 + TP_fast_assign( 335 + __entry->xid = xid; 336 + __entry->tid = tid; 337 + __entry->sesid = sesid; 338 + __entry->rc = rc; 339 + ), 340 + TP_printk("xid=%u sid=0x%llx tid=0x%x rc=%d", 341 + __entry->xid, __entry->sesid, __entry->tid, 342 + __entry->rc) 343 + ) 344 + 345 + #define DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(name) \ 346 + DEFINE_EVENT(smb3_inf_compound_err_class, smb3_##name, \ 347 + TP_PROTO(unsigned int xid, \ 348 + __u32 tid, \ 349 + __u64 sesid, \ 350 + int rc), \ 351 + TP_ARGS(xid, tid, sesid, rc)) 352 + 353 + DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(query_info_compound_err); 354 + DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(hardlink_err); 355 + DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rename_err); 356 + DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(rmdir_err); 357 + DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_eof_err); 358 + DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(set_info_compound_err); 359 + DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(mkdir_err); 360 + DEFINE_SMB3_INF_COMPOUND_ERR_EVENT(delete_err); 250 361 251 362 /* 252 363 * For logging SMB3 Status code and Command for responses which return errors ··· 836 713 TP_ARGS(currmid, hostname, credits)) 837 714 838 715 DEFINE_SMB3_CREDIT_EVENT(reconnect_with_invalid_credits); 716 + DEFINE_SMB3_CREDIT_EVENT(credit_timeout); 839 717 840 718 #endif /* _CIFS_TRACE_H */ 841 719
+122 -104
fs/cifs/transport.c
··· 486 486 } 487 487 488 488 static int 489 - wait_for_free_credits(struct TCP_Server_Info *server, const int timeout, 490 - int *credits, unsigned int *instance) 489 + wait_for_free_credits(struct TCP_Server_Info *server, const int num_credits, 490 + const int timeout, const int flags, 491 + unsigned int *instance) 491 492 { 492 493 int rc; 494 + int *credits; 495 + int optype; 496 + long int t; 497 + 498 + if (timeout < 0) 499 + t = MAX_JIFFY_OFFSET; 500 + else 501 + t = msecs_to_jiffies(timeout); 502 + 503 + optype = flags & CIFS_OP_MASK; 493 504 494 505 *instance = 0; 495 506 507 + credits = server->ops->get_credits_field(server, optype); 508 + /* Since an echo is already inflight, no need to wait to send another */ 509 + if (*credits <= 0 && optype == CIFS_ECHO_OP) 510 + return -EAGAIN; 511 + 496 512 spin_lock(&server->req_lock); 497 - if (timeout == CIFS_ASYNC_OP) { 513 + if ((flags & CIFS_TIMEOUT_MASK) == CIFS_ASYNC_OP) { 498 514 /* oplock breaks must not be held up */ 499 515 server->in_flight++; 500 516 *credits -= 1; ··· 520 504 } 521 505 522 506 while (1) { 523 - if (*credits <= 0) { 507 + if (*credits < num_credits) { 524 508 spin_unlock(&server->req_lock); 525 509 cifs_num_waiters_inc(server); 526 - rc = wait_event_killable(server->request_q, 527 - has_credits(server, credits)); 510 + rc = wait_event_killable_timeout(server->request_q, 511 + has_credits(server, credits, num_credits), t); 528 512 cifs_num_waiters_dec(server); 529 - if (rc) 530 - return rc; 513 + if (!rc) { 514 + trace_smb3_credit_timeout(server->CurrentMid, 515 + server->hostname, num_credits); 516 + cifs_dbg(VFS, "wait timed out after %d ms\n", 517 + timeout); 518 + return -ENOTSUPP; 519 + } 520 + if (rc == -ERESTARTSYS) 521 + return -ERESTARTSYS; 531 522 spin_lock(&server->req_lock); 532 523 } else { 533 524 if (server->tcpStatus == CifsExiting) { ··· 543 520 } 544 521 545 522 /* 523 + * For normal commands, reserve the last MAX_COMPOUND 524 + * credits to compound requests. 525 + * Otherwise these compounds could be permanently 526 + * starved for credits by single-credit requests. 527 + * 528 + * To prevent spinning CPU, block this thread until 529 + * there are >MAX_COMPOUND credits available. 530 + * But only do this is we already have a lot of 531 + * credits in flight to avoid triggering this check 532 + * for servers that are slow to hand out credits on 533 + * new sessions. 534 + */ 535 + if (!optype && num_credits == 1 && 536 + server->in_flight > 2 * MAX_COMPOUND && 537 + *credits <= MAX_COMPOUND) { 538 + spin_unlock(&server->req_lock); 539 + cifs_num_waiters_inc(server); 540 + rc = wait_event_killable_timeout( 541 + server->request_q, 542 + has_credits(server, credits, 543 + MAX_COMPOUND + 1), 544 + t); 545 + cifs_num_waiters_dec(server); 546 + if (!rc) { 547 + trace_smb3_credit_timeout( 548 + server->CurrentMid, 549 + server->hostname, num_credits); 550 + cifs_dbg(VFS, "wait timed out after %d ms\n", 551 + timeout); 552 + return -ENOTSUPP; 553 + } 554 + if (rc == -ERESTARTSYS) 555 + return -ERESTARTSYS; 556 + spin_lock(&server->req_lock); 557 + continue; 558 + } 559 + 560 + /* 546 561 * Can not count locking commands against total 547 562 * as they are allowed to block on server. 548 563 */ 549 564 550 565 /* update # of requests on the wire to server */ 551 - if (timeout != CIFS_BLOCKING_OP) { 552 - *credits -= 1; 553 - server->in_flight++; 566 + if ((flags & CIFS_TIMEOUT_MASK) != CIFS_BLOCKING_OP) { 567 + *credits -= num_credits; 568 + server->in_flight += num_credits; 554 569 *instance = server->reconnect_instance; 555 570 } 556 571 spin_unlock(&server->req_lock); ··· 599 538 } 600 539 601 540 static int 602 - wait_for_free_request(struct TCP_Server_Info *server, const int timeout, 603 - const int optype, unsigned int *instance) 541 + wait_for_free_request(struct TCP_Server_Info *server, const int flags, 542 + unsigned int *instance) 604 543 { 605 - int *val; 544 + return wait_for_free_credits(server, 1, -1, flags, 545 + instance); 546 + } 606 547 607 - val = server->ops->get_credits_field(server, optype); 608 - /* Since an echo is already inflight, no need to wait to send another */ 609 - if (*val <= 0 && optype == CIFS_ECHO_OP) 610 - return -EAGAIN; 611 - return wait_for_free_credits(server, timeout, val, instance); 548 + static int 549 + wait_for_compound_request(struct TCP_Server_Info *server, int num, 550 + const int flags, unsigned int *instance) 551 + { 552 + int *credits; 553 + 554 + credits = server->ops->get_credits_field(server, flags & CIFS_OP_MASK); 555 + 556 + spin_lock(&server->req_lock); 557 + if (*credits < num) { 558 + /* 559 + * Return immediately if not too many requests in flight since 560 + * we will likely be stuck on waiting for credits. 561 + */ 562 + if (server->in_flight < num - *credits) { 563 + spin_unlock(&server->req_lock); 564 + return -ENOTSUPP; 565 + } 566 + } 567 + spin_unlock(&server->req_lock); 568 + 569 + return wait_for_free_credits(server, num, 60000, flags, 570 + instance); 612 571 } 613 572 614 573 int ··· 727 646 mid_handle_t *handle, void *cbdata, const int flags, 728 647 const struct cifs_credits *exist_credits) 729 648 { 730 - int rc, timeout, optype; 649 + int rc; 731 650 struct mid_q_entry *mid; 732 651 struct cifs_credits credits = { .value = 0, .instance = 0 }; 733 652 unsigned int instance; 653 + int optype; 734 654 735 - timeout = flags & CIFS_TIMEOUT_MASK; 736 655 optype = flags & CIFS_OP_MASK; 737 656 738 657 if ((flags & CIFS_HAS_CREDITS) == 0) { 739 - rc = wait_for_free_request(server, timeout, optype, &instance); 658 + rc = wait_for_free_request(server, flags, &instance); 740 659 if (rc) 741 660 return rc; 742 661 credits.value = 1; ··· 952 871 const int flags, const int num_rqst, struct smb_rqst *rqst, 953 872 int *resp_buf_type, struct kvec *resp_iov) 954 873 { 955 - int i, j, rc = 0; 956 - int timeout, optype; 874 + int i, j, optype, rc = 0; 957 875 struct mid_q_entry *midQ[MAX_COMPOUND]; 958 876 bool cancelled_mid[MAX_COMPOUND] = {false}; 959 877 struct cifs_credits credits[MAX_COMPOUND] = { 960 878 { .value = 0, .instance = 0 } 961 879 }; 962 880 unsigned int instance; 963 - unsigned int first_instance = 0; 964 881 char *buf; 965 882 966 - timeout = flags & CIFS_TIMEOUT_MASK; 967 883 optype = flags & CIFS_OP_MASK; 968 884 969 885 for (i = 0; i < num_rqst; i++) ··· 974 896 if (ses->server->tcpStatus == CifsExiting) 975 897 return -ENOENT; 976 898 977 - spin_lock(&ses->server->req_lock); 978 - if (ses->server->credits < num_rqst) { 979 - /* 980 - * Return immediately if not too many requests in flight since 981 - * we will likely be stuck on waiting for credits. 982 - */ 983 - if (ses->server->in_flight < num_rqst - ses->server->credits) { 984 - spin_unlock(&ses->server->req_lock); 985 - return -ENOTSUPP; 986 - } 987 - } else { 988 - /* enough credits to send the whole compounded request */ 989 - ses->server->credits -= num_rqst; 990 - ses->server->in_flight += num_rqst; 991 - first_instance = ses->server->reconnect_instance; 992 - } 993 - spin_unlock(&ses->server->req_lock); 994 - 995 - if (first_instance) { 996 - cifs_dbg(FYI, "Acquired %d credits at once\n", num_rqst); 997 - for (i = 0; i < num_rqst; i++) { 998 - credits[i].value = 1; 999 - credits[i].instance = first_instance; 1000 - } 1001 - goto setup_rqsts; 1002 - } 1003 - 1004 899 /* 1005 - * There are not enough credits to send the whole compound request but 1006 - * there are requests in flight that may bring credits from the server. 900 + * Wait for all the requests to become available. 1007 901 * This approach still leaves the possibility to be stuck waiting for 1008 902 * credits if the server doesn't grant credits to the outstanding 1009 - * requests. This should be fixed by returning immediately and letting 1010 - * a caller fallback to sequential commands instead of compounding. 1011 - * Ensure we obtain 1 credit per request in the compound chain. 903 + * requests and if the client is completely idle, not generating any 904 + * other requests. 905 + * This can be handled by the eventual session reconnect. 1012 906 */ 907 + rc = wait_for_compound_request(ses->server, num_rqst, flags, 908 + &instance); 909 + if (rc) 910 + return rc; 911 + 1013 912 for (i = 0; i < num_rqst; i++) { 1014 - rc = wait_for_free_request(ses->server, timeout, optype, 1015 - &instance); 1016 - 1017 - if (rc == 0) { 1018 - credits[i].value = 1; 1019 - credits[i].instance = instance; 1020 - /* 1021 - * All parts of the compound chain must get credits from 1022 - * the same session, otherwise we may end up using more 1023 - * credits than the server granted. If there were 1024 - * reconnects in between, return -EAGAIN and let callers 1025 - * handle it. 1026 - */ 1027 - if (i == 0) 1028 - first_instance = instance; 1029 - else if (first_instance != instance) { 1030 - i++; 1031 - rc = -EAGAIN; 1032 - } 1033 - } 1034 - 1035 - if (rc) { 1036 - /* 1037 - * We haven't sent an SMB packet to the server yet but 1038 - * we already obtained credits for i requests in the 1039 - * compound chain - need to return those credits back 1040 - * for future use. Note that we need to call add_credits 1041 - * multiple times to match the way we obtained credits 1042 - * in the first place and to account for in flight 1043 - * requests correctly. 1044 - */ 1045 - for (j = 0; j < i; j++) 1046 - add_credits(ses->server, &credits[j], optype); 1047 - return rc; 1048 - } 913 + credits[i].value = 1; 914 + credits[i].instance = instance; 1049 915 } 1050 916 1051 - setup_rqsts: 1052 917 /* 1053 918 * Make sure that we sign in the same order that we send on this socket 1054 919 * and avoid races inside tcp sendmsg code that could cause corruption ··· 1002 981 1003 982 /* 1004 983 * All the parts of the compound chain belong obtained credits from the 1005 - * same session (see the appropriate checks above). In the same time 1006 - * there might be reconnects after those checks but before we acquired 1007 - * the srv_mutex. We can not use credits obtained from the previous 984 + * same session. We can not use credits obtained from the previous 1008 985 * session to send this request. Check if there were reconnects after 1009 986 * we obtained credits and return -EAGAIN in such cases to let callers 1010 987 * handle it. 1011 988 */ 1012 - if (first_instance != ses->server->reconnect_instance) { 989 + if (instance != ses->server->reconnect_instance) { 1013 990 mutex_unlock(&ses->server->srv_mutex); 1014 991 for (j = 0; j < num_rqst; j++) 1015 992 add_credits(ses->server, &credits[j], optype); ··· 1076 1057 smb311_update_preauth_hash(ses, rqst[0].rq_iov, 1077 1058 rqst[0].rq_nvec); 1078 1059 1079 - if (timeout == CIFS_ASYNC_OP) 1060 + if ((flags & CIFS_TIMEOUT_MASK) == CIFS_ASYNC_OP) 1080 1061 goto out; 1081 1062 1082 1063 for (i = 0; i < num_rqst; i++) { ··· 1213 1194 int 1214 1195 SendReceive(const unsigned int xid, struct cifs_ses *ses, 1215 1196 struct smb_hdr *in_buf, struct smb_hdr *out_buf, 1216 - int *pbytes_returned, const int timeout) 1197 + int *pbytes_returned, const int flags) 1217 1198 { 1218 1199 int rc = 0; 1219 1200 struct mid_q_entry *midQ; ··· 1244 1225 return -EIO; 1245 1226 } 1246 1227 1247 - rc = wait_for_free_request(ses->server, timeout, 0, &credits.instance); 1228 + rc = wait_for_free_request(ses->server, flags, &credits.instance); 1248 1229 if (rc) 1249 1230 return rc; 1250 1231 ··· 1283 1264 if (rc < 0) 1284 1265 goto out; 1285 1266 1286 - if (timeout == CIFS_ASYNC_OP) 1267 + if ((flags & CIFS_TIMEOUT_MASK) == CIFS_ASYNC_OP) 1287 1268 goto out; 1288 1269 1289 1270 rc = wait_for_response(ses->server, midQ); ··· 1386 1367 return -EIO; 1387 1368 } 1388 1369 1389 - rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP, 0, 1390 - &instance); 1370 + rc = wait_for_free_request(ses->server, CIFS_BLOCKING_OP, &instance); 1391 1371 if (rc) 1392 1372 return rc; 1393 1373