334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1) /*
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -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>
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 4)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 5) This program can be distributed under the terms of the GNU GPL.
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 6) See the file COPYING.
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 7) */
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 8)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 9) #include "fuse_i.h"
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 10)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 11) #include <linux/init.h>
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 12) #include <linux/module.h>
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 13) #include <linux/poll.h>
174cd4b1e5fbd (Ingo Molnar 2017-02-02 19:15:33 +0100 14) #include <linux/sched/signal.h>
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 15) #include <linux/uio.h>
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 16) #include <linux/miscdevice.h>
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 17) #include <linux/pagemap.h>
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 18) #include <linux/file.h>
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 19) #include <linux/slab.h>
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 20) #include <linux/pipe_fs_i.h>
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 21) #include <linux/swap.h>
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 22) #include <linux/splice.h>
0b6e9ea041e6c (Seth Forshee 2014-07-02 16:29:19 -0500 23) #include <linux/sched.h>
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 24)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 25) MODULE_ALIAS_MISCDEV(FUSE_MINOR);
578454ff7eab6 (Kay Sievers 2010-05-20 18:07:20 +0200 26) MODULE_ALIAS("devname:fuse");
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 27)
c59fd85e4fd07 (Kirill Tkhai 2018-09-11 13:11:56 +0300 28) /* Ordinary requests have even IDs, while interrupts IDs are odd */
c59fd85e4fd07 (Kirill Tkhai 2018-09-11 13:11:56 +0300 29) #define FUSE_INT_REQ_BIT (1ULL << 0)
c59fd85e4fd07 (Kirill Tkhai 2018-09-11 13:11:56 +0300 30) #define FUSE_REQ_ID_STEP (1ULL << 1)
c59fd85e4fd07 (Kirill Tkhai 2018-09-11 13:11:56 +0300 31)
e18b890bb0881 (Christoph Lameter 2006-12-06 20:33:20 -0800 32) static struct kmem_cache *fuse_req_cachep;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 33)
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 34) static struct fuse_dev *fuse_get_dev(struct file *file)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 35) {
0720b31597644 (Miklos Szeredi 2006-04-10 22:54:55 -0700 36) /*
0720b31597644 (Miklos Szeredi 2006-04-10 22:54:55 -0700 37) * Lockless access is OK, because file->private data is set
0720b31597644 (Miklos Szeredi 2006-04-10 22:54:55 -0700 38) * once during mount and is valid until the file is released.
0720b31597644 (Miklos Szeredi 2006-04-10 22:54:55 -0700 39) */
6aa7de059173a (Mark Rutland 2017-10-23 14:07:29 -0700 40) return READ_ONCE(file->private_data);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 41) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 42)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 43) static void fuse_request_init(struct fuse_mount *fm, struct fuse_req *req)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 44) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 45) INIT_LIST_HEAD(&req->list);
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 46) INIT_LIST_HEAD(&req->intr_entry);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 47) init_waitqueue_head(&req->waitq);
ec99f6d31f259 (Elena Reshetova 2017-03-03 11:04:04 +0200 48) refcount_set(&req->count, 1);
33e14b4dfdc47 (Miklos Szeredi 2015-07-01 16:26:01 +0200 49) __set_bit(FR_PENDING, &req->flags);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 50) req->fm = fm;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 51) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 52)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 53) static struct fuse_req *fuse_request_alloc(struct fuse_mount *fm, gfp_t flags)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 54) {
8a7aa286ab67d (Miklos Szeredi 2018-10-01 10:07:05 +0200 55) struct fuse_req *req = kmem_cache_zalloc(fuse_req_cachep, flags);
7213394c4e184 (Miklos Szeredi 2019-09-10 15:04:11 +0200 56) if (req)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 57) fuse_request_init(fm, req);
4250c0668ea10 (Maxim Patlasov 2012-10-26 19:48:07 +0400 58)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 59) return req;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 60) }
4250c0668ea10 (Maxim Patlasov 2012-10-26 19:48:07 +0400 61)
66abc3599c3c8 (Miklos Szeredi 2019-09-10 15:04:11 +0200 62) static void fuse_request_free(struct fuse_req *req)
e52a8250480ac (Miklos Szeredi 2018-10-01 10:07:06 +0200 63) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 64) kmem_cache_free(fuse_req_cachep, req);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 65) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 66)
66abc3599c3c8 (Miklos Szeredi 2019-09-10 15:04:11 +0200 67) static void __fuse_get_request(struct fuse_req *req)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 68) {
ec99f6d31f259 (Elena Reshetova 2017-03-03 11:04:04 +0200 69) refcount_inc(&req->count);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 70) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 71)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 72) /* Must be called with > 1 refcount */
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 73) static void __fuse_put_request(struct fuse_req *req)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 74) {
ec99f6d31f259 (Elena Reshetova 2017-03-03 11:04:04 +0200 75) refcount_dec(&req->count);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 76) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 77)
9759bd5189945 (Miklos Szeredi 2015-01-06 10:45:35 +0100 78) void fuse_set_initialized(struct fuse_conn *fc)
9759bd5189945 (Miklos Szeredi 2015-01-06 10:45:35 +0100 79) {
9759bd5189945 (Miklos Szeredi 2015-01-06 10:45:35 +0100 80) /* Make sure stores before this are seen on another CPU */
9759bd5189945 (Miklos Szeredi 2015-01-06 10:45:35 +0100 81) smp_wmb();
9759bd5189945 (Miklos Szeredi 2015-01-06 10:45:35 +0100 82) fc->initialized = 1;
9759bd5189945 (Miklos Szeredi 2015-01-06 10:45:35 +0100 83) }
9759bd5189945 (Miklos Szeredi 2015-01-06 10:45:35 +0100 84)
0aada88476a33 (Maxim Patlasov 2013-03-21 18:02:28 +0400 85) static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background)
0aada88476a33 (Maxim Patlasov 2013-03-21 18:02:28 +0400 86) {
0aada88476a33 (Maxim Patlasov 2013-03-21 18:02:28 +0400 87) return !fc->initialized || (for_background && fc->blocked);
0aada88476a33 (Maxim Patlasov 2013-03-21 18:02:28 +0400 88) }
0aada88476a33 (Maxim Patlasov 2013-03-21 18:02:28 +0400 89)
b8f95e5d13f5f (Miklos Szeredi 2018-07-26 16:13:11 +0200 90) static void fuse_drop_waiting(struct fuse_conn *fc)
b8f95e5d13f5f (Miklos Szeredi 2018-07-26 16:13:11 +0200 91) {
2d84a2d19b615 (Miklos Szeredi 2018-11-09 15:52:16 +0100 92) /*
2d84a2d19b615 (Miklos Szeredi 2018-11-09 15:52:16 +0100 93) * lockess check of fc->connected is okay, because atomic_dec_and_test()
2d84a2d19b615 (Miklos Szeredi 2018-11-09 15:52:16 +0100 94) * provides a memory barrier mached with the one in fuse_wait_aborted()
2d84a2d19b615 (Miklos Szeredi 2018-11-09 15:52:16 +0100 95) * to ensure no wake-up is missed.
2d84a2d19b615 (Miklos Szeredi 2018-11-09 15:52:16 +0100 96) */
2d84a2d19b615 (Miklos Szeredi 2018-11-09 15:52:16 +0100 97) if (atomic_dec_and_test(&fc->num_waiting) &&
2d84a2d19b615 (Miklos Szeredi 2018-11-09 15:52:16 +0100 98) !READ_ONCE(fc->connected)) {
b8f95e5d13f5f (Miklos Szeredi 2018-07-26 16:13:11 +0200 99) /* wake up aborters */
b8f95e5d13f5f (Miklos Szeredi 2018-07-26 16:13:11 +0200 100) wake_up_all(&fc->blocked_waitq);
b8f95e5d13f5f (Miklos Szeredi 2018-07-26 16:13:11 +0200 101) }
b8f95e5d13f5f (Miklos Szeredi 2018-07-26 16:13:11 +0200 102) }
b8f95e5d13f5f (Miklos Szeredi 2018-07-26 16:13:11 +0200 103)
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 104) static void fuse_put_request(struct fuse_req *req);
66abc3599c3c8 (Miklos Szeredi 2019-09-10 15:04:11 +0200 105)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 106) static struct fuse_req *fuse_get_req(struct fuse_mount *fm, bool for_background)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 107) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 108) struct fuse_conn *fc = fm->fc;
08a53cdce62d3 (Miklos Szeredi 2006-04-10 22:54:59 -0700 109) struct fuse_req *req;
08a53cdce62d3 (Miklos Szeredi 2006-04-10 22:54:59 -0700 110) int err;
9bc5dddad1294 (Miklos Szeredi 2006-04-11 21:16:09 +0200 111) atomic_inc(&fc->num_waiting);
0aada88476a33 (Maxim Patlasov 2013-03-21 18:02:28 +0400 112)
0aada88476a33 (Maxim Patlasov 2013-03-21 18:02:28 +0400 113) if (fuse_block_alloc(fc, for_background)) {
0aada88476a33 (Maxim Patlasov 2013-03-21 18:02:28 +0400 114) err = -EINTR;
7d3a07fcb8a0d (Al Viro 2016-07-19 03:08:27 -0400 115) if (wait_event_killable_exclusive(fc->blocked_waitq,
7d3a07fcb8a0d (Al Viro 2016-07-19 03:08:27 -0400 116) !fuse_block_alloc(fc, for_background)))
0aada88476a33 (Maxim Patlasov 2013-03-21 18:02:28 +0400 117) goto out;
0aada88476a33 (Maxim Patlasov 2013-03-21 18:02:28 +0400 118) }
9759bd5189945 (Miklos Szeredi 2015-01-06 10:45:35 +0100 119) /* Matches smp_wmb() in fuse_set_initialized() */
9759bd5189945 (Miklos Szeredi 2015-01-06 10:45:35 +0100 120) smp_rmb();
08a53cdce62d3 (Miklos Szeredi 2006-04-10 22:54:59 -0700 121)
51eb01e73599e (Miklos Szeredi 2006-06-25 05:48:50 -0700 122) err = -ENOTCONN;
51eb01e73599e (Miklos Szeredi 2006-06-25 05:48:50 -0700 123) if (!fc->connected)
51eb01e73599e (Miklos Szeredi 2006-06-25 05:48:50 -0700 124) goto out;
51eb01e73599e (Miklos Szeredi 2006-06-25 05:48:50 -0700 125)
de15522646b98 (Miklos Szeredi 2015-07-01 16:25:57 +0200 126) err = -ECONNREFUSED;
de15522646b98 (Miklos Szeredi 2015-07-01 16:25:57 +0200 127) if (fc->conn_error)
de15522646b98 (Miklos Szeredi 2015-07-01 16:25:57 +0200 128) goto out;
de15522646b98 (Miklos Szeredi 2015-07-01 16:25:57 +0200 129)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 130) req = fuse_request_alloc(fm, GFP_KERNEL);
9bc5dddad1294 (Miklos Szeredi 2006-04-11 21:16:09 +0200 131) err = -ENOMEM;
722d2bea8c601 (Maxim Patlasov 2013-03-21 18:02:36 +0400 132) if (!req) {
722d2bea8c601 (Maxim Patlasov 2013-03-21 18:02:36 +0400 133) if (for_background)
722d2bea8c601 (Maxim Patlasov 2013-03-21 18:02:36 +0400 134) wake_up(&fc->blocked_waitq);
9bc5dddad1294 (Miklos Szeredi 2006-04-11 21:16:09 +0200 135) goto out;
722d2bea8c601 (Maxim Patlasov 2013-03-21 18:02:36 +0400 136) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 137)
8cb08329b0809 (Eric W. Biederman 2018-02-21 11:18:07 -0600 138) req->in.h.uid = from_kuid(fc->user_ns, current_fsuid());
8cb08329b0809 (Eric W. Biederman 2018-02-21 11:18:07 -0600 139) req->in.h.gid = from_kgid(fc->user_ns, current_fsgid());
c9582eb0ff7d2 (Eric W. Biederman 2018-02-21 10:52:06 -0600 140) req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns);
c9582eb0ff7d2 (Eric W. Biederman 2018-02-21 10:52:06 -0600 141)
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 142) __set_bit(FR_WAITING, &req->flags);
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 143) if (for_background)
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 144) __set_bit(FR_BACKGROUND, &req->flags);
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 145)
c9582eb0ff7d2 (Eric W. Biederman 2018-02-21 10:52:06 -0600 146) if (unlikely(req->in.h.uid == ((uid_t)-1) ||
c9582eb0ff7d2 (Eric W. Biederman 2018-02-21 10:52:06 -0600 147) req->in.h.gid == ((gid_t)-1))) {
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 148) fuse_put_request(req);
c9582eb0ff7d2 (Eric W. Biederman 2018-02-21 10:52:06 -0600 149) return ERR_PTR(-EOVERFLOW);
c9582eb0ff7d2 (Eric W. Biederman 2018-02-21 10:52:06 -0600 150) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 151) return req;
9bc5dddad1294 (Miklos Szeredi 2006-04-11 21:16:09 +0200 152)
9bc5dddad1294 (Miklos Szeredi 2006-04-11 21:16:09 +0200 153) out:
b8f95e5d13f5f (Miklos Szeredi 2018-07-26 16:13:11 +0200 154) fuse_drop_waiting(fc);
9bc5dddad1294 (Miklos Szeredi 2006-04-11 21:16:09 +0200 155) return ERR_PTR(err);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 156) }
8b41e6715ed55 (Maxim Patlasov 2013-03-21 18:02:04 +0400 157)
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 158) static void fuse_put_request(struct fuse_req *req)
7128ec2a747d7 (Miklos Szeredi 2006-02-04 23:27:40 -0800 159) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 160) struct fuse_conn *fc = req->fm->fc;
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 161)
ec99f6d31f259 (Elena Reshetova 2017-03-03 11:04:04 +0200 162) if (refcount_dec_and_test(&req->count)) {
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 163) if (test_bit(FR_BACKGROUND, &req->flags)) {
722d2bea8c601 (Maxim Patlasov 2013-03-21 18:02:36 +0400 164) /*
722d2bea8c601 (Maxim Patlasov 2013-03-21 18:02:36 +0400 165) * We get here in the unlikely case that a background
722d2bea8c601 (Maxim Patlasov 2013-03-21 18:02:36 +0400 166) * request was allocated but not sent
722d2bea8c601 (Maxim Patlasov 2013-03-21 18:02:36 +0400 167) */
ae2dffa39485c (Kirill Tkhai 2018-08-27 18:29:46 +0300 168) spin_lock(&fc->bg_lock);
722d2bea8c601 (Maxim Patlasov 2013-03-21 18:02:36 +0400 169) if (!fc->blocked)
722d2bea8c601 (Maxim Patlasov 2013-03-21 18:02:36 +0400 170) wake_up(&fc->blocked_waitq);
ae2dffa39485c (Kirill Tkhai 2018-08-27 18:29:46 +0300 171) spin_unlock(&fc->bg_lock);
722d2bea8c601 (Maxim Patlasov 2013-03-21 18:02:36 +0400 172) }
722d2bea8c601 (Maxim Patlasov 2013-03-21 18:02:36 +0400 173)
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 174) if (test_bit(FR_WAITING, &req->flags)) {
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 175) __clear_bit(FR_WAITING, &req->flags);
b8f95e5d13f5f (Miklos Szeredi 2018-07-26 16:13:11 +0200 176) fuse_drop_waiting(fc);
73e0e738441b2 (Miklos Szeredi 2015-07-01 16:25:56 +0200 177) }
33649c91a3df5 (Miklos Szeredi 2006-06-25 05:48:52 -0700 178)
40ac7ab2d0217 (Miklos Szeredi 2019-09-10 15:04:08 +0200 179) fuse_request_free(req);
7128ec2a747d7 (Miklos Szeredi 2006-02-04 23:27:40 -0800 180) }
7128ec2a747d7 (Miklos Szeredi 2006-02-04 23:27:40 -0800 181) }
7128ec2a747d7 (Miklos Szeredi 2006-02-04 23:27:40 -0800 182)
14d46d7abc397 (Stefan Hajnoczi 2018-06-21 09:34:25 +0100 183) unsigned int fuse_len_args(unsigned int numargs, struct fuse_arg *args)
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 184) {
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 185) unsigned nbytes = 0;
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 186) unsigned i;
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 187)
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 188) for (i = 0; i < numargs; i++)
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 189) nbytes += args[i].size;
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 190)
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 191) return nbytes;
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 192) }
14d46d7abc397 (Stefan Hajnoczi 2018-06-21 09:34:25 +0100 193) EXPORT_SYMBOL_GPL(fuse_len_args);
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 194)
79d96efffda75 (Stefan Hajnoczi 2018-06-22 13:48:30 +0100 195) u64 fuse_get_unique(struct fuse_iqueue *fiq)
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 196) {
c59fd85e4fd07 (Kirill Tkhai 2018-09-11 13:11:56 +0300 197) fiq->reqctr += FUSE_REQ_ID_STEP;
c59fd85e4fd07 (Kirill Tkhai 2018-09-11 13:11:56 +0300 198) return fiq->reqctr;
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 199) }
79d96efffda75 (Stefan Hajnoczi 2018-06-22 13:48:30 +0100 200) EXPORT_SYMBOL_GPL(fuse_get_unique);
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 201)
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 202) static unsigned int fuse_req_hash(u64 unique)
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 203) {
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 204) return hash_long(unique & ~FUSE_INT_REQ_BIT, FUSE_PQ_HASH_BITS);
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 205) }
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 206)
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 207) /**
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 208) * A new request is available, wake fiq->waitq
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 209) */
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 210) static void fuse_dev_wake_and_unlock(struct fuse_iqueue *fiq)
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 211) __releases(fiq->lock)
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 212) {
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 213) wake_up(&fiq->waitq);
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 214) kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 215) spin_unlock(&fiq->lock);
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 216) }
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 217)
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 218) const struct fuse_iqueue_ops fuse_dev_fiq_ops = {
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 219) .wake_forget_and_unlock = fuse_dev_wake_and_unlock,
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 220) .wake_interrupt_and_unlock = fuse_dev_wake_and_unlock,
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 221) .wake_pending_and_unlock = fuse_dev_wake_and_unlock,
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 222) };
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 223) EXPORT_SYMBOL_GPL(fuse_dev_fiq_ops);
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 224)
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 225) static void queue_request_and_unlock(struct fuse_iqueue *fiq,
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 226) struct fuse_req *req)
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 227) __releases(fiq->lock)
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 228) {
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 229) req->in.h.len = sizeof(struct fuse_in_header) +
14d46d7abc397 (Stefan Hajnoczi 2018-06-21 09:34:25 +0100 230) fuse_len_args(req->args->in_numargs,
14d46d7abc397 (Stefan Hajnoczi 2018-06-21 09:34:25 +0100 231) (struct fuse_arg *) req->args->in_args);
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 232) list_add_tail(&req->list, &fiq->pending);
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 233) fiq->ops->wake_pending_and_unlock(fiq);
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 234) }
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 235)
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 236) void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget,
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 237) u64 nodeid, u64 nlookup)
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 238) {
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 239) struct fuse_iqueue *fiq = &fc->iq;
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 240)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 241) forget->forget_one.nodeid = nodeid;
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 242) forget->forget_one.nlookup = nlookup;
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 243)
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 244) spin_lock(&fiq->lock);
e16714d8756dc (Miklos Szeredi 2015-07-01 16:26:01 +0200 245) if (fiq->connected) {
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 246) fiq->forget_list_tail->next = forget;
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 247) fiq->forget_list_tail = forget;
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 248) fiq->ops->wake_forget_and_unlock(fiq);
5dfcc87fd79df (Miklos Szeredi 2011-09-12 09:38:03 +0200 249) } else {
5dfcc87fd79df (Miklos Szeredi 2011-09-12 09:38:03 +0200 250) kfree(forget);
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 251) spin_unlock(&fiq->lock);
5dfcc87fd79df (Miklos Szeredi 2011-09-12 09:38:03 +0200 252) }
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 253) }
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 254)
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 255) static void flush_bg_queue(struct fuse_conn *fc)
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 256) {
e287179afe219 (Kirill Tkhai 2018-07-31 13:25:25 +0300 257) struct fuse_iqueue *fiq = &fc->iq;
e287179afe219 (Kirill Tkhai 2018-07-31 13:25:25 +0300 258)
7a6d3c8b3049d (Csaba Henk 2009-07-01 17:28:41 -0700 259) while (fc->active_background < fc->max_background &&
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 260) !list_empty(&fc->bg_queue)) {
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 261) struct fuse_req *req;
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 262)
e287179afe219 (Kirill Tkhai 2018-07-31 13:25:25 +0300 263) req = list_first_entry(&fc->bg_queue, struct fuse_req, list);
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 264) list_del(&req->list);
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 265) fc->active_background++;
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 266) spin_lock(&fiq->lock);
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 267) req->in.h.unique = fuse_get_unique(fiq);
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 268) queue_request_and_unlock(fiq, req);
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 269) }
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 270) }
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 271)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 272) /*
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 273) * This function is called when a request is finished. Either a reply
f9a2842e5612b (Miklos Szeredi 2006-06-25 05:48:53 -0700 274) * has arrived or it was aborted (and not yet sent) or some error
f43b155a5a8a9 (Miklos Szeredi 2006-01-16 22:14:26 -0800 275) * occurred during communication with userspace, or the device file
51eb01e73599e (Miklos Szeredi 2006-06-25 05:48:50 -0700 276) * was closed. The requester thread is woken up (if still waiting),
51eb01e73599e (Miklos Szeredi 2006-06-25 05:48:50 -0700 277) * the 'end' callback is called if given, else the reference to the
51eb01e73599e (Miklos Szeredi 2006-06-25 05:48:50 -0700 278) * request is released
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 279) */
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 280) void fuse_request_end(struct fuse_req *req)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 281) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 282) struct fuse_mount *fm = req->fm;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 283) struct fuse_conn *fc = fm->fc;
4ce6081260ea4 (Miklos Szeredi 2015-07-01 16:26:02 +0200 284) struct fuse_iqueue *fiq = &fc->iq;
365ae710df91e (Miklos Szeredi 2015-07-01 16:26:06 +0200 285)
efe2800facb45 (Miklos Szeredi 2015-07-01 16:26:07 +0200 286) if (test_and_set_bit(FR_FINISHED, &req->flags))
b8f95e5d13f5f (Miklos Szeredi 2018-07-26 16:13:11 +0200 287) goto put_request;
2b319d1f6f92a (Miklos Szeredi 2019-10-21 09:11:40 +0200 288)
217316a601016 (Kirill Tkhai 2018-11-08 12:05:25 +0300 289) /*
217316a601016 (Kirill Tkhai 2018-11-08 12:05:25 +0300 290) * test_and_set_bit() implies smp_mb() between bit
217316a601016 (Kirill Tkhai 2018-11-08 12:05:25 +0300 291) * changing and below intr_entry check. Pairs with
217316a601016 (Kirill Tkhai 2018-11-08 12:05:25 +0300 292) * smp_mb() from queue_interrupt().
217316a601016 (Kirill Tkhai 2018-11-08 12:05:25 +0300 293) */
217316a601016 (Kirill Tkhai 2018-11-08 12:05:25 +0300 294) if (!list_empty(&req->intr_entry)) {
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 295) spin_lock(&fiq->lock);
217316a601016 (Kirill Tkhai 2018-11-08 12:05:25 +0300 296) list_del_init(&req->intr_entry);
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 297) spin_unlock(&fiq->lock);
217316a601016 (Kirill Tkhai 2018-11-08 12:05:25 +0300 298) }
33e14b4dfdc47 (Miklos Szeredi 2015-07-01 16:26:01 +0200 299) WARN_ON(test_bit(FR_PENDING, &req->flags));
33e14b4dfdc47 (Miklos Szeredi 2015-07-01 16:26:01 +0200 300) WARN_ON(test_bit(FR_SENT, &req->flags));
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 301) if (test_bit(FR_BACKGROUND, &req->flags)) {
ae2dffa39485c (Kirill Tkhai 2018-08-27 18:29:46 +0300 302) spin_lock(&fc->bg_lock);
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 303) clear_bit(FR_BACKGROUND, &req->flags);
908a572b80f6e (Miklos Szeredi 2018-09-28 16:43:22 +0200 304) if (fc->num_background == fc->max_background) {
51eb01e73599e (Miklos Szeredi 2006-06-25 05:48:50 -0700 305) fc->blocked = 0;
722d2bea8c601 (Maxim Patlasov 2013-03-21 18:02:36 +0400 306) wake_up(&fc->blocked_waitq);
908a572b80f6e (Miklos Szeredi 2018-09-28 16:43:22 +0200 307) } else if (!fc->blocked) {
908a572b80f6e (Miklos Szeredi 2018-09-28 16:43:22 +0200 308) /*
908a572b80f6e (Miklos Szeredi 2018-09-28 16:43:22 +0200 309) * Wake up next waiter, if any. It's okay to use
908a572b80f6e (Miklos Szeredi 2018-09-28 16:43:22 +0200 310) * waitqueue_active(), as we've already synced up
908a572b80f6e (Miklos Szeredi 2018-09-28 16:43:22 +0200 311) * fc->blocked with waiters with the wake_up() call
908a572b80f6e (Miklos Szeredi 2018-09-28 16:43:22 +0200 312) * above.
908a572b80f6e (Miklos Szeredi 2018-09-28 16:43:22 +0200 313) */
908a572b80f6e (Miklos Szeredi 2018-09-28 16:43:22 +0200 314) if (waitqueue_active(&fc->blocked_waitq))
908a572b80f6e (Miklos Szeredi 2018-09-28 16:43:22 +0200 315) wake_up(&fc->blocked_waitq);
908a572b80f6e (Miklos Szeredi 2018-09-28 16:43:22 +0200 316) }
722d2bea8c601 (Maxim Patlasov 2013-03-21 18:02:36 +0400 317)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 318) if (fc->num_background == fc->congestion_threshold && fm->sb) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 319) clear_bdi_congested(fm->sb->s_bdi, BLK_RW_SYNC);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 320) clear_bdi_congested(fm->sb->s_bdi, BLK_RW_ASYNC);
f92b99b9dccb6 (Miklos Szeredi 2007-10-16 23:30:59 -0700 321) }
51eb01e73599e (Miklos Szeredi 2006-06-25 05:48:50 -0700 322) fc->num_background--;
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 323) fc->active_background--;
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 324) flush_bg_queue(fc);
ae2dffa39485c (Kirill Tkhai 2018-08-27 18:29:46 +0300 325) spin_unlock(&fc->bg_lock);
5e0fed717a383 (Kirill Tkhai 2018-11-08 12:05:31 +0300 326) } else {
5e0fed717a383 (Kirill Tkhai 2018-11-08 12:05:31 +0300 327) /* Wake up waiter sleeping in request_wait_answer() */
5e0fed717a383 (Kirill Tkhai 2018-11-08 12:05:31 +0300 328) wake_up(&req->waitq);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 329) }
5e0fed717a383 (Kirill Tkhai 2018-11-08 12:05:31 +0300 330)
3e8cb8b2eaeb2 (Miklos Szeredi 2020-02-13 09:16:07 +0100 331) if (test_bit(FR_ASYNC, &req->flags))
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 332) req->args->end(fm, req->args, req->out.h.error);
b8f95e5d13f5f (Miklos Szeredi 2018-07-26 16:13:11 +0200 333) put_request:
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 334) fuse_put_request(req);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 335) }
04ec5af0776e9 (Stefan Hajnoczi 2018-06-21 09:33:40 +0100 336) EXPORT_SYMBOL_GPL(fuse_request_end);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 337)
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 338) static int queue_interrupt(struct fuse_req *req)
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 339) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 340) struct fuse_iqueue *fiq = &req->fm->fc->iq;
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 341)
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 342) spin_lock(&fiq->lock);
b782911b5297c (Kirill Tkhai 2018-11-08 12:05:42 +0300 343) /* Check for we've sent request to interrupt this req */
b782911b5297c (Kirill Tkhai 2018-11-08 12:05:42 +0300 344) if (unlikely(!test_bit(FR_INTERRUPTED, &req->flags))) {
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 345) spin_unlock(&fiq->lock);
b782911b5297c (Kirill Tkhai 2018-11-08 12:05:42 +0300 346) return -EINVAL;
b782911b5297c (Kirill Tkhai 2018-11-08 12:05:42 +0300 347) }
b782911b5297c (Kirill Tkhai 2018-11-08 12:05:42 +0300 348)
8f7bb368dbdda (Miklos Szeredi 2015-07-01 16:26:03 +0200 349) if (list_empty(&req->intr_entry)) {
8f7bb368dbdda (Miklos Szeredi 2015-07-01 16:26:03 +0200 350) list_add_tail(&req->intr_entry, &fiq->interrupts);
217316a601016 (Kirill Tkhai 2018-11-08 12:05:25 +0300 351) /*
217316a601016 (Kirill Tkhai 2018-11-08 12:05:25 +0300 352) * Pairs with smp_mb() implied by test_and_set_bit()
75d892588e959 (Kirill Tkhai 2020-02-28 15:15:24 +0300 353) * from fuse_request_end().
217316a601016 (Kirill Tkhai 2018-11-08 12:05:25 +0300 354) */
217316a601016 (Kirill Tkhai 2018-11-08 12:05:25 +0300 355) smp_mb();
217316a601016 (Kirill Tkhai 2018-11-08 12:05:25 +0300 356) if (test_bit(FR_FINISHED, &req->flags)) {
217316a601016 (Kirill Tkhai 2018-11-08 12:05:25 +0300 357) list_del_init(&req->intr_entry);
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 358) spin_unlock(&fiq->lock);
b782911b5297c (Kirill Tkhai 2018-11-08 12:05:42 +0300 359) return 0;
217316a601016 (Kirill Tkhai 2018-11-08 12:05:25 +0300 360) }
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 361) fiq->ops->wake_interrupt_and_unlock(fiq);
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 362) } else {
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 363) spin_unlock(&fiq->lock);
8f7bb368dbdda (Miklos Szeredi 2015-07-01 16:26:03 +0200 364) }
b782911b5297c (Kirill Tkhai 2018-11-08 12:05:42 +0300 365) return 0;
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 366) }
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 367)
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 368) static void request_wait_answer(struct fuse_req *req)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 369) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 370) struct fuse_conn *fc = req->fm->fc;
4ce6081260ea4 (Miklos Szeredi 2015-07-01 16:26:02 +0200 371) struct fuse_iqueue *fiq = &fc->iq;
c47752673acb1 (Miklos Szeredi 2015-07-01 16:26:00 +0200 372) int err;
c47752673acb1 (Miklos Szeredi 2015-07-01 16:26:00 +0200 373)
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 374) if (!fc->no_interrupt) {
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 375) /* Any signal may interrupt this */
c47752673acb1 (Miklos Szeredi 2015-07-01 16:26:00 +0200 376) err = wait_event_interruptible(req->waitq,
33e14b4dfdc47 (Miklos Szeredi 2015-07-01 16:26:01 +0200 377) test_bit(FR_FINISHED, &req->flags));
c47752673acb1 (Miklos Szeredi 2015-07-01 16:26:00 +0200 378) if (!err)
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 379) return;
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 380)
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 381) set_bit(FR_INTERRUPTED, &req->flags);
8f7bb368dbdda (Miklos Szeredi 2015-07-01 16:26:03 +0200 382) /* matches barrier in fuse_dev_do_read() */
8f7bb368dbdda (Miklos Szeredi 2015-07-01 16:26:03 +0200 383) smp_mb__after_atomic();
33e14b4dfdc47 (Miklos Szeredi 2015-07-01 16:26:01 +0200 384) if (test_bit(FR_SENT, &req->flags))
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 385) queue_interrupt(req);
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 386) }
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 387)
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 388) if (!test_bit(FR_FORCE, &req->flags)) {
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 389) /* Only fatal signals may interrupt this */
7d3a07fcb8a0d (Al Viro 2016-07-19 03:08:27 -0400 390) err = wait_event_killable(req->waitq,
33e14b4dfdc47 (Miklos Szeredi 2015-07-01 16:26:01 +0200 391) test_bit(FR_FINISHED, &req->flags));
c47752673acb1 (Miklos Szeredi 2015-07-01 16:26:00 +0200 392) if (!err)
a131de0a482ac (Miklos Szeredi 2007-10-16 23:31:04 -0700 393) return;
a131de0a482ac (Miklos Szeredi 2007-10-16 23:31:04 -0700 394)
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 395) spin_lock(&fiq->lock);
a131de0a482ac (Miklos Szeredi 2007-10-16 23:31:04 -0700 396) /* Request is not yet in userspace, bail out */
33e14b4dfdc47 (Miklos Szeredi 2015-07-01 16:26:01 +0200 397) if (test_bit(FR_PENDING, &req->flags)) {
a131de0a482ac (Miklos Szeredi 2007-10-16 23:31:04 -0700 398) list_del(&req->list);
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 399) spin_unlock(&fiq->lock);
a131de0a482ac (Miklos Szeredi 2007-10-16 23:31:04 -0700 400) __fuse_put_request(req);
a131de0a482ac (Miklos Szeredi 2007-10-16 23:31:04 -0700 401) req->out.h.error = -EINTR;
a131de0a482ac (Miklos Szeredi 2007-10-16 23:31:04 -0700 402) return;
a131de0a482ac (Miklos Szeredi 2007-10-16 23:31:04 -0700 403) }
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 404) spin_unlock(&fiq->lock);
51eb01e73599e (Miklos Szeredi 2006-06-25 05:48:50 -0700 405) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 406)
a131de0a482ac (Miklos Szeredi 2007-10-16 23:31:04 -0700 407) /*
a131de0a482ac (Miklos Szeredi 2007-10-16 23:31:04 -0700 408) * Either request is already in userspace, or it was forced.
a131de0a482ac (Miklos Szeredi 2007-10-16 23:31:04 -0700 409) * Wait it out.
a131de0a482ac (Miklos Szeredi 2007-10-16 23:31:04 -0700 410) */
33e14b4dfdc47 (Miklos Szeredi 2015-07-01 16:26:01 +0200 411) wait_event(req->waitq, test_bit(FR_FINISHED, &req->flags));
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 412) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 413)
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 414) static void __fuse_request_send(struct fuse_req *req)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 415) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 416) struct fuse_iqueue *fiq = &req->fm->fc->iq;
e16714d8756dc (Miklos Szeredi 2015-07-01 16:26:01 +0200 417)
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 418) BUG_ON(test_bit(FR_BACKGROUND, &req->flags));
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 419) spin_lock(&fiq->lock);
e16714d8756dc (Miklos Szeredi 2015-07-01 16:26:01 +0200 420) if (!fiq->connected) {
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 421) spin_unlock(&fiq->lock);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 422) req->out.h.error = -ENOTCONN;
c47752673acb1 (Miklos Szeredi 2015-07-01 16:26:00 +0200 423) } else {
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 424) req->in.h.unique = fuse_get_unique(fiq);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 425) /* acquire extra reference, since request is still needed
04ec5af0776e9 (Stefan Hajnoczi 2018-06-21 09:33:40 +0100 426) after fuse_request_end() */
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 427) __fuse_get_request(req);
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 428) queue_request_and_unlock(fiq, req);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 429)
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 430) request_wait_answer(req);
04ec5af0776e9 (Stefan Hajnoczi 2018-06-21 09:33:40 +0100 431) /* Pairs with smp_wmb() in fuse_request_end() */
c47752673acb1 (Miklos Szeredi 2015-07-01 16:26:00 +0200 432) smp_rmb();
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 433) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 434) }
6a4e922c3db06 (Eric Wong 2013-02-04 13:04:44 +0000 435)
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 436) static void fuse_adjust_compat(struct fuse_conn *fc, struct fuse_args *args)
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 437) {
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 438) if (fc->minor < 4 && args->opcode == FUSE_STATFS)
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 439) args->out_args[0].size = FUSE_COMPAT_STATFS_SIZE;
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 440)
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 441) if (fc->minor < 9) {
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 442) switch (args->opcode) {
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 443) case FUSE_LOOKUP:
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 444) case FUSE_CREATE:
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 445) case FUSE_MKNOD:
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 446) case FUSE_MKDIR:
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 447) case FUSE_SYMLINK:
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 448) case FUSE_LINK:
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 449) args->out_args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 450) break;
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 451) case FUSE_GETATTR:
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 452) case FUSE_SETATTR:
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 453) args->out_args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 454) break;
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 455) }
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 456) }
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 457) if (fc->minor < 12) {
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 458) switch (args->opcode) {
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 459) case FUSE_CREATE:
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 460) args->in_args[0].size = sizeof(struct fuse_open_in);
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 461) break;
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 462) case FUSE_MKNOD:
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 463) args->in_args[0].size = FUSE_COMPAT_MKNOD_IN_SIZE;
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 464) break;
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 465) }
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 466) }
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 467) }
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 468)
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 469) static void fuse_force_creds(struct fuse_req *req)
e413754b267e0 (Miklos Szeredi 2019-09-10 15:04:08 +0200 470) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 471) struct fuse_conn *fc = req->fm->fc;
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 472)
e413754b267e0 (Miklos Szeredi 2019-09-10 15:04:08 +0200 473) req->in.h.uid = from_kuid_munged(fc->user_ns, current_fsuid());
e413754b267e0 (Miklos Szeredi 2019-09-10 15:04:08 +0200 474) req->in.h.gid = from_kgid_munged(fc->user_ns, current_fsgid());
e413754b267e0 (Miklos Szeredi 2019-09-10 15:04:08 +0200 475) req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns);
e413754b267e0 (Miklos Szeredi 2019-09-10 15:04:08 +0200 476) }
e413754b267e0 (Miklos Szeredi 2019-09-10 15:04:08 +0200 477)
5addcd5dbd8c2 (YueHaibing 2019-09-23 13:52:31 +0800 478) static void fuse_args_to_req(struct fuse_req *req, struct fuse_args *args)
68583165f9627 (Miklos Szeredi 2019-09-10 15:04:09 +0200 479) {
68583165f9627 (Miklos Szeredi 2019-09-10 15:04:09 +0200 480) req->in.h.opcode = args->opcode;
68583165f9627 (Miklos Szeredi 2019-09-10 15:04:09 +0200 481) req->in.h.nodeid = args->nodeid;
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 482) req->args = args;
3e8cb8b2eaeb2 (Miklos Szeredi 2020-02-13 09:16:07 +0100 483) if (args->end)
3e8cb8b2eaeb2 (Miklos Szeredi 2020-02-13 09:16:07 +0100 484) __set_bit(FR_ASYNC, &req->flags);
68583165f9627 (Miklos Szeredi 2019-09-10 15:04:09 +0200 485) }
68583165f9627 (Miklos Szeredi 2019-09-10 15:04:09 +0200 486)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 487) ssize_t fuse_simple_request(struct fuse_mount *fm, struct fuse_args *args)
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 488) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 489) struct fuse_conn *fc = fm->fc;
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 490) struct fuse_req *req;
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 491) ssize_t ret;
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 492)
c500ebaa908db (Miklos Szeredi 2019-09-10 15:04:08 +0200 493) if (args->force) {
e413754b267e0 (Miklos Szeredi 2019-09-10 15:04:08 +0200 494) atomic_inc(&fc->num_waiting);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 495) req = fuse_request_alloc(fm, GFP_KERNEL | __GFP_NOFAIL);
e413754b267e0 (Miklos Szeredi 2019-09-10 15:04:08 +0200 496)
e413754b267e0 (Miklos Szeredi 2019-09-10 15:04:08 +0200 497) if (!args->nocreds)
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 498) fuse_force_creds(req);
e413754b267e0 (Miklos Szeredi 2019-09-10 15:04:08 +0200 499)
e413754b267e0 (Miklos Szeredi 2019-09-10 15:04:08 +0200 500) __set_bit(FR_WAITING, &req->flags);
c500ebaa908db (Miklos Szeredi 2019-09-10 15:04:08 +0200 501) __set_bit(FR_FORCE, &req->flags);
c500ebaa908db (Miklos Szeredi 2019-09-10 15:04:08 +0200 502) } else {
e413754b267e0 (Miklos Szeredi 2019-09-10 15:04:08 +0200 503) WARN_ON(args->nocreds);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 504) req = fuse_get_req(fm, false);
c500ebaa908db (Miklos Szeredi 2019-09-10 15:04:08 +0200 505) if (IS_ERR(req))
c500ebaa908db (Miklos Szeredi 2019-09-10 15:04:08 +0200 506) return PTR_ERR(req);
c500ebaa908db (Miklos Szeredi 2019-09-10 15:04:08 +0200 507) }
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 508)
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 509) /* Needs to be done after fuse_get_req() so that fc->minor is valid */
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 510) fuse_adjust_compat(fc, args);
68583165f9627 (Miklos Szeredi 2019-09-10 15:04:09 +0200 511) fuse_args_to_req(req, args);
21f621741a770 (Miklos Szeredi 2015-01-06 10:45:35 +0100 512)
454a7613f54e6 (Miklos Szeredi 2019-09-10 15:04:08 +0200 513) if (!args->noreply)
454a7613f54e6 (Miklos Szeredi 2019-09-10 15:04:08 +0200 514) __set_bit(FR_ISREPLY, &req->flags);
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 515) __fuse_request_send(req);
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 516) ret = req->out.h.error;
d5b4854357f47 (Miklos Szeredi 2019-09-10 15:04:08 +0200 517) if (!ret && args->out_argvar) {
093f38a2c1a81 (Miklos Szeredi 2019-09-10 15:04:09 +0200 518) BUG_ON(args->out_numargs == 0);
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 519) ret = args->out_args[args->out_numargs - 1].size;
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 520) }
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 521) fuse_put_request(req);
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 522)
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 523) return ret;
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 524) }
7078187a795f8 (Miklos Szeredi 2014-12-12 09:49:05 +0100 525)
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 526) static bool fuse_request_queue_background(struct fuse_req *req)
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 527) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 528) struct fuse_mount *fm = req->fm;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 529) struct fuse_conn *fc = fm->fc;
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 530) bool queued = false;
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 531)
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 532) WARN_ON(!test_bit(FR_BACKGROUND, &req->flags));
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 533) if (!test_bit(FR_WAITING, &req->flags)) {
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 534) __set_bit(FR_WAITING, &req->flags);
5437f2417225d (Miklos Szeredi 2015-07-01 16:25:56 +0200 535) atomic_inc(&fc->num_waiting);
5437f2417225d (Miklos Szeredi 2015-07-01 16:25:56 +0200 536) }
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 537) __set_bit(FR_ISREPLY, &req->flags);
ae2dffa39485c (Kirill Tkhai 2018-08-27 18:29:46 +0300 538) spin_lock(&fc->bg_lock);
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 539) if (likely(fc->connected)) {
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 540) fc->num_background++;
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 541) if (fc->num_background == fc->max_background)
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 542) fc->blocked = 1;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 543) if (fc->num_background == fc->congestion_threshold && fm->sb) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 544) set_bdi_congested(fm->sb->s_bdi, BLK_RW_SYNC);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 545) set_bdi_congested(fm->sb->s_bdi, BLK_RW_ASYNC);
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 546) }
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 547) list_add_tail(&req->list, &fc->bg_queue);
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 548) flush_bg_queue(fc);
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 549) queued = true;
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 550) }
ae2dffa39485c (Kirill Tkhai 2018-08-27 18:29:46 +0300 551) spin_unlock(&fc->bg_lock);
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 552)
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 553) return queued;
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 554) }
d12def1bcb809 (Miklos Szeredi 2008-02-06 01:38:39 -0800 555)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 556) int fuse_simple_background(struct fuse_mount *fm, struct fuse_args *args,
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 557) gfp_t gfp_flags)
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 558) {
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 559) struct fuse_req *req;
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 560)
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 561) if (args->force) {
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 562) WARN_ON(!args->nocreds);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 563) req = fuse_request_alloc(fm, gfp_flags);
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 564) if (!req)
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 565) return -ENOMEM;
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 566) __set_bit(FR_BACKGROUND, &req->flags);
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 567) } else {
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 568) WARN_ON(args->nocreds);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 569) req = fuse_get_req(fm, true);
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 570) if (IS_ERR(req))
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 571) return PTR_ERR(req);
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 572) }
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 573)
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 574) fuse_args_to_req(req, args);
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 575)
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 576) if (!fuse_request_queue_background(req)) {
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 577) fuse_put_request(req);
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 578) return -ENOTCONN;
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 579) }
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 580)
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 581) return 0;
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 582) }
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 583) EXPORT_SYMBOL_GPL(fuse_simple_background);
1259728731a79 (Miklos Szeredi 2019-09-10 15:04:10 +0200 584)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 585) static int fuse_simple_notify_reply(struct fuse_mount *fm,
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 586) struct fuse_args *args, u64 unique)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 587) {
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 588) struct fuse_req *req;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 589) struct fuse_iqueue *fiq = &fm->fc->iq;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 590) int err = 0;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 591)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 592) req = fuse_get_req(fm, false);
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 593) if (IS_ERR(req))
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 594) return PTR_ERR(req);
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 595)
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 596) __clear_bit(FR_ISREPLY, &req->flags);
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 597) req->in.h.unique = unique;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 598)
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 599) fuse_args_to_req(req, args);
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 600)
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 601) spin_lock(&fiq->lock);
e16714d8756dc (Miklos Szeredi 2015-07-01 16:26:01 +0200 602) if (fiq->connected) {
ae3aad77f46fb (Stefan Hajnoczi 2018-06-18 15:53:19 +0100 603) queue_request_and_unlock(fiq, req);
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 604) } else {
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 605) err = -ENODEV;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 606) spin_unlock(&fiq->lock);
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 607) fuse_put_request(req);
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 608) }
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 609)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 610) return err;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 611) }
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 612)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 613) /*
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 614) * Lock the request. Up to the next unlock_request() there mustn't be
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 615) * anything that could cause a page-fault. If the request was already
f9a2842e5612b (Miklos Szeredi 2006-06-25 05:48:53 -0700 616) * aborted bail out.
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 617) */
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 618) static int lock_request(struct fuse_req *req)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 619) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 620) int err = 0;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 621) if (req) {
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 622) spin_lock(&req->waitq.lock);
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 623) if (test_bit(FR_ABORTED, &req->flags))
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 624) err = -ENOENT;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 625) else
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 626) set_bit(FR_LOCKED, &req->flags);
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 627) spin_unlock(&req->waitq.lock);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 628) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 629) return err;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 630) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 631)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 632) /*
0d8e84b0432be (Miklos Szeredi 2015-07-01 16:25:58 +0200 633) * Unlock request. If it was aborted while locked, caller is responsible
0d8e84b0432be (Miklos Szeredi 2015-07-01 16:25:58 +0200 634) * for unlocking and ending the request.
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 635) */
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 636) static int unlock_request(struct fuse_req *req)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 637) {
0d8e84b0432be (Miklos Szeredi 2015-07-01 16:25:58 +0200 638) int err = 0;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 639) if (req) {
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 640) spin_lock(&req->waitq.lock);
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 641) if (test_bit(FR_ABORTED, &req->flags))
0d8e84b0432be (Miklos Szeredi 2015-07-01 16:25:58 +0200 642) err = -ENOENT;
0d8e84b0432be (Miklos Szeredi 2015-07-01 16:25:58 +0200 643) else
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 644) clear_bit(FR_LOCKED, &req->flags);
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 645) spin_unlock(&req->waitq.lock);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 646) }
0d8e84b0432be (Miklos Szeredi 2015-07-01 16:25:58 +0200 647) return err;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 648) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 649)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 650) struct fuse_copy_state {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 651) int write;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 652) struct fuse_req *req;
6c09e94a32e10 (Al Viro 2015-04-03 22:06:08 -0400 653) struct iov_iter *iter;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 654) struct pipe_buffer *pipebufs;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 655) struct pipe_buffer *currbuf;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 656) struct pipe_inode_info *pipe;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 657) unsigned long nr_segs;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 658) struct page *pg;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 659) unsigned len;
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 660) unsigned offset;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 661) unsigned move_pages:1;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 662) };
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 663)
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 664) static void fuse_copy_init(struct fuse_copy_state *cs, int write,
6c09e94a32e10 (Al Viro 2015-04-03 22:06:08 -0400 665) struct iov_iter *iter)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 666) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 667) memset(cs, 0, sizeof(*cs));
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 668) cs->write = write;
6c09e94a32e10 (Al Viro 2015-04-03 22:06:08 -0400 669) cs->iter = iter;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 670) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 671)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 672) /* Unmap and put previous page of userspace buffer */
8bfc016d2e2ff (Miklos Szeredi 2006-01-16 22:14:28 -0800 673) static void fuse_copy_finish(struct fuse_copy_state *cs)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 674) {
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 675) if (cs->currbuf) {
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 676) struct pipe_buffer *buf = cs->currbuf;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 677)
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 678) if (cs->write)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 679) buf->len = PAGE_SIZE - cs->len;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 680) cs->currbuf = NULL;
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 681) } else if (cs->pg) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 682) if (cs->write) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 683) flush_dcache_page(cs->pg);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 684) set_page_dirty_lock(cs->pg);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 685) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 686) put_page(cs->pg);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 687) }
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 688) cs->pg = NULL;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 689) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 690)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 691) /*
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 692) * Get another pagefull of userspace buffer, and map it to kernel
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 693) * address space, and lock request
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 694) */
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 695) static int fuse_copy_fill(struct fuse_copy_state *cs)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 696) {
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 697) struct page *page;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 698) int err;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 699)
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 700) err = unlock_request(cs->req);
0d8e84b0432be (Miklos Szeredi 2015-07-01 16:25:58 +0200 701) if (err)
0d8e84b0432be (Miklos Szeredi 2015-07-01 16:25:58 +0200 702) return err;
0d8e84b0432be (Miklos Szeredi 2015-07-01 16:25:58 +0200 703)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 704) fuse_copy_finish(cs);
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 705) if (cs->pipebufs) {
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 706) struct pipe_buffer *buf = cs->pipebufs;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 707)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 708) if (!cs->write) {
fba597db4218a (Miklos Szeredi 2016-09-27 10:45:12 +0200 709) err = pipe_buf_confirm(cs->pipe, buf);
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 710) if (err)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 711) return err;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 712)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 713) BUG_ON(!cs->nr_segs);
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 714) cs->currbuf = buf;
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 715) cs->pg = buf->page;
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 716) cs->offset = buf->offset;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 717) cs->len = buf->len;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 718) cs->pipebufs++;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 719) cs->nr_segs--;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 720) } else {
6718b6f855a0b (David Howells 2019-10-16 16:47:32 +0100 721) if (cs->nr_segs >= cs->pipe->max_usage)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 722) return -EIO;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 723)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 724) page = alloc_page(GFP_HIGHUSER);
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 725) if (!page)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 726) return -ENOMEM;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 727)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 728) buf->page = page;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 729) buf->offset = 0;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 730) buf->len = 0;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 731)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 732) cs->currbuf = buf;
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 733) cs->pg = page;
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 734) cs->offset = 0;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 735) cs->len = PAGE_SIZE;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 736) cs->pipebufs++;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 737) cs->nr_segs++;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 738) }
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 739) } else {
6c09e94a32e10 (Al Viro 2015-04-03 22:06:08 -0400 740) size_t off;
6c09e94a32e10 (Al Viro 2015-04-03 22:06:08 -0400 741) err = iov_iter_get_pages(cs->iter, &page, PAGE_SIZE, 1, &off);
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 742) if (err < 0)
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 743) return err;
6c09e94a32e10 (Al Viro 2015-04-03 22:06:08 -0400 744) BUG_ON(!err);
6c09e94a32e10 (Al Viro 2015-04-03 22:06:08 -0400 745) cs->len = err;
6c09e94a32e10 (Al Viro 2015-04-03 22:06:08 -0400 746) cs->offset = off;
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 747) cs->pg = page;
6c09e94a32e10 (Al Viro 2015-04-03 22:06:08 -0400 748) iov_iter_advance(cs->iter, err);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 749) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 750)
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 751) return lock_request(cs->req);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 752) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 753)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 754) /* Do as much copy to/from userspace buffer as we can */
8bfc016d2e2ff (Miklos Szeredi 2006-01-16 22:14:28 -0800 755) static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 756) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 757) unsigned ncpy = min(*size, cs->len);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 758) if (val) {
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 759) void *pgaddr = kmap_atomic(cs->pg);
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 760) void *buf = pgaddr + cs->offset;
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 761)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 762) if (cs->write)
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 763) memcpy(buf, *val, ncpy);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 764) else
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 765) memcpy(*val, buf, ncpy);
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 766)
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 767) kunmap_atomic(pgaddr);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 768) *val += ncpy;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 769) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 770) *size -= ncpy;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 771) cs->len -= ncpy;
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 772) cs->offset += ncpy;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 773) return ncpy;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 774) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 775)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 776) static int fuse_check_page(struct page *page)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 777) {
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 778) if (page_mapcount(page) ||
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 779) page->mapping != NULL ||
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 780) (page->flags & PAGE_FLAGS_CHECK_AT_PREP &
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 781) ~(1 << PG_locked |
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 782) 1 << PG_referenced |
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 783) 1 << PG_uptodate |
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 784) 1 << PG_lru |
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 785) 1 << PG_active |
76d97f2f3b028 (Miklos Szeredi 2021-06-18 21:16:42 +0200 786) 1 << PG_workingset |
a5005c3cda6ee (Miklos Szeredi 2020-05-19 14:50:37 +0200 787) 1 << PG_reclaim |
a5005c3cda6ee (Miklos Szeredi 2020-05-19 14:50:37 +0200 788) 1 << PG_waiters))) {
00589386172ac (Miklos Szeredi 2020-05-19 14:50:37 +0200 789) dump_page(page, "fuse: trying to steal weird page");
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 790) return 1;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 791) }
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 792) return 0;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 793) }
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 794)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 795) static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 796) {
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 797) int err;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 798) struct page *oldpage = *pagep;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 799) struct page *newpage;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 800) struct pipe_buffer *buf = cs->pipebufs;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 801)
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 802) get_page(oldpage);
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 803) err = unlock_request(cs->req);
0d8e84b0432be (Miklos Szeredi 2015-07-01 16:25:58 +0200 804) if (err)
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 805) goto out_put_old;
0d8e84b0432be (Miklos Szeredi 2015-07-01 16:25:58 +0200 806)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 807) fuse_copy_finish(cs);
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 808)
fba597db4218a (Miklos Szeredi 2016-09-27 10:45:12 +0200 809) err = pipe_buf_confirm(cs->pipe, buf);
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 810) if (err)
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 811) goto out_put_old;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 812)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 813) BUG_ON(!cs->nr_segs);
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 814) cs->currbuf = buf;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 815) cs->len = buf->len;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 816) cs->pipebufs++;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 817) cs->nr_segs--;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 818)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 819) if (cs->len != PAGE_SIZE)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 820) goto out_fallback;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 821)
c928f642c29a5 (Christoph Hellwig 2020-05-20 17:58:16 +0200 822) if (!pipe_buf_try_steal(cs->pipe, buf))
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 823) goto out_fallback;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 824)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 825) newpage = buf->page;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 826)
aa991b3b267e2 (Miklos Szeredi 2015-02-26 11:45:47 +0100 827) if (!PageUptodate(newpage))
aa991b3b267e2 (Miklos Szeredi 2015-02-26 11:45:47 +0100 828) SetPageUptodate(newpage);
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 829)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 830) ClearPageMappedToDisk(newpage);
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 831)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 832) if (fuse_check_page(newpage) != 0)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 833) goto out_fallback_unlock;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 834)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 835) /*
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 836) * This is a new and locked page, it shouldn't be mapped or
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 837) * have any special flags on it
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 838) */
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 839) if (WARN_ON(page_mapped(oldpage)))
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 840) goto out_fallback_unlock;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 841) if (WARN_ON(page_has_private(oldpage)))
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 842) goto out_fallback_unlock;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 843) if (WARN_ON(PageDirty(oldpage) || PageWriteback(oldpage)))
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 844) goto out_fallback_unlock;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 845) if (WARN_ON(PageMlocked(oldpage)))
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 846) goto out_fallback_unlock;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 847)
1f7ef65774034 (Baolin Wang 2021-02-24 12:01:42 -0800 848) replace_page_cache_page(oldpage, newpage);
ef6a3c63112e8 (Miklos Szeredi 2011-03-22 16:30:52 -0700 849)
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 850) get_page(newpage);
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 851)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 852) if (!(buf->flags & PIPE_BUF_FLAG_LRU))
6058eaec816f2 (Johannes Weiner 2020-06-03 16:02:40 -0700 853) lru_cache_add(newpage);
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 854)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 855) err = 0;
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 856) spin_lock(&cs->req->waitq.lock);
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 857) if (test_bit(FR_ABORTED, &cs->req->flags))
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 858) err = -ENOENT;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 859) else
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 860) *pagep = newpage;
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 861) spin_unlock(&cs->req->waitq.lock);
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 862)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 863) if (err) {
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 864) unlock_page(newpage);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 865) put_page(newpage);
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 866) goto out_put_old;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 867) }
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 868)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 869) unlock_page(oldpage);
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 870) /* Drop ref for ap->pages[] array */
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 871) put_page(oldpage);
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 872) cs->len = 0;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 873)
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 874) err = 0;
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 875) out_put_old:
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 876) /* Drop ref obtained in this function */
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 877) put_page(oldpage);
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 878) return err;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 879)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 880) out_fallback_unlock:
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 881) unlock_page(newpage);
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 882) out_fallback:
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 883) cs->pg = buf->page;
c55a01d360afa (Miklos Szeredi 2014-07-07 15:28:51 +0200 884) cs->offset = buf->offset;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 885)
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 886) err = lock_request(cs->req);
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 887) if (!err)
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 888) err = 1;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 889)
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 890) goto out_put_old;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 891) }
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 892)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 893) static int fuse_ref_page(struct fuse_copy_state *cs, struct page *page,
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 894) unsigned offset, unsigned count)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 895) {
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 896) struct pipe_buffer *buf;
0d8e84b0432be (Miklos Szeredi 2015-07-01 16:25:58 +0200 897) int err;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 898)
6718b6f855a0b (David Howells 2019-10-16 16:47:32 +0100 899) if (cs->nr_segs >= cs->pipe->max_usage)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 900) return -EIO;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 901)
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 902) get_page(page);
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 903) err = unlock_request(cs->req);
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 904) if (err) {
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 905) put_page(page);
0d8e84b0432be (Miklos Szeredi 2015-07-01 16:25:58 +0200 906) return err;
d78092e4937de (Miklos Szeredi 2020-09-18 10:36:50 +0200 907) }
0d8e84b0432be (Miklos Szeredi 2015-07-01 16:25:58 +0200 908)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 909) fuse_copy_finish(cs);
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 910)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 911) buf = cs->pipebufs;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 912) buf->page = page;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 913) buf->offset = offset;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 914) buf->len = count;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 915)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 916) cs->pipebufs++;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 917) cs->nr_segs++;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 918) cs->len = 0;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 919)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 920) return 0;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 921) }
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 922)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 923) /*
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 924) * Copy a page in the request to/from the userspace buffer. Must be
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 925) * done atomically
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 926) */
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 927) static int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep,
8bfc016d2e2ff (Miklos Szeredi 2006-01-16 22:14:28 -0800 928) unsigned offset, unsigned count, int zeroing)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 929) {
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 930) int err;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 931) struct page *page = *pagep;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 932)
b6777c40c7916 (Miklos Szeredi 2010-10-26 14:22:27 -0700 933) if (page && zeroing && count < PAGE_SIZE)
b6777c40c7916 (Miklos Szeredi 2010-10-26 14:22:27 -0700 934) clear_highpage(page);
b6777c40c7916 (Miklos Szeredi 2010-10-26 14:22:27 -0700 935)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 936) while (count) {
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 937) if (cs->write && cs->pipebufs && page) {
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 938) return fuse_ref_page(cs, page, offset, count);
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 939) } else if (!cs->len) {
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 940) if (cs->move_pages && page &&
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 941) offset == 0 && count == PAGE_SIZE) {
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 942) err = fuse_try_move_page(cs, pagep);
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 943) if (err <= 0)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 944) return err;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 945) } else {
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 946) err = fuse_copy_fill(cs);
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 947) if (err)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 948) return err;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 949) }
1729a16c2c92b (Miklos Szeredi 2008-11-26 12:03:54 +0100 950) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 951) if (page) {
2408f6ef6bf58 (Cong Wang 2011-11-25 23:14:30 +0800 952) void *mapaddr = kmap_atomic(page);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 953) void *buf = mapaddr + offset;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 954) offset += fuse_copy_do(cs, &buf, &count);
2408f6ef6bf58 (Cong Wang 2011-11-25 23:14:30 +0800 955) kunmap_atomic(mapaddr);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 956) } else
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 957) offset += fuse_copy_do(cs, NULL, &count);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 958) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 959) if (page && !cs->write)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 960) flush_dcache_page(page);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 961) return 0;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 962) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 963)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 964) /* Copy pages in the request to/from userspace buffer */
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 965) static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes,
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 966) int zeroing)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 967) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 968) unsigned i;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 969) struct fuse_req *req = cs->req;
05ea48cc2b098 (Miklos Szeredi 2019-09-10 15:04:11 +0200 970) struct fuse_args_pages *ap = container_of(req->args, typeof(*ap), args);
05ea48cc2b098 (Miklos Szeredi 2019-09-10 15:04:11 +0200 971)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 972)
05ea48cc2b098 (Miklos Szeredi 2019-09-10 15:04:11 +0200 973) for (i = 0; i < ap->num_pages && (nbytes || zeroing); i++) {
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 974) int err;
05ea48cc2b098 (Miklos Szeredi 2019-09-10 15:04:11 +0200 975) unsigned int offset = ap->descs[i].offset;
05ea48cc2b098 (Miklos Szeredi 2019-09-10 15:04:11 +0200 976) unsigned int count = min(nbytes, ap->descs[i].length);
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 977)
05ea48cc2b098 (Miklos Szeredi 2019-09-10 15:04:11 +0200 978) err = fuse_copy_page(cs, &ap->pages[i], offset, count, zeroing);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 979) if (err)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 980) return err;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 981)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 982) nbytes -= count;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 983) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 984) return 0;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 985) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 986)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 987) /* Copy a single argument in the request to/from userspace buffer */
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 988) static int fuse_copy_one(struct fuse_copy_state *cs, void *val, unsigned size)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 989) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 990) while (size) {
1729a16c2c92b (Miklos Szeredi 2008-11-26 12:03:54 +0100 991) if (!cs->len) {
1729a16c2c92b (Miklos Szeredi 2008-11-26 12:03:54 +0100 992) int err = fuse_copy_fill(cs);
1729a16c2c92b (Miklos Szeredi 2008-11-26 12:03:54 +0100 993) if (err)
1729a16c2c92b (Miklos Szeredi 2008-11-26 12:03:54 +0100 994) return err;
1729a16c2c92b (Miklos Szeredi 2008-11-26 12:03:54 +0100 995) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 996) fuse_copy_do(cs, &val, &size);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 997) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 998) return 0;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 999) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1000)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1001) /* Copy request arguments to/from userspace buffer */
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1002) static int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs,
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1003) unsigned argpages, struct fuse_arg *args,
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1004) int zeroing)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1005) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1006) int err = 0;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1007) unsigned i;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1008)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1009) for (i = 0; !err && i < numargs; i++) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1010) struct fuse_arg *arg = &args[i];
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1011) if (i == numargs - 1 && argpages)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1012) err = fuse_copy_pages(cs, arg->size, zeroing);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1013) else
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1014) err = fuse_copy_one(cs, arg->value, arg->size);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1015) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1016) return err;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1017) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1018)
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1019) static int forget_pending(struct fuse_iqueue *fiq)
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1020) {
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1021) return fiq->forget_list_head.next != NULL;
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1022) }
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1023)
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1024) static int request_pending(struct fuse_iqueue *fiq)
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1025) {
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1026) return !list_empty(&fiq->pending) || !list_empty(&fiq->interrupts) ||
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1027) forget_pending(fiq);
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1028) }
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1029)
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1030) /*
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1031) * Transfer an interrupt request to userspace
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1032) *
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1033) * Unlike other requests this is assembled on demand, without a need
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1034) * to allocate a separate fuse_req structure.
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1035) *
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1036) * Called with fiq->lock held, releases it
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1037) */
fd22d62ed0c36 (Miklos Szeredi 2015-07-01 16:26:03 +0200 1038) static int fuse_read_interrupt(struct fuse_iqueue *fiq,
fd22d62ed0c36 (Miklos Szeredi 2015-07-01 16:26:03 +0200 1039) struct fuse_copy_state *cs,
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1040) size_t nbytes, struct fuse_req *req)
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1041) __releases(fiq->lock)
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1042) {
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1043) struct fuse_in_header ih;
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1044) struct fuse_interrupt_in arg;
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1045) unsigned reqsize = sizeof(ih) + sizeof(arg);
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1046) int err;
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1047)
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1048) list_del_init(&req->intr_entry);
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1049) memset(&ih, 0, sizeof(ih));
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1050) memset(&arg, 0, sizeof(arg));
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1051) ih.len = reqsize;
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1052) ih.opcode = FUSE_INTERRUPT;
3a5358d1a1b70 (Kirill Tkhai 2018-09-11 13:12:05 +0300 1053) ih.unique = (req->in.h.unique | FUSE_INT_REQ_BIT);
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1054) arg.unique = req->in.h.unique;
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1055)
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1056) spin_unlock(&fiq->lock);
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1057) if (nbytes < reqsize)
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1058) return -EINVAL;
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1059)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1060) err = fuse_copy_one(cs, &ih, sizeof(ih));
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1061) if (!err)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1062) err = fuse_copy_one(cs, &arg, sizeof(arg));
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1063) fuse_copy_finish(cs);
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1064)
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1065) return err ? err : reqsize;
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1066) }
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1067)
4388c5aac4bae (Vivek Goyal 2019-06-05 15:50:43 -0400 1068) struct fuse_forget_link *fuse_dequeue_forget(struct fuse_iqueue *fiq,
4388c5aac4bae (Vivek Goyal 2019-06-05 15:50:43 -0400 1069) unsigned int max,
4388c5aac4bae (Vivek Goyal 2019-06-05 15:50:43 -0400 1070) unsigned int *countp)
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1071) {
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1072) struct fuse_forget_link *head = fiq->forget_list_head.next;
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1073) struct fuse_forget_link **newhead = &head;
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1074) unsigned count;
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1075)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1076) for (count = 0; *newhead != NULL && count < max; count++)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1077) newhead = &(*newhead)->next;
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1078)
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1079) fiq->forget_list_head.next = *newhead;
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1080) *newhead = NULL;
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1081) if (fiq->forget_list_head.next == NULL)
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1082) fiq->forget_list_tail = &fiq->forget_list_head;
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1083)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1084) if (countp != NULL)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1085) *countp = count;
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1086)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1087) return head;
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1088) }
4388c5aac4bae (Vivek Goyal 2019-06-05 15:50:43 -0400 1089) EXPORT_SYMBOL(fuse_dequeue_forget);
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1090)
fd22d62ed0c36 (Miklos Szeredi 2015-07-01 16:26:03 +0200 1091) static int fuse_read_single_forget(struct fuse_iqueue *fiq,
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1092) struct fuse_copy_state *cs,
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1093) size_t nbytes)
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1094) __releases(fiq->lock)
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1095) {
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1096) int err;
4388c5aac4bae (Vivek Goyal 2019-06-05 15:50:43 -0400 1097) struct fuse_forget_link *forget = fuse_dequeue_forget(fiq, 1, NULL);
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1098) struct fuse_forget_in arg = {
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1099) .nlookup = forget->forget_one.nlookup,
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1100) };
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1101) struct fuse_in_header ih = {
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1102) .opcode = FUSE_FORGET,
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1103) .nodeid = forget->forget_one.nodeid,
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1104) .unique = fuse_get_unique(fiq),
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1105) .len = sizeof(ih) + sizeof(arg),
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1106) };
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1107)
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1108) spin_unlock(&fiq->lock);
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1109) kfree(forget);
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1110) if (nbytes < ih.len)
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1111) return -EINVAL;
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1112)
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1113) err = fuse_copy_one(cs, &ih, sizeof(ih));
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1114) if (!err)
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1115) err = fuse_copy_one(cs, &arg, sizeof(arg));
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1116) fuse_copy_finish(cs);
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1117)
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1118) if (err)
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1119) return err;
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1120)
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1121) return ih.len;
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1122) }
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1123)
fd22d62ed0c36 (Miklos Szeredi 2015-07-01 16:26:03 +0200 1124) static int fuse_read_batch_forget(struct fuse_iqueue *fiq,
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1125) struct fuse_copy_state *cs, size_t nbytes)
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1126) __releases(fiq->lock)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1127) {
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1128) int err;
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1129) unsigned max_forgets;
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1130) unsigned count;
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1131) struct fuse_forget_link *head;
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1132) struct fuse_batch_forget_in arg = { .count = 0 };
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1133) struct fuse_in_header ih = {
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1134) .opcode = FUSE_BATCH_FORGET,
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1135) .unique = fuse_get_unique(fiq),
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1136) .len = sizeof(ih) + sizeof(arg),
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1137) };
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1138)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1139) if (nbytes < ih.len) {
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1140) spin_unlock(&fiq->lock);
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1141) return -EINVAL;
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1142) }
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1143)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1144) max_forgets = (nbytes - ih.len) / sizeof(struct fuse_forget_one);
4388c5aac4bae (Vivek Goyal 2019-06-05 15:50:43 -0400 1145) head = fuse_dequeue_forget(fiq, max_forgets, &count);
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1146) spin_unlock(&fiq->lock);
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1147)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1148) arg.count = count;
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1149) ih.len += count * sizeof(struct fuse_forget_one);
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1150) err = fuse_copy_one(cs, &ih, sizeof(ih));
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1151) if (!err)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1152) err = fuse_copy_one(cs, &arg, sizeof(arg));
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1153)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1154) while (head) {
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1155) struct fuse_forget_link *forget = head;
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1156)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1157) if (!err) {
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1158) err = fuse_copy_one(cs, &forget->forget_one,
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1159) sizeof(forget->forget_one));
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1160) }
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1161) head = forget->next;
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1162) kfree(forget);
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1163) }
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1164)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1165) fuse_copy_finish(cs);
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1166)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1167) if (err)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1168) return err;
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1169)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1170) return ih.len;
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1171) }
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1172)
fd22d62ed0c36 (Miklos Szeredi 2015-07-01 16:26:03 +0200 1173) static int fuse_read_forget(struct fuse_conn *fc, struct fuse_iqueue *fiq,
fd22d62ed0c36 (Miklos Szeredi 2015-07-01 16:26:03 +0200 1174) struct fuse_copy_state *cs,
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1175) size_t nbytes)
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1176) __releases(fiq->lock)
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1177) {
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1178) if (fc->minor < 16 || fiq->forget_list_head.next->next == NULL)
fd22d62ed0c36 (Miklos Szeredi 2015-07-01 16:26:03 +0200 1179) return fuse_read_single_forget(fiq, cs, nbytes);
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1180) else
fd22d62ed0c36 (Miklos Szeredi 2015-07-01 16:26:03 +0200 1181) return fuse_read_batch_forget(fiq, cs, nbytes);
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1182) }
02c048b919455 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1183)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1184) /*
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1185) * Read a single request into the userspace filesystem's buffer. This
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1186) * function waits until a request is available, then removes it from
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1187) * the pending list and copies request data to userspace buffer. If
f9a2842e5612b (Miklos Szeredi 2006-06-25 05:48:53 -0700 1188) * no reply is needed (FORGET) or request has been aborted or there
f9a2842e5612b (Miklos Szeredi 2006-06-25 05:48:53 -0700 1189) * was an error during the copying then it's finished by calling
04ec5af0776e9 (Stefan Hajnoczi 2018-06-21 09:33:40 +0100 1190) * fuse_request_end(). Otherwise add it to the processing list, and set
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1191) * the 'sent' flag.
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1192) */
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 1193) static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1194) struct fuse_copy_state *cs, size_t nbytes)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1195) {
82cbdcd320852 (Miklos Szeredi 2015-07-01 16:26:05 +0200 1196) ssize_t err;
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 1197) struct fuse_conn *fc = fud->fc;
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1198) struct fuse_iqueue *fiq = &fc->iq;
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 1199) struct fuse_pqueue *fpq = &fud->pq;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1200) struct fuse_req *req;
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1201) struct fuse_args *args;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1202) unsigned reqsize;
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 1203) unsigned int hash;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1204)
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1205) /*
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1206) * Require sane minimum read buffer - that has capacity for fixed part
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1207) * of any request header + negotiated max_write room for data.
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1208) *
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1209) * Historically libfuse reserves 4K for fixed header room, but e.g.
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1210) * GlusterFS reserves only 80 bytes
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1211) *
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1212) * = `sizeof(fuse_in_header) + sizeof(fuse_write_in)`
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1213) *
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1214) * which is the absolute minimum any sane filesystem should be using
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1215) * for header room.
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1216) */
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1217) if (nbytes < max_t(size_t, FUSE_MIN_READ_BUFFER,
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1218) sizeof(struct fuse_in_header) +
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1219) sizeof(struct fuse_write_in) +
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1220) fc->max_write))
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1221) return -EINVAL;
1fb027d759646 (Kirill Smelkov 2019-07-08 17:03:31 +0000 1222)
1d3d752b471d2 (Miklos Szeredi 2006-01-06 00:19:40 -0800 1223) restart:
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1224) for (;;) {
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1225) spin_lock(&fiq->lock);
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1226) if (!fiq->connected || request_pending(fiq))
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1227) break;
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1228) spin_unlock(&fiq->lock);
e5ac1d1e70a8c (Jeff Dike 2006-04-10 22:54:53 -0700 1229)
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1230) if (file->f_flags & O_NONBLOCK)
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1231) return -EAGAIN;
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1232) err = wait_event_interruptible_exclusive(fiq->waitq,
5250921bb0b25 (Miklos Szeredi 2015-07-01 16:26:03 +0200 1233) !fiq->connected || request_pending(fiq));
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1234) if (err)
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1235) return err;
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1236) }
5250921bb0b25 (Miklos Szeredi 2015-07-01 16:26:03 +0200 1237)
3b7008b226f3d (Szymon Lukasz 2017-11-09 21:23:35 +0100 1238) if (!fiq->connected) {
eb98e3bdf3aa7 (Miklos Szeredi 2019-01-24 10:40:16 +0100 1239) err = fc->aborted ? -ECONNABORTED : -ENODEV;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1240) goto err_unlock;
3b7008b226f3d (Szymon Lukasz 2017-11-09 21:23:35 +0100 1241) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1242)
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1243) if (!list_empty(&fiq->interrupts)) {
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1244) req = list_entry(fiq->interrupts.next, struct fuse_req,
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1245) intr_entry);
fd22d62ed0c36 (Miklos Szeredi 2015-07-01 16:26:03 +0200 1246) return fuse_read_interrupt(fiq, cs, nbytes, req);
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1247) }
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1248)
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1249) if (forget_pending(fiq)) {
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1250) if (list_empty(&fiq->pending) || fiq->forget_batch-- > 0)
fd22d62ed0c36 (Miklos Szeredi 2015-07-01 16:26:03 +0200 1251) return fuse_read_forget(fc, fiq, cs, nbytes);
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1252)
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1253) if (fiq->forget_batch <= -8)
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1254) fiq->forget_batch = 16;
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1255) }
07e77dca8a1f1 (Miklos Szeredi 2010-12-07 20:16:56 +0100 1256)
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1257) req = list_entry(fiq->pending.next, struct fuse_req, list);
33e14b4dfdc47 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1258) clear_bit(FR_PENDING, &req->flags);
ef759258869c6 (Miklos Szeredi 2015-07-01 16:26:02 +0200 1259) list_del_init(&req->list);
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1260) spin_unlock(&fiq->lock);
4ce6081260ea4 (Miklos Szeredi 2015-07-01 16:26:02 +0200 1261)
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1262) args = req->args;
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1263) reqsize = req->in.h.len;
5d6d3a301c4e7 (Miklos Szeredi 2017-09-12 16:57:53 +0200 1264)
1d3d752b471d2 (Miklos Szeredi 2006-01-06 00:19:40 -0800 1265) /* If request is too large, reply with an error and restart the read */
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1266) if (nbytes < reqsize) {
1d3d752b471d2 (Miklos Szeredi 2006-01-06 00:19:40 -0800 1267) req->out.h.error = -EIO;
1d3d752b471d2 (Miklos Szeredi 2006-01-06 00:19:40 -0800 1268) /* SETXATTR is special, since it may contain too large data */
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1269) if (args->opcode == FUSE_SETXATTR)
1d3d752b471d2 (Miklos Szeredi 2006-01-06 00:19:40 -0800 1270) req->out.h.error = -E2BIG;
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 1271) fuse_request_end(req);
1d3d752b471d2 (Miklos Szeredi 2006-01-06 00:19:40 -0800 1272) goto restart;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1273) }
45a91cb1a4fd9 (Miklos Szeredi 2015-07-01 16:26:06 +0200 1274) spin_lock(&fpq->lock);
2644fd6588e59 (Miklos Szeredi 2021-06-22 09:15:35 +0200 1275) /*
2644fd6588e59 (Miklos Szeredi 2021-06-22 09:15:35 +0200 1276) * Must not put request on fpq->io queue after having been shut down by
2644fd6588e59 (Miklos Szeredi 2021-06-22 09:15:35 +0200 1277) * fuse_abort_conn()
2644fd6588e59 (Miklos Szeredi 2021-06-22 09:15:35 +0200 1278) */
2644fd6588e59 (Miklos Szeredi 2021-06-22 09:15:35 +0200 1279) if (!fpq->connected) {
2644fd6588e59 (Miklos Szeredi 2021-06-22 09:15:35 +0200 1280) req->out.h.error = err = -ECONNABORTED;
2644fd6588e59 (Miklos Szeredi 2021-06-22 09:15:35 +0200 1281) goto out_end;
2644fd6588e59 (Miklos Szeredi 2021-06-22 09:15:35 +0200 1282)
2644fd6588e59 (Miklos Szeredi 2021-06-22 09:15:35 +0200 1283) }
82cbdcd320852 (Miklos Szeredi 2015-07-01 16:26:05 +0200 1284) list_add(&req->list, &fpq->io);
45a91cb1a4fd9 (Miklos Szeredi 2015-07-01 16:26:06 +0200 1285) spin_unlock(&fpq->lock);
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1286) cs->req = req;
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1287) err = fuse_copy_one(cs, &req->in.h, sizeof(req->in.h));
1d3d752b471d2 (Miklos Szeredi 2006-01-06 00:19:40 -0800 1288) if (!err)
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1289) err = fuse_copy_args(cs, args->in_numargs, args->in_pages,
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1290) (struct fuse_arg *) args->in_args, 0);
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1291) fuse_copy_finish(cs);
45a91cb1a4fd9 (Miklos Szeredi 2015-07-01 16:26:06 +0200 1292) spin_lock(&fpq->lock);
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 1293) clear_bit(FR_LOCKED, &req->flags);
e96edd94d0887 (Miklos Szeredi 2015-07-01 16:26:04 +0200 1294) if (!fpq->connected) {
eb98e3bdf3aa7 (Miklos Szeredi 2019-01-24 10:40:16 +0100 1295) err = fc->aborted ? -ECONNABORTED : -ENODEV;
82cbdcd320852 (Miklos Szeredi 2015-07-01 16:26:05 +0200 1296) goto out_end;
c9c9d7df5f8ae (Miklos Szeredi 2007-10-16 23:31:05 -0700 1297) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1298) if (err) {
c9c9d7df5f8ae (Miklos Szeredi 2007-10-16 23:31:05 -0700 1299) req->out.h.error = -EIO;
82cbdcd320852 (Miklos Szeredi 2015-07-01 16:26:05 +0200 1300) goto out_end;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1301) }
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 1302) if (!test_bit(FR_ISREPLY, &req->flags)) {
82cbdcd320852 (Miklos Szeredi 2015-07-01 16:26:05 +0200 1303) err = reqsize;
82cbdcd320852 (Miklos Szeredi 2015-07-01 16:26:05 +0200 1304) goto out_end;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1305) }
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 1306) hash = fuse_req_hash(req->in.h.unique);
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 1307) list_move_tail(&req->list, &fpq->processing[hash]);
bc78abbd55dd2 (Kirill Tkhai 2018-09-25 12:28:55 +0300 1308) __fuse_get_request(req);
82cbdcd320852 (Miklos Szeredi 2015-07-01 16:26:05 +0200 1309) set_bit(FR_SENT, &req->flags);
4c316f2f3ff31 (Miklos Szeredi 2018-09-28 16:43:22 +0200 1310) spin_unlock(&fpq->lock);
82cbdcd320852 (Miklos Szeredi 2015-07-01 16:26:05 +0200 1311) /* matches barrier in request_wait_answer() */
82cbdcd320852 (Miklos Szeredi 2015-07-01 16:26:05 +0200 1312) smp_mb__after_atomic();
82cbdcd320852 (Miklos Szeredi 2015-07-01 16:26:05 +0200 1313) if (test_bit(FR_INTERRUPTED, &req->flags))
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 1314) queue_interrupt(req);
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 1315) fuse_put_request(req);
82cbdcd320852 (Miklos Szeredi 2015-07-01 16:26:05 +0200 1316)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1317) return reqsize;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1318)
82cbdcd320852 (Miklos Szeredi 2015-07-01 16:26:05 +0200 1319) out_end:
77cd9d488b32d (Miklos Szeredi 2015-07-01 16:26:06 +0200 1320) if (!test_bit(FR_PRIVATE, &req->flags))
77cd9d488b32d (Miklos Szeredi 2015-07-01 16:26:06 +0200 1321) list_del_init(&req->list);
45a91cb1a4fd9 (Miklos Szeredi 2015-07-01 16:26:06 +0200 1322) spin_unlock(&fpq->lock);
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 1323) fuse_request_end(req);
82cbdcd320852 (Miklos Szeredi 2015-07-01 16:26:05 +0200 1324) return err;
82cbdcd320852 (Miklos Szeredi 2015-07-01 16:26:05 +0200 1325)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1326) err_unlock:
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 1327) spin_unlock(&fiq->lock);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1328) return err;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1329) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1330)
94e4fe2cab3d4 (Tom Van Braeckel 2015-01-12 05:22:16 +0100 1331) static int fuse_dev_open(struct inode *inode, struct file *file)
94e4fe2cab3d4 (Tom Van Braeckel 2015-01-12 05:22:16 +0100 1332) {
94e4fe2cab3d4 (Tom Van Braeckel 2015-01-12 05:22:16 +0100 1333) /*
94e4fe2cab3d4 (Tom Van Braeckel 2015-01-12 05:22:16 +0100 1334) * The fuse device's file's private_data is used to hold
94e4fe2cab3d4 (Tom Van Braeckel 2015-01-12 05:22:16 +0100 1335) * the fuse_conn(ection) when it is mounted, and is used to
94e4fe2cab3d4 (Tom Van Braeckel 2015-01-12 05:22:16 +0100 1336) * keep track of whether the file has been mounted already.
94e4fe2cab3d4 (Tom Van Braeckel 2015-01-12 05:22:16 +0100 1337) */
94e4fe2cab3d4 (Tom Van Braeckel 2015-01-12 05:22:16 +0100 1338) file->private_data = NULL;
94e4fe2cab3d4 (Tom Van Braeckel 2015-01-12 05:22:16 +0100 1339) return 0;
94e4fe2cab3d4 (Tom Van Braeckel 2015-01-12 05:22:16 +0100 1340) }
94e4fe2cab3d4 (Tom Van Braeckel 2015-01-12 05:22:16 +0100 1341)
fbdbacca61531 (Al Viro 2015-04-03 21:53:39 -0400 1342) static ssize_t fuse_dev_read(struct kiocb *iocb, struct iov_iter *to)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1343) {
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1344) struct fuse_copy_state cs;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1345) struct file *file = iocb->ki_filp;
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 1346) struct fuse_dev *fud = fuse_get_dev(file);
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 1347)
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 1348) if (!fud)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1349) return -EPERM;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1350)
fbdbacca61531 (Al Viro 2015-04-03 21:53:39 -0400 1351) if (!iter_is_iovec(to))
fbdbacca61531 (Al Viro 2015-04-03 21:53:39 -0400 1352) return -EINVAL;
fbdbacca61531 (Al Viro 2015-04-03 21:53:39 -0400 1353)
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 1354) fuse_copy_init(&cs, 1, to);
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1355)
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 1356) return fuse_dev_do_read(fud, file, &cs, iov_iter_count(to));
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1357) }
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1358)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1359) static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1360) struct pipe_inode_info *pipe,
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1361) size_t len, unsigned int flags)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1362) {
d82718e348fee (Al Viro 2016-09-17 22:56:25 -0400 1363) int total, ret;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1364) int page_nr = 0;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1365) struct pipe_buffer *bufs;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1366) struct fuse_copy_state cs;
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 1367) struct fuse_dev *fud = fuse_get_dev(in);
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 1368)
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 1369) if (!fud)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1370) return -EPERM;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1371)
6718b6f855a0b (David Howells 2019-10-16 16:47:32 +0100 1372) bufs = kvmalloc_array(pipe->max_usage, sizeof(struct pipe_buffer),
d6d931adce119 (Andrey Ryabinin 2018-07-17 19:00:34 +0300 1373) GFP_KERNEL);
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1374) if (!bufs)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1375) return -ENOMEM;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1376)
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 1377) fuse_copy_init(&cs, 1, NULL);
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1378) cs.pipebufs = bufs;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1379) cs.pipe = pipe;
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 1380) ret = fuse_dev_do_read(fud, in, &cs, len);
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1381) if (ret < 0)
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1382) goto out;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1383)
6718b6f855a0b (David Howells 2019-10-16 16:47:32 +0100 1384) if (pipe_occupancy(pipe->head, pipe->tail) + cs.nr_segs > pipe->max_usage) {
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1385) ret = -EIO;
d82718e348fee (Al Viro 2016-09-17 22:56:25 -0400 1386) goto out;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1387) }
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1388)
d82718e348fee (Al Viro 2016-09-17 22:56:25 -0400 1389) for (ret = total = 0; page_nr < cs.nr_segs; total += ret) {
28a625cbc2a14 (Miklos Szeredi 2014-01-22 19:36:57 +0100 1390) /*
28a625cbc2a14 (Miklos Szeredi 2014-01-22 19:36:57 +0100 1391) * Need to be careful about this. Having buf->ops in module
28a625cbc2a14 (Miklos Szeredi 2014-01-22 19:36:57 +0100 1392) * code can Oops if the buffer persists after module unload.
28a625cbc2a14 (Miklos Szeredi 2014-01-22 19:36:57 +0100 1393) */
d82718e348fee (Al Viro 2016-09-17 22:56:25 -0400 1394) bufs[page_nr].ops = &nosteal_pipe_buf_ops;
84588a93d097b (Miklos Szeredi 2017-02-16 15:08:20 +0100 1395) bufs[page_nr].flags = 0;
d82718e348fee (Al Viro 2016-09-17 22:56:25 -0400 1396) ret = add_to_pipe(pipe, &bufs[page_nr++]);
d82718e348fee (Al Viro 2016-09-17 22:56:25 -0400 1397) if (unlikely(ret < 0))
d82718e348fee (Al Viro 2016-09-17 22:56:25 -0400 1398) break;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1399) }
d82718e348fee (Al Viro 2016-09-17 22:56:25 -0400 1400) if (total)
d82718e348fee (Al Viro 2016-09-17 22:56:25 -0400 1401) ret = total;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1402) out:
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1403) for (; page_nr < cs.nr_segs; page_nr++)
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1404) put_page(bufs[page_nr].page);
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1405)
d6d931adce119 (Andrey Ryabinin 2018-07-17 19:00:34 +0300 1406) kvfree(bufs);
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1407) return ret;
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1408) }
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1409)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 1410) static int fuse_notify_poll(struct fuse_conn *fc, unsigned int size,
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 1411) struct fuse_copy_state *cs)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 1412) {
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 1413) struct fuse_notify_poll_wakeup_out outarg;
f6d47a1761896 (Miklos Szeredi 2009-01-26 15:00:59 +0100 1414) int err = -EINVAL;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 1415)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 1416) if (size != sizeof(outarg))
f6d47a1761896 (Miklos Szeredi 2009-01-26 15:00:59 +0100 1417) goto err;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 1418)
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 1419) err = fuse_copy_one(cs, &outarg, sizeof(outarg));
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 1420) if (err)
f6d47a1761896 (Miklos Szeredi 2009-01-26 15:00:59 +0100 1421) goto err;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 1422)
f6d47a1761896 (Miklos Szeredi 2009-01-26 15:00:59 +0100 1423) fuse_copy_finish(cs);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 1424) return fuse_notify_poll_wakeup(fc, &outarg);
f6d47a1761896 (Miklos Szeredi 2009-01-26 15:00:59 +0100 1425)
f6d47a1761896 (Miklos Szeredi 2009-01-26 15:00:59 +0100 1426) err:
f6d47a1761896 (Miklos Szeredi 2009-01-26 15:00:59 +0100 1427) fuse_copy_finish(cs);
f6d47a1761896 (Miklos Szeredi 2009-01-26 15:00:59 +0100 1428) return err;
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 1429) }
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 1430)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1431) static int fuse_notify_inval_inode(struct fuse_conn *fc, unsigned int size,
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1432) struct fuse_copy_state *cs)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1433) {
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1434) struct fuse_notify_inval_inode_out outarg;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1435) int err = -EINVAL;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1436)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1437) if (size != sizeof(outarg))
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1438) goto err;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1439)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1440) err = fuse_copy_one(cs, &outarg, sizeof(outarg));
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1441) if (err)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1442) goto err;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1443) fuse_copy_finish(cs);
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1444)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1445) down_read(&fc->killsb);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1446) err = fuse_reverse_inval_inode(fc, outarg.ino,
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1447) outarg.off, outarg.len);
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1448) up_read(&fc->killsb);
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1449) return err;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1450)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1451) err:
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1452) fuse_copy_finish(cs);
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1453) return err;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1454) }
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1455)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1456) static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size,
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1457) struct fuse_copy_state *cs)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1458) {
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1459) struct fuse_notify_inval_entry_out outarg;
b2d82ee3c8b21 (Fang Wenqi 2009-12-30 18:37:13 +0800 1460) int err = -ENOMEM;
b2d82ee3c8b21 (Fang Wenqi 2009-12-30 18:37:13 +0800 1461) char *buf;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1462) struct qstr name;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1463)
b2d82ee3c8b21 (Fang Wenqi 2009-12-30 18:37:13 +0800 1464) buf = kzalloc(FUSE_NAME_MAX + 1, GFP_KERNEL);
b2d82ee3c8b21 (Fang Wenqi 2009-12-30 18:37:13 +0800 1465) if (!buf)
b2d82ee3c8b21 (Fang Wenqi 2009-12-30 18:37:13 +0800 1466) goto err;
b2d82ee3c8b21 (Fang Wenqi 2009-12-30 18:37:13 +0800 1467)
b2d82ee3c8b21 (Fang Wenqi 2009-12-30 18:37:13 +0800 1468) err = -EINVAL;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1469) if (size < sizeof(outarg))
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1470) goto err;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1471)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1472) err = fuse_copy_one(cs, &outarg, sizeof(outarg));
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1473) if (err)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1474) goto err;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1475)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1476) err = -ENAMETOOLONG;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1477) if (outarg.namelen > FUSE_NAME_MAX)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1478) goto err;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1479)
c2183d1e9b3f3 (Miklos Szeredi 2011-08-24 10:20:17 +0200 1480) err = -EINVAL;
c2183d1e9b3f3 (Miklos Szeredi 2011-08-24 10:20:17 +0200 1481) if (size != sizeof(outarg) + outarg.namelen + 1)
c2183d1e9b3f3 (Miklos Szeredi 2011-08-24 10:20:17 +0200 1482) goto err;
c2183d1e9b3f3 (Miklos Szeredi 2011-08-24 10:20:17 +0200 1483)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1484) name.name = buf;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1485) name.len = outarg.namelen;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1486) err = fuse_copy_one(cs, buf, outarg.namelen + 1);
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1487) if (err)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1488) goto err;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1489) fuse_copy_finish(cs);
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1490) buf[outarg.namelen] = 0;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1491)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1492) down_read(&fc->killsb);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1493) err = fuse_reverse_inval_entry(fc, outarg.parent, 0, &name);
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1494) up_read(&fc->killsb);
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1495) kfree(buf);
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1496) return err;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1497)
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1498) err:
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1499) kfree(buf);
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1500) fuse_copy_finish(cs);
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1501) return err;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1502) }
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1503)
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1504) static int fuse_notify_delete(struct fuse_conn *fc, unsigned int size,
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1505) struct fuse_copy_state *cs)
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1506) {
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1507) struct fuse_notify_delete_out outarg;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1508) int err = -ENOMEM;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1509) char *buf;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1510) struct qstr name;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1511)
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1512) buf = kzalloc(FUSE_NAME_MAX + 1, GFP_KERNEL);
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1513) if (!buf)
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1514) goto err;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1515)
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1516) err = -EINVAL;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1517) if (size < sizeof(outarg))
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1518) goto err;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1519)
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1520) err = fuse_copy_one(cs, &outarg, sizeof(outarg));
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1521) if (err)
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1522) goto err;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1523)
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1524) err = -ENAMETOOLONG;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1525) if (outarg.namelen > FUSE_NAME_MAX)
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1526) goto err;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1527)
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1528) err = -EINVAL;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1529) if (size != sizeof(outarg) + outarg.namelen + 1)
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1530) goto err;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1531)
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1532) name.name = buf;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1533) name.len = outarg.namelen;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1534) err = fuse_copy_one(cs, buf, outarg.namelen + 1);
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1535) if (err)
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1536) goto err;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1537) fuse_copy_finish(cs);
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1538) buf[outarg.namelen] = 0;
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1539)
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1540) down_read(&fc->killsb);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1541) err = fuse_reverse_inval_entry(fc, outarg.parent, outarg.child, &name);
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1542) up_read(&fc->killsb);
b2d82ee3c8b21 (Fang Wenqi 2009-12-30 18:37:13 +0800 1543) kfree(buf);
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1544) return err;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1545)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1546) err:
b2d82ee3c8b21 (Fang Wenqi 2009-12-30 18:37:13 +0800 1547) kfree(buf);
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1548) fuse_copy_finish(cs);
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1549) return err;
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1550) }
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1551)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1552) static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1553) struct fuse_copy_state *cs)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1554) {
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1555) struct fuse_notify_store_out outarg;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1556) struct inode *inode;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1557) struct address_space *mapping;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1558) u64 nodeid;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1559) int err;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1560) pgoff_t index;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1561) unsigned int offset;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1562) unsigned int num;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1563) loff_t file_size;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1564) loff_t end;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1565)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1566) err = -EINVAL;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1567) if (size < sizeof(outarg))
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1568) goto out_finish;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1569)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1570) err = fuse_copy_one(cs, &outarg, sizeof(outarg));
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1571) if (err)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1572) goto out_finish;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1573)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1574) err = -EINVAL;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1575) if (size - sizeof(outarg) != outarg.size)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1576) goto out_finish;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1577)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1578) nodeid = outarg.nodeid;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1579)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1580) down_read(&fc->killsb);
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1581)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1582) err = -ENOENT;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1583) inode = fuse_ilookup(fc, nodeid, NULL);
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1584) if (!inode)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1585) goto out_up_killsb;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1586)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1587) mapping = inode->i_mapping;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1588) index = outarg.offset >> PAGE_SHIFT;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1589) offset = outarg.offset & ~PAGE_MASK;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1590) file_size = i_size_read(inode);
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1591) end = outarg.offset + outarg.size;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1592) if (end > file_size) {
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1593) file_size = end;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1594) fuse_write_update_size(inode, file_size);
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1595) }
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1596)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1597) num = outarg.size;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1598) while (num) {
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1599) struct page *page;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1600) unsigned int this_num;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1601)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1602) err = -ENOMEM;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1603) page = find_or_create_page(mapping, index,
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1604) mapping_gfp_mask(mapping));
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1605) if (!page)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1606) goto out_iput;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1607)
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1608) this_num = min_t(unsigned, num, PAGE_SIZE - offset);
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1609) err = fuse_copy_page(cs, &page, offset, this_num, 0);
063ec1e595f8a (Miklos Szeredi 2014-01-22 19:36:58 +0100 1610) if (!err && offset == 0 &&
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1611) (this_num == PAGE_SIZE || file_size == end))
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1612) SetPageUptodate(page);
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1613) unlock_page(page);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1614) put_page(page);
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1615)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1616) if (err)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1617) goto out_iput;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1618)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1619) num -= this_num;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1620) offset = 0;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1621) index++;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1622) }
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1623)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1624) err = 0;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1625)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1626) out_iput:
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1627) iput(inode);
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1628) out_up_killsb:
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1629) up_read(&fc->killsb);
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1630) out_finish:
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1631) fuse_copy_finish(cs);
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1632) return err;
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1633) }
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1634)
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1635) struct fuse_retrieve_args {
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1636) struct fuse_args_pages ap;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1637) struct fuse_notify_retrieve_in inarg;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1638) };
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1639)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1640) static void fuse_retrieve_end(struct fuse_mount *fm, struct fuse_args *args,
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1641) int error)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1642) {
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1643) struct fuse_retrieve_args *ra =
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1644) container_of(args, typeof(*ra), ap.args);
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1645)
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1646) release_pages(ra->ap.pages, ra->ap.num_pages);
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1647) kfree(ra);
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1648) }
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1649)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1650) static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1651) struct fuse_notify_retrieve_out *outarg)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1652) {
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1653) int err;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1654) struct address_space *mapping = inode->i_mapping;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1655) pgoff_t index;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1656) loff_t file_size;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1657) unsigned int num;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1658) unsigned int offset;
0157443c56bcc (Geert Uytterhoeven 2010-09-30 22:06:21 +0200 1659) size_t total_len = 0;
5da784cce4308 (Constantine Shulyupin 2018-09-06 15:37:06 +0300 1660) unsigned int num_pages;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1661) struct fuse_conn *fc = fm->fc;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1662) struct fuse_retrieve_args *ra;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1663) size_t args_size = sizeof(*ra);
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1664) struct fuse_args_pages *ap;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1665) struct fuse_args *args;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1666)
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1667) offset = outarg->offset & ~PAGE_MASK;
4d53dc99baf13 (Maxim Patlasov 2012-10-26 19:48:42 +0400 1668) file_size = i_size_read(inode);
4d53dc99baf13 (Maxim Patlasov 2012-10-26 19:48:42 +0400 1669)
7640682e67b33 (Kirill Smelkov 2019-03-27 10:15:19 +0000 1670) num = min(outarg->size, fc->max_write);
4d53dc99baf13 (Maxim Patlasov 2012-10-26 19:48:42 +0400 1671) if (outarg->offset > file_size)
4d53dc99baf13 (Maxim Patlasov 2012-10-26 19:48:42 +0400 1672) num = 0;
4d53dc99baf13 (Maxim Patlasov 2012-10-26 19:48:42 +0400 1673) else if (outarg->offset + num > file_size)
4d53dc99baf13 (Maxim Patlasov 2012-10-26 19:48:42 +0400 1674) num = file_size - outarg->offset;
4d53dc99baf13 (Maxim Patlasov 2012-10-26 19:48:42 +0400 1675)
4d53dc99baf13 (Maxim Patlasov 2012-10-26 19:48:42 +0400 1676) num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
5da784cce4308 (Constantine Shulyupin 2018-09-06 15:37:06 +0300 1677) num_pages = min(num_pages, fc->max_pages);
4d53dc99baf13 (Maxim Patlasov 2012-10-26 19:48:42 +0400 1678)
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1679) args_size += num_pages * (sizeof(ap->pages[0]) + sizeof(ap->descs[0]));
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1680)
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1681) ra = kzalloc(args_size, GFP_KERNEL);
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1682) if (!ra)
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1683) return -ENOMEM;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1684)
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1685) ap = &ra->ap;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1686) ap->pages = (void *) (ra + 1);
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1687) ap->descs = (void *) (ap->pages + num_pages);
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1688)
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1689) args = &ap->args;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1690) args->nodeid = outarg->nodeid;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1691) args->opcode = FUSE_NOTIFY_REPLY;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1692) args->in_numargs = 2;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1693) args->in_pages = true;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1694) args->end = fuse_retrieve_end;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1695)
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1696) index = outarg->offset >> PAGE_SHIFT;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1697)
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1698) while (num && ap->num_pages < num_pages) {
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1699) struct page *page;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1700) unsigned int this_num;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1701)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1702) page = find_get_page(mapping, index);
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1703) if (!page)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1704) break;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1705)
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 1706) this_num = min_t(unsigned, num, PAGE_SIZE - offset);
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1707) ap->pages[ap->num_pages] = page;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1708) ap->descs[ap->num_pages].offset = offset;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1709) ap->descs[ap->num_pages].length = this_num;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1710) ap->num_pages++;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1711)
c9e67d483776d (Miklos Szeredi 2012-09-04 18:45:54 +0200 1712) offset = 0;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1713) num -= this_num;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1714) total_len += this_num;
48706d0a91583 (Miklos Szeredi 2011-12-13 10:36:59 +0100 1715) index++;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1716) }
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1717) ra->inarg.offset = outarg->offset;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1718) ra->inarg.size = total_len;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1719) args->in_args[0].size = sizeof(ra->inarg);
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1720) args->in_args[0].value = &ra->inarg;
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1721) args->in_args[1].size = total_len;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1722)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1723) err = fuse_simple_notify_reply(fm, args, outarg->notify_unique);
75b399dda5be1 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1724) if (err)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1725) fuse_retrieve_end(fm, args, err);
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1726)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1727) return err;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1728) }
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1729)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1730) static int fuse_notify_retrieve(struct fuse_conn *fc, unsigned int size,
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1731) struct fuse_copy_state *cs)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1732) {
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1733) struct fuse_notify_retrieve_out outarg;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1734) struct fuse_mount *fm;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1735) struct inode *inode;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1736) u64 nodeid;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1737) int err;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1738)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1739) err = -EINVAL;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1740) if (size != sizeof(outarg))
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1741) goto copy_finish;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1742)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1743) err = fuse_copy_one(cs, &outarg, sizeof(outarg));
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1744) if (err)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1745) goto copy_finish;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1746)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1747) fuse_copy_finish(cs);
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1748)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1749) down_read(&fc->killsb);
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1750) err = -ENOENT;
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1751) nodeid = outarg.nodeid;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1752)
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1753) inode = fuse_ilookup(fc, nodeid, &fm);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1754) if (inode) {
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1755) err = fuse_retrieve(fm, inode, &outarg);
fcee216beb9c1 (Max Reitz 2020-05-06 17:44:12 +0200 1756) iput(inode);
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1757) }
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1758) up_read(&fc->killsb);
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1759)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1760) return err;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1761)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1762) copy_finish:
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1763) fuse_copy_finish(cs);
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1764) return err;
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1765) }
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1766)
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1767) static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1768) unsigned int size, struct fuse_copy_state *cs)
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1769) {
0d2783626a53d (Miklos Szeredi 2015-02-26 11:45:47 +0100 1770) /* Don't try to move pages (yet) */
0d2783626a53d (Miklos Szeredi 2015-02-26 11:45:47 +0100 1771) cs->move_pages = 0;
0d2783626a53d (Miklos Szeredi 2015-02-26 11:45:47 +0100 1772)
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1773) switch (code) {
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 1774) case FUSE_NOTIFY_POLL:
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 1775) return fuse_notify_poll(fc, size, cs);
95668a69a4bb8 (Tejun Heo 2008-11-26 12:03:55 +0100 1776)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1777) case FUSE_NOTIFY_INVAL_INODE:
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1778) return fuse_notify_inval_inode(fc, size, cs);
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1779)
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1780) case FUSE_NOTIFY_INVAL_ENTRY:
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1781) return fuse_notify_inval_entry(fc, size, cs);
3b463ae0c6264 (John Muir 2009-05-31 11:13:57 -0400 1782)
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1783) case FUSE_NOTIFY_STORE:
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1784) return fuse_notify_store(fc, size, cs);
a1d75f258230b (Miklos Szeredi 2010-07-12 14:41:40 +0200 1785)
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1786) case FUSE_NOTIFY_RETRIEVE:
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1787) return fuse_notify_retrieve(fc, size, cs);
2d45ba381a74a (Miklos Szeredi 2010-07-12 14:41:40 +0200 1788)
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1789) case FUSE_NOTIFY_DELETE:
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1790) return fuse_notify_delete(fc, size, cs);
451d0f599934f (John Muir 2011-12-06 21:50:06 +0100 1791)
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1792) default:
f6d47a1761896 (Miklos Szeredi 2009-01-26 15:00:59 +0100 1793) fuse_copy_finish(cs);
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1794) return -EINVAL;
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1795) }
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1796) }
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1797)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1798) /* Look up request on processing list by unique ID */
3a2b5b9cd9610 (Miklos Szeredi 2015-07-01 16:26:04 +0200 1799) static struct fuse_req *request_find(struct fuse_pqueue *fpq, u64 unique)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1800) {
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 1801) unsigned int hash = fuse_req_hash(unique);
05726acabef10 (Dong Fang 2013-07-30 22:50:01 -0400 1802) struct fuse_req *req;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1803)
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 1804) list_for_each_entry(req, &fpq->processing[hash], list) {
3a5358d1a1b70 (Kirill Tkhai 2018-09-11 13:12:05 +0300 1805) if (req->in.h.unique == unique)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1806) return req;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1807) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1808) return NULL;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1809) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1810)
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1811) static int copy_out_args(struct fuse_copy_state *cs, struct fuse_args *args,
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1812) unsigned nbytes)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1813) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1814) unsigned reqsize = sizeof(struct fuse_out_header);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1815)
14d46d7abc397 (Stefan Hajnoczi 2018-06-21 09:34:25 +0100 1816) reqsize += fuse_len_args(args->out_numargs, args->out_args);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1817)
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1818) if (reqsize < nbytes || (reqsize > nbytes && !args->out_argvar))
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1819) return -EINVAL;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1820) else if (reqsize > nbytes) {
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1821) struct fuse_arg *lastarg = &args->out_args[args->out_numargs-1];
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1822) unsigned diffsize = reqsize - nbytes;
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1823)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1824) if (diffsize > lastarg->size)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1825) return -EINVAL;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1826) lastarg->size -= diffsize;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1827) }
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1828) return fuse_copy_args(cs, args->out_numargs, args->out_pages,
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1829) args->out_args, args->page_zeroing);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1830) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1831)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1832) /*
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1833) * Write a single reply to a request. First the header is copied from
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1834) * the write buffer. The request is then searched on the processing
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1835) * list by the unique ID found in the header. If found, then remove
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1836) * it from the list and copy the rest of the buffer to the request.
04ec5af0776e9 (Stefan Hajnoczi 2018-06-21 09:33:40 +0100 1837) * The request is finished by calling fuse_request_end().
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1838) */
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 1839) static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1840) struct fuse_copy_state *cs, size_t nbytes)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1841) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1842) int err;
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 1843) struct fuse_conn *fc = fud->fc;
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 1844) struct fuse_pqueue *fpq = &fud->pq;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1845) struct fuse_req *req;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1846) struct fuse_out_header oh;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1847)
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1848) err = -EINVAL;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1849) if (nbytes < sizeof(struct fuse_out_header))
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1850) goto out;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1851)
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1852) err = fuse_copy_one(cs, &oh, sizeof(oh));
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1853) if (err)
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1854) goto copy_finish;
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1855)
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1856) err = -EINVAL;
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1857) if (oh.len != nbytes)
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1858) goto copy_finish;
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1859)
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1860) /*
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1861) * Zero oh.unique indicates unsolicited notification message
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1862) * and error contains notification code.
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1863) */
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1864) if (!oh.unique) {
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1865) err = fuse_notify(fc, oh.error, nbytes - sizeof(oh), cs);
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1866) goto out;
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1867) }
8599396b5062b (Tejun Heo 2008-11-26 12:03:55 +0100 1868)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1869) err = -EINVAL;
0c1678f223daf (Miklos Szeredi 2021-06-22 09:15:35 +0200 1870) if (oh.error <= -512 || oh.error > 0)
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1871) goto copy_finish;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1872)
45a91cb1a4fd9 (Miklos Szeredi 2015-07-01 16:26:06 +0200 1873) spin_lock(&fpq->lock);
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1874) req = NULL;
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1875) if (fpq->connected)
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1876) req = request_find(fpq, oh.unique & ~FUSE_INT_REQ_BIT);
69a53bf267fa5 (Miklos Szeredi 2006-01-16 22:14:41 -0800 1877)
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1878) err = -ENOENT;
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1879) if (!req) {
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1880) spin_unlock(&fpq->lock);
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1881) goto copy_finish;
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1882) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1883)
3a5358d1a1b70 (Kirill Tkhai 2018-09-11 13:12:05 +0300 1884) /* Is it an interrupt reply ID? */
3a5358d1a1b70 (Kirill Tkhai 2018-09-11 13:12:05 +0300 1885) if (oh.unique & FUSE_INT_REQ_BIT) {
d2d2d4fb1f54e (Kirill Tkhai 2018-09-25 12:52:42 +0300 1886) __fuse_get_request(req);
45a91cb1a4fd9 (Miklos Szeredi 2015-07-01 16:26:06 +0200 1887) spin_unlock(&fpq->lock);
45a91cb1a4fd9 (Miklos Szeredi 2015-07-01 16:26:06 +0200 1888)
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1889) err = 0;
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1890) if (nbytes != sizeof(struct fuse_out_header))
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1891) err = -EINVAL;
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1892) else if (oh.error == -ENOSYS)
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1893) fc->no_interrupt = 1;
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1894) else if (oh.error == -EAGAIN)
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 1895) err = queue_interrupt(req);
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1896)
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 1897) fuse_put_request(req);
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1898)
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1899) goto copy_finish;
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1900) }
a4d27e75ffb7b (Miklos Szeredi 2006-06-25 05:48:54 -0700 1901)
33e14b4dfdc47 (Miklos Szeredi 2015-07-01 16:26:01 +0200 1902) clear_bit(FR_SENT, &req->flags);
3a2b5b9cd9610 (Miklos Szeredi 2015-07-01 16:26:04 +0200 1903) list_move(&req->list, &fpq->io);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1904) req->out.h = oh;
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 1905) set_bit(FR_LOCKED, &req->flags);
45a91cb1a4fd9 (Miklos Szeredi 2015-07-01 16:26:06 +0200 1906) spin_unlock(&fpq->lock);
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1907) cs->req = req;
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1908) if (!req->args->page_replace)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 1909) cs->move_pages = 0;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1910)
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1911) if (oh.error)
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1912) err = nbytes != sizeof(oh) ? -EINVAL : 0;
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1913) else
d49937749fef2 (Miklos Szeredi 2019-09-10 15:04:11 +0200 1914) err = copy_out_args(cs, req->args, nbytes);
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1915) fuse_copy_finish(cs);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1916)
45a91cb1a4fd9 (Miklos Szeredi 2015-07-01 16:26:06 +0200 1917) spin_lock(&fpq->lock);
825d6d3395e88 (Miklos Szeredi 2015-07-01 16:25:58 +0200 1918) clear_bit(FR_LOCKED, &req->flags);
e96edd94d0887 (Miklos Szeredi 2015-07-01 16:26:04 +0200 1919) if (!fpq->connected)
0d8e84b0432be (Miklos Szeredi 2015-07-01 16:25:58 +0200 1920) err = -ENOENT;
0d8e84b0432be (Miklos Szeredi 2015-07-01 16:25:58 +0200 1921) else if (err)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1922) req->out.h.error = -EIO;
77cd9d488b32d (Miklos Szeredi 2015-07-01 16:26:06 +0200 1923) if (!test_bit(FR_PRIVATE, &req->flags))
77cd9d488b32d (Miklos Szeredi 2015-07-01 16:26:06 +0200 1924) list_del_init(&req->list);
45a91cb1a4fd9 (Miklos Szeredi 2015-07-01 16:26:06 +0200 1925) spin_unlock(&fpq->lock);
46c34a348b0ac (Miklos Szeredi 2015-07-01 16:26:07 +0200 1926)
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 1927) fuse_request_end(req);
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1928) out:
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1929) return err ? err : nbytes;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1930)
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1931) copy_finish:
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1932) fuse_copy_finish(cs);
7407a10de57f5 (Kirill Tkhai 2018-11-08 12:05:36 +0300 1933) goto out;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1934) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 1935)
fbdbacca61531 (Al Viro 2015-04-03 21:53:39 -0400 1936) static ssize_t fuse_dev_write(struct kiocb *iocb, struct iov_iter *from)
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1937) {
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1938) struct fuse_copy_state cs;
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 1939) struct fuse_dev *fud = fuse_get_dev(iocb->ki_filp);
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 1940)
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 1941) if (!fud)
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1942) return -EPERM;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1943)
fbdbacca61531 (Al Viro 2015-04-03 21:53:39 -0400 1944) if (!iter_is_iovec(from))
fbdbacca61531 (Al Viro 2015-04-03 21:53:39 -0400 1945) return -EINVAL;
fbdbacca61531 (Al Viro 2015-04-03 21:53:39 -0400 1946)
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 1947) fuse_copy_init(&cs, 0, from);
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1948)
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 1949) return fuse_dev_do_write(fud, &cs, iov_iter_count(from));
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1950) }
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1951)
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1952) static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1953) struct file *out, loff_t *ppos,
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1954) size_t len, unsigned int flags)
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1955) {
8cefc107ca54c (David Howells 2019-11-15 13:30:32 +0000 1956) unsigned int head, tail, mask, count;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1957) unsigned nbuf;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1958) unsigned idx;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1959) struct pipe_buffer *bufs;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1960) struct fuse_copy_state cs;
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 1961) struct fuse_dev *fud;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1962) size_t rem;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1963) ssize_t ret;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1964)
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 1965) fud = fuse_get_dev(out);
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 1966) if (!fud)
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1967) return -EPERM;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1968)
a2477b0e67c52 (Andrey Ryabinin 2018-07-17 19:00:33 +0300 1969) pipe_lock(pipe);
a2477b0e67c52 (Andrey Ryabinin 2018-07-17 19:00:33 +0300 1970)
8cefc107ca54c (David Howells 2019-11-15 13:30:32 +0000 1971) head = pipe->head;
8cefc107ca54c (David Howells 2019-11-15 13:30:32 +0000 1972) tail = pipe->tail;
8cefc107ca54c (David Howells 2019-11-15 13:30:32 +0000 1973) mask = pipe->ring_size - 1;
8cefc107ca54c (David Howells 2019-11-15 13:30:32 +0000 1974) count = head - tail;
8cefc107ca54c (David Howells 2019-11-15 13:30:32 +0000 1975)
8cefc107ca54c (David Howells 2019-11-15 13:30:32 +0000 1976) bufs = kvmalloc_array(count, sizeof(struct pipe_buffer), GFP_KERNEL);
a2477b0e67c52 (Andrey Ryabinin 2018-07-17 19:00:33 +0300 1977) if (!bufs) {
a2477b0e67c52 (Andrey Ryabinin 2018-07-17 19:00:33 +0300 1978) pipe_unlock(pipe);
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1979) return -ENOMEM;
a2477b0e67c52 (Andrey Ryabinin 2018-07-17 19:00:33 +0300 1980) }
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1981)
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1982) nbuf = 0;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1983) rem = 0;
76f6777c9cc04 (David Howells 2019-12-06 21:34:51 +0000 1984) for (idx = tail; idx != head && rem < len; idx++)
8cefc107ca54c (David Howells 2019-11-15 13:30:32 +0000 1985) rem += pipe->bufs[idx & mask].len;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1986)
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1987) ret = -EINVAL;
15fab63e1e57b (Matthew Wilcox 2019-04-05 14:02:10 -0700 1988) if (rem < len)
15fab63e1e57b (Matthew Wilcox 2019-04-05 14:02:10 -0700 1989) goto out_free;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1990)
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1991) rem = len;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1992) while (rem) {
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1993) struct pipe_buffer *ibuf;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1994) struct pipe_buffer *obuf;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 1995)
0e9fb6f17ad5b (Vasily Averin 2019-08-19 09:53:50 +0300 1996) if (WARN_ON(nbuf >= count || tail == head))
0e9fb6f17ad5b (Vasily Averin 2019-08-19 09:53:50 +0300 1997) goto out_free;
0e9fb6f17ad5b (Vasily Averin 2019-08-19 09:53:50 +0300 1998)
8cefc107ca54c (David Howells 2019-11-15 13:30:32 +0000 1999) ibuf = &pipe->bufs[tail & mask];
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2000) obuf = &bufs[nbuf];
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2001)
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2002) if (rem >= ibuf->len) {
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2003) *obuf = *ibuf;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2004) ibuf->ops = NULL;
8cefc107ca54c (David Howells 2019-11-15 13:30:32 +0000 2005) tail++;
8cefc107ca54c (David Howells 2019-11-15 13:30:32 +0000 2006) pipe->tail = tail;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2007) } else {
15fab63e1e57b (Matthew Wilcox 2019-04-05 14:02:10 -0700 2008) if (!pipe_buf_get(pipe, ibuf))
15fab63e1e57b (Matthew Wilcox 2019-04-05 14:02:10 -0700 2009) goto out_free;
15fab63e1e57b (Matthew Wilcox 2019-04-05 14:02:10 -0700 2010)
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2011) *obuf = *ibuf;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2012) obuf->flags &= ~PIPE_BUF_FLAG_GIFT;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2013) obuf->len = rem;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2014) ibuf->offset += obuf->len;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2015) ibuf->len -= obuf->len;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2016) }
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2017) nbuf++;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2018) rem -= obuf->len;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2019) }
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2020) pipe_unlock(pipe);
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2021)
dc00809a53edd (Miklos Szeredi 2015-07-01 16:25:58 +0200 2022) fuse_copy_init(&cs, 0, NULL);
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2023) cs.pipebufs = bufs;
6c09e94a32e10 (Al Viro 2015-04-03 22:06:08 -0400 2024) cs.nr_segs = nbuf;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2025) cs.pipe = pipe;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2026)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 2027) if (flags & SPLICE_F_MOVE)
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 2028) cs.move_pages = 1;
ce534fb052928 (Miklos Szeredi 2010-05-25 15:06:07 +0200 2029)
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2030) ret = fuse_dev_do_write(fud, &cs, len);
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2031)
9509941e9c534 (Jann Horn 2019-01-12 02:39:05 +0100 2032) pipe_lock(pipe);
15fab63e1e57b (Matthew Wilcox 2019-04-05 14:02:10 -0700 2033) out_free:
a779638cf622f (Miklos Szeredi 2016-09-27 10:45:12 +0200 2034) for (idx = 0; idx < nbuf; idx++)
a779638cf622f (Miklos Szeredi 2016-09-27 10:45:12 +0200 2035) pipe_buf_release(pipe, &bufs[idx]);
9509941e9c534 (Jann Horn 2019-01-12 02:39:05 +0100 2036) pipe_unlock(pipe);
a779638cf622f (Miklos Szeredi 2016-09-27 10:45:12 +0200 2037)
d6d931adce119 (Andrey Ryabinin 2018-07-17 19:00:34 +0300 2038) kvfree(bufs);
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2039) return ret;
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2040) }
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2041)
076ccb76e1a6c (Al Viro 2017-07-03 01:02:18 -0400 2042) static __poll_t fuse_dev_poll(struct file *file, poll_table *wait)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2043) {
a9a08845e9acb (Linus Torvalds 2018-02-11 14:34:03 -0800 2044) __poll_t mask = EPOLLOUT | EPOLLWRNORM;
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 2045) struct fuse_iqueue *fiq;
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2046) struct fuse_dev *fud = fuse_get_dev(file);
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2047)
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2048) if (!fud)
a9a08845e9acb (Linus Torvalds 2018-02-11 14:34:03 -0800 2049) return EPOLLERR;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2050)
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2051) fiq = &fud->fc->iq;
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 2052) poll_wait(file, &fiq->waitq, wait);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2053)
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 2054) spin_lock(&fiq->lock);
e16714d8756dc (Miklos Szeredi 2015-07-01 16:26:01 +0200 2055) if (!fiq->connected)
a9a08845e9acb (Linus Torvalds 2018-02-11 14:34:03 -0800 2056) mask = EPOLLERR;
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 2057) else if (request_pending(fiq))
a9a08845e9acb (Linus Torvalds 2018-02-11 14:34:03 -0800 2058) mask |= EPOLLIN | EPOLLRDNORM;
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 2059) spin_unlock(&fiq->lock);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2060)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2061) return mask;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2062) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2063)
340617508d24d (Kirill Tkhai 2018-11-06 12:15:20 +0300 2064) /* Abort all requests on the given list (pending or processing) */
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 2065) static void end_requests(struct list_head *head)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2066) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2067) while (!list_empty(head)) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2068) struct fuse_req *req;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2069) req = list_entry(head->next, struct fuse_req, list);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2070) req->out.h.error = -ECONNABORTED;
33e14b4dfdc47 (Miklos Szeredi 2015-07-01 16:26:01 +0200 2071) clear_bit(FR_SENT, &req->flags);
f377cb799e4f6 (Miklos Szeredi 2015-07-01 16:26:04 +0200 2072) list_del_init(&req->list);
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 2073) fuse_request_end(req);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2074) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2075) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2076)
357ccf2b69bce (Bryan Green 2011-03-01 16:43:52 -0800 2077) static void end_polls(struct fuse_conn *fc)
357ccf2b69bce (Bryan Green 2011-03-01 16:43:52 -0800 2078) {
357ccf2b69bce (Bryan Green 2011-03-01 16:43:52 -0800 2079) struct rb_node *p;
357ccf2b69bce (Bryan Green 2011-03-01 16:43:52 -0800 2080)
357ccf2b69bce (Bryan Green 2011-03-01 16:43:52 -0800 2081) p = rb_first(&fc->polled_files);
357ccf2b69bce (Bryan Green 2011-03-01 16:43:52 -0800 2082)
357ccf2b69bce (Bryan Green 2011-03-01 16:43:52 -0800 2083) while (p) {
357ccf2b69bce (Bryan Green 2011-03-01 16:43:52 -0800 2084) struct fuse_file *ff;
357ccf2b69bce (Bryan Green 2011-03-01 16:43:52 -0800 2085) ff = rb_entry(p, struct fuse_file, polled_node);
357ccf2b69bce (Bryan Green 2011-03-01 16:43:52 -0800 2086) wake_up_interruptible_all(&ff->poll_wait);
357ccf2b69bce (Bryan Green 2011-03-01 16:43:52 -0800 2087)
357ccf2b69bce (Bryan Green 2011-03-01 16:43:52 -0800 2088) p = rb_next(p);
357ccf2b69bce (Bryan Green 2011-03-01 16:43:52 -0800 2089) }
357ccf2b69bce (Bryan Green 2011-03-01 16:43:52 -0800 2090) }
357ccf2b69bce (Bryan Green 2011-03-01 16:43:52 -0800 2091)
69a53bf267fa5 (Miklos Szeredi 2006-01-16 22:14:41 -0800 2092) /*
69a53bf267fa5 (Miklos Szeredi 2006-01-16 22:14:41 -0800 2093) * Abort all requests.
69a53bf267fa5 (Miklos Szeredi 2006-01-16 22:14:41 -0800 2094) *
b716d425385ed (Miklos Szeredi 2015-07-01 16:25:59 +0200 2095) * Emergency exit in case of a malicious or accidental deadlock, or just a hung
b716d425385ed (Miklos Szeredi 2015-07-01 16:25:59 +0200 2096) * filesystem.
b716d425385ed (Miklos Szeredi 2015-07-01 16:25:59 +0200 2097) *
b716d425385ed (Miklos Szeredi 2015-07-01 16:25:59 +0200 2098) * The same effect is usually achievable through killing the filesystem daemon
b716d425385ed (Miklos Szeredi 2015-07-01 16:25:59 +0200 2099) * and all users of the filesystem. The exception is the combination of an
b716d425385ed (Miklos Szeredi 2015-07-01 16:25:59 +0200 2100) * asynchronous request and the tricky deadlock (see
72ef5e52b3f74 (Mauro Carvalho Chehab 2020-04-14 18:48:35 +0200 2101) * Documentation/filesystems/fuse.rst).
69a53bf267fa5 (Miklos Szeredi 2006-01-16 22:14:41 -0800 2102) *
b716d425385ed (Miklos Szeredi 2015-07-01 16:25:59 +0200 2103) * Aborting requests under I/O goes as follows: 1: Separate out unlocked
b716d425385ed (Miklos Szeredi 2015-07-01 16:25:59 +0200 2104) * requests, they should be finished off immediately. Locked requests will be
b716d425385ed (Miklos Szeredi 2015-07-01 16:25:59 +0200 2105) * finished after unlock; see unlock_request(). 2: Finish off the unlocked
b716d425385ed (Miklos Szeredi 2015-07-01 16:25:59 +0200 2106) * requests. It is possible that some request will finish before we can. This
b716d425385ed (Miklos Szeredi 2015-07-01 16:25:59 +0200 2107) * is OK, the request will in that case be removed from the list before we touch
b716d425385ed (Miklos Szeredi 2015-07-01 16:25:59 +0200 2108) * it.
69a53bf267fa5 (Miklos Szeredi 2006-01-16 22:14:41 -0800 2109) */
eb98e3bdf3aa7 (Miklos Szeredi 2019-01-24 10:40:16 +0100 2110) void fuse_abort_conn(struct fuse_conn *fc)
69a53bf267fa5 (Miklos Szeredi 2006-01-16 22:14:41 -0800 2111) {
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 2112) struct fuse_iqueue *fiq = &fc->iq;
f88996a933244 (Miklos Szeredi 2015-07-01 16:26:01 +0200 2113)
d713311464bcc (Miklos Szeredi 2006-04-10 22:54:55 -0700 2114) spin_lock(&fc->lock);
69a53bf267fa5 (Miklos Szeredi 2006-01-16 22:14:41 -0800 2115) if (fc->connected) {
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2116) struct fuse_dev *fud;
b716d425385ed (Miklos Szeredi 2015-07-01 16:25:59 +0200 2117) struct fuse_req *req, *next;
75f3ee4c288d9 (Miklos Szeredi 2018-07-26 16:13:12 +0200 2118) LIST_HEAD(to_end);
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 2119) unsigned int i;
b716d425385ed (Miklos Szeredi 2015-07-01 16:25:59 +0200 2120)
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 2121) /* Background queuing checks fc->connected under bg_lock */
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 2122) spin_lock(&fc->bg_lock);
69a53bf267fa5 (Miklos Szeredi 2006-01-16 22:14:41 -0800 2123) fc->connected = 0;
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 2124) spin_unlock(&fc->bg_lock);
63825b4e1da5a (Kirill Tkhai 2018-08-27 18:29:56 +0300 2125)
9759bd5189945 (Miklos Szeredi 2015-01-06 10:45:35 +0100 2126) fuse_set_initialized(fc);
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2127) list_for_each_entry(fud, &fc->devices, entry) {
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2128) struct fuse_pqueue *fpq = &fud->pq;
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2129)
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2130) spin_lock(&fpq->lock);
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2131) fpq->connected = 0;
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2132) list_for_each_entry_safe(req, next, &fpq->io, list) {
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2133) req->out.h.error = -ECONNABORTED;
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2134) spin_lock(&req->waitq.lock);
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2135) set_bit(FR_ABORTED, &req->flags);
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2136) if (!test_bit(FR_LOCKED, &req->flags)) {
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2137) set_bit(FR_PRIVATE, &req->flags);
87114373ea507 (Miklos Szeredi 2018-07-26 16:13:11 +0200 2138) __fuse_get_request(req);
75f3ee4c288d9 (Miklos Szeredi 2018-07-26 16:13:12 +0200 2139) list_move(&req->list, &to_end);
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2140) }
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2141) spin_unlock(&req->waitq.lock);
77cd9d488b32d (Miklos Szeredi 2015-07-01 16:26:06 +0200 2142) }
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 2143) for (i = 0; i < FUSE_PQ_HASH_SIZE; i++)
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 2144) list_splice_tail_init(&fpq->processing[i],
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 2145) &to_end);
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2146) spin_unlock(&fpq->lock);
b716d425385ed (Miklos Szeredi 2015-07-01 16:25:59 +0200 2147) }
ae2dffa39485c (Kirill Tkhai 2018-08-27 18:29:46 +0300 2148) spin_lock(&fc->bg_lock);
ae2dffa39485c (Kirill Tkhai 2018-08-27 18:29:46 +0300 2149) fc->blocked = 0;
41f982747e817 (Miklos Szeredi 2015-07-01 16:25:59 +0200 2150) fc->max_background = UINT_MAX;
41f982747e817 (Miklos Szeredi 2015-07-01 16:25:59 +0200 2151) flush_bg_queue(fc);
ae2dffa39485c (Kirill Tkhai 2018-08-27 18:29:46 +0300 2152) spin_unlock(&fc->bg_lock);
8c91189a2a8f5 (Miklos Szeredi 2015-07-01 16:26:02 +0200 2153)
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 2154) spin_lock(&fiq->lock);
8c91189a2a8f5 (Miklos Szeredi 2015-07-01 16:26:02 +0200 2155) fiq->connected = 0;
75f3ee4c288d9 (Miklos Szeredi 2018-07-26 16:13:12 +0200 2156) list_for_each_entry(req, &fiq->pending, list)
a8a86d78d673b (Tahsin Erdogan 2017-01-12 12:04:04 -0800 2157) clear_bit(FR_PENDING, &req->flags);
75f3ee4c288d9 (Miklos Szeredi 2018-07-26 16:13:12 +0200 2158) list_splice_tail_init(&fiq->pending, &to_end);
8c91189a2a8f5 (Miklos Szeredi 2015-07-01 16:26:02 +0200 2159) while (forget_pending(fiq))
4388c5aac4bae (Vivek Goyal 2019-06-05 15:50:43 -0400 2160) kfree(fuse_dequeue_forget(fiq, 1, NULL));
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 2161) wake_up_all(&fiq->waitq);
76e43c8ccaa35 (Eric Biggers 2019-09-08 20:15:18 -0700 2162) spin_unlock(&fiq->lock);
8c91189a2a8f5 (Miklos Szeredi 2015-07-01 16:26:02 +0200 2163) kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
ee314a870e402 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2164) end_polls(fc);
ee314a870e402 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2165) wake_up_all(&fc->blocked_waitq);
ee314a870e402 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2166) spin_unlock(&fc->lock);
8c91189a2a8f5 (Miklos Szeredi 2015-07-01 16:26:02 +0200 2167)
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 2168) end_requests(&to_end);
ee314a870e402 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2169) } else {
ee314a870e402 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2170) spin_unlock(&fc->lock);
69a53bf267fa5 (Miklos Szeredi 2006-01-16 22:14:41 -0800 2171) }
69a53bf267fa5 (Miklos Szeredi 2006-01-16 22:14:41 -0800 2172) }
08cbf542bf24f (Tejun Heo 2009-04-14 10:54:53 +0900 2173) EXPORT_SYMBOL_GPL(fuse_abort_conn);
69a53bf267fa5 (Miklos Szeredi 2006-01-16 22:14:41 -0800 2174)
b8f95e5d13f5f (Miklos Szeredi 2018-07-26 16:13:11 +0200 2175) void fuse_wait_aborted(struct fuse_conn *fc)
b8f95e5d13f5f (Miklos Szeredi 2018-07-26 16:13:11 +0200 2176) {
2d84a2d19b615 (Miklos Szeredi 2018-11-09 15:52:16 +0100 2177) /* matches implicit memory barrier in fuse_drop_waiting() */
2d84a2d19b615 (Miklos Szeredi 2018-11-09 15:52:16 +0100 2178) smp_mb();
b8f95e5d13f5f (Miklos Szeredi 2018-07-26 16:13:11 +0200 2179) wait_event(fc->blocked_waitq, atomic_read(&fc->num_waiting) == 0);
b8f95e5d13f5f (Miklos Szeredi 2018-07-26 16:13:11 +0200 2180) }
b8f95e5d13f5f (Miklos Szeredi 2018-07-26 16:13:11 +0200 2181)
08cbf542bf24f (Tejun Heo 2009-04-14 10:54:53 +0900 2182) int fuse_dev_release(struct inode *inode, struct file *file)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2183) {
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2184) struct fuse_dev *fud = fuse_get_dev(file);
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2185)
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2186) if (fud) {
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2187) struct fuse_conn *fc = fud->fc;
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2188) struct fuse_pqueue *fpq = &fud->pq;
45ff350bbd9d0 (Miklos Szeredi 2018-07-26 16:13:11 +0200 2189) LIST_HEAD(to_end);
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 2190) unsigned int i;
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2191)
45ff350bbd9d0 (Miklos Szeredi 2018-07-26 16:13:11 +0200 2192) spin_lock(&fpq->lock);
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2193) WARN_ON(!list_empty(&fpq->io));
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 2194) for (i = 0; i < FUSE_PQ_HASH_SIZE; i++)
be2ff42c5d6eb (Kirill Tkhai 2018-09-11 13:12:14 +0300 2195) list_splice_init(&fpq->processing[i], &to_end);
45ff350bbd9d0 (Miklos Szeredi 2018-07-26 16:13:11 +0200 2196) spin_unlock(&fpq->lock);
45ff350bbd9d0 (Miklos Szeredi 2018-07-26 16:13:11 +0200 2197)
8f622e9497bbb (Max Reitz 2020-04-20 17:59:34 +0200 2198) end_requests(&to_end);
45ff350bbd9d0 (Miklos Szeredi 2018-07-26 16:13:11 +0200 2199)
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2200) /* Are we the last open device? */
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2201) if (atomic_dec_and_test(&fc->dev_count)) {
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2202) WARN_ON(fc->iq.fasync != NULL);
eb98e3bdf3aa7 (Miklos Szeredi 2019-01-24 10:40:16 +0100 2203) fuse_abort_conn(fc);
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2204) }
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2205) fuse_dev_free(fud);
385a17bfc3cb0 (Jeff Dike 2006-04-10 22:54:52 -0700 2206) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2207) return 0;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2208) }
08cbf542bf24f (Tejun Heo 2009-04-14 10:54:53 +0900 2209) EXPORT_SYMBOL_GPL(fuse_dev_release);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2210)
385a17bfc3cb0 (Jeff Dike 2006-04-10 22:54:52 -0700 2211) static int fuse_dev_fasync(int fd, struct file *file, int on)
385a17bfc3cb0 (Jeff Dike 2006-04-10 22:54:52 -0700 2212) {
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2213) struct fuse_dev *fud = fuse_get_dev(file);
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2214)
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2215) if (!fud)
a87046d822f2d (Miklos Szeredi 2006-04-10 22:54:56 -0700 2216) return -EPERM;
385a17bfc3cb0 (Jeff Dike 2006-04-10 22:54:52 -0700 2217)
385a17bfc3cb0 (Jeff Dike 2006-04-10 22:54:52 -0700 2218) /* No locking - fasync_helper does its own locking */
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2219) return fasync_helper(fd, file, on, &fud->fc->iq.fasync);
385a17bfc3cb0 (Jeff Dike 2006-04-10 22:54:52 -0700 2220) }
385a17bfc3cb0 (Jeff Dike 2006-04-10 22:54:52 -0700 2221)
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2222) static int fuse_device_clone(struct fuse_conn *fc, struct file *new)
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2223) {
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2224) struct fuse_dev *fud;
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2225)
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2226) if (new->private_data)
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2227) return -EINVAL;
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2228)
0cd1eb9a4160a (Vivek Goyal 2019-03-06 16:51:40 -0500 2229) fud = fuse_dev_alloc_install(fc);
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2230) if (!fud)
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2231) return -ENOMEM;
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2232)
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2233) new->private_data = fud;
c3696046beb3a (Miklos Szeredi 2015-07-01 16:26:09 +0200 2234) atomic_inc(&fc->dev_count);
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2235)
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2236) return 0;
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2237) }
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2238)
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2239) static long fuse_dev_ioctl(struct file *file, unsigned int cmd,
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2240) unsigned long arg)
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2241) {
f8425c9396639 (Alessio Balsini 2021-01-25 15:30:51 +0000 2242) int res;
f8425c9396639 (Alessio Balsini 2021-01-25 15:30:51 +0000 2243) int oldfd;
f8425c9396639 (Alessio Balsini 2021-01-25 15:30:51 +0000 2244) struct fuse_dev *fud = NULL;
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2245)
6076f5f341e61 (Alessio Balsini 2021-03-19 15:05:14 +0000 2246) switch (cmd) {
6076f5f341e61 (Alessio Balsini 2021-03-19 15:05:14 +0000 2247) case FUSE_DEV_IOC_CLONE:
f8425c9396639 (Alessio Balsini 2021-01-25 15:30:51 +0000 2248) res = -EFAULT;
f8425c9396639 (Alessio Balsini 2021-01-25 15:30:51 +0000 2249) if (!get_user(oldfd, (__u32 __user *)arg)) {
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2250) struct file *old = fget(oldfd);
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2251)
f8425c9396639 (Alessio Balsini 2021-01-25 15:30:51 +0000 2252) res = -EINVAL;
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2253) if (old) {
8ed1f0e22f49e (Jann Horn 2015-08-16 20:27:01 +0200 2254) /*
8ed1f0e22f49e (Jann Horn 2015-08-16 20:27:01 +0200 2255) * Check against file->f_op because CUSE
8ed1f0e22f49e (Jann Horn 2015-08-16 20:27:01 +0200 2256) * uses the same ioctl handler.
8ed1f0e22f49e (Jann Horn 2015-08-16 20:27:01 +0200 2257) */
8ed1f0e22f49e (Jann Horn 2015-08-16 20:27:01 +0200 2258) if (old->f_op == file->f_op &&
8ed1f0e22f49e (Jann Horn 2015-08-16 20:27:01 +0200 2259) old->f_cred->user_ns == file->f_cred->user_ns)
8ed1f0e22f49e (Jann Horn 2015-08-16 20:27:01 +0200 2260) fud = fuse_get_dev(old);
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2261)
cc080e9e9be16 (Miklos Szeredi 2015-07-01 16:26:08 +0200 2262) if (fud) {
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2263) mutex_lock(&fuse_mutex);
f8425c9396639 (Alessio Balsini 2021-01-25 15:30:51 +0000 2264) res = fuse_device_clone(fud->fc, file);
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2265) mutex_unlock(&fuse_mutex);
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2266) }
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2267) fput(old);
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2268) }
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2269) }
f8425c9396639 (Alessio Balsini 2021-01-25 15:30:51 +0000 2270) break;
f8425c9396639 (Alessio Balsini 2021-01-25 15:30:51 +0000 2271) default:
f8425c9396639 (Alessio Balsini 2021-01-25 15:30:51 +0000 2272) res = -ENOTTY;
f8425c9396639 (Alessio Balsini 2021-01-25 15:30:51 +0000 2273) break;
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2274) }
f8425c9396639 (Alessio Balsini 2021-01-25 15:30:51 +0000 2275) return res;
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2276) }
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2277)
4b6f5d20b04dc (Arjan van de Ven 2006-03-28 01:56:42 -0800 2278) const struct file_operations fuse_dev_operations = {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2279) .owner = THIS_MODULE,
94e4fe2cab3d4 (Tom Van Braeckel 2015-01-12 05:22:16 +0100 2280) .open = fuse_dev_open,
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2281) .llseek = no_llseek,
fbdbacca61531 (Al Viro 2015-04-03 21:53:39 -0400 2282) .read_iter = fuse_dev_read,
c3021629a0d82 (Miklos Szeredi 2010-05-25 15:06:07 +0200 2283) .splice_read = fuse_dev_splice_read,
fbdbacca61531 (Al Viro 2015-04-03 21:53:39 -0400 2284) .write_iter = fuse_dev_write,
dd3bb14f44a63 (Miklos Szeredi 2010-05-25 15:06:06 +0200 2285) .splice_write = fuse_dev_splice_write,
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2286) .poll = fuse_dev_poll,
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2287) .release = fuse_dev_release,
385a17bfc3cb0 (Jeff Dike 2006-04-10 22:54:52 -0700 2288) .fasync = fuse_dev_fasync,
00c570f4ba43a (Miklos Szeredi 2015-07-01 16:26:08 +0200 2289) .unlocked_ioctl = fuse_dev_ioctl,
1832f2d8ff691 (Arnd Bergmann 2018-09-11 21:59:08 +0200 2290) .compat_ioctl = compat_ptr_ioctl,
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2291) };
08cbf542bf24f (Tejun Heo 2009-04-14 10:54:53 +0900 2292) EXPORT_SYMBOL_GPL(fuse_dev_operations);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2293)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2294) static struct miscdevice fuse_miscdevice = {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2295) .minor = FUSE_MINOR,
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2296) .name = "fuse",
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2297) .fops = &fuse_dev_operations,
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2298) };
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2299)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2300) int __init fuse_dev_init(void)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2301) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2302) int err = -ENOMEM;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2303) fuse_req_cachep = kmem_cache_create("fuse_request",
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2304) sizeof(struct fuse_req),
20c2df83d25c6 (Paul Mundt 2007-07-20 10:11:58 +0900 2305) 0, 0, NULL);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2306) if (!fuse_req_cachep)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2307) goto out;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2308)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2309) err = misc_register(&fuse_miscdevice);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2310) if (err)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2311) goto out_cache_clean;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2312)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2313) return 0;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2314)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2315) out_cache_clean:
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2316) kmem_cache_destroy(fuse_req_cachep);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2317) out:
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2318) return err;
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2319) }
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2320)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2321) void fuse_dev_cleanup(void)
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2322) {
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2323) misc_deregister(&fuse_miscdevice);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2324) kmem_cache_destroy(fuse_req_cachep);
334f485df85ac (Miklos Szeredi 2005-09-09 13:10:27 -0700 2325) }