138c8a9a5SSteve French // SPDX-License-Identifier: LGPL-2.1 238c8a9a5SSteve French /* 338c8a9a5SSteve French * 438c8a9a5SSteve French * vfs operations that deal with files 538c8a9a5SSteve French * 638c8a9a5SSteve French * Copyright (C) International Business Machines Corp., 2002,2010 738c8a9a5SSteve French * Author(s): Steve French (sfrench@us.ibm.com) 838c8a9a5SSteve French * Jeremy Allison (jra@samba.org) 938c8a9a5SSteve French * 1038c8a9a5SSteve French */ 1138c8a9a5SSteve French #include <linux/fs.h> 1238c8a9a5SSteve French #include <linux/filelock.h> 1338c8a9a5SSteve French #include <linux/backing-dev.h> 1438c8a9a5SSteve French #include <linux/stat.h> 1538c8a9a5SSteve French #include <linux/fcntl.h> 1638c8a9a5SSteve French #include <linux/pagemap.h> 1738c8a9a5SSteve French #include <linux/pagevec.h> 1838c8a9a5SSteve French #include <linux/writeback.h> 1938c8a9a5SSteve French #include <linux/task_io_accounting_ops.h> 2038c8a9a5SSteve French #include <linux/delay.h> 2138c8a9a5SSteve French #include <linux/mount.h> 2238c8a9a5SSteve French #include <linux/slab.h> 2338c8a9a5SSteve French #include <linux/swap.h> 2438c8a9a5SSteve French #include <linux/mm.h> 2538c8a9a5SSteve French #include <asm/div64.h> 2638c8a9a5SSteve French #include "cifsfs.h" 2738c8a9a5SSteve French #include "cifspdu.h" 2838c8a9a5SSteve French #include "cifsglob.h" 2938c8a9a5SSteve French #include "cifsproto.h" 3038c8a9a5SSteve French #include "smb2proto.h" 3138c8a9a5SSteve French #include "cifs_unicode.h" 3238c8a9a5SSteve French #include "cifs_debug.h" 3338c8a9a5SSteve French #include "cifs_fs_sb.h" 3438c8a9a5SSteve French #include "fscache.h" 3538c8a9a5SSteve French #include "smbdirect.h" 3638c8a9a5SSteve French #include "fs_context.h" 3738c8a9a5SSteve French #include "cifs_ioctl.h" 3838c8a9a5SSteve French #include "cached_dir.h" 3938c8a9a5SSteve French 4038c8a9a5SSteve French /* 4138c8a9a5SSteve French * Remove the dirty flags from a span of pages. 4238c8a9a5SSteve French */ 4338c8a9a5SSteve French static void cifs_undirty_folios(struct inode *inode, loff_t start, unsigned int len) 4438c8a9a5SSteve French { 4538c8a9a5SSteve French struct address_space *mapping = inode->i_mapping; 4638c8a9a5SSteve French struct folio *folio; 4738c8a9a5SSteve French pgoff_t end; 4838c8a9a5SSteve French 4938c8a9a5SSteve French XA_STATE(xas, &mapping->i_pages, start / PAGE_SIZE); 5038c8a9a5SSteve French 5138c8a9a5SSteve French rcu_read_lock(); 5238c8a9a5SSteve French 5338c8a9a5SSteve French end = (start + len - 1) / PAGE_SIZE; 5438c8a9a5SSteve French xas_for_each_marked(&xas, folio, end, PAGECACHE_TAG_DIRTY) { 5538c8a9a5SSteve French if (xas_retry(&xas, folio)) 5638c8a9a5SSteve French continue; 5738c8a9a5SSteve French xas_pause(&xas); 5838c8a9a5SSteve French rcu_read_unlock(); 5938c8a9a5SSteve French folio_lock(folio); 6038c8a9a5SSteve French folio_clear_dirty_for_io(folio); 6138c8a9a5SSteve French folio_unlock(folio); 6238c8a9a5SSteve French rcu_read_lock(); 6338c8a9a5SSteve French } 6438c8a9a5SSteve French 6538c8a9a5SSteve French rcu_read_unlock(); 6638c8a9a5SSteve French } 6738c8a9a5SSteve French 6838c8a9a5SSteve French /* 6938c8a9a5SSteve French * Completion of write to server. 7038c8a9a5SSteve French */ 7138c8a9a5SSteve French void cifs_pages_written_back(struct inode *inode, loff_t start, unsigned int len) 7238c8a9a5SSteve French { 7338c8a9a5SSteve French struct address_space *mapping = inode->i_mapping; 7438c8a9a5SSteve French struct folio *folio; 7538c8a9a5SSteve French pgoff_t end; 7638c8a9a5SSteve French 7738c8a9a5SSteve French XA_STATE(xas, &mapping->i_pages, start / PAGE_SIZE); 7838c8a9a5SSteve French 7938c8a9a5SSteve French if (!len) 8038c8a9a5SSteve French return; 8138c8a9a5SSteve French 8238c8a9a5SSteve French rcu_read_lock(); 8338c8a9a5SSteve French 8438c8a9a5SSteve French end = (start + len - 1) / PAGE_SIZE; 8538c8a9a5SSteve French xas_for_each(&xas, folio, end) { 8638c8a9a5SSteve French if (xas_retry(&xas, folio)) 8738c8a9a5SSteve French continue; 8838c8a9a5SSteve French if (!folio_test_writeback(folio)) { 8938c8a9a5SSteve French WARN_ONCE(1, "bad %x @%llx page %lx %lx\n", 90d3c79235SDavid Howells len, start, folio->index, end); 9138c8a9a5SSteve French continue; 9238c8a9a5SSteve French } 9338c8a9a5SSteve French 9438c8a9a5SSteve French folio_detach_private(folio); 9538c8a9a5SSteve French folio_end_writeback(folio); 9638c8a9a5SSteve French } 9738c8a9a5SSteve French 9838c8a9a5SSteve French rcu_read_unlock(); 9938c8a9a5SSteve French } 10038c8a9a5SSteve French 10138c8a9a5SSteve French /* 10238c8a9a5SSteve French * Failure of write to server. 10338c8a9a5SSteve French */ 10438c8a9a5SSteve French void cifs_pages_write_failed(struct inode *inode, loff_t start, unsigned int len) 10538c8a9a5SSteve French { 10638c8a9a5SSteve French struct address_space *mapping = inode->i_mapping; 10738c8a9a5SSteve French struct folio *folio; 10838c8a9a5SSteve French pgoff_t end; 10938c8a9a5SSteve French 11038c8a9a5SSteve French XA_STATE(xas, &mapping->i_pages, start / PAGE_SIZE); 11138c8a9a5SSteve French 11238c8a9a5SSteve French if (!len) 11338c8a9a5SSteve French return; 11438c8a9a5SSteve French 11538c8a9a5SSteve French rcu_read_lock(); 11638c8a9a5SSteve French 11738c8a9a5SSteve French end = (start + len - 1) / PAGE_SIZE; 11838c8a9a5SSteve French xas_for_each(&xas, folio, end) { 11938c8a9a5SSteve French if (xas_retry(&xas, folio)) 12038c8a9a5SSteve French continue; 12138c8a9a5SSteve French if (!folio_test_writeback(folio)) { 12238c8a9a5SSteve French WARN_ONCE(1, "bad %x @%llx page %lx %lx\n", 123d3c79235SDavid Howells len, start, folio->index, end); 12438c8a9a5SSteve French continue; 12538c8a9a5SSteve French } 12638c8a9a5SSteve French 12738c8a9a5SSteve French folio_set_error(folio); 12838c8a9a5SSteve French folio_end_writeback(folio); 12938c8a9a5SSteve French } 13038c8a9a5SSteve French 13138c8a9a5SSteve French rcu_read_unlock(); 13238c8a9a5SSteve French } 13338c8a9a5SSteve French 13438c8a9a5SSteve French /* 13538c8a9a5SSteve French * Redirty pages after a temporary failure. 13638c8a9a5SSteve French */ 13738c8a9a5SSteve French void cifs_pages_write_redirty(struct inode *inode, loff_t start, unsigned int len) 13838c8a9a5SSteve French { 13938c8a9a5SSteve French struct address_space *mapping = inode->i_mapping; 14038c8a9a5SSteve French struct folio *folio; 14138c8a9a5SSteve French pgoff_t end; 14238c8a9a5SSteve French 14338c8a9a5SSteve French XA_STATE(xas, &mapping->i_pages, start / PAGE_SIZE); 14438c8a9a5SSteve French 14538c8a9a5SSteve French if (!len) 14638c8a9a5SSteve French return; 14738c8a9a5SSteve French 14838c8a9a5SSteve French rcu_read_lock(); 14938c8a9a5SSteve French 15038c8a9a5SSteve French end = (start + len - 1) / PAGE_SIZE; 15138c8a9a5SSteve French xas_for_each(&xas, folio, end) { 15238c8a9a5SSteve French if (!folio_test_writeback(folio)) { 15338c8a9a5SSteve French WARN_ONCE(1, "bad %x @%llx page %lx %lx\n", 154d3c79235SDavid Howells len, start, folio->index, end); 15538c8a9a5SSteve French continue; 15638c8a9a5SSteve French } 15738c8a9a5SSteve French 15838c8a9a5SSteve French filemap_dirty_folio(folio->mapping, folio); 15938c8a9a5SSteve French folio_end_writeback(folio); 16038c8a9a5SSteve French } 16138c8a9a5SSteve French 16238c8a9a5SSteve French rcu_read_unlock(); 16338c8a9a5SSteve French } 16438c8a9a5SSteve French 16538c8a9a5SSteve French /* 16638c8a9a5SSteve French * Mark as invalid, all open files on tree connections since they 16738c8a9a5SSteve French * were closed when session to server was lost. 16838c8a9a5SSteve French */ 16938c8a9a5SSteve French void 17038c8a9a5SSteve French cifs_mark_open_files_invalid(struct cifs_tcon *tcon) 17138c8a9a5SSteve French { 17238c8a9a5SSteve French struct cifsFileInfo *open_file = NULL; 17338c8a9a5SSteve French struct list_head *tmp; 17438c8a9a5SSteve French struct list_head *tmp1; 17538c8a9a5SSteve French 17638c8a9a5SSteve French /* only send once per connect */ 17738c8a9a5SSteve French spin_lock(&tcon->tc_lock); 178cd743cfeSShyam Prasad N if (tcon->need_reconnect) 179cd743cfeSShyam Prasad N tcon->status = TID_NEED_RECON; 180cd743cfeSShyam Prasad N 18138c8a9a5SSteve French if (tcon->status != TID_NEED_RECON) { 18238c8a9a5SSteve French spin_unlock(&tcon->tc_lock); 18338c8a9a5SSteve French return; 18438c8a9a5SSteve French } 18538c8a9a5SSteve French tcon->status = TID_IN_FILES_INVALIDATE; 18638c8a9a5SSteve French spin_unlock(&tcon->tc_lock); 18738c8a9a5SSteve French 18838c8a9a5SSteve French /* list all files open on tree connection and mark them invalid */ 18938c8a9a5SSteve French spin_lock(&tcon->open_file_lock); 19038c8a9a5SSteve French list_for_each_safe(tmp, tmp1, &tcon->openFileList) { 19138c8a9a5SSteve French open_file = list_entry(tmp, struct cifsFileInfo, tlist); 19238c8a9a5SSteve French open_file->invalidHandle = true; 19338c8a9a5SSteve French open_file->oplock_break_cancelled = true; 19438c8a9a5SSteve French } 19538c8a9a5SSteve French spin_unlock(&tcon->open_file_lock); 19638c8a9a5SSteve French 19738c8a9a5SSteve French invalidate_all_cached_dirs(tcon); 19838c8a9a5SSteve French spin_lock(&tcon->tc_lock); 19938c8a9a5SSteve French if (tcon->status == TID_IN_FILES_INVALIDATE) 20038c8a9a5SSteve French tcon->status = TID_NEED_TCON; 20138c8a9a5SSteve French spin_unlock(&tcon->tc_lock); 20238c8a9a5SSteve French 20338c8a9a5SSteve French /* 20438c8a9a5SSteve French * BB Add call to invalidate_inodes(sb) for all superblocks mounted 20538c8a9a5SSteve French * to this tcon. 20638c8a9a5SSteve French */ 20738c8a9a5SSteve French } 20838c8a9a5SSteve French 209*0fdada1eSDavid Howells static inline int cifs_convert_flags(unsigned int flags, int rdwr_for_fscache) 21038c8a9a5SSteve French { 21138c8a9a5SSteve French if ((flags & O_ACCMODE) == O_RDONLY) 21238c8a9a5SSteve French return GENERIC_READ; 21338c8a9a5SSteve French else if ((flags & O_ACCMODE) == O_WRONLY) 214*0fdada1eSDavid Howells return rdwr_for_fscache == 1 ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_WRITE; 21538c8a9a5SSteve French else if ((flags & O_ACCMODE) == O_RDWR) { 21638c8a9a5SSteve French /* GENERIC_ALL is too much permission to request 21738c8a9a5SSteve French can cause unnecessary access denied on create */ 21838c8a9a5SSteve French /* return GENERIC_ALL; */ 21938c8a9a5SSteve French return (GENERIC_READ | GENERIC_WRITE); 22038c8a9a5SSteve French } 22138c8a9a5SSteve French 22238c8a9a5SSteve French return (READ_CONTROL | FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | 22338c8a9a5SSteve French FILE_WRITE_EA | FILE_APPEND_DATA | FILE_WRITE_DATA | 22438c8a9a5SSteve French FILE_READ_DATA); 22538c8a9a5SSteve French } 22638c8a9a5SSteve French 22738c8a9a5SSteve French #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 22838c8a9a5SSteve French static u32 cifs_posix_convert_flags(unsigned int flags) 22938c8a9a5SSteve French { 23038c8a9a5SSteve French u32 posix_flags = 0; 23138c8a9a5SSteve French 23238c8a9a5SSteve French if ((flags & O_ACCMODE) == O_RDONLY) 23338c8a9a5SSteve French posix_flags = SMB_O_RDONLY; 23438c8a9a5SSteve French else if ((flags & O_ACCMODE) == O_WRONLY) 23538c8a9a5SSteve French posix_flags = SMB_O_WRONLY; 23638c8a9a5SSteve French else if ((flags & O_ACCMODE) == O_RDWR) 23738c8a9a5SSteve French posix_flags = SMB_O_RDWR; 23838c8a9a5SSteve French 23938c8a9a5SSteve French if (flags & O_CREAT) { 24038c8a9a5SSteve French posix_flags |= SMB_O_CREAT; 24138c8a9a5SSteve French if (flags & O_EXCL) 24238c8a9a5SSteve French posix_flags |= SMB_O_EXCL; 24338c8a9a5SSteve French } else if (flags & O_EXCL) 24438c8a9a5SSteve French cifs_dbg(FYI, "Application %s pid %d has incorrectly set O_EXCL flag but not O_CREAT on file open. Ignoring O_EXCL\n", 24538c8a9a5SSteve French current->comm, current->tgid); 24638c8a9a5SSteve French 24738c8a9a5SSteve French if (flags & O_TRUNC) 24838c8a9a5SSteve French posix_flags |= SMB_O_TRUNC; 24938c8a9a5SSteve French /* be safe and imply O_SYNC for O_DSYNC */ 25038c8a9a5SSteve French if (flags & O_DSYNC) 25138c8a9a5SSteve French posix_flags |= SMB_O_SYNC; 25238c8a9a5SSteve French if (flags & O_DIRECTORY) 25338c8a9a5SSteve French posix_flags |= SMB_O_DIRECTORY; 25438c8a9a5SSteve French if (flags & O_NOFOLLOW) 25538c8a9a5SSteve French posix_flags |= SMB_O_NOFOLLOW; 25638c8a9a5SSteve French if (flags & O_DIRECT) 25738c8a9a5SSteve French posix_flags |= SMB_O_DIRECT; 25838c8a9a5SSteve French 25938c8a9a5SSteve French return posix_flags; 26038c8a9a5SSteve French } 26138c8a9a5SSteve French #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 26238c8a9a5SSteve French 26338c8a9a5SSteve French static inline int cifs_get_disposition(unsigned int flags) 26438c8a9a5SSteve French { 26538c8a9a5SSteve French if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) 26638c8a9a5SSteve French return FILE_CREATE; 26738c8a9a5SSteve French else if ((flags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) 26838c8a9a5SSteve French return FILE_OVERWRITE_IF; 26938c8a9a5SSteve French else if ((flags & O_CREAT) == O_CREAT) 27038c8a9a5SSteve French return FILE_OPEN_IF; 27138c8a9a5SSteve French else if ((flags & O_TRUNC) == O_TRUNC) 27238c8a9a5SSteve French return FILE_OVERWRITE; 27338c8a9a5SSteve French else 27438c8a9a5SSteve French return FILE_OPEN; 27538c8a9a5SSteve French } 27638c8a9a5SSteve French 27738c8a9a5SSteve French #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 27838c8a9a5SSteve French int cifs_posix_open(const char *full_path, struct inode **pinode, 27938c8a9a5SSteve French struct super_block *sb, int mode, unsigned int f_flags, 28038c8a9a5SSteve French __u32 *poplock, __u16 *pnetfid, unsigned int xid) 28138c8a9a5SSteve French { 28238c8a9a5SSteve French int rc; 28338c8a9a5SSteve French FILE_UNIX_BASIC_INFO *presp_data; 28438c8a9a5SSteve French __u32 posix_flags = 0; 28538c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 28638c8a9a5SSteve French struct cifs_fattr fattr; 28738c8a9a5SSteve French struct tcon_link *tlink; 28838c8a9a5SSteve French struct cifs_tcon *tcon; 28938c8a9a5SSteve French 29038c8a9a5SSteve French cifs_dbg(FYI, "posix open %s\n", full_path); 29138c8a9a5SSteve French 29238c8a9a5SSteve French presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL); 29338c8a9a5SSteve French if (presp_data == NULL) 29438c8a9a5SSteve French return -ENOMEM; 29538c8a9a5SSteve French 29638c8a9a5SSteve French tlink = cifs_sb_tlink(cifs_sb); 29738c8a9a5SSteve French if (IS_ERR(tlink)) { 29838c8a9a5SSteve French rc = PTR_ERR(tlink); 29938c8a9a5SSteve French goto posix_open_ret; 30038c8a9a5SSteve French } 30138c8a9a5SSteve French 30238c8a9a5SSteve French tcon = tlink_tcon(tlink); 30338c8a9a5SSteve French mode &= ~current_umask(); 30438c8a9a5SSteve French 30538c8a9a5SSteve French posix_flags = cifs_posix_convert_flags(f_flags); 30638c8a9a5SSteve French rc = CIFSPOSIXCreate(xid, tcon, posix_flags, mode, pnetfid, presp_data, 30738c8a9a5SSteve French poplock, full_path, cifs_sb->local_nls, 30838c8a9a5SSteve French cifs_remap(cifs_sb)); 30938c8a9a5SSteve French cifs_put_tlink(tlink); 31038c8a9a5SSteve French 31138c8a9a5SSteve French if (rc) 31238c8a9a5SSteve French goto posix_open_ret; 31338c8a9a5SSteve French 31438c8a9a5SSteve French if (presp_data->Type == cpu_to_le32(-1)) 31538c8a9a5SSteve French goto posix_open_ret; /* open ok, caller does qpathinfo */ 31638c8a9a5SSteve French 31738c8a9a5SSteve French if (!pinode) 31838c8a9a5SSteve French goto posix_open_ret; /* caller does not need info */ 31938c8a9a5SSteve French 32038c8a9a5SSteve French cifs_unix_basic_to_fattr(&fattr, presp_data, cifs_sb); 32138c8a9a5SSteve French 32238c8a9a5SSteve French /* get new inode and set it up */ 32338c8a9a5SSteve French if (*pinode == NULL) { 32438c8a9a5SSteve French cifs_fill_uniqueid(sb, &fattr); 32538c8a9a5SSteve French *pinode = cifs_iget(sb, &fattr); 32638c8a9a5SSteve French if (!*pinode) { 32738c8a9a5SSteve French rc = -ENOMEM; 32838c8a9a5SSteve French goto posix_open_ret; 32938c8a9a5SSteve French } 33038c8a9a5SSteve French } else { 33138c8a9a5SSteve French cifs_revalidate_mapping(*pinode); 3329179aa27SBharath SM rc = cifs_fattr_to_inode(*pinode, &fattr, false); 33338c8a9a5SSteve French } 33438c8a9a5SSteve French 33538c8a9a5SSteve French posix_open_ret: 33638c8a9a5SSteve French kfree(presp_data); 33738c8a9a5SSteve French return rc; 33838c8a9a5SSteve French } 33938c8a9a5SSteve French #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 34038c8a9a5SSteve French 34138c8a9a5SSteve French static int cifs_nt_open(const char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, 34238c8a9a5SSteve French struct cifs_tcon *tcon, unsigned int f_flags, __u32 *oplock, 34338c8a9a5SSteve French struct cifs_fid *fid, unsigned int xid, struct cifs_open_info_data *buf) 34438c8a9a5SSteve French { 34538c8a9a5SSteve French int rc; 34638c8a9a5SSteve French int desired_access; 34738c8a9a5SSteve French int disposition; 34838c8a9a5SSteve French int create_options = CREATE_NOT_DIR; 34938c8a9a5SSteve French struct TCP_Server_Info *server = tcon->ses->server; 35038c8a9a5SSteve French struct cifs_open_parms oparms; 351*0fdada1eSDavid Howells int rdwr_for_fscache = 0; 35238c8a9a5SSteve French 35338c8a9a5SSteve French if (!server->ops->open) 35438c8a9a5SSteve French return -ENOSYS; 35538c8a9a5SSteve French 356*0fdada1eSDavid Howells /* If we're caching, we need to be able to fill in around partial writes. */ 357*0fdada1eSDavid Howells if (cifs_fscache_enabled(inode) && (f_flags & O_ACCMODE) == O_WRONLY) 358*0fdada1eSDavid Howells rdwr_for_fscache = 1; 359*0fdada1eSDavid Howells 360*0fdada1eSDavid Howells desired_access = cifs_convert_flags(f_flags, rdwr_for_fscache); 36138c8a9a5SSteve French 36238c8a9a5SSteve French /********************************************************************* 36338c8a9a5SSteve French * open flag mapping table: 36438c8a9a5SSteve French * 36538c8a9a5SSteve French * POSIX Flag CIFS Disposition 36638c8a9a5SSteve French * ---------- ---------------- 36738c8a9a5SSteve French * O_CREAT FILE_OPEN_IF 36838c8a9a5SSteve French * O_CREAT | O_EXCL FILE_CREATE 36938c8a9a5SSteve French * O_CREAT | O_TRUNC FILE_OVERWRITE_IF 37038c8a9a5SSteve French * O_TRUNC FILE_OVERWRITE 37138c8a9a5SSteve French * none of the above FILE_OPEN 37238c8a9a5SSteve French * 37338c8a9a5SSteve French * Note that there is not a direct match between disposition 37438c8a9a5SSteve French * FILE_SUPERSEDE (ie create whether or not file exists although 37538c8a9a5SSteve French * O_CREAT | O_TRUNC is similar but truncates the existing 37638c8a9a5SSteve French * file rather than creating a new file as FILE_SUPERSEDE does 37738c8a9a5SSteve French * (which uses the attributes / metadata passed in on open call) 37838c8a9a5SSteve French *? 37938c8a9a5SSteve French *? O_SYNC is a reasonable match to CIFS writethrough flag 38038c8a9a5SSteve French *? and the read write flags match reasonably. O_LARGEFILE 38138c8a9a5SSteve French *? is irrelevant because largefile support is always used 38238c8a9a5SSteve French *? by this client. Flags O_APPEND, O_DIRECT, O_DIRECTORY, 38338c8a9a5SSteve French * O_FASYNC, O_NOFOLLOW, O_NONBLOCK need further investigation 38438c8a9a5SSteve French *********************************************************************/ 38538c8a9a5SSteve French 38638c8a9a5SSteve French disposition = cifs_get_disposition(f_flags); 38738c8a9a5SSteve French 38838c8a9a5SSteve French /* BB pass O_SYNC flag through on file attributes .. BB */ 38938c8a9a5SSteve French 39038c8a9a5SSteve French /* O_SYNC also has bit for O_DSYNC so following check picks up either */ 39138c8a9a5SSteve French if (f_flags & O_SYNC) 39238c8a9a5SSteve French create_options |= CREATE_WRITE_THROUGH; 39338c8a9a5SSteve French 39438c8a9a5SSteve French if (f_flags & O_DIRECT) 39538c8a9a5SSteve French create_options |= CREATE_NO_BUFFER; 39638c8a9a5SSteve French 397*0fdada1eSDavid Howells retry_open: 39838c8a9a5SSteve French oparms = (struct cifs_open_parms) { 39938c8a9a5SSteve French .tcon = tcon, 40038c8a9a5SSteve French .cifs_sb = cifs_sb, 40138c8a9a5SSteve French .desired_access = desired_access, 40238c8a9a5SSteve French .create_options = cifs_create_options(cifs_sb, create_options), 40338c8a9a5SSteve French .disposition = disposition, 40438c8a9a5SSteve French .path = full_path, 40538c8a9a5SSteve French .fid = fid, 40638c8a9a5SSteve French }; 40738c8a9a5SSteve French 40838c8a9a5SSteve French rc = server->ops->open(xid, &oparms, oplock, buf); 409*0fdada1eSDavid Howells if (rc) { 410*0fdada1eSDavid Howells if (rc == -EACCES && rdwr_for_fscache == 1) { 411*0fdada1eSDavid Howells desired_access = cifs_convert_flags(f_flags, 0); 412*0fdada1eSDavid Howells rdwr_for_fscache = 2; 413*0fdada1eSDavid Howells goto retry_open; 414*0fdada1eSDavid Howells } 41538c8a9a5SSteve French return rc; 416*0fdada1eSDavid Howells } 417*0fdada1eSDavid Howells if (rdwr_for_fscache == 2) 418*0fdada1eSDavid Howells cifs_invalidate_cache(inode, FSCACHE_INVAL_DIO_WRITE); 41938c8a9a5SSteve French 42038c8a9a5SSteve French /* TODO: Add support for calling posix query info but with passing in fid */ 42138c8a9a5SSteve French if (tcon->unix_ext) 42238c8a9a5SSteve French rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb, 42338c8a9a5SSteve French xid); 42438c8a9a5SSteve French else 42538c8a9a5SSteve French rc = cifs_get_inode_info(&inode, full_path, buf, inode->i_sb, 42638c8a9a5SSteve French xid, fid); 42738c8a9a5SSteve French 42838c8a9a5SSteve French if (rc) { 42938c8a9a5SSteve French server->ops->close(xid, tcon, fid); 43038c8a9a5SSteve French if (rc == -ESTALE) 43138c8a9a5SSteve French rc = -EOPENSTALE; 43238c8a9a5SSteve French } 43338c8a9a5SSteve French 43438c8a9a5SSteve French return rc; 43538c8a9a5SSteve French } 43638c8a9a5SSteve French 43738c8a9a5SSteve French static bool 43838c8a9a5SSteve French cifs_has_mand_locks(struct cifsInodeInfo *cinode) 43938c8a9a5SSteve French { 44038c8a9a5SSteve French struct cifs_fid_locks *cur; 44138c8a9a5SSteve French bool has_locks = false; 44238c8a9a5SSteve French 44338c8a9a5SSteve French down_read(&cinode->lock_sem); 44438c8a9a5SSteve French list_for_each_entry(cur, &cinode->llist, llist) { 44538c8a9a5SSteve French if (!list_empty(&cur->locks)) { 44638c8a9a5SSteve French has_locks = true; 44738c8a9a5SSteve French break; 44838c8a9a5SSteve French } 44938c8a9a5SSteve French } 45038c8a9a5SSteve French up_read(&cinode->lock_sem); 45138c8a9a5SSteve French return has_locks; 45238c8a9a5SSteve French } 45338c8a9a5SSteve French 45438c8a9a5SSteve French void 45538c8a9a5SSteve French cifs_down_write(struct rw_semaphore *sem) 45638c8a9a5SSteve French { 45738c8a9a5SSteve French while (!down_write_trylock(sem)) 45838c8a9a5SSteve French msleep(10); 45938c8a9a5SSteve French } 46038c8a9a5SSteve French 46138c8a9a5SSteve French static void cifsFileInfo_put_work(struct work_struct *work); 46238c8a9a5SSteve French 46338c8a9a5SSteve French struct cifsFileInfo *cifs_new_fileinfo(struct cifs_fid *fid, struct file *file, 46438c8a9a5SSteve French struct tcon_link *tlink, __u32 oplock, 46538c8a9a5SSteve French const char *symlink_target) 46638c8a9a5SSteve French { 46738c8a9a5SSteve French struct dentry *dentry = file_dentry(file); 46838c8a9a5SSteve French struct inode *inode = d_inode(dentry); 46938c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(inode); 47038c8a9a5SSteve French struct cifsFileInfo *cfile; 47138c8a9a5SSteve French struct cifs_fid_locks *fdlocks; 47238c8a9a5SSteve French struct cifs_tcon *tcon = tlink_tcon(tlink); 47338c8a9a5SSteve French struct TCP_Server_Info *server = tcon->ses->server; 47438c8a9a5SSteve French 47538c8a9a5SSteve French cfile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); 47638c8a9a5SSteve French if (cfile == NULL) 47738c8a9a5SSteve French return cfile; 47838c8a9a5SSteve French 47938c8a9a5SSteve French fdlocks = kzalloc(sizeof(struct cifs_fid_locks), GFP_KERNEL); 48038c8a9a5SSteve French if (!fdlocks) { 48138c8a9a5SSteve French kfree(cfile); 48238c8a9a5SSteve French return NULL; 48338c8a9a5SSteve French } 48438c8a9a5SSteve French 48538c8a9a5SSteve French if (symlink_target) { 48638c8a9a5SSteve French cfile->symlink_target = kstrdup(symlink_target, GFP_KERNEL); 48738c8a9a5SSteve French if (!cfile->symlink_target) { 48838c8a9a5SSteve French kfree(fdlocks); 48938c8a9a5SSteve French kfree(cfile); 49038c8a9a5SSteve French return NULL; 49138c8a9a5SSteve French } 49238c8a9a5SSteve French } 49338c8a9a5SSteve French 49438c8a9a5SSteve French INIT_LIST_HEAD(&fdlocks->locks); 49538c8a9a5SSteve French fdlocks->cfile = cfile; 49638c8a9a5SSteve French cfile->llist = fdlocks; 49738c8a9a5SSteve French 49838c8a9a5SSteve French cfile->count = 1; 49938c8a9a5SSteve French cfile->pid = current->tgid; 50038c8a9a5SSteve French cfile->uid = current_fsuid(); 50138c8a9a5SSteve French cfile->dentry = dget(dentry); 50238c8a9a5SSteve French cfile->f_flags = file->f_flags; 50338c8a9a5SSteve French cfile->invalidHandle = false; 50438c8a9a5SSteve French cfile->deferred_close_scheduled = false; 50538c8a9a5SSteve French cfile->tlink = cifs_get_tlink(tlink); 50638c8a9a5SSteve French INIT_WORK(&cfile->oplock_break, cifs_oplock_break); 50738c8a9a5SSteve French INIT_WORK(&cfile->put, cifsFileInfo_put_work); 50838c8a9a5SSteve French INIT_DELAYED_WORK(&cfile->deferred, smb2_deferred_work_close); 50938c8a9a5SSteve French mutex_init(&cfile->fh_mutex); 51038c8a9a5SSteve French spin_lock_init(&cfile->file_info_lock); 51138c8a9a5SSteve French 51238c8a9a5SSteve French cifs_sb_active(inode->i_sb); 51338c8a9a5SSteve French 51438c8a9a5SSteve French /* 51538c8a9a5SSteve French * If the server returned a read oplock and we have mandatory brlocks, 51638c8a9a5SSteve French * set oplock level to None. 51738c8a9a5SSteve French */ 51838c8a9a5SSteve French if (server->ops->is_read_op(oplock) && cifs_has_mand_locks(cinode)) { 51938c8a9a5SSteve French cifs_dbg(FYI, "Reset oplock val from read to None due to mand locks\n"); 52038c8a9a5SSteve French oplock = 0; 52138c8a9a5SSteve French } 52238c8a9a5SSteve French 52338c8a9a5SSteve French cifs_down_write(&cinode->lock_sem); 52438c8a9a5SSteve French list_add(&fdlocks->llist, &cinode->llist); 52538c8a9a5SSteve French up_write(&cinode->lock_sem); 52638c8a9a5SSteve French 52738c8a9a5SSteve French spin_lock(&tcon->open_file_lock); 52838c8a9a5SSteve French if (fid->pending_open->oplock != CIFS_OPLOCK_NO_CHANGE && oplock) 52938c8a9a5SSteve French oplock = fid->pending_open->oplock; 53038c8a9a5SSteve French list_del(&fid->pending_open->olist); 53138c8a9a5SSteve French 53238c8a9a5SSteve French fid->purge_cache = false; 53338c8a9a5SSteve French server->ops->set_fid(cfile, fid, oplock); 53438c8a9a5SSteve French 53538c8a9a5SSteve French list_add(&cfile->tlist, &tcon->openFileList); 53638c8a9a5SSteve French atomic_inc(&tcon->num_local_opens); 53738c8a9a5SSteve French 53838c8a9a5SSteve French /* if readable file instance put first in list*/ 53938c8a9a5SSteve French spin_lock(&cinode->open_file_lock); 54038c8a9a5SSteve French if (file->f_mode & FMODE_READ) 54138c8a9a5SSteve French list_add(&cfile->flist, &cinode->openFileList); 54238c8a9a5SSteve French else 54338c8a9a5SSteve French list_add_tail(&cfile->flist, &cinode->openFileList); 54438c8a9a5SSteve French spin_unlock(&cinode->open_file_lock); 54538c8a9a5SSteve French spin_unlock(&tcon->open_file_lock); 54638c8a9a5SSteve French 54738c8a9a5SSteve French if (fid->purge_cache) 54838c8a9a5SSteve French cifs_zap_mapping(inode); 54938c8a9a5SSteve French 55038c8a9a5SSteve French file->private_data = cfile; 55138c8a9a5SSteve French return cfile; 55238c8a9a5SSteve French } 55338c8a9a5SSteve French 55438c8a9a5SSteve French struct cifsFileInfo * 55538c8a9a5SSteve French cifsFileInfo_get(struct cifsFileInfo *cifs_file) 55638c8a9a5SSteve French { 55738c8a9a5SSteve French spin_lock(&cifs_file->file_info_lock); 55838c8a9a5SSteve French cifsFileInfo_get_locked(cifs_file); 55938c8a9a5SSteve French spin_unlock(&cifs_file->file_info_lock); 56038c8a9a5SSteve French return cifs_file; 56138c8a9a5SSteve French } 56238c8a9a5SSteve French 56338c8a9a5SSteve French static void cifsFileInfo_put_final(struct cifsFileInfo *cifs_file) 56438c8a9a5SSteve French { 56538c8a9a5SSteve French struct inode *inode = d_inode(cifs_file->dentry); 56638c8a9a5SSteve French struct cifsInodeInfo *cifsi = CIFS_I(inode); 56738c8a9a5SSteve French struct cifsLockInfo *li, *tmp; 56838c8a9a5SSteve French struct super_block *sb = inode->i_sb; 56938c8a9a5SSteve French 57038c8a9a5SSteve French /* 57138c8a9a5SSteve French * Delete any outstanding lock records. We'll lose them when the file 57238c8a9a5SSteve French * is closed anyway. 57338c8a9a5SSteve French */ 57438c8a9a5SSteve French cifs_down_write(&cifsi->lock_sem); 57538c8a9a5SSteve French list_for_each_entry_safe(li, tmp, &cifs_file->llist->locks, llist) { 57638c8a9a5SSteve French list_del(&li->llist); 57738c8a9a5SSteve French cifs_del_lock_waiters(li); 57838c8a9a5SSteve French kfree(li); 57938c8a9a5SSteve French } 58038c8a9a5SSteve French list_del(&cifs_file->llist->llist); 58138c8a9a5SSteve French kfree(cifs_file->llist); 58238c8a9a5SSteve French up_write(&cifsi->lock_sem); 58338c8a9a5SSteve French 58438c8a9a5SSteve French cifs_put_tlink(cifs_file->tlink); 58538c8a9a5SSteve French dput(cifs_file->dentry); 58638c8a9a5SSteve French cifs_sb_deactive(sb); 58738c8a9a5SSteve French kfree(cifs_file->symlink_target); 58838c8a9a5SSteve French kfree(cifs_file); 58938c8a9a5SSteve French } 59038c8a9a5SSteve French 59138c8a9a5SSteve French static void cifsFileInfo_put_work(struct work_struct *work) 59238c8a9a5SSteve French { 59338c8a9a5SSteve French struct cifsFileInfo *cifs_file = container_of(work, 59438c8a9a5SSteve French struct cifsFileInfo, put); 59538c8a9a5SSteve French 59638c8a9a5SSteve French cifsFileInfo_put_final(cifs_file); 59738c8a9a5SSteve French } 59838c8a9a5SSteve French 59938c8a9a5SSteve French /** 60038c8a9a5SSteve French * cifsFileInfo_put - release a reference of file priv data 60138c8a9a5SSteve French * 60238c8a9a5SSteve French * Always potentially wait for oplock handler. See _cifsFileInfo_put(). 60338c8a9a5SSteve French * 60438c8a9a5SSteve French * @cifs_file: cifs/smb3 specific info (eg refcounts) for an open file 60538c8a9a5SSteve French */ 60638c8a9a5SSteve French void cifsFileInfo_put(struct cifsFileInfo *cifs_file) 60738c8a9a5SSteve French { 60838c8a9a5SSteve French _cifsFileInfo_put(cifs_file, true, true); 60938c8a9a5SSteve French } 61038c8a9a5SSteve French 61138c8a9a5SSteve French /** 61238c8a9a5SSteve French * _cifsFileInfo_put - release a reference of file priv data 61338c8a9a5SSteve French * 61438c8a9a5SSteve French * This may involve closing the filehandle @cifs_file out on the 61538c8a9a5SSteve French * server. Must be called without holding tcon->open_file_lock, 61638c8a9a5SSteve French * cinode->open_file_lock and cifs_file->file_info_lock. 61738c8a9a5SSteve French * 61838c8a9a5SSteve French * If @wait_for_oplock_handler is true and we are releasing the last 61938c8a9a5SSteve French * reference, wait for any running oplock break handler of the file 62038c8a9a5SSteve French * and cancel any pending one. 62138c8a9a5SSteve French * 62238c8a9a5SSteve French * @cifs_file: cifs/smb3 specific info (eg refcounts) for an open file 62338c8a9a5SSteve French * @wait_oplock_handler: must be false if called from oplock_break_handler 62438c8a9a5SSteve French * @offload: not offloaded on close and oplock breaks 62538c8a9a5SSteve French * 62638c8a9a5SSteve French */ 62738c8a9a5SSteve French void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, 62838c8a9a5SSteve French bool wait_oplock_handler, bool offload) 62938c8a9a5SSteve French { 63038c8a9a5SSteve French struct inode *inode = d_inode(cifs_file->dentry); 63138c8a9a5SSteve French struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink); 63238c8a9a5SSteve French struct TCP_Server_Info *server = tcon->ses->server; 63338c8a9a5SSteve French struct cifsInodeInfo *cifsi = CIFS_I(inode); 63438c8a9a5SSteve French struct super_block *sb = inode->i_sb; 63538c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(sb); 63638c8a9a5SSteve French struct cifs_fid fid = {}; 63738c8a9a5SSteve French struct cifs_pending_open open; 63838c8a9a5SSteve French bool oplock_break_cancelled; 63938c8a9a5SSteve French 64038c8a9a5SSteve French spin_lock(&tcon->open_file_lock); 64138c8a9a5SSteve French spin_lock(&cifsi->open_file_lock); 64238c8a9a5SSteve French spin_lock(&cifs_file->file_info_lock); 64338c8a9a5SSteve French if (--cifs_file->count > 0) { 64438c8a9a5SSteve French spin_unlock(&cifs_file->file_info_lock); 64538c8a9a5SSteve French spin_unlock(&cifsi->open_file_lock); 64638c8a9a5SSteve French spin_unlock(&tcon->open_file_lock); 64738c8a9a5SSteve French return; 64838c8a9a5SSteve French } 64938c8a9a5SSteve French spin_unlock(&cifs_file->file_info_lock); 65038c8a9a5SSteve French 65138c8a9a5SSteve French if (server->ops->get_lease_key) 65238c8a9a5SSteve French server->ops->get_lease_key(inode, &fid); 65338c8a9a5SSteve French 65438c8a9a5SSteve French /* store open in pending opens to make sure we don't miss lease break */ 65538c8a9a5SSteve French cifs_add_pending_open_locked(&fid, cifs_file->tlink, &open); 65638c8a9a5SSteve French 65738c8a9a5SSteve French /* remove it from the lists */ 65838c8a9a5SSteve French list_del(&cifs_file->flist); 65938c8a9a5SSteve French list_del(&cifs_file->tlist); 66038c8a9a5SSteve French atomic_dec(&tcon->num_local_opens); 66138c8a9a5SSteve French 66238c8a9a5SSteve French if (list_empty(&cifsi->openFileList)) { 66338c8a9a5SSteve French cifs_dbg(FYI, "closing last open instance for inode %p\n", 66438c8a9a5SSteve French d_inode(cifs_file->dentry)); 66538c8a9a5SSteve French /* 66638c8a9a5SSteve French * In strict cache mode we need invalidate mapping on the last 66738c8a9a5SSteve French * close because it may cause a error when we open this file 66838c8a9a5SSteve French * again and get at least level II oplock. 66938c8a9a5SSteve French */ 67038c8a9a5SSteve French if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) 67138c8a9a5SSteve French set_bit(CIFS_INO_INVALID_MAPPING, &cifsi->flags); 67238c8a9a5SSteve French cifs_set_oplock_level(cifsi, 0); 67338c8a9a5SSteve French } 67438c8a9a5SSteve French 67538c8a9a5SSteve French spin_unlock(&cifsi->open_file_lock); 67638c8a9a5SSteve French spin_unlock(&tcon->open_file_lock); 67738c8a9a5SSteve French 67838c8a9a5SSteve French oplock_break_cancelled = wait_oplock_handler ? 67938c8a9a5SSteve French cancel_work_sync(&cifs_file->oplock_break) : false; 68038c8a9a5SSteve French 68138c8a9a5SSteve French if (!tcon->need_reconnect && !cifs_file->invalidHandle) { 68238c8a9a5SSteve French struct TCP_Server_Info *server = tcon->ses->server; 68338c8a9a5SSteve French unsigned int xid; 68438c8a9a5SSteve French 68538c8a9a5SSteve French xid = get_xid(); 68638c8a9a5SSteve French if (server->ops->close_getattr) 68738c8a9a5SSteve French server->ops->close_getattr(xid, tcon, cifs_file); 68838c8a9a5SSteve French else if (server->ops->close) 68938c8a9a5SSteve French server->ops->close(xid, tcon, &cifs_file->fid); 69038c8a9a5SSteve French _free_xid(xid); 69138c8a9a5SSteve French } 69238c8a9a5SSteve French 69338c8a9a5SSteve French if (oplock_break_cancelled) 69438c8a9a5SSteve French cifs_done_oplock_break(cifsi); 69538c8a9a5SSteve French 69638c8a9a5SSteve French cifs_del_pending_open(&open); 69738c8a9a5SSteve French 69838c8a9a5SSteve French if (offload) 69938c8a9a5SSteve French queue_work(fileinfo_put_wq, &cifs_file->put); 70038c8a9a5SSteve French else 70138c8a9a5SSteve French cifsFileInfo_put_final(cifs_file); 70238c8a9a5SSteve French } 70338c8a9a5SSteve French 70438c8a9a5SSteve French int cifs_open(struct inode *inode, struct file *file) 70538c8a9a5SSteve French 70638c8a9a5SSteve French { 70738c8a9a5SSteve French int rc = -EACCES; 70838c8a9a5SSteve French unsigned int xid; 70938c8a9a5SSteve French __u32 oplock; 71038c8a9a5SSteve French struct cifs_sb_info *cifs_sb; 71138c8a9a5SSteve French struct TCP_Server_Info *server; 71238c8a9a5SSteve French struct cifs_tcon *tcon; 71338c8a9a5SSteve French struct tcon_link *tlink; 71438c8a9a5SSteve French struct cifsFileInfo *cfile = NULL; 71538c8a9a5SSteve French void *page; 71638c8a9a5SSteve French const char *full_path; 71738c8a9a5SSteve French bool posix_open_ok = false; 71838c8a9a5SSteve French struct cifs_fid fid = {}; 71938c8a9a5SSteve French struct cifs_pending_open open; 72038c8a9a5SSteve French struct cifs_open_info_data data = {}; 72138c8a9a5SSteve French 72238c8a9a5SSteve French xid = get_xid(); 72338c8a9a5SSteve French 72438c8a9a5SSteve French cifs_sb = CIFS_SB(inode->i_sb); 72538c8a9a5SSteve French if (unlikely(cifs_forced_shutdown(cifs_sb))) { 72638c8a9a5SSteve French free_xid(xid); 72738c8a9a5SSteve French return -EIO; 72838c8a9a5SSteve French } 72938c8a9a5SSteve French 73038c8a9a5SSteve French tlink = cifs_sb_tlink(cifs_sb); 73138c8a9a5SSteve French if (IS_ERR(tlink)) { 73238c8a9a5SSteve French free_xid(xid); 73338c8a9a5SSteve French return PTR_ERR(tlink); 73438c8a9a5SSteve French } 73538c8a9a5SSteve French tcon = tlink_tcon(tlink); 73638c8a9a5SSteve French server = tcon->ses->server; 73738c8a9a5SSteve French 73838c8a9a5SSteve French page = alloc_dentry_path(); 73938c8a9a5SSteve French full_path = build_path_from_dentry(file_dentry(file), page); 74038c8a9a5SSteve French if (IS_ERR(full_path)) { 74138c8a9a5SSteve French rc = PTR_ERR(full_path); 74238c8a9a5SSteve French goto out; 74338c8a9a5SSteve French } 74438c8a9a5SSteve French 74538c8a9a5SSteve French cifs_dbg(FYI, "inode = 0x%p file flags are 0x%x for %s\n", 74638c8a9a5SSteve French inode, file->f_flags, full_path); 74738c8a9a5SSteve French 74838c8a9a5SSteve French if (file->f_flags & O_DIRECT && 74938c8a9a5SSteve French cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) { 75038c8a9a5SSteve French if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) 75138c8a9a5SSteve French file->f_op = &cifs_file_direct_nobrl_ops; 75238c8a9a5SSteve French else 75338c8a9a5SSteve French file->f_op = &cifs_file_direct_ops; 75438c8a9a5SSteve French } 75538c8a9a5SSteve French 75638c8a9a5SSteve French /* Get the cached handle as SMB2 close is deferred */ 75738c8a9a5SSteve French rc = cifs_get_readable_path(tcon, full_path, &cfile); 75838c8a9a5SSteve French if (rc == 0) { 75938c8a9a5SSteve French if (file->f_flags == cfile->f_flags) { 76038c8a9a5SSteve French file->private_data = cfile; 76138c8a9a5SSteve French spin_lock(&CIFS_I(inode)->deferred_lock); 76238c8a9a5SSteve French cifs_del_deferred_close(cfile); 76338c8a9a5SSteve French spin_unlock(&CIFS_I(inode)->deferred_lock); 76438c8a9a5SSteve French goto use_cache; 76538c8a9a5SSteve French } else { 76638c8a9a5SSteve French _cifsFileInfo_put(cfile, true, false); 76738c8a9a5SSteve French } 76838c8a9a5SSteve French } 76938c8a9a5SSteve French 77038c8a9a5SSteve French if (server->oplocks) 77138c8a9a5SSteve French oplock = REQ_OPLOCK; 77238c8a9a5SSteve French else 77338c8a9a5SSteve French oplock = 0; 77438c8a9a5SSteve French 77538c8a9a5SSteve French #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 77638c8a9a5SSteve French if (!tcon->broken_posix_open && tcon->unix_ext && 77738c8a9a5SSteve French cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP & 77838c8a9a5SSteve French le64_to_cpu(tcon->fsUnixInfo.Capability))) { 77938c8a9a5SSteve French /* can not refresh inode info since size could be stale */ 78038c8a9a5SSteve French rc = cifs_posix_open(full_path, &inode, inode->i_sb, 78138c8a9a5SSteve French cifs_sb->ctx->file_mode /* ignored */, 78238c8a9a5SSteve French file->f_flags, &oplock, &fid.netfid, xid); 78338c8a9a5SSteve French if (rc == 0) { 78438c8a9a5SSteve French cifs_dbg(FYI, "posix open succeeded\n"); 78538c8a9a5SSteve French posix_open_ok = true; 78638c8a9a5SSteve French } else if ((rc == -EINVAL) || (rc == -EOPNOTSUPP)) { 78738c8a9a5SSteve French if (tcon->ses->serverNOS) 78838c8a9a5SSteve French cifs_dbg(VFS, "server %s of type %s returned unexpected error on SMB posix open, disabling posix open support. Check if server update available.\n", 78938c8a9a5SSteve French tcon->ses->ip_addr, 79038c8a9a5SSteve French tcon->ses->serverNOS); 79138c8a9a5SSteve French tcon->broken_posix_open = true; 79238c8a9a5SSteve French } else if ((rc != -EIO) && (rc != -EREMOTE) && 79338c8a9a5SSteve French (rc != -EOPNOTSUPP)) /* path not found or net err */ 79438c8a9a5SSteve French goto out; 79538c8a9a5SSteve French /* 79638c8a9a5SSteve French * Else fallthrough to retry open the old way on network i/o 79738c8a9a5SSteve French * or DFS errors. 79838c8a9a5SSteve French */ 79938c8a9a5SSteve French } 80038c8a9a5SSteve French #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 80138c8a9a5SSteve French 80238c8a9a5SSteve French if (server->ops->get_lease_key) 80338c8a9a5SSteve French server->ops->get_lease_key(inode, &fid); 80438c8a9a5SSteve French 80538c8a9a5SSteve French cifs_add_pending_open(&fid, tlink, &open); 80638c8a9a5SSteve French 80738c8a9a5SSteve French if (!posix_open_ok) { 80838c8a9a5SSteve French if (server->ops->get_lease_key) 80938c8a9a5SSteve French server->ops->get_lease_key(inode, &fid); 81038c8a9a5SSteve French 81138c8a9a5SSteve French rc = cifs_nt_open(full_path, inode, cifs_sb, tcon, file->f_flags, &oplock, &fid, 81238c8a9a5SSteve French xid, &data); 81338c8a9a5SSteve French if (rc) { 81438c8a9a5SSteve French cifs_del_pending_open(&open); 81538c8a9a5SSteve French goto out; 81638c8a9a5SSteve French } 81738c8a9a5SSteve French } 81838c8a9a5SSteve French 81938c8a9a5SSteve French cfile = cifs_new_fileinfo(&fid, file, tlink, oplock, data.symlink_target); 82038c8a9a5SSteve French if (cfile == NULL) { 82138c8a9a5SSteve French if (server->ops->close) 82238c8a9a5SSteve French server->ops->close(xid, tcon, &fid); 82338c8a9a5SSteve French cifs_del_pending_open(&open); 82438c8a9a5SSteve French rc = -ENOMEM; 82538c8a9a5SSteve French goto out; 82638c8a9a5SSteve French } 82738c8a9a5SSteve French 82838c8a9a5SSteve French #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 82938c8a9a5SSteve French if ((oplock & CIFS_CREATE_ACTION) && !posix_open_ok && tcon->unix_ext) { 83038c8a9a5SSteve French /* 83138c8a9a5SSteve French * Time to set mode which we can not set earlier due to 83238c8a9a5SSteve French * problems creating new read-only files. 83338c8a9a5SSteve French */ 83438c8a9a5SSteve French struct cifs_unix_set_info_args args = { 83538c8a9a5SSteve French .mode = inode->i_mode, 83638c8a9a5SSteve French .uid = INVALID_UID, /* no change */ 83738c8a9a5SSteve French .gid = INVALID_GID, /* no change */ 83838c8a9a5SSteve French .ctime = NO_CHANGE_64, 83938c8a9a5SSteve French .atime = NO_CHANGE_64, 84038c8a9a5SSteve French .mtime = NO_CHANGE_64, 84138c8a9a5SSteve French .device = 0, 84238c8a9a5SSteve French }; 84338c8a9a5SSteve French CIFSSMBUnixSetFileInfo(xid, tcon, &args, fid.netfid, 84438c8a9a5SSteve French cfile->pid); 84538c8a9a5SSteve French } 84638c8a9a5SSteve French #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 84738c8a9a5SSteve French 84838c8a9a5SSteve French use_cache: 84938c8a9a5SSteve French fscache_use_cookie(cifs_inode_cookie(file_inode(file)), 85038c8a9a5SSteve French file->f_mode & FMODE_WRITE); 851*0fdada1eSDavid Howells if (!(file->f_flags & O_DIRECT)) 852*0fdada1eSDavid Howells goto out; 853*0fdada1eSDavid Howells if ((file->f_flags & (O_ACCMODE | O_APPEND)) == O_RDONLY) 854*0fdada1eSDavid Howells goto out; 855*0fdada1eSDavid Howells cifs_invalidate_cache(file_inode(file), FSCACHE_INVAL_DIO_WRITE); 85638c8a9a5SSteve French 85738c8a9a5SSteve French out: 85838c8a9a5SSteve French free_dentry_path(page); 85938c8a9a5SSteve French free_xid(xid); 86038c8a9a5SSteve French cifs_put_tlink(tlink); 86138c8a9a5SSteve French cifs_free_open_info(&data); 86238c8a9a5SSteve French return rc; 86338c8a9a5SSteve French } 86438c8a9a5SSteve French 86538c8a9a5SSteve French #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 86638c8a9a5SSteve French static int cifs_push_posix_locks(struct cifsFileInfo *cfile); 86738c8a9a5SSteve French #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 86838c8a9a5SSteve French 86938c8a9a5SSteve French /* 87038c8a9a5SSteve French * Try to reacquire byte range locks that were released when session 87138c8a9a5SSteve French * to server was lost. 87238c8a9a5SSteve French */ 87338c8a9a5SSteve French static int 87438c8a9a5SSteve French cifs_relock_file(struct cifsFileInfo *cfile) 87538c8a9a5SSteve French { 87638c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); 87738c8a9a5SSteve French struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 87838c8a9a5SSteve French int rc = 0; 87938c8a9a5SSteve French #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 88038c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb); 88138c8a9a5SSteve French #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 88238c8a9a5SSteve French 88338c8a9a5SSteve French down_read_nested(&cinode->lock_sem, SINGLE_DEPTH_NESTING); 88438c8a9a5SSteve French if (cinode->can_cache_brlcks) { 88538c8a9a5SSteve French /* can cache locks - no need to relock */ 88638c8a9a5SSteve French up_read(&cinode->lock_sem); 88738c8a9a5SSteve French return rc; 88838c8a9a5SSteve French } 88938c8a9a5SSteve French 89038c8a9a5SSteve French #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 89138c8a9a5SSteve French if (cap_unix(tcon->ses) && 89238c8a9a5SSteve French (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && 89338c8a9a5SSteve French ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) 89438c8a9a5SSteve French rc = cifs_push_posix_locks(cfile); 89538c8a9a5SSteve French else 89638c8a9a5SSteve French #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 89738c8a9a5SSteve French rc = tcon->ses->server->ops->push_mand_locks(cfile); 89838c8a9a5SSteve French 89938c8a9a5SSteve French up_read(&cinode->lock_sem); 90038c8a9a5SSteve French return rc; 90138c8a9a5SSteve French } 90238c8a9a5SSteve French 90338c8a9a5SSteve French static int 90438c8a9a5SSteve French cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush) 90538c8a9a5SSteve French { 90638c8a9a5SSteve French int rc = -EACCES; 90738c8a9a5SSteve French unsigned int xid; 90838c8a9a5SSteve French __u32 oplock; 90938c8a9a5SSteve French struct cifs_sb_info *cifs_sb; 91038c8a9a5SSteve French struct cifs_tcon *tcon; 91138c8a9a5SSteve French struct TCP_Server_Info *server; 91238c8a9a5SSteve French struct cifsInodeInfo *cinode; 91338c8a9a5SSteve French struct inode *inode; 91438c8a9a5SSteve French void *page; 91538c8a9a5SSteve French const char *full_path; 91638c8a9a5SSteve French int desired_access; 91738c8a9a5SSteve French int disposition = FILE_OPEN; 91838c8a9a5SSteve French int create_options = CREATE_NOT_DIR; 91938c8a9a5SSteve French struct cifs_open_parms oparms; 920*0fdada1eSDavid Howells int rdwr_for_fscache = 0; 92138c8a9a5SSteve French 92238c8a9a5SSteve French xid = get_xid(); 92338c8a9a5SSteve French mutex_lock(&cfile->fh_mutex); 92438c8a9a5SSteve French if (!cfile->invalidHandle) { 92538c8a9a5SSteve French mutex_unlock(&cfile->fh_mutex); 92638c8a9a5SSteve French free_xid(xid); 92738c8a9a5SSteve French return 0; 92838c8a9a5SSteve French } 92938c8a9a5SSteve French 93038c8a9a5SSteve French inode = d_inode(cfile->dentry); 93138c8a9a5SSteve French cifs_sb = CIFS_SB(inode->i_sb); 93238c8a9a5SSteve French tcon = tlink_tcon(cfile->tlink); 93338c8a9a5SSteve French server = tcon->ses->server; 93438c8a9a5SSteve French 93538c8a9a5SSteve French /* 93638c8a9a5SSteve French * Can not grab rename sem here because various ops, including those 93738c8a9a5SSteve French * that already have the rename sem can end up causing writepage to get 93838c8a9a5SSteve French * called and if the server was down that means we end up here, and we 93938c8a9a5SSteve French * can never tell if the caller already has the rename_sem. 94038c8a9a5SSteve French */ 94138c8a9a5SSteve French page = alloc_dentry_path(); 94238c8a9a5SSteve French full_path = build_path_from_dentry(cfile->dentry, page); 94338c8a9a5SSteve French if (IS_ERR(full_path)) { 94438c8a9a5SSteve French mutex_unlock(&cfile->fh_mutex); 94538c8a9a5SSteve French free_dentry_path(page); 94638c8a9a5SSteve French free_xid(xid); 94738c8a9a5SSteve French return PTR_ERR(full_path); 94838c8a9a5SSteve French } 94938c8a9a5SSteve French 95038c8a9a5SSteve French cifs_dbg(FYI, "inode = 0x%p file flags 0x%x for %s\n", 95138c8a9a5SSteve French inode, cfile->f_flags, full_path); 95238c8a9a5SSteve French 95338c8a9a5SSteve French if (tcon->ses->server->oplocks) 95438c8a9a5SSteve French oplock = REQ_OPLOCK; 95538c8a9a5SSteve French else 95638c8a9a5SSteve French oplock = 0; 95738c8a9a5SSteve French 95838c8a9a5SSteve French #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 95938c8a9a5SSteve French if (tcon->unix_ext && cap_unix(tcon->ses) && 96038c8a9a5SSteve French (CIFS_UNIX_POSIX_PATH_OPS_CAP & 96138c8a9a5SSteve French le64_to_cpu(tcon->fsUnixInfo.Capability))) { 96238c8a9a5SSteve French /* 96338c8a9a5SSteve French * O_CREAT, O_EXCL and O_TRUNC already had their effect on the 96438c8a9a5SSteve French * original open. Must mask them off for a reopen. 96538c8a9a5SSteve French */ 96638c8a9a5SSteve French unsigned int oflags = cfile->f_flags & 96738c8a9a5SSteve French ~(O_CREAT | O_EXCL | O_TRUNC); 96838c8a9a5SSteve French 96938c8a9a5SSteve French rc = cifs_posix_open(full_path, NULL, inode->i_sb, 97038c8a9a5SSteve French cifs_sb->ctx->file_mode /* ignored */, 97138c8a9a5SSteve French oflags, &oplock, &cfile->fid.netfid, xid); 97238c8a9a5SSteve French if (rc == 0) { 97338c8a9a5SSteve French cifs_dbg(FYI, "posix reopen succeeded\n"); 97438c8a9a5SSteve French oparms.reconnect = true; 97538c8a9a5SSteve French goto reopen_success; 97638c8a9a5SSteve French } 97738c8a9a5SSteve French /* 97838c8a9a5SSteve French * fallthrough to retry open the old way on errors, especially 97938c8a9a5SSteve French * in the reconnect path it is important to retry hard 98038c8a9a5SSteve French */ 98138c8a9a5SSteve French } 98238c8a9a5SSteve French #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 98338c8a9a5SSteve French 984*0fdada1eSDavid Howells /* If we're caching, we need to be able to fill in around partial writes. */ 985*0fdada1eSDavid Howells if (cifs_fscache_enabled(inode) && (cfile->f_flags & O_ACCMODE) == O_WRONLY) 986*0fdada1eSDavid Howells rdwr_for_fscache = 1; 987*0fdada1eSDavid Howells 988*0fdada1eSDavid Howells desired_access = cifs_convert_flags(cfile->f_flags, rdwr_for_fscache); 98938c8a9a5SSteve French 99038c8a9a5SSteve French /* O_SYNC also has bit for O_DSYNC so following check picks up either */ 99138c8a9a5SSteve French if (cfile->f_flags & O_SYNC) 99238c8a9a5SSteve French create_options |= CREATE_WRITE_THROUGH; 99338c8a9a5SSteve French 99438c8a9a5SSteve French if (cfile->f_flags & O_DIRECT) 99538c8a9a5SSteve French create_options |= CREATE_NO_BUFFER; 99638c8a9a5SSteve French 99738c8a9a5SSteve French if (server->ops->get_lease_key) 99838c8a9a5SSteve French server->ops->get_lease_key(inode, &cfile->fid); 99938c8a9a5SSteve French 1000*0fdada1eSDavid Howells retry_open: 100138c8a9a5SSteve French oparms = (struct cifs_open_parms) { 100238c8a9a5SSteve French .tcon = tcon, 100338c8a9a5SSteve French .cifs_sb = cifs_sb, 100438c8a9a5SSteve French .desired_access = desired_access, 100538c8a9a5SSteve French .create_options = cifs_create_options(cifs_sb, create_options), 100638c8a9a5SSteve French .disposition = disposition, 100738c8a9a5SSteve French .path = full_path, 100838c8a9a5SSteve French .fid = &cfile->fid, 100938c8a9a5SSteve French .reconnect = true, 101038c8a9a5SSteve French }; 101138c8a9a5SSteve French 101238c8a9a5SSteve French /* 101338c8a9a5SSteve French * Can not refresh inode by passing in file_info buf to be returned by 101438c8a9a5SSteve French * ops->open and then calling get_inode_info with returned buf since 101538c8a9a5SSteve French * file might have write behind data that needs to be flushed and server 101638c8a9a5SSteve French * version of file size can be stale. If we knew for sure that inode was 101738c8a9a5SSteve French * not dirty locally we could do this. 101838c8a9a5SSteve French */ 101938c8a9a5SSteve French rc = server->ops->open(xid, &oparms, &oplock, NULL); 102038c8a9a5SSteve French if (rc == -ENOENT && oparms.reconnect == false) { 102138c8a9a5SSteve French /* durable handle timeout is expired - open the file again */ 102238c8a9a5SSteve French rc = server->ops->open(xid, &oparms, &oplock, NULL); 102338c8a9a5SSteve French /* indicate that we need to relock the file */ 102438c8a9a5SSteve French oparms.reconnect = true; 102538c8a9a5SSteve French } 1026*0fdada1eSDavid Howells if (rc == -EACCES && rdwr_for_fscache == 1) { 1027*0fdada1eSDavid Howells desired_access = cifs_convert_flags(cfile->f_flags, 0); 1028*0fdada1eSDavid Howells rdwr_for_fscache = 2; 1029*0fdada1eSDavid Howells goto retry_open; 1030*0fdada1eSDavid Howells } 103138c8a9a5SSteve French 103238c8a9a5SSteve French if (rc) { 103338c8a9a5SSteve French mutex_unlock(&cfile->fh_mutex); 103438c8a9a5SSteve French cifs_dbg(FYI, "cifs_reopen returned 0x%x\n", rc); 103538c8a9a5SSteve French cifs_dbg(FYI, "oplock: %d\n", oplock); 103638c8a9a5SSteve French goto reopen_error_exit; 103738c8a9a5SSteve French } 103838c8a9a5SSteve French 1039*0fdada1eSDavid Howells if (rdwr_for_fscache == 2) 1040*0fdada1eSDavid Howells cifs_invalidate_cache(inode, FSCACHE_INVAL_DIO_WRITE); 1041*0fdada1eSDavid Howells 104238c8a9a5SSteve French #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 104338c8a9a5SSteve French reopen_success: 104438c8a9a5SSteve French #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 104538c8a9a5SSteve French cfile->invalidHandle = false; 104638c8a9a5SSteve French mutex_unlock(&cfile->fh_mutex); 104738c8a9a5SSteve French cinode = CIFS_I(inode); 104838c8a9a5SSteve French 104938c8a9a5SSteve French if (can_flush) { 105038c8a9a5SSteve French rc = filemap_write_and_wait(inode->i_mapping); 105138c8a9a5SSteve French if (!is_interrupt_error(rc)) 105238c8a9a5SSteve French mapping_set_error(inode->i_mapping, rc); 105338c8a9a5SSteve French 105438c8a9a5SSteve French if (tcon->posix_extensions) 105538c8a9a5SSteve French rc = smb311_posix_get_inode_info(&inode, full_path, inode->i_sb, xid); 105638c8a9a5SSteve French else if (tcon->unix_ext) 105738c8a9a5SSteve French rc = cifs_get_inode_info_unix(&inode, full_path, 105838c8a9a5SSteve French inode->i_sb, xid); 105938c8a9a5SSteve French else 106038c8a9a5SSteve French rc = cifs_get_inode_info(&inode, full_path, NULL, 106138c8a9a5SSteve French inode->i_sb, xid, NULL); 106238c8a9a5SSteve French } 106338c8a9a5SSteve French /* 106438c8a9a5SSteve French * Else we are writing out data to server already and could deadlock if 106538c8a9a5SSteve French * we tried to flush data, and since we do not know if we have data that 106638c8a9a5SSteve French * would invalidate the current end of file on the server we can not go 106738c8a9a5SSteve French * to the server to get the new inode info. 106838c8a9a5SSteve French */ 106938c8a9a5SSteve French 107038c8a9a5SSteve French /* 107138c8a9a5SSteve French * If the server returned a read oplock and we have mandatory brlocks, 107238c8a9a5SSteve French * set oplock level to None. 107338c8a9a5SSteve French */ 107438c8a9a5SSteve French if (server->ops->is_read_op(oplock) && cifs_has_mand_locks(cinode)) { 107538c8a9a5SSteve French cifs_dbg(FYI, "Reset oplock val from read to None due to mand locks\n"); 107638c8a9a5SSteve French oplock = 0; 107738c8a9a5SSteve French } 107838c8a9a5SSteve French 107938c8a9a5SSteve French server->ops->set_fid(cfile, &cfile->fid, oplock); 108038c8a9a5SSteve French if (oparms.reconnect) 108138c8a9a5SSteve French cifs_relock_file(cfile); 108238c8a9a5SSteve French 108338c8a9a5SSteve French reopen_error_exit: 108438c8a9a5SSteve French free_dentry_path(page); 108538c8a9a5SSteve French free_xid(xid); 108638c8a9a5SSteve French return rc; 108738c8a9a5SSteve French } 108838c8a9a5SSteve French 108938c8a9a5SSteve French void smb2_deferred_work_close(struct work_struct *work) 109038c8a9a5SSteve French { 109138c8a9a5SSteve French struct cifsFileInfo *cfile = container_of(work, 109238c8a9a5SSteve French struct cifsFileInfo, deferred.work); 109338c8a9a5SSteve French 109438c8a9a5SSteve French spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock); 109538c8a9a5SSteve French cifs_del_deferred_close(cfile); 109638c8a9a5SSteve French cfile->deferred_close_scheduled = false; 109738c8a9a5SSteve French spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock); 109838c8a9a5SSteve French _cifsFileInfo_put(cfile, true, false); 109938c8a9a5SSteve French } 110038c8a9a5SSteve French 110138c8a9a5SSteve French int cifs_close(struct inode *inode, struct file *file) 110238c8a9a5SSteve French { 110338c8a9a5SSteve French struct cifsFileInfo *cfile; 110438c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(inode); 110538c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 110638c8a9a5SSteve French struct cifs_deferred_close *dclose; 110738c8a9a5SSteve French 110838c8a9a5SSteve French cifs_fscache_unuse_inode_cookie(inode, file->f_mode & FMODE_WRITE); 110938c8a9a5SSteve French 111038c8a9a5SSteve French if (file->private_data != NULL) { 111138c8a9a5SSteve French cfile = file->private_data; 111238c8a9a5SSteve French file->private_data = NULL; 111338c8a9a5SSteve French dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL); 1114df9d70c1SBharath SM if ((cifs_sb->ctx->closetimeo && cinode->oplock == CIFS_CACHE_RHW_FLG) 1115df9d70c1SBharath SM && cinode->lease_granted && 111638c8a9a5SSteve French !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags) && 111738c8a9a5SSteve French dclose) { 111838c8a9a5SSteve French if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) { 111923171df5SJeff Layton inode_set_mtime_to_ts(inode, 112023171df5SJeff Layton inode_set_ctime_current(inode)); 112138c8a9a5SSteve French } 112238c8a9a5SSteve French spin_lock(&cinode->deferred_lock); 112338c8a9a5SSteve French cifs_add_deferred_close(cfile, dclose); 112438c8a9a5SSteve French if (cfile->deferred_close_scheduled && 112538c8a9a5SSteve French delayed_work_pending(&cfile->deferred)) { 112638c8a9a5SSteve French /* 112738c8a9a5SSteve French * If there is no pending work, mod_delayed_work queues new work. 112838c8a9a5SSteve French * So, Increase the ref count to avoid use-after-free. 112938c8a9a5SSteve French */ 113038c8a9a5SSteve French if (!mod_delayed_work(deferredclose_wq, 113138c8a9a5SSteve French &cfile->deferred, cifs_sb->ctx->closetimeo)) 113238c8a9a5SSteve French cifsFileInfo_get(cfile); 113338c8a9a5SSteve French } else { 113438c8a9a5SSteve French /* Deferred close for files */ 113538c8a9a5SSteve French queue_delayed_work(deferredclose_wq, 113638c8a9a5SSteve French &cfile->deferred, cifs_sb->ctx->closetimeo); 113738c8a9a5SSteve French cfile->deferred_close_scheduled = true; 113838c8a9a5SSteve French spin_unlock(&cinode->deferred_lock); 113938c8a9a5SSteve French return 0; 114038c8a9a5SSteve French } 114138c8a9a5SSteve French spin_unlock(&cinode->deferred_lock); 114238c8a9a5SSteve French _cifsFileInfo_put(cfile, true, false); 114338c8a9a5SSteve French } else { 114438c8a9a5SSteve French _cifsFileInfo_put(cfile, true, false); 114538c8a9a5SSteve French kfree(dclose); 114638c8a9a5SSteve French } 114738c8a9a5SSteve French } 114838c8a9a5SSteve French 114938c8a9a5SSteve French /* return code from the ->release op is always ignored */ 115038c8a9a5SSteve French return 0; 115138c8a9a5SSteve French } 115238c8a9a5SSteve French 115338c8a9a5SSteve French void 115438c8a9a5SSteve French cifs_reopen_persistent_handles(struct cifs_tcon *tcon) 115538c8a9a5SSteve French { 115638c8a9a5SSteve French struct cifsFileInfo *open_file, *tmp; 115738c8a9a5SSteve French struct list_head tmp_list; 115838c8a9a5SSteve French 115938c8a9a5SSteve French if (!tcon->use_persistent || !tcon->need_reopen_files) 116038c8a9a5SSteve French return; 116138c8a9a5SSteve French 116238c8a9a5SSteve French tcon->need_reopen_files = false; 116338c8a9a5SSteve French 116438c8a9a5SSteve French cifs_dbg(FYI, "Reopen persistent handles\n"); 116538c8a9a5SSteve French INIT_LIST_HEAD(&tmp_list); 116638c8a9a5SSteve French 116738c8a9a5SSteve French /* list all files open on tree connection, reopen resilient handles */ 116838c8a9a5SSteve French spin_lock(&tcon->open_file_lock); 116938c8a9a5SSteve French list_for_each_entry(open_file, &tcon->openFileList, tlist) { 117038c8a9a5SSteve French if (!open_file->invalidHandle) 117138c8a9a5SSteve French continue; 117238c8a9a5SSteve French cifsFileInfo_get(open_file); 117338c8a9a5SSteve French list_add_tail(&open_file->rlist, &tmp_list); 117438c8a9a5SSteve French } 117538c8a9a5SSteve French spin_unlock(&tcon->open_file_lock); 117638c8a9a5SSteve French 117738c8a9a5SSteve French list_for_each_entry_safe(open_file, tmp, &tmp_list, rlist) { 117838c8a9a5SSteve French if (cifs_reopen_file(open_file, false /* do not flush */)) 117938c8a9a5SSteve French tcon->need_reopen_files = true; 118038c8a9a5SSteve French list_del_init(&open_file->rlist); 118138c8a9a5SSteve French cifsFileInfo_put(open_file); 118238c8a9a5SSteve French } 118338c8a9a5SSteve French } 118438c8a9a5SSteve French 118538c8a9a5SSteve French int cifs_closedir(struct inode *inode, struct file *file) 118638c8a9a5SSteve French { 118738c8a9a5SSteve French int rc = 0; 118838c8a9a5SSteve French unsigned int xid; 118938c8a9a5SSteve French struct cifsFileInfo *cfile = file->private_data; 119038c8a9a5SSteve French struct cifs_tcon *tcon; 119138c8a9a5SSteve French struct TCP_Server_Info *server; 119238c8a9a5SSteve French char *buf; 119338c8a9a5SSteve French 119438c8a9a5SSteve French cifs_dbg(FYI, "Closedir inode = 0x%p\n", inode); 119538c8a9a5SSteve French 119638c8a9a5SSteve French if (cfile == NULL) 119738c8a9a5SSteve French return rc; 119838c8a9a5SSteve French 119938c8a9a5SSteve French xid = get_xid(); 120038c8a9a5SSteve French tcon = tlink_tcon(cfile->tlink); 120138c8a9a5SSteve French server = tcon->ses->server; 120238c8a9a5SSteve French 120338c8a9a5SSteve French cifs_dbg(FYI, "Freeing private data in close dir\n"); 120438c8a9a5SSteve French spin_lock(&cfile->file_info_lock); 120538c8a9a5SSteve French if (server->ops->dir_needs_close(cfile)) { 120638c8a9a5SSteve French cfile->invalidHandle = true; 120738c8a9a5SSteve French spin_unlock(&cfile->file_info_lock); 120838c8a9a5SSteve French if (server->ops->close_dir) 120938c8a9a5SSteve French rc = server->ops->close_dir(xid, tcon, &cfile->fid); 121038c8a9a5SSteve French else 121138c8a9a5SSteve French rc = -ENOSYS; 121238c8a9a5SSteve French cifs_dbg(FYI, "Closing uncompleted readdir with rc %d\n", rc); 121338c8a9a5SSteve French /* not much we can do if it fails anyway, ignore rc */ 121438c8a9a5SSteve French rc = 0; 121538c8a9a5SSteve French } else 121638c8a9a5SSteve French spin_unlock(&cfile->file_info_lock); 121738c8a9a5SSteve French 121838c8a9a5SSteve French buf = cfile->srch_inf.ntwrk_buf_start; 121938c8a9a5SSteve French if (buf) { 122038c8a9a5SSteve French cifs_dbg(FYI, "closedir free smb buf in srch struct\n"); 122138c8a9a5SSteve French cfile->srch_inf.ntwrk_buf_start = NULL; 122238c8a9a5SSteve French if (cfile->srch_inf.smallBuf) 122338c8a9a5SSteve French cifs_small_buf_release(buf); 122438c8a9a5SSteve French else 122538c8a9a5SSteve French cifs_buf_release(buf); 122638c8a9a5SSteve French } 122738c8a9a5SSteve French 122838c8a9a5SSteve French cifs_put_tlink(cfile->tlink); 122938c8a9a5SSteve French kfree(file->private_data); 123038c8a9a5SSteve French file->private_data = NULL; 123138c8a9a5SSteve French /* BB can we lock the filestruct while this is going on? */ 123238c8a9a5SSteve French free_xid(xid); 123338c8a9a5SSteve French return rc; 123438c8a9a5SSteve French } 123538c8a9a5SSteve French 123638c8a9a5SSteve French static struct cifsLockInfo * 123738c8a9a5SSteve French cifs_lock_init(__u64 offset, __u64 length, __u8 type, __u16 flags) 123838c8a9a5SSteve French { 123938c8a9a5SSteve French struct cifsLockInfo *lock = 124038c8a9a5SSteve French kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL); 124138c8a9a5SSteve French if (!lock) 124238c8a9a5SSteve French return lock; 124338c8a9a5SSteve French lock->offset = offset; 124438c8a9a5SSteve French lock->length = length; 124538c8a9a5SSteve French lock->type = type; 124638c8a9a5SSteve French lock->pid = current->tgid; 124738c8a9a5SSteve French lock->flags = flags; 124838c8a9a5SSteve French INIT_LIST_HEAD(&lock->blist); 124938c8a9a5SSteve French init_waitqueue_head(&lock->block_q); 125038c8a9a5SSteve French return lock; 125138c8a9a5SSteve French } 125238c8a9a5SSteve French 125338c8a9a5SSteve French void 125438c8a9a5SSteve French cifs_del_lock_waiters(struct cifsLockInfo *lock) 125538c8a9a5SSteve French { 125638c8a9a5SSteve French struct cifsLockInfo *li, *tmp; 125738c8a9a5SSteve French list_for_each_entry_safe(li, tmp, &lock->blist, blist) { 125838c8a9a5SSteve French list_del_init(&li->blist); 125938c8a9a5SSteve French wake_up(&li->block_q); 126038c8a9a5SSteve French } 126138c8a9a5SSteve French } 126238c8a9a5SSteve French 126338c8a9a5SSteve French #define CIFS_LOCK_OP 0 126438c8a9a5SSteve French #define CIFS_READ_OP 1 126538c8a9a5SSteve French #define CIFS_WRITE_OP 2 126638c8a9a5SSteve French 126738c8a9a5SSteve French /* @rw_check : 0 - no op, 1 - read, 2 - write */ 126838c8a9a5SSteve French static bool 126938c8a9a5SSteve French cifs_find_fid_lock_conflict(struct cifs_fid_locks *fdlocks, __u64 offset, 127038c8a9a5SSteve French __u64 length, __u8 type, __u16 flags, 127138c8a9a5SSteve French struct cifsFileInfo *cfile, 127238c8a9a5SSteve French struct cifsLockInfo **conf_lock, int rw_check) 127338c8a9a5SSteve French { 127438c8a9a5SSteve French struct cifsLockInfo *li; 127538c8a9a5SSteve French struct cifsFileInfo *cur_cfile = fdlocks->cfile; 127638c8a9a5SSteve French struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; 127738c8a9a5SSteve French 127838c8a9a5SSteve French list_for_each_entry(li, &fdlocks->locks, llist) { 127938c8a9a5SSteve French if (offset + length <= li->offset || 128038c8a9a5SSteve French offset >= li->offset + li->length) 128138c8a9a5SSteve French continue; 128238c8a9a5SSteve French if (rw_check != CIFS_LOCK_OP && current->tgid == li->pid && 128338c8a9a5SSteve French server->ops->compare_fids(cfile, cur_cfile)) { 128438c8a9a5SSteve French /* shared lock prevents write op through the same fid */ 128538c8a9a5SSteve French if (!(li->type & server->vals->shared_lock_type) || 128638c8a9a5SSteve French rw_check != CIFS_WRITE_OP) 128738c8a9a5SSteve French continue; 128838c8a9a5SSteve French } 128938c8a9a5SSteve French if ((type & server->vals->shared_lock_type) && 129038c8a9a5SSteve French ((server->ops->compare_fids(cfile, cur_cfile) && 129138c8a9a5SSteve French current->tgid == li->pid) || type == li->type)) 129238c8a9a5SSteve French continue; 129338c8a9a5SSteve French if (rw_check == CIFS_LOCK_OP && 129438c8a9a5SSteve French (flags & FL_OFDLCK) && (li->flags & FL_OFDLCK) && 129538c8a9a5SSteve French server->ops->compare_fids(cfile, cur_cfile)) 129638c8a9a5SSteve French continue; 129738c8a9a5SSteve French if (conf_lock) 129838c8a9a5SSteve French *conf_lock = li; 129938c8a9a5SSteve French return true; 130038c8a9a5SSteve French } 130138c8a9a5SSteve French return false; 130238c8a9a5SSteve French } 130338c8a9a5SSteve French 130438c8a9a5SSteve French bool 130538c8a9a5SSteve French cifs_find_lock_conflict(struct cifsFileInfo *cfile, __u64 offset, __u64 length, 130638c8a9a5SSteve French __u8 type, __u16 flags, 130738c8a9a5SSteve French struct cifsLockInfo **conf_lock, int rw_check) 130838c8a9a5SSteve French { 130938c8a9a5SSteve French bool rc = false; 131038c8a9a5SSteve French struct cifs_fid_locks *cur; 131138c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); 131238c8a9a5SSteve French 131338c8a9a5SSteve French list_for_each_entry(cur, &cinode->llist, llist) { 131438c8a9a5SSteve French rc = cifs_find_fid_lock_conflict(cur, offset, length, type, 131538c8a9a5SSteve French flags, cfile, conf_lock, 131638c8a9a5SSteve French rw_check); 131738c8a9a5SSteve French if (rc) 131838c8a9a5SSteve French break; 131938c8a9a5SSteve French } 132038c8a9a5SSteve French 132138c8a9a5SSteve French return rc; 132238c8a9a5SSteve French } 132338c8a9a5SSteve French 132438c8a9a5SSteve French /* 132538c8a9a5SSteve French * Check if there is another lock that prevents us to set the lock (mandatory 132638c8a9a5SSteve French * style). If such a lock exists, update the flock structure with its 132738c8a9a5SSteve French * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks 132838c8a9a5SSteve French * or leave it the same if we can't. Returns 0 if we don't need to request to 132938c8a9a5SSteve French * the server or 1 otherwise. 133038c8a9a5SSteve French */ 133138c8a9a5SSteve French static int 133238c8a9a5SSteve French cifs_lock_test(struct cifsFileInfo *cfile, __u64 offset, __u64 length, 133338c8a9a5SSteve French __u8 type, struct file_lock *flock) 133438c8a9a5SSteve French { 133538c8a9a5SSteve French int rc = 0; 133638c8a9a5SSteve French struct cifsLockInfo *conf_lock; 133738c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); 133838c8a9a5SSteve French struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; 133938c8a9a5SSteve French bool exist; 134038c8a9a5SSteve French 134138c8a9a5SSteve French down_read(&cinode->lock_sem); 134238c8a9a5SSteve French 134338c8a9a5SSteve French exist = cifs_find_lock_conflict(cfile, offset, length, type, 134438c8a9a5SSteve French flock->fl_flags, &conf_lock, 134538c8a9a5SSteve French CIFS_LOCK_OP); 134638c8a9a5SSteve French if (exist) { 134738c8a9a5SSteve French flock->fl_start = conf_lock->offset; 134838c8a9a5SSteve French flock->fl_end = conf_lock->offset + conf_lock->length - 1; 134938c8a9a5SSteve French flock->fl_pid = conf_lock->pid; 135038c8a9a5SSteve French if (conf_lock->type & server->vals->shared_lock_type) 135138c8a9a5SSteve French flock->fl_type = F_RDLCK; 135238c8a9a5SSteve French else 135338c8a9a5SSteve French flock->fl_type = F_WRLCK; 135438c8a9a5SSteve French } else if (!cinode->can_cache_brlcks) 135538c8a9a5SSteve French rc = 1; 135638c8a9a5SSteve French else 135738c8a9a5SSteve French flock->fl_type = F_UNLCK; 135838c8a9a5SSteve French 135938c8a9a5SSteve French up_read(&cinode->lock_sem); 136038c8a9a5SSteve French return rc; 136138c8a9a5SSteve French } 136238c8a9a5SSteve French 136338c8a9a5SSteve French static void 136438c8a9a5SSteve French cifs_lock_add(struct cifsFileInfo *cfile, struct cifsLockInfo *lock) 136538c8a9a5SSteve French { 136638c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); 136738c8a9a5SSteve French cifs_down_write(&cinode->lock_sem); 136838c8a9a5SSteve French list_add_tail(&lock->llist, &cfile->llist->locks); 136938c8a9a5SSteve French up_write(&cinode->lock_sem); 137038c8a9a5SSteve French } 137138c8a9a5SSteve French 137238c8a9a5SSteve French /* 137338c8a9a5SSteve French * Set the byte-range lock (mandatory style). Returns: 137438c8a9a5SSteve French * 1) 0, if we set the lock and don't need to request to the server; 137538c8a9a5SSteve French * 2) 1, if no locks prevent us but we need to request to the server; 137638c8a9a5SSteve French * 3) -EACCES, if there is a lock that prevents us and wait is false. 137738c8a9a5SSteve French */ 137838c8a9a5SSteve French static int 137938c8a9a5SSteve French cifs_lock_add_if(struct cifsFileInfo *cfile, struct cifsLockInfo *lock, 138038c8a9a5SSteve French bool wait) 138138c8a9a5SSteve French { 138238c8a9a5SSteve French struct cifsLockInfo *conf_lock; 138338c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); 138438c8a9a5SSteve French bool exist; 138538c8a9a5SSteve French int rc = 0; 138638c8a9a5SSteve French 138738c8a9a5SSteve French try_again: 138838c8a9a5SSteve French exist = false; 138938c8a9a5SSteve French cifs_down_write(&cinode->lock_sem); 139038c8a9a5SSteve French 139138c8a9a5SSteve French exist = cifs_find_lock_conflict(cfile, lock->offset, lock->length, 139238c8a9a5SSteve French lock->type, lock->flags, &conf_lock, 139338c8a9a5SSteve French CIFS_LOCK_OP); 139438c8a9a5SSteve French if (!exist && cinode->can_cache_brlcks) { 139538c8a9a5SSteve French list_add_tail(&lock->llist, &cfile->llist->locks); 139638c8a9a5SSteve French up_write(&cinode->lock_sem); 139738c8a9a5SSteve French return rc; 139838c8a9a5SSteve French } 139938c8a9a5SSteve French 140038c8a9a5SSteve French if (!exist) 140138c8a9a5SSteve French rc = 1; 140238c8a9a5SSteve French else if (!wait) 140338c8a9a5SSteve French rc = -EACCES; 140438c8a9a5SSteve French else { 140538c8a9a5SSteve French list_add_tail(&lock->blist, &conf_lock->blist); 140638c8a9a5SSteve French up_write(&cinode->lock_sem); 140738c8a9a5SSteve French rc = wait_event_interruptible(lock->block_q, 140838c8a9a5SSteve French (lock->blist.prev == &lock->blist) && 140938c8a9a5SSteve French (lock->blist.next == &lock->blist)); 141038c8a9a5SSteve French if (!rc) 141138c8a9a5SSteve French goto try_again; 141238c8a9a5SSteve French cifs_down_write(&cinode->lock_sem); 141338c8a9a5SSteve French list_del_init(&lock->blist); 141438c8a9a5SSteve French } 141538c8a9a5SSteve French 141638c8a9a5SSteve French up_write(&cinode->lock_sem); 141738c8a9a5SSteve French return rc; 141838c8a9a5SSteve French } 141938c8a9a5SSteve French 142038c8a9a5SSteve French #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 142138c8a9a5SSteve French /* 142238c8a9a5SSteve French * Check if there is another lock that prevents us to set the lock (posix 142338c8a9a5SSteve French * style). If such a lock exists, update the flock structure with its 142438c8a9a5SSteve French * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks 142538c8a9a5SSteve French * or leave it the same if we can't. Returns 0 if we don't need to request to 142638c8a9a5SSteve French * the server or 1 otherwise. 142738c8a9a5SSteve French */ 142838c8a9a5SSteve French static int 142938c8a9a5SSteve French cifs_posix_lock_test(struct file *file, struct file_lock *flock) 143038c8a9a5SSteve French { 143138c8a9a5SSteve French int rc = 0; 143238c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(file_inode(file)); 143338c8a9a5SSteve French unsigned char saved_type = flock->fl_type; 143438c8a9a5SSteve French 143538c8a9a5SSteve French if ((flock->fl_flags & FL_POSIX) == 0) 143638c8a9a5SSteve French return 1; 143738c8a9a5SSteve French 143838c8a9a5SSteve French down_read(&cinode->lock_sem); 143938c8a9a5SSteve French posix_test_lock(file, flock); 144038c8a9a5SSteve French 144138c8a9a5SSteve French if (flock->fl_type == F_UNLCK && !cinode->can_cache_brlcks) { 144238c8a9a5SSteve French flock->fl_type = saved_type; 144338c8a9a5SSteve French rc = 1; 144438c8a9a5SSteve French } 144538c8a9a5SSteve French 144638c8a9a5SSteve French up_read(&cinode->lock_sem); 144738c8a9a5SSteve French return rc; 144838c8a9a5SSteve French } 144938c8a9a5SSteve French 145038c8a9a5SSteve French /* 145138c8a9a5SSteve French * Set the byte-range lock (posix style). Returns: 145238c8a9a5SSteve French * 1) <0, if the error occurs while setting the lock; 145338c8a9a5SSteve French * 2) 0, if we set the lock and don't need to request to the server; 145438c8a9a5SSteve French * 3) FILE_LOCK_DEFERRED, if we will wait for some other file_lock; 145538c8a9a5SSteve French * 4) FILE_LOCK_DEFERRED + 1, if we need to request to the server. 145638c8a9a5SSteve French */ 145738c8a9a5SSteve French static int 145838c8a9a5SSteve French cifs_posix_lock_set(struct file *file, struct file_lock *flock) 145938c8a9a5SSteve French { 146038c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(file_inode(file)); 146138c8a9a5SSteve French int rc = FILE_LOCK_DEFERRED + 1; 146238c8a9a5SSteve French 146338c8a9a5SSteve French if ((flock->fl_flags & FL_POSIX) == 0) 146438c8a9a5SSteve French return rc; 146538c8a9a5SSteve French 146638c8a9a5SSteve French cifs_down_write(&cinode->lock_sem); 146738c8a9a5SSteve French if (!cinode->can_cache_brlcks) { 146838c8a9a5SSteve French up_write(&cinode->lock_sem); 146938c8a9a5SSteve French return rc; 147038c8a9a5SSteve French } 147138c8a9a5SSteve French 147238c8a9a5SSteve French rc = posix_lock_file(file, flock, NULL); 147338c8a9a5SSteve French up_write(&cinode->lock_sem); 147438c8a9a5SSteve French return rc; 147538c8a9a5SSteve French } 147638c8a9a5SSteve French 147738c8a9a5SSteve French int 147838c8a9a5SSteve French cifs_push_mandatory_locks(struct cifsFileInfo *cfile) 147938c8a9a5SSteve French { 148038c8a9a5SSteve French unsigned int xid; 148138c8a9a5SSteve French int rc = 0, stored_rc; 148238c8a9a5SSteve French struct cifsLockInfo *li, *tmp; 148338c8a9a5SSteve French struct cifs_tcon *tcon; 148438c8a9a5SSteve French unsigned int num, max_num, max_buf; 148538c8a9a5SSteve French LOCKING_ANDX_RANGE *buf, *cur; 148638c8a9a5SSteve French static const int types[] = { 148738c8a9a5SSteve French LOCKING_ANDX_LARGE_FILES, 148838c8a9a5SSteve French LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES 148938c8a9a5SSteve French }; 149038c8a9a5SSteve French int i; 149138c8a9a5SSteve French 149238c8a9a5SSteve French xid = get_xid(); 149338c8a9a5SSteve French tcon = tlink_tcon(cfile->tlink); 149438c8a9a5SSteve French 149538c8a9a5SSteve French /* 149638c8a9a5SSteve French * Accessing maxBuf is racy with cifs_reconnect - need to store value 149738c8a9a5SSteve French * and check it before using. 149838c8a9a5SSteve French */ 149938c8a9a5SSteve French max_buf = tcon->ses->server->maxBuf; 150038c8a9a5SSteve French if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE))) { 150138c8a9a5SSteve French free_xid(xid); 150238c8a9a5SSteve French return -EINVAL; 150338c8a9a5SSteve French } 150438c8a9a5SSteve French 150538c8a9a5SSteve French BUILD_BUG_ON(sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE) > 150638c8a9a5SSteve French PAGE_SIZE); 150738c8a9a5SSteve French max_buf = min_t(unsigned int, max_buf - sizeof(struct smb_hdr), 150838c8a9a5SSteve French PAGE_SIZE); 150938c8a9a5SSteve French max_num = (max_buf - sizeof(struct smb_hdr)) / 151038c8a9a5SSteve French sizeof(LOCKING_ANDX_RANGE); 151138c8a9a5SSteve French buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); 151238c8a9a5SSteve French if (!buf) { 151338c8a9a5SSteve French free_xid(xid); 151438c8a9a5SSteve French return -ENOMEM; 151538c8a9a5SSteve French } 151638c8a9a5SSteve French 151738c8a9a5SSteve French for (i = 0; i < 2; i++) { 151838c8a9a5SSteve French cur = buf; 151938c8a9a5SSteve French num = 0; 152038c8a9a5SSteve French list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) { 152138c8a9a5SSteve French if (li->type != types[i]) 152238c8a9a5SSteve French continue; 152338c8a9a5SSteve French cur->Pid = cpu_to_le16(li->pid); 152438c8a9a5SSteve French cur->LengthLow = cpu_to_le32((u32)li->length); 152538c8a9a5SSteve French cur->LengthHigh = cpu_to_le32((u32)(li->length>>32)); 152638c8a9a5SSteve French cur->OffsetLow = cpu_to_le32((u32)li->offset); 152738c8a9a5SSteve French cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32)); 152838c8a9a5SSteve French if (++num == max_num) { 152938c8a9a5SSteve French stored_rc = cifs_lockv(xid, tcon, 153038c8a9a5SSteve French cfile->fid.netfid, 153138c8a9a5SSteve French (__u8)li->type, 0, num, 153238c8a9a5SSteve French buf); 153338c8a9a5SSteve French if (stored_rc) 153438c8a9a5SSteve French rc = stored_rc; 153538c8a9a5SSteve French cur = buf; 153638c8a9a5SSteve French num = 0; 153738c8a9a5SSteve French } else 153838c8a9a5SSteve French cur++; 153938c8a9a5SSteve French } 154038c8a9a5SSteve French 154138c8a9a5SSteve French if (num) { 154238c8a9a5SSteve French stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid, 154338c8a9a5SSteve French (__u8)types[i], 0, num, buf); 154438c8a9a5SSteve French if (stored_rc) 154538c8a9a5SSteve French rc = stored_rc; 154638c8a9a5SSteve French } 154738c8a9a5SSteve French } 154838c8a9a5SSteve French 154938c8a9a5SSteve French kfree(buf); 155038c8a9a5SSteve French free_xid(xid); 155138c8a9a5SSteve French return rc; 155238c8a9a5SSteve French } 155338c8a9a5SSteve French 155438c8a9a5SSteve French static __u32 155538c8a9a5SSteve French hash_lockowner(fl_owner_t owner) 155638c8a9a5SSteve French { 155738c8a9a5SSteve French return cifs_lock_secret ^ hash32_ptr((const void *)owner); 155838c8a9a5SSteve French } 155938c8a9a5SSteve French #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 156038c8a9a5SSteve French 156138c8a9a5SSteve French struct lock_to_push { 156238c8a9a5SSteve French struct list_head llist; 156338c8a9a5SSteve French __u64 offset; 156438c8a9a5SSteve French __u64 length; 156538c8a9a5SSteve French __u32 pid; 156638c8a9a5SSteve French __u16 netfid; 156738c8a9a5SSteve French __u8 type; 156838c8a9a5SSteve French }; 156938c8a9a5SSteve French 157038c8a9a5SSteve French #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 157138c8a9a5SSteve French static int 157238c8a9a5SSteve French cifs_push_posix_locks(struct cifsFileInfo *cfile) 157338c8a9a5SSteve French { 157438c8a9a5SSteve French struct inode *inode = d_inode(cfile->dentry); 157538c8a9a5SSteve French struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 157638c8a9a5SSteve French struct file_lock *flock; 157738c8a9a5SSteve French struct file_lock_context *flctx = locks_inode_context(inode); 157838c8a9a5SSteve French unsigned int count = 0, i; 157938c8a9a5SSteve French int rc = 0, xid, type; 158038c8a9a5SSteve French struct list_head locks_to_send, *el; 158138c8a9a5SSteve French struct lock_to_push *lck, *tmp; 158238c8a9a5SSteve French __u64 length; 158338c8a9a5SSteve French 158438c8a9a5SSteve French xid = get_xid(); 158538c8a9a5SSteve French 158638c8a9a5SSteve French if (!flctx) 158738c8a9a5SSteve French goto out; 158838c8a9a5SSteve French 158938c8a9a5SSteve French spin_lock(&flctx->flc_lock); 159038c8a9a5SSteve French list_for_each(el, &flctx->flc_posix) { 159138c8a9a5SSteve French count++; 159238c8a9a5SSteve French } 159338c8a9a5SSteve French spin_unlock(&flctx->flc_lock); 159438c8a9a5SSteve French 159538c8a9a5SSteve French INIT_LIST_HEAD(&locks_to_send); 159638c8a9a5SSteve French 159738c8a9a5SSteve French /* 159838c8a9a5SSteve French * Allocating count locks is enough because no FL_POSIX locks can be 159938c8a9a5SSteve French * added to the list while we are holding cinode->lock_sem that 160038c8a9a5SSteve French * protects locking operations of this inode. 160138c8a9a5SSteve French */ 160238c8a9a5SSteve French for (i = 0; i < count; i++) { 160338c8a9a5SSteve French lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL); 160438c8a9a5SSteve French if (!lck) { 160538c8a9a5SSteve French rc = -ENOMEM; 160638c8a9a5SSteve French goto err_out; 160738c8a9a5SSteve French } 160838c8a9a5SSteve French list_add_tail(&lck->llist, &locks_to_send); 160938c8a9a5SSteve French } 161038c8a9a5SSteve French 161138c8a9a5SSteve French el = locks_to_send.next; 161238c8a9a5SSteve French spin_lock(&flctx->flc_lock); 161338c8a9a5SSteve French list_for_each_entry(flock, &flctx->flc_posix, fl_list) { 161438c8a9a5SSteve French if (el == &locks_to_send) { 161538c8a9a5SSteve French /* 161638c8a9a5SSteve French * The list ended. We don't have enough allocated 161738c8a9a5SSteve French * structures - something is really wrong. 161838c8a9a5SSteve French */ 161938c8a9a5SSteve French cifs_dbg(VFS, "Can't push all brlocks!\n"); 162038c8a9a5SSteve French break; 162138c8a9a5SSteve French } 162238c8a9a5SSteve French length = cifs_flock_len(flock); 162338c8a9a5SSteve French if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK) 162438c8a9a5SSteve French type = CIFS_RDLCK; 162538c8a9a5SSteve French else 162638c8a9a5SSteve French type = CIFS_WRLCK; 162738c8a9a5SSteve French lck = list_entry(el, struct lock_to_push, llist); 162838c8a9a5SSteve French lck->pid = hash_lockowner(flock->fl_owner); 162938c8a9a5SSteve French lck->netfid = cfile->fid.netfid; 163038c8a9a5SSteve French lck->length = length; 163138c8a9a5SSteve French lck->type = type; 163238c8a9a5SSteve French lck->offset = flock->fl_start; 163338c8a9a5SSteve French } 163438c8a9a5SSteve French spin_unlock(&flctx->flc_lock); 163538c8a9a5SSteve French 163638c8a9a5SSteve French list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) { 163738c8a9a5SSteve French int stored_rc; 163838c8a9a5SSteve French 163938c8a9a5SSteve French stored_rc = CIFSSMBPosixLock(xid, tcon, lck->netfid, lck->pid, 164038c8a9a5SSteve French lck->offset, lck->length, NULL, 164138c8a9a5SSteve French lck->type, 0); 164238c8a9a5SSteve French if (stored_rc) 164338c8a9a5SSteve French rc = stored_rc; 164438c8a9a5SSteve French list_del(&lck->llist); 164538c8a9a5SSteve French kfree(lck); 164638c8a9a5SSteve French } 164738c8a9a5SSteve French 164838c8a9a5SSteve French out: 164938c8a9a5SSteve French free_xid(xid); 165038c8a9a5SSteve French return rc; 165138c8a9a5SSteve French err_out: 165238c8a9a5SSteve French list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) { 165338c8a9a5SSteve French list_del(&lck->llist); 165438c8a9a5SSteve French kfree(lck); 165538c8a9a5SSteve French } 165638c8a9a5SSteve French goto out; 165738c8a9a5SSteve French } 165838c8a9a5SSteve French #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 165938c8a9a5SSteve French 166038c8a9a5SSteve French static int 166138c8a9a5SSteve French cifs_push_locks(struct cifsFileInfo *cfile) 166238c8a9a5SSteve French { 166338c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); 166438c8a9a5SSteve French struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 166538c8a9a5SSteve French int rc = 0; 166638c8a9a5SSteve French #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 166738c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb); 166838c8a9a5SSteve French #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 166938c8a9a5SSteve French 167038c8a9a5SSteve French /* we are going to update can_cache_brlcks here - need a write access */ 167138c8a9a5SSteve French cifs_down_write(&cinode->lock_sem); 167238c8a9a5SSteve French if (!cinode->can_cache_brlcks) { 167338c8a9a5SSteve French up_write(&cinode->lock_sem); 167438c8a9a5SSteve French return rc; 167538c8a9a5SSteve French } 167638c8a9a5SSteve French 167738c8a9a5SSteve French #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 167838c8a9a5SSteve French if (cap_unix(tcon->ses) && 167938c8a9a5SSteve French (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && 168038c8a9a5SSteve French ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) 168138c8a9a5SSteve French rc = cifs_push_posix_locks(cfile); 168238c8a9a5SSteve French else 168338c8a9a5SSteve French #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 168438c8a9a5SSteve French rc = tcon->ses->server->ops->push_mand_locks(cfile); 168538c8a9a5SSteve French 168638c8a9a5SSteve French cinode->can_cache_brlcks = false; 168738c8a9a5SSteve French up_write(&cinode->lock_sem); 168838c8a9a5SSteve French return rc; 168938c8a9a5SSteve French } 169038c8a9a5SSteve French 169138c8a9a5SSteve French static void 169238c8a9a5SSteve French cifs_read_flock(struct file_lock *flock, __u32 *type, int *lock, int *unlock, 169338c8a9a5SSteve French bool *wait_flag, struct TCP_Server_Info *server) 169438c8a9a5SSteve French { 169538c8a9a5SSteve French if (flock->fl_flags & FL_POSIX) 169638c8a9a5SSteve French cifs_dbg(FYI, "Posix\n"); 169738c8a9a5SSteve French if (flock->fl_flags & FL_FLOCK) 169838c8a9a5SSteve French cifs_dbg(FYI, "Flock\n"); 169938c8a9a5SSteve French if (flock->fl_flags & FL_SLEEP) { 170038c8a9a5SSteve French cifs_dbg(FYI, "Blocking lock\n"); 170138c8a9a5SSteve French *wait_flag = true; 170238c8a9a5SSteve French } 170338c8a9a5SSteve French if (flock->fl_flags & FL_ACCESS) 170438c8a9a5SSteve French cifs_dbg(FYI, "Process suspended by mandatory locking - not implemented yet\n"); 170538c8a9a5SSteve French if (flock->fl_flags & FL_LEASE) 170638c8a9a5SSteve French cifs_dbg(FYI, "Lease on file - not implemented yet\n"); 170738c8a9a5SSteve French if (flock->fl_flags & 170838c8a9a5SSteve French (~(FL_POSIX | FL_FLOCK | FL_SLEEP | 170938c8a9a5SSteve French FL_ACCESS | FL_LEASE | FL_CLOSE | FL_OFDLCK))) 171038c8a9a5SSteve French cifs_dbg(FYI, "Unknown lock flags 0x%x\n", flock->fl_flags); 171138c8a9a5SSteve French 171238c8a9a5SSteve French *type = server->vals->large_lock_type; 171338c8a9a5SSteve French if (flock->fl_type == F_WRLCK) { 171438c8a9a5SSteve French cifs_dbg(FYI, "F_WRLCK\n"); 171538c8a9a5SSteve French *type |= server->vals->exclusive_lock_type; 171638c8a9a5SSteve French *lock = 1; 171738c8a9a5SSteve French } else if (flock->fl_type == F_UNLCK) { 171838c8a9a5SSteve French cifs_dbg(FYI, "F_UNLCK\n"); 171938c8a9a5SSteve French *type |= server->vals->unlock_lock_type; 172038c8a9a5SSteve French *unlock = 1; 172138c8a9a5SSteve French /* Check if unlock includes more than one lock range */ 172238c8a9a5SSteve French } else if (flock->fl_type == F_RDLCK) { 172338c8a9a5SSteve French cifs_dbg(FYI, "F_RDLCK\n"); 172438c8a9a5SSteve French *type |= server->vals->shared_lock_type; 172538c8a9a5SSteve French *lock = 1; 172638c8a9a5SSteve French } else if (flock->fl_type == F_EXLCK) { 172738c8a9a5SSteve French cifs_dbg(FYI, "F_EXLCK\n"); 172838c8a9a5SSteve French *type |= server->vals->exclusive_lock_type; 172938c8a9a5SSteve French *lock = 1; 173038c8a9a5SSteve French } else if (flock->fl_type == F_SHLCK) { 173138c8a9a5SSteve French cifs_dbg(FYI, "F_SHLCK\n"); 173238c8a9a5SSteve French *type |= server->vals->shared_lock_type; 173338c8a9a5SSteve French *lock = 1; 173438c8a9a5SSteve French } else 173538c8a9a5SSteve French cifs_dbg(FYI, "Unknown type of lock\n"); 173638c8a9a5SSteve French } 173738c8a9a5SSteve French 173838c8a9a5SSteve French static int 173938c8a9a5SSteve French cifs_getlk(struct file *file, struct file_lock *flock, __u32 type, 174038c8a9a5SSteve French bool wait_flag, bool posix_lck, unsigned int xid) 174138c8a9a5SSteve French { 174238c8a9a5SSteve French int rc = 0; 174338c8a9a5SSteve French __u64 length = cifs_flock_len(flock); 174438c8a9a5SSteve French struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; 174538c8a9a5SSteve French struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 174638c8a9a5SSteve French struct TCP_Server_Info *server = tcon->ses->server; 174738c8a9a5SSteve French #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 174838c8a9a5SSteve French __u16 netfid = cfile->fid.netfid; 174938c8a9a5SSteve French 175038c8a9a5SSteve French if (posix_lck) { 175138c8a9a5SSteve French int posix_lock_type; 175238c8a9a5SSteve French 175338c8a9a5SSteve French rc = cifs_posix_lock_test(file, flock); 175438c8a9a5SSteve French if (!rc) 175538c8a9a5SSteve French return rc; 175638c8a9a5SSteve French 175738c8a9a5SSteve French if (type & server->vals->shared_lock_type) 175838c8a9a5SSteve French posix_lock_type = CIFS_RDLCK; 175938c8a9a5SSteve French else 176038c8a9a5SSteve French posix_lock_type = CIFS_WRLCK; 176138c8a9a5SSteve French rc = CIFSSMBPosixLock(xid, tcon, netfid, 176238c8a9a5SSteve French hash_lockowner(flock->fl_owner), 176338c8a9a5SSteve French flock->fl_start, length, flock, 176438c8a9a5SSteve French posix_lock_type, wait_flag); 176538c8a9a5SSteve French return rc; 176638c8a9a5SSteve French } 176738c8a9a5SSteve French #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 176838c8a9a5SSteve French 176938c8a9a5SSteve French rc = cifs_lock_test(cfile, flock->fl_start, length, type, flock); 177038c8a9a5SSteve French if (!rc) 177138c8a9a5SSteve French return rc; 177238c8a9a5SSteve French 177338c8a9a5SSteve French /* BB we could chain these into one lock request BB */ 177438c8a9a5SSteve French rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length, type, 177538c8a9a5SSteve French 1, 0, false); 177638c8a9a5SSteve French if (rc == 0) { 177738c8a9a5SSteve French rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length, 177838c8a9a5SSteve French type, 0, 1, false); 177938c8a9a5SSteve French flock->fl_type = F_UNLCK; 178038c8a9a5SSteve French if (rc != 0) 178138c8a9a5SSteve French cifs_dbg(VFS, "Error unlocking previously locked range %d during test of lock\n", 178238c8a9a5SSteve French rc); 178338c8a9a5SSteve French return 0; 178438c8a9a5SSteve French } 178538c8a9a5SSteve French 178638c8a9a5SSteve French if (type & server->vals->shared_lock_type) { 178738c8a9a5SSteve French flock->fl_type = F_WRLCK; 178838c8a9a5SSteve French return 0; 178938c8a9a5SSteve French } 179038c8a9a5SSteve French 179138c8a9a5SSteve French type &= ~server->vals->exclusive_lock_type; 179238c8a9a5SSteve French 179338c8a9a5SSteve French rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length, 179438c8a9a5SSteve French type | server->vals->shared_lock_type, 179538c8a9a5SSteve French 1, 0, false); 179638c8a9a5SSteve French if (rc == 0) { 179738c8a9a5SSteve French rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length, 179838c8a9a5SSteve French type | server->vals->shared_lock_type, 0, 1, false); 179938c8a9a5SSteve French flock->fl_type = F_RDLCK; 180038c8a9a5SSteve French if (rc != 0) 180138c8a9a5SSteve French cifs_dbg(VFS, "Error unlocking previously locked range %d during test of lock\n", 180238c8a9a5SSteve French rc); 180338c8a9a5SSteve French } else 180438c8a9a5SSteve French flock->fl_type = F_WRLCK; 180538c8a9a5SSteve French 180638c8a9a5SSteve French return 0; 180738c8a9a5SSteve French } 180838c8a9a5SSteve French 180938c8a9a5SSteve French void 181038c8a9a5SSteve French cifs_move_llist(struct list_head *source, struct list_head *dest) 181138c8a9a5SSteve French { 181238c8a9a5SSteve French struct list_head *li, *tmp; 181338c8a9a5SSteve French list_for_each_safe(li, tmp, source) 181438c8a9a5SSteve French list_move(li, dest); 181538c8a9a5SSteve French } 181638c8a9a5SSteve French 181738c8a9a5SSteve French void 181838c8a9a5SSteve French cifs_free_llist(struct list_head *llist) 181938c8a9a5SSteve French { 182038c8a9a5SSteve French struct cifsLockInfo *li, *tmp; 182138c8a9a5SSteve French list_for_each_entry_safe(li, tmp, llist, llist) { 182238c8a9a5SSteve French cifs_del_lock_waiters(li); 182338c8a9a5SSteve French list_del(&li->llist); 182438c8a9a5SSteve French kfree(li); 182538c8a9a5SSteve French } 182638c8a9a5SSteve French } 182738c8a9a5SSteve French 182838c8a9a5SSteve French #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 182938c8a9a5SSteve French int 183038c8a9a5SSteve French cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, 183138c8a9a5SSteve French unsigned int xid) 183238c8a9a5SSteve French { 183338c8a9a5SSteve French int rc = 0, stored_rc; 183438c8a9a5SSteve French static const int types[] = { 183538c8a9a5SSteve French LOCKING_ANDX_LARGE_FILES, 183638c8a9a5SSteve French LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES 183738c8a9a5SSteve French }; 183838c8a9a5SSteve French unsigned int i; 183938c8a9a5SSteve French unsigned int max_num, num, max_buf; 184038c8a9a5SSteve French LOCKING_ANDX_RANGE *buf, *cur; 184138c8a9a5SSteve French struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 184238c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(d_inode(cfile->dentry)); 184338c8a9a5SSteve French struct cifsLockInfo *li, *tmp; 184438c8a9a5SSteve French __u64 length = cifs_flock_len(flock); 184538c8a9a5SSteve French struct list_head tmp_llist; 184638c8a9a5SSteve French 184738c8a9a5SSteve French INIT_LIST_HEAD(&tmp_llist); 184838c8a9a5SSteve French 184938c8a9a5SSteve French /* 185038c8a9a5SSteve French * Accessing maxBuf is racy with cifs_reconnect - need to store value 185138c8a9a5SSteve French * and check it before using. 185238c8a9a5SSteve French */ 185338c8a9a5SSteve French max_buf = tcon->ses->server->maxBuf; 185438c8a9a5SSteve French if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE))) 185538c8a9a5SSteve French return -EINVAL; 185638c8a9a5SSteve French 185738c8a9a5SSteve French BUILD_BUG_ON(sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE) > 185838c8a9a5SSteve French PAGE_SIZE); 185938c8a9a5SSteve French max_buf = min_t(unsigned int, max_buf - sizeof(struct smb_hdr), 186038c8a9a5SSteve French PAGE_SIZE); 186138c8a9a5SSteve French max_num = (max_buf - sizeof(struct smb_hdr)) / 186238c8a9a5SSteve French sizeof(LOCKING_ANDX_RANGE); 186338c8a9a5SSteve French buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); 186438c8a9a5SSteve French if (!buf) 186538c8a9a5SSteve French return -ENOMEM; 186638c8a9a5SSteve French 186738c8a9a5SSteve French cifs_down_write(&cinode->lock_sem); 186838c8a9a5SSteve French for (i = 0; i < 2; i++) { 186938c8a9a5SSteve French cur = buf; 187038c8a9a5SSteve French num = 0; 187138c8a9a5SSteve French list_for_each_entry_safe(li, tmp, &cfile->llist->locks, llist) { 187238c8a9a5SSteve French if (flock->fl_start > li->offset || 187338c8a9a5SSteve French (flock->fl_start + length) < 187438c8a9a5SSteve French (li->offset + li->length)) 187538c8a9a5SSteve French continue; 187638c8a9a5SSteve French if (current->tgid != li->pid) 187738c8a9a5SSteve French continue; 187838c8a9a5SSteve French if (types[i] != li->type) 187938c8a9a5SSteve French continue; 188038c8a9a5SSteve French if (cinode->can_cache_brlcks) { 188138c8a9a5SSteve French /* 188238c8a9a5SSteve French * We can cache brlock requests - simply remove 188338c8a9a5SSteve French * a lock from the file's list. 188438c8a9a5SSteve French */ 188538c8a9a5SSteve French list_del(&li->llist); 188638c8a9a5SSteve French cifs_del_lock_waiters(li); 188738c8a9a5SSteve French kfree(li); 188838c8a9a5SSteve French continue; 188938c8a9a5SSteve French } 189038c8a9a5SSteve French cur->Pid = cpu_to_le16(li->pid); 189138c8a9a5SSteve French cur->LengthLow = cpu_to_le32((u32)li->length); 189238c8a9a5SSteve French cur->LengthHigh = cpu_to_le32((u32)(li->length>>32)); 189338c8a9a5SSteve French cur->OffsetLow = cpu_to_le32((u32)li->offset); 189438c8a9a5SSteve French cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32)); 189538c8a9a5SSteve French /* 189638c8a9a5SSteve French * We need to save a lock here to let us add it again to 189738c8a9a5SSteve French * the file's list if the unlock range request fails on 189838c8a9a5SSteve French * the server. 189938c8a9a5SSteve French */ 190038c8a9a5SSteve French list_move(&li->llist, &tmp_llist); 190138c8a9a5SSteve French if (++num == max_num) { 190238c8a9a5SSteve French stored_rc = cifs_lockv(xid, tcon, 190338c8a9a5SSteve French cfile->fid.netfid, 190438c8a9a5SSteve French li->type, num, 0, buf); 190538c8a9a5SSteve French if (stored_rc) { 190638c8a9a5SSteve French /* 190738c8a9a5SSteve French * We failed on the unlock range 190838c8a9a5SSteve French * request - add all locks from the tmp 190938c8a9a5SSteve French * list to the head of the file's list. 191038c8a9a5SSteve French */ 191138c8a9a5SSteve French cifs_move_llist(&tmp_llist, 191238c8a9a5SSteve French &cfile->llist->locks); 191338c8a9a5SSteve French rc = stored_rc; 191438c8a9a5SSteve French } else 191538c8a9a5SSteve French /* 191638c8a9a5SSteve French * The unlock range request succeed - 191738c8a9a5SSteve French * free the tmp list. 191838c8a9a5SSteve French */ 191938c8a9a5SSteve French cifs_free_llist(&tmp_llist); 192038c8a9a5SSteve French cur = buf; 192138c8a9a5SSteve French num = 0; 192238c8a9a5SSteve French } else 192338c8a9a5SSteve French cur++; 192438c8a9a5SSteve French } 192538c8a9a5SSteve French if (num) { 192638c8a9a5SSteve French stored_rc = cifs_lockv(xid, tcon, cfile->fid.netfid, 192738c8a9a5SSteve French types[i], num, 0, buf); 192838c8a9a5SSteve French if (stored_rc) { 192938c8a9a5SSteve French cifs_move_llist(&tmp_llist, 193038c8a9a5SSteve French &cfile->llist->locks); 193138c8a9a5SSteve French rc = stored_rc; 193238c8a9a5SSteve French } else 193338c8a9a5SSteve French cifs_free_llist(&tmp_llist); 193438c8a9a5SSteve French } 193538c8a9a5SSteve French } 193638c8a9a5SSteve French 193738c8a9a5SSteve French up_write(&cinode->lock_sem); 193838c8a9a5SSteve French kfree(buf); 193938c8a9a5SSteve French return rc; 194038c8a9a5SSteve French } 194138c8a9a5SSteve French #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 194238c8a9a5SSteve French 194338c8a9a5SSteve French static int 194438c8a9a5SSteve French cifs_setlk(struct file *file, struct file_lock *flock, __u32 type, 194538c8a9a5SSteve French bool wait_flag, bool posix_lck, int lock, int unlock, 194638c8a9a5SSteve French unsigned int xid) 194738c8a9a5SSteve French { 194838c8a9a5SSteve French int rc = 0; 194938c8a9a5SSteve French __u64 length = cifs_flock_len(flock); 195038c8a9a5SSteve French struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; 195138c8a9a5SSteve French struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 195238c8a9a5SSteve French struct TCP_Server_Info *server = tcon->ses->server; 195338c8a9a5SSteve French struct inode *inode = d_inode(cfile->dentry); 195438c8a9a5SSteve French 195538c8a9a5SSteve French #ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY 195638c8a9a5SSteve French if (posix_lck) { 195738c8a9a5SSteve French int posix_lock_type; 195838c8a9a5SSteve French 195938c8a9a5SSteve French rc = cifs_posix_lock_set(file, flock); 196038c8a9a5SSteve French if (rc <= FILE_LOCK_DEFERRED) 196138c8a9a5SSteve French return rc; 196238c8a9a5SSteve French 196338c8a9a5SSteve French if (type & server->vals->shared_lock_type) 196438c8a9a5SSteve French posix_lock_type = CIFS_RDLCK; 196538c8a9a5SSteve French else 196638c8a9a5SSteve French posix_lock_type = CIFS_WRLCK; 196738c8a9a5SSteve French 196838c8a9a5SSteve French if (unlock == 1) 196938c8a9a5SSteve French posix_lock_type = CIFS_UNLCK; 197038c8a9a5SSteve French 197138c8a9a5SSteve French rc = CIFSSMBPosixLock(xid, tcon, cfile->fid.netfid, 197238c8a9a5SSteve French hash_lockowner(flock->fl_owner), 197338c8a9a5SSteve French flock->fl_start, length, 197438c8a9a5SSteve French NULL, posix_lock_type, wait_flag); 197538c8a9a5SSteve French goto out; 197638c8a9a5SSteve French } 197738c8a9a5SSteve French #endif /* CONFIG_CIFS_ALLOW_INSECURE_LEGACY */ 197838c8a9a5SSteve French if (lock) { 197938c8a9a5SSteve French struct cifsLockInfo *lock; 198038c8a9a5SSteve French 198138c8a9a5SSteve French lock = cifs_lock_init(flock->fl_start, length, type, 198238c8a9a5SSteve French flock->fl_flags); 198338c8a9a5SSteve French if (!lock) 198438c8a9a5SSteve French return -ENOMEM; 198538c8a9a5SSteve French 198638c8a9a5SSteve French rc = cifs_lock_add_if(cfile, lock, wait_flag); 198738c8a9a5SSteve French if (rc < 0) { 198838c8a9a5SSteve French kfree(lock); 198938c8a9a5SSteve French return rc; 199038c8a9a5SSteve French } 199138c8a9a5SSteve French if (!rc) 199238c8a9a5SSteve French goto out; 199338c8a9a5SSteve French 199438c8a9a5SSteve French /* 199538c8a9a5SSteve French * Windows 7 server can delay breaking lease from read to None 199638c8a9a5SSteve French * if we set a byte-range lock on a file - break it explicitly 199738c8a9a5SSteve French * before sending the lock to the server to be sure the next 199838c8a9a5SSteve French * read won't conflict with non-overlapted locks due to 199938c8a9a5SSteve French * pagereading. 200038c8a9a5SSteve French */ 200138c8a9a5SSteve French if (!CIFS_CACHE_WRITE(CIFS_I(inode)) && 200238c8a9a5SSteve French CIFS_CACHE_READ(CIFS_I(inode))) { 200338c8a9a5SSteve French cifs_zap_mapping(inode); 200438c8a9a5SSteve French cifs_dbg(FYI, "Set no oplock for inode=%p due to mand locks\n", 200538c8a9a5SSteve French inode); 200638c8a9a5SSteve French CIFS_I(inode)->oplock = 0; 200738c8a9a5SSteve French } 200838c8a9a5SSteve French 200938c8a9a5SSteve French rc = server->ops->mand_lock(xid, cfile, flock->fl_start, length, 201038c8a9a5SSteve French type, 1, 0, wait_flag); 201138c8a9a5SSteve French if (rc) { 201238c8a9a5SSteve French kfree(lock); 201338c8a9a5SSteve French return rc; 201438c8a9a5SSteve French } 201538c8a9a5SSteve French 201638c8a9a5SSteve French cifs_lock_add(cfile, lock); 201738c8a9a5SSteve French } else if (unlock) 201838c8a9a5SSteve French rc = server->ops->mand_unlock_range(cfile, flock, xid); 201938c8a9a5SSteve French 202038c8a9a5SSteve French out: 202138c8a9a5SSteve French if ((flock->fl_flags & FL_POSIX) || (flock->fl_flags & FL_FLOCK)) { 202238c8a9a5SSteve French /* 202338c8a9a5SSteve French * If this is a request to remove all locks because we 202438c8a9a5SSteve French * are closing the file, it doesn't matter if the 202538c8a9a5SSteve French * unlocking failed as both cifs.ko and the SMB server 202638c8a9a5SSteve French * remove the lock on file close 202738c8a9a5SSteve French */ 202838c8a9a5SSteve French if (rc) { 202938c8a9a5SSteve French cifs_dbg(VFS, "%s failed rc=%d\n", __func__, rc); 203038c8a9a5SSteve French if (!(flock->fl_flags & FL_CLOSE)) 203138c8a9a5SSteve French return rc; 203238c8a9a5SSteve French } 203338c8a9a5SSteve French rc = locks_lock_file_wait(file, flock); 203438c8a9a5SSteve French } 203538c8a9a5SSteve French return rc; 203638c8a9a5SSteve French } 203738c8a9a5SSteve French 203838c8a9a5SSteve French int cifs_flock(struct file *file, int cmd, struct file_lock *fl) 203938c8a9a5SSteve French { 204038c8a9a5SSteve French int rc, xid; 204138c8a9a5SSteve French int lock = 0, unlock = 0; 204238c8a9a5SSteve French bool wait_flag = false; 204338c8a9a5SSteve French bool posix_lck = false; 204438c8a9a5SSteve French struct cifs_sb_info *cifs_sb; 204538c8a9a5SSteve French struct cifs_tcon *tcon; 204638c8a9a5SSteve French struct cifsFileInfo *cfile; 204738c8a9a5SSteve French __u32 type; 204838c8a9a5SSteve French 204938c8a9a5SSteve French xid = get_xid(); 205038c8a9a5SSteve French 205138c8a9a5SSteve French if (!(fl->fl_flags & FL_FLOCK)) { 205238c8a9a5SSteve French rc = -ENOLCK; 205338c8a9a5SSteve French free_xid(xid); 205438c8a9a5SSteve French return rc; 205538c8a9a5SSteve French } 205638c8a9a5SSteve French 205738c8a9a5SSteve French cfile = (struct cifsFileInfo *)file->private_data; 205838c8a9a5SSteve French tcon = tlink_tcon(cfile->tlink); 205938c8a9a5SSteve French 206038c8a9a5SSteve French cifs_read_flock(fl, &type, &lock, &unlock, &wait_flag, 206138c8a9a5SSteve French tcon->ses->server); 206238c8a9a5SSteve French cifs_sb = CIFS_FILE_SB(file); 206338c8a9a5SSteve French 206438c8a9a5SSteve French if (cap_unix(tcon->ses) && 206538c8a9a5SSteve French (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && 206638c8a9a5SSteve French ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) 206738c8a9a5SSteve French posix_lck = true; 206838c8a9a5SSteve French 206938c8a9a5SSteve French if (!lock && !unlock) { 207038c8a9a5SSteve French /* 207138c8a9a5SSteve French * if no lock or unlock then nothing to do since we do not 207238c8a9a5SSteve French * know what it is 207338c8a9a5SSteve French */ 207438c8a9a5SSteve French rc = -EOPNOTSUPP; 207538c8a9a5SSteve French free_xid(xid); 207638c8a9a5SSteve French return rc; 207738c8a9a5SSteve French } 207838c8a9a5SSteve French 207938c8a9a5SSteve French rc = cifs_setlk(file, fl, type, wait_flag, posix_lck, lock, unlock, 208038c8a9a5SSteve French xid); 208138c8a9a5SSteve French free_xid(xid); 208238c8a9a5SSteve French return rc; 208338c8a9a5SSteve French 208438c8a9a5SSteve French 208538c8a9a5SSteve French } 208638c8a9a5SSteve French 208738c8a9a5SSteve French int cifs_lock(struct file *file, int cmd, struct file_lock *flock) 208838c8a9a5SSteve French { 208938c8a9a5SSteve French int rc, xid; 209038c8a9a5SSteve French int lock = 0, unlock = 0; 209138c8a9a5SSteve French bool wait_flag = false; 209238c8a9a5SSteve French bool posix_lck = false; 209338c8a9a5SSteve French struct cifs_sb_info *cifs_sb; 209438c8a9a5SSteve French struct cifs_tcon *tcon; 209538c8a9a5SSteve French struct cifsFileInfo *cfile; 209638c8a9a5SSteve French __u32 type; 209738c8a9a5SSteve French 209838c8a9a5SSteve French rc = -EACCES; 209938c8a9a5SSteve French xid = get_xid(); 210038c8a9a5SSteve French 210138c8a9a5SSteve French cifs_dbg(FYI, "%s: %pD2 cmd=0x%x type=0x%x flags=0x%x r=%lld:%lld\n", __func__, file, cmd, 210238c8a9a5SSteve French flock->fl_flags, flock->fl_type, (long long)flock->fl_start, 210338c8a9a5SSteve French (long long)flock->fl_end); 210438c8a9a5SSteve French 210538c8a9a5SSteve French cfile = (struct cifsFileInfo *)file->private_data; 210638c8a9a5SSteve French tcon = tlink_tcon(cfile->tlink); 210738c8a9a5SSteve French 210838c8a9a5SSteve French cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag, 210938c8a9a5SSteve French tcon->ses->server); 211038c8a9a5SSteve French cifs_sb = CIFS_FILE_SB(file); 211138c8a9a5SSteve French set_bit(CIFS_INO_CLOSE_ON_LOCK, &CIFS_I(d_inode(cfile->dentry))->flags); 211238c8a9a5SSteve French 211338c8a9a5SSteve French if (cap_unix(tcon->ses) && 211438c8a9a5SSteve French (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && 211538c8a9a5SSteve French ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) 211638c8a9a5SSteve French posix_lck = true; 211738c8a9a5SSteve French /* 211838c8a9a5SSteve French * BB add code here to normalize offset and length to account for 211938c8a9a5SSteve French * negative length which we can not accept over the wire. 212038c8a9a5SSteve French */ 212138c8a9a5SSteve French if (IS_GETLK(cmd)) { 212238c8a9a5SSteve French rc = cifs_getlk(file, flock, type, wait_flag, posix_lck, xid); 212338c8a9a5SSteve French free_xid(xid); 212438c8a9a5SSteve French return rc; 212538c8a9a5SSteve French } 212638c8a9a5SSteve French 212738c8a9a5SSteve French if (!lock && !unlock) { 212838c8a9a5SSteve French /* 212938c8a9a5SSteve French * if no lock or unlock then nothing to do since we do not 213038c8a9a5SSteve French * know what it is 213138c8a9a5SSteve French */ 213238c8a9a5SSteve French free_xid(xid); 213338c8a9a5SSteve French return -EOPNOTSUPP; 213438c8a9a5SSteve French } 213538c8a9a5SSteve French 213638c8a9a5SSteve French rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, unlock, 213738c8a9a5SSteve French xid); 213838c8a9a5SSteve French free_xid(xid); 213938c8a9a5SSteve French return rc; 214038c8a9a5SSteve French } 214138c8a9a5SSteve French 214238c8a9a5SSteve French /* 214338c8a9a5SSteve French * update the file size (if needed) after a write. Should be called with 214438c8a9a5SSteve French * the inode->i_lock held 214538c8a9a5SSteve French */ 214638c8a9a5SSteve French void 214738c8a9a5SSteve French cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, 214838c8a9a5SSteve French unsigned int bytes_written) 214938c8a9a5SSteve French { 215038c8a9a5SSteve French loff_t end_of_write = offset + bytes_written; 215138c8a9a5SSteve French 215238c8a9a5SSteve French if (end_of_write > cifsi->server_eof) 215338c8a9a5SSteve French cifsi->server_eof = end_of_write; 215438c8a9a5SSteve French } 215538c8a9a5SSteve French 215638c8a9a5SSteve French static ssize_t 215738c8a9a5SSteve French cifs_write(struct cifsFileInfo *open_file, __u32 pid, const char *write_data, 215838c8a9a5SSteve French size_t write_size, loff_t *offset) 215938c8a9a5SSteve French { 216038c8a9a5SSteve French int rc = 0; 216138c8a9a5SSteve French unsigned int bytes_written = 0; 216238c8a9a5SSteve French unsigned int total_written; 216338c8a9a5SSteve French struct cifs_tcon *tcon; 216438c8a9a5SSteve French struct TCP_Server_Info *server; 216538c8a9a5SSteve French unsigned int xid; 216638c8a9a5SSteve French struct dentry *dentry = open_file->dentry; 216738c8a9a5SSteve French struct cifsInodeInfo *cifsi = CIFS_I(d_inode(dentry)); 216838c8a9a5SSteve French struct cifs_io_parms io_parms = {0}; 216938c8a9a5SSteve French 217038c8a9a5SSteve French cifs_dbg(FYI, "write %zd bytes to offset %lld of %pd\n", 217138c8a9a5SSteve French write_size, *offset, dentry); 217238c8a9a5SSteve French 217338c8a9a5SSteve French tcon = tlink_tcon(open_file->tlink); 217438c8a9a5SSteve French server = tcon->ses->server; 217538c8a9a5SSteve French 217638c8a9a5SSteve French if (!server->ops->sync_write) 217738c8a9a5SSteve French return -ENOSYS; 217838c8a9a5SSteve French 217938c8a9a5SSteve French xid = get_xid(); 218038c8a9a5SSteve French 218138c8a9a5SSteve French for (total_written = 0; write_size > total_written; 218238c8a9a5SSteve French total_written += bytes_written) { 218338c8a9a5SSteve French rc = -EAGAIN; 218438c8a9a5SSteve French while (rc == -EAGAIN) { 218538c8a9a5SSteve French struct kvec iov[2]; 218638c8a9a5SSteve French unsigned int len; 218738c8a9a5SSteve French 218838c8a9a5SSteve French if (open_file->invalidHandle) { 218938c8a9a5SSteve French /* we could deadlock if we called 219038c8a9a5SSteve French filemap_fdatawait from here so tell 219138c8a9a5SSteve French reopen_file not to flush data to 219238c8a9a5SSteve French server now */ 219338c8a9a5SSteve French rc = cifs_reopen_file(open_file, false); 219438c8a9a5SSteve French if (rc != 0) 219538c8a9a5SSteve French break; 219638c8a9a5SSteve French } 219738c8a9a5SSteve French 219838c8a9a5SSteve French len = min(server->ops->wp_retry_size(d_inode(dentry)), 219938c8a9a5SSteve French (unsigned int)write_size - total_written); 220038c8a9a5SSteve French /* iov[0] is reserved for smb header */ 220138c8a9a5SSteve French iov[1].iov_base = (char *)write_data + total_written; 220238c8a9a5SSteve French iov[1].iov_len = len; 220338c8a9a5SSteve French io_parms.pid = pid; 220438c8a9a5SSteve French io_parms.tcon = tcon; 220538c8a9a5SSteve French io_parms.offset = *offset; 220638c8a9a5SSteve French io_parms.length = len; 220738c8a9a5SSteve French rc = server->ops->sync_write(xid, &open_file->fid, 220838c8a9a5SSteve French &io_parms, &bytes_written, iov, 1); 220938c8a9a5SSteve French } 221038c8a9a5SSteve French if (rc || (bytes_written == 0)) { 221138c8a9a5SSteve French if (total_written) 221238c8a9a5SSteve French break; 221338c8a9a5SSteve French else { 221438c8a9a5SSteve French free_xid(xid); 221538c8a9a5SSteve French return rc; 221638c8a9a5SSteve French } 221738c8a9a5SSteve French } else { 221838c8a9a5SSteve French spin_lock(&d_inode(dentry)->i_lock); 221938c8a9a5SSteve French cifs_update_eof(cifsi, *offset, bytes_written); 222038c8a9a5SSteve French spin_unlock(&d_inode(dentry)->i_lock); 222138c8a9a5SSteve French *offset += bytes_written; 222238c8a9a5SSteve French } 222338c8a9a5SSteve French } 222438c8a9a5SSteve French 222538c8a9a5SSteve French cifs_stats_bytes_written(tcon, total_written); 222638c8a9a5SSteve French 222738c8a9a5SSteve French if (total_written > 0) { 222838c8a9a5SSteve French spin_lock(&d_inode(dentry)->i_lock); 222938c8a9a5SSteve French if (*offset > d_inode(dentry)->i_size) { 223038c8a9a5SSteve French i_size_write(d_inode(dentry), *offset); 223138c8a9a5SSteve French d_inode(dentry)->i_blocks = (512 - 1 + *offset) >> 9; 223238c8a9a5SSteve French } 223338c8a9a5SSteve French spin_unlock(&d_inode(dentry)->i_lock); 223438c8a9a5SSteve French } 223538c8a9a5SSteve French mark_inode_dirty_sync(d_inode(dentry)); 223638c8a9a5SSteve French free_xid(xid); 223738c8a9a5SSteve French return total_written; 223838c8a9a5SSteve French } 223938c8a9a5SSteve French 224038c8a9a5SSteve French struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, 224138c8a9a5SSteve French bool fsuid_only) 224238c8a9a5SSteve French { 224338c8a9a5SSteve French struct cifsFileInfo *open_file = NULL; 224438c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_inode->netfs.inode.i_sb); 224538c8a9a5SSteve French 224638c8a9a5SSteve French /* only filter by fsuid on multiuser mounts */ 224738c8a9a5SSteve French if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) 224838c8a9a5SSteve French fsuid_only = false; 224938c8a9a5SSteve French 225038c8a9a5SSteve French spin_lock(&cifs_inode->open_file_lock); 225138c8a9a5SSteve French /* we could simply get the first_list_entry since write-only entries 225238c8a9a5SSteve French are always at the end of the list but since the first entry might 225338c8a9a5SSteve French have a close pending, we go through the whole list */ 225438c8a9a5SSteve French list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { 225538c8a9a5SSteve French if (fsuid_only && !uid_eq(open_file->uid, current_fsuid())) 225638c8a9a5SSteve French continue; 225738c8a9a5SSteve French if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) { 225838c8a9a5SSteve French if ((!open_file->invalidHandle)) { 225938c8a9a5SSteve French /* found a good file */ 226038c8a9a5SSteve French /* lock it so it will not be closed on us */ 226138c8a9a5SSteve French cifsFileInfo_get(open_file); 226238c8a9a5SSteve French spin_unlock(&cifs_inode->open_file_lock); 226338c8a9a5SSteve French return open_file; 226438c8a9a5SSteve French } /* else might as well continue, and look for 226538c8a9a5SSteve French another, or simply have the caller reopen it 226638c8a9a5SSteve French again rather than trying to fix this handle */ 226738c8a9a5SSteve French } else /* write only file */ 226838c8a9a5SSteve French break; /* write only files are last so must be done */ 226938c8a9a5SSteve French } 227038c8a9a5SSteve French spin_unlock(&cifs_inode->open_file_lock); 227138c8a9a5SSteve French return NULL; 227238c8a9a5SSteve French } 227338c8a9a5SSteve French 227438c8a9a5SSteve French /* Return -EBADF if no handle is found and general rc otherwise */ 227538c8a9a5SSteve French int 227638c8a9a5SSteve French cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, int flags, 227738c8a9a5SSteve French struct cifsFileInfo **ret_file) 227838c8a9a5SSteve French { 227938c8a9a5SSteve French struct cifsFileInfo *open_file, *inv_file = NULL; 228038c8a9a5SSteve French struct cifs_sb_info *cifs_sb; 228138c8a9a5SSteve French bool any_available = false; 228238c8a9a5SSteve French int rc = -EBADF; 228338c8a9a5SSteve French unsigned int refind = 0; 228438c8a9a5SSteve French bool fsuid_only = flags & FIND_WR_FSUID_ONLY; 228538c8a9a5SSteve French bool with_delete = flags & FIND_WR_WITH_DELETE; 228638c8a9a5SSteve French *ret_file = NULL; 228738c8a9a5SSteve French 228838c8a9a5SSteve French /* 228938c8a9a5SSteve French * Having a null inode here (because mapping->host was set to zero by 229038c8a9a5SSteve French * the VFS or MM) should not happen but we had reports of on oops (due 229138c8a9a5SSteve French * to it being zero) during stress testcases so we need to check for it 229238c8a9a5SSteve French */ 229338c8a9a5SSteve French 229438c8a9a5SSteve French if (cifs_inode == NULL) { 229538c8a9a5SSteve French cifs_dbg(VFS, "Null inode passed to cifs_writeable_file\n"); 229638c8a9a5SSteve French dump_stack(); 229738c8a9a5SSteve French return rc; 229838c8a9a5SSteve French } 229938c8a9a5SSteve French 230038c8a9a5SSteve French cifs_sb = CIFS_SB(cifs_inode->netfs.inode.i_sb); 230138c8a9a5SSteve French 230238c8a9a5SSteve French /* only filter by fsuid on multiuser mounts */ 230338c8a9a5SSteve French if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)) 230438c8a9a5SSteve French fsuid_only = false; 230538c8a9a5SSteve French 230638c8a9a5SSteve French spin_lock(&cifs_inode->open_file_lock); 230738c8a9a5SSteve French refind_writable: 230838c8a9a5SSteve French if (refind > MAX_REOPEN_ATT) { 230938c8a9a5SSteve French spin_unlock(&cifs_inode->open_file_lock); 231038c8a9a5SSteve French return rc; 231138c8a9a5SSteve French } 231238c8a9a5SSteve French list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { 231338c8a9a5SSteve French if (!any_available && open_file->pid != current->tgid) 231438c8a9a5SSteve French continue; 231538c8a9a5SSteve French if (fsuid_only && !uid_eq(open_file->uid, current_fsuid())) 231638c8a9a5SSteve French continue; 231738c8a9a5SSteve French if (with_delete && !(open_file->fid.access & DELETE)) 231838c8a9a5SSteve French continue; 231938c8a9a5SSteve French if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { 232038c8a9a5SSteve French if (!open_file->invalidHandle) { 232138c8a9a5SSteve French /* found a good writable file */ 232238c8a9a5SSteve French cifsFileInfo_get(open_file); 232338c8a9a5SSteve French spin_unlock(&cifs_inode->open_file_lock); 232438c8a9a5SSteve French *ret_file = open_file; 232538c8a9a5SSteve French return 0; 232638c8a9a5SSteve French } else { 232738c8a9a5SSteve French if (!inv_file) 232838c8a9a5SSteve French inv_file = open_file; 232938c8a9a5SSteve French } 233038c8a9a5SSteve French } 233138c8a9a5SSteve French } 233238c8a9a5SSteve French /* couldn't find useable FH with same pid, try any available */ 233338c8a9a5SSteve French if (!any_available) { 233438c8a9a5SSteve French any_available = true; 233538c8a9a5SSteve French goto refind_writable; 233638c8a9a5SSteve French } 233738c8a9a5SSteve French 233838c8a9a5SSteve French if (inv_file) { 233938c8a9a5SSteve French any_available = false; 234038c8a9a5SSteve French cifsFileInfo_get(inv_file); 234138c8a9a5SSteve French } 234238c8a9a5SSteve French 234338c8a9a5SSteve French spin_unlock(&cifs_inode->open_file_lock); 234438c8a9a5SSteve French 234538c8a9a5SSteve French if (inv_file) { 234638c8a9a5SSteve French rc = cifs_reopen_file(inv_file, false); 234738c8a9a5SSteve French if (!rc) { 234838c8a9a5SSteve French *ret_file = inv_file; 234938c8a9a5SSteve French return 0; 235038c8a9a5SSteve French } 235138c8a9a5SSteve French 235238c8a9a5SSteve French spin_lock(&cifs_inode->open_file_lock); 235338c8a9a5SSteve French list_move_tail(&inv_file->flist, &cifs_inode->openFileList); 235438c8a9a5SSteve French spin_unlock(&cifs_inode->open_file_lock); 235538c8a9a5SSteve French cifsFileInfo_put(inv_file); 235638c8a9a5SSteve French ++refind; 235738c8a9a5SSteve French inv_file = NULL; 235838c8a9a5SSteve French spin_lock(&cifs_inode->open_file_lock); 235938c8a9a5SSteve French goto refind_writable; 236038c8a9a5SSteve French } 236138c8a9a5SSteve French 236238c8a9a5SSteve French return rc; 236338c8a9a5SSteve French } 236438c8a9a5SSteve French 236538c8a9a5SSteve French struct cifsFileInfo * 236638c8a9a5SSteve French find_writable_file(struct cifsInodeInfo *cifs_inode, int flags) 236738c8a9a5SSteve French { 236838c8a9a5SSteve French struct cifsFileInfo *cfile; 236938c8a9a5SSteve French int rc; 237038c8a9a5SSteve French 237138c8a9a5SSteve French rc = cifs_get_writable_file(cifs_inode, flags, &cfile); 237238c8a9a5SSteve French if (rc) 237338c8a9a5SSteve French cifs_dbg(FYI, "Couldn't find writable handle rc=%d\n", rc); 237438c8a9a5SSteve French 237538c8a9a5SSteve French return cfile; 237638c8a9a5SSteve French } 237738c8a9a5SSteve French 237838c8a9a5SSteve French int 237938c8a9a5SSteve French cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, 238038c8a9a5SSteve French int flags, 238138c8a9a5SSteve French struct cifsFileInfo **ret_file) 238238c8a9a5SSteve French { 238338c8a9a5SSteve French struct cifsFileInfo *cfile; 238438c8a9a5SSteve French void *page = alloc_dentry_path(); 238538c8a9a5SSteve French 238638c8a9a5SSteve French *ret_file = NULL; 238738c8a9a5SSteve French 238838c8a9a5SSteve French spin_lock(&tcon->open_file_lock); 238938c8a9a5SSteve French list_for_each_entry(cfile, &tcon->openFileList, tlist) { 239038c8a9a5SSteve French struct cifsInodeInfo *cinode; 239138c8a9a5SSteve French const char *full_path = build_path_from_dentry(cfile->dentry, page); 239238c8a9a5SSteve French if (IS_ERR(full_path)) { 239338c8a9a5SSteve French spin_unlock(&tcon->open_file_lock); 239438c8a9a5SSteve French free_dentry_path(page); 239538c8a9a5SSteve French return PTR_ERR(full_path); 239638c8a9a5SSteve French } 239738c8a9a5SSteve French if (strcmp(full_path, name)) 239838c8a9a5SSteve French continue; 239938c8a9a5SSteve French 240038c8a9a5SSteve French cinode = CIFS_I(d_inode(cfile->dentry)); 240138c8a9a5SSteve French spin_unlock(&tcon->open_file_lock); 240238c8a9a5SSteve French free_dentry_path(page); 240338c8a9a5SSteve French return cifs_get_writable_file(cinode, flags, ret_file); 240438c8a9a5SSteve French } 240538c8a9a5SSteve French 240638c8a9a5SSteve French spin_unlock(&tcon->open_file_lock); 240738c8a9a5SSteve French free_dentry_path(page); 240838c8a9a5SSteve French return -ENOENT; 240938c8a9a5SSteve French } 241038c8a9a5SSteve French 241138c8a9a5SSteve French int 241238c8a9a5SSteve French cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, 241338c8a9a5SSteve French struct cifsFileInfo **ret_file) 241438c8a9a5SSteve French { 241538c8a9a5SSteve French struct cifsFileInfo *cfile; 241638c8a9a5SSteve French void *page = alloc_dentry_path(); 241738c8a9a5SSteve French 241838c8a9a5SSteve French *ret_file = NULL; 241938c8a9a5SSteve French 242038c8a9a5SSteve French spin_lock(&tcon->open_file_lock); 242138c8a9a5SSteve French list_for_each_entry(cfile, &tcon->openFileList, tlist) { 242238c8a9a5SSteve French struct cifsInodeInfo *cinode; 242338c8a9a5SSteve French const char *full_path = build_path_from_dentry(cfile->dentry, page); 242438c8a9a5SSteve French if (IS_ERR(full_path)) { 242538c8a9a5SSteve French spin_unlock(&tcon->open_file_lock); 242638c8a9a5SSteve French free_dentry_path(page); 242738c8a9a5SSteve French return PTR_ERR(full_path); 242838c8a9a5SSteve French } 242938c8a9a5SSteve French if (strcmp(full_path, name)) 243038c8a9a5SSteve French continue; 243138c8a9a5SSteve French 243238c8a9a5SSteve French cinode = CIFS_I(d_inode(cfile->dentry)); 243338c8a9a5SSteve French spin_unlock(&tcon->open_file_lock); 243438c8a9a5SSteve French free_dentry_path(page); 243538c8a9a5SSteve French *ret_file = find_readable_file(cinode, 0); 243638c8a9a5SSteve French return *ret_file ? 0 : -ENOENT; 243738c8a9a5SSteve French } 243838c8a9a5SSteve French 243938c8a9a5SSteve French spin_unlock(&tcon->open_file_lock); 244038c8a9a5SSteve French free_dentry_path(page); 244138c8a9a5SSteve French return -ENOENT; 244238c8a9a5SSteve French } 244338c8a9a5SSteve French 244438c8a9a5SSteve French void 244538c8a9a5SSteve French cifs_writedata_release(struct kref *refcount) 244638c8a9a5SSteve French { 244738c8a9a5SSteve French struct cifs_writedata *wdata = container_of(refcount, 244838c8a9a5SSteve French struct cifs_writedata, refcount); 244938c8a9a5SSteve French #ifdef CONFIG_CIFS_SMB_DIRECT 245038c8a9a5SSteve French if (wdata->mr) { 245138c8a9a5SSteve French smbd_deregister_mr(wdata->mr); 245238c8a9a5SSteve French wdata->mr = NULL; 245338c8a9a5SSteve French } 245438c8a9a5SSteve French #endif 245538c8a9a5SSteve French 245638c8a9a5SSteve French if (wdata->cfile) 245738c8a9a5SSteve French cifsFileInfo_put(wdata->cfile); 245838c8a9a5SSteve French 245938c8a9a5SSteve French kfree(wdata); 246038c8a9a5SSteve French } 246138c8a9a5SSteve French 246238c8a9a5SSteve French /* 246338c8a9a5SSteve French * Write failed with a retryable error. Resend the write request. It's also 246438c8a9a5SSteve French * possible that the page was redirtied so re-clean the page. 246538c8a9a5SSteve French */ 246638c8a9a5SSteve French static void 246738c8a9a5SSteve French cifs_writev_requeue(struct cifs_writedata *wdata) 246838c8a9a5SSteve French { 246938c8a9a5SSteve French int rc = 0; 247038c8a9a5SSteve French struct inode *inode = d_inode(wdata->cfile->dentry); 247138c8a9a5SSteve French struct TCP_Server_Info *server; 247238c8a9a5SSteve French unsigned int rest_len = wdata->bytes; 247338c8a9a5SSteve French loff_t fpos = wdata->offset; 247438c8a9a5SSteve French 247538c8a9a5SSteve French server = tlink_tcon(wdata->cfile->tlink)->ses->server; 247638c8a9a5SSteve French do { 247738c8a9a5SSteve French struct cifs_writedata *wdata2; 247838c8a9a5SSteve French unsigned int wsize, cur_len; 247938c8a9a5SSteve French 248038c8a9a5SSteve French wsize = server->ops->wp_retry_size(inode); 248138c8a9a5SSteve French if (wsize < rest_len) { 248238c8a9a5SSteve French if (wsize < PAGE_SIZE) { 248338c8a9a5SSteve French rc = -EOPNOTSUPP; 248438c8a9a5SSteve French break; 248538c8a9a5SSteve French } 248638c8a9a5SSteve French cur_len = min(round_down(wsize, PAGE_SIZE), rest_len); 248738c8a9a5SSteve French } else { 248838c8a9a5SSteve French cur_len = rest_len; 248938c8a9a5SSteve French } 249038c8a9a5SSteve French 249138c8a9a5SSteve French wdata2 = cifs_writedata_alloc(cifs_writev_complete); 249238c8a9a5SSteve French if (!wdata2) { 249338c8a9a5SSteve French rc = -ENOMEM; 249438c8a9a5SSteve French break; 249538c8a9a5SSteve French } 249638c8a9a5SSteve French 249738c8a9a5SSteve French wdata2->sync_mode = wdata->sync_mode; 249838c8a9a5SSteve French wdata2->offset = fpos; 249938c8a9a5SSteve French wdata2->bytes = cur_len; 250038c8a9a5SSteve French wdata2->iter = wdata->iter; 250138c8a9a5SSteve French 250238c8a9a5SSteve French iov_iter_advance(&wdata2->iter, fpos - wdata->offset); 250338c8a9a5SSteve French iov_iter_truncate(&wdata2->iter, wdata2->bytes); 250438c8a9a5SSteve French 250538c8a9a5SSteve French if (iov_iter_is_xarray(&wdata2->iter)) 250638c8a9a5SSteve French /* Check for pages having been redirtied and clean 250738c8a9a5SSteve French * them. We can do this by walking the xarray. If 250838c8a9a5SSteve French * it's not an xarray, then it's a DIO and we shouldn't 250938c8a9a5SSteve French * be mucking around with the page bits. 251038c8a9a5SSteve French */ 251138c8a9a5SSteve French cifs_undirty_folios(inode, fpos, cur_len); 251238c8a9a5SSteve French 251338c8a9a5SSteve French rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, 251438c8a9a5SSteve French &wdata2->cfile); 251538c8a9a5SSteve French if (!wdata2->cfile) { 251638c8a9a5SSteve French cifs_dbg(VFS, "No writable handle to retry writepages rc=%d\n", 251738c8a9a5SSteve French rc); 251838c8a9a5SSteve French if (!is_retryable_error(rc)) 251938c8a9a5SSteve French rc = -EBADF; 252038c8a9a5SSteve French } else { 252138c8a9a5SSteve French wdata2->pid = wdata2->cfile->pid; 252238c8a9a5SSteve French rc = server->ops->async_writev(wdata2, 252338c8a9a5SSteve French cifs_writedata_release); 252438c8a9a5SSteve French } 252538c8a9a5SSteve French 252638c8a9a5SSteve French kref_put(&wdata2->refcount, cifs_writedata_release); 252738c8a9a5SSteve French if (rc) { 252838c8a9a5SSteve French if (is_retryable_error(rc)) 252938c8a9a5SSteve French continue; 253038c8a9a5SSteve French fpos += cur_len; 253138c8a9a5SSteve French rest_len -= cur_len; 253238c8a9a5SSteve French break; 253338c8a9a5SSteve French } 253438c8a9a5SSteve French 253538c8a9a5SSteve French fpos += cur_len; 253638c8a9a5SSteve French rest_len -= cur_len; 253738c8a9a5SSteve French } while (rest_len > 0); 253838c8a9a5SSteve French 253938c8a9a5SSteve French /* Clean up remaining pages from the original wdata */ 254038c8a9a5SSteve French if (iov_iter_is_xarray(&wdata->iter)) 254138c8a9a5SSteve French cifs_pages_write_failed(inode, fpos, rest_len); 254238c8a9a5SSteve French 254338c8a9a5SSteve French if (rc != 0 && !is_retryable_error(rc)) 254438c8a9a5SSteve French mapping_set_error(inode->i_mapping, rc); 254538c8a9a5SSteve French kref_put(&wdata->refcount, cifs_writedata_release); 254638c8a9a5SSteve French } 254738c8a9a5SSteve French 254838c8a9a5SSteve French void 254938c8a9a5SSteve French cifs_writev_complete(struct work_struct *work) 255038c8a9a5SSteve French { 255138c8a9a5SSteve French struct cifs_writedata *wdata = container_of(work, 255238c8a9a5SSteve French struct cifs_writedata, work); 255338c8a9a5SSteve French struct inode *inode = d_inode(wdata->cfile->dentry); 255438c8a9a5SSteve French 255538c8a9a5SSteve French if (wdata->result == 0) { 255638c8a9a5SSteve French spin_lock(&inode->i_lock); 255738c8a9a5SSteve French cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes); 255838c8a9a5SSteve French spin_unlock(&inode->i_lock); 255938c8a9a5SSteve French cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink), 256038c8a9a5SSteve French wdata->bytes); 256138c8a9a5SSteve French } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN) 256238c8a9a5SSteve French return cifs_writev_requeue(wdata); 256338c8a9a5SSteve French 256438c8a9a5SSteve French if (wdata->result == -EAGAIN) 256538c8a9a5SSteve French cifs_pages_write_redirty(inode, wdata->offset, wdata->bytes); 256638c8a9a5SSteve French else if (wdata->result < 0) 256738c8a9a5SSteve French cifs_pages_write_failed(inode, wdata->offset, wdata->bytes); 256838c8a9a5SSteve French else 256938c8a9a5SSteve French cifs_pages_written_back(inode, wdata->offset, wdata->bytes); 257038c8a9a5SSteve French 257138c8a9a5SSteve French if (wdata->result != -EAGAIN) 257238c8a9a5SSteve French mapping_set_error(inode->i_mapping, wdata->result); 257338c8a9a5SSteve French kref_put(&wdata->refcount, cifs_writedata_release); 257438c8a9a5SSteve French } 257538c8a9a5SSteve French 257638c8a9a5SSteve French struct cifs_writedata *cifs_writedata_alloc(work_func_t complete) 257738c8a9a5SSteve French { 257838c8a9a5SSteve French struct cifs_writedata *wdata; 257938c8a9a5SSteve French 258038c8a9a5SSteve French wdata = kzalloc(sizeof(*wdata), GFP_NOFS); 258138c8a9a5SSteve French if (wdata != NULL) { 258238c8a9a5SSteve French kref_init(&wdata->refcount); 258338c8a9a5SSteve French INIT_LIST_HEAD(&wdata->list); 258438c8a9a5SSteve French init_completion(&wdata->done); 258538c8a9a5SSteve French INIT_WORK(&wdata->work, complete); 258638c8a9a5SSteve French } 258738c8a9a5SSteve French return wdata; 258838c8a9a5SSteve French } 258938c8a9a5SSteve French 259038c8a9a5SSteve French static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) 259138c8a9a5SSteve French { 259238c8a9a5SSteve French struct address_space *mapping = page->mapping; 259338c8a9a5SSteve French loff_t offset = (loff_t)page->index << PAGE_SHIFT; 259438c8a9a5SSteve French char *write_data; 259538c8a9a5SSteve French int rc = -EFAULT; 259638c8a9a5SSteve French int bytes_written = 0; 259738c8a9a5SSteve French struct inode *inode; 259838c8a9a5SSteve French struct cifsFileInfo *open_file; 259938c8a9a5SSteve French 260038c8a9a5SSteve French if (!mapping || !mapping->host) 260138c8a9a5SSteve French return -EFAULT; 260238c8a9a5SSteve French 260338c8a9a5SSteve French inode = page->mapping->host; 260438c8a9a5SSteve French 260538c8a9a5SSteve French offset += (loff_t)from; 260638c8a9a5SSteve French write_data = kmap(page); 260738c8a9a5SSteve French write_data += from; 260838c8a9a5SSteve French 260938c8a9a5SSteve French if ((to > PAGE_SIZE) || (from > to)) { 261038c8a9a5SSteve French kunmap(page); 261138c8a9a5SSteve French return -EIO; 261238c8a9a5SSteve French } 261338c8a9a5SSteve French 261438c8a9a5SSteve French /* racing with truncate? */ 261538c8a9a5SSteve French if (offset > mapping->host->i_size) { 261638c8a9a5SSteve French kunmap(page); 261738c8a9a5SSteve French return 0; /* don't care */ 261838c8a9a5SSteve French } 261938c8a9a5SSteve French 262038c8a9a5SSteve French /* check to make sure that we are not extending the file */ 262138c8a9a5SSteve French if (mapping->host->i_size - offset < (loff_t)to) 262238c8a9a5SSteve French to = (unsigned)(mapping->host->i_size - offset); 262338c8a9a5SSteve French 262438c8a9a5SSteve French rc = cifs_get_writable_file(CIFS_I(mapping->host), FIND_WR_ANY, 262538c8a9a5SSteve French &open_file); 262638c8a9a5SSteve French if (!rc) { 262738c8a9a5SSteve French bytes_written = cifs_write(open_file, open_file->pid, 262838c8a9a5SSteve French write_data, to - from, &offset); 262938c8a9a5SSteve French cifsFileInfo_put(open_file); 263038c8a9a5SSteve French /* Does mm or vfs already set times? */ 263123171df5SJeff Layton simple_inode_init_ts(inode); 263238c8a9a5SSteve French if ((bytes_written > 0) && (offset)) 263338c8a9a5SSteve French rc = 0; 263438c8a9a5SSteve French else if (bytes_written < 0) 263538c8a9a5SSteve French rc = bytes_written; 263638c8a9a5SSteve French else 263738c8a9a5SSteve French rc = -EFAULT; 263838c8a9a5SSteve French } else { 263938c8a9a5SSteve French cifs_dbg(FYI, "No writable handle for write page rc=%d\n", rc); 264038c8a9a5SSteve French if (!is_retryable_error(rc)) 264138c8a9a5SSteve French rc = -EIO; 264238c8a9a5SSteve French } 264338c8a9a5SSteve French 264438c8a9a5SSteve French kunmap(page); 264538c8a9a5SSteve French return rc; 264638c8a9a5SSteve French } 264738c8a9a5SSteve French 264838c8a9a5SSteve French /* 264938c8a9a5SSteve French * Extend the region to be written back to include subsequent contiguously 265038c8a9a5SSteve French * dirty pages if possible, but don't sleep while doing so. 265138c8a9a5SSteve French */ 265238c8a9a5SSteve French static void cifs_extend_writeback(struct address_space *mapping, 2653e45deec3SDavid Howells struct xa_state *xas, 265438c8a9a5SSteve French long *_count, 265538c8a9a5SSteve French loff_t start, 265638c8a9a5SSteve French int max_pages, 2657e45deec3SDavid Howells loff_t max_len, 2658e45deec3SDavid Howells size_t *_len) 265938c8a9a5SSteve French { 266038c8a9a5SSteve French struct folio_batch batch; 266138c8a9a5SSteve French struct folio *folio; 2662e45deec3SDavid Howells unsigned int nr_pages; 2663e45deec3SDavid Howells pgoff_t index = (start + *_len) / PAGE_SIZE; 2664e45deec3SDavid Howells size_t len; 266538c8a9a5SSteve French bool stop = true; 266638c8a9a5SSteve French unsigned int i; 266738c8a9a5SSteve French 266838c8a9a5SSteve French folio_batch_init(&batch); 266938c8a9a5SSteve French 267038c8a9a5SSteve French do { 267138c8a9a5SSteve French /* Firstly, we gather up a batch of contiguous dirty pages 267238c8a9a5SSteve French * under the RCU read lock - but we can't clear the dirty flags 267338c8a9a5SSteve French * there if any of those pages are mapped. 267438c8a9a5SSteve French */ 267538c8a9a5SSteve French rcu_read_lock(); 267638c8a9a5SSteve French 2677e45deec3SDavid Howells xas_for_each(xas, folio, ULONG_MAX) { 267838c8a9a5SSteve French stop = true; 2679e45deec3SDavid Howells if (xas_retry(xas, folio)) 268038c8a9a5SSteve French continue; 268138c8a9a5SSteve French if (xa_is_value(folio)) 268238c8a9a5SSteve French break; 2683e45deec3SDavid Howells if (folio->index != index) { 2684e45deec3SDavid Howells xas_reset(xas); 268538c8a9a5SSteve French break; 2686e45deec3SDavid Howells } 2687e45deec3SDavid Howells 268838c8a9a5SSteve French if (!folio_try_get_rcu(folio)) { 2689e45deec3SDavid Howells xas_reset(xas); 269038c8a9a5SSteve French continue; 269138c8a9a5SSteve French } 269238c8a9a5SSteve French nr_pages = folio_nr_pages(folio); 2693e45deec3SDavid Howells if (nr_pages > max_pages) { 2694e45deec3SDavid Howells xas_reset(xas); 269538c8a9a5SSteve French break; 2696e45deec3SDavid Howells } 269738c8a9a5SSteve French 269838c8a9a5SSteve French /* Has the page moved or been split? */ 2699e45deec3SDavid Howells if (unlikely(folio != xas_reload(xas))) { 270038c8a9a5SSteve French folio_put(folio); 2701e45deec3SDavid Howells xas_reset(xas); 270238c8a9a5SSteve French break; 270338c8a9a5SSteve French } 270438c8a9a5SSteve French 270538c8a9a5SSteve French if (!folio_trylock(folio)) { 270638c8a9a5SSteve French folio_put(folio); 2707e45deec3SDavid Howells xas_reset(xas); 270838c8a9a5SSteve French break; 270938c8a9a5SSteve French } 2710e45deec3SDavid Howells if (!folio_test_dirty(folio) || 2711e45deec3SDavid Howells folio_test_writeback(folio)) { 271238c8a9a5SSteve French folio_unlock(folio); 271338c8a9a5SSteve French folio_put(folio); 2714e45deec3SDavid Howells xas_reset(xas); 271538c8a9a5SSteve French break; 271638c8a9a5SSteve French } 271738c8a9a5SSteve French 271838c8a9a5SSteve French max_pages -= nr_pages; 2719e45deec3SDavid Howells len = folio_size(folio); 272038c8a9a5SSteve French stop = false; 272138c8a9a5SSteve French 272238c8a9a5SSteve French index += nr_pages; 2723e45deec3SDavid Howells *_count -= nr_pages; 2724e45deec3SDavid Howells *_len += len; 2725e45deec3SDavid Howells if (max_pages <= 0 || *_len >= max_len || *_count <= 0) 2726e45deec3SDavid Howells stop = true; 2727e45deec3SDavid Howells 272838c8a9a5SSteve French if (!folio_batch_add(&batch, folio)) 272938c8a9a5SSteve French break; 273038c8a9a5SSteve French if (stop) 273138c8a9a5SSteve French break; 273238c8a9a5SSteve French } 273338c8a9a5SSteve French 2734e45deec3SDavid Howells xas_pause(xas); 273538c8a9a5SSteve French rcu_read_unlock(); 273638c8a9a5SSteve French 273738c8a9a5SSteve French /* Now, if we obtained any pages, we can shift them to being 273838c8a9a5SSteve French * writable and mark them for caching. 273938c8a9a5SSteve French */ 274038c8a9a5SSteve French if (!folio_batch_count(&batch)) 274138c8a9a5SSteve French break; 274238c8a9a5SSteve French 274338c8a9a5SSteve French for (i = 0; i < folio_batch_count(&batch); i++) { 274438c8a9a5SSteve French folio = batch.folios[i]; 274538c8a9a5SSteve French /* The folio should be locked, dirty and not undergoing 274638c8a9a5SSteve French * writeback from the loop above. 274738c8a9a5SSteve French */ 274838c8a9a5SSteve French if (!folio_clear_dirty_for_io(folio)) 274938c8a9a5SSteve French WARN_ON(1); 27502e411c57SMatthew Wilcox (Oracle) folio_start_writeback(folio); 275138c8a9a5SSteve French folio_unlock(folio); 275238c8a9a5SSteve French } 275338c8a9a5SSteve French 275438c8a9a5SSteve French folio_batch_release(&batch); 275538c8a9a5SSteve French cond_resched(); 275638c8a9a5SSteve French } while (!stop); 275738c8a9a5SSteve French } 275838c8a9a5SSteve French 275938c8a9a5SSteve French /* 276038c8a9a5SSteve French * Write back the locked page and any subsequent non-locked dirty pages. 276138c8a9a5SSteve French */ 276238c8a9a5SSteve French static ssize_t cifs_write_back_from_locked_folio(struct address_space *mapping, 276338c8a9a5SSteve French struct writeback_control *wbc, 2764e45deec3SDavid Howells struct xa_state *xas, 276538c8a9a5SSteve French struct folio *folio, 2766e45deec3SDavid Howells unsigned long long start, 2767e45deec3SDavid Howells unsigned long long end) 276838c8a9a5SSteve French { 276938c8a9a5SSteve French struct inode *inode = mapping->host; 277038c8a9a5SSteve French struct TCP_Server_Info *server; 277138c8a9a5SSteve French struct cifs_writedata *wdata; 277238c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 277338c8a9a5SSteve French struct cifs_credits credits_on_stack; 277438c8a9a5SSteve French struct cifs_credits *credits = &credits_on_stack; 277538c8a9a5SSteve French struct cifsFileInfo *cfile = NULL; 2776e45deec3SDavid Howells unsigned long long i_size = i_size_read(inode), max_len; 2777e45deec3SDavid Howells unsigned int xid, wsize; 2778e45deec3SDavid Howells size_t len = folio_size(folio); 277938c8a9a5SSteve French long count = wbc->nr_to_write; 278038c8a9a5SSteve French int rc; 278138c8a9a5SSteve French 278238c8a9a5SSteve French /* The folio should be locked, dirty and not undergoing writeback. */ 2783e45deec3SDavid Howells if (!folio_clear_dirty_for_io(folio)) 2784e45deec3SDavid Howells WARN_ON_ONCE(1); 27852e411c57SMatthew Wilcox (Oracle) folio_start_writeback(folio); 278638c8a9a5SSteve French 278738c8a9a5SSteve French count -= folio_nr_pages(folio); 278838c8a9a5SSteve French 278938c8a9a5SSteve French xid = get_xid(); 279038c8a9a5SSteve French server = cifs_pick_channel(cifs_sb_master_tcon(cifs_sb)->ses); 279138c8a9a5SSteve French 279238c8a9a5SSteve French rc = cifs_get_writable_file(CIFS_I(inode), FIND_WR_ANY, &cfile); 279338c8a9a5SSteve French if (rc) { 279438c8a9a5SSteve French cifs_dbg(VFS, "No writable handle in writepages rc=%d\n", rc); 279538c8a9a5SSteve French goto err_xid; 279638c8a9a5SSteve French } 279738c8a9a5SSteve French 279838c8a9a5SSteve French rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->wsize, 279938c8a9a5SSteve French &wsize, credits); 280038c8a9a5SSteve French if (rc != 0) 280138c8a9a5SSteve French goto err_close; 280238c8a9a5SSteve French 280338c8a9a5SSteve French wdata = cifs_writedata_alloc(cifs_writev_complete); 280438c8a9a5SSteve French if (!wdata) { 280538c8a9a5SSteve French rc = -ENOMEM; 280638c8a9a5SSteve French goto err_uncredit; 280738c8a9a5SSteve French } 280838c8a9a5SSteve French 280938c8a9a5SSteve French wdata->sync_mode = wbc->sync_mode; 281038c8a9a5SSteve French wdata->offset = folio_pos(folio); 281138c8a9a5SSteve French wdata->pid = cfile->pid; 281238c8a9a5SSteve French wdata->credits = credits_on_stack; 281338c8a9a5SSteve French wdata->cfile = cfile; 281438c8a9a5SSteve French wdata->server = server; 281538c8a9a5SSteve French cfile = NULL; 281638c8a9a5SSteve French 2817e45deec3SDavid Howells /* Find all consecutive lockable dirty pages that have contiguous 2818e45deec3SDavid Howells * written regions, stopping when we find a page that is not 2819e45deec3SDavid Howells * immediately lockable, is not dirty or is missing, or we reach the 2820e45deec3SDavid Howells * end of the range. 282138c8a9a5SSteve French */ 282238c8a9a5SSteve French if (start < i_size) { 282338c8a9a5SSteve French /* Trim the write to the EOF; the extra data is ignored. Also 282438c8a9a5SSteve French * put an upper limit on the size of a single storedata op. 282538c8a9a5SSteve French */ 282638c8a9a5SSteve French max_len = wsize; 282738c8a9a5SSteve French max_len = min_t(unsigned long long, max_len, end - start + 1); 282838c8a9a5SSteve French max_len = min_t(unsigned long long, max_len, i_size - start); 282938c8a9a5SSteve French 283038c8a9a5SSteve French if (len < max_len) { 283138c8a9a5SSteve French int max_pages = INT_MAX; 283238c8a9a5SSteve French 283338c8a9a5SSteve French #ifdef CONFIG_CIFS_SMB_DIRECT 283438c8a9a5SSteve French if (server->smbd_conn) 283538c8a9a5SSteve French max_pages = server->smbd_conn->max_frmr_depth; 283638c8a9a5SSteve French #endif 283738c8a9a5SSteve French max_pages -= folio_nr_pages(folio); 283838c8a9a5SSteve French 283938c8a9a5SSteve French if (max_pages > 0) 2840e45deec3SDavid Howells cifs_extend_writeback(mapping, xas, &count, start, 284138c8a9a5SSteve French max_pages, max_len, &len); 284238c8a9a5SSteve French } 284338c8a9a5SSteve French } 2844e45deec3SDavid Howells len = min_t(unsigned long long, len, i_size - start); 284538c8a9a5SSteve French 284638c8a9a5SSteve French /* We now have a contiguous set of dirty pages, each with writeback 284738c8a9a5SSteve French * set; the first page is still locked at this point, but all the rest 284838c8a9a5SSteve French * have been unlocked. 284938c8a9a5SSteve French */ 285038c8a9a5SSteve French folio_unlock(folio); 2851e45deec3SDavid Howells wdata->bytes = len; 285238c8a9a5SSteve French 285338c8a9a5SSteve French if (start < i_size) { 285438c8a9a5SSteve French iov_iter_xarray(&wdata->iter, ITER_SOURCE, &mapping->i_pages, 285538c8a9a5SSteve French start, len); 285638c8a9a5SSteve French 285738c8a9a5SSteve French rc = adjust_credits(wdata->server, &wdata->credits, wdata->bytes); 285838c8a9a5SSteve French if (rc) 285938c8a9a5SSteve French goto err_wdata; 286038c8a9a5SSteve French 286138c8a9a5SSteve French if (wdata->cfile->invalidHandle) 286238c8a9a5SSteve French rc = -EAGAIN; 286338c8a9a5SSteve French else 286438c8a9a5SSteve French rc = wdata->server->ops->async_writev(wdata, 286538c8a9a5SSteve French cifs_writedata_release); 286638c8a9a5SSteve French if (rc >= 0) { 286738c8a9a5SSteve French kref_put(&wdata->refcount, cifs_writedata_release); 286838c8a9a5SSteve French goto err_close; 286938c8a9a5SSteve French } 287038c8a9a5SSteve French } else { 287138c8a9a5SSteve French /* The dirty region was entirely beyond the EOF. */ 287238c8a9a5SSteve French cifs_pages_written_back(inode, start, len); 287338c8a9a5SSteve French rc = 0; 287438c8a9a5SSteve French } 287538c8a9a5SSteve French 287638c8a9a5SSteve French err_wdata: 287738c8a9a5SSteve French kref_put(&wdata->refcount, cifs_writedata_release); 287838c8a9a5SSteve French err_uncredit: 287938c8a9a5SSteve French add_credits_and_wake_if(server, credits, 0); 288038c8a9a5SSteve French err_close: 288138c8a9a5SSteve French if (cfile) 288238c8a9a5SSteve French cifsFileInfo_put(cfile); 288338c8a9a5SSteve French err_xid: 288438c8a9a5SSteve French free_xid(xid); 288538c8a9a5SSteve French if (rc == 0) { 288638c8a9a5SSteve French wbc->nr_to_write = count; 288738c8a9a5SSteve French rc = len; 288838c8a9a5SSteve French } else if (is_retryable_error(rc)) { 288938c8a9a5SSteve French cifs_pages_write_redirty(inode, start, len); 289038c8a9a5SSteve French } else { 289138c8a9a5SSteve French cifs_pages_write_failed(inode, start, len); 289238c8a9a5SSteve French mapping_set_error(mapping, rc); 289338c8a9a5SSteve French } 289438c8a9a5SSteve French /* Indication to update ctime and mtime as close is deferred */ 289538c8a9a5SSteve French set_bit(CIFS_INO_MODIFIED_ATTR, &CIFS_I(inode)->flags); 289638c8a9a5SSteve French return rc; 289738c8a9a5SSteve French } 289838c8a9a5SSteve French 289938c8a9a5SSteve French /* 290038c8a9a5SSteve French * write a region of pages back to the server 290138c8a9a5SSteve French */ 2902e45deec3SDavid Howells static ssize_t cifs_writepages_begin(struct address_space *mapping, 290338c8a9a5SSteve French struct writeback_control *wbc, 2904e45deec3SDavid Howells struct xa_state *xas, 2905e45deec3SDavid Howells unsigned long long *_start, 2906e45deec3SDavid Howells unsigned long long end) 290738c8a9a5SSteve French { 2908e45deec3SDavid Howells struct folio *folio; 2909e45deec3SDavid Howells unsigned long long start = *_start; 2910e45deec3SDavid Howells ssize_t ret; 291138c8a9a5SSteve French int skips = 0; 291238c8a9a5SSteve French 2913e45deec3SDavid Howells search_again: 2914e45deec3SDavid Howells /* Find the first dirty page. */ 2915e45deec3SDavid Howells rcu_read_lock(); 291638c8a9a5SSteve French 2917e45deec3SDavid Howells for (;;) { 2918e45deec3SDavid Howells folio = xas_find_marked(xas, end / PAGE_SIZE, PAGECACHE_TAG_DIRTY); 2919e45deec3SDavid Howells if (xas_retry(xas, folio) || xa_is_value(folio)) 2920e45deec3SDavid Howells continue; 2921e45deec3SDavid Howells if (!folio) 292238c8a9a5SSteve French break; 292338c8a9a5SSteve French 2924e45deec3SDavid Howells if (!folio_try_get_rcu(folio)) { 2925e45deec3SDavid Howells xas_reset(xas); 2926e45deec3SDavid Howells continue; 2927e45deec3SDavid Howells } 292838c8a9a5SSteve French 2929e45deec3SDavid Howells if (unlikely(folio != xas_reload(xas))) { 2930e45deec3SDavid Howells folio_put(folio); 2931e45deec3SDavid Howells xas_reset(xas); 2932e45deec3SDavid Howells continue; 2933e45deec3SDavid Howells } 2934e45deec3SDavid Howells 2935e45deec3SDavid Howells xas_pause(xas); 2936e45deec3SDavid Howells break; 2937e45deec3SDavid Howells } 2938e45deec3SDavid Howells rcu_read_unlock(); 2939e45deec3SDavid Howells if (!folio) 2940e45deec3SDavid Howells return 0; 2941e45deec3SDavid Howells 294238c8a9a5SSteve French start = folio_pos(folio); /* May regress with THPs */ 294338c8a9a5SSteve French 2944e45deec3SDavid Howells /* At this point we hold neither the i_pages lock nor the page lock: 2945e45deec3SDavid Howells * the page may be truncated or invalidated (changing page->mapping to 2946e45deec3SDavid Howells * NULL), or even swizzled back from swapper_space to tmpfs file 2947e45deec3SDavid Howells * mapping 294838c8a9a5SSteve French */ 2949e45deec3SDavid Howells lock_again: 295038c8a9a5SSteve French if (wbc->sync_mode != WB_SYNC_NONE) { 295138c8a9a5SSteve French ret = folio_lock_killable(folio); 295238c8a9a5SSteve French if (ret < 0) 2953e45deec3SDavid Howells return ret; 295438c8a9a5SSteve French } else { 295538c8a9a5SSteve French if (!folio_trylock(folio)) 2956e45deec3SDavid Howells goto search_again; 295738c8a9a5SSteve French } 295838c8a9a5SSteve French 2959d3c79235SDavid Howells if (folio->mapping != mapping || 296038c8a9a5SSteve French !folio_test_dirty(folio)) { 296138c8a9a5SSteve French start += folio_size(folio); 296238c8a9a5SSteve French folio_unlock(folio); 2963e45deec3SDavid Howells goto search_again; 296438c8a9a5SSteve French } 296538c8a9a5SSteve French 296638c8a9a5SSteve French if (folio_test_writeback(folio) || 296738c8a9a5SSteve French folio_test_fscache(folio)) { 296838c8a9a5SSteve French folio_unlock(folio); 2969e45deec3SDavid Howells if (wbc->sync_mode != WB_SYNC_NONE) { 297038c8a9a5SSteve French folio_wait_writeback(folio); 297138c8a9a5SSteve French #ifdef CONFIG_CIFS_FSCACHE 297238c8a9a5SSteve French folio_wait_fscache(folio); 297338c8a9a5SSteve French #endif 2974e45deec3SDavid Howells goto lock_again; 297538c8a9a5SSteve French } 297638c8a9a5SSteve French 2977e45deec3SDavid Howells start += folio_size(folio); 2978e45deec3SDavid Howells if (wbc->sync_mode == WB_SYNC_NONE) { 297938c8a9a5SSteve French if (skips >= 5 || need_resched()) { 298038c8a9a5SSteve French ret = 0; 2981e45deec3SDavid Howells goto out; 298238c8a9a5SSteve French } 298338c8a9a5SSteve French skips++; 2984e45deec3SDavid Howells } 2985e45deec3SDavid Howells goto search_again; 298638c8a9a5SSteve French } 298738c8a9a5SSteve French 2988e45deec3SDavid Howells ret = cifs_write_back_from_locked_folio(mapping, wbc, xas, folio, start, end); 2989e45deec3SDavid Howells out: 2990e45deec3SDavid Howells if (ret > 0) 2991e45deec3SDavid Howells *_start = start + ret; 2992e45deec3SDavid Howells return ret; 2993e45deec3SDavid Howells } 299438c8a9a5SSteve French 2995e45deec3SDavid Howells /* 2996e45deec3SDavid Howells * Write a region of pages back to the server 2997e45deec3SDavid Howells */ 2998e45deec3SDavid Howells static int cifs_writepages_region(struct address_space *mapping, 2999e45deec3SDavid Howells struct writeback_control *wbc, 3000e45deec3SDavid Howells unsigned long long *_start, 3001e45deec3SDavid Howells unsigned long long end) 3002e45deec3SDavid Howells { 3003e45deec3SDavid Howells ssize_t ret; 3004e45deec3SDavid Howells 3005e45deec3SDavid Howells XA_STATE(xas, &mapping->i_pages, *_start / PAGE_SIZE); 3006e45deec3SDavid Howells 3007e45deec3SDavid Howells do { 3008e45deec3SDavid Howells ret = cifs_writepages_begin(mapping, wbc, &xas, _start, end); 3009e45deec3SDavid Howells if (ret > 0 && wbc->nr_to_write > 0) 3010e45deec3SDavid Howells cond_resched(); 3011e45deec3SDavid Howells } while (ret > 0 && wbc->nr_to_write > 0); 3012e45deec3SDavid Howells 3013e45deec3SDavid Howells return ret > 0 ? 0 : ret; 301438c8a9a5SSteve French } 301538c8a9a5SSteve French 301638c8a9a5SSteve French /* 301738c8a9a5SSteve French * Write some of the pending data back to the server 301838c8a9a5SSteve French */ 301938c8a9a5SSteve French static int cifs_writepages(struct address_space *mapping, 302038c8a9a5SSteve French struct writeback_control *wbc) 302138c8a9a5SSteve French { 3022e45deec3SDavid Howells loff_t start, end; 302338c8a9a5SSteve French int ret; 302438c8a9a5SSteve French 302538c8a9a5SSteve French /* We have to be careful as we can end up racing with setattr() 302638c8a9a5SSteve French * truncating the pagecache since the caller doesn't take a lock here 302738c8a9a5SSteve French * to prevent it. 302838c8a9a5SSteve French */ 302938c8a9a5SSteve French 3030e45deec3SDavid Howells if (wbc->range_cyclic && mapping->writeback_index) { 303138c8a9a5SSteve French start = mapping->writeback_index * PAGE_SIZE; 3032e45deec3SDavid Howells ret = cifs_writepages_region(mapping, wbc, &start, LLONG_MAX); 3033e45deec3SDavid Howells if (ret < 0) 3034e45deec3SDavid Howells goto out; 3035e45deec3SDavid Howells 3036e45deec3SDavid Howells if (wbc->nr_to_write <= 0) { 3037e45deec3SDavid Howells mapping->writeback_index = start / PAGE_SIZE; 3038e45deec3SDavid Howells goto out; 303938c8a9a5SSteve French } 304038c8a9a5SSteve French 3041e45deec3SDavid Howells start = 0; 3042e45deec3SDavid Howells end = mapping->writeback_index * PAGE_SIZE; 3043e45deec3SDavid Howells mapping->writeback_index = 0; 3044e45deec3SDavid Howells ret = cifs_writepages_region(mapping, wbc, &start, end); 3045e45deec3SDavid Howells if (ret == 0) 3046e45deec3SDavid Howells mapping->writeback_index = start / PAGE_SIZE; 3047e45deec3SDavid Howells } else if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) { 3048e45deec3SDavid Howells start = 0; 3049e45deec3SDavid Howells ret = cifs_writepages_region(mapping, wbc, &start, LLONG_MAX); 3050e45deec3SDavid Howells if (wbc->nr_to_write > 0 && ret == 0) 3051e45deec3SDavid Howells mapping->writeback_index = start / PAGE_SIZE; 3052e45deec3SDavid Howells } else { 3053e45deec3SDavid Howells start = wbc->range_start; 3054e45deec3SDavid Howells ret = cifs_writepages_region(mapping, wbc, &start, wbc->range_end); 3055e45deec3SDavid Howells } 3056e45deec3SDavid Howells 3057e45deec3SDavid Howells out: 305838c8a9a5SSteve French return ret; 305938c8a9a5SSteve French } 306038c8a9a5SSteve French 306138c8a9a5SSteve French static int 306238c8a9a5SSteve French cifs_writepage_locked(struct page *page, struct writeback_control *wbc) 306338c8a9a5SSteve French { 306438c8a9a5SSteve French int rc; 306538c8a9a5SSteve French unsigned int xid; 306638c8a9a5SSteve French 306738c8a9a5SSteve French xid = get_xid(); 306838c8a9a5SSteve French /* BB add check for wbc flags */ 306938c8a9a5SSteve French get_page(page); 307038c8a9a5SSteve French if (!PageUptodate(page)) 307138c8a9a5SSteve French cifs_dbg(FYI, "ppw - page not up to date\n"); 307238c8a9a5SSteve French 307338c8a9a5SSteve French /* 307438c8a9a5SSteve French * Set the "writeback" flag, and clear "dirty" in the radix tree. 307538c8a9a5SSteve French * 307638c8a9a5SSteve French * A writepage() implementation always needs to do either this, 307738c8a9a5SSteve French * or re-dirty the page with "redirty_page_for_writepage()" in 307838c8a9a5SSteve French * the case of a failure. 307938c8a9a5SSteve French * 308038c8a9a5SSteve French * Just unlocking the page will cause the radix tree tag-bits 308138c8a9a5SSteve French * to fail to update with the state of the page correctly. 308238c8a9a5SSteve French */ 308338c8a9a5SSteve French set_page_writeback(page); 308438c8a9a5SSteve French retry_write: 308538c8a9a5SSteve French rc = cifs_partialpagewrite(page, 0, PAGE_SIZE); 308638c8a9a5SSteve French if (is_retryable_error(rc)) { 308738c8a9a5SSteve French if (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN) 308838c8a9a5SSteve French goto retry_write; 308938c8a9a5SSteve French redirty_page_for_writepage(wbc, page); 309038c8a9a5SSteve French } else if (rc != 0) { 309138c8a9a5SSteve French SetPageError(page); 309238c8a9a5SSteve French mapping_set_error(page->mapping, rc); 309338c8a9a5SSteve French } else { 309438c8a9a5SSteve French SetPageUptodate(page); 309538c8a9a5SSteve French } 309638c8a9a5SSteve French end_page_writeback(page); 309738c8a9a5SSteve French put_page(page); 309838c8a9a5SSteve French free_xid(xid); 309938c8a9a5SSteve French return rc; 310038c8a9a5SSteve French } 310138c8a9a5SSteve French 310238c8a9a5SSteve French static int cifs_write_end(struct file *file, struct address_space *mapping, 310338c8a9a5SSteve French loff_t pos, unsigned len, unsigned copied, 310438c8a9a5SSteve French struct page *page, void *fsdata) 310538c8a9a5SSteve French { 310638c8a9a5SSteve French int rc; 310738c8a9a5SSteve French struct inode *inode = mapping->host; 310838c8a9a5SSteve French struct cifsFileInfo *cfile = file->private_data; 310938c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb); 311038c8a9a5SSteve French struct folio *folio = page_folio(page); 311138c8a9a5SSteve French __u32 pid; 311238c8a9a5SSteve French 311338c8a9a5SSteve French if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) 311438c8a9a5SSteve French pid = cfile->pid; 311538c8a9a5SSteve French else 311638c8a9a5SSteve French pid = current->tgid; 311738c8a9a5SSteve French 311838c8a9a5SSteve French cifs_dbg(FYI, "write_end for page %p from pos %lld with %d bytes\n", 311938c8a9a5SSteve French page, pos, copied); 312038c8a9a5SSteve French 312138c8a9a5SSteve French if (folio_test_checked(folio)) { 312238c8a9a5SSteve French if (copied == len) 312338c8a9a5SSteve French folio_mark_uptodate(folio); 312438c8a9a5SSteve French folio_clear_checked(folio); 312538c8a9a5SSteve French } else if (!folio_test_uptodate(folio) && copied == PAGE_SIZE) 312638c8a9a5SSteve French folio_mark_uptodate(folio); 312738c8a9a5SSteve French 312838c8a9a5SSteve French if (!folio_test_uptodate(folio)) { 312938c8a9a5SSteve French char *page_data; 313038c8a9a5SSteve French unsigned offset = pos & (PAGE_SIZE - 1); 313138c8a9a5SSteve French unsigned int xid; 313238c8a9a5SSteve French 313338c8a9a5SSteve French xid = get_xid(); 313438c8a9a5SSteve French /* this is probably better than directly calling 313538c8a9a5SSteve French partialpage_write since in this function the file handle is 313638c8a9a5SSteve French known which we might as well leverage */ 313738c8a9a5SSteve French /* BB check if anything else missing out of ppw 313838c8a9a5SSteve French such as updating last write time */ 313938c8a9a5SSteve French page_data = kmap(page); 314038c8a9a5SSteve French rc = cifs_write(cfile, pid, page_data + offset, copied, &pos); 314138c8a9a5SSteve French /* if (rc < 0) should we set writebehind rc? */ 314238c8a9a5SSteve French kunmap(page); 314338c8a9a5SSteve French 314438c8a9a5SSteve French free_xid(xid); 314538c8a9a5SSteve French } else { 314638c8a9a5SSteve French rc = copied; 314738c8a9a5SSteve French pos += copied; 314838c8a9a5SSteve French set_page_dirty(page); 314938c8a9a5SSteve French } 315038c8a9a5SSteve French 315138c8a9a5SSteve French if (rc > 0) { 315238c8a9a5SSteve French spin_lock(&inode->i_lock); 315338c8a9a5SSteve French if (pos > inode->i_size) { 315438c8a9a5SSteve French i_size_write(inode, pos); 315538c8a9a5SSteve French inode->i_blocks = (512 - 1 + pos) >> 9; 315638c8a9a5SSteve French } 315738c8a9a5SSteve French spin_unlock(&inode->i_lock); 315838c8a9a5SSteve French } 315938c8a9a5SSteve French 316038c8a9a5SSteve French unlock_page(page); 316138c8a9a5SSteve French put_page(page); 316238c8a9a5SSteve French /* Indication to update ctime and mtime as close is deferred */ 316338c8a9a5SSteve French set_bit(CIFS_INO_MODIFIED_ATTR, &CIFS_I(inode)->flags); 316438c8a9a5SSteve French 316538c8a9a5SSteve French return rc; 316638c8a9a5SSteve French } 316738c8a9a5SSteve French 316838c8a9a5SSteve French int cifs_strict_fsync(struct file *file, loff_t start, loff_t end, 316938c8a9a5SSteve French int datasync) 317038c8a9a5SSteve French { 317138c8a9a5SSteve French unsigned int xid; 317238c8a9a5SSteve French int rc = 0; 317338c8a9a5SSteve French struct cifs_tcon *tcon; 317438c8a9a5SSteve French struct TCP_Server_Info *server; 317538c8a9a5SSteve French struct cifsFileInfo *smbfile = file->private_data; 317638c8a9a5SSteve French struct inode *inode = file_inode(file); 317738c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 317838c8a9a5SSteve French 317938c8a9a5SSteve French rc = file_write_and_wait_range(file, start, end); 318038c8a9a5SSteve French if (rc) { 318138c8a9a5SSteve French trace_cifs_fsync_err(inode->i_ino, rc); 318238c8a9a5SSteve French return rc; 318338c8a9a5SSteve French } 318438c8a9a5SSteve French 318538c8a9a5SSteve French xid = get_xid(); 318638c8a9a5SSteve French 318738c8a9a5SSteve French cifs_dbg(FYI, "Sync file - name: %pD datasync: 0x%x\n", 318838c8a9a5SSteve French file, datasync); 318938c8a9a5SSteve French 319038c8a9a5SSteve French if (!CIFS_CACHE_READ(CIFS_I(inode))) { 319138c8a9a5SSteve French rc = cifs_zap_mapping(inode); 319238c8a9a5SSteve French if (rc) { 319338c8a9a5SSteve French cifs_dbg(FYI, "rc: %d during invalidate phase\n", rc); 319438c8a9a5SSteve French rc = 0; /* don't care about it in fsync */ 319538c8a9a5SSteve French } 319638c8a9a5SSteve French } 319738c8a9a5SSteve French 319838c8a9a5SSteve French tcon = tlink_tcon(smbfile->tlink); 319938c8a9a5SSteve French if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { 320038c8a9a5SSteve French server = tcon->ses->server; 320138c8a9a5SSteve French if (server->ops->flush == NULL) { 320238c8a9a5SSteve French rc = -ENOSYS; 320338c8a9a5SSteve French goto strict_fsync_exit; 320438c8a9a5SSteve French } 320538c8a9a5SSteve French 320638c8a9a5SSteve French if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) { 320738c8a9a5SSteve French smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY); 320838c8a9a5SSteve French if (smbfile) { 320938c8a9a5SSteve French rc = server->ops->flush(xid, tcon, &smbfile->fid); 321038c8a9a5SSteve French cifsFileInfo_put(smbfile); 321138c8a9a5SSteve French } else 321238c8a9a5SSteve French cifs_dbg(FYI, "ignore fsync for file not open for write\n"); 321338c8a9a5SSteve French } else 321438c8a9a5SSteve French rc = server->ops->flush(xid, tcon, &smbfile->fid); 321538c8a9a5SSteve French } 321638c8a9a5SSteve French 321738c8a9a5SSteve French strict_fsync_exit: 321838c8a9a5SSteve French free_xid(xid); 321938c8a9a5SSteve French return rc; 322038c8a9a5SSteve French } 322138c8a9a5SSteve French 322238c8a9a5SSteve French int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync) 322338c8a9a5SSteve French { 322438c8a9a5SSteve French unsigned int xid; 322538c8a9a5SSteve French int rc = 0; 322638c8a9a5SSteve French struct cifs_tcon *tcon; 322738c8a9a5SSteve French struct TCP_Server_Info *server; 322838c8a9a5SSteve French struct cifsFileInfo *smbfile = file->private_data; 322938c8a9a5SSteve French struct inode *inode = file_inode(file); 323038c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(file); 323138c8a9a5SSteve French 323238c8a9a5SSteve French rc = file_write_and_wait_range(file, start, end); 323338c8a9a5SSteve French if (rc) { 323438c8a9a5SSteve French trace_cifs_fsync_err(file_inode(file)->i_ino, rc); 323538c8a9a5SSteve French return rc; 323638c8a9a5SSteve French } 323738c8a9a5SSteve French 323838c8a9a5SSteve French xid = get_xid(); 323938c8a9a5SSteve French 324038c8a9a5SSteve French cifs_dbg(FYI, "Sync file - name: %pD datasync: 0x%x\n", 324138c8a9a5SSteve French file, datasync); 324238c8a9a5SSteve French 324338c8a9a5SSteve French tcon = tlink_tcon(smbfile->tlink); 324438c8a9a5SSteve French if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) { 324538c8a9a5SSteve French server = tcon->ses->server; 324638c8a9a5SSteve French if (server->ops->flush == NULL) { 324738c8a9a5SSteve French rc = -ENOSYS; 324838c8a9a5SSteve French goto fsync_exit; 324938c8a9a5SSteve French } 325038c8a9a5SSteve French 325138c8a9a5SSteve French if ((OPEN_FMODE(smbfile->f_flags) & FMODE_WRITE) == 0) { 325238c8a9a5SSteve French smbfile = find_writable_file(CIFS_I(inode), FIND_WR_ANY); 325338c8a9a5SSteve French if (smbfile) { 325438c8a9a5SSteve French rc = server->ops->flush(xid, tcon, &smbfile->fid); 325538c8a9a5SSteve French cifsFileInfo_put(smbfile); 325638c8a9a5SSteve French } else 325738c8a9a5SSteve French cifs_dbg(FYI, "ignore fsync for file not open for write\n"); 325838c8a9a5SSteve French } else 325938c8a9a5SSteve French rc = server->ops->flush(xid, tcon, &smbfile->fid); 326038c8a9a5SSteve French } 326138c8a9a5SSteve French 326238c8a9a5SSteve French fsync_exit: 326338c8a9a5SSteve French free_xid(xid); 326438c8a9a5SSteve French return rc; 326538c8a9a5SSteve French } 326638c8a9a5SSteve French 326738c8a9a5SSteve French /* 326838c8a9a5SSteve French * As file closes, flush all cached write data for this inode checking 326938c8a9a5SSteve French * for write behind errors. 327038c8a9a5SSteve French */ 327138c8a9a5SSteve French int cifs_flush(struct file *file, fl_owner_t id) 327238c8a9a5SSteve French { 327338c8a9a5SSteve French struct inode *inode = file_inode(file); 327438c8a9a5SSteve French int rc = 0; 327538c8a9a5SSteve French 327638c8a9a5SSteve French if (file->f_mode & FMODE_WRITE) 327738c8a9a5SSteve French rc = filemap_write_and_wait(inode->i_mapping); 327838c8a9a5SSteve French 327938c8a9a5SSteve French cifs_dbg(FYI, "Flush inode %p file %p rc %d\n", inode, file, rc); 328038c8a9a5SSteve French if (rc) { 328138c8a9a5SSteve French /* get more nuanced writeback errors */ 328238c8a9a5SSteve French rc = filemap_check_wb_err(file->f_mapping, 0); 328338c8a9a5SSteve French trace_cifs_flush_err(inode->i_ino, rc); 328438c8a9a5SSteve French } 328538c8a9a5SSteve French return rc; 328638c8a9a5SSteve French } 328738c8a9a5SSteve French 328838c8a9a5SSteve French static void 328938c8a9a5SSteve French cifs_uncached_writedata_release(struct kref *refcount) 329038c8a9a5SSteve French { 329138c8a9a5SSteve French struct cifs_writedata *wdata = container_of(refcount, 329238c8a9a5SSteve French struct cifs_writedata, refcount); 329338c8a9a5SSteve French 329438c8a9a5SSteve French kref_put(&wdata->ctx->refcount, cifs_aio_ctx_release); 329538c8a9a5SSteve French cifs_writedata_release(refcount); 329638c8a9a5SSteve French } 329738c8a9a5SSteve French 329838c8a9a5SSteve French static void collect_uncached_write_data(struct cifs_aio_ctx *ctx); 329938c8a9a5SSteve French 330038c8a9a5SSteve French static void 330138c8a9a5SSteve French cifs_uncached_writev_complete(struct work_struct *work) 330238c8a9a5SSteve French { 330338c8a9a5SSteve French struct cifs_writedata *wdata = container_of(work, 330438c8a9a5SSteve French struct cifs_writedata, work); 330538c8a9a5SSteve French struct inode *inode = d_inode(wdata->cfile->dentry); 330638c8a9a5SSteve French struct cifsInodeInfo *cifsi = CIFS_I(inode); 330738c8a9a5SSteve French 330838c8a9a5SSteve French spin_lock(&inode->i_lock); 330938c8a9a5SSteve French cifs_update_eof(cifsi, wdata->offset, wdata->bytes); 331038c8a9a5SSteve French if (cifsi->server_eof > inode->i_size) 331138c8a9a5SSteve French i_size_write(inode, cifsi->server_eof); 331238c8a9a5SSteve French spin_unlock(&inode->i_lock); 331338c8a9a5SSteve French 331438c8a9a5SSteve French complete(&wdata->done); 331538c8a9a5SSteve French collect_uncached_write_data(wdata->ctx); 331638c8a9a5SSteve French /* the below call can possibly free the last ref to aio ctx */ 331738c8a9a5SSteve French kref_put(&wdata->refcount, cifs_uncached_writedata_release); 331838c8a9a5SSteve French } 331938c8a9a5SSteve French 332038c8a9a5SSteve French static int 332138c8a9a5SSteve French cifs_resend_wdata(struct cifs_writedata *wdata, struct list_head *wdata_list, 332238c8a9a5SSteve French struct cifs_aio_ctx *ctx) 332338c8a9a5SSteve French { 332438c8a9a5SSteve French unsigned int wsize; 332538c8a9a5SSteve French struct cifs_credits credits; 332638c8a9a5SSteve French int rc; 332738c8a9a5SSteve French struct TCP_Server_Info *server = wdata->server; 332838c8a9a5SSteve French 332938c8a9a5SSteve French do { 333038c8a9a5SSteve French if (wdata->cfile->invalidHandle) { 333138c8a9a5SSteve French rc = cifs_reopen_file(wdata->cfile, false); 333238c8a9a5SSteve French if (rc == -EAGAIN) 333338c8a9a5SSteve French continue; 333438c8a9a5SSteve French else if (rc) 333538c8a9a5SSteve French break; 333638c8a9a5SSteve French } 333738c8a9a5SSteve French 333838c8a9a5SSteve French 333938c8a9a5SSteve French /* 334038c8a9a5SSteve French * Wait for credits to resend this wdata. 334138c8a9a5SSteve French * Note: we are attempting to resend the whole wdata not in 334238c8a9a5SSteve French * segments 334338c8a9a5SSteve French */ 334438c8a9a5SSteve French do { 334538c8a9a5SSteve French rc = server->ops->wait_mtu_credits(server, wdata->bytes, 334638c8a9a5SSteve French &wsize, &credits); 334738c8a9a5SSteve French if (rc) 334838c8a9a5SSteve French goto fail; 334938c8a9a5SSteve French 335038c8a9a5SSteve French if (wsize < wdata->bytes) { 335138c8a9a5SSteve French add_credits_and_wake_if(server, &credits, 0); 335238c8a9a5SSteve French msleep(1000); 335338c8a9a5SSteve French } 335438c8a9a5SSteve French } while (wsize < wdata->bytes); 335538c8a9a5SSteve French wdata->credits = credits; 335638c8a9a5SSteve French 335738c8a9a5SSteve French rc = adjust_credits(server, &wdata->credits, wdata->bytes); 335838c8a9a5SSteve French 335938c8a9a5SSteve French if (!rc) { 336038c8a9a5SSteve French if (wdata->cfile->invalidHandle) 336138c8a9a5SSteve French rc = -EAGAIN; 336238c8a9a5SSteve French else { 336338c8a9a5SSteve French #ifdef CONFIG_CIFS_SMB_DIRECT 336438c8a9a5SSteve French if (wdata->mr) { 336538c8a9a5SSteve French wdata->mr->need_invalidate = true; 336638c8a9a5SSteve French smbd_deregister_mr(wdata->mr); 336738c8a9a5SSteve French wdata->mr = NULL; 336838c8a9a5SSteve French } 336938c8a9a5SSteve French #endif 337038c8a9a5SSteve French rc = server->ops->async_writev(wdata, 337138c8a9a5SSteve French cifs_uncached_writedata_release); 337238c8a9a5SSteve French } 337338c8a9a5SSteve French } 337438c8a9a5SSteve French 337538c8a9a5SSteve French /* If the write was successfully sent, we are done */ 337638c8a9a5SSteve French if (!rc) { 337738c8a9a5SSteve French list_add_tail(&wdata->list, wdata_list); 337838c8a9a5SSteve French return 0; 337938c8a9a5SSteve French } 338038c8a9a5SSteve French 338138c8a9a5SSteve French /* Roll back credits and retry if needed */ 338238c8a9a5SSteve French add_credits_and_wake_if(server, &wdata->credits, 0); 338338c8a9a5SSteve French } while (rc == -EAGAIN); 338438c8a9a5SSteve French 338538c8a9a5SSteve French fail: 338638c8a9a5SSteve French kref_put(&wdata->refcount, cifs_uncached_writedata_release); 338738c8a9a5SSteve French return rc; 338838c8a9a5SSteve French } 338938c8a9a5SSteve French 339038c8a9a5SSteve French /* 339138c8a9a5SSteve French * Select span of a bvec iterator we're going to use. Limit it by both maximum 339238c8a9a5SSteve French * size and maximum number of segments. 339338c8a9a5SSteve French */ 339438c8a9a5SSteve French static size_t cifs_limit_bvec_subset(const struct iov_iter *iter, size_t max_size, 339538c8a9a5SSteve French size_t max_segs, unsigned int *_nsegs) 339638c8a9a5SSteve French { 339738c8a9a5SSteve French const struct bio_vec *bvecs = iter->bvec; 339838c8a9a5SSteve French unsigned int nbv = iter->nr_segs, ix = 0, nsegs = 0; 339938c8a9a5SSteve French size_t len, span = 0, n = iter->count; 340038c8a9a5SSteve French size_t skip = iter->iov_offset; 340138c8a9a5SSteve French 340238c8a9a5SSteve French if (WARN_ON(!iov_iter_is_bvec(iter)) || n == 0) 340338c8a9a5SSteve French return 0; 340438c8a9a5SSteve French 340538c8a9a5SSteve French while (n && ix < nbv && skip) { 340638c8a9a5SSteve French len = bvecs[ix].bv_len; 340738c8a9a5SSteve French if (skip < len) 340838c8a9a5SSteve French break; 340938c8a9a5SSteve French skip -= len; 341038c8a9a5SSteve French n -= len; 341138c8a9a5SSteve French ix++; 341238c8a9a5SSteve French } 341338c8a9a5SSteve French 341438c8a9a5SSteve French while (n && ix < nbv) { 341538c8a9a5SSteve French len = min3(n, bvecs[ix].bv_len - skip, max_size); 341638c8a9a5SSteve French span += len; 341738c8a9a5SSteve French max_size -= len; 341838c8a9a5SSteve French nsegs++; 341938c8a9a5SSteve French ix++; 342038c8a9a5SSteve French if (max_size == 0 || nsegs >= max_segs) 342138c8a9a5SSteve French break; 342238c8a9a5SSteve French skip = 0; 342338c8a9a5SSteve French n -= len; 342438c8a9a5SSteve French } 342538c8a9a5SSteve French 342638c8a9a5SSteve French *_nsegs = nsegs; 342738c8a9a5SSteve French return span; 342838c8a9a5SSteve French } 342938c8a9a5SSteve French 343038c8a9a5SSteve French static int 343138c8a9a5SSteve French cifs_write_from_iter(loff_t fpos, size_t len, struct iov_iter *from, 343238c8a9a5SSteve French struct cifsFileInfo *open_file, 343338c8a9a5SSteve French struct cifs_sb_info *cifs_sb, struct list_head *wdata_list, 343438c8a9a5SSteve French struct cifs_aio_ctx *ctx) 343538c8a9a5SSteve French { 343638c8a9a5SSteve French int rc = 0; 343738c8a9a5SSteve French size_t cur_len, max_len; 343838c8a9a5SSteve French struct cifs_writedata *wdata; 343938c8a9a5SSteve French pid_t pid; 344038c8a9a5SSteve French struct TCP_Server_Info *server; 344138c8a9a5SSteve French unsigned int xid, max_segs = INT_MAX; 344238c8a9a5SSteve French 344338c8a9a5SSteve French if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) 344438c8a9a5SSteve French pid = open_file->pid; 344538c8a9a5SSteve French else 344638c8a9a5SSteve French pid = current->tgid; 344738c8a9a5SSteve French 344838c8a9a5SSteve French server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses); 344938c8a9a5SSteve French xid = get_xid(); 345038c8a9a5SSteve French 345138c8a9a5SSteve French #ifdef CONFIG_CIFS_SMB_DIRECT 345238c8a9a5SSteve French if (server->smbd_conn) 345338c8a9a5SSteve French max_segs = server->smbd_conn->max_frmr_depth; 345438c8a9a5SSteve French #endif 345538c8a9a5SSteve French 345638c8a9a5SSteve French do { 345738c8a9a5SSteve French struct cifs_credits credits_on_stack; 345838c8a9a5SSteve French struct cifs_credits *credits = &credits_on_stack; 345938c8a9a5SSteve French unsigned int wsize, nsegs = 0; 346038c8a9a5SSteve French 346138c8a9a5SSteve French if (signal_pending(current)) { 346238c8a9a5SSteve French rc = -EINTR; 346338c8a9a5SSteve French break; 346438c8a9a5SSteve French } 346538c8a9a5SSteve French 346638c8a9a5SSteve French if (open_file->invalidHandle) { 346738c8a9a5SSteve French rc = cifs_reopen_file(open_file, false); 346838c8a9a5SSteve French if (rc == -EAGAIN) 346938c8a9a5SSteve French continue; 347038c8a9a5SSteve French else if (rc) 347138c8a9a5SSteve French break; 347238c8a9a5SSteve French } 347338c8a9a5SSteve French 347438c8a9a5SSteve French rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->wsize, 347538c8a9a5SSteve French &wsize, credits); 347638c8a9a5SSteve French if (rc) 347738c8a9a5SSteve French break; 347838c8a9a5SSteve French 347938c8a9a5SSteve French max_len = min_t(const size_t, len, wsize); 348038c8a9a5SSteve French if (!max_len) { 348138c8a9a5SSteve French rc = -EAGAIN; 348238c8a9a5SSteve French add_credits_and_wake_if(server, credits, 0); 348338c8a9a5SSteve French break; 348438c8a9a5SSteve French } 348538c8a9a5SSteve French 348638c8a9a5SSteve French cur_len = cifs_limit_bvec_subset(from, max_len, max_segs, &nsegs); 348738c8a9a5SSteve French cifs_dbg(FYI, "write_from_iter len=%zx/%zx nsegs=%u/%lu/%u\n", 348838c8a9a5SSteve French cur_len, max_len, nsegs, from->nr_segs, max_segs); 348938c8a9a5SSteve French if (cur_len == 0) { 349038c8a9a5SSteve French rc = -EIO; 349138c8a9a5SSteve French add_credits_and_wake_if(server, credits, 0); 349238c8a9a5SSteve French break; 349338c8a9a5SSteve French } 349438c8a9a5SSteve French 349538c8a9a5SSteve French wdata = cifs_writedata_alloc(cifs_uncached_writev_complete); 349638c8a9a5SSteve French if (!wdata) { 349738c8a9a5SSteve French rc = -ENOMEM; 349838c8a9a5SSteve French add_credits_and_wake_if(server, credits, 0); 349938c8a9a5SSteve French break; 350038c8a9a5SSteve French } 350138c8a9a5SSteve French 350238c8a9a5SSteve French wdata->sync_mode = WB_SYNC_ALL; 350338c8a9a5SSteve French wdata->offset = (__u64)fpos; 350438c8a9a5SSteve French wdata->cfile = cifsFileInfo_get(open_file); 350538c8a9a5SSteve French wdata->server = server; 350638c8a9a5SSteve French wdata->pid = pid; 350738c8a9a5SSteve French wdata->bytes = cur_len; 350838c8a9a5SSteve French wdata->credits = credits_on_stack; 350938c8a9a5SSteve French wdata->iter = *from; 351038c8a9a5SSteve French wdata->ctx = ctx; 351138c8a9a5SSteve French kref_get(&ctx->refcount); 351238c8a9a5SSteve French 351338c8a9a5SSteve French iov_iter_truncate(&wdata->iter, cur_len); 351438c8a9a5SSteve French 351538c8a9a5SSteve French rc = adjust_credits(server, &wdata->credits, wdata->bytes); 351638c8a9a5SSteve French 351738c8a9a5SSteve French if (!rc) { 351838c8a9a5SSteve French if (wdata->cfile->invalidHandle) 351938c8a9a5SSteve French rc = -EAGAIN; 352038c8a9a5SSteve French else 352138c8a9a5SSteve French rc = server->ops->async_writev(wdata, 352238c8a9a5SSteve French cifs_uncached_writedata_release); 352338c8a9a5SSteve French } 352438c8a9a5SSteve French 352538c8a9a5SSteve French if (rc) { 352638c8a9a5SSteve French add_credits_and_wake_if(server, &wdata->credits, 0); 352738c8a9a5SSteve French kref_put(&wdata->refcount, 352838c8a9a5SSteve French cifs_uncached_writedata_release); 352938c8a9a5SSteve French if (rc == -EAGAIN) 353038c8a9a5SSteve French continue; 353138c8a9a5SSteve French break; 353238c8a9a5SSteve French } 353338c8a9a5SSteve French 353438c8a9a5SSteve French list_add_tail(&wdata->list, wdata_list); 353538c8a9a5SSteve French iov_iter_advance(from, cur_len); 353638c8a9a5SSteve French fpos += cur_len; 353738c8a9a5SSteve French len -= cur_len; 353838c8a9a5SSteve French } while (len > 0); 353938c8a9a5SSteve French 354038c8a9a5SSteve French free_xid(xid); 354138c8a9a5SSteve French return rc; 354238c8a9a5SSteve French } 354338c8a9a5SSteve French 354438c8a9a5SSteve French static void collect_uncached_write_data(struct cifs_aio_ctx *ctx) 354538c8a9a5SSteve French { 354638c8a9a5SSteve French struct cifs_writedata *wdata, *tmp; 354738c8a9a5SSteve French struct cifs_tcon *tcon; 354838c8a9a5SSteve French struct cifs_sb_info *cifs_sb; 354938c8a9a5SSteve French struct dentry *dentry = ctx->cfile->dentry; 355038c8a9a5SSteve French ssize_t rc; 355138c8a9a5SSteve French 355238c8a9a5SSteve French tcon = tlink_tcon(ctx->cfile->tlink); 355338c8a9a5SSteve French cifs_sb = CIFS_SB(dentry->d_sb); 355438c8a9a5SSteve French 355538c8a9a5SSteve French mutex_lock(&ctx->aio_mutex); 355638c8a9a5SSteve French 355738c8a9a5SSteve French if (list_empty(&ctx->list)) { 355838c8a9a5SSteve French mutex_unlock(&ctx->aio_mutex); 355938c8a9a5SSteve French return; 356038c8a9a5SSteve French } 356138c8a9a5SSteve French 356238c8a9a5SSteve French rc = ctx->rc; 356338c8a9a5SSteve French /* 356438c8a9a5SSteve French * Wait for and collect replies for any successful sends in order of 356538c8a9a5SSteve French * increasing offset. Once an error is hit, then return without waiting 356638c8a9a5SSteve French * for any more replies. 356738c8a9a5SSteve French */ 356838c8a9a5SSteve French restart_loop: 356938c8a9a5SSteve French list_for_each_entry_safe(wdata, tmp, &ctx->list, list) { 357038c8a9a5SSteve French if (!rc) { 357138c8a9a5SSteve French if (!try_wait_for_completion(&wdata->done)) { 357238c8a9a5SSteve French mutex_unlock(&ctx->aio_mutex); 357338c8a9a5SSteve French return; 357438c8a9a5SSteve French } 357538c8a9a5SSteve French 357638c8a9a5SSteve French if (wdata->result) 357738c8a9a5SSteve French rc = wdata->result; 357838c8a9a5SSteve French else 357938c8a9a5SSteve French ctx->total_len += wdata->bytes; 358038c8a9a5SSteve French 358138c8a9a5SSteve French /* resend call if it's a retryable error */ 358238c8a9a5SSteve French if (rc == -EAGAIN) { 358338c8a9a5SSteve French struct list_head tmp_list; 358438c8a9a5SSteve French struct iov_iter tmp_from = ctx->iter; 358538c8a9a5SSteve French 358638c8a9a5SSteve French INIT_LIST_HEAD(&tmp_list); 358738c8a9a5SSteve French list_del_init(&wdata->list); 358838c8a9a5SSteve French 358938c8a9a5SSteve French if (ctx->direct_io) 359038c8a9a5SSteve French rc = cifs_resend_wdata( 359138c8a9a5SSteve French wdata, &tmp_list, ctx); 359238c8a9a5SSteve French else { 359338c8a9a5SSteve French iov_iter_advance(&tmp_from, 359438c8a9a5SSteve French wdata->offset - ctx->pos); 359538c8a9a5SSteve French 359638c8a9a5SSteve French rc = cifs_write_from_iter(wdata->offset, 359738c8a9a5SSteve French wdata->bytes, &tmp_from, 359838c8a9a5SSteve French ctx->cfile, cifs_sb, &tmp_list, 359938c8a9a5SSteve French ctx); 360038c8a9a5SSteve French 360138c8a9a5SSteve French kref_put(&wdata->refcount, 360238c8a9a5SSteve French cifs_uncached_writedata_release); 360338c8a9a5SSteve French } 360438c8a9a5SSteve French 360538c8a9a5SSteve French list_splice(&tmp_list, &ctx->list); 360638c8a9a5SSteve French goto restart_loop; 360738c8a9a5SSteve French } 360838c8a9a5SSteve French } 360938c8a9a5SSteve French list_del_init(&wdata->list); 361038c8a9a5SSteve French kref_put(&wdata->refcount, cifs_uncached_writedata_release); 361138c8a9a5SSteve French } 361238c8a9a5SSteve French 361338c8a9a5SSteve French cifs_stats_bytes_written(tcon, ctx->total_len); 361438c8a9a5SSteve French set_bit(CIFS_INO_INVALID_MAPPING, &CIFS_I(dentry->d_inode)->flags); 361538c8a9a5SSteve French 361638c8a9a5SSteve French ctx->rc = (rc == 0) ? ctx->total_len : rc; 361738c8a9a5SSteve French 361838c8a9a5SSteve French mutex_unlock(&ctx->aio_mutex); 361938c8a9a5SSteve French 362038c8a9a5SSteve French if (ctx->iocb && ctx->iocb->ki_complete) 362138c8a9a5SSteve French ctx->iocb->ki_complete(ctx->iocb, ctx->rc); 362238c8a9a5SSteve French else 362338c8a9a5SSteve French complete(&ctx->done); 362438c8a9a5SSteve French } 362538c8a9a5SSteve French 362638c8a9a5SSteve French static ssize_t __cifs_writev( 362738c8a9a5SSteve French struct kiocb *iocb, struct iov_iter *from, bool direct) 362838c8a9a5SSteve French { 362938c8a9a5SSteve French struct file *file = iocb->ki_filp; 363038c8a9a5SSteve French ssize_t total_written = 0; 363138c8a9a5SSteve French struct cifsFileInfo *cfile; 363238c8a9a5SSteve French struct cifs_tcon *tcon; 363338c8a9a5SSteve French struct cifs_sb_info *cifs_sb; 363438c8a9a5SSteve French struct cifs_aio_ctx *ctx; 363538c8a9a5SSteve French int rc; 363638c8a9a5SSteve French 363738c8a9a5SSteve French rc = generic_write_checks(iocb, from); 363838c8a9a5SSteve French if (rc <= 0) 363938c8a9a5SSteve French return rc; 364038c8a9a5SSteve French 364138c8a9a5SSteve French cifs_sb = CIFS_FILE_SB(file); 364238c8a9a5SSteve French cfile = file->private_data; 364338c8a9a5SSteve French tcon = tlink_tcon(cfile->tlink); 364438c8a9a5SSteve French 364538c8a9a5SSteve French if (!tcon->ses->server->ops->async_writev) 364638c8a9a5SSteve French return -ENOSYS; 364738c8a9a5SSteve French 364838c8a9a5SSteve French ctx = cifs_aio_ctx_alloc(); 364938c8a9a5SSteve French if (!ctx) 365038c8a9a5SSteve French return -ENOMEM; 365138c8a9a5SSteve French 365238c8a9a5SSteve French ctx->cfile = cifsFileInfo_get(cfile); 365338c8a9a5SSteve French 365438c8a9a5SSteve French if (!is_sync_kiocb(iocb)) 365538c8a9a5SSteve French ctx->iocb = iocb; 365638c8a9a5SSteve French 365738c8a9a5SSteve French ctx->pos = iocb->ki_pos; 365838c8a9a5SSteve French ctx->direct_io = direct; 365938c8a9a5SSteve French ctx->nr_pinned_pages = 0; 366038c8a9a5SSteve French 366138c8a9a5SSteve French if (user_backed_iter(from)) { 366238c8a9a5SSteve French /* 366338c8a9a5SSteve French * Extract IOVEC/UBUF-type iterators to a BVEC-type iterator as 366438c8a9a5SSteve French * they contain references to the calling process's virtual 366538c8a9a5SSteve French * memory layout which won't be available in an async worker 366638c8a9a5SSteve French * thread. This also takes a pin on every folio involved. 366738c8a9a5SSteve French */ 366838c8a9a5SSteve French rc = netfs_extract_user_iter(from, iov_iter_count(from), 366938c8a9a5SSteve French &ctx->iter, 0); 367038c8a9a5SSteve French if (rc < 0) { 367138c8a9a5SSteve French kref_put(&ctx->refcount, cifs_aio_ctx_release); 367238c8a9a5SSteve French return rc; 367338c8a9a5SSteve French } 367438c8a9a5SSteve French 367538c8a9a5SSteve French ctx->nr_pinned_pages = rc; 367638c8a9a5SSteve French ctx->bv = (void *)ctx->iter.bvec; 367738c8a9a5SSteve French ctx->bv_need_unpin = iov_iter_extract_will_pin(from); 367838c8a9a5SSteve French } else if ((iov_iter_is_bvec(from) || iov_iter_is_kvec(from)) && 367938c8a9a5SSteve French !is_sync_kiocb(iocb)) { 368038c8a9a5SSteve French /* 368138c8a9a5SSteve French * If the op is asynchronous, we need to copy the list attached 368238c8a9a5SSteve French * to a BVEC/KVEC-type iterator, but we assume that the storage 368338c8a9a5SSteve French * will be pinned by the caller; in any case, we may or may not 368438c8a9a5SSteve French * be able to pin the pages, so we don't try. 368538c8a9a5SSteve French */ 368638c8a9a5SSteve French ctx->bv = (void *)dup_iter(&ctx->iter, from, GFP_KERNEL); 368738c8a9a5SSteve French if (!ctx->bv) { 368838c8a9a5SSteve French kref_put(&ctx->refcount, cifs_aio_ctx_release); 368938c8a9a5SSteve French return -ENOMEM; 369038c8a9a5SSteve French } 369138c8a9a5SSteve French } else { 369238c8a9a5SSteve French /* 369338c8a9a5SSteve French * Otherwise, we just pass the iterator down as-is and rely on 369438c8a9a5SSteve French * the caller to make sure the pages referred to by the 369538c8a9a5SSteve French * iterator don't evaporate. 369638c8a9a5SSteve French */ 369738c8a9a5SSteve French ctx->iter = *from; 369838c8a9a5SSteve French } 369938c8a9a5SSteve French 370038c8a9a5SSteve French ctx->len = iov_iter_count(&ctx->iter); 370138c8a9a5SSteve French 370238c8a9a5SSteve French /* grab a lock here due to read response handlers can access ctx */ 370338c8a9a5SSteve French mutex_lock(&ctx->aio_mutex); 370438c8a9a5SSteve French 370538c8a9a5SSteve French rc = cifs_write_from_iter(iocb->ki_pos, ctx->len, &ctx->iter, 370638c8a9a5SSteve French cfile, cifs_sb, &ctx->list, ctx); 370738c8a9a5SSteve French 370838c8a9a5SSteve French /* 370938c8a9a5SSteve French * If at least one write was successfully sent, then discard any rc 371038c8a9a5SSteve French * value from the later writes. If the other write succeeds, then 371138c8a9a5SSteve French * we'll end up returning whatever was written. If it fails, then 371238c8a9a5SSteve French * we'll get a new rc value from that. 371338c8a9a5SSteve French */ 371438c8a9a5SSteve French if (!list_empty(&ctx->list)) 371538c8a9a5SSteve French rc = 0; 371638c8a9a5SSteve French 371738c8a9a5SSteve French mutex_unlock(&ctx->aio_mutex); 371838c8a9a5SSteve French 371938c8a9a5SSteve French if (rc) { 372038c8a9a5SSteve French kref_put(&ctx->refcount, cifs_aio_ctx_release); 372138c8a9a5SSteve French return rc; 372238c8a9a5SSteve French } 372338c8a9a5SSteve French 372438c8a9a5SSteve French if (!is_sync_kiocb(iocb)) { 372538c8a9a5SSteve French kref_put(&ctx->refcount, cifs_aio_ctx_release); 372638c8a9a5SSteve French return -EIOCBQUEUED; 372738c8a9a5SSteve French } 372838c8a9a5SSteve French 372938c8a9a5SSteve French rc = wait_for_completion_killable(&ctx->done); 373038c8a9a5SSteve French if (rc) { 373138c8a9a5SSteve French mutex_lock(&ctx->aio_mutex); 373238c8a9a5SSteve French ctx->rc = rc = -EINTR; 373338c8a9a5SSteve French total_written = ctx->total_len; 373438c8a9a5SSteve French mutex_unlock(&ctx->aio_mutex); 373538c8a9a5SSteve French } else { 373638c8a9a5SSteve French rc = ctx->rc; 373738c8a9a5SSteve French total_written = ctx->total_len; 373838c8a9a5SSteve French } 373938c8a9a5SSteve French 374038c8a9a5SSteve French kref_put(&ctx->refcount, cifs_aio_ctx_release); 374138c8a9a5SSteve French 374238c8a9a5SSteve French if (unlikely(!total_written)) 374338c8a9a5SSteve French return rc; 374438c8a9a5SSteve French 374538c8a9a5SSteve French iocb->ki_pos += total_written; 374638c8a9a5SSteve French return total_written; 374738c8a9a5SSteve French } 374838c8a9a5SSteve French 374938c8a9a5SSteve French ssize_t cifs_direct_writev(struct kiocb *iocb, struct iov_iter *from) 375038c8a9a5SSteve French { 375138c8a9a5SSteve French struct file *file = iocb->ki_filp; 375238c8a9a5SSteve French 375338c8a9a5SSteve French cifs_revalidate_mapping(file->f_inode); 375438c8a9a5SSteve French return __cifs_writev(iocb, from, true); 375538c8a9a5SSteve French } 375638c8a9a5SSteve French 375738c8a9a5SSteve French ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from) 375838c8a9a5SSteve French { 375938c8a9a5SSteve French return __cifs_writev(iocb, from, false); 376038c8a9a5SSteve French } 376138c8a9a5SSteve French 376238c8a9a5SSteve French static ssize_t 376338c8a9a5SSteve French cifs_writev(struct kiocb *iocb, struct iov_iter *from) 376438c8a9a5SSteve French { 376538c8a9a5SSteve French struct file *file = iocb->ki_filp; 376638c8a9a5SSteve French struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; 376738c8a9a5SSteve French struct inode *inode = file->f_mapping->host; 376838c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(inode); 376938c8a9a5SSteve French struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; 377038c8a9a5SSteve French ssize_t rc; 377138c8a9a5SSteve French 377238c8a9a5SSteve French inode_lock(inode); 377338c8a9a5SSteve French /* 377438c8a9a5SSteve French * We need to hold the sem to be sure nobody modifies lock list 377538c8a9a5SSteve French * with a brlock that prevents writing. 377638c8a9a5SSteve French */ 377738c8a9a5SSteve French down_read(&cinode->lock_sem); 377838c8a9a5SSteve French 377938c8a9a5SSteve French rc = generic_write_checks(iocb, from); 378038c8a9a5SSteve French if (rc <= 0) 378138c8a9a5SSteve French goto out; 378238c8a9a5SSteve French 378338c8a9a5SSteve French if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from), 378438c8a9a5SSteve French server->vals->exclusive_lock_type, 0, 378538c8a9a5SSteve French NULL, CIFS_WRITE_OP)) 378638c8a9a5SSteve French rc = __generic_file_write_iter(iocb, from); 378738c8a9a5SSteve French else 378838c8a9a5SSteve French rc = -EACCES; 378938c8a9a5SSteve French out: 379038c8a9a5SSteve French up_read(&cinode->lock_sem); 379138c8a9a5SSteve French inode_unlock(inode); 379238c8a9a5SSteve French 379338c8a9a5SSteve French if (rc > 0) 379438c8a9a5SSteve French rc = generic_write_sync(iocb, rc); 379538c8a9a5SSteve French return rc; 379638c8a9a5SSteve French } 379738c8a9a5SSteve French 379838c8a9a5SSteve French ssize_t 379938c8a9a5SSteve French cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from) 380038c8a9a5SSteve French { 380138c8a9a5SSteve French struct inode *inode = file_inode(iocb->ki_filp); 380238c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(inode); 380338c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 380438c8a9a5SSteve French struct cifsFileInfo *cfile = (struct cifsFileInfo *) 380538c8a9a5SSteve French iocb->ki_filp->private_data; 380638c8a9a5SSteve French struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 380738c8a9a5SSteve French ssize_t written; 380838c8a9a5SSteve French 380938c8a9a5SSteve French written = cifs_get_writer(cinode); 381038c8a9a5SSteve French if (written) 381138c8a9a5SSteve French return written; 381238c8a9a5SSteve French 381338c8a9a5SSteve French if (CIFS_CACHE_WRITE(cinode)) { 381438c8a9a5SSteve French if (cap_unix(tcon->ses) && 381538c8a9a5SSteve French (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) 381638c8a9a5SSteve French && ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) { 381738c8a9a5SSteve French written = generic_file_write_iter(iocb, from); 381838c8a9a5SSteve French goto out; 381938c8a9a5SSteve French } 382038c8a9a5SSteve French written = cifs_writev(iocb, from); 382138c8a9a5SSteve French goto out; 382238c8a9a5SSteve French } 382338c8a9a5SSteve French /* 382438c8a9a5SSteve French * For non-oplocked files in strict cache mode we need to write the data 382538c8a9a5SSteve French * to the server exactly from the pos to pos+len-1 rather than flush all 382638c8a9a5SSteve French * affected pages because it may cause a error with mandatory locks on 382738c8a9a5SSteve French * these pages but not on the region from pos to ppos+len-1. 382838c8a9a5SSteve French */ 382938c8a9a5SSteve French written = cifs_user_writev(iocb, from); 383038c8a9a5SSteve French if (CIFS_CACHE_READ(cinode)) { 383138c8a9a5SSteve French /* 383238c8a9a5SSteve French * We have read level caching and we have just sent a write 383338c8a9a5SSteve French * request to the server thus making data in the cache stale. 383438c8a9a5SSteve French * Zap the cache and set oplock/lease level to NONE to avoid 383538c8a9a5SSteve French * reading stale data from the cache. All subsequent read 383638c8a9a5SSteve French * operations will read new data from the server. 383738c8a9a5SSteve French */ 383838c8a9a5SSteve French cifs_zap_mapping(inode); 383938c8a9a5SSteve French cifs_dbg(FYI, "Set Oplock/Lease to NONE for inode=%p after write\n", 384038c8a9a5SSteve French inode); 384138c8a9a5SSteve French cinode->oplock = 0; 384238c8a9a5SSteve French } 384338c8a9a5SSteve French out: 384438c8a9a5SSteve French cifs_put_writer(cinode); 384538c8a9a5SSteve French return written; 384638c8a9a5SSteve French } 384738c8a9a5SSteve French 384838c8a9a5SSteve French static struct cifs_readdata *cifs_readdata_alloc(work_func_t complete) 384938c8a9a5SSteve French { 385038c8a9a5SSteve French struct cifs_readdata *rdata; 385138c8a9a5SSteve French 385238c8a9a5SSteve French rdata = kzalloc(sizeof(*rdata), GFP_KERNEL); 385338c8a9a5SSteve French if (rdata) { 385438c8a9a5SSteve French kref_init(&rdata->refcount); 385538c8a9a5SSteve French INIT_LIST_HEAD(&rdata->list); 385638c8a9a5SSteve French init_completion(&rdata->done); 385738c8a9a5SSteve French INIT_WORK(&rdata->work, complete); 385838c8a9a5SSteve French } 385938c8a9a5SSteve French 386038c8a9a5SSteve French return rdata; 386138c8a9a5SSteve French } 386238c8a9a5SSteve French 386338c8a9a5SSteve French void 386438c8a9a5SSteve French cifs_readdata_release(struct kref *refcount) 386538c8a9a5SSteve French { 386638c8a9a5SSteve French struct cifs_readdata *rdata = container_of(refcount, 386738c8a9a5SSteve French struct cifs_readdata, refcount); 386838c8a9a5SSteve French 386938c8a9a5SSteve French if (rdata->ctx) 387038c8a9a5SSteve French kref_put(&rdata->ctx->refcount, cifs_aio_ctx_release); 387138c8a9a5SSteve French #ifdef CONFIG_CIFS_SMB_DIRECT 387238c8a9a5SSteve French if (rdata->mr) { 387338c8a9a5SSteve French smbd_deregister_mr(rdata->mr); 387438c8a9a5SSteve French rdata->mr = NULL; 387538c8a9a5SSteve French } 387638c8a9a5SSteve French #endif 387738c8a9a5SSteve French if (rdata->cfile) 387838c8a9a5SSteve French cifsFileInfo_put(rdata->cfile); 387938c8a9a5SSteve French 388038c8a9a5SSteve French kfree(rdata); 388138c8a9a5SSteve French } 388238c8a9a5SSteve French 388338c8a9a5SSteve French static void collect_uncached_read_data(struct cifs_aio_ctx *ctx); 388438c8a9a5SSteve French 388538c8a9a5SSteve French static void 388638c8a9a5SSteve French cifs_uncached_readv_complete(struct work_struct *work) 388738c8a9a5SSteve French { 388838c8a9a5SSteve French struct cifs_readdata *rdata = container_of(work, 388938c8a9a5SSteve French struct cifs_readdata, work); 389038c8a9a5SSteve French 389138c8a9a5SSteve French complete(&rdata->done); 389238c8a9a5SSteve French collect_uncached_read_data(rdata->ctx); 389338c8a9a5SSteve French /* the below call can possibly free the last ref to aio ctx */ 389438c8a9a5SSteve French kref_put(&rdata->refcount, cifs_readdata_release); 389538c8a9a5SSteve French } 389638c8a9a5SSteve French 389738c8a9a5SSteve French static int cifs_resend_rdata(struct cifs_readdata *rdata, 389838c8a9a5SSteve French struct list_head *rdata_list, 389938c8a9a5SSteve French struct cifs_aio_ctx *ctx) 390038c8a9a5SSteve French { 390138c8a9a5SSteve French unsigned int rsize; 390238c8a9a5SSteve French struct cifs_credits credits; 390338c8a9a5SSteve French int rc; 390438c8a9a5SSteve French struct TCP_Server_Info *server; 390538c8a9a5SSteve French 390638c8a9a5SSteve French /* XXX: should we pick a new channel here? */ 390738c8a9a5SSteve French server = rdata->server; 390838c8a9a5SSteve French 390938c8a9a5SSteve French do { 391038c8a9a5SSteve French if (rdata->cfile->invalidHandle) { 391138c8a9a5SSteve French rc = cifs_reopen_file(rdata->cfile, true); 391238c8a9a5SSteve French if (rc == -EAGAIN) 391338c8a9a5SSteve French continue; 391438c8a9a5SSteve French else if (rc) 391538c8a9a5SSteve French break; 391638c8a9a5SSteve French } 391738c8a9a5SSteve French 391838c8a9a5SSteve French /* 391938c8a9a5SSteve French * Wait for credits to resend this rdata. 392038c8a9a5SSteve French * Note: we are attempting to resend the whole rdata not in 392138c8a9a5SSteve French * segments 392238c8a9a5SSteve French */ 392338c8a9a5SSteve French do { 392438c8a9a5SSteve French rc = server->ops->wait_mtu_credits(server, rdata->bytes, 392538c8a9a5SSteve French &rsize, &credits); 392638c8a9a5SSteve French 392738c8a9a5SSteve French if (rc) 392838c8a9a5SSteve French goto fail; 392938c8a9a5SSteve French 393038c8a9a5SSteve French if (rsize < rdata->bytes) { 393138c8a9a5SSteve French add_credits_and_wake_if(server, &credits, 0); 393238c8a9a5SSteve French msleep(1000); 393338c8a9a5SSteve French } 393438c8a9a5SSteve French } while (rsize < rdata->bytes); 393538c8a9a5SSteve French rdata->credits = credits; 393638c8a9a5SSteve French 393738c8a9a5SSteve French rc = adjust_credits(server, &rdata->credits, rdata->bytes); 393838c8a9a5SSteve French if (!rc) { 393938c8a9a5SSteve French if (rdata->cfile->invalidHandle) 394038c8a9a5SSteve French rc = -EAGAIN; 394138c8a9a5SSteve French else { 394238c8a9a5SSteve French #ifdef CONFIG_CIFS_SMB_DIRECT 394338c8a9a5SSteve French if (rdata->mr) { 394438c8a9a5SSteve French rdata->mr->need_invalidate = true; 394538c8a9a5SSteve French smbd_deregister_mr(rdata->mr); 394638c8a9a5SSteve French rdata->mr = NULL; 394738c8a9a5SSteve French } 394838c8a9a5SSteve French #endif 394938c8a9a5SSteve French rc = server->ops->async_readv(rdata); 395038c8a9a5SSteve French } 395138c8a9a5SSteve French } 395238c8a9a5SSteve French 395338c8a9a5SSteve French /* If the read was successfully sent, we are done */ 395438c8a9a5SSteve French if (!rc) { 395538c8a9a5SSteve French /* Add to aio pending list */ 395638c8a9a5SSteve French list_add_tail(&rdata->list, rdata_list); 395738c8a9a5SSteve French return 0; 395838c8a9a5SSteve French } 395938c8a9a5SSteve French 396038c8a9a5SSteve French /* Roll back credits and retry if needed */ 396138c8a9a5SSteve French add_credits_and_wake_if(server, &rdata->credits, 0); 396238c8a9a5SSteve French } while (rc == -EAGAIN); 396338c8a9a5SSteve French 396438c8a9a5SSteve French fail: 396538c8a9a5SSteve French kref_put(&rdata->refcount, cifs_readdata_release); 396638c8a9a5SSteve French return rc; 396738c8a9a5SSteve French } 396838c8a9a5SSteve French 396938c8a9a5SSteve French static int 397038c8a9a5SSteve French cifs_send_async_read(loff_t fpos, size_t len, struct cifsFileInfo *open_file, 397138c8a9a5SSteve French struct cifs_sb_info *cifs_sb, struct list_head *rdata_list, 397238c8a9a5SSteve French struct cifs_aio_ctx *ctx) 397338c8a9a5SSteve French { 397438c8a9a5SSteve French struct cifs_readdata *rdata; 397538c8a9a5SSteve French unsigned int rsize, nsegs, max_segs = INT_MAX; 397638c8a9a5SSteve French struct cifs_credits credits_on_stack; 397738c8a9a5SSteve French struct cifs_credits *credits = &credits_on_stack; 397838c8a9a5SSteve French size_t cur_len, max_len; 397938c8a9a5SSteve French int rc; 398038c8a9a5SSteve French pid_t pid; 398138c8a9a5SSteve French struct TCP_Server_Info *server; 398238c8a9a5SSteve French 398338c8a9a5SSteve French server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses); 398438c8a9a5SSteve French 398538c8a9a5SSteve French #ifdef CONFIG_CIFS_SMB_DIRECT 398638c8a9a5SSteve French if (server->smbd_conn) 398738c8a9a5SSteve French max_segs = server->smbd_conn->max_frmr_depth; 398838c8a9a5SSteve French #endif 398938c8a9a5SSteve French 399038c8a9a5SSteve French if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) 399138c8a9a5SSteve French pid = open_file->pid; 399238c8a9a5SSteve French else 399338c8a9a5SSteve French pid = current->tgid; 399438c8a9a5SSteve French 399538c8a9a5SSteve French do { 399638c8a9a5SSteve French if (open_file->invalidHandle) { 399738c8a9a5SSteve French rc = cifs_reopen_file(open_file, true); 399838c8a9a5SSteve French if (rc == -EAGAIN) 399938c8a9a5SSteve French continue; 400038c8a9a5SSteve French else if (rc) 400138c8a9a5SSteve French break; 400238c8a9a5SSteve French } 400338c8a9a5SSteve French 400438c8a9a5SSteve French if (cifs_sb->ctx->rsize == 0) 400538c8a9a5SSteve French cifs_sb->ctx->rsize = 400638c8a9a5SSteve French server->ops->negotiate_rsize(tlink_tcon(open_file->tlink), 400738c8a9a5SSteve French cifs_sb->ctx); 400838c8a9a5SSteve French 400938c8a9a5SSteve French rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize, 401038c8a9a5SSteve French &rsize, credits); 401138c8a9a5SSteve French if (rc) 401238c8a9a5SSteve French break; 401338c8a9a5SSteve French 401438c8a9a5SSteve French max_len = min_t(size_t, len, rsize); 401538c8a9a5SSteve French 401638c8a9a5SSteve French cur_len = cifs_limit_bvec_subset(&ctx->iter, max_len, 401738c8a9a5SSteve French max_segs, &nsegs); 401838c8a9a5SSteve French cifs_dbg(FYI, "read-to-iter len=%zx/%zx nsegs=%u/%lu/%u\n", 401938c8a9a5SSteve French cur_len, max_len, nsegs, ctx->iter.nr_segs, max_segs); 402038c8a9a5SSteve French if (cur_len == 0) { 402138c8a9a5SSteve French rc = -EIO; 402238c8a9a5SSteve French add_credits_and_wake_if(server, credits, 0); 402338c8a9a5SSteve French break; 402438c8a9a5SSteve French } 402538c8a9a5SSteve French 402638c8a9a5SSteve French rdata = cifs_readdata_alloc(cifs_uncached_readv_complete); 402738c8a9a5SSteve French if (!rdata) { 402838c8a9a5SSteve French add_credits_and_wake_if(server, credits, 0); 402938c8a9a5SSteve French rc = -ENOMEM; 403038c8a9a5SSteve French break; 403138c8a9a5SSteve French } 403238c8a9a5SSteve French 403338c8a9a5SSteve French rdata->server = server; 403438c8a9a5SSteve French rdata->cfile = cifsFileInfo_get(open_file); 403538c8a9a5SSteve French rdata->offset = fpos; 403638c8a9a5SSteve French rdata->bytes = cur_len; 403738c8a9a5SSteve French rdata->pid = pid; 403838c8a9a5SSteve French rdata->credits = credits_on_stack; 403938c8a9a5SSteve French rdata->ctx = ctx; 404038c8a9a5SSteve French kref_get(&ctx->refcount); 404138c8a9a5SSteve French 404238c8a9a5SSteve French rdata->iter = ctx->iter; 404338c8a9a5SSteve French iov_iter_truncate(&rdata->iter, cur_len); 404438c8a9a5SSteve French 404538c8a9a5SSteve French rc = adjust_credits(server, &rdata->credits, rdata->bytes); 404638c8a9a5SSteve French 404738c8a9a5SSteve French if (!rc) { 404838c8a9a5SSteve French if (rdata->cfile->invalidHandle) 404938c8a9a5SSteve French rc = -EAGAIN; 405038c8a9a5SSteve French else 405138c8a9a5SSteve French rc = server->ops->async_readv(rdata); 405238c8a9a5SSteve French } 405338c8a9a5SSteve French 405438c8a9a5SSteve French if (rc) { 405538c8a9a5SSteve French add_credits_and_wake_if(server, &rdata->credits, 0); 405638c8a9a5SSteve French kref_put(&rdata->refcount, cifs_readdata_release); 405738c8a9a5SSteve French if (rc == -EAGAIN) 405838c8a9a5SSteve French continue; 405938c8a9a5SSteve French break; 406038c8a9a5SSteve French } 406138c8a9a5SSteve French 406238c8a9a5SSteve French list_add_tail(&rdata->list, rdata_list); 406338c8a9a5SSteve French iov_iter_advance(&ctx->iter, cur_len); 406438c8a9a5SSteve French fpos += cur_len; 406538c8a9a5SSteve French len -= cur_len; 406638c8a9a5SSteve French } while (len > 0); 406738c8a9a5SSteve French 406838c8a9a5SSteve French return rc; 406938c8a9a5SSteve French } 407038c8a9a5SSteve French 407138c8a9a5SSteve French static void 407238c8a9a5SSteve French collect_uncached_read_data(struct cifs_aio_ctx *ctx) 407338c8a9a5SSteve French { 407438c8a9a5SSteve French struct cifs_readdata *rdata, *tmp; 407538c8a9a5SSteve French struct cifs_sb_info *cifs_sb; 407638c8a9a5SSteve French int rc; 407738c8a9a5SSteve French 407838c8a9a5SSteve French cifs_sb = CIFS_SB(ctx->cfile->dentry->d_sb); 407938c8a9a5SSteve French 408038c8a9a5SSteve French mutex_lock(&ctx->aio_mutex); 408138c8a9a5SSteve French 408238c8a9a5SSteve French if (list_empty(&ctx->list)) { 408338c8a9a5SSteve French mutex_unlock(&ctx->aio_mutex); 408438c8a9a5SSteve French return; 408538c8a9a5SSteve French } 408638c8a9a5SSteve French 408738c8a9a5SSteve French rc = ctx->rc; 408838c8a9a5SSteve French /* the loop below should proceed in the order of increasing offsets */ 408938c8a9a5SSteve French again: 409038c8a9a5SSteve French list_for_each_entry_safe(rdata, tmp, &ctx->list, list) { 409138c8a9a5SSteve French if (!rc) { 409238c8a9a5SSteve French if (!try_wait_for_completion(&rdata->done)) { 409338c8a9a5SSteve French mutex_unlock(&ctx->aio_mutex); 409438c8a9a5SSteve French return; 409538c8a9a5SSteve French } 409638c8a9a5SSteve French 409738c8a9a5SSteve French if (rdata->result == -EAGAIN) { 409838c8a9a5SSteve French /* resend call if it's a retryable error */ 409938c8a9a5SSteve French struct list_head tmp_list; 410038c8a9a5SSteve French unsigned int got_bytes = rdata->got_bytes; 410138c8a9a5SSteve French 410238c8a9a5SSteve French list_del_init(&rdata->list); 410338c8a9a5SSteve French INIT_LIST_HEAD(&tmp_list); 410438c8a9a5SSteve French 410538c8a9a5SSteve French if (ctx->direct_io) { 410638c8a9a5SSteve French /* 410738c8a9a5SSteve French * Re-use rdata as this is a 410838c8a9a5SSteve French * direct I/O 410938c8a9a5SSteve French */ 411038c8a9a5SSteve French rc = cifs_resend_rdata( 411138c8a9a5SSteve French rdata, 411238c8a9a5SSteve French &tmp_list, ctx); 411338c8a9a5SSteve French } else { 411438c8a9a5SSteve French rc = cifs_send_async_read( 411538c8a9a5SSteve French rdata->offset + got_bytes, 411638c8a9a5SSteve French rdata->bytes - got_bytes, 411738c8a9a5SSteve French rdata->cfile, cifs_sb, 411838c8a9a5SSteve French &tmp_list, ctx); 411938c8a9a5SSteve French 412038c8a9a5SSteve French kref_put(&rdata->refcount, 412138c8a9a5SSteve French cifs_readdata_release); 412238c8a9a5SSteve French } 412338c8a9a5SSteve French 412438c8a9a5SSteve French list_splice(&tmp_list, &ctx->list); 412538c8a9a5SSteve French 412638c8a9a5SSteve French goto again; 412738c8a9a5SSteve French } else if (rdata->result) 412838c8a9a5SSteve French rc = rdata->result; 412938c8a9a5SSteve French 413038c8a9a5SSteve French /* if there was a short read -- discard anything left */ 413138c8a9a5SSteve French if (rdata->got_bytes && rdata->got_bytes < rdata->bytes) 413238c8a9a5SSteve French rc = -ENODATA; 413338c8a9a5SSteve French 413438c8a9a5SSteve French ctx->total_len += rdata->got_bytes; 413538c8a9a5SSteve French } 413638c8a9a5SSteve French list_del_init(&rdata->list); 413738c8a9a5SSteve French kref_put(&rdata->refcount, cifs_readdata_release); 413838c8a9a5SSteve French } 413938c8a9a5SSteve French 414038c8a9a5SSteve French /* mask nodata case */ 414138c8a9a5SSteve French if (rc == -ENODATA) 414238c8a9a5SSteve French rc = 0; 414338c8a9a5SSteve French 414438c8a9a5SSteve French ctx->rc = (rc == 0) ? (ssize_t)ctx->total_len : rc; 414538c8a9a5SSteve French 414638c8a9a5SSteve French mutex_unlock(&ctx->aio_mutex); 414738c8a9a5SSteve French 414838c8a9a5SSteve French if (ctx->iocb && ctx->iocb->ki_complete) 414938c8a9a5SSteve French ctx->iocb->ki_complete(ctx->iocb, ctx->rc); 415038c8a9a5SSteve French else 415138c8a9a5SSteve French complete(&ctx->done); 415238c8a9a5SSteve French } 415338c8a9a5SSteve French 415438c8a9a5SSteve French static ssize_t __cifs_readv( 415538c8a9a5SSteve French struct kiocb *iocb, struct iov_iter *to, bool direct) 415638c8a9a5SSteve French { 415738c8a9a5SSteve French size_t len; 415838c8a9a5SSteve French struct file *file = iocb->ki_filp; 415938c8a9a5SSteve French struct cifs_sb_info *cifs_sb; 416038c8a9a5SSteve French struct cifsFileInfo *cfile; 416138c8a9a5SSteve French struct cifs_tcon *tcon; 416238c8a9a5SSteve French ssize_t rc, total_read = 0; 416338c8a9a5SSteve French loff_t offset = iocb->ki_pos; 416438c8a9a5SSteve French struct cifs_aio_ctx *ctx; 416538c8a9a5SSteve French 416638c8a9a5SSteve French len = iov_iter_count(to); 416738c8a9a5SSteve French if (!len) 416838c8a9a5SSteve French return 0; 416938c8a9a5SSteve French 417038c8a9a5SSteve French cifs_sb = CIFS_FILE_SB(file); 417138c8a9a5SSteve French cfile = file->private_data; 417238c8a9a5SSteve French tcon = tlink_tcon(cfile->tlink); 417338c8a9a5SSteve French 417438c8a9a5SSteve French if (!tcon->ses->server->ops->async_readv) 417538c8a9a5SSteve French return -ENOSYS; 417638c8a9a5SSteve French 417738c8a9a5SSteve French if ((file->f_flags & O_ACCMODE) == O_WRONLY) 417838c8a9a5SSteve French cifs_dbg(FYI, "attempting read on write only file instance\n"); 417938c8a9a5SSteve French 418038c8a9a5SSteve French ctx = cifs_aio_ctx_alloc(); 418138c8a9a5SSteve French if (!ctx) 418238c8a9a5SSteve French return -ENOMEM; 418338c8a9a5SSteve French 418438c8a9a5SSteve French ctx->pos = offset; 418538c8a9a5SSteve French ctx->direct_io = direct; 418638c8a9a5SSteve French ctx->len = len; 418738c8a9a5SSteve French ctx->cfile = cifsFileInfo_get(cfile); 418838c8a9a5SSteve French ctx->nr_pinned_pages = 0; 418938c8a9a5SSteve French 419038c8a9a5SSteve French if (!is_sync_kiocb(iocb)) 419138c8a9a5SSteve French ctx->iocb = iocb; 419238c8a9a5SSteve French 419338c8a9a5SSteve French if (user_backed_iter(to)) { 419438c8a9a5SSteve French /* 419538c8a9a5SSteve French * Extract IOVEC/UBUF-type iterators to a BVEC-type iterator as 419638c8a9a5SSteve French * they contain references to the calling process's virtual 419738c8a9a5SSteve French * memory layout which won't be available in an async worker 419838c8a9a5SSteve French * thread. This also takes a pin on every folio involved. 419938c8a9a5SSteve French */ 420038c8a9a5SSteve French rc = netfs_extract_user_iter(to, iov_iter_count(to), 420138c8a9a5SSteve French &ctx->iter, 0); 420238c8a9a5SSteve French if (rc < 0) { 420338c8a9a5SSteve French kref_put(&ctx->refcount, cifs_aio_ctx_release); 420438c8a9a5SSteve French return rc; 420538c8a9a5SSteve French } 420638c8a9a5SSteve French 420738c8a9a5SSteve French ctx->nr_pinned_pages = rc; 420838c8a9a5SSteve French ctx->bv = (void *)ctx->iter.bvec; 420938c8a9a5SSteve French ctx->bv_need_unpin = iov_iter_extract_will_pin(to); 421038c8a9a5SSteve French ctx->should_dirty = true; 421138c8a9a5SSteve French } else if ((iov_iter_is_bvec(to) || iov_iter_is_kvec(to)) && 421238c8a9a5SSteve French !is_sync_kiocb(iocb)) { 421338c8a9a5SSteve French /* 421438c8a9a5SSteve French * If the op is asynchronous, we need to copy the list attached 421538c8a9a5SSteve French * to a BVEC/KVEC-type iterator, but we assume that the storage 421638c8a9a5SSteve French * will be retained by the caller; in any case, we may or may 421738c8a9a5SSteve French * not be able to pin the pages, so we don't try. 421838c8a9a5SSteve French */ 421938c8a9a5SSteve French ctx->bv = (void *)dup_iter(&ctx->iter, to, GFP_KERNEL); 422038c8a9a5SSteve French if (!ctx->bv) { 422138c8a9a5SSteve French kref_put(&ctx->refcount, cifs_aio_ctx_release); 422238c8a9a5SSteve French return -ENOMEM; 422338c8a9a5SSteve French } 422438c8a9a5SSteve French } else { 422538c8a9a5SSteve French /* 422638c8a9a5SSteve French * Otherwise, we just pass the iterator down as-is and rely on 422738c8a9a5SSteve French * the caller to make sure the pages referred to by the 422838c8a9a5SSteve French * iterator don't evaporate. 422938c8a9a5SSteve French */ 423038c8a9a5SSteve French ctx->iter = *to; 423138c8a9a5SSteve French } 423238c8a9a5SSteve French 423338c8a9a5SSteve French if (direct) { 423438c8a9a5SSteve French rc = filemap_write_and_wait_range(file->f_inode->i_mapping, 423538c8a9a5SSteve French offset, offset + len - 1); 423638c8a9a5SSteve French if (rc) { 423738c8a9a5SSteve French kref_put(&ctx->refcount, cifs_aio_ctx_release); 423838c8a9a5SSteve French return -EAGAIN; 423938c8a9a5SSteve French } 424038c8a9a5SSteve French } 424138c8a9a5SSteve French 424238c8a9a5SSteve French /* grab a lock here due to read response handlers can access ctx */ 424338c8a9a5SSteve French mutex_lock(&ctx->aio_mutex); 424438c8a9a5SSteve French 424538c8a9a5SSteve French rc = cifs_send_async_read(offset, len, cfile, cifs_sb, &ctx->list, ctx); 424638c8a9a5SSteve French 424738c8a9a5SSteve French /* if at least one read request send succeeded, then reset rc */ 424838c8a9a5SSteve French if (!list_empty(&ctx->list)) 424938c8a9a5SSteve French rc = 0; 425038c8a9a5SSteve French 425138c8a9a5SSteve French mutex_unlock(&ctx->aio_mutex); 425238c8a9a5SSteve French 425338c8a9a5SSteve French if (rc) { 425438c8a9a5SSteve French kref_put(&ctx->refcount, cifs_aio_ctx_release); 425538c8a9a5SSteve French return rc; 425638c8a9a5SSteve French } 425738c8a9a5SSteve French 425838c8a9a5SSteve French if (!is_sync_kiocb(iocb)) { 425938c8a9a5SSteve French kref_put(&ctx->refcount, cifs_aio_ctx_release); 426038c8a9a5SSteve French return -EIOCBQUEUED; 426138c8a9a5SSteve French } 426238c8a9a5SSteve French 426338c8a9a5SSteve French rc = wait_for_completion_killable(&ctx->done); 426438c8a9a5SSteve French if (rc) { 426538c8a9a5SSteve French mutex_lock(&ctx->aio_mutex); 426638c8a9a5SSteve French ctx->rc = rc = -EINTR; 426738c8a9a5SSteve French total_read = ctx->total_len; 426838c8a9a5SSteve French mutex_unlock(&ctx->aio_mutex); 426938c8a9a5SSteve French } else { 427038c8a9a5SSteve French rc = ctx->rc; 427138c8a9a5SSteve French total_read = ctx->total_len; 427238c8a9a5SSteve French } 427338c8a9a5SSteve French 427438c8a9a5SSteve French kref_put(&ctx->refcount, cifs_aio_ctx_release); 427538c8a9a5SSteve French 427638c8a9a5SSteve French if (total_read) { 427738c8a9a5SSteve French iocb->ki_pos += total_read; 427838c8a9a5SSteve French return total_read; 427938c8a9a5SSteve French } 428038c8a9a5SSteve French return rc; 428138c8a9a5SSteve French } 428238c8a9a5SSteve French 428338c8a9a5SSteve French ssize_t cifs_direct_readv(struct kiocb *iocb, struct iov_iter *to) 428438c8a9a5SSteve French { 428538c8a9a5SSteve French return __cifs_readv(iocb, to, true); 428638c8a9a5SSteve French } 428738c8a9a5SSteve French 428838c8a9a5SSteve French ssize_t cifs_user_readv(struct kiocb *iocb, struct iov_iter *to) 428938c8a9a5SSteve French { 429038c8a9a5SSteve French return __cifs_readv(iocb, to, false); 429138c8a9a5SSteve French } 429238c8a9a5SSteve French 429338c8a9a5SSteve French ssize_t 429438c8a9a5SSteve French cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to) 429538c8a9a5SSteve French { 429638c8a9a5SSteve French struct inode *inode = file_inode(iocb->ki_filp); 429738c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(inode); 429838c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 429938c8a9a5SSteve French struct cifsFileInfo *cfile = (struct cifsFileInfo *) 430038c8a9a5SSteve French iocb->ki_filp->private_data; 430138c8a9a5SSteve French struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); 430238c8a9a5SSteve French int rc = -EACCES; 430338c8a9a5SSteve French 430438c8a9a5SSteve French /* 430538c8a9a5SSteve French * In strict cache mode we need to read from the server all the time 430638c8a9a5SSteve French * if we don't have level II oplock because the server can delay mtime 430738c8a9a5SSteve French * change - so we can't make a decision about inode invalidating. 430838c8a9a5SSteve French * And we can also fail with pagereading if there are mandatory locks 430938c8a9a5SSteve French * on pages affected by this read but not on the region from pos to 431038c8a9a5SSteve French * pos+len-1. 431138c8a9a5SSteve French */ 431238c8a9a5SSteve French if (!CIFS_CACHE_READ(cinode)) 431338c8a9a5SSteve French return cifs_user_readv(iocb, to); 431438c8a9a5SSteve French 431538c8a9a5SSteve French if (cap_unix(tcon->ses) && 431638c8a9a5SSteve French (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && 431738c8a9a5SSteve French ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) 431838c8a9a5SSteve French return generic_file_read_iter(iocb, to); 431938c8a9a5SSteve French 432038c8a9a5SSteve French /* 432138c8a9a5SSteve French * We need to hold the sem to be sure nobody modifies lock list 432238c8a9a5SSteve French * with a brlock that prevents reading. 432338c8a9a5SSteve French */ 432438c8a9a5SSteve French down_read(&cinode->lock_sem); 432538c8a9a5SSteve French if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(to), 432638c8a9a5SSteve French tcon->ses->server->vals->shared_lock_type, 432738c8a9a5SSteve French 0, NULL, CIFS_READ_OP)) 432838c8a9a5SSteve French rc = generic_file_read_iter(iocb, to); 432938c8a9a5SSteve French up_read(&cinode->lock_sem); 433038c8a9a5SSteve French return rc; 433138c8a9a5SSteve French } 433238c8a9a5SSteve French 433338c8a9a5SSteve French static ssize_t 433438c8a9a5SSteve French cifs_read(struct file *file, char *read_data, size_t read_size, loff_t *offset) 433538c8a9a5SSteve French { 433638c8a9a5SSteve French int rc = -EACCES; 433738c8a9a5SSteve French unsigned int bytes_read = 0; 433838c8a9a5SSteve French unsigned int total_read; 433938c8a9a5SSteve French unsigned int current_read_size; 434038c8a9a5SSteve French unsigned int rsize; 434138c8a9a5SSteve French struct cifs_sb_info *cifs_sb; 434238c8a9a5SSteve French struct cifs_tcon *tcon; 434338c8a9a5SSteve French struct TCP_Server_Info *server; 434438c8a9a5SSteve French unsigned int xid; 434538c8a9a5SSteve French char *cur_offset; 434638c8a9a5SSteve French struct cifsFileInfo *open_file; 434738c8a9a5SSteve French struct cifs_io_parms io_parms = {0}; 434838c8a9a5SSteve French int buf_type = CIFS_NO_BUFFER; 434938c8a9a5SSteve French __u32 pid; 435038c8a9a5SSteve French 435138c8a9a5SSteve French xid = get_xid(); 435238c8a9a5SSteve French cifs_sb = CIFS_FILE_SB(file); 435338c8a9a5SSteve French 435438c8a9a5SSteve French /* FIXME: set up handlers for larger reads and/or convert to async */ 435538c8a9a5SSteve French rsize = min_t(unsigned int, cifs_sb->ctx->rsize, CIFSMaxBufSize); 435638c8a9a5SSteve French 435738c8a9a5SSteve French if (file->private_data == NULL) { 435838c8a9a5SSteve French rc = -EBADF; 435938c8a9a5SSteve French free_xid(xid); 436038c8a9a5SSteve French return rc; 436138c8a9a5SSteve French } 436238c8a9a5SSteve French open_file = file->private_data; 436338c8a9a5SSteve French tcon = tlink_tcon(open_file->tlink); 436438c8a9a5SSteve French server = cifs_pick_channel(tcon->ses); 436538c8a9a5SSteve French 436638c8a9a5SSteve French if (!server->ops->sync_read) { 436738c8a9a5SSteve French free_xid(xid); 436838c8a9a5SSteve French return -ENOSYS; 436938c8a9a5SSteve French } 437038c8a9a5SSteve French 437138c8a9a5SSteve French if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) 437238c8a9a5SSteve French pid = open_file->pid; 437338c8a9a5SSteve French else 437438c8a9a5SSteve French pid = current->tgid; 437538c8a9a5SSteve French 437638c8a9a5SSteve French if ((file->f_flags & O_ACCMODE) == O_WRONLY) 437738c8a9a5SSteve French cifs_dbg(FYI, "attempting read on write only file instance\n"); 437838c8a9a5SSteve French 437938c8a9a5SSteve French for (total_read = 0, cur_offset = read_data; read_size > total_read; 438038c8a9a5SSteve French total_read += bytes_read, cur_offset += bytes_read) { 438138c8a9a5SSteve French do { 438238c8a9a5SSteve French current_read_size = min_t(uint, read_size - total_read, 438338c8a9a5SSteve French rsize); 438438c8a9a5SSteve French /* 438538c8a9a5SSteve French * For windows me and 9x we do not want to request more 438638c8a9a5SSteve French * than it negotiated since it will refuse the read 438738c8a9a5SSteve French * then. 438838c8a9a5SSteve French */ 438938c8a9a5SSteve French if (!(tcon->ses->capabilities & 439038c8a9a5SSteve French tcon->ses->server->vals->cap_large_files)) { 439138c8a9a5SSteve French current_read_size = min_t(uint, 439238c8a9a5SSteve French current_read_size, CIFSMaxBufSize); 439338c8a9a5SSteve French } 439438c8a9a5SSteve French if (open_file->invalidHandle) { 439538c8a9a5SSteve French rc = cifs_reopen_file(open_file, true); 439638c8a9a5SSteve French if (rc != 0) 439738c8a9a5SSteve French break; 439838c8a9a5SSteve French } 439938c8a9a5SSteve French io_parms.pid = pid; 440038c8a9a5SSteve French io_parms.tcon = tcon; 440138c8a9a5SSteve French io_parms.offset = *offset; 440238c8a9a5SSteve French io_parms.length = current_read_size; 440338c8a9a5SSteve French io_parms.server = server; 440438c8a9a5SSteve French rc = server->ops->sync_read(xid, &open_file->fid, &io_parms, 440538c8a9a5SSteve French &bytes_read, &cur_offset, 440638c8a9a5SSteve French &buf_type); 440738c8a9a5SSteve French } while (rc == -EAGAIN); 440838c8a9a5SSteve French 440938c8a9a5SSteve French if (rc || (bytes_read == 0)) { 441038c8a9a5SSteve French if (total_read) { 441138c8a9a5SSteve French break; 441238c8a9a5SSteve French } else { 441338c8a9a5SSteve French free_xid(xid); 441438c8a9a5SSteve French return rc; 441538c8a9a5SSteve French } 441638c8a9a5SSteve French } else { 441738c8a9a5SSteve French cifs_stats_bytes_read(tcon, total_read); 441838c8a9a5SSteve French *offset += bytes_read; 441938c8a9a5SSteve French } 442038c8a9a5SSteve French } 442138c8a9a5SSteve French free_xid(xid); 442238c8a9a5SSteve French return total_read; 442338c8a9a5SSteve French } 442438c8a9a5SSteve French 442538c8a9a5SSteve French /* 442638c8a9a5SSteve French * If the page is mmap'ed into a process' page tables, then we need to make 442738c8a9a5SSteve French * sure that it doesn't change while being written back. 442838c8a9a5SSteve French */ 442938c8a9a5SSteve French static vm_fault_t cifs_page_mkwrite(struct vm_fault *vmf) 443038c8a9a5SSteve French { 443138c8a9a5SSteve French struct folio *folio = page_folio(vmf->page); 443238c8a9a5SSteve French 443338c8a9a5SSteve French /* Wait for the folio to be written to the cache before we allow it to 443438c8a9a5SSteve French * be modified. We then assume the entire folio will need writing back. 443538c8a9a5SSteve French */ 443638c8a9a5SSteve French #ifdef CONFIG_CIFS_FSCACHE 443738c8a9a5SSteve French if (folio_test_fscache(folio) && 443838c8a9a5SSteve French folio_wait_fscache_killable(folio) < 0) 443938c8a9a5SSteve French return VM_FAULT_RETRY; 444038c8a9a5SSteve French #endif 444138c8a9a5SSteve French 444238c8a9a5SSteve French folio_wait_writeback(folio); 444338c8a9a5SSteve French 444438c8a9a5SSteve French if (folio_lock_killable(folio) < 0) 444538c8a9a5SSteve French return VM_FAULT_RETRY; 444638c8a9a5SSteve French return VM_FAULT_LOCKED; 444738c8a9a5SSteve French } 444838c8a9a5SSteve French 444938c8a9a5SSteve French static const struct vm_operations_struct cifs_file_vm_ops = { 445038c8a9a5SSteve French .fault = filemap_fault, 445138c8a9a5SSteve French .map_pages = filemap_map_pages, 445238c8a9a5SSteve French .page_mkwrite = cifs_page_mkwrite, 445338c8a9a5SSteve French }; 445438c8a9a5SSteve French 445538c8a9a5SSteve French int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma) 445638c8a9a5SSteve French { 445738c8a9a5SSteve French int xid, rc = 0; 445838c8a9a5SSteve French struct inode *inode = file_inode(file); 445938c8a9a5SSteve French 446038c8a9a5SSteve French xid = get_xid(); 446138c8a9a5SSteve French 446238c8a9a5SSteve French if (!CIFS_CACHE_READ(CIFS_I(inode))) 446338c8a9a5SSteve French rc = cifs_zap_mapping(inode); 446438c8a9a5SSteve French if (!rc) 446538c8a9a5SSteve French rc = generic_file_mmap(file, vma); 446638c8a9a5SSteve French if (!rc) 446738c8a9a5SSteve French vma->vm_ops = &cifs_file_vm_ops; 446838c8a9a5SSteve French 446938c8a9a5SSteve French free_xid(xid); 447038c8a9a5SSteve French return rc; 447138c8a9a5SSteve French } 447238c8a9a5SSteve French 447338c8a9a5SSteve French int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) 447438c8a9a5SSteve French { 447538c8a9a5SSteve French int rc, xid; 447638c8a9a5SSteve French 447738c8a9a5SSteve French xid = get_xid(); 447838c8a9a5SSteve French 447938c8a9a5SSteve French rc = cifs_revalidate_file(file); 448038c8a9a5SSteve French if (rc) 448138c8a9a5SSteve French cifs_dbg(FYI, "Validation prior to mmap failed, error=%d\n", 448238c8a9a5SSteve French rc); 448338c8a9a5SSteve French if (!rc) 448438c8a9a5SSteve French rc = generic_file_mmap(file, vma); 448538c8a9a5SSteve French if (!rc) 448638c8a9a5SSteve French vma->vm_ops = &cifs_file_vm_ops; 448738c8a9a5SSteve French 448838c8a9a5SSteve French free_xid(xid); 448938c8a9a5SSteve French return rc; 449038c8a9a5SSteve French } 449138c8a9a5SSteve French 449238c8a9a5SSteve French /* 449338c8a9a5SSteve French * Unlock a bunch of folios in the pagecache. 449438c8a9a5SSteve French */ 449538c8a9a5SSteve French static void cifs_unlock_folios(struct address_space *mapping, pgoff_t first, pgoff_t last) 449638c8a9a5SSteve French { 449738c8a9a5SSteve French struct folio *folio; 449838c8a9a5SSteve French XA_STATE(xas, &mapping->i_pages, first); 449938c8a9a5SSteve French 450038c8a9a5SSteve French rcu_read_lock(); 450138c8a9a5SSteve French xas_for_each(&xas, folio, last) { 450238c8a9a5SSteve French folio_unlock(folio); 450338c8a9a5SSteve French } 450438c8a9a5SSteve French rcu_read_unlock(); 450538c8a9a5SSteve French } 450638c8a9a5SSteve French 450738c8a9a5SSteve French static void cifs_readahead_complete(struct work_struct *work) 450838c8a9a5SSteve French { 450938c8a9a5SSteve French struct cifs_readdata *rdata = container_of(work, 451038c8a9a5SSteve French struct cifs_readdata, work); 451138c8a9a5SSteve French struct folio *folio; 451238c8a9a5SSteve French pgoff_t last; 451338c8a9a5SSteve French bool good = rdata->result == 0 || (rdata->result == -EAGAIN && rdata->got_bytes); 451438c8a9a5SSteve French 451538c8a9a5SSteve French XA_STATE(xas, &rdata->mapping->i_pages, rdata->offset / PAGE_SIZE); 451638c8a9a5SSteve French 451738c8a9a5SSteve French if (good) 451838c8a9a5SSteve French cifs_readahead_to_fscache(rdata->mapping->host, 451938c8a9a5SSteve French rdata->offset, rdata->bytes); 452038c8a9a5SSteve French 452138c8a9a5SSteve French if (iov_iter_count(&rdata->iter) > 0) 452238c8a9a5SSteve French iov_iter_zero(iov_iter_count(&rdata->iter), &rdata->iter); 452338c8a9a5SSteve French 452438c8a9a5SSteve French last = (rdata->offset + rdata->bytes - 1) / PAGE_SIZE; 452538c8a9a5SSteve French 452638c8a9a5SSteve French rcu_read_lock(); 452738c8a9a5SSteve French xas_for_each(&xas, folio, last) { 452838c8a9a5SSteve French if (good) { 452938c8a9a5SSteve French flush_dcache_folio(folio); 453038c8a9a5SSteve French folio_mark_uptodate(folio); 453138c8a9a5SSteve French } 453238c8a9a5SSteve French folio_unlock(folio); 453338c8a9a5SSteve French } 453438c8a9a5SSteve French rcu_read_unlock(); 453538c8a9a5SSteve French 453638c8a9a5SSteve French kref_put(&rdata->refcount, cifs_readdata_release); 453738c8a9a5SSteve French } 453838c8a9a5SSteve French 453938c8a9a5SSteve French static void cifs_readahead(struct readahead_control *ractl) 454038c8a9a5SSteve French { 454138c8a9a5SSteve French struct cifsFileInfo *open_file = ractl->file->private_data; 454238c8a9a5SSteve French struct cifs_sb_info *cifs_sb = CIFS_FILE_SB(ractl->file); 454338c8a9a5SSteve French struct TCP_Server_Info *server; 454438c8a9a5SSteve French unsigned int xid, nr_pages, cache_nr_pages = 0; 454538c8a9a5SSteve French unsigned int ra_pages; 454638c8a9a5SSteve French pgoff_t next_cached = ULONG_MAX, ra_index; 454738c8a9a5SSteve French bool caching = fscache_cookie_enabled(cifs_inode_cookie(ractl->mapping->host)) && 454838c8a9a5SSteve French cifs_inode_cookie(ractl->mapping->host)->cache_priv; 454938c8a9a5SSteve French bool check_cache = caching; 455038c8a9a5SSteve French pid_t pid; 455138c8a9a5SSteve French int rc = 0; 455238c8a9a5SSteve French 455338c8a9a5SSteve French /* Note that readahead_count() lags behind our dequeuing of pages from 455438c8a9a5SSteve French * the ractl, wo we have to keep track for ourselves. 455538c8a9a5SSteve French */ 455638c8a9a5SSteve French ra_pages = readahead_count(ractl); 455738c8a9a5SSteve French ra_index = readahead_index(ractl); 455838c8a9a5SSteve French 455938c8a9a5SSteve French xid = get_xid(); 456038c8a9a5SSteve French 456138c8a9a5SSteve French if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) 456238c8a9a5SSteve French pid = open_file->pid; 456338c8a9a5SSteve French else 456438c8a9a5SSteve French pid = current->tgid; 456538c8a9a5SSteve French 456638c8a9a5SSteve French server = cifs_pick_channel(tlink_tcon(open_file->tlink)->ses); 456738c8a9a5SSteve French 456838c8a9a5SSteve French cifs_dbg(FYI, "%s: file=%p mapping=%p num_pages=%u\n", 456938c8a9a5SSteve French __func__, ractl->file, ractl->mapping, ra_pages); 457038c8a9a5SSteve French 457138c8a9a5SSteve French /* 457238c8a9a5SSteve French * Chop the readahead request up into rsize-sized read requests. 457338c8a9a5SSteve French */ 457438c8a9a5SSteve French while ((nr_pages = ra_pages)) { 457538c8a9a5SSteve French unsigned int i, rsize; 457638c8a9a5SSteve French struct cifs_readdata *rdata; 457738c8a9a5SSteve French struct cifs_credits credits_on_stack; 457838c8a9a5SSteve French struct cifs_credits *credits = &credits_on_stack; 457938c8a9a5SSteve French struct folio *folio; 458038c8a9a5SSteve French pgoff_t fsize; 458138c8a9a5SSteve French 458238c8a9a5SSteve French /* 458338c8a9a5SSteve French * Find out if we have anything cached in the range of 458438c8a9a5SSteve French * interest, and if so, where the next chunk of cached data is. 458538c8a9a5SSteve French */ 458638c8a9a5SSteve French if (caching) { 458738c8a9a5SSteve French if (check_cache) { 458838c8a9a5SSteve French rc = cifs_fscache_query_occupancy( 458938c8a9a5SSteve French ractl->mapping->host, ra_index, nr_pages, 459038c8a9a5SSteve French &next_cached, &cache_nr_pages); 459138c8a9a5SSteve French if (rc < 0) 459238c8a9a5SSteve French caching = false; 459338c8a9a5SSteve French check_cache = false; 459438c8a9a5SSteve French } 459538c8a9a5SSteve French 459638c8a9a5SSteve French if (ra_index == next_cached) { 459738c8a9a5SSteve French /* 459838c8a9a5SSteve French * TODO: Send a whole batch of pages to be read 459938c8a9a5SSteve French * by the cache. 460038c8a9a5SSteve French */ 460138c8a9a5SSteve French folio = readahead_folio(ractl); 460238c8a9a5SSteve French fsize = folio_nr_pages(folio); 460338c8a9a5SSteve French ra_pages -= fsize; 460438c8a9a5SSteve French ra_index += fsize; 460538c8a9a5SSteve French if (cifs_readpage_from_fscache(ractl->mapping->host, 460638c8a9a5SSteve French &folio->page) < 0) { 460738c8a9a5SSteve French /* 460838c8a9a5SSteve French * TODO: Deal with cache read failure 460938c8a9a5SSteve French * here, but for the moment, delegate 461038c8a9a5SSteve French * that to readpage. 461138c8a9a5SSteve French */ 461238c8a9a5SSteve French caching = false; 461338c8a9a5SSteve French } 461438c8a9a5SSteve French folio_unlock(folio); 461538c8a9a5SSteve French next_cached += fsize; 461638c8a9a5SSteve French cache_nr_pages -= fsize; 461738c8a9a5SSteve French if (cache_nr_pages == 0) 461838c8a9a5SSteve French check_cache = true; 461938c8a9a5SSteve French continue; 462038c8a9a5SSteve French } 462138c8a9a5SSteve French } 462238c8a9a5SSteve French 462338c8a9a5SSteve French if (open_file->invalidHandle) { 462438c8a9a5SSteve French rc = cifs_reopen_file(open_file, true); 462538c8a9a5SSteve French if (rc) { 462638c8a9a5SSteve French if (rc == -EAGAIN) 462738c8a9a5SSteve French continue; 462838c8a9a5SSteve French break; 462938c8a9a5SSteve French } 463038c8a9a5SSteve French } 463138c8a9a5SSteve French 463238c8a9a5SSteve French if (cifs_sb->ctx->rsize == 0) 463338c8a9a5SSteve French cifs_sb->ctx->rsize = 463438c8a9a5SSteve French server->ops->negotiate_rsize(tlink_tcon(open_file->tlink), 463538c8a9a5SSteve French cifs_sb->ctx); 463638c8a9a5SSteve French 463738c8a9a5SSteve French rc = server->ops->wait_mtu_credits(server, cifs_sb->ctx->rsize, 463838c8a9a5SSteve French &rsize, credits); 463938c8a9a5SSteve French if (rc) 464038c8a9a5SSteve French break; 464138c8a9a5SSteve French nr_pages = min_t(size_t, rsize / PAGE_SIZE, ra_pages); 464238c8a9a5SSteve French if (next_cached != ULONG_MAX) 464338c8a9a5SSteve French nr_pages = min_t(size_t, nr_pages, next_cached - ra_index); 464438c8a9a5SSteve French 464538c8a9a5SSteve French /* 464638c8a9a5SSteve French * Give up immediately if rsize is too small to read an entire 464738c8a9a5SSteve French * page. The VFS will fall back to readpage. We should never 464838c8a9a5SSteve French * reach this point however since we set ra_pages to 0 when the 464938c8a9a5SSteve French * rsize is smaller than a cache page. 465038c8a9a5SSteve French */ 465138c8a9a5SSteve French if (unlikely(!nr_pages)) { 465238c8a9a5SSteve French add_credits_and_wake_if(server, credits, 0); 465338c8a9a5SSteve French break; 465438c8a9a5SSteve French } 465538c8a9a5SSteve French 465638c8a9a5SSteve French rdata = cifs_readdata_alloc(cifs_readahead_complete); 465738c8a9a5SSteve French if (!rdata) { 465838c8a9a5SSteve French /* best to give up if we're out of mem */ 465938c8a9a5SSteve French add_credits_and_wake_if(server, credits, 0); 466038c8a9a5SSteve French break; 466138c8a9a5SSteve French } 466238c8a9a5SSteve French 466338c8a9a5SSteve French rdata->offset = ra_index * PAGE_SIZE; 466438c8a9a5SSteve French rdata->bytes = nr_pages * PAGE_SIZE; 466538c8a9a5SSteve French rdata->cfile = cifsFileInfo_get(open_file); 466638c8a9a5SSteve French rdata->server = server; 466738c8a9a5SSteve French rdata->mapping = ractl->mapping; 466838c8a9a5SSteve French rdata->pid = pid; 466938c8a9a5SSteve French rdata->credits = credits_on_stack; 467038c8a9a5SSteve French 467138c8a9a5SSteve French for (i = 0; i < nr_pages; i++) { 467238c8a9a5SSteve French if (!readahead_folio(ractl)) 467338c8a9a5SSteve French WARN_ON(1); 467438c8a9a5SSteve French } 467538c8a9a5SSteve French ra_pages -= nr_pages; 467638c8a9a5SSteve French ra_index += nr_pages; 467738c8a9a5SSteve French 467838c8a9a5SSteve French iov_iter_xarray(&rdata->iter, ITER_DEST, &rdata->mapping->i_pages, 467938c8a9a5SSteve French rdata->offset, rdata->bytes); 468038c8a9a5SSteve French 468138c8a9a5SSteve French rc = adjust_credits(server, &rdata->credits, rdata->bytes); 468238c8a9a5SSteve French if (!rc) { 468338c8a9a5SSteve French if (rdata->cfile->invalidHandle) 468438c8a9a5SSteve French rc = -EAGAIN; 468538c8a9a5SSteve French else 468638c8a9a5SSteve French rc = server->ops->async_readv(rdata); 468738c8a9a5SSteve French } 468838c8a9a5SSteve French 468938c8a9a5SSteve French if (rc) { 469038c8a9a5SSteve French add_credits_and_wake_if(server, &rdata->credits, 0); 469138c8a9a5SSteve French cifs_unlock_folios(rdata->mapping, 469238c8a9a5SSteve French rdata->offset / PAGE_SIZE, 469338c8a9a5SSteve French (rdata->offset + rdata->bytes - 1) / PAGE_SIZE); 469438c8a9a5SSteve French /* Fallback to the readpage in error/reconnect cases */ 469538c8a9a5SSteve French kref_put(&rdata->refcount, cifs_readdata_release); 469638c8a9a5SSteve French break; 469738c8a9a5SSteve French } 469838c8a9a5SSteve French 469938c8a9a5SSteve French kref_put(&rdata->refcount, cifs_readdata_release); 470038c8a9a5SSteve French } 470138c8a9a5SSteve French 470238c8a9a5SSteve French free_xid(xid); 470338c8a9a5SSteve French } 470438c8a9a5SSteve French 470538c8a9a5SSteve French /* 470638c8a9a5SSteve French * cifs_readpage_worker must be called with the page pinned 470738c8a9a5SSteve French */ 470838c8a9a5SSteve French static int cifs_readpage_worker(struct file *file, struct page *page, 470938c8a9a5SSteve French loff_t *poffset) 471038c8a9a5SSteve French { 471123171df5SJeff Layton struct inode *inode = file_inode(file); 471223171df5SJeff Layton struct timespec64 atime, mtime; 471338c8a9a5SSteve French char *read_data; 471438c8a9a5SSteve French int rc; 471538c8a9a5SSteve French 471638c8a9a5SSteve French /* Is the page cached? */ 471723171df5SJeff Layton rc = cifs_readpage_from_fscache(inode, page); 471838c8a9a5SSteve French if (rc == 0) 471938c8a9a5SSteve French goto read_complete; 472038c8a9a5SSteve French 472138c8a9a5SSteve French read_data = kmap(page); 472238c8a9a5SSteve French /* for reads over a certain size could initiate async read ahead */ 472338c8a9a5SSteve French 472438c8a9a5SSteve French rc = cifs_read(file, read_data, PAGE_SIZE, poffset); 472538c8a9a5SSteve French 472638c8a9a5SSteve French if (rc < 0) 472738c8a9a5SSteve French goto io_error; 472838c8a9a5SSteve French else 472938c8a9a5SSteve French cifs_dbg(FYI, "Bytes read %d\n", rc); 473038c8a9a5SSteve French 473138c8a9a5SSteve French /* we do not want atime to be less than mtime, it broke some apps */ 473223171df5SJeff Layton atime = inode_set_atime_to_ts(inode, current_time(inode)); 473323171df5SJeff Layton mtime = inode_get_mtime(inode); 47349a498744SZizhi Wo if (timespec64_compare(&atime, &mtime) < 0) 473523171df5SJeff Layton inode_set_atime_to_ts(inode, inode_get_mtime(inode)); 473638c8a9a5SSteve French 473738c8a9a5SSteve French if (PAGE_SIZE > rc) 473838c8a9a5SSteve French memset(read_data + rc, 0, PAGE_SIZE - rc); 473938c8a9a5SSteve French 474038c8a9a5SSteve French flush_dcache_page(page); 474138c8a9a5SSteve French SetPageUptodate(page); 474238c8a9a5SSteve French rc = 0; 474338c8a9a5SSteve French 474438c8a9a5SSteve French io_error: 474538c8a9a5SSteve French kunmap(page); 474638c8a9a5SSteve French 474738c8a9a5SSteve French read_complete: 474869513dd6SRussell Harmon via samba-technical unlock_page(page); 474938c8a9a5SSteve French return rc; 475038c8a9a5SSteve French } 475138c8a9a5SSteve French 475238c8a9a5SSteve French static int cifs_read_folio(struct file *file, struct folio *folio) 475338c8a9a5SSteve French { 475438c8a9a5SSteve French struct page *page = &folio->page; 475538c8a9a5SSteve French loff_t offset = page_file_offset(page); 475638c8a9a5SSteve French int rc = -EACCES; 475738c8a9a5SSteve French unsigned int xid; 475838c8a9a5SSteve French 475938c8a9a5SSteve French xid = get_xid(); 476038c8a9a5SSteve French 476138c8a9a5SSteve French if (file->private_data == NULL) { 476238c8a9a5SSteve French rc = -EBADF; 476338c8a9a5SSteve French free_xid(xid); 476438c8a9a5SSteve French return rc; 476538c8a9a5SSteve French } 476638c8a9a5SSteve French 476738c8a9a5SSteve French cifs_dbg(FYI, "read_folio %p at offset %d 0x%x\n", 476838c8a9a5SSteve French page, (int)offset, (int)offset); 476938c8a9a5SSteve French 477038c8a9a5SSteve French rc = cifs_readpage_worker(file, page, &offset); 477138c8a9a5SSteve French 477238c8a9a5SSteve French free_xid(xid); 477338c8a9a5SSteve French return rc; 477438c8a9a5SSteve French } 477538c8a9a5SSteve French 477638c8a9a5SSteve French static int is_inode_writable(struct cifsInodeInfo *cifs_inode) 477738c8a9a5SSteve French { 477838c8a9a5SSteve French struct cifsFileInfo *open_file; 477938c8a9a5SSteve French 478038c8a9a5SSteve French spin_lock(&cifs_inode->open_file_lock); 478138c8a9a5SSteve French list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { 478238c8a9a5SSteve French if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { 478338c8a9a5SSteve French spin_unlock(&cifs_inode->open_file_lock); 478438c8a9a5SSteve French return 1; 478538c8a9a5SSteve French } 478638c8a9a5SSteve French } 478738c8a9a5SSteve French spin_unlock(&cifs_inode->open_file_lock); 478838c8a9a5SSteve French return 0; 478938c8a9a5SSteve French } 479038c8a9a5SSteve French 479138c8a9a5SSteve French /* We do not want to update the file size from server for inodes 479238c8a9a5SSteve French open for write - to avoid races with writepage extending 479338c8a9a5SSteve French the file - in the future we could consider allowing 479438c8a9a5SSteve French refreshing the inode only on increases in the file size 479538c8a9a5SSteve French but this is tricky to do without racing with writebehind 479638c8a9a5SSteve French page caching in the current Linux kernel design */ 47979179aa27SBharath SM bool is_size_safe_to_change(struct cifsInodeInfo *cifsInode, __u64 end_of_file, 47989179aa27SBharath SM bool from_readdir) 479938c8a9a5SSteve French { 480038c8a9a5SSteve French if (!cifsInode) 480138c8a9a5SSteve French return true; 480238c8a9a5SSteve French 48039179aa27SBharath SM if (is_inode_writable(cifsInode) || 48049179aa27SBharath SM ((cifsInode->oplock & CIFS_CACHE_RW_FLG) != 0 && from_readdir)) { 480538c8a9a5SSteve French /* This inode is open for write at least once */ 480638c8a9a5SSteve French struct cifs_sb_info *cifs_sb; 480738c8a9a5SSteve French 480838c8a9a5SSteve French cifs_sb = CIFS_SB(cifsInode->netfs.inode.i_sb); 480938c8a9a5SSteve French if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) { 481038c8a9a5SSteve French /* since no page cache to corrupt on directio 481138c8a9a5SSteve French we can change size safely */ 481238c8a9a5SSteve French return true; 481338c8a9a5SSteve French } 481438c8a9a5SSteve French 481538c8a9a5SSteve French if (i_size_read(&cifsInode->netfs.inode) < end_of_file) 481638c8a9a5SSteve French return true; 481738c8a9a5SSteve French 481838c8a9a5SSteve French return false; 481938c8a9a5SSteve French } else 482038c8a9a5SSteve French return true; 482138c8a9a5SSteve French } 482238c8a9a5SSteve French 482338c8a9a5SSteve French static int cifs_write_begin(struct file *file, struct address_space *mapping, 482438c8a9a5SSteve French loff_t pos, unsigned len, 482538c8a9a5SSteve French struct page **pagep, void **fsdata) 482638c8a9a5SSteve French { 482738c8a9a5SSteve French int oncethru = 0; 482838c8a9a5SSteve French pgoff_t index = pos >> PAGE_SHIFT; 482938c8a9a5SSteve French loff_t offset = pos & (PAGE_SIZE - 1); 483038c8a9a5SSteve French loff_t page_start = pos & PAGE_MASK; 483138c8a9a5SSteve French loff_t i_size; 483238c8a9a5SSteve French struct page *page; 483338c8a9a5SSteve French int rc = 0; 483438c8a9a5SSteve French 483538c8a9a5SSteve French cifs_dbg(FYI, "write_begin from %lld len %d\n", (long long)pos, len); 483638c8a9a5SSteve French 483738c8a9a5SSteve French start: 483838c8a9a5SSteve French page = grab_cache_page_write_begin(mapping, index); 483938c8a9a5SSteve French if (!page) { 484038c8a9a5SSteve French rc = -ENOMEM; 484138c8a9a5SSteve French goto out; 484238c8a9a5SSteve French } 484338c8a9a5SSteve French 484438c8a9a5SSteve French if (PageUptodate(page)) 484538c8a9a5SSteve French goto out; 484638c8a9a5SSteve French 484738c8a9a5SSteve French /* 484838c8a9a5SSteve French * If we write a full page it will be up to date, no need to read from 484938c8a9a5SSteve French * the server. If the write is short, we'll end up doing a sync write 485038c8a9a5SSteve French * instead. 485138c8a9a5SSteve French */ 485238c8a9a5SSteve French if (len == PAGE_SIZE) 485338c8a9a5SSteve French goto out; 485438c8a9a5SSteve French 485538c8a9a5SSteve French /* 485638c8a9a5SSteve French * optimize away the read when we have an oplock, and we're not 485738c8a9a5SSteve French * expecting to use any of the data we'd be reading in. That 485838c8a9a5SSteve French * is, when the page lies beyond the EOF, or straddles the EOF 485938c8a9a5SSteve French * and the write will cover all of the existing data. 486038c8a9a5SSteve French */ 486138c8a9a5SSteve French if (CIFS_CACHE_READ(CIFS_I(mapping->host))) { 486238c8a9a5SSteve French i_size = i_size_read(mapping->host); 486338c8a9a5SSteve French if (page_start >= i_size || 486438c8a9a5SSteve French (offset == 0 && (pos + len) >= i_size)) { 486538c8a9a5SSteve French zero_user_segments(page, 0, offset, 486638c8a9a5SSteve French offset + len, 486738c8a9a5SSteve French PAGE_SIZE); 486838c8a9a5SSteve French /* 486938c8a9a5SSteve French * PageChecked means that the parts of the page 487038c8a9a5SSteve French * to which we're not writing are considered up 487138c8a9a5SSteve French * to date. Once the data is copied to the 487238c8a9a5SSteve French * page, it can be set uptodate. 487338c8a9a5SSteve French */ 487438c8a9a5SSteve French SetPageChecked(page); 487538c8a9a5SSteve French goto out; 487638c8a9a5SSteve French } 487738c8a9a5SSteve French } 487838c8a9a5SSteve French 487938c8a9a5SSteve French if ((file->f_flags & O_ACCMODE) != O_WRONLY && !oncethru) { 488038c8a9a5SSteve French /* 488138c8a9a5SSteve French * might as well read a page, it is fast enough. If we get 488238c8a9a5SSteve French * an error, we don't need to return it. cifs_write_end will 488338c8a9a5SSteve French * do a sync write instead since PG_uptodate isn't set. 488438c8a9a5SSteve French */ 488538c8a9a5SSteve French cifs_readpage_worker(file, page, &page_start); 488638c8a9a5SSteve French put_page(page); 488738c8a9a5SSteve French oncethru = 1; 488838c8a9a5SSteve French goto start; 488938c8a9a5SSteve French } else { 489038c8a9a5SSteve French /* we could try using another file handle if there is one - 489138c8a9a5SSteve French but how would we lock it to prevent close of that handle 489238c8a9a5SSteve French racing with this read? In any case 489338c8a9a5SSteve French this will be written out by write_end so is fine */ 489438c8a9a5SSteve French } 489538c8a9a5SSteve French out: 489638c8a9a5SSteve French *pagep = page; 489738c8a9a5SSteve French return rc; 489838c8a9a5SSteve French } 489938c8a9a5SSteve French 490038c8a9a5SSteve French static bool cifs_release_folio(struct folio *folio, gfp_t gfp) 490138c8a9a5SSteve French { 490238c8a9a5SSteve French if (folio_test_private(folio)) 490338c8a9a5SSteve French return 0; 490438c8a9a5SSteve French if (folio_test_fscache(folio)) { 490538c8a9a5SSteve French if (current_is_kswapd() || !(gfp & __GFP_FS)) 490638c8a9a5SSteve French return false; 490738c8a9a5SSteve French folio_wait_fscache(folio); 490838c8a9a5SSteve French } 490938c8a9a5SSteve French fscache_note_page_release(cifs_inode_cookie(folio->mapping->host)); 491038c8a9a5SSteve French return true; 491138c8a9a5SSteve French } 491238c8a9a5SSteve French 491338c8a9a5SSteve French static void cifs_invalidate_folio(struct folio *folio, size_t offset, 491438c8a9a5SSteve French size_t length) 491538c8a9a5SSteve French { 491638c8a9a5SSteve French folio_wait_fscache(folio); 491738c8a9a5SSteve French } 491838c8a9a5SSteve French 491938c8a9a5SSteve French static int cifs_launder_folio(struct folio *folio) 492038c8a9a5SSteve French { 492138c8a9a5SSteve French int rc = 0; 492238c8a9a5SSteve French loff_t range_start = folio_pos(folio); 492338c8a9a5SSteve French loff_t range_end = range_start + folio_size(folio); 492438c8a9a5SSteve French struct writeback_control wbc = { 492538c8a9a5SSteve French .sync_mode = WB_SYNC_ALL, 492638c8a9a5SSteve French .nr_to_write = 0, 492738c8a9a5SSteve French .range_start = range_start, 492838c8a9a5SSteve French .range_end = range_end, 492938c8a9a5SSteve French }; 493038c8a9a5SSteve French 493138c8a9a5SSteve French cifs_dbg(FYI, "Launder page: %lu\n", folio->index); 493238c8a9a5SSteve French 493338c8a9a5SSteve French if (folio_clear_dirty_for_io(folio)) 493438c8a9a5SSteve French rc = cifs_writepage_locked(&folio->page, &wbc); 493538c8a9a5SSteve French 493638c8a9a5SSteve French folio_wait_fscache(folio); 493738c8a9a5SSteve French return rc; 493838c8a9a5SSteve French } 493938c8a9a5SSteve French 494038c8a9a5SSteve French void cifs_oplock_break(struct work_struct *work) 494138c8a9a5SSteve French { 494238c8a9a5SSteve French struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, 494338c8a9a5SSteve French oplock_break); 494438c8a9a5SSteve French struct inode *inode = d_inode(cfile->dentry); 4945e8f5f849SSteve French struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); 494638c8a9a5SSteve French struct cifsInodeInfo *cinode = CIFS_I(inode); 4947e8f5f849SSteve French struct cifs_tcon *tcon; 4948e8f5f849SSteve French struct TCP_Server_Info *server; 4949e8f5f849SSteve French struct tcon_link *tlink; 495038c8a9a5SSteve French int rc = 0; 495138c8a9a5SSteve French bool purge_cache = false, oplock_break_cancelled; 495238c8a9a5SSteve French __u64 persistent_fid, volatile_fid; 495338c8a9a5SSteve French __u16 net_fid; 495438c8a9a5SSteve French 495538c8a9a5SSteve French wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS, 495638c8a9a5SSteve French TASK_UNINTERRUPTIBLE); 495738c8a9a5SSteve French 4958e8f5f849SSteve French tlink = cifs_sb_tlink(cifs_sb); 4959e8f5f849SSteve French if (IS_ERR(tlink)) 4960e8f5f849SSteve French goto out; 4961e8f5f849SSteve French tcon = tlink_tcon(tlink); 4962e8f5f849SSteve French server = tcon->ses->server; 4963e8f5f849SSteve French 496438c8a9a5SSteve French server->ops->downgrade_oplock(server, cinode, cfile->oplock_level, 496538c8a9a5SSteve French cfile->oplock_epoch, &purge_cache); 496638c8a9a5SSteve French 496738c8a9a5SSteve French if (!CIFS_CACHE_WRITE(cinode) && CIFS_CACHE_READ(cinode) && 496838c8a9a5SSteve French cifs_has_mand_locks(cinode)) { 496938c8a9a5SSteve French cifs_dbg(FYI, "Reset oplock to None for inode=%p due to mand locks\n", 497038c8a9a5SSteve French inode); 497138c8a9a5SSteve French cinode->oplock = 0; 497238c8a9a5SSteve French } 497338c8a9a5SSteve French 497438c8a9a5SSteve French if (inode && S_ISREG(inode->i_mode)) { 497538c8a9a5SSteve French if (CIFS_CACHE_READ(cinode)) 497638c8a9a5SSteve French break_lease(inode, O_RDONLY); 497738c8a9a5SSteve French else 497838c8a9a5SSteve French break_lease(inode, O_WRONLY); 497938c8a9a5SSteve French rc = filemap_fdatawrite(inode->i_mapping); 498038c8a9a5SSteve French if (!CIFS_CACHE_READ(cinode) || purge_cache) { 498138c8a9a5SSteve French rc = filemap_fdatawait(inode->i_mapping); 498238c8a9a5SSteve French mapping_set_error(inode->i_mapping, rc); 498338c8a9a5SSteve French cifs_zap_mapping(inode); 498438c8a9a5SSteve French } 498538c8a9a5SSteve French cifs_dbg(FYI, "Oplock flush inode %p rc %d\n", inode, rc); 498638c8a9a5SSteve French if (CIFS_CACHE_WRITE(cinode)) 498738c8a9a5SSteve French goto oplock_break_ack; 498838c8a9a5SSteve French } 498938c8a9a5SSteve French 499038c8a9a5SSteve French rc = cifs_push_locks(cfile); 499138c8a9a5SSteve French if (rc) 499238c8a9a5SSteve French cifs_dbg(VFS, "Push locks rc = %d\n", rc); 499338c8a9a5SSteve French 499438c8a9a5SSteve French oplock_break_ack: 499538c8a9a5SSteve French /* 499638c8a9a5SSteve French * When oplock break is received and there are no active 499738c8a9a5SSteve French * file handles but cached, then schedule deferred close immediately. 499838c8a9a5SSteve French * So, new open will not use cached handle. 499938c8a9a5SSteve French */ 500038c8a9a5SSteve French 500138c8a9a5SSteve French if (!CIFS_CACHE_HANDLE(cinode) && !list_empty(&cinode->deferred_closes)) 500238c8a9a5SSteve French cifs_close_deferred_file(cinode); 500338c8a9a5SSteve French 500438c8a9a5SSteve French persistent_fid = cfile->fid.persistent_fid; 500538c8a9a5SSteve French volatile_fid = cfile->fid.volatile_fid; 500638c8a9a5SSteve French net_fid = cfile->fid.netfid; 500738c8a9a5SSteve French oplock_break_cancelled = cfile->oplock_break_cancelled; 500838c8a9a5SSteve French 500938c8a9a5SSteve French _cifsFileInfo_put(cfile, false /* do not wait for ourself */, false); 501038c8a9a5SSteve French /* 5011da787d5bSBharath SM * MS-SMB2 3.2.5.19.1 and 3.2.5.19.2 (and MS-CIFS 3.2.5.42) do not require 5012da787d5bSBharath SM * an acknowledgment to be sent when the file has already been closed. 501338c8a9a5SSteve French */ 5014da787d5bSBharath SM spin_lock(&cinode->open_file_lock); 5015e8f5f849SSteve French /* check list empty since can race with kill_sb calling tree disconnect */ 5016e8f5f849SSteve French if (!oplock_break_cancelled && !list_empty(&cinode->openFileList)) { 5017da787d5bSBharath SM spin_unlock(&cinode->open_file_lock); 5018e8f5f849SSteve French rc = server->ops->oplock_response(tcon, persistent_fid, 501938c8a9a5SSteve French volatile_fid, net_fid, cinode); 502038c8a9a5SSteve French cifs_dbg(FYI, "Oplock release rc = %d\n", rc); 5021c774e677SSteve French } else 5022da787d5bSBharath SM spin_unlock(&cinode->open_file_lock); 502338c8a9a5SSteve French 5024e8f5f849SSteve French cifs_put_tlink(tlink); 5025e8f5f849SSteve French out: 502638c8a9a5SSteve French cifs_done_oplock_break(cinode); 502738c8a9a5SSteve French } 502838c8a9a5SSteve French 502938c8a9a5SSteve French /* 503038c8a9a5SSteve French * The presence of cifs_direct_io() in the address space ops vector 503138c8a9a5SSteve French * allowes open() O_DIRECT flags which would have failed otherwise. 503238c8a9a5SSteve French * 503338c8a9a5SSteve French * In the non-cached mode (mount with cache=none), we shunt off direct read and write requests 503438c8a9a5SSteve French * so this method should never be called. 503538c8a9a5SSteve French * 503638c8a9a5SSteve French * Direct IO is not yet supported in the cached mode. 503738c8a9a5SSteve French */ 503838c8a9a5SSteve French static ssize_t 503938c8a9a5SSteve French cifs_direct_io(struct kiocb *iocb, struct iov_iter *iter) 504038c8a9a5SSteve French { 504138c8a9a5SSteve French /* 504238c8a9a5SSteve French * FIXME 504338c8a9a5SSteve French * Eventually need to support direct IO for non forcedirectio mounts 504438c8a9a5SSteve French */ 504538c8a9a5SSteve French return -EINVAL; 504638c8a9a5SSteve French } 504738c8a9a5SSteve French 504838c8a9a5SSteve French static int cifs_swap_activate(struct swap_info_struct *sis, 504938c8a9a5SSteve French struct file *swap_file, sector_t *span) 505038c8a9a5SSteve French { 505138c8a9a5SSteve French struct cifsFileInfo *cfile = swap_file->private_data; 505238c8a9a5SSteve French struct inode *inode = swap_file->f_mapping->host; 505338c8a9a5SSteve French unsigned long blocks; 505438c8a9a5SSteve French long long isize; 505538c8a9a5SSteve French 505638c8a9a5SSteve French cifs_dbg(FYI, "swap activate\n"); 505738c8a9a5SSteve French 505838c8a9a5SSteve French if (!swap_file->f_mapping->a_ops->swap_rw) 505938c8a9a5SSteve French /* Cannot support swap */ 506038c8a9a5SSteve French return -EINVAL; 506138c8a9a5SSteve French 506238c8a9a5SSteve French spin_lock(&inode->i_lock); 506338c8a9a5SSteve French blocks = inode->i_blocks; 506438c8a9a5SSteve French isize = inode->i_size; 506538c8a9a5SSteve French spin_unlock(&inode->i_lock); 506638c8a9a5SSteve French if (blocks*512 < isize) { 506738c8a9a5SSteve French pr_warn("swap activate: swapfile has holes\n"); 506838c8a9a5SSteve French return -EINVAL; 506938c8a9a5SSteve French } 507038c8a9a5SSteve French *span = sis->pages; 507138c8a9a5SSteve French 507238c8a9a5SSteve French pr_warn_once("Swap support over SMB3 is experimental\n"); 507338c8a9a5SSteve French 507438c8a9a5SSteve French /* 507538c8a9a5SSteve French * TODO: consider adding ACL (or documenting how) to prevent other 507638c8a9a5SSteve French * users (on this or other systems) from reading it 507738c8a9a5SSteve French */ 507838c8a9a5SSteve French 507938c8a9a5SSteve French 508038c8a9a5SSteve French /* TODO: add sk_set_memalloc(inet) or similar */ 508138c8a9a5SSteve French 508238c8a9a5SSteve French if (cfile) 508338c8a9a5SSteve French cfile->swapfile = true; 508438c8a9a5SSteve French /* 508538c8a9a5SSteve French * TODO: Since file already open, we can't open with DENY_ALL here 508638c8a9a5SSteve French * but we could add call to grab a byte range lock to prevent others 508738c8a9a5SSteve French * from reading or writing the file 508838c8a9a5SSteve French */ 508938c8a9a5SSteve French 509038c8a9a5SSteve French sis->flags |= SWP_FS_OPS; 509138c8a9a5SSteve French return add_swap_extent(sis, 0, sis->max, 0); 509238c8a9a5SSteve French } 509338c8a9a5SSteve French 509438c8a9a5SSteve French static void cifs_swap_deactivate(struct file *file) 509538c8a9a5SSteve French { 509638c8a9a5SSteve French struct cifsFileInfo *cfile = file->private_data; 509738c8a9a5SSteve French 509838c8a9a5SSteve French cifs_dbg(FYI, "swap deactivate\n"); 509938c8a9a5SSteve French 510038c8a9a5SSteve French /* TODO: undo sk_set_memalloc(inet) will eventually be needed */ 510138c8a9a5SSteve French 510238c8a9a5SSteve French if (cfile) 510338c8a9a5SSteve French cfile->swapfile = false; 510438c8a9a5SSteve French 510538c8a9a5SSteve French /* do we need to unpin (or unlock) the file */ 510638c8a9a5SSteve French } 510738c8a9a5SSteve French 510838c8a9a5SSteve French /* 510938c8a9a5SSteve French * Mark a page as having been made dirty and thus needing writeback. We also 511038c8a9a5SSteve French * need to pin the cache object to write back to. 511138c8a9a5SSteve French */ 511238c8a9a5SSteve French #ifdef CONFIG_CIFS_FSCACHE 511338c8a9a5SSteve French static bool cifs_dirty_folio(struct address_space *mapping, struct folio *folio) 511438c8a9a5SSteve French { 511538c8a9a5SSteve French return fscache_dirty_folio(mapping, folio, 511638c8a9a5SSteve French cifs_inode_cookie(mapping->host)); 511738c8a9a5SSteve French } 511838c8a9a5SSteve French #else 511938c8a9a5SSteve French #define cifs_dirty_folio filemap_dirty_folio 512038c8a9a5SSteve French #endif 512138c8a9a5SSteve French 512238c8a9a5SSteve French const struct address_space_operations cifs_addr_ops = { 512338c8a9a5SSteve French .read_folio = cifs_read_folio, 512438c8a9a5SSteve French .readahead = cifs_readahead, 512538c8a9a5SSteve French .writepages = cifs_writepages, 512638c8a9a5SSteve French .write_begin = cifs_write_begin, 512738c8a9a5SSteve French .write_end = cifs_write_end, 512838c8a9a5SSteve French .dirty_folio = cifs_dirty_folio, 512938c8a9a5SSteve French .release_folio = cifs_release_folio, 513038c8a9a5SSteve French .direct_IO = cifs_direct_io, 513138c8a9a5SSteve French .invalidate_folio = cifs_invalidate_folio, 513238c8a9a5SSteve French .launder_folio = cifs_launder_folio, 513338c8a9a5SSteve French .migrate_folio = filemap_migrate_folio, 513438c8a9a5SSteve French /* 513538c8a9a5SSteve French * TODO: investigate and if useful we could add an is_dirty_writeback 513638c8a9a5SSteve French * helper if needed 513738c8a9a5SSteve French */ 513838c8a9a5SSteve French .swap_activate = cifs_swap_activate, 513938c8a9a5SSteve French .swap_deactivate = cifs_swap_deactivate, 514038c8a9a5SSteve French }; 514138c8a9a5SSteve French 514238c8a9a5SSteve French /* 514338c8a9a5SSteve French * cifs_readahead requires the server to support a buffer large enough to 514438c8a9a5SSteve French * contain the header plus one complete page of data. Otherwise, we need 514538c8a9a5SSteve French * to leave cifs_readahead out of the address space operations. 514638c8a9a5SSteve French */ 514738c8a9a5SSteve French const struct address_space_operations cifs_addr_ops_smallbuf = { 514838c8a9a5SSteve French .read_folio = cifs_read_folio, 514938c8a9a5SSteve French .writepages = cifs_writepages, 515038c8a9a5SSteve French .write_begin = cifs_write_begin, 515138c8a9a5SSteve French .write_end = cifs_write_end, 515238c8a9a5SSteve French .dirty_folio = cifs_dirty_folio, 515338c8a9a5SSteve French .release_folio = cifs_release_folio, 515438c8a9a5SSteve French .invalidate_folio = cifs_invalidate_folio, 515538c8a9a5SSteve French .launder_folio = cifs_launder_folio, 515638c8a9a5SSteve French .migrate_folio = filemap_migrate_folio, 515738c8a9a5SSteve French }; 5158