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 'v7.0-rc-part2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull smb client fixes from Steve French:

- Fix three potential double free vulnerabilities

- Fix data corruption due to racy lease checks

- Enforce SMB1 signing verification checks

- Fix invalid mount option parsing

- Remove unneeded tracepoint

- Various minor error code corrections

- Minor cleanup

* tag 'v7.0-rc-part2-smb3-client-fixes' of git://git.samba.org/sfrench/cifs-2.6:
smb: client: terminate session upon failed client required signing
cifs: some missing initializations on replay
cifs: remove unnecessary tracing after put tcon
cifs: update internal module version number
smb: client: fix data corruption due to racy lease checks
smb/client: move NT_STATUS_MORE_ENTRIES
smb/client: rename to NT_ERROR_INVALID_DATATYPE
smb/client: rename to NT_STATUS_SOME_NOT_MAPPED
smb/client: map NT_STATUS_PRIVILEGE_NOT_HELD
smb/client: map NT_STATUS_MORE_PROCESSING_REQUIRED
smb/client: map NT_STATUS_BUFFER_OVERFLOW
smb/client: map NT_STATUS_NOTIFY_ENUM_DIR
cifs: SMB1 split: Remove duplicate include of cifs_debug.h
smb: client: fix regression with mount options parsing

+136 -73
+2 -2
fs/smb/client/cifsfs.h
··· 147 147 #endif /* CONFIG_CIFS_NFSD_EXPORT */ 148 148 149 149 /* when changing internal version - update following two lines at same time */ 150 - #define SMB3_PRODUCT_BUILD 58 151 - #define CIFS_VERSION "2.58" 150 + #define SMB3_PRODUCT_BUILD 59 151 + #define CIFS_VERSION "2.59" 152 152 #endif /* _CIFSFS_H */
+30 -6
fs/smb/client/cifsglob.h
··· 515 515 /* check for STATUS_NETWORK_SESSION_EXPIRED */ 516 516 bool (*is_session_expired)(char *); 517 517 /* send oplock break response */ 518 - int (*oplock_response)(struct cifs_tcon *tcon, __u64 persistent_fid, __u64 volatile_fid, 519 - __u16 net_fid, struct cifsInodeInfo *cifs_inode); 518 + int (*oplock_response)(struct cifs_tcon *tcon, __u64 persistent_fid, 519 + __u64 volatile_fid, __u16 net_fid, 520 + struct cifsInodeInfo *cifs_inode, 521 + unsigned int oplock); 520 522 /* query remote filesystem */ 521 523 int (*queryfs)(const unsigned int, struct cifs_tcon *, 522 524 const char *, struct cifs_sb_info *, struct kstatfs *); ··· 1533 1531 #define CIFS_CACHE_RW_FLG (CIFS_CACHE_READ_FLG | CIFS_CACHE_WRITE_FLG) 1534 1532 #define CIFS_CACHE_RHW_FLG (CIFS_CACHE_RW_FLG | CIFS_CACHE_HANDLE_FLG) 1535 1533 1536 - #define CIFS_CACHE_READ(cinode) ((cinode->oplock & CIFS_CACHE_READ_FLG) || (CIFS_SB(cinode->netfs.inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE)) 1537 - #define CIFS_CACHE_HANDLE(cinode) (cinode->oplock & CIFS_CACHE_HANDLE_FLG) 1538 - #define CIFS_CACHE_WRITE(cinode) ((cinode->oplock & CIFS_CACHE_WRITE_FLG) || (CIFS_SB(cinode->netfs.inode.i_sb)->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE)) 1539 - 1540 1534 /* 1541 1535 * One of these for each file inode 1542 1536 */ ··· 2308 2310 delay = umin(delay + CIFS_RECONN_DELAY_SECS, CIFS_MAX_RECONN_DELAY); 2309 2311 WRITE_ONCE(server->reconn_delay, delay); 2310 2312 queue_delayed_work(cifsiod_wq, &server->reconnect, delay * HZ); 2313 + } 2314 + 2315 + static inline bool __cifs_cache_state_check(struct cifsInodeInfo *cinode, 2316 + unsigned int oplock_flags, 2317 + unsigned int sb_flags) 2318 + { 2319 + struct cifs_sb_info *cifs_sb = CIFS_SB(cinode->netfs.inode.i_sb); 2320 + unsigned int oplock = READ_ONCE(cinode->oplock); 2321 + unsigned int sflags = cifs_sb->mnt_cifs_flags; 2322 + 2323 + return (oplock & oplock_flags) || (sflags & sb_flags); 2324 + } 2325 + 2326 + #define CIFS_CACHE_READ(cinode) \ 2327 + __cifs_cache_state_check(cinode, CIFS_CACHE_READ_FLG, \ 2328 + CIFS_MOUNT_RO_CACHE) 2329 + #define CIFS_CACHE_HANDLE(cinode) \ 2330 + __cifs_cache_state_check(cinode, CIFS_CACHE_HANDLE_FLG, 0) 2331 + #define CIFS_CACHE_WRITE(cinode) \ 2332 + __cifs_cache_state_check(cinode, CIFS_CACHE_WRITE_FLG, \ 2333 + CIFS_MOUNT_RW_CACHE) 2334 + 2335 + static inline void cifs_reset_oplock(struct cifsInodeInfo *cinode) 2336 + { 2337 + scoped_guard(spinlock, &cinode->open_file_lock) 2338 + WRITE_ONCE(cinode->oplock, 0); 2311 2339 } 2312 2340 2313 2341 #endif /* _CIFS_GLOB_H */
+36 -21
fs/smb/client/file.c
··· 731 731 oplock = fid->pending_open->oplock; 732 732 list_del(&fid->pending_open->olist); 733 733 734 - fid->purge_cache = false; 735 - server->ops->set_fid(cfile, fid, oplock); 736 - 737 734 list_add(&cfile->tlist, &tcon->openFileList); 738 735 atomic_inc(&tcon->num_local_opens); 739 736 740 737 /* if readable file instance put first in list*/ 741 738 spin_lock(&cinode->open_file_lock); 739 + fid->purge_cache = false; 740 + server->ops->set_fid(cfile, fid, oplock); 741 + 742 742 if (file->f_mode & FMODE_READ) 743 743 list_add(&cfile->flist, &cinode->openFileList); 744 744 else ··· 1410 1410 oplock = 0; 1411 1411 } 1412 1412 1413 - server->ops->set_fid(cfile, &cfile->fid, oplock); 1413 + scoped_guard(spinlock, &cinode->open_file_lock) 1414 + server->ops->set_fid(cfile, &cfile->fid, oplock); 1414 1415 if (oparms.reconnect) 1415 1416 cifs_relock_file(cfile); 1416 1417 ··· 1438 1437 { 1439 1438 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 1440 1439 struct cifsInodeInfo *cinode = CIFS_I(inode); 1440 + unsigned int oplock = READ_ONCE(cinode->oplock); 1441 1441 1442 - return (cifs_sb->ctx->closetimeo && cinode->lease_granted && dclose && 1443 - (cinode->oplock == CIFS_CACHE_RHW_FLG || 1444 - cinode->oplock == CIFS_CACHE_RH_FLG) && 1445 - !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags)); 1442 + return cifs_sb->ctx->closetimeo && cinode->lease_granted && dclose && 1443 + (oplock == CIFS_CACHE_RHW_FLG || oplock == CIFS_CACHE_RH_FLG) && 1444 + !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags); 1446 1445 1447 1446 } 1448 1447 ··· 2372 2371 cifs_zap_mapping(inode); 2373 2372 cifs_dbg(FYI, "Set no oplock for inode=%p due to mand locks\n", 2374 2373 inode); 2375 - CIFS_I(inode)->oplock = 0; 2374 + cifs_reset_oplock(CIFS_I(inode)); 2376 2375 } 2377 2376 2378 2377 rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length, ··· 2931 2930 cifs_zap_mapping(inode); 2932 2931 cifs_dbg(FYI, "Set Oplock/Lease to NONE for inode=%p after write\n", 2933 2932 inode); 2934 - cinode->oplock = 0; 2933 + cifs_reset_oplock(cinode); 2935 2934 } 2936 2935 out: 2937 2936 cifs_put_writer(cinode); ··· 2967 2966 cifs_dbg(FYI, 2968 2967 "Set no oplock for inode=%p after a write operation\n", 2969 2968 inode); 2970 - cinode->oplock = 0; 2969 + cifs_reset_oplock(cinode); 2971 2970 } 2972 2971 return written; 2973 2972 } ··· 3155 3154 struct super_block *sb = inode->i_sb; 3156 3155 struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 3157 3156 struct cifsInodeInfo *cinode = CIFS_I(inode); 3157 + bool cache_read, cache_write, cache_handle; 3158 3158 struct cifs_tcon *tcon; 3159 3159 struct TCP_Server_Info *server; 3160 3160 struct tcon_link *tlink; 3161 + unsigned int oplock; 3161 3162 int rc = 0; 3162 3163 bool purge_cache = false, oplock_break_cancelled; 3163 3164 __u64 persistent_fid, volatile_fid; ··· 3180 3177 tcon = tlink_tcon(tlink); 3181 3178 server = tcon->ses->server; 3182 3179 3183 - server->ops->downgrade_oplock(server, cinode, cfile->oplock_level, 3184 - cfile->oplock_epoch, &purge_cache); 3180 + scoped_guard(spinlock, &cinode->open_file_lock) { 3181 + unsigned int sbflags = cifs_sb->mnt_cifs_flags; 3185 3182 3186 - if (!CIFS_CACHE_WRITE(cinode) && CIFS_CACHE_READ(cinode) && 3187 - cifs_has_mand_locks(cinode)) { 3183 + server->ops->downgrade_oplock(server, cinode, cfile->oplock_level, 3184 + cfile->oplock_epoch, &purge_cache); 3185 + oplock = READ_ONCE(cinode->oplock); 3186 + cache_read = (oplock & CIFS_CACHE_READ_FLG) || 3187 + (sbflags & CIFS_MOUNT_RO_CACHE); 3188 + cache_write = (oplock & CIFS_CACHE_WRITE_FLG) || 3189 + (sbflags & CIFS_MOUNT_RW_CACHE); 3190 + cache_handle = oplock & CIFS_CACHE_HANDLE_FLG; 3191 + } 3192 + 3193 + if (!cache_write && cache_read && cifs_has_mand_locks(cinode)) { 3188 3194 cifs_dbg(FYI, "Reset oplock to None for inode=%p due to mand locks\n", 3189 3195 inode); 3190 - cinode->oplock = 0; 3196 + cifs_reset_oplock(cinode); 3197 + oplock = 0; 3198 + cache_read = cache_write = cache_handle = false; 3191 3199 } 3192 3200 3193 3201 if (S_ISREG(inode->i_mode)) { 3194 - if (CIFS_CACHE_READ(cinode)) 3202 + if (cache_read) 3195 3203 break_lease(inode, O_RDONLY); 3196 3204 else 3197 3205 break_lease(inode, O_WRONLY); 3198 3206 rc = filemap_fdatawrite(inode->i_mapping); 3199 - if (!CIFS_CACHE_READ(cinode) || purge_cache) { 3207 + if (!cache_read || purge_cache) { 3200 3208 rc = filemap_fdatawait(inode->i_mapping); 3201 3209 mapping_set_error(inode->i_mapping, rc); 3202 3210 cifs_zap_mapping(inode); 3203 3211 } 3204 3212 cifs_dbg(FYI, "Oplock flush inode %p rc %d\n", inode, rc); 3205 - if (CIFS_CACHE_WRITE(cinode)) 3213 + if (cache_write) 3206 3214 goto oplock_break_ack; 3207 3215 } 3208 3216 ··· 3228 3214 * So, new open will not use cached handle. 3229 3215 */ 3230 3216 3231 - if (!CIFS_CACHE_HANDLE(cinode) && !list_empty(&cinode->deferred_closes)) 3217 + if (!cache_handle && !list_empty(&cinode->deferred_closes)) 3232 3218 cifs_close_deferred_file(cinode); 3233 3219 3234 3220 persistent_fid = cfile->fid.persistent_fid; ··· 3246 3232 if (!oplock_break_cancelled && !list_empty(&cinode->openFileList)) { 3247 3233 spin_unlock(&cinode->open_file_lock); 3248 3234 rc = server->ops->oplock_response(tcon, persistent_fid, 3249 - volatile_fid, net_fid, cinode); 3235 + volatile_fid, net_fid, 3236 + cinode, oplock); 3250 3237 cifs_dbg(FYI, "Oplock release rc = %d\n", rc); 3251 3238 } else 3252 3239 spin_unlock(&cinode->open_file_lock);
+1 -3
fs/smb/client/fs_context.c
··· 825 825 if (ret < 0) 826 826 break; 827 827 } 828 - ret = smb3_handle_conflicting_options(fc); 829 - 830 - return ret; 828 + return ret ?: smb3_handle_conflicting_options(fc); 831 829 } 832 830 833 831 /*
+2 -1
fs/smb/client/nterr.c
··· 14 14 const struct nt_err_code_struct nt_errs[] = { 15 15 {"NT_STATUS_OK", NT_STATUS_OK}, 16 16 {"NT_STATUS_PENDING", NT_STATUS_PENDING}, 17 + {"NT_STATUS_NOTIFY_ENUM_DIR", NT_STATUS_NOTIFY_ENUM_DIR}, 17 18 {"NT_STATUS_MEDIA_CHANGED", NT_STATUS_MEDIA_CHANGED}, 18 19 {"NT_STATUS_END_OF_MEDIA", NT_STATUS_END_OF_MEDIA}, 19 20 {"NT_STATUS_MEDIA_CHECK", NT_STATUS_MEDIA_CHECK}, ··· 695 694 {"NT_STATUS_NETWORK_SESSION_EXPIRED", NT_STATUS_NETWORK_SESSION_EXPIRED}, 696 695 {"NT_STATUS_NO_MORE_ENTRIES", NT_STATUS_NO_MORE_ENTRIES}, 697 696 {"NT_STATUS_MORE_ENTRIES", NT_STATUS_MORE_ENTRIES}, 698 - {"NT_STATUS_SOME_UNMAPPED", NT_STATUS_SOME_UNMAPPED}, 697 + {"NT_STATUS_SOME_NOT_MAPPED", NT_STATUS_SOME_NOT_MAPPED}, 699 698 {"NT_STATUS_NO_SUCH_JOB", NT_STATUS_NO_SUCH_JOB}, 700 699 {"NT_STATUS_NO_PREAUTH_INTEGRITY_HASH_OVERLAP", 701 700 NT_STATUS_NO_PREAUTH_INTEGRITY_HASH_OVERLAP},
+6 -6
fs/smb/client/nterr.h
··· 22 22 23 23 extern const struct nt_err_code_struct nt_errs[]; 24 24 25 - /* Win32 Status codes. */ 26 - #define NT_STATUS_MORE_ENTRIES 0x0105 25 + /* Win32 Error Codes. */ 27 26 #define NT_ERROR_INVALID_PARAMETER 0x0057 28 27 #define NT_ERROR_INSUFFICIENT_BUFFER 0x007a 29 - #define NT_STATUS_1804 0x070c 30 - #define NT_STATUS_NOTIFY_ENUM_DIR 0x010c 28 + #define NT_ERROR_INVALID_DATATYPE 0x070c 31 29 32 30 /* 33 - * Win32 Error codes extracted using a loop in smbclient then printing a netmon 31 + * NTSTATUS Values extracted using a loop in smbclient then printing a netmon 34 32 * sniff to a file. 35 33 */ 36 34 37 35 #define NT_STATUS_OK 0x0000 38 36 #define NT_STATUS_PENDING 0x0103 39 - #define NT_STATUS_SOME_UNMAPPED 0x0107 37 + #define NT_STATUS_MORE_ENTRIES 0x0105 38 + #define NT_STATUS_SOME_NOT_MAPPED 0x0107 39 + #define NT_STATUS_NOTIFY_ENUM_DIR 0x010c 40 40 #define NT_STATUS_BUFFER_OVERFLOW 0x80000005 41 41 #define NT_STATUS_NO_MORE_ENTRIES 0x8000001a 42 42 #define NT_STATUS_MEDIA_CHANGED 0x8000001c
+4
fs/smb/client/smb1maperror.c
··· 112 112 __u32 ntstatus; 113 113 } ntstatus_to_dos_map[] = { 114 114 { 115 + ERRSRV, ERR_NOTIFY_ENUM_DIR, NT_STATUS_NOTIFY_ENUM_DIR}, { 116 + ERRDOS, ERRmoredata, NT_STATUS_BUFFER_OVERFLOW}, { 117 + ERRDOS, ERRmoredata, NT_STATUS_MORE_PROCESSING_REQUIRED}, { 118 + ERRDOS, ERRnoaccess, NT_STATUS_PRIVILEGE_NOT_HELD}, { 115 119 ERRDOS, ERRgeneral, NT_STATUS_UNSUCCESSFUL}, { 116 120 ERRDOS, ERRbadfunc, NT_STATUS_NOT_IMPLEMENTED}, { 117 121 ERRDOS, ERRbadpipe, NT_STATUS_INVALID_INFO_CLASS}, {
+12 -4
fs/smb/client/smb1ops.c
··· 395 395 struct cifsInodeInfo *cinode, __u32 oplock, 396 396 __u16 epoch, bool *purge_cache) 397 397 { 398 + lockdep_assert_held(&cinode->open_file_lock); 398 399 cifs_set_oplock_level(cinode, oplock); 399 400 } 400 401 ··· 895 894 cifs_set_fid(struct cifsFileInfo *cfile, struct cifs_fid *fid, __u32 oplock) 896 895 { 897 896 struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); 897 + 898 + lockdep_assert_held(&cinode->open_file_lock); 899 + 898 900 cfile->fid.netfid = fid->netfid; 899 901 cifs_set_oplock_level(cinode, oplock); 900 902 cinode->can_cache_brlcks = CIFS_CACHE_WRITE(cinode); ··· 1143 1139 return CIFSFindClose(xid, tcon, fid->netfid); 1144 1140 } 1145 1141 1146 - static int 1147 - cifs_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid, 1148 - __u64 volatile_fid, __u16 net_fid, struct cifsInodeInfo *cinode) 1142 + static int cifs_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid, 1143 + __u64 volatile_fid, __u16 net_fid, 1144 + struct cifsInodeInfo *cinode, unsigned int oplock) 1149 1145 { 1146 + unsigned int sbflags = CIFS_SB(cinode->netfs.inode.i_sb)->mnt_cifs_flags; 1147 + __u8 op; 1148 + 1149 + op = !!((oplock & CIFS_CACHE_READ_FLG) || (sbflags & CIFS_MOUNT_RO_CACHE)); 1150 1150 return CIFSSMBLock(0, tcon, net_fid, current->tgid, 0, 0, 0, 0, 1151 - LOCKING_ANDX_OPLOCK_RELEASE, false, CIFS_CACHE_READ(cinode) ? 1 : 0); 1151 + LOCKING_ANDX_OPLOCK_RELEASE, false, op); 1152 1152 } 1153 1153 1154 1154 static int
+8 -3
fs/smb/client/smb1transport.c
··· 29 29 #include "cifs_debug.h" 30 30 #include "smbdirect.h" 31 31 #include "compress.h" 32 - #include "cifs_debug.h" 33 32 34 33 /* Max number of iovectors we can use off the stack when sending requests. */ 35 34 #define CIFS_MAX_IOV_SIZE 8 ··· 169 170 170 171 iov[0].iov_base = mid->resp_buf; 171 172 iov[0].iov_len = len; 172 - /* FIXME: add code to kill session */ 173 + 173 174 rc = cifs_verify_signature(&rqst, server, 174 175 mid->sequence_number); 175 - if (rc) 176 + if (rc) { 176 177 cifs_server_dbg(VFS, "SMB signature verification returned error = %d\n", 177 178 rc); 179 + 180 + if (!(server->sec_mode & SECMODE_SIGN_REQUIRED)) { 181 + cifs_reconnect(server, true); 182 + return rc; 183 + } 184 + } 178 185 } 179 186 180 187 /* BB special case reconnect tid and uid here? */
+5 -5
fs/smb/client/smb2misc.c
··· 484 484 return to; 485 485 } 486 486 487 - __le32 488 - smb2_get_lease_state(struct cifsInodeInfo *cinode) 487 + __le32 smb2_get_lease_state(struct cifsInodeInfo *cinode, unsigned int oplock) 489 488 { 489 + unsigned int sbflags = CIFS_SB(cinode->netfs.inode.i_sb)->mnt_cifs_flags; 490 490 __le32 lease = 0; 491 491 492 - if (CIFS_CACHE_WRITE(cinode)) 492 + if ((oplock & CIFS_CACHE_WRITE_FLG) || (sbflags & CIFS_MOUNT_RW_CACHE)) 493 493 lease |= SMB2_LEASE_WRITE_CACHING_LE; 494 - if (CIFS_CACHE_HANDLE(cinode)) 494 + if (oplock & CIFS_CACHE_HANDLE_FLG) 495 495 lease |= SMB2_LEASE_HANDLE_CACHING_LE; 496 - if (CIFS_CACHE_READ(cinode)) 496 + if ((oplock & CIFS_CACHE_READ_FLG) || (sbflags & CIFS_MOUNT_RO_CACHE)) 497 497 lease |= SMB2_LEASE_READ_CACHING_LE; 498 498 return lease; 499 499 }
+28 -20
fs/smb/client/smb2ops.c
··· 1185 1185 1186 1186 replay_again: 1187 1187 /* reinitialize for possible replay */ 1188 + used_len = 0; 1188 1189 flags = CIFS_CP_CREATE_CLOSE_OP; 1189 1190 oplock = SMB2_OPLOCK_LEVEL_NONE; 1190 1191 server = cifs_pick_channel(ses); ··· 1461 1460 struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); 1462 1461 struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; 1463 1462 1463 + lockdep_assert_held(&cinode->open_file_lock); 1464 + 1464 1465 cfile->fid.persistent_fid = fid->persistent_fid; 1465 1466 cfile->fid.volatile_fid = fid->volatile_fid; 1466 1467 cfile->fid.access = fid->access; ··· 1589 1586 1590 1587 replay_again: 1591 1588 /* reinitialize for possible replay */ 1589 + buffer = NULL; 1592 1590 flags = CIFS_CP_CREATE_CLOSE_OP; 1593 1591 oplock = SMB2_OPLOCK_LEVEL_NONE; 1594 1592 server = cifs_pick_channel(ses); ··· 2688 2684 return false; 2689 2685 } 2690 2686 2691 - static int 2692 - smb2_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid, 2693 - __u64 volatile_fid, __u16 net_fid, struct cifsInodeInfo *cinode) 2687 + static int smb2_oplock_response(struct cifs_tcon *tcon, __u64 persistent_fid, 2688 + __u64 volatile_fid, __u16 net_fid, 2689 + struct cifsInodeInfo *cinode, unsigned int oplock) 2694 2690 { 2691 + unsigned int sbflags = CIFS_SB(cinode->netfs.inode.i_sb)->mnt_cifs_flags; 2692 + __u8 op; 2693 + 2695 2694 if (tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING) 2696 2695 return SMB2_lease_break(0, tcon, cinode->lease_key, 2697 - smb2_get_lease_state(cinode)); 2696 + smb2_get_lease_state(cinode, oplock)); 2698 2697 2699 - return SMB2_oplock_break(0, tcon, persistent_fid, volatile_fid, 2700 - CIFS_CACHE_READ(cinode) ? 1 : 0); 2698 + op = !!((oplock & CIFS_CACHE_READ_FLG) || (sbflags & CIFS_MOUNT_RO_CACHE)); 2699 + return SMB2_oplock_break(0, tcon, persistent_fid, volatile_fid, op); 2701 2700 } 2702 2701 2703 2702 void ··· 3183 3176 if (tcon && !tcon->ipc) { 3184 3177 /* ipc tcons are not refcounted */ 3185 3178 cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_dfs_refer); 3186 - trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count, 3187 - netfs_trace_tcon_ref_dec_dfs_refer); 3188 3179 } 3189 3180 kfree(utf16_path); 3190 3181 kfree(dfs_req); ··· 4058 4053 struct cifsInodeInfo *cinode, __u32 oplock, 4059 4054 __u16 epoch, bool *purge_cache) 4060 4055 { 4056 + lockdep_assert_held(&cinode->open_file_lock); 4061 4057 server->ops->set_oplock_level(cinode, oplock, 0, NULL); 4062 4058 } 4063 4059 ··· 4099 4093 if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE) 4100 4094 return; 4101 4095 if (oplock == SMB2_OPLOCK_LEVEL_BATCH) { 4102 - cinode->oplock = CIFS_CACHE_RHW_FLG; 4096 + WRITE_ONCE(cinode->oplock, CIFS_CACHE_RHW_FLG); 4103 4097 cifs_dbg(FYI, "Batch Oplock granted on inode %p\n", 4104 4098 &cinode->netfs.inode); 4105 4099 } else if (oplock == SMB2_OPLOCK_LEVEL_EXCLUSIVE) { 4106 - cinode->oplock = CIFS_CACHE_RW_FLG; 4100 + WRITE_ONCE(cinode->oplock, CIFS_CACHE_RW_FLG); 4107 4101 cifs_dbg(FYI, "Exclusive Oplock granted on inode %p\n", 4108 4102 &cinode->netfs.inode); 4109 4103 } else if (oplock == SMB2_OPLOCK_LEVEL_II) { 4110 - cinode->oplock = CIFS_CACHE_READ_FLG; 4104 + WRITE_ONCE(cinode->oplock, CIFS_CACHE_READ_FLG); 4111 4105 cifs_dbg(FYI, "Level II Oplock granted on inode %p\n", 4112 4106 &cinode->netfs.inode); 4113 4107 } else 4114 - cinode->oplock = 0; 4108 + WRITE_ONCE(cinode->oplock, 0); 4115 4109 } 4116 4110 4117 4111 static void ··· 4146 4140 if (!new_oplock) 4147 4141 strscpy(message, "None"); 4148 4142 4149 - cinode->oplock = new_oplock; 4143 + WRITE_ONCE(cinode->oplock, new_oplock); 4150 4144 cifs_dbg(FYI, "%s Lease granted on inode %p\n", message, 4151 4145 &cinode->netfs.inode); 4152 4146 } ··· 4155 4149 smb3_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, 4156 4150 __u16 epoch, bool *purge_cache) 4157 4151 { 4158 - unsigned int old_oplock = cinode->oplock; 4152 + unsigned int old_oplock = READ_ONCE(cinode->oplock); 4153 + unsigned int new_oplock; 4159 4154 4160 4155 smb21_set_oplock_level(cinode, oplock, epoch, purge_cache); 4156 + new_oplock = READ_ONCE(cinode->oplock); 4161 4157 4162 4158 if (purge_cache) { 4163 4159 *purge_cache = false; 4164 4160 if (old_oplock == CIFS_CACHE_READ_FLG) { 4165 - if (cinode->oplock == CIFS_CACHE_READ_FLG && 4161 + if (new_oplock == CIFS_CACHE_READ_FLG && 4166 4162 (epoch - cinode->epoch > 0)) 4167 4163 *purge_cache = true; 4168 - else if (cinode->oplock == CIFS_CACHE_RH_FLG && 4164 + else if (new_oplock == CIFS_CACHE_RH_FLG && 4169 4165 (epoch - cinode->epoch > 1)) 4170 4166 *purge_cache = true; 4171 - else if (cinode->oplock == CIFS_CACHE_RHW_FLG && 4167 + else if (new_oplock == CIFS_CACHE_RHW_FLG && 4172 4168 (epoch - cinode->epoch > 1)) 4173 4169 *purge_cache = true; 4174 - else if (cinode->oplock == 0 && 4170 + else if (new_oplock == 0 && 4175 4171 (epoch - cinode->epoch > 0)) 4176 4172 *purge_cache = true; 4177 4173 } else if (old_oplock == CIFS_CACHE_RH_FLG) { 4178 - if (cinode->oplock == CIFS_CACHE_RH_FLG && 4174 + if (new_oplock == CIFS_CACHE_RH_FLG && 4179 4175 (epoch - cinode->epoch > 0)) 4180 4176 *purge_cache = true; 4181 - else if (cinode->oplock == CIFS_CACHE_RHW_FLG && 4177 + else if (new_oplock == CIFS_CACHE_RHW_FLG && 4182 4178 (epoch - cinode->epoch > 1)) 4183 4179 *purge_cache = true; 4184 4180 }
+1
fs/smb/client/smb2pdu.c
··· 2908 2908 2909 2909 replay_again: 2910 2910 /* reinitialize for possible replay */ 2911 + pc_buf = NULL; 2911 2912 flags = 0; 2912 2913 n_iov = 2; 2913 2914 server = cifs_pick_channel(ses);
+1 -1
fs/smb/client/smb2proto.h
··· 42 42 struct smb_rqst *rqst); 43 43 struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server, 44 44 __u64 ses_id, __u32 tid); 45 - __le32 smb2_get_lease_state(struct cifsInodeInfo *cinode); 45 + __le32 smb2_get_lease_state(struct cifsInodeInfo *cinode, unsigned int oplock); 46 46 bool smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server); 47 47 int smb3_handle_read_data(struct TCP_Server_Info *server, 48 48 struct mid_q_entry *mid);
-1
fs/smb/client/trace.h
··· 168 168 E_(cifs_trace_rw_credits_zero_in_flight, "ZERO-IN-FLT") 169 169 170 170 #define smb3_tcon_ref_traces \ 171 - EM(netfs_trace_tcon_ref_dec_dfs_refer, "DEC DfsRef") \ 172 171 EM(netfs_trace_tcon_ref_free, "FRE ") \ 173 172 EM(netfs_trace_tcon_ref_free_fail, "FRE Fail ") \ 174 173 EM(netfs_trace_tcon_ref_free_ipc, "FRE Ipc ") \