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 '6.0-rc2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull cfis fixes from Steve French:

- two locking fixes (zero range, punch hole)

- DFS 9 fix (padding), affecting some servers

- three minor cleanup changes

* tag '6.0-rc2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
cifs: Add helper function to check smb1+ server
cifs: Use help macro to get the mid header size
cifs: Use help macro to get the header preamble size
cifs: skip extra NULL byte in filenames
smb3: missing inode locks in punch hole
smb3: missing inode locks in zero range

+70 -67
+1 -2
fs/cifs/cifsencrypt.c
··· 32 32 int rc; 33 33 struct kvec *iov = rqst->rq_iov; 34 34 int n_vec = rqst->rq_nvec; 35 - int is_smb2 = server->vals->header_preamble_size == 0; 36 35 37 36 /* iov[0] is actual data and not the rfc1002 length for SMB2+ */ 38 - if (is_smb2) { 37 + if (!is_smb1(server)) { 39 38 if (iov[0].iov_len <= 4) 40 39 return -EIO; 41 40 i = 0;
+7
fs/cifs/cifsglob.h
··· 557 557 558 558 #define HEADER_SIZE(server) (server->vals->header_size) 559 559 #define MAX_HEADER_SIZE(server) (server->vals->max_header_size) 560 + #define HEADER_PREAMBLE_SIZE(server) (server->vals->header_preamble_size) 561 + #define MID_HEADER_SIZE(server) (HEADER_SIZE(server) - 1 - HEADER_PREAMBLE_SIZE(server)) 560 562 561 563 /** 562 564 * CIFS superblock mount flags (mnt_cifs_flags) to consider when ··· 751 749 char *origin_fullpath, *leaf_fullpath, *current_fullpath; 752 750 #endif 753 751 }; 752 + 753 + static inline bool is_smb1(struct TCP_Server_Info *server) 754 + { 755 + return HEADER_PREAMBLE_SIZE(server) != 0; 756 + } 754 757 755 758 static inline void cifs_server_lock(struct TCP_Server_Info *server) 756 759 {
+10 -13
fs/cifs/connect.c
··· 871 871 /* 872 872 * SMB1 does not use credits. 873 873 */ 874 - if (server->vals->header_preamble_size) 874 + if (is_smb1(server)) 875 875 return 0; 876 876 877 877 return le16_to_cpu(shdr->CreditRequest); ··· 1050 1050 1051 1051 /* make sure this will fit in a large buffer */ 1052 1052 if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) - 1053 - server->vals->header_preamble_size) { 1053 + HEADER_PREAMBLE_SIZE(server)) { 1054 1054 cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length); 1055 1055 cifs_reconnect(server, true); 1056 1056 return -ECONNABORTED; ··· 1065 1065 1066 1066 /* now read the rest */ 1067 1067 length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1, 1068 - pdu_length - HEADER_SIZE(server) + 1 1069 - + server->vals->header_preamble_size); 1068 + pdu_length - MID_HEADER_SIZE(server)); 1070 1069 1071 1070 if (length < 0) 1072 1071 return length; ··· 1121 1122 /* 1122 1123 * SMB1 does not use credits. 1123 1124 */ 1124 - if (server->vals->header_preamble_size) 1125 + if (is_smb1(server)) 1125 1126 return; 1126 1127 1127 1128 if (shdr->CreditRequest) { ··· 1179 1180 if (length < 0) 1180 1181 continue; 1181 1182 1182 - if (server->vals->header_preamble_size == 0) 1183 - server->total_read = 0; 1184 - else 1183 + if (is_smb1(server)) 1185 1184 server->total_read = length; 1185 + else 1186 + server->total_read = 0; 1186 1187 1187 1188 /* 1188 1189 * The right amount was read from socket - 4 bytes, ··· 1197 1198 server->pdu_size = pdu_length; 1198 1199 1199 1200 /* make sure we have enough to get to the MID */ 1200 - if (server->pdu_size < HEADER_SIZE(server) - 1 - 1201 - server->vals->header_preamble_size) { 1201 + if (server->pdu_size < MID_HEADER_SIZE(server)) { 1202 1202 cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n", 1203 1203 server->pdu_size); 1204 1204 cifs_reconnect(server, true); ··· 1206 1208 1207 1209 /* read down to the MID */ 1208 1210 length = cifs_read_from_socket(server, 1209 - buf + server->vals->header_preamble_size, 1210 - HEADER_SIZE(server) - 1 1211 - - server->vals->header_preamble_size); 1211 + buf + HEADER_PREAMBLE_SIZE(server), 1212 + MID_HEADER_SIZE(server)); 1212 1213 if (length < 0) 1213 1214 continue; 1214 1215 server->total_read += length;
+36 -31
fs/cifs/smb2ops.c
··· 3307 3307 return pntsd; 3308 3308 } 3309 3309 3310 + static long smb3_zero_data(struct file *file, struct cifs_tcon *tcon, 3311 + loff_t offset, loff_t len, unsigned int xid) 3312 + { 3313 + struct cifsFileInfo *cfile = file->private_data; 3314 + struct file_zero_data_information fsctl_buf; 3315 + 3316 + cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len); 3317 + 3318 + fsctl_buf.FileOffset = cpu_to_le64(offset); 3319 + fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len); 3320 + 3321 + return SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, 3322 + cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA, 3323 + (char *)&fsctl_buf, 3324 + sizeof(struct file_zero_data_information), 3325 + 0, NULL, NULL); 3326 + } 3327 + 3310 3328 static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon, 3311 3329 loff_t offset, loff_t len, bool keep_size) 3312 3330 { 3313 3331 struct cifs_ses *ses = tcon->ses; 3314 - struct inode *inode; 3315 - struct cifsInodeInfo *cifsi; 3332 + struct inode *inode = file_inode(file); 3333 + struct cifsInodeInfo *cifsi = CIFS_I(inode); 3316 3334 struct cifsFileInfo *cfile = file->private_data; 3317 - struct file_zero_data_information fsctl_buf; 3318 3335 long rc; 3319 3336 unsigned int xid; 3320 3337 __le64 eof; 3321 3338 3322 3339 xid = get_xid(); 3323 3340 3324 - inode = d_inode(cfile->dentry); 3325 - cifsi = CIFS_I(inode); 3326 - 3327 3341 trace_smb3_zero_enter(xid, cfile->fid.persistent_fid, tcon->tid, 3328 3342 ses->Suid, offset, len); 3343 + 3344 + inode_lock(inode); 3345 + filemap_invalidate_lock(inode->i_mapping); 3329 3346 3330 3347 /* 3331 3348 * We zero the range through ioctl, so we need remove the page caches ··· 3351 3334 truncate_pagecache_range(inode, offset, offset + len - 1); 3352 3335 3353 3336 /* if file not oplocked can't be sure whether asking to extend size */ 3354 - if (!CIFS_CACHE_READ(cifsi)) 3355 - if (keep_size == false) { 3356 - rc = -EOPNOTSUPP; 3357 - trace_smb3_zero_err(xid, cfile->fid.persistent_fid, 3358 - tcon->tid, ses->Suid, offset, len, rc); 3359 - free_xid(xid); 3360 - return rc; 3361 - } 3337 + rc = -EOPNOTSUPP; 3338 + if (keep_size == false && !CIFS_CACHE_READ(cifsi)) 3339 + goto zero_range_exit; 3362 3340 3363 - cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len); 3364 - 3365 - fsctl_buf.FileOffset = cpu_to_le64(offset); 3366 - fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len); 3367 - 3368 - rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, 3369 - cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA, 3370 - (char *)&fsctl_buf, 3371 - sizeof(struct file_zero_data_information), 3372 - 0, NULL, NULL); 3373 - if (rc) 3341 + rc = smb3_zero_data(file, tcon, offset, len, xid); 3342 + if (rc < 0) 3374 3343 goto zero_range_exit; 3375 3344 3376 3345 /* ··· 3369 3366 } 3370 3367 3371 3368 zero_range_exit: 3369 + filemap_invalidate_unlock(inode->i_mapping); 3370 + inode_unlock(inode); 3372 3371 free_xid(xid); 3373 3372 if (rc) 3374 3373 trace_smb3_zero_err(xid, cfile->fid.persistent_fid, tcon->tid, ··· 3384 3379 static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, 3385 3380 loff_t offset, loff_t len) 3386 3381 { 3387 - struct inode *inode; 3382 + struct inode *inode = file_inode(file); 3388 3383 struct cifsFileInfo *cfile = file->private_data; 3389 3384 struct file_zero_data_information fsctl_buf; 3390 3385 long rc; ··· 3393 3388 3394 3389 xid = get_xid(); 3395 3390 3396 - inode = d_inode(cfile->dentry); 3397 - 3391 + inode_lock(inode); 3398 3392 /* Need to make file sparse, if not already, before freeing range. */ 3399 3393 /* Consider adding equivalent for compressed since it could also work */ 3400 3394 if (!smb2_set_sparse(xid, tcon, cfile, inode, set_sparse)) { 3401 3395 rc = -EOPNOTSUPP; 3402 - free_xid(xid); 3403 - return rc; 3396 + goto out; 3404 3397 } 3405 3398 3406 3399 filemap_invalidate_lock(inode->i_mapping); ··· 3418 3415 (char *)&fsctl_buf, 3419 3416 sizeof(struct file_zero_data_information), 3420 3417 CIFSMaxBufSize, NULL, NULL); 3421 - free_xid(xid); 3422 3418 filemap_invalidate_unlock(inode->i_mapping); 3419 + out: 3420 + inode_unlock(inode); 3421 + free_xid(xid); 3423 3422 return rc; 3424 3423 } 3425 3424
+6 -10
fs/cifs/smb2pdu.c
··· 2572 2572 2573 2573 path_len = UniStrnlen((wchar_t *)path, PATH_MAX); 2574 2574 2575 - /* 2576 - * make room for one path separator between the treename and 2577 - * path 2578 - */ 2579 - *out_len = treename_len + 1 + path_len; 2575 + /* make room for one path separator only if @path isn't empty */ 2576 + *out_len = treename_len + (path[0] ? 1 : 0) + path_len; 2580 2577 2581 2578 /* 2582 - * final path needs to be null-terminated UTF16 with a 2583 - * size aligned to 8 2579 + * final path needs to be 8-byte aligned as specified in 2580 + * MS-SMB2 2.2.13 SMB2 CREATE Request. 2584 2581 */ 2585 - 2586 - *out_size = roundup((*out_len+1)*2, 8); 2587 - *out_path = kzalloc(*out_size, GFP_KERNEL); 2582 + *out_size = roundup(*out_len * sizeof(__le16), 8); 2583 + *out_path = kzalloc(*out_size + sizeof(__le16) /* null */, GFP_KERNEL); 2588 2584 if (!*out_path) 2589 2585 return -ENOMEM; 2590 2586
+10 -11
fs/cifs/transport.c
··· 261 261 int nvec; 262 262 unsigned long buflen = 0; 263 263 264 - if (server->vals->header_preamble_size == 0 && 265 - rqst->rq_nvec >= 2 && rqst->rq_iov[0].iov_len == 4) { 264 + if (!is_smb1(server) && rqst->rq_nvec >= 2 && 265 + rqst->rq_iov[0].iov_len == 4) { 266 266 iov = &rqst->rq_iov[1]; 267 267 nvec = rqst->rq_nvec - 1; 268 268 } else { ··· 346 346 sigprocmask(SIG_BLOCK, &mask, &oldmask); 347 347 348 348 /* Generate a rfc1002 marker for SMB2+ */ 349 - if (server->vals->header_preamble_size == 0) { 349 + if (!is_smb1(server)) { 350 350 struct kvec hiov = { 351 351 .iov_base = &rfc1002_marker, 352 352 .iov_len = 4 ··· 1238 1238 buf = (char *)midQ[i]->resp_buf; 1239 1239 resp_iov[i].iov_base = buf; 1240 1240 resp_iov[i].iov_len = midQ[i]->resp_buf_size + 1241 - server->vals->header_preamble_size; 1241 + HEADER_PREAMBLE_SIZE(server); 1242 1242 1243 1243 if (midQ[i]->large_buf) 1244 1244 resp_buf_type[i] = CIFS_LARGE_BUFFER; ··· 1643 1643 cifs_discard_remaining_data(struct TCP_Server_Info *server) 1644 1644 { 1645 1645 unsigned int rfclen = server->pdu_size; 1646 - int remaining = rfclen + server->vals->header_preamble_size - 1646 + int remaining = rfclen + HEADER_PREAMBLE_SIZE(server) - 1647 1647 server->total_read; 1648 1648 1649 1649 while (remaining > 0) { ··· 1689 1689 unsigned int data_offset, data_len; 1690 1690 struct cifs_readdata *rdata = mid->callback_data; 1691 1691 char *buf = server->smallbuf; 1692 - unsigned int buflen = server->pdu_size + 1693 - server->vals->header_preamble_size; 1692 + unsigned int buflen = server->pdu_size + HEADER_PREAMBLE_SIZE(server); 1694 1693 bool use_rdma_mr = false; 1695 1694 1696 1695 cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n", ··· 1723 1724 1724 1725 /* set up first two iov for signature check and to get credits */ 1725 1726 rdata->iov[0].iov_base = buf; 1726 - rdata->iov[0].iov_len = server->vals->header_preamble_size; 1727 - rdata->iov[1].iov_base = buf + server->vals->header_preamble_size; 1727 + rdata->iov[0].iov_len = HEADER_PREAMBLE_SIZE(server); 1728 + rdata->iov[1].iov_base = buf + HEADER_PREAMBLE_SIZE(server); 1728 1729 rdata->iov[1].iov_len = 1729 - server->total_read - server->vals->header_preamble_size; 1730 + server->total_read - HEADER_PREAMBLE_SIZE(server); 1730 1731 cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n", 1731 1732 rdata->iov[0].iov_base, rdata->iov[0].iov_len); 1732 1733 cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n", ··· 1751 1752 } 1752 1753 1753 1754 data_offset = server->ops->read_data_offset(buf) + 1754 - server->vals->header_preamble_size; 1755 + HEADER_PREAMBLE_SIZE(server); 1755 1756 if (data_offset < server->total_read) { 1756 1757 /* 1757 1758 * win2k8 sometimes sends an offset of 0 when the read