18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci  FUSE: Filesystem in Userspace
38c2ecf20Sopenharmony_ci  Copyright (C) 2001-2008  Miklos Szeredi <miklos@szeredi.hu>
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci  This program can be distributed under the terms of the GNU GPL.
68c2ecf20Sopenharmony_ci  See the file COPYING.
78c2ecf20Sopenharmony_ci*/
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include "fuse_i.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/pagemap.h>
128c2ecf20Sopenharmony_ci#include <linux/slab.h>
138c2ecf20Sopenharmony_ci#include <linux/kernel.h>
148c2ecf20Sopenharmony_ci#include <linux/sched.h>
158c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
168c2ecf20Sopenharmony_ci#include <linux/module.h>
178c2ecf20Sopenharmony_ci#include <linux/compat.h>
188c2ecf20Sopenharmony_ci#include <linux/swap.h>
198c2ecf20Sopenharmony_ci#include <linux/falloc.h>
208c2ecf20Sopenharmony_ci#include <linux/uio.h>
218c2ecf20Sopenharmony_ci#include <linux/fs.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_cistatic struct page **fuse_pages_alloc(unsigned int npages, gfp_t flags,
248c2ecf20Sopenharmony_ci				      struct fuse_page_desc **desc)
258c2ecf20Sopenharmony_ci{
268c2ecf20Sopenharmony_ci	struct page **pages;
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci	pages = kzalloc(npages * (sizeof(struct page *) +
298c2ecf20Sopenharmony_ci				  sizeof(struct fuse_page_desc)), flags);
308c2ecf20Sopenharmony_ci	*desc = (void *) (pages + npages);
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	return pages;
338c2ecf20Sopenharmony_ci}
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistatic int fuse_send_open(struct fuse_mount *fm, u64 nodeid, struct file *file,
368c2ecf20Sopenharmony_ci			  int opcode, struct fuse_open_out *outargp)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	struct fuse_open_in inarg;
398c2ecf20Sopenharmony_ci	FUSE_ARGS(args);
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	memset(&inarg, 0, sizeof(inarg));
428c2ecf20Sopenharmony_ci	inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY);
438c2ecf20Sopenharmony_ci	if (!fm->fc->atomic_o_trunc)
448c2ecf20Sopenharmony_ci		inarg.flags &= ~O_TRUNC;
458c2ecf20Sopenharmony_ci	args.opcode = opcode;
468c2ecf20Sopenharmony_ci	args.nodeid = nodeid;
478c2ecf20Sopenharmony_ci	args.in_numargs = 1;
488c2ecf20Sopenharmony_ci	args.in_args[0].size = sizeof(inarg);
498c2ecf20Sopenharmony_ci	args.in_args[0].value = &inarg;
508c2ecf20Sopenharmony_ci	args.out_numargs = 1;
518c2ecf20Sopenharmony_ci	args.out_args[0].size = sizeof(*outargp);
528c2ecf20Sopenharmony_ci	args.out_args[0].value = outargp;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	return fuse_simple_request(fm, &args);
558c2ecf20Sopenharmony_ci}
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cistruct fuse_release_args {
588c2ecf20Sopenharmony_ci	struct fuse_args args;
598c2ecf20Sopenharmony_ci	struct fuse_release_in inarg;
608c2ecf20Sopenharmony_ci	struct inode *inode;
618c2ecf20Sopenharmony_ci};
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistruct fuse_file *fuse_file_alloc(struct fuse_mount *fm)
648c2ecf20Sopenharmony_ci{
658c2ecf20Sopenharmony_ci	struct fuse_file *ff;
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	ff = kzalloc(sizeof(struct fuse_file), GFP_KERNEL_ACCOUNT);
688c2ecf20Sopenharmony_ci	if (unlikely(!ff))
698c2ecf20Sopenharmony_ci		return NULL;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	ff->fm = fm;
728c2ecf20Sopenharmony_ci	ff->release_args = kzalloc(sizeof(*ff->release_args),
738c2ecf20Sopenharmony_ci				   GFP_KERNEL_ACCOUNT);
748c2ecf20Sopenharmony_ci	if (!ff->release_args) {
758c2ecf20Sopenharmony_ci		kfree(ff);
768c2ecf20Sopenharmony_ci		return NULL;
778c2ecf20Sopenharmony_ci	}
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&ff->write_entry);
808c2ecf20Sopenharmony_ci	mutex_init(&ff->readdir.lock);
818c2ecf20Sopenharmony_ci	refcount_set(&ff->count, 1);
828c2ecf20Sopenharmony_ci	RB_CLEAR_NODE(&ff->polled_node);
838c2ecf20Sopenharmony_ci	init_waitqueue_head(&ff->poll_wait);
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	ff->kh = atomic64_inc_return(&fm->fc->khctr);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	return ff;
888c2ecf20Sopenharmony_ci}
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_civoid fuse_file_free(struct fuse_file *ff)
918c2ecf20Sopenharmony_ci{
928c2ecf20Sopenharmony_ci	kfree(ff->release_args);
938c2ecf20Sopenharmony_ci	mutex_destroy(&ff->readdir.lock);
948c2ecf20Sopenharmony_ci	kfree(ff);
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistatic struct fuse_file *fuse_file_get(struct fuse_file *ff)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	refcount_inc(&ff->count);
1008c2ecf20Sopenharmony_ci	return ff;
1018c2ecf20Sopenharmony_ci}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistatic void fuse_release_end(struct fuse_mount *fm, struct fuse_args *args,
1048c2ecf20Sopenharmony_ci			     int error)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	struct fuse_release_args *ra = container_of(args, typeof(*ra), args);
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	iput(ra->inode);
1098c2ecf20Sopenharmony_ci	kfree(ra);
1108c2ecf20Sopenharmony_ci}
1118c2ecf20Sopenharmony_ci
1128c2ecf20Sopenharmony_cistatic void fuse_file_put(struct fuse_file *ff, bool sync, bool isdir)
1138c2ecf20Sopenharmony_ci{
1148c2ecf20Sopenharmony_ci	if (refcount_dec_and_test(&ff->count)) {
1158c2ecf20Sopenharmony_ci		struct fuse_args *args = &ff->release_args->args;
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci		if (isdir ? ff->fm->fc->no_opendir : ff->fm->fc->no_open) {
1188c2ecf20Sopenharmony_ci			/* Do nothing when client does not implement 'open' */
1198c2ecf20Sopenharmony_ci			fuse_release_end(ff->fm, args, 0);
1208c2ecf20Sopenharmony_ci		} else if (sync) {
1218c2ecf20Sopenharmony_ci			fuse_simple_request(ff->fm, args);
1228c2ecf20Sopenharmony_ci			fuse_release_end(ff->fm, args, 0);
1238c2ecf20Sopenharmony_ci		} else {
1248c2ecf20Sopenharmony_ci			args->end = fuse_release_end;
1258c2ecf20Sopenharmony_ci			if (fuse_simple_background(ff->fm, args,
1268c2ecf20Sopenharmony_ci						   GFP_KERNEL | __GFP_NOFAIL))
1278c2ecf20Sopenharmony_ci				fuse_release_end(ff->fm, args, -ENOTCONN);
1288c2ecf20Sopenharmony_ci		}
1298c2ecf20Sopenharmony_ci		kfree(ff);
1308c2ecf20Sopenharmony_ci	}
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ciint fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file,
1348c2ecf20Sopenharmony_ci		 bool isdir)
1358c2ecf20Sopenharmony_ci{
1368c2ecf20Sopenharmony_ci	struct fuse_conn *fc = fm->fc;
1378c2ecf20Sopenharmony_ci	struct fuse_file *ff;
1388c2ecf20Sopenharmony_ci	int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	ff = fuse_file_alloc(fm);
1418c2ecf20Sopenharmony_ci	if (!ff)
1428c2ecf20Sopenharmony_ci		return -ENOMEM;
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci	ff->fh = 0;
1458c2ecf20Sopenharmony_ci	/* Default for no-open */
1468c2ecf20Sopenharmony_ci	ff->open_flags = FOPEN_KEEP_CACHE | (isdir ? FOPEN_CACHE_DIR : 0);
1478c2ecf20Sopenharmony_ci	if (isdir ? !fc->no_opendir : !fc->no_open) {
1488c2ecf20Sopenharmony_ci		struct fuse_open_out outarg;
1498c2ecf20Sopenharmony_ci		int err;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci		err = fuse_send_open(fm, nodeid, file, opcode, &outarg);
1528c2ecf20Sopenharmony_ci		if (!err) {
1538c2ecf20Sopenharmony_ci			ff->fh = outarg.fh;
1548c2ecf20Sopenharmony_ci			ff->open_flags = outarg.open_flags;
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci		} else if (err != -ENOSYS) {
1578c2ecf20Sopenharmony_ci			fuse_file_free(ff);
1588c2ecf20Sopenharmony_ci			return err;
1598c2ecf20Sopenharmony_ci		} else {
1608c2ecf20Sopenharmony_ci			if (isdir)
1618c2ecf20Sopenharmony_ci				fc->no_opendir = 1;
1628c2ecf20Sopenharmony_ci			else
1638c2ecf20Sopenharmony_ci				fc->no_open = 1;
1648c2ecf20Sopenharmony_ci		}
1658c2ecf20Sopenharmony_ci	}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	if (isdir)
1688c2ecf20Sopenharmony_ci		ff->open_flags &= ~FOPEN_DIRECT_IO;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	ff->nodeid = nodeid;
1718c2ecf20Sopenharmony_ci	file->private_data = ff;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	return 0;
1748c2ecf20Sopenharmony_ci}
1758c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fuse_do_open);
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cistatic void fuse_link_write_file(struct file *file)
1788c2ecf20Sopenharmony_ci{
1798c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(file);
1808c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(inode);
1818c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
1828c2ecf20Sopenharmony_ci	/*
1838c2ecf20Sopenharmony_ci	 * file may be written through mmap, so chain it onto the
1848c2ecf20Sopenharmony_ci	 * inodes's write_file list
1858c2ecf20Sopenharmony_ci	 */
1868c2ecf20Sopenharmony_ci	spin_lock(&fi->lock);
1878c2ecf20Sopenharmony_ci	if (list_empty(&ff->write_entry))
1888c2ecf20Sopenharmony_ci		list_add(&ff->write_entry, &fi->write_files);
1898c2ecf20Sopenharmony_ci	spin_unlock(&fi->lock);
1908c2ecf20Sopenharmony_ci}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_civoid fuse_finish_open(struct inode *inode, struct file *file)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
1958c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	if (ff->open_flags & FOPEN_STREAM)
1988c2ecf20Sopenharmony_ci		stream_open(inode, file);
1998c2ecf20Sopenharmony_ci	else if (ff->open_flags & FOPEN_NONSEEKABLE)
2008c2ecf20Sopenharmony_ci		nonseekable_open(inode, file);
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC)) {
2038c2ecf20Sopenharmony_ci		struct fuse_inode *fi = get_fuse_inode(inode);
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci		spin_lock(&fi->lock);
2068c2ecf20Sopenharmony_ci		fi->attr_version = atomic64_inc_return(&fc->attr_version);
2078c2ecf20Sopenharmony_ci		i_size_write(inode, 0);
2088c2ecf20Sopenharmony_ci		spin_unlock(&fi->lock);
2098c2ecf20Sopenharmony_ci		fuse_invalidate_attr(inode);
2108c2ecf20Sopenharmony_ci		if (fc->writeback_cache)
2118c2ecf20Sopenharmony_ci			file_update_time(file);
2128c2ecf20Sopenharmony_ci	}
2138c2ecf20Sopenharmony_ci	if ((file->f_mode & FMODE_WRITE) && fc->writeback_cache)
2148c2ecf20Sopenharmony_ci		fuse_link_write_file(file);
2158c2ecf20Sopenharmony_ci}
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ciint fuse_open_common(struct inode *inode, struct file *file, bool isdir)
2188c2ecf20Sopenharmony_ci{
2198c2ecf20Sopenharmony_ci	struct fuse_mount *fm = get_fuse_mount(inode);
2208c2ecf20Sopenharmony_ci	struct fuse_conn *fc = fm->fc;
2218c2ecf20Sopenharmony_ci	int err;
2228c2ecf20Sopenharmony_ci	bool is_wb_truncate = (file->f_flags & O_TRUNC) &&
2238c2ecf20Sopenharmony_ci			  fc->atomic_o_trunc &&
2248c2ecf20Sopenharmony_ci			  fc->writeback_cache;
2258c2ecf20Sopenharmony_ci	bool dax_truncate = (file->f_flags & O_TRUNC) &&
2268c2ecf20Sopenharmony_ci			  fc->atomic_o_trunc && FUSE_IS_DAX(inode);
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	if (fuse_is_bad(inode))
2298c2ecf20Sopenharmony_ci		return -EIO;
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	err = generic_file_open(inode, file);
2328c2ecf20Sopenharmony_ci	if (err)
2338c2ecf20Sopenharmony_ci		return err;
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	if (is_wb_truncate || dax_truncate)
2368c2ecf20Sopenharmony_ci		inode_lock(inode);
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	if (dax_truncate) {
2398c2ecf20Sopenharmony_ci		down_write(&get_fuse_inode(inode)->i_mmap_sem);
2408c2ecf20Sopenharmony_ci		err = fuse_dax_break_layouts(inode, 0, 0);
2418c2ecf20Sopenharmony_ci		if (err)
2428c2ecf20Sopenharmony_ci			goto out_inode_unlock;
2438c2ecf20Sopenharmony_ci	}
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	if (is_wb_truncate || dax_truncate)
2468c2ecf20Sopenharmony_ci		fuse_set_nowrite(inode);
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	err = fuse_do_open(fm, get_node_id(inode), file, isdir);
2498c2ecf20Sopenharmony_ci	if (!err)
2508c2ecf20Sopenharmony_ci		fuse_finish_open(inode, file);
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	if (is_wb_truncate || dax_truncate)
2538c2ecf20Sopenharmony_ci		fuse_release_nowrite(inode);
2548c2ecf20Sopenharmony_ci	if (!err) {
2558c2ecf20Sopenharmony_ci		struct fuse_file *ff = file->private_data;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci		if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC))
2588c2ecf20Sopenharmony_ci			truncate_pagecache(inode, 0);
2598c2ecf20Sopenharmony_ci		else if (!(ff->open_flags & FOPEN_KEEP_CACHE))
2608c2ecf20Sopenharmony_ci			invalidate_inode_pages2(inode->i_mapping);
2618c2ecf20Sopenharmony_ci	}
2628c2ecf20Sopenharmony_ci	if (dax_truncate)
2638c2ecf20Sopenharmony_ci		up_write(&get_fuse_inode(inode)->i_mmap_sem);
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ciout_inode_unlock:
2668c2ecf20Sopenharmony_ci	if (is_wb_truncate || dax_truncate)
2678c2ecf20Sopenharmony_ci		inode_unlock(inode);
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci	return err;
2708c2ecf20Sopenharmony_ci}
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_cistatic void fuse_prepare_release(struct fuse_inode *fi, struct fuse_file *ff,
2738c2ecf20Sopenharmony_ci				 int flags, int opcode)
2748c2ecf20Sopenharmony_ci{
2758c2ecf20Sopenharmony_ci	struct fuse_conn *fc = ff->fm->fc;
2768c2ecf20Sopenharmony_ci	struct fuse_release_args *ra = ff->release_args;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	/* Inode is NULL on error path of fuse_create_open() */
2798c2ecf20Sopenharmony_ci	if (likely(fi)) {
2808c2ecf20Sopenharmony_ci		spin_lock(&fi->lock);
2818c2ecf20Sopenharmony_ci		list_del(&ff->write_entry);
2828c2ecf20Sopenharmony_ci		spin_unlock(&fi->lock);
2838c2ecf20Sopenharmony_ci	}
2848c2ecf20Sopenharmony_ci	spin_lock(&fc->lock);
2858c2ecf20Sopenharmony_ci	if (!RB_EMPTY_NODE(&ff->polled_node))
2868c2ecf20Sopenharmony_ci		rb_erase(&ff->polled_node, &fc->polled_files);
2878c2ecf20Sopenharmony_ci	spin_unlock(&fc->lock);
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	wake_up_interruptible_all(&ff->poll_wait);
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	ra->inarg.fh = ff->fh;
2928c2ecf20Sopenharmony_ci	ra->inarg.flags = flags;
2938c2ecf20Sopenharmony_ci	ra->args.in_numargs = 1;
2948c2ecf20Sopenharmony_ci	ra->args.in_args[0].size = sizeof(struct fuse_release_in);
2958c2ecf20Sopenharmony_ci	ra->args.in_args[0].value = &ra->inarg;
2968c2ecf20Sopenharmony_ci	ra->args.opcode = opcode;
2978c2ecf20Sopenharmony_ci	ra->args.nodeid = ff->nodeid;
2988c2ecf20Sopenharmony_ci	ra->args.force = true;
2998c2ecf20Sopenharmony_ci	ra->args.nocreds = true;
3008c2ecf20Sopenharmony_ci}
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_civoid fuse_release_common(struct file *file, bool isdir)
3038c2ecf20Sopenharmony_ci{
3048c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(file_inode(file));
3058c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
3068c2ecf20Sopenharmony_ci	struct fuse_release_args *ra = ff->release_args;
3078c2ecf20Sopenharmony_ci	int opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE;
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	fuse_prepare_release(fi, ff, file->f_flags, opcode);
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	if (ff->flock) {
3128c2ecf20Sopenharmony_ci		ra->inarg.release_flags |= FUSE_RELEASE_FLOCK_UNLOCK;
3138c2ecf20Sopenharmony_ci		ra->inarg.lock_owner = fuse_lock_owner_id(ff->fm->fc,
3148c2ecf20Sopenharmony_ci							  (fl_owner_t) file);
3158c2ecf20Sopenharmony_ci	}
3168c2ecf20Sopenharmony_ci	/* Hold inode until release is finished */
3178c2ecf20Sopenharmony_ci	ra->inode = igrab(file_inode(file));
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	/*
3208c2ecf20Sopenharmony_ci	 * Normally this will send the RELEASE request, however if
3218c2ecf20Sopenharmony_ci	 * some asynchronous READ or WRITE requests are outstanding,
3228c2ecf20Sopenharmony_ci	 * the sending will be delayed.
3238c2ecf20Sopenharmony_ci	 *
3248c2ecf20Sopenharmony_ci	 * Make the release synchronous if this is a fuseblk mount,
3258c2ecf20Sopenharmony_ci	 * synchronous RELEASE is allowed (and desirable) in this case
3268c2ecf20Sopenharmony_ci	 * because the server can be trusted not to screw up.
3278c2ecf20Sopenharmony_ci	 */
3288c2ecf20Sopenharmony_ci	fuse_file_put(ff, ff->fm->fc->destroy, isdir);
3298c2ecf20Sopenharmony_ci}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_cistatic int fuse_open(struct inode *inode, struct file *file)
3328c2ecf20Sopenharmony_ci{
3338c2ecf20Sopenharmony_ci	return fuse_open_common(inode, file, false);
3348c2ecf20Sopenharmony_ci}
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_cistatic int fuse_release(struct inode *inode, struct file *file)
3378c2ecf20Sopenharmony_ci{
3388c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	/* see fuse_vma_close() for !writeback_cache case */
3418c2ecf20Sopenharmony_ci	if (fc->writeback_cache)
3428c2ecf20Sopenharmony_ci		write_inode_now(inode, 1);
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	fuse_release_common(file, false);
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	/* return value is ignored by VFS */
3478c2ecf20Sopenharmony_ci	return 0;
3488c2ecf20Sopenharmony_ci}
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_civoid fuse_sync_release(struct fuse_inode *fi, struct fuse_file *ff, int flags)
3518c2ecf20Sopenharmony_ci{
3528c2ecf20Sopenharmony_ci	WARN_ON(refcount_read(&ff->count) > 1);
3538c2ecf20Sopenharmony_ci	fuse_prepare_release(fi, ff, flags, FUSE_RELEASE);
3548c2ecf20Sopenharmony_ci	/*
3558c2ecf20Sopenharmony_ci	 * iput(NULL) is a no-op and since the refcount is 1 and everything's
3568c2ecf20Sopenharmony_ci	 * synchronous, we are fine with not doing igrab() here"
3578c2ecf20Sopenharmony_ci	 */
3588c2ecf20Sopenharmony_ci	fuse_file_put(ff, true, false);
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fuse_sync_release);
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci/*
3638c2ecf20Sopenharmony_ci * Scramble the ID space with XTEA, so that the value of the files_struct
3648c2ecf20Sopenharmony_ci * pointer is not exposed to userspace.
3658c2ecf20Sopenharmony_ci */
3668c2ecf20Sopenharmony_ciu64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
3678c2ecf20Sopenharmony_ci{
3688c2ecf20Sopenharmony_ci	u32 *k = fc->scramble_key;
3698c2ecf20Sopenharmony_ci	u64 v = (unsigned long) id;
3708c2ecf20Sopenharmony_ci	u32 v0 = v;
3718c2ecf20Sopenharmony_ci	u32 v1 = v >> 32;
3728c2ecf20Sopenharmony_ci	u32 sum = 0;
3738c2ecf20Sopenharmony_ci	int i;
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci	for (i = 0; i < 32; i++) {
3768c2ecf20Sopenharmony_ci		v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]);
3778c2ecf20Sopenharmony_ci		sum += 0x9E3779B9;
3788c2ecf20Sopenharmony_ci		v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum>>11 & 3]);
3798c2ecf20Sopenharmony_ci	}
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	return (u64) v0 + ((u64) v1 << 32);
3828c2ecf20Sopenharmony_ci}
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_cistruct fuse_writepage_args {
3858c2ecf20Sopenharmony_ci	struct fuse_io_args ia;
3868c2ecf20Sopenharmony_ci	struct rb_node writepages_entry;
3878c2ecf20Sopenharmony_ci	struct list_head queue_entry;
3888c2ecf20Sopenharmony_ci	struct fuse_writepage_args *next;
3898c2ecf20Sopenharmony_ci	struct inode *inode;
3908c2ecf20Sopenharmony_ci};
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_cistatic struct fuse_writepage_args *fuse_find_writeback(struct fuse_inode *fi,
3938c2ecf20Sopenharmony_ci					    pgoff_t idx_from, pgoff_t idx_to)
3948c2ecf20Sopenharmony_ci{
3958c2ecf20Sopenharmony_ci	struct rb_node *n;
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	n = fi->writepages.rb_node;
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	while (n) {
4008c2ecf20Sopenharmony_ci		struct fuse_writepage_args *wpa;
4018c2ecf20Sopenharmony_ci		pgoff_t curr_index;
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci		wpa = rb_entry(n, struct fuse_writepage_args, writepages_entry);
4048c2ecf20Sopenharmony_ci		WARN_ON(get_fuse_inode(wpa->inode) != fi);
4058c2ecf20Sopenharmony_ci		curr_index = wpa->ia.write.in.offset >> PAGE_SHIFT;
4068c2ecf20Sopenharmony_ci		if (idx_from >= curr_index + wpa->ia.ap.num_pages)
4078c2ecf20Sopenharmony_ci			n = n->rb_right;
4088c2ecf20Sopenharmony_ci		else if (idx_to < curr_index)
4098c2ecf20Sopenharmony_ci			n = n->rb_left;
4108c2ecf20Sopenharmony_ci		else
4118c2ecf20Sopenharmony_ci			return wpa;
4128c2ecf20Sopenharmony_ci	}
4138c2ecf20Sopenharmony_ci	return NULL;
4148c2ecf20Sopenharmony_ci}
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci/*
4178c2ecf20Sopenharmony_ci * Check if any page in a range is under writeback
4188c2ecf20Sopenharmony_ci *
4198c2ecf20Sopenharmony_ci * This is currently done by walking the list of writepage requests
4208c2ecf20Sopenharmony_ci * for the inode, which can be pretty inefficient.
4218c2ecf20Sopenharmony_ci */
4228c2ecf20Sopenharmony_cistatic bool fuse_range_is_writeback(struct inode *inode, pgoff_t idx_from,
4238c2ecf20Sopenharmony_ci				   pgoff_t idx_to)
4248c2ecf20Sopenharmony_ci{
4258c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(inode);
4268c2ecf20Sopenharmony_ci	bool found;
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	spin_lock(&fi->lock);
4298c2ecf20Sopenharmony_ci	found = fuse_find_writeback(fi, idx_from, idx_to);
4308c2ecf20Sopenharmony_ci	spin_unlock(&fi->lock);
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	return found;
4338c2ecf20Sopenharmony_ci}
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_cistatic inline bool fuse_page_is_writeback(struct inode *inode, pgoff_t index)
4368c2ecf20Sopenharmony_ci{
4378c2ecf20Sopenharmony_ci	return fuse_range_is_writeback(inode, index, index);
4388c2ecf20Sopenharmony_ci}
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci/*
4418c2ecf20Sopenharmony_ci * Wait for page writeback to be completed.
4428c2ecf20Sopenharmony_ci *
4438c2ecf20Sopenharmony_ci * Since fuse doesn't rely on the VM writeback tracking, this has to
4448c2ecf20Sopenharmony_ci * use some other means.
4458c2ecf20Sopenharmony_ci */
4468c2ecf20Sopenharmony_cistatic void fuse_wait_on_page_writeback(struct inode *inode, pgoff_t index)
4478c2ecf20Sopenharmony_ci{
4488c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(inode);
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	wait_event(fi->page_waitq, !fuse_page_is_writeback(inode, index));
4518c2ecf20Sopenharmony_ci}
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci/*
4548c2ecf20Sopenharmony_ci * Wait for all pending writepages on the inode to finish.
4558c2ecf20Sopenharmony_ci *
4568c2ecf20Sopenharmony_ci * This is currently done by blocking further writes with FUSE_NOWRITE
4578c2ecf20Sopenharmony_ci * and waiting for all sent writes to complete.
4588c2ecf20Sopenharmony_ci *
4598c2ecf20Sopenharmony_ci * This must be called under i_mutex, otherwise the FUSE_NOWRITE usage
4608c2ecf20Sopenharmony_ci * could conflict with truncation.
4618c2ecf20Sopenharmony_ci */
4628c2ecf20Sopenharmony_cistatic void fuse_sync_writes(struct inode *inode)
4638c2ecf20Sopenharmony_ci{
4648c2ecf20Sopenharmony_ci	fuse_set_nowrite(inode);
4658c2ecf20Sopenharmony_ci	fuse_release_nowrite(inode);
4668c2ecf20Sopenharmony_ci}
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_cistatic int fuse_flush(struct file *file, fl_owner_t id)
4698c2ecf20Sopenharmony_ci{
4708c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(file);
4718c2ecf20Sopenharmony_ci	struct fuse_mount *fm = get_fuse_mount(inode);
4728c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
4738c2ecf20Sopenharmony_ci	struct fuse_flush_in inarg;
4748c2ecf20Sopenharmony_ci	FUSE_ARGS(args);
4758c2ecf20Sopenharmony_ci	int err;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	if (fuse_is_bad(inode))
4788c2ecf20Sopenharmony_ci		return -EIO;
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	err = write_inode_now(inode, 1);
4818c2ecf20Sopenharmony_ci	if (err)
4828c2ecf20Sopenharmony_ci		return err;
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	inode_lock(inode);
4858c2ecf20Sopenharmony_ci	fuse_sync_writes(inode);
4868c2ecf20Sopenharmony_ci	inode_unlock(inode);
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	err = filemap_check_errors(file->f_mapping);
4898c2ecf20Sopenharmony_ci	if (err)
4908c2ecf20Sopenharmony_ci		return err;
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	err = 0;
4938c2ecf20Sopenharmony_ci	if (fm->fc->no_flush)
4948c2ecf20Sopenharmony_ci		goto inval_attr_out;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	memset(&inarg, 0, sizeof(inarg));
4978c2ecf20Sopenharmony_ci	inarg.fh = ff->fh;
4988c2ecf20Sopenharmony_ci	inarg.lock_owner = fuse_lock_owner_id(fm->fc, id);
4998c2ecf20Sopenharmony_ci	args.opcode = FUSE_FLUSH;
5008c2ecf20Sopenharmony_ci	args.nodeid = get_node_id(inode);
5018c2ecf20Sopenharmony_ci	args.in_numargs = 1;
5028c2ecf20Sopenharmony_ci	args.in_args[0].size = sizeof(inarg);
5038c2ecf20Sopenharmony_ci	args.in_args[0].value = &inarg;
5048c2ecf20Sopenharmony_ci	args.force = true;
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci	err = fuse_simple_request(fm, &args);
5078c2ecf20Sopenharmony_ci	if (err == -ENOSYS) {
5088c2ecf20Sopenharmony_ci		fm->fc->no_flush = 1;
5098c2ecf20Sopenharmony_ci		err = 0;
5108c2ecf20Sopenharmony_ci	}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ciinval_attr_out:
5138c2ecf20Sopenharmony_ci	/*
5148c2ecf20Sopenharmony_ci	 * In memory i_blocks is not maintained by fuse, if writeback cache is
5158c2ecf20Sopenharmony_ci	 * enabled, i_blocks from cached attr may not be accurate.
5168c2ecf20Sopenharmony_ci	 */
5178c2ecf20Sopenharmony_ci	if (!err && fm->fc->writeback_cache)
5188c2ecf20Sopenharmony_ci		fuse_invalidate_attr(inode);
5198c2ecf20Sopenharmony_ci	return err;
5208c2ecf20Sopenharmony_ci}
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ciint fuse_fsync_common(struct file *file, loff_t start, loff_t end,
5238c2ecf20Sopenharmony_ci		      int datasync, int opcode)
5248c2ecf20Sopenharmony_ci{
5258c2ecf20Sopenharmony_ci	struct inode *inode = file->f_mapping->host;
5268c2ecf20Sopenharmony_ci	struct fuse_mount *fm = get_fuse_mount(inode);
5278c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
5288c2ecf20Sopenharmony_ci	FUSE_ARGS(args);
5298c2ecf20Sopenharmony_ci	struct fuse_fsync_in inarg;
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	memset(&inarg, 0, sizeof(inarg));
5328c2ecf20Sopenharmony_ci	inarg.fh = ff->fh;
5338c2ecf20Sopenharmony_ci	inarg.fsync_flags = datasync ? FUSE_FSYNC_FDATASYNC : 0;
5348c2ecf20Sopenharmony_ci	args.opcode = opcode;
5358c2ecf20Sopenharmony_ci	args.nodeid = get_node_id(inode);
5368c2ecf20Sopenharmony_ci	args.in_numargs = 1;
5378c2ecf20Sopenharmony_ci	args.in_args[0].size = sizeof(inarg);
5388c2ecf20Sopenharmony_ci	args.in_args[0].value = &inarg;
5398c2ecf20Sopenharmony_ci	return fuse_simple_request(fm, &args);
5408c2ecf20Sopenharmony_ci}
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_cistatic int fuse_fsync(struct file *file, loff_t start, loff_t end,
5438c2ecf20Sopenharmony_ci		      int datasync)
5448c2ecf20Sopenharmony_ci{
5458c2ecf20Sopenharmony_ci	struct inode *inode = file->f_mapping->host;
5468c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
5478c2ecf20Sopenharmony_ci	int err;
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	if (fuse_is_bad(inode))
5508c2ecf20Sopenharmony_ci		return -EIO;
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci	inode_lock(inode);
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	/*
5558c2ecf20Sopenharmony_ci	 * Start writeback against all dirty pages of the inode, then
5568c2ecf20Sopenharmony_ci	 * wait for all outstanding writes, before sending the FSYNC
5578c2ecf20Sopenharmony_ci	 * request.
5588c2ecf20Sopenharmony_ci	 */
5598c2ecf20Sopenharmony_ci	err = file_write_and_wait_range(file, start, end);
5608c2ecf20Sopenharmony_ci	if (err)
5618c2ecf20Sopenharmony_ci		goto out;
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci	fuse_sync_writes(inode);
5648c2ecf20Sopenharmony_ci
5658c2ecf20Sopenharmony_ci	/*
5668c2ecf20Sopenharmony_ci	 * Due to implementation of fuse writeback
5678c2ecf20Sopenharmony_ci	 * file_write_and_wait_range() does not catch errors.
5688c2ecf20Sopenharmony_ci	 * We have to do this directly after fuse_sync_writes()
5698c2ecf20Sopenharmony_ci	 */
5708c2ecf20Sopenharmony_ci	err = file_check_and_advance_wb_err(file);
5718c2ecf20Sopenharmony_ci	if (err)
5728c2ecf20Sopenharmony_ci		goto out;
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci	err = sync_inode_metadata(inode, 1);
5758c2ecf20Sopenharmony_ci	if (err)
5768c2ecf20Sopenharmony_ci		goto out;
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	if (fc->no_fsync)
5798c2ecf20Sopenharmony_ci		goto out;
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci	err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNC);
5828c2ecf20Sopenharmony_ci	if (err == -ENOSYS) {
5838c2ecf20Sopenharmony_ci		fc->no_fsync = 1;
5848c2ecf20Sopenharmony_ci		err = 0;
5858c2ecf20Sopenharmony_ci	}
5868c2ecf20Sopenharmony_ciout:
5878c2ecf20Sopenharmony_ci	inode_unlock(inode);
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	return err;
5908c2ecf20Sopenharmony_ci}
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_civoid fuse_read_args_fill(struct fuse_io_args *ia, struct file *file, loff_t pos,
5938c2ecf20Sopenharmony_ci			 size_t count, int opcode)
5948c2ecf20Sopenharmony_ci{
5958c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
5968c2ecf20Sopenharmony_ci	struct fuse_args *args = &ia->ap.args;
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	ia->read.in.fh = ff->fh;
5998c2ecf20Sopenharmony_ci	ia->read.in.offset = pos;
6008c2ecf20Sopenharmony_ci	ia->read.in.size = count;
6018c2ecf20Sopenharmony_ci	ia->read.in.flags = file->f_flags;
6028c2ecf20Sopenharmony_ci	args->opcode = opcode;
6038c2ecf20Sopenharmony_ci	args->nodeid = ff->nodeid;
6048c2ecf20Sopenharmony_ci	args->in_numargs = 1;
6058c2ecf20Sopenharmony_ci	args->in_args[0].size = sizeof(ia->read.in);
6068c2ecf20Sopenharmony_ci	args->in_args[0].value = &ia->read.in;
6078c2ecf20Sopenharmony_ci	args->out_argvar = true;
6088c2ecf20Sopenharmony_ci	args->out_numargs = 1;
6098c2ecf20Sopenharmony_ci	args->out_args[0].size = count;
6108c2ecf20Sopenharmony_ci}
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_cistatic void fuse_release_user_pages(struct fuse_args_pages *ap,
6138c2ecf20Sopenharmony_ci				    bool should_dirty)
6148c2ecf20Sopenharmony_ci{
6158c2ecf20Sopenharmony_ci	unsigned int i;
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci	for (i = 0; i < ap->num_pages; i++) {
6188c2ecf20Sopenharmony_ci		if (should_dirty)
6198c2ecf20Sopenharmony_ci			set_page_dirty_lock(ap->pages[i]);
6208c2ecf20Sopenharmony_ci		put_page(ap->pages[i]);
6218c2ecf20Sopenharmony_ci	}
6228c2ecf20Sopenharmony_ci}
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_cistatic void fuse_io_release(struct kref *kref)
6258c2ecf20Sopenharmony_ci{
6268c2ecf20Sopenharmony_ci	kfree(container_of(kref, struct fuse_io_priv, refcnt));
6278c2ecf20Sopenharmony_ci}
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_cistatic ssize_t fuse_get_res_by_io(struct fuse_io_priv *io)
6308c2ecf20Sopenharmony_ci{
6318c2ecf20Sopenharmony_ci	if (io->err)
6328c2ecf20Sopenharmony_ci		return io->err;
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci	if (io->bytes >= 0 && io->write)
6358c2ecf20Sopenharmony_ci		return -EIO;
6368c2ecf20Sopenharmony_ci
6378c2ecf20Sopenharmony_ci	return io->bytes < 0 ? io->size : io->bytes;
6388c2ecf20Sopenharmony_ci}
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci/**
6418c2ecf20Sopenharmony_ci * In case of short read, the caller sets 'pos' to the position of
6428c2ecf20Sopenharmony_ci * actual end of fuse request in IO request. Otherwise, if bytes_requested
6438c2ecf20Sopenharmony_ci * == bytes_transferred or rw == WRITE, the caller sets 'pos' to -1.
6448c2ecf20Sopenharmony_ci *
6458c2ecf20Sopenharmony_ci * An example:
6468c2ecf20Sopenharmony_ci * User requested DIO read of 64K. It was splitted into two 32K fuse requests,
6478c2ecf20Sopenharmony_ci * both submitted asynchronously. The first of them was ACKed by userspace as
6488c2ecf20Sopenharmony_ci * fully completed (req->out.args[0].size == 32K) resulting in pos == -1. The
6498c2ecf20Sopenharmony_ci * second request was ACKed as short, e.g. only 1K was read, resulting in
6508c2ecf20Sopenharmony_ci * pos == 33K.
6518c2ecf20Sopenharmony_ci *
6528c2ecf20Sopenharmony_ci * Thus, when all fuse requests are completed, the minimal non-negative 'pos'
6538c2ecf20Sopenharmony_ci * will be equal to the length of the longest contiguous fragment of
6548c2ecf20Sopenharmony_ci * transferred data starting from the beginning of IO request.
6558c2ecf20Sopenharmony_ci */
6568c2ecf20Sopenharmony_cistatic void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos)
6578c2ecf20Sopenharmony_ci{
6588c2ecf20Sopenharmony_ci	int left;
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	spin_lock(&io->lock);
6618c2ecf20Sopenharmony_ci	if (err)
6628c2ecf20Sopenharmony_ci		io->err = io->err ? : err;
6638c2ecf20Sopenharmony_ci	else if (pos >= 0 && (io->bytes < 0 || pos < io->bytes))
6648c2ecf20Sopenharmony_ci		io->bytes = pos;
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_ci	left = --io->reqs;
6678c2ecf20Sopenharmony_ci	if (!left && io->blocking)
6688c2ecf20Sopenharmony_ci		complete(io->done);
6698c2ecf20Sopenharmony_ci	spin_unlock(&io->lock);
6708c2ecf20Sopenharmony_ci
6718c2ecf20Sopenharmony_ci	if (!left && !io->blocking) {
6728c2ecf20Sopenharmony_ci		ssize_t res = fuse_get_res_by_io(io);
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci		if (res >= 0) {
6758c2ecf20Sopenharmony_ci			struct inode *inode = file_inode(io->iocb->ki_filp);
6768c2ecf20Sopenharmony_ci			struct fuse_conn *fc = get_fuse_conn(inode);
6778c2ecf20Sopenharmony_ci			struct fuse_inode *fi = get_fuse_inode(inode);
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci			spin_lock(&fi->lock);
6808c2ecf20Sopenharmony_ci			fi->attr_version = atomic64_inc_return(&fc->attr_version);
6818c2ecf20Sopenharmony_ci			spin_unlock(&fi->lock);
6828c2ecf20Sopenharmony_ci		}
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci		io->iocb->ki_complete(io->iocb, res, 0);
6858c2ecf20Sopenharmony_ci	}
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	kref_put(&io->refcnt, fuse_io_release);
6888c2ecf20Sopenharmony_ci}
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_cistatic struct fuse_io_args *fuse_io_alloc(struct fuse_io_priv *io,
6918c2ecf20Sopenharmony_ci					  unsigned int npages)
6928c2ecf20Sopenharmony_ci{
6938c2ecf20Sopenharmony_ci	struct fuse_io_args *ia;
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	ia = kzalloc(sizeof(*ia), GFP_KERNEL);
6968c2ecf20Sopenharmony_ci	if (ia) {
6978c2ecf20Sopenharmony_ci		ia->io = io;
6988c2ecf20Sopenharmony_ci		ia->ap.pages = fuse_pages_alloc(npages, GFP_KERNEL,
6998c2ecf20Sopenharmony_ci						&ia->ap.descs);
7008c2ecf20Sopenharmony_ci		if (!ia->ap.pages) {
7018c2ecf20Sopenharmony_ci			kfree(ia);
7028c2ecf20Sopenharmony_ci			ia = NULL;
7038c2ecf20Sopenharmony_ci		}
7048c2ecf20Sopenharmony_ci	}
7058c2ecf20Sopenharmony_ci	return ia;
7068c2ecf20Sopenharmony_ci}
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_cistatic void fuse_io_free(struct fuse_io_args *ia)
7098c2ecf20Sopenharmony_ci{
7108c2ecf20Sopenharmony_ci	kfree(ia->ap.pages);
7118c2ecf20Sopenharmony_ci	kfree(ia);
7128c2ecf20Sopenharmony_ci}
7138c2ecf20Sopenharmony_ci
7148c2ecf20Sopenharmony_cistatic void fuse_aio_complete_req(struct fuse_mount *fm, struct fuse_args *args,
7158c2ecf20Sopenharmony_ci				  int err)
7168c2ecf20Sopenharmony_ci{
7178c2ecf20Sopenharmony_ci	struct fuse_io_args *ia = container_of(args, typeof(*ia), ap.args);
7188c2ecf20Sopenharmony_ci	struct fuse_io_priv *io = ia->io;
7198c2ecf20Sopenharmony_ci	ssize_t pos = -1;
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci	fuse_release_user_pages(&ia->ap, io->should_dirty);
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	if (err) {
7248c2ecf20Sopenharmony_ci		/* Nothing */
7258c2ecf20Sopenharmony_ci	} else if (io->write) {
7268c2ecf20Sopenharmony_ci		if (ia->write.out.size > ia->write.in.size) {
7278c2ecf20Sopenharmony_ci			err = -EIO;
7288c2ecf20Sopenharmony_ci		} else if (ia->write.in.size != ia->write.out.size) {
7298c2ecf20Sopenharmony_ci			pos = ia->write.in.offset - io->offset +
7308c2ecf20Sopenharmony_ci				ia->write.out.size;
7318c2ecf20Sopenharmony_ci		}
7328c2ecf20Sopenharmony_ci	} else {
7338c2ecf20Sopenharmony_ci		u32 outsize = args->out_args[0].size;
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci		if (ia->read.in.size != outsize)
7368c2ecf20Sopenharmony_ci			pos = ia->read.in.offset - io->offset + outsize;
7378c2ecf20Sopenharmony_ci	}
7388c2ecf20Sopenharmony_ci
7398c2ecf20Sopenharmony_ci	fuse_aio_complete(io, err, pos);
7408c2ecf20Sopenharmony_ci	fuse_io_free(ia);
7418c2ecf20Sopenharmony_ci}
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_cistatic ssize_t fuse_async_req_send(struct fuse_mount *fm,
7448c2ecf20Sopenharmony_ci				   struct fuse_io_args *ia, size_t num_bytes)
7458c2ecf20Sopenharmony_ci{
7468c2ecf20Sopenharmony_ci	ssize_t err;
7478c2ecf20Sopenharmony_ci	struct fuse_io_priv *io = ia->io;
7488c2ecf20Sopenharmony_ci
7498c2ecf20Sopenharmony_ci	spin_lock(&io->lock);
7508c2ecf20Sopenharmony_ci	kref_get(&io->refcnt);
7518c2ecf20Sopenharmony_ci	io->size += num_bytes;
7528c2ecf20Sopenharmony_ci	io->reqs++;
7538c2ecf20Sopenharmony_ci	spin_unlock(&io->lock);
7548c2ecf20Sopenharmony_ci
7558c2ecf20Sopenharmony_ci	ia->ap.args.end = fuse_aio_complete_req;
7568c2ecf20Sopenharmony_ci	ia->ap.args.may_block = io->should_dirty;
7578c2ecf20Sopenharmony_ci	err = fuse_simple_background(fm, &ia->ap.args, GFP_KERNEL);
7588c2ecf20Sopenharmony_ci	if (err)
7598c2ecf20Sopenharmony_ci		fuse_aio_complete_req(fm, &ia->ap.args, err);
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci	return num_bytes;
7628c2ecf20Sopenharmony_ci}
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_cistatic ssize_t fuse_send_read(struct fuse_io_args *ia, loff_t pos, size_t count,
7658c2ecf20Sopenharmony_ci			      fl_owner_t owner)
7668c2ecf20Sopenharmony_ci{
7678c2ecf20Sopenharmony_ci	struct file *file = ia->io->iocb->ki_filp;
7688c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
7698c2ecf20Sopenharmony_ci	struct fuse_mount *fm = ff->fm;
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_ci	fuse_read_args_fill(ia, file, pos, count, FUSE_READ);
7728c2ecf20Sopenharmony_ci	if (owner != NULL) {
7738c2ecf20Sopenharmony_ci		ia->read.in.read_flags |= FUSE_READ_LOCKOWNER;
7748c2ecf20Sopenharmony_ci		ia->read.in.lock_owner = fuse_lock_owner_id(fm->fc, owner);
7758c2ecf20Sopenharmony_ci	}
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci	if (ia->io->async)
7788c2ecf20Sopenharmony_ci		return fuse_async_req_send(fm, ia, count);
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	return fuse_simple_request(fm, &ia->ap.args);
7818c2ecf20Sopenharmony_ci}
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_cistatic void fuse_read_update_size(struct inode *inode, loff_t size,
7848c2ecf20Sopenharmony_ci				  u64 attr_ver)
7858c2ecf20Sopenharmony_ci{
7868c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
7878c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(inode);
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci	spin_lock(&fi->lock);
7908c2ecf20Sopenharmony_ci	if (attr_ver >= fi->attr_version && size < inode->i_size &&
7918c2ecf20Sopenharmony_ci	    !test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) {
7928c2ecf20Sopenharmony_ci		fi->attr_version = atomic64_inc_return(&fc->attr_version);
7938c2ecf20Sopenharmony_ci		i_size_write(inode, size);
7948c2ecf20Sopenharmony_ci	}
7958c2ecf20Sopenharmony_ci	spin_unlock(&fi->lock);
7968c2ecf20Sopenharmony_ci}
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_cistatic void fuse_short_read(struct inode *inode, u64 attr_ver, size_t num_read,
7998c2ecf20Sopenharmony_ci			    struct fuse_args_pages *ap)
8008c2ecf20Sopenharmony_ci{
8018c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	if (fc->writeback_cache) {
8048c2ecf20Sopenharmony_ci		/*
8058c2ecf20Sopenharmony_ci		 * A hole in a file. Some data after the hole are in page cache,
8068c2ecf20Sopenharmony_ci		 * but have not reached the client fs yet. So, the hole is not
8078c2ecf20Sopenharmony_ci		 * present there.
8088c2ecf20Sopenharmony_ci		 */
8098c2ecf20Sopenharmony_ci		int i;
8108c2ecf20Sopenharmony_ci		int start_idx = num_read >> PAGE_SHIFT;
8118c2ecf20Sopenharmony_ci		size_t off = num_read & (PAGE_SIZE - 1);
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci		for (i = start_idx; i < ap->num_pages; i++) {
8148c2ecf20Sopenharmony_ci			zero_user_segment(ap->pages[i], off, PAGE_SIZE);
8158c2ecf20Sopenharmony_ci			off = 0;
8168c2ecf20Sopenharmony_ci		}
8178c2ecf20Sopenharmony_ci	} else {
8188c2ecf20Sopenharmony_ci		loff_t pos = page_offset(ap->pages[0]) + num_read;
8198c2ecf20Sopenharmony_ci		fuse_read_update_size(inode, pos, attr_ver);
8208c2ecf20Sopenharmony_ci	}
8218c2ecf20Sopenharmony_ci}
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_cistatic int fuse_do_readpage(struct file *file, struct page *page)
8248c2ecf20Sopenharmony_ci{
8258c2ecf20Sopenharmony_ci	struct inode *inode = page->mapping->host;
8268c2ecf20Sopenharmony_ci	struct fuse_mount *fm = get_fuse_mount(inode);
8278c2ecf20Sopenharmony_ci	loff_t pos = page_offset(page);
8288c2ecf20Sopenharmony_ci	struct fuse_page_desc desc = { .length = PAGE_SIZE };
8298c2ecf20Sopenharmony_ci	struct fuse_io_args ia = {
8308c2ecf20Sopenharmony_ci		.ap.args.page_zeroing = true,
8318c2ecf20Sopenharmony_ci		.ap.args.out_pages = true,
8328c2ecf20Sopenharmony_ci		.ap.num_pages = 1,
8338c2ecf20Sopenharmony_ci		.ap.pages = &page,
8348c2ecf20Sopenharmony_ci		.ap.descs = &desc,
8358c2ecf20Sopenharmony_ci	};
8368c2ecf20Sopenharmony_ci	ssize_t res;
8378c2ecf20Sopenharmony_ci	u64 attr_ver;
8388c2ecf20Sopenharmony_ci
8398c2ecf20Sopenharmony_ci	/*
8408c2ecf20Sopenharmony_ci	 * Page writeback can extend beyond the lifetime of the
8418c2ecf20Sopenharmony_ci	 * page-cache page, so make sure we read a properly synced
8428c2ecf20Sopenharmony_ci	 * page.
8438c2ecf20Sopenharmony_ci	 */
8448c2ecf20Sopenharmony_ci	fuse_wait_on_page_writeback(inode, page->index);
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	attr_ver = fuse_get_attr_version(fm->fc);
8478c2ecf20Sopenharmony_ci
8488c2ecf20Sopenharmony_ci	/* Don't overflow end offset */
8498c2ecf20Sopenharmony_ci	if (pos + (desc.length - 1) == LLONG_MAX)
8508c2ecf20Sopenharmony_ci		desc.length--;
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	fuse_read_args_fill(&ia, file, pos, desc.length, FUSE_READ);
8538c2ecf20Sopenharmony_ci	res = fuse_simple_request(fm, &ia.ap.args);
8548c2ecf20Sopenharmony_ci	if (res < 0)
8558c2ecf20Sopenharmony_ci		return res;
8568c2ecf20Sopenharmony_ci	/*
8578c2ecf20Sopenharmony_ci	 * Short read means EOF.  If file size is larger, truncate it
8588c2ecf20Sopenharmony_ci	 */
8598c2ecf20Sopenharmony_ci	if (res < desc.length)
8608c2ecf20Sopenharmony_ci		fuse_short_read(inode, attr_ver, res, &ia.ap);
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ci	SetPageUptodate(page);
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	return 0;
8658c2ecf20Sopenharmony_ci}
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_cistatic int fuse_readpage(struct file *file, struct page *page)
8688c2ecf20Sopenharmony_ci{
8698c2ecf20Sopenharmony_ci	struct inode *inode = page->mapping->host;
8708c2ecf20Sopenharmony_ci	int err;
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci	err = -EIO;
8738c2ecf20Sopenharmony_ci	if (fuse_is_bad(inode))
8748c2ecf20Sopenharmony_ci		goto out;
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ci	err = fuse_do_readpage(file, page);
8778c2ecf20Sopenharmony_ci	fuse_invalidate_atime(inode);
8788c2ecf20Sopenharmony_ci out:
8798c2ecf20Sopenharmony_ci	unlock_page(page);
8808c2ecf20Sopenharmony_ci	return err;
8818c2ecf20Sopenharmony_ci}
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_cistatic void fuse_readpages_end(struct fuse_mount *fm, struct fuse_args *args,
8848c2ecf20Sopenharmony_ci			       int err)
8858c2ecf20Sopenharmony_ci{
8868c2ecf20Sopenharmony_ci	int i;
8878c2ecf20Sopenharmony_ci	struct fuse_io_args *ia = container_of(args, typeof(*ia), ap.args);
8888c2ecf20Sopenharmony_ci	struct fuse_args_pages *ap = &ia->ap;
8898c2ecf20Sopenharmony_ci	size_t count = ia->read.in.size;
8908c2ecf20Sopenharmony_ci	size_t num_read = args->out_args[0].size;
8918c2ecf20Sopenharmony_ci	struct address_space *mapping = NULL;
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	for (i = 0; mapping == NULL && i < ap->num_pages; i++)
8948c2ecf20Sopenharmony_ci		mapping = ap->pages[i]->mapping;
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_ci	if (mapping) {
8978c2ecf20Sopenharmony_ci		struct inode *inode = mapping->host;
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci		/*
9008c2ecf20Sopenharmony_ci		 * Short read means EOF. If file size is larger, truncate it
9018c2ecf20Sopenharmony_ci		 */
9028c2ecf20Sopenharmony_ci		if (!err && num_read < count)
9038c2ecf20Sopenharmony_ci			fuse_short_read(inode, ia->read.attr_ver, num_read, ap);
9048c2ecf20Sopenharmony_ci
9058c2ecf20Sopenharmony_ci		fuse_invalidate_atime(inode);
9068c2ecf20Sopenharmony_ci	}
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	for (i = 0; i < ap->num_pages; i++) {
9098c2ecf20Sopenharmony_ci		struct page *page = ap->pages[i];
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci		if (!err)
9128c2ecf20Sopenharmony_ci			SetPageUptodate(page);
9138c2ecf20Sopenharmony_ci		else
9148c2ecf20Sopenharmony_ci			SetPageError(page);
9158c2ecf20Sopenharmony_ci		unlock_page(page);
9168c2ecf20Sopenharmony_ci		put_page(page);
9178c2ecf20Sopenharmony_ci	}
9188c2ecf20Sopenharmony_ci	if (ia->ff)
9198c2ecf20Sopenharmony_ci		fuse_file_put(ia->ff, false, false);
9208c2ecf20Sopenharmony_ci
9218c2ecf20Sopenharmony_ci	fuse_io_free(ia);
9228c2ecf20Sopenharmony_ci}
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_cistatic void fuse_send_readpages(struct fuse_io_args *ia, struct file *file)
9258c2ecf20Sopenharmony_ci{
9268c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
9278c2ecf20Sopenharmony_ci	struct fuse_mount *fm = ff->fm;
9288c2ecf20Sopenharmony_ci	struct fuse_args_pages *ap = &ia->ap;
9298c2ecf20Sopenharmony_ci	loff_t pos = page_offset(ap->pages[0]);
9308c2ecf20Sopenharmony_ci	size_t count = ap->num_pages << PAGE_SHIFT;
9318c2ecf20Sopenharmony_ci	ssize_t res;
9328c2ecf20Sopenharmony_ci	int err;
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci	ap->args.out_pages = true;
9358c2ecf20Sopenharmony_ci	ap->args.page_zeroing = true;
9368c2ecf20Sopenharmony_ci	ap->args.page_replace = true;
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	/* Don't overflow end offset */
9398c2ecf20Sopenharmony_ci	if (pos + (count - 1) == LLONG_MAX) {
9408c2ecf20Sopenharmony_ci		count--;
9418c2ecf20Sopenharmony_ci		ap->descs[ap->num_pages - 1].length--;
9428c2ecf20Sopenharmony_ci	}
9438c2ecf20Sopenharmony_ci	WARN_ON((loff_t) (pos + count) < 0);
9448c2ecf20Sopenharmony_ci
9458c2ecf20Sopenharmony_ci	fuse_read_args_fill(ia, file, pos, count, FUSE_READ);
9468c2ecf20Sopenharmony_ci	ia->read.attr_ver = fuse_get_attr_version(fm->fc);
9478c2ecf20Sopenharmony_ci	if (fm->fc->async_read) {
9488c2ecf20Sopenharmony_ci		ia->ff = fuse_file_get(ff);
9498c2ecf20Sopenharmony_ci		ap->args.end = fuse_readpages_end;
9508c2ecf20Sopenharmony_ci		err = fuse_simple_background(fm, &ap->args, GFP_KERNEL);
9518c2ecf20Sopenharmony_ci		if (!err)
9528c2ecf20Sopenharmony_ci			return;
9538c2ecf20Sopenharmony_ci	} else {
9548c2ecf20Sopenharmony_ci		res = fuse_simple_request(fm, &ap->args);
9558c2ecf20Sopenharmony_ci		err = res < 0 ? res : 0;
9568c2ecf20Sopenharmony_ci	}
9578c2ecf20Sopenharmony_ci	fuse_readpages_end(fm, &ap->args, err);
9588c2ecf20Sopenharmony_ci}
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_cistatic void fuse_readahead(struct readahead_control *rac)
9618c2ecf20Sopenharmony_ci{
9628c2ecf20Sopenharmony_ci	struct inode *inode = rac->mapping->host;
9638c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
9648c2ecf20Sopenharmony_ci	unsigned int i, max_pages, nr_pages = 0;
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci	if (fuse_is_bad(inode))
9678c2ecf20Sopenharmony_ci		return;
9688c2ecf20Sopenharmony_ci
9698c2ecf20Sopenharmony_ci	max_pages = min_t(unsigned int, fc->max_pages,
9708c2ecf20Sopenharmony_ci			fc->max_read / PAGE_SIZE);
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	for (;;) {
9738c2ecf20Sopenharmony_ci		struct fuse_io_args *ia;
9748c2ecf20Sopenharmony_ci		struct fuse_args_pages *ap;
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci		nr_pages = readahead_count(rac) - nr_pages;
9778c2ecf20Sopenharmony_ci		if (nr_pages > max_pages)
9788c2ecf20Sopenharmony_ci			nr_pages = max_pages;
9798c2ecf20Sopenharmony_ci		if (nr_pages == 0)
9808c2ecf20Sopenharmony_ci			break;
9818c2ecf20Sopenharmony_ci		ia = fuse_io_alloc(NULL, nr_pages);
9828c2ecf20Sopenharmony_ci		if (!ia)
9838c2ecf20Sopenharmony_ci			return;
9848c2ecf20Sopenharmony_ci		ap = &ia->ap;
9858c2ecf20Sopenharmony_ci		nr_pages = __readahead_batch(rac, ap->pages, nr_pages);
9868c2ecf20Sopenharmony_ci		for (i = 0; i < nr_pages; i++) {
9878c2ecf20Sopenharmony_ci			fuse_wait_on_page_writeback(inode,
9888c2ecf20Sopenharmony_ci						    readahead_index(rac) + i);
9898c2ecf20Sopenharmony_ci			ap->descs[i].length = PAGE_SIZE;
9908c2ecf20Sopenharmony_ci		}
9918c2ecf20Sopenharmony_ci		ap->num_pages = nr_pages;
9928c2ecf20Sopenharmony_ci		fuse_send_readpages(ia, rac->file);
9938c2ecf20Sopenharmony_ci	}
9948c2ecf20Sopenharmony_ci}
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_cistatic ssize_t fuse_cache_read_iter(struct kiocb *iocb, struct iov_iter *to)
9978c2ecf20Sopenharmony_ci{
9988c2ecf20Sopenharmony_ci	struct inode *inode = iocb->ki_filp->f_mapping->host;
9998c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
10008c2ecf20Sopenharmony_ci
10018c2ecf20Sopenharmony_ci	/*
10028c2ecf20Sopenharmony_ci	 * In auto invalidate mode, always update attributes on read.
10038c2ecf20Sopenharmony_ci	 * Otherwise, only update if we attempt to read past EOF (to ensure
10048c2ecf20Sopenharmony_ci	 * i_size is up to date).
10058c2ecf20Sopenharmony_ci	 */
10068c2ecf20Sopenharmony_ci	if (fc->auto_inval_data ||
10078c2ecf20Sopenharmony_ci	    (iocb->ki_pos + iov_iter_count(to) > i_size_read(inode))) {
10088c2ecf20Sopenharmony_ci		int err;
10098c2ecf20Sopenharmony_ci		err = fuse_update_attributes(inode, iocb->ki_filp);
10108c2ecf20Sopenharmony_ci		if (err)
10118c2ecf20Sopenharmony_ci			return err;
10128c2ecf20Sopenharmony_ci	}
10138c2ecf20Sopenharmony_ci
10148c2ecf20Sopenharmony_ci	return generic_file_read_iter(iocb, to);
10158c2ecf20Sopenharmony_ci}
10168c2ecf20Sopenharmony_ci
10178c2ecf20Sopenharmony_cistatic void fuse_write_args_fill(struct fuse_io_args *ia, struct fuse_file *ff,
10188c2ecf20Sopenharmony_ci				 loff_t pos, size_t count)
10198c2ecf20Sopenharmony_ci{
10208c2ecf20Sopenharmony_ci	struct fuse_args *args = &ia->ap.args;
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci	ia->write.in.fh = ff->fh;
10238c2ecf20Sopenharmony_ci	ia->write.in.offset = pos;
10248c2ecf20Sopenharmony_ci	ia->write.in.size = count;
10258c2ecf20Sopenharmony_ci	args->opcode = FUSE_WRITE;
10268c2ecf20Sopenharmony_ci	args->nodeid = ff->nodeid;
10278c2ecf20Sopenharmony_ci	args->in_numargs = 2;
10288c2ecf20Sopenharmony_ci	if (ff->fm->fc->minor < 9)
10298c2ecf20Sopenharmony_ci		args->in_args[0].size = FUSE_COMPAT_WRITE_IN_SIZE;
10308c2ecf20Sopenharmony_ci	else
10318c2ecf20Sopenharmony_ci		args->in_args[0].size = sizeof(ia->write.in);
10328c2ecf20Sopenharmony_ci	args->in_args[0].value = &ia->write.in;
10338c2ecf20Sopenharmony_ci	args->in_args[1].size = count;
10348c2ecf20Sopenharmony_ci	args->out_numargs = 1;
10358c2ecf20Sopenharmony_ci	args->out_args[0].size = sizeof(ia->write.out);
10368c2ecf20Sopenharmony_ci	args->out_args[0].value = &ia->write.out;
10378c2ecf20Sopenharmony_ci}
10388c2ecf20Sopenharmony_ci
10398c2ecf20Sopenharmony_cistatic unsigned int fuse_write_flags(struct kiocb *iocb)
10408c2ecf20Sopenharmony_ci{
10418c2ecf20Sopenharmony_ci	unsigned int flags = iocb->ki_filp->f_flags;
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	if (iocb->ki_flags & IOCB_DSYNC)
10448c2ecf20Sopenharmony_ci		flags |= O_DSYNC;
10458c2ecf20Sopenharmony_ci	if (iocb->ki_flags & IOCB_SYNC)
10468c2ecf20Sopenharmony_ci		flags |= O_SYNC;
10478c2ecf20Sopenharmony_ci
10488c2ecf20Sopenharmony_ci	return flags;
10498c2ecf20Sopenharmony_ci}
10508c2ecf20Sopenharmony_ci
10518c2ecf20Sopenharmony_cistatic ssize_t fuse_send_write(struct fuse_io_args *ia, loff_t pos,
10528c2ecf20Sopenharmony_ci			       size_t count, fl_owner_t owner)
10538c2ecf20Sopenharmony_ci{
10548c2ecf20Sopenharmony_ci	struct kiocb *iocb = ia->io->iocb;
10558c2ecf20Sopenharmony_ci	struct file *file = iocb->ki_filp;
10568c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
10578c2ecf20Sopenharmony_ci	struct fuse_mount *fm = ff->fm;
10588c2ecf20Sopenharmony_ci	struct fuse_write_in *inarg = &ia->write.in;
10598c2ecf20Sopenharmony_ci	ssize_t err;
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_ci	fuse_write_args_fill(ia, ff, pos, count);
10628c2ecf20Sopenharmony_ci	inarg->flags = fuse_write_flags(iocb);
10638c2ecf20Sopenharmony_ci	if (owner != NULL) {
10648c2ecf20Sopenharmony_ci		inarg->write_flags |= FUSE_WRITE_LOCKOWNER;
10658c2ecf20Sopenharmony_ci		inarg->lock_owner = fuse_lock_owner_id(fm->fc, owner);
10668c2ecf20Sopenharmony_ci	}
10678c2ecf20Sopenharmony_ci
10688c2ecf20Sopenharmony_ci	if (ia->io->async)
10698c2ecf20Sopenharmony_ci		return fuse_async_req_send(fm, ia, count);
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_ci	err = fuse_simple_request(fm, &ia->ap.args);
10728c2ecf20Sopenharmony_ci	if (!err && ia->write.out.size > count)
10738c2ecf20Sopenharmony_ci		err = -EIO;
10748c2ecf20Sopenharmony_ci
10758c2ecf20Sopenharmony_ci	return err ?: ia->write.out.size;
10768c2ecf20Sopenharmony_ci}
10778c2ecf20Sopenharmony_ci
10788c2ecf20Sopenharmony_cibool fuse_write_update_size(struct inode *inode, loff_t pos)
10798c2ecf20Sopenharmony_ci{
10808c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
10818c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(inode);
10828c2ecf20Sopenharmony_ci	bool ret = false;
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci	spin_lock(&fi->lock);
10858c2ecf20Sopenharmony_ci	fi->attr_version = atomic64_inc_return(&fc->attr_version);
10868c2ecf20Sopenharmony_ci	if (pos > inode->i_size) {
10878c2ecf20Sopenharmony_ci		i_size_write(inode, pos);
10888c2ecf20Sopenharmony_ci		ret = true;
10898c2ecf20Sopenharmony_ci	}
10908c2ecf20Sopenharmony_ci	spin_unlock(&fi->lock);
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci	return ret;
10938c2ecf20Sopenharmony_ci}
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_cistatic ssize_t fuse_send_write_pages(struct fuse_io_args *ia,
10968c2ecf20Sopenharmony_ci				     struct kiocb *iocb, struct inode *inode,
10978c2ecf20Sopenharmony_ci				     loff_t pos, size_t count)
10988c2ecf20Sopenharmony_ci{
10998c2ecf20Sopenharmony_ci	struct fuse_args_pages *ap = &ia->ap;
11008c2ecf20Sopenharmony_ci	struct file *file = iocb->ki_filp;
11018c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
11028c2ecf20Sopenharmony_ci	struct fuse_mount *fm = ff->fm;
11038c2ecf20Sopenharmony_ci	unsigned int offset, i;
11048c2ecf20Sopenharmony_ci	bool short_write;
11058c2ecf20Sopenharmony_ci	int err;
11068c2ecf20Sopenharmony_ci
11078c2ecf20Sopenharmony_ci	for (i = 0; i < ap->num_pages; i++)
11088c2ecf20Sopenharmony_ci		fuse_wait_on_page_writeback(inode, ap->pages[i]->index);
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci	fuse_write_args_fill(ia, ff, pos, count);
11118c2ecf20Sopenharmony_ci	ia->write.in.flags = fuse_write_flags(iocb);
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_ci	err = fuse_simple_request(fm, &ap->args);
11148c2ecf20Sopenharmony_ci	if (!err && ia->write.out.size > count)
11158c2ecf20Sopenharmony_ci		err = -EIO;
11168c2ecf20Sopenharmony_ci
11178c2ecf20Sopenharmony_ci	short_write = ia->write.out.size < count;
11188c2ecf20Sopenharmony_ci	offset = ap->descs[0].offset;
11198c2ecf20Sopenharmony_ci	count = ia->write.out.size;
11208c2ecf20Sopenharmony_ci	for (i = 0; i < ap->num_pages; i++) {
11218c2ecf20Sopenharmony_ci		struct page *page = ap->pages[i];
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci		if (err) {
11248c2ecf20Sopenharmony_ci			ClearPageUptodate(page);
11258c2ecf20Sopenharmony_ci		} else {
11268c2ecf20Sopenharmony_ci			if (count >= PAGE_SIZE - offset)
11278c2ecf20Sopenharmony_ci				count -= PAGE_SIZE - offset;
11288c2ecf20Sopenharmony_ci			else {
11298c2ecf20Sopenharmony_ci				if (short_write)
11308c2ecf20Sopenharmony_ci					ClearPageUptodate(page);
11318c2ecf20Sopenharmony_ci				count = 0;
11328c2ecf20Sopenharmony_ci			}
11338c2ecf20Sopenharmony_ci			offset = 0;
11348c2ecf20Sopenharmony_ci		}
11358c2ecf20Sopenharmony_ci		if (ia->write.page_locked && (i == ap->num_pages - 1))
11368c2ecf20Sopenharmony_ci			unlock_page(page);
11378c2ecf20Sopenharmony_ci		put_page(page);
11388c2ecf20Sopenharmony_ci	}
11398c2ecf20Sopenharmony_ci
11408c2ecf20Sopenharmony_ci	return err;
11418c2ecf20Sopenharmony_ci}
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_cistatic ssize_t fuse_fill_write_pages(struct fuse_io_args *ia,
11448c2ecf20Sopenharmony_ci				     struct address_space *mapping,
11458c2ecf20Sopenharmony_ci				     struct iov_iter *ii, loff_t pos,
11468c2ecf20Sopenharmony_ci				     unsigned int max_pages)
11478c2ecf20Sopenharmony_ci{
11488c2ecf20Sopenharmony_ci	struct fuse_args_pages *ap = &ia->ap;
11498c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(mapping->host);
11508c2ecf20Sopenharmony_ci	unsigned offset = pos & (PAGE_SIZE - 1);
11518c2ecf20Sopenharmony_ci	size_t count = 0;
11528c2ecf20Sopenharmony_ci	int err;
11538c2ecf20Sopenharmony_ci
11548c2ecf20Sopenharmony_ci	ap->args.in_pages = true;
11558c2ecf20Sopenharmony_ci	ap->descs[0].offset = offset;
11568c2ecf20Sopenharmony_ci
11578c2ecf20Sopenharmony_ci	do {
11588c2ecf20Sopenharmony_ci		size_t tmp;
11598c2ecf20Sopenharmony_ci		struct page *page;
11608c2ecf20Sopenharmony_ci		pgoff_t index = pos >> PAGE_SHIFT;
11618c2ecf20Sopenharmony_ci		size_t bytes = min_t(size_t, PAGE_SIZE - offset,
11628c2ecf20Sopenharmony_ci				     iov_iter_count(ii));
11638c2ecf20Sopenharmony_ci
11648c2ecf20Sopenharmony_ci		bytes = min_t(size_t, bytes, fc->max_write - count);
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ci again:
11678c2ecf20Sopenharmony_ci		err = -EFAULT;
11688c2ecf20Sopenharmony_ci		if (iov_iter_fault_in_readable(ii, bytes))
11698c2ecf20Sopenharmony_ci			break;
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_ci		err = -ENOMEM;
11728c2ecf20Sopenharmony_ci		page = grab_cache_page_write_begin(mapping, index, 0);
11738c2ecf20Sopenharmony_ci		if (!page)
11748c2ecf20Sopenharmony_ci			break;
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_ci		if (mapping_writably_mapped(mapping))
11778c2ecf20Sopenharmony_ci			flush_dcache_page(page);
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci		tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes);
11808c2ecf20Sopenharmony_ci		flush_dcache_page(page);
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci		iov_iter_advance(ii, tmp);
11838c2ecf20Sopenharmony_ci		if (!tmp) {
11848c2ecf20Sopenharmony_ci			unlock_page(page);
11858c2ecf20Sopenharmony_ci			put_page(page);
11868c2ecf20Sopenharmony_ci			bytes = min(bytes, iov_iter_single_seg_count(ii));
11878c2ecf20Sopenharmony_ci			goto again;
11888c2ecf20Sopenharmony_ci		}
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci		err = 0;
11918c2ecf20Sopenharmony_ci		ap->pages[ap->num_pages] = page;
11928c2ecf20Sopenharmony_ci		ap->descs[ap->num_pages].length = tmp;
11938c2ecf20Sopenharmony_ci		ap->num_pages++;
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_ci		count += tmp;
11968c2ecf20Sopenharmony_ci		pos += tmp;
11978c2ecf20Sopenharmony_ci		offset += tmp;
11988c2ecf20Sopenharmony_ci		if (offset == PAGE_SIZE)
11998c2ecf20Sopenharmony_ci			offset = 0;
12008c2ecf20Sopenharmony_ci
12018c2ecf20Sopenharmony_ci		/* If we copied full page, mark it uptodate */
12028c2ecf20Sopenharmony_ci		if (tmp == PAGE_SIZE)
12038c2ecf20Sopenharmony_ci			SetPageUptodate(page);
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci		if (PageUptodate(page)) {
12068c2ecf20Sopenharmony_ci			unlock_page(page);
12078c2ecf20Sopenharmony_ci		} else {
12088c2ecf20Sopenharmony_ci			ia->write.page_locked = true;
12098c2ecf20Sopenharmony_ci			break;
12108c2ecf20Sopenharmony_ci		}
12118c2ecf20Sopenharmony_ci		if (!fc->big_writes)
12128c2ecf20Sopenharmony_ci			break;
12138c2ecf20Sopenharmony_ci	} while (iov_iter_count(ii) && count < fc->max_write &&
12148c2ecf20Sopenharmony_ci		 ap->num_pages < max_pages && offset == 0);
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci	return count > 0 ? count : err;
12178c2ecf20Sopenharmony_ci}
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_cistatic inline unsigned int fuse_wr_pages(loff_t pos, size_t len,
12208c2ecf20Sopenharmony_ci				     unsigned int max_pages)
12218c2ecf20Sopenharmony_ci{
12228c2ecf20Sopenharmony_ci	return min_t(unsigned int,
12238c2ecf20Sopenharmony_ci		     ((pos + len - 1) >> PAGE_SHIFT) -
12248c2ecf20Sopenharmony_ci		     (pos >> PAGE_SHIFT) + 1,
12258c2ecf20Sopenharmony_ci		     max_pages);
12268c2ecf20Sopenharmony_ci}
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_cistatic ssize_t fuse_perform_write(struct kiocb *iocb,
12298c2ecf20Sopenharmony_ci				  struct address_space *mapping,
12308c2ecf20Sopenharmony_ci				  struct iov_iter *ii, loff_t pos)
12318c2ecf20Sopenharmony_ci{
12328c2ecf20Sopenharmony_ci	struct inode *inode = mapping->host;
12338c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
12348c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(inode);
12358c2ecf20Sopenharmony_ci	int err = 0;
12368c2ecf20Sopenharmony_ci	ssize_t res = 0;
12378c2ecf20Sopenharmony_ci
12388c2ecf20Sopenharmony_ci	if (inode->i_size < pos + iov_iter_count(ii))
12398c2ecf20Sopenharmony_ci		set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_ci	do {
12428c2ecf20Sopenharmony_ci		ssize_t count;
12438c2ecf20Sopenharmony_ci		struct fuse_io_args ia = {};
12448c2ecf20Sopenharmony_ci		struct fuse_args_pages *ap = &ia.ap;
12458c2ecf20Sopenharmony_ci		unsigned int nr_pages = fuse_wr_pages(pos, iov_iter_count(ii),
12468c2ecf20Sopenharmony_ci						      fc->max_pages);
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci		ap->pages = fuse_pages_alloc(nr_pages, GFP_KERNEL, &ap->descs);
12498c2ecf20Sopenharmony_ci		if (!ap->pages) {
12508c2ecf20Sopenharmony_ci			err = -ENOMEM;
12518c2ecf20Sopenharmony_ci			break;
12528c2ecf20Sopenharmony_ci		}
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_ci		count = fuse_fill_write_pages(&ia, mapping, ii, pos, nr_pages);
12558c2ecf20Sopenharmony_ci		if (count <= 0) {
12568c2ecf20Sopenharmony_ci			err = count;
12578c2ecf20Sopenharmony_ci		} else {
12588c2ecf20Sopenharmony_ci			err = fuse_send_write_pages(&ia, iocb, inode,
12598c2ecf20Sopenharmony_ci						    pos, count);
12608c2ecf20Sopenharmony_ci			if (!err) {
12618c2ecf20Sopenharmony_ci				size_t num_written = ia.write.out.size;
12628c2ecf20Sopenharmony_ci
12638c2ecf20Sopenharmony_ci				res += num_written;
12648c2ecf20Sopenharmony_ci				pos += num_written;
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_ci				/* break out of the loop on short write */
12678c2ecf20Sopenharmony_ci				if (num_written != count)
12688c2ecf20Sopenharmony_ci					err = -EIO;
12698c2ecf20Sopenharmony_ci			}
12708c2ecf20Sopenharmony_ci		}
12718c2ecf20Sopenharmony_ci		kfree(ap->pages);
12728c2ecf20Sopenharmony_ci	} while (!err && iov_iter_count(ii));
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci	if (res > 0)
12758c2ecf20Sopenharmony_ci		fuse_write_update_size(inode, pos);
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ci	clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
12788c2ecf20Sopenharmony_ci	fuse_invalidate_attr(inode);
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci	return res > 0 ? res : err;
12818c2ecf20Sopenharmony_ci}
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_cistatic ssize_t fuse_cache_write_iter(struct kiocb *iocb, struct iov_iter *from)
12848c2ecf20Sopenharmony_ci{
12858c2ecf20Sopenharmony_ci	struct file *file = iocb->ki_filp;
12868c2ecf20Sopenharmony_ci	struct address_space *mapping = file->f_mapping;
12878c2ecf20Sopenharmony_ci	ssize_t written = 0;
12888c2ecf20Sopenharmony_ci	ssize_t written_buffered = 0;
12898c2ecf20Sopenharmony_ci	struct inode *inode = mapping->host;
12908c2ecf20Sopenharmony_ci	ssize_t err;
12918c2ecf20Sopenharmony_ci	loff_t endbyte = 0;
12928c2ecf20Sopenharmony_ci
12938c2ecf20Sopenharmony_ci	if (get_fuse_conn(inode)->writeback_cache) {
12948c2ecf20Sopenharmony_ci		/* Update size (EOF optimization) and mode (SUID clearing) */
12958c2ecf20Sopenharmony_ci		err = fuse_update_attributes(mapping->host, file);
12968c2ecf20Sopenharmony_ci		if (err)
12978c2ecf20Sopenharmony_ci			return err;
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_ci		return generic_file_write_iter(iocb, from);
13008c2ecf20Sopenharmony_ci	}
13018c2ecf20Sopenharmony_ci
13028c2ecf20Sopenharmony_ci	inode_lock(inode);
13038c2ecf20Sopenharmony_ci
13048c2ecf20Sopenharmony_ci	/* We can write back this queue in page reclaim */
13058c2ecf20Sopenharmony_ci	current->backing_dev_info = inode_to_bdi(inode);
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_ci	err = generic_write_checks(iocb, from);
13088c2ecf20Sopenharmony_ci	if (err <= 0)
13098c2ecf20Sopenharmony_ci		goto out;
13108c2ecf20Sopenharmony_ci
13118c2ecf20Sopenharmony_ci	err = file_remove_privs(file);
13128c2ecf20Sopenharmony_ci	if (err)
13138c2ecf20Sopenharmony_ci		goto out;
13148c2ecf20Sopenharmony_ci
13158c2ecf20Sopenharmony_ci	err = file_update_time(file);
13168c2ecf20Sopenharmony_ci	if (err)
13178c2ecf20Sopenharmony_ci		goto out;
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_ci	if (iocb->ki_flags & IOCB_DIRECT) {
13208c2ecf20Sopenharmony_ci		loff_t pos = iocb->ki_pos;
13218c2ecf20Sopenharmony_ci		written = generic_file_direct_write(iocb, from);
13228c2ecf20Sopenharmony_ci		if (written < 0 || !iov_iter_count(from))
13238c2ecf20Sopenharmony_ci			goto out;
13248c2ecf20Sopenharmony_ci
13258c2ecf20Sopenharmony_ci		pos += written;
13268c2ecf20Sopenharmony_ci
13278c2ecf20Sopenharmony_ci		written_buffered = fuse_perform_write(iocb, mapping, from, pos);
13288c2ecf20Sopenharmony_ci		if (written_buffered < 0) {
13298c2ecf20Sopenharmony_ci			err = written_buffered;
13308c2ecf20Sopenharmony_ci			goto out;
13318c2ecf20Sopenharmony_ci		}
13328c2ecf20Sopenharmony_ci		endbyte = pos + written_buffered - 1;
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_ci		err = filemap_write_and_wait_range(file->f_mapping, pos,
13358c2ecf20Sopenharmony_ci						   endbyte);
13368c2ecf20Sopenharmony_ci		if (err)
13378c2ecf20Sopenharmony_ci			goto out;
13388c2ecf20Sopenharmony_ci
13398c2ecf20Sopenharmony_ci		invalidate_mapping_pages(file->f_mapping,
13408c2ecf20Sopenharmony_ci					 pos >> PAGE_SHIFT,
13418c2ecf20Sopenharmony_ci					 endbyte >> PAGE_SHIFT);
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ci		written += written_buffered;
13448c2ecf20Sopenharmony_ci		iocb->ki_pos = pos + written_buffered;
13458c2ecf20Sopenharmony_ci	} else {
13468c2ecf20Sopenharmony_ci		written = fuse_perform_write(iocb, mapping, from, iocb->ki_pos);
13478c2ecf20Sopenharmony_ci		if (written >= 0)
13488c2ecf20Sopenharmony_ci			iocb->ki_pos += written;
13498c2ecf20Sopenharmony_ci	}
13508c2ecf20Sopenharmony_ciout:
13518c2ecf20Sopenharmony_ci	current->backing_dev_info = NULL;
13528c2ecf20Sopenharmony_ci	inode_unlock(inode);
13538c2ecf20Sopenharmony_ci	if (written > 0)
13548c2ecf20Sopenharmony_ci		written = generic_write_sync(iocb, written);
13558c2ecf20Sopenharmony_ci
13568c2ecf20Sopenharmony_ci	return written ? written : err;
13578c2ecf20Sopenharmony_ci}
13588c2ecf20Sopenharmony_ci
13598c2ecf20Sopenharmony_cistatic inline void fuse_page_descs_length_init(struct fuse_page_desc *descs,
13608c2ecf20Sopenharmony_ci					       unsigned int index,
13618c2ecf20Sopenharmony_ci					       unsigned int nr_pages)
13628c2ecf20Sopenharmony_ci{
13638c2ecf20Sopenharmony_ci	int i;
13648c2ecf20Sopenharmony_ci
13658c2ecf20Sopenharmony_ci	for (i = index; i < index + nr_pages; i++)
13668c2ecf20Sopenharmony_ci		descs[i].length = PAGE_SIZE - descs[i].offset;
13678c2ecf20Sopenharmony_ci}
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_cistatic inline unsigned long fuse_get_user_addr(const struct iov_iter *ii)
13708c2ecf20Sopenharmony_ci{
13718c2ecf20Sopenharmony_ci	return (unsigned long)ii->iov->iov_base + ii->iov_offset;
13728c2ecf20Sopenharmony_ci}
13738c2ecf20Sopenharmony_ci
13748c2ecf20Sopenharmony_cistatic inline size_t fuse_get_frag_size(const struct iov_iter *ii,
13758c2ecf20Sopenharmony_ci					size_t max_size)
13768c2ecf20Sopenharmony_ci{
13778c2ecf20Sopenharmony_ci	return min(iov_iter_single_seg_count(ii), max_size);
13788c2ecf20Sopenharmony_ci}
13798c2ecf20Sopenharmony_ci
13808c2ecf20Sopenharmony_cistatic int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii,
13818c2ecf20Sopenharmony_ci			       size_t *nbytesp, int write,
13828c2ecf20Sopenharmony_ci			       unsigned int max_pages)
13838c2ecf20Sopenharmony_ci{
13848c2ecf20Sopenharmony_ci	size_t nbytes = 0;  /* # bytes already packed in req */
13858c2ecf20Sopenharmony_ci	ssize_t ret = 0;
13868c2ecf20Sopenharmony_ci
13878c2ecf20Sopenharmony_ci	/* Special case for kernel I/O: can copy directly into the buffer */
13888c2ecf20Sopenharmony_ci	if (iov_iter_is_kvec(ii)) {
13898c2ecf20Sopenharmony_ci		unsigned long user_addr = fuse_get_user_addr(ii);
13908c2ecf20Sopenharmony_ci		size_t frag_size = fuse_get_frag_size(ii, *nbytesp);
13918c2ecf20Sopenharmony_ci
13928c2ecf20Sopenharmony_ci		if (write)
13938c2ecf20Sopenharmony_ci			ap->args.in_args[1].value = (void *) user_addr;
13948c2ecf20Sopenharmony_ci		else
13958c2ecf20Sopenharmony_ci			ap->args.out_args[0].value = (void *) user_addr;
13968c2ecf20Sopenharmony_ci
13978c2ecf20Sopenharmony_ci		iov_iter_advance(ii, frag_size);
13988c2ecf20Sopenharmony_ci		*nbytesp = frag_size;
13998c2ecf20Sopenharmony_ci		return 0;
14008c2ecf20Sopenharmony_ci	}
14018c2ecf20Sopenharmony_ci
14028c2ecf20Sopenharmony_ci	while (nbytes < *nbytesp && ap->num_pages < max_pages) {
14038c2ecf20Sopenharmony_ci		unsigned npages;
14048c2ecf20Sopenharmony_ci		size_t start;
14058c2ecf20Sopenharmony_ci		ret = iov_iter_get_pages(ii, &ap->pages[ap->num_pages],
14068c2ecf20Sopenharmony_ci					*nbytesp - nbytes,
14078c2ecf20Sopenharmony_ci					max_pages - ap->num_pages,
14088c2ecf20Sopenharmony_ci					&start);
14098c2ecf20Sopenharmony_ci		if (ret < 0)
14108c2ecf20Sopenharmony_ci			break;
14118c2ecf20Sopenharmony_ci
14128c2ecf20Sopenharmony_ci		iov_iter_advance(ii, ret);
14138c2ecf20Sopenharmony_ci		nbytes += ret;
14148c2ecf20Sopenharmony_ci
14158c2ecf20Sopenharmony_ci		ret += start;
14168c2ecf20Sopenharmony_ci		npages = (ret + PAGE_SIZE - 1) / PAGE_SIZE;
14178c2ecf20Sopenharmony_ci
14188c2ecf20Sopenharmony_ci		ap->descs[ap->num_pages].offset = start;
14198c2ecf20Sopenharmony_ci		fuse_page_descs_length_init(ap->descs, ap->num_pages, npages);
14208c2ecf20Sopenharmony_ci
14218c2ecf20Sopenharmony_ci		ap->num_pages += npages;
14228c2ecf20Sopenharmony_ci		ap->descs[ap->num_pages - 1].length -=
14238c2ecf20Sopenharmony_ci			(PAGE_SIZE - ret) & (PAGE_SIZE - 1);
14248c2ecf20Sopenharmony_ci	}
14258c2ecf20Sopenharmony_ci
14268c2ecf20Sopenharmony_ci	ap->args.user_pages = true;
14278c2ecf20Sopenharmony_ci	if (write)
14288c2ecf20Sopenharmony_ci		ap->args.in_pages = true;
14298c2ecf20Sopenharmony_ci	else
14308c2ecf20Sopenharmony_ci		ap->args.out_pages = true;
14318c2ecf20Sopenharmony_ci
14328c2ecf20Sopenharmony_ci	*nbytesp = nbytes;
14338c2ecf20Sopenharmony_ci
14348c2ecf20Sopenharmony_ci	return ret < 0 ? ret : 0;
14358c2ecf20Sopenharmony_ci}
14368c2ecf20Sopenharmony_ci
14378c2ecf20Sopenharmony_cissize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
14388c2ecf20Sopenharmony_ci		       loff_t *ppos, int flags)
14398c2ecf20Sopenharmony_ci{
14408c2ecf20Sopenharmony_ci	int write = flags & FUSE_DIO_WRITE;
14418c2ecf20Sopenharmony_ci	int cuse = flags & FUSE_DIO_CUSE;
14428c2ecf20Sopenharmony_ci	struct file *file = io->iocb->ki_filp;
14438c2ecf20Sopenharmony_ci	struct inode *inode = file->f_mapping->host;
14448c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
14458c2ecf20Sopenharmony_ci	struct fuse_conn *fc = ff->fm->fc;
14468c2ecf20Sopenharmony_ci	size_t nmax = write ? fc->max_write : fc->max_read;
14478c2ecf20Sopenharmony_ci	loff_t pos = *ppos;
14488c2ecf20Sopenharmony_ci	size_t count = iov_iter_count(iter);
14498c2ecf20Sopenharmony_ci	pgoff_t idx_from = pos >> PAGE_SHIFT;
14508c2ecf20Sopenharmony_ci	pgoff_t idx_to = (pos + count - 1) >> PAGE_SHIFT;
14518c2ecf20Sopenharmony_ci	ssize_t res = 0;
14528c2ecf20Sopenharmony_ci	int err = 0;
14538c2ecf20Sopenharmony_ci	struct fuse_io_args *ia;
14548c2ecf20Sopenharmony_ci	unsigned int max_pages;
14558c2ecf20Sopenharmony_ci
14568c2ecf20Sopenharmony_ci	max_pages = iov_iter_npages(iter, fc->max_pages);
14578c2ecf20Sopenharmony_ci	ia = fuse_io_alloc(io, max_pages);
14588c2ecf20Sopenharmony_ci	if (!ia)
14598c2ecf20Sopenharmony_ci		return -ENOMEM;
14608c2ecf20Sopenharmony_ci
14618c2ecf20Sopenharmony_ci	ia->io = io;
14628c2ecf20Sopenharmony_ci	if (!cuse && fuse_range_is_writeback(inode, idx_from, idx_to)) {
14638c2ecf20Sopenharmony_ci		if (!write)
14648c2ecf20Sopenharmony_ci			inode_lock(inode);
14658c2ecf20Sopenharmony_ci		fuse_sync_writes(inode);
14668c2ecf20Sopenharmony_ci		if (!write)
14678c2ecf20Sopenharmony_ci			inode_unlock(inode);
14688c2ecf20Sopenharmony_ci	}
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci	io->should_dirty = !write && iter_is_iovec(iter);
14718c2ecf20Sopenharmony_ci	while (count) {
14728c2ecf20Sopenharmony_ci		ssize_t nres;
14738c2ecf20Sopenharmony_ci		fl_owner_t owner = current->files;
14748c2ecf20Sopenharmony_ci		size_t nbytes = min(count, nmax);
14758c2ecf20Sopenharmony_ci
14768c2ecf20Sopenharmony_ci		err = fuse_get_user_pages(&ia->ap, iter, &nbytes, write,
14778c2ecf20Sopenharmony_ci					  max_pages);
14788c2ecf20Sopenharmony_ci		if (err && !nbytes)
14798c2ecf20Sopenharmony_ci			break;
14808c2ecf20Sopenharmony_ci
14818c2ecf20Sopenharmony_ci		if (write) {
14828c2ecf20Sopenharmony_ci			if (!capable(CAP_FSETID))
14838c2ecf20Sopenharmony_ci				ia->write.in.write_flags |= FUSE_WRITE_KILL_PRIV;
14848c2ecf20Sopenharmony_ci
14858c2ecf20Sopenharmony_ci			nres = fuse_send_write(ia, pos, nbytes, owner);
14868c2ecf20Sopenharmony_ci		} else {
14878c2ecf20Sopenharmony_ci			nres = fuse_send_read(ia, pos, nbytes, owner);
14888c2ecf20Sopenharmony_ci		}
14898c2ecf20Sopenharmony_ci
14908c2ecf20Sopenharmony_ci		if (!io->async || nres < 0) {
14918c2ecf20Sopenharmony_ci			fuse_release_user_pages(&ia->ap, io->should_dirty);
14928c2ecf20Sopenharmony_ci			fuse_io_free(ia);
14938c2ecf20Sopenharmony_ci		}
14948c2ecf20Sopenharmony_ci		ia = NULL;
14958c2ecf20Sopenharmony_ci		if (nres < 0) {
14968c2ecf20Sopenharmony_ci			iov_iter_revert(iter, nbytes);
14978c2ecf20Sopenharmony_ci			err = nres;
14988c2ecf20Sopenharmony_ci			break;
14998c2ecf20Sopenharmony_ci		}
15008c2ecf20Sopenharmony_ci		WARN_ON(nres > nbytes);
15018c2ecf20Sopenharmony_ci
15028c2ecf20Sopenharmony_ci		count -= nres;
15038c2ecf20Sopenharmony_ci		res += nres;
15048c2ecf20Sopenharmony_ci		pos += nres;
15058c2ecf20Sopenharmony_ci		if (nres != nbytes) {
15068c2ecf20Sopenharmony_ci			iov_iter_revert(iter, nbytes - nres);
15078c2ecf20Sopenharmony_ci			break;
15088c2ecf20Sopenharmony_ci		}
15098c2ecf20Sopenharmony_ci		if (count) {
15108c2ecf20Sopenharmony_ci			max_pages = iov_iter_npages(iter, fc->max_pages);
15118c2ecf20Sopenharmony_ci			ia = fuse_io_alloc(io, max_pages);
15128c2ecf20Sopenharmony_ci			if (!ia)
15138c2ecf20Sopenharmony_ci				break;
15148c2ecf20Sopenharmony_ci		}
15158c2ecf20Sopenharmony_ci	}
15168c2ecf20Sopenharmony_ci	if (ia)
15178c2ecf20Sopenharmony_ci		fuse_io_free(ia);
15188c2ecf20Sopenharmony_ci	if (res > 0)
15198c2ecf20Sopenharmony_ci		*ppos = pos;
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci	return res > 0 ? res : err;
15228c2ecf20Sopenharmony_ci}
15238c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fuse_direct_io);
15248c2ecf20Sopenharmony_ci
15258c2ecf20Sopenharmony_cistatic ssize_t __fuse_direct_read(struct fuse_io_priv *io,
15268c2ecf20Sopenharmony_ci				  struct iov_iter *iter,
15278c2ecf20Sopenharmony_ci				  loff_t *ppos)
15288c2ecf20Sopenharmony_ci{
15298c2ecf20Sopenharmony_ci	ssize_t res;
15308c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(io->iocb->ki_filp);
15318c2ecf20Sopenharmony_ci
15328c2ecf20Sopenharmony_ci	res = fuse_direct_io(io, iter, ppos, 0);
15338c2ecf20Sopenharmony_ci
15348c2ecf20Sopenharmony_ci	fuse_invalidate_atime(inode);
15358c2ecf20Sopenharmony_ci
15368c2ecf20Sopenharmony_ci	return res;
15378c2ecf20Sopenharmony_ci}
15388c2ecf20Sopenharmony_ci
15398c2ecf20Sopenharmony_cistatic ssize_t fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter);
15408c2ecf20Sopenharmony_ci
15418c2ecf20Sopenharmony_cistatic ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to)
15428c2ecf20Sopenharmony_ci{
15438c2ecf20Sopenharmony_ci	ssize_t res;
15448c2ecf20Sopenharmony_ci
15458c2ecf20Sopenharmony_ci	if (!is_sync_kiocb(iocb) && iocb->ki_flags & IOCB_DIRECT) {
15468c2ecf20Sopenharmony_ci		res = fuse_direct_IO(iocb, to);
15478c2ecf20Sopenharmony_ci	} else {
15488c2ecf20Sopenharmony_ci		struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb);
15498c2ecf20Sopenharmony_ci
15508c2ecf20Sopenharmony_ci		res = __fuse_direct_read(&io, to, &iocb->ki_pos);
15518c2ecf20Sopenharmony_ci	}
15528c2ecf20Sopenharmony_ci
15538c2ecf20Sopenharmony_ci	return res;
15548c2ecf20Sopenharmony_ci}
15558c2ecf20Sopenharmony_ci
15568c2ecf20Sopenharmony_cistatic ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
15578c2ecf20Sopenharmony_ci{
15588c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(iocb->ki_filp);
15598c2ecf20Sopenharmony_ci	struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb);
15608c2ecf20Sopenharmony_ci	ssize_t res;
15618c2ecf20Sopenharmony_ci
15628c2ecf20Sopenharmony_ci	/* Don't allow parallel writes to the same file */
15638c2ecf20Sopenharmony_ci	inode_lock(inode);
15648c2ecf20Sopenharmony_ci	res = generic_write_checks(iocb, from);
15658c2ecf20Sopenharmony_ci	if (res > 0) {
15668c2ecf20Sopenharmony_ci		if (!is_sync_kiocb(iocb) && iocb->ki_flags & IOCB_DIRECT) {
15678c2ecf20Sopenharmony_ci			res = fuse_direct_IO(iocb, from);
15688c2ecf20Sopenharmony_ci		} else {
15698c2ecf20Sopenharmony_ci			res = fuse_direct_io(&io, from, &iocb->ki_pos,
15708c2ecf20Sopenharmony_ci					     FUSE_DIO_WRITE);
15718c2ecf20Sopenharmony_ci		}
15728c2ecf20Sopenharmony_ci	}
15738c2ecf20Sopenharmony_ci	fuse_invalidate_attr(inode);
15748c2ecf20Sopenharmony_ci	if (res > 0)
15758c2ecf20Sopenharmony_ci		fuse_write_update_size(inode, iocb->ki_pos);
15768c2ecf20Sopenharmony_ci	inode_unlock(inode);
15778c2ecf20Sopenharmony_ci
15788c2ecf20Sopenharmony_ci	return res;
15798c2ecf20Sopenharmony_ci}
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_cistatic ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
15828c2ecf20Sopenharmony_ci{
15838c2ecf20Sopenharmony_ci	struct file *file = iocb->ki_filp;
15848c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
15858c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(file);
15868c2ecf20Sopenharmony_ci
15878c2ecf20Sopenharmony_ci	if (fuse_is_bad(inode))
15888c2ecf20Sopenharmony_ci		return -EIO;
15898c2ecf20Sopenharmony_ci
15908c2ecf20Sopenharmony_ci	if (FUSE_IS_DAX(inode))
15918c2ecf20Sopenharmony_ci		return fuse_dax_read_iter(iocb, to);
15928c2ecf20Sopenharmony_ci
15938c2ecf20Sopenharmony_ci	if (!(ff->open_flags & FOPEN_DIRECT_IO))
15948c2ecf20Sopenharmony_ci		return fuse_cache_read_iter(iocb, to);
15958c2ecf20Sopenharmony_ci	else
15968c2ecf20Sopenharmony_ci		return fuse_direct_read_iter(iocb, to);
15978c2ecf20Sopenharmony_ci}
15988c2ecf20Sopenharmony_ci
15998c2ecf20Sopenharmony_cistatic ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
16008c2ecf20Sopenharmony_ci{
16018c2ecf20Sopenharmony_ci	struct file *file = iocb->ki_filp;
16028c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
16038c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(file);
16048c2ecf20Sopenharmony_ci
16058c2ecf20Sopenharmony_ci	if (fuse_is_bad(inode))
16068c2ecf20Sopenharmony_ci		return -EIO;
16078c2ecf20Sopenharmony_ci
16088c2ecf20Sopenharmony_ci	if (FUSE_IS_DAX(inode))
16098c2ecf20Sopenharmony_ci		return fuse_dax_write_iter(iocb, from);
16108c2ecf20Sopenharmony_ci
16118c2ecf20Sopenharmony_ci	if (!(ff->open_flags & FOPEN_DIRECT_IO))
16128c2ecf20Sopenharmony_ci		return fuse_cache_write_iter(iocb, from);
16138c2ecf20Sopenharmony_ci	else
16148c2ecf20Sopenharmony_ci		return fuse_direct_write_iter(iocb, from);
16158c2ecf20Sopenharmony_ci}
16168c2ecf20Sopenharmony_ci
16178c2ecf20Sopenharmony_cistatic void fuse_writepage_free(struct fuse_writepage_args *wpa)
16188c2ecf20Sopenharmony_ci{
16198c2ecf20Sopenharmony_ci	struct fuse_args_pages *ap = &wpa->ia.ap;
16208c2ecf20Sopenharmony_ci	int i;
16218c2ecf20Sopenharmony_ci
16228c2ecf20Sopenharmony_ci	for (i = 0; i < ap->num_pages; i++)
16238c2ecf20Sopenharmony_ci		__free_page(ap->pages[i]);
16248c2ecf20Sopenharmony_ci
16258c2ecf20Sopenharmony_ci	if (wpa->ia.ff)
16268c2ecf20Sopenharmony_ci		fuse_file_put(wpa->ia.ff, false, false);
16278c2ecf20Sopenharmony_ci
16288c2ecf20Sopenharmony_ci	kfree(ap->pages);
16298c2ecf20Sopenharmony_ci	kfree(wpa);
16308c2ecf20Sopenharmony_ci}
16318c2ecf20Sopenharmony_ci
16328c2ecf20Sopenharmony_cistatic void fuse_writepage_finish(struct fuse_mount *fm,
16338c2ecf20Sopenharmony_ci				  struct fuse_writepage_args *wpa)
16348c2ecf20Sopenharmony_ci{
16358c2ecf20Sopenharmony_ci	struct fuse_args_pages *ap = &wpa->ia.ap;
16368c2ecf20Sopenharmony_ci	struct inode *inode = wpa->inode;
16378c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(inode);
16388c2ecf20Sopenharmony_ci	struct backing_dev_info *bdi = inode_to_bdi(inode);
16398c2ecf20Sopenharmony_ci	int i;
16408c2ecf20Sopenharmony_ci
16418c2ecf20Sopenharmony_ci	for (i = 0; i < ap->num_pages; i++) {
16428c2ecf20Sopenharmony_ci		dec_wb_stat(&bdi->wb, WB_WRITEBACK);
16438c2ecf20Sopenharmony_ci		dec_node_page_state(ap->pages[i], NR_WRITEBACK_TEMP);
16448c2ecf20Sopenharmony_ci		wb_writeout_inc(&bdi->wb);
16458c2ecf20Sopenharmony_ci	}
16468c2ecf20Sopenharmony_ci	wake_up(&fi->page_waitq);
16478c2ecf20Sopenharmony_ci}
16488c2ecf20Sopenharmony_ci
16498c2ecf20Sopenharmony_ci/* Called under fi->lock, may release and reacquire it */
16508c2ecf20Sopenharmony_cistatic void fuse_send_writepage(struct fuse_mount *fm,
16518c2ecf20Sopenharmony_ci				struct fuse_writepage_args *wpa, loff_t size)
16528c2ecf20Sopenharmony_ci__releases(fi->lock)
16538c2ecf20Sopenharmony_ci__acquires(fi->lock)
16548c2ecf20Sopenharmony_ci{
16558c2ecf20Sopenharmony_ci	struct fuse_writepage_args *aux, *next;
16568c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(wpa->inode);
16578c2ecf20Sopenharmony_ci	struct fuse_write_in *inarg = &wpa->ia.write.in;
16588c2ecf20Sopenharmony_ci	struct fuse_args *args = &wpa->ia.ap.args;
16598c2ecf20Sopenharmony_ci	__u64 data_size = wpa->ia.ap.num_pages * PAGE_SIZE;
16608c2ecf20Sopenharmony_ci	int err;
16618c2ecf20Sopenharmony_ci
16628c2ecf20Sopenharmony_ci	fi->writectr++;
16638c2ecf20Sopenharmony_ci	if (inarg->offset + data_size <= size) {
16648c2ecf20Sopenharmony_ci		inarg->size = data_size;
16658c2ecf20Sopenharmony_ci	} else if (inarg->offset < size) {
16668c2ecf20Sopenharmony_ci		inarg->size = size - inarg->offset;
16678c2ecf20Sopenharmony_ci	} else {
16688c2ecf20Sopenharmony_ci		/* Got truncated off completely */
16698c2ecf20Sopenharmony_ci		goto out_free;
16708c2ecf20Sopenharmony_ci	}
16718c2ecf20Sopenharmony_ci
16728c2ecf20Sopenharmony_ci	args->in_args[1].size = inarg->size;
16738c2ecf20Sopenharmony_ci	args->force = true;
16748c2ecf20Sopenharmony_ci	args->nocreds = true;
16758c2ecf20Sopenharmony_ci
16768c2ecf20Sopenharmony_ci	err = fuse_simple_background(fm, args, GFP_ATOMIC);
16778c2ecf20Sopenharmony_ci	if (err == -ENOMEM) {
16788c2ecf20Sopenharmony_ci		spin_unlock(&fi->lock);
16798c2ecf20Sopenharmony_ci		err = fuse_simple_background(fm, args, GFP_NOFS | __GFP_NOFAIL);
16808c2ecf20Sopenharmony_ci		spin_lock(&fi->lock);
16818c2ecf20Sopenharmony_ci	}
16828c2ecf20Sopenharmony_ci
16838c2ecf20Sopenharmony_ci	/* Fails on broken connection only */
16848c2ecf20Sopenharmony_ci	if (unlikely(err))
16858c2ecf20Sopenharmony_ci		goto out_free;
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_ci	return;
16888c2ecf20Sopenharmony_ci
16898c2ecf20Sopenharmony_ci out_free:
16908c2ecf20Sopenharmony_ci	fi->writectr--;
16918c2ecf20Sopenharmony_ci	rb_erase(&wpa->writepages_entry, &fi->writepages);
16928c2ecf20Sopenharmony_ci	fuse_writepage_finish(fm, wpa);
16938c2ecf20Sopenharmony_ci	spin_unlock(&fi->lock);
16948c2ecf20Sopenharmony_ci
16958c2ecf20Sopenharmony_ci	/* After fuse_writepage_finish() aux request list is private */
16968c2ecf20Sopenharmony_ci	for (aux = wpa->next; aux; aux = next) {
16978c2ecf20Sopenharmony_ci		next = aux->next;
16988c2ecf20Sopenharmony_ci		aux->next = NULL;
16998c2ecf20Sopenharmony_ci		fuse_writepage_free(aux);
17008c2ecf20Sopenharmony_ci	}
17018c2ecf20Sopenharmony_ci
17028c2ecf20Sopenharmony_ci	fuse_writepage_free(wpa);
17038c2ecf20Sopenharmony_ci	spin_lock(&fi->lock);
17048c2ecf20Sopenharmony_ci}
17058c2ecf20Sopenharmony_ci
17068c2ecf20Sopenharmony_ci/*
17078c2ecf20Sopenharmony_ci * If fi->writectr is positive (no truncate or fsync going on) send
17088c2ecf20Sopenharmony_ci * all queued writepage requests.
17098c2ecf20Sopenharmony_ci *
17108c2ecf20Sopenharmony_ci * Called with fi->lock
17118c2ecf20Sopenharmony_ci */
17128c2ecf20Sopenharmony_civoid fuse_flush_writepages(struct inode *inode)
17138c2ecf20Sopenharmony_ci__releases(fi->lock)
17148c2ecf20Sopenharmony_ci__acquires(fi->lock)
17158c2ecf20Sopenharmony_ci{
17168c2ecf20Sopenharmony_ci	struct fuse_mount *fm = get_fuse_mount(inode);
17178c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(inode);
17188c2ecf20Sopenharmony_ci	loff_t crop = i_size_read(inode);
17198c2ecf20Sopenharmony_ci	struct fuse_writepage_args *wpa;
17208c2ecf20Sopenharmony_ci
17218c2ecf20Sopenharmony_ci	while (fi->writectr >= 0 && !list_empty(&fi->queued_writes)) {
17228c2ecf20Sopenharmony_ci		wpa = list_entry(fi->queued_writes.next,
17238c2ecf20Sopenharmony_ci				 struct fuse_writepage_args, queue_entry);
17248c2ecf20Sopenharmony_ci		list_del_init(&wpa->queue_entry);
17258c2ecf20Sopenharmony_ci		fuse_send_writepage(fm, wpa, crop);
17268c2ecf20Sopenharmony_ci	}
17278c2ecf20Sopenharmony_ci}
17288c2ecf20Sopenharmony_ci
17298c2ecf20Sopenharmony_cistatic struct fuse_writepage_args *fuse_insert_writeback(struct rb_root *root,
17308c2ecf20Sopenharmony_ci						struct fuse_writepage_args *wpa)
17318c2ecf20Sopenharmony_ci{
17328c2ecf20Sopenharmony_ci	pgoff_t idx_from = wpa->ia.write.in.offset >> PAGE_SHIFT;
17338c2ecf20Sopenharmony_ci	pgoff_t idx_to = idx_from + wpa->ia.ap.num_pages - 1;
17348c2ecf20Sopenharmony_ci	struct rb_node **p = &root->rb_node;
17358c2ecf20Sopenharmony_ci	struct rb_node  *parent = NULL;
17368c2ecf20Sopenharmony_ci
17378c2ecf20Sopenharmony_ci	WARN_ON(!wpa->ia.ap.num_pages);
17388c2ecf20Sopenharmony_ci	while (*p) {
17398c2ecf20Sopenharmony_ci		struct fuse_writepage_args *curr;
17408c2ecf20Sopenharmony_ci		pgoff_t curr_index;
17418c2ecf20Sopenharmony_ci
17428c2ecf20Sopenharmony_ci		parent = *p;
17438c2ecf20Sopenharmony_ci		curr = rb_entry(parent, struct fuse_writepage_args,
17448c2ecf20Sopenharmony_ci				writepages_entry);
17458c2ecf20Sopenharmony_ci		WARN_ON(curr->inode != wpa->inode);
17468c2ecf20Sopenharmony_ci		curr_index = curr->ia.write.in.offset >> PAGE_SHIFT;
17478c2ecf20Sopenharmony_ci
17488c2ecf20Sopenharmony_ci		if (idx_from >= curr_index + curr->ia.ap.num_pages)
17498c2ecf20Sopenharmony_ci			p = &(*p)->rb_right;
17508c2ecf20Sopenharmony_ci		else if (idx_to < curr_index)
17518c2ecf20Sopenharmony_ci			p = &(*p)->rb_left;
17528c2ecf20Sopenharmony_ci		else
17538c2ecf20Sopenharmony_ci			return curr;
17548c2ecf20Sopenharmony_ci	}
17558c2ecf20Sopenharmony_ci
17568c2ecf20Sopenharmony_ci	rb_link_node(&wpa->writepages_entry, parent, p);
17578c2ecf20Sopenharmony_ci	rb_insert_color(&wpa->writepages_entry, root);
17588c2ecf20Sopenharmony_ci	return NULL;
17598c2ecf20Sopenharmony_ci}
17608c2ecf20Sopenharmony_ci
17618c2ecf20Sopenharmony_cistatic void tree_insert(struct rb_root *root, struct fuse_writepage_args *wpa)
17628c2ecf20Sopenharmony_ci{
17638c2ecf20Sopenharmony_ci	WARN_ON(fuse_insert_writeback(root, wpa));
17648c2ecf20Sopenharmony_ci}
17658c2ecf20Sopenharmony_ci
17668c2ecf20Sopenharmony_cistatic void fuse_writepage_end(struct fuse_mount *fm, struct fuse_args *args,
17678c2ecf20Sopenharmony_ci			       int error)
17688c2ecf20Sopenharmony_ci{
17698c2ecf20Sopenharmony_ci	struct fuse_writepage_args *wpa =
17708c2ecf20Sopenharmony_ci		container_of(args, typeof(*wpa), ia.ap.args);
17718c2ecf20Sopenharmony_ci	struct inode *inode = wpa->inode;
17728c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(inode);
17738c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
17748c2ecf20Sopenharmony_ci
17758c2ecf20Sopenharmony_ci	mapping_set_error(inode->i_mapping, error);
17768c2ecf20Sopenharmony_ci	/*
17778c2ecf20Sopenharmony_ci	 * A writeback finished and this might have updated mtime/ctime on
17788c2ecf20Sopenharmony_ci	 * server making local mtime/ctime stale.  Hence invalidate attrs.
17798c2ecf20Sopenharmony_ci	 * Do this only if writeback_cache is not enabled.  If writeback_cache
17808c2ecf20Sopenharmony_ci	 * is enabled, we trust local ctime/mtime.
17818c2ecf20Sopenharmony_ci	 */
17828c2ecf20Sopenharmony_ci	if (!fc->writeback_cache)
17838c2ecf20Sopenharmony_ci		fuse_invalidate_attr(inode);
17848c2ecf20Sopenharmony_ci	spin_lock(&fi->lock);
17858c2ecf20Sopenharmony_ci	rb_erase(&wpa->writepages_entry, &fi->writepages);
17868c2ecf20Sopenharmony_ci	while (wpa->next) {
17878c2ecf20Sopenharmony_ci		struct fuse_mount *fm = get_fuse_mount(inode);
17888c2ecf20Sopenharmony_ci		struct fuse_write_in *inarg = &wpa->ia.write.in;
17898c2ecf20Sopenharmony_ci		struct fuse_writepage_args *next = wpa->next;
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_ci		wpa->next = next->next;
17928c2ecf20Sopenharmony_ci		next->next = NULL;
17938c2ecf20Sopenharmony_ci		next->ia.ff = fuse_file_get(wpa->ia.ff);
17948c2ecf20Sopenharmony_ci		tree_insert(&fi->writepages, next);
17958c2ecf20Sopenharmony_ci
17968c2ecf20Sopenharmony_ci		/*
17978c2ecf20Sopenharmony_ci		 * Skip fuse_flush_writepages() to make it easy to crop requests
17988c2ecf20Sopenharmony_ci		 * based on primary request size.
17998c2ecf20Sopenharmony_ci		 *
18008c2ecf20Sopenharmony_ci		 * 1st case (trivial): there are no concurrent activities using
18018c2ecf20Sopenharmony_ci		 * fuse_set/release_nowrite.  Then we're on safe side because
18028c2ecf20Sopenharmony_ci		 * fuse_flush_writepages() would call fuse_send_writepage()
18038c2ecf20Sopenharmony_ci		 * anyway.
18048c2ecf20Sopenharmony_ci		 *
18058c2ecf20Sopenharmony_ci		 * 2nd case: someone called fuse_set_nowrite and it is waiting
18068c2ecf20Sopenharmony_ci		 * now for completion of all in-flight requests.  This happens
18078c2ecf20Sopenharmony_ci		 * rarely and no more than once per page, so this should be
18088c2ecf20Sopenharmony_ci		 * okay.
18098c2ecf20Sopenharmony_ci		 *
18108c2ecf20Sopenharmony_ci		 * 3rd case: someone (e.g. fuse_do_setattr()) is in the middle
18118c2ecf20Sopenharmony_ci		 * of fuse_set_nowrite..fuse_release_nowrite section.  The fact
18128c2ecf20Sopenharmony_ci		 * that fuse_set_nowrite returned implies that all in-flight
18138c2ecf20Sopenharmony_ci		 * requests were completed along with all of their secondary
18148c2ecf20Sopenharmony_ci		 * requests.  Further primary requests are blocked by negative
18158c2ecf20Sopenharmony_ci		 * writectr.  Hence there cannot be any in-flight requests and
18168c2ecf20Sopenharmony_ci		 * no invocations of fuse_writepage_end() while we're in
18178c2ecf20Sopenharmony_ci		 * fuse_set_nowrite..fuse_release_nowrite section.
18188c2ecf20Sopenharmony_ci		 */
18198c2ecf20Sopenharmony_ci		fuse_send_writepage(fm, next, inarg->offset + inarg->size);
18208c2ecf20Sopenharmony_ci	}
18218c2ecf20Sopenharmony_ci	fi->writectr--;
18228c2ecf20Sopenharmony_ci	fuse_writepage_finish(fm, wpa);
18238c2ecf20Sopenharmony_ci	spin_unlock(&fi->lock);
18248c2ecf20Sopenharmony_ci	fuse_writepage_free(wpa);
18258c2ecf20Sopenharmony_ci}
18268c2ecf20Sopenharmony_ci
18278c2ecf20Sopenharmony_cistatic struct fuse_file *__fuse_write_file_get(struct fuse_conn *fc,
18288c2ecf20Sopenharmony_ci					       struct fuse_inode *fi)
18298c2ecf20Sopenharmony_ci{
18308c2ecf20Sopenharmony_ci	struct fuse_file *ff = NULL;
18318c2ecf20Sopenharmony_ci
18328c2ecf20Sopenharmony_ci	spin_lock(&fi->lock);
18338c2ecf20Sopenharmony_ci	if (!list_empty(&fi->write_files)) {
18348c2ecf20Sopenharmony_ci		ff = list_entry(fi->write_files.next, struct fuse_file,
18358c2ecf20Sopenharmony_ci				write_entry);
18368c2ecf20Sopenharmony_ci		fuse_file_get(ff);
18378c2ecf20Sopenharmony_ci	}
18388c2ecf20Sopenharmony_ci	spin_unlock(&fi->lock);
18398c2ecf20Sopenharmony_ci
18408c2ecf20Sopenharmony_ci	return ff;
18418c2ecf20Sopenharmony_ci}
18428c2ecf20Sopenharmony_ci
18438c2ecf20Sopenharmony_cistatic struct fuse_file *fuse_write_file_get(struct fuse_conn *fc,
18448c2ecf20Sopenharmony_ci					     struct fuse_inode *fi)
18458c2ecf20Sopenharmony_ci{
18468c2ecf20Sopenharmony_ci	struct fuse_file *ff = __fuse_write_file_get(fc, fi);
18478c2ecf20Sopenharmony_ci	WARN_ON(!ff);
18488c2ecf20Sopenharmony_ci	return ff;
18498c2ecf20Sopenharmony_ci}
18508c2ecf20Sopenharmony_ci
18518c2ecf20Sopenharmony_ciint fuse_write_inode(struct inode *inode, struct writeback_control *wbc)
18528c2ecf20Sopenharmony_ci{
18538c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
18548c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(inode);
18558c2ecf20Sopenharmony_ci	struct fuse_file *ff;
18568c2ecf20Sopenharmony_ci	int err;
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_ci	/*
18598c2ecf20Sopenharmony_ci	 * Inode is always written before the last reference is dropped and
18608c2ecf20Sopenharmony_ci	 * hence this should not be reached from reclaim.
18618c2ecf20Sopenharmony_ci	 *
18628c2ecf20Sopenharmony_ci	 * Writing back the inode from reclaim can deadlock if the request
18638c2ecf20Sopenharmony_ci	 * processing itself needs an allocation.  Allocations triggering
18648c2ecf20Sopenharmony_ci	 * reclaim while serving a request can't be prevented, because it can
18658c2ecf20Sopenharmony_ci	 * involve any number of unrelated userspace processes.
18668c2ecf20Sopenharmony_ci	 */
18678c2ecf20Sopenharmony_ci	WARN_ON(wbc->for_reclaim);
18688c2ecf20Sopenharmony_ci
18698c2ecf20Sopenharmony_ci	ff = __fuse_write_file_get(fc, fi);
18708c2ecf20Sopenharmony_ci	err = fuse_flush_times(inode, ff);
18718c2ecf20Sopenharmony_ci	if (ff)
18728c2ecf20Sopenharmony_ci		fuse_file_put(ff, false, false);
18738c2ecf20Sopenharmony_ci
18748c2ecf20Sopenharmony_ci	return err;
18758c2ecf20Sopenharmony_ci}
18768c2ecf20Sopenharmony_ci
18778c2ecf20Sopenharmony_cistatic struct fuse_writepage_args *fuse_writepage_args_alloc(void)
18788c2ecf20Sopenharmony_ci{
18798c2ecf20Sopenharmony_ci	struct fuse_writepage_args *wpa;
18808c2ecf20Sopenharmony_ci	struct fuse_args_pages *ap;
18818c2ecf20Sopenharmony_ci
18828c2ecf20Sopenharmony_ci	wpa = kzalloc(sizeof(*wpa), GFP_NOFS);
18838c2ecf20Sopenharmony_ci	if (wpa) {
18848c2ecf20Sopenharmony_ci		ap = &wpa->ia.ap;
18858c2ecf20Sopenharmony_ci		ap->num_pages = 0;
18868c2ecf20Sopenharmony_ci		ap->pages = fuse_pages_alloc(1, GFP_NOFS, &ap->descs);
18878c2ecf20Sopenharmony_ci		if (!ap->pages) {
18888c2ecf20Sopenharmony_ci			kfree(wpa);
18898c2ecf20Sopenharmony_ci			wpa = NULL;
18908c2ecf20Sopenharmony_ci		}
18918c2ecf20Sopenharmony_ci	}
18928c2ecf20Sopenharmony_ci	return wpa;
18938c2ecf20Sopenharmony_ci
18948c2ecf20Sopenharmony_ci}
18958c2ecf20Sopenharmony_ci
18968c2ecf20Sopenharmony_cistatic int fuse_writepage_locked(struct page *page)
18978c2ecf20Sopenharmony_ci{
18988c2ecf20Sopenharmony_ci	struct address_space *mapping = page->mapping;
18998c2ecf20Sopenharmony_ci	struct inode *inode = mapping->host;
19008c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
19018c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(inode);
19028c2ecf20Sopenharmony_ci	struct fuse_writepage_args *wpa;
19038c2ecf20Sopenharmony_ci	struct fuse_args_pages *ap;
19048c2ecf20Sopenharmony_ci	struct page *tmp_page;
19058c2ecf20Sopenharmony_ci	int error = -ENOMEM;
19068c2ecf20Sopenharmony_ci
19078c2ecf20Sopenharmony_ci	set_page_writeback(page);
19088c2ecf20Sopenharmony_ci
19098c2ecf20Sopenharmony_ci	wpa = fuse_writepage_args_alloc();
19108c2ecf20Sopenharmony_ci	if (!wpa)
19118c2ecf20Sopenharmony_ci		goto err;
19128c2ecf20Sopenharmony_ci	ap = &wpa->ia.ap;
19138c2ecf20Sopenharmony_ci
19148c2ecf20Sopenharmony_ci	tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
19158c2ecf20Sopenharmony_ci	if (!tmp_page)
19168c2ecf20Sopenharmony_ci		goto err_free;
19178c2ecf20Sopenharmony_ci
19188c2ecf20Sopenharmony_ci	error = -EIO;
19198c2ecf20Sopenharmony_ci	wpa->ia.ff = fuse_write_file_get(fc, fi);
19208c2ecf20Sopenharmony_ci	if (!wpa->ia.ff)
19218c2ecf20Sopenharmony_ci		goto err_nofile;
19228c2ecf20Sopenharmony_ci
19238c2ecf20Sopenharmony_ci	fuse_write_args_fill(&wpa->ia, wpa->ia.ff, page_offset(page), 0);
19248c2ecf20Sopenharmony_ci
19258c2ecf20Sopenharmony_ci	copy_highpage(tmp_page, page);
19268c2ecf20Sopenharmony_ci	wpa->ia.write.in.write_flags |= FUSE_WRITE_CACHE;
19278c2ecf20Sopenharmony_ci	wpa->next = NULL;
19288c2ecf20Sopenharmony_ci	ap->args.in_pages = true;
19298c2ecf20Sopenharmony_ci	ap->num_pages = 1;
19308c2ecf20Sopenharmony_ci	ap->pages[0] = tmp_page;
19318c2ecf20Sopenharmony_ci	ap->descs[0].offset = 0;
19328c2ecf20Sopenharmony_ci	ap->descs[0].length = PAGE_SIZE;
19338c2ecf20Sopenharmony_ci	ap->args.end = fuse_writepage_end;
19348c2ecf20Sopenharmony_ci	wpa->inode = inode;
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_ci	inc_wb_stat(&inode_to_bdi(inode)->wb, WB_WRITEBACK);
19378c2ecf20Sopenharmony_ci	inc_node_page_state(tmp_page, NR_WRITEBACK_TEMP);
19388c2ecf20Sopenharmony_ci
19398c2ecf20Sopenharmony_ci	spin_lock(&fi->lock);
19408c2ecf20Sopenharmony_ci	tree_insert(&fi->writepages, wpa);
19418c2ecf20Sopenharmony_ci	list_add_tail(&wpa->queue_entry, &fi->queued_writes);
19428c2ecf20Sopenharmony_ci	fuse_flush_writepages(inode);
19438c2ecf20Sopenharmony_ci	spin_unlock(&fi->lock);
19448c2ecf20Sopenharmony_ci
19458c2ecf20Sopenharmony_ci	end_page_writeback(page);
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_ci	return 0;
19488c2ecf20Sopenharmony_ci
19498c2ecf20Sopenharmony_cierr_nofile:
19508c2ecf20Sopenharmony_ci	__free_page(tmp_page);
19518c2ecf20Sopenharmony_cierr_free:
19528c2ecf20Sopenharmony_ci	kfree(wpa);
19538c2ecf20Sopenharmony_cierr:
19548c2ecf20Sopenharmony_ci	mapping_set_error(page->mapping, error);
19558c2ecf20Sopenharmony_ci	end_page_writeback(page);
19568c2ecf20Sopenharmony_ci	return error;
19578c2ecf20Sopenharmony_ci}
19588c2ecf20Sopenharmony_ci
19598c2ecf20Sopenharmony_cistatic int fuse_writepage(struct page *page, struct writeback_control *wbc)
19608c2ecf20Sopenharmony_ci{
19618c2ecf20Sopenharmony_ci	int err;
19628c2ecf20Sopenharmony_ci
19638c2ecf20Sopenharmony_ci	if (fuse_page_is_writeback(page->mapping->host, page->index)) {
19648c2ecf20Sopenharmony_ci		/*
19658c2ecf20Sopenharmony_ci		 * ->writepages() should be called for sync() and friends.  We
19668c2ecf20Sopenharmony_ci		 * should only get here on direct reclaim and then we are
19678c2ecf20Sopenharmony_ci		 * allowed to skip a page which is already in flight
19688c2ecf20Sopenharmony_ci		 */
19698c2ecf20Sopenharmony_ci		WARN_ON(wbc->sync_mode == WB_SYNC_ALL);
19708c2ecf20Sopenharmony_ci
19718c2ecf20Sopenharmony_ci		redirty_page_for_writepage(wbc, page);
19728c2ecf20Sopenharmony_ci		unlock_page(page);
19738c2ecf20Sopenharmony_ci		return 0;
19748c2ecf20Sopenharmony_ci	}
19758c2ecf20Sopenharmony_ci
19768c2ecf20Sopenharmony_ci	err = fuse_writepage_locked(page);
19778c2ecf20Sopenharmony_ci	unlock_page(page);
19788c2ecf20Sopenharmony_ci
19798c2ecf20Sopenharmony_ci	return err;
19808c2ecf20Sopenharmony_ci}
19818c2ecf20Sopenharmony_ci
19828c2ecf20Sopenharmony_cistruct fuse_fill_wb_data {
19838c2ecf20Sopenharmony_ci	struct fuse_writepage_args *wpa;
19848c2ecf20Sopenharmony_ci	struct fuse_file *ff;
19858c2ecf20Sopenharmony_ci	struct inode *inode;
19868c2ecf20Sopenharmony_ci	struct page **orig_pages;
19878c2ecf20Sopenharmony_ci	unsigned int max_pages;
19888c2ecf20Sopenharmony_ci};
19898c2ecf20Sopenharmony_ci
19908c2ecf20Sopenharmony_cistatic bool fuse_pages_realloc(struct fuse_fill_wb_data *data)
19918c2ecf20Sopenharmony_ci{
19928c2ecf20Sopenharmony_ci	struct fuse_args_pages *ap = &data->wpa->ia.ap;
19938c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(data->inode);
19948c2ecf20Sopenharmony_ci	struct page **pages;
19958c2ecf20Sopenharmony_ci	struct fuse_page_desc *descs;
19968c2ecf20Sopenharmony_ci	unsigned int npages = min_t(unsigned int,
19978c2ecf20Sopenharmony_ci				    max_t(unsigned int, data->max_pages * 2,
19988c2ecf20Sopenharmony_ci					  FUSE_DEFAULT_MAX_PAGES_PER_REQ),
19998c2ecf20Sopenharmony_ci				    fc->max_pages);
20008c2ecf20Sopenharmony_ci	WARN_ON(npages <= data->max_pages);
20018c2ecf20Sopenharmony_ci
20028c2ecf20Sopenharmony_ci	pages = fuse_pages_alloc(npages, GFP_NOFS, &descs);
20038c2ecf20Sopenharmony_ci	if (!pages)
20048c2ecf20Sopenharmony_ci		return false;
20058c2ecf20Sopenharmony_ci
20068c2ecf20Sopenharmony_ci	memcpy(pages, ap->pages, sizeof(struct page *) * ap->num_pages);
20078c2ecf20Sopenharmony_ci	memcpy(descs, ap->descs, sizeof(struct fuse_page_desc) * ap->num_pages);
20088c2ecf20Sopenharmony_ci	kfree(ap->pages);
20098c2ecf20Sopenharmony_ci	ap->pages = pages;
20108c2ecf20Sopenharmony_ci	ap->descs = descs;
20118c2ecf20Sopenharmony_ci	data->max_pages = npages;
20128c2ecf20Sopenharmony_ci
20138c2ecf20Sopenharmony_ci	return true;
20148c2ecf20Sopenharmony_ci}
20158c2ecf20Sopenharmony_ci
20168c2ecf20Sopenharmony_cistatic void fuse_writepages_send(struct fuse_fill_wb_data *data)
20178c2ecf20Sopenharmony_ci{
20188c2ecf20Sopenharmony_ci	struct fuse_writepage_args *wpa = data->wpa;
20198c2ecf20Sopenharmony_ci	struct inode *inode = data->inode;
20208c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(inode);
20218c2ecf20Sopenharmony_ci	int num_pages = wpa->ia.ap.num_pages;
20228c2ecf20Sopenharmony_ci	int i;
20238c2ecf20Sopenharmony_ci
20248c2ecf20Sopenharmony_ci	wpa->ia.ff = fuse_file_get(data->ff);
20258c2ecf20Sopenharmony_ci	spin_lock(&fi->lock);
20268c2ecf20Sopenharmony_ci	list_add_tail(&wpa->queue_entry, &fi->queued_writes);
20278c2ecf20Sopenharmony_ci	fuse_flush_writepages(inode);
20288c2ecf20Sopenharmony_ci	spin_unlock(&fi->lock);
20298c2ecf20Sopenharmony_ci
20308c2ecf20Sopenharmony_ci	for (i = 0; i < num_pages; i++)
20318c2ecf20Sopenharmony_ci		end_page_writeback(data->orig_pages[i]);
20328c2ecf20Sopenharmony_ci}
20338c2ecf20Sopenharmony_ci
20348c2ecf20Sopenharmony_ci/*
20358c2ecf20Sopenharmony_ci * Check under fi->lock if the page is under writeback, and insert it onto the
20368c2ecf20Sopenharmony_ci * rb_tree if not. Otherwise iterate auxiliary write requests, to see if there's
20378c2ecf20Sopenharmony_ci * one already added for a page at this offset.  If there's none, then insert
20388c2ecf20Sopenharmony_ci * this new request onto the auxiliary list, otherwise reuse the existing one by
20398c2ecf20Sopenharmony_ci * swapping the new temp page with the old one.
20408c2ecf20Sopenharmony_ci */
20418c2ecf20Sopenharmony_cistatic bool fuse_writepage_add(struct fuse_writepage_args *new_wpa,
20428c2ecf20Sopenharmony_ci			       struct page *page)
20438c2ecf20Sopenharmony_ci{
20448c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(new_wpa->inode);
20458c2ecf20Sopenharmony_ci	struct fuse_writepage_args *tmp;
20468c2ecf20Sopenharmony_ci	struct fuse_writepage_args *old_wpa;
20478c2ecf20Sopenharmony_ci	struct fuse_args_pages *new_ap = &new_wpa->ia.ap;
20488c2ecf20Sopenharmony_ci
20498c2ecf20Sopenharmony_ci	WARN_ON(new_ap->num_pages != 0);
20508c2ecf20Sopenharmony_ci	new_ap->num_pages = 1;
20518c2ecf20Sopenharmony_ci
20528c2ecf20Sopenharmony_ci	spin_lock(&fi->lock);
20538c2ecf20Sopenharmony_ci	old_wpa = fuse_insert_writeback(&fi->writepages, new_wpa);
20548c2ecf20Sopenharmony_ci	if (!old_wpa) {
20558c2ecf20Sopenharmony_ci		spin_unlock(&fi->lock);
20568c2ecf20Sopenharmony_ci		return true;
20578c2ecf20Sopenharmony_ci	}
20588c2ecf20Sopenharmony_ci
20598c2ecf20Sopenharmony_ci	for (tmp = old_wpa->next; tmp; tmp = tmp->next) {
20608c2ecf20Sopenharmony_ci		pgoff_t curr_index;
20618c2ecf20Sopenharmony_ci
20628c2ecf20Sopenharmony_ci		WARN_ON(tmp->inode != new_wpa->inode);
20638c2ecf20Sopenharmony_ci		curr_index = tmp->ia.write.in.offset >> PAGE_SHIFT;
20648c2ecf20Sopenharmony_ci		if (curr_index == page->index) {
20658c2ecf20Sopenharmony_ci			WARN_ON(tmp->ia.ap.num_pages != 1);
20668c2ecf20Sopenharmony_ci			swap(tmp->ia.ap.pages[0], new_ap->pages[0]);
20678c2ecf20Sopenharmony_ci			break;
20688c2ecf20Sopenharmony_ci		}
20698c2ecf20Sopenharmony_ci	}
20708c2ecf20Sopenharmony_ci
20718c2ecf20Sopenharmony_ci	if (!tmp) {
20728c2ecf20Sopenharmony_ci		new_wpa->next = old_wpa->next;
20738c2ecf20Sopenharmony_ci		old_wpa->next = new_wpa;
20748c2ecf20Sopenharmony_ci	}
20758c2ecf20Sopenharmony_ci
20768c2ecf20Sopenharmony_ci	spin_unlock(&fi->lock);
20778c2ecf20Sopenharmony_ci
20788c2ecf20Sopenharmony_ci	if (tmp) {
20798c2ecf20Sopenharmony_ci		struct backing_dev_info *bdi = inode_to_bdi(new_wpa->inode);
20808c2ecf20Sopenharmony_ci
20818c2ecf20Sopenharmony_ci		dec_wb_stat(&bdi->wb, WB_WRITEBACK);
20828c2ecf20Sopenharmony_ci		dec_node_page_state(new_ap->pages[0], NR_WRITEBACK_TEMP);
20838c2ecf20Sopenharmony_ci		wb_writeout_inc(&bdi->wb);
20848c2ecf20Sopenharmony_ci		fuse_writepage_free(new_wpa);
20858c2ecf20Sopenharmony_ci	}
20868c2ecf20Sopenharmony_ci
20878c2ecf20Sopenharmony_ci	return false;
20888c2ecf20Sopenharmony_ci}
20898c2ecf20Sopenharmony_ci
20908c2ecf20Sopenharmony_cistatic bool fuse_writepage_need_send(struct fuse_conn *fc, struct page *page,
20918c2ecf20Sopenharmony_ci				     struct fuse_args_pages *ap,
20928c2ecf20Sopenharmony_ci				     struct fuse_fill_wb_data *data)
20938c2ecf20Sopenharmony_ci{
20948c2ecf20Sopenharmony_ci	WARN_ON(!ap->num_pages);
20958c2ecf20Sopenharmony_ci
20968c2ecf20Sopenharmony_ci	/*
20978c2ecf20Sopenharmony_ci	 * Being under writeback is unlikely but possible.  For example direct
20988c2ecf20Sopenharmony_ci	 * read to an mmaped fuse file will set the page dirty twice; once when
20998c2ecf20Sopenharmony_ci	 * the pages are faulted with get_user_pages(), and then after the read
21008c2ecf20Sopenharmony_ci	 * completed.
21018c2ecf20Sopenharmony_ci	 */
21028c2ecf20Sopenharmony_ci	if (fuse_page_is_writeback(data->inode, page->index))
21038c2ecf20Sopenharmony_ci		return true;
21048c2ecf20Sopenharmony_ci
21058c2ecf20Sopenharmony_ci	/* Reached max pages */
21068c2ecf20Sopenharmony_ci	if (ap->num_pages == fc->max_pages)
21078c2ecf20Sopenharmony_ci		return true;
21088c2ecf20Sopenharmony_ci
21098c2ecf20Sopenharmony_ci	/* Reached max write bytes */
21108c2ecf20Sopenharmony_ci	if ((ap->num_pages + 1) * PAGE_SIZE > fc->max_write)
21118c2ecf20Sopenharmony_ci		return true;
21128c2ecf20Sopenharmony_ci
21138c2ecf20Sopenharmony_ci	/* Discontinuity */
21148c2ecf20Sopenharmony_ci	if (data->orig_pages[ap->num_pages - 1]->index + 1 != page->index)
21158c2ecf20Sopenharmony_ci		return true;
21168c2ecf20Sopenharmony_ci
21178c2ecf20Sopenharmony_ci	/* Need to grow the pages array?  If so, did the expansion fail? */
21188c2ecf20Sopenharmony_ci	if (ap->num_pages == data->max_pages && !fuse_pages_realloc(data))
21198c2ecf20Sopenharmony_ci		return true;
21208c2ecf20Sopenharmony_ci
21218c2ecf20Sopenharmony_ci	return false;
21228c2ecf20Sopenharmony_ci}
21238c2ecf20Sopenharmony_ci
21248c2ecf20Sopenharmony_cistatic int fuse_writepages_fill(struct page *page,
21258c2ecf20Sopenharmony_ci		struct writeback_control *wbc, void *_data)
21268c2ecf20Sopenharmony_ci{
21278c2ecf20Sopenharmony_ci	struct fuse_fill_wb_data *data = _data;
21288c2ecf20Sopenharmony_ci	struct fuse_writepage_args *wpa = data->wpa;
21298c2ecf20Sopenharmony_ci	struct fuse_args_pages *ap = &wpa->ia.ap;
21308c2ecf20Sopenharmony_ci	struct inode *inode = data->inode;
21318c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(inode);
21328c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
21338c2ecf20Sopenharmony_ci	struct page *tmp_page;
21348c2ecf20Sopenharmony_ci	int err;
21358c2ecf20Sopenharmony_ci
21368c2ecf20Sopenharmony_ci	if (!data->ff) {
21378c2ecf20Sopenharmony_ci		err = -EIO;
21388c2ecf20Sopenharmony_ci		data->ff = fuse_write_file_get(fc, fi);
21398c2ecf20Sopenharmony_ci		if (!data->ff)
21408c2ecf20Sopenharmony_ci			goto out_unlock;
21418c2ecf20Sopenharmony_ci	}
21428c2ecf20Sopenharmony_ci
21438c2ecf20Sopenharmony_ci	if (wpa && fuse_writepage_need_send(fc, page, ap, data)) {
21448c2ecf20Sopenharmony_ci		fuse_writepages_send(data);
21458c2ecf20Sopenharmony_ci		data->wpa = NULL;
21468c2ecf20Sopenharmony_ci	}
21478c2ecf20Sopenharmony_ci
21488c2ecf20Sopenharmony_ci	err = -ENOMEM;
21498c2ecf20Sopenharmony_ci	tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
21508c2ecf20Sopenharmony_ci	if (!tmp_page)
21518c2ecf20Sopenharmony_ci		goto out_unlock;
21528c2ecf20Sopenharmony_ci
21538c2ecf20Sopenharmony_ci	/*
21548c2ecf20Sopenharmony_ci	 * The page must not be redirtied until the writeout is completed
21558c2ecf20Sopenharmony_ci	 * (i.e. userspace has sent a reply to the write request).  Otherwise
21568c2ecf20Sopenharmony_ci	 * there could be more than one temporary page instance for each real
21578c2ecf20Sopenharmony_ci	 * page.
21588c2ecf20Sopenharmony_ci	 *
21598c2ecf20Sopenharmony_ci	 * This is ensured by holding the page lock in page_mkwrite() while
21608c2ecf20Sopenharmony_ci	 * checking fuse_page_is_writeback().  We already hold the page lock
21618c2ecf20Sopenharmony_ci	 * since clear_page_dirty_for_io() and keep it held until we add the
21628c2ecf20Sopenharmony_ci	 * request to the fi->writepages list and increment ap->num_pages.
21638c2ecf20Sopenharmony_ci	 * After this fuse_page_is_writeback() will indicate that the page is
21648c2ecf20Sopenharmony_ci	 * under writeback, so we can release the page lock.
21658c2ecf20Sopenharmony_ci	 */
21668c2ecf20Sopenharmony_ci	if (data->wpa == NULL) {
21678c2ecf20Sopenharmony_ci		err = -ENOMEM;
21688c2ecf20Sopenharmony_ci		wpa = fuse_writepage_args_alloc();
21698c2ecf20Sopenharmony_ci		if (!wpa) {
21708c2ecf20Sopenharmony_ci			__free_page(tmp_page);
21718c2ecf20Sopenharmony_ci			goto out_unlock;
21728c2ecf20Sopenharmony_ci		}
21738c2ecf20Sopenharmony_ci		data->max_pages = 1;
21748c2ecf20Sopenharmony_ci
21758c2ecf20Sopenharmony_ci		ap = &wpa->ia.ap;
21768c2ecf20Sopenharmony_ci		fuse_write_args_fill(&wpa->ia, data->ff, page_offset(page), 0);
21778c2ecf20Sopenharmony_ci		wpa->ia.write.in.write_flags |= FUSE_WRITE_CACHE;
21788c2ecf20Sopenharmony_ci		wpa->next = NULL;
21798c2ecf20Sopenharmony_ci		ap->args.in_pages = true;
21808c2ecf20Sopenharmony_ci		ap->args.end = fuse_writepage_end;
21818c2ecf20Sopenharmony_ci		ap->num_pages = 0;
21828c2ecf20Sopenharmony_ci		wpa->inode = inode;
21838c2ecf20Sopenharmony_ci	}
21848c2ecf20Sopenharmony_ci	set_page_writeback(page);
21858c2ecf20Sopenharmony_ci
21868c2ecf20Sopenharmony_ci	copy_highpage(tmp_page, page);
21878c2ecf20Sopenharmony_ci	ap->pages[ap->num_pages] = tmp_page;
21888c2ecf20Sopenharmony_ci	ap->descs[ap->num_pages].offset = 0;
21898c2ecf20Sopenharmony_ci	ap->descs[ap->num_pages].length = PAGE_SIZE;
21908c2ecf20Sopenharmony_ci	data->orig_pages[ap->num_pages] = page;
21918c2ecf20Sopenharmony_ci
21928c2ecf20Sopenharmony_ci	inc_wb_stat(&inode_to_bdi(inode)->wb, WB_WRITEBACK);
21938c2ecf20Sopenharmony_ci	inc_node_page_state(tmp_page, NR_WRITEBACK_TEMP);
21948c2ecf20Sopenharmony_ci
21958c2ecf20Sopenharmony_ci	err = 0;
21968c2ecf20Sopenharmony_ci	if (data->wpa) {
21978c2ecf20Sopenharmony_ci		/*
21988c2ecf20Sopenharmony_ci		 * Protected by fi->lock against concurrent access by
21998c2ecf20Sopenharmony_ci		 * fuse_page_is_writeback().
22008c2ecf20Sopenharmony_ci		 */
22018c2ecf20Sopenharmony_ci		spin_lock(&fi->lock);
22028c2ecf20Sopenharmony_ci		ap->num_pages++;
22038c2ecf20Sopenharmony_ci		spin_unlock(&fi->lock);
22048c2ecf20Sopenharmony_ci	} else if (fuse_writepage_add(wpa, page)) {
22058c2ecf20Sopenharmony_ci		data->wpa = wpa;
22068c2ecf20Sopenharmony_ci	} else {
22078c2ecf20Sopenharmony_ci		end_page_writeback(page);
22088c2ecf20Sopenharmony_ci	}
22098c2ecf20Sopenharmony_ciout_unlock:
22108c2ecf20Sopenharmony_ci	unlock_page(page);
22118c2ecf20Sopenharmony_ci
22128c2ecf20Sopenharmony_ci	return err;
22138c2ecf20Sopenharmony_ci}
22148c2ecf20Sopenharmony_ci
22158c2ecf20Sopenharmony_cistatic int fuse_writepages(struct address_space *mapping,
22168c2ecf20Sopenharmony_ci			   struct writeback_control *wbc)
22178c2ecf20Sopenharmony_ci{
22188c2ecf20Sopenharmony_ci	struct inode *inode = mapping->host;
22198c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
22208c2ecf20Sopenharmony_ci	struct fuse_fill_wb_data data;
22218c2ecf20Sopenharmony_ci	int err;
22228c2ecf20Sopenharmony_ci
22238c2ecf20Sopenharmony_ci	err = -EIO;
22248c2ecf20Sopenharmony_ci	if (fuse_is_bad(inode))
22258c2ecf20Sopenharmony_ci		goto out;
22268c2ecf20Sopenharmony_ci
22278c2ecf20Sopenharmony_ci	data.inode = inode;
22288c2ecf20Sopenharmony_ci	data.wpa = NULL;
22298c2ecf20Sopenharmony_ci	data.ff = NULL;
22308c2ecf20Sopenharmony_ci
22318c2ecf20Sopenharmony_ci	err = -ENOMEM;
22328c2ecf20Sopenharmony_ci	data.orig_pages = kcalloc(fc->max_pages,
22338c2ecf20Sopenharmony_ci				  sizeof(struct page *),
22348c2ecf20Sopenharmony_ci				  GFP_NOFS);
22358c2ecf20Sopenharmony_ci	if (!data.orig_pages)
22368c2ecf20Sopenharmony_ci		goto out;
22378c2ecf20Sopenharmony_ci
22388c2ecf20Sopenharmony_ci	err = write_cache_pages(mapping, wbc, fuse_writepages_fill, &data);
22398c2ecf20Sopenharmony_ci	if (data.wpa) {
22408c2ecf20Sopenharmony_ci		WARN_ON(!data.wpa->ia.ap.num_pages);
22418c2ecf20Sopenharmony_ci		fuse_writepages_send(&data);
22428c2ecf20Sopenharmony_ci	}
22438c2ecf20Sopenharmony_ci	if (data.ff)
22448c2ecf20Sopenharmony_ci		fuse_file_put(data.ff, false, false);
22458c2ecf20Sopenharmony_ci
22468c2ecf20Sopenharmony_ci	kfree(data.orig_pages);
22478c2ecf20Sopenharmony_ciout:
22488c2ecf20Sopenharmony_ci	return err;
22498c2ecf20Sopenharmony_ci}
22508c2ecf20Sopenharmony_ci
22518c2ecf20Sopenharmony_ci/*
22528c2ecf20Sopenharmony_ci * It's worthy to make sure that space is reserved on disk for the write,
22538c2ecf20Sopenharmony_ci * but how to implement it without killing performance need more thinking.
22548c2ecf20Sopenharmony_ci */
22558c2ecf20Sopenharmony_cistatic int fuse_write_begin(struct file *file, struct address_space *mapping,
22568c2ecf20Sopenharmony_ci		loff_t pos, unsigned len, unsigned flags,
22578c2ecf20Sopenharmony_ci		struct page **pagep, void **fsdata)
22588c2ecf20Sopenharmony_ci{
22598c2ecf20Sopenharmony_ci	pgoff_t index = pos >> PAGE_SHIFT;
22608c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(file_inode(file));
22618c2ecf20Sopenharmony_ci	struct page *page;
22628c2ecf20Sopenharmony_ci	loff_t fsize;
22638c2ecf20Sopenharmony_ci	int err = -ENOMEM;
22648c2ecf20Sopenharmony_ci
22658c2ecf20Sopenharmony_ci	WARN_ON(!fc->writeback_cache);
22668c2ecf20Sopenharmony_ci
22678c2ecf20Sopenharmony_ci	page = grab_cache_page_write_begin(mapping, index, flags);
22688c2ecf20Sopenharmony_ci	if (!page)
22698c2ecf20Sopenharmony_ci		goto error;
22708c2ecf20Sopenharmony_ci
22718c2ecf20Sopenharmony_ci	fuse_wait_on_page_writeback(mapping->host, page->index);
22728c2ecf20Sopenharmony_ci
22738c2ecf20Sopenharmony_ci	if (PageUptodate(page) || len == PAGE_SIZE)
22748c2ecf20Sopenharmony_ci		goto success;
22758c2ecf20Sopenharmony_ci	/*
22768c2ecf20Sopenharmony_ci	 * Check if the start this page comes after the end of file, in which
22778c2ecf20Sopenharmony_ci	 * case the readpage can be optimized away.
22788c2ecf20Sopenharmony_ci	 */
22798c2ecf20Sopenharmony_ci	fsize = i_size_read(mapping->host);
22808c2ecf20Sopenharmony_ci	if (fsize <= (pos & PAGE_MASK)) {
22818c2ecf20Sopenharmony_ci		size_t off = pos & ~PAGE_MASK;
22828c2ecf20Sopenharmony_ci		if (off)
22838c2ecf20Sopenharmony_ci			zero_user_segment(page, 0, off);
22848c2ecf20Sopenharmony_ci		goto success;
22858c2ecf20Sopenharmony_ci	}
22868c2ecf20Sopenharmony_ci	err = fuse_do_readpage(file, page);
22878c2ecf20Sopenharmony_ci	if (err)
22888c2ecf20Sopenharmony_ci		goto cleanup;
22898c2ecf20Sopenharmony_cisuccess:
22908c2ecf20Sopenharmony_ci	*pagep = page;
22918c2ecf20Sopenharmony_ci	return 0;
22928c2ecf20Sopenharmony_ci
22938c2ecf20Sopenharmony_cicleanup:
22948c2ecf20Sopenharmony_ci	unlock_page(page);
22958c2ecf20Sopenharmony_ci	put_page(page);
22968c2ecf20Sopenharmony_cierror:
22978c2ecf20Sopenharmony_ci	return err;
22988c2ecf20Sopenharmony_ci}
22998c2ecf20Sopenharmony_ci
23008c2ecf20Sopenharmony_cistatic int fuse_write_end(struct file *file, struct address_space *mapping,
23018c2ecf20Sopenharmony_ci		loff_t pos, unsigned len, unsigned copied,
23028c2ecf20Sopenharmony_ci		struct page *page, void *fsdata)
23038c2ecf20Sopenharmony_ci{
23048c2ecf20Sopenharmony_ci	struct inode *inode = page->mapping->host;
23058c2ecf20Sopenharmony_ci
23068c2ecf20Sopenharmony_ci	/* Haven't copied anything?  Skip zeroing, size extending, dirtying. */
23078c2ecf20Sopenharmony_ci	if (!copied)
23088c2ecf20Sopenharmony_ci		goto unlock;
23098c2ecf20Sopenharmony_ci
23108c2ecf20Sopenharmony_ci	if (!PageUptodate(page)) {
23118c2ecf20Sopenharmony_ci		/* Zero any unwritten bytes at the end of the page */
23128c2ecf20Sopenharmony_ci		size_t endoff = (pos + copied) & ~PAGE_MASK;
23138c2ecf20Sopenharmony_ci		if (endoff)
23148c2ecf20Sopenharmony_ci			zero_user_segment(page, endoff, PAGE_SIZE);
23158c2ecf20Sopenharmony_ci		SetPageUptodate(page);
23168c2ecf20Sopenharmony_ci	}
23178c2ecf20Sopenharmony_ci
23188c2ecf20Sopenharmony_ci	fuse_write_update_size(inode, pos + copied);
23198c2ecf20Sopenharmony_ci	set_page_dirty(page);
23208c2ecf20Sopenharmony_ci
23218c2ecf20Sopenharmony_ciunlock:
23228c2ecf20Sopenharmony_ci	unlock_page(page);
23238c2ecf20Sopenharmony_ci	put_page(page);
23248c2ecf20Sopenharmony_ci
23258c2ecf20Sopenharmony_ci	return copied;
23268c2ecf20Sopenharmony_ci}
23278c2ecf20Sopenharmony_ci
23288c2ecf20Sopenharmony_cistatic int fuse_launder_page(struct page *page)
23298c2ecf20Sopenharmony_ci{
23308c2ecf20Sopenharmony_ci	int err = 0;
23318c2ecf20Sopenharmony_ci	if (clear_page_dirty_for_io(page)) {
23328c2ecf20Sopenharmony_ci		struct inode *inode = page->mapping->host;
23338c2ecf20Sopenharmony_ci		err = fuse_writepage_locked(page);
23348c2ecf20Sopenharmony_ci		if (!err)
23358c2ecf20Sopenharmony_ci			fuse_wait_on_page_writeback(inode, page->index);
23368c2ecf20Sopenharmony_ci	}
23378c2ecf20Sopenharmony_ci	return err;
23388c2ecf20Sopenharmony_ci}
23398c2ecf20Sopenharmony_ci
23408c2ecf20Sopenharmony_ci/*
23418c2ecf20Sopenharmony_ci * Write back dirty pages now, because there may not be any suitable
23428c2ecf20Sopenharmony_ci * open files later
23438c2ecf20Sopenharmony_ci */
23448c2ecf20Sopenharmony_cistatic void fuse_vma_close(struct vm_area_struct *vma)
23458c2ecf20Sopenharmony_ci{
23468c2ecf20Sopenharmony_ci	filemap_write_and_wait(vma->vm_file->f_mapping);
23478c2ecf20Sopenharmony_ci}
23488c2ecf20Sopenharmony_ci
23498c2ecf20Sopenharmony_ci/*
23508c2ecf20Sopenharmony_ci * Wait for writeback against this page to complete before allowing it
23518c2ecf20Sopenharmony_ci * to be marked dirty again, and hence written back again, possibly
23528c2ecf20Sopenharmony_ci * before the previous writepage completed.
23538c2ecf20Sopenharmony_ci *
23548c2ecf20Sopenharmony_ci * Block here, instead of in ->writepage(), so that the userspace fs
23558c2ecf20Sopenharmony_ci * can only block processes actually operating on the filesystem.
23568c2ecf20Sopenharmony_ci *
23578c2ecf20Sopenharmony_ci * Otherwise unprivileged userspace fs would be able to block
23588c2ecf20Sopenharmony_ci * unrelated:
23598c2ecf20Sopenharmony_ci *
23608c2ecf20Sopenharmony_ci * - page migration
23618c2ecf20Sopenharmony_ci * - sync(2)
23628c2ecf20Sopenharmony_ci * - try_to_free_pages() with order > PAGE_ALLOC_COSTLY_ORDER
23638c2ecf20Sopenharmony_ci */
23648c2ecf20Sopenharmony_cistatic vm_fault_t fuse_page_mkwrite(struct vm_fault *vmf)
23658c2ecf20Sopenharmony_ci{
23668c2ecf20Sopenharmony_ci	struct page *page = vmf->page;
23678c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(vmf->vma->vm_file);
23688c2ecf20Sopenharmony_ci
23698c2ecf20Sopenharmony_ci	file_update_time(vmf->vma->vm_file);
23708c2ecf20Sopenharmony_ci	lock_page(page);
23718c2ecf20Sopenharmony_ci	if (page->mapping != inode->i_mapping) {
23728c2ecf20Sopenharmony_ci		unlock_page(page);
23738c2ecf20Sopenharmony_ci		return VM_FAULT_NOPAGE;
23748c2ecf20Sopenharmony_ci	}
23758c2ecf20Sopenharmony_ci
23768c2ecf20Sopenharmony_ci	fuse_wait_on_page_writeback(inode, page->index);
23778c2ecf20Sopenharmony_ci	return VM_FAULT_LOCKED;
23788c2ecf20Sopenharmony_ci}
23798c2ecf20Sopenharmony_ci
23808c2ecf20Sopenharmony_cistatic const struct vm_operations_struct fuse_file_vm_ops = {
23818c2ecf20Sopenharmony_ci	.close		= fuse_vma_close,
23828c2ecf20Sopenharmony_ci	.fault		= filemap_fault,
23838c2ecf20Sopenharmony_ci	.map_pages	= filemap_map_pages,
23848c2ecf20Sopenharmony_ci	.page_mkwrite	= fuse_page_mkwrite,
23858c2ecf20Sopenharmony_ci};
23868c2ecf20Sopenharmony_ci
23878c2ecf20Sopenharmony_cistatic int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
23888c2ecf20Sopenharmony_ci{
23898c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
23908c2ecf20Sopenharmony_ci
23918c2ecf20Sopenharmony_ci	/* DAX mmap is superior to direct_io mmap */
23928c2ecf20Sopenharmony_ci	if (FUSE_IS_DAX(file_inode(file)))
23938c2ecf20Sopenharmony_ci		return fuse_dax_mmap(file, vma);
23948c2ecf20Sopenharmony_ci
23958c2ecf20Sopenharmony_ci	if (ff->open_flags & FOPEN_DIRECT_IO) {
23968c2ecf20Sopenharmony_ci		/* Can't provide the coherency needed for MAP_SHARED */
23978c2ecf20Sopenharmony_ci		if (vma->vm_flags & VM_MAYSHARE)
23988c2ecf20Sopenharmony_ci			return -ENODEV;
23998c2ecf20Sopenharmony_ci
24008c2ecf20Sopenharmony_ci		invalidate_inode_pages2(file->f_mapping);
24018c2ecf20Sopenharmony_ci
24028c2ecf20Sopenharmony_ci		return generic_file_mmap(file, vma);
24038c2ecf20Sopenharmony_ci	}
24048c2ecf20Sopenharmony_ci
24058c2ecf20Sopenharmony_ci	if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
24068c2ecf20Sopenharmony_ci		fuse_link_write_file(file);
24078c2ecf20Sopenharmony_ci
24088c2ecf20Sopenharmony_ci	file_accessed(file);
24098c2ecf20Sopenharmony_ci	vma->vm_ops = &fuse_file_vm_ops;
24108c2ecf20Sopenharmony_ci	return 0;
24118c2ecf20Sopenharmony_ci}
24128c2ecf20Sopenharmony_ci
24138c2ecf20Sopenharmony_cistatic int convert_fuse_file_lock(struct fuse_conn *fc,
24148c2ecf20Sopenharmony_ci				  const struct fuse_file_lock *ffl,
24158c2ecf20Sopenharmony_ci				  struct file_lock *fl)
24168c2ecf20Sopenharmony_ci{
24178c2ecf20Sopenharmony_ci	switch (ffl->type) {
24188c2ecf20Sopenharmony_ci	case F_UNLCK:
24198c2ecf20Sopenharmony_ci		break;
24208c2ecf20Sopenharmony_ci
24218c2ecf20Sopenharmony_ci	case F_RDLCK:
24228c2ecf20Sopenharmony_ci	case F_WRLCK:
24238c2ecf20Sopenharmony_ci		if (ffl->start > OFFSET_MAX || ffl->end > OFFSET_MAX ||
24248c2ecf20Sopenharmony_ci		    ffl->end < ffl->start)
24258c2ecf20Sopenharmony_ci			return -EIO;
24268c2ecf20Sopenharmony_ci
24278c2ecf20Sopenharmony_ci		fl->fl_start = ffl->start;
24288c2ecf20Sopenharmony_ci		fl->fl_end = ffl->end;
24298c2ecf20Sopenharmony_ci
24308c2ecf20Sopenharmony_ci		/*
24318c2ecf20Sopenharmony_ci		 * Convert pid into init's pid namespace.  The locks API will
24328c2ecf20Sopenharmony_ci		 * translate it into the caller's pid namespace.
24338c2ecf20Sopenharmony_ci		 */
24348c2ecf20Sopenharmony_ci		rcu_read_lock();
24358c2ecf20Sopenharmony_ci		fl->fl_pid = pid_nr_ns(find_pid_ns(ffl->pid, fc->pid_ns), &init_pid_ns);
24368c2ecf20Sopenharmony_ci		rcu_read_unlock();
24378c2ecf20Sopenharmony_ci		break;
24388c2ecf20Sopenharmony_ci
24398c2ecf20Sopenharmony_ci	default:
24408c2ecf20Sopenharmony_ci		return -EIO;
24418c2ecf20Sopenharmony_ci	}
24428c2ecf20Sopenharmony_ci	fl->fl_type = ffl->type;
24438c2ecf20Sopenharmony_ci	return 0;
24448c2ecf20Sopenharmony_ci}
24458c2ecf20Sopenharmony_ci
24468c2ecf20Sopenharmony_cistatic void fuse_lk_fill(struct fuse_args *args, struct file *file,
24478c2ecf20Sopenharmony_ci			 const struct file_lock *fl, int opcode, pid_t pid,
24488c2ecf20Sopenharmony_ci			 int flock, struct fuse_lk_in *inarg)
24498c2ecf20Sopenharmony_ci{
24508c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(file);
24518c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
24528c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
24538c2ecf20Sopenharmony_ci
24548c2ecf20Sopenharmony_ci	memset(inarg, 0, sizeof(*inarg));
24558c2ecf20Sopenharmony_ci	inarg->fh = ff->fh;
24568c2ecf20Sopenharmony_ci	inarg->owner = fuse_lock_owner_id(fc, fl->fl_owner);
24578c2ecf20Sopenharmony_ci	inarg->lk.start = fl->fl_start;
24588c2ecf20Sopenharmony_ci	inarg->lk.end = fl->fl_end;
24598c2ecf20Sopenharmony_ci	inarg->lk.type = fl->fl_type;
24608c2ecf20Sopenharmony_ci	inarg->lk.pid = pid;
24618c2ecf20Sopenharmony_ci	if (flock)
24628c2ecf20Sopenharmony_ci		inarg->lk_flags |= FUSE_LK_FLOCK;
24638c2ecf20Sopenharmony_ci	args->opcode = opcode;
24648c2ecf20Sopenharmony_ci	args->nodeid = get_node_id(inode);
24658c2ecf20Sopenharmony_ci	args->in_numargs = 1;
24668c2ecf20Sopenharmony_ci	args->in_args[0].size = sizeof(*inarg);
24678c2ecf20Sopenharmony_ci	args->in_args[0].value = inarg;
24688c2ecf20Sopenharmony_ci}
24698c2ecf20Sopenharmony_ci
24708c2ecf20Sopenharmony_cistatic int fuse_getlk(struct file *file, struct file_lock *fl)
24718c2ecf20Sopenharmony_ci{
24728c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(file);
24738c2ecf20Sopenharmony_ci	struct fuse_mount *fm = get_fuse_mount(inode);
24748c2ecf20Sopenharmony_ci	FUSE_ARGS(args);
24758c2ecf20Sopenharmony_ci	struct fuse_lk_in inarg;
24768c2ecf20Sopenharmony_ci	struct fuse_lk_out outarg;
24778c2ecf20Sopenharmony_ci	int err;
24788c2ecf20Sopenharmony_ci
24798c2ecf20Sopenharmony_ci	fuse_lk_fill(&args, file, fl, FUSE_GETLK, 0, 0, &inarg);
24808c2ecf20Sopenharmony_ci	args.out_numargs = 1;
24818c2ecf20Sopenharmony_ci	args.out_args[0].size = sizeof(outarg);
24828c2ecf20Sopenharmony_ci	args.out_args[0].value = &outarg;
24838c2ecf20Sopenharmony_ci	err = fuse_simple_request(fm, &args);
24848c2ecf20Sopenharmony_ci	if (!err)
24858c2ecf20Sopenharmony_ci		err = convert_fuse_file_lock(fm->fc, &outarg.lk, fl);
24868c2ecf20Sopenharmony_ci
24878c2ecf20Sopenharmony_ci	return err;
24888c2ecf20Sopenharmony_ci}
24898c2ecf20Sopenharmony_ci
24908c2ecf20Sopenharmony_cistatic int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
24918c2ecf20Sopenharmony_ci{
24928c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(file);
24938c2ecf20Sopenharmony_ci	struct fuse_mount *fm = get_fuse_mount(inode);
24948c2ecf20Sopenharmony_ci	FUSE_ARGS(args);
24958c2ecf20Sopenharmony_ci	struct fuse_lk_in inarg;
24968c2ecf20Sopenharmony_ci	int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
24978c2ecf20Sopenharmony_ci	struct pid *pid = fl->fl_type != F_UNLCK ? task_tgid(current) : NULL;
24988c2ecf20Sopenharmony_ci	pid_t pid_nr = pid_nr_ns(pid, fm->fc->pid_ns);
24998c2ecf20Sopenharmony_ci	int err;
25008c2ecf20Sopenharmony_ci
25018c2ecf20Sopenharmony_ci	if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
25028c2ecf20Sopenharmony_ci		/* NLM needs asynchronous locks, which we don't support yet */
25038c2ecf20Sopenharmony_ci		return -ENOLCK;
25048c2ecf20Sopenharmony_ci	}
25058c2ecf20Sopenharmony_ci
25068c2ecf20Sopenharmony_ci	/* Unlock on close is handled by the flush method */
25078c2ecf20Sopenharmony_ci	if ((fl->fl_flags & FL_CLOSE_POSIX) == FL_CLOSE_POSIX)
25088c2ecf20Sopenharmony_ci		return 0;
25098c2ecf20Sopenharmony_ci
25108c2ecf20Sopenharmony_ci	fuse_lk_fill(&args, file, fl, opcode, pid_nr, flock, &inarg);
25118c2ecf20Sopenharmony_ci	err = fuse_simple_request(fm, &args);
25128c2ecf20Sopenharmony_ci
25138c2ecf20Sopenharmony_ci	/* locking is restartable */
25148c2ecf20Sopenharmony_ci	if (err == -EINTR)
25158c2ecf20Sopenharmony_ci		err = -ERESTARTSYS;
25168c2ecf20Sopenharmony_ci
25178c2ecf20Sopenharmony_ci	return err;
25188c2ecf20Sopenharmony_ci}
25198c2ecf20Sopenharmony_ci
25208c2ecf20Sopenharmony_cistatic int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
25218c2ecf20Sopenharmony_ci{
25228c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(file);
25238c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
25248c2ecf20Sopenharmony_ci	int err;
25258c2ecf20Sopenharmony_ci
25268c2ecf20Sopenharmony_ci	if (cmd == F_CANCELLK) {
25278c2ecf20Sopenharmony_ci		err = 0;
25288c2ecf20Sopenharmony_ci	} else if (cmd == F_GETLK) {
25298c2ecf20Sopenharmony_ci		if (fc->no_lock) {
25308c2ecf20Sopenharmony_ci			posix_test_lock(file, fl);
25318c2ecf20Sopenharmony_ci			err = 0;
25328c2ecf20Sopenharmony_ci		} else
25338c2ecf20Sopenharmony_ci			err = fuse_getlk(file, fl);
25348c2ecf20Sopenharmony_ci	} else {
25358c2ecf20Sopenharmony_ci		if (fc->no_lock)
25368c2ecf20Sopenharmony_ci			err = posix_lock_file(file, fl, NULL);
25378c2ecf20Sopenharmony_ci		else
25388c2ecf20Sopenharmony_ci			err = fuse_setlk(file, fl, 0);
25398c2ecf20Sopenharmony_ci	}
25408c2ecf20Sopenharmony_ci	return err;
25418c2ecf20Sopenharmony_ci}
25428c2ecf20Sopenharmony_ci
25438c2ecf20Sopenharmony_cistatic int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl)
25448c2ecf20Sopenharmony_ci{
25458c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(file);
25468c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
25478c2ecf20Sopenharmony_ci	int err;
25488c2ecf20Sopenharmony_ci
25498c2ecf20Sopenharmony_ci	if (fc->no_flock) {
25508c2ecf20Sopenharmony_ci		err = locks_lock_file_wait(file, fl);
25518c2ecf20Sopenharmony_ci	} else {
25528c2ecf20Sopenharmony_ci		struct fuse_file *ff = file->private_data;
25538c2ecf20Sopenharmony_ci
25548c2ecf20Sopenharmony_ci		/* emulate flock with POSIX locks */
25558c2ecf20Sopenharmony_ci		ff->flock = true;
25568c2ecf20Sopenharmony_ci		err = fuse_setlk(file, fl, 1);
25578c2ecf20Sopenharmony_ci	}
25588c2ecf20Sopenharmony_ci
25598c2ecf20Sopenharmony_ci	return err;
25608c2ecf20Sopenharmony_ci}
25618c2ecf20Sopenharmony_ci
25628c2ecf20Sopenharmony_cistatic sector_t fuse_bmap(struct address_space *mapping, sector_t block)
25638c2ecf20Sopenharmony_ci{
25648c2ecf20Sopenharmony_ci	struct inode *inode = mapping->host;
25658c2ecf20Sopenharmony_ci	struct fuse_mount *fm = get_fuse_mount(inode);
25668c2ecf20Sopenharmony_ci	FUSE_ARGS(args);
25678c2ecf20Sopenharmony_ci	struct fuse_bmap_in inarg;
25688c2ecf20Sopenharmony_ci	struct fuse_bmap_out outarg;
25698c2ecf20Sopenharmony_ci	int err;
25708c2ecf20Sopenharmony_ci
25718c2ecf20Sopenharmony_ci	if (!inode->i_sb->s_bdev || fm->fc->no_bmap)
25728c2ecf20Sopenharmony_ci		return 0;
25738c2ecf20Sopenharmony_ci
25748c2ecf20Sopenharmony_ci	memset(&inarg, 0, sizeof(inarg));
25758c2ecf20Sopenharmony_ci	inarg.block = block;
25768c2ecf20Sopenharmony_ci	inarg.blocksize = inode->i_sb->s_blocksize;
25778c2ecf20Sopenharmony_ci	args.opcode = FUSE_BMAP;
25788c2ecf20Sopenharmony_ci	args.nodeid = get_node_id(inode);
25798c2ecf20Sopenharmony_ci	args.in_numargs = 1;
25808c2ecf20Sopenharmony_ci	args.in_args[0].size = sizeof(inarg);
25818c2ecf20Sopenharmony_ci	args.in_args[0].value = &inarg;
25828c2ecf20Sopenharmony_ci	args.out_numargs = 1;
25838c2ecf20Sopenharmony_ci	args.out_args[0].size = sizeof(outarg);
25848c2ecf20Sopenharmony_ci	args.out_args[0].value = &outarg;
25858c2ecf20Sopenharmony_ci	err = fuse_simple_request(fm, &args);
25868c2ecf20Sopenharmony_ci	if (err == -ENOSYS)
25878c2ecf20Sopenharmony_ci		fm->fc->no_bmap = 1;
25888c2ecf20Sopenharmony_ci
25898c2ecf20Sopenharmony_ci	return err ? 0 : outarg.block;
25908c2ecf20Sopenharmony_ci}
25918c2ecf20Sopenharmony_ci
25928c2ecf20Sopenharmony_cistatic loff_t fuse_lseek(struct file *file, loff_t offset, int whence)
25938c2ecf20Sopenharmony_ci{
25948c2ecf20Sopenharmony_ci	struct inode *inode = file->f_mapping->host;
25958c2ecf20Sopenharmony_ci	struct fuse_mount *fm = get_fuse_mount(inode);
25968c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
25978c2ecf20Sopenharmony_ci	FUSE_ARGS(args);
25988c2ecf20Sopenharmony_ci	struct fuse_lseek_in inarg = {
25998c2ecf20Sopenharmony_ci		.fh = ff->fh,
26008c2ecf20Sopenharmony_ci		.offset = offset,
26018c2ecf20Sopenharmony_ci		.whence = whence
26028c2ecf20Sopenharmony_ci	};
26038c2ecf20Sopenharmony_ci	struct fuse_lseek_out outarg;
26048c2ecf20Sopenharmony_ci	int err;
26058c2ecf20Sopenharmony_ci
26068c2ecf20Sopenharmony_ci	if (fm->fc->no_lseek)
26078c2ecf20Sopenharmony_ci		goto fallback;
26088c2ecf20Sopenharmony_ci
26098c2ecf20Sopenharmony_ci	args.opcode = FUSE_LSEEK;
26108c2ecf20Sopenharmony_ci	args.nodeid = ff->nodeid;
26118c2ecf20Sopenharmony_ci	args.in_numargs = 1;
26128c2ecf20Sopenharmony_ci	args.in_args[0].size = sizeof(inarg);
26138c2ecf20Sopenharmony_ci	args.in_args[0].value = &inarg;
26148c2ecf20Sopenharmony_ci	args.out_numargs = 1;
26158c2ecf20Sopenharmony_ci	args.out_args[0].size = sizeof(outarg);
26168c2ecf20Sopenharmony_ci	args.out_args[0].value = &outarg;
26178c2ecf20Sopenharmony_ci	err = fuse_simple_request(fm, &args);
26188c2ecf20Sopenharmony_ci	if (err) {
26198c2ecf20Sopenharmony_ci		if (err == -ENOSYS) {
26208c2ecf20Sopenharmony_ci			fm->fc->no_lseek = 1;
26218c2ecf20Sopenharmony_ci			goto fallback;
26228c2ecf20Sopenharmony_ci		}
26238c2ecf20Sopenharmony_ci		return err;
26248c2ecf20Sopenharmony_ci	}
26258c2ecf20Sopenharmony_ci
26268c2ecf20Sopenharmony_ci	return vfs_setpos(file, outarg.offset, inode->i_sb->s_maxbytes);
26278c2ecf20Sopenharmony_ci
26288c2ecf20Sopenharmony_cifallback:
26298c2ecf20Sopenharmony_ci	err = fuse_update_attributes(inode, file);
26308c2ecf20Sopenharmony_ci	if (!err)
26318c2ecf20Sopenharmony_ci		return generic_file_llseek(file, offset, whence);
26328c2ecf20Sopenharmony_ci	else
26338c2ecf20Sopenharmony_ci		return err;
26348c2ecf20Sopenharmony_ci}
26358c2ecf20Sopenharmony_ci
26368c2ecf20Sopenharmony_cistatic loff_t fuse_file_llseek(struct file *file, loff_t offset, int whence)
26378c2ecf20Sopenharmony_ci{
26388c2ecf20Sopenharmony_ci	loff_t retval;
26398c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(file);
26408c2ecf20Sopenharmony_ci
26418c2ecf20Sopenharmony_ci	switch (whence) {
26428c2ecf20Sopenharmony_ci	case SEEK_SET:
26438c2ecf20Sopenharmony_ci	case SEEK_CUR:
26448c2ecf20Sopenharmony_ci		 /* No i_mutex protection necessary for SEEK_CUR and SEEK_SET */
26458c2ecf20Sopenharmony_ci		retval = generic_file_llseek(file, offset, whence);
26468c2ecf20Sopenharmony_ci		break;
26478c2ecf20Sopenharmony_ci	case SEEK_END:
26488c2ecf20Sopenharmony_ci		inode_lock(inode);
26498c2ecf20Sopenharmony_ci		retval = fuse_update_attributes(inode, file);
26508c2ecf20Sopenharmony_ci		if (!retval)
26518c2ecf20Sopenharmony_ci			retval = generic_file_llseek(file, offset, whence);
26528c2ecf20Sopenharmony_ci		inode_unlock(inode);
26538c2ecf20Sopenharmony_ci		break;
26548c2ecf20Sopenharmony_ci	case SEEK_HOLE:
26558c2ecf20Sopenharmony_ci	case SEEK_DATA:
26568c2ecf20Sopenharmony_ci		inode_lock(inode);
26578c2ecf20Sopenharmony_ci		retval = fuse_lseek(file, offset, whence);
26588c2ecf20Sopenharmony_ci		inode_unlock(inode);
26598c2ecf20Sopenharmony_ci		break;
26608c2ecf20Sopenharmony_ci	default:
26618c2ecf20Sopenharmony_ci		retval = -EINVAL;
26628c2ecf20Sopenharmony_ci	}
26638c2ecf20Sopenharmony_ci
26648c2ecf20Sopenharmony_ci	return retval;
26658c2ecf20Sopenharmony_ci}
26668c2ecf20Sopenharmony_ci
26678c2ecf20Sopenharmony_ci/*
26688c2ecf20Sopenharmony_ci * CUSE servers compiled on 32bit broke on 64bit kernels because the
26698c2ecf20Sopenharmony_ci * ABI was defined to be 'struct iovec' which is different on 32bit
26708c2ecf20Sopenharmony_ci * and 64bit.  Fortunately we can determine which structure the server
26718c2ecf20Sopenharmony_ci * used from the size of the reply.
26728c2ecf20Sopenharmony_ci */
26738c2ecf20Sopenharmony_cistatic int fuse_copy_ioctl_iovec_old(struct iovec *dst, void *src,
26748c2ecf20Sopenharmony_ci				     size_t transferred, unsigned count,
26758c2ecf20Sopenharmony_ci				     bool is_compat)
26768c2ecf20Sopenharmony_ci{
26778c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT
26788c2ecf20Sopenharmony_ci	if (count * sizeof(struct compat_iovec) == transferred) {
26798c2ecf20Sopenharmony_ci		struct compat_iovec *ciov = src;
26808c2ecf20Sopenharmony_ci		unsigned i;
26818c2ecf20Sopenharmony_ci
26828c2ecf20Sopenharmony_ci		/*
26838c2ecf20Sopenharmony_ci		 * With this interface a 32bit server cannot support
26848c2ecf20Sopenharmony_ci		 * non-compat (i.e. ones coming from 64bit apps) ioctl
26858c2ecf20Sopenharmony_ci		 * requests
26868c2ecf20Sopenharmony_ci		 */
26878c2ecf20Sopenharmony_ci		if (!is_compat)
26888c2ecf20Sopenharmony_ci			return -EINVAL;
26898c2ecf20Sopenharmony_ci
26908c2ecf20Sopenharmony_ci		for (i = 0; i < count; i++) {
26918c2ecf20Sopenharmony_ci			dst[i].iov_base = compat_ptr(ciov[i].iov_base);
26928c2ecf20Sopenharmony_ci			dst[i].iov_len = ciov[i].iov_len;
26938c2ecf20Sopenharmony_ci		}
26948c2ecf20Sopenharmony_ci		return 0;
26958c2ecf20Sopenharmony_ci	}
26968c2ecf20Sopenharmony_ci#endif
26978c2ecf20Sopenharmony_ci
26988c2ecf20Sopenharmony_ci	if (count * sizeof(struct iovec) != transferred)
26998c2ecf20Sopenharmony_ci		return -EIO;
27008c2ecf20Sopenharmony_ci
27018c2ecf20Sopenharmony_ci	memcpy(dst, src, transferred);
27028c2ecf20Sopenharmony_ci	return 0;
27038c2ecf20Sopenharmony_ci}
27048c2ecf20Sopenharmony_ci
27058c2ecf20Sopenharmony_ci/* Make sure iov_length() won't overflow */
27068c2ecf20Sopenharmony_cistatic int fuse_verify_ioctl_iov(struct fuse_conn *fc, struct iovec *iov,
27078c2ecf20Sopenharmony_ci				 size_t count)
27088c2ecf20Sopenharmony_ci{
27098c2ecf20Sopenharmony_ci	size_t n;
27108c2ecf20Sopenharmony_ci	u32 max = fc->max_pages << PAGE_SHIFT;
27118c2ecf20Sopenharmony_ci
27128c2ecf20Sopenharmony_ci	for (n = 0; n < count; n++, iov++) {
27138c2ecf20Sopenharmony_ci		if (iov->iov_len > (size_t) max)
27148c2ecf20Sopenharmony_ci			return -ENOMEM;
27158c2ecf20Sopenharmony_ci		max -= iov->iov_len;
27168c2ecf20Sopenharmony_ci	}
27178c2ecf20Sopenharmony_ci	return 0;
27188c2ecf20Sopenharmony_ci}
27198c2ecf20Sopenharmony_ci
27208c2ecf20Sopenharmony_cistatic int fuse_copy_ioctl_iovec(struct fuse_conn *fc, struct iovec *dst,
27218c2ecf20Sopenharmony_ci				 void *src, size_t transferred, unsigned count,
27228c2ecf20Sopenharmony_ci				 bool is_compat)
27238c2ecf20Sopenharmony_ci{
27248c2ecf20Sopenharmony_ci	unsigned i;
27258c2ecf20Sopenharmony_ci	struct fuse_ioctl_iovec *fiov = src;
27268c2ecf20Sopenharmony_ci
27278c2ecf20Sopenharmony_ci	if (fc->minor < 16) {
27288c2ecf20Sopenharmony_ci		return fuse_copy_ioctl_iovec_old(dst, src, transferred,
27298c2ecf20Sopenharmony_ci						 count, is_compat);
27308c2ecf20Sopenharmony_ci	}
27318c2ecf20Sopenharmony_ci
27328c2ecf20Sopenharmony_ci	if (count * sizeof(struct fuse_ioctl_iovec) != transferred)
27338c2ecf20Sopenharmony_ci		return -EIO;
27348c2ecf20Sopenharmony_ci
27358c2ecf20Sopenharmony_ci	for (i = 0; i < count; i++) {
27368c2ecf20Sopenharmony_ci		/* Did the server supply an inappropriate value? */
27378c2ecf20Sopenharmony_ci		if (fiov[i].base != (unsigned long) fiov[i].base ||
27388c2ecf20Sopenharmony_ci		    fiov[i].len != (unsigned long) fiov[i].len)
27398c2ecf20Sopenharmony_ci			return -EIO;
27408c2ecf20Sopenharmony_ci
27418c2ecf20Sopenharmony_ci		dst[i].iov_base = (void __user *) (unsigned long) fiov[i].base;
27428c2ecf20Sopenharmony_ci		dst[i].iov_len = (size_t) fiov[i].len;
27438c2ecf20Sopenharmony_ci
27448c2ecf20Sopenharmony_ci#ifdef CONFIG_COMPAT
27458c2ecf20Sopenharmony_ci		if (is_compat &&
27468c2ecf20Sopenharmony_ci		    (ptr_to_compat(dst[i].iov_base) != fiov[i].base ||
27478c2ecf20Sopenharmony_ci		     (compat_size_t) dst[i].iov_len != fiov[i].len))
27488c2ecf20Sopenharmony_ci			return -EIO;
27498c2ecf20Sopenharmony_ci#endif
27508c2ecf20Sopenharmony_ci	}
27518c2ecf20Sopenharmony_ci
27528c2ecf20Sopenharmony_ci	return 0;
27538c2ecf20Sopenharmony_ci}
27548c2ecf20Sopenharmony_ci
27558c2ecf20Sopenharmony_ci
27568c2ecf20Sopenharmony_ci/*
27578c2ecf20Sopenharmony_ci * For ioctls, there is no generic way to determine how much memory
27588c2ecf20Sopenharmony_ci * needs to be read and/or written.  Furthermore, ioctls are allowed
27598c2ecf20Sopenharmony_ci * to dereference the passed pointer, so the parameter requires deep
27608c2ecf20Sopenharmony_ci * copying but FUSE has no idea whatsoever about what to copy in or
27618c2ecf20Sopenharmony_ci * out.
27628c2ecf20Sopenharmony_ci *
27638c2ecf20Sopenharmony_ci * This is solved by allowing FUSE server to retry ioctl with
27648c2ecf20Sopenharmony_ci * necessary in/out iovecs.  Let's assume the ioctl implementation
27658c2ecf20Sopenharmony_ci * needs to read in the following structure.
27668c2ecf20Sopenharmony_ci *
27678c2ecf20Sopenharmony_ci * struct a {
27688c2ecf20Sopenharmony_ci *	char	*buf;
27698c2ecf20Sopenharmony_ci *	size_t	buflen;
27708c2ecf20Sopenharmony_ci * }
27718c2ecf20Sopenharmony_ci *
27728c2ecf20Sopenharmony_ci * On the first callout to FUSE server, inarg->in_size and
27738c2ecf20Sopenharmony_ci * inarg->out_size will be NULL; then, the server completes the ioctl
27748c2ecf20Sopenharmony_ci * with FUSE_IOCTL_RETRY set in out->flags, out->in_iovs set to 1 and
27758c2ecf20Sopenharmony_ci * the actual iov array to
27768c2ecf20Sopenharmony_ci *
27778c2ecf20Sopenharmony_ci * { { .iov_base = inarg.arg,	.iov_len = sizeof(struct a) } }
27788c2ecf20Sopenharmony_ci *
27798c2ecf20Sopenharmony_ci * which tells FUSE to copy in the requested area and retry the ioctl.
27808c2ecf20Sopenharmony_ci * On the second round, the server has access to the structure and
27818c2ecf20Sopenharmony_ci * from that it can tell what to look for next, so on the invocation,
27828c2ecf20Sopenharmony_ci * it sets FUSE_IOCTL_RETRY, out->in_iovs to 2 and iov array to
27838c2ecf20Sopenharmony_ci *
27848c2ecf20Sopenharmony_ci * { { .iov_base = inarg.arg,	.iov_len = sizeof(struct a)	},
27858c2ecf20Sopenharmony_ci *   { .iov_base = a.buf,	.iov_len = a.buflen		} }
27868c2ecf20Sopenharmony_ci *
27878c2ecf20Sopenharmony_ci * FUSE will copy both struct a and the pointed buffer from the
27888c2ecf20Sopenharmony_ci * process doing the ioctl and retry ioctl with both struct a and the
27898c2ecf20Sopenharmony_ci * buffer.
27908c2ecf20Sopenharmony_ci *
27918c2ecf20Sopenharmony_ci * This time, FUSE server has everything it needs and completes ioctl
27928c2ecf20Sopenharmony_ci * without FUSE_IOCTL_RETRY which finishes the ioctl call.
27938c2ecf20Sopenharmony_ci *
27948c2ecf20Sopenharmony_ci * Copying data out works the same way.
27958c2ecf20Sopenharmony_ci *
27968c2ecf20Sopenharmony_ci * Note that if FUSE_IOCTL_UNRESTRICTED is clear, the kernel
27978c2ecf20Sopenharmony_ci * automatically initializes in and out iovs by decoding @cmd with
27988c2ecf20Sopenharmony_ci * _IOC_* macros and the server is not allowed to request RETRY.  This
27998c2ecf20Sopenharmony_ci * limits ioctl data transfers to well-formed ioctls and is the forced
28008c2ecf20Sopenharmony_ci * behavior for all FUSE servers.
28018c2ecf20Sopenharmony_ci */
28028c2ecf20Sopenharmony_cilong fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
28038c2ecf20Sopenharmony_ci		   unsigned int flags)
28048c2ecf20Sopenharmony_ci{
28058c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
28068c2ecf20Sopenharmony_ci	struct fuse_mount *fm = ff->fm;
28078c2ecf20Sopenharmony_ci	struct fuse_ioctl_in inarg = {
28088c2ecf20Sopenharmony_ci		.fh = ff->fh,
28098c2ecf20Sopenharmony_ci		.cmd = cmd,
28108c2ecf20Sopenharmony_ci		.arg = arg,
28118c2ecf20Sopenharmony_ci		.flags = flags
28128c2ecf20Sopenharmony_ci	};
28138c2ecf20Sopenharmony_ci	struct fuse_ioctl_out outarg;
28148c2ecf20Sopenharmony_ci	struct iovec *iov_page = NULL;
28158c2ecf20Sopenharmony_ci	struct iovec *in_iov = NULL, *out_iov = NULL;
28168c2ecf20Sopenharmony_ci	unsigned int in_iovs = 0, out_iovs = 0, max_pages;
28178c2ecf20Sopenharmony_ci	size_t in_size, out_size, c;
28188c2ecf20Sopenharmony_ci	ssize_t transferred;
28198c2ecf20Sopenharmony_ci	int err, i;
28208c2ecf20Sopenharmony_ci	struct iov_iter ii;
28218c2ecf20Sopenharmony_ci	struct fuse_args_pages ap = {};
28228c2ecf20Sopenharmony_ci
28238c2ecf20Sopenharmony_ci#if BITS_PER_LONG == 32
28248c2ecf20Sopenharmony_ci	inarg.flags |= FUSE_IOCTL_32BIT;
28258c2ecf20Sopenharmony_ci#else
28268c2ecf20Sopenharmony_ci	if (flags & FUSE_IOCTL_COMPAT) {
28278c2ecf20Sopenharmony_ci		inarg.flags |= FUSE_IOCTL_32BIT;
28288c2ecf20Sopenharmony_ci#ifdef CONFIG_X86_X32
28298c2ecf20Sopenharmony_ci		if (in_x32_syscall())
28308c2ecf20Sopenharmony_ci			inarg.flags |= FUSE_IOCTL_COMPAT_X32;
28318c2ecf20Sopenharmony_ci#endif
28328c2ecf20Sopenharmony_ci	}
28338c2ecf20Sopenharmony_ci#endif
28348c2ecf20Sopenharmony_ci
28358c2ecf20Sopenharmony_ci	/* assume all the iovs returned by client always fits in a page */
28368c2ecf20Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct fuse_ioctl_iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE);
28378c2ecf20Sopenharmony_ci
28388c2ecf20Sopenharmony_ci	err = -ENOMEM;
28398c2ecf20Sopenharmony_ci	ap.pages = fuse_pages_alloc(fm->fc->max_pages, GFP_KERNEL, &ap.descs);
28408c2ecf20Sopenharmony_ci	iov_page = (struct iovec *) __get_free_page(GFP_KERNEL);
28418c2ecf20Sopenharmony_ci	if (!ap.pages || !iov_page)
28428c2ecf20Sopenharmony_ci		goto out;
28438c2ecf20Sopenharmony_ci
28448c2ecf20Sopenharmony_ci	fuse_page_descs_length_init(ap.descs, 0, fm->fc->max_pages);
28458c2ecf20Sopenharmony_ci
28468c2ecf20Sopenharmony_ci	/*
28478c2ecf20Sopenharmony_ci	 * If restricted, initialize IO parameters as encoded in @cmd.
28488c2ecf20Sopenharmony_ci	 * RETRY from server is not allowed.
28498c2ecf20Sopenharmony_ci	 */
28508c2ecf20Sopenharmony_ci	if (!(flags & FUSE_IOCTL_UNRESTRICTED)) {
28518c2ecf20Sopenharmony_ci		struct iovec *iov = iov_page;
28528c2ecf20Sopenharmony_ci
28538c2ecf20Sopenharmony_ci		iov->iov_base = (void __user *)arg;
28548c2ecf20Sopenharmony_ci
28558c2ecf20Sopenharmony_ci		switch (cmd) {
28568c2ecf20Sopenharmony_ci		case FS_IOC_GETFLAGS:
28578c2ecf20Sopenharmony_ci		case FS_IOC_SETFLAGS:
28588c2ecf20Sopenharmony_ci			iov->iov_len = sizeof(int);
28598c2ecf20Sopenharmony_ci			break;
28608c2ecf20Sopenharmony_ci		default:
28618c2ecf20Sopenharmony_ci			iov->iov_len = _IOC_SIZE(cmd);
28628c2ecf20Sopenharmony_ci			break;
28638c2ecf20Sopenharmony_ci		}
28648c2ecf20Sopenharmony_ci
28658c2ecf20Sopenharmony_ci		if (_IOC_DIR(cmd) & _IOC_WRITE) {
28668c2ecf20Sopenharmony_ci			in_iov = iov;
28678c2ecf20Sopenharmony_ci			in_iovs = 1;
28688c2ecf20Sopenharmony_ci		}
28698c2ecf20Sopenharmony_ci
28708c2ecf20Sopenharmony_ci		if (_IOC_DIR(cmd) & _IOC_READ) {
28718c2ecf20Sopenharmony_ci			out_iov = iov;
28728c2ecf20Sopenharmony_ci			out_iovs = 1;
28738c2ecf20Sopenharmony_ci		}
28748c2ecf20Sopenharmony_ci	}
28758c2ecf20Sopenharmony_ci
28768c2ecf20Sopenharmony_ci retry:
28778c2ecf20Sopenharmony_ci	inarg.in_size = in_size = iov_length(in_iov, in_iovs);
28788c2ecf20Sopenharmony_ci	inarg.out_size = out_size = iov_length(out_iov, out_iovs);
28798c2ecf20Sopenharmony_ci
28808c2ecf20Sopenharmony_ci	/*
28818c2ecf20Sopenharmony_ci	 * Out data can be used either for actual out data or iovs,
28828c2ecf20Sopenharmony_ci	 * make sure there always is at least one page.
28838c2ecf20Sopenharmony_ci	 */
28848c2ecf20Sopenharmony_ci	out_size = max_t(size_t, out_size, PAGE_SIZE);
28858c2ecf20Sopenharmony_ci	max_pages = DIV_ROUND_UP(max(in_size, out_size), PAGE_SIZE);
28868c2ecf20Sopenharmony_ci
28878c2ecf20Sopenharmony_ci	/* make sure there are enough buffer pages and init request with them */
28888c2ecf20Sopenharmony_ci	err = -ENOMEM;
28898c2ecf20Sopenharmony_ci	if (max_pages > fm->fc->max_pages)
28908c2ecf20Sopenharmony_ci		goto out;
28918c2ecf20Sopenharmony_ci	while (ap.num_pages < max_pages) {
28928c2ecf20Sopenharmony_ci		ap.pages[ap.num_pages] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
28938c2ecf20Sopenharmony_ci		if (!ap.pages[ap.num_pages])
28948c2ecf20Sopenharmony_ci			goto out;
28958c2ecf20Sopenharmony_ci		ap.num_pages++;
28968c2ecf20Sopenharmony_ci	}
28978c2ecf20Sopenharmony_ci
28988c2ecf20Sopenharmony_ci
28998c2ecf20Sopenharmony_ci	/* okay, let's send it to the client */
29008c2ecf20Sopenharmony_ci	ap.args.opcode = FUSE_IOCTL;
29018c2ecf20Sopenharmony_ci	ap.args.nodeid = ff->nodeid;
29028c2ecf20Sopenharmony_ci	ap.args.in_numargs = 1;
29038c2ecf20Sopenharmony_ci	ap.args.in_args[0].size = sizeof(inarg);
29048c2ecf20Sopenharmony_ci	ap.args.in_args[0].value = &inarg;
29058c2ecf20Sopenharmony_ci	if (in_size) {
29068c2ecf20Sopenharmony_ci		ap.args.in_numargs++;
29078c2ecf20Sopenharmony_ci		ap.args.in_args[1].size = in_size;
29088c2ecf20Sopenharmony_ci		ap.args.in_pages = true;
29098c2ecf20Sopenharmony_ci
29108c2ecf20Sopenharmony_ci		err = -EFAULT;
29118c2ecf20Sopenharmony_ci		iov_iter_init(&ii, WRITE, in_iov, in_iovs, in_size);
29128c2ecf20Sopenharmony_ci		for (i = 0; iov_iter_count(&ii) && !WARN_ON(i >= ap.num_pages); i++) {
29138c2ecf20Sopenharmony_ci			c = copy_page_from_iter(ap.pages[i], 0, PAGE_SIZE, &ii);
29148c2ecf20Sopenharmony_ci			if (c != PAGE_SIZE && iov_iter_count(&ii))
29158c2ecf20Sopenharmony_ci				goto out;
29168c2ecf20Sopenharmony_ci		}
29178c2ecf20Sopenharmony_ci	}
29188c2ecf20Sopenharmony_ci
29198c2ecf20Sopenharmony_ci	ap.args.out_numargs = 2;
29208c2ecf20Sopenharmony_ci	ap.args.out_args[0].size = sizeof(outarg);
29218c2ecf20Sopenharmony_ci	ap.args.out_args[0].value = &outarg;
29228c2ecf20Sopenharmony_ci	ap.args.out_args[1].size = out_size;
29238c2ecf20Sopenharmony_ci	ap.args.out_pages = true;
29248c2ecf20Sopenharmony_ci	ap.args.out_argvar = true;
29258c2ecf20Sopenharmony_ci
29268c2ecf20Sopenharmony_ci	transferred = fuse_simple_request(fm, &ap.args);
29278c2ecf20Sopenharmony_ci	err = transferred;
29288c2ecf20Sopenharmony_ci	if (transferred < 0)
29298c2ecf20Sopenharmony_ci		goto out;
29308c2ecf20Sopenharmony_ci
29318c2ecf20Sopenharmony_ci	/* did it ask for retry? */
29328c2ecf20Sopenharmony_ci	if (outarg.flags & FUSE_IOCTL_RETRY) {
29338c2ecf20Sopenharmony_ci		void *vaddr;
29348c2ecf20Sopenharmony_ci
29358c2ecf20Sopenharmony_ci		/* no retry if in restricted mode */
29368c2ecf20Sopenharmony_ci		err = -EIO;
29378c2ecf20Sopenharmony_ci		if (!(flags & FUSE_IOCTL_UNRESTRICTED))
29388c2ecf20Sopenharmony_ci			goto out;
29398c2ecf20Sopenharmony_ci
29408c2ecf20Sopenharmony_ci		in_iovs = outarg.in_iovs;
29418c2ecf20Sopenharmony_ci		out_iovs = outarg.out_iovs;
29428c2ecf20Sopenharmony_ci
29438c2ecf20Sopenharmony_ci		/*
29448c2ecf20Sopenharmony_ci		 * Make sure things are in boundary, separate checks
29458c2ecf20Sopenharmony_ci		 * are to protect against overflow.
29468c2ecf20Sopenharmony_ci		 */
29478c2ecf20Sopenharmony_ci		err = -ENOMEM;
29488c2ecf20Sopenharmony_ci		if (in_iovs > FUSE_IOCTL_MAX_IOV ||
29498c2ecf20Sopenharmony_ci		    out_iovs > FUSE_IOCTL_MAX_IOV ||
29508c2ecf20Sopenharmony_ci		    in_iovs + out_iovs > FUSE_IOCTL_MAX_IOV)
29518c2ecf20Sopenharmony_ci			goto out;
29528c2ecf20Sopenharmony_ci
29538c2ecf20Sopenharmony_ci		vaddr = kmap_atomic(ap.pages[0]);
29548c2ecf20Sopenharmony_ci		err = fuse_copy_ioctl_iovec(fm->fc, iov_page, vaddr,
29558c2ecf20Sopenharmony_ci					    transferred, in_iovs + out_iovs,
29568c2ecf20Sopenharmony_ci					    (flags & FUSE_IOCTL_COMPAT) != 0);
29578c2ecf20Sopenharmony_ci		kunmap_atomic(vaddr);
29588c2ecf20Sopenharmony_ci		if (err)
29598c2ecf20Sopenharmony_ci			goto out;
29608c2ecf20Sopenharmony_ci
29618c2ecf20Sopenharmony_ci		in_iov = iov_page;
29628c2ecf20Sopenharmony_ci		out_iov = in_iov + in_iovs;
29638c2ecf20Sopenharmony_ci
29648c2ecf20Sopenharmony_ci		err = fuse_verify_ioctl_iov(fm->fc, in_iov, in_iovs);
29658c2ecf20Sopenharmony_ci		if (err)
29668c2ecf20Sopenharmony_ci			goto out;
29678c2ecf20Sopenharmony_ci
29688c2ecf20Sopenharmony_ci		err = fuse_verify_ioctl_iov(fm->fc, out_iov, out_iovs);
29698c2ecf20Sopenharmony_ci		if (err)
29708c2ecf20Sopenharmony_ci			goto out;
29718c2ecf20Sopenharmony_ci
29728c2ecf20Sopenharmony_ci		goto retry;
29738c2ecf20Sopenharmony_ci	}
29748c2ecf20Sopenharmony_ci
29758c2ecf20Sopenharmony_ci	err = -EIO;
29768c2ecf20Sopenharmony_ci	if (transferred > inarg.out_size)
29778c2ecf20Sopenharmony_ci		goto out;
29788c2ecf20Sopenharmony_ci
29798c2ecf20Sopenharmony_ci	err = -EFAULT;
29808c2ecf20Sopenharmony_ci	iov_iter_init(&ii, READ, out_iov, out_iovs, transferred);
29818c2ecf20Sopenharmony_ci	for (i = 0; iov_iter_count(&ii) && !WARN_ON(i >= ap.num_pages); i++) {
29828c2ecf20Sopenharmony_ci		c = copy_page_to_iter(ap.pages[i], 0, PAGE_SIZE, &ii);
29838c2ecf20Sopenharmony_ci		if (c != PAGE_SIZE && iov_iter_count(&ii))
29848c2ecf20Sopenharmony_ci			goto out;
29858c2ecf20Sopenharmony_ci	}
29868c2ecf20Sopenharmony_ci	err = 0;
29878c2ecf20Sopenharmony_ci out:
29888c2ecf20Sopenharmony_ci	free_page((unsigned long) iov_page);
29898c2ecf20Sopenharmony_ci	while (ap.num_pages)
29908c2ecf20Sopenharmony_ci		__free_page(ap.pages[--ap.num_pages]);
29918c2ecf20Sopenharmony_ci	kfree(ap.pages);
29928c2ecf20Sopenharmony_ci
29938c2ecf20Sopenharmony_ci	return err ? err : outarg.result;
29948c2ecf20Sopenharmony_ci}
29958c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fuse_do_ioctl);
29968c2ecf20Sopenharmony_ci
29978c2ecf20Sopenharmony_cilong fuse_ioctl_common(struct file *file, unsigned int cmd,
29988c2ecf20Sopenharmony_ci		       unsigned long arg, unsigned int flags)
29998c2ecf20Sopenharmony_ci{
30008c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(file);
30018c2ecf20Sopenharmony_ci	struct fuse_conn *fc = get_fuse_conn(inode);
30028c2ecf20Sopenharmony_ci
30038c2ecf20Sopenharmony_ci	if (!fuse_allow_current_process(fc))
30048c2ecf20Sopenharmony_ci		return -EACCES;
30058c2ecf20Sopenharmony_ci
30068c2ecf20Sopenharmony_ci	if (fuse_is_bad(inode))
30078c2ecf20Sopenharmony_ci		return -EIO;
30088c2ecf20Sopenharmony_ci
30098c2ecf20Sopenharmony_ci	return fuse_do_ioctl(file, cmd, arg, flags);
30108c2ecf20Sopenharmony_ci}
30118c2ecf20Sopenharmony_ci
30128c2ecf20Sopenharmony_cistatic long fuse_file_ioctl(struct file *file, unsigned int cmd,
30138c2ecf20Sopenharmony_ci			    unsigned long arg)
30148c2ecf20Sopenharmony_ci{
30158c2ecf20Sopenharmony_ci	return fuse_ioctl_common(file, cmd, arg, 0);
30168c2ecf20Sopenharmony_ci}
30178c2ecf20Sopenharmony_ci
30188c2ecf20Sopenharmony_cistatic long fuse_file_compat_ioctl(struct file *file, unsigned int cmd,
30198c2ecf20Sopenharmony_ci				   unsigned long arg)
30208c2ecf20Sopenharmony_ci{
30218c2ecf20Sopenharmony_ci	return fuse_ioctl_common(file, cmd, arg, FUSE_IOCTL_COMPAT);
30228c2ecf20Sopenharmony_ci}
30238c2ecf20Sopenharmony_ci
30248c2ecf20Sopenharmony_ci/*
30258c2ecf20Sopenharmony_ci * All files which have been polled are linked to RB tree
30268c2ecf20Sopenharmony_ci * fuse_conn->polled_files which is indexed by kh.  Walk the tree and
30278c2ecf20Sopenharmony_ci * find the matching one.
30288c2ecf20Sopenharmony_ci */
30298c2ecf20Sopenharmony_cistatic struct rb_node **fuse_find_polled_node(struct fuse_conn *fc, u64 kh,
30308c2ecf20Sopenharmony_ci					      struct rb_node **parent_out)
30318c2ecf20Sopenharmony_ci{
30328c2ecf20Sopenharmony_ci	struct rb_node **link = &fc->polled_files.rb_node;
30338c2ecf20Sopenharmony_ci	struct rb_node *last = NULL;
30348c2ecf20Sopenharmony_ci
30358c2ecf20Sopenharmony_ci	while (*link) {
30368c2ecf20Sopenharmony_ci		struct fuse_file *ff;
30378c2ecf20Sopenharmony_ci
30388c2ecf20Sopenharmony_ci		last = *link;
30398c2ecf20Sopenharmony_ci		ff = rb_entry(last, struct fuse_file, polled_node);
30408c2ecf20Sopenharmony_ci
30418c2ecf20Sopenharmony_ci		if (kh < ff->kh)
30428c2ecf20Sopenharmony_ci			link = &last->rb_left;
30438c2ecf20Sopenharmony_ci		else if (kh > ff->kh)
30448c2ecf20Sopenharmony_ci			link = &last->rb_right;
30458c2ecf20Sopenharmony_ci		else
30468c2ecf20Sopenharmony_ci			return link;
30478c2ecf20Sopenharmony_ci	}
30488c2ecf20Sopenharmony_ci
30498c2ecf20Sopenharmony_ci	if (parent_out)
30508c2ecf20Sopenharmony_ci		*parent_out = last;
30518c2ecf20Sopenharmony_ci	return link;
30528c2ecf20Sopenharmony_ci}
30538c2ecf20Sopenharmony_ci
30548c2ecf20Sopenharmony_ci/*
30558c2ecf20Sopenharmony_ci * The file is about to be polled.  Make sure it's on the polled_files
30568c2ecf20Sopenharmony_ci * RB tree.  Note that files once added to the polled_files tree are
30578c2ecf20Sopenharmony_ci * not removed before the file is released.  This is because a file
30588c2ecf20Sopenharmony_ci * polled once is likely to be polled again.
30598c2ecf20Sopenharmony_ci */
30608c2ecf20Sopenharmony_cistatic void fuse_register_polled_file(struct fuse_conn *fc,
30618c2ecf20Sopenharmony_ci				      struct fuse_file *ff)
30628c2ecf20Sopenharmony_ci{
30638c2ecf20Sopenharmony_ci	spin_lock(&fc->lock);
30648c2ecf20Sopenharmony_ci	if (RB_EMPTY_NODE(&ff->polled_node)) {
30658c2ecf20Sopenharmony_ci		struct rb_node **link, *parent;
30668c2ecf20Sopenharmony_ci
30678c2ecf20Sopenharmony_ci		link = fuse_find_polled_node(fc, ff->kh, &parent);
30688c2ecf20Sopenharmony_ci		BUG_ON(*link);
30698c2ecf20Sopenharmony_ci		rb_link_node(&ff->polled_node, parent, link);
30708c2ecf20Sopenharmony_ci		rb_insert_color(&ff->polled_node, &fc->polled_files);
30718c2ecf20Sopenharmony_ci	}
30728c2ecf20Sopenharmony_ci	spin_unlock(&fc->lock);
30738c2ecf20Sopenharmony_ci}
30748c2ecf20Sopenharmony_ci
30758c2ecf20Sopenharmony_ci__poll_t fuse_file_poll(struct file *file, poll_table *wait)
30768c2ecf20Sopenharmony_ci{
30778c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
30788c2ecf20Sopenharmony_ci	struct fuse_mount *fm = ff->fm;
30798c2ecf20Sopenharmony_ci	struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh };
30808c2ecf20Sopenharmony_ci	struct fuse_poll_out outarg;
30818c2ecf20Sopenharmony_ci	FUSE_ARGS(args);
30828c2ecf20Sopenharmony_ci	int err;
30838c2ecf20Sopenharmony_ci
30848c2ecf20Sopenharmony_ci	if (fm->fc->no_poll)
30858c2ecf20Sopenharmony_ci		return DEFAULT_POLLMASK;
30868c2ecf20Sopenharmony_ci
30878c2ecf20Sopenharmony_ci	poll_wait(file, &ff->poll_wait, wait);
30888c2ecf20Sopenharmony_ci	inarg.events = mangle_poll(poll_requested_events(wait));
30898c2ecf20Sopenharmony_ci
30908c2ecf20Sopenharmony_ci	/*
30918c2ecf20Sopenharmony_ci	 * Ask for notification iff there's someone waiting for it.
30928c2ecf20Sopenharmony_ci	 * The client may ignore the flag and always notify.
30938c2ecf20Sopenharmony_ci	 */
30948c2ecf20Sopenharmony_ci	if (waitqueue_active(&ff->poll_wait)) {
30958c2ecf20Sopenharmony_ci		inarg.flags |= FUSE_POLL_SCHEDULE_NOTIFY;
30968c2ecf20Sopenharmony_ci		fuse_register_polled_file(fm->fc, ff);
30978c2ecf20Sopenharmony_ci	}
30988c2ecf20Sopenharmony_ci
30998c2ecf20Sopenharmony_ci	args.opcode = FUSE_POLL;
31008c2ecf20Sopenharmony_ci	args.nodeid = ff->nodeid;
31018c2ecf20Sopenharmony_ci	args.in_numargs = 1;
31028c2ecf20Sopenharmony_ci	args.in_args[0].size = sizeof(inarg);
31038c2ecf20Sopenharmony_ci	args.in_args[0].value = &inarg;
31048c2ecf20Sopenharmony_ci	args.out_numargs = 1;
31058c2ecf20Sopenharmony_ci	args.out_args[0].size = sizeof(outarg);
31068c2ecf20Sopenharmony_ci	args.out_args[0].value = &outarg;
31078c2ecf20Sopenharmony_ci	err = fuse_simple_request(fm, &args);
31088c2ecf20Sopenharmony_ci
31098c2ecf20Sopenharmony_ci	if (!err)
31108c2ecf20Sopenharmony_ci		return demangle_poll(outarg.revents);
31118c2ecf20Sopenharmony_ci	if (err == -ENOSYS) {
31128c2ecf20Sopenharmony_ci		fm->fc->no_poll = 1;
31138c2ecf20Sopenharmony_ci		return DEFAULT_POLLMASK;
31148c2ecf20Sopenharmony_ci	}
31158c2ecf20Sopenharmony_ci	return EPOLLERR;
31168c2ecf20Sopenharmony_ci}
31178c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(fuse_file_poll);
31188c2ecf20Sopenharmony_ci
31198c2ecf20Sopenharmony_ci/*
31208c2ecf20Sopenharmony_ci * This is called from fuse_handle_notify() on FUSE_NOTIFY_POLL and
31218c2ecf20Sopenharmony_ci * wakes up the poll waiters.
31228c2ecf20Sopenharmony_ci */
31238c2ecf20Sopenharmony_ciint fuse_notify_poll_wakeup(struct fuse_conn *fc,
31248c2ecf20Sopenharmony_ci			    struct fuse_notify_poll_wakeup_out *outarg)
31258c2ecf20Sopenharmony_ci{
31268c2ecf20Sopenharmony_ci	u64 kh = outarg->kh;
31278c2ecf20Sopenharmony_ci	struct rb_node **link;
31288c2ecf20Sopenharmony_ci
31298c2ecf20Sopenharmony_ci	spin_lock(&fc->lock);
31308c2ecf20Sopenharmony_ci
31318c2ecf20Sopenharmony_ci	link = fuse_find_polled_node(fc, kh, NULL);
31328c2ecf20Sopenharmony_ci	if (*link) {
31338c2ecf20Sopenharmony_ci		struct fuse_file *ff;
31348c2ecf20Sopenharmony_ci
31358c2ecf20Sopenharmony_ci		ff = rb_entry(*link, struct fuse_file, polled_node);
31368c2ecf20Sopenharmony_ci		wake_up_interruptible_sync(&ff->poll_wait);
31378c2ecf20Sopenharmony_ci	}
31388c2ecf20Sopenharmony_ci
31398c2ecf20Sopenharmony_ci	spin_unlock(&fc->lock);
31408c2ecf20Sopenharmony_ci	return 0;
31418c2ecf20Sopenharmony_ci}
31428c2ecf20Sopenharmony_ci
31438c2ecf20Sopenharmony_cistatic void fuse_do_truncate(struct file *file)
31448c2ecf20Sopenharmony_ci{
31458c2ecf20Sopenharmony_ci	struct inode *inode = file->f_mapping->host;
31468c2ecf20Sopenharmony_ci	struct iattr attr;
31478c2ecf20Sopenharmony_ci
31488c2ecf20Sopenharmony_ci	attr.ia_valid = ATTR_SIZE;
31498c2ecf20Sopenharmony_ci	attr.ia_size = i_size_read(inode);
31508c2ecf20Sopenharmony_ci
31518c2ecf20Sopenharmony_ci	attr.ia_file = file;
31528c2ecf20Sopenharmony_ci	attr.ia_valid |= ATTR_FILE;
31538c2ecf20Sopenharmony_ci
31548c2ecf20Sopenharmony_ci	fuse_do_setattr(file_dentry(file), &attr, file);
31558c2ecf20Sopenharmony_ci}
31568c2ecf20Sopenharmony_ci
31578c2ecf20Sopenharmony_cistatic inline loff_t fuse_round_up(struct fuse_conn *fc, loff_t off)
31588c2ecf20Sopenharmony_ci{
31598c2ecf20Sopenharmony_ci	return round_up(off, fc->max_pages << PAGE_SHIFT);
31608c2ecf20Sopenharmony_ci}
31618c2ecf20Sopenharmony_ci
31628c2ecf20Sopenharmony_cistatic ssize_t
31638c2ecf20Sopenharmony_cifuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
31648c2ecf20Sopenharmony_ci{
31658c2ecf20Sopenharmony_ci	DECLARE_COMPLETION_ONSTACK(wait);
31668c2ecf20Sopenharmony_ci	ssize_t ret = 0;
31678c2ecf20Sopenharmony_ci	struct file *file = iocb->ki_filp;
31688c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
31698c2ecf20Sopenharmony_ci	loff_t pos = 0;
31708c2ecf20Sopenharmony_ci	struct inode *inode;
31718c2ecf20Sopenharmony_ci	loff_t i_size;
31728c2ecf20Sopenharmony_ci	size_t count = iov_iter_count(iter), shortened = 0;
31738c2ecf20Sopenharmony_ci	loff_t offset = iocb->ki_pos;
31748c2ecf20Sopenharmony_ci	struct fuse_io_priv *io;
31758c2ecf20Sopenharmony_ci
31768c2ecf20Sopenharmony_ci	pos = offset;
31778c2ecf20Sopenharmony_ci	inode = file->f_mapping->host;
31788c2ecf20Sopenharmony_ci	i_size = i_size_read(inode);
31798c2ecf20Sopenharmony_ci
31808c2ecf20Sopenharmony_ci	if ((iov_iter_rw(iter) == READ) && (offset >= i_size))
31818c2ecf20Sopenharmony_ci		return 0;
31828c2ecf20Sopenharmony_ci
31838c2ecf20Sopenharmony_ci	io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL);
31848c2ecf20Sopenharmony_ci	if (!io)
31858c2ecf20Sopenharmony_ci		return -ENOMEM;
31868c2ecf20Sopenharmony_ci	spin_lock_init(&io->lock);
31878c2ecf20Sopenharmony_ci	kref_init(&io->refcnt);
31888c2ecf20Sopenharmony_ci	io->reqs = 1;
31898c2ecf20Sopenharmony_ci	io->bytes = -1;
31908c2ecf20Sopenharmony_ci	io->size = 0;
31918c2ecf20Sopenharmony_ci	io->offset = offset;
31928c2ecf20Sopenharmony_ci	io->write = (iov_iter_rw(iter) == WRITE);
31938c2ecf20Sopenharmony_ci	io->err = 0;
31948c2ecf20Sopenharmony_ci	/*
31958c2ecf20Sopenharmony_ci	 * By default, we want to optimize all I/Os with async request
31968c2ecf20Sopenharmony_ci	 * submission to the client filesystem if supported.
31978c2ecf20Sopenharmony_ci	 */
31988c2ecf20Sopenharmony_ci	io->async = ff->fm->fc->async_dio;
31998c2ecf20Sopenharmony_ci	io->iocb = iocb;
32008c2ecf20Sopenharmony_ci	io->blocking = is_sync_kiocb(iocb);
32018c2ecf20Sopenharmony_ci
32028c2ecf20Sopenharmony_ci	/* optimization for short read */
32038c2ecf20Sopenharmony_ci	if (io->async && !io->write && offset + count > i_size) {
32048c2ecf20Sopenharmony_ci		iov_iter_truncate(iter, fuse_round_up(ff->fm->fc, i_size - offset));
32058c2ecf20Sopenharmony_ci		shortened = count - iov_iter_count(iter);
32068c2ecf20Sopenharmony_ci		count -= shortened;
32078c2ecf20Sopenharmony_ci	}
32088c2ecf20Sopenharmony_ci
32098c2ecf20Sopenharmony_ci	/*
32108c2ecf20Sopenharmony_ci	 * We cannot asynchronously extend the size of a file.
32118c2ecf20Sopenharmony_ci	 * In such case the aio will behave exactly like sync io.
32128c2ecf20Sopenharmony_ci	 */
32138c2ecf20Sopenharmony_ci	if ((offset + count > i_size) && io->write)
32148c2ecf20Sopenharmony_ci		io->blocking = true;
32158c2ecf20Sopenharmony_ci
32168c2ecf20Sopenharmony_ci	if (io->async && io->blocking) {
32178c2ecf20Sopenharmony_ci		/*
32188c2ecf20Sopenharmony_ci		 * Additional reference to keep io around after
32198c2ecf20Sopenharmony_ci		 * calling fuse_aio_complete()
32208c2ecf20Sopenharmony_ci		 */
32218c2ecf20Sopenharmony_ci		kref_get(&io->refcnt);
32228c2ecf20Sopenharmony_ci		io->done = &wait;
32238c2ecf20Sopenharmony_ci	}
32248c2ecf20Sopenharmony_ci
32258c2ecf20Sopenharmony_ci	if (iov_iter_rw(iter) == WRITE) {
32268c2ecf20Sopenharmony_ci		ret = fuse_direct_io(io, iter, &pos, FUSE_DIO_WRITE);
32278c2ecf20Sopenharmony_ci		fuse_invalidate_attr(inode);
32288c2ecf20Sopenharmony_ci	} else {
32298c2ecf20Sopenharmony_ci		ret = __fuse_direct_read(io, iter, &pos);
32308c2ecf20Sopenharmony_ci	}
32318c2ecf20Sopenharmony_ci	iov_iter_reexpand(iter, iov_iter_count(iter) + shortened);
32328c2ecf20Sopenharmony_ci
32338c2ecf20Sopenharmony_ci	if (io->async) {
32348c2ecf20Sopenharmony_ci		bool blocking = io->blocking;
32358c2ecf20Sopenharmony_ci
32368c2ecf20Sopenharmony_ci		fuse_aio_complete(io, ret < 0 ? ret : 0, -1);
32378c2ecf20Sopenharmony_ci
32388c2ecf20Sopenharmony_ci		/* we have a non-extending, async request, so return */
32398c2ecf20Sopenharmony_ci		if (!blocking)
32408c2ecf20Sopenharmony_ci			return -EIOCBQUEUED;
32418c2ecf20Sopenharmony_ci
32428c2ecf20Sopenharmony_ci		wait_for_completion(&wait);
32438c2ecf20Sopenharmony_ci		ret = fuse_get_res_by_io(io);
32448c2ecf20Sopenharmony_ci	}
32458c2ecf20Sopenharmony_ci
32468c2ecf20Sopenharmony_ci	kref_put(&io->refcnt, fuse_io_release);
32478c2ecf20Sopenharmony_ci
32488c2ecf20Sopenharmony_ci	if (iov_iter_rw(iter) == WRITE) {
32498c2ecf20Sopenharmony_ci		if (ret > 0)
32508c2ecf20Sopenharmony_ci			fuse_write_update_size(inode, pos);
32518c2ecf20Sopenharmony_ci		else if (ret < 0 && offset + count > i_size)
32528c2ecf20Sopenharmony_ci			fuse_do_truncate(file);
32538c2ecf20Sopenharmony_ci	}
32548c2ecf20Sopenharmony_ci
32558c2ecf20Sopenharmony_ci	return ret;
32568c2ecf20Sopenharmony_ci}
32578c2ecf20Sopenharmony_ci
32588c2ecf20Sopenharmony_cistatic int fuse_writeback_range(struct inode *inode, loff_t start, loff_t end)
32598c2ecf20Sopenharmony_ci{
32608c2ecf20Sopenharmony_ci	int err = filemap_write_and_wait_range(inode->i_mapping, start, LLONG_MAX);
32618c2ecf20Sopenharmony_ci
32628c2ecf20Sopenharmony_ci	if (!err)
32638c2ecf20Sopenharmony_ci		fuse_sync_writes(inode);
32648c2ecf20Sopenharmony_ci
32658c2ecf20Sopenharmony_ci	return err;
32668c2ecf20Sopenharmony_ci}
32678c2ecf20Sopenharmony_ci
32688c2ecf20Sopenharmony_cistatic long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
32698c2ecf20Sopenharmony_ci				loff_t length)
32708c2ecf20Sopenharmony_ci{
32718c2ecf20Sopenharmony_ci	struct fuse_file *ff = file->private_data;
32728c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(file);
32738c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(inode);
32748c2ecf20Sopenharmony_ci	struct fuse_mount *fm = ff->fm;
32758c2ecf20Sopenharmony_ci	FUSE_ARGS(args);
32768c2ecf20Sopenharmony_ci	struct fuse_fallocate_in inarg = {
32778c2ecf20Sopenharmony_ci		.fh = ff->fh,
32788c2ecf20Sopenharmony_ci		.offset = offset,
32798c2ecf20Sopenharmony_ci		.length = length,
32808c2ecf20Sopenharmony_ci		.mode = mode
32818c2ecf20Sopenharmony_ci	};
32828c2ecf20Sopenharmony_ci	int err;
32838c2ecf20Sopenharmony_ci	bool block_faults = FUSE_IS_DAX(inode) &&
32848c2ecf20Sopenharmony_ci		(!(mode & FALLOC_FL_KEEP_SIZE) ||
32858c2ecf20Sopenharmony_ci		 (mode & FALLOC_FL_PUNCH_HOLE));
32868c2ecf20Sopenharmony_ci
32878c2ecf20Sopenharmony_ci	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
32888c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
32898c2ecf20Sopenharmony_ci
32908c2ecf20Sopenharmony_ci	if (fm->fc->no_fallocate)
32918c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
32928c2ecf20Sopenharmony_ci
32938c2ecf20Sopenharmony_ci	inode_lock(inode);
32948c2ecf20Sopenharmony_ci	if (block_faults) {
32958c2ecf20Sopenharmony_ci		down_write(&fi->i_mmap_sem);
32968c2ecf20Sopenharmony_ci		err = fuse_dax_break_layouts(inode, 0, 0);
32978c2ecf20Sopenharmony_ci		if (err)
32988c2ecf20Sopenharmony_ci			goto out;
32998c2ecf20Sopenharmony_ci	}
33008c2ecf20Sopenharmony_ci
33018c2ecf20Sopenharmony_ci	if (mode & FALLOC_FL_PUNCH_HOLE) {
33028c2ecf20Sopenharmony_ci		loff_t endbyte = offset + length - 1;
33038c2ecf20Sopenharmony_ci
33048c2ecf20Sopenharmony_ci		err = fuse_writeback_range(inode, offset, endbyte);
33058c2ecf20Sopenharmony_ci		if (err)
33068c2ecf20Sopenharmony_ci			goto out;
33078c2ecf20Sopenharmony_ci	}
33088c2ecf20Sopenharmony_ci
33098c2ecf20Sopenharmony_ci	if (!(mode & FALLOC_FL_KEEP_SIZE) &&
33108c2ecf20Sopenharmony_ci	    offset + length > i_size_read(inode)) {
33118c2ecf20Sopenharmony_ci		err = inode_newsize_ok(inode, offset + length);
33128c2ecf20Sopenharmony_ci		if (err)
33138c2ecf20Sopenharmony_ci			goto out;
33148c2ecf20Sopenharmony_ci	}
33158c2ecf20Sopenharmony_ci
33168c2ecf20Sopenharmony_ci	err = file_modified(file);
33178c2ecf20Sopenharmony_ci	if (err)
33188c2ecf20Sopenharmony_ci		goto out;
33198c2ecf20Sopenharmony_ci
33208c2ecf20Sopenharmony_ci	if (!(mode & FALLOC_FL_KEEP_SIZE))
33218c2ecf20Sopenharmony_ci		set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
33228c2ecf20Sopenharmony_ci
33238c2ecf20Sopenharmony_ci	args.opcode = FUSE_FALLOCATE;
33248c2ecf20Sopenharmony_ci	args.nodeid = ff->nodeid;
33258c2ecf20Sopenharmony_ci	args.in_numargs = 1;
33268c2ecf20Sopenharmony_ci	args.in_args[0].size = sizeof(inarg);
33278c2ecf20Sopenharmony_ci	args.in_args[0].value = &inarg;
33288c2ecf20Sopenharmony_ci	err = fuse_simple_request(fm, &args);
33298c2ecf20Sopenharmony_ci	if (err == -ENOSYS) {
33308c2ecf20Sopenharmony_ci		fm->fc->no_fallocate = 1;
33318c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
33328c2ecf20Sopenharmony_ci	}
33338c2ecf20Sopenharmony_ci	if (err)
33348c2ecf20Sopenharmony_ci		goto out;
33358c2ecf20Sopenharmony_ci
33368c2ecf20Sopenharmony_ci	/* we could have extended the file */
33378c2ecf20Sopenharmony_ci	if (!(mode & FALLOC_FL_KEEP_SIZE)) {
33388c2ecf20Sopenharmony_ci		bool changed = fuse_write_update_size(inode, offset + length);
33398c2ecf20Sopenharmony_ci
33408c2ecf20Sopenharmony_ci		if (changed && fm->fc->writeback_cache)
33418c2ecf20Sopenharmony_ci			file_update_time(file);
33428c2ecf20Sopenharmony_ci	}
33438c2ecf20Sopenharmony_ci
33448c2ecf20Sopenharmony_ci	if (mode & FALLOC_FL_PUNCH_HOLE)
33458c2ecf20Sopenharmony_ci		truncate_pagecache_range(inode, offset, offset + length - 1);
33468c2ecf20Sopenharmony_ci
33478c2ecf20Sopenharmony_ci	fuse_invalidate_attr(inode);
33488c2ecf20Sopenharmony_ci
33498c2ecf20Sopenharmony_ciout:
33508c2ecf20Sopenharmony_ci	if (!(mode & FALLOC_FL_KEEP_SIZE))
33518c2ecf20Sopenharmony_ci		clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
33528c2ecf20Sopenharmony_ci
33538c2ecf20Sopenharmony_ci	if (block_faults)
33548c2ecf20Sopenharmony_ci		up_write(&fi->i_mmap_sem);
33558c2ecf20Sopenharmony_ci
33568c2ecf20Sopenharmony_ci	inode_unlock(inode);
33578c2ecf20Sopenharmony_ci
33588c2ecf20Sopenharmony_ci	fuse_flush_time_update(inode);
33598c2ecf20Sopenharmony_ci
33608c2ecf20Sopenharmony_ci	return err;
33618c2ecf20Sopenharmony_ci}
33628c2ecf20Sopenharmony_ci
33638c2ecf20Sopenharmony_cistatic ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in,
33648c2ecf20Sopenharmony_ci				      struct file *file_out, loff_t pos_out,
33658c2ecf20Sopenharmony_ci				      size_t len, unsigned int flags)
33668c2ecf20Sopenharmony_ci{
33678c2ecf20Sopenharmony_ci	struct fuse_file *ff_in = file_in->private_data;
33688c2ecf20Sopenharmony_ci	struct fuse_file *ff_out = file_out->private_data;
33698c2ecf20Sopenharmony_ci	struct inode *inode_in = file_inode(file_in);
33708c2ecf20Sopenharmony_ci	struct inode *inode_out = file_inode(file_out);
33718c2ecf20Sopenharmony_ci	struct fuse_inode *fi_out = get_fuse_inode(inode_out);
33728c2ecf20Sopenharmony_ci	struct fuse_mount *fm = ff_in->fm;
33738c2ecf20Sopenharmony_ci	struct fuse_conn *fc = fm->fc;
33748c2ecf20Sopenharmony_ci	FUSE_ARGS(args);
33758c2ecf20Sopenharmony_ci	struct fuse_copy_file_range_in inarg = {
33768c2ecf20Sopenharmony_ci		.fh_in = ff_in->fh,
33778c2ecf20Sopenharmony_ci		.off_in = pos_in,
33788c2ecf20Sopenharmony_ci		.nodeid_out = ff_out->nodeid,
33798c2ecf20Sopenharmony_ci		.fh_out = ff_out->fh,
33808c2ecf20Sopenharmony_ci		.off_out = pos_out,
33818c2ecf20Sopenharmony_ci		.len = len,
33828c2ecf20Sopenharmony_ci		.flags = flags
33838c2ecf20Sopenharmony_ci	};
33848c2ecf20Sopenharmony_ci	struct fuse_write_out outarg;
33858c2ecf20Sopenharmony_ci	ssize_t err;
33868c2ecf20Sopenharmony_ci	/* mark unstable when write-back is not used, and file_out gets
33878c2ecf20Sopenharmony_ci	 * extended */
33888c2ecf20Sopenharmony_ci	bool is_unstable = (!fc->writeback_cache) &&
33898c2ecf20Sopenharmony_ci			   ((pos_out + len) > inode_out->i_size);
33908c2ecf20Sopenharmony_ci
33918c2ecf20Sopenharmony_ci	if (fc->no_copy_file_range)
33928c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
33938c2ecf20Sopenharmony_ci
33948c2ecf20Sopenharmony_ci	if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb)
33958c2ecf20Sopenharmony_ci		return -EXDEV;
33968c2ecf20Sopenharmony_ci
33978c2ecf20Sopenharmony_ci	inode_lock(inode_in);
33988c2ecf20Sopenharmony_ci	err = fuse_writeback_range(inode_in, pos_in, pos_in + len - 1);
33998c2ecf20Sopenharmony_ci	inode_unlock(inode_in);
34008c2ecf20Sopenharmony_ci	if (err)
34018c2ecf20Sopenharmony_ci		return err;
34028c2ecf20Sopenharmony_ci
34038c2ecf20Sopenharmony_ci	inode_lock(inode_out);
34048c2ecf20Sopenharmony_ci
34058c2ecf20Sopenharmony_ci	err = file_modified(file_out);
34068c2ecf20Sopenharmony_ci	if (err)
34078c2ecf20Sopenharmony_ci		goto out;
34088c2ecf20Sopenharmony_ci
34098c2ecf20Sopenharmony_ci	/*
34108c2ecf20Sopenharmony_ci	 * Write out dirty pages in the destination file before sending the COPY
34118c2ecf20Sopenharmony_ci	 * request to userspace.  After the request is completed, truncate off
34128c2ecf20Sopenharmony_ci	 * pages (including partial ones) from the cache that have been copied,
34138c2ecf20Sopenharmony_ci	 * since these contain stale data at that point.
34148c2ecf20Sopenharmony_ci	 *
34158c2ecf20Sopenharmony_ci	 * This should be mostly correct, but if the COPY writes to partial
34168c2ecf20Sopenharmony_ci	 * pages (at the start or end) and the parts not covered by the COPY are
34178c2ecf20Sopenharmony_ci	 * written through a memory map after calling fuse_writeback_range(),
34188c2ecf20Sopenharmony_ci	 * then these partial page modifications will be lost on truncation.
34198c2ecf20Sopenharmony_ci	 *
34208c2ecf20Sopenharmony_ci	 * It is unlikely that someone would rely on such mixed style
34218c2ecf20Sopenharmony_ci	 * modifications.  Yet this does give less guarantees than if the
34228c2ecf20Sopenharmony_ci	 * copying was performed with write(2).
34238c2ecf20Sopenharmony_ci	 *
34248c2ecf20Sopenharmony_ci	 * To fix this a i_mmap_sem style lock could be used to prevent new
34258c2ecf20Sopenharmony_ci	 * faults while the copy is ongoing.
34268c2ecf20Sopenharmony_ci	 */
34278c2ecf20Sopenharmony_ci	err = fuse_writeback_range(inode_out, pos_out, pos_out + len - 1);
34288c2ecf20Sopenharmony_ci	if (err)
34298c2ecf20Sopenharmony_ci		goto out;
34308c2ecf20Sopenharmony_ci
34318c2ecf20Sopenharmony_ci	if (is_unstable)
34328c2ecf20Sopenharmony_ci		set_bit(FUSE_I_SIZE_UNSTABLE, &fi_out->state);
34338c2ecf20Sopenharmony_ci
34348c2ecf20Sopenharmony_ci	args.opcode = FUSE_COPY_FILE_RANGE;
34358c2ecf20Sopenharmony_ci	args.nodeid = ff_in->nodeid;
34368c2ecf20Sopenharmony_ci	args.in_numargs = 1;
34378c2ecf20Sopenharmony_ci	args.in_args[0].size = sizeof(inarg);
34388c2ecf20Sopenharmony_ci	args.in_args[0].value = &inarg;
34398c2ecf20Sopenharmony_ci	args.out_numargs = 1;
34408c2ecf20Sopenharmony_ci	args.out_args[0].size = sizeof(outarg);
34418c2ecf20Sopenharmony_ci	args.out_args[0].value = &outarg;
34428c2ecf20Sopenharmony_ci	err = fuse_simple_request(fm, &args);
34438c2ecf20Sopenharmony_ci	if (err == -ENOSYS) {
34448c2ecf20Sopenharmony_ci		fc->no_copy_file_range = 1;
34458c2ecf20Sopenharmony_ci		err = -EOPNOTSUPP;
34468c2ecf20Sopenharmony_ci	}
34478c2ecf20Sopenharmony_ci	if (err)
34488c2ecf20Sopenharmony_ci		goto out;
34498c2ecf20Sopenharmony_ci
34508c2ecf20Sopenharmony_ci	truncate_inode_pages_range(inode_out->i_mapping,
34518c2ecf20Sopenharmony_ci				   ALIGN_DOWN(pos_out, PAGE_SIZE),
34528c2ecf20Sopenharmony_ci				   ALIGN(pos_out + outarg.size, PAGE_SIZE) - 1);
34538c2ecf20Sopenharmony_ci
34548c2ecf20Sopenharmony_ci	if (fc->writeback_cache) {
34558c2ecf20Sopenharmony_ci		fuse_write_update_size(inode_out, pos_out + outarg.size);
34568c2ecf20Sopenharmony_ci		file_update_time(file_out);
34578c2ecf20Sopenharmony_ci	}
34588c2ecf20Sopenharmony_ci
34598c2ecf20Sopenharmony_ci	fuse_invalidate_attr(inode_out);
34608c2ecf20Sopenharmony_ci
34618c2ecf20Sopenharmony_ci	err = outarg.size;
34628c2ecf20Sopenharmony_ciout:
34638c2ecf20Sopenharmony_ci	if (is_unstable)
34648c2ecf20Sopenharmony_ci		clear_bit(FUSE_I_SIZE_UNSTABLE, &fi_out->state);
34658c2ecf20Sopenharmony_ci
34668c2ecf20Sopenharmony_ci	inode_unlock(inode_out);
34678c2ecf20Sopenharmony_ci	file_accessed(file_in);
34688c2ecf20Sopenharmony_ci
34698c2ecf20Sopenharmony_ci	fuse_flush_time_update(inode_out);
34708c2ecf20Sopenharmony_ci
34718c2ecf20Sopenharmony_ci	return err;
34728c2ecf20Sopenharmony_ci}
34738c2ecf20Sopenharmony_ci
34748c2ecf20Sopenharmony_cistatic ssize_t fuse_copy_file_range(struct file *src_file, loff_t src_off,
34758c2ecf20Sopenharmony_ci				    struct file *dst_file, loff_t dst_off,
34768c2ecf20Sopenharmony_ci				    size_t len, unsigned int flags)
34778c2ecf20Sopenharmony_ci{
34788c2ecf20Sopenharmony_ci	ssize_t ret;
34798c2ecf20Sopenharmony_ci
34808c2ecf20Sopenharmony_ci	ret = __fuse_copy_file_range(src_file, src_off, dst_file, dst_off,
34818c2ecf20Sopenharmony_ci				     len, flags);
34828c2ecf20Sopenharmony_ci
34838c2ecf20Sopenharmony_ci	if (ret == -EOPNOTSUPP || ret == -EXDEV)
34848c2ecf20Sopenharmony_ci		ret = generic_copy_file_range(src_file, src_off, dst_file,
34858c2ecf20Sopenharmony_ci					      dst_off, len, flags);
34868c2ecf20Sopenharmony_ci	return ret;
34878c2ecf20Sopenharmony_ci}
34888c2ecf20Sopenharmony_ci
34898c2ecf20Sopenharmony_cistatic const struct file_operations fuse_file_operations = {
34908c2ecf20Sopenharmony_ci	.llseek		= fuse_file_llseek,
34918c2ecf20Sopenharmony_ci	.read_iter	= fuse_file_read_iter,
34928c2ecf20Sopenharmony_ci	.write_iter	= fuse_file_write_iter,
34938c2ecf20Sopenharmony_ci	.mmap		= fuse_file_mmap,
34948c2ecf20Sopenharmony_ci	.open		= fuse_open,
34958c2ecf20Sopenharmony_ci	.flush		= fuse_flush,
34968c2ecf20Sopenharmony_ci	.release	= fuse_release,
34978c2ecf20Sopenharmony_ci	.fsync		= fuse_fsync,
34988c2ecf20Sopenharmony_ci	.lock		= fuse_file_lock,
34998c2ecf20Sopenharmony_ci	.get_unmapped_area = thp_get_unmapped_area,
35008c2ecf20Sopenharmony_ci	.flock		= fuse_file_flock,
35018c2ecf20Sopenharmony_ci	.splice_read	= generic_file_splice_read,
35028c2ecf20Sopenharmony_ci	.splice_write	= iter_file_splice_write,
35038c2ecf20Sopenharmony_ci	.unlocked_ioctl	= fuse_file_ioctl,
35048c2ecf20Sopenharmony_ci	.compat_ioctl	= fuse_file_compat_ioctl,
35058c2ecf20Sopenharmony_ci	.poll		= fuse_file_poll,
35068c2ecf20Sopenharmony_ci	.fallocate	= fuse_file_fallocate,
35078c2ecf20Sopenharmony_ci	.copy_file_range = fuse_copy_file_range,
35088c2ecf20Sopenharmony_ci};
35098c2ecf20Sopenharmony_ci
35108c2ecf20Sopenharmony_cistatic const struct address_space_operations fuse_file_aops  = {
35118c2ecf20Sopenharmony_ci	.readpage	= fuse_readpage,
35128c2ecf20Sopenharmony_ci	.readahead	= fuse_readahead,
35138c2ecf20Sopenharmony_ci	.writepage	= fuse_writepage,
35148c2ecf20Sopenharmony_ci	.writepages	= fuse_writepages,
35158c2ecf20Sopenharmony_ci	.launder_page	= fuse_launder_page,
35168c2ecf20Sopenharmony_ci	.set_page_dirty	= __set_page_dirty_nobuffers,
35178c2ecf20Sopenharmony_ci	.bmap		= fuse_bmap,
35188c2ecf20Sopenharmony_ci	.direct_IO	= fuse_direct_IO,
35198c2ecf20Sopenharmony_ci	.write_begin	= fuse_write_begin,
35208c2ecf20Sopenharmony_ci	.write_end	= fuse_write_end,
35218c2ecf20Sopenharmony_ci};
35228c2ecf20Sopenharmony_ci
35238c2ecf20Sopenharmony_civoid fuse_init_file_inode(struct inode *inode)
35248c2ecf20Sopenharmony_ci{
35258c2ecf20Sopenharmony_ci	struct fuse_inode *fi = get_fuse_inode(inode);
35268c2ecf20Sopenharmony_ci
35278c2ecf20Sopenharmony_ci	inode->i_fop = &fuse_file_operations;
35288c2ecf20Sopenharmony_ci	inode->i_data.a_ops = &fuse_file_aops;
35298c2ecf20Sopenharmony_ci
35308c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&fi->write_files);
35318c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&fi->queued_writes);
35328c2ecf20Sopenharmony_ci	fi->writectr = 0;
35338c2ecf20Sopenharmony_ci	init_waitqueue_head(&fi->page_waitq);
35348c2ecf20Sopenharmony_ci	fi->writepages = RB_ROOT;
35358c2ecf20Sopenharmony_ci
35368c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_FUSE_DAX))
35378c2ecf20Sopenharmony_ci		fuse_dax_inode_init(inode);
35388c2ecf20Sopenharmony_ci}
3539