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 branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6

Pull CIFS fixes from Steve French:
"This is a set of CIFS/SMB3 fixes for stable.

There is another set of four SMB3 reconnect fixes for stable in
progress but they are still being reviewed/tested, so didn't want to
wait any longer to send these five below"

* 'for-next' of git://git.samba.org/sfrench/cifs-2.6:
Reset TreeId to zero on SMB2 TREE_CONNECT
CIFS: Fix build failure with smb2
Introduce cifs_copy_file_range()
SMB3: Rename clone_range to copychunk_range
Handle mismatched open calls

+270 -92
+87
fs/cifs/cifsfs.c
··· 972 972 return rc; 973 973 } 974 974 975 + ssize_t cifs_file_copychunk_range(unsigned int xid, 976 + struct file *src_file, loff_t off, 977 + struct file *dst_file, loff_t destoff, 978 + size_t len, unsigned int flags) 979 + { 980 + struct inode *src_inode = file_inode(src_file); 981 + struct inode *target_inode = file_inode(dst_file); 982 + struct cifsFileInfo *smb_file_src; 983 + struct cifsFileInfo *smb_file_target; 984 + struct cifs_tcon *src_tcon; 985 + struct cifs_tcon *target_tcon; 986 + ssize_t rc; 987 + 988 + cifs_dbg(FYI, "copychunk range\n"); 989 + 990 + if (src_inode == target_inode) { 991 + rc = -EINVAL; 992 + goto out; 993 + } 994 + 995 + if (!src_file->private_data || !dst_file->private_data) { 996 + rc = -EBADF; 997 + cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n"); 998 + goto out; 999 + } 1000 + 1001 + rc = -EXDEV; 1002 + smb_file_target = dst_file->private_data; 1003 + smb_file_src = src_file->private_data; 1004 + src_tcon = tlink_tcon(smb_file_src->tlink); 1005 + target_tcon = tlink_tcon(smb_file_target->tlink); 1006 + 1007 + if (src_tcon->ses != target_tcon->ses) { 1008 + cifs_dbg(VFS, "source and target of copy not on same server\n"); 1009 + goto out; 1010 + } 1011 + 1012 + /* 1013 + * Note: cifs case is easier than btrfs since server responsible for 1014 + * checks for proper open modes and file type and if it wants 1015 + * server could even support copy of range where source = target 1016 + */ 1017 + lock_two_nondirectories(target_inode, src_inode); 1018 + 1019 + cifs_dbg(FYI, "about to flush pages\n"); 1020 + /* should we flush first and last page first */ 1021 + truncate_inode_pages(&target_inode->i_data, 0); 1022 + 1023 + if (target_tcon->ses->server->ops->copychunk_range) 1024 + rc = target_tcon->ses->server->ops->copychunk_range(xid, 1025 + smb_file_src, smb_file_target, off, len, destoff); 1026 + else 1027 + rc = -EOPNOTSUPP; 1028 + 1029 + /* force revalidate of size and timestamps of target file now 1030 + * that target is updated on the server 1031 + */ 1032 + CIFS_I(target_inode)->time = 0; 1033 + /* although unlocking in the reverse order from locking is not 1034 + * strictly necessary here it is a little cleaner to be consistent 1035 + */ 1036 + unlock_two_nondirectories(src_inode, target_inode); 1037 + 1038 + out: 1039 + return rc; 1040 + } 1041 + 1042 + static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off, 1043 + struct file *dst_file, loff_t destoff, 1044 + size_t len, unsigned int flags) 1045 + { 1046 + unsigned int xid = get_xid(); 1047 + ssize_t rc; 1048 + 1049 + rc = cifs_file_copychunk_range(xid, src_file, off, dst_file, destoff, 1050 + len, flags); 1051 + free_xid(xid); 1052 + return rc; 1053 + } 1054 + 975 1055 const struct file_operations cifs_file_ops = { 976 1056 .read_iter = cifs_loose_read_iter, 977 1057 .write_iter = cifs_file_write_iter, ··· 1064 984 .splice_read = generic_file_splice_read, 1065 985 .llseek = cifs_llseek, 1066 986 .unlocked_ioctl = cifs_ioctl, 987 + .copy_file_range = cifs_copy_file_range, 1067 988 .clone_file_range = cifs_clone_file_range, 1068 989 .setlease = cifs_setlease, 1069 990 .fallocate = cifs_fallocate, ··· 1082 1001 .splice_read = generic_file_splice_read, 1083 1002 .llseek = cifs_llseek, 1084 1003 .unlocked_ioctl = cifs_ioctl, 1004 + .copy_file_range = cifs_copy_file_range, 1085 1005 .clone_file_range = cifs_clone_file_range, 1086 1006 .setlease = cifs_setlease, 1087 1007 .fallocate = cifs_fallocate, ··· 1100 1018 .mmap = cifs_file_mmap, 1101 1019 .splice_read = generic_file_splice_read, 1102 1020 .unlocked_ioctl = cifs_ioctl, 1021 + .copy_file_range = cifs_copy_file_range, 1103 1022 .clone_file_range = cifs_clone_file_range, 1104 1023 .llseek = cifs_llseek, 1105 1024 .setlease = cifs_setlease, ··· 1118 1035 .splice_read = generic_file_splice_read, 1119 1036 .llseek = cifs_llseek, 1120 1037 .unlocked_ioctl = cifs_ioctl, 1038 + .copy_file_range = cifs_copy_file_range, 1121 1039 .clone_file_range = cifs_clone_file_range, 1122 1040 .setlease = cifs_setlease, 1123 1041 .fallocate = cifs_fallocate, ··· 1135 1051 .splice_read = generic_file_splice_read, 1136 1052 .llseek = cifs_llseek, 1137 1053 .unlocked_ioctl = cifs_ioctl, 1054 + .copy_file_range = cifs_copy_file_range, 1138 1055 .clone_file_range = cifs_clone_file_range, 1139 1056 .setlease = cifs_setlease, 1140 1057 .fallocate = cifs_fallocate, ··· 1152 1067 .mmap = cifs_file_mmap, 1153 1068 .splice_read = generic_file_splice_read, 1154 1069 .unlocked_ioctl = cifs_ioctl, 1070 + .copy_file_range = cifs_copy_file_range, 1155 1071 .clone_file_range = cifs_clone_file_range, 1156 1072 .llseek = cifs_llseek, 1157 1073 .setlease = cifs_setlease, ··· 1164 1078 .release = cifs_closedir, 1165 1079 .read = generic_read_dir, 1166 1080 .unlocked_ioctl = cifs_ioctl, 1081 + .copy_file_range = cifs_copy_file_range, 1167 1082 .clone_file_range = cifs_clone_file_range, 1168 1083 .llseek = generic_file_llseek, 1169 1084 };
+5
fs/cifs/cifsfs.h
··· 139 139 # define cifs_listxattr NULL 140 140 #endif 141 141 142 + extern ssize_t cifs_file_copychunk_range(unsigned int xid, 143 + struct file *src_file, loff_t off, 144 + struct file *dst_file, loff_t destoff, 145 + size_t len, unsigned int flags); 146 + 142 147 extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); 143 148 #ifdef CONFIG_CIFS_NFSD_EXPORT 144 149 extern const struct export_operations cifs_export_ops;
+15 -3
fs/cifs/cifsglob.h
··· 243 243 /* verify the message */ 244 244 int (*check_message)(char *, unsigned int, struct TCP_Server_Info *); 245 245 bool (*is_oplock_break)(char *, struct TCP_Server_Info *); 246 + int (*handle_cancelled_mid)(char *, struct TCP_Server_Info *); 246 247 void (*downgrade_oplock)(struct TCP_Server_Info *, 247 248 struct cifsInodeInfo *, bool); 248 249 /* process transaction2 response */ ··· 408 407 char * (*create_lease_buf)(u8 *, u8); 409 408 /* parse lease context buffer and return oplock/epoch info */ 410 409 __u8 (*parse_lease_buf)(void *, unsigned int *); 411 - int (*clone_range)(const unsigned int, struct cifsFileInfo *src_file, 412 - struct cifsFileInfo *target_file, u64 src_off, u64 len, 413 - u64 dest_off); 410 + ssize_t (*copychunk_range)(const unsigned int, 411 + struct cifsFileInfo *src_file, 412 + struct cifsFileInfo *target_file, 413 + u64 src_off, u64 len, u64 dest_off); 414 414 int (*duplicate_extents)(const unsigned int, struct cifsFileInfo *src, 415 415 struct cifsFileInfo *target_file, u64 src_off, u64 len, 416 416 u64 dest_off); ··· 1345 1343 void *callback_data; /* general purpose pointer for callback */ 1346 1344 void *resp_buf; /* pointer to received SMB header */ 1347 1345 int mid_state; /* wish this were enum but can not pass to wait_event */ 1346 + unsigned int mid_flags; 1348 1347 __le16 command; /* smb command code */ 1349 1348 bool large_buf:1; /* if valid response, is pointer to large buf */ 1350 1349 bool multiRsp:1; /* multiple trans2 responses for one request */ 1351 1350 bool multiEnd:1; /* both received */ 1352 1351 bool decrypted:1; /* decrypted entry */ 1352 + }; 1353 + 1354 + struct close_cancelled_open { 1355 + struct cifs_fid fid; 1356 + struct cifs_tcon *tcon; 1357 + struct work_struct work; 1353 1358 }; 1354 1359 1355 1360 /* Make code in transport.c a little cleaner by moving ··· 1489 1480 #define MID_RETRY_NEEDED 8 /* session closed while this request out */ 1490 1481 #define MID_RESPONSE_MALFORMED 0x10 1491 1482 #define MID_SHUTDOWN 0x20 1483 + 1484 + /* Flags */ 1485 + #define MID_WAIT_CANCELLED 1 /* Cancelled while waiting for response */ 1492 1486 1493 1487 /* Types of response buffer returned from SendReceive2 */ 1494 1488 #define CIFS_NO_BUFFER 0 /* Response buffer not returned */
+2 -1
fs/cifs/cifsproto.h
··· 79 79 extern void cifs_wake_up_task(struct mid_q_entry *mid); 80 80 extern int cifs_handle_standard(struct TCP_Server_Info *server, 81 81 struct mid_q_entry *mid); 82 - extern int cifs_discard_remaining_data(struct TCP_Server_Info *server); 82 + extern int cifs_discard_remaining_data(struct TCP_Server_Info *server, 83 + char *buf); 83 84 extern int cifs_call_async(struct TCP_Server_Info *server, 84 85 struct smb_rqst *rqst, 85 86 mid_receive_t *receive, mid_callback_t *callback,
+7 -4
fs/cifs/cifssmb.c
··· 1400 1400 * current bigbuf. 1401 1401 */ 1402 1402 int 1403 - cifs_discard_remaining_data(struct TCP_Server_Info *server) 1403 + cifs_discard_remaining_data(struct TCP_Server_Info *server, char *buf) 1404 1404 { 1405 - unsigned int rfclen = get_rfc1002_length(server->smallbuf); 1405 + unsigned int rfclen = get_rfc1002_length(buf); 1406 1406 int remaining = rfclen + 4 - server->total_read; 1407 1407 1408 1408 while (remaining > 0) { ··· 1426 1426 int length; 1427 1427 struct cifs_readdata *rdata = mid->callback_data; 1428 1428 1429 - length = cifs_discard_remaining_data(server); 1429 + length = cifs_discard_remaining_data(server, mid->resp_buf); 1430 1430 dequeue_mid(mid, rdata->result); 1431 1431 return length; 1432 1432 } ··· 1459 1459 1460 1460 if (server->ops->is_status_pending && 1461 1461 server->ops->is_status_pending(buf, server, 0)) { 1462 - cifs_discard_remaining_data(server); 1462 + cifs_discard_remaining_data(server, buf); 1463 1463 return -1; 1464 1464 } 1465 1465 ··· 1518 1518 rdata->iov[1].iov_len = server->total_read - 4; 1519 1519 cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n", 1520 1520 rdata->iov[0].iov_base, server->total_read); 1521 + 1522 + mid->resp_buf = server->smallbuf; 1523 + server->smallbuf = NULL; 1521 1524 1522 1525 /* how much data is in the response? */ 1523 1526 data_len = server->ops->read_data_length(buf);
+11 -2
fs/cifs/connect.c
··· 904 904 905 905 server->lstrp = jiffies; 906 906 if (mid_entry != NULL) { 907 + if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) && 908 + mid_entry->mid_state == MID_RESPONSE_RECEIVED && 909 + server->ops->handle_cancelled_mid) 910 + server->ops->handle_cancelled_mid( 911 + mid_entry->resp_buf, 912 + server); 913 + 907 914 if (!mid_entry->multiRsp || mid_entry->multiEnd) 908 915 mid_entry->callback(mid_entry); 909 - } else if (!server->ops->is_oplock_break || 910 - !server->ops->is_oplock_break(buf, server)) { 916 + } else if (server->ops->is_oplock_break && 917 + server->ops->is_oplock_break(buf, server)) { 918 + cifs_dbg(FYI, "Received oplock break\n"); 919 + } else { 911 920 cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n", 912 921 atomic_read(&midCount)); 913 922 cifs_dump_mem("Received Data is: ", buf,
+5 -61
fs/cifs/ioctl.c
··· 34 34 #include "cifs_ioctl.h" 35 35 #include <linux/btrfs.h> 36 36 37 - static int cifs_file_clone_range(unsigned int xid, struct file *src_file, 38 - struct file *dst_file) 39 - { 40 - struct inode *src_inode = file_inode(src_file); 41 - struct inode *target_inode = file_inode(dst_file); 42 - struct cifsFileInfo *smb_file_src; 43 - struct cifsFileInfo *smb_file_target; 44 - struct cifs_tcon *src_tcon; 45 - struct cifs_tcon *target_tcon; 46 - int rc; 47 - 48 - cifs_dbg(FYI, "ioctl clone range\n"); 49 - 50 - if (!src_file->private_data || !dst_file->private_data) { 51 - rc = -EBADF; 52 - cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n"); 53 - goto out; 54 - } 55 - 56 - rc = -EXDEV; 57 - smb_file_target = dst_file->private_data; 58 - smb_file_src = src_file->private_data; 59 - src_tcon = tlink_tcon(smb_file_src->tlink); 60 - target_tcon = tlink_tcon(smb_file_target->tlink); 61 - 62 - if (src_tcon->ses != target_tcon->ses) { 63 - cifs_dbg(VFS, "source and target of copy not on same server\n"); 64 - goto out; 65 - } 66 - 67 - /* 68 - * Note: cifs case is easier than btrfs since server responsible for 69 - * checks for proper open modes and file type and if it wants 70 - * server could even support copy of range where source = target 71 - */ 72 - lock_two_nondirectories(target_inode, src_inode); 73 - 74 - cifs_dbg(FYI, "about to flush pages\n"); 75 - /* should we flush first and last page first */ 76 - truncate_inode_pages(&target_inode->i_data, 0); 77 - 78 - if (target_tcon->ses->server->ops->clone_range) 79 - rc = target_tcon->ses->server->ops->clone_range(xid, 80 - smb_file_src, smb_file_target, 0, src_inode->i_size, 0); 81 - else 82 - rc = -EOPNOTSUPP; 83 - 84 - /* force revalidate of size and timestamps of target file now 85 - that target is updated on the server */ 86 - CIFS_I(target_inode)->time = 0; 87 - /* although unlocking in the reverse order from locking is not 88 - strictly necessary here it is a little cleaner to be consistent */ 89 - unlock_two_nondirectories(src_inode, target_inode); 90 - out: 91 - return rc; 92 - } 93 - 94 - static long cifs_ioctl_clone(unsigned int xid, struct file *dst_file, 37 + static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file, 95 38 unsigned long srcfd) 96 39 { 97 40 int rc; 98 41 struct fd src_file; 99 42 struct inode *src_inode; 100 43 101 - cifs_dbg(FYI, "ioctl clone range\n"); 44 + cifs_dbg(FYI, "ioctl copychunk range\n"); 102 45 /* the destination must be opened for writing */ 103 46 if (!(dst_file->f_mode & FMODE_WRITE)) { 104 47 cifs_dbg(FYI, "file target not open for write\n"); ··· 72 129 if (S_ISDIR(src_inode->i_mode)) 73 130 goto out_fput; 74 131 75 - rc = cifs_file_clone_range(xid, src_file.file, dst_file); 132 + rc = cifs_file_copychunk_range(xid, src_file.file, 0, dst_file, 0, 133 + src_inode->i_size, 0); 76 134 77 135 out_fput: 78 136 fdput(src_file); ··· 195 251 } 196 252 break; 197 253 case CIFS_IOC_COPYCHUNK_FILE: 198 - rc = cifs_ioctl_clone(xid, filep, arg); 254 + rc = cifs_ioctl_copychunk(xid, filep, arg); 199 255 break; 200 256 case CIFS_IOC_SET_INTEGRITY: 201 257 if (pSMBFile == NULL)
+46
fs/cifs/smb2misc.c
··· 659 659 cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n"); 660 660 return false; 661 661 } 662 + 663 + void 664 + smb2_cancelled_close_fid(struct work_struct *work) 665 + { 666 + struct close_cancelled_open *cancelled = container_of(work, 667 + struct close_cancelled_open, work); 668 + 669 + cifs_dbg(VFS, "Close unmatched open\n"); 670 + 671 + SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid, 672 + cancelled->fid.volatile_fid); 673 + cifs_put_tcon(cancelled->tcon); 674 + kfree(cancelled); 675 + } 676 + 677 + int 678 + smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server) 679 + { 680 + struct smb2_sync_hdr *sync_hdr = get_sync_hdr(buffer); 681 + struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer; 682 + struct cifs_tcon *tcon; 683 + struct close_cancelled_open *cancelled; 684 + 685 + if (sync_hdr->Command != SMB2_CREATE || 686 + sync_hdr->Status != STATUS_SUCCESS) 687 + return 0; 688 + 689 + cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL); 690 + if (!cancelled) 691 + return -ENOMEM; 692 + 693 + tcon = smb2_find_smb_tcon(server, sync_hdr->SessionId, 694 + sync_hdr->TreeId); 695 + if (!tcon) { 696 + kfree(cancelled); 697 + return -ENOENT; 698 + } 699 + 700 + cancelled->fid.persistent_fid = rsp->PersistentFileId; 701 + cancelled->fid.volatile_fid = rsp->VolatileFileId; 702 + cancelled->tcon = tcon; 703 + INIT_WORK(&cancelled->work, smb2_cancelled_close_fid); 704 + queue_work(cifsiod_wq, &cancelled->work); 705 + 706 + return 0; 707 + }
+26 -15
fs/cifs/smb2ops.c
··· 21 21 #include <linux/vfs.h> 22 22 #include <linux/falloc.h> 23 23 #include <linux/scatterlist.h> 24 + #include <linux/uuid.h> 24 25 #include <crypto/aead.h> 25 26 #include "cifsglob.h" 26 27 #include "smb2pdu.h" ··· 593 592 return rc; 594 593 } 595 594 596 - static int 597 - smb2_clone_range(const unsigned int xid, 595 + static ssize_t 596 + smb2_copychunk_range(const unsigned int xid, 598 597 struct cifsFileInfo *srcfile, 599 598 struct cifsFileInfo *trgtfile, u64 src_off, 600 599 u64 len, u64 dest_off) ··· 606 605 struct cifs_tcon *tcon; 607 606 int chunks_copied = 0; 608 607 bool chunk_sizes_updated = false; 608 + ssize_t bytes_written, total_bytes_written = 0; 609 609 610 610 pcchunk = kmalloc(sizeof(struct copychunk_ioctl), GFP_KERNEL); 611 611 612 612 if (pcchunk == NULL) 613 613 return -ENOMEM; 614 614 615 - cifs_dbg(FYI, "in smb2_clone_range - about to call request res key\n"); 615 + cifs_dbg(FYI, "in smb2_copychunk_range - about to call request res key\n"); 616 616 /* Request a key from the server to identify the source of the copy */ 617 617 rc = SMB2_request_res_key(xid, tlink_tcon(srcfile->tlink), 618 618 srcfile->fid.persistent_fid, ··· 671 669 } 672 670 chunks_copied++; 673 671 674 - src_off += le32_to_cpu(retbuf->TotalBytesWritten); 675 - dest_off += le32_to_cpu(retbuf->TotalBytesWritten); 676 - len -= le32_to_cpu(retbuf->TotalBytesWritten); 672 + bytes_written = le32_to_cpu(retbuf->TotalBytesWritten); 673 + src_off += bytes_written; 674 + dest_off += bytes_written; 675 + len -= bytes_written; 676 + total_bytes_written += bytes_written; 677 677 678 - cifs_dbg(FYI, "Chunks %d PartialChunk %d Total %d\n", 678 + cifs_dbg(FYI, "Chunks %d PartialChunk %d Total %zu\n", 679 679 le32_to_cpu(retbuf->ChunksWritten), 680 680 le32_to_cpu(retbuf->ChunkBytesWritten), 681 - le32_to_cpu(retbuf->TotalBytesWritten)); 681 + bytes_written); 682 682 } else if (rc == -EINVAL) { 683 683 if (ret_data_len != sizeof(struct copychunk_ioctl_rsp)) 684 684 goto cchunk_out; ··· 717 713 cchunk_out: 718 714 kfree(pcchunk); 719 715 kfree(retbuf); 720 - return rc; 716 + if (rc) 717 + return rc; 718 + else 719 + return total_bytes_written; 721 720 } 722 721 723 722 static int ··· 2195 2188 if (rc) 2196 2189 goto free_pages; 2197 2190 2198 - rc = cifs_discard_remaining_data(server); 2191 + rc = cifs_discard_remaining_data(server, buf); 2199 2192 if (rc) 2200 2193 goto free_pages; 2201 2194 ··· 2221 2214 kfree(pages); 2222 2215 return rc; 2223 2216 discard_data: 2224 - cifs_discard_remaining_data(server); 2217 + cifs_discard_remaining_data(server, buf); 2225 2218 goto free_pages; 2226 2219 } 2227 2220 ··· 2329 2322 .clear_stats = smb2_clear_stats, 2330 2323 .print_stats = smb2_print_stats, 2331 2324 .is_oplock_break = smb2_is_valid_oplock_break, 2325 + .handle_cancelled_mid = smb2_handle_cancelled_mid, 2332 2326 .downgrade_oplock = smb2_downgrade_oplock, 2333 2327 .need_neg = smb2_need_neg, 2334 2328 .negotiate = smb2_negotiate, ··· 2385 2377 .set_oplock_level = smb2_set_oplock_level, 2386 2378 .create_lease_buf = smb2_create_lease_buf, 2387 2379 .parse_lease_buf = smb2_parse_lease_buf, 2388 - .clone_range = smb2_clone_range, 2380 + .copychunk_range = smb2_copychunk_range, 2389 2381 .wp_retry_size = smb2_wp_retry_size, 2390 2382 .dir_needs_close = smb2_dir_needs_close, 2391 2383 .get_dfs_refer = smb2_get_dfs_refer, ··· 2412 2404 .clear_stats = smb2_clear_stats, 2413 2405 .print_stats = smb2_print_stats, 2414 2406 .is_oplock_break = smb2_is_valid_oplock_break, 2407 + .handle_cancelled_mid = smb2_handle_cancelled_mid, 2415 2408 .downgrade_oplock = smb2_downgrade_oplock, 2416 2409 .need_neg = smb2_need_neg, 2417 2410 .negotiate = smb2_negotiate, ··· 2468 2459 .set_oplock_level = smb21_set_oplock_level, 2469 2460 .create_lease_buf = smb2_create_lease_buf, 2470 2461 .parse_lease_buf = smb2_parse_lease_buf, 2471 - .clone_range = smb2_clone_range, 2462 + .copychunk_range = smb2_copychunk_range, 2472 2463 .wp_retry_size = smb2_wp_retry_size, 2473 2464 .dir_needs_close = smb2_dir_needs_close, 2474 2465 .enum_snapshots = smb3_enum_snapshots, ··· 2497 2488 .print_stats = smb2_print_stats, 2498 2489 .dump_share_caps = smb2_dump_share_caps, 2499 2490 .is_oplock_break = smb2_is_valid_oplock_break, 2491 + .handle_cancelled_mid = smb2_handle_cancelled_mid, 2500 2492 .downgrade_oplock = smb2_downgrade_oplock, 2501 2493 .need_neg = smb2_need_neg, 2502 2494 .negotiate = smb2_negotiate, ··· 2555 2545 .set_oplock_level = smb3_set_oplock_level, 2556 2546 .create_lease_buf = smb3_create_lease_buf, 2557 2547 .parse_lease_buf = smb3_parse_lease_buf, 2558 - .clone_range = smb2_clone_range, 2548 + .copychunk_range = smb2_copychunk_range, 2559 2549 .duplicate_extents = smb2_duplicate_extents, 2560 2550 .validate_negotiate = smb3_validate_negotiate, 2561 2551 .wp_retry_size = smb2_wp_retry_size, ··· 2592 2582 .print_stats = smb2_print_stats, 2593 2583 .dump_share_caps = smb2_dump_share_caps, 2594 2584 .is_oplock_break = smb2_is_valid_oplock_break, 2585 + .handle_cancelled_mid = smb2_handle_cancelled_mid, 2595 2586 .downgrade_oplock = smb2_downgrade_oplock, 2596 2587 .need_neg = smb2_need_neg, 2597 2588 .negotiate = smb2_negotiate, ··· 2650 2639 .set_oplock_level = smb3_set_oplock_level, 2651 2640 .create_lease_buf = smb3_create_lease_buf, 2652 2641 .parse_lease_buf = smb3_parse_lease_buf, 2653 - .clone_range = smb2_clone_range, 2642 + .copychunk_range = smb2_copychunk_range, 2654 2643 .duplicate_extents = smb2_duplicate_extents, 2655 2644 /* .validate_negotiate = smb3_validate_negotiate, */ /* not used in 3.11 */ 2656 2645 .wp_retry_size = smb2_wp_retry_size,
+4
fs/cifs/smb2pdu.c
··· 1185 1185 return -EINVAL; 1186 1186 } 1187 1187 1188 + /* SMB2 TREE_CONNECT request must be called with TreeId == 0 */ 1189 + if (tcon) 1190 + tcon->tid = 0; 1191 + 1188 1192 rc = small_smb2_init(SMB2_TREE_CONNECT, tcon, (void **) &req); 1189 1193 if (rc) { 1190 1194 kfree(unc_path);
+7
fs/cifs/smb2proto.h
··· 48 48 struct smb_rqst *rqst); 49 49 extern struct mid_q_entry *smb2_setup_async_request( 50 50 struct TCP_Server_Info *server, struct smb_rqst *rqst); 51 + extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server, 52 + __u64 ses_id); 53 + extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server, 54 + __u64 ses_id, __u32 tid); 51 55 extern int smb2_calc_signature(struct smb_rqst *rqst, 52 56 struct TCP_Server_Info *server); 53 57 extern int smb3_calc_signature(struct smb_rqst *rqst, ··· 168 164 extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon, 169 165 const u64 persistent_fid, const u64 volatile_fid, 170 166 const __u8 oplock_level); 167 + extern int smb2_handle_cancelled_mid(char *buffer, 168 + struct TCP_Server_Info *server); 169 + void smb2_cancelled_close_fid(struct work_struct *work); 171 170 extern int SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon, 172 171 u64 persistent_file_id, u64 volatile_file_id, 173 172 struct kstatfs *FSData);
+53 -6
fs/cifs/smb2transport.c
··· 115 115 return 0; 116 116 } 117 117 118 + static struct cifs_ses * 119 + smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id) 120 + { 121 + struct cifs_ses *ses; 122 + 123 + list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { 124 + if (ses->Suid != ses_id) 125 + continue; 126 + return ses; 127 + } 128 + 129 + return NULL; 130 + } 131 + 118 132 struct cifs_ses * 119 133 smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id) 120 134 { 121 135 struct cifs_ses *ses; 122 136 123 137 spin_lock(&cifs_tcp_ses_lock); 124 - list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { 125 - if (ses->Suid != ses_id) 126 - continue; 127 - spin_unlock(&cifs_tcp_ses_lock); 128 - return ses; 129 - } 138 + ses = smb2_find_smb_ses_unlocked(server, ses_id); 130 139 spin_unlock(&cifs_tcp_ses_lock); 131 140 141 + return ses; 142 + } 143 + 144 + static struct cifs_tcon * 145 + smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32 tid) 146 + { 147 + struct cifs_tcon *tcon; 148 + 149 + list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { 150 + if (tcon->tid != tid) 151 + continue; 152 + ++tcon->tc_count; 153 + return tcon; 154 + } 155 + 132 156 return NULL; 157 + } 158 + 159 + /* 160 + * Obtain tcon corresponding to the tid in the given 161 + * cifs_ses 162 + */ 163 + 164 + struct cifs_tcon * 165 + smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid) 166 + { 167 + struct cifs_ses *ses; 168 + struct cifs_tcon *tcon; 169 + 170 + spin_lock(&cifs_tcp_ses_lock); 171 + ses = smb2_find_smb_ses_unlocked(server, ses_id); 172 + if (!ses) { 173 + spin_unlock(&cifs_tcp_ses_lock); 174 + return NULL; 175 + } 176 + tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid); 177 + spin_unlock(&cifs_tcp_ses_lock); 178 + 179 + return tcon; 133 180 } 134 181 135 182 int
+2
fs/cifs/transport.c
··· 752 752 753 753 rc = wait_for_response(ses->server, midQ); 754 754 if (rc != 0) { 755 + cifs_dbg(FYI, "Cancelling wait for mid %llu\n", midQ->mid); 755 756 send_cancel(ses->server, rqst, midQ); 756 757 spin_lock(&GlobalMid_Lock); 757 758 if (midQ->mid_state == MID_REQUEST_SUBMITTED) { 759 + midQ->mid_flags |= MID_WAIT_CANCELLED; 758 760 midQ->callback = DeleteMidQEntry; 759 761 spin_unlock(&GlobalMid_Lock); 760 762 add_credits(ses->server, 1, optype);