xref: /openbmc/linux/fs/smb/client/file.c (revision 0fdada1e)
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