b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 1) /*
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 2) FUSE: Filesystem in Userspace
1729a16c2c92b (Miklos Szeredi 2008-11-26 12:03:54 +0100 3) Copyright (C) 2001-2008 Miklos Szeredi <miklos@szeredi.hu>
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 4)
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 5) This program can be distributed under the terms of the GNU GPL.
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 6) See the file COPYING.
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 7) */
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 8)
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 9) #include "fuse_i.h"
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 10)
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 11) #include <linux/pagemap.h>
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 12) #include <linux/slab.h>
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 13) #include <linux/kernel.h>
e8edc6e03a5c8 (Alexey Dobriyan 2007-05-21 01:22:52 +0400 14) #include <linux/sched.h>
7a36094d61bfe (Eric W. Biederman 2017-09-26 12:45:33 -0500 15) #include <linux/sched/signal.h>
08cbf542bf24f (Tejun Heo 2009-04-14 10:54:53 +0900 16) #include <linux/module.h>
478e0841b3dce (Johannes Weiner 2011-07-25 22:35:35 +0200 17) #include <linux/swap.h>
3634a6327815d (Brian Foster 2013-05-17 09:30:32 -0400 18) #include <linux/falloc.h>
e2e40f2c1ed43 (Christoph Hellwig 2015-02-22 08:58:50 -0800 19) #include <linux/uio.h>
31070f6ccec09 (Chirantan Ekbote 2020-07-14 19:26:39 +0900 20) #include <linux/fs.h>
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 21)
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 22) static int fuse_send_open(struct fuse_mount *fm, u64 nodeid,
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 23) unsigned int open_flags, int opcode,
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 24) struct fuse_open_out *outargp)
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 25) {
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 26) struct fuse_open_in inarg;
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 27) FUSE_ARGS(args);
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 28)
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 29) memset(&inarg, 0, sizeof(inarg));
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 30) inarg.flags = open_flags & ~(O_CREAT | O_EXCL | O_NOCTTY);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 31) if (!fm->fc->atomic_o_trunc)
6ff958edbf39c (Miklos Szeredi 2007-10-18 03:07:02 -0700 32) inarg.flags &= ~O_TRUNC;
643a666a89c35 (Vivek Goyal 2020-10-09 14:15:11 -0400 33)
643a666a89c35 (Vivek Goyal 2020-10-09 14:15:11 -0400 34) if (fm->fc->handle_killpriv_v2 &&
643a666a89c35 (Vivek Goyal 2020-10-09 14:15:11 -0400 35) (inarg.flags & O_TRUNC) && !capable(CAP_FSETID)) {
643a666a89c35 (Vivek Goyal 2020-10-09 14:15:11 -0400 36) inarg.open_flags |= FUSE_OPEN_KILL_SUIDGID;
643a666a89c35 (Vivek Goyal 2020-10-09 14:15:11 -0400 37) }
643a666a89c35 (Vivek Goyal 2020-10-09 14:15:11 -0400 38)
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 39) args.opcode = opcode;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 40) args.nodeid = nodeid;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 41) args.in_numargs = 1;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 42) args.in_args[0].size = sizeof(inarg);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 43) args.in_args[0].value = &inarg;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 44) args.out_numargs = 1;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 45) args.out_args[0].size = sizeof(*outargp);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 46) args.out_args[0].value = outargp;
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 47)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 48) return fuse_simple_request(fm, &args);
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 49) }
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 50)
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 51) struct fuse_release_args {
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 52) struct fuse_args args;
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 53) struct fuse_release_in inarg;
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 54) struct inode *inode;
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 55) };
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 56)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 57) struct fuse_file *fuse_file_alloc(struct fuse_mount *fm)
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 58) {
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 59) struct fuse_file *ff;
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 60)
dc69e98c241e1 (Khazhismel Kumykov 2019-09-17 12:35:33 -0700 61) ff = kzalloc(sizeof(struct fuse_file), GFP_KERNEL_ACCOUNT);
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 62) if (unlikely(!ff))
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 63) return NULL;
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 64)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 65) ff->fm = fm;
dc69e98c241e1 (Khazhismel Kumykov 2019-09-17 12:35:33 -0700 66) ff->release_args = kzalloc(sizeof(*ff->release_args),
dc69e98c241e1 (Khazhismel Kumykov 2019-09-17 12:35:33 -0700 67) GFP_KERNEL_ACCOUNT);
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 68) if (!ff->release_args) {
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 69) kfree(ff);
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 70) return NULL;
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 71) }
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 72)
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 73) INIT_LIST_HEAD(&ff->write_entry);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 74) mutex_init(&ff->readdir.lock);
4e8c2eb54327a (Elena Reshetova 2017-03-03 11:04:03 +0200 75) refcount_set(&ff->count, 1);
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 76) RB_CLEAR_NODE(&ff->polled_node);
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 77) init_waitqueue_head(&ff->poll_wait);
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 78)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 79) ff->kh = atomic64_inc_return(&fm->fc->khctr);
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 80)
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 81) return ff;
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 82) }
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 83)
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 84) void fuse_file_free(struct fuse_file *ff)
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 85) {
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 86) kfree(ff->release_args);
5d7bc7e8680c7 (Miklos Szeredi 2018-10-01 10:07:04 +0200 87) mutex_destroy(&ff->readdir.lock);
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 88) kfree(ff);
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 89) }
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 90)
267d84449f523 (Miklos Szeredi 2017-02-22 20:08:25 +0100 91) static struct fuse_file *fuse_file_get(struct fuse_file *ff)
c756e0a4d7920 (Miklos Szeredi 2007-10-16 23:31:00 -0700 92) {
4e8c2eb54327a (Elena Reshetova 2017-03-03 11:04:03 +0200 93) refcount_inc(&ff->count);
c756e0a4d7920 (Miklos Szeredi 2007-10-16 23:31:00 -0700 94) return ff;
c756e0a4d7920 (Miklos Szeredi 2007-10-16 23:31:00 -0700 95) }
c756e0a4d7920 (Miklos Szeredi 2007-10-16 23:31:00 -0700 96)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 97) static void fuse_release_end(struct fuse_mount *fm, struct fuse_args *args,
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 98) int error)
819c4b3b40092 (Miklos Szeredi 2007-10-16 23:31:04 -0700 99) {
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 100) struct fuse_release_args *ra = container_of(args, typeof(*ra), args);
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 101)
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 102) iput(ra->inode);
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 103) kfree(ra);
819c4b3b40092 (Miklos Szeredi 2007-10-16 23:31:04 -0700 104) }
819c4b3b40092 (Miklos Szeredi 2007-10-16 23:31:04 -0700 105)
2e64ff154ce6c (Chad Austin 2018-12-10 10:54:52 -0800 106) static void fuse_file_put(struct fuse_file *ff, bool sync, bool isdir)
c756e0a4d7920 (Miklos Szeredi 2007-10-16 23:31:00 -0700 107) {
4e8c2eb54327a (Elena Reshetova 2017-03-03 11:04:03 +0200 108) if (refcount_dec_and_test(&ff->count)) {
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 109) struct fuse_args *args = &ff->release_args->args;
8b0797a4984de (Miklos Szeredi 2009-04-28 16:56:39 +0200 110)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 111) if (isdir ? ff->fm->fc->no_opendir : ff->fm->fc->no_open) {
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 112) /* Do nothing when client does not implement 'open' */
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 113) fuse_release_end(ff->fm, args, 0);
7678ac50615d9 (Andrew Gallagher 2013-11-05 16:05:52 +0100 114) } else if (sync) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 115) fuse_simple_request(ff->fm, args);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 116) fuse_release_end(ff->fm, args, 0);
5a18ec176c934 (Miklos Szeredi 2011-02-25 14:44:58 +0100 117) } else {
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 118) args->end = fuse_release_end;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 119) if (fuse_simple_background(ff->fm, args,
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 120) GFP_KERNEL | __GFP_NOFAIL))
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 121) fuse_release_end(ff->fm, args, -ENOTCONN);
5a18ec176c934 (Miklos Szeredi 2011-02-25 14:44:58 +0100 122) }
c756e0a4d7920 (Miklos Szeredi 2007-10-16 23:31:00 -0700 123) kfree(ff);
c756e0a4d7920 (Miklos Szeredi 2007-10-16 23:31:00 -0700 124) }
c756e0a4d7920 (Miklos Szeredi 2007-10-16 23:31:00 -0700 125) }
c756e0a4d7920 (Miklos Szeredi 2007-10-16 23:31:00 -0700 126)
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 127) struct fuse_file *fuse_file_open(struct fuse_mount *fm, u64 nodeid,
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 128) unsigned int open_flags, bool isdir)
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 129) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 130) struct fuse_conn *fc = fm->fc;
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 131) struct fuse_file *ff;
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 132) int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 133)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 134) ff = fuse_file_alloc(fm);
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 135) if (!ff)
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 136) return ERR_PTR(-ENOMEM);
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 137)
7678ac50615d9 (Andrew Gallagher 2013-11-05 16:05:52 +0100 138) ff->fh = 0;
fabf7e0262d0b (Chad Austin 2019-01-28 16:34:34 -0800 139) /* Default for no-open */
fabf7e0262d0b (Chad Austin 2019-01-28 16:34:34 -0800 140) ff->open_flags = FOPEN_KEEP_CACHE | (isdir ? FOPEN_CACHE_DIR : 0);
d9a9ea94f748f (Chad Austin 2019-01-07 16:53:17 -0800 141) if (isdir ? !fc->no_opendir : !fc->no_open) {
7678ac50615d9 (Andrew Gallagher 2013-11-05 16:05:52 +0100 142) struct fuse_open_out outarg;
7678ac50615d9 (Andrew Gallagher 2013-11-05 16:05:52 +0100 143) int err;
7678ac50615d9 (Andrew Gallagher 2013-11-05 16:05:52 +0100 144)
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 145) err = fuse_send_open(fm, nodeid, open_flags, opcode, &outarg);
7678ac50615d9 (Andrew Gallagher 2013-11-05 16:05:52 +0100 146) if (!err) {
7678ac50615d9 (Andrew Gallagher 2013-11-05 16:05:52 +0100 147) ff->fh = outarg.fh;
7678ac50615d9 (Andrew Gallagher 2013-11-05 16:05:52 +0100 148) ff->open_flags = outarg.open_flags;
7678ac50615d9 (Andrew Gallagher 2013-11-05 16:05:52 +0100 149)
d9a9ea94f748f (Chad Austin 2019-01-07 16:53:17 -0800 150) } else if (err != -ENOSYS) {
7678ac50615d9 (Andrew Gallagher 2013-11-05 16:05:52 +0100 151) fuse_file_free(ff);
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 152) return ERR_PTR(err);
7678ac50615d9 (Andrew Gallagher 2013-11-05 16:05:52 +0100 153) } else {
d9a9ea94f748f (Chad Austin 2019-01-07 16:53:17 -0800 154) if (isdir)
d9a9ea94f748f (Chad Austin 2019-01-07 16:53:17 -0800 155) fc->no_opendir = 1;
d9a9ea94f748f (Chad Austin 2019-01-07 16:53:17 -0800 156) else
d9a9ea94f748f (Chad Austin 2019-01-07 16:53:17 -0800 157) fc->no_open = 1;
7678ac50615d9 (Andrew Gallagher 2013-11-05 16:05:52 +0100 158) }
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 159) }
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 160)
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 161) if (isdir)
7678ac50615d9 (Andrew Gallagher 2013-11-05 16:05:52 +0100 162) ff->open_flags &= ~FOPEN_DIRECT_IO;
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 163)
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 164) ff->nodeid = nodeid;
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 165)
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 166) return ff;
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 167) }
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 168)
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 169) int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file,
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 170) bool isdir)
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 171) {
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 172) struct fuse_file *ff = fuse_file_open(fm, nodeid, file->f_flags, isdir);
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 173)
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 174) if (!IS_ERR(ff))
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 175) file->private_data = ff;
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 176)
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 177) return PTR_ERR_OR_ZERO(ff);
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 178) }
08cbf542bf24f (Tejun Heo 2009-04-14 10:54:53 +0900 179) EXPORT_SYMBOL_GPL(fuse_do_open);
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 180)
650b22b941fa0 (Pavel Emelyanov 2013-10-10 17:10:04 +0400 181) static void fuse_link_write_file(struct file *file)
650b22b941fa0 (Pavel Emelyanov 2013-10-10 17:10:04 +0400 182) {
650b22b941fa0 (Pavel Emelyanov 2013-10-10 17:10:04 +0400 183) struct inode *inode = file_inode(file);
650b22b941fa0 (Pavel Emelyanov 2013-10-10 17:10:04 +0400 184) struct fuse_inode *fi = get_fuse_inode(inode);
650b22b941fa0 (Pavel Emelyanov 2013-10-10 17:10:04 +0400 185) struct fuse_file *ff = file->private_data;
650b22b941fa0 (Pavel Emelyanov 2013-10-10 17:10:04 +0400 186) /*
650b22b941fa0 (Pavel Emelyanov 2013-10-10 17:10:04 +0400 187) * file may be written through mmap, so chain it onto the
650b22b941fa0 (Pavel Emelyanov 2013-10-10 17:10:04 +0400 188) * inodes's write_file list
650b22b941fa0 (Pavel Emelyanov 2013-10-10 17:10:04 +0400 189) */
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 190) spin_lock(&fi->lock);
650b22b941fa0 (Pavel Emelyanov 2013-10-10 17:10:04 +0400 191) if (list_empty(&ff->write_entry))
650b22b941fa0 (Pavel Emelyanov 2013-10-10 17:10:04 +0400 192) list_add(&ff->write_entry, &fi->write_files);
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 193) spin_unlock(&fi->lock);
650b22b941fa0 (Pavel Emelyanov 2013-10-10 17:10:04 +0400 194) }
650b22b941fa0 (Pavel Emelyanov 2013-10-10 17:10:04 +0400 195)
c7b7143c6342b (Miklos Szeredi 2009-04-28 16:56:37 +0200 196) void fuse_finish_open(struct inode *inode, struct file *file)
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 197) {
c7b7143c6342b (Miklos Szeredi 2009-04-28 16:56:37 +0200 198) struct fuse_file *ff = file->private_data;
a0822c55779d9 (Ken Sumrall 2010-11-24 12:57:00 -0800 199) struct fuse_conn *fc = get_fuse_conn(inode);
c7b7143c6342b (Miklos Szeredi 2009-04-28 16:56:37 +0200 200)
c7b7143c6342b (Miklos Szeredi 2009-04-28 16:56:37 +0200 201) if (!(ff->open_flags & FOPEN_KEEP_CACHE))
b10099792b627 (Miklos Szeredi 2007-10-16 23:31:01 -0700 202) invalidate_inode_pages2(inode->i_mapping);
bbd84f33652f8 (Kirill Smelkov 2019-04-24 07:13:57 +0000 203) if (ff->open_flags & FOPEN_STREAM)
bbd84f33652f8 (Kirill Smelkov 2019-04-24 07:13:57 +0000 204) stream_open(inode, file);
bbd84f33652f8 (Kirill Smelkov 2019-04-24 07:13:57 +0000 205) else if (ff->open_flags & FOPEN_NONSEEKABLE)
a7c1b990f7157 (Tejun Heo 2008-10-16 16:08:57 +0200 206) nonseekable_open(inode, file);
a0822c55779d9 (Ken Sumrall 2010-11-24 12:57:00 -0800 207) if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC)) {
a0822c55779d9 (Ken Sumrall 2010-11-24 12:57:00 -0800 208) struct fuse_inode *fi = get_fuse_inode(inode);
a0822c55779d9 (Ken Sumrall 2010-11-24 12:57:00 -0800 209)
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 210) spin_lock(&fi->lock);
4510d86fbbb36 (Kirill Tkhai 2018-11-09 13:33:17 +0300 211) fi->attr_version = atomic64_inc_return(&fc->attr_version);
a0822c55779d9 (Ken Sumrall 2010-11-24 12:57:00 -0800 212) i_size_write(inode, 0);
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 213) spin_unlock(&fi->lock);
a0822c55779d9 (Ken Sumrall 2010-11-24 12:57:00 -0800 214) fuse_invalidate_attr(inode);
75caeecdf9c71 (Maxim Patlasov 2014-04-28 14:19:22 +0200 215) if (fc->writeback_cache)
75caeecdf9c71 (Maxim Patlasov 2014-04-28 14:19:22 +0200 216) file_update_time(file);
a0822c55779d9 (Ken Sumrall 2010-11-24 12:57:00 -0800 217) }
4d99ff8f12eb2 (Pavel Emelyanov 2013-10-10 17:12:18 +0400 218) if ((file->f_mode & FMODE_WRITE) && fc->writeback_cache)
4d99ff8f12eb2 (Pavel Emelyanov 2013-10-10 17:12:18 +0400 219) fuse_link_write_file(file);
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 220) }
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 221)
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 222) int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 223) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 224) struct fuse_mount *fm = get_fuse_mount(inode);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 225) struct fuse_conn *fc = fm->fc;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 226) int err;
e4648309b85a7 (Miklos Szeredi 2019-10-23 14:26:37 +0200 227) bool is_wb_truncate = (file->f_flags & O_TRUNC) &&
75caeecdf9c71 (Maxim Patlasov 2014-04-28 14:19:22 +0200 228) fc->atomic_o_trunc &&
75caeecdf9c71 (Maxim Patlasov 2014-04-28 14:19:22 +0200 229) fc->writeback_cache;
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 230) bool dax_truncate = (file->f_flags & O_TRUNC) &&
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 231) fc->atomic_o_trunc && FUSE_IS_DAX(inode);
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 232)
5d069dbe8aaf2 (Miklos Szeredi 2020-12-10 15:33:14 +0100 233) if (fuse_is_bad(inode))
5d069dbe8aaf2 (Miklos Szeredi 2020-12-10 15:33:14 +0100 234) return -EIO;
5d069dbe8aaf2 (Miklos Szeredi 2020-12-10 15:33:14 +0100 235)
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 236) err = generic_file_open(inode, file);
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 237) if (err)
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 238) return err;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 239)
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 240) if (is_wb_truncate || dax_truncate) {
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 241) inode_lock(inode);
e4648309b85a7 (Miklos Szeredi 2019-10-23 14:26:37 +0200 242) fuse_set_nowrite(inode);
e4648309b85a7 (Miklos Szeredi 2019-10-23 14:26:37 +0200 243) }
75caeecdf9c71 (Maxim Patlasov 2014-04-28 14:19:22 +0200 244)
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 245) if (dax_truncate) {
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 246) down_write(&get_fuse_inode(inode)->i_mmap_sem);
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 247) err = fuse_dax_break_layouts(inode, 0, 0);
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 248) if (err)
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 249) goto out;
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 250) }
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 251)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 252) err = fuse_do_open(fm, get_node_id(inode), file, isdir);
75caeecdf9c71 (Maxim Patlasov 2014-04-28 14:19:22 +0200 253) if (!err)
75caeecdf9c71 (Maxim Patlasov 2014-04-28 14:19:22 +0200 254) fuse_finish_open(inode, file);
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 255)
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 256) out:
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 257) if (dax_truncate)
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 258) up_write(&get_fuse_inode(inode)->i_mmap_sem);
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 259)
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 260) if (is_wb_truncate | dax_truncate) {
e4648309b85a7 (Miklos Szeredi 2019-10-23 14:26:37 +0200 261) fuse_release_nowrite(inode);
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 262) inode_unlock(inode);
e4648309b85a7 (Miklos Szeredi 2019-10-23 14:26:37 +0200 263) }
75caeecdf9c71 (Maxim Patlasov 2014-04-28 14:19:22 +0200 264)
75caeecdf9c71 (Maxim Patlasov 2014-04-28 14:19:22 +0200 265) return err;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 266) }
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 267)
ebf84d0c7220c (Kirill Tkhai 2018-11-09 13:33:11 +0300 268) static void fuse_prepare_release(struct fuse_inode *fi, struct fuse_file *ff,
54d601cb67572 (Miklos Szeredi 2021-04-07 14:36:45 +0200 269) unsigned int flags, int opcode)
64c6d8ed4c55f (Miklos Szeredi 2006-01-16 22:14:42 -0800 270) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 271) struct fuse_conn *fc = ff->fm->fc;
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 272) struct fuse_release_args *ra = ff->release_args;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 273)
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 274) /* Inode is NULL on error path of fuse_create_open() */
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 275) if (likely(fi)) {
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 276) spin_lock(&fi->lock);
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 277) list_del(&ff->write_entry);
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 278) spin_unlock(&fi->lock);
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 279) }
8b0797a4984de (Miklos Szeredi 2009-04-28 16:56:39 +0200 280) spin_lock(&fc->lock);
8b0797a4984de (Miklos Szeredi 2009-04-28 16:56:39 +0200 281) if (!RB_EMPTY_NODE(&ff->polled_node))
8b0797a4984de (Miklos Szeredi 2009-04-28 16:56:39 +0200 282) rb_erase(&ff->polled_node, &fc->polled_files);
8b0797a4984de (Miklos Szeredi 2009-04-28 16:56:39 +0200 283) spin_unlock(&fc->lock);
8b0797a4984de (Miklos Szeredi 2009-04-28 16:56:39 +0200 284)
357ccf2b69bce (Bryan Green 2011-03-01 16:43:52 -0800 285) wake_up_interruptible_all(&ff->poll_wait);
8b0797a4984de (Miklos Szeredi 2009-04-28 16:56:39 +0200 286)
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 287) ra->inarg.fh = ff->fh;
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 288) ra->inarg.flags = flags;
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 289) ra->args.in_numargs = 1;
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 290) ra->args.in_args[0].size = sizeof(struct fuse_release_in);
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 291) ra->args.in_args[0].value = &ra->inarg;
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 292) ra->args.opcode = opcode;
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 293) ra->args.nodeid = ff->nodeid;
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 294) ra->args.force = true;
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 295) ra->args.nocreds = true;
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 296) }
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 297)
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 298) void fuse_file_release(struct inode *inode, struct fuse_file *ff,
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 299) unsigned int open_flags, fl_owner_t id, bool isdir)
fd72faac95d7e (Miklos Szeredi 2005-11-07 00:59:51 -0800 300) {
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 301) struct fuse_inode *fi = get_fuse_inode(inode);
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 302) struct fuse_release_args *ra = ff->release_args;
2e64ff154ce6c (Chad Austin 2018-12-10 10:54:52 -0800 303) int opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE;
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 304)
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 305) fuse_prepare_release(fi, ff, open_flags, opcode);
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 306)
37fb3a30b4623 (Miklos Szeredi 2011-08-08 16:08:08 +0200 307) if (ff->flock) {
4cb548666e4c1 (Miklos Szeredi 2019-09-10 15:04:10 +0200 308) ra->inarg.release_flags |= FUSE_RELEASE_FLOCK_UNLOCK;
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 309) ra->inarg.lock_owner = fuse_lock_owner_id(ff->fm->fc, id);
37fb3a30b4623 (Miklos Szeredi 2011-08-08 16:08:08 +0200 310) }
baebccbe997d5 (Miklos Szeredi 2014-12-12 09:49:04 +0100 311) /* Hold inode until release is finished */
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 312) ra->inode = igrab(inode);
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 313)
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 314) /*
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 315) * Normally this will send the RELEASE request, however if
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 316) * some asynchronous READ or WRITE requests are outstanding,
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 317) * the sending will be delayed.
5a18ec176c934 (Miklos Szeredi 2011-02-25 14:44:58 +0100 318) *
5a18ec176c934 (Miklos Szeredi 2011-02-25 14:44:58 +0100 319) * Make the release synchronous if this is a fuseblk mount,
5a18ec176c934 (Miklos Szeredi 2011-02-25 14:44:58 +0100 320) * synchronous RELEASE is allowed (and desirable) in this case
5a18ec176c934 (Miklos Szeredi 2011-02-25 14:44:58 +0100 321) * because the server can be trusted not to screw up.
6b2db28a7a2da (Tejun Heo 2009-04-14 10:54:49 +0900 322) */
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 323) fuse_file_put(ff, ff->fm->fc->destroy, isdir);
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 324) }
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 325)
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 326) void fuse_release_common(struct file *file, bool isdir)
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 327) {
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 328) fuse_file_release(file_inode(file), file->private_data, file->f_flags,
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 329) (fl_owner_t) file, isdir);
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 330) }
b9d54c6f29d9d (Miklos Szeredi 2021-04-07 14:36:45 +0200 331)
04730fef1f9c7 (Miklos Szeredi 2005-09-09 13:10:36 -0700 332) static int fuse_open(struct inode *inode, struct file *file)
04730fef1f9c7 (Miklos Szeredi 2005-09-09 13:10:36 -0700 333) {
91fe96b403f8a (Miklos Szeredi 2009-04-28 16:56:37 +0200 334) return fuse_open_common(inode, file, false);
04730fef1f9c7 (Miklos Szeredi 2005-09-09 13:10:36 -0700 335) }
04730fef1f9c7 (Miklos Szeredi 2005-09-09 13:10:36 -0700 336)
04730fef1f9c7 (Miklos Szeredi 2005-09-09 13:10:36 -0700 337) static int fuse_release(struct inode *inode, struct file *file)
04730fef1f9c7 (Miklos Szeredi 2005-09-09 13:10:36 -0700 338) {
e7cc133c370f5 (Pavel Emelyanov 2013-10-10 17:19:06 +0400 339) struct fuse_conn *fc = get_fuse_conn(inode);
e7cc133c370f5 (Pavel Emelyanov 2013-10-10 17:19:06 +0400 340)
e7cc133c370f5 (Pavel Emelyanov 2013-10-10 17:19:06 +0400 341) /* see fuse_vma_close() for !writeback_cache case */
e7cc133c370f5 (Pavel Emelyanov 2013-10-10 17:19:06 +0400 342) if (fc->writeback_cache)
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 343) write_inode_now(inode, 1);
b0aa760652179 (Maxim Patlasov 2013-12-26 19:51:11 +0400 344)
2e64ff154ce6c (Chad Austin 2018-12-10 10:54:52 -0800 345) fuse_release_common(file, false);
8b0797a4984de (Miklos Szeredi 2009-04-28 16:56:39 +0200 346)
8b0797a4984de (Miklos Szeredi 2009-04-28 16:56:39 +0200 347) /* return value is ignored by VFS */
8b0797a4984de (Miklos Szeredi 2009-04-28 16:56:39 +0200 348) return 0;
8b0797a4984de (Miklos Szeredi 2009-04-28 16:56:39 +0200 349) }
8b0797a4984de (Miklos Szeredi 2009-04-28 16:56:39 +0200 350)
54d601cb67572 (Miklos Szeredi 2021-04-07 14:36:45 +0200 351) void fuse_sync_release(struct fuse_inode *fi, struct fuse_file *ff,
54d601cb67572 (Miklos Szeredi 2021-04-07 14:36:45 +0200 352) unsigned int flags)
8b0797a4984de (Miklos Szeredi 2009-04-28 16:56:39 +0200 353) {
4e8c2eb54327a (Elena Reshetova 2017-03-03 11:04:03 +0200 354) WARN_ON(refcount_read(&ff->count) > 1);
ebf84d0c7220c (Kirill Tkhai 2018-11-09 13:33:11 +0300 355) fuse_prepare_release(fi, ff, flags, FUSE_RELEASE);
267d84449f523 (Miklos Szeredi 2017-02-22 20:08:25 +0100 356) /*
267d84449f523 (Miklos Szeredi 2017-02-22 20:08:25 +0100 357) * iput(NULL) is a no-op and since the refcount is 1 and everything's
267d84449f523 (Miklos Szeredi 2017-02-22 20:08:25 +0100 358) * synchronous, we are fine with not doing igrab() here"
267d84449f523 (Miklos Szeredi 2017-02-22 20:08:25 +0100 359) */
2e64ff154ce6c (Chad Austin 2018-12-10 10:54:52 -0800 360) fuse_file_put(ff, true, false);
04730fef1f9c7 (Miklos Szeredi 2005-09-09 13:10:36 -0700 361) }
08cbf542bf24f (Tejun Heo 2009-04-14 10:54:53 +0900 362) EXPORT_SYMBOL_GPL(fuse_sync_release);
04730fef1f9c7 (Miklos Szeredi 2005-09-09 13:10:36 -0700 363)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 364) /*
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 365) * Scramble the ID space with XTEA, so that the value of the files_struct
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 366) * pointer is not exposed to userspace.
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 367) */
f33321141b273 (Miklos Szeredi 2007-10-18 03:07:04 -0700 368) u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 369) {
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 370) u32 *k = fc->scramble_key;
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 371) u64 v = (unsigned long) id;
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 372) u32 v0 = v;
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 373) u32 v1 = v >> 32;
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 374) u32 sum = 0;
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 375) int i;
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 376)
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 377) for (i = 0; i < 32; i++) {
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 378) v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]);
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 379) sum += 0x9E3779B9;
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 380) v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum>>11 & 3]);
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 381) }
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 382)
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 383) return (u64) v0 + ((u64) v1 << 32);
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 384) }
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 385)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 386) struct fuse_writepage_args {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 387) struct fuse_io_args ia;
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 388) struct rb_node writepages_entry;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 389) struct list_head queue_entry;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 390) struct fuse_writepage_args *next;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 391) struct inode *inode;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 392) };
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 393)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 394) static struct fuse_writepage_args *fuse_find_writeback(struct fuse_inode *fi,
2fe93bd432642 (Miklos Szeredi 2019-01-16 10:27:59 +0100 395) pgoff_t idx_from, pgoff_t idx_to)
2fe93bd432642 (Miklos Szeredi 2019-01-16 10:27:59 +0100 396) {
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 397) struct rb_node *n;
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 398)
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 399) n = fi->writepages.rb_node;
2fe93bd432642 (Miklos Szeredi 2019-01-16 10:27:59 +0100 400)
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 401) while (n) {
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 402) struct fuse_writepage_args *wpa;
2fe93bd432642 (Miklos Szeredi 2019-01-16 10:27:59 +0100 403) pgoff_t curr_index;
2fe93bd432642 (Miklos Szeredi 2019-01-16 10:27:59 +0100 404)
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 405) wpa = rb_entry(n, struct fuse_writepage_args, writepages_entry);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 406) WARN_ON(get_fuse_inode(wpa->inode) != fi);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 407) curr_index = wpa->ia.write.in.offset >> PAGE_SHIFT;
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 408) if (idx_from >= curr_index + wpa->ia.ap.num_pages)
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 409) n = n->rb_right;
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 410) else if (idx_to < curr_index)
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 411) n = n->rb_left;
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 412) else
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 413) return wpa;
2fe93bd432642 (Miklos Szeredi 2019-01-16 10:27:59 +0100 414) }
2fe93bd432642 (Miklos Szeredi 2019-01-16 10:27:59 +0100 415) return NULL;
2fe93bd432642 (Miklos Szeredi 2019-01-16 10:27:59 +0100 416) }
2fe93bd432642 (Miklos Szeredi 2019-01-16 10:27:59 +0100 417)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 418) /*
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 419) * Check if any page in a range is under writeback
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 420) *
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 421) * This is currently done by walking the list of writepage requests
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 422) * for the inode, which can be pretty inefficient.
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 423) */
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 424) static bool fuse_range_is_writeback(struct inode *inode, pgoff_t idx_from,
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 425) pgoff_t idx_to)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 426) {
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 427) struct fuse_inode *fi = get_fuse_inode(inode);
2fe93bd432642 (Miklos Szeredi 2019-01-16 10:27:59 +0100 428) bool found;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 429)
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 430) spin_lock(&fi->lock);
2fe93bd432642 (Miklos Szeredi 2019-01-16 10:27:59 +0100 431) found = fuse_find_writeback(fi, idx_from, idx_to);
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 432) spin_unlock(&fi->lock);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 433)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 434) return found;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 435) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 436)
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 437) static inline bool fuse_page_is_writeback(struct inode *inode, pgoff_t index)
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 438) {
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 439) return fuse_range_is_writeback(inode, index, index);
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 440) }
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 441)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 442) /*
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 443) * Wait for page writeback to be completed.
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 444) *
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 445) * Since fuse doesn't rely on the VM writeback tracking, this has to
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 446) * use some other means.
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 447) */
17b2cbe294922 (Maxim Patlasov 2019-07-22 10:17:17 +0300 448) static void fuse_wait_on_page_writeback(struct inode *inode, pgoff_t index)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 449) {
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 450) struct fuse_inode *fi = get_fuse_inode(inode);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 451)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 452) wait_event(fi->page_waitq, !fuse_page_is_writeback(inode, index));
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 453) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 454)
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 455) /*
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 456) * Wait for all pending writepages on the inode to finish.
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 457) *
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 458) * This is currently done by blocking further writes with FUSE_NOWRITE
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 459) * and waiting for all sent writes to complete.
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 460) *
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 461) * This must be called under i_mutex, otherwise the FUSE_NOWRITE usage
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 462) * could conflict with truncation.
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 463) */
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 464) static void fuse_sync_writes(struct inode *inode)
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 465) {
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 466) fuse_set_nowrite(inode);
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 467) fuse_release_nowrite(inode);
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 468) }
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 469)
75e1fcc0b18df (Miklos Szeredi 2006-06-23 02:05:12 -0700 470) static int fuse_flush(struct file *file, fl_owner_t id)
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 471) {
6131ffaa1f091 (Al Viro 2013-02-27 16:59:05 -0500 472) struct inode *inode = file_inode(file);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 473) struct fuse_mount *fm = get_fuse_mount(inode);
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 474) struct fuse_file *ff = file->private_data;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 475) struct fuse_flush_in inarg;
c500ebaa908db (Miklos Szeredi 2019-09-10 15:04:08 +0200 476) FUSE_ARGS(args);
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 477) int err;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 478)
5d069dbe8aaf2 (Miklos Szeredi 2020-12-10 15:33:14 +0100 479) if (fuse_is_bad(inode))
248d86e87d12d (Miklos Szeredi 2006-01-06 00:19:39 -0800 480) return -EIO;
248d86e87d12d (Miklos Szeredi 2006-01-06 00:19:39 -0800 481)
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 482) err = write_inode_now(inode, 1);
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 483) if (err)
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 484) return err;
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 485)
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 486) inode_lock(inode);
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 487) fuse_sync_writes(inode);
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 488) inode_unlock(inode);
fe38d7df230b0 (Maxim Patlasov 2013-10-10 17:11:54 +0400 489)
4a7f4e88fef17 (Miklos Szeredi 2016-07-29 14:10:57 +0200 490) err = filemap_check_errors(file->f_mapping);
9ebce595f63a4 (Maxim Patlasov 2016-07-19 18:12:26 -0700 491) if (err)
9ebce595f63a4 (Maxim Patlasov 2016-07-19 18:12:26 -0700 492) return err;
9ebce595f63a4 (Maxim Patlasov 2016-07-19 18:12:26 -0700 493)
614c026e8a466 (Miklos Szeredi 2020-05-19 14:50:37 +0200 494) err = 0;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 495) if (fm->fc->no_flush)
614c026e8a466 (Miklos Szeredi 2020-05-19 14:50:37 +0200 496) goto inval_attr_out;
614c026e8a466 (Miklos Szeredi 2020-05-19 14:50:37 +0200 497)
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 498) memset(&inarg, 0, sizeof(inarg));
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 499) inarg.fh = ff->fh;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 500) inarg.lock_owner = fuse_lock_owner_id(fm->fc, id);
c500ebaa908db (Miklos Szeredi 2019-09-10 15:04:08 +0200 501) args.opcode = FUSE_FLUSH;
c500ebaa908db (Miklos Szeredi 2019-09-10 15:04:08 +0200 502) args.nodeid = get_node_id(inode);
c500ebaa908db (Miklos Szeredi 2019-09-10 15:04:08 +0200 503) args.in_numargs = 1;
c500ebaa908db (Miklos Szeredi 2019-09-10 15:04:08 +0200 504) args.in_args[0].size = sizeof(inarg);
c500ebaa908db (Miklos Szeredi 2019-09-10 15:04:08 +0200 505) args.in_args[0].value = &inarg;
c500ebaa908db (Miklos Szeredi 2019-09-10 15:04:08 +0200 506) args.force = true;
c500ebaa908db (Miklos Szeredi 2019-09-10 15:04:08 +0200 507)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 508) err = fuse_simple_request(fm, &args);
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 509) if (err == -ENOSYS) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 510) fm->fc->no_flush = 1;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 511) err = 0;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 512) }
cf576c58b3a28 (Eryu Guan 2020-05-12 10:29:04 +0800 513)
cf576c58b3a28 (Eryu Guan 2020-05-12 10:29:04 +0800 514) inval_attr_out:
cf576c58b3a28 (Eryu Guan 2020-05-12 10:29:04 +0800 515) /*
cf576c58b3a28 (Eryu Guan 2020-05-12 10:29:04 +0800 516) * In memory i_blocks is not maintained by fuse, if writeback cache is
cf576c58b3a28 (Eryu Guan 2020-05-12 10:29:04 +0800 517) * enabled, i_blocks from cached attr may not be accurate.
cf576c58b3a28 (Eryu Guan 2020-05-12 10:29:04 +0800 518) */
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 519) if (!err && fm->fc->writeback_cache)
cf576c58b3a28 (Eryu Guan 2020-05-12 10:29:04 +0800 520) fuse_invalidate_attr(inode);
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 521) return err;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 522) }
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 523)
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 524) int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
a9c2d1e82fc29 (Miklos Szeredi 2018-12-03 10:14:43 +0100 525) int datasync, int opcode)
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 526) {
7ea8085910ef3 (Christoph Hellwig 2010-05-26 17:53:25 +0200 527) struct inode *inode = file->f_mapping->host;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 528) struct fuse_mount *fm = get_fuse_mount(inode);
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 529) struct fuse_file *ff = file->private_data;
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 530) FUSE_ARGS(args);
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 531) struct fuse_fsync_in inarg;
a9c2d1e82fc29 (Miklos Szeredi 2018-12-03 10:14:43 +0100 532)
a9c2d1e82fc29 (Miklos Szeredi 2018-12-03 10:14:43 +0100 533) memset(&inarg, 0, sizeof(inarg));
a9c2d1e82fc29 (Miklos Szeredi 2018-12-03 10:14:43 +0100 534) inarg.fh = ff->fh;
154603fe3ec46 (Alan Somers 2019-04-19 15:42:44 -0600 535) inarg.fsync_flags = datasync ? FUSE_FSYNC_FDATASYNC : 0;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 536) args.opcode = opcode;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 537) args.nodeid = get_node_id(inode);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 538) args.in_numargs = 1;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 539) args.in_args[0].size = sizeof(inarg);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 540) args.in_args[0].value = &inarg;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 541) return fuse_simple_request(fm, &args);
a9c2d1e82fc29 (Miklos Szeredi 2018-12-03 10:14:43 +0100 542) }
a9c2d1e82fc29 (Miklos Szeredi 2018-12-03 10:14:43 +0100 543)
a9c2d1e82fc29 (Miklos Szeredi 2018-12-03 10:14:43 +0100 544) static int fuse_fsync(struct file *file, loff_t start, loff_t end,
a9c2d1e82fc29 (Miklos Szeredi 2018-12-03 10:14:43 +0100 545) int datasync)
a9c2d1e82fc29 (Miklos Szeredi 2018-12-03 10:14:43 +0100 546) {
a9c2d1e82fc29 (Miklos Szeredi 2018-12-03 10:14:43 +0100 547) struct inode *inode = file->f_mapping->host;
a9c2d1e82fc29 (Miklos Szeredi 2018-12-03 10:14:43 +0100 548) struct fuse_conn *fc = get_fuse_conn(inode);
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 549) int err;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 550)
5d069dbe8aaf2 (Miklos Szeredi 2020-12-10 15:33:14 +0100 551) if (fuse_is_bad(inode))
248d86e87d12d (Miklos Szeredi 2006-01-06 00:19:39 -0800 552) return -EIO;
248d86e87d12d (Miklos Szeredi 2006-01-06 00:19:39 -0800 553)
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 554) inode_lock(inode);
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 555)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 556) /*
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 557) * Start writeback against all dirty pages of the inode, then
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 558) * wait for all outstanding writes, before sending the FSYNC
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 559) * request.
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 560) */
7e51fe1dd180e (Jeff Layton 2017-07-22 09:27:43 -0400 561) err = file_write_and_wait_range(file, start, end);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 562) if (err)
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 563) goto out;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 564)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 565) fuse_sync_writes(inode);
ac7f052b9e153 (Alexey Kuznetsov 2016-07-19 12:48:01 -0700 566)
ac7f052b9e153 (Alexey Kuznetsov 2016-07-19 12:48:01 -0700 567) /*
ac7f052b9e153 (Alexey Kuznetsov 2016-07-19 12:48:01 -0700 568) * Due to implementation of fuse writeback
7e51fe1dd180e (Jeff Layton 2017-07-22 09:27:43 -0400 569) * file_write_and_wait_range() does not catch errors.
ac7f052b9e153 (Alexey Kuznetsov 2016-07-19 12:48:01 -0700 570) * We have to do this directly after fuse_sync_writes()
ac7f052b9e153 (Alexey Kuznetsov 2016-07-19 12:48:01 -0700 571) */
7e51fe1dd180e (Jeff Layton 2017-07-22 09:27:43 -0400 572) err = file_check_and_advance_wb_err(file);
ac7f052b9e153 (Alexey Kuznetsov 2016-07-19 12:48:01 -0700 573) if (err)
ac7f052b9e153 (Alexey Kuznetsov 2016-07-19 12:48:01 -0700 574) goto out;
ac7f052b9e153 (Alexey Kuznetsov 2016-07-19 12:48:01 -0700 575)
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 576) err = sync_inode_metadata(inode, 1);
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 577) if (err)
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 578) goto out;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 579)
a9c2d1e82fc29 (Miklos Szeredi 2018-12-03 10:14:43 +0100 580) if (fc->no_fsync)
22401e7b7a686 (Miklos Szeredi 2014-04-28 14:19:23 +0200 581) goto out;
b0aa760652179 (Maxim Patlasov 2013-12-26 19:51:11 +0400 582)
a9c2d1e82fc29 (Miklos Szeredi 2018-12-03 10:14:43 +0100 583) err = fuse_fsync_common(file, start, end, datasync, FUSE_FSYNC);
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 584) if (err == -ENOSYS) {
a9c2d1e82fc29 (Miklos Szeredi 2018-12-03 10:14:43 +0100 585) fc->no_fsync = 1;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 586) err = 0;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 587) }
02c24a82187d5 (Josef Bacik 2011-07-16 20:44:56 -0400 588) out:
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 589) inode_unlock(inode);
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 590)
a9c2d1e82fc29 (Miklos Szeredi 2018-12-03 10:14:43 +0100 591) return err;
8254798199332 (Miklos Szeredi 2005-09-09 13:10:38 -0700 592) }
8254798199332 (Miklos Szeredi 2005-09-09 13:10:38 -0700 593)
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 594) void fuse_read_args_fill(struct fuse_io_args *ia, struct file *file, loff_t pos,
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 595) size_t count, int opcode)
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 596) {
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 597) struct fuse_file *ff = file->private_data;
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 598) struct fuse_args *args = &ia->ap.args;
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 599)
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 600) ia->read.in.fh = ff->fh;
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 601) ia->read.in.offset = pos;
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 602) ia->read.in.size = count;
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 603) ia->read.in.flags = file->f_flags;
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 604) args->opcode = opcode;
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 605) args->nodeid = ff->nodeid;
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 606) args->in_numargs = 1;
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 607) args->in_args[0].size = sizeof(ia->read.in);
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 608) args->in_args[0].value = &ia->read.in;
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 609) args->out_argvar = true;
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 610) args->out_numargs = 1;
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 611) args->out_args[0].size = count;
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 612) }
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 613)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 614) static void fuse_release_user_pages(struct fuse_args_pages *ap,
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 615) bool should_dirty)
187c5c36330bc (Maxim Patlasov 2012-12-14 19:20:25 +0400 616) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 617) unsigned int i;
187c5c36330bc (Maxim Patlasov 2012-12-14 19:20:25 +0400 618)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 619) for (i = 0; i < ap->num_pages; i++) {
8fba54aebbdf1 (Miklos Szeredi 2016-08-24 18:17:04 +0200 620) if (should_dirty)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 621) set_page_dirty_lock(ap->pages[i]);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 622) put_page(ap->pages[i]);
187c5c36330bc (Maxim Patlasov 2012-12-14 19:20:25 +0400 623) }
187c5c36330bc (Maxim Patlasov 2012-12-14 19:20:25 +0400 624) }
187c5c36330bc (Maxim Patlasov 2012-12-14 19:20:25 +0400 625)
744742d692e37 (Seth Forshee 2016-03-11 10:35:34 -0600 626) static void fuse_io_release(struct kref *kref)
744742d692e37 (Seth Forshee 2016-03-11 10:35:34 -0600 627) {
744742d692e37 (Seth Forshee 2016-03-11 10:35:34 -0600 628) kfree(container_of(kref, struct fuse_io_priv, refcnt));
744742d692e37 (Seth Forshee 2016-03-11 10:35:34 -0600 629) }
744742d692e37 (Seth Forshee 2016-03-11 10:35:34 -0600 630)
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 631) static ssize_t fuse_get_res_by_io(struct fuse_io_priv *io)
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 632) {
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 633) if (io->err)
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 634) return io->err;
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 635)
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 636) if (io->bytes >= 0 && io->write)
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 637) return -EIO;
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 638)
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 639) return io->bytes < 0 ? io->size : io->bytes;
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 640) }
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 641)
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 642) /**
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 643) * In case of short read, the caller sets 'pos' to the position of
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 644) * actual end of fuse request in IO request. Otherwise, if bytes_requested
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 645) * == bytes_transferred or rw == WRITE, the caller sets 'pos' to -1.
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 646) *
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 647) * An example:
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 648) * User requested DIO read of 64K. It was splitted into two 32K fuse requests,
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 649) * both submitted asynchronously. The first of them was ACKed by userspace as
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 650) * fully completed (req->out.args[0].size == 32K) resulting in pos == -1. The
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 651) * second request was ACKed as short, e.g. only 1K was read, resulting in
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 652) * pos == 33K.
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 653) *
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 654) * Thus, when all fuse requests are completed, the minimal non-negative 'pos'
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 655) * will be equal to the length of the longest contiguous fragment of
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 656) * transferred data starting from the beginning of IO request.
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 657) */
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 658) static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos)
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 659) {
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 660) int left;
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 661)
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 662) spin_lock(&io->lock);
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 663) if (err)
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 664) io->err = io->err ? : err;
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 665) else if (pos >= 0 && (io->bytes < 0 || pos < io->bytes))
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 666) io->bytes = pos;
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 667)
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 668) left = --io->reqs;
7879c4e58b7c8 (Ashish Sangwan 2016-04-07 17:18:11 +0530 669) if (!left && io->blocking)
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 670) complete(io->done);
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 671) spin_unlock(&io->lock);
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 672)
7879c4e58b7c8 (Ashish Sangwan 2016-04-07 17:18:11 +0530 673) if (!left && !io->blocking) {
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 674) ssize_t res = fuse_get_res_by_io(io);
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 675)
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 676) if (res >= 0) {
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 677) struct inode *inode = file_inode(io->iocb->ki_filp);
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 678) struct fuse_conn *fc = get_fuse_conn(inode);
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 679) struct fuse_inode *fi = get_fuse_inode(inode);
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 680)
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 681) spin_lock(&fi->lock);
4510d86fbbb36 (Kirill Tkhai 2018-11-09 13:33:17 +0300 682) fi->attr_version = atomic64_inc_return(&fc->attr_version);
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 683) spin_unlock(&fi->lock);
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 684) }
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 685)
04b2fa9f8f36e (Christoph Hellwig 2015-02-02 14:49:06 +0100 686) io->iocb->ki_complete(io->iocb, res, 0);
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 687) }
744742d692e37 (Seth Forshee 2016-03-11 10:35:34 -0600 688)
744742d692e37 (Seth Forshee 2016-03-11 10:35:34 -0600 689) kref_put(&io->refcnt, fuse_io_release);
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 690) }
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 691)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 692) static struct fuse_io_args *fuse_io_alloc(struct fuse_io_priv *io,
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 693) unsigned int npages)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 694) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 695) struct fuse_io_args *ia;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 696)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 697) ia = kzalloc(sizeof(*ia), GFP_KERNEL);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 698) if (ia) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 699) ia->io = io;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 700) ia->ap.pages = fuse_pages_alloc(npages, GFP_KERNEL,
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 701) &ia->ap.descs);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 702) if (!ia->ap.pages) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 703) kfree(ia);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 704) ia = NULL;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 705) }
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 706) }
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 707) return ia;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 708) }
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 709)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 710) static void fuse_io_free(struct fuse_io_args *ia)
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 711) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 712) kfree(ia->ap.pages);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 713) kfree(ia);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 714) }
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 715)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 716) static void fuse_aio_complete_req(struct fuse_mount *fm, struct fuse_args *args,
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 717) int err)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 718) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 719) struct fuse_io_args *ia = container_of(args, typeof(*ia), ap.args);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 720) struct fuse_io_priv *io = ia->io;
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 721) ssize_t pos = -1;
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 722)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 723) fuse_release_user_pages(&ia->ap, io->should_dirty);
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 724)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 725) if (err) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 726) /* Nothing */
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 727) } else if (io->write) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 728) if (ia->write.out.size > ia->write.in.size) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 729) err = -EIO;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 730) } else if (ia->write.in.size != ia->write.out.size) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 731) pos = ia->write.in.offset - io->offset +
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 732) ia->write.out.size;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 733) }
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 734) } else {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 735) u32 outsize = args->out_args[0].size;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 736)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 737) if (ia->read.in.size != outsize)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 738) pos = ia->read.in.offset - io->offset + outsize;
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 739) }
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 740)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 741) fuse_aio_complete(io, err, pos);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 742) fuse_io_free(ia);
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 743) }
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 744)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 745) static ssize_t fuse_async_req_send(struct fuse_mount *fm,
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 746) struct fuse_io_args *ia, size_t num_bytes)
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 747) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 748) ssize_t err;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 749) struct fuse_io_priv *io = ia->io;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 750)
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 751) spin_lock(&io->lock);
744742d692e37 (Seth Forshee 2016-03-11 10:35:34 -0600 752) kref_get(&io->refcnt);
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 753) io->size += num_bytes;
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 754) io->reqs++;
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 755) spin_unlock(&io->lock);
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 756)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 757) ia->ap.args.end = fuse_aio_complete_req;
bb737bbe48bea (Vivek Goyal 2020-04-20 17:01:34 +0200 758) ia->ap.args.may_block = io->should_dirty;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 759) err = fuse_simple_background(fm, &ia->ap.args, GFP_KERNEL);
f1ebdeffc6f32 (Miklos Szeredi 2019-11-25 20:48:46 +0100 760) if (err)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 761) fuse_aio_complete_req(fm, &ia->ap.args, err);
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 762)
f1ebdeffc6f32 (Miklos Szeredi 2019-11-25 20:48:46 +0100 763) return num_bytes;
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 764) }
01e9d11a3e790 (Maxim Patlasov 2012-12-14 19:20:41 +0400 765)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 766) static ssize_t fuse_send_read(struct fuse_io_args *ia, loff_t pos, size_t count,
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 767) fl_owner_t owner)
04730fef1f9c7 (Miklos Szeredi 2005-09-09 13:10:36 -0700 768) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 769) struct file *file = ia->io->iocb->ki_filp;
2106cb1893031 (Miklos Szeredi 2009-04-28 16:56:37 +0200 770) struct fuse_file *ff = file->private_data;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 771) struct fuse_mount *fm = ff->fm;
f33321141b273 (Miklos Szeredi 2007-10-18 03:07:04 -0700 772)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 773) fuse_read_args_fill(ia, file, pos, count, FUSE_READ);
f33321141b273 (Miklos Szeredi 2007-10-18 03:07:04 -0700 774) if (owner != NULL) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 775) ia->read.in.read_flags |= FUSE_READ_LOCKOWNER;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 776) ia->read.in.lock_owner = fuse_lock_owner_id(fm->fc, owner);
f33321141b273 (Miklos Szeredi 2007-10-18 03:07:04 -0700 777) }
36cf66ed9f871 (Maxim Patlasov 2012-12-14 19:20:51 +0400 778)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 779) if (ia->io->async)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 780) return fuse_async_req_send(fm, ia, count);
36cf66ed9f871 (Maxim Patlasov 2012-12-14 19:20:51 +0400 781)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 782) return fuse_simple_request(fm, &ia->ap.args);
04730fef1f9c7 (Miklos Szeredi 2005-09-09 13:10:36 -0700 783) }
04730fef1f9c7 (Miklos Szeredi 2005-09-09 13:10:36 -0700 784)
5c5c5e51b2641 (Miklos Szeredi 2008-04-30 00:54:43 -0700 785) static void fuse_read_update_size(struct inode *inode, loff_t size,
5c5c5e51b2641 (Miklos Szeredi 2008-04-30 00:54:43 -0700 786) u64 attr_ver)
5c5c5e51b2641 (Miklos Szeredi 2008-04-30 00:54:43 -0700 787) {
5c5c5e51b2641 (Miklos Szeredi 2008-04-30 00:54:43 -0700 788) struct fuse_conn *fc = get_fuse_conn(inode);
5c5c5e51b2641 (Miklos Szeredi 2008-04-30 00:54:43 -0700 789) struct fuse_inode *fi = get_fuse_inode(inode);
5c5c5e51b2641 (Miklos Szeredi 2008-04-30 00:54:43 -0700 790)
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 791) spin_lock(&fi->lock);
06a7c3c278140 (Maxim Patlasov 2013-08-30 17:06:04 +0400 792) if (attr_ver == fi->attr_version && size < inode->i_size &&
06a7c3c278140 (Maxim Patlasov 2013-08-30 17:06:04 +0400 793) !test_bit(FUSE_I_SIZE_UNSTABLE, &fi->state)) {
4510d86fbbb36 (Kirill Tkhai 2018-11-09 13:33:17 +0300 794) fi->attr_version = atomic64_inc_return(&fc->attr_version);
5c5c5e51b2641 (Miklos Szeredi 2008-04-30 00:54:43 -0700 795) i_size_write(inode, size);
5c5c5e51b2641 (Miklos Szeredi 2008-04-30 00:54:43 -0700 796) }
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 797) spin_unlock(&fi->lock);
5c5c5e51b2641 (Miklos Szeredi 2008-04-30 00:54:43 -0700 798) }
5c5c5e51b2641 (Miklos Szeredi 2008-04-30 00:54:43 -0700 799)
a0d45d84f4c9d (Miklos Szeredi 2019-09-10 15:04:09 +0200 800) static void fuse_short_read(struct inode *inode, u64 attr_ver, size_t num_read,
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 801) struct fuse_args_pages *ap)
a92adc824ed5f (Pavel Emelyanov 2013-10-10 17:10:16 +0400 802) {
8373200b124d0 (Pavel Emelyanov 2013-10-10 17:10:46 +0400 803) struct fuse_conn *fc = get_fuse_conn(inode);
8373200b124d0 (Pavel Emelyanov 2013-10-10 17:10:46 +0400 804)
a73d47f57792d (Miklos Szeredi 2021-04-14 10:40:56 +0200 805) /*
a73d47f57792d (Miklos Szeredi 2021-04-14 10:40:56 +0200 806) * If writeback_cache is enabled, a short read means there's a hole in
a73d47f57792d (Miklos Szeredi 2021-04-14 10:40:56 +0200 807) * the file. Some data after the hole is in page cache, but has not
a73d47f57792d (Miklos Szeredi 2021-04-14 10:40:56 +0200 808) * reached the client fs yet. So the hole is not present there.
a73d47f57792d (Miklos Szeredi 2021-04-14 10:40:56 +0200 809) */
a73d47f57792d (Miklos Szeredi 2021-04-14 10:40:56 +0200 810) if (!fc->writeback_cache) {
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 811) loff_t pos = page_offset(ap->pages[0]) + num_read;
8373200b124d0 (Pavel Emelyanov 2013-10-10 17:10:46 +0400 812) fuse_read_update_size(inode, pos, attr_ver);
8373200b124d0 (Pavel Emelyanov 2013-10-10 17:10:46 +0400 813) }
a92adc824ed5f (Pavel Emelyanov 2013-10-10 17:10:16 +0400 814) }
a92adc824ed5f (Pavel Emelyanov 2013-10-10 17:10:16 +0400 815)
482fce55d2809 (Maxim Patlasov 2013-10-10 17:11:25 +0400 816) static int fuse_do_readpage(struct file *file, struct page *page)
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 817) {
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 818) struct inode *inode = page->mapping->host;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 819) struct fuse_mount *fm = get_fuse_mount(inode);
5c5c5e51b2641 (Miklos Szeredi 2008-04-30 00:54:43 -0700 820) loff_t pos = page_offset(page);
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 821) struct fuse_page_desc desc = { .length = PAGE_SIZE };
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 822) struct fuse_io_args ia = {
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 823) .ap.args.page_zeroing = true,
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 824) .ap.args.out_pages = true,
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 825) .ap.num_pages = 1,
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 826) .ap.pages = &page,
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 827) .ap.descs = &desc,
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 828) };
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 829) ssize_t res;
5c5c5e51b2641 (Miklos Szeredi 2008-04-30 00:54:43 -0700 830) u64 attr_ver;
248d86e87d12d (Miklos Szeredi 2006-01-06 00:19:39 -0800 831)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 832) /*
25985edcedea6 (Lucas De Marchi 2011-03-30 22:57:33 -0300 833) * Page writeback can extend beyond the lifetime of the
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 834) * page-cache page, so make sure we read a properly synced
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 835) * page.
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 836) */
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 837) fuse_wait_on_page_writeback(inode, page->index);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 838)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 839) attr_ver = fuse_get_attr_version(fm->fc);
5c5c5e51b2641 (Miklos Szeredi 2008-04-30 00:54:43 -0700 840)
2f1398291bf35 (Miklos Szeredi 2020-02-06 16:39:28 +0100 841) /* Don't overflow end offset */
2f1398291bf35 (Miklos Szeredi 2020-02-06 16:39:28 +0100 842) if (pos + (desc.length - 1) == LLONG_MAX)
2f1398291bf35 (Miklos Szeredi 2020-02-06 16:39:28 +0100 843) desc.length--;
2f1398291bf35 (Miklos Szeredi 2020-02-06 16:39:28 +0100 844)
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 845) fuse_read_args_fill(&ia, file, pos, desc.length, FUSE_READ);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 846) res = fuse_simple_request(fm, &ia.ap.args);
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 847) if (res < 0)
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 848) return res;
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 849) /*
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 850) * Short read means EOF. If file size is larger, truncate it
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 851) */
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 852) if (res < desc.length)
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 853) fuse_short_read(inode, attr_ver, res, &ia.ap);
5c5c5e51b2641 (Miklos Szeredi 2008-04-30 00:54:43 -0700 854)
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 855) SetPageUptodate(page);
482fce55d2809 (Maxim Patlasov 2013-10-10 17:11:25 +0400 856)
00793ca5d4439 (Miklos Szeredi 2019-09-10 15:04:09 +0200 857) return 0;
482fce55d2809 (Maxim Patlasov 2013-10-10 17:11:25 +0400 858) }
482fce55d2809 (Maxim Patlasov 2013-10-10 17:11:25 +0400 859)
482fce55d2809 (Maxim Patlasov 2013-10-10 17:11:25 +0400 860) static int fuse_readpage(struct file *file, struct page *page)
482fce55d2809 (Maxim Patlasov 2013-10-10 17:11:25 +0400 861) {
482fce55d2809 (Maxim Patlasov 2013-10-10 17:11:25 +0400 862) struct inode *inode = page->mapping->host;
482fce55d2809 (Maxim Patlasov 2013-10-10 17:11:25 +0400 863) int err;
482fce55d2809 (Maxim Patlasov 2013-10-10 17:11:25 +0400 864)
482fce55d2809 (Maxim Patlasov 2013-10-10 17:11:25 +0400 865) err = -EIO;
5d069dbe8aaf2 (Miklos Szeredi 2020-12-10 15:33:14 +0100 866) if (fuse_is_bad(inode))
482fce55d2809 (Maxim Patlasov 2013-10-10 17:11:25 +0400 867) goto out;
482fce55d2809 (Maxim Patlasov 2013-10-10 17:11:25 +0400 868)
482fce55d2809 (Maxim Patlasov 2013-10-10 17:11:25 +0400 869) err = fuse_do_readpage(file, page);
451418fc928b5 (Andrew Gallagher 2013-11-05 03:55:43 -0800 870) fuse_invalidate_atime(inode);
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 871) out:
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 872) unlock_page(page);
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 873) return err;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 874) }
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 875)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 876) static void fuse_readpages_end(struct fuse_mount *fm, struct fuse_args *args,
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 877) int err)
db50b96c0f28a (Miklos Szeredi 2005-09-09 13:10:33 -0700 878) {
c1aa96a52e959 (Miklos Szeredi 2006-01-16 22:14:46 -0800 879) int i;
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 880) struct fuse_io_args *ia = container_of(args, typeof(*ia), ap.args);
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 881) struct fuse_args_pages *ap = &ia->ap;
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 882) size_t count = ia->read.in.size;
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 883) size_t num_read = args->out_args[0].size;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 884) struct address_space *mapping = NULL;
c1aa96a52e959 (Miklos Szeredi 2006-01-16 22:14:46 -0800 885)
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 886) for (i = 0; mapping == NULL && i < ap->num_pages; i++)
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 887) mapping = ap->pages[i]->mapping;
5c5c5e51b2641 (Miklos Szeredi 2008-04-30 00:54:43 -0700 888)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 889) if (mapping) {
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 890) struct inode *inode = mapping->host;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 891)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 892) /*
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 893) * Short read means EOF. If file size is larger, truncate it
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 894) */
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 895) if (!err && num_read < count)
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 896) fuse_short_read(inode, ia->read.attr_ver, num_read, ap);
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 897)
451418fc928b5 (Andrew Gallagher 2013-11-05 03:55:43 -0800 898) fuse_invalidate_atime(inode);
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 899) }
c1aa96a52e959 (Miklos Szeredi 2006-01-16 22:14:46 -0800 900)
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 901) for (i = 0; i < ap->num_pages; i++) {
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 902) struct page *page = ap->pages[i];
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 903)
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 904) if (!err)
db50b96c0f28a (Miklos Szeredi 2005-09-09 13:10:33 -0700 905) SetPageUptodate(page);
c1aa96a52e959 (Miklos Szeredi 2006-01-16 22:14:46 -0800 906) else
c1aa96a52e959 (Miklos Szeredi 2006-01-16 22:14:46 -0800 907) SetPageError(page);
db50b96c0f28a (Miklos Szeredi 2005-09-09 13:10:33 -0700 908) unlock_page(page);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 909) put_page(page);
db50b96c0f28a (Miklos Szeredi 2005-09-09 13:10:33 -0700 910) }
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 911) if (ia->ff)
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 912) fuse_file_put(ia->ff, false, false);
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 913)
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 914) fuse_io_free(ia);
c1aa96a52e959 (Miklos Szeredi 2006-01-16 22:14:46 -0800 915) }
c1aa96a52e959 (Miklos Szeredi 2006-01-16 22:14:46 -0800 916)
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 917) static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file)
c1aa96a52e959 (Miklos Szeredi 2006-01-16 22:14:46 -0800 918) {
2106cb1893031 (Miklos Szeredi 2009-04-28 16:56:37 +0200 919) struct fuse_file *ff = file->private_data;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 920) struct fuse_mount *fm = ff->fm;
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 921) struct fuse_args_pages *ap = &ia->ap;
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 922) loff_t pos = page_offset(ap->pages[0]);
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 923) size_t count = ap->num_pages << PAGE_SHIFT;
7df1e988c723a (Miklos Szeredi 2020-01-16 11:09:36 +0100 924) ssize_t res;
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 925) int err;
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 926)
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 927) ap->args.out_pages = true;
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 928) ap->args.page_zeroing = true;
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 929) ap->args.page_replace = true;
2f1398291bf35 (Miklos Szeredi 2020-02-06 16:39:28 +0100 930)
2f1398291bf35 (Miklos Szeredi 2020-02-06 16:39:28 +0100 931) /* Don't overflow end offset */
2f1398291bf35 (Miklos Szeredi 2020-02-06 16:39:28 +0100 932) if (pos + (count - 1) == LLONG_MAX) {
2f1398291bf35 (Miklos Szeredi 2020-02-06 16:39:28 +0100 933) count--;
2f1398291bf35 (Miklos Szeredi 2020-02-06 16:39:28 +0100 934) ap->descs[ap->num_pages - 1].length--;
2f1398291bf35 (Miklos Szeredi 2020-02-06 16:39:28 +0100 935) }
2f1398291bf35 (Miklos Szeredi 2020-02-06 16:39:28 +0100 936) WARN_ON((loff_t) (pos + count) < 0);
2f1398291bf35 (Miklos Szeredi 2020-02-06 16:39:28 +0100 937)
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 938) fuse_read_args_fill(ia, file, pos, count, FUSE_READ);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 939) ia->read.attr_ver = fuse_get_attr_version(fm->fc);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 940) if (fm->fc->async_read) {
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 941) ia->ff = fuse_file_get(ff);
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 942) ap->args.end = fuse_readpages_end;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 943) err = fuse_simple_background(fm, &ap->args, GFP_KERNEL);
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 944) if (!err)
134831e36bbdd (Miklos Szeredi 2019-09-10 15:04:10 +0200 945) return;
9cd684551124e (Miklos Szeredi 2006-02-01 03:04:40 -0800 946) } else {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 947) res = fuse_simple_request(fm, &ap->args);
7df1e988c723a (Miklos Szeredi 2020-01-16 11:09:36 +0100 948) err = res < 0 ? res : 0;
9cd684551124e (Miklos Szeredi 2006-02-01 03:04:40 -0800 949) }
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 950) fuse_readpages_end(fm, &ap->args, err);
db50b96c0f28a (Miklos Szeredi 2005-09-09 13:10:33 -0700 951) }
db50b96c0f28a (Miklos Szeredi 2005-09-09 13:10:33 -0700 952)
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 953) static void fuse_readahead(struct readahead_control *rac)
db50b96c0f28a (Miklos Szeredi 2005-09-09 13:10:33 -0700 954) {
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 955) struct inode *inode = rac->mapping->host;
db50b96c0f28a (Miklos Szeredi 2005-09-09 13:10:33 -0700 956) struct fuse_conn *fc = get_fuse_conn(inode);
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 957) unsigned int i, max_pages, nr_pages = 0;
db50b96c0f28a (Miklos Szeredi 2005-09-09 13:10:33 -0700 958)
5d069dbe8aaf2 (Miklos Szeredi 2020-12-10 15:33:14 +0100 959) if (fuse_is_bad(inode))
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 960) return;
248d86e87d12d (Miklos Szeredi 2006-01-06 00:19:39 -0800 961)
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 962) max_pages = min_t(unsigned int, fc->max_pages,
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 963) fc->max_read / PAGE_SIZE);
db50b96c0f28a (Miklos Szeredi 2005-09-09 13:10:33 -0700 964)
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 965) for (;;) {
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 966) struct fuse_io_args *ia;
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 967) struct fuse_args_pages *ap;
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 968)
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 969) nr_pages = readahead_count(rac) - nr_pages;
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 970) if (nr_pages > max_pages)
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 971) nr_pages = max_pages;
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 972) if (nr_pages == 0)
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 973) break;
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 974) ia = fuse_io_alloc(NULL, nr_pages);
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 975) if (!ia)
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 976) return;
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 977) ap = &ia->ap;
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 978) nr_pages = __readahead_batch(rac, ap->pages, nr_pages);
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 979) for (i = 0; i < nr_pages; i++) {
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 980) fuse_wait_on_page_writeback(inode,
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 981) readahead_index(rac) + i);
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 982) ap->descs[i].length = PAGE_SIZE;
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 983) }
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 984) ap->num_pages = nr_pages;
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 985) fuse_send_readpages(ia, rac->file);
d3406ffa4af8a (Miklos Szeredi 2006-04-10 22:54:49 -0700 986) }
db50b96c0f28a (Miklos Szeredi 2005-09-09 13:10:33 -0700 987) }
db50b96c0f28a (Miklos Szeredi 2005-09-09 13:10:33 -0700 988)
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 989) static ssize_t fuse_cache_read_iter(struct kiocb *iocb, struct iov_iter *to)
bcb4be809d2a8 (Miklos Szeredi 2007-11-28 16:21:59 -0800 990) {
bcb4be809d2a8 (Miklos Szeredi 2007-11-28 16:21:59 -0800 991) struct inode *inode = iocb->ki_filp->f_mapping->host;
a8894274a3581 (Brian Foster 2012-07-16 15:23:50 -0400 992) struct fuse_conn *fc = get_fuse_conn(inode);
bcb4be809d2a8 (Miklos Szeredi 2007-11-28 16:21:59 -0800 993)
a8894274a3581 (Brian Foster 2012-07-16 15:23:50 -0400 994) /*
a8894274a3581 (Brian Foster 2012-07-16 15:23:50 -0400 995) * In auto invalidate mode, always update attributes on read.
a8894274a3581 (Brian Foster 2012-07-16 15:23:50 -0400 996) * Otherwise, only update if we attempt to read past EOF (to ensure
a8894274a3581 (Brian Foster 2012-07-16 15:23:50 -0400 997) * i_size is up to date).
a8894274a3581 (Brian Foster 2012-07-16 15:23:50 -0400 998) */
a8894274a3581 (Brian Foster 2012-07-16 15:23:50 -0400 999) if (fc->auto_inval_data ||
37c20f16e7a73 (Al Viro 2014-04-02 14:47:09 -0400 1000) (iocb->ki_pos + iov_iter_count(to) > i_size_read(inode))) {
bcb4be809d2a8 (Miklos Szeredi 2007-11-28 16:21:59 -0800 1001) int err;
5b97eeacbd80a (Miklos Szeredi 2017-09-12 16:57:54 +0200 1002) err = fuse_update_attributes(inode, iocb->ki_filp);
bcb4be809d2a8 (Miklos Szeredi 2007-11-28 16:21:59 -0800 1003) if (err)
bcb4be809d2a8 (Miklos Szeredi 2007-11-28 16:21:59 -0800 1004) return err;
bcb4be809d2a8 (Miklos Szeredi 2007-11-28 16:21:59 -0800 1005) }
bcb4be809d2a8 (Miklos Szeredi 2007-11-28 16:21:59 -0800 1006)
37c20f16e7a73 (Al Viro 2014-04-02 14:47:09 -0400 1007) return generic_file_read_iter(iocb, to);
bcb4be809d2a8 (Miklos Szeredi 2007-11-28 16:21:59 -0800 1008) }
bcb4be809d2a8 (Miklos Szeredi 2007-11-28 16:21:59 -0800 1009)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1010) static void fuse_write_args_fill(struct fuse_io_args *ia, struct fuse_file *ff,
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1011) loff_t pos, size_t count)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1012) {
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1013) struct fuse_args *args = &ia->ap.args;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1014)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1015) ia->write.in.fh = ff->fh;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1016) ia->write.in.offset = pos;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1017) ia->write.in.size = count;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1018) args->opcode = FUSE_WRITE;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1019) args->nodeid = ff->nodeid;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1020) args->in_numargs = 2;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1021) if (ff->fm->fc->minor < 9)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1022) args->in_args[0].size = FUSE_COMPAT_WRITE_IN_SIZE;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1023) else
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1024) args->in_args[0].size = sizeof(ia->write.in);
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1025) args->in_args[0].value = &ia->write.in;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1026) args->in_args[1].size = count;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1027) args->out_numargs = 1;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1028) args->out_args[0].size = sizeof(ia->write.out);
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1029) args->out_args[0].value = &ia->write.out;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1030) }
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1031)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1032) static unsigned int fuse_write_flags(struct kiocb *iocb)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1033) {
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1034) unsigned int flags = iocb->ki_filp->f_flags;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1035)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1036) if (iocb->ki_flags & IOCB_DSYNC)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1037) flags |= O_DSYNC;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1038) if (iocb->ki_flags & IOCB_SYNC)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1039) flags |= O_SYNC;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1040)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1041) return flags;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1042) }
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1043)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1044) static ssize_t fuse_send_write(struct fuse_io_args *ia, loff_t pos,
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1045) size_t count, fl_owner_t owner)
b25e82e5673c7 (Miklos Szeredi 2007-10-18 03:07:03 -0700 1046) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1047) struct kiocb *iocb = ia->io->iocb;
e1c0eecba1a41 (Miklos Szeredi 2017-09-12 16:57:53 +0200 1048) struct file *file = iocb->ki_filp;
2106cb1893031 (Miklos Szeredi 2009-04-28 16:56:37 +0200 1049) struct fuse_file *ff = file->private_data;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1050) struct fuse_mount *fm = ff->fm;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1051) struct fuse_write_in *inarg = &ia->write.in;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1052) ssize_t err;
2d698b0703824 (Miklos Szeredi 2009-04-28 16:56:36 +0200 1053)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1054) fuse_write_args_fill(ia, ff, pos, count);
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1055) inarg->flags = fuse_write_flags(iocb);
f33321141b273 (Miklos Szeredi 2007-10-18 03:07:04 -0700 1056) if (owner != NULL) {
f33321141b273 (Miklos Szeredi 2007-10-18 03:07:04 -0700 1057) inarg->write_flags |= FUSE_WRITE_LOCKOWNER;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1058) inarg->lock_owner = fuse_lock_owner_id(fm->fc, owner);
f33321141b273 (Miklos Szeredi 2007-10-18 03:07:04 -0700 1059) }
36cf66ed9f871 (Maxim Patlasov 2012-12-14 19:20:51 +0400 1060)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1061) if (ia->io->async)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1062) return fuse_async_req_send(fm, ia, count);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1063)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1064) err = fuse_simple_request(fm, &ia->ap.args);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1065) if (!err && ia->write.out.size > count)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1066) err = -EIO;
36cf66ed9f871 (Maxim Patlasov 2012-12-14 19:20:51 +0400 1067)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1068) return err ?: ia->write.out.size;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 1069) }
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 1070)
b0aa760652179 (Maxim Patlasov 2013-12-26 19:51:11 +0400 1071) bool fuse_write_update_size(struct inode *inode, loff_t pos)
854512ec358f2 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1072) {
854512ec358f2 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1073) struct fuse_conn *fc = get_fuse_conn(inode);
854512ec358f2 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1074) struct fuse_inode *fi = get_fuse_inode(inode);
b0aa760652179 (Maxim Patlasov 2013-12-26 19:51:11 +0400 1075) bool ret = false;
854512ec358f2 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1076)
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1077) spin_lock(&fi->lock);
4510d86fbbb36 (Kirill Tkhai 2018-11-09 13:33:17 +0300 1078) fi->attr_version = atomic64_inc_return(&fc->attr_version);
b0aa760652179 (Maxim Patlasov 2013-12-26 19:51:11 +0400 1079) if (pos > inode->i_size) {
854512ec358f2 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1080) i_size_write(inode, pos);
b0aa760652179 (Maxim Patlasov 2013-12-26 19:51:11 +0400 1081) ret = true;
b0aa760652179 (Maxim Patlasov 2013-12-26 19:51:11 +0400 1082) }
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1083) spin_unlock(&fi->lock);
b0aa760652179 (Maxim Patlasov 2013-12-26 19:51:11 +0400 1084)
b0aa760652179 (Maxim Patlasov 2013-12-26 19:51:11 +0400 1085) return ret;
854512ec358f2 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1086) }
854512ec358f2 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1087)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1088) static ssize_t fuse_send_write_pages(struct fuse_io_args *ia,
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1089) struct kiocb *iocb, struct inode *inode,
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1090) loff_t pos, size_t count)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1091) {
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1092) struct fuse_args_pages *ap = &ia->ap;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1093) struct file *file = iocb->ki_filp;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1094) struct fuse_file *ff = file->private_data;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1095) struct fuse_mount *fm = ff->fm;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1096) unsigned int offset, i;
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1097) bool short_write;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1098) int err;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1099)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1100) for (i = 0; i < ap->num_pages; i++)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1101) fuse_wait_on_page_writeback(inode, ap->pages[i]->index);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1102)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1103) fuse_write_args_fill(ia, ff, pos, count);
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1104) ia->write.in.flags = fuse_write_flags(iocb);
b866739596ae3 (Vivek Goyal 2020-10-09 14:15:08 -0400 1105) if (fm->fc->handle_killpriv_v2 && !capable(CAP_FSETID))
b866739596ae3 (Vivek Goyal 2020-10-09 14:15:08 -0400 1106) ia->write.in.write_flags |= FUSE_WRITE_KILL_SUIDGID;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1107)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1108) err = fuse_simple_request(fm, &ap->args);
8aab336b14c11 (Miklos Szeredi 2019-11-12 11:49:04 +0100 1109) if (!err && ia->write.out.size > count)
8aab336b14c11 (Miklos Szeredi 2019-11-12 11:49:04 +0100 1110) err = -EIO;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1111)
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1112) short_write = ia->write.out.size < count;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1113) offset = ap->descs[0].offset;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1114) count = ia->write.out.size;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1115) for (i = 0; i < ap->num_pages; i++) {
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1116) struct page *page = ap->pages[i];
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1117)
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1118) if (err) {
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1119) ClearPageUptodate(page);
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1120) } else {
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1121) if (count >= PAGE_SIZE - offset)
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1122) count -= PAGE_SIZE - offset;
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1123) else {
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1124) if (short_write)
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1125) ClearPageUptodate(page);
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1126) count = 0;
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1127) }
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1128) offset = 0;
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1129) }
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1130) if (ia->write.page_locked && (i == ap->num_pages - 1))
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1131) unlock_page(page);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1132) put_page(page);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1133) }
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1134)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1135) return err;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1136) }
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1137)
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1138) static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia,
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1139) struct address_space *mapping,
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1140) struct iov_iter *ii, loff_t pos,
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1141) unsigned int max_pages)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1142) {
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1143) struct fuse_args_pages *ap = &ia->ap;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1144) struct fuse_conn *fc = get_fuse_conn(mapping->host);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1145) unsigned offset = pos & (PAGE_SIZE - 1);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1146) size_t count = 0;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1147) int err;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1148)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1149) ap->args.in_pages = true;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1150) ap->descs[0].offset = offset;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1151)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1152) do {
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1153) size_t tmp;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1154) struct page *page;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1155) pgoff_t index = pos >> PAGE_SHIFT;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1156) size_t bytes = min_t(size_t, PAGE_SIZE - offset,
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1157) iov_iter_count(ii));
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1158)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1159) bytes = min_t(size_t, bytes, fc->max_write - count);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1160)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1161) again:
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1162) err = -EFAULT;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1163) if (iov_iter_fault_in_readable(ii, bytes))
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1164) break;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1165)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1166) err = -ENOMEM;
54566b2c1594c (Nicholas Piggin 2009-01-04 12:00:53 -0800 1167) page = grab_cache_page_write_begin(mapping, index, 0);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1168) if (!page)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1169) break;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1170)
931e80e4b3263 (anfei zhou 2010-02-02 13:44:02 -0800 1171) if (mapping_writably_mapped(mapping))
931e80e4b3263 (anfei zhou 2010-02-02 13:44:02 -0800 1172) flush_dcache_page(page);
931e80e4b3263 (anfei zhou 2010-02-02 13:44:02 -0800 1173)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1174) tmp = iov_iter_copy_from_user_atomic(page, ii, offset, bytes);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1175) flush_dcache_page(page);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1176)
3ca8138f014a9 (Roman Gushchin 2015-10-12 16:33:44 +0300 1177) iov_iter_advance(ii, tmp);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1178) if (!tmp) {
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1179) unlock_page(page);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1180) put_page(page);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1181) bytes = min(bytes, iov_iter_single_seg_count(ii));
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1182) goto again;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1183) }
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1184)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1185) err = 0;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1186) ap->pages[ap->num_pages] = page;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1187) ap->descs[ap->num_pages].length = tmp;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1188) ap->num_pages++;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1189)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1190) count += tmp;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1191) pos += tmp;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1192) offset += tmp;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1193) if (offset == PAGE_SIZE)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1194) offset = 0;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1195)
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1196) /* If we copied full page, mark it uptodate */
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1197) if (tmp == PAGE_SIZE)
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1198) SetPageUptodate(page);
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1199)
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1200) if (PageUptodate(page)) {
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1201) unlock_page(page);
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1202) } else {
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1203) ia->write.page_locked = true;
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1204) break;
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1205) }
78bb6cb9a890d (Miklos Szeredi 2008-05-12 14:02:32 -0700 1206) if (!fc->big_writes)
78bb6cb9a890d (Miklos Szeredi 2008-05-12 14:02:32 -0700 1207) break;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1208) } while (iov_iter_count(ii) && count < fc->max_write &&
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1209) ap->num_pages < max_pages && offset == 0);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1210)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1211) return count > 0 ? count : err;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1212) }
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1213)
5da784cce4308 (Constantine Shulyupin 2018-09-06 15:37:06 +0300 1214) static inline unsigned int fuse_wr_pages(loff_t pos, size_t len,
5da784cce4308 (Constantine Shulyupin 2018-09-06 15:37:06 +0300 1215) unsigned int max_pages)
d07f09f509fb2 (Maxim Patlasov 2012-10-26 19:49:00 +0400 1216) {
5da784cce4308 (Constantine Shulyupin 2018-09-06 15:37:06 +0300 1217) return min_t(unsigned int,
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1218) ((pos + len - 1) >> PAGE_SHIFT) -
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1219) (pos >> PAGE_SHIFT) + 1,
5da784cce4308 (Constantine Shulyupin 2018-09-06 15:37:06 +0300 1220) max_pages);
d07f09f509fb2 (Maxim Patlasov 2012-10-26 19:49:00 +0400 1221) }
d07f09f509fb2 (Maxim Patlasov 2012-10-26 19:49:00 +0400 1222)
e1c0eecba1a41 (Miklos Szeredi 2017-09-12 16:57:53 +0200 1223) static ssize_t fuse_perform_write(struct kiocb *iocb,
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1224) struct address_space *mapping,
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1225) struct iov_iter *ii, loff_t pos)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1226) {
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1227) struct inode *inode = mapping->host;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1228) struct fuse_conn *fc = get_fuse_conn(inode);
06a7c3c278140 (Maxim Patlasov 2013-08-30 17:06:04 +0400 1229) struct fuse_inode *fi = get_fuse_inode(inode);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1230) int err = 0;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1231) ssize_t res = 0;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1232)
06a7c3c278140 (Maxim Patlasov 2013-08-30 17:06:04 +0400 1233) if (inode->i_size < pos + iov_iter_count(ii))
06a7c3c278140 (Maxim Patlasov 2013-08-30 17:06:04 +0400 1234) set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
06a7c3c278140 (Maxim Patlasov 2013-08-30 17:06:04 +0400 1235)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1236) do {
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1237) ssize_t count;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1238) struct fuse_io_args ia = {};
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1239) struct fuse_args_pages *ap = &ia.ap;
5da784cce4308 (Constantine Shulyupin 2018-09-06 15:37:06 +0300 1240) unsigned int nr_pages = fuse_wr_pages(pos, iov_iter_count(ii),
5da784cce4308 (Constantine Shulyupin 2018-09-06 15:37:06 +0300 1241) fc->max_pages);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1242)
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1243) ap->pages = fuse_pages_alloc(nr_pages, GFP_KERNEL, &ap->descs);
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1244) if (!ap->pages) {
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1245) err = -ENOMEM;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1246) break;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1247) }
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1248)
4f06dd92b5d0a (Vivek Goyal 2020-10-21 16:12:49 -0400 1249) count = fuse_fill_write_pages(&ia, mapping, ii, pos, nr_pages);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1250) if (count <= 0) {
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1251) err = count;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1252) } else {
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1253) err = fuse_send_write_pages(&ia, iocb, inode,
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1254) pos, count);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1255) if (!err) {
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1256) size_t num_written = ia.write.out.size;
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1257)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1258) res += num_written;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1259) pos += num_written;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1260)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1261) /* break out of the loop on short write */
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1262) if (num_written != count)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1263) err = -EIO;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1264) }
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1265) }
338f2e3f3341a (Miklos Szeredi 2019-09-10 15:04:09 +0200 1266) kfree(ap->pages);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1267) } while (!err && iov_iter_count(ii));
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1268)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1269) if (res > 0)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1270) fuse_write_update_size(inode, pos);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1271)
06a7c3c278140 (Maxim Patlasov 2013-08-30 17:06:04 +0400 1272) clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1273) fuse_invalidate_attr(inode);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1274)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1275) return res > 0 ? res : err;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1276) }
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1277)
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1278) static ssize_t fuse_cache_write_iter(struct kiocb *iocb, struct iov_iter *from)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1279) {
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1280) struct file *file = iocb->ki_filp;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1281) struct address_space *mapping = file->f_mapping;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1282) ssize_t written = 0;
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1283) ssize_t written_buffered = 0;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1284) struct inode *inode = mapping->host;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1285) ssize_t err;
8981bdfda7445 (Vivek Goyal 2020-10-09 14:15:10 -0400 1286) struct fuse_conn *fc = get_fuse_conn(inode);
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1287) loff_t endbyte = 0;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1288)
8981bdfda7445 (Vivek Goyal 2020-10-09 14:15:10 -0400 1289) if (fc->writeback_cache) {
4d99ff8f12eb2 (Pavel Emelyanov 2013-10-10 17:12:18 +0400 1290) /* Update size (EOF optimization) and mode (SUID clearing) */
5b97eeacbd80a (Miklos Szeredi 2017-09-12 16:57:54 +0200 1291) err = fuse_update_attributes(mapping->host, file);
4d99ff8f12eb2 (Pavel Emelyanov 2013-10-10 17:12:18 +0400 1292) if (err)
4d99ff8f12eb2 (Pavel Emelyanov 2013-10-10 17:12:18 +0400 1293) return err;
4d99ff8f12eb2 (Pavel Emelyanov 2013-10-10 17:12:18 +0400 1294)
8981bdfda7445 (Vivek Goyal 2020-10-09 14:15:10 -0400 1295) if (fc->handle_killpriv_v2 &&
8981bdfda7445 (Vivek Goyal 2020-10-09 14:15:10 -0400 1296) should_remove_suid(file_dentry(file))) {
8981bdfda7445 (Vivek Goyal 2020-10-09 14:15:10 -0400 1297) goto writethrough;
8981bdfda7445 (Vivek Goyal 2020-10-09 14:15:10 -0400 1298) }
8981bdfda7445 (Vivek Goyal 2020-10-09 14:15:10 -0400 1299)
84c3d55cc474f (Al Viro 2014-04-03 14:33:23 -0400 1300) return generic_file_write_iter(iocb, from);
4d99ff8f12eb2 (Pavel Emelyanov 2013-10-10 17:12:18 +0400 1301) }
4d99ff8f12eb2 (Pavel Emelyanov 2013-10-10 17:12:18 +0400 1302)
8981bdfda7445 (Vivek Goyal 2020-10-09 14:15:10 -0400 1303) writethrough:
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 1304) inode_lock(inode);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1305)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1306) /* We can write back this queue in page reclaim */
de1414a654e66 (Christoph Hellwig 2015-01-14 10:42:36 +0100 1307) current->backing_dev_info = inode_to_bdi(inode);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1308)
3309dd04cbcd2 (Al Viro 2015-04-09 12:55:47 -0400 1309) err = generic_write_checks(iocb, from);
3309dd04cbcd2 (Al Viro 2015-04-09 12:55:47 -0400 1310) if (err <= 0)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1311) goto out;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1312)
5fa8e0a1c6a76 (Jan Kara 2015-05-21 16:05:53 +0200 1313) err = file_remove_privs(file);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1314) if (err)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1315) goto out;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1316)
c3b2da3148344 (Josef Bacik 2012-03-26 09:59:21 -0400 1317) err = file_update_time(file);
c3b2da3148344 (Josef Bacik 2012-03-26 09:59:21 -0400 1318) if (err)
c3b2da3148344 (Josef Bacik 2012-03-26 09:59:21 -0400 1319) goto out;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1320)
2ba48ce513c4e (Al Viro 2015-04-09 13:52:01 -0400 1321) if (iocb->ki_flags & IOCB_DIRECT) {
3309dd04cbcd2 (Al Viro 2015-04-09 12:55:47 -0400 1322) loff_t pos = iocb->ki_pos;
1af5bb491fbb4 (Christoph Hellwig 2016-04-07 08:51:56 -0700 1323) written = generic_file_direct_write(iocb, from);
84c3d55cc474f (Al Viro 2014-04-03 14:33:23 -0400 1324) if (written < 0 || !iov_iter_count(from))
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1325) goto out;
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1326)
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1327) pos += written;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1328)
e1c0eecba1a41 (Miklos Szeredi 2017-09-12 16:57:53 +0200 1329) written_buffered = fuse_perform_write(iocb, mapping, from, pos);
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1330) if (written_buffered < 0) {
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1331) err = written_buffered;
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1332) goto out;
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1333) }
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1334) endbyte = pos + written_buffered - 1;
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1335)
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1336) err = filemap_write_and_wait_range(file->f_mapping, pos,
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1337) endbyte);
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1338) if (err)
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1339) goto out;
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1340)
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1341) invalidate_mapping_pages(file->f_mapping,
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1342) pos >> PAGE_SHIFT,
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1343) endbyte >> PAGE_SHIFT);
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1344)
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1345) written += written_buffered;
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1346) iocb->ki_pos = pos + written_buffered;
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1347) } else {
e1c0eecba1a41 (Miklos Szeredi 2017-09-12 16:57:53 +0200 1348) written = fuse_perform_write(iocb, mapping, from, iocb->ki_pos);
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1349) if (written >= 0)
3309dd04cbcd2 (Al Viro 2015-04-09 12:55:47 -0400 1350) iocb->ki_pos += written;
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1351) }
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1352) out:
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1353) current->backing_dev_info = NULL;
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 1354) inode_unlock(inode);
e1c0eecba1a41 (Miklos Szeredi 2017-09-12 16:57:53 +0200 1355) if (written > 0)
e1c0eecba1a41 (Miklos Szeredi 2017-09-12 16:57:53 +0200 1356) written = generic_write_sync(iocb, written);
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1357)
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1358) return written ? written : err;
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1359) }
ea9b9907b82a0 (Nicholas Piggin 2008-04-30 00:54:42 -0700 1360)
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1361) static inline unsigned long fuse_get_user_addr(const struct iov_iter *ii)
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1362) {
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1363) return (unsigned long)ii->iov->iov_base + ii->iov_offset;
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1364) }
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1365)
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1366) static inline size_t fuse_get_frag_size(const struct iov_iter *ii,
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1367) size_t max_size)
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1368) {
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1369) return min(iov_iter_single_seg_count(ii), max_size);
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1370) }
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1371)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1372) static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii,
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1373) size_t *nbytesp, int write,
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1374) unsigned int max_pages)
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1375) {
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1376) size_t nbytes = 0; /* # bytes already packed in req */
742f992708dff (Ashish Samant 2016-03-14 21:57:35 -0700 1377) ssize_t ret = 0;
b98d023a24496 (Maxim Patlasov 2012-10-26 19:50:15 +0400 1378)
f4975c67dd9ad (Miklos Szeredi 2009-04-02 14:25:34 +0200 1379) /* Special case for kernel I/O: can copy directly into the buffer */
00e23707442a7 (David Howells 2018-10-22 13:07:28 +0100 1380) if (iov_iter_is_kvec(ii)) {
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1381) unsigned long user_addr = fuse_get_user_addr(ii);
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1382) size_t frag_size = fuse_get_frag_size(ii, *nbytesp);
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1383)
f4975c67dd9ad (Miklos Szeredi 2009-04-02 14:25:34 +0200 1384) if (write)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1385) ap->args.in_args[1].value = (void *) user_addr;
f4975c67dd9ad (Miklos Szeredi 2009-04-02 14:25:34 +0200 1386) else
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1387) ap->args.out_args[0].value = (void *) user_addr;
f4975c67dd9ad (Miklos Szeredi 2009-04-02 14:25:34 +0200 1388)
b98d023a24496 (Maxim Patlasov 2012-10-26 19:50:15 +0400 1389) iov_iter_advance(ii, frag_size);
b98d023a24496 (Maxim Patlasov 2012-10-26 19:50:15 +0400 1390) *nbytesp = frag_size;
f4975c67dd9ad (Miklos Szeredi 2009-04-02 14:25:34 +0200 1391) return 0;
f4975c67dd9ad (Miklos Szeredi 2009-04-02 14:25:34 +0200 1392) }
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1393)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1394) while (nbytes < *nbytesp && ap->num_pages < max_pages) {
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1395) unsigned npages;
f67da30c1d5fc (Al Viro 2014-03-19 01:16:16 -0400 1396) size_t start;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1397) ret = iov_iter_get_pages(ii, &ap->pages[ap->num_pages],
2c80929c4c4d5 (Miklos Szeredi 2014-09-24 17:09:11 +0200 1398) *nbytesp - nbytes,
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1399) max_pages - ap->num_pages,
c7f3888ad7f09 (Al Viro 2014-06-18 20:34:33 -0400 1400) &start);
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1401) if (ret < 0)
742f992708dff (Ashish Samant 2016-03-14 21:57:35 -0700 1402) break;
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1403)
c9c37e2e63786 (Al Viro 2014-03-16 16:08:30 -0400 1404) iov_iter_advance(ii, ret);
c9c37e2e63786 (Al Viro 2014-03-16 16:08:30 -0400 1405) nbytes += ret;
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1406)
c9c37e2e63786 (Al Viro 2014-03-16 16:08:30 -0400 1407) ret += start;
c9c37e2e63786 (Al Viro 2014-03-16 16:08:30 -0400 1408) npages = (ret + PAGE_SIZE - 1) / PAGE_SIZE;
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1409)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1410) ap->descs[ap->num_pages].offset = start;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1411) fuse_page_descs_length_init(ap->descs, ap->num_pages, npages);
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1412)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1413) ap->num_pages += npages;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1414) ap->descs[ap->num_pages - 1].length -=
c9c37e2e63786 (Al Viro 2014-03-16 16:08:30 -0400 1415) (PAGE_SIZE - ret) & (PAGE_SIZE - 1);
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1416) }
f4975c67dd9ad (Miklos Szeredi 2009-04-02 14:25:34 +0200 1417)
f4975c67dd9ad (Miklos Szeredi 2009-04-02 14:25:34 +0200 1418) if (write)
cabdb4fa2f666 (zhengbin 2020-01-14 20:39:45 +0800 1419) ap->args.in_pages = true;
f4975c67dd9ad (Miklos Szeredi 2009-04-02 14:25:34 +0200 1420) else
cabdb4fa2f666 (zhengbin 2020-01-14 20:39:45 +0800 1421) ap->args.out_pages = true;
f4975c67dd9ad (Miklos Szeredi 2009-04-02 14:25:34 +0200 1422)
7c190c8b9c0dd (Maxim Patlasov 2012-10-26 19:50:29 +0400 1423) *nbytesp = nbytes;
f4975c67dd9ad (Miklos Szeredi 2009-04-02 14:25:34 +0200 1424)
2c932d4c9165d (Ashish Samant 2016-03-25 10:53:41 -0700 1425) return ret < 0 ? ret : 0;
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1426) }
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1427)
d22a943f44c79 (Al Viro 2014-03-16 15:50:47 -0400 1428) ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
d22a943f44c79 (Al Viro 2014-03-16 15:50:47 -0400 1429) loff_t *ppos, int flags)
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1430) {
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 1431) int write = flags & FUSE_DIO_WRITE;
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 1432) int cuse = flags & FUSE_DIO_CUSE;
e1c0eecba1a41 (Miklos Szeredi 2017-09-12 16:57:53 +0200 1433) struct file *file = io->iocb->ki_filp;
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 1434) struct inode *inode = file->f_mapping->host;
2106cb1893031 (Miklos Szeredi 2009-04-28 16:56:37 +0200 1435) struct fuse_file *ff = file->private_data;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1436) struct fuse_conn *fc = ff->fm->fc;
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1437) size_t nmax = write ? fc->max_write : fc->max_read;
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1438) loff_t pos = *ppos;
d22a943f44c79 (Al Viro 2014-03-16 15:50:47 -0400 1439) size_t count = iov_iter_count(iter);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1440) pgoff_t idx_from = pos >> PAGE_SHIFT;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1441) pgoff_t idx_to = (pos + count - 1) >> PAGE_SHIFT;
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1442) ssize_t res = 0;
742f992708dff (Ashish Samant 2016-03-14 21:57:35 -0700 1443) int err = 0;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1444) struct fuse_io_args *ia;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1445) unsigned int max_pages;
248d86e87d12d (Miklos Szeredi 2006-01-06 00:19:39 -0800 1446)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1447) max_pages = iov_iter_npages(iter, fc->max_pages);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1448) ia = fuse_io_alloc(io, max_pages);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1449) if (!ia)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1450) return -ENOMEM;
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1451)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1452) ia->io = io;
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 1453) if (!cuse && fuse_range_is_writeback(inode, idx_from, idx_to)) {
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 1454) if (!write)
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 1455) inode_lock(inode);
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 1456) fuse_sync_writes(inode);
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 1457) if (!write)
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 1458) inode_unlock(inode);
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 1459) }
ea8cd33390faf (Pavel Emelyanov 2013-10-10 17:12:05 +0400 1460)
61c12b49e1c9c (Ashish Samant 2017-07-12 19:26:58 -0700 1461) io->should_dirty = !write && iter_is_iovec(iter);
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1462) while (count) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1463) ssize_t nres;
2106cb1893031 (Miklos Szeredi 2009-04-28 16:56:37 +0200 1464) fl_owner_t owner = current->files;
f4975c67dd9ad (Miklos Szeredi 2009-04-02 14:25:34 +0200 1465) size_t nbytes = min(count, nmax);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1466)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1467) err = fuse_get_user_pages(&ia->ap, iter, &nbytes, write,
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1468) max_pages);
742f992708dff (Ashish Samant 2016-03-14 21:57:35 -0700 1469) if (err && !nbytes)
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1470) break;
f4975c67dd9ad (Miklos Szeredi 2009-04-02 14:25:34 +0200 1471)
4a2abf99f9c28 (Miklos Szeredi 2019-05-27 09:08:12 +0200 1472) if (write) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1473) if (!capable(CAP_FSETID))
10c52c84e3f48 (Miklos Szeredi 2020-11-11 17:22:32 +0100 1474) ia->write.in.write_flags |= FUSE_WRITE_KILL_SUIDGID;
4a2abf99f9c28 (Miklos Szeredi 2019-05-27 09:08:12 +0200 1475)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1476) nres = fuse_send_write(ia, pos, nbytes, owner);
4a2abf99f9c28 (Miklos Szeredi 2019-05-27 09:08:12 +0200 1477) } else {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1478) nres = fuse_send_read(ia, pos, nbytes, owner);
4a2abf99f9c28 (Miklos Szeredi 2019-05-27 09:08:12 +0200 1479) }
2106cb1893031 (Miklos Szeredi 2009-04-28 16:56:37 +0200 1480)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1481) if (!io->async || nres < 0) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1482) fuse_release_user_pages(&ia->ap, io->should_dirty);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1483) fuse_io_free(ia);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1484) }
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1485) ia = NULL;
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1486) if (nres < 0) {
f658adeea45e4 (Miklos Szeredi 2020-02-06 16:39:28 +0100 1487) iov_iter_revert(iter, nbytes);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1488) err = nres;
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1489) break;
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1490) }
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1491) WARN_ON(nres > nbytes);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1492)
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1493) count -= nres;
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1494) res += nres;
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1495) pos += nres;
f658adeea45e4 (Miklos Szeredi 2020-02-06 16:39:28 +0100 1496) if (nres != nbytes) {
f658adeea45e4 (Miklos Szeredi 2020-02-06 16:39:28 +0100 1497) iov_iter_revert(iter, nbytes - nres);
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1498) break;
f658adeea45e4 (Miklos Szeredi 2020-02-06 16:39:28 +0100 1499) }
56cf34ff07956 (Miklos Szeredi 2006-04-11 21:16:51 +0200 1500) if (count) {
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1501) max_pages = iov_iter_npages(iter, fc->max_pages);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1502) ia = fuse_io_alloc(io, max_pages);
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1503) if (!ia)
56cf34ff07956 (Miklos Szeredi 2006-04-11 21:16:51 +0200 1504) break;
56cf34ff07956 (Miklos Szeredi 2006-04-11 21:16:51 +0200 1505) }
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1506) }
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1507) if (ia)
45ac96ed7c369 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1508) fuse_io_free(ia);
d09cb9d7f6e4c (Miklos Szeredi 2009-04-28 16:56:36 +0200 1509) if (res > 0)
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1510) *ppos = pos;
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1511)
742f992708dff (Ashish Samant 2016-03-14 21:57:35 -0700 1512) return res > 0 ? res : err;
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1513) }
08cbf542bf24f (Tejun Heo 2009-04-14 10:54:53 +0900 1514) EXPORT_SYMBOL_GPL(fuse_direct_io);
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1515)
36cf66ed9f871 (Maxim Patlasov 2012-12-14 19:20:51 +0400 1516) static ssize_t __fuse_direct_read(struct fuse_io_priv *io,
d22a943f44c79 (Al Viro 2014-03-16 15:50:47 -0400 1517) struct iov_iter *iter,
d22a943f44c79 (Al Viro 2014-03-16 15:50:47 -0400 1518) loff_t *ppos)
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1519) {
d09cb9d7f6e4c (Miklos Szeredi 2009-04-28 16:56:36 +0200 1520) ssize_t res;
e1c0eecba1a41 (Miklos Szeredi 2017-09-12 16:57:53 +0200 1521) struct inode *inode = file_inode(io->iocb->ki_filp);
d09cb9d7f6e4c (Miklos Szeredi 2009-04-28 16:56:36 +0200 1522)
d22a943f44c79 (Al Viro 2014-03-16 15:50:47 -0400 1523) res = fuse_direct_io(io, iter, ppos, 0);
d09cb9d7f6e4c (Miklos Szeredi 2009-04-28 16:56:36 +0200 1524)
9a2eb24d1a349 (Miklos Szeredi 2018-10-15 15:43:06 +0200 1525) fuse_invalidate_atime(inode);
d09cb9d7f6e4c (Miklos Szeredi 2009-04-28 16:56:36 +0200 1526)
d09cb9d7f6e4c (Miklos Szeredi 2009-04-28 16:56:36 +0200 1527) return res;
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1528) }
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 1529)
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1530) static ssize_t fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter);
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1531)
15316263649d9 (Al Viro 2015-03-30 22:08:36 -0400 1532) static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to)
b98d023a24496 (Maxim Patlasov 2012-10-26 19:50:15 +0400 1533) {
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1534) ssize_t res;
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1535)
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1536) if (!is_sync_kiocb(iocb) && iocb->ki_flags & IOCB_DIRECT) {
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1537) res = fuse_direct_IO(iocb, to);
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1538) } else {
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1539) struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb);
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1540)
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1541) res = __fuse_direct_read(&io, to, &iocb->ki_pos);
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1542) }
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1543)
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1544) return res;
b98d023a24496 (Maxim Patlasov 2012-10-26 19:50:15 +0400 1545) }
b98d023a24496 (Maxim Patlasov 2012-10-26 19:50:15 +0400 1546)
15316263649d9 (Al Viro 2015-03-30 22:08:36 -0400 1547) static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1548) {
e1c0eecba1a41 (Miklos Szeredi 2017-09-12 16:57:53 +0200 1549) struct inode *inode = file_inode(iocb->ki_filp);
e1c0eecba1a41 (Miklos Szeredi 2017-09-12 16:57:53 +0200 1550) struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb);
15316263649d9 (Al Viro 2015-03-30 22:08:36 -0400 1551) ssize_t res;
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1552)
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1553) /* Don't allow parallel writes to the same file */
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 1554) inode_lock(inode);
3309dd04cbcd2 (Al Viro 2015-04-09 12:55:47 -0400 1555) res = generic_write_checks(iocb, from);
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1556) if (res > 0) {
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1557) if (!is_sync_kiocb(iocb) && iocb->ki_flags & IOCB_DIRECT) {
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1558) res = fuse_direct_IO(iocb, from);
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1559) } else {
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1560) res = fuse_direct_io(&io, from, &iocb->ki_pos,
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1561) FUSE_DIO_WRITE);
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1562) }
23c94e1cdcbf5 (Martin Raiber 2018-10-27 16:48:48 +0000 1563) }
812408fb51ef5 (Al Viro 2015-03-30 22:15:58 -0400 1564) fuse_invalidate_attr(inode);
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 1565) if (res > 0)
15316263649d9 (Al Viro 2015-03-30 22:08:36 -0400 1566) fuse_write_update_size(inode, iocb->ki_pos);
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 1567) inode_unlock(inode);
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1568)
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1569) return res;
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1570) }
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 1571)
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1572) static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1573) {
2f7b6f5bed01a (Miklos Szeredi 2019-01-24 10:40:17 +0100 1574) struct file *file = iocb->ki_filp;
2f7b6f5bed01a (Miklos Szeredi 2019-01-24 10:40:17 +0100 1575) struct fuse_file *ff = file->private_data;
c2d0ad00d948d (Vivek Goyal 2020-08-19 18:19:51 -0400 1576) struct inode *inode = file_inode(file);
2f7b6f5bed01a (Miklos Szeredi 2019-01-24 10:40:17 +0100 1577)
5d069dbe8aaf2 (Miklos Szeredi 2020-12-10 15:33:14 +0100 1578) if (fuse_is_bad(inode))
2f7b6f5bed01a (Miklos Szeredi 2019-01-24 10:40:17 +0100 1579) return -EIO;
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1580)
c2d0ad00d948d (Vivek Goyal 2020-08-19 18:19:51 -0400 1581) if (FUSE_IS_DAX(inode))
c2d0ad00d948d (Vivek Goyal 2020-08-19 18:19:51 -0400 1582) return fuse_dax_read_iter(iocb, to);
c2d0ad00d948d (Vivek Goyal 2020-08-19 18:19:51 -0400 1583)
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1584) if (!(ff->open_flags & FOPEN_DIRECT_IO))
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1585) return fuse_cache_read_iter(iocb, to);
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1586) else
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1587) return fuse_direct_read_iter(iocb, to);
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1588) }
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1589)
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1590) static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1591) {
2f7b6f5bed01a (Miklos Szeredi 2019-01-24 10:40:17 +0100 1592) struct file *file = iocb->ki_filp;
2f7b6f5bed01a (Miklos Szeredi 2019-01-24 10:40:17 +0100 1593) struct fuse_file *ff = file->private_data;
c2d0ad00d948d (Vivek Goyal 2020-08-19 18:19:51 -0400 1594) struct inode *inode = file_inode(file);
2f7b6f5bed01a (Miklos Szeredi 2019-01-24 10:40:17 +0100 1595)
5d069dbe8aaf2 (Miklos Szeredi 2020-12-10 15:33:14 +0100 1596) if (fuse_is_bad(inode))
2f7b6f5bed01a (Miklos Szeredi 2019-01-24 10:40:17 +0100 1597) return -EIO;
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1598)
c2d0ad00d948d (Vivek Goyal 2020-08-19 18:19:51 -0400 1599) if (FUSE_IS_DAX(inode))
c2d0ad00d948d (Vivek Goyal 2020-08-19 18:19:51 -0400 1600) return fuse_dax_write_iter(iocb, from);
c2d0ad00d948d (Vivek Goyal 2020-08-19 18:19:51 -0400 1601)
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1602) if (!(ff->open_flags & FOPEN_DIRECT_IO))
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1603) return fuse_cache_write_iter(iocb, from);
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1604) else
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1605) return fuse_direct_write_iter(iocb, from);
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1606) }
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 1607)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1608) static void fuse_writepage_free(struct fuse_writepage_args *wpa)
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 1609) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1610) struct fuse_args_pages *ap = &wpa->ia.ap;
385b126815d92 (Pavel Emelyanov 2013-06-29 21:42:48 +0400 1611) int i;
385b126815d92 (Pavel Emelyanov 2013-06-29 21:42:48 +0400 1612)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1613) for (i = 0; i < ap->num_pages; i++)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1614) __free_page(ap->pages[i]);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1615)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1616) if (wpa->ia.ff)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1617) fuse_file_put(wpa->ia.ff, false, false);
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 1618)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1619) kfree(ap->pages);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1620) kfree(wpa);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1621) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1622)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1623) static void fuse_writepage_finish(struct fuse_mount *fm,
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1624) struct fuse_writepage_args *wpa)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1625) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1626) struct fuse_args_pages *ap = &wpa->ia.ap;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1627) struct inode *inode = wpa->inode;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1628) struct fuse_inode *fi = get_fuse_inode(inode);
de1414a654e66 (Christoph Hellwig 2015-01-14 10:42:36 +0100 1629) struct backing_dev_info *bdi = inode_to_bdi(inode);
385b126815d92 (Pavel Emelyanov 2013-06-29 21:42:48 +0400 1630) int i;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1631)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1632) for (i = 0; i < ap->num_pages; i++) {
93f78d882865c (Tejun Heo 2015-05-22 17:13:27 -0400 1633) dec_wb_stat(&bdi->wb, WB_WRITEBACK);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1634) dec_node_page_state(ap->pages[i], NR_WRITEBACK_TEMP);
93f78d882865c (Tejun Heo 2015-05-22 17:13:27 -0400 1635) wb_writeout_inc(&bdi->wb);
385b126815d92 (Pavel Emelyanov 2013-06-29 21:42:48 +0400 1636) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1637) wake_up(&fi->page_waitq);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1638) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1639)
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1640) /* Called under fi->lock, may release and reacquire it */
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1641) static void fuse_send_writepage(struct fuse_mount *fm,
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1642) struct fuse_writepage_args *wpa, loff_t size)
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1643) __releases(fi->lock)
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1644) __acquires(fi->lock)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1645) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1646) struct fuse_writepage_args *aux, *next;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1647) struct fuse_inode *fi = get_fuse_inode(wpa->inode);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1648) struct fuse_write_in *inarg = &wpa->ia.write.in;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1649) struct fuse_args *args = &wpa->ia.ap.args;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1650) __u64 data_size = wpa->ia.ap.num_pages * PAGE_SIZE;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1651) int err;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1652)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1653) fi->writectr++;
385b126815d92 (Pavel Emelyanov 2013-06-29 21:42:48 +0400 1654) if (inarg->offset + data_size <= size) {
385b126815d92 (Pavel Emelyanov 2013-06-29 21:42:48 +0400 1655) inarg->size = data_size;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1656) } else if (inarg->offset < size) {
385b126815d92 (Pavel Emelyanov 2013-06-29 21:42:48 +0400 1657) inarg->size = size - inarg->offset;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1658) } else {
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1659) /* Got truncated off completely */
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1660) goto out_free;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 1661) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1662)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1663) args->in_args[1].size = inarg->size;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1664) args->force = true;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1665) args->nocreds = true;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1666)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1667) err = fuse_simple_background(fm, args, GFP_ATOMIC);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1668) if (err == -ENOMEM) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1669) spin_unlock(&fi->lock);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1670) err = fuse_simple_background(fm, args, GFP_NOFS | __GFP_NOFAIL);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1671) spin_lock(&fi->lock);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1672) }
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1673)
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1674) /* Fails on broken connection only */
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1675) if (unlikely(err))
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1676) goto out_free;
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1677)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1678) return;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1679)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1680) out_free:
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1681) fi->writectr--;
69a6487ac0ea1 (Miklos Szeredi 2020-07-14 14:45:41 +0200 1682) rb_erase(&wpa->writepages_entry, &fi->writepages);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1683) fuse_writepage_finish(fm, wpa);
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1684) spin_unlock(&fi->lock);
e2653bd53a984 (Miklos Szeredi 2019-01-24 10:40:15 +0100 1685)
e2653bd53a984 (Miklos Szeredi 2019-01-24 10:40:15 +0100 1686) /* After fuse_writepage_finish() aux request list is private */
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1687) for (aux = wpa->next; aux; aux = next) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1688) next = aux->next;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1689) aux->next = NULL;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1690) fuse_writepage_free(aux);
e2653bd53a984 (Miklos Szeredi 2019-01-24 10:40:15 +0100 1691) }
e2653bd53a984 (Miklos Szeredi 2019-01-24 10:40:15 +0100 1692)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1693) fuse_writepage_free(wpa);
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1694) spin_lock(&fi->lock);
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 1695) }
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 1696)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1697) /*
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1698) * If fi->writectr is positive (no truncate or fsync going on) send
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1699) * all queued writepage requests.
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1700) *
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1701) * Called with fi->lock
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1702) */
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1703) void fuse_flush_writepages(struct inode *inode)
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1704) __releases(fi->lock)
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1705) __acquires(fi->lock)
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 1706) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1707) struct fuse_mount *fm = get_fuse_mount(inode);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1708) struct fuse_inode *fi = get_fuse_inode(inode);
9de5be06d0a89 (Miklos Szeredi 2019-04-24 17:05:06 +0200 1709) loff_t crop = i_size_read(inode);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1710) struct fuse_writepage_args *wpa;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1711)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1712) while (fi->writectr >= 0 && !list_empty(&fi->queued_writes)) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1713) wpa = list_entry(fi->queued_writes.next,
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1714) struct fuse_writepage_args, queue_entry);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1715) list_del_init(&wpa->queue_entry);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1716) fuse_send_writepage(fm, wpa, crop);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1717) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1718) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1719)
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 1720) static struct fuse_writepage_args *fuse_insert_writeback(struct rb_root *root,
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 1721) struct fuse_writepage_args *wpa)
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1722) {
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1723) pgoff_t idx_from = wpa->ia.write.in.offset >> PAGE_SHIFT;
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1724) pgoff_t idx_to = idx_from + wpa->ia.ap.num_pages - 1;
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1725) struct rb_node **p = &root->rb_node;
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1726) struct rb_node *parent = NULL;
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1727)
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1728) WARN_ON(!wpa->ia.ap.num_pages);
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1729) while (*p) {
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1730) struct fuse_writepage_args *curr;
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1731) pgoff_t curr_index;
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1732)
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1733) parent = *p;
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1734) curr = rb_entry(parent, struct fuse_writepage_args,
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1735) writepages_entry);
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1736) WARN_ON(curr->inode != wpa->inode);
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1737) curr_index = curr->ia.write.in.offset >> PAGE_SHIFT;
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1738)
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1739) if (idx_from >= curr_index + curr->ia.ap.num_pages)
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1740) p = &(*p)->rb_right;
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1741) else if (idx_to < curr_index)
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1742) p = &(*p)->rb_left;
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1743) else
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 1744) return curr;
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1745) }
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1746)
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1747) rb_link_node(&wpa->writepages_entry, parent, p);
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1748) rb_insert_color(&wpa->writepages_entry, root);
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 1749) return NULL;
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 1750) }
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 1751)
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 1752) static void tree_insert(struct rb_root *root, struct fuse_writepage_args *wpa)
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 1753) {
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 1754) WARN_ON(fuse_insert_writeback(root, wpa));
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1755) }
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1756)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1757) static void fuse_writepage_end(struct fuse_mount *fm, struct fuse_args *args,
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1758) int error)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1759) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1760) struct fuse_writepage_args *wpa =
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1761) container_of(args, typeof(*wpa), ia.ap.args);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1762) struct inode *inode = wpa->inode;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1763) struct fuse_inode *fi = get_fuse_inode(inode);
3466958beb31a (Vivek Goyal 2021-04-06 10:07:06 -0400 1764) struct fuse_conn *fc = get_fuse_conn(inode);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1765)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1766) mapping_set_error(inode->i_mapping, error);
3466958beb31a (Vivek Goyal 2021-04-06 10:07:06 -0400 1767) /*
3466958beb31a (Vivek Goyal 2021-04-06 10:07:06 -0400 1768) * A writeback finished and this might have updated mtime/ctime on
3466958beb31a (Vivek Goyal 2021-04-06 10:07:06 -0400 1769) * server making local mtime/ctime stale. Hence invalidate attrs.
3466958beb31a (Vivek Goyal 2021-04-06 10:07:06 -0400 1770) * Do this only if writeback_cache is not enabled. If writeback_cache
3466958beb31a (Vivek Goyal 2021-04-06 10:07:06 -0400 1771) * is enabled, we trust local ctime/mtime.
3466958beb31a (Vivek Goyal 2021-04-06 10:07:06 -0400 1772) */
3466958beb31a (Vivek Goyal 2021-04-06 10:07:06 -0400 1773) if (!fc->writeback_cache)
3466958beb31a (Vivek Goyal 2021-04-06 10:07:06 -0400 1774) fuse_invalidate_attr(inode);
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1775) spin_lock(&fi->lock);
69a6487ac0ea1 (Miklos Szeredi 2020-07-14 14:45:41 +0200 1776) rb_erase(&wpa->writepages_entry, &fi->writepages);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1777) while (wpa->next) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1778) struct fuse_mount *fm = get_fuse_mount(inode);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1779) struct fuse_write_in *inarg = &wpa->ia.write.in;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1780) struct fuse_writepage_args *next = wpa->next;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1781)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1782) wpa->next = next->next;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1783) next->next = NULL;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1784) next->ia.ff = fuse_file_get(wpa->ia.ff);
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1785) tree_insert(&fi->writepages, next);
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1786)
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1787) /*
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1788) * Skip fuse_flush_writepages() to make it easy to crop requests
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1789) * based on primary request size.
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1790) *
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1791) * 1st case (trivial): there are no concurrent activities using
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1792) * fuse_set/release_nowrite. Then we're on safe side because
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1793) * fuse_flush_writepages() would call fuse_send_writepage()
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1794) * anyway.
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1795) *
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1796) * 2nd case: someone called fuse_set_nowrite and it is waiting
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1797) * now for completion of all in-flight requests. This happens
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1798) * rarely and no more than once per page, so this should be
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1799) * okay.
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1800) *
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1801) * 3rd case: someone (e.g. fuse_do_setattr()) is in the middle
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1802) * of fuse_set_nowrite..fuse_release_nowrite section. The fact
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1803) * that fuse_set_nowrite returned implies that all in-flight
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1804) * requests were completed along with all of their secondary
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1805) * requests. Further primary requests are blocked by negative
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1806) * writectr. Hence there cannot be any in-flight requests and
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1807) * no invocations of fuse_writepage_end() while we're in
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1808) * fuse_set_nowrite..fuse_release_nowrite section.
6eaf4782eb09e (Maxim Patlasov 2013-10-02 21:38:32 +0400 1809) */
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1810) fuse_send_writepage(fm, next, inarg->offset + inarg->size);
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 1811) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1812) fi->writectr--;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1813) fuse_writepage_finish(fm, wpa);
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1814) spin_unlock(&fi->lock);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1815) fuse_writepage_free(wpa);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1816) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1817)
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1818) static struct fuse_file *__fuse_write_file_get(struct fuse_conn *fc,
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1819) struct fuse_inode *fi)
adcadfa8f373f (Pavel Emelyanov 2013-06-29 21:42:20 +0400 1820) {
72523425fb434 (Miklos Szeredi 2013-10-01 16:44:52 +0200 1821) struct fuse_file *ff = NULL;
adcadfa8f373f (Pavel Emelyanov 2013-06-29 21:42:20 +0400 1822)
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1823) spin_lock(&fi->lock);
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1824) if (!list_empty(&fi->write_files)) {
72523425fb434 (Miklos Szeredi 2013-10-01 16:44:52 +0200 1825) ff = list_entry(fi->write_files.next, struct fuse_file,
72523425fb434 (Miklos Szeredi 2013-10-01 16:44:52 +0200 1826) write_entry);
72523425fb434 (Miklos Szeredi 2013-10-01 16:44:52 +0200 1827) fuse_file_get(ff);
72523425fb434 (Miklos Szeredi 2013-10-01 16:44:52 +0200 1828) }
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1829) spin_unlock(&fi->lock);
adcadfa8f373f (Pavel Emelyanov 2013-06-29 21:42:20 +0400 1830)
adcadfa8f373f (Pavel Emelyanov 2013-06-29 21:42:20 +0400 1831) return ff;
adcadfa8f373f (Pavel Emelyanov 2013-06-29 21:42:20 +0400 1832) }
adcadfa8f373f (Pavel Emelyanov 2013-06-29 21:42:20 +0400 1833)
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1834) static struct fuse_file *fuse_write_file_get(struct fuse_conn *fc,
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1835) struct fuse_inode *fi)
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1836) {
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1837) struct fuse_file *ff = __fuse_write_file_get(fc, fi);
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1838) WARN_ON(!ff);
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1839) return ff;
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1840) }
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1841)
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1842) int fuse_write_inode(struct inode *inode, struct writeback_control *wbc)
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1843) {
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1844) struct fuse_conn *fc = get_fuse_conn(inode);
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1845) struct fuse_inode *fi = get_fuse_inode(inode);
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1846) struct fuse_file *ff;
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1847) int err;
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1848)
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1849) ff = __fuse_write_file_get(fc, fi);
ab9e13f7c771b (Maxim Patlasov 2014-04-28 14:19:24 +0200 1850) err = fuse_flush_times(inode, ff);
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1851) if (ff)
2e64ff154ce6c (Chad Austin 2018-12-10 10:54:52 -0800 1852) fuse_file_put(ff, false, false);
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1853)
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1854) return err;
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1855) }
1e18bda86e2dc (Miklos Szeredi 2014-04-28 14:19:23 +0200 1856)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1857) static struct fuse_writepage_args *fuse_writepage_args_alloc(void)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1858) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1859) struct fuse_writepage_args *wpa;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1860) struct fuse_args_pages *ap;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1861)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1862) wpa = kzalloc(sizeof(*wpa), GFP_NOFS);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1863) if (wpa) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1864) ap = &wpa->ia.ap;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1865) ap->num_pages = 0;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1866) ap->pages = fuse_pages_alloc(1, GFP_NOFS, &ap->descs);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1867) if (!ap->pages) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1868) kfree(wpa);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1869) wpa = NULL;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1870) }
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1871) }
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1872) return wpa;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1873)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1874) }
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1875)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1876) static int fuse_writepage_locked(struct page *page)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1877) {
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1878) struct address_space *mapping = page->mapping;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1879) struct inode *inode = mapping->host;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1880) struct fuse_conn *fc = get_fuse_conn(inode);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1881) struct fuse_inode *fi = get_fuse_inode(inode);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1882) struct fuse_writepage_args *wpa;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1883) struct fuse_args_pages *ap;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1884) struct page *tmp_page;
72523425fb434 (Miklos Szeredi 2013-10-01 16:44:52 +0200 1885) int error = -ENOMEM;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1886)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1887) set_page_writeback(page);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1888)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1889) wpa = fuse_writepage_args_alloc();
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1890) if (!wpa)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1891) goto err;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1892) ap = &wpa->ia.ap;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1893)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1894) tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1895) if (!tmp_page)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1896) goto err_free;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1897)
72523425fb434 (Miklos Szeredi 2013-10-01 16:44:52 +0200 1898) error = -EIO;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1899) wpa->ia.ff = fuse_write_file_get(fc, fi);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1900) if (!wpa->ia.ff)
27f1b36326bc8 (Maxim Patlasov 2014-07-10 15:32:43 +0400 1901) goto err_nofile;
72523425fb434 (Miklos Szeredi 2013-10-01 16:44:52 +0200 1902)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1903) fuse_write_args_fill(&wpa->ia, wpa->ia.ff, page_offset(page), 0);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1904)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1905) copy_highpage(tmp_page, page);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1906) wpa->ia.write.in.write_flags |= FUSE_WRITE_CACHE;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1907) wpa->next = NULL;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1908) ap->args.in_pages = true;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1909) ap->num_pages = 1;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1910) ap->pages[0] = tmp_page;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1911) ap->descs[0].offset = 0;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1912) ap->descs[0].length = PAGE_SIZE;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1913) ap->args.end = fuse_writepage_end;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1914) wpa->inode = inode;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1915)
93f78d882865c (Tejun Heo 2015-05-22 17:13:27 -0400 1916) inc_wb_stat(&inode_to_bdi(inode)->wb, WB_WRITEBACK);
11fb998986a72 (Mel Gorman 2016-07-28 15:46:20 -0700 1917) inc_node_page_state(tmp_page, NR_WRITEBACK_TEMP);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1918)
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1919) spin_lock(&fi->lock);
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 1920) tree_insert(&fi->writepages, wpa);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1921) list_add_tail(&wpa->queue_entry, &fi->queued_writes);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1922) fuse_flush_writepages(inode);
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 1923) spin_unlock(&fi->lock);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1924)
4a4ac4eba1010 (Maxim Patlasov 2013-08-12 20:39:30 +0400 1925) end_page_writeback(page);
4a4ac4eba1010 (Maxim Patlasov 2013-08-12 20:39:30 +0400 1926)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1927) return 0;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1928)
27f1b36326bc8 (Maxim Patlasov 2014-07-10 15:32:43 +0400 1929) err_nofile:
27f1b36326bc8 (Maxim Patlasov 2014-07-10 15:32:43 +0400 1930) __free_page(tmp_page);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1931) err_free:
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1932) kfree(wpa);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1933) err:
9183976ef1c85 (Jeff Layton 2017-05-25 06:57:50 -0400 1934) mapping_set_error(page->mapping, error);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1935) end_page_writeback(page);
72523425fb434 (Miklos Szeredi 2013-10-01 16:44:52 +0200 1936) return error;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1937) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1938)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1939) static int fuse_writepage(struct page *page, struct writeback_control *wbc)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1940) {
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1941) int err;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1942)
ff17be0864777 (Miklos Szeredi 2013-10-01 16:44:53 +0200 1943) if (fuse_page_is_writeback(page->mapping->host, page->index)) {
ff17be0864777 (Miklos Szeredi 2013-10-01 16:44:53 +0200 1944) /*
ff17be0864777 (Miklos Szeredi 2013-10-01 16:44:53 +0200 1945) * ->writepages() should be called for sync() and friends. We
ff17be0864777 (Miklos Szeredi 2013-10-01 16:44:53 +0200 1946) * should only get here on direct reclaim and then we are
ff17be0864777 (Miklos Szeredi 2013-10-01 16:44:53 +0200 1947) * allowed to skip a page which is already in flight
ff17be0864777 (Miklos Szeredi 2013-10-01 16:44:53 +0200 1948) */
ff17be0864777 (Miklos Szeredi 2013-10-01 16:44:53 +0200 1949) WARN_ON(wbc->sync_mode == WB_SYNC_ALL);
ff17be0864777 (Miklos Szeredi 2013-10-01 16:44:53 +0200 1950)
ff17be0864777 (Miklos Szeredi 2013-10-01 16:44:53 +0200 1951) redirty_page_for_writepage(wbc, page);
d5880c7a86202 (Vasily Averin 2019-09-13 18:17:11 +0300 1952) unlock_page(page);
ff17be0864777 (Miklos Szeredi 2013-10-01 16:44:53 +0200 1953) return 0;
ff17be0864777 (Miklos Szeredi 2013-10-01 16:44:53 +0200 1954) }
ff17be0864777 (Miklos Szeredi 2013-10-01 16:44:53 +0200 1955)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1956) err = fuse_writepage_locked(page);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1957) unlock_page(page);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1958)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1959) return err;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1960) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 1961)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 1962) struct fuse_fill_wb_data {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1963) struct fuse_writepage_args *wpa;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 1964) struct fuse_file *ff;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 1965) struct inode *inode;
2d033eaa0073d (Maxim Patlasov 2013-08-16 15:51:41 +0400 1966) struct page **orig_pages;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1967) unsigned int max_pages;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 1968) };
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 1969)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1970) static bool fuse_pages_realloc(struct fuse_fill_wb_data *data)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1971) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1972) struct fuse_args_pages *ap = &data->wpa->ia.ap;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1973) struct fuse_conn *fc = get_fuse_conn(data->inode);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1974) struct page **pages;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1975) struct fuse_page_desc *descs;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1976) unsigned int npages = min_t(unsigned int,
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1977) max_t(unsigned int, data->max_pages * 2,
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1978) FUSE_DEFAULT_MAX_PAGES_PER_REQ),
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1979) fc->max_pages);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1980) WARN_ON(npages <= data->max_pages);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1981)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1982) pages = fuse_pages_alloc(npages, GFP_NOFS, &descs);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1983) if (!pages)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1984) return false;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1985)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1986) memcpy(pages, ap->pages, sizeof(struct page *) * ap->num_pages);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1987) memcpy(descs, ap->descs, sizeof(struct fuse_page_desc) * ap->num_pages);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1988) kfree(ap->pages);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1989) ap->pages = pages;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1990) ap->descs = descs;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1991) data->max_pages = npages;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1992)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1993) return true;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1994) }
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1995)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 1996) static void fuse_writepages_send(struct fuse_fill_wb_data *data)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 1997) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 1998) struct fuse_writepage_args *wpa = data->wpa;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 1999) struct inode *inode = data->inode;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2000) struct fuse_inode *fi = get_fuse_inode(inode);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2001) int num_pages = wpa->ia.ap.num_pages;
2d033eaa0073d (Maxim Patlasov 2013-08-16 15:51:41 +0400 2002) int i;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2003)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2004) wpa->ia.ff = fuse_file_get(data->ff);
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 2005) spin_lock(&fi->lock);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2006) list_add_tail(&wpa->queue_entry, &fi->queued_writes);
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2007) fuse_flush_writepages(inode);
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 2008) spin_unlock(&fi->lock);
2d033eaa0073d (Maxim Patlasov 2013-08-16 15:51:41 +0400 2009)
2d033eaa0073d (Maxim Patlasov 2013-08-16 15:51:41 +0400 2010) for (i = 0; i < num_pages; i++)
2d033eaa0073d (Maxim Patlasov 2013-08-16 15:51:41 +0400 2011) end_page_writeback(data->orig_pages[i]);
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2012) }
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2013)
7f305ca1928d8 (Miklos Szeredi 2019-01-16 10:27:59 +0100 2014) /*
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2015) * Check under fi->lock if the page is under writeback, and insert it onto the
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2016) * rb_tree if not. Otherwise iterate auxiliary write requests, to see if there's
419234d5958b8 (Miklos Szeredi 2019-01-16 10:27:59 +0100 2017) * one already added for a page at this offset. If there's none, then insert
419234d5958b8 (Miklos Szeredi 2019-01-16 10:27:59 +0100 2018) * this new request onto the auxiliary list, otherwise reuse the existing one by
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2019) * swapping the new temp page with the old one.
7f305ca1928d8 (Miklos Szeredi 2019-01-16 10:27:59 +0100 2020) */
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2021) static bool fuse_writepage_add(struct fuse_writepage_args *new_wpa,
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2022) struct page *page)
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 2023) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2024) struct fuse_inode *fi = get_fuse_inode(new_wpa->inode);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2025) struct fuse_writepage_args *tmp;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2026) struct fuse_writepage_args *old_wpa;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2027) struct fuse_args_pages *new_ap = &new_wpa->ia.ap;
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 2028)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2029) WARN_ON(new_ap->num_pages != 0);
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2030) new_ap->num_pages = 1;
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 2031)
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 2032) spin_lock(&fi->lock);
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2033) old_wpa = fuse_insert_writeback(&fi->writepages, new_wpa);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2034) if (!old_wpa) {
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 2035) spin_unlock(&fi->lock);
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2036) return true;
f6011081f5e29 (Maxim Patlasov 2013-10-02 15:01:07 +0400 2037) }
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 2038)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2039) for (tmp = old_wpa->next; tmp; tmp = tmp->next) {
7f305ca1928d8 (Miklos Szeredi 2019-01-16 10:27:59 +0100 2040) pgoff_t curr_index;
7f305ca1928d8 (Miklos Szeredi 2019-01-16 10:27:59 +0100 2041)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2042) WARN_ON(tmp->inode != new_wpa->inode);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2043) curr_index = tmp->ia.write.in.offset >> PAGE_SHIFT;
419234d5958b8 (Miklos Szeredi 2019-01-16 10:27:59 +0100 2044) if (curr_index == page->index) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2045) WARN_ON(tmp->ia.ap.num_pages != 1);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2046) swap(tmp->ia.ap.pages[0], new_ap->pages[0]);
7f305ca1928d8 (Miklos Szeredi 2019-01-16 10:27:59 +0100 2047) break;
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 2048) }
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 2049) }
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 2050)
7f305ca1928d8 (Miklos Szeredi 2019-01-16 10:27:59 +0100 2051) if (!tmp) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2052) new_wpa->next = old_wpa->next;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2053) old_wpa->next = new_wpa;
7f305ca1928d8 (Miklos Szeredi 2019-01-16 10:27:59 +0100 2054) }
41b6e41fc6097 (Maxim Patlasov 2013-10-02 21:38:43 +0400 2055)
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 2056) spin_unlock(&fi->lock);
7f305ca1928d8 (Miklos Szeredi 2019-01-16 10:27:59 +0100 2057)
7f305ca1928d8 (Miklos Szeredi 2019-01-16 10:27:59 +0100 2058) if (tmp) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2059) struct backing_dev_info *bdi = inode_to_bdi(new_wpa->inode);
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 2060)
93f78d882865c (Tejun Heo 2015-05-22 17:13:27 -0400 2061) dec_wb_stat(&bdi->wb, WB_WRITEBACK);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2062) dec_node_page_state(new_ap->pages[0], NR_WRITEBACK_TEMP);
93f78d882865c (Tejun Heo 2015-05-22 17:13:27 -0400 2063) wb_writeout_inc(&bdi->wb);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2064) fuse_writepage_free(new_wpa);
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 2065) }
7f305ca1928d8 (Miklos Szeredi 2019-01-16 10:27:59 +0100 2066)
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2067) return false;
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 2068) }
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 2069)
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2070) static bool fuse_writepage_need_send(struct fuse_conn *fc, struct page *page,
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2071) struct fuse_args_pages *ap,
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2072) struct fuse_fill_wb_data *data)
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2073) {
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2074) WARN_ON(!ap->num_pages);
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2075)
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2076) /*
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2077) * Being under writeback is unlikely but possible. For example direct
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2078) * read to an mmaped fuse file will set the page dirty twice; once when
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2079) * the pages are faulted with get_user_pages(), and then after the read
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2080) * completed.
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2081) */
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2082) if (fuse_page_is_writeback(data->inode, page->index))
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2083) return true;
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2084)
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2085) /* Reached max pages */
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2086) if (ap->num_pages == fc->max_pages)
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2087) return true;
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2088)
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2089) /* Reached max write bytes */
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2090) if ((ap->num_pages + 1) * PAGE_SIZE > fc->max_write)
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2091) return true;
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2092)
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2093) /* Discontinuity */
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2094) if (data->orig_pages[ap->num_pages - 1]->index + 1 != page->index)
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2095) return true;
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2096)
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2097) /* Need to grow the pages array? If so, did the expansion fail? */
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2098) if (ap->num_pages == data->max_pages && !fuse_pages_realloc(data))
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2099) return true;
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2100)
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2101) return false;
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2102) }
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2103)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2104) static int fuse_writepages_fill(struct page *page,
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2105) struct writeback_control *wbc, void *_data)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2106) {
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2107) struct fuse_fill_wb_data *data = _data;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2108) struct fuse_writepage_args *wpa = data->wpa;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2109) struct fuse_args_pages *ap = &wpa->ia.ap;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2110) struct inode *inode = data->inode;
f15ecfef058d9 (Kirill Tkhai 2018-11-09 13:33:22 +0300 2111) struct fuse_inode *fi = get_fuse_inode(inode);
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2112) struct fuse_conn *fc = get_fuse_conn(inode);
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2113) struct page *tmp_page;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2114) int err;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2115)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2116) if (!data->ff) {
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2117) err = -EIO;
091d1a7267726 (Vasily Averin 2019-08-19 08:48:26 +0300 2118) data->ff = fuse_write_file_get(fc, fi);
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2119) if (!data->ff)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2120) goto out_unlock;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2121) }
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2122)
6ddf3af93e32b (Miklos Szeredi 2020-07-14 14:45:41 +0200 2123) if (wpa && fuse_writepage_need_send(fc, page, ap, data)) {
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 2124) fuse_writepages_send(data);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2125) data->wpa = NULL;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2126) }
e52a8250480ac (Miklos Szeredi 2018-10-01 10:07:06 +0200 2127)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2128) err = -ENOMEM;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2129) tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM);
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2130) if (!tmp_page)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2131) goto out_unlock;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2132)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2133) /*
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2134) * The page must not be redirtied until the writeout is completed
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2135) * (i.e. userspace has sent a reply to the write request). Otherwise
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2136) * there could be more than one temporary page instance for each real
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2137) * page.
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2138) *
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2139) * This is ensured by holding the page lock in page_mkwrite() while
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2140) * checking fuse_page_is_writeback(). We already hold the page lock
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2141) * since clear_page_dirty_for_io() and keep it held until we add the
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2142) * request to the fi->writepages list and increment ap->num_pages.
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2143) * After this fuse_page_is_writeback() will indicate that the page is
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2144) * under writeback, so we can release the page lock.
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2145) */
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2146) if (data->wpa == NULL) {
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2147) err = -ENOMEM;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2148) wpa = fuse_writepage_args_alloc();
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2149) if (!wpa) {
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2150) __free_page(tmp_page);
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2151) goto out_unlock;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2152) }
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2153) data->max_pages = 1;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2154)
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2155) ap = &wpa->ia.ap;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2156) fuse_write_args_fill(&wpa->ia, data->ff, page_offset(page), 0);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2157) wpa->ia.write.in.write_flags |= FUSE_WRITE_CACHE;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2158) wpa->next = NULL;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2159) ap->args.in_pages = true;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2160) ap->args.end = fuse_writepage_end;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2161) ap->num_pages = 0;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2162) wpa->inode = inode;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2163) }
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2164) set_page_writeback(page);
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2165)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2166) copy_highpage(tmp_page, page);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2167) ap->pages[ap->num_pages] = tmp_page;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2168) ap->descs[ap->num_pages].offset = 0;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2169) ap->descs[ap->num_pages].length = PAGE_SIZE;
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2170) data->orig_pages[ap->num_pages] = page;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2171)
93f78d882865c (Tejun Heo 2015-05-22 17:13:27 -0400 2172) inc_wb_stat(&inode_to_bdi(inode)->wb, WB_WRITEBACK);
11fb998986a72 (Mel Gorman 2016-07-28 15:46:20 -0700 2173) inc_node_page_state(tmp_page, NR_WRITEBACK_TEMP);
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 2174)
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 2175) err = 0;
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2176) if (data->wpa) {
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2177) /*
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2178) * Protected by fi->lock against concurrent access by
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2179) * fuse_page_is_writeback().
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2180) */
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2181) spin_lock(&fi->lock);
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2182) ap->num_pages++;
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2183) spin_unlock(&fi->lock);
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2184) } else if (fuse_writepage_add(wpa, page)) {
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2185) data->wpa = wpa;
c146024ec44c2 (Miklos Szeredi 2020-07-14 14:45:41 +0200 2186) } else {
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 2187) end_page_writeback(page);
8b284dc47291d (Miklos Szeredi 2013-10-01 16:44:53 +0200 2188) }
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2189) out_unlock:
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2190) unlock_page(page);
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2191)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2192) return err;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2193) }
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2194)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2195) static int fuse_writepages(struct address_space *mapping,
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2196) struct writeback_control *wbc)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2197) {
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2198) struct inode *inode = mapping->host;
5da784cce4308 (Constantine Shulyupin 2018-09-06 15:37:06 +0300 2199) struct fuse_conn *fc = get_fuse_conn(inode);
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2200) struct fuse_fill_wb_data data;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2201) int err;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2202)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2203) err = -EIO;
5d069dbe8aaf2 (Miklos Szeredi 2020-12-10 15:33:14 +0100 2204) if (fuse_is_bad(inode))
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2205) goto out;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2206)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2207) data.inode = inode;
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2208) data.wpa = NULL;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2209) data.ff = NULL;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2210)
2d033eaa0073d (Maxim Patlasov 2013-08-16 15:51:41 +0400 2211) err = -ENOMEM;
5da784cce4308 (Constantine Shulyupin 2018-09-06 15:37:06 +0300 2212) data.orig_pages = kcalloc(fc->max_pages,
f2b3455e47c72 (Fabian Frederick 2014-06-23 18:35:15 +0200 2213) sizeof(struct page *),
2d033eaa0073d (Maxim Patlasov 2013-08-16 15:51:41 +0400 2214) GFP_NOFS);
2d033eaa0073d (Maxim Patlasov 2013-08-16 15:51:41 +0400 2215) if (!data.orig_pages)
2d033eaa0073d (Maxim Patlasov 2013-08-16 15:51:41 +0400 2216) goto out;
2d033eaa0073d (Maxim Patlasov 2013-08-16 15:51:41 +0400 2217)
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2218) err = write_cache_pages(mapping, wbc, fuse_writepages_fill, &data);
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2219) if (data.wpa) {
33826ebbbe4b4 (Miklos Szeredi 2019-09-10 15:04:10 +0200 2220) WARN_ON(!data.wpa->ia.ap.num_pages);
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2221) fuse_writepages_send(&data);
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2222) }
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2223) if (data.ff)
2e64ff154ce6c (Chad Austin 2018-12-10 10:54:52 -0800 2224) fuse_file_put(data.ff, false, false);
2d033eaa0073d (Maxim Patlasov 2013-08-16 15:51:41 +0400 2225)
2d033eaa0073d (Maxim Patlasov 2013-08-16 15:51:41 +0400 2226) kfree(data.orig_pages);
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2227) out:
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2228) return err;
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2229) }
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 2230)
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2231) /*
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2232) * It's worthy to make sure that space is reserved on disk for the write,
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2233) * but how to implement it without killing performance need more thinking.
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2234) */
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2235) static int fuse_write_begin(struct file *file, struct address_space *mapping,
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2236) loff_t pos, unsigned len, unsigned flags,
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2237) struct page **pagep, void **fsdata)
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2238) {
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 2239) pgoff_t index = pos >> PAGE_SHIFT;
a455589f181e6 (Al Viro 2014-10-21 20:11:25 -0400 2240) struct fuse_conn *fc = get_fuse_conn(file_inode(file));
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2241) struct page *page;
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2242) loff_t fsize;
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2243) int err = -ENOMEM;
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2244)
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2245) WARN_ON(!fc->writeback_cache);
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2246)
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2247) page = grab_cache_page_write_begin(mapping, index, flags);
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2248) if (!page)
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2249) goto error;
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2250)
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2251) fuse_wait_on_page_writeback(mapping->host, page->index);
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2252)
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 2253) if (PageUptodate(page) || len == PAGE_SIZE)
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2254) goto success;
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2255) /*
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2256) * Check if the start this page comes after the end of file, in which
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2257) * case the readpage can be optimized away.
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2258) */
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2259) fsize = i_size_read(mapping->host);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 2260) if (fsize <= (pos & PAGE_MASK)) {
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 2261) size_t off = pos & ~PAGE_MASK;
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2262) if (off)
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2263) zero_user_segment(page, 0, off);
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2264) goto success;
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2265) }
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2266) err = fuse_do_readpage(file, page);
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2267) if (err)
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2268) goto cleanup;
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2269) success:
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2270) *pagep = page;
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2271) return 0;
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2272)
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2273) cleanup:
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2274) unlock_page(page);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 2275) put_page(page);
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2276) error:
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2277) return err;
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2278) }
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2279)
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2280) static int fuse_write_end(struct file *file, struct address_space *mapping,
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2281) loff_t pos, unsigned len, unsigned copied,
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2282) struct page *page, void *fsdata)
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2283) {
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2284) struct inode *inode = page->mapping->host;
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2285)
59c3b76cc61d1 (Miklos Szeredi 2016-08-18 09:10:44 +0200 2286) /* Haven't copied anything? Skip zeroing, size extending, dirtying. */
59c3b76cc61d1 (Miklos Szeredi 2016-08-18 09:10:44 +0200 2287) if (!copied)
59c3b76cc61d1 (Miklos Szeredi 2016-08-18 09:10:44 +0200 2288) goto unlock;
59c3b76cc61d1 (Miklos Szeredi 2016-08-18 09:10:44 +0200 2289)
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2290) if (!PageUptodate(page)) {
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2291) /* Zero any unwritten bytes at the end of the page */
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 2292) size_t endoff = (pos + copied) & ~PAGE_MASK;
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2293) if (endoff)
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 2294) zero_user_segment(page, endoff, PAGE_SIZE);
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2295) SetPageUptodate(page);
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2296) }
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2297)
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2298) fuse_write_update_size(inode, pos + copied);
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2299) set_page_dirty(page);
59c3b76cc61d1 (Miklos Szeredi 2016-08-18 09:10:44 +0200 2300)
59c3b76cc61d1 (Miklos Szeredi 2016-08-18 09:10:44 +0200 2301) unlock:
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2302) unlock_page(page);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 2303) put_page(page);
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2304)
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2305) return copied;
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2306) }
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 2307)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2308) static int fuse_launder_page(struct page *page)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2309) {
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2310) int err = 0;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2311) if (clear_page_dirty_for_io(page)) {
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2312) struct inode *inode = page->mapping->host;
3993382bb3198 (Miklos Szeredi 2020-11-11 17:22:31 +0100 2313)
3993382bb3198 (Miklos Szeredi 2020-11-11 17:22:31 +0100 2314) /* Serialize with pending writeback for the same page */
3993382bb3198 (Miklos Szeredi 2020-11-11 17:22:31 +0100 2315) fuse_wait_on_page_writeback(inode, page->index);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2316) err = fuse_writepage_locked(page);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2317) if (!err)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2318) fuse_wait_on_page_writeback(inode, page->index);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2319) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2320) return err;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2321) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2322)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2323) /*
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2324) * Write back dirty pages now, because there may not be any suitable
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2325) * open files later
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2326) */
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2327) static void fuse_vma_close(struct vm_area_struct *vma)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2328) {
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2329) filemap_write_and_wait(vma->vm_file->f_mapping);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2330) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2331)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2332) /*
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2333) * Wait for writeback against this page to complete before allowing it
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2334) * to be marked dirty again, and hence written back again, possibly
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2335) * before the previous writepage completed.
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2336) *
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2337) * Block here, instead of in ->writepage(), so that the userspace fs
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2338) * can only block processes actually operating on the filesystem.
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2339) *
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2340) * Otherwise unprivileged userspace fs would be able to block
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2341) * unrelated:
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2342) *
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2343) * - page migration
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2344) * - sync(2)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2345) * - try_to_free_pages() with order > PAGE_ALLOC_COSTLY_ORDER
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2346) */
46fb504a7145a (Souptick Joarder 2018-05-12 10:25:37 +0530 2347) static vm_fault_t fuse_page_mkwrite(struct vm_fault *vmf)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2348) {
c2ec175c39f62 (Nicholas Piggin 2009-03-31 15:23:21 -0700 2349) struct page *page = vmf->page;
11bac80004499 (Dave Jiang 2017-02-24 14:56:41 -0800 2350) struct inode *inode = file_inode(vmf->vma->vm_file);
cca2437045dda (Miklos Szeredi 2013-10-01 16:44:51 +0200 2351)
11bac80004499 (Dave Jiang 2017-02-24 14:56:41 -0800 2352) file_update_time(vmf->vma->vm_file);
cca2437045dda (Miklos Szeredi 2013-10-01 16:44:51 +0200 2353) lock_page(page);
cca2437045dda (Miklos Szeredi 2013-10-01 16:44:51 +0200 2354) if (page->mapping != inode->i_mapping) {
cca2437045dda (Miklos Szeredi 2013-10-01 16:44:51 +0200 2355) unlock_page(page);
cca2437045dda (Miklos Szeredi 2013-10-01 16:44:51 +0200 2356) return VM_FAULT_NOPAGE;
cca2437045dda (Miklos Szeredi 2013-10-01 16:44:51 +0200 2357) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2358)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2359) fuse_wait_on_page_writeback(inode, page->index);
cca2437045dda (Miklos Szeredi 2013-10-01 16:44:51 +0200 2360) return VM_FAULT_LOCKED;
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2361) }
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2362)
f0f37e2f77731 (Alexey Dobriyan 2009-09-27 22:29:37 +0400 2363) static const struct vm_operations_struct fuse_file_vm_ops = {
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2364) .close = fuse_vma_close,
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2365) .fault = filemap_fault,
f1820361f83d5 (Kirill A. Shutemov 2014-04-07 15:37:19 -0700 2366) .map_pages = filemap_map_pages,
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2367) .page_mkwrite = fuse_page_mkwrite,
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2368) };
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2369)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2370) static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2371) {
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 2372) struct fuse_file *ff = file->private_data;
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 2373)
2a9a609a0c4a3 (Stefan Hajnoczi 2020-08-19 18:19:52 -0400 2374) /* DAX mmap is superior to direct_io mmap */
2a9a609a0c4a3 (Stefan Hajnoczi 2020-08-19 18:19:52 -0400 2375) if (FUSE_IS_DAX(file_inode(file)))
2a9a609a0c4a3 (Stefan Hajnoczi 2020-08-19 18:19:52 -0400 2376) return fuse_dax_mmap(file, vma);
2a9a609a0c4a3 (Stefan Hajnoczi 2020-08-19 18:19:52 -0400 2377)
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 2378) if (ff->open_flags & FOPEN_DIRECT_IO) {
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 2379) /* Can't provide the coherency needed for MAP_SHARED */
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 2380) if (vma->vm_flags & VM_MAYSHARE)
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 2381) return -ENODEV;
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 2382)
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 2383) invalidate_inode_pages2(file->f_mapping);
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 2384)
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 2385) return generic_file_mmap(file, vma);
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 2386) }
55752a3aba138 (Miklos Szeredi 2019-01-24 10:40:17 +0100 2387)
650b22b941fa0 (Pavel Emelyanov 2013-10-10 17:10:04 +0400 2388) if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
650b22b941fa0 (Pavel Emelyanov 2013-10-10 17:10:04 +0400 2389) fuse_link_write_file(file);
650b22b941fa0 (Pavel Emelyanov 2013-10-10 17:10:04 +0400 2390)
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2391) file_accessed(file);
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 2392) vma->vm_ops = &fuse_file_vm_ops;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 2393) return 0;
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 2394) }
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 2395)
0b6e9ea041e6c (Seth Forshee 2014-07-02 16:29:19 -0500 2396) static int convert_fuse_file_lock(struct fuse_conn *fc,
0b6e9ea041e6c (Seth Forshee 2014-07-02 16:29:19 -0500 2397) const struct fuse_file_lock *ffl,
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2398) struct file_lock *fl)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2399) {
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2400) switch (ffl->type) {
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2401) case F_UNLCK:
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2402) break;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2403)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2404) case F_RDLCK:
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2405) case F_WRLCK:
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2406) if (ffl->start > OFFSET_MAX || ffl->end > OFFSET_MAX ||
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2407) ffl->end < ffl->start)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2408) return -EIO;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2409)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2410) fl->fl_start = ffl->start;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2411) fl->fl_end = ffl->end;
0b6e9ea041e6c (Seth Forshee 2014-07-02 16:29:19 -0500 2412)
0b6e9ea041e6c (Seth Forshee 2014-07-02 16:29:19 -0500 2413) /*
9d5b86ac13c57 (Benjamin Coddington 2017-07-16 10:28:22 -0400 2414) * Convert pid into init's pid namespace. The locks API will
9d5b86ac13c57 (Benjamin Coddington 2017-07-16 10:28:22 -0400 2415) * translate it into the caller's pid namespace.
0b6e9ea041e6c (Seth Forshee 2014-07-02 16:29:19 -0500 2416) */
0b6e9ea041e6c (Seth Forshee 2014-07-02 16:29:19 -0500 2417) rcu_read_lock();
9d5b86ac13c57 (Benjamin Coddington 2017-07-16 10:28:22 -0400 2418) fl->fl_pid = pid_nr_ns(find_pid_ns(ffl->pid, fc->pid_ns), &init_pid_ns);
0b6e9ea041e6c (Seth Forshee 2014-07-02 16:29:19 -0500 2419) rcu_read_unlock();
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2420) break;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2421)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2422) default:
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2423) return -EIO;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2424) }
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2425) fl->fl_type = ffl->type;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2426) return 0;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2427) }
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2428)
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2429) static void fuse_lk_fill(struct fuse_args *args, struct file *file,
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2430) const struct file_lock *fl, int opcode, pid_t pid,
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2431) int flock, struct fuse_lk_in *inarg)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2432) {
6131ffaa1f091 (Al Viro 2013-02-27 16:59:05 -0500 2433) struct inode *inode = file_inode(file);
9c8ef5614da22 (Miklos Szeredi 2006-06-25 05:48:55 -0700 2434) struct fuse_conn *fc = get_fuse_conn(inode);
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2435) struct fuse_file *ff = file->private_data;
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2436)
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2437) memset(inarg, 0, sizeof(*inarg));
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2438) inarg->fh = ff->fh;
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2439) inarg->owner = fuse_lock_owner_id(fc, fl->fl_owner);
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2440) inarg->lk.start = fl->fl_start;
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2441) inarg->lk.end = fl->fl_end;
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2442) inarg->lk.type = fl->fl_type;
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2443) inarg->lk.pid = pid;
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2444) if (flock)
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2445) inarg->lk_flags |= FUSE_LK_FLOCK;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2446) args->opcode = opcode;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2447) args->nodeid = get_node_id(inode);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2448) args->in_numargs = 1;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2449) args->in_args[0].size = sizeof(*inarg);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2450) args->in_args[0].value = inarg;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2451) }
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2452)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2453) static int fuse_getlk(struct file *file, struct file_lock *fl)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2454) {
6131ffaa1f091 (Al Viro 2013-02-27 16:59:05 -0500 2455) struct inode *inode = file_inode(file);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2456) struct fuse_mount *fm = get_fuse_mount(inode);
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2457) FUSE_ARGS(args);
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2458) struct fuse_lk_in inarg;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2459) struct fuse_lk_out outarg;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2460) int err;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2461)
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2462) fuse_lk_fill(&args, file, fl, FUSE_GETLK, 0, 0, &inarg);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2463) args.out_numargs = 1;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2464) args.out_args[0].size = sizeof(outarg);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2465) args.out_args[0].value = &outarg;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2466) err = fuse_simple_request(fm, &args);
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2467) if (!err)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2468) err = convert_fuse_file_lock(fm->fc, &outarg.lk, fl);
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2469)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2470) return err;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2471) }
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2472)
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2473) static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2474) {
6131ffaa1f091 (Al Viro 2013-02-27 16:59:05 -0500 2475) struct inode *inode = file_inode(file);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2476) struct fuse_mount *fm = get_fuse_mount(inode);
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2477) FUSE_ARGS(args);
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2478) struct fuse_lk_in inarg;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2479) int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
0b6e9ea041e6c (Seth Forshee 2014-07-02 16:29:19 -0500 2480) struct pid *pid = fl->fl_type != F_UNLCK ? task_tgid(current) : NULL;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2481) pid_t pid_nr = pid_nr_ns(pid, fm->fc->pid_ns);
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2482) int err;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2483)
8fb47a4fbf858 (J. Bruce Fields 2011-07-20 20:21:59 -0400 2484) if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
48e90761b570f (Miklos Szeredi 2008-07-25 01:49:02 -0700 2485) /* NLM needs asynchronous locks, which we don't support yet */
48e90761b570f (Miklos Szeredi 2008-07-25 01:49:02 -0700 2486) return -ENOLCK;
48e90761b570f (Miklos Szeredi 2008-07-25 01:49:02 -0700 2487) }
48e90761b570f (Miklos Szeredi 2008-07-25 01:49:02 -0700 2488)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2489) /* Unlock on close is handled by the flush method */
50f2112cf7a3e (Benjamin Coddington 2017-04-11 12:50:09 -0400 2490) if ((fl->fl_flags & FL_CLOSE_POSIX) == FL_CLOSE_POSIX)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2491) return 0;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2492)
0b6e9ea041e6c (Seth Forshee 2014-07-02 16:29:19 -0500 2493) fuse_lk_fill(&args, file, fl, opcode, pid_nr, flock, &inarg);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2494) err = fuse_simple_request(fm, &args);
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2495)
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 2496) /* locking is restartable */
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 2497) if (err == -EINTR)
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 2498) err = -ERESTARTSYS;
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2499)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2500) return err;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2501) }
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2502)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2503) static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2504) {
6131ffaa1f091 (Al Viro 2013-02-27 16:59:05 -0500 2505) struct inode *inode = file_inode(file);
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2506) struct fuse_conn *fc = get_fuse_conn(inode);
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2507) int err;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2508)
48e90761b570f (Miklos Szeredi 2008-07-25 01:49:02 -0700 2509) if (cmd == F_CANCELLK) {
48e90761b570f (Miklos Szeredi 2008-07-25 01:49:02 -0700 2510) err = 0;
48e90761b570f (Miklos Szeredi 2008-07-25 01:49:02 -0700 2511) } else if (cmd == F_GETLK) {
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2512) if (fc->no_lock) {
9d6a8c5c213e3 (Marc Eshel 2007-02-21 00:55:18 -0500 2513) posix_test_lock(file, fl);
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2514) err = 0;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2515) } else
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2516) err = fuse_getlk(file, fl);
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2517) } else {
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2518) if (fc->no_lock)
48e90761b570f (Miklos Szeredi 2008-07-25 01:49:02 -0700 2519) err = posix_lock_file(file, fl, NULL);
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2520) else
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2521) err = fuse_setlk(file, fl, 0);
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2522) }
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2523) return err;
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2524) }
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 2525)
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2526) static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl)
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2527) {
6131ffaa1f091 (Al Viro 2013-02-27 16:59:05 -0500 2528) struct inode *inode = file_inode(file);
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2529) struct fuse_conn *fc = get_fuse_conn(inode);
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2530) int err;
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2531)
37fb3a30b4623 (Miklos Szeredi 2011-08-08 16:08:08 +0200 2532) if (fc->no_flock) {
4f6563677ae83 (Benjamin Coddington 2015-10-22 13:38:14 -0400 2533) err = locks_lock_file_wait(file, fl);
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2534) } else {
37fb3a30b4623 (Miklos Szeredi 2011-08-08 16:08:08 +0200 2535) struct fuse_file *ff = file->private_data;
37fb3a30b4623 (Miklos Szeredi 2011-08-08 16:08:08 +0200 2536)
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2537) /* emulate flock with POSIX locks */
37fb3a30b4623 (Miklos Szeredi 2011-08-08 16:08:08 +0200 2538) ff->flock = true;
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2539) err = fuse_setlk(file, fl, 1);
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2540) }
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2541)
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2542) return err;
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2543) }
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 2544)
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2545) static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2546) {
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2547) struct inode *inode = mapping->host;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2548) struct fuse_mount *fm = get_fuse_mount(inode);
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2549) FUSE_ARGS(args);
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2550) struct fuse_bmap_in inarg;
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2551) struct fuse_bmap_out outarg;
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2552) int err;
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2553)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2554) if (!inode->i_sb->s_bdev || fm->fc->no_bmap)
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2555) return 0;
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2556)
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2557) memset(&inarg, 0, sizeof(inarg));
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2558) inarg.block = block;
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2559) inarg.blocksize = inode->i_sb->s_blocksize;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2560) args.opcode = FUSE_BMAP;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2561) args.nodeid = get_node_id(inode);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2562) args.in_numargs = 1;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2563) args.in_args[0].size = sizeof(inarg);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2564) args.in_args[0].value = &inarg;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2565) args.out_numargs = 1;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2566) args.out_args[0].size = sizeof(outarg);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2567) args.out_args[0].value = &outarg;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2568) err = fuse_simple_request(fm, &args);
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2569) if (err == -ENOSYS)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2570) fm->fc->no_bmap = 1;
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2571)
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2572) return err ? 0 : outarg.block;
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2573) }
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 2574)
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2575) static loff_t fuse_lseek(struct file *file, loff_t offset, int whence)
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2576) {
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2577) struct inode *inode = file->f_mapping->host;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2578) struct fuse_mount *fm = get_fuse_mount(inode);
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2579) struct fuse_file *ff = file->private_data;
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2580) FUSE_ARGS(args);
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2581) struct fuse_lseek_in inarg = {
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2582) .fh = ff->fh,
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2583) .offset = offset,
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2584) .whence = whence
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2585) };
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2586) struct fuse_lseek_out outarg;
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2587) int err;
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2588)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2589) if (fm->fc->no_lseek)
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2590) goto fallback;
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2591)
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2592) args.opcode = FUSE_LSEEK;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2593) args.nodeid = ff->nodeid;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2594) args.in_numargs = 1;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2595) args.in_args[0].size = sizeof(inarg);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2596) args.in_args[0].value = &inarg;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2597) args.out_numargs = 1;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2598) args.out_args[0].size = sizeof(outarg);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2599) args.out_args[0].value = &outarg;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2600) err = fuse_simple_request(fm, &args);
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2601) if (err) {
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2602) if (err == -ENOSYS) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2603) fm->fc->no_lseek = 1;
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2604) goto fallback;
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2605) }
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2606) return err;
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2607) }
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2608)
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2609) return vfs_setpos(file, outarg.offset, inode->i_sb->s_maxbytes);
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2610)
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2611) fallback:
5b97eeacbd80a (Miklos Szeredi 2017-09-12 16:57:54 +0200 2612) err = fuse_update_attributes(inode, file);
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2613) if (!err)
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2614) return generic_file_llseek(file, offset, whence);
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2615) else
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2616) return err;
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2617) }
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2618)
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 2619) static loff_t fuse_file_llseek(struct file *file, loff_t offset, int whence)
5559b8f4d1f63 (Miklos Szeredi 2008-04-30 00:54:45 -0700 2620) {
5559b8f4d1f63 (Miklos Szeredi 2008-04-30 00:54:45 -0700 2621) loff_t retval;
6131ffaa1f091 (Al Viro 2013-02-27 16:59:05 -0500 2622) struct inode *inode = file_inode(file);
5559b8f4d1f63 (Miklos Szeredi 2008-04-30 00:54:45 -0700 2623)
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2624) switch (whence) {
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2625) case SEEK_SET:
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2626) case SEEK_CUR:
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2627) /* No i_mutex protection necessary for SEEK_CUR and SEEK_SET */
965c8e59cfcf8 (Andrew Morton 2012-12-17 15:59:39 -0800 2628) retval = generic_file_llseek(file, offset, whence);
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2629) break;
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2630) case SEEK_END:
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 2631) inode_lock(inode);
5b97eeacbd80a (Miklos Szeredi 2017-09-12 16:57:54 +0200 2632) retval = fuse_update_attributes(inode, file);
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2633) if (!retval)
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2634) retval = generic_file_llseek(file, offset, whence);
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 2635) inode_unlock(inode);
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2636) break;
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2637) case SEEK_HOLE:
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2638) case SEEK_DATA:
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 2639) inode_lock(inode);
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2640) retval = fuse_lseek(file, offset, whence);
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 2641) inode_unlock(inode);
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2642) break;
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2643) default:
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2644) retval = -EINVAL;
0b5da8db145bf (Ravishankar N 2015-06-30 23:40:22 +0530 2645) }
c07c3d193412b (Miklos Szeredi 2011-12-13 11:58:48 +0100 2646)
5559b8f4d1f63 (Miklos Szeredi 2008-04-30 00:54:45 -0700 2647) return retval;
5559b8f4d1f63 (Miklos Szeredi 2008-04-30 00:54:45 -0700 2648) }
5559b8f4d1f63 (Miklos Szeredi 2008-04-30 00:54:45 -0700 2649)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2650) /*
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2651) * All files which have been polled are linked to RB tree
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2652) * fuse_conn->polled_files which is indexed by kh. Walk the tree and
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2653) * find the matching one.
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2654) */
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2655) static struct rb_node **fuse_find_polled_node(struct fuse_conn *fc, u64 kh,
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2656) struct rb_node **parent_out)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2657) {
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2658) struct rb_node **link = &fc->polled_files.rb_node;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2659) struct rb_node *last = NULL;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2660)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2661) while (*link) {
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2662) struct fuse_file *ff;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2663)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2664) last = *link;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2665) ff = rb_entry(last, struct fuse_file, polled_node);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2666)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2667) if (kh < ff->kh)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2668) link = &last->rb_left;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2669) else if (kh > ff->kh)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2670) link = &last->rb_right;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2671) else
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2672) return link;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2673) }
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2674)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2675) if (parent_out)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2676) *parent_out = last;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2677) return link;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2678) }
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2679)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2680) /*
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2681) * The file is about to be polled. Make sure it's on the polled_files
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2682) * RB tree. Note that files once added to the polled_files tree are
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2683) * not removed before the file is released. This is because a file
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2684) * polled once is likely to be polled again.
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2685) */
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2686) static void fuse_register_polled_file(struct fuse_conn *fc,
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2687) struct fuse_file *ff)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2688) {
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2689) spin_lock(&fc->lock);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2690) if (RB_EMPTY_NODE(&ff->polled_node)) {
3f649ab728cda (Kees Cook 2020-06-03 13:09:38 -0700 2691) struct rb_node **link, *parent;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2692)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2693) link = fuse_find_polled_node(fc, ff->kh, &parent);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2694) BUG_ON(*link);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2695) rb_link_node(&ff->polled_node, parent, link);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2696) rb_insert_color(&ff->polled_node, &fc->polled_files);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2697) }
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2698) spin_unlock(&fc->lock);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2699) }
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2700)
076ccb76e1a6c (Al Viro 2017-07-03 01:02:18 -0400 2701) __poll_t fuse_file_poll(struct file *file, poll_table *wait)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2702) {
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2703) struct fuse_file *ff = file->private_data;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2704) struct fuse_mount *fm = ff->fm;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2705) struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh };
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2706) struct fuse_poll_out outarg;
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2707) FUSE_ARGS(args);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2708) int err;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2709)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2710) if (fm->fc->no_poll)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2711) return DEFAULT_POLLMASK;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2712)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2713) poll_wait(file, &ff->poll_wait, wait);
c71d227fc4133 (Al Viro 2017-11-29 19:00:41 -0500 2714) inarg.events = mangle_poll(poll_requested_events(wait));
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2715)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2716) /*
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2717) * Ask for notification iff there's someone waiting for it.
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2718) * The client may ignore the flag and always notify.
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2719) */
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2720) if (waitqueue_active(&ff->poll_wait)) {
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2721) inarg.flags |= FUSE_POLL_SCHEDULE_NOTIFY;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2722) fuse_register_polled_file(fm->fc, ff);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2723) }
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2724)
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2725) args.opcode = FUSE_POLL;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2726) args.nodeid = ff->nodeid;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2727) args.in_numargs = 1;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2728) args.in_args[0].size = sizeof(inarg);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2729) args.in_args[0].value = &inarg;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2730) args.out_numargs = 1;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2731) args.out_args[0].size = sizeof(outarg);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2732) args.out_args[0].value = &outarg;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2733) err = fuse_simple_request(fm, &args);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2734)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2735) if (!err)
c71d227fc4133 (Al Viro 2017-11-29 19:00:41 -0500 2736) return demangle_poll(outarg.revents);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2737) if (err == -ENOSYS) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2738) fm->fc->no_poll = 1;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2739) return DEFAULT_POLLMASK;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2740) }
a9a08845e9acb (Linus Torvalds 2018-02-11 14:34:03 -0800 2741) return EPOLLERR;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2742) }
08cbf542bf24f (Tejun Heo 2009-04-14 10:54:53 +0900 2743) EXPORT_SYMBOL_GPL(fuse_file_poll);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2744)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2745) /*
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2746) * This is called from fuse_handle_notify() on FUSE_NOTIFY_POLL and
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2747) * wakes up the poll waiters.
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2748) */
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2749) int fuse_notify_poll_wakeup(struct fuse_conn *fc,
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2750) struct fuse_notify_poll_wakeup_out *outarg)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2751) {
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2752) u64 kh = outarg->kh;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2753) struct rb_node **link;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2754)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2755) spin_lock(&fc->lock);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2756)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2757) link = fuse_find_polled_node(fc, kh, NULL);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2758) if (*link) {
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2759) struct fuse_file *ff;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2760)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2761) ff = rb_entry(*link, struct fuse_file, polled_node);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2762) wake_up_interruptible_sync(&ff->poll_wait);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2763) }
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2764)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2765) spin_unlock(&fc->lock);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2766) return 0;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2767) }
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 2768)
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2769) static void fuse_do_truncate(struct file *file)
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2770) {
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2771) struct inode *inode = file->f_mapping->host;
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2772) struct iattr attr;
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2773)
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2774) attr.ia_valid = ATTR_SIZE;
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2775) attr.ia_size = i_size_read(inode);
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2776)
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2777) attr.ia_file = file;
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2778) attr.ia_valid |= ATTR_FILE;
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2779)
62490330769c1 (Jan Kara 2016-05-26 17:12:41 +0200 2780) fuse_do_setattr(file_dentry(file), &attr, file);
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2781) }
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2782)
5da784cce4308 (Constantine Shulyupin 2018-09-06 15:37:06 +0300 2783) static inline loff_t fuse_round_up(struct fuse_conn *fc, loff_t off)
e5c5f05dca0cf (Maxim Patlasov 2013-05-30 16:41:34 +0400 2784) {
5da784cce4308 (Constantine Shulyupin 2018-09-06 15:37:06 +0300 2785) return round_up(off, fc->max_pages << PAGE_SHIFT);
e5c5f05dca0cf (Maxim Patlasov 2013-05-30 16:41:34 +0400 2786) }
e5c5f05dca0cf (Maxim Patlasov 2013-05-30 16:41:34 +0400 2787)
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 2788) static ssize_t
c8b8e32d700fe (Christoph Hellwig 2016-04-07 08:51:58 -0700 2789) fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 2790) {
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 2791) DECLARE_COMPLETION_ONSTACK(wait);
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 2792) ssize_t ret = 0;
60b9df7a54804 (Miklos Szeredi 2013-05-01 14:37:21 +0200 2793) struct file *file = iocb->ki_filp;
60b9df7a54804 (Miklos Szeredi 2013-05-01 14:37:21 +0200 2794) struct fuse_file *ff = file->private_data;
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 2795) loff_t pos = 0;
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2796) struct inode *inode;
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2797) loff_t i_size;
933a3752babcf (Al Viro 2020-09-17 17:26:56 -0400 2798) size_t count = iov_iter_count(iter), shortened = 0;
c8b8e32d700fe (Christoph Hellwig 2016-04-07 08:51:58 -0700 2799) loff_t offset = iocb->ki_pos;
36cf66ed9f871 (Maxim Patlasov 2012-12-14 19:20:51 +0400 2800) struct fuse_io_priv *io;
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 2801)
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 2802) pos = offset;
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2803) inode = file->f_mapping->host;
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2804) i_size = i_size_read(inode);
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 2805)
933a3752babcf (Al Viro 2020-09-17 17:26:56 -0400 2806) if ((iov_iter_rw(iter) == READ) && (offset >= i_size))
9fe55eea7e4b4 (Steven Whitehouse 2014-01-24 14:42:22 +0000 2807) return 0;
9fe55eea7e4b4 (Steven Whitehouse 2014-01-24 14:42:22 +0000 2808)
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2809) io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL);
36cf66ed9f871 (Maxim Patlasov 2012-12-14 19:20:51 +0400 2810) if (!io)
36cf66ed9f871 (Maxim Patlasov 2012-12-14 19:20:51 +0400 2811) return -ENOMEM;
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2812) spin_lock_init(&io->lock);
744742d692e37 (Seth Forshee 2016-03-11 10:35:34 -0600 2813) kref_init(&io->refcnt);
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2814) io->reqs = 1;
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2815) io->bytes = -1;
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2816) io->size = 0;
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2817) io->offset = offset;
6f67376318abe (Omar Sandoval 2015-03-16 04:33:52 -0700 2818) io->write = (iov_iter_rw(iter) == WRITE);
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2819) io->err = 0;
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2820) /*
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2821) * By default, we want to optimize all I/Os with async request
60b9df7a54804 (Miklos Szeredi 2013-05-01 14:37:21 +0200 2822) * submission to the client filesystem if supported.
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2823) */
694565356c2e0 (Linus Torvalds 2020-10-19 14:28:30 -0700 2824) io->async = ff->fm->fc->async_dio;
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2825) io->iocb = iocb;
7879c4e58b7c8 (Ashish Sangwan 2016-04-07 17:18:11 +0530 2826) io->blocking = is_sync_kiocb(iocb);
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2827)
933a3752babcf (Al Viro 2020-09-17 17:26:56 -0400 2828) /* optimization for short read */
933a3752babcf (Al Viro 2020-09-17 17:26:56 -0400 2829) if (io->async && !io->write && offset + count > i_size) {
694565356c2e0 (Linus Torvalds 2020-10-19 14:28:30 -0700 2830) iov_iter_truncate(iter, fuse_round_up(ff->fm->fc, i_size - offset));
933a3752babcf (Al Viro 2020-09-17 17:26:56 -0400 2831) shortened = count - iov_iter_count(iter);
933a3752babcf (Al Viro 2020-09-17 17:26:56 -0400 2832) count -= shortened;
933a3752babcf (Al Viro 2020-09-17 17:26:56 -0400 2833) }
933a3752babcf (Al Viro 2020-09-17 17:26:56 -0400 2834)
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2835) /*
7879c4e58b7c8 (Ashish Sangwan 2016-04-07 17:18:11 +0530 2836) * We cannot asynchronously extend the size of a file.
7879c4e58b7c8 (Ashish Sangwan 2016-04-07 17:18:11 +0530 2837) * In such case the aio will behave exactly like sync io.
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2838) */
933a3752babcf (Al Viro 2020-09-17 17:26:56 -0400 2839) if ((offset + count > i_size) && io->write)
7879c4e58b7c8 (Ashish Sangwan 2016-04-07 17:18:11 +0530 2840) io->blocking = true;
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 2841)
7879c4e58b7c8 (Ashish Sangwan 2016-04-07 17:18:11 +0530 2842) if (io->async && io->blocking) {
744742d692e37 (Seth Forshee 2016-03-11 10:35:34 -0600 2843) /*
744742d692e37 (Seth Forshee 2016-03-11 10:35:34 -0600 2844) * Additional reference to keep io around after
744742d692e37 (Seth Forshee 2016-03-11 10:35:34 -0600 2845) * calling fuse_aio_complete()
744742d692e37 (Seth Forshee 2016-03-11 10:35:34 -0600 2846) */
744742d692e37 (Seth Forshee 2016-03-11 10:35:34 -0600 2847) kref_get(&io->refcnt);
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 2848) io->done = &wait;
744742d692e37 (Seth Forshee 2016-03-11 10:35:34 -0600 2849) }
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 2850)
6f67376318abe (Omar Sandoval 2015-03-16 04:33:52 -0700 2851) if (iov_iter_rw(iter) == WRITE) {
6b775b18eecf6 (Al Viro 2015-04-07 15:06:19 -0400 2852) ret = fuse_direct_io(io, iter, &pos, FUSE_DIO_WRITE);
812408fb51ef5 (Al Viro 2015-03-30 22:15:58 -0400 2853) fuse_invalidate_attr(inode);
812408fb51ef5 (Al Viro 2015-03-30 22:15:58 -0400 2854) } else {
d22a943f44c79 (Al Viro 2014-03-16 15:50:47 -0400 2855) ret = __fuse_direct_read(io, iter, &pos);
812408fb51ef5 (Al Viro 2015-03-30 22:15:58 -0400 2856) }
933a3752babcf (Al Viro 2020-09-17 17:26:56 -0400 2857) iov_iter_reexpand(iter, iov_iter_count(iter) + shortened);
36cf66ed9f871 (Maxim Patlasov 2012-12-14 19:20:51 +0400 2858)
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2859) if (io->async) {
ebacb81273599 (Lukas Czerner 2018-11-09 14:51:46 +0100 2860) bool blocking = io->blocking;
ebacb81273599 (Lukas Czerner 2018-11-09 14:51:46 +0100 2861)
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2862) fuse_aio_complete(io, ret < 0 ? ret : 0, -1);
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2863)
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2864) /* we have a non-extending, async request, so return */
ebacb81273599 (Lukas Czerner 2018-11-09 14:51:46 +0100 2865) if (!blocking)
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2866) return -EIOCBQUEUED;
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2867)
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 2868) wait_for_completion(&wait);
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 2869) ret = fuse_get_res_by_io(io);
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2870) }
bcba24ccdc82f (Maxim Patlasov 2012-12-14 19:21:08 +0400 2871)
744742d692e37 (Seth Forshee 2016-03-11 10:35:34 -0600 2872) kref_put(&io->refcnt, fuse_io_release);
9d5722b7777e6 (Christoph Hellwig 2015-02-02 14:59:43 +0100 2873)
6f67376318abe (Omar Sandoval 2015-03-16 04:33:52 -0700 2874) if (iov_iter_rw(iter) == WRITE) {
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2875) if (ret > 0)
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2876) fuse_write_update_size(inode, pos);
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2877) else if (ret < 0 && offset + count > i_size)
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2878) fuse_do_truncate(file);
efb9fa9e911b2 (Maxim Patlasov 2012-12-18 14:05:08 +0400 2879) }
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 2880)
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 2881) return ret;
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 2882) }
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 2883)
26eb3bae50035 (Miklos Szeredi 2019-05-28 13:22:50 +0200 2884) static int fuse_writeback_range(struct inode *inode, loff_t start, loff_t end)
26eb3bae50035 (Miklos Szeredi 2019-05-28 13:22:50 +0200 2885) {
26eb3bae50035 (Miklos Szeredi 2019-05-28 13:22:50 +0200 2886) int err = filemap_write_and_wait_range(inode->i_mapping, start, end);
26eb3bae50035 (Miklos Szeredi 2019-05-28 13:22:50 +0200 2887)
26eb3bae50035 (Miklos Szeredi 2019-05-28 13:22:50 +0200 2888) if (!err)
26eb3bae50035 (Miklos Szeredi 2019-05-28 13:22:50 +0200 2889) fuse_sync_writes(inode);
26eb3bae50035 (Miklos Szeredi 2019-05-28 13:22:50 +0200 2890)
26eb3bae50035 (Miklos Szeredi 2019-05-28 13:22:50 +0200 2891) return err;
26eb3bae50035 (Miklos Szeredi 2019-05-28 13:22:50 +0200 2892) }
26eb3bae50035 (Miklos Szeredi 2019-05-28 13:22:50 +0200 2893)
cdadb11cef180 (Miklos Szeredi 2012-11-10 16:55:56 +0100 2894) static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
cdadb11cef180 (Miklos Szeredi 2012-11-10 16:55:56 +0100 2895) loff_t length)
05ba1f0823004 (Anatol Pomozov 2012-04-22 18:45:24 -0700 2896) {
05ba1f0823004 (Anatol Pomozov 2012-04-22 18:45:24 -0700 2897) struct fuse_file *ff = file->private_data;
1c68271cf1bfe (Miklos Szeredi 2014-12-12 10:04:51 +0100 2898) struct inode *inode = file_inode(file);
0ab08f576b9e6 (Maxim Patlasov 2013-09-13 19:20:16 +0400 2899) struct fuse_inode *fi = get_fuse_inode(inode);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2900) struct fuse_mount *fm = ff->fm;
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 2901) FUSE_ARGS(args);
05ba1f0823004 (Anatol Pomozov 2012-04-22 18:45:24 -0700 2902) struct fuse_fallocate_in inarg = {
05ba1f0823004 (Anatol Pomozov 2012-04-22 18:45:24 -0700 2903) .fh = ff->fh,
05ba1f0823004 (Anatol Pomozov 2012-04-22 18:45:24 -0700 2904) .offset = offset,
05ba1f0823004 (Anatol Pomozov 2012-04-22 18:45:24 -0700 2905) .length = length,
05ba1f0823004 (Anatol Pomozov 2012-04-22 18:45:24 -0700 2906) .mode = mode
05ba1f0823004 (Anatol Pomozov 2012-04-22 18:45:24 -0700 2907) };
05ba1f0823004 (Anatol Pomozov 2012-04-22 18:45:24 -0700 2908) int err;
14c14414d157e (Maxim Patlasov 2013-06-13 12:16:39 +0400 2909) bool lock_inode = !(mode & FALLOC_FL_KEEP_SIZE) ||
14c14414d157e (Maxim Patlasov 2013-06-13 12:16:39 +0400 2910) (mode & FALLOC_FL_PUNCH_HOLE);
05ba1f0823004 (Anatol Pomozov 2012-04-22 18:45:24 -0700 2911)
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 2912) bool block_faults = FUSE_IS_DAX(inode) && lock_inode;
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 2913)
4adb83029de8e (Miklos Szeredi 2014-04-28 14:19:21 +0200 2914) if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
4adb83029de8e (Miklos Szeredi 2014-04-28 14:19:21 +0200 2915) return -EOPNOTSUPP;
4adb83029de8e (Miklos Szeredi 2014-04-28 14:19:21 +0200 2916)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2917) if (fm->fc->no_fallocate)
519c6040ce044 (Miklos Szeredi 2012-04-26 10:56:36 +0200 2918) return -EOPNOTSUPP;
519c6040ce044 (Miklos Szeredi 2012-04-26 10:56:36 +0200 2919)
14c14414d157e (Maxim Patlasov 2013-06-13 12:16:39 +0400 2920) if (lock_inode) {
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 2921) inode_lock(inode);
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 2922) if (block_faults) {
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 2923) down_write(&fi->i_mmap_sem);
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 2924) err = fuse_dax_break_layouts(inode, 0, 0);
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 2925) if (err)
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 2926) goto out;
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 2927) }
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 2928)
bde52788bdb75 (Maxim Patlasov 2013-09-13 19:19:54 +0400 2929) if (mode & FALLOC_FL_PUNCH_HOLE) {
bde52788bdb75 (Maxim Patlasov 2013-09-13 19:19:54 +0400 2930) loff_t endbyte = offset + length - 1;
26eb3bae50035 (Miklos Szeredi 2019-05-28 13:22:50 +0200 2931)
26eb3bae50035 (Miklos Szeredi 2019-05-28 13:22:50 +0200 2932) err = fuse_writeback_range(inode, offset, endbyte);
bde52788bdb75 (Maxim Patlasov 2013-09-13 19:19:54 +0400 2933) if (err)
bde52788bdb75 (Maxim Patlasov 2013-09-13 19:19:54 +0400 2934) goto out;
bde52788bdb75 (Maxim Patlasov 2013-09-13 19:19:54 +0400 2935) }
3634a6327815d (Brian Foster 2013-05-17 09:30:32 -0400 2936) }
3634a6327815d (Brian Foster 2013-05-17 09:30:32 -0400 2937)
0cbade024ba50 (Liu Bo 2019-04-18 04:04:41 +0800 2938) if (!(mode & FALLOC_FL_KEEP_SIZE) &&
0cbade024ba50 (Liu Bo 2019-04-18 04:04:41 +0800 2939) offset + length > i_size_read(inode)) {
0cbade024ba50 (Liu Bo 2019-04-18 04:04:41 +0800 2940) err = inode_newsize_ok(inode, offset + length);
0cbade024ba50 (Liu Bo 2019-04-18 04:04:41 +0800 2941) if (err)
35d6fcbb7c3e2 (Miklos Szeredi 2019-05-27 11:42:07 +0200 2942) goto out;
0cbade024ba50 (Liu Bo 2019-04-18 04:04:41 +0800 2943) }
0cbade024ba50 (Liu Bo 2019-04-18 04:04:41 +0800 2944)
0ab08f576b9e6 (Maxim Patlasov 2013-09-13 19:20:16 +0400 2945) if (!(mode & FALLOC_FL_KEEP_SIZE))
0ab08f576b9e6 (Maxim Patlasov 2013-09-13 19:20:16 +0400 2946) set_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
0ab08f576b9e6 (Maxim Patlasov 2013-09-13 19:20:16 +0400 2947)
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2948) args.opcode = FUSE_FALLOCATE;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2949) args.nodeid = ff->nodeid;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2950) args.in_numargs = 1;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2951) args.in_args[0].size = sizeof(inarg);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 2952) args.in_args[0].value = &inarg;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2953) err = fuse_simple_request(fm, &args);
519c6040ce044 (Miklos Szeredi 2012-04-26 10:56:36 +0200 2954) if (err == -ENOSYS) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2955) fm->fc->no_fallocate = 1;
519c6040ce044 (Miklos Szeredi 2012-04-26 10:56:36 +0200 2956) err = -EOPNOTSUPP;
519c6040ce044 (Miklos Szeredi 2012-04-26 10:56:36 +0200 2957) }
bee6c307800bb (Brian Foster 2013-05-17 15:27:34 -0400 2958) if (err)
bee6c307800bb (Brian Foster 2013-05-17 15:27:34 -0400 2959) goto out;
bee6c307800bb (Brian Foster 2013-05-17 15:27:34 -0400 2960)
bee6c307800bb (Brian Foster 2013-05-17 15:27:34 -0400 2961) /* we could have extended the file */
b0aa760652179 (Maxim Patlasov 2013-12-26 19:51:11 +0400 2962) if (!(mode & FALLOC_FL_KEEP_SIZE)) {
b0aa760652179 (Maxim Patlasov 2013-12-26 19:51:11 +0400 2963) bool changed = fuse_write_update_size(inode, offset + length);
b0aa760652179 (Maxim Patlasov 2013-12-26 19:51:11 +0400 2964)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2965) if (changed && fm->fc->writeback_cache)
93d2269d2ffb8 (Miklos Szeredi 2014-04-28 14:19:22 +0200 2966) file_update_time(file);
b0aa760652179 (Maxim Patlasov 2013-12-26 19:51:11 +0400 2967) }
bee6c307800bb (Brian Foster 2013-05-17 15:27:34 -0400 2968)
bee6c307800bb (Brian Foster 2013-05-17 15:27:34 -0400 2969) if (mode & FALLOC_FL_PUNCH_HOLE)
bee6c307800bb (Brian Foster 2013-05-17 15:27:34 -0400 2970) truncate_pagecache_range(inode, offset, offset + length - 1);
bee6c307800bb (Brian Foster 2013-05-17 15:27:34 -0400 2971)
bee6c307800bb (Brian Foster 2013-05-17 15:27:34 -0400 2972) fuse_invalidate_attr(inode);
bee6c307800bb (Brian Foster 2013-05-17 15:27:34 -0400 2973)
3634a6327815d (Brian Foster 2013-05-17 09:30:32 -0400 2974) out:
0ab08f576b9e6 (Maxim Patlasov 2013-09-13 19:20:16 +0400 2975) if (!(mode & FALLOC_FL_KEEP_SIZE))
0ab08f576b9e6 (Maxim Patlasov 2013-09-13 19:20:16 +0400 2976) clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
0ab08f576b9e6 (Maxim Patlasov 2013-09-13 19:20:16 +0400 2977)
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 2978) if (block_faults)
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 2979) up_write(&fi->i_mmap_sem);
6ae330cad6ef2 (Vivek Goyal 2020-08-19 18:19:54 -0400 2980)
bde52788bdb75 (Maxim Patlasov 2013-09-13 19:19:54 +0400 2981) if (lock_inode)
5955102c9984f (Al Viro 2016-01-22 15:40:57 -0500 2982) inode_unlock(inode);
3634a6327815d (Brian Foster 2013-05-17 09:30:32 -0400 2983)
05ba1f0823004 (Anatol Pomozov 2012-04-22 18:45:24 -0700 2984) return err;
05ba1f0823004 (Anatol Pomozov 2012-04-22 18:45:24 -0700 2985) }
05ba1f0823004 (Anatol Pomozov 2012-04-22 18:45:24 -0700 2986)
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 2987) static ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in,
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 2988) struct file *file_out, loff_t pos_out,
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 2989) size_t len, unsigned int flags)
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 2990) {
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 2991) struct fuse_file *ff_in = file_in->private_data;
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 2992) struct fuse_file *ff_out = file_out->private_data;
a2bc923629410 (Miklos Szeredi 2019-05-28 13:22:50 +0200 2993) struct inode *inode_in = file_inode(file_in);
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 2994) struct inode *inode_out = file_inode(file_out);
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 2995) struct fuse_inode *fi_out = get_fuse_inode(inode_out);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2996) struct fuse_mount *fm = ff_in->fm;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 2997) struct fuse_conn *fc = fm->fc;
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 2998) FUSE_ARGS(args);
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 2999) struct fuse_copy_file_range_in inarg = {
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3000) .fh_in = ff_in->fh,
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3001) .off_in = pos_in,
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3002) .nodeid_out = ff_out->nodeid,
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3003) .fh_out = ff_out->fh,
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3004) .off_out = pos_out,
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3005) .len = len,
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3006) .flags = flags
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3007) };
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3008) struct fuse_write_out outarg;
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3009) ssize_t err;
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3010) /* mark unstable when write-back is not used, and file_out gets
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3011) * extended */
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3012) bool is_unstable = (!fc->writeback_cache) &&
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3013) ((pos_out + len) > inode_out->i_size);
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3014)
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3015) if (fc->no_copy_file_range)
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3016) return -EOPNOTSUPP;
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3017)
5dae222a5ff0c (Amir Goldstein 2019-06-05 08:04:50 -0700 3018) if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb)
5dae222a5ff0c (Amir Goldstein 2019-06-05 08:04:50 -0700 3019) return -EXDEV;
5dae222a5ff0c (Amir Goldstein 2019-06-05 08:04:50 -0700 3020)
2c4656dfd9945 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3021) inode_lock(inode_in);
2c4656dfd9945 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3022) err = fuse_writeback_range(inode_in, pos_in, pos_in + len - 1);
2c4656dfd9945 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3023) inode_unlock(inode_in);
2c4656dfd9945 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3024) if (err)
2c4656dfd9945 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3025) return err;
a2bc923629410 (Miklos Szeredi 2019-05-28 13:22:50 +0200 3026)
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3027) inode_lock(inode_out);
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3028)
fe0da9c09b2dc (Amir Goldstein 2019-06-05 08:04:51 -0700 3029) err = file_modified(file_out);
fe0da9c09b2dc (Amir Goldstein 2019-06-05 08:04:51 -0700 3030) if (err)
fe0da9c09b2dc (Amir Goldstein 2019-06-05 08:04:51 -0700 3031) goto out;
fe0da9c09b2dc (Amir Goldstein 2019-06-05 08:04:51 -0700 3032)
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3033) /*
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3034) * Write out dirty pages in the destination file before sending the COPY
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3035) * request to userspace. After the request is completed, truncate off
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3036) * pages (including partial ones) from the cache that have been copied,
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3037) * since these contain stale data at that point.
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3038) *
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3039) * This should be mostly correct, but if the COPY writes to partial
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3040) * pages (at the start or end) and the parts not covered by the COPY are
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3041) * written through a memory map after calling fuse_writeback_range(),
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3042) * then these partial page modifications will be lost on truncation.
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3043) *
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3044) * It is unlikely that someone would rely on such mixed style
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3045) * modifications. Yet this does give less guarantees than if the
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3046) * copying was performed with write(2).
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3047) *
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3048) * To fix this a i_mmap_sem style lock could be used to prevent new
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3049) * faults while the copy is ongoing.
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3050) */
2c4656dfd9945 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3051) err = fuse_writeback_range(inode_out, pos_out, pos_out + len - 1);
2c4656dfd9945 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3052) if (err)
2c4656dfd9945 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3053) goto out;
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3054)
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3055) if (is_unstable)
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3056) set_bit(FUSE_I_SIZE_UNSTABLE, &fi_out->state);
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3057)
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 3058) args.opcode = FUSE_COPY_FILE_RANGE;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 3059) args.nodeid = ff_in->nodeid;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 3060) args.in_numargs = 1;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 3061) args.in_args[0].size = sizeof(inarg);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 3062) args.in_args[0].value = &inarg;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 3063) args.out_numargs = 1;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 3064) args.out_args[0].size = sizeof(outarg);
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 3065) args.out_args[0].value = &outarg;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 3066) err = fuse_simple_request(fm, &args);
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3067) if (err == -ENOSYS) {
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3068) fc->no_copy_file_range = 1;
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3069) err = -EOPNOTSUPP;
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3070) }
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3071) if (err)
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3072) goto out;
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3073)
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3074) truncate_inode_pages_range(inode_out->i_mapping,
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3075) ALIGN_DOWN(pos_out, PAGE_SIZE),
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3076) ALIGN(pos_out + outarg.size, PAGE_SIZE) - 1);
9b46418c40fe9 (Miklos Szeredi 2020-05-20 11:39:35 +0200 3077)
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3078) if (fc->writeback_cache) {
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3079) fuse_write_update_size(inode_out, pos_out + outarg.size);
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3080) file_update_time(file_out);
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3081) }
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3082)
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3083) fuse_invalidate_attr(inode_out);
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3084)
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3085) err = outarg.size;
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3086) out:
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3087) if (is_unstable)
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3088) clear_bit(FUSE_I_SIZE_UNSTABLE, &fi_out->state);
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3089)
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3090) inode_unlock(inode_out);
fe0da9c09b2dc (Amir Goldstein 2019-06-05 08:04:51 -0700 3091) file_accessed(file_in);
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3092)
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3093) return err;
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3094) }
88bc7d5097a11 (Niels de Vos 2018-08-21 14:36:31 +0200 3095)
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 3096) static ssize_t fuse_copy_file_range(struct file *src_file, loff_t src_off,
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 3097) struct file *dst_file, loff_t dst_off,
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 3098) size_t len, unsigned int flags)
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 3099) {
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 3100) ssize_t ret;
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 3101)
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 3102) ret = __fuse_copy_file_range(src_file, src_off, dst_file, dst_off,
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 3103) len, flags);
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 3104)
5dae222a5ff0c (Amir Goldstein 2019-06-05 08:04:50 -0700 3105) if (ret == -EOPNOTSUPP || ret == -EXDEV)
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 3106) ret = generic_copy_file_range(src_file, src_off, dst_file,
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 3107) dst_off, len, flags);
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 3108) return ret;
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 3109) }
64bf5ff58dff7 (Dave Chinner 2019-06-05 08:04:47 -0700 3110)
4b6f5d20b04dc (Arjan van de Ven 2006-03-28 01:56:42 -0800 3111) static const struct file_operations fuse_file_operations = {
5559b8f4d1f63 (Miklos Szeredi 2008-04-30 00:54:45 -0700 3112) .llseek = fuse_file_llseek,
37c20f16e7a73 (Al Viro 2014-04-02 14:47:09 -0400 3113) .read_iter = fuse_file_read_iter,
84c3d55cc474f (Al Viro 2014-04-03 14:33:23 -0400 3114) .write_iter = fuse_file_write_iter,
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 3115) .mmap = fuse_file_mmap,
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 3116) .open = fuse_open,
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 3117) .flush = fuse_flush,
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 3118) .release = fuse_release,
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 3119) .fsync = fuse_fsync,
7142125937e14 (Miklos Szeredi 2006-06-25 05:48:52 -0700 3120) .lock = fuse_file_lock,
2a9a609a0c4a3 (Stefan Hajnoczi 2020-08-19 18:19:52 -0400 3121) .get_unmapped_area = thp_get_unmapped_area,
a9ff4f87056cd (Miklos Szeredi 2007-10-18 03:07:02 -0700 3122) .flock = fuse_file_flock,
3c3db095b68c5 (Miklos Szeredi 2019-01-24 10:40:17 +0100 3123) .splice_read = generic_file_splice_read,
3c3db095b68c5 (Miklos Szeredi 2019-01-24 10:40:17 +0100 3124) .splice_write = iter_file_splice_write,
59efec7b90398 (Tejun Heo 2008-11-26 12:03:55 +0100 3125) .unlocked_ioctl = fuse_file_ioctl,
59efec7b90398 (Tejun Heo 2008-11-26 12:03:55 +0100 3126) .compat_ioctl = fuse_file_compat_ioctl,
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 3127) .poll = fuse_file_poll,
05ba1f0823004 (Anatol Pomozov 2012-04-22 18:45:24 -0700 3128) .fallocate = fuse_file_fallocate,
d4136d60751a5 (Miklos Szeredi 2019-01-24 10:40:17 +0100 3129) .copy_file_range = fuse_copy_file_range,
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 3130) };
413ef8cb30251 (Miklos Szeredi 2005-09-09 13:10:35 -0700 3131)
f5e54d6e53a20 (Christoph Hellwig 2006-06-28 04:26:44 -0700 3132) static const struct address_space_operations fuse_file_aops = {
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 3133) .readpage = fuse_readpage,
76a0294eb19b5 (Matthew Wilcox (Oracle) 2020-06-01 21:47:31 -0700 3134) .readahead = fuse_readahead,
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 3135) .writepage = fuse_writepage,
26d614df1da9d (Pavel Emelyanov 2013-06-29 21:45:29 +0400 3136) .writepages = fuse_writepages,
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 3137) .launder_page = fuse_launder_page,
3be5a52b30aa5 (Miklos Szeredi 2008-04-30 00:54:41 -0700 3138) .set_page_dirty = __set_page_dirty_nobuffers,
b2d2272fae1e1 (Miklos Szeredi 2006-12-06 20:35:51 -0800 3139) .bmap = fuse_bmap,
4273b793ec687 (Anand Avati 2012-02-17 12:46:25 -0500 3140) .direct_IO = fuse_direct_IO,
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 3141) .write_begin = fuse_write_begin,
6b12c1b37e555 (Pavel Emelyanov 2013-10-10 17:11:43 +0400 3142) .write_end = fuse_write_end,
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 3143) };
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 3144)
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 3145) void fuse_init_file_inode(struct inode *inode)
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 3146) {
ab2257e9941b9 (Miklos Szeredi 2018-10-01 10:07:05 +0200 3147) struct fuse_inode *fi = get_fuse_inode(inode);
ab2257e9941b9 (Miklos Szeredi 2018-10-01 10:07:05 +0200 3148)
45323fb76465a (Miklos Szeredi 2005-09-09 13:10:37 -0700 3149) inode->i_fop = &fuse_file_operations;
45323fb76465a (Miklos Szeredi 2005-09-09 13:10:37 -0700 3150) inode->i_data.a_ops = &fuse_file_aops;
ab2257e9941b9 (Miklos Szeredi 2018-10-01 10:07:05 +0200 3151)
ab2257e9941b9 (Miklos Szeredi 2018-10-01 10:07:05 +0200 3152) INIT_LIST_HEAD(&fi->write_files);
ab2257e9941b9 (Miklos Szeredi 2018-10-01 10:07:05 +0200 3153) INIT_LIST_HEAD(&fi->queued_writes);
ab2257e9941b9 (Miklos Szeredi 2018-10-01 10:07:05 +0200 3154) fi->writectr = 0;
ab2257e9941b9 (Miklos Szeredi 2018-10-01 10:07:05 +0200 3155) init_waitqueue_head(&fi->page_waitq);
6b2fb79963fbe (Maxim Patlasov 2019-09-19 17:11:20 +0300 3156) fi->writepages = RB_ROOT;
c2d0ad00d948d (Vivek Goyal 2020-08-19 18:19:51 -0400 3157)
c2d0ad00d948d (Vivek Goyal 2020-08-19 18:19:51 -0400 3158) if (IS_ENABLED(CONFIG_FUSE_DAX))
c2d0ad00d948d (Vivek Goyal 2020-08-19 18:19:51 -0400 3159) fuse_dax_inode_init(inode);
b6aeadeda22a9 (Miklos Szeredi 2005-09-09 13:10:30 -0700 3160) }