18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * fs/cifs/cifsfs.c 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) International Business Machines Corp., 2002,2008 58c2ecf20Sopenharmony_ci * Author(s): Steve French (sfrench@us.ibm.com) 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Common Internet FileSystem (CIFS) client 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This library is free software; you can redistribute it and/or modify 108c2ecf20Sopenharmony_ci * it under the terms of the GNU Lesser General Public License as published 118c2ecf20Sopenharmony_ci * by the Free Software Foundation; either version 2.1 of the License, or 128c2ecf20Sopenharmony_ci * (at your option) any later version. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * This library is distributed in the hope that it will be useful, 158c2ecf20Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 168c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 178c2ecf20Sopenharmony_ci * the GNU Lesser General Public License for more details. 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * You should have received a copy of the GNU Lesser General Public License 208c2ecf20Sopenharmony_ci * along with this library; if not, write to the Free Software 218c2ecf20Sopenharmony_ci * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci/* Note that BB means BUGBUG (ie something to fix eventually) */ 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include <linux/module.h> 278c2ecf20Sopenharmony_ci#include <linux/fs.h> 288c2ecf20Sopenharmony_ci#include <linux/mount.h> 298c2ecf20Sopenharmony_ci#include <linux/slab.h> 308c2ecf20Sopenharmony_ci#include <linux/init.h> 318c2ecf20Sopenharmony_ci#include <linux/list.h> 328c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 338c2ecf20Sopenharmony_ci#include <linux/vfs.h> 348c2ecf20Sopenharmony_ci#include <linux/mempool.h> 358c2ecf20Sopenharmony_ci#include <linux/delay.h> 368c2ecf20Sopenharmony_ci#include <linux/kthread.h> 378c2ecf20Sopenharmony_ci#include <linux/freezer.h> 388c2ecf20Sopenharmony_ci#include <linux/namei.h> 398c2ecf20Sopenharmony_ci#include <linux/random.h> 408c2ecf20Sopenharmony_ci#include <linux/uuid.h> 418c2ecf20Sopenharmony_ci#include <linux/xattr.h> 428c2ecf20Sopenharmony_ci#include <net/ipv6.h> 438c2ecf20Sopenharmony_ci#include "cifsfs.h" 448c2ecf20Sopenharmony_ci#include "cifspdu.h" 458c2ecf20Sopenharmony_ci#define DECLARE_GLOBALS_HERE 468c2ecf20Sopenharmony_ci#include "cifsglob.h" 478c2ecf20Sopenharmony_ci#include "cifsproto.h" 488c2ecf20Sopenharmony_ci#include "cifs_debug.h" 498c2ecf20Sopenharmony_ci#include "cifs_fs_sb.h" 508c2ecf20Sopenharmony_ci#include <linux/mm.h> 518c2ecf20Sopenharmony_ci#include <linux/key-type.h> 528c2ecf20Sopenharmony_ci#include "cifs_spnego.h" 538c2ecf20Sopenharmony_ci#include "fscache.h" 548c2ecf20Sopenharmony_ci#include "smb2pdu.h" 558c2ecf20Sopenharmony_ci#ifdef CONFIG_CIFS_DFS_UPCALL 568c2ecf20Sopenharmony_ci#include "dfs_cache.h" 578c2ecf20Sopenharmony_ci#endif 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/* 608c2ecf20Sopenharmony_ci * DOS dates from 1980/1/1 through 2107/12/31 618c2ecf20Sopenharmony_ci * Protocol specifications indicate the range should be to 119, which 628c2ecf20Sopenharmony_ci * limits maximum year to 2099. But this range has not been checked. 638c2ecf20Sopenharmony_ci */ 648c2ecf20Sopenharmony_ci#define SMB_DATE_MAX (127<<9 | 12<<5 | 31) 658c2ecf20Sopenharmony_ci#define SMB_DATE_MIN (0<<9 | 1<<5 | 1) 668c2ecf20Sopenharmony_ci#define SMB_TIME_MAX (23<<11 | 59<<5 | 29) 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ciint cifsFYI = 0; 698c2ecf20Sopenharmony_cibool traceSMB; 708c2ecf20Sopenharmony_cibool enable_oplocks = true; 718c2ecf20Sopenharmony_cibool linuxExtEnabled = true; 728c2ecf20Sopenharmony_cibool lookupCacheEnabled = true; 738c2ecf20Sopenharmony_cibool disable_legacy_dialects; /* false by default */ 748c2ecf20Sopenharmony_cibool enable_gcm_256; /* false by default, change when more servers support it */ 758c2ecf20Sopenharmony_cibool require_gcm_256; /* false by default */ 768c2ecf20Sopenharmony_ciunsigned int global_secflags = CIFSSEC_DEF; 778c2ecf20Sopenharmony_ci/* unsigned int ntlmv2_support = 0; */ 788c2ecf20Sopenharmony_ciunsigned int sign_CIFS_PDUs = 1; 798c2ecf20Sopenharmony_cistatic const struct super_operations cifs_super_ops; 808c2ecf20Sopenharmony_ciunsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; 818c2ecf20Sopenharmony_cimodule_param(CIFSMaxBufSize, uint, 0444); 828c2ecf20Sopenharmony_ciMODULE_PARM_DESC(CIFSMaxBufSize, "Network buffer size (not including header) " 838c2ecf20Sopenharmony_ci "for CIFS requests. " 848c2ecf20Sopenharmony_ci "Default: 16384 Range: 8192 to 130048"); 858c2ecf20Sopenharmony_ciunsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL; 868c2ecf20Sopenharmony_cimodule_param(cifs_min_rcv, uint, 0444); 878c2ecf20Sopenharmony_ciMODULE_PARM_DESC(cifs_min_rcv, "Network buffers in pool. Default: 4 Range: " 888c2ecf20Sopenharmony_ci "1 to 64"); 898c2ecf20Sopenharmony_ciunsigned int cifs_min_small = 30; 908c2ecf20Sopenharmony_cimodule_param(cifs_min_small, uint, 0444); 918c2ecf20Sopenharmony_ciMODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 " 928c2ecf20Sopenharmony_ci "Range: 2 to 256"); 938c2ecf20Sopenharmony_ciunsigned int cifs_max_pending = CIFS_MAX_REQ; 948c2ecf20Sopenharmony_cimodule_param(cifs_max_pending, uint, 0444); 958c2ecf20Sopenharmony_ciMODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server for " 968c2ecf20Sopenharmony_ci "CIFS/SMB1 dialect (N/A for SMB3) " 978c2ecf20Sopenharmony_ci "Default: 32767 Range: 2 to 32767."); 988c2ecf20Sopenharmony_ci#ifdef CONFIG_CIFS_STATS2 998c2ecf20Sopenharmony_ciunsigned int slow_rsp_threshold = 1; 1008c2ecf20Sopenharmony_cimodule_param(slow_rsp_threshold, uint, 0644); 1018c2ecf20Sopenharmony_ciMODULE_PARM_DESC(slow_rsp_threshold, "Amount of time (in seconds) to wait " 1028c2ecf20Sopenharmony_ci "before logging that a response is delayed. " 1038c2ecf20Sopenharmony_ci "Default: 1 (if set to 0 disables msg)."); 1048c2ecf20Sopenharmony_ci#endif /* STATS2 */ 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_cimodule_param(enable_oplocks, bool, 0644); 1078c2ecf20Sopenharmony_ciMODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks. Default: y/Y/1"); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cimodule_param(enable_gcm_256, bool, 0644); 1108c2ecf20Sopenharmony_ciMODULE_PARM_DESC(enable_gcm_256, "Enable requesting strongest (256 bit) GCM encryption. Default: n/N/0"); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_cimodule_param(require_gcm_256, bool, 0644); 1138c2ecf20Sopenharmony_ciMODULE_PARM_DESC(require_gcm_256, "Require strongest (256 bit) GCM encryption. Default: n/N/0"); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cimodule_param(disable_legacy_dialects, bool, 0644); 1168c2ecf20Sopenharmony_ciMODULE_PARM_DESC(disable_legacy_dialects, "To improve security it may be " 1178c2ecf20Sopenharmony_ci "helpful to restrict the ability to " 1188c2ecf20Sopenharmony_ci "override the default dialects (SMB2.1, " 1198c2ecf20Sopenharmony_ci "SMB3 and SMB3.02) on mount with old " 1208c2ecf20Sopenharmony_ci "dialects (CIFS/SMB1 and SMB2) since " 1218c2ecf20Sopenharmony_ci "vers=1.0 (CIFS/SMB1) and vers=2.0 are weaker" 1228c2ecf20Sopenharmony_ci " and less secure. Default: n/N/0"); 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ciextern mempool_t *cifs_sm_req_poolp; 1258c2ecf20Sopenharmony_ciextern mempool_t *cifs_req_poolp; 1268c2ecf20Sopenharmony_ciextern mempool_t *cifs_mid_poolp; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistruct workqueue_struct *cifsiod_wq; 1298c2ecf20Sopenharmony_cistruct workqueue_struct *decrypt_wq; 1308c2ecf20Sopenharmony_cistruct workqueue_struct *fileinfo_put_wq; 1318c2ecf20Sopenharmony_cistruct workqueue_struct *cifsoplockd_wq; 1328c2ecf20Sopenharmony_ci__u32 cifs_lock_secret; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci/* 1358c2ecf20Sopenharmony_ci * Bumps refcount for cifs super block. 1368c2ecf20Sopenharmony_ci * Note that it should be only called if a referece to VFS super block is 1378c2ecf20Sopenharmony_ci * already held, e.g. in open-type syscalls context. Otherwise it can race with 1388c2ecf20Sopenharmony_ci * atomic_dec_and_test in deactivate_locked_super. 1398c2ecf20Sopenharmony_ci */ 1408c2ecf20Sopenharmony_civoid 1418c2ecf20Sopenharmony_cicifs_sb_active(struct super_block *sb) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci struct cifs_sb_info *server = CIFS_SB(sb); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci if (atomic_inc_return(&server->active) == 1) 1468c2ecf20Sopenharmony_ci atomic_inc(&sb->s_active); 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_civoid 1508c2ecf20Sopenharmony_cicifs_sb_deactive(struct super_block *sb) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci struct cifs_sb_info *server = CIFS_SB(sb); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci if (atomic_dec_and_test(&server->active)) 1558c2ecf20Sopenharmony_ci deactivate_super(sb); 1568c2ecf20Sopenharmony_ci} 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistatic int 1598c2ecf20Sopenharmony_cicifs_read_super(struct super_block *sb) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci struct inode *inode; 1628c2ecf20Sopenharmony_ci struct cifs_sb_info *cifs_sb; 1638c2ecf20Sopenharmony_ci struct cifs_tcon *tcon; 1648c2ecf20Sopenharmony_ci struct timespec64 ts; 1658c2ecf20Sopenharmony_ci int rc = 0; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci cifs_sb = CIFS_SB(sb); 1688c2ecf20Sopenharmony_ci tcon = cifs_sb_master_tcon(cifs_sb); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL) 1718c2ecf20Sopenharmony_ci sb->s_flags |= SB_POSIXACL; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci if (tcon->snapshot_time) 1748c2ecf20Sopenharmony_ci sb->s_flags |= SB_RDONLY; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci if (tcon->ses->capabilities & tcon->ses->server->vals->cap_large_files) 1778c2ecf20Sopenharmony_ci sb->s_maxbytes = MAX_LFS_FILESIZE; 1788c2ecf20Sopenharmony_ci else 1798c2ecf20Sopenharmony_ci sb->s_maxbytes = MAX_NON_LFS; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci /* 1828c2ecf20Sopenharmony_ci * Some very old servers like DOS and OS/2 used 2 second granularity 1838c2ecf20Sopenharmony_ci * (while all current servers use 100ns granularity - see MS-DTYP) 1848c2ecf20Sopenharmony_ci * but 1 second is the maximum allowed granularity for the VFS 1858c2ecf20Sopenharmony_ci * so for old servers set time granularity to 1 second while for 1868c2ecf20Sopenharmony_ci * everything else (current servers) set it to 100ns. 1878c2ecf20Sopenharmony_ci */ 1888c2ecf20Sopenharmony_ci if ((tcon->ses->server->vals->protocol_id == SMB10_PROT_ID) && 1898c2ecf20Sopenharmony_ci ((tcon->ses->capabilities & 1908c2ecf20Sopenharmony_ci tcon->ses->server->vals->cap_nt_find) == 0) && 1918c2ecf20Sopenharmony_ci !tcon->unix_ext) { 1928c2ecf20Sopenharmony_ci sb->s_time_gran = 1000000000; /* 1 second is max allowed gran */ 1938c2ecf20Sopenharmony_ci ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MIN), 0, 0); 1948c2ecf20Sopenharmony_ci sb->s_time_min = ts.tv_sec; 1958c2ecf20Sopenharmony_ci ts = cnvrtDosUnixTm(cpu_to_le16(SMB_DATE_MAX), 1968c2ecf20Sopenharmony_ci cpu_to_le16(SMB_TIME_MAX), 0); 1978c2ecf20Sopenharmony_ci sb->s_time_max = ts.tv_sec; 1988c2ecf20Sopenharmony_ci } else { 1998c2ecf20Sopenharmony_ci /* 2008c2ecf20Sopenharmony_ci * Almost every server, including all SMB2+, uses DCE TIME 2018c2ecf20Sopenharmony_ci * ie 100 nanosecond units, since 1601. See MS-DTYP and MS-FSCC 2028c2ecf20Sopenharmony_ci */ 2038c2ecf20Sopenharmony_ci sb->s_time_gran = 100; 2048c2ecf20Sopenharmony_ci ts = cifs_NTtimeToUnix(0); 2058c2ecf20Sopenharmony_ci sb->s_time_min = ts.tv_sec; 2068c2ecf20Sopenharmony_ci ts = cifs_NTtimeToUnix(cpu_to_le64(S64_MAX)); 2078c2ecf20Sopenharmony_ci sb->s_time_max = ts.tv_sec; 2088c2ecf20Sopenharmony_ci } 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci sb->s_magic = CIFS_MAGIC_NUMBER; 2118c2ecf20Sopenharmony_ci sb->s_op = &cifs_super_ops; 2128c2ecf20Sopenharmony_ci sb->s_xattr = cifs_xattr_handlers; 2138c2ecf20Sopenharmony_ci rc = super_setup_bdi(sb); 2148c2ecf20Sopenharmony_ci if (rc) 2158c2ecf20Sopenharmony_ci goto out_no_root; 2168c2ecf20Sopenharmony_ci /* tune readahead according to rsize */ 2178c2ecf20Sopenharmony_ci sb->s_bdi->ra_pages = cifs_sb->rsize / PAGE_SIZE; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci sb->s_blocksize = CIFS_MAX_MSGSIZE; 2208c2ecf20Sopenharmony_ci sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ 2218c2ecf20Sopenharmony_ci inode = cifs_root_iget(sb); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci if (IS_ERR(inode)) { 2248c2ecf20Sopenharmony_ci rc = PTR_ERR(inode); 2258c2ecf20Sopenharmony_ci goto out_no_root; 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci if (tcon->nocase) 2298c2ecf20Sopenharmony_ci sb->s_d_op = &cifs_ci_dentry_ops; 2308c2ecf20Sopenharmony_ci else 2318c2ecf20Sopenharmony_ci sb->s_d_op = &cifs_dentry_ops; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci sb->s_root = d_make_root(inode); 2348c2ecf20Sopenharmony_ci if (!sb->s_root) { 2358c2ecf20Sopenharmony_ci rc = -ENOMEM; 2368c2ecf20Sopenharmony_ci goto out_no_root; 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci#ifdef CONFIG_CIFS_NFSD_EXPORT 2408c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { 2418c2ecf20Sopenharmony_ci cifs_dbg(FYI, "export ops supported\n"); 2428c2ecf20Sopenharmony_ci sb->s_export_op = &cifs_export_ops; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci#endif /* CONFIG_CIFS_NFSD_EXPORT */ 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci return 0; 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ciout_no_root: 2498c2ecf20Sopenharmony_ci cifs_dbg(VFS, "%s: get root inode failed\n", __func__); 2508c2ecf20Sopenharmony_ci return rc; 2518c2ecf20Sopenharmony_ci} 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_cistatic void cifs_kill_sb(struct super_block *sb) 2548c2ecf20Sopenharmony_ci{ 2558c2ecf20Sopenharmony_ci struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 2568c2ecf20Sopenharmony_ci kill_anon_super(sb); 2578c2ecf20Sopenharmony_ci cifs_umount(cifs_sb); 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistatic int 2618c2ecf20Sopenharmony_cicifs_statfs(struct dentry *dentry, struct kstatfs *buf) 2628c2ecf20Sopenharmony_ci{ 2638c2ecf20Sopenharmony_ci struct super_block *sb = dentry->d_sb; 2648c2ecf20Sopenharmony_ci struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 2658c2ecf20Sopenharmony_ci struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 2668c2ecf20Sopenharmony_ci struct TCP_Server_Info *server = tcon->ses->server; 2678c2ecf20Sopenharmony_ci unsigned int xid; 2688c2ecf20Sopenharmony_ci int rc = 0; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci xid = get_xid(); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci if (le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength) > 0) 2738c2ecf20Sopenharmony_ci buf->f_namelen = 2748c2ecf20Sopenharmony_ci le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength); 2758c2ecf20Sopenharmony_ci else 2768c2ecf20Sopenharmony_ci buf->f_namelen = PATH_MAX; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci buf->f_fsid.val[0] = tcon->vol_serial_number; 2798c2ecf20Sopenharmony_ci /* are using part of create time for more randomness, see man statfs */ 2808c2ecf20Sopenharmony_ci buf->f_fsid.val[1] = (int)le64_to_cpu(tcon->vol_create_time); 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci buf->f_files = 0; /* undefined */ 2838c2ecf20Sopenharmony_ci buf->f_ffree = 0; /* unlimited */ 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci if (server->ops->queryfs) 2868c2ecf20Sopenharmony_ci rc = server->ops->queryfs(xid, tcon, cifs_sb, buf); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci free_xid(xid); 2898c2ecf20Sopenharmony_ci return rc; 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistatic long cifs_fallocate(struct file *file, int mode, loff_t off, loff_t len) 2938c2ecf20Sopenharmony_ci{ 2948c2ecf20Sopenharmony_ci struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file); 2958c2ecf20Sopenharmony_ci struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 2968c2ecf20Sopenharmony_ci struct TCP_Server_Info *server = tcon->ses->server; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci if (server->ops->fallocate) 2998c2ecf20Sopenharmony_ci return server->ops->fallocate(file, tcon, mode, off, len); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic int cifs_permission(struct inode *inode, int mask) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci struct cifs_sb_info *cifs_sb; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci cifs_sb = CIFS_SB(inode->i_sb); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { 3118c2ecf20Sopenharmony_ci if ((mask & MAY_EXEC) && !execute_ok(inode)) 3128c2ecf20Sopenharmony_ci return -EACCES; 3138c2ecf20Sopenharmony_ci else 3148c2ecf20Sopenharmony_ci return 0; 3158c2ecf20Sopenharmony_ci } else /* file mode might have been restricted at mount time 3168c2ecf20Sopenharmony_ci on the client (above and beyond ACL on servers) for 3178c2ecf20Sopenharmony_ci servers which do not support setting and viewing mode bits, 3188c2ecf20Sopenharmony_ci so allowing client to check permissions is useful */ 3198c2ecf20Sopenharmony_ci return generic_permission(inode, mask); 3208c2ecf20Sopenharmony_ci} 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_cistatic struct kmem_cache *cifs_inode_cachep; 3238c2ecf20Sopenharmony_cistatic struct kmem_cache *cifs_req_cachep; 3248c2ecf20Sopenharmony_cistatic struct kmem_cache *cifs_mid_cachep; 3258c2ecf20Sopenharmony_cistatic struct kmem_cache *cifs_sm_req_cachep; 3268c2ecf20Sopenharmony_cimempool_t *cifs_sm_req_poolp; 3278c2ecf20Sopenharmony_cimempool_t *cifs_req_poolp; 3288c2ecf20Sopenharmony_cimempool_t *cifs_mid_poolp; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_cistatic struct inode * 3318c2ecf20Sopenharmony_cicifs_alloc_inode(struct super_block *sb) 3328c2ecf20Sopenharmony_ci{ 3338c2ecf20Sopenharmony_ci struct cifsInodeInfo *cifs_inode; 3348c2ecf20Sopenharmony_ci cifs_inode = kmem_cache_alloc(cifs_inode_cachep, GFP_KERNEL); 3358c2ecf20Sopenharmony_ci if (!cifs_inode) 3368c2ecf20Sopenharmony_ci return NULL; 3378c2ecf20Sopenharmony_ci cifs_inode->cifsAttrs = 0x20; /* default */ 3388c2ecf20Sopenharmony_ci cifs_inode->time = 0; 3398c2ecf20Sopenharmony_ci /* 3408c2ecf20Sopenharmony_ci * Until the file is open and we have gotten oplock info back from the 3418c2ecf20Sopenharmony_ci * server, can not assume caching of file data or metadata. 3428c2ecf20Sopenharmony_ci */ 3438c2ecf20Sopenharmony_ci cifs_set_oplock_level(cifs_inode, 0); 3448c2ecf20Sopenharmony_ci cifs_inode->flags = 0; 3458c2ecf20Sopenharmony_ci spin_lock_init(&cifs_inode->writers_lock); 3468c2ecf20Sopenharmony_ci cifs_inode->writers = 0; 3478c2ecf20Sopenharmony_ci cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ 3488c2ecf20Sopenharmony_ci cifs_inode->server_eof = 0; 3498c2ecf20Sopenharmony_ci cifs_inode->uniqueid = 0; 3508c2ecf20Sopenharmony_ci cifs_inode->createtime = 0; 3518c2ecf20Sopenharmony_ci cifs_inode->epoch = 0; 3528c2ecf20Sopenharmony_ci spin_lock_init(&cifs_inode->open_file_lock); 3538c2ecf20Sopenharmony_ci generate_random_uuid(cifs_inode->lease_key); 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci /* 3568c2ecf20Sopenharmony_ci * Can not set i_flags here - they get immediately overwritten to zero 3578c2ecf20Sopenharmony_ci * by the VFS. 3588c2ecf20Sopenharmony_ci */ 3598c2ecf20Sopenharmony_ci /* cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME; */ 3608c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&cifs_inode->openFileList); 3618c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&cifs_inode->llist); 3628c2ecf20Sopenharmony_ci return &cifs_inode->vfs_inode; 3638c2ecf20Sopenharmony_ci} 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_cistatic void 3668c2ecf20Sopenharmony_cicifs_free_inode(struct inode *inode) 3678c2ecf20Sopenharmony_ci{ 3688c2ecf20Sopenharmony_ci kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); 3698c2ecf20Sopenharmony_ci} 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_cistatic void 3728c2ecf20Sopenharmony_cicifs_evict_inode(struct inode *inode) 3738c2ecf20Sopenharmony_ci{ 3748c2ecf20Sopenharmony_ci truncate_inode_pages_final(&inode->i_data); 3758c2ecf20Sopenharmony_ci clear_inode(inode); 3768c2ecf20Sopenharmony_ci cifs_fscache_release_inode_cookie(inode); 3778c2ecf20Sopenharmony_ci} 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_cistatic void 3808c2ecf20Sopenharmony_cicifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci struct sockaddr_in *sa = (struct sockaddr_in *) &server->dstaddr; 3838c2ecf20Sopenharmony_ci struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *) &server->dstaddr; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci seq_puts(s, ",addr="); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci switch (server->dstaddr.ss_family) { 3888c2ecf20Sopenharmony_ci case AF_INET: 3898c2ecf20Sopenharmony_ci seq_printf(s, "%pI4", &sa->sin_addr.s_addr); 3908c2ecf20Sopenharmony_ci break; 3918c2ecf20Sopenharmony_ci case AF_INET6: 3928c2ecf20Sopenharmony_ci seq_printf(s, "%pI6", &sa6->sin6_addr.s6_addr); 3938c2ecf20Sopenharmony_ci if (sa6->sin6_scope_id) 3948c2ecf20Sopenharmony_ci seq_printf(s, "%%%u", sa6->sin6_scope_id); 3958c2ecf20Sopenharmony_ci break; 3968c2ecf20Sopenharmony_ci default: 3978c2ecf20Sopenharmony_ci seq_puts(s, "(unknown)"); 3988c2ecf20Sopenharmony_ci } 3998c2ecf20Sopenharmony_ci if (server->rdma) 4008c2ecf20Sopenharmony_ci seq_puts(s, ",rdma"); 4018c2ecf20Sopenharmony_ci} 4028c2ecf20Sopenharmony_ci 4038c2ecf20Sopenharmony_cistatic void 4048c2ecf20Sopenharmony_cicifs_show_security(struct seq_file *s, struct cifs_ses *ses) 4058c2ecf20Sopenharmony_ci{ 4068c2ecf20Sopenharmony_ci if (ses->sectype == Unspecified) { 4078c2ecf20Sopenharmony_ci if (ses->user_name == NULL) 4088c2ecf20Sopenharmony_ci seq_puts(s, ",sec=none"); 4098c2ecf20Sopenharmony_ci return; 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci seq_puts(s, ",sec="); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci switch (ses->sectype) { 4158c2ecf20Sopenharmony_ci case LANMAN: 4168c2ecf20Sopenharmony_ci seq_puts(s, "lanman"); 4178c2ecf20Sopenharmony_ci break; 4188c2ecf20Sopenharmony_ci case NTLMv2: 4198c2ecf20Sopenharmony_ci seq_puts(s, "ntlmv2"); 4208c2ecf20Sopenharmony_ci break; 4218c2ecf20Sopenharmony_ci case NTLM: 4228c2ecf20Sopenharmony_ci seq_puts(s, "ntlm"); 4238c2ecf20Sopenharmony_ci break; 4248c2ecf20Sopenharmony_ci case Kerberos: 4258c2ecf20Sopenharmony_ci seq_puts(s, "krb5"); 4268c2ecf20Sopenharmony_ci break; 4278c2ecf20Sopenharmony_ci case RawNTLMSSP: 4288c2ecf20Sopenharmony_ci seq_puts(s, "ntlmssp"); 4298c2ecf20Sopenharmony_ci break; 4308c2ecf20Sopenharmony_ci default: 4318c2ecf20Sopenharmony_ci /* shouldn't ever happen */ 4328c2ecf20Sopenharmony_ci seq_puts(s, "unknown"); 4338c2ecf20Sopenharmony_ci break; 4348c2ecf20Sopenharmony_ci } 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci if (ses->sign) 4378c2ecf20Sopenharmony_ci seq_puts(s, "i"); 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci if (ses->sectype == Kerberos) 4408c2ecf20Sopenharmony_ci seq_printf(s, ",cruid=%u", 4418c2ecf20Sopenharmony_ci from_kuid_munged(&init_user_ns, ses->cred_uid)); 4428c2ecf20Sopenharmony_ci} 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_cistatic void 4458c2ecf20Sopenharmony_cicifs_show_cache_flavor(struct seq_file *s, struct cifs_sb_info *cifs_sb) 4468c2ecf20Sopenharmony_ci{ 4478c2ecf20Sopenharmony_ci seq_puts(s, ",cache="); 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) 4508c2ecf20Sopenharmony_ci seq_puts(s, "strict"); 4518c2ecf20Sopenharmony_ci else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) 4528c2ecf20Sopenharmony_ci seq_puts(s, "none"); 4538c2ecf20Sopenharmony_ci else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RW_CACHE) 4548c2ecf20Sopenharmony_ci seq_puts(s, "singleclient"); /* assume only one client access */ 4558c2ecf20Sopenharmony_ci else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RO_CACHE) 4568c2ecf20Sopenharmony_ci seq_puts(s, "ro"); /* read only caching assumed */ 4578c2ecf20Sopenharmony_ci else 4588c2ecf20Sopenharmony_ci seq_puts(s, "loose"); 4598c2ecf20Sopenharmony_ci} 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_cistatic void 4628c2ecf20Sopenharmony_cicifs_show_nls(struct seq_file *s, struct nls_table *cur) 4638c2ecf20Sopenharmony_ci{ 4648c2ecf20Sopenharmony_ci struct nls_table *def; 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci /* Display iocharset= option if it's not default charset */ 4678c2ecf20Sopenharmony_ci def = load_nls_default(); 4688c2ecf20Sopenharmony_ci if (def != cur) 4698c2ecf20Sopenharmony_ci seq_printf(s, ",iocharset=%s", cur->charset); 4708c2ecf20Sopenharmony_ci unload_nls(def); 4718c2ecf20Sopenharmony_ci} 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci/* 4748c2ecf20Sopenharmony_ci * cifs_show_options() is for displaying mount options in /proc/mounts. 4758c2ecf20Sopenharmony_ci * Not all settable options are displayed but most of the important 4768c2ecf20Sopenharmony_ci * ones are. 4778c2ecf20Sopenharmony_ci */ 4788c2ecf20Sopenharmony_cistatic int 4798c2ecf20Sopenharmony_cicifs_show_options(struct seq_file *s, struct dentry *root) 4808c2ecf20Sopenharmony_ci{ 4818c2ecf20Sopenharmony_ci struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb); 4828c2ecf20Sopenharmony_ci struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); 4838c2ecf20Sopenharmony_ci struct sockaddr *srcaddr; 4848c2ecf20Sopenharmony_ci srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr; 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci seq_show_option(s, "vers", tcon->ses->server->vals->version_string); 4878c2ecf20Sopenharmony_ci cifs_show_security(s, tcon->ses); 4888c2ecf20Sopenharmony_ci cifs_show_cache_flavor(s, cifs_sb); 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci if (tcon->no_lease) 4918c2ecf20Sopenharmony_ci seq_puts(s, ",nolease"); 4928c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) 4938c2ecf20Sopenharmony_ci seq_puts(s, ",multiuser"); 4948c2ecf20Sopenharmony_ci else if (tcon->ses->user_name) 4958c2ecf20Sopenharmony_ci seq_show_option(s, "username", tcon->ses->user_name); 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci if (tcon->ses->domainName && tcon->ses->domainName[0] != 0) 4988c2ecf20Sopenharmony_ci seq_show_option(s, "domain", tcon->ses->domainName); 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci if (srcaddr->sa_family != AF_UNSPEC) { 5018c2ecf20Sopenharmony_ci struct sockaddr_in *saddr4; 5028c2ecf20Sopenharmony_ci struct sockaddr_in6 *saddr6; 5038c2ecf20Sopenharmony_ci saddr4 = (struct sockaddr_in *)srcaddr; 5048c2ecf20Sopenharmony_ci saddr6 = (struct sockaddr_in6 *)srcaddr; 5058c2ecf20Sopenharmony_ci if (srcaddr->sa_family == AF_INET6) 5068c2ecf20Sopenharmony_ci seq_printf(s, ",srcaddr=%pI6c", 5078c2ecf20Sopenharmony_ci &saddr6->sin6_addr); 5088c2ecf20Sopenharmony_ci else if (srcaddr->sa_family == AF_INET) 5098c2ecf20Sopenharmony_ci seq_printf(s, ",srcaddr=%pI4", 5108c2ecf20Sopenharmony_ci &saddr4->sin_addr.s_addr); 5118c2ecf20Sopenharmony_ci else 5128c2ecf20Sopenharmony_ci seq_printf(s, ",srcaddr=BAD-AF:%i", 5138c2ecf20Sopenharmony_ci (int)(srcaddr->sa_family)); 5148c2ecf20Sopenharmony_ci } 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ci seq_printf(s, ",uid=%u", 5178c2ecf20Sopenharmony_ci from_kuid_munged(&init_user_ns, cifs_sb->mnt_uid)); 5188c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) 5198c2ecf20Sopenharmony_ci seq_puts(s, ",forceuid"); 5208c2ecf20Sopenharmony_ci else 5218c2ecf20Sopenharmony_ci seq_puts(s, ",noforceuid"); 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci seq_printf(s, ",gid=%u", 5248c2ecf20Sopenharmony_ci from_kgid_munged(&init_user_ns, cifs_sb->mnt_gid)); 5258c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) 5268c2ecf20Sopenharmony_ci seq_puts(s, ",forcegid"); 5278c2ecf20Sopenharmony_ci else 5288c2ecf20Sopenharmony_ci seq_puts(s, ",noforcegid"); 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci cifs_show_address(s, tcon->ses->server); 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci if (!tcon->unix_ext) 5338c2ecf20Sopenharmony_ci seq_printf(s, ",file_mode=0%ho,dir_mode=0%ho", 5348c2ecf20Sopenharmony_ci cifs_sb->mnt_file_mode, 5358c2ecf20Sopenharmony_ci cifs_sb->mnt_dir_mode); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci cifs_show_nls(s, cifs_sb->local_nls); 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci if (tcon->seal) 5408c2ecf20Sopenharmony_ci seq_puts(s, ",seal"); 5418c2ecf20Sopenharmony_ci else if (tcon->ses->server->ignore_signature) 5428c2ecf20Sopenharmony_ci seq_puts(s, ",signloosely"); 5438c2ecf20Sopenharmony_ci if (tcon->nocase) 5448c2ecf20Sopenharmony_ci seq_puts(s, ",nocase"); 5458c2ecf20Sopenharmony_ci if (tcon->nodelete) 5468c2ecf20Sopenharmony_ci seq_puts(s, ",nodelete"); 5478c2ecf20Sopenharmony_ci if (tcon->local_lease) 5488c2ecf20Sopenharmony_ci seq_puts(s, ",locallease"); 5498c2ecf20Sopenharmony_ci if (tcon->retry) 5508c2ecf20Sopenharmony_ci seq_puts(s, ",hard"); 5518c2ecf20Sopenharmony_ci else 5528c2ecf20Sopenharmony_ci seq_puts(s, ",soft"); 5538c2ecf20Sopenharmony_ci if (tcon->use_persistent) 5548c2ecf20Sopenharmony_ci seq_puts(s, ",persistenthandles"); 5558c2ecf20Sopenharmony_ci else if (tcon->use_resilient) 5568c2ecf20Sopenharmony_ci seq_puts(s, ",resilienthandles"); 5578c2ecf20Sopenharmony_ci if (tcon->posix_extensions) 5588c2ecf20Sopenharmony_ci seq_puts(s, ",posix"); 5598c2ecf20Sopenharmony_ci else if (tcon->unix_ext) 5608c2ecf20Sopenharmony_ci seq_puts(s, ",unix"); 5618c2ecf20Sopenharmony_ci else 5628c2ecf20Sopenharmony_ci seq_puts(s, ",nounix"); 5638c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_DFS) 5648c2ecf20Sopenharmony_ci seq_puts(s, ",nodfs"); 5658c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) 5668c2ecf20Sopenharmony_ci seq_puts(s, ",posixpaths"); 5678c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) 5688c2ecf20Sopenharmony_ci seq_puts(s, ",setuids"); 5698c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL) 5708c2ecf20Sopenharmony_ci seq_puts(s, ",idsfromsid"); 5718c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) 5728c2ecf20Sopenharmony_ci seq_puts(s, ",serverino"); 5738c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) 5748c2ecf20Sopenharmony_ci seq_puts(s, ",rwpidforward"); 5758c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) 5768c2ecf20Sopenharmony_ci seq_puts(s, ",forcemand"); 5778c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 5788c2ecf20Sopenharmony_ci seq_puts(s, ",nouser_xattr"); 5798c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) 5808c2ecf20Sopenharmony_ci seq_puts(s, ",mapchars"); 5818c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SFM_CHR) 5828c2ecf20Sopenharmony_ci seq_puts(s, ",mapposix"); 5838c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) 5848c2ecf20Sopenharmony_ci seq_puts(s, ",sfu"); 5858c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 5868c2ecf20Sopenharmony_ci seq_puts(s, ",nobrl"); 5878c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_HANDLE_CACHE) 5888c2ecf20Sopenharmony_ci seq_puts(s, ",nohandlecache"); 5898c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MODE_FROM_SID) 5908c2ecf20Sopenharmony_ci seq_puts(s, ",modefromsid"); 5918c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) 5928c2ecf20Sopenharmony_ci seq_puts(s, ",cifsacl"); 5938c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) 5948c2ecf20Sopenharmony_ci seq_puts(s, ",dynperm"); 5958c2ecf20Sopenharmony_ci if (root->d_sb->s_flags & SB_POSIXACL) 5968c2ecf20Sopenharmony_ci seq_puts(s, ",acl"); 5978c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) 5988c2ecf20Sopenharmony_ci seq_puts(s, ",mfsymlinks"); 5998c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) 6008c2ecf20Sopenharmony_ci seq_puts(s, ",fsc"); 6018c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC) 6028c2ecf20Sopenharmony_ci seq_puts(s, ",nostrictsync"); 6038c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) 6048c2ecf20Sopenharmony_ci seq_puts(s, ",noperm"); 6058c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) 6068c2ecf20Sopenharmony_ci seq_printf(s, ",backupuid=%u", 6078c2ecf20Sopenharmony_ci from_kuid_munged(&init_user_ns, 6088c2ecf20Sopenharmony_ci cifs_sb->mnt_backupuid)); 6098c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) 6108c2ecf20Sopenharmony_ci seq_printf(s, ",backupgid=%u", 6118c2ecf20Sopenharmony_ci from_kgid_munged(&init_user_ns, 6128c2ecf20Sopenharmony_ci cifs_sb->mnt_backupgid)); 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_ci seq_printf(s, ",rsize=%u", cifs_sb->rsize); 6158c2ecf20Sopenharmony_ci seq_printf(s, ",wsize=%u", cifs_sb->wsize); 6168c2ecf20Sopenharmony_ci seq_printf(s, ",bsize=%u", cifs_sb->bsize); 6178c2ecf20Sopenharmony_ci if (tcon->ses->server->min_offload) 6188c2ecf20Sopenharmony_ci seq_printf(s, ",esize=%u", tcon->ses->server->min_offload); 6198c2ecf20Sopenharmony_ci seq_printf(s, ",echo_interval=%lu", 6208c2ecf20Sopenharmony_ci tcon->ses->server->echo_interval / HZ); 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci /* Only display the following if overridden on mount */ 6238c2ecf20Sopenharmony_ci if (tcon->ses->server->max_credits != SMB2_MAX_CREDITS_AVAILABLE) 6248c2ecf20Sopenharmony_ci seq_printf(s, ",max_credits=%u", tcon->ses->server->max_credits); 6258c2ecf20Sopenharmony_ci if (tcon->ses->server->tcp_nodelay) 6268c2ecf20Sopenharmony_ci seq_puts(s, ",tcpnodelay"); 6278c2ecf20Sopenharmony_ci if (tcon->ses->server->noautotune) 6288c2ecf20Sopenharmony_ci seq_puts(s, ",noautotune"); 6298c2ecf20Sopenharmony_ci if (tcon->ses->server->noblocksnd) 6308c2ecf20Sopenharmony_ci seq_puts(s, ",noblocksend"); 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci if (tcon->snapshot_time) 6338c2ecf20Sopenharmony_ci seq_printf(s, ",snapshot=%llu", tcon->snapshot_time); 6348c2ecf20Sopenharmony_ci if (tcon->handle_timeout) 6358c2ecf20Sopenharmony_ci seq_printf(s, ",handletimeout=%u", tcon->handle_timeout); 6368c2ecf20Sopenharmony_ci /* convert actimeo and display it in seconds */ 6378c2ecf20Sopenharmony_ci seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ); 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci if (tcon->ses->chan_max > 1) 6408c2ecf20Sopenharmony_ci seq_printf(s, ",multichannel,max_channels=%zu", 6418c2ecf20Sopenharmony_ci tcon->ses->chan_max); 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci return 0; 6448c2ecf20Sopenharmony_ci} 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_cistatic void cifs_umount_begin(struct super_block *sb) 6478c2ecf20Sopenharmony_ci{ 6488c2ecf20Sopenharmony_ci struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 6498c2ecf20Sopenharmony_ci struct cifs_tcon *tcon; 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci if (cifs_sb == NULL) 6528c2ecf20Sopenharmony_ci return; 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci tcon = cifs_sb_master_tcon(cifs_sb); 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci spin_lock(&cifs_tcp_ses_lock); 6578c2ecf20Sopenharmony_ci if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) { 6588c2ecf20Sopenharmony_ci /* we have other mounts to same share or we have 6598c2ecf20Sopenharmony_ci already tried to force umount this and woken up 6608c2ecf20Sopenharmony_ci all waiting network requests, nothing to do */ 6618c2ecf20Sopenharmony_ci spin_unlock(&cifs_tcp_ses_lock); 6628c2ecf20Sopenharmony_ci return; 6638c2ecf20Sopenharmony_ci } else if (tcon->tc_count == 1) 6648c2ecf20Sopenharmony_ci tcon->tidStatus = CifsExiting; 6658c2ecf20Sopenharmony_ci spin_unlock(&cifs_tcp_ses_lock); 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci /* cancel_brl_requests(tcon); */ /* BB mark all brl mids as exiting */ 6688c2ecf20Sopenharmony_ci /* cancel_notify_requests(tcon); */ 6698c2ecf20Sopenharmony_ci if (tcon->ses && tcon->ses->server) { 6708c2ecf20Sopenharmony_ci cifs_dbg(FYI, "wake up tasks now - umount begin not complete\n"); 6718c2ecf20Sopenharmony_ci wake_up_all(&tcon->ses->server->request_q); 6728c2ecf20Sopenharmony_ci wake_up_all(&tcon->ses->server->response_q); 6738c2ecf20Sopenharmony_ci msleep(1); /* yield */ 6748c2ecf20Sopenharmony_ci /* we have to kick the requests once more */ 6758c2ecf20Sopenharmony_ci wake_up_all(&tcon->ses->server->response_q); 6768c2ecf20Sopenharmony_ci msleep(1); 6778c2ecf20Sopenharmony_ci } 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci return; 6808c2ecf20Sopenharmony_ci} 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci#ifdef CONFIG_CIFS_STATS2 6838c2ecf20Sopenharmony_cistatic int cifs_show_stats(struct seq_file *s, struct dentry *root) 6848c2ecf20Sopenharmony_ci{ 6858c2ecf20Sopenharmony_ci /* BB FIXME */ 6868c2ecf20Sopenharmony_ci return 0; 6878c2ecf20Sopenharmony_ci} 6888c2ecf20Sopenharmony_ci#endif 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_cistatic int cifs_remount(struct super_block *sb, int *flags, char *data) 6918c2ecf20Sopenharmony_ci{ 6928c2ecf20Sopenharmony_ci sync_filesystem(sb); 6938c2ecf20Sopenharmony_ci *flags |= SB_NODIRATIME; 6948c2ecf20Sopenharmony_ci return 0; 6958c2ecf20Sopenharmony_ci} 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_cistatic int cifs_drop_inode(struct inode *inode) 6988c2ecf20Sopenharmony_ci{ 6998c2ecf20Sopenharmony_ci struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci /* no serverino => unconditional eviction */ 7028c2ecf20Sopenharmony_ci return !(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) || 7038c2ecf20Sopenharmony_ci generic_drop_inode(inode); 7048c2ecf20Sopenharmony_ci} 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_cistatic const struct super_operations cifs_super_ops = { 7078c2ecf20Sopenharmony_ci .statfs = cifs_statfs, 7088c2ecf20Sopenharmony_ci .alloc_inode = cifs_alloc_inode, 7098c2ecf20Sopenharmony_ci .free_inode = cifs_free_inode, 7108c2ecf20Sopenharmony_ci .drop_inode = cifs_drop_inode, 7118c2ecf20Sopenharmony_ci .evict_inode = cifs_evict_inode, 7128c2ecf20Sopenharmony_ci/* .delete_inode = cifs_delete_inode, */ /* Do not need above 7138c2ecf20Sopenharmony_ci function unless later we add lazy close of inodes or unless the 7148c2ecf20Sopenharmony_ci kernel forgets to call us with the same number of releases (closes) 7158c2ecf20Sopenharmony_ci as opens */ 7168c2ecf20Sopenharmony_ci .show_options = cifs_show_options, 7178c2ecf20Sopenharmony_ci .umount_begin = cifs_umount_begin, 7188c2ecf20Sopenharmony_ci .remount_fs = cifs_remount, 7198c2ecf20Sopenharmony_ci#ifdef CONFIG_CIFS_STATS2 7208c2ecf20Sopenharmony_ci .show_stats = cifs_show_stats, 7218c2ecf20Sopenharmony_ci#endif 7228c2ecf20Sopenharmony_ci}; 7238c2ecf20Sopenharmony_ci 7248c2ecf20Sopenharmony_ci/* 7258c2ecf20Sopenharmony_ci * Get root dentry from superblock according to prefix path mount option. 7268c2ecf20Sopenharmony_ci * Return dentry with refcount + 1 on success and NULL otherwise. 7278c2ecf20Sopenharmony_ci */ 7288c2ecf20Sopenharmony_cistatic struct dentry * 7298c2ecf20Sopenharmony_cicifs_get_root(struct smb_vol *vol, struct super_block *sb) 7308c2ecf20Sopenharmony_ci{ 7318c2ecf20Sopenharmony_ci struct dentry *dentry; 7328c2ecf20Sopenharmony_ci struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 7338c2ecf20Sopenharmony_ci char *full_path = NULL; 7348c2ecf20Sopenharmony_ci char *s, *p; 7358c2ecf20Sopenharmony_ci char sep; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH) 7388c2ecf20Sopenharmony_ci return dget(sb->s_root); 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci full_path = cifs_build_path_to_root(vol, cifs_sb, 7418c2ecf20Sopenharmony_ci cifs_sb_master_tcon(cifs_sb), 0); 7428c2ecf20Sopenharmony_ci if (full_path == NULL) 7438c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 7448c2ecf20Sopenharmony_ci 7458c2ecf20Sopenharmony_ci cifs_dbg(FYI, "Get root dentry for %s\n", full_path); 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci sep = CIFS_DIR_SEP(cifs_sb); 7488c2ecf20Sopenharmony_ci dentry = dget(sb->s_root); 7498c2ecf20Sopenharmony_ci p = s = full_path; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci do { 7528c2ecf20Sopenharmony_ci struct inode *dir = d_inode(dentry); 7538c2ecf20Sopenharmony_ci struct dentry *child; 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci if (!S_ISDIR(dir->i_mode)) { 7568c2ecf20Sopenharmony_ci dput(dentry); 7578c2ecf20Sopenharmony_ci dentry = ERR_PTR(-ENOTDIR); 7588c2ecf20Sopenharmony_ci break; 7598c2ecf20Sopenharmony_ci } 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci /* skip separators */ 7628c2ecf20Sopenharmony_ci while (*s == sep) 7638c2ecf20Sopenharmony_ci s++; 7648c2ecf20Sopenharmony_ci if (!*s) 7658c2ecf20Sopenharmony_ci break; 7668c2ecf20Sopenharmony_ci p = s++; 7678c2ecf20Sopenharmony_ci /* next separator */ 7688c2ecf20Sopenharmony_ci while (*s && *s != sep) 7698c2ecf20Sopenharmony_ci s++; 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci child = lookup_positive_unlocked(p, dentry, s - p); 7728c2ecf20Sopenharmony_ci dput(dentry); 7738c2ecf20Sopenharmony_ci dentry = child; 7748c2ecf20Sopenharmony_ci } while (!IS_ERR(dentry)); 7758c2ecf20Sopenharmony_ci kfree(full_path); 7768c2ecf20Sopenharmony_ci return dentry; 7778c2ecf20Sopenharmony_ci} 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_cistatic int cifs_set_super(struct super_block *sb, void *data) 7808c2ecf20Sopenharmony_ci{ 7818c2ecf20Sopenharmony_ci struct cifs_mnt_data *mnt_data = data; 7828c2ecf20Sopenharmony_ci sb->s_fs_info = mnt_data->cifs_sb; 7838c2ecf20Sopenharmony_ci return set_anon_super(sb, NULL); 7848c2ecf20Sopenharmony_ci} 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_cistatic struct dentry * 7878c2ecf20Sopenharmony_cicifs_smb3_do_mount(struct file_system_type *fs_type, 7888c2ecf20Sopenharmony_ci int flags, const char *dev_name, void *data, bool is_smb3) 7898c2ecf20Sopenharmony_ci{ 7908c2ecf20Sopenharmony_ci int rc; 7918c2ecf20Sopenharmony_ci struct super_block *sb; 7928c2ecf20Sopenharmony_ci struct cifs_sb_info *cifs_sb; 7938c2ecf20Sopenharmony_ci struct smb_vol *volume_info; 7948c2ecf20Sopenharmony_ci struct cifs_mnt_data mnt_data; 7958c2ecf20Sopenharmony_ci struct dentry *root; 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_ci /* 7988c2ecf20Sopenharmony_ci * Prints in Kernel / CIFS log the attempted mount operation 7998c2ecf20Sopenharmony_ci * If CIFS_DEBUG && cifs_FYI 8008c2ecf20Sopenharmony_ci */ 8018c2ecf20Sopenharmony_ci if (cifsFYI) 8028c2ecf20Sopenharmony_ci cifs_dbg(FYI, "Devname: %s flags: %d\n", dev_name, flags); 8038c2ecf20Sopenharmony_ci else 8048c2ecf20Sopenharmony_ci cifs_info("Attempting to mount %s\n", dev_name); 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci volume_info = cifs_get_volume_info((char *)data, dev_name, is_smb3); 8078c2ecf20Sopenharmony_ci if (IS_ERR(volume_info)) 8088c2ecf20Sopenharmony_ci return ERR_CAST(volume_info); 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); 8118c2ecf20Sopenharmony_ci if (cifs_sb == NULL) { 8128c2ecf20Sopenharmony_ci root = ERR_PTR(-ENOMEM); 8138c2ecf20Sopenharmony_ci goto out_nls; 8148c2ecf20Sopenharmony_ci } 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); 8178c2ecf20Sopenharmony_ci if (cifs_sb->mountdata == NULL) { 8188c2ecf20Sopenharmony_ci root = ERR_PTR(-ENOMEM); 8198c2ecf20Sopenharmony_ci goto out_free; 8208c2ecf20Sopenharmony_ci } 8218c2ecf20Sopenharmony_ci 8228c2ecf20Sopenharmony_ci rc = cifs_setup_cifs_sb(volume_info, cifs_sb); 8238c2ecf20Sopenharmony_ci if (rc) { 8248c2ecf20Sopenharmony_ci root = ERR_PTR(rc); 8258c2ecf20Sopenharmony_ci goto out_free; 8268c2ecf20Sopenharmony_ci } 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci rc = cifs_mount(cifs_sb, volume_info); 8298c2ecf20Sopenharmony_ci if (rc) { 8308c2ecf20Sopenharmony_ci if (!(flags & SB_SILENT)) 8318c2ecf20Sopenharmony_ci cifs_dbg(VFS, "cifs_mount failed w/return code = %d\n", 8328c2ecf20Sopenharmony_ci rc); 8338c2ecf20Sopenharmony_ci root = ERR_PTR(rc); 8348c2ecf20Sopenharmony_ci goto out_free; 8358c2ecf20Sopenharmony_ci } 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci mnt_data.vol = volume_info; 8388c2ecf20Sopenharmony_ci mnt_data.cifs_sb = cifs_sb; 8398c2ecf20Sopenharmony_ci mnt_data.flags = flags; 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci /* BB should we make this contingent on mount parm? */ 8428c2ecf20Sopenharmony_ci flags |= SB_NODIRATIME | SB_NOATIME; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci sb = sget(fs_type, cifs_match_super, cifs_set_super, flags, &mnt_data); 8458c2ecf20Sopenharmony_ci if (IS_ERR(sb)) { 8468c2ecf20Sopenharmony_ci root = ERR_CAST(sb); 8478c2ecf20Sopenharmony_ci cifs_umount(cifs_sb); 8488c2ecf20Sopenharmony_ci goto out; 8498c2ecf20Sopenharmony_ci } 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci if (sb->s_root) { 8528c2ecf20Sopenharmony_ci cifs_dbg(FYI, "Use existing superblock\n"); 8538c2ecf20Sopenharmony_ci cifs_umount(cifs_sb); 8548c2ecf20Sopenharmony_ci } else { 8558c2ecf20Sopenharmony_ci rc = cifs_read_super(sb); 8568c2ecf20Sopenharmony_ci if (rc) { 8578c2ecf20Sopenharmony_ci root = ERR_PTR(rc); 8588c2ecf20Sopenharmony_ci goto out_super; 8598c2ecf20Sopenharmony_ci } 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci sb->s_flags |= SB_ACTIVE; 8628c2ecf20Sopenharmony_ci } 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci root = cifs_get_root(volume_info, sb); 8658c2ecf20Sopenharmony_ci if (IS_ERR(root)) 8668c2ecf20Sopenharmony_ci goto out_super; 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci cifs_dbg(FYI, "dentry root is: %p\n", root); 8698c2ecf20Sopenharmony_ci goto out; 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ciout_super: 8728c2ecf20Sopenharmony_ci deactivate_locked_super(sb); 8738c2ecf20Sopenharmony_ci return root; 8748c2ecf20Sopenharmony_ciout: 8758c2ecf20Sopenharmony_ci cifs_cleanup_volume_info(volume_info); 8768c2ecf20Sopenharmony_ci return root; 8778c2ecf20Sopenharmony_ci 8788c2ecf20Sopenharmony_ciout_free: 8798c2ecf20Sopenharmony_ci kfree(cifs_sb->prepath); 8808c2ecf20Sopenharmony_ci kfree(cifs_sb->mountdata); 8818c2ecf20Sopenharmony_ci kfree(cifs_sb); 8828c2ecf20Sopenharmony_ciout_nls: 8838c2ecf20Sopenharmony_ci unload_nls(volume_info->local_nls); 8848c2ecf20Sopenharmony_ci goto out; 8858c2ecf20Sopenharmony_ci} 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_cistatic struct dentry * 8888c2ecf20Sopenharmony_cismb3_do_mount(struct file_system_type *fs_type, 8898c2ecf20Sopenharmony_ci int flags, const char *dev_name, void *data) 8908c2ecf20Sopenharmony_ci{ 8918c2ecf20Sopenharmony_ci return cifs_smb3_do_mount(fs_type, flags, dev_name, data, true); 8928c2ecf20Sopenharmony_ci} 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_cistatic struct dentry * 8958c2ecf20Sopenharmony_cicifs_do_mount(struct file_system_type *fs_type, 8968c2ecf20Sopenharmony_ci int flags, const char *dev_name, void *data) 8978c2ecf20Sopenharmony_ci{ 8988c2ecf20Sopenharmony_ci return cifs_smb3_do_mount(fs_type, flags, dev_name, data, false); 8998c2ecf20Sopenharmony_ci} 9008c2ecf20Sopenharmony_ci 9018c2ecf20Sopenharmony_cistatic ssize_t 9028c2ecf20Sopenharmony_cicifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter) 9038c2ecf20Sopenharmony_ci{ 9048c2ecf20Sopenharmony_ci ssize_t rc; 9058c2ecf20Sopenharmony_ci struct inode *inode = file_inode(iocb->ki_filp); 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci if (iocb->ki_flags & IOCB_DIRECT) 9088c2ecf20Sopenharmony_ci return cifs_user_readv(iocb, iter); 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci rc = cifs_revalidate_mapping(inode); 9118c2ecf20Sopenharmony_ci if (rc) 9128c2ecf20Sopenharmony_ci return rc; 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_ci return generic_file_read_iter(iocb, iter); 9158c2ecf20Sopenharmony_ci} 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_cistatic ssize_t cifs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) 9188c2ecf20Sopenharmony_ci{ 9198c2ecf20Sopenharmony_ci struct inode *inode = file_inode(iocb->ki_filp); 9208c2ecf20Sopenharmony_ci struct cifsInodeInfo *cinode = CIFS_I(inode); 9218c2ecf20Sopenharmony_ci ssize_t written; 9228c2ecf20Sopenharmony_ci int rc; 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci if (iocb->ki_filp->f_flags & O_DIRECT) { 9258c2ecf20Sopenharmony_ci written = cifs_user_writev(iocb, from); 9268c2ecf20Sopenharmony_ci if (written > 0 && CIFS_CACHE_READ(cinode)) { 9278c2ecf20Sopenharmony_ci cifs_zap_mapping(inode); 9288c2ecf20Sopenharmony_ci cifs_dbg(FYI, 9298c2ecf20Sopenharmony_ci "Set no oplock for inode=%p after a write operation\n", 9308c2ecf20Sopenharmony_ci inode); 9318c2ecf20Sopenharmony_ci cinode->oplock = 0; 9328c2ecf20Sopenharmony_ci } 9338c2ecf20Sopenharmony_ci return written; 9348c2ecf20Sopenharmony_ci } 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci written = cifs_get_writer(cinode); 9378c2ecf20Sopenharmony_ci if (written) 9388c2ecf20Sopenharmony_ci return written; 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_ci written = generic_file_write_iter(iocb, from); 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci if (CIFS_CACHE_WRITE(CIFS_I(inode))) 9438c2ecf20Sopenharmony_ci goto out; 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci rc = filemap_fdatawrite(inode->i_mapping); 9468c2ecf20Sopenharmony_ci if (rc) 9478c2ecf20Sopenharmony_ci cifs_dbg(FYI, "cifs_file_write_iter: %d rc on %p inode\n", 9488c2ecf20Sopenharmony_ci rc, inode); 9498c2ecf20Sopenharmony_ci 9508c2ecf20Sopenharmony_ciout: 9518c2ecf20Sopenharmony_ci cifs_put_writer(cinode); 9528c2ecf20Sopenharmony_ci return written; 9538c2ecf20Sopenharmony_ci} 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_cistatic loff_t cifs_llseek(struct file *file, loff_t offset, int whence) 9568c2ecf20Sopenharmony_ci{ 9578c2ecf20Sopenharmony_ci struct cifsFileInfo *cfile = file->private_data; 9588c2ecf20Sopenharmony_ci struct cifs_tcon *tcon; 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci /* 9618c2ecf20Sopenharmony_ci * whence == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate 9628c2ecf20Sopenharmony_ci * the cached file length 9638c2ecf20Sopenharmony_ci */ 9648c2ecf20Sopenharmony_ci if (whence != SEEK_SET && whence != SEEK_CUR) { 9658c2ecf20Sopenharmony_ci int rc; 9668c2ecf20Sopenharmony_ci struct inode *inode = file_inode(file); 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci /* 9698c2ecf20Sopenharmony_ci * We need to be sure that all dirty pages are written and the 9708c2ecf20Sopenharmony_ci * server has the newest file length. 9718c2ecf20Sopenharmony_ci */ 9728c2ecf20Sopenharmony_ci if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping && 9738c2ecf20Sopenharmony_ci inode->i_mapping->nrpages != 0) { 9748c2ecf20Sopenharmony_ci rc = filemap_fdatawait(inode->i_mapping); 9758c2ecf20Sopenharmony_ci if (rc) { 9768c2ecf20Sopenharmony_ci mapping_set_error(inode->i_mapping, rc); 9778c2ecf20Sopenharmony_ci return rc; 9788c2ecf20Sopenharmony_ci } 9798c2ecf20Sopenharmony_ci } 9808c2ecf20Sopenharmony_ci /* 9818c2ecf20Sopenharmony_ci * Some applications poll for the file length in this strange 9828c2ecf20Sopenharmony_ci * way so we must seek to end on non-oplocked files by 9838c2ecf20Sopenharmony_ci * setting the revalidate time to zero. 9848c2ecf20Sopenharmony_ci */ 9858c2ecf20Sopenharmony_ci CIFS_I(inode)->time = 0; 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci rc = cifs_revalidate_file_attr(file); 9888c2ecf20Sopenharmony_ci if (rc < 0) 9898c2ecf20Sopenharmony_ci return (loff_t)rc; 9908c2ecf20Sopenharmony_ci } 9918c2ecf20Sopenharmony_ci if (cfile && cfile->tlink) { 9928c2ecf20Sopenharmony_ci tcon = tlink_tcon(cfile->tlink); 9938c2ecf20Sopenharmony_ci if (tcon->ses->server->ops->llseek) 9948c2ecf20Sopenharmony_ci return tcon->ses->server->ops->llseek(file, tcon, 9958c2ecf20Sopenharmony_ci offset, whence); 9968c2ecf20Sopenharmony_ci } 9978c2ecf20Sopenharmony_ci return generic_file_llseek(file, offset, whence); 9988c2ecf20Sopenharmony_ci} 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_cistatic int 10018c2ecf20Sopenharmony_cicifs_setlease(struct file *file, long arg, struct file_lock **lease, void **priv) 10028c2ecf20Sopenharmony_ci{ 10038c2ecf20Sopenharmony_ci /* 10048c2ecf20Sopenharmony_ci * Note that this is called by vfs setlease with i_lock held to 10058c2ecf20Sopenharmony_ci * protect *lease from going away. 10068c2ecf20Sopenharmony_ci */ 10078c2ecf20Sopenharmony_ci struct inode *inode = file_inode(file); 10088c2ecf20Sopenharmony_ci struct cifsFileInfo *cfile = file->private_data; 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci if (!(S_ISREG(inode->i_mode))) 10118c2ecf20Sopenharmony_ci return -EINVAL; 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci /* Check if file is oplocked if this is request for new lease */ 10148c2ecf20Sopenharmony_ci if (arg == F_UNLCK || 10158c2ecf20Sopenharmony_ci ((arg == F_RDLCK) && CIFS_CACHE_READ(CIFS_I(inode))) || 10168c2ecf20Sopenharmony_ci ((arg == F_WRLCK) && CIFS_CACHE_WRITE(CIFS_I(inode)))) 10178c2ecf20Sopenharmony_ci return generic_setlease(file, arg, lease, priv); 10188c2ecf20Sopenharmony_ci else if (tlink_tcon(cfile->tlink)->local_lease && 10198c2ecf20Sopenharmony_ci !CIFS_CACHE_READ(CIFS_I(inode))) 10208c2ecf20Sopenharmony_ci /* 10218c2ecf20Sopenharmony_ci * If the server claims to support oplock on this file, then we 10228c2ecf20Sopenharmony_ci * still need to check oplock even if the local_lease mount 10238c2ecf20Sopenharmony_ci * option is set, but there are servers which do not support 10248c2ecf20Sopenharmony_ci * oplock for which this mount option may be useful if the user 10258c2ecf20Sopenharmony_ci * knows that the file won't be changed on the server by anyone 10268c2ecf20Sopenharmony_ci * else. 10278c2ecf20Sopenharmony_ci */ 10288c2ecf20Sopenharmony_ci return generic_setlease(file, arg, lease, priv); 10298c2ecf20Sopenharmony_ci else 10308c2ecf20Sopenharmony_ci return -EAGAIN; 10318c2ecf20Sopenharmony_ci} 10328c2ecf20Sopenharmony_ci 10338c2ecf20Sopenharmony_cistruct file_system_type cifs_fs_type = { 10348c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 10358c2ecf20Sopenharmony_ci .name = "cifs", 10368c2ecf20Sopenharmony_ci .mount = cifs_do_mount, 10378c2ecf20Sopenharmony_ci .kill_sb = cifs_kill_sb, 10388c2ecf20Sopenharmony_ci .fs_flags = FS_RENAME_DOES_D_MOVE, 10398c2ecf20Sopenharmony_ci}; 10408c2ecf20Sopenharmony_ciMODULE_ALIAS_FS("cifs"); 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_cistruct file_system_type smb3_fs_type = { 10438c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 10448c2ecf20Sopenharmony_ci .name = "smb3", 10458c2ecf20Sopenharmony_ci .mount = smb3_do_mount, 10468c2ecf20Sopenharmony_ci .kill_sb = cifs_kill_sb, 10478c2ecf20Sopenharmony_ci .fs_flags = FS_RENAME_DOES_D_MOVE, 10488c2ecf20Sopenharmony_ci}; 10498c2ecf20Sopenharmony_ciMODULE_ALIAS_FS("smb3"); 10508c2ecf20Sopenharmony_ciMODULE_ALIAS("smb3"); 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ciconst struct inode_operations cifs_dir_inode_ops = { 10538c2ecf20Sopenharmony_ci .create = cifs_create, 10548c2ecf20Sopenharmony_ci .atomic_open = cifs_atomic_open, 10558c2ecf20Sopenharmony_ci .lookup = cifs_lookup, 10568c2ecf20Sopenharmony_ci .getattr = cifs_getattr, 10578c2ecf20Sopenharmony_ci .unlink = cifs_unlink, 10588c2ecf20Sopenharmony_ci .link = cifs_hardlink, 10598c2ecf20Sopenharmony_ci .mkdir = cifs_mkdir, 10608c2ecf20Sopenharmony_ci .rmdir = cifs_rmdir, 10618c2ecf20Sopenharmony_ci .rename = cifs_rename2, 10628c2ecf20Sopenharmony_ci .permission = cifs_permission, 10638c2ecf20Sopenharmony_ci .setattr = cifs_setattr, 10648c2ecf20Sopenharmony_ci .symlink = cifs_symlink, 10658c2ecf20Sopenharmony_ci .mknod = cifs_mknod, 10668c2ecf20Sopenharmony_ci .listxattr = cifs_listxattr, 10678c2ecf20Sopenharmony_ci}; 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ciconst struct inode_operations cifs_file_inode_ops = { 10708c2ecf20Sopenharmony_ci .setattr = cifs_setattr, 10718c2ecf20Sopenharmony_ci .getattr = cifs_getattr, 10728c2ecf20Sopenharmony_ci .permission = cifs_permission, 10738c2ecf20Sopenharmony_ci .listxattr = cifs_listxattr, 10748c2ecf20Sopenharmony_ci .fiemap = cifs_fiemap, 10758c2ecf20Sopenharmony_ci}; 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ciconst struct inode_operations cifs_symlink_inode_ops = { 10788c2ecf20Sopenharmony_ci .get_link = cifs_get_link, 10798c2ecf20Sopenharmony_ci .setattr = cifs_setattr, 10808c2ecf20Sopenharmony_ci .permission = cifs_permission, 10818c2ecf20Sopenharmony_ci .listxattr = cifs_listxattr, 10828c2ecf20Sopenharmony_ci}; 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_cistatic loff_t cifs_remap_file_range(struct file *src_file, loff_t off, 10858c2ecf20Sopenharmony_ci struct file *dst_file, loff_t destoff, loff_t len, 10868c2ecf20Sopenharmony_ci unsigned int remap_flags) 10878c2ecf20Sopenharmony_ci{ 10888c2ecf20Sopenharmony_ci struct inode *src_inode = file_inode(src_file); 10898c2ecf20Sopenharmony_ci struct inode *target_inode = file_inode(dst_file); 10908c2ecf20Sopenharmony_ci struct cifsFileInfo *smb_file_src = src_file->private_data; 10918c2ecf20Sopenharmony_ci struct cifsFileInfo *smb_file_target; 10928c2ecf20Sopenharmony_ci struct cifs_tcon *target_tcon; 10938c2ecf20Sopenharmony_ci unsigned int xid; 10948c2ecf20Sopenharmony_ci int rc; 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci if (remap_flags & REMAP_FILE_DEDUP) 10978c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 10988c2ecf20Sopenharmony_ci if (remap_flags & ~REMAP_FILE_ADVISORY) 10998c2ecf20Sopenharmony_ci return -EINVAL; 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci cifs_dbg(FYI, "clone range\n"); 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci xid = get_xid(); 11048c2ecf20Sopenharmony_ci 11058c2ecf20Sopenharmony_ci if (!src_file->private_data || !dst_file->private_data) { 11068c2ecf20Sopenharmony_ci rc = -EBADF; 11078c2ecf20Sopenharmony_ci cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n"); 11088c2ecf20Sopenharmony_ci goto out; 11098c2ecf20Sopenharmony_ci } 11108c2ecf20Sopenharmony_ci 11118c2ecf20Sopenharmony_ci smb_file_target = dst_file->private_data; 11128c2ecf20Sopenharmony_ci target_tcon = tlink_tcon(smb_file_target->tlink); 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci /* 11158c2ecf20Sopenharmony_ci * Note: cifs case is easier than btrfs since server responsible for 11168c2ecf20Sopenharmony_ci * checks for proper open modes and file type and if it wants 11178c2ecf20Sopenharmony_ci * server could even support copy of range where source = target 11188c2ecf20Sopenharmony_ci */ 11198c2ecf20Sopenharmony_ci lock_two_nondirectories(target_inode, src_inode); 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci if (len == 0) 11228c2ecf20Sopenharmony_ci len = src_inode->i_size - off; 11238c2ecf20Sopenharmony_ci 11248c2ecf20Sopenharmony_ci cifs_dbg(FYI, "about to flush pages\n"); 11258c2ecf20Sopenharmony_ci /* should we flush first and last page first */ 11268c2ecf20Sopenharmony_ci truncate_inode_pages_range(&target_inode->i_data, destoff, 11278c2ecf20Sopenharmony_ci PAGE_ALIGN(destoff + len)-1); 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci if (target_tcon->ses->server->ops->duplicate_extents) 11308c2ecf20Sopenharmony_ci rc = target_tcon->ses->server->ops->duplicate_extents(xid, 11318c2ecf20Sopenharmony_ci smb_file_src, smb_file_target, off, len, destoff); 11328c2ecf20Sopenharmony_ci else 11338c2ecf20Sopenharmony_ci rc = -EOPNOTSUPP; 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci /* force revalidate of size and timestamps of target file now 11368c2ecf20Sopenharmony_ci that target is updated on the server */ 11378c2ecf20Sopenharmony_ci CIFS_I(target_inode)->time = 0; 11388c2ecf20Sopenharmony_ci /* although unlocking in the reverse order from locking is not 11398c2ecf20Sopenharmony_ci strictly necessary here it is a little cleaner to be consistent */ 11408c2ecf20Sopenharmony_ci unlock_two_nondirectories(src_inode, target_inode); 11418c2ecf20Sopenharmony_ciout: 11428c2ecf20Sopenharmony_ci free_xid(xid); 11438c2ecf20Sopenharmony_ci return rc < 0 ? rc : len; 11448c2ecf20Sopenharmony_ci} 11458c2ecf20Sopenharmony_ci 11468c2ecf20Sopenharmony_cissize_t cifs_file_copychunk_range(unsigned int xid, 11478c2ecf20Sopenharmony_ci struct file *src_file, loff_t off, 11488c2ecf20Sopenharmony_ci struct file *dst_file, loff_t destoff, 11498c2ecf20Sopenharmony_ci size_t len, unsigned int flags) 11508c2ecf20Sopenharmony_ci{ 11518c2ecf20Sopenharmony_ci struct inode *src_inode = file_inode(src_file); 11528c2ecf20Sopenharmony_ci struct inode *target_inode = file_inode(dst_file); 11538c2ecf20Sopenharmony_ci struct cifsFileInfo *smb_file_src; 11548c2ecf20Sopenharmony_ci struct cifsFileInfo *smb_file_target; 11558c2ecf20Sopenharmony_ci struct cifs_tcon *src_tcon; 11568c2ecf20Sopenharmony_ci struct cifs_tcon *target_tcon; 11578c2ecf20Sopenharmony_ci ssize_t rc; 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci cifs_dbg(FYI, "copychunk range\n"); 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci if (!src_file->private_data || !dst_file->private_data) { 11628c2ecf20Sopenharmony_ci rc = -EBADF; 11638c2ecf20Sopenharmony_ci cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n"); 11648c2ecf20Sopenharmony_ci goto out; 11658c2ecf20Sopenharmony_ci } 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci rc = -EXDEV; 11688c2ecf20Sopenharmony_ci smb_file_target = dst_file->private_data; 11698c2ecf20Sopenharmony_ci smb_file_src = src_file->private_data; 11708c2ecf20Sopenharmony_ci src_tcon = tlink_tcon(smb_file_src->tlink); 11718c2ecf20Sopenharmony_ci target_tcon = tlink_tcon(smb_file_target->tlink); 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci if (src_tcon->ses != target_tcon->ses) { 11748c2ecf20Sopenharmony_ci cifs_dbg(VFS, "source and target of copy not on same server\n"); 11758c2ecf20Sopenharmony_ci goto out; 11768c2ecf20Sopenharmony_ci } 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ci rc = -EOPNOTSUPP; 11798c2ecf20Sopenharmony_ci if (!target_tcon->ses->server->ops->copychunk_range) 11808c2ecf20Sopenharmony_ci goto out; 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci /* 11838c2ecf20Sopenharmony_ci * Note: cifs case is easier than btrfs since server responsible for 11848c2ecf20Sopenharmony_ci * checks for proper open modes and file type and if it wants 11858c2ecf20Sopenharmony_ci * server could even support copy of range where source = target 11868c2ecf20Sopenharmony_ci */ 11878c2ecf20Sopenharmony_ci lock_two_nondirectories(target_inode, src_inode); 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci cifs_dbg(FYI, "about to flush pages\n"); 11908c2ecf20Sopenharmony_ci /* should we flush first and last page first */ 11918c2ecf20Sopenharmony_ci truncate_inode_pages(&target_inode->i_data, 0); 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci rc = file_modified(dst_file); 11948c2ecf20Sopenharmony_ci if (!rc) 11958c2ecf20Sopenharmony_ci rc = target_tcon->ses->server->ops->copychunk_range(xid, 11968c2ecf20Sopenharmony_ci smb_file_src, smb_file_target, off, len, destoff); 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci file_accessed(src_file); 11998c2ecf20Sopenharmony_ci 12008c2ecf20Sopenharmony_ci /* force revalidate of size and timestamps of target file now 12018c2ecf20Sopenharmony_ci * that target is updated on the server 12028c2ecf20Sopenharmony_ci */ 12038c2ecf20Sopenharmony_ci CIFS_I(target_inode)->time = 0; 12048c2ecf20Sopenharmony_ci /* although unlocking in the reverse order from locking is not 12058c2ecf20Sopenharmony_ci * strictly necessary here it is a little cleaner to be consistent 12068c2ecf20Sopenharmony_ci */ 12078c2ecf20Sopenharmony_ci unlock_two_nondirectories(src_inode, target_inode); 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ciout: 12108c2ecf20Sopenharmony_ci return rc; 12118c2ecf20Sopenharmony_ci} 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci/* 12148c2ecf20Sopenharmony_ci * Directory operations under CIFS/SMB2/SMB3 are synchronous, so fsync() 12158c2ecf20Sopenharmony_ci * is a dummy operation. 12168c2ecf20Sopenharmony_ci */ 12178c2ecf20Sopenharmony_cistatic int cifs_dir_fsync(struct file *file, loff_t start, loff_t end, int datasync) 12188c2ecf20Sopenharmony_ci{ 12198c2ecf20Sopenharmony_ci cifs_dbg(FYI, "Sync directory - name: %pD datasync: 0x%x\n", 12208c2ecf20Sopenharmony_ci file, datasync); 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci return 0; 12238c2ecf20Sopenharmony_ci} 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_cistatic ssize_t cifs_copy_file_range(struct file *src_file, loff_t off, 12268c2ecf20Sopenharmony_ci struct file *dst_file, loff_t destoff, 12278c2ecf20Sopenharmony_ci size_t len, unsigned int flags) 12288c2ecf20Sopenharmony_ci{ 12298c2ecf20Sopenharmony_ci unsigned int xid = get_xid(); 12308c2ecf20Sopenharmony_ci ssize_t rc; 12318c2ecf20Sopenharmony_ci struct cifsFileInfo *cfile = dst_file->private_data; 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci if (cfile->swapfile) { 12348c2ecf20Sopenharmony_ci rc = -EOPNOTSUPP; 12358c2ecf20Sopenharmony_ci free_xid(xid); 12368c2ecf20Sopenharmony_ci return rc; 12378c2ecf20Sopenharmony_ci } 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_ci rc = cifs_file_copychunk_range(xid, src_file, off, dst_file, destoff, 12408c2ecf20Sopenharmony_ci len, flags); 12418c2ecf20Sopenharmony_ci free_xid(xid); 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci if (rc == -EOPNOTSUPP || rc == -EXDEV) 12448c2ecf20Sopenharmony_ci rc = generic_copy_file_range(src_file, off, dst_file, 12458c2ecf20Sopenharmony_ci destoff, len, flags); 12468c2ecf20Sopenharmony_ci return rc; 12478c2ecf20Sopenharmony_ci} 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ciconst struct file_operations cifs_file_ops = { 12508c2ecf20Sopenharmony_ci .read_iter = cifs_loose_read_iter, 12518c2ecf20Sopenharmony_ci .write_iter = cifs_file_write_iter, 12528c2ecf20Sopenharmony_ci .open = cifs_open, 12538c2ecf20Sopenharmony_ci .release = cifs_close, 12548c2ecf20Sopenharmony_ci .lock = cifs_lock, 12558c2ecf20Sopenharmony_ci .flock = cifs_flock, 12568c2ecf20Sopenharmony_ci .fsync = cifs_fsync, 12578c2ecf20Sopenharmony_ci .flush = cifs_flush, 12588c2ecf20Sopenharmony_ci .mmap = cifs_file_mmap, 12598c2ecf20Sopenharmony_ci .splice_read = generic_file_splice_read, 12608c2ecf20Sopenharmony_ci .splice_write = iter_file_splice_write, 12618c2ecf20Sopenharmony_ci .llseek = cifs_llseek, 12628c2ecf20Sopenharmony_ci .unlocked_ioctl = cifs_ioctl, 12638c2ecf20Sopenharmony_ci .copy_file_range = cifs_copy_file_range, 12648c2ecf20Sopenharmony_ci .remap_file_range = cifs_remap_file_range, 12658c2ecf20Sopenharmony_ci .setlease = cifs_setlease, 12668c2ecf20Sopenharmony_ci .fallocate = cifs_fallocate, 12678c2ecf20Sopenharmony_ci}; 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ciconst struct file_operations cifs_file_strict_ops = { 12708c2ecf20Sopenharmony_ci .read_iter = cifs_strict_readv, 12718c2ecf20Sopenharmony_ci .write_iter = cifs_strict_writev, 12728c2ecf20Sopenharmony_ci .open = cifs_open, 12738c2ecf20Sopenharmony_ci .release = cifs_close, 12748c2ecf20Sopenharmony_ci .lock = cifs_lock, 12758c2ecf20Sopenharmony_ci .flock = cifs_flock, 12768c2ecf20Sopenharmony_ci .fsync = cifs_strict_fsync, 12778c2ecf20Sopenharmony_ci .flush = cifs_flush, 12788c2ecf20Sopenharmony_ci .mmap = cifs_file_strict_mmap, 12798c2ecf20Sopenharmony_ci .splice_read = generic_file_splice_read, 12808c2ecf20Sopenharmony_ci .splice_write = iter_file_splice_write, 12818c2ecf20Sopenharmony_ci .llseek = cifs_llseek, 12828c2ecf20Sopenharmony_ci .unlocked_ioctl = cifs_ioctl, 12838c2ecf20Sopenharmony_ci .copy_file_range = cifs_copy_file_range, 12848c2ecf20Sopenharmony_ci .remap_file_range = cifs_remap_file_range, 12858c2ecf20Sopenharmony_ci .setlease = cifs_setlease, 12868c2ecf20Sopenharmony_ci .fallocate = cifs_fallocate, 12878c2ecf20Sopenharmony_ci}; 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ciconst struct file_operations cifs_file_direct_ops = { 12908c2ecf20Sopenharmony_ci .read_iter = cifs_direct_readv, 12918c2ecf20Sopenharmony_ci .write_iter = cifs_direct_writev, 12928c2ecf20Sopenharmony_ci .open = cifs_open, 12938c2ecf20Sopenharmony_ci .release = cifs_close, 12948c2ecf20Sopenharmony_ci .lock = cifs_lock, 12958c2ecf20Sopenharmony_ci .flock = cifs_flock, 12968c2ecf20Sopenharmony_ci .fsync = cifs_fsync, 12978c2ecf20Sopenharmony_ci .flush = cifs_flush, 12988c2ecf20Sopenharmony_ci .mmap = cifs_file_mmap, 12998c2ecf20Sopenharmony_ci .splice_read = generic_file_splice_read, 13008c2ecf20Sopenharmony_ci .splice_write = iter_file_splice_write, 13018c2ecf20Sopenharmony_ci .unlocked_ioctl = cifs_ioctl, 13028c2ecf20Sopenharmony_ci .copy_file_range = cifs_copy_file_range, 13038c2ecf20Sopenharmony_ci .remap_file_range = cifs_remap_file_range, 13048c2ecf20Sopenharmony_ci .llseek = cifs_llseek, 13058c2ecf20Sopenharmony_ci .setlease = cifs_setlease, 13068c2ecf20Sopenharmony_ci .fallocate = cifs_fallocate, 13078c2ecf20Sopenharmony_ci}; 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ciconst struct file_operations cifs_file_nobrl_ops = { 13108c2ecf20Sopenharmony_ci .read_iter = cifs_loose_read_iter, 13118c2ecf20Sopenharmony_ci .write_iter = cifs_file_write_iter, 13128c2ecf20Sopenharmony_ci .open = cifs_open, 13138c2ecf20Sopenharmony_ci .release = cifs_close, 13148c2ecf20Sopenharmony_ci .fsync = cifs_fsync, 13158c2ecf20Sopenharmony_ci .flush = cifs_flush, 13168c2ecf20Sopenharmony_ci .mmap = cifs_file_mmap, 13178c2ecf20Sopenharmony_ci .splice_read = generic_file_splice_read, 13188c2ecf20Sopenharmony_ci .splice_write = iter_file_splice_write, 13198c2ecf20Sopenharmony_ci .llseek = cifs_llseek, 13208c2ecf20Sopenharmony_ci .unlocked_ioctl = cifs_ioctl, 13218c2ecf20Sopenharmony_ci .copy_file_range = cifs_copy_file_range, 13228c2ecf20Sopenharmony_ci .remap_file_range = cifs_remap_file_range, 13238c2ecf20Sopenharmony_ci .setlease = cifs_setlease, 13248c2ecf20Sopenharmony_ci .fallocate = cifs_fallocate, 13258c2ecf20Sopenharmony_ci}; 13268c2ecf20Sopenharmony_ci 13278c2ecf20Sopenharmony_ciconst struct file_operations cifs_file_strict_nobrl_ops = { 13288c2ecf20Sopenharmony_ci .read_iter = cifs_strict_readv, 13298c2ecf20Sopenharmony_ci .write_iter = cifs_strict_writev, 13308c2ecf20Sopenharmony_ci .open = cifs_open, 13318c2ecf20Sopenharmony_ci .release = cifs_close, 13328c2ecf20Sopenharmony_ci .fsync = cifs_strict_fsync, 13338c2ecf20Sopenharmony_ci .flush = cifs_flush, 13348c2ecf20Sopenharmony_ci .mmap = cifs_file_strict_mmap, 13358c2ecf20Sopenharmony_ci .splice_read = generic_file_splice_read, 13368c2ecf20Sopenharmony_ci .splice_write = iter_file_splice_write, 13378c2ecf20Sopenharmony_ci .llseek = cifs_llseek, 13388c2ecf20Sopenharmony_ci .unlocked_ioctl = cifs_ioctl, 13398c2ecf20Sopenharmony_ci .copy_file_range = cifs_copy_file_range, 13408c2ecf20Sopenharmony_ci .remap_file_range = cifs_remap_file_range, 13418c2ecf20Sopenharmony_ci .setlease = cifs_setlease, 13428c2ecf20Sopenharmony_ci .fallocate = cifs_fallocate, 13438c2ecf20Sopenharmony_ci}; 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ciconst struct file_operations cifs_file_direct_nobrl_ops = { 13468c2ecf20Sopenharmony_ci .read_iter = cifs_direct_readv, 13478c2ecf20Sopenharmony_ci .write_iter = cifs_direct_writev, 13488c2ecf20Sopenharmony_ci .open = cifs_open, 13498c2ecf20Sopenharmony_ci .release = cifs_close, 13508c2ecf20Sopenharmony_ci .fsync = cifs_fsync, 13518c2ecf20Sopenharmony_ci .flush = cifs_flush, 13528c2ecf20Sopenharmony_ci .mmap = cifs_file_mmap, 13538c2ecf20Sopenharmony_ci .splice_read = generic_file_splice_read, 13548c2ecf20Sopenharmony_ci .splice_write = iter_file_splice_write, 13558c2ecf20Sopenharmony_ci .unlocked_ioctl = cifs_ioctl, 13568c2ecf20Sopenharmony_ci .copy_file_range = cifs_copy_file_range, 13578c2ecf20Sopenharmony_ci .remap_file_range = cifs_remap_file_range, 13588c2ecf20Sopenharmony_ci .llseek = cifs_llseek, 13598c2ecf20Sopenharmony_ci .setlease = cifs_setlease, 13608c2ecf20Sopenharmony_ci .fallocate = cifs_fallocate, 13618c2ecf20Sopenharmony_ci}; 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ciconst struct file_operations cifs_dir_ops = { 13648c2ecf20Sopenharmony_ci .iterate_shared = cifs_readdir, 13658c2ecf20Sopenharmony_ci .release = cifs_closedir, 13668c2ecf20Sopenharmony_ci .read = generic_read_dir, 13678c2ecf20Sopenharmony_ci .unlocked_ioctl = cifs_ioctl, 13688c2ecf20Sopenharmony_ci .copy_file_range = cifs_copy_file_range, 13698c2ecf20Sopenharmony_ci .remap_file_range = cifs_remap_file_range, 13708c2ecf20Sopenharmony_ci .llseek = generic_file_llseek, 13718c2ecf20Sopenharmony_ci .fsync = cifs_dir_fsync, 13728c2ecf20Sopenharmony_ci}; 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_cistatic void 13758c2ecf20Sopenharmony_cicifs_init_once(void *inode) 13768c2ecf20Sopenharmony_ci{ 13778c2ecf20Sopenharmony_ci struct cifsInodeInfo *cifsi = inode; 13788c2ecf20Sopenharmony_ci 13798c2ecf20Sopenharmony_ci inode_init_once(&cifsi->vfs_inode); 13808c2ecf20Sopenharmony_ci init_rwsem(&cifsi->lock_sem); 13818c2ecf20Sopenharmony_ci} 13828c2ecf20Sopenharmony_ci 13838c2ecf20Sopenharmony_cistatic int __init 13848c2ecf20Sopenharmony_cicifs_init_inodecache(void) 13858c2ecf20Sopenharmony_ci{ 13868c2ecf20Sopenharmony_ci cifs_inode_cachep = kmem_cache_create("cifs_inode_cache", 13878c2ecf20Sopenharmony_ci sizeof(struct cifsInodeInfo), 13888c2ecf20Sopenharmony_ci 0, (SLAB_RECLAIM_ACCOUNT| 13898c2ecf20Sopenharmony_ci SLAB_MEM_SPREAD|SLAB_ACCOUNT), 13908c2ecf20Sopenharmony_ci cifs_init_once); 13918c2ecf20Sopenharmony_ci if (cifs_inode_cachep == NULL) 13928c2ecf20Sopenharmony_ci return -ENOMEM; 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci return 0; 13958c2ecf20Sopenharmony_ci} 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_cistatic void 13988c2ecf20Sopenharmony_cicifs_destroy_inodecache(void) 13998c2ecf20Sopenharmony_ci{ 14008c2ecf20Sopenharmony_ci /* 14018c2ecf20Sopenharmony_ci * Make sure all delayed rcu free inodes are flushed before we 14028c2ecf20Sopenharmony_ci * destroy cache. 14038c2ecf20Sopenharmony_ci */ 14048c2ecf20Sopenharmony_ci rcu_barrier(); 14058c2ecf20Sopenharmony_ci kmem_cache_destroy(cifs_inode_cachep); 14068c2ecf20Sopenharmony_ci} 14078c2ecf20Sopenharmony_ci 14088c2ecf20Sopenharmony_cistatic int 14098c2ecf20Sopenharmony_cicifs_init_request_bufs(void) 14108c2ecf20Sopenharmony_ci{ 14118c2ecf20Sopenharmony_ci /* 14128c2ecf20Sopenharmony_ci * SMB2 maximum header size is bigger than CIFS one - no problems to 14138c2ecf20Sopenharmony_ci * allocate some more bytes for CIFS. 14148c2ecf20Sopenharmony_ci */ 14158c2ecf20Sopenharmony_ci size_t max_hdr_size = MAX_SMB2_HDR_SIZE; 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ci if (CIFSMaxBufSize < 8192) { 14188c2ecf20Sopenharmony_ci /* Buffer size can not be smaller than 2 * PATH_MAX since maximum 14198c2ecf20Sopenharmony_ci Unicode path name has to fit in any SMB/CIFS path based frames */ 14208c2ecf20Sopenharmony_ci CIFSMaxBufSize = 8192; 14218c2ecf20Sopenharmony_ci } else if (CIFSMaxBufSize > 1024*127) { 14228c2ecf20Sopenharmony_ci CIFSMaxBufSize = 1024 * 127; 14238c2ecf20Sopenharmony_ci } else { 14248c2ecf20Sopenharmony_ci CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/ 14258c2ecf20Sopenharmony_ci } 14268c2ecf20Sopenharmony_ci/* 14278c2ecf20Sopenharmony_ci cifs_dbg(VFS, "CIFSMaxBufSize %d 0x%x\n", 14288c2ecf20Sopenharmony_ci CIFSMaxBufSize, CIFSMaxBufSize); 14298c2ecf20Sopenharmony_ci*/ 14308c2ecf20Sopenharmony_ci cifs_req_cachep = kmem_cache_create_usercopy("cifs_request", 14318c2ecf20Sopenharmony_ci CIFSMaxBufSize + max_hdr_size, 0, 14328c2ecf20Sopenharmony_ci SLAB_HWCACHE_ALIGN, 0, 14338c2ecf20Sopenharmony_ci CIFSMaxBufSize + max_hdr_size, 14348c2ecf20Sopenharmony_ci NULL); 14358c2ecf20Sopenharmony_ci if (cifs_req_cachep == NULL) 14368c2ecf20Sopenharmony_ci return -ENOMEM; 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci if (cifs_min_rcv < 1) 14398c2ecf20Sopenharmony_ci cifs_min_rcv = 1; 14408c2ecf20Sopenharmony_ci else if (cifs_min_rcv > 64) { 14418c2ecf20Sopenharmony_ci cifs_min_rcv = 64; 14428c2ecf20Sopenharmony_ci cifs_dbg(VFS, "cifs_min_rcv set to maximum (64)\n"); 14438c2ecf20Sopenharmony_ci } 14448c2ecf20Sopenharmony_ci 14458c2ecf20Sopenharmony_ci cifs_req_poolp = mempool_create_slab_pool(cifs_min_rcv, 14468c2ecf20Sopenharmony_ci cifs_req_cachep); 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci if (cifs_req_poolp == NULL) { 14498c2ecf20Sopenharmony_ci kmem_cache_destroy(cifs_req_cachep); 14508c2ecf20Sopenharmony_ci return -ENOMEM; 14518c2ecf20Sopenharmony_ci } 14528c2ecf20Sopenharmony_ci /* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and 14538c2ecf20Sopenharmony_ci almost all handle based requests (but not write response, nor is it 14548c2ecf20Sopenharmony_ci sufficient for path based requests). A smaller size would have 14558c2ecf20Sopenharmony_ci been more efficient (compacting multiple slab items on one 4k page) 14568c2ecf20Sopenharmony_ci for the case in which debug was on, but this larger size allows 14578c2ecf20Sopenharmony_ci more SMBs to use small buffer alloc and is still much more 14588c2ecf20Sopenharmony_ci efficient to alloc 1 per page off the slab compared to 17K (5page) 14598c2ecf20Sopenharmony_ci alloc of large cifs buffers even when page debugging is on */ 14608c2ecf20Sopenharmony_ci cifs_sm_req_cachep = kmem_cache_create_usercopy("cifs_small_rq", 14618c2ecf20Sopenharmony_ci MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN, 14628c2ecf20Sopenharmony_ci 0, MAX_CIFS_SMALL_BUFFER_SIZE, NULL); 14638c2ecf20Sopenharmony_ci if (cifs_sm_req_cachep == NULL) { 14648c2ecf20Sopenharmony_ci mempool_destroy(cifs_req_poolp); 14658c2ecf20Sopenharmony_ci kmem_cache_destroy(cifs_req_cachep); 14668c2ecf20Sopenharmony_ci return -ENOMEM; 14678c2ecf20Sopenharmony_ci } 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_ci if (cifs_min_small < 2) 14708c2ecf20Sopenharmony_ci cifs_min_small = 2; 14718c2ecf20Sopenharmony_ci else if (cifs_min_small > 256) { 14728c2ecf20Sopenharmony_ci cifs_min_small = 256; 14738c2ecf20Sopenharmony_ci cifs_dbg(FYI, "cifs_min_small set to maximum (256)\n"); 14748c2ecf20Sopenharmony_ci } 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci cifs_sm_req_poolp = mempool_create_slab_pool(cifs_min_small, 14778c2ecf20Sopenharmony_ci cifs_sm_req_cachep); 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci if (cifs_sm_req_poolp == NULL) { 14808c2ecf20Sopenharmony_ci mempool_destroy(cifs_req_poolp); 14818c2ecf20Sopenharmony_ci kmem_cache_destroy(cifs_req_cachep); 14828c2ecf20Sopenharmony_ci kmem_cache_destroy(cifs_sm_req_cachep); 14838c2ecf20Sopenharmony_ci return -ENOMEM; 14848c2ecf20Sopenharmony_ci } 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci return 0; 14878c2ecf20Sopenharmony_ci} 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_cistatic void 14908c2ecf20Sopenharmony_cicifs_destroy_request_bufs(void) 14918c2ecf20Sopenharmony_ci{ 14928c2ecf20Sopenharmony_ci mempool_destroy(cifs_req_poolp); 14938c2ecf20Sopenharmony_ci kmem_cache_destroy(cifs_req_cachep); 14948c2ecf20Sopenharmony_ci mempool_destroy(cifs_sm_req_poolp); 14958c2ecf20Sopenharmony_ci kmem_cache_destroy(cifs_sm_req_cachep); 14968c2ecf20Sopenharmony_ci} 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_cistatic int 14998c2ecf20Sopenharmony_cicifs_init_mids(void) 15008c2ecf20Sopenharmony_ci{ 15018c2ecf20Sopenharmony_ci cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids", 15028c2ecf20Sopenharmony_ci sizeof(struct mid_q_entry), 0, 15038c2ecf20Sopenharmony_ci SLAB_HWCACHE_ALIGN, NULL); 15048c2ecf20Sopenharmony_ci if (cifs_mid_cachep == NULL) 15058c2ecf20Sopenharmony_ci return -ENOMEM; 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci /* 3 is a reasonable minimum number of simultaneous operations */ 15088c2ecf20Sopenharmony_ci cifs_mid_poolp = mempool_create_slab_pool(3, cifs_mid_cachep); 15098c2ecf20Sopenharmony_ci if (cifs_mid_poolp == NULL) { 15108c2ecf20Sopenharmony_ci kmem_cache_destroy(cifs_mid_cachep); 15118c2ecf20Sopenharmony_ci return -ENOMEM; 15128c2ecf20Sopenharmony_ci } 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci return 0; 15158c2ecf20Sopenharmony_ci} 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_cistatic void 15188c2ecf20Sopenharmony_cicifs_destroy_mids(void) 15198c2ecf20Sopenharmony_ci{ 15208c2ecf20Sopenharmony_ci mempool_destroy(cifs_mid_poolp); 15218c2ecf20Sopenharmony_ci kmem_cache_destroy(cifs_mid_cachep); 15228c2ecf20Sopenharmony_ci} 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_cistatic int __init 15258c2ecf20Sopenharmony_ciinit_cifs(void) 15268c2ecf20Sopenharmony_ci{ 15278c2ecf20Sopenharmony_ci int rc = 0; 15288c2ecf20Sopenharmony_ci cifs_proc_init(); 15298c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&cifs_tcp_ses_list); 15308c2ecf20Sopenharmony_ci#ifdef CONFIG_CIFS_DNOTIFY_EXPERIMENTAL /* unused temporarily */ 15318c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&GlobalDnotifyReqList); 15328c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&GlobalDnotifyRsp_Q); 15338c2ecf20Sopenharmony_ci#endif /* was needed for dnotify, and will be needed for inotify when VFS fix */ 15348c2ecf20Sopenharmony_ci/* 15358c2ecf20Sopenharmony_ci * Initialize Global counters 15368c2ecf20Sopenharmony_ci */ 15378c2ecf20Sopenharmony_ci atomic_set(&sesInfoAllocCount, 0); 15388c2ecf20Sopenharmony_ci atomic_set(&tconInfoAllocCount, 0); 15398c2ecf20Sopenharmony_ci atomic_set(&tcpSesAllocCount, 0); 15408c2ecf20Sopenharmony_ci atomic_set(&tcpSesReconnectCount, 0); 15418c2ecf20Sopenharmony_ci atomic_set(&tconInfoReconnectCount, 0); 15428c2ecf20Sopenharmony_ci 15438c2ecf20Sopenharmony_ci atomic_set(&bufAllocCount, 0); 15448c2ecf20Sopenharmony_ci atomic_set(&smBufAllocCount, 0); 15458c2ecf20Sopenharmony_ci#ifdef CONFIG_CIFS_STATS2 15468c2ecf20Sopenharmony_ci atomic_set(&totBufAllocCount, 0); 15478c2ecf20Sopenharmony_ci atomic_set(&totSmBufAllocCount, 0); 15488c2ecf20Sopenharmony_ci if (slow_rsp_threshold < 1) 15498c2ecf20Sopenharmony_ci cifs_dbg(FYI, "slow_response_threshold msgs disabled\n"); 15508c2ecf20Sopenharmony_ci else if (slow_rsp_threshold > 32767) 15518c2ecf20Sopenharmony_ci cifs_dbg(VFS, 15528c2ecf20Sopenharmony_ci "slow response threshold set higher than recommended (0 to 32767)\n"); 15538c2ecf20Sopenharmony_ci#endif /* CONFIG_CIFS_STATS2 */ 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ci atomic_set(&midCount, 0); 15568c2ecf20Sopenharmony_ci GlobalCurrentXid = 0; 15578c2ecf20Sopenharmony_ci GlobalTotalActiveXid = 0; 15588c2ecf20Sopenharmony_ci GlobalMaxActiveXid = 0; 15598c2ecf20Sopenharmony_ci spin_lock_init(&cifs_tcp_ses_lock); 15608c2ecf20Sopenharmony_ci spin_lock_init(&GlobalMid_Lock); 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci cifs_lock_secret = get_random_u32(); 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci if (cifs_max_pending < 2) { 15658c2ecf20Sopenharmony_ci cifs_max_pending = 2; 15668c2ecf20Sopenharmony_ci cifs_dbg(FYI, "cifs_max_pending set to min of 2\n"); 15678c2ecf20Sopenharmony_ci } else if (cifs_max_pending > CIFS_MAX_REQ) { 15688c2ecf20Sopenharmony_ci cifs_max_pending = CIFS_MAX_REQ; 15698c2ecf20Sopenharmony_ci cifs_dbg(FYI, "cifs_max_pending set to max of %u\n", 15708c2ecf20Sopenharmony_ci CIFS_MAX_REQ); 15718c2ecf20Sopenharmony_ci } 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_ci cifsiod_wq = alloc_workqueue("cifsiod", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); 15748c2ecf20Sopenharmony_ci if (!cifsiod_wq) { 15758c2ecf20Sopenharmony_ci rc = -ENOMEM; 15768c2ecf20Sopenharmony_ci goto out_clean_proc; 15778c2ecf20Sopenharmony_ci } 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci /* 15808c2ecf20Sopenharmony_ci * Consider in future setting limit!=0 maybe to min(num_of_cores - 1, 3) 15818c2ecf20Sopenharmony_ci * so that we don't launch too many worker threads but 15828c2ecf20Sopenharmony_ci * Documentation/core-api/workqueue.rst recommends setting it to 0 15838c2ecf20Sopenharmony_ci */ 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_ci /* WQ_UNBOUND allows decrypt tasks to run on any CPU */ 15868c2ecf20Sopenharmony_ci decrypt_wq = alloc_workqueue("smb3decryptd", 15878c2ecf20Sopenharmony_ci WQ_UNBOUND|WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); 15888c2ecf20Sopenharmony_ci if (!decrypt_wq) { 15898c2ecf20Sopenharmony_ci rc = -ENOMEM; 15908c2ecf20Sopenharmony_ci goto out_destroy_cifsiod_wq; 15918c2ecf20Sopenharmony_ci } 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci fileinfo_put_wq = alloc_workqueue("cifsfileinfoput", 15948c2ecf20Sopenharmony_ci WQ_UNBOUND|WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); 15958c2ecf20Sopenharmony_ci if (!fileinfo_put_wq) { 15968c2ecf20Sopenharmony_ci rc = -ENOMEM; 15978c2ecf20Sopenharmony_ci goto out_destroy_decrypt_wq; 15988c2ecf20Sopenharmony_ci } 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci cifsoplockd_wq = alloc_workqueue("cifsoplockd", 16018c2ecf20Sopenharmony_ci WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); 16028c2ecf20Sopenharmony_ci if (!cifsoplockd_wq) { 16038c2ecf20Sopenharmony_ci rc = -ENOMEM; 16048c2ecf20Sopenharmony_ci goto out_destroy_fileinfo_put_wq; 16058c2ecf20Sopenharmony_ci } 16068c2ecf20Sopenharmony_ci 16078c2ecf20Sopenharmony_ci rc = cifs_fscache_register(); 16088c2ecf20Sopenharmony_ci if (rc) 16098c2ecf20Sopenharmony_ci goto out_destroy_cifsoplockd_wq; 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_ci rc = cifs_init_inodecache(); 16128c2ecf20Sopenharmony_ci if (rc) 16138c2ecf20Sopenharmony_ci goto out_unreg_fscache; 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci rc = cifs_init_mids(); 16168c2ecf20Sopenharmony_ci if (rc) 16178c2ecf20Sopenharmony_ci goto out_destroy_inodecache; 16188c2ecf20Sopenharmony_ci 16198c2ecf20Sopenharmony_ci rc = cifs_init_request_bufs(); 16208c2ecf20Sopenharmony_ci if (rc) 16218c2ecf20Sopenharmony_ci goto out_destroy_mids; 16228c2ecf20Sopenharmony_ci 16238c2ecf20Sopenharmony_ci#ifdef CONFIG_CIFS_DFS_UPCALL 16248c2ecf20Sopenharmony_ci rc = dfs_cache_init(); 16258c2ecf20Sopenharmony_ci if (rc) 16268c2ecf20Sopenharmony_ci goto out_destroy_request_bufs; 16278c2ecf20Sopenharmony_ci#endif /* CONFIG_CIFS_DFS_UPCALL */ 16288c2ecf20Sopenharmony_ci#ifdef CONFIG_CIFS_UPCALL 16298c2ecf20Sopenharmony_ci rc = init_cifs_spnego(); 16308c2ecf20Sopenharmony_ci if (rc) 16318c2ecf20Sopenharmony_ci goto out_destroy_dfs_cache; 16328c2ecf20Sopenharmony_ci#endif /* CONFIG_CIFS_UPCALL */ 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci rc = init_cifs_idmap(); 16358c2ecf20Sopenharmony_ci if (rc) 16368c2ecf20Sopenharmony_ci goto out_register_key_type; 16378c2ecf20Sopenharmony_ci 16388c2ecf20Sopenharmony_ci rc = register_filesystem(&cifs_fs_type); 16398c2ecf20Sopenharmony_ci if (rc) 16408c2ecf20Sopenharmony_ci goto out_init_cifs_idmap; 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci rc = register_filesystem(&smb3_fs_type); 16438c2ecf20Sopenharmony_ci if (rc) { 16448c2ecf20Sopenharmony_ci unregister_filesystem(&cifs_fs_type); 16458c2ecf20Sopenharmony_ci goto out_init_cifs_idmap; 16468c2ecf20Sopenharmony_ci } 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_ci return 0; 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ciout_init_cifs_idmap: 16518c2ecf20Sopenharmony_ci exit_cifs_idmap(); 16528c2ecf20Sopenharmony_ciout_register_key_type: 16538c2ecf20Sopenharmony_ci#ifdef CONFIG_CIFS_UPCALL 16548c2ecf20Sopenharmony_ci exit_cifs_spnego(); 16558c2ecf20Sopenharmony_ciout_destroy_dfs_cache: 16568c2ecf20Sopenharmony_ci#endif 16578c2ecf20Sopenharmony_ci#ifdef CONFIG_CIFS_DFS_UPCALL 16588c2ecf20Sopenharmony_ci dfs_cache_destroy(); 16598c2ecf20Sopenharmony_ciout_destroy_request_bufs: 16608c2ecf20Sopenharmony_ci#endif 16618c2ecf20Sopenharmony_ci cifs_destroy_request_bufs(); 16628c2ecf20Sopenharmony_ciout_destroy_mids: 16638c2ecf20Sopenharmony_ci cifs_destroy_mids(); 16648c2ecf20Sopenharmony_ciout_destroy_inodecache: 16658c2ecf20Sopenharmony_ci cifs_destroy_inodecache(); 16668c2ecf20Sopenharmony_ciout_unreg_fscache: 16678c2ecf20Sopenharmony_ci cifs_fscache_unregister(); 16688c2ecf20Sopenharmony_ciout_destroy_cifsoplockd_wq: 16698c2ecf20Sopenharmony_ci destroy_workqueue(cifsoplockd_wq); 16708c2ecf20Sopenharmony_ciout_destroy_fileinfo_put_wq: 16718c2ecf20Sopenharmony_ci destroy_workqueue(fileinfo_put_wq); 16728c2ecf20Sopenharmony_ciout_destroy_decrypt_wq: 16738c2ecf20Sopenharmony_ci destroy_workqueue(decrypt_wq); 16748c2ecf20Sopenharmony_ciout_destroy_cifsiod_wq: 16758c2ecf20Sopenharmony_ci destroy_workqueue(cifsiod_wq); 16768c2ecf20Sopenharmony_ciout_clean_proc: 16778c2ecf20Sopenharmony_ci cifs_proc_clean(); 16788c2ecf20Sopenharmony_ci return rc; 16798c2ecf20Sopenharmony_ci} 16808c2ecf20Sopenharmony_ci 16818c2ecf20Sopenharmony_cistatic void __exit 16828c2ecf20Sopenharmony_ciexit_cifs(void) 16838c2ecf20Sopenharmony_ci{ 16848c2ecf20Sopenharmony_ci cifs_dbg(NOISY, "exit_smb3\n"); 16858c2ecf20Sopenharmony_ci unregister_filesystem(&cifs_fs_type); 16868c2ecf20Sopenharmony_ci unregister_filesystem(&smb3_fs_type); 16878c2ecf20Sopenharmony_ci cifs_dfs_release_automount_timer(); 16888c2ecf20Sopenharmony_ci exit_cifs_idmap(); 16898c2ecf20Sopenharmony_ci#ifdef CONFIG_CIFS_UPCALL 16908c2ecf20Sopenharmony_ci exit_cifs_spnego(); 16918c2ecf20Sopenharmony_ci#endif 16928c2ecf20Sopenharmony_ci#ifdef CONFIG_CIFS_DFS_UPCALL 16938c2ecf20Sopenharmony_ci dfs_cache_destroy(); 16948c2ecf20Sopenharmony_ci#endif 16958c2ecf20Sopenharmony_ci cifs_destroy_request_bufs(); 16968c2ecf20Sopenharmony_ci cifs_destroy_mids(); 16978c2ecf20Sopenharmony_ci cifs_destroy_inodecache(); 16988c2ecf20Sopenharmony_ci cifs_fscache_unregister(); 16998c2ecf20Sopenharmony_ci destroy_workqueue(cifsoplockd_wq); 17008c2ecf20Sopenharmony_ci destroy_workqueue(decrypt_wq); 17018c2ecf20Sopenharmony_ci destroy_workqueue(fileinfo_put_wq); 17028c2ecf20Sopenharmony_ci destroy_workqueue(cifsiod_wq); 17038c2ecf20Sopenharmony_ci cifs_proc_clean(); 17048c2ecf20Sopenharmony_ci} 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_ciMODULE_AUTHOR("Steve French"); 17078c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */ 17088c2ecf20Sopenharmony_ciMODULE_DESCRIPTION 17098c2ecf20Sopenharmony_ci ("VFS to access SMB3 servers e.g. Samba, Macs, Azure and Windows (and " 17108c2ecf20Sopenharmony_ci "also older servers complying with the SNIA CIFS Specification)"); 17118c2ecf20Sopenharmony_ciMODULE_VERSION(CIFS_VERSION); 17128c2ecf20Sopenharmony_ciMODULE_SOFTDEP("ecb"); 17138c2ecf20Sopenharmony_ciMODULE_SOFTDEP("hmac"); 17148c2ecf20Sopenharmony_ciMODULE_SOFTDEP("md4"); 17158c2ecf20Sopenharmony_ciMODULE_SOFTDEP("md5"); 17168c2ecf20Sopenharmony_ciMODULE_SOFTDEP("nls"); 17178c2ecf20Sopenharmony_ciMODULE_SOFTDEP("aes"); 17188c2ecf20Sopenharmony_ciMODULE_SOFTDEP("cmac"); 17198c2ecf20Sopenharmony_ciMODULE_SOFTDEP("sha256"); 17208c2ecf20Sopenharmony_ciMODULE_SOFTDEP("sha512"); 17218c2ecf20Sopenharmony_ciMODULE_SOFTDEP("aead2"); 17228c2ecf20Sopenharmony_ciMODULE_SOFTDEP("ccm"); 17238c2ecf20Sopenharmony_ciMODULE_SOFTDEP("gcm"); 17248c2ecf20Sopenharmony_cimodule_init(init_cifs) 17258c2ecf20Sopenharmony_cimodule_exit(exit_cifs) 1726