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