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

Pull cifs fixes from Steve French:

- multichannel fixes, addressing additional reconnect and DFS scenarios

- reenabling fscache support (indexing rewrite, metadata caching e.g.)

- send additional version information during NTLMSSP negotiate to
improve debugging

- fix for a mount race

- DFS fixes

- fix for a memory leak for stable

* tag '5.17-rc-part2-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
cifs: update internal module number
smb3: send NTLMSSP version information
cifs: Support fscache indexing rewrite
cifs: cifs_ses_mark_for_reconnect should also update reconnect bits
cifs: update tcpStatus during negotiate and sess setup
cifs: make status checks in version independent callers
cifs: remove repeated state change in dfs tree connect
cifs: fix the cifs_reconnect path for DFS
cifs: remove unused variable ses_selected
cifs: protect all accesses to chan_* with chan_lock
cifs: fix the connection state transitions with multichannel
cifs: check reconnects for channels of active tcons too
smb3: add new defines from protocol specification
cifs: serialize all mount attempts
cifs: quirk for STATUS_OBJECT_NAME_INVALID returned for non-ASCII dfs refs
cifs: alloc_path_with_tree_prefix: do not append sep. if the path is empty
cifs: clean up an inconsistent indenting
cifs: free ntlmsspblob allocated in negotiate

+578 -631
+1 -1
fs/cifs/Kconfig
··· 188 188 189 189 config CIFS_FSCACHE 190 190 bool "Provide CIFS client caching support" 191 - depends on CIFS=m && FSCACHE_OLD_API || CIFS=y && FSCACHE_OLD_API=y 191 + depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y 192 192 help 193 193 Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data 194 194 to be cached locally on disk through the general filesystem cache
+1 -1
fs/cifs/Makefile
··· 25 25 26 26 cifs-$(CONFIG_CIFS_SWN_UPCALL) += netlink.o cifs_swn.o 27 27 28 - cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o cache.o 28 + cifs-$(CONFIG_CIFS_FSCACHE) += fscache.o 29 29 30 30 cifs-$(CONFIG_CIFS_SMB_DIRECT) += smbdirect.o 31 31
-105
fs/cifs/cache.c
··· 1 - // SPDX-License-Identifier: LGPL-2.1 2 - /* 3 - * CIFS filesystem cache index structure definitions 4 - * 5 - * Copyright (c) 2010 Novell, Inc. 6 - * Authors(s): Suresh Jayaraman (sjayaraman@suse.de> 7 - * 8 - */ 9 - #include "fscache.h" 10 - #include "cifs_debug.h" 11 - 12 - /* 13 - * CIFS filesystem definition for FS-Cache 14 - */ 15 - struct fscache_netfs cifs_fscache_netfs = { 16 - .name = "cifs", 17 - .version = 0, 18 - }; 19 - 20 - /* 21 - * Register CIFS for caching with FS-Cache 22 - */ 23 - int cifs_fscache_register(void) 24 - { 25 - return fscache_register_netfs(&cifs_fscache_netfs); 26 - } 27 - 28 - /* 29 - * Unregister CIFS for caching 30 - */ 31 - void cifs_fscache_unregister(void) 32 - { 33 - fscache_unregister_netfs(&cifs_fscache_netfs); 34 - } 35 - 36 - /* 37 - * Server object for FS-Cache 38 - */ 39 - const struct fscache_cookie_def cifs_fscache_server_index_def = { 40 - .name = "CIFS.server", 41 - .type = FSCACHE_COOKIE_TYPE_INDEX, 42 - }; 43 - 44 - static enum 45 - fscache_checkaux cifs_fscache_super_check_aux(void *cookie_netfs_data, 46 - const void *data, 47 - uint16_t datalen, 48 - loff_t object_size) 49 - { 50 - struct cifs_fscache_super_auxdata auxdata; 51 - const struct cifs_tcon *tcon = cookie_netfs_data; 52 - 53 - if (datalen != sizeof(auxdata)) 54 - return FSCACHE_CHECKAUX_OBSOLETE; 55 - 56 - memset(&auxdata, 0, sizeof(auxdata)); 57 - auxdata.resource_id = tcon->resource_id; 58 - auxdata.vol_create_time = tcon->vol_create_time; 59 - auxdata.vol_serial_number = tcon->vol_serial_number; 60 - 61 - if (memcmp(data, &auxdata, datalen) != 0) 62 - return FSCACHE_CHECKAUX_OBSOLETE; 63 - 64 - return FSCACHE_CHECKAUX_OKAY; 65 - } 66 - 67 - /* 68 - * Superblock object for FS-Cache 69 - */ 70 - const struct fscache_cookie_def cifs_fscache_super_index_def = { 71 - .name = "CIFS.super", 72 - .type = FSCACHE_COOKIE_TYPE_INDEX, 73 - .check_aux = cifs_fscache_super_check_aux, 74 - }; 75 - 76 - static enum 77 - fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data, 78 - const void *data, 79 - uint16_t datalen, 80 - loff_t object_size) 81 - { 82 - struct cifs_fscache_inode_auxdata auxdata; 83 - struct cifsInodeInfo *cifsi = cookie_netfs_data; 84 - 85 - if (datalen != sizeof(auxdata)) 86 - return FSCACHE_CHECKAUX_OBSOLETE; 87 - 88 - memset(&auxdata, 0, sizeof(auxdata)); 89 - auxdata.eof = cifsi->server_eof; 90 - auxdata.last_write_time_sec = cifsi->vfs_inode.i_mtime.tv_sec; 91 - auxdata.last_change_time_sec = cifsi->vfs_inode.i_ctime.tv_sec; 92 - auxdata.last_write_time_nsec = cifsi->vfs_inode.i_mtime.tv_nsec; 93 - auxdata.last_change_time_nsec = cifsi->vfs_inode.i_ctime.tv_nsec; 94 - 95 - if (memcmp(data, &auxdata, datalen) != 0) 96 - return FSCACHE_CHECKAUX_OBSOLETE; 97 - 98 - return FSCACHE_CHECKAUX_OKAY; 99 - } 100 - 101 - const struct fscache_cookie_def cifs_fscache_inode_object_def = { 102 - .name = "CIFS.uniqueid", 103 - .type = FSCACHE_COOKIE_TYPE_DATAFILE, 104 - .check_aux = cifs_fscache_inode_check_aux, 105 - };
+3 -6
fs/cifs/cifs_swn.c
··· 396 396 switch (state) { 397 397 case CIFS_SWN_RESOURCE_STATE_UNAVAILABLE: 398 398 cifs_dbg(FYI, "%s: resource name '%s' become unavailable\n", __func__, name); 399 - cifs_ses_mark_for_reconnect(swnreg->tcon->ses); 399 + cifs_reconnect(swnreg->tcon->ses->server, true); 400 400 break; 401 401 case CIFS_SWN_RESOURCE_STATE_AVAILABLE: 402 402 cifs_dbg(FYI, "%s: resource name '%s' become available\n", __func__, name); 403 - cifs_ses_mark_for_reconnect(swnreg->tcon->ses); 403 + cifs_reconnect(swnreg->tcon->ses->server, true); 404 404 break; 405 405 case CIFS_SWN_RESOURCE_STATE_UNKNOWN: 406 406 cifs_dbg(FYI, "%s: resource name '%s' changed to unknown state\n", __func__, name); ··· 498 498 goto unlock; 499 499 } 500 500 501 - spin_lock(&cifs_tcp_ses_lock); 502 - if (tcon->ses->server->tcpStatus != CifsExiting) 503 - tcon->ses->server->tcpStatus = CifsNeedReconnect; 504 - spin_unlock(&cifs_tcp_ses_lock); 501 + cifs_reconnect(tcon->ses->server, false); 505 502 506 503 unlock: 507 504 mutex_unlock(&tcon->ses->server->srv_mutex);
+11 -8
fs/cifs/cifsfs.c
··· 397 397 cifs_evict_inode(struct inode *inode) 398 398 { 399 399 truncate_inode_pages_final(&inode->i_data); 400 + if (inode->i_state & I_PINNING_FSCACHE_WB) 401 + cifs_fscache_unuse_inode_cookie(inode, true); 402 + cifs_fscache_release_inode_cookie(inode); 400 403 clear_inode(inode); 401 404 } 402 405 ··· 724 721 } 725 722 #endif 726 723 724 + static int cifs_write_inode(struct inode *inode, struct writeback_control *wbc) 725 + { 726 + fscache_unpin_writeback(wbc, cifs_inode_cookie(inode)); 727 + return 0; 728 + } 729 + 727 730 static int cifs_drop_inode(struct inode *inode) 728 731 { 729 732 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); ··· 742 733 static const struct super_operations cifs_super_ops = { 743 734 .statfs = cifs_statfs, 744 735 .alloc_inode = cifs_alloc_inode, 736 + .write_inode = cifs_write_inode, 745 737 .free_inode = cifs_free_inode, 746 738 .drop_inode = cifs_drop_inode, 747 739 .evict_inode = cifs_evict_inode, ··· 1635 1625 goto out_destroy_cifsoplockd_wq; 1636 1626 } 1637 1627 1638 - rc = cifs_fscache_register(); 1639 - if (rc) 1640 - goto out_destroy_deferredclose_wq; 1641 - 1642 1628 rc = cifs_init_inodecache(); 1643 1629 if (rc) 1644 - goto out_unreg_fscache; 1630 + goto out_destroy_deferredclose_wq; 1645 1631 1646 1632 rc = cifs_init_mids(); 1647 1633 if (rc) ··· 1699 1693 cifs_destroy_mids(); 1700 1694 out_destroy_inodecache: 1701 1695 cifs_destroy_inodecache(); 1702 - out_unreg_fscache: 1703 - cifs_fscache_unregister(); 1704 1696 out_destroy_deferredclose_wq: 1705 1697 destroy_workqueue(deferredclose_wq); 1706 1698 out_destroy_cifsoplockd_wq: ··· 1734 1730 cifs_destroy_request_bufs(); 1735 1731 cifs_destroy_mids(); 1736 1732 cifs_destroy_inodecache(); 1737 - cifs_fscache_unregister(); 1738 1733 destroy_workqueue(deferredclose_wq); 1739 1734 destroy_workqueue(cifsoplockd_wq); 1740 1735 destroy_workqueue(decrypt_wq);
+2 -1
fs/cifs/cifsfs.h
··· 152 152 extern const struct export_operations cifs_export_ops; 153 153 #endif /* CONFIG_CIFS_NFSD_EXPORT */ 154 154 155 - #define CIFS_VERSION "2.34" 155 + #define SMB3_PRODUCT_BUILD 35 156 + #define CIFS_VERSION "2.35" 156 157 #endif /* _CIFSFS_H */
+3 -4
fs/cifs/cifsglob.h
··· 117 117 CifsInSessSetup, 118 118 CifsNeedTcon, 119 119 CifsInTcon, 120 + CifsNeedFilesInvalidate, 120 121 CifsInFilesInvalidate 121 122 }; 122 123 ··· 668 667 unsigned int total_read; /* total amount of data read in this pass */ 669 668 atomic_t in_send; /* requests trying to send */ 670 669 atomic_t num_waiters; /* blocked waiting to get in sendrecv */ 671 - #ifdef CONFIG_CIFS_FSCACHE 672 - struct fscache_cookie *fscache; /* client index cache cookie */ 673 - #endif 674 670 #ifdef CONFIG_CIFS_STATS2 675 671 atomic_t num_cmds[NUMBER_OF_SMB2_COMMANDS]; /* total requests by cmd */ 676 672 atomic_t smb2slowcmd[NUMBER_OF_SMB2_COMMANDS]; /* count resps > 1 sec */ ··· 921 923 */ 922 924 struct cifs_ses { 923 925 struct list_head smb_ses_list; 926 + struct list_head rlist; /* reconnect list */ 924 927 struct list_head tcon_list; 925 928 struct cifs_tcon *tcon_ipc; 926 929 struct mutex session_mutex; ··· 1109 1110 __u32 max_bytes_copy; 1110 1111 #ifdef CONFIG_CIFS_FSCACHE 1111 1112 u64 resource_id; /* server resource id */ 1112 - struct fscache_cookie *fscache; /* cookie for share */ 1113 + struct fscache_volume *fscache; /* cookie for share */ 1113 1114 #endif 1114 1115 struct list_head pending_opens; /* list of incomplete opens */ 1115 1116 struct cached_fid crfid; /* Cached root fid */
+8
fs/cifs/cifsproto.h
··· 131 131 struct smb_hdr *in_buf , 132 132 struct smb_hdr *out_buf, 133 133 int *bytes_returned); 134 + void 135 + cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server, 136 + bool mark_smb_session); 134 137 extern int cifs_reconnect(struct TCP_Server_Info *server, 135 138 bool mark_smb_session); 136 139 extern int checkSMB(char *buf, unsigned int len, struct TCP_Server_Info *srvr); ··· 650 647 int match_target_ip(struct TCP_Server_Info *server, 651 648 const char *share, size_t share_len, 652 649 bool *result); 650 + 651 + int cifs_dfs_query_info_nonascii_quirk(const unsigned int xid, 652 + struct cifs_tcon *tcon, 653 + struct cifs_sb_info *cifs_sb, 654 + const char *dfs_link_path); 653 655 #endif 654 656 655 657 static inline int cifs_create_options(struct cifs_sb_info *cifs_sb, int options)
+95 -47
fs/cifs/connect.c
··· 168 168 * @server needs to be previously set to CifsNeedReconnect. 169 169 * 170 170 */ 171 - static void 171 + void 172 172 cifs_mark_tcp_ses_conns_for_reconnect(struct TCP_Server_Info *server, 173 173 bool mark_smb_session) 174 174 { ··· 181 181 server->maxBuf = 0; 182 182 server->max_read = 0; 183 183 184 - cifs_dbg(FYI, "Mark tcp session as need reconnect\n"); 185 - trace_smb3_reconnect(server->CurrentMid, server->conn_id, server->hostname); 186 184 /* 187 185 * before reconnecting the tcp session, mark the smb session (uid) and the tid bad so they 188 186 * are not used until reconnected. 189 187 */ 190 - cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect\n", __func__); 188 + cifs_dbg(FYI, "%s: marking necessary sessions and tcons for reconnect\n", __func__); 191 189 192 190 /* If server is a channel, select the primary channel */ 193 191 pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server; 192 + 194 193 195 194 spin_lock(&cifs_tcp_ses_lock); 196 195 list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { ··· 197 198 if (!mark_smb_session && cifs_chan_needs_reconnect(ses, server)) 198 199 goto next_session; 199 200 200 - cifs_chan_set_need_reconnect(ses, server); 201 + if (mark_smb_session) 202 + CIFS_SET_ALL_CHANS_NEED_RECONNECT(ses); 203 + else 204 + cifs_chan_set_need_reconnect(ses, server); 201 205 202 206 /* If all channels need reconnect, then tcon needs reconnect */ 203 207 if (!mark_smb_session && !CIFS_ALL_CHANS_NEED_RECONNECT(ses)) ··· 220 218 } 221 219 spin_unlock(&cifs_tcp_ses_lock); 222 220 223 - /* 224 - * before reconnecting the tcp session, mark the smb session (uid) 225 - * and the tid bad so they are not used until reconnected 226 - */ 227 - cifs_dbg(FYI, "%s: marking sessions and tcons for reconnect and tearing down socket\n", 228 - __func__); 229 221 /* do not want to be sending data on a socket we are freeing */ 222 + cifs_dbg(FYI, "%s: tearing down socket\n", __func__); 230 223 mutex_lock(&server->srv_mutex); 231 224 if (server->ssocket) { 232 225 cifs_dbg(FYI, "State: 0x%x Flags: 0x%lx\n", server->ssocket->state, ··· 277 280 wake_up(&server->response_q); 278 281 return false; 279 282 } 283 + 284 + cifs_dbg(FYI, "Mark tcp session as need reconnect\n"); 285 + trace_smb3_reconnect(server->CurrentMid, server->conn_id, 286 + server->hostname); 280 287 server->tcpStatus = CifsNeedReconnect; 288 + 281 289 spin_unlock(&cifs_tcp_ses_lock); 282 290 return true; 283 291 } ··· 337 335 spin_unlock(&cifs_tcp_ses_lock); 338 336 cifs_swn_reset_server_dstaddr(server); 339 337 mutex_unlock(&server->srv_mutex); 338 + mod_delayed_work(cifsiod_wq, &server->reconnect, 0); 340 339 } 341 340 } while (server->tcpStatus == CifsNeedReconnect); 342 341 342 + spin_lock(&cifs_tcp_ses_lock); 343 343 if (server->tcpStatus == CifsNeedNegotiate) 344 344 mod_delayed_work(cifsiod_wq, &server->echo, 0); 345 + spin_unlock(&cifs_tcp_ses_lock); 345 346 346 347 wake_up(&server->response_q); 347 348 return rc; ··· 459 454 spin_unlock(&cifs_tcp_ses_lock); 460 455 cifs_swn_reset_server_dstaddr(server); 461 456 mutex_unlock(&server->srv_mutex); 457 + mod_delayed_work(cifsiod_wq, &server->reconnect, 0); 462 458 } while (server->tcpStatus == CifsNeedReconnect); 463 459 464 460 if (target_hint) ··· 639 633 640 634 if (server->tcpStatus == CifsNeedReconnect) { 641 635 spin_unlock(&cifs_tcp_ses_lock); 642 - cifs_reconnect(server, false); 643 636 return -ECONNABORTED; 644 637 } 645 638 spin_unlock(&cifs_tcp_ses_lock); ··· 1444 1439 1445 1440 cifs_crypto_secmech_release(server); 1446 1441 1447 - /* fscache server cookies are based on primary channel only */ 1448 - if (!CIFS_SERVER_IS_CHAN(server)) 1449 - cifs_fscache_release_client_cookie(server); 1450 - 1451 1442 kfree(server->session_key.response); 1452 1443 server->session_key.response = NULL; 1453 1444 server->session_key.len = 0; ··· 1604 1603 spin_lock(&cifs_tcp_ses_lock); 1605 1604 list_add(&tcp_ses->tcp_ses_list, &cifs_tcp_ses_list); 1606 1605 spin_unlock(&cifs_tcp_ses_lock); 1607 - 1608 - /* fscache server cookies are based on primary channel only */ 1609 - if (!CIFS_SERVER_IS_CHAN(tcp_ses)) 1610 - cifs_fscache_get_client_cookie(tcp_ses); 1611 - #ifdef CONFIG_CIFS_FSCACHE 1612 - else 1613 - tcp_ses->fscache = tcp_ses->primary_server->fscache; 1614 - #endif /* CONFIG_CIFS_FSCACHE */ 1615 1606 1616 1607 /* queue echo request delayed work */ 1617 1608 queue_delayed_work(cifsiod_wq, &tcp_ses->echo, tcp_ses->echo_interval); ··· 1825 1832 1826 1833 spin_lock(&ses->chan_lock); 1827 1834 chan_count = ses->chan_count; 1828 - spin_unlock(&ses->chan_lock); 1829 1835 1830 1836 /* close any extra channels */ 1831 1837 if (chan_count > 1) { ··· 1841 1849 ses->chans[i].server = NULL; 1842 1850 } 1843 1851 } 1852 + spin_unlock(&ses->chan_lock); 1844 1853 1845 1854 sesInfoFree(ses); 1846 1855 cifs_put_tcp_session(server, 0); ··· 2117 2124 mutex_unlock(&ses->session_mutex); 2118 2125 2119 2126 /* each channel uses a different signing key */ 2127 + spin_lock(&ses->chan_lock); 2120 2128 memcpy(ses->chans[0].signkey, ses->smb3signingkey, 2121 2129 sizeof(ses->smb3signingkey)); 2130 + spin_unlock(&ses->chan_lock); 2122 2131 2123 2132 if (rc) 2124 2133 goto get_ses_fail; ··· 3116 3121 * Inside cifs_fscache_get_super_cookie it checks 3117 3122 * that we do not get super cookie twice. 3118 3123 */ 3119 - cifs_fscache_get_super_cookie(tcon); 3124 + if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) 3125 + cifs_fscache_get_super_cookie(tcon); 3120 3126 3121 3127 out: 3122 3128 mnt_ctx->server = server; ··· 3370 3374 3371 3375 rc = server->ops->is_path_accessible(xid, tcon, cifs_sb, 3372 3376 full_path); 3377 + #ifdef CONFIG_CIFS_DFS_UPCALL 3378 + if (rc == -ENOENT && is_tcon_dfs(tcon)) 3379 + rc = cifs_dfs_query_info_nonascii_quirk(xid, tcon, cifs_sb, 3380 + full_path); 3381 + #endif 3373 3382 if (rc != 0 && rc != -EREMOTE) { 3374 3383 kfree(full_path); 3375 3384 return rc; ··· 3762 3761 if (rc == 0) { 3763 3762 bool is_unicode; 3764 3763 3765 - spin_lock(&cifs_tcp_ses_lock); 3766 - tcon->tidStatus = CifsGood; 3767 - spin_unlock(&cifs_tcp_ses_lock); 3768 - tcon->need_reconnect = false; 3769 3764 tcon->tid = smb_buffer_response->Tid; 3770 3765 bcc_ptr = pByteArea(smb_buffer_response); 3771 3766 bytes_left = get_bcc(smb_buffer_response); ··· 3876 3879 else 3877 3880 rc = -EHOSTDOWN; 3878 3881 spin_unlock(&cifs_tcp_ses_lock); 3882 + } else { 3883 + spin_lock(&cifs_tcp_ses_lock); 3884 + if (server->tcpStatus == CifsInNegotiate) 3885 + server->tcpStatus = CifsNeedNegotiate; 3886 + spin_unlock(&cifs_tcp_ses_lock); 3879 3887 } 3880 3888 3881 3889 return rc; ··· 3900 3898 spin_unlock(&cifs_tcp_ses_lock); 3901 3899 return 0; 3902 3900 } 3903 - ses->status = CifsInSessSetup; 3901 + server->tcpStatus = CifsInSessSetup; 3904 3902 spin_unlock(&cifs_tcp_ses_lock); 3905 3903 3906 3904 spin_lock(&ses->chan_lock); ··· 3927 3925 if (server->ops->sess_setup) 3928 3926 rc = server->ops->sess_setup(xid, ses, server, nls_info); 3929 3927 3930 - if (rc) 3928 + if (rc) { 3931 3929 cifs_server_dbg(VFS, "Send error in SessSetup = %d\n", rc); 3930 + spin_lock(&cifs_tcp_ses_lock); 3931 + if (server->tcpStatus == CifsInSessSetup) 3932 + server->tcpStatus = CifsNeedSessSetup; 3933 + spin_unlock(&cifs_tcp_ses_lock); 3934 + } else { 3935 + spin_lock(&cifs_tcp_ses_lock); 3936 + if (server->tcpStatus == CifsInSessSetup) 3937 + server->tcpStatus = CifsGood; 3938 + /* Even if one channel is active, session is in good state */ 3939 + ses->status = CifsGood; 3940 + spin_unlock(&cifs_tcp_ses_lock); 3941 + 3942 + spin_lock(&ses->chan_lock); 3943 + cifs_chan_clear_need_reconnect(ses, server); 3944 + spin_unlock(&ses->chan_lock); 3945 + } 3932 3946 3933 3947 return rc; 3934 3948 } ··· 4289 4271 struct dfs_cache_tgt_iterator *tit; 4290 4272 bool target_match; 4291 4273 4292 - /* only send once per connect */ 4293 - spin_lock(&cifs_tcp_ses_lock); 4294 - if (tcon->ses->status != CifsGood || 4295 - (tcon->tidStatus != CifsNew && 4296 - tcon->tidStatus != CifsNeedTcon)) { 4297 - spin_unlock(&cifs_tcp_ses_lock); 4298 - return 0; 4299 - } 4300 - tcon->tidStatus = CifsInTcon; 4301 - spin_unlock(&cifs_tcp_ses_lock); 4302 - 4303 4274 extract_unc_hostname(server->hostname, &tcp_host, &tcp_host_len); 4304 4275 4305 4276 tit = dfs_cache_get_tgt_iterator(tl); ··· 4388 4381 */ 4389 4382 if (rc && server->current_fullpath != server->origin_fullpath) { 4390 4383 server->current_fullpath = server->origin_fullpath; 4391 - cifs_ses_mark_for_reconnect(tcon->ses); 4384 + cifs_reconnect(tcon->ses->server, true); 4392 4385 } 4393 4386 4394 4387 dfs_cache_free_tgts(tl); ··· 4406 4399 char *tree; 4407 4400 struct dfs_info3_param ref = {0}; 4408 4401 4402 + /* only send once per connect */ 4403 + spin_lock(&cifs_tcp_ses_lock); 4404 + if (tcon->ses->status != CifsGood || 4405 + (tcon->tidStatus != CifsNew && 4406 + tcon->tidStatus != CifsNeedTcon)) { 4407 + spin_unlock(&cifs_tcp_ses_lock); 4408 + return 0; 4409 + } 4410 + tcon->tidStatus = CifsInTcon; 4411 + spin_unlock(&cifs_tcp_ses_lock); 4412 + 4409 4413 tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL); 4410 - if (!tree) 4411 - return -ENOMEM; 4414 + if (!tree) { 4415 + rc = -ENOMEM; 4416 + goto out; 4417 + } 4412 4418 4413 4419 if (tcon->ipc) { 4414 4420 scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname); ··· 4453 4433 kfree(tree); 4454 4434 cifs_put_tcp_super(sb); 4455 4435 4436 + if (rc) { 4437 + spin_lock(&cifs_tcp_ses_lock); 4438 + if (tcon->tidStatus == CifsInTcon) 4439 + tcon->tidStatus = CifsNeedTcon; 4440 + spin_unlock(&cifs_tcp_ses_lock); 4441 + } else { 4442 + spin_lock(&cifs_tcp_ses_lock); 4443 + if (tcon->tidStatus == CifsInTcon) 4444 + tcon->tidStatus = CifsGood; 4445 + spin_unlock(&cifs_tcp_ses_lock); 4446 + tcon->need_reconnect = false; 4447 + } 4448 + 4456 4449 return rc; 4457 4450 } 4458 4451 #else 4459 4452 int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc) 4460 4453 { 4454 + int rc; 4461 4455 const struct smb_version_operations *ops = tcon->ses->server->ops; 4462 4456 4463 4457 /* only send once per connect */ ··· 4485 4451 tcon->tidStatus = CifsInTcon; 4486 4452 spin_unlock(&cifs_tcp_ses_lock); 4487 4453 4488 - return ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc); 4454 + rc = ops->tree_connect(xid, tcon->ses, tcon->treeName, tcon, nlsc); 4455 + if (rc) { 4456 + spin_lock(&cifs_tcp_ses_lock); 4457 + if (tcon->tidStatus == CifsInTcon) 4458 + tcon->tidStatus = CifsNeedTcon; 4459 + spin_unlock(&cifs_tcp_ses_lock); 4460 + } else { 4461 + spin_lock(&cifs_tcp_ses_lock); 4462 + if (tcon->tidStatus == CifsInTcon) 4463 + tcon->tidStatus = CifsGood; 4464 + spin_unlock(&cifs_tcp_ses_lock); 4465 + tcon->need_reconnect = false; 4466 + } 4467 + 4468 + return rc; 4489 4469 } 4490 4470 #endif
+1 -1
fs/cifs/dfs_cache.c
··· 1355 1355 } 1356 1356 1357 1357 cifs_dbg(FYI, "%s: no cached or matched targets. mark dfs share for reconnect.\n", __func__); 1358 - cifs_ses_mark_for_reconnect(tcon->ses); 1358 + cifs_reconnect(tcon->ses->server, true); 1359 1359 } 1360 1360 1361 1361 /* Refresh dfs referral of tcon and mark it for reconnect if needed */
+5
fs/cifs/dir.c
··· 22 22 #include "cifs_unicode.h" 23 23 #include "fs_context.h" 24 24 #include "cifs_ioctl.h" 25 + #include "fscache.h" 25 26 26 27 static void 27 28 renew_parental_timestamps(struct dentry *direntry) ··· 508 507 server->ops->close(xid, tcon, &fid); 509 508 cifs_del_pending_open(&open); 510 509 rc = -ENOMEM; 510 + goto out; 511 511 } 512 + 513 + fscache_use_cookie(cifs_inode_cookie(file_inode(file)), 514 + file->f_mode & FMODE_WRITE); 512 515 513 516 out: 514 517 cifs_put_tlink(tlink);
+41 -25
fs/cifs/file.c
··· 376 376 struct cifsLockInfo *li, *tmp; 377 377 struct super_block *sb = inode->i_sb; 378 378 379 - cifs_fscache_release_inode_cookie(inode); 380 - 381 379 /* 382 380 * Delete any outstanding lock records. We'll lose them when the file 383 381 * is closed anyway. ··· 568 570 spin_lock(&CIFS_I(inode)->deferred_lock); 569 571 cifs_del_deferred_close(cfile); 570 572 spin_unlock(&CIFS_I(inode)->deferred_lock); 571 - goto out; 573 + goto use_cache; 572 574 } else { 573 575 _cifsFileInfo_put(cfile, true, false); 574 576 } ··· 630 632 goto out; 631 633 } 632 634 633 - cifs_fscache_set_inode_cookie(inode, file); 634 - 635 635 if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) { 636 636 /* 637 637 * Time to set mode which we can not set earlier due to ··· 647 651 CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid.netfid, 648 652 cfile->pid); 649 653 } 654 + 655 + use_cache: 656 + fscache_use_cookie(cifs_inode_cookie(file_inode(file)), 657 + file->f_mode & FMODE_WRITE); 658 + if (file->f_flags & O_DIRECT && 659 + (!((file->f_flags & O_ACCMODE) != O_RDONLY) || 660 + file->f_flags & O_APPEND)) 661 + cifs_invalidate_cache(file_inode(file), 662 + FSCACHE_INVAL_DIO_WRITE); 650 663 651 664 out: 652 665 free_dentry_path(page); ··· 881 876 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 882 877 struct cifs_deferred_close *dclose; 883 878 879 + cifs_fscache_unuse_inode_cookie(inode, file->f_mode & FMODE_WRITE); 880 + 884 881 if (file->private_data != NULL) { 885 882 cfile = file->private_data; 886 883 file->private_data = NULL; ··· 893 886 dclose) { 894 887 if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) { 895 888 inode->i_ctime = inode->i_mtime = current_time(inode); 896 - cifs_fscache_update_inode_cookie(inode); 897 889 } 898 890 spin_lock(&cinode->deferred_lock); 899 891 cifs_add_deferred_close(cfile, dclose); ··· 4204 4198 cifs_page_mkwrite(struct vm_fault *vmf) 4205 4199 { 4206 4200 struct page *page = vmf->page; 4207 - struct file *file = vmf->vma->vm_file; 4208 - struct inode *inode = file_inode(file); 4209 4201 4210 - cifs_fscache_wait_on_page_write(inode, page); 4202 + #ifdef CONFIG_CIFS_FSCACHE 4203 + if (PageFsCache(page) && 4204 + wait_on_page_fscache_killable(page) < 0) 4205 + return VM_FAULT_RETRY; 4206 + #endif 4211 4207 4212 4208 lock_page(page); 4213 4209 return VM_FAULT_LOCKED; ··· 4283 4275 if (rdata->result == 0 || 4284 4276 (rdata->result == -EAGAIN && got_bytes)) 4285 4277 cifs_readpage_to_fscache(rdata->mapping->host, page); 4286 - else 4287 - cifs_fscache_uncache_page(rdata->mapping->host, page); 4288 4278 4289 4279 got_bytes -= min_t(unsigned int, PAGE_SIZE, got_bytes); 4290 4280 ··· 4599 4593 kref_put(&rdata->refcount, cifs_readdata_release); 4600 4594 } 4601 4595 4602 - /* Any pages that have been shown to fscache but didn't get added to 4603 - * the pagecache must be uncached before they get returned to the 4604 - * allocator. 4605 - */ 4606 - cifs_fscache_readpages_cancel(mapping->host, page_list); 4607 4596 free_xid(xid); 4608 4597 return rc; 4609 4598 } ··· 4802 4801 { 4803 4802 if (PagePrivate(page)) 4804 4803 return 0; 4805 - 4806 - return cifs_fscache_release_page(page, gfp); 4804 + if (PageFsCache(page)) { 4805 + if (current_is_kswapd() || !(gfp & __GFP_FS)) 4806 + return false; 4807 + wait_on_page_fscache(page); 4808 + } 4809 + fscache_note_page_release(cifs_inode_cookie(page->mapping->host)); 4810 + return true; 4807 4811 } 4808 4812 4809 4813 static void cifs_invalidate_page(struct page *page, unsigned int offset, 4810 4814 unsigned int length) 4811 4815 { 4812 - struct cifsInodeInfo *cifsi = CIFS_I(page->mapping->host); 4813 - 4814 - if (offset == 0 && length == PAGE_SIZE) 4815 - cifs_fscache_invalidate_page(page, &cifsi->vfs_inode); 4816 + wait_on_page_fscache(page); 4816 4817 } 4817 4818 4818 4819 static int cifs_launder_page(struct page *page) ··· 4834 4831 if (clear_page_dirty_for_io(page)) 4835 4832 rc = cifs_writepage_locked(page, &wbc); 4836 4833 4837 - cifs_fscache_invalidate_page(page, page->mapping->host); 4834 + wait_on_page_fscache(page); 4838 4835 return rc; 4839 4836 } 4840 4837 ··· 4991 4988 /* do we need to unpin (or unlock) the file */ 4992 4989 } 4993 4990 4991 + /* 4992 + * Mark a page as having been made dirty and thus needing writeback. We also 4993 + * need to pin the cache object to write back to. 4994 + */ 4995 + #ifdef CONFIG_CIFS_FSCACHE 4996 + static int cifs_set_page_dirty(struct page *page) 4997 + { 4998 + return fscache_set_page_dirty(page, cifs_inode_cookie(page->mapping->host)); 4999 + } 5000 + #else 5001 + #define cifs_set_page_dirty __set_page_dirty_nobuffers 5002 + #endif 5003 + 4994 5004 const struct address_space_operations cifs_addr_ops = { 4995 5005 .readpage = cifs_readpage, 4996 5006 .readpages = cifs_readpages, ··· 5011 4995 .writepages = cifs_writepages, 5012 4996 .write_begin = cifs_write_begin, 5013 4997 .write_end = cifs_write_end, 5014 - .set_page_dirty = __set_page_dirty_nobuffers, 4998 + .set_page_dirty = cifs_set_page_dirty, 5015 4999 .releasepage = cifs_release_page, 5016 5000 .direct_IO = cifs_direct_io, 5017 5001 .invalidatepage = cifs_invalidate_page, ··· 5036 5020 .writepages = cifs_writepages, 5037 5021 .write_begin = cifs_write_begin, 5038 5022 .write_end = cifs_write_end, 5039 - .set_page_dirty = __set_page_dirty_nobuffers, 5023 + .set_page_dirty = cifs_set_page_dirty, 5040 5024 .releasepage = cifs_release_page, 5041 5025 .invalidatepage = cifs_invalidate_page, 5042 5026 .launder_page = cifs_launder_page,
+7 -1
fs/cifs/fs_context.c
··· 37 37 #include "rfc1002pdu.h" 38 38 #include "fs_context.h" 39 39 40 + static DEFINE_MUTEX(cifs_mount_mutex); 41 + 40 42 static const match_table_t cifs_smb_version_tokens = { 41 43 { Smb_1, SMB1_VERSION_STRING }, 42 44 { Smb_20, SMB20_VERSION_STRING}, ··· 709 707 static int smb3_get_tree(struct fs_context *fc) 710 708 { 711 709 int err = smb3_fs_context_validate(fc); 710 + int ret; 712 711 713 712 if (err) 714 713 return err; 715 - return smb3_get_tree_common(fc); 714 + mutex_lock(&cifs_mount_mutex); 715 + ret = smb3_get_tree_common(fc); 716 + mutex_unlock(&cifs_mount_mutex); 717 + return ret; 716 718 } 717 719 718 720 static void smb3_fs_context_free(struct fs_context *fc)
+84 -257
fs/cifs/fscache.c
··· 12 12 #include "cifs_fs_sb.h" 13 13 #include "cifsproto.h" 14 14 15 - /* 16 - * Key layout of CIFS server cache index object 17 - */ 18 - struct cifs_server_key { 19 - __u64 conn_id; 20 - } __packed; 21 - 22 - /* 23 - * Get a cookie for a server object keyed by {IPaddress,port,family} tuple 24 - */ 25 - void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) 15 + static void cifs_fscache_fill_volume_coherency( 16 + struct cifs_tcon *tcon, 17 + struct cifs_fscache_volume_coherency_data *cd) 26 18 { 27 - struct cifs_server_key key; 19 + memset(cd, 0, sizeof(*cd)); 20 + cd->resource_id = cpu_to_le64(tcon->resource_id); 21 + cd->vol_create_time = tcon->vol_create_time; 22 + cd->vol_serial_number = cpu_to_le32(tcon->vol_serial_number); 23 + } 28 24 29 - /* 30 - * Check if cookie was already initialized so don't reinitialize it. 31 - * In the future, as we integrate with newer fscache features, 32 - * we may want to instead add a check if cookie has changed 33 - */ 34 - if (server->fscache) 35 - return; 25 + int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) 26 + { 27 + struct cifs_fscache_volume_coherency_data cd; 28 + struct TCP_Server_Info *server = tcon->ses->server; 29 + struct fscache_volume *vcookie; 30 + const struct sockaddr *sa = (struct sockaddr *)&server->dstaddr; 31 + size_t slen, i; 32 + char *sharename; 33 + char *key; 34 + int ret = -ENOMEM; 35 + 36 + tcon->fscache = NULL; 37 + switch (sa->sa_family) { 38 + case AF_INET: 39 + case AF_INET6: 40 + break; 41 + default: 42 + cifs_dbg(VFS, "Unknown network family '%d'\n", sa->sa_family); 43 + return -EINVAL; 44 + } 36 45 37 46 memset(&key, 0, sizeof(key)); 38 - key.conn_id = server->conn_id; 39 - 40 - server->fscache = 41 - fscache_acquire_cookie(cifs_fscache_netfs.primary_index, 42 - &cifs_fscache_server_index_def, 43 - &key, sizeof(key), 44 - NULL, 0, 45 - server, 0, true); 46 - cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", 47 - __func__, server, server->fscache); 48 - } 49 - 50 - void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server) 51 - { 52 - cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", 53 - __func__, server, server->fscache); 54 - fscache_relinquish_cookie(server->fscache, NULL, false); 55 - server->fscache = NULL; 56 - } 57 - 58 - void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) 59 - { 60 - struct TCP_Server_Info *server = tcon->ses->server; 61 - char *sharename; 62 - struct cifs_fscache_super_auxdata auxdata; 63 - 64 - /* 65 - * Check if cookie was already initialized so don't reinitialize it. 66 - * In the future, as we integrate with newer fscache features, 67 - * we may want to instead add a check if cookie has changed 68 - */ 69 - if (tcon->fscache) 70 - return; 71 47 72 48 sharename = extract_sharename(tcon->treeName); 73 49 if (IS_ERR(sharename)) { 74 50 cifs_dbg(FYI, "%s: couldn't extract sharename\n", __func__); 75 - tcon->fscache = NULL; 76 - return; 51 + return -EINVAL; 77 52 } 78 53 79 - memset(&auxdata, 0, sizeof(auxdata)); 80 - auxdata.resource_id = tcon->resource_id; 81 - auxdata.vol_create_time = tcon->vol_create_time; 82 - auxdata.vol_serial_number = tcon->vol_serial_number; 54 + slen = strlen(sharename); 55 + for (i = 0; i < slen; i++) 56 + if (sharename[i] == '/') 57 + sharename[i] = ';'; 83 58 84 - tcon->fscache = 85 - fscache_acquire_cookie(server->fscache, 86 - &cifs_fscache_super_index_def, 87 - sharename, strlen(sharename), 88 - &auxdata, sizeof(auxdata), 89 - tcon, 0, true); 59 + key = kasprintf(GFP_KERNEL, "cifs,%pISpc,%s", sa, sharename); 60 + if (!key) 61 + goto out; 62 + 63 + cifs_fscache_fill_volume_coherency(tcon, &cd); 64 + vcookie = fscache_acquire_volume(key, 65 + NULL, /* preferred_cache */ 66 + &cd, sizeof(cd)); 67 + cifs_dbg(FYI, "%s: (%s/0x%p)\n", __func__, key, vcookie); 68 + if (IS_ERR(vcookie)) { 69 + if (vcookie != ERR_PTR(-EBUSY)) { 70 + ret = PTR_ERR(vcookie); 71 + goto out_2; 72 + } 73 + pr_err("Cache volume key already in use (%s)\n", key); 74 + vcookie = NULL; 75 + } 76 + 77 + tcon->fscache = vcookie; 78 + ret = 0; 79 + out_2: 80 + kfree(key); 81 + out: 90 82 kfree(sharename); 91 - cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", 92 - __func__, server->fscache, tcon->fscache); 83 + return ret; 93 84 } 94 85 95 86 void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) 96 87 { 97 - struct cifs_fscache_super_auxdata auxdata; 98 - 99 - memset(&auxdata, 0, sizeof(auxdata)); 100 - auxdata.resource_id = tcon->resource_id; 101 - auxdata.vol_create_time = tcon->vol_create_time; 102 - auxdata.vol_serial_number = tcon->vol_serial_number; 88 + struct cifs_fscache_volume_coherency_data cd; 103 89 104 90 cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache); 105 - fscache_relinquish_cookie(tcon->fscache, &auxdata, false); 91 + 92 + cifs_fscache_fill_volume_coherency(tcon, &cd); 93 + fscache_relinquish_volume(tcon->fscache, &cd, false); 106 94 tcon->fscache = NULL; 107 95 } 108 96 109 - static void cifs_fscache_acquire_inode_cookie(struct cifsInodeInfo *cifsi, 110 - struct cifs_tcon *tcon) 97 + void cifs_fscache_get_inode_cookie(struct inode *inode) 111 98 { 112 - struct cifs_fscache_inode_auxdata auxdata; 113 - 114 - memset(&auxdata, 0, sizeof(auxdata)); 115 - auxdata.eof = cifsi->server_eof; 116 - auxdata.last_write_time_sec = cifsi->vfs_inode.i_mtime.tv_sec; 117 - auxdata.last_change_time_sec = cifsi->vfs_inode.i_ctime.tv_sec; 118 - auxdata.last_write_time_nsec = cifsi->vfs_inode.i_mtime.tv_nsec; 119 - auxdata.last_change_time_nsec = cifsi->vfs_inode.i_ctime.tv_nsec; 120 - 121 - cifsi->fscache = 122 - fscache_acquire_cookie(tcon->fscache, 123 - &cifs_fscache_inode_object_def, 124 - &cifsi->uniqueid, sizeof(cifsi->uniqueid), 125 - &auxdata, sizeof(auxdata), 126 - cifsi, cifsi->vfs_inode.i_size, true); 127 - } 128 - 129 - static void cifs_fscache_enable_inode_cookie(struct inode *inode) 130 - { 99 + struct cifs_fscache_inode_coherency_data cd; 131 100 struct cifsInodeInfo *cifsi = CIFS_I(inode); 132 101 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 133 102 struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 134 103 135 - if (cifsi->fscache) 136 - return; 104 + cifs_fscache_fill_coherency(&cifsi->vfs_inode, &cd); 137 105 138 - if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE)) 139 - return; 106 + cifsi->fscache = 107 + fscache_acquire_cookie(tcon->fscache, 0, 108 + &cifsi->uniqueid, sizeof(cifsi->uniqueid), 109 + &cd, sizeof(cd), 110 + i_size_read(&cifsi->vfs_inode)); 111 + } 140 112 141 - cifs_fscache_acquire_inode_cookie(cifsi, tcon); 113 + void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update) 114 + { 115 + if (update) { 116 + struct cifs_fscache_inode_coherency_data cd; 117 + loff_t i_size = i_size_read(inode); 142 118 143 - cifs_dbg(FYI, "%s: got FH cookie (0x%p/0x%p)\n", 144 - __func__, tcon->fscache, cifsi->fscache); 119 + cifs_fscache_fill_coherency(inode, &cd); 120 + fscache_unuse_cookie(cifs_inode_cookie(inode), &cd, &i_size); 121 + } else { 122 + fscache_unuse_cookie(cifs_inode_cookie(inode), NULL, NULL); 123 + } 145 124 } 146 125 147 126 void cifs_fscache_release_inode_cookie(struct inode *inode) 148 127 { 149 - struct cifs_fscache_inode_auxdata auxdata; 150 128 struct cifsInodeInfo *cifsi = CIFS_I(inode); 151 129 152 130 if (cifsi->fscache) { 153 - memset(&auxdata, 0, sizeof(auxdata)); 154 - auxdata.eof = cifsi->server_eof; 155 - auxdata.last_write_time_sec = cifsi->vfs_inode.i_mtime.tv_sec; 156 - auxdata.last_change_time_sec = cifsi->vfs_inode.i_ctime.tv_sec; 157 - auxdata.last_write_time_nsec = cifsi->vfs_inode.i_mtime.tv_nsec; 158 - auxdata.last_change_time_nsec = cifsi->vfs_inode.i_ctime.tv_nsec; 159 - 160 131 cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache); 161 - /* fscache_relinquish_cookie does not seem to update auxdata */ 162 - fscache_update_cookie(cifsi->fscache, &auxdata); 163 - fscache_relinquish_cookie(cifsi->fscache, &auxdata, false); 132 + fscache_relinquish_cookie(cifsi->fscache, false); 164 133 cifsi->fscache = NULL; 165 134 } 166 - } 167 - 168 - void cifs_fscache_update_inode_cookie(struct inode *inode) 169 - { 170 - struct cifs_fscache_inode_auxdata auxdata; 171 - struct cifsInodeInfo *cifsi = CIFS_I(inode); 172 - 173 - if (cifsi->fscache) { 174 - memset(&auxdata, 0, sizeof(auxdata)); 175 - auxdata.eof = cifsi->server_eof; 176 - auxdata.last_write_time_sec = cifsi->vfs_inode.i_mtime.tv_sec; 177 - auxdata.last_change_time_sec = cifsi->vfs_inode.i_ctime.tv_sec; 178 - auxdata.last_write_time_nsec = cifsi->vfs_inode.i_mtime.tv_nsec; 179 - auxdata.last_change_time_nsec = cifsi->vfs_inode.i_ctime.tv_nsec; 180 - 181 - cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache); 182 - fscache_update_cookie(cifsi->fscache, &auxdata); 183 - } 184 - } 185 - 186 - void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp) 187 - { 188 - cifs_fscache_enable_inode_cookie(inode); 189 - } 190 - 191 - void cifs_fscache_reset_inode_cookie(struct inode *inode) 192 - { 193 - struct cifsInodeInfo *cifsi = CIFS_I(inode); 194 - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 195 - struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 196 - struct fscache_cookie *old = cifsi->fscache; 197 - 198 - if (cifsi->fscache) { 199 - /* retire the current fscache cache and get a new one */ 200 - fscache_relinquish_cookie(cifsi->fscache, NULL, true); 201 - 202 - cifs_fscache_acquire_inode_cookie(cifsi, tcon); 203 - cifs_dbg(FYI, "%s: new cookie 0x%p oldcookie 0x%p\n", 204 - __func__, cifsi->fscache, old); 205 - } 206 - } 207 - 208 - int cifs_fscache_release_page(struct page *page, gfp_t gfp) 209 - { 210 - if (PageFsCache(page)) { 211 - struct inode *inode = page->mapping->host; 212 - struct cifsInodeInfo *cifsi = CIFS_I(inode); 213 - 214 - cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", 215 - __func__, page, cifsi->fscache); 216 - if (!fscache_maybe_release_page(cifsi->fscache, page, gfp)) 217 - return 0; 218 - } 219 - 220 - return 1; 221 - } 222 - 223 - static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx, 224 - int error) 225 - { 226 - cifs_dbg(FYI, "%s: (0x%p/%d)\n", __func__, page, error); 227 - if (!error) 228 - SetPageUptodate(page); 229 - unlock_page(page); 230 135 } 231 136 232 137 /* ··· 139 234 */ 140 235 int __cifs_readpage_from_fscache(struct inode *inode, struct page *page) 141 236 { 142 - int ret; 143 - 144 237 cifs_dbg(FYI, "%s: (fsc:%p, p:%p, i:0x%p\n", 145 238 __func__, CIFS_I(inode)->fscache, page, inode); 146 - ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page, 147 - cifs_readpage_from_fscache_complete, 148 - NULL, 149 - GFP_KERNEL); 150 - switch (ret) { 151 - 152 - case 0: /* page found in fscache, read submitted */ 153 - cifs_dbg(FYI, "%s: submitted\n", __func__); 154 - return ret; 155 - case -ENOBUFS: /* page won't be cached */ 156 - case -ENODATA: /* page not in cache */ 157 - cifs_dbg(FYI, "%s: %d\n", __func__, ret); 158 - return 1; 159 - 160 - default: 161 - cifs_dbg(VFS, "unknown error ret = %d\n", ret); 162 - } 163 - return ret; 239 + return -ENOBUFS; // Needs conversion to using netfslib 164 240 } 165 241 166 242 /* ··· 152 266 struct list_head *pages, 153 267 unsigned *nr_pages) 154 268 { 155 - int ret; 156 - 157 269 cifs_dbg(FYI, "%s: (0x%p/%u/0x%p)\n", 158 270 __func__, CIFS_I(inode)->fscache, *nr_pages, inode); 159 - ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping, 160 - pages, nr_pages, 161 - cifs_readpage_from_fscache_complete, 162 - NULL, 163 - mapping_gfp_mask(mapping)); 164 - switch (ret) { 165 - case 0: /* read submitted to the cache for all pages */ 166 - cifs_dbg(FYI, "%s: submitted\n", __func__); 167 - return ret; 168 - 169 - case -ENOBUFS: /* some pages are not cached and can't be */ 170 - case -ENODATA: /* some pages are not cached */ 171 - cifs_dbg(FYI, "%s: no page\n", __func__); 172 - return 1; 173 - 174 - default: 175 - cifs_dbg(FYI, "unknown error ret = %d\n", ret); 176 - } 177 - 178 - return ret; 271 + return -ENOBUFS; // Needs conversion to using netfslib 179 272 } 180 273 181 274 void __cifs_readpage_to_fscache(struct inode *inode, struct page *page) 182 275 { 183 276 struct cifsInodeInfo *cifsi = CIFS_I(inode); 184 - int ret; 185 277 186 278 WARN_ON(!cifsi->fscache); 187 279 188 280 cifs_dbg(FYI, "%s: (fsc: %p, p: %p, i: %p)\n", 189 281 __func__, cifsi->fscache, page, inode); 190 - ret = fscache_write_page(cifsi->fscache, page, 191 - cifsi->vfs_inode.i_size, GFP_KERNEL); 192 - if (ret != 0) 193 - fscache_uncache_page(cifsi->fscache, page); 194 - } 195 282 196 - void __cifs_fscache_readpages_cancel(struct inode *inode, struct list_head *pages) 197 - { 198 - cifs_dbg(FYI, "%s: (fsc: %p, i: %p)\n", 199 - __func__, CIFS_I(inode)->fscache, inode); 200 - fscache_readpages_cancel(CIFS_I(inode)->fscache, pages); 201 - } 202 - 203 - void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode) 204 - { 205 - struct cifsInodeInfo *cifsi = CIFS_I(inode); 206 - struct fscache_cookie *cookie = cifsi->fscache; 207 - 208 - cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", __func__, page, cookie); 209 - fscache_wait_on_page_write(cookie, page); 210 - fscache_uncache_page(cookie, page); 211 - } 212 - 213 - void __cifs_fscache_wait_on_page_write(struct inode *inode, struct page *page) 214 - { 215 - struct cifsInodeInfo *cifsi = CIFS_I(inode); 216 - struct fscache_cookie *cookie = cifsi->fscache; 217 - 218 - cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", __func__, page, cookie); 219 - fscache_wait_on_page_write(cookie, page); 220 - } 221 - 222 - void __cifs_fscache_uncache_page(struct inode *inode, struct page *page) 223 - { 224 - struct cifsInodeInfo *cifsi = CIFS_I(inode); 225 - struct fscache_cookie *cookie = cifsi->fscache; 226 - 227 - cifs_dbg(FYI, "%s: (0x%p/0x%p)\n", __func__, page, cookie); 228 - fscache_uncache_page(cookie, page); 283 + // Needs conversion to using netfslib 229 284 }
+46 -84
fs/cifs/fscache.h
··· 13 13 14 14 #include "cifsglob.h" 15 15 16 - #ifdef CONFIG_CIFS_FSCACHE 17 - 18 16 /* 19 - * Auxiliary data attached to CIFS superblock within the cache 17 + * Coherency data attached to CIFS volume within the cache 20 18 */ 21 - struct cifs_fscache_super_auxdata { 22 - u64 resource_id; /* unique server resource id */ 19 + struct cifs_fscache_volume_coherency_data { 20 + __le64 resource_id; /* unique server resource id */ 23 21 __le64 vol_create_time; 24 - u32 vol_serial_number; 22 + __le32 vol_serial_number; 25 23 } __packed; 26 24 27 25 /* 28 - * Auxiliary data attached to CIFS inode within the cache 26 + * Coherency data attached to CIFS inode within the cache. 29 27 */ 30 - struct cifs_fscache_inode_auxdata { 31 - u64 last_write_time_sec; 32 - u64 last_change_time_sec; 33 - u32 last_write_time_nsec; 34 - u32 last_change_time_nsec; 35 - u64 eof; 28 + struct cifs_fscache_inode_coherency_data { 29 + __le64 last_write_time_sec; 30 + __le64 last_change_time_sec; 31 + __le32 last_write_time_nsec; 32 + __le32 last_change_time_nsec; 36 33 }; 37 34 38 - /* 39 - * cache.c 40 - */ 41 - extern struct fscache_netfs cifs_fscache_netfs; 42 - extern const struct fscache_cookie_def cifs_fscache_server_index_def; 43 - extern const struct fscache_cookie_def cifs_fscache_super_index_def; 44 - extern const struct fscache_cookie_def cifs_fscache_inode_object_def; 45 - 46 - extern int cifs_fscache_register(void); 47 - extern void cifs_fscache_unregister(void); 35 + #ifdef CONFIG_CIFS_FSCACHE 48 36 49 37 /* 50 38 * fscache.c 51 39 */ 52 - extern void cifs_fscache_get_client_cookie(struct TCP_Server_Info *); 53 - extern void cifs_fscache_release_client_cookie(struct TCP_Server_Info *); 54 - extern void cifs_fscache_get_super_cookie(struct cifs_tcon *); 40 + extern int cifs_fscache_get_super_cookie(struct cifs_tcon *); 55 41 extern void cifs_fscache_release_super_cookie(struct cifs_tcon *); 56 42 43 + extern void cifs_fscache_get_inode_cookie(struct inode *inode); 57 44 extern void cifs_fscache_release_inode_cookie(struct inode *); 58 - extern void cifs_fscache_update_inode_cookie(struct inode *inode); 59 - extern void cifs_fscache_set_inode_cookie(struct inode *, struct file *); 60 - extern void cifs_fscache_reset_inode_cookie(struct inode *); 45 + extern void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update); 61 46 62 - extern void __cifs_fscache_invalidate_page(struct page *, struct inode *); 63 - extern void __cifs_fscache_wait_on_page_write(struct inode *inode, struct page *page); 64 - extern void __cifs_fscache_uncache_page(struct inode *inode, struct page *page); 47 + static inline 48 + void cifs_fscache_fill_coherency(struct inode *inode, 49 + struct cifs_fscache_inode_coherency_data *cd) 50 + { 51 + struct cifsInodeInfo *cifsi = CIFS_I(inode); 52 + 53 + memset(cd, 0, sizeof(*cd)); 54 + cd->last_write_time_sec = cpu_to_le64(cifsi->vfs_inode.i_mtime.tv_sec); 55 + cd->last_write_time_nsec = cpu_to_le32(cifsi->vfs_inode.i_mtime.tv_nsec); 56 + cd->last_change_time_sec = cpu_to_le64(cifsi->vfs_inode.i_ctime.tv_sec); 57 + cd->last_change_time_nsec = cpu_to_le32(cifsi->vfs_inode.i_ctime.tv_nsec); 58 + } 59 + 60 + 65 61 extern int cifs_fscache_release_page(struct page *page, gfp_t gfp); 66 62 extern int __cifs_readpage_from_fscache(struct inode *, struct page *); 67 63 extern int __cifs_readpages_from_fscache(struct inode *, 68 64 struct address_space *, 69 65 struct list_head *, 70 66 unsigned *); 71 - extern void __cifs_fscache_readpages_cancel(struct inode *, struct list_head *); 72 - 73 67 extern void __cifs_readpage_to_fscache(struct inode *, struct page *); 74 68 75 - static inline void cifs_fscache_invalidate_page(struct page *page, 76 - struct inode *inode) 69 + static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) 77 70 { 78 - if (PageFsCache(page)) 79 - __cifs_fscache_invalidate_page(page, inode); 71 + return CIFS_I(inode)->fscache; 80 72 } 81 73 82 - static inline void cifs_fscache_wait_on_page_write(struct inode *inode, 83 - struct page *page) 74 + static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags) 84 75 { 85 - if (PageFsCache(page)) 86 - __cifs_fscache_wait_on_page_write(inode, page); 87 - } 76 + struct cifs_fscache_inode_coherency_data cd; 88 77 89 - static inline void cifs_fscache_uncache_page(struct inode *inode, 90 - struct page *page) 91 - { 92 - if (PageFsCache(page)) 93 - __cifs_fscache_uncache_page(inode, page); 78 + cifs_fscache_fill_coherency(inode, &cd); 79 + fscache_invalidate(cifs_inode_cookie(inode), &cd, 80 + i_size_read(inode), flags); 94 81 } 95 82 96 83 static inline int cifs_readpage_from_fscache(struct inode *inode, ··· 107 120 __cifs_readpage_to_fscache(inode, page); 108 121 } 109 122 110 - static inline void cifs_fscache_readpages_cancel(struct inode *inode, 111 - struct list_head *pages) 112 - { 113 - if (CIFS_I(inode)->fscache) 114 - return __cifs_fscache_readpages_cancel(inode, pages); 115 - } 116 - 117 123 #else /* CONFIG_CIFS_FSCACHE */ 118 - static inline int cifs_fscache_register(void) { return 0; } 119 - static inline void cifs_fscache_unregister(void) {} 120 - 121 - static inline void 122 - cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) {} 123 - static inline void 124 - cifs_fscache_release_client_cookie(struct TCP_Server_Info *server) {} 125 - static inline void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) {} 126 - static inline void 127 - cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) {} 128 - 129 - static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {} 130 - static inline void cifs_fscache_update_inode_cookie(struct inode *inode) {} 131 - static inline void cifs_fscache_set_inode_cookie(struct inode *inode, 132 - struct file *filp) {} 133 - static inline void cifs_fscache_reset_inode_cookie(struct inode *inode) {} 134 - static inline int cifs_fscache_release_page(struct page *page, gfp_t gfp) 124 + static inline 125 + void cifs_fscache_fill_coherency(struct inode *inode, 126 + struct cifs_fscache_inode_coherency_data *cd) 135 127 { 136 - return 1; /* May release page */ 137 128 } 138 129 139 - static inline void cifs_fscache_invalidate_page(struct page *page, 140 - struct inode *inode) {} 141 - static inline void cifs_fscache_wait_on_page_write(struct inode *inode, 142 - struct page *page) {} 143 - static inline void cifs_fscache_uncache_page(struct inode *inode, 144 - struct page *page) {} 130 + static inline int cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) { return 0; } 131 + static inline void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) {} 132 + 133 + static inline void cifs_fscache_get_inode_cookie(struct inode *inode) {} 134 + static inline void cifs_fscache_release_inode_cookie(struct inode *inode) {} 135 + static inline void cifs_fscache_unuse_inode_cookie(struct inode *inode, bool update) {} 136 + static inline struct fscache_cookie *cifs_inode_cookie(struct inode *inode) { return NULL; } 137 + static inline void cifs_invalidate_cache(struct inode *inode, unsigned int flags) {} 145 138 146 139 static inline int 147 140 cifs_readpage_from_fscache(struct inode *inode, struct page *page) ··· 139 172 140 173 static inline void cifs_readpage_to_fscache(struct inode *inode, 141 174 struct page *page) {} 142 - 143 - static inline void cifs_fscache_readpages_cancel(struct inode *inode, 144 - struct list_head *pages) 145 - { 146 - } 147 175 148 176 #endif /* CONFIG_CIFS_FSCACHE */ 149 177
+18 -7
fs/cifs/inode.c
··· 952 952 rc = server->ops->query_path_info(xid, tcon, cifs_sb, 953 953 full_path, tmp_data, 954 954 &adjust_tz, &is_reparse_point); 955 + #ifdef CONFIG_CIFS_DFS_UPCALL 956 + if (rc == -ENOENT && is_tcon_dfs(tcon)) 957 + rc = cifs_dfs_query_info_nonascii_quirk(xid, tcon, 958 + cifs_sb, 959 + full_path); 960 + #endif 955 961 data = tmp_data; 956 962 } 957 963 ··· 1304 1298 inode->i_flags |= S_NOATIME | S_NOCMTIME; 1305 1299 if (inode->i_state & I_NEW) { 1306 1300 inode->i_ino = hash; 1307 - #ifdef CONFIG_CIFS_FSCACHE 1308 - /* initialize per-inode cache cookie pointer */ 1309 - CIFS_I(inode)->fscache = NULL; 1310 - #endif 1301 + cifs_fscache_get_inode_cookie(inode); 1311 1302 unlock_new_inode(inode); 1312 1303 } 1313 1304 } ··· 1373 1370 iget_failed(inode); 1374 1371 inode = ERR_PTR(rc); 1375 1372 } 1373 + 1376 1374 out: 1377 1375 kfree(path); 1378 1376 free_xid(xid); ··· 2261 2257 int 2262 2258 cifs_invalidate_mapping(struct inode *inode) 2263 2259 { 2260 + struct cifs_fscache_inode_coherency_data cd; 2261 + struct cifsInodeInfo *cifsi = CIFS_I(inode); 2264 2262 int rc = 0; 2265 2263 2266 2264 if (inode->i_mapping && inode->i_mapping->nrpages != 0) { ··· 2272 2266 __func__, inode); 2273 2267 } 2274 2268 2275 - cifs_fscache_reset_inode_cookie(inode); 2269 + cifs_fscache_fill_coherency(&cifsi->vfs_inode, &cd); 2270 + fscache_invalidate(cifs_inode_cookie(inode), &cd, i_size_read(inode), 0); 2276 2271 return rc; 2277 2272 } 2278 2273 ··· 2778 2771 goto out; 2779 2772 2780 2773 if ((attrs->ia_valid & ATTR_SIZE) && 2781 - attrs->ia_size != i_size_read(inode)) 2774 + attrs->ia_size != i_size_read(inode)) { 2782 2775 truncate_setsize(inode, attrs->ia_size); 2776 + fscache_resize_cookie(cifs_inode_cookie(inode), attrs->ia_size); 2777 + } 2783 2778 2784 2779 setattr_copy(&init_user_ns, inode, attrs); 2785 2780 mark_inode_dirty(inode); ··· 2976 2967 goto cifs_setattr_exit; 2977 2968 2978 2969 if ((attrs->ia_valid & ATTR_SIZE) && 2979 - attrs->ia_size != i_size_read(inode)) 2970 + attrs->ia_size != i_size_read(inode)) { 2980 2971 truncate_setsize(inode, attrs->ia_size); 2972 + fscache_resize_cookie(cifs_inode_cookie(inode), attrs->ia_size); 2973 + } 2981 2974 2982 2975 setattr_copy(&init_user_ns, inode, attrs); 2983 2976 mark_inode_dirty(inode);
+49
fs/cifs/misc.c
··· 1302 1302 cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_USE_PREFIX_PATH; 1303 1303 return 0; 1304 1304 } 1305 + 1306 + /** cifs_dfs_query_info_nonascii_quirk 1307 + * Handle weird Windows SMB server behaviour. It responds with 1308 + * STATUS_OBJECT_NAME_INVALID code to SMB2 QUERY_INFO request 1309 + * for "\<server>\<dfsname>\<linkpath>" DFS reference, 1310 + * where <dfsname> contains non-ASCII unicode symbols. 1311 + * 1312 + * Check such DFS reference and emulate -ENOENT if it is actual. 1313 + */ 1314 + int cifs_dfs_query_info_nonascii_quirk(const unsigned int xid, 1315 + struct cifs_tcon *tcon, 1316 + struct cifs_sb_info *cifs_sb, 1317 + const char *linkpath) 1318 + { 1319 + char *treename, *dfspath, sep; 1320 + int treenamelen, linkpathlen, rc; 1321 + 1322 + treename = tcon->treeName; 1323 + /* MS-DFSC: All paths in REQ_GET_DFS_REFERRAL and RESP_GET_DFS_REFERRAL 1324 + * messages MUST be encoded with exactly one leading backslash, not two 1325 + * leading backslashes. 1326 + */ 1327 + sep = CIFS_DIR_SEP(cifs_sb); 1328 + if (treename[0] == sep && treename[1] == sep) 1329 + treename++; 1330 + linkpathlen = strlen(linkpath); 1331 + treenamelen = strnlen(treename, MAX_TREE_SIZE + 1); 1332 + dfspath = kzalloc(treenamelen + linkpathlen + 1, GFP_KERNEL); 1333 + if (!dfspath) 1334 + return -ENOMEM; 1335 + if (treenamelen) 1336 + memcpy(dfspath, treename, treenamelen); 1337 + memcpy(dfspath + treenamelen, linkpath, linkpathlen); 1338 + rc = dfs_cache_find(xid, tcon->ses, cifs_sb->local_nls, 1339 + cifs_remap(cifs_sb), dfspath, NULL, NULL); 1340 + if (rc == 0) { 1341 + cifs_dbg(FYI, "DFS ref '%s' is found, emulate -EREMOTE\n", 1342 + dfspath); 1343 + rc = -EREMOTE; 1344 + } else if (rc == -EEXIST) { 1345 + cifs_dbg(FYI, "DFS ref '%s' is not found, emulate -ENOENT\n", 1346 + dfspath); 1347 + rc = -ENOENT; 1348 + } else { 1349 + cifs_dbg(FYI, "%s: dfs_cache_find returned %d\n", __func__, rc); 1350 + } 1351 + kfree(dfspath); 1352 + return rc; 1353 + } 1305 1354 #endif
+1 -4
fs/cifs/netmisc.c
··· 896 896 if (class == ERRSRV && code == ERRbaduid) { 897 897 cifs_dbg(FYI, "Server returned 0x%x, reconnecting session...\n", 898 898 code); 899 - spin_lock(&cifs_tcp_ses_lock); 900 - if (mid->server->tcpStatus != CifsExiting) 901 - mid->server->tcpStatus = CifsNeedReconnect; 902 - spin_unlock(&cifs_tcp_ses_lock); 899 + cifs_reconnect(mid->server, false); 903 900 } 904 901 } 905 902
+29 -1
fs/cifs/ntlmssp.h
··· 40 40 #define NTLMSSP_REQUEST_NON_NT_KEY 0x400000 41 41 #define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000 42 42 /* #define reserved4 0x1000000 */ 43 - #define NTLMSSP_NEGOTIATE_VERSION 0x2000000 /* we do not set */ 43 + #define NTLMSSP_NEGOTIATE_VERSION 0x2000000 /* we only set for SMB2+ */ 44 44 /* #define reserved3 0x4000000 */ 45 45 /* #define reserved2 0x8000000 */ 46 46 /* #define reserved1 0x10000000 */ ··· 87 87 /* followed by WorkstationString */ 88 88 } __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE; 89 89 90 + #define NTLMSSP_REVISION_W2K3 0x0F 91 + 92 + /* See MS-NLMP section 2.2.2.10 */ 93 + struct ntlmssp_version { 94 + __u8 ProductMajorVersion; 95 + __u8 ProductMinorVersion; 96 + __le16 ProductBuild; /* we send the cifs.ko module version here */ 97 + __u8 Reserved[3]; 98 + __u8 NTLMRevisionCurrent; /* currently 0x0F */ 99 + } __packed; 100 + 101 + /* see MS-NLMP section 2.2.1.1 */ 102 + struct negotiate_message { 103 + __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; 104 + __le32 MessageType; /* NtLmNegotiate = 1 */ 105 + __le32 NegotiateFlags; 106 + SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */ 107 + SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */ 108 + struct ntlmssp_version Version; 109 + /* SECURITY_BUFFER */ 110 + char DomainString[0]; 111 + /* followed by WorkstationString */ 112 + } __packed; 113 + 90 114 typedef struct _CHALLENGE_MESSAGE { 91 115 __u8 Signature[sizeof(NTLMSSP_SIGNATURE)]; 92 116 __le32 MessageType; /* NtLmChallenge = 2 */ ··· 144 120 145 121 int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, struct cifs_ses *ses); 146 122 int build_ntlmssp_negotiate_blob(unsigned char **pbuffer, u16 *buflen, 123 + struct cifs_ses *ses, 124 + struct TCP_Server_Info *server, 125 + const struct nls_table *nls_cp); 126 + int build_ntlmssp_smb3_negotiate_blob(unsigned char **pbuffer, u16 *buflen, 147 127 struct cifs_ses *ses, 148 128 struct TCP_Server_Info *server, 149 129 const struct nls_table *nls_cp);
+82 -30
fs/cifs/sess.c
··· 17 17 #include "nterr.h" 18 18 #include <linux/utsname.h> 19 19 #include <linux/slab.h> 20 + #include <linux/version.h> 21 + #include "cifsfs.h" 20 22 #include "cifs_spnego.h" 21 23 #include "smb2proto.h" 22 24 #include "fs_context.h" ··· 66 64 spin_unlock(&ses->chan_lock); 67 65 return false; 68 66 } 67 + 68 + /* channel helper functions. assumed that chan_lock is held by caller. */ 69 69 70 70 unsigned int 71 71 cifs_ses_get_chan_index(struct cifs_ses *ses, ··· 138 134 left = ses->chan_max - ses->chan_count; 139 135 140 136 if (left <= 0) { 137 + spin_unlock(&ses->chan_lock); 141 138 cifs_dbg(FYI, 142 139 "ses already at max_channels (%zu), nothing to open\n", 143 140 ses->chan_max); 144 - spin_unlock(&ses->chan_lock); 145 141 return 0; 146 142 } 147 143 ··· 366 362 cifs_put_tcp_session(chan->server, 0); 367 363 368 364 return rc; 369 - } 370 - 371 - /* Mark all session channels for reconnect */ 372 - void cifs_ses_mark_for_reconnect(struct cifs_ses *ses) 373 - { 374 - int i; 375 - 376 - for (i = 0; i < ses->chan_count; i++) { 377 - spin_lock(&cifs_tcp_ses_lock); 378 - if (ses->chans[i].server->tcpStatus != CifsExiting) 379 - ses->chans[i].server->tcpStatus = CifsNeedReconnect; 380 - spin_unlock(&cifs_tcp_ses_lock); 381 - } 382 365 } 383 366 384 367 static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, ··· 811 820 return rc; 812 821 } 813 822 823 + /* 824 + * Build ntlmssp blob with additional fields, such as version, 825 + * supported by modern servers. For safety limit to SMB3 or later 826 + * See notes in MS-NLMP Section 2.2.2.1 e.g. 827 + */ 828 + int build_ntlmssp_smb3_negotiate_blob(unsigned char **pbuffer, 829 + u16 *buflen, 830 + struct cifs_ses *ses, 831 + struct TCP_Server_Info *server, 832 + const struct nls_table *nls_cp) 833 + { 834 + int rc = 0; 835 + struct negotiate_message *sec_blob; 836 + __u32 flags; 837 + unsigned char *tmp; 838 + int len; 839 + 840 + len = size_of_ntlmssp_blob(ses, sizeof(struct negotiate_message)); 841 + *pbuffer = kmalloc(len, GFP_KERNEL); 842 + if (!*pbuffer) { 843 + rc = -ENOMEM; 844 + cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc); 845 + *buflen = 0; 846 + goto setup_ntlm_smb3_neg_ret; 847 + } 848 + sec_blob = (struct negotiate_message *)*pbuffer; 849 + 850 + memset(*pbuffer, 0, sizeof(struct negotiate_message)); 851 + memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8); 852 + sec_blob->MessageType = NtLmNegotiate; 853 + 854 + /* BB is NTLMV2 session security format easier to use here? */ 855 + flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET | 856 + NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE | 857 + NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SEC | 858 + NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL | 859 + NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_VERSION; 860 + if (!server->session_estab || ses->ntlmssp->sesskey_per_smbsess) 861 + flags |= NTLMSSP_NEGOTIATE_KEY_XCH; 862 + 863 + sec_blob->Version.ProductMajorVersion = LINUX_VERSION_MAJOR; 864 + sec_blob->Version.ProductMinorVersion = LINUX_VERSION_PATCHLEVEL; 865 + sec_blob->Version.ProductBuild = cpu_to_le16(SMB3_PRODUCT_BUILD); 866 + sec_blob->Version.NTLMRevisionCurrent = NTLMSSP_REVISION_W2K3; 867 + 868 + tmp = *pbuffer + sizeof(struct negotiate_message); 869 + ses->ntlmssp->client_flags = flags; 870 + sec_blob->NegotiateFlags = cpu_to_le32(flags); 871 + 872 + /* these fields should be null in negotiate phase MS-NLMP 3.1.5.1.1 */ 873 + cifs_security_buffer_from_str(&sec_blob->DomainName, 874 + NULL, 875 + CIFS_MAX_DOMAINNAME_LEN, 876 + *pbuffer, &tmp, 877 + nls_cp); 878 + 879 + cifs_security_buffer_from_str(&sec_blob->WorkstationName, 880 + NULL, 881 + CIFS_MAX_WORKSTATION_LEN, 882 + *pbuffer, &tmp, 883 + nls_cp); 884 + 885 + *buflen = tmp - *pbuffer; 886 + setup_ntlm_smb3_neg_ret: 887 + return rc; 888 + } 889 + 890 + 814 891 int build_ntlmssp_auth_blob(unsigned char **pbuffer, 815 892 u16 *buflen, 816 893 struct cifs_ses *ses, ··· 1107 1048 mutex_unlock(&server->srv_mutex); 1108 1049 1109 1050 cifs_dbg(FYI, "CIFS session established successfully\n"); 1110 - spin_lock(&ses->chan_lock); 1111 - cifs_chan_clear_need_reconnect(ses, server); 1112 - spin_unlock(&ses->chan_lock); 1113 - 1114 - /* Even if one channel is active, session is in good state */ 1115 - spin_lock(&cifs_tcp_ses_lock); 1116 - server->tcpStatus = CifsGood; 1117 - ses->status = CifsGood; 1118 - spin_unlock(&cifs_tcp_ses_lock); 1119 - 1120 1051 return 0; 1121 1052 } 1122 1053 ··· 1462 1413 &blob_len, ses, server, 1463 1414 sess_data->nls_cp); 1464 1415 if (rc) 1465 - goto out; 1416 + goto out_free_ntlmsspblob; 1466 1417 1467 1418 sess_data->iov[1].iov_len = blob_len; 1468 1419 sess_data->iov[1].iov_base = ntlmsspblob; ··· 1470 1421 1471 1422 rc = _sess_auth_rawntlmssp_assemble_req(sess_data); 1472 1423 if (rc) 1473 - goto out; 1424 + goto out_free_ntlmsspblob; 1474 1425 1475 1426 rc = sess_sendreceive(sess_data); 1476 1427 ··· 1484 1435 rc = 0; 1485 1436 1486 1437 if (rc) 1487 - goto out; 1438 + goto out_free_ntlmsspblob; 1488 1439 1489 1440 cifs_dbg(FYI, "rawntlmssp session setup challenge phase\n"); 1490 1441 1491 1442 if (smb_buf->WordCount != 4) { 1492 1443 rc = -EIO; 1493 1444 cifs_dbg(VFS, "bad word count %d\n", smb_buf->WordCount); 1494 - goto out; 1445 + goto out_free_ntlmsspblob; 1495 1446 } 1496 1447 1497 1448 ses->Suid = smb_buf->Uid; /* UID left in wire format (le) */ ··· 1505 1456 cifs_dbg(VFS, "bad security blob length %d\n", 1506 1457 blob_len); 1507 1458 rc = -EINVAL; 1508 - goto out; 1459 + goto out_free_ntlmsspblob; 1509 1460 } 1510 1461 1511 1462 rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses); 1463 + 1464 + out_free_ntlmsspblob: 1465 + kfree(ntlmsspblob); 1512 1466 out: 1513 1467 sess_free_buffer(sess_data); 1514 1468 ··· 1626 1574 out: 1627 1575 sess_free_buffer(sess_data); 1628 1576 1629 - if (!rc) 1577 + if (!rc) 1630 1578 rc = sess_establish_session(sess_data); 1631 1579 1632 1580 /* Cleanup */
+77 -35
fs/cifs/smb2pdu.c
··· 244 244 spin_unlock(&ses->chan_lock); 245 245 return 0; 246 246 } 247 + spin_unlock(&ses->chan_lock); 247 248 cifs_dbg(FYI, "sess reconnect mask: 0x%lx, tcon reconnect: %d", 248 249 tcon->ses->chans_need_reconnect, 249 250 tcon->need_reconnect); 250 - spin_unlock(&ses->chan_lock); 251 251 252 252 nls_codepage = load_nls_default(); 253 253 ··· 289 289 rc = -EHOSTDOWN; 290 290 goto failed; 291 291 } 292 - } 293 - 294 - if (rc || !tcon->need_reconnect) { 292 + } else { 295 293 mutex_unlock(&ses->session_mutex); 296 294 goto out; 297 295 } 296 + mutex_unlock(&ses->session_mutex); 298 297 299 298 skip_sess_setup: 299 + mutex_lock(&ses->session_mutex); 300 + if (!tcon->need_reconnect) { 301 + mutex_unlock(&ses->session_mutex); 302 + goto out; 303 + } 300 304 cifs_mark_open_files_invalid(tcon); 301 305 if (tcon->use_persistent) 302 306 tcon->need_reopen_files = true; ··· 1386 1382 mutex_unlock(&server->srv_mutex); 1387 1383 1388 1384 cifs_dbg(FYI, "SMB2/3 session established successfully\n"); 1389 - 1390 - spin_lock(&ses->chan_lock); 1391 - cifs_chan_clear_need_reconnect(ses, server); 1392 - spin_unlock(&ses->chan_lock); 1393 - 1394 - /* Even if one channel is active, session is in good state */ 1395 - spin_lock(&cifs_tcp_ses_lock); 1396 - server->tcpStatus = CifsGood; 1397 - ses->status = CifsGood; 1398 - spin_unlock(&cifs_tcp_ses_lock); 1399 - 1400 1385 return rc; 1401 1386 } 1402 1387 ··· 1506 1513 if (rc) 1507 1514 goto out_err; 1508 1515 1509 - rc = build_ntlmssp_negotiate_blob(&ntlmssp_blob, 1516 + rc = build_ntlmssp_smb3_negotiate_blob(&ntlmssp_blob, 1510 1517 &blob_length, ses, server, 1511 1518 sess_data->nls_cp); 1512 1519 if (rc) ··· 1913 1920 tcon->share_flags = le32_to_cpu(rsp->ShareFlags); 1914 1921 tcon->capabilities = rsp->Capabilities; /* we keep caps little endian */ 1915 1922 tcon->maximal_access = le32_to_cpu(rsp->MaximalAccess); 1916 - spin_lock(&cifs_tcp_ses_lock); 1917 - tcon->tidStatus = CifsGood; 1918 - spin_unlock(&cifs_tcp_ses_lock); 1919 - tcon->need_reconnect = false; 1920 1923 tcon->tid = le32_to_cpu(rsp->hdr.Id.SyncId.TreeId); 1921 1924 strlcpy(tcon->treeName, tree, sizeof(tcon->treeName)); 1922 1925 ··· 2576 2587 2577 2588 cp = load_nls_default(); 2578 2589 cifs_strtoUTF16(*out_path, treename, treename_len, cp); 2579 - UniStrcat(*out_path, sep); 2580 - UniStrcat(*out_path, path); 2590 + 2591 + /* Do not append the separator if the path is empty */ 2592 + if (path[0] != cpu_to_le16(0x0000)) { 2593 + UniStrcat(*out_path, sep); 2594 + UniStrcat(*out_path, path); 2595 + } 2596 + 2581 2597 unload_nls(cp); 2582 2598 2583 2599 return 0; ··· 3776 3782 { 3777 3783 struct TCP_Server_Info *server = container_of(work, 3778 3784 struct TCP_Server_Info, reconnect.work); 3779 - struct cifs_ses *ses; 3785 + struct TCP_Server_Info *pserver; 3786 + struct cifs_ses *ses, *ses2; 3780 3787 struct cifs_tcon *tcon, *tcon2; 3781 - struct list_head tmp_list; 3782 - int tcon_exist = false; 3788 + struct list_head tmp_list, tmp_ses_list; 3789 + bool tcon_exist = false, ses_exist = false; 3790 + bool tcon_selected = false; 3783 3791 int rc; 3784 - int resched = false; 3792 + bool resched = false; 3785 3793 3794 + /* If server is a channel, select the primary channel */ 3795 + pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server; 3786 3796 3787 3797 /* Prevent simultaneous reconnects that can corrupt tcon->rlist list */ 3788 - mutex_lock(&server->reconnect_mutex); 3798 + mutex_lock(&pserver->reconnect_mutex); 3789 3799 3790 3800 INIT_LIST_HEAD(&tmp_list); 3791 - cifs_dbg(FYI, "Need negotiate, reconnecting tcons\n"); 3801 + INIT_LIST_HEAD(&tmp_ses_list); 3802 + cifs_dbg(FYI, "Reconnecting tcons and channels\n"); 3792 3803 3793 3804 spin_lock(&cifs_tcp_ses_lock); 3794 - list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) { 3805 + list_for_each_entry(ses, &pserver->smb_ses_list, smb_ses_list) { 3806 + 3807 + tcon_selected = false; 3808 + 3795 3809 list_for_each_entry(tcon, &ses->tcon_list, tcon_list) { 3796 3810 if (tcon->need_reconnect || tcon->need_reopen_files) { 3797 3811 tcon->tc_count++; 3798 3812 list_add_tail(&tcon->rlist, &tmp_list); 3799 - tcon_exist = true; 3813 + tcon_selected = tcon_exist = true; 3800 3814 } 3801 3815 } 3802 3816 /* ··· 3813 3811 */ 3814 3812 if (ses->tcon_ipc && ses->tcon_ipc->need_reconnect) { 3815 3813 list_add_tail(&ses->tcon_ipc->rlist, &tmp_list); 3816 - tcon_exist = true; 3814 + tcon_selected = tcon_exist = true; 3817 3815 ses->ses_count++; 3818 3816 } 3817 + /* 3818 + * handle the case where channel needs to reconnect 3819 + * binding session, but tcon is healthy (some other channel 3820 + * is active) 3821 + */ 3822 + spin_lock(&ses->chan_lock); 3823 + if (!tcon_selected && cifs_chan_needs_reconnect(ses, server)) { 3824 + list_add_tail(&ses->rlist, &tmp_ses_list); 3825 + ses_exist = true; 3826 + ses->ses_count++; 3827 + } 3828 + spin_unlock(&ses->chan_lock); 3819 3829 } 3820 3830 /* 3821 3831 * Get the reference to server struct to be sure that the last call of 3822 3832 * cifs_put_tcon() in the loop below won't release the server pointer. 3823 3833 */ 3824 - if (tcon_exist) 3834 + if (tcon_exist || ses_exist) 3825 3835 server->srv_count++; 3826 3836 3827 3837 spin_unlock(&cifs_tcp_ses_lock); ··· 3851 3837 cifs_put_tcon(tcon); 3852 3838 } 3853 3839 3854 - cifs_dbg(FYI, "Reconnecting tcons finished\n"); 3840 + if (!ses_exist) 3841 + goto done; 3842 + 3843 + /* allocate a dummy tcon struct used for reconnect */ 3844 + tcon = kzalloc(sizeof(struct cifs_tcon), GFP_KERNEL); 3845 + if (!tcon) { 3846 + resched = true; 3847 + list_del_init(&ses->rlist); 3848 + cifs_put_smb_ses(ses); 3849 + goto done; 3850 + } 3851 + 3852 + tcon->tidStatus = CifsGood; 3853 + tcon->retry = false; 3854 + tcon->need_reconnect = false; 3855 + 3856 + /* now reconnect sessions for necessary channels */ 3857 + list_for_each_entry_safe(ses, ses2, &tmp_ses_list, rlist) { 3858 + tcon->ses = ses; 3859 + rc = smb2_reconnect(SMB2_INTERNAL_CMD, tcon, server); 3860 + if (rc) 3861 + resched = true; 3862 + list_del_init(&ses->rlist); 3863 + cifs_put_smb_ses(ses); 3864 + } 3865 + kfree(tcon); 3866 + 3867 + done: 3868 + cifs_dbg(FYI, "Reconnecting tcons and channels finished\n"); 3855 3869 if (resched) 3856 3870 queue_delayed_work(cifsiod_wq, &server->reconnect, 2 * HZ); 3857 - mutex_unlock(&server->reconnect_mutex); 3871 + mutex_unlock(&pserver->reconnect_mutex); 3858 3872 3859 3873 /* now we can safely release srv struct */ 3860 - if (tcon_exist) 3874 + if (tcon_exist || ses_exist) 3861 3875 cifs_put_tcp_session(server, 1); 3862 3876 } 3863 3877
+6
fs/cifs/smb2transport.c
··· 100 100 goto out; 101 101 102 102 found: 103 + spin_lock(&ses->chan_lock); 103 104 if (cifs_chan_needs_reconnect(ses, server) && 104 105 !CIFS_ALL_CHANS_NEED_RECONNECT(ses)) { 105 106 /* ··· 109 108 * session key 110 109 */ 111 110 memcpy(key, ses->smb3signingkey, SMB3_SIGN_KEY_SIZE); 111 + spin_unlock(&ses->chan_lock); 112 112 goto out; 113 113 } 114 114 ··· 121 119 chan = ses->chans + i; 122 120 if (chan->server == server) { 123 121 memcpy(key, chan->signkey, SMB3_SIGN_KEY_SIZE); 122 + spin_unlock(&ses->chan_lock); 124 123 goto out; 125 124 } 126 125 } 126 + spin_unlock(&ses->chan_lock); 127 127 128 128 cifs_dbg(VFS, 129 129 "%s: Could not find channel signing key for session 0x%llx\n", ··· 434 430 return rc; 435 431 436 432 /* safe to access primary channel, since it will never go away */ 433 + spin_lock(&ses->chan_lock); 437 434 memcpy(ses->chans[0].signkey, ses->smb3signingkey, 438 435 SMB3_SIGN_KEY_SIZE); 436 + spin_unlock(&ses->chan_lock); 439 437 440 438 rc = generate_key(ses, ptriplet->encryption.label, 441 439 ptriplet->encryption.context,
+5 -12
fs/cifs/transport.c
··· 431 431 * socket so the server throws away the partial SMB 432 432 */ 433 433 spin_lock(&cifs_tcp_ses_lock); 434 - server->tcpStatus = CifsNeedReconnect; 434 + if (server->tcpStatus != CifsExiting) 435 + server->tcpStatus = CifsNeedReconnect; 435 436 spin_unlock(&cifs_tcp_ses_lock); 436 437 trace_smb3_partial_send_reconnect(server->CurrentMid, 437 438 server->conn_id, server->hostname); ··· 730 729 struct mid_q_entry **ppmidQ) 731 730 { 732 731 spin_lock(&cifs_tcp_ses_lock); 733 - if (ses->server->tcpStatus == CifsExiting) { 734 - spin_unlock(&cifs_tcp_ses_lock); 735 - return -ENOENT; 736 - } 737 - 738 - if (ses->server->tcpStatus == CifsNeedReconnect) { 739 - spin_unlock(&cifs_tcp_ses_lock); 740 - cifs_dbg(FYI, "tcp session dead - return to caller to retry\n"); 741 - return -EAGAIN; 742 - } 743 - 744 732 if (ses->status == CifsNew) { 745 733 if ((in_buf->Command != SMB_COM_SESSION_SETUP_ANDX) && 746 734 (in_buf->Command != SMB_COM_NEGOTIATE)) { ··· 1049 1059 1050 1060 /* round robin */ 1051 1061 index = (uint)atomic_inc_return(&ses->chan_seq); 1062 + 1063 + spin_lock(&ses->chan_lock); 1052 1064 index %= ses->chan_count; 1065 + spin_unlock(&ses->chan_lock); 1053 1066 1054 1067 return ses->chans[index].server; 1055 1068 }
+1 -1
fs/smbfs_common/smb2pdu.h
··· 449 449 */ 450 450 451 451 /* Flags */ 452 - #define SMB2_ACCEPT_TRANSFORM_LEVEL_SECURITY 0x00000001 452 + #define SMB2_ACCEPT_TRANSPORT_LEVEL_SECURITY 0x00000001 453 453 454 454 struct smb2_transport_capabilities_context { 455 455 __le16 ContextType; /* 6 */
+2
fs/smbfs_common/smbfsctl.h
··· 95 95 #define FSCTL_SET_SHORT_NAME_BEHAVIOR 0x000901B4 /* BB add struct */ 96 96 #define FSCTL_GET_INTEGRITY_INFORMATION 0x0009027C 97 97 #define FSCTL_GET_REFS_VOLUME_DATA 0x000902D8 /* See MS-FSCC 2.3.24 */ 98 + #define FSCTL_SET_INTEGRITY_INFORMATION_EXT 0x00090380 98 99 #define FSCTL_GET_RETRIEVAL_POINTERS_AND_REFCOUNT 0x000903d3 99 100 #define FSCTL_GET_RETRIEVAL_POINTER_COUNT 0x0009042b 101 + #define FSCTL_REFS_STREAM_SNAPSHOT_MANAGEMENT 0x00090440 100 102 #define FSCTL_QUERY_ALLOCATED_RANGES 0x000940CF 101 103 #define FSCTL_SET_DEFECT_MANAGEMENT 0x00098134 /* BB add struct */ 102 104 #define FSCTL_FILE_LEVEL_TRIM 0x00098208 /* BB add struct */