1334f485dSMiklos Szeredi /*
2334f485dSMiklos Szeredi FUSE: Filesystem in Userspace
31729a16cSMiklos Szeredi Copyright (C) 2001-2008 Miklos Szeredi <[email protected]>
4334f485dSMiklos Szeredi
5334f485dSMiklos Szeredi This program can be distributed under the terms of the GNU GPL.
6334f485dSMiklos Szeredi See the file COPYING.
7334f485dSMiklos Szeredi */
8334f485dSMiklos Szeredi
94a9bfb9bSBernd Schubert #include "dev_uring_i.h"
10334f485dSMiklos Szeredi #include "fuse_i.h"
1192270d07SBernd Schubert #include "fuse_dev_i.h"
12334f485dSMiklos Szeredi
13334f485dSMiklos Szeredi #include <linux/init.h>
14334f485dSMiklos Szeredi #include <linux/module.h>
15334f485dSMiklos Szeredi #include <linux/poll.h>
16174cd4b1SIngo Molnar #include <linux/sched/signal.h>
17334f485dSMiklos Szeredi #include <linux/uio.h>
18334f485dSMiklos Szeredi #include <linux/miscdevice.h>
19334f485dSMiklos Szeredi #include <linux/pagemap.h>
20334f485dSMiklos Szeredi #include <linux/file.h>
21334f485dSMiklos Szeredi #include <linux/slab.h>
22dd3bb14fSMiklos Szeredi #include <linux/pipe_fs_i.h>
23ce534fb0SMiklos Szeredi #include <linux/swap.h>
24ce534fb0SMiklos Szeredi #include <linux/splice.h>
250b6e9ea0SSeth Forshee #include <linux/sched.h>
26334f485dSMiklos Szeredi
27396b209eSJosef Bacik #define CREATE_TRACE_POINTS
28396b209eSJosef Bacik #include "fuse_trace.h"
29396b209eSJosef Bacik
30334f485dSMiklos Szeredi MODULE_ALIAS_MISCDEV(FUSE_MINOR);
31578454ffSKay Sievers MODULE_ALIAS("devname:fuse");
32334f485dSMiklos Szeredi
33e18b890bSChristoph Lameter static struct kmem_cache *fuse_req_cachep;
34334f485dSMiklos Szeredi
350f6439f6SJoanne Koong const unsigned long fuse_timeout_timer_freq =
360f6439f6SJoanne Koong secs_to_jiffies(FUSE_TIMEOUT_TIMER_FREQ);
370f6439f6SJoanne Koong
fuse_request_expired(struct fuse_conn * fc,struct list_head * list)380f6439f6SJoanne Koong bool fuse_request_expired(struct fuse_conn *fc, struct list_head *list)
390f6439f6SJoanne Koong {
400f6439f6SJoanne Koong struct fuse_req *req;
410f6439f6SJoanne Koong
420f6439f6SJoanne Koong req = list_first_entry_or_null(list, struct fuse_req, list);
430f6439f6SJoanne Koong if (!req)
440f6439f6SJoanne Koong return false;
450f6439f6SJoanne Koong return time_is_before_jiffies(req->create_time + fc->timeout.req_timeout);
460f6439f6SJoanne Koong }
470f6439f6SJoanne Koong
fuse_fpq_processing_expired(struct fuse_conn * fc,struct list_head * processing)480f6439f6SJoanne Koong bool fuse_fpq_processing_expired(struct fuse_conn *fc, struct list_head *processing)
490f6439f6SJoanne Koong {
500f6439f6SJoanne Koong int i;
510f6439f6SJoanne Koong
520f6439f6SJoanne Koong for (i = 0; i < FUSE_PQ_HASH_SIZE; i++)
530f6439f6SJoanne Koong if (fuse_request_expired(fc, &processing[i]))
540f6439f6SJoanne Koong return true;
550f6439f6SJoanne Koong
560f6439f6SJoanne Koong return false;
570f6439f6SJoanne Koong }
580f6439f6SJoanne Koong
590f6439f6SJoanne Koong /*
600f6439f6SJoanne Koong * Check if any requests aren't being completed by the time the request timeout
610f6439f6SJoanne Koong * elapses. To do so, we:
620f6439f6SJoanne Koong * - check the fiq pending list
630f6439f6SJoanne Koong * - check the bg queue
640f6439f6SJoanne Koong * - check the fpq io and processing lists
650f6439f6SJoanne Koong *
660f6439f6SJoanne Koong * To make this fast, we only check against the head request on each list since
670f6439f6SJoanne Koong * these are generally queued in order of creation time (eg newer requests get
680f6439f6SJoanne Koong * queued to the tail). We might miss a few edge cases (eg requests transitioning
690f6439f6SJoanne Koong * between lists, re-sent requests at the head of the pending list having a
700f6439f6SJoanne Koong * later creation time than other requests on that list, etc.) but that is fine
710f6439f6SJoanne Koong * since if the request never gets fulfilled, it will eventually be caught.
720f6439f6SJoanne Koong */
fuse_check_timeout(struct work_struct * work)730f6439f6SJoanne Koong void fuse_check_timeout(struct work_struct *work)
740f6439f6SJoanne Koong {
750f6439f6SJoanne Koong struct delayed_work *dwork = to_delayed_work(work);
760f6439f6SJoanne Koong struct fuse_conn *fc = container_of(dwork, struct fuse_conn,
770f6439f6SJoanne Koong timeout.work);
780f6439f6SJoanne Koong struct fuse_iqueue *fiq = &fc->iq;
790f6439f6SJoanne Koong struct fuse_dev *fud;
800f6439f6SJoanne Koong struct fuse_pqueue *fpq;
810f6439f6SJoanne Koong bool expired = false;
820f6439f6SJoanne Koong
830f6439f6SJoanne Koong if (!atomic_read(&fc->num_waiting))
840f6439f6SJoanne Koong goto out;
850f6439f6SJoanne Koong
860f6439f6SJoanne Koong spin_lock(&fiq->lock);
870f6439f6SJoanne Koong expired = fuse_request_expired(fc, &fiq->pending);
880f6439f6SJoanne Koong spin_unlock(&fiq->lock);
890f6439f6SJoanne Koong if (expired)
900f6439f6SJoanne Koong goto abort_conn;
910f6439f6SJoanne Koong
920f6439f6SJoanne Koong spin_lock(&fc->bg_lock);
930f6439f6SJoanne Koong expired = fuse_request_expired(fc, &fc->bg_queue);
940f6439f6SJoanne Koong spin_unlock(&fc->bg_lock);
950f6439f6SJoanne Koong if (expired)
960f6439f6SJoanne Koong goto abort_conn;
970f6439f6SJoanne Koong
980f6439f6SJoanne Koong spin_lock(&fc->lock);
990f6439f6SJoanne Koong if (!fc->connected) {
1000f6439f6SJoanne Koong spin_unlock(&fc->lock);
1010f6439f6SJoanne Koong return;
1020f6439f6SJoanne Koong }
1030f6439f6SJoanne Koong list_for_each_entry(fud, &fc->devices, entry) {
1040f6439f6SJoanne Koong fpq = &fud->pq;
1050f6439f6SJoanne Koong spin_lock(&fpq->lock);
1060f6439f6SJoanne Koong if (fuse_request_expired(fc, &fpq->io) ||
1070f6439f6SJoanne Koong fuse_fpq_processing_expired(fc, fpq->processing)) {
1080f6439f6SJoanne Koong spin_unlock(&fpq->lock);
1090f6439f6SJoanne Koong spin_unlock(&fc->lock);
1100f6439f6SJoanne Koong goto abort_conn;
1110f6439f6SJoanne Koong }
1120f6439f6SJoanne Koong
1130f6439f6SJoanne Koong spin_unlock(&fpq->lock);
1140f6439f6SJoanne Koong }
1150f6439f6SJoanne Koong spin_unlock(&fc->lock);
1160f6439f6SJoanne Koong
1170f6439f6SJoanne Koong if (fuse_uring_request_expired(fc))
1180f6439f6SJoanne Koong goto abort_conn;
1190f6439f6SJoanne Koong
1200f6439f6SJoanne Koong out:
1210f6439f6SJoanne Koong queue_delayed_work(system_wq, &fc->timeout.work,
1220f6439f6SJoanne Koong fuse_timeout_timer_freq);
1230f6439f6SJoanne Koong return;
1240f6439f6SJoanne Koong
1250f6439f6SJoanne Koong abort_conn:
1260f6439f6SJoanne Koong fuse_abort_conn(fc);
1270f6439f6SJoanne Koong }
1280f6439f6SJoanne Koong
fuse_request_init(struct fuse_mount * fm,struct fuse_req * req)129fcee216bSMax Reitz static void fuse_request_init(struct fuse_mount *fm, struct fuse_req *req)
130334f485dSMiklos Szeredi {
131334f485dSMiklos Szeredi INIT_LIST_HEAD(&req->list);
132a4d27e75SMiklos Szeredi INIT_LIST_HEAD(&req->intr_entry);
133334f485dSMiklos Szeredi init_waitqueue_head(&req->waitq);
134ec99f6d3SElena Reshetova refcount_set(&req->count, 1);
13533e14b4dSMiklos Szeredi __set_bit(FR_PENDING, &req->flags);
136fcee216bSMax Reitz req->fm = fm;
1370f6439f6SJoanne Koong req->create_time = jiffies;
138334f485dSMiklos Szeredi }
139334f485dSMiklos Szeredi
fuse_request_alloc(struct fuse_mount * fm,gfp_t flags)140fcee216bSMax Reitz static struct fuse_req *fuse_request_alloc(struct fuse_mount *fm, gfp_t flags)
141334f485dSMiklos Szeredi {
1428a7aa286SMiklos Szeredi struct fuse_req *req = kmem_cache_zalloc(fuse_req_cachep, flags);
1437213394cSMiklos Szeredi if (req)
144fcee216bSMax Reitz fuse_request_init(fm, req);
1454250c066SMaxim Patlasov
146334f485dSMiklos Szeredi return req;
147334f485dSMiklos Szeredi }
1484250c066SMaxim Patlasov
fuse_request_free(struct fuse_req * req)14966abc359SMiklos Szeredi static void fuse_request_free(struct fuse_req *req)
150e52a8250SMiklos Szeredi {
151334f485dSMiklos Szeredi kmem_cache_free(fuse_req_cachep, req);
152334f485dSMiklos Szeredi }
153334f485dSMiklos Szeredi
__fuse_get_request(struct fuse_req * req)15466abc359SMiklos Szeredi static void __fuse_get_request(struct fuse_req *req)
155334f485dSMiklos Szeredi {
156ec99f6d3SElena Reshetova refcount_inc(&req->count);
157334f485dSMiklos Szeredi }
158334f485dSMiklos Szeredi
159334f485dSMiklos Szeredi /* Must be called with > 1 refcount */
__fuse_put_request(struct fuse_req * req)160334f485dSMiklos Szeredi static void __fuse_put_request(struct fuse_req *req)
161334f485dSMiklos Szeredi {
162ec99f6d3SElena Reshetova refcount_dec(&req->count);
163334f485dSMiklos Szeredi }
164334f485dSMiklos Szeredi
fuse_set_initialized(struct fuse_conn * fc)1659759bd51SMiklos Szeredi void fuse_set_initialized(struct fuse_conn *fc)
1669759bd51SMiklos Szeredi {
1679759bd51SMiklos Szeredi /* Make sure stores before this are seen on another CPU */
1689759bd51SMiklos Szeredi smp_wmb();
1699759bd51SMiklos Szeredi fc->initialized = 1;
1709759bd51SMiklos Szeredi }
1719759bd51SMiklos Szeredi
fuse_block_alloc(struct fuse_conn * fc,bool for_background)1720aada884SMaxim Patlasov static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background)
1730aada884SMaxim Patlasov {
1743393ff96SBernd Schubert return !fc->initialized || (for_background && fc->blocked) ||
1753393ff96SBernd Schubert (fc->io_uring && fc->connected && !fuse_uring_ready(fc));
1760aada884SMaxim Patlasov }
1770aada884SMaxim Patlasov
fuse_drop_waiting(struct fuse_conn * fc)178b8f95e5dSMiklos Szeredi static void fuse_drop_waiting(struct fuse_conn *fc)
179b8f95e5dSMiklos Szeredi {
1802d84a2d1SMiklos Szeredi /*
1812d84a2d1SMiklos Szeredi * lockess check of fc->connected is okay, because atomic_dec_and_test()
182c4e0cd4eSZheng Yongjun * provides a memory barrier matched with the one in fuse_wait_aborted()
1832d84a2d1SMiklos Szeredi * to ensure no wake-up is missed.
1842d84a2d1SMiklos Szeredi */
1852d84a2d1SMiklos Szeredi if (atomic_dec_and_test(&fc->num_waiting) &&
1862d84a2d1SMiklos Szeredi !READ_ONCE(fc->connected)) {
187b8f95e5dSMiklos Szeredi /* wake up aborters */
188b8f95e5dSMiklos Szeredi wake_up_all(&fc->blocked_waitq);
189b8f95e5dSMiklos Szeredi }
190b8f95e5dSMiklos Szeredi }
191b8f95e5dSMiklos Szeredi
1928f622e94SMax Reitz static void fuse_put_request(struct fuse_req *req);
19366abc359SMiklos Szeredi
fuse_get_req(struct mnt_idmap * idmap,struct fuse_mount * fm,bool for_background)194aa16880dSAlexander Mikhalitsyn static struct fuse_req *fuse_get_req(struct mnt_idmap *idmap,
195aa16880dSAlexander Mikhalitsyn struct fuse_mount *fm,
196aa16880dSAlexander Mikhalitsyn bool for_background)
197334f485dSMiklos Szeredi {
198fcee216bSMax Reitz struct fuse_conn *fc = fm->fc;
19908a53cdcSMiklos Szeredi struct fuse_req *req;
200106e4593SAlexander Mikhalitsyn bool no_idmap = !fm->sb || (fm->sb->s_iflags & SB_I_NOIDMAP);
201106e4593SAlexander Mikhalitsyn kuid_t fsuid;
202106e4593SAlexander Mikhalitsyn kgid_t fsgid;
2030aada884SMaxim Patlasov int err;
204106e4593SAlexander Mikhalitsyn
2050aada884SMaxim Patlasov atomic_inc(&fc->num_waiting);
2060aada884SMaxim Patlasov
2070aada884SMaxim Patlasov if (fuse_block_alloc(fc, for_background)) {
2089bc5dddaSMiklos Szeredi err = -EINTR;
2097d3a07fcSAl Viro if (wait_event_killable_exclusive(fc->blocked_waitq,
2107d3a07fcSAl Viro !fuse_block_alloc(fc, for_background)))
2119bc5dddaSMiklos Szeredi goto out;
2120aada884SMaxim Patlasov }
2139759bd51SMiklos Szeredi /* Matches smp_wmb() in fuse_set_initialized() */
2149759bd51SMiklos Szeredi smp_rmb();
21508a53cdcSMiklos Szeredi
21651eb01e7SMiklos Szeredi err = -ENOTCONN;
21751eb01e7SMiklos Szeredi if (!fc->connected)
21851eb01e7SMiklos Szeredi goto out;
21951eb01e7SMiklos Szeredi
220de155226SMiklos Szeredi err = -ECONNREFUSED;
221de155226SMiklos Szeredi if (fc->conn_error)
222de155226SMiklos Szeredi goto out;
223de155226SMiklos Szeredi
224fcee216bSMax Reitz req = fuse_request_alloc(fm, GFP_KERNEL);
2259bc5dddaSMiklos Szeredi err = -ENOMEM;
226722d2beaSMaxim Patlasov if (!req) {
227722d2beaSMaxim Patlasov if (for_background)
228722d2beaSMaxim Patlasov wake_up(&fc->blocked_waitq);
2299bc5dddaSMiklos Szeredi goto out;
230722d2beaSMaxim Patlasov }
231334f485dSMiklos Szeredi
232c9582eb0SEric W. Biederman req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns);
233c9582eb0SEric W. Biederman
234825d6d33SMiklos Szeredi __set_bit(FR_WAITING, &req->flags);
235825d6d33SMiklos Szeredi if (for_background)
236825d6d33SMiklos Szeredi __set_bit(FR_BACKGROUND, &req->flags);
237825d6d33SMiklos Szeredi
238aa16880dSAlexander Mikhalitsyn /*
239106e4593SAlexander Mikhalitsyn * Keep the old behavior when idmappings support was not
240106e4593SAlexander Mikhalitsyn * declared by a FUSE server.
241106e4593SAlexander Mikhalitsyn *
242106e4593SAlexander Mikhalitsyn * For those FUSE servers who support idmapped mounts,
243106e4593SAlexander Mikhalitsyn * we send UID/GID only along with "inode creation"
244106e4593SAlexander Mikhalitsyn * fuse requests, otherwise idmap == &invalid_mnt_idmap and
245106e4593SAlexander Mikhalitsyn * req->in.h.{u,g}id will be equal to FUSE_INVALID_UIDGID.
246aa16880dSAlexander Mikhalitsyn */
247106e4593SAlexander Mikhalitsyn fsuid = no_idmap ? current_fsuid() : mapped_fsuid(idmap, fc->user_ns);
248106e4593SAlexander Mikhalitsyn fsgid = no_idmap ? current_fsgid() : mapped_fsgid(idmap, fc->user_ns);
249106e4593SAlexander Mikhalitsyn req->in.h.uid = from_kuid(fc->user_ns, fsuid);
250106e4593SAlexander Mikhalitsyn req->in.h.gid = from_kgid(fc->user_ns, fsgid);
251aa16880dSAlexander Mikhalitsyn
252106e4593SAlexander Mikhalitsyn if (no_idmap && unlikely(req->in.h.uid == ((uid_t)-1) ||
253c9582eb0SEric W. Biederman req->in.h.gid == ((gid_t)-1))) {
2548f622e94SMax Reitz fuse_put_request(req);
255c9582eb0SEric W. Biederman return ERR_PTR(-EOVERFLOW);
256c9582eb0SEric W. Biederman }
257aa16880dSAlexander Mikhalitsyn
258334f485dSMiklos Szeredi return req;
2599bc5dddaSMiklos Szeredi
2609bc5dddaSMiklos Szeredi out:
261b8f95e5dSMiklos Szeredi fuse_drop_waiting(fc);
2629bc5dddaSMiklos Szeredi return ERR_PTR(err);
263334f485dSMiklos Szeredi }
2648b41e671SMaxim Patlasov
fuse_put_request(struct fuse_req * req)2658f622e94SMax Reitz static void fuse_put_request(struct fuse_req *req)
266334f485dSMiklos Szeredi {
267fcee216bSMax Reitz struct fuse_conn *fc = req->fm->fc;
2688f622e94SMax Reitz
269ec99f6d3SElena Reshetova if (refcount_dec_and_test(&req->count)) {
270825d6d33SMiklos Szeredi if (test_bit(FR_BACKGROUND, &req->flags)) {
271722d2beaSMaxim Patlasov /*
272722d2beaSMaxim Patlasov * We get here in the unlikely case that a background
273722d2beaSMaxim Patlasov * request was allocated but not sent
274722d2beaSMaxim Patlasov */
275ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock);
276722d2beaSMaxim Patlasov if (!fc->blocked)
277722d2beaSMaxim Patlasov wake_up(&fc->blocked_waitq);
278ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock);
279722d2beaSMaxim Patlasov }
280722d2beaSMaxim Patlasov
281825d6d33SMiklos Szeredi if (test_bit(FR_WAITING, &req->flags)) {
282825d6d33SMiklos Szeredi __clear_bit(FR_WAITING, &req->flags);
283b8f95e5dSMiklos Szeredi fuse_drop_waiting(fc);
28473e0e738SMiklos Szeredi }
28533649c91SMiklos Szeredi
286ce1d5a49SMiklos Szeredi fuse_request_free(req);
2877128ec2aSMiklos Szeredi }
2887128ec2aSMiklos Szeredi }
2897128ec2aSMiklos Szeredi
fuse_len_args(unsigned int numargs,struct fuse_arg * args)29014d46d7aSStefan Hajnoczi unsigned int fuse_len_args(unsigned int numargs, struct fuse_arg *args)
291d12def1bSMiklos Szeredi {
292d12def1bSMiklos Szeredi unsigned nbytes = 0;
293d12def1bSMiklos Szeredi unsigned i;
294d12def1bSMiklos Szeredi
295d12def1bSMiklos Szeredi for (i = 0; i < numargs; i++)
296d12def1bSMiklos Szeredi nbytes += args[i].size;
297d12def1bSMiklos Szeredi
298d12def1bSMiklos Szeredi return nbytes;
299d12def1bSMiklos Szeredi }
30014d46d7aSStefan Hajnoczi EXPORT_SYMBOL_GPL(fuse_len_args);
301d12def1bSMiklos Szeredi
fuse_get_unique_locked(struct fuse_iqueue * fiq)3025de8acb4SMiklos Szeredi static u64 fuse_get_unique_locked(struct fuse_iqueue *fiq)
303d12def1bSMiklos Szeredi {
304c59fd85eSKirill Tkhai fiq->reqctr += FUSE_REQ_ID_STEP;
305c59fd85eSKirill Tkhai return fiq->reqctr;
306d12def1bSMiklos Szeredi }
3075de8acb4SMiklos Szeredi
fuse_get_unique(struct fuse_iqueue * fiq)3085de8acb4SMiklos Szeredi u64 fuse_get_unique(struct fuse_iqueue *fiq)
3095de8acb4SMiklos Szeredi {
3105de8acb4SMiklos Szeredi u64 ret;
3115de8acb4SMiklos Szeredi
3125de8acb4SMiklos Szeredi spin_lock(&fiq->lock);
3135de8acb4SMiklos Szeredi ret = fuse_get_unique_locked(fiq);
3145de8acb4SMiklos Szeredi spin_unlock(&fiq->lock);
3155de8acb4SMiklos Szeredi
3165de8acb4SMiklos Szeredi return ret;
3175de8acb4SMiklos Szeredi }
31879d96effSStefan Hajnoczi EXPORT_SYMBOL_GPL(fuse_get_unique);
319d12def1bSMiklos Szeredi
fuse_req_hash(u64 unique)32038213365SBernd Schubert unsigned int fuse_req_hash(u64 unique)
321be2ff42cSKirill Tkhai {
322be2ff42cSKirill Tkhai return hash_long(unique & ~FUSE_INT_REQ_BIT, FUSE_PQ_HASH_BITS);
323be2ff42cSKirill Tkhai }
324be2ff42cSKirill Tkhai
32506bbb761SRandy Dunlap /*
326ae3aad77SStefan Hajnoczi * A new request is available, wake fiq->waitq
327ae3aad77SStefan Hajnoczi */
fuse_dev_wake_and_unlock(struct fuse_iqueue * fiq)328ae3aad77SStefan Hajnoczi static void fuse_dev_wake_and_unlock(struct fuse_iqueue *fiq)
329ae3aad77SStefan Hajnoczi __releases(fiq->lock)
330ae3aad77SStefan Hajnoczi {
331ae3aad77SStefan Hajnoczi wake_up(&fiq->waitq);
332ae3aad77SStefan Hajnoczi kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
333ae3aad77SStefan Hajnoczi spin_unlock(&fiq->lock);
334ae3aad77SStefan Hajnoczi }
335ae3aad77SStefan Hajnoczi
fuse_dev_queue_forget(struct fuse_iqueue * fiq,struct fuse_forget_link * forget)336ba74ba57SBernd Schubert void fuse_dev_queue_forget(struct fuse_iqueue *fiq,
337ba74ba57SBernd Schubert struct fuse_forget_link *forget)
3385de8acb4SMiklos Szeredi {
3395de8acb4SMiklos Szeredi spin_lock(&fiq->lock);
3405de8acb4SMiklos Szeredi if (fiq->connected) {
3415de8acb4SMiklos Szeredi fiq->forget_list_tail->next = forget;
3425de8acb4SMiklos Szeredi fiq->forget_list_tail = forget;
3435de8acb4SMiklos Szeredi fuse_dev_wake_and_unlock(fiq);
3445de8acb4SMiklos Szeredi } else {
3455de8acb4SMiklos Szeredi kfree(forget);
3465de8acb4SMiklos Szeredi spin_unlock(&fiq->lock);
3475de8acb4SMiklos Szeredi }
3485de8acb4SMiklos Szeredi }
3495de8acb4SMiklos Szeredi
fuse_dev_queue_interrupt(struct fuse_iqueue * fiq,struct fuse_req * req)350ba74ba57SBernd Schubert void fuse_dev_queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req)
3515de8acb4SMiklos Szeredi {
3525de8acb4SMiklos Szeredi spin_lock(&fiq->lock);
3535de8acb4SMiklos Szeredi if (list_empty(&req->intr_entry)) {
3545de8acb4SMiklos Szeredi list_add_tail(&req->intr_entry, &fiq->interrupts);
3555de8acb4SMiklos Szeredi /*
3565de8acb4SMiklos Szeredi * Pairs with smp_mb() implied by test_and_set_bit()
3575de8acb4SMiklos Szeredi * from fuse_request_end().
3585de8acb4SMiklos Szeredi */
3595de8acb4SMiklos Szeredi smp_mb();
3605de8acb4SMiklos Szeredi if (test_bit(FR_FINISHED, &req->flags)) {
3615de8acb4SMiklos Szeredi list_del_init(&req->intr_entry);
3625de8acb4SMiklos Szeredi spin_unlock(&fiq->lock);
3635de8acb4SMiklos Szeredi } else {
3645de8acb4SMiklos Szeredi fuse_dev_wake_and_unlock(fiq);
3655de8acb4SMiklos Szeredi }
3665de8acb4SMiklos Szeredi } else {
3675de8acb4SMiklos Szeredi spin_unlock(&fiq->lock);
3685de8acb4SMiklos Szeredi }
3695de8acb4SMiklos Szeredi }
3705de8acb4SMiklos Szeredi
fuse_dev_queue_req(struct fuse_iqueue * fiq,struct fuse_req * req)3715de8acb4SMiklos Szeredi static void fuse_dev_queue_req(struct fuse_iqueue *fiq, struct fuse_req *req)
3725de8acb4SMiklos Szeredi {
3735de8acb4SMiklos Szeredi spin_lock(&fiq->lock);
3745de8acb4SMiklos Szeredi if (fiq->connected) {
3755de8acb4SMiklos Szeredi if (req->in.h.opcode != FUSE_NOTIFY_REPLY)
3765de8acb4SMiklos Szeredi req->in.h.unique = fuse_get_unique_locked(fiq);
3775de8acb4SMiklos Szeredi list_add_tail(&req->list, &fiq->pending);
3785de8acb4SMiklos Szeredi fuse_dev_wake_and_unlock(fiq);
3795de8acb4SMiklos Szeredi } else {
3805de8acb4SMiklos Szeredi spin_unlock(&fiq->lock);
3815de8acb4SMiklos Szeredi req->out.h.error = -ENOTCONN;
382fcd2d9e1SMiklos Szeredi clear_bit(FR_PENDING, &req->flags);
3835de8acb4SMiklos Szeredi fuse_request_end(req);
3845de8acb4SMiklos Szeredi }
3855de8acb4SMiklos Szeredi }
3865de8acb4SMiklos Szeredi
387ae3aad77SStefan Hajnoczi const struct fuse_iqueue_ops fuse_dev_fiq_ops = {
3885de8acb4SMiklos Szeredi .send_forget = fuse_dev_queue_forget,
3895de8acb4SMiklos Szeredi .send_interrupt = fuse_dev_queue_interrupt,
3905de8acb4SMiklos Szeredi .send_req = fuse_dev_queue_req,
391ae3aad77SStefan Hajnoczi };
392ae3aad77SStefan Hajnoczi EXPORT_SYMBOL_GPL(fuse_dev_fiq_ops);
393ae3aad77SStefan Hajnoczi
fuse_send_one(struct fuse_iqueue * fiq,struct fuse_req * req)3945de8acb4SMiklos Szeredi static void fuse_send_one(struct fuse_iqueue *fiq, struct fuse_req *req)
395d12def1bSMiklos Szeredi {
396d12def1bSMiklos Szeredi req->in.h.len = sizeof(struct fuse_in_header) +
39714d46d7aSStefan Hajnoczi fuse_len_args(req->args->in_numargs,
398d4993774SMiklos Szeredi (struct fuse_arg *) req->args->in_args);
399396b209eSJosef Bacik trace_fuse_request_send(req);
4005de8acb4SMiklos Szeredi fiq->ops->send_req(fiq, req);
401d12def1bSMiklos Szeredi }
402d12def1bSMiklos Szeredi
fuse_queue_forget(struct fuse_conn * fc,struct fuse_forget_link * forget,u64 nodeid,u64 nlookup)40307e77dcaSMiklos Szeredi void fuse_queue_forget(struct fuse_conn *fc, struct fuse_forget_link *forget,
40407e77dcaSMiklos Szeredi u64 nodeid, u64 nlookup)
40507e77dcaSMiklos Szeredi {
406f88996a9SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq;
407f88996a9SMiklos Szeredi
40802c048b9SMiklos Szeredi forget->forget_one.nodeid = nodeid;
40902c048b9SMiklos Szeredi forget->forget_one.nlookup = nlookup;
41007e77dcaSMiklos Szeredi
4115de8acb4SMiklos Szeredi fiq->ops->send_forget(fiq, forget);
412ae3aad77SStefan Hajnoczi }
41307e77dcaSMiklos Szeredi
flush_bg_queue(struct fuse_conn * fc)414d12def1bSMiklos Szeredi static void flush_bg_queue(struct fuse_conn *fc)
415d12def1bSMiklos Szeredi {
416e287179aSKirill Tkhai struct fuse_iqueue *fiq = &fc->iq;
417e287179aSKirill Tkhai
4187a6d3c8bSCsaba Henk while (fc->active_background < fc->max_background &&
419d12def1bSMiklos Szeredi !list_empty(&fc->bg_queue)) {
420d12def1bSMiklos Szeredi struct fuse_req *req;
421d12def1bSMiklos Szeredi
422e287179aSKirill Tkhai req = list_first_entry(&fc->bg_queue, struct fuse_req, list);
423d12def1bSMiklos Szeredi list_del(&req->list);
424d12def1bSMiklos Szeredi fc->active_background++;
4255de8acb4SMiklos Szeredi fuse_send_one(fiq, req);
426d12def1bSMiklos Szeredi }
427d12def1bSMiklos Szeredi }
428d12def1bSMiklos Szeredi
4296dbbcb12SMiklos Szeredi /*
430334f485dSMiklos Szeredi * This function is called when a request is finished. Either a reply
431f9a2842eSMiklos Szeredi * has arrived or it was aborted (and not yet sent) or some error
432f43b155aSMiklos Szeredi * occurred during communication with userspace, or the device file
43351eb01e7SMiklos Szeredi * was closed. The requester thread is woken up (if still waiting),
43451eb01e7SMiklos Szeredi * the 'end' callback is called if given, else the reference to the
43551eb01e7SMiklos Szeredi * request is released
436334f485dSMiklos Szeredi */
fuse_request_end(struct fuse_req * req)4378f622e94SMax Reitz void fuse_request_end(struct fuse_req *req)
438334f485dSMiklos Szeredi {
439fcee216bSMax Reitz struct fuse_mount *fm = req->fm;
440fcee216bSMax Reitz struct fuse_conn *fc = fm->fc;
4414ce60812SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq;
442365ae710SMiklos Szeredi
443efe2800fSMiklos Szeredi if (test_and_set_bit(FR_FINISHED, &req->flags))
444b8f95e5dSMiklos Szeredi goto put_request;
4452b319d1fSMiklos Szeredi
446396b209eSJosef Bacik trace_fuse_request_end(req);
447217316a6SKirill Tkhai /*
448217316a6SKirill Tkhai * test_and_set_bit() implies smp_mb() between bit
449e1e71c16SMiklos Szeredi * changing and below FR_INTERRUPTED check. Pairs with
450217316a6SKirill Tkhai * smp_mb() from queue_interrupt().
451217316a6SKirill Tkhai */
452e1e71c16SMiklos Szeredi if (test_bit(FR_INTERRUPTED, &req->flags)) {
45376e43c8cSEric Biggers spin_lock(&fiq->lock);
4540d8e84b0SMiklos Szeredi list_del_init(&req->intr_entry);
45576e43c8cSEric Biggers spin_unlock(&fiq->lock);
456217316a6SKirill Tkhai }
45733e14b4dSMiklos Szeredi WARN_ON(test_bit(FR_PENDING, &req->flags));
45833e14b4dSMiklos Szeredi WARN_ON(test_bit(FR_SENT, &req->flags));
459825d6d33SMiklos Szeredi if (test_bit(FR_BACKGROUND, &req->flags)) {
460ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock);
461825d6d33SMiklos Szeredi clear_bit(FR_BACKGROUND, &req->flags);
462908a572bSMiklos Szeredi if (fc->num_background == fc->max_background) {
46351eb01e7SMiklos Szeredi fc->blocked = 0;
464722d2beaSMaxim Patlasov wake_up(&fc->blocked_waitq);
465908a572bSMiklos Szeredi } else if (!fc->blocked) {
466908a572bSMiklos Szeredi /*
467908a572bSMiklos Szeredi * Wake up next waiter, if any. It's okay to use
468908a572bSMiklos Szeredi * waitqueue_active(), as we've already synced up
469908a572bSMiklos Szeredi * fc->blocked with waiters with the wake_up() call
470908a572bSMiklos Szeredi * above.
471908a572bSMiklos Szeredi */
472908a572bSMiklos Szeredi if (waitqueue_active(&fc->blocked_waitq))
473908a572bSMiklos Szeredi wake_up(&fc->blocked_waitq);
474908a572bSMiklos Szeredi }
475722d2beaSMaxim Patlasov
47651eb01e7SMiklos Szeredi fc->num_background--;
477d12def1bSMiklos Szeredi fc->active_background--;
478d12def1bSMiklos Szeredi flush_bg_queue(fc);
479ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock);
4805e0fed71SKirill Tkhai } else {
4815e0fed71SKirill Tkhai /* Wake up waiter sleeping in request_wait_answer() */
48251eb01e7SMiklos Szeredi wake_up(&req->waitq);
4835e0fed71SKirill Tkhai }
4845e0fed71SKirill Tkhai
4853e8cb8b2SMiklos Szeredi if (test_bit(FR_ASYNC, &req->flags))
486fcee216bSMax Reitz req->args->end(fm, req->args, req->out.h.error);
487b8f95e5dSMiklos Szeredi put_request:
4888f622e94SMax Reitz fuse_put_request(req);
489334f485dSMiklos Szeredi }
49004ec5af0SStefan Hajnoczi EXPORT_SYMBOL_GPL(fuse_request_end);
491334f485dSMiklos Szeredi
queue_interrupt(struct fuse_req * req)4928f622e94SMax Reitz static int queue_interrupt(struct fuse_req *req)
493a4d27e75SMiklos Szeredi {
494fcee216bSMax Reitz struct fuse_iqueue *fiq = &req->fm->fc->iq;
4958f622e94SMax Reitz
496b782911bSKirill Tkhai /* Check for we've sent request to interrupt this req */
4975de8acb4SMiklos Szeredi if (unlikely(!test_bit(FR_INTERRUPTED, &req->flags)))
498b782911bSKirill Tkhai return -EINVAL;
499b782911bSKirill Tkhai
5005de8acb4SMiklos Szeredi fiq->ops->send_interrupt(fiq, req);
5015de8acb4SMiklos Szeredi
502b782911bSKirill Tkhai return 0;
503a4d27e75SMiklos Szeredi }
504a4d27e75SMiklos Szeredi
fuse_remove_pending_req(struct fuse_req * req,spinlock_t * lock)50509098e62SBernd Schubert bool fuse_remove_pending_req(struct fuse_req *req, spinlock_t *lock)
50609098e62SBernd Schubert {
50709098e62SBernd Schubert spin_lock(lock);
50809098e62SBernd Schubert if (test_bit(FR_PENDING, &req->flags)) {
50909098e62SBernd Schubert /*
51009098e62SBernd Schubert * FR_PENDING does not get cleared as the request will end
51109098e62SBernd Schubert * up in destruction anyway.
51209098e62SBernd Schubert */
51309098e62SBernd Schubert list_del(&req->list);
51409098e62SBernd Schubert spin_unlock(lock);
51509098e62SBernd Schubert __fuse_put_request(req);
51609098e62SBernd Schubert req->out.h.error = -EINTR;
51709098e62SBernd Schubert return true;
51809098e62SBernd Schubert }
51909098e62SBernd Schubert spin_unlock(lock);
52009098e62SBernd Schubert return false;
52109098e62SBernd Schubert }
52209098e62SBernd Schubert
request_wait_answer(struct fuse_req * req)5238f622e94SMax Reitz static void request_wait_answer(struct fuse_req *req)
524334f485dSMiklos Szeredi {
525fcee216bSMax Reitz struct fuse_conn *fc = req->fm->fc;
5264ce60812SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq;
527c4775267SMiklos Szeredi int err;
528c4775267SMiklos Szeredi
529a4d27e75SMiklos Szeredi if (!fc->no_interrupt) {
530a4d27e75SMiklos Szeredi /* Any signal may interrupt this */
531c4775267SMiklos Szeredi err = wait_event_interruptible(req->waitq,
53233e14b4dSMiklos Szeredi test_bit(FR_FINISHED, &req->flags));
533c4775267SMiklos Szeredi if (!err)
534334f485dSMiklos Szeredi return;
535334f485dSMiklos Szeredi
536825d6d33SMiklos Szeredi set_bit(FR_INTERRUPTED, &req->flags);
5378f7bb368SMiklos Szeredi /* matches barrier in fuse_dev_do_read() */
5388f7bb368SMiklos Szeredi smp_mb__after_atomic();
53933e14b4dSMiklos Szeredi if (test_bit(FR_SENT, &req->flags))
5408f622e94SMax Reitz queue_interrupt(req);
541a4d27e75SMiklos Szeredi }
542a4d27e75SMiklos Szeredi
543825d6d33SMiklos Szeredi if (!test_bit(FR_FORCE, &req->flags)) {
54409098e62SBernd Schubert bool removed;
54509098e62SBernd Schubert
546a4d27e75SMiklos Szeredi /* Only fatal signals may interrupt this */
5477d3a07fcSAl Viro err = wait_event_killable(req->waitq,
54833e14b4dSMiklos Szeredi test_bit(FR_FINISHED, &req->flags));
549c4775267SMiklos Szeredi if (!err)
550a4d27e75SMiklos Szeredi return;
551a4d27e75SMiklos Szeredi
55209098e62SBernd Schubert if (test_bit(FR_URING, &req->flags))
55309098e62SBernd Schubert removed = fuse_uring_remove_pending_req(req);
55409098e62SBernd Schubert else
55509098e62SBernd Schubert removed = fuse_remove_pending_req(req, &fiq->lock);
55609098e62SBernd Schubert if (removed)
557a131de0aSMiklos Szeredi return;
558a131de0aSMiklos Szeredi }
559a131de0aSMiklos Szeredi
560a131de0aSMiklos Szeredi /*
561a131de0aSMiklos Szeredi * Either request is already in userspace, or it was forced.
562a131de0aSMiklos Szeredi * Wait it out.
563a131de0aSMiklos Szeredi */
56433e14b4dSMiklos Szeredi wait_event(req->waitq, test_bit(FR_FINISHED, &req->flags));
565334f485dSMiklos Szeredi }
566334f485dSMiklos Szeredi
__fuse_request_send(struct fuse_req * req)5678f622e94SMax Reitz static void __fuse_request_send(struct fuse_req *req)
568334f485dSMiklos Szeredi {
569fcee216bSMax Reitz struct fuse_iqueue *fiq = &req->fm->fc->iq;
570e16714d8SMiklos Szeredi
571825d6d33SMiklos Szeredi BUG_ON(test_bit(FR_BACKGROUND, &req->flags));
5725de8acb4SMiklos Szeredi
5735de8acb4SMiklos Szeredi /* acquire extra reference, since request is still needed after
5745de8acb4SMiklos Szeredi fuse_request_end() */
575334f485dSMiklos Szeredi __fuse_get_request(req);
5765de8acb4SMiklos Szeredi fuse_send_one(fiq, req);
577334f485dSMiklos Szeredi
5788f622e94SMax Reitz request_wait_answer(req);
57904ec5af0SStefan Hajnoczi /* Pairs with smp_wmb() in fuse_request_end() */
580c4775267SMiklos Szeredi smp_rmb();
581334f485dSMiklos Szeredi }
5826a4e922cSEric Wong
fuse_adjust_compat(struct fuse_conn * fc,struct fuse_args * args)58321f62174SMiklos Szeredi static void fuse_adjust_compat(struct fuse_conn *fc, struct fuse_args *args)
58421f62174SMiklos Szeredi {
585d5b48543SMiklos Szeredi if (fc->minor < 4 && args->opcode == FUSE_STATFS)
586d5b48543SMiklos Szeredi args->out_args[0].size = FUSE_COMPAT_STATFS_SIZE;
58721f62174SMiklos Szeredi
58821f62174SMiklos Szeredi if (fc->minor < 9) {
589d5b48543SMiklos Szeredi switch (args->opcode) {
59021f62174SMiklos Szeredi case FUSE_LOOKUP:
59121f62174SMiklos Szeredi case FUSE_CREATE:
59221f62174SMiklos Szeredi case FUSE_MKNOD:
59321f62174SMiklos Szeredi case FUSE_MKDIR:
59421f62174SMiklos Szeredi case FUSE_SYMLINK:
59521f62174SMiklos Szeredi case FUSE_LINK:
596d5b48543SMiklos Szeredi args->out_args[0].size = FUSE_COMPAT_ENTRY_OUT_SIZE;
59721f62174SMiklos Szeredi break;
59821f62174SMiklos Szeredi case FUSE_GETATTR:
59921f62174SMiklos Szeredi case FUSE_SETATTR:
600d5b48543SMiklos Szeredi args->out_args[0].size = FUSE_COMPAT_ATTR_OUT_SIZE;
60121f62174SMiklos Szeredi break;
60221f62174SMiklos Szeredi }
60321f62174SMiklos Szeredi }
60421f62174SMiklos Szeredi if (fc->minor < 12) {
605d5b48543SMiklos Szeredi switch (args->opcode) {
60621f62174SMiklos Szeredi case FUSE_CREATE:
607d5b48543SMiklos Szeredi args->in_args[0].size = sizeof(struct fuse_open_in);
60821f62174SMiklos Szeredi break;
60921f62174SMiklos Szeredi case FUSE_MKNOD:
610d5b48543SMiklos Szeredi args->in_args[0].size = FUSE_COMPAT_MKNOD_IN_SIZE;
61121f62174SMiklos Szeredi break;
61221f62174SMiklos Szeredi }
61321f62174SMiklos Szeredi }
61421f62174SMiklos Szeredi }
61521f62174SMiklos Szeredi
fuse_force_creds(struct fuse_req * req)6168f622e94SMax Reitz static void fuse_force_creds(struct fuse_req *req)
617e413754bSMiklos Szeredi {
618fcee216bSMax Reitz struct fuse_conn *fc = req->fm->fc;
6198f622e94SMax Reitz
6203988a60dSAlexander Mikhalitsyn if (!req->fm->sb || req->fm->sb->s_iflags & SB_I_NOIDMAP) {
621e413754bSMiklos Szeredi req->in.h.uid = from_kuid_munged(fc->user_ns, current_fsuid());
622e413754bSMiklos Szeredi req->in.h.gid = from_kgid_munged(fc->user_ns, current_fsgid());
623aa16880dSAlexander Mikhalitsyn } else {
624aa16880dSAlexander Mikhalitsyn req->in.h.uid = FUSE_INVALID_UIDGID;
625aa16880dSAlexander Mikhalitsyn req->in.h.gid = FUSE_INVALID_UIDGID;
626aa16880dSAlexander Mikhalitsyn }
627aa16880dSAlexander Mikhalitsyn
628e413754bSMiklos Szeredi req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns);
629e413754bSMiklos Szeredi }
630e413754bSMiklos Szeredi
fuse_args_to_req(struct fuse_req * req,struct fuse_args * args)6315addcd5dSYueHaibing static void fuse_args_to_req(struct fuse_req *req, struct fuse_args *args)
63268583165SMiklos Szeredi {
63368583165SMiklos Szeredi req->in.h.opcode = args->opcode;
63468583165SMiklos Szeredi req->in.h.nodeid = args->nodeid;
635d4993774SMiklos Szeredi req->args = args;
63615d937d7SMiklos Szeredi if (args->is_ext)
63715d937d7SMiklos Szeredi req->in.h.total_extlen = args->in_args[args->ext_idx].size / 8;
6383e8cb8b2SMiklos Szeredi if (args->end)
6393e8cb8b2SMiklos Szeredi __set_bit(FR_ASYNC, &req->flags);
64068583165SMiklos Szeredi }
64168583165SMiklos Szeredi
__fuse_simple_request(struct mnt_idmap * idmap,struct fuse_mount * fm,struct fuse_args * args)6420c679382SAlexander Mikhalitsyn ssize_t __fuse_simple_request(struct mnt_idmap *idmap,
64310dc7218SAlexander Mikhalitsyn struct fuse_mount *fm,
64410dc7218SAlexander Mikhalitsyn struct fuse_args *args)
6457078187aSMiklos Szeredi {
646fcee216bSMax Reitz struct fuse_conn *fc = fm->fc;
6477078187aSMiklos Szeredi struct fuse_req *req;
6487078187aSMiklos Szeredi ssize_t ret;
6497078187aSMiklos Szeredi
650c500ebaaSMiklos Szeredi if (args->force) {
651e413754bSMiklos Szeredi atomic_inc(&fc->num_waiting);
652fcee216bSMax Reitz req = fuse_request_alloc(fm, GFP_KERNEL | __GFP_NOFAIL);
653e413754bSMiklos Szeredi
654e413754bSMiklos Szeredi if (!args->nocreds)
6558f622e94SMax Reitz fuse_force_creds(req);
656e413754bSMiklos Szeredi
657e413754bSMiklos Szeredi __set_bit(FR_WAITING, &req->flags);
658c500ebaaSMiklos Szeredi __set_bit(FR_FORCE, &req->flags);
659c500ebaaSMiklos Szeredi } else {
660e413754bSMiklos Szeredi WARN_ON(args->nocreds);
66110dc7218SAlexander Mikhalitsyn req = fuse_get_req(idmap, fm, false);
6627078187aSMiklos Szeredi if (IS_ERR(req))
6637078187aSMiklos Szeredi return PTR_ERR(req);
664c500ebaaSMiklos Szeredi }
6657078187aSMiklos Szeredi
66621f62174SMiklos Szeredi /* Needs to be done after fuse_get_req() so that fc->minor is valid */
66721f62174SMiklos Szeredi fuse_adjust_compat(fc, args);
66868583165SMiklos Szeredi fuse_args_to_req(req, args);
66921f62174SMiklos Szeredi
670454a7613SMiklos Szeredi if (!args->noreply)
671454a7613SMiklos Szeredi __set_bit(FR_ISREPLY, &req->flags);
6728f622e94SMax Reitz __fuse_request_send(req);
6737078187aSMiklos Szeredi ret = req->out.h.error;
674d5b48543SMiklos Szeredi if (!ret && args->out_argvar) {
675093f38a2SMiklos Szeredi BUG_ON(args->out_numargs == 0);
676d4993774SMiklos Szeredi ret = args->out_args[args->out_numargs - 1].size;
6777078187aSMiklos Szeredi }
6788f622e94SMax Reitz fuse_put_request(req);
6797078187aSMiklos Szeredi
6807078187aSMiklos Szeredi return ret;
6817078187aSMiklos Szeredi }
6827078187aSMiklos Szeredi
683857b0263SBernd Schubert #ifdef CONFIG_FUSE_IO_URING
fuse_request_queue_background_uring(struct fuse_conn * fc,struct fuse_req * req)684857b0263SBernd Schubert static bool fuse_request_queue_background_uring(struct fuse_conn *fc,
685857b0263SBernd Schubert struct fuse_req *req)
686857b0263SBernd Schubert {
687857b0263SBernd Schubert struct fuse_iqueue *fiq = &fc->iq;
688857b0263SBernd Schubert
689857b0263SBernd Schubert req->in.h.unique = fuse_get_unique(fiq);
690857b0263SBernd Schubert req->in.h.len = sizeof(struct fuse_in_header) +
691857b0263SBernd Schubert fuse_len_args(req->args->in_numargs,
692857b0263SBernd Schubert (struct fuse_arg *) req->args->in_args);
693857b0263SBernd Schubert
694857b0263SBernd Schubert return fuse_uring_queue_bq_req(req);
695857b0263SBernd Schubert }
696857b0263SBernd Schubert #endif
697857b0263SBernd Schubert
698857b0263SBernd Schubert /*
699857b0263SBernd Schubert * @return true if queued
700857b0263SBernd Schubert */
fuse_request_queue_background(struct fuse_req * req)701857b0263SBernd Schubert static int fuse_request_queue_background(struct fuse_req *req)
702334f485dSMiklos Szeredi {
703fcee216bSMax Reitz struct fuse_mount *fm = req->fm;
704fcee216bSMax Reitz struct fuse_conn *fc = fm->fc;
70563825b4eSKirill Tkhai bool queued = false;
70663825b4eSKirill Tkhai
70763825b4eSKirill Tkhai WARN_ON(!test_bit(FR_BACKGROUND, &req->flags));
708825d6d33SMiklos Szeredi if (!test_bit(FR_WAITING, &req->flags)) {
709825d6d33SMiklos Szeredi __set_bit(FR_WAITING, &req->flags);
7105437f241SMiklos Szeredi atomic_inc(&fc->num_waiting);
7115437f241SMiklos Szeredi }
712825d6d33SMiklos Szeredi __set_bit(FR_ISREPLY, &req->flags);
713857b0263SBernd Schubert
714857b0263SBernd Schubert #ifdef CONFIG_FUSE_IO_URING
715857b0263SBernd Schubert if (fuse_uring_ready(fc))
716857b0263SBernd Schubert return fuse_request_queue_background_uring(fc, req);
717857b0263SBernd Schubert #endif
718857b0263SBernd Schubert
719ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock);
72063825b4eSKirill Tkhai if (likely(fc->connected)) {
72151eb01e7SMiklos Szeredi fc->num_background++;
7227a6d3c8bSCsaba Henk if (fc->num_background == fc->max_background)
72351eb01e7SMiklos Szeredi fc->blocked = 1;
724d12def1bSMiklos Szeredi list_add_tail(&req->list, &fc->bg_queue);
725d12def1bSMiklos Szeredi flush_bg_queue(fc);
72663825b4eSKirill Tkhai queued = true;
72763825b4eSKirill Tkhai }
728ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock);
72963825b4eSKirill Tkhai
73063825b4eSKirill Tkhai return queued;
731d12def1bSMiklos Szeredi }
73251eb01e7SMiklos Szeredi
fuse_simple_background(struct fuse_mount * fm,struct fuse_args * args,gfp_t gfp_flags)733fcee216bSMax Reitz int fuse_simple_background(struct fuse_mount *fm, struct fuse_args *args,
73412597287SMiklos Szeredi gfp_t gfp_flags)
73512597287SMiklos Szeredi {
73612597287SMiklos Szeredi struct fuse_req *req;
73712597287SMiklos Szeredi
73812597287SMiklos Szeredi if (args->force) {
73912597287SMiklos Szeredi WARN_ON(!args->nocreds);
740fcee216bSMax Reitz req = fuse_request_alloc(fm, gfp_flags);
74112597287SMiklos Szeredi if (!req)
74212597287SMiklos Szeredi return -ENOMEM;
74312597287SMiklos Szeredi __set_bit(FR_BACKGROUND, &req->flags);
74412597287SMiklos Szeredi } else {
74512597287SMiklos Szeredi WARN_ON(args->nocreds);
746106e4593SAlexander Mikhalitsyn req = fuse_get_req(&invalid_mnt_idmap, fm, true);
74712597287SMiklos Szeredi if (IS_ERR(req))
74812597287SMiklos Szeredi return PTR_ERR(req);
74912597287SMiklos Szeredi }
75012597287SMiklos Szeredi
75112597287SMiklos Szeredi fuse_args_to_req(req, args);
75212597287SMiklos Szeredi
7538f622e94SMax Reitz if (!fuse_request_queue_background(req)) {
7548f622e94SMax Reitz fuse_put_request(req);
75512597287SMiklos Szeredi return -ENOTCONN;
75612597287SMiklos Szeredi }
75712597287SMiklos Szeredi
75812597287SMiklos Szeredi return 0;
75912597287SMiklos Szeredi }
76012597287SMiklos Szeredi EXPORT_SYMBOL_GPL(fuse_simple_background);
76112597287SMiklos Szeredi
fuse_simple_notify_reply(struct fuse_mount * fm,struct fuse_args * args,u64 unique)762fcee216bSMax Reitz static int fuse_simple_notify_reply(struct fuse_mount *fm,
76375b399ddSMiklos Szeredi struct fuse_args *args, u64 unique)
7642d45ba38SMiklos Szeredi {
76575b399ddSMiklos Szeredi struct fuse_req *req;
766fcee216bSMax Reitz struct fuse_iqueue *fiq = &fm->fc->iq;
76775b399ddSMiklos Szeredi
768106e4593SAlexander Mikhalitsyn req = fuse_get_req(&invalid_mnt_idmap, fm, false);
76975b399ddSMiklos Szeredi if (IS_ERR(req))
77075b399ddSMiklos Szeredi return PTR_ERR(req);
7712d45ba38SMiklos Szeredi
772825d6d33SMiklos Szeredi __clear_bit(FR_ISREPLY, &req->flags);
7732d45ba38SMiklos Szeredi req->in.h.unique = unique;
77475b399ddSMiklos Szeredi
77575b399ddSMiklos Szeredi fuse_args_to_req(req, args);
77675b399ddSMiklos Szeredi
7775de8acb4SMiklos Szeredi fuse_send_one(fiq, req);
7782d45ba38SMiklos Szeredi
7795de8acb4SMiklos Szeredi return 0;
7802d45ba38SMiklos Szeredi }
7812d45ba38SMiklos Szeredi
7823be5a52bSMiklos Szeredi /*
783334f485dSMiklos Szeredi * Lock the request. Up to the next unlock_request() there mustn't be
784334f485dSMiklos Szeredi * anything that could cause a page-fault. If the request was already
785f9a2842eSMiklos Szeredi * aborted bail out.
786334f485dSMiklos Szeredi */
lock_request(struct fuse_req * req)787dc00809aSMiklos Szeredi static int lock_request(struct fuse_req *req)
788334f485dSMiklos Szeredi {
789334f485dSMiklos Szeredi int err = 0;
790334f485dSMiklos Szeredi if (req) {
791dc00809aSMiklos Szeredi spin_lock(&req->waitq.lock);
792825d6d33SMiklos Szeredi if (test_bit(FR_ABORTED, &req->flags))
793334f485dSMiklos Szeredi err = -ENOENT;
794334f485dSMiklos Szeredi else
795825d6d33SMiklos Szeredi set_bit(FR_LOCKED, &req->flags);
796dc00809aSMiklos Szeredi spin_unlock(&req->waitq.lock);
797334f485dSMiklos Szeredi }
798334f485dSMiklos Szeredi return err;
799334f485dSMiklos Szeredi }
800334f485dSMiklos Szeredi
801334f485dSMiklos Szeredi /*
8020d8e84b0SMiklos Szeredi * Unlock request. If it was aborted while locked, caller is responsible
8030d8e84b0SMiklos Szeredi * for unlocking and ending the request.
804334f485dSMiklos Szeredi */
unlock_request(struct fuse_req * req)805dc00809aSMiklos Szeredi static int unlock_request(struct fuse_req *req)
806334f485dSMiklos Szeredi {
8070d8e84b0SMiklos Szeredi int err = 0;
808334f485dSMiklos Szeredi if (req) {
809dc00809aSMiklos Szeredi spin_lock(&req->waitq.lock);
810825d6d33SMiklos Szeredi if (test_bit(FR_ABORTED, &req->flags))
8110d8e84b0SMiklos Szeredi err = -ENOENT;
8120d8e84b0SMiklos Szeredi else
813825d6d33SMiklos Szeredi clear_bit(FR_LOCKED, &req->flags);
814dc00809aSMiklos Szeredi spin_unlock(&req->waitq.lock);
815334f485dSMiklos Szeredi }
8160d8e84b0SMiklos Szeredi return err;
817334f485dSMiklos Szeredi }
818334f485dSMiklos Szeredi
fuse_copy_init(struct fuse_copy_state * cs,int write,struct iov_iter * iter)819d0f9c62aSBernd Schubert void fuse_copy_init(struct fuse_copy_state *cs, int write,
8206c09e94aSAl Viro struct iov_iter *iter)
821334f485dSMiklos Szeredi {
822334f485dSMiklos Szeredi memset(cs, 0, sizeof(*cs));
823334f485dSMiklos Szeredi cs->write = write;
8246c09e94aSAl Viro cs->iter = iter;
825334f485dSMiklos Szeredi }
826334f485dSMiklos Szeredi
827334f485dSMiklos Szeredi /* Unmap and put previous page of userspace buffer */
fuse_copy_finish(struct fuse_copy_state * cs)8288bfc016dSMiklos Szeredi static void fuse_copy_finish(struct fuse_copy_state *cs)
829334f485dSMiklos Szeredi {
830dd3bb14fSMiklos Szeredi if (cs->currbuf) {
831dd3bb14fSMiklos Szeredi struct pipe_buffer *buf = cs->currbuf;
832dd3bb14fSMiklos Szeredi
833c55a01d3SMiklos Szeredi if (cs->write)
834c3021629SMiklos Szeredi buf->len = PAGE_SIZE - cs->len;
835dd3bb14fSMiklos Szeredi cs->currbuf = NULL;
836c55a01d3SMiklos Szeredi } else if (cs->pg) {
837334f485dSMiklos Szeredi if (cs->write) {
838334f485dSMiklos Szeredi flush_dcache_page(cs->pg);
839334f485dSMiklos Szeredi set_page_dirty_lock(cs->pg);
840334f485dSMiklos Szeredi }
841334f485dSMiklos Szeredi put_page(cs->pg);
842334f485dSMiklos Szeredi }
843c55a01d3SMiklos Szeredi cs->pg = NULL;
844334f485dSMiklos Szeredi }
845334f485dSMiklos Szeredi
846334f485dSMiklos Szeredi /*
847334f485dSMiklos Szeredi * Get another pagefull of userspace buffer, and map it to kernel
848334f485dSMiklos Szeredi * address space, and lock request
849334f485dSMiklos Szeredi */
fuse_copy_fill(struct fuse_copy_state * cs)850334f485dSMiklos Szeredi static int fuse_copy_fill(struct fuse_copy_state *cs)
851334f485dSMiklos Szeredi {
852c55a01d3SMiklos Szeredi struct page *page;
853334f485dSMiklos Szeredi int err;
854334f485dSMiklos Szeredi
855dc00809aSMiklos Szeredi err = unlock_request(cs->req);
8560d8e84b0SMiklos Szeredi if (err)
8570d8e84b0SMiklos Szeredi return err;
8580d8e84b0SMiklos Szeredi
859334f485dSMiklos Szeredi fuse_copy_finish(cs);
860dd3bb14fSMiklos Szeredi if (cs->pipebufs) {
861dd3bb14fSMiklos Szeredi struct pipe_buffer *buf = cs->pipebufs;
862dd3bb14fSMiklos Szeredi
863c3021629SMiklos Szeredi if (!cs->write) {
864fba597dbSMiklos Szeredi err = pipe_buf_confirm(cs->pipe, buf);
865dd3bb14fSMiklos Szeredi if (err)
866dd3bb14fSMiklos Szeredi return err;
867dd3bb14fSMiklos Szeredi
868dd3bb14fSMiklos Szeredi BUG_ON(!cs->nr_segs);
869dd3bb14fSMiklos Szeredi cs->currbuf = buf;
870c55a01d3SMiklos Szeredi cs->pg = buf->page;
871c55a01d3SMiklos Szeredi cs->offset = buf->offset;
872dd3bb14fSMiklos Szeredi cs->len = buf->len;
873dd3bb14fSMiklos Szeredi cs->pipebufs++;
874dd3bb14fSMiklos Szeredi cs->nr_segs--;
875dd3bb14fSMiklos Szeredi } else {
8766718b6f8SDavid Howells if (cs->nr_segs >= cs->pipe->max_usage)
877c3021629SMiklos Szeredi return -EIO;
878c3021629SMiklos Szeredi
879c3021629SMiklos Szeredi page = alloc_page(GFP_HIGHUSER);
880c3021629SMiklos Szeredi if (!page)
881c3021629SMiklos Szeredi return -ENOMEM;
882c3021629SMiklos Szeredi
883c3021629SMiklos Szeredi buf->page = page;
884c3021629SMiklos Szeredi buf->offset = 0;
885c3021629SMiklos Szeredi buf->len = 0;
886c3021629SMiklos Szeredi
887c3021629SMiklos Szeredi cs->currbuf = buf;
888c55a01d3SMiklos Szeredi cs->pg = page;
889c55a01d3SMiklos Szeredi cs->offset = 0;
890c3021629SMiklos Szeredi cs->len = PAGE_SIZE;
891c3021629SMiklos Szeredi cs->pipebufs++;
892c3021629SMiklos Szeredi cs->nr_segs++;
893c3021629SMiklos Szeredi }
894c3021629SMiklos Szeredi } else {
8956c09e94aSAl Viro size_t off;
8961ef255e2SAl Viro err = iov_iter_get_pages2(cs->iter, &page, PAGE_SIZE, 1, &off);
897334f485dSMiklos Szeredi if (err < 0)
898334f485dSMiklos Szeredi return err;
8996c09e94aSAl Viro BUG_ON(!err);
9006c09e94aSAl Viro cs->len = err;
9016c09e94aSAl Viro cs->offset = off;
902c55a01d3SMiklos Szeredi cs->pg = page;
903dd3bb14fSMiklos Szeredi }
904334f485dSMiklos Szeredi
905dc00809aSMiklos Szeredi return lock_request(cs->req);
906334f485dSMiklos Szeredi }
907334f485dSMiklos Szeredi
908334f485dSMiklos Szeredi /* Do as much copy to/from userspace buffer as we can */
fuse_copy_do(struct fuse_copy_state * cs,void ** val,unsigned * size)9098bfc016dSMiklos Szeredi static int fuse_copy_do(struct fuse_copy_state *cs, void **val, unsigned *size)
910334f485dSMiklos Szeredi {
911334f485dSMiklos Szeredi unsigned ncpy = min(*size, cs->len);
912334f485dSMiklos Szeredi if (val) {
9135fe0fc9fSPeng Hao void *pgaddr = kmap_local_page(cs->pg);
914c55a01d3SMiklos Szeredi void *buf = pgaddr + cs->offset;
915c55a01d3SMiklos Szeredi
916334f485dSMiklos Szeredi if (cs->write)
917c55a01d3SMiklos Szeredi memcpy(buf, *val, ncpy);
918334f485dSMiklos Szeredi else
919c55a01d3SMiklos Szeredi memcpy(*val, buf, ncpy);
920c55a01d3SMiklos Szeredi
9215fe0fc9fSPeng Hao kunmap_local(pgaddr);
922334f485dSMiklos Szeredi *val += ncpy;
923334f485dSMiklos Szeredi }
924334f485dSMiklos Szeredi *size -= ncpy;
925334f485dSMiklos Szeredi cs->len -= ncpy;
926c55a01d3SMiklos Szeredi cs->offset += ncpy;
927f773a7c2SBernd Schubert if (cs->is_uring)
928f773a7c2SBernd Schubert cs->ring.copied_sz += ncpy;
929f773a7c2SBernd Schubert
930334f485dSMiklos Szeredi return ncpy;
931334f485dSMiklos Szeredi }
932334f485dSMiklos Szeredi
fuse_check_folio(struct folio * folio)933063aaad7SVishal Moola (Oracle) static int fuse_check_folio(struct folio *folio)
934ce534fb0SMiklos Szeredi {
935063aaad7SVishal Moola (Oracle) if (folio_mapped(folio) ||
936063aaad7SVishal Moola (Oracle) folio->mapping != NULL ||
937063aaad7SVishal Moola (Oracle) (folio->flags & PAGE_FLAGS_CHECK_AT_PREP &
938ce534fb0SMiklos Szeredi ~(1 << PG_locked |
939ce534fb0SMiklos Szeredi 1 << PG_referenced |
940ce534fb0SMiklos Szeredi 1 << PG_lru |
941ce534fb0SMiklos Szeredi 1 << PG_active |
942b89ecd60SMiklos Szeredi 1 << PG_workingset |
943a5005c3cSMiklos Szeredi 1 << PG_reclaim |
944ec1c86b2SYu Zhao 1 << PG_waiters |
945ec1c86b2SYu Zhao LRU_GEN_MASK | LRU_REFS_MASK))) {
946063aaad7SVishal Moola (Oracle) dump_page(&folio->page, "fuse: trying to steal weird page");
947ce534fb0SMiklos Szeredi return 1;
948ce534fb0SMiklos Szeredi }
949ce534fb0SMiklos Szeredi return 0;
950ce534fb0SMiklos Szeredi }
951ce534fb0SMiklos Szeredi
9520c67c37eSJoanne Koong /*
9530c67c37eSJoanne Koong * Attempt to steal a page from the splice() pipe and move it into the
9540c67c37eSJoanne Koong * pagecache. If successful, the pointer in @pagep will be updated. The
9550c67c37eSJoanne Koong * folio that was originally in @pagep will lose a reference and the new
9560c67c37eSJoanne Koong * folio returned in @pagep will carry a reference.
9570c67c37eSJoanne Koong */
fuse_try_move_page(struct fuse_copy_state * cs,struct page ** pagep)958ce534fb0SMiklos Szeredi static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep)
959ce534fb0SMiklos Szeredi {
960ce534fb0SMiklos Szeredi int err;
961063aaad7SVishal Moola (Oracle) struct folio *oldfolio = page_folio(*pagep);
962063aaad7SVishal Moola (Oracle) struct folio *newfolio;
963ce534fb0SMiklos Szeredi struct pipe_buffer *buf = cs->pipebufs;
964ce534fb0SMiklos Szeredi
965063aaad7SVishal Moola (Oracle) folio_get(oldfolio);
966dc00809aSMiklos Szeredi err = unlock_request(cs->req);
9670d8e84b0SMiklos Szeredi if (err)
968d78092e4SMiklos Szeredi goto out_put_old;
9690d8e84b0SMiklos Szeredi
970ce534fb0SMiklos Szeredi fuse_copy_finish(cs);
971ce534fb0SMiklos Szeredi
972fba597dbSMiklos Szeredi err = pipe_buf_confirm(cs->pipe, buf);
973ce534fb0SMiklos Szeredi if (err)
974d78092e4SMiklos Szeredi goto out_put_old;
975ce534fb0SMiklos Szeredi
976ce534fb0SMiklos Szeredi BUG_ON(!cs->nr_segs);
977ce534fb0SMiklos Szeredi cs->currbuf = buf;
978ce534fb0SMiklos Szeredi cs->len = buf->len;
979ce534fb0SMiklos Szeredi cs->pipebufs++;
980ce534fb0SMiklos Szeredi cs->nr_segs--;
981ce534fb0SMiklos Szeredi
982ce534fb0SMiklos Szeredi if (cs->len != PAGE_SIZE)
983ce534fb0SMiklos Szeredi goto out_fallback;
984ce534fb0SMiklos Szeredi
985c928f642SChristoph Hellwig if (!pipe_buf_try_steal(cs->pipe, buf))
986ce534fb0SMiklos Szeredi goto out_fallback;
987ce534fb0SMiklos Szeredi
988063aaad7SVishal Moola (Oracle) newfolio = page_folio(buf->page);
989ce534fb0SMiklos Szeredi
99076a51ac0SMiklos Szeredi folio_clear_uptodate(newfolio);
991063aaad7SVishal Moola (Oracle) folio_clear_mappedtodisk(newfolio);
992ce534fb0SMiklos Szeredi
993063aaad7SVishal Moola (Oracle) if (fuse_check_folio(newfolio) != 0)
994ce534fb0SMiklos Szeredi goto out_fallback_unlock;
995ce534fb0SMiklos Szeredi
996ce534fb0SMiklos Szeredi /*
997ce534fb0SMiklos Szeredi * This is a new and locked page, it shouldn't be mapped or
998ce534fb0SMiklos Szeredi * have any special flags on it
999ce534fb0SMiklos Szeredi */
1000063aaad7SVishal Moola (Oracle) if (WARN_ON(folio_mapped(oldfolio)))
1001ce534fb0SMiklos Szeredi goto out_fallback_unlock;
1002063aaad7SVishal Moola (Oracle) if (WARN_ON(folio_has_private(oldfolio)))
1003ce534fb0SMiklos Szeredi goto out_fallback_unlock;
1004063aaad7SVishal Moola (Oracle) if (WARN_ON(folio_test_dirty(oldfolio) ||
1005063aaad7SVishal Moola (Oracle) folio_test_writeback(oldfolio)))
1006ce534fb0SMiklos Szeredi goto out_fallback_unlock;
1007063aaad7SVishal Moola (Oracle) if (WARN_ON(folio_test_mlocked(oldfolio)))
1008ce534fb0SMiklos Szeredi goto out_fallback_unlock;
1009ce534fb0SMiklos Szeredi
1010063aaad7SVishal Moola (Oracle) replace_page_cache_folio(oldfolio, newfolio);
1011ef6a3c63SMiklos Szeredi
1012063aaad7SVishal Moola (Oracle) folio_get(newfolio);
101347344172SMiklos Szeredi
101447344172SMiklos Szeredi if (!(buf->flags & PIPE_BUF_FLAG_LRU))
1015063aaad7SVishal Moola (Oracle) folio_add_lru(newfolio);
101647344172SMiklos Szeredi
1017712a9510SMiklos Szeredi /*
1018712a9510SMiklos Szeredi * Release while we have extra ref on stolen page. Otherwise
1019712a9510SMiklos Szeredi * anon_pipe_buf_release() might think the page can be reused.
1020712a9510SMiklos Szeredi */
1021712a9510SMiklos Szeredi pipe_buf_release(cs->pipe, buf);
1022712a9510SMiklos Szeredi
1023ce534fb0SMiklos Szeredi err = 0;
1024dc00809aSMiklos Szeredi spin_lock(&cs->req->waitq.lock);
1025825d6d33SMiklos Szeredi if (test_bit(FR_ABORTED, &cs->req->flags))
1026ce534fb0SMiklos Szeredi err = -ENOENT;
1027ce534fb0SMiklos Szeredi else
1028063aaad7SVishal Moola (Oracle) *pagep = &newfolio->page;
1029dc00809aSMiklos Szeredi spin_unlock(&cs->req->waitq.lock);
1030ce534fb0SMiklos Szeredi
1031ce534fb0SMiklos Szeredi if (err) {
1032063aaad7SVishal Moola (Oracle) folio_unlock(newfolio);
1033063aaad7SVishal Moola (Oracle) folio_put(newfolio);
1034d78092e4SMiklos Szeredi goto out_put_old;
1035ce534fb0SMiklos Szeredi }
1036ce534fb0SMiklos Szeredi
1037063aaad7SVishal Moola (Oracle) folio_unlock(oldfolio);
1038d78092e4SMiklos Szeredi /* Drop ref for ap->pages[] array */
1039063aaad7SVishal Moola (Oracle) folio_put(oldfolio);
1040ce534fb0SMiklos Szeredi cs->len = 0;
1041ce534fb0SMiklos Szeredi
1042d78092e4SMiklos Szeredi err = 0;
1043d78092e4SMiklos Szeredi out_put_old:
1044d78092e4SMiklos Szeredi /* Drop ref obtained in this function */
1045063aaad7SVishal Moola (Oracle) folio_put(oldfolio);
1046d78092e4SMiklos Szeredi return err;
1047ce534fb0SMiklos Szeredi
1048ce534fb0SMiklos Szeredi out_fallback_unlock:
1049063aaad7SVishal Moola (Oracle) folio_unlock(newfolio);
1050ce534fb0SMiklos Szeredi out_fallback:
1051c55a01d3SMiklos Szeredi cs->pg = buf->page;
1052c55a01d3SMiklos Szeredi cs->offset = buf->offset;
1053ce534fb0SMiklos Szeredi
1054dc00809aSMiklos Szeredi err = lock_request(cs->req);
1055d78092e4SMiklos Szeredi if (!err)
1056d78092e4SMiklos Szeredi err = 1;
1057ce534fb0SMiklos Szeredi
1058d78092e4SMiklos Szeredi goto out_put_old;
1059ce534fb0SMiklos Szeredi }
1060ce534fb0SMiklos Szeredi
fuse_ref_page(struct fuse_copy_state * cs,struct page * page,unsigned offset,unsigned count)1061c3021629SMiklos Szeredi static int fuse_ref_page(struct fuse_copy_state *cs, struct page *page,
1062c3021629SMiklos Szeredi unsigned offset, unsigned count)
1063c3021629SMiklos Szeredi {
1064c3021629SMiklos Szeredi struct pipe_buffer *buf;
10650d8e84b0SMiklos Szeredi int err;
1066c3021629SMiklos Szeredi
10676718b6f8SDavid Howells if (cs->nr_segs >= cs->pipe->max_usage)
1068c3021629SMiklos Szeredi return -EIO;
1069c3021629SMiklos Szeredi
1070d78092e4SMiklos Szeredi get_page(page);
1071dc00809aSMiklos Szeredi err = unlock_request(cs->req);
1072d78092e4SMiklos Szeredi if (err) {
1073d78092e4SMiklos Szeredi put_page(page);
10740d8e84b0SMiklos Szeredi return err;
1075d78092e4SMiklos Szeredi }
10760d8e84b0SMiklos Szeredi
1077c3021629SMiklos Szeredi fuse_copy_finish(cs);
1078c3021629SMiklos Szeredi
1079c3021629SMiklos Szeredi buf = cs->pipebufs;
1080c3021629SMiklos Szeredi buf->page = page;
1081c3021629SMiklos Szeredi buf->offset = offset;
1082c3021629SMiklos Szeredi buf->len = count;
1083c3021629SMiklos Szeredi
1084c3021629SMiklos Szeredi cs->pipebufs++;
1085c3021629SMiklos Szeredi cs->nr_segs++;
1086c3021629SMiklos Szeredi cs->len = 0;
1087c3021629SMiklos Szeredi
1088c3021629SMiklos Szeredi return 0;
1089c3021629SMiklos Szeredi }
1090c3021629SMiklos Szeredi
1091334f485dSMiklos Szeredi /*
1092334f485dSMiklos Szeredi * Copy a page in the request to/from the userspace buffer. Must be
1093334f485dSMiklos Szeredi * done atomically
1094334f485dSMiklos Szeredi */
fuse_copy_page(struct fuse_copy_state * cs,struct page ** pagep,unsigned offset,unsigned count,int zeroing)1095ce534fb0SMiklos Szeredi static int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep,
1096334f485dSMiklos Szeredi unsigned offset, unsigned count, int zeroing)
1097334f485dSMiklos Szeredi {
1098ce534fb0SMiklos Szeredi int err;
1099ce534fb0SMiklos Szeredi struct page *page = *pagep;
1100ce534fb0SMiklos Szeredi
1101b6777c40SMiklos Szeredi if (page && zeroing && count < PAGE_SIZE)
1102b6777c40SMiklos Szeredi clear_highpage(page);
1103b6777c40SMiklos Szeredi
1104334f485dSMiklos Szeredi while (count) {
1105c3021629SMiklos Szeredi if (cs->write && cs->pipebufs && page) {
11060c4bcfdeSMiklos Szeredi /*
11070c4bcfdeSMiklos Szeredi * Can't control lifetime of pipe buffers, so always
11080c4bcfdeSMiklos Szeredi * copy user pages.
11090c4bcfdeSMiklos Szeredi */
11100c4bcfdeSMiklos Szeredi if (cs->req->args->user_pages) {
11110c4bcfdeSMiklos Szeredi err = fuse_copy_fill(cs);
11120c4bcfdeSMiklos Szeredi if (err)
11130c4bcfdeSMiklos Szeredi return err;
11140c4bcfdeSMiklos Szeredi } else {
1115c3021629SMiklos Szeredi return fuse_ref_page(cs, page, offset, count);
11160c4bcfdeSMiklos Szeredi }
1117c3021629SMiklos Szeredi } else if (!cs->len) {
1118ce534fb0SMiklos Szeredi if (cs->move_pages && page &&
1119ce534fb0SMiklos Szeredi offset == 0 && count == PAGE_SIZE) {
1120ce534fb0SMiklos Szeredi err = fuse_try_move_page(cs, pagep);
1121ce534fb0SMiklos Szeredi if (err <= 0)
1122ce534fb0SMiklos Szeredi return err;
1123ce534fb0SMiklos Szeredi } else {
1124ce534fb0SMiklos Szeredi err = fuse_copy_fill(cs);
11251729a16cSMiklos Szeredi if (err)
1126334f485dSMiklos Szeredi return err;
11271729a16cSMiklos Szeredi }
1128ce534fb0SMiklos Szeredi }
1129334f485dSMiklos Szeredi if (page) {
11305fe0fc9fSPeng Hao void *mapaddr = kmap_local_page(page);
1131334f485dSMiklos Szeredi void *buf = mapaddr + offset;
1132334f485dSMiklos Szeredi offset += fuse_copy_do(cs, &buf, &count);
11335fe0fc9fSPeng Hao kunmap_local(mapaddr);
1134334f485dSMiklos Szeredi } else
1135334f485dSMiklos Szeredi offset += fuse_copy_do(cs, NULL, &count);
1136334f485dSMiklos Szeredi }
1137334f485dSMiklos Szeredi if (page && !cs->write)
1138334f485dSMiklos Szeredi flush_dcache_page(page);
1139334f485dSMiklos Szeredi return 0;
1140334f485dSMiklos Szeredi }
1141334f485dSMiklos Szeredi
1142334f485dSMiklos Szeredi /* Copy pages in the request to/from userspace buffer */
fuse_copy_pages(struct fuse_copy_state * cs,unsigned nbytes,int zeroing)1143334f485dSMiklos Szeredi static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes,
1144334f485dSMiklos Szeredi int zeroing)
1145334f485dSMiklos Szeredi {
1146334f485dSMiklos Szeredi unsigned i;
1147334f485dSMiklos Szeredi struct fuse_req *req = cs->req;
114805ea48ccSMiklos Szeredi struct fuse_args_pages *ap = container_of(req->args, typeof(*ap), args);
1149334f485dSMiklos Szeredi
1150a669c2dfSJoanne Koong for (i = 0; i < ap->num_folios && (nbytes || zeroing); i++) {
1151ce534fb0SMiklos Szeredi int err;
115205ea48ccSMiklos Szeredi unsigned int offset = ap->descs[i].offset;
115305ea48ccSMiklos Szeredi unsigned int count = min(nbytes, ap->descs[i].length);
1154a669c2dfSJoanne Koong struct page *orig, *pagep;
1155ce534fb0SMiklos Szeredi
1156a669c2dfSJoanne Koong orig = pagep = &ap->folios[i]->page;
1157a669c2dfSJoanne Koong
1158a669c2dfSJoanne Koong err = fuse_copy_page(cs, &pagep, offset, count, zeroing);
1159334f485dSMiklos Szeredi if (err)
1160334f485dSMiklos Szeredi return err;
1161334f485dSMiklos Szeredi
1162334f485dSMiklos Szeredi nbytes -= count;
1163a669c2dfSJoanne Koong
1164a669c2dfSJoanne Koong /*
116568bfb7ebSJoanne Koong * fuse_copy_page may have moved a page from a pipe instead of
116668bfb7ebSJoanne Koong * copying into our given page, so update the folios if it was
116768bfb7ebSJoanne Koong * replaced.
1168a669c2dfSJoanne Koong */
1169a669c2dfSJoanne Koong if (pagep != orig)
1170a669c2dfSJoanne Koong ap->folios[i] = page_folio(pagep);
1171334f485dSMiklos Szeredi }
1172334f485dSMiklos Szeredi return 0;
1173334f485dSMiklos Szeredi }
1174334f485dSMiklos Szeredi
1175334f485dSMiklos Szeredi /* Copy a single argument in the request to/from userspace buffer */
fuse_copy_one(struct fuse_copy_state * cs,void * val,unsigned size)1176334f485dSMiklos Szeredi static int fuse_copy_one(struct fuse_copy_state *cs, void *val, unsigned size)
1177334f485dSMiklos Szeredi {
1178334f485dSMiklos Szeredi while (size) {
11791729a16cSMiklos Szeredi if (!cs->len) {
11801729a16cSMiklos Szeredi int err = fuse_copy_fill(cs);
11811729a16cSMiklos Szeredi if (err)
1182334f485dSMiklos Szeredi return err;
11831729a16cSMiklos Szeredi }
1184334f485dSMiklos Szeredi fuse_copy_do(cs, &val, &size);
1185334f485dSMiklos Szeredi }
1186334f485dSMiklos Szeredi return 0;
1187334f485dSMiklos Szeredi }
1188334f485dSMiklos Szeredi
1189334f485dSMiklos Szeredi /* Copy request arguments to/from userspace buffer */
fuse_copy_args(struct fuse_copy_state * cs,unsigned numargs,unsigned argpages,struct fuse_arg * args,int zeroing)1190d0f9c62aSBernd Schubert int fuse_copy_args(struct fuse_copy_state *cs, unsigned numargs,
1191334f485dSMiklos Szeredi unsigned argpages, struct fuse_arg *args,
1192334f485dSMiklos Szeredi int zeroing)
1193334f485dSMiklos Szeredi {
1194334f485dSMiklos Szeredi int err = 0;
1195334f485dSMiklos Szeredi unsigned i;
1196334f485dSMiklos Szeredi
1197334f485dSMiklos Szeredi for (i = 0; !err && i < numargs; i++) {
1198334f485dSMiklos Szeredi struct fuse_arg *arg = &args[i];
1199334f485dSMiklos Szeredi if (i == numargs - 1 && argpages)
1200334f485dSMiklos Szeredi err = fuse_copy_pages(cs, arg->size, zeroing);
1201334f485dSMiklos Szeredi else
1202334f485dSMiklos Szeredi err = fuse_copy_one(cs, arg->value, arg->size);
1203334f485dSMiklos Szeredi }
1204334f485dSMiklos Szeredi return err;
1205334f485dSMiklos Szeredi }
1206334f485dSMiklos Szeredi
forget_pending(struct fuse_iqueue * fiq)1207f88996a9SMiklos Szeredi static int forget_pending(struct fuse_iqueue *fiq)
120807e77dcaSMiklos Szeredi {
1209f88996a9SMiklos Szeredi return fiq->forget_list_head.next != NULL;
121007e77dcaSMiklos Szeredi }
121107e77dcaSMiklos Szeredi
request_pending(struct fuse_iqueue * fiq)1212f88996a9SMiklos Szeredi static int request_pending(struct fuse_iqueue *fiq)
1213a4d27e75SMiklos Szeredi {
1214f88996a9SMiklos Szeredi return !list_empty(&fiq->pending) || !list_empty(&fiq->interrupts) ||
1215f88996a9SMiklos Szeredi forget_pending(fiq);
1216a4d27e75SMiklos Szeredi }
1217a4d27e75SMiklos Szeredi
1218334f485dSMiklos Szeredi /*
1219a4d27e75SMiklos Szeredi * Transfer an interrupt request to userspace
1220a4d27e75SMiklos Szeredi *
1221a4d27e75SMiklos Szeredi * Unlike other requests this is assembled on demand, without a need
1222a4d27e75SMiklos Szeredi * to allocate a separate fuse_req structure.
1223a4d27e75SMiklos Szeredi *
122476e43c8cSEric Biggers * Called with fiq->lock held, releases it
1225a4d27e75SMiklos Szeredi */
fuse_read_interrupt(struct fuse_iqueue * fiq,struct fuse_copy_state * cs,size_t nbytes,struct fuse_req * req)1226fd22d62eSMiklos Szeredi static int fuse_read_interrupt(struct fuse_iqueue *fiq,
1227fd22d62eSMiklos Szeredi struct fuse_copy_state *cs,
1228c3021629SMiklos Szeredi size_t nbytes, struct fuse_req *req)
122976e43c8cSEric Biggers __releases(fiq->lock)
1230a4d27e75SMiklos Szeredi {
1231a4d27e75SMiklos Szeredi struct fuse_in_header ih;
1232a4d27e75SMiklos Szeredi struct fuse_interrupt_in arg;
1233a4d27e75SMiklos Szeredi unsigned reqsize = sizeof(ih) + sizeof(arg);
1234a4d27e75SMiklos Szeredi int err;
1235a4d27e75SMiklos Szeredi
1236a4d27e75SMiklos Szeredi list_del_init(&req->intr_entry);
1237a4d27e75SMiklos Szeredi memset(&ih, 0, sizeof(ih));
1238a4d27e75SMiklos Szeredi memset(&arg, 0, sizeof(arg));
1239a4d27e75SMiklos Szeredi ih.len = reqsize;
1240a4d27e75SMiklos Szeredi ih.opcode = FUSE_INTERRUPT;
12413a5358d1SKirill Tkhai ih.unique = (req->in.h.unique | FUSE_INT_REQ_BIT);
1242a4d27e75SMiklos Szeredi arg.unique = req->in.h.unique;
1243a4d27e75SMiklos Szeredi
124476e43c8cSEric Biggers spin_unlock(&fiq->lock);
1245c3021629SMiklos Szeredi if (nbytes < reqsize)
1246a4d27e75SMiklos Szeredi return -EINVAL;
1247a4d27e75SMiklos Szeredi
1248c3021629SMiklos Szeredi err = fuse_copy_one(cs, &ih, sizeof(ih));
1249a4d27e75SMiklos Szeredi if (!err)
1250c3021629SMiklos Szeredi err = fuse_copy_one(cs, &arg, sizeof(arg));
1251c3021629SMiklos Szeredi fuse_copy_finish(cs);
1252a4d27e75SMiklos Szeredi
1253a4d27e75SMiklos Szeredi return err ? err : reqsize;
1254a4d27e75SMiklos Szeredi }
1255a4d27e75SMiklos Szeredi
fuse_dequeue_forget(struct fuse_iqueue * fiq,unsigned int max,unsigned int * countp)12565de8acb4SMiklos Szeredi static struct fuse_forget_link *fuse_dequeue_forget(struct fuse_iqueue *fiq,
12574388c5aaSVivek Goyal unsigned int max,
12584388c5aaSVivek Goyal unsigned int *countp)
125907e77dcaSMiklos Szeredi {
1260f88996a9SMiklos Szeredi struct fuse_forget_link *head = fiq->forget_list_head.next;
126102c048b9SMiklos Szeredi struct fuse_forget_link **newhead = &head;
126202c048b9SMiklos Szeredi unsigned count;
126307e77dcaSMiklos Szeredi
126402c048b9SMiklos Szeredi for (count = 0; *newhead != NULL && count < max; count++)
126502c048b9SMiklos Szeredi newhead = &(*newhead)->next;
126602c048b9SMiklos Szeredi
1267f88996a9SMiklos Szeredi fiq->forget_list_head.next = *newhead;
126802c048b9SMiklos Szeredi *newhead = NULL;
1269f88996a9SMiklos Szeredi if (fiq->forget_list_head.next == NULL)
1270f88996a9SMiklos Szeredi fiq->forget_list_tail = &fiq->forget_list_head;
127107e77dcaSMiklos Szeredi
127202c048b9SMiklos Szeredi if (countp != NULL)
127302c048b9SMiklos Szeredi *countp = count;
127402c048b9SMiklos Szeredi
127502c048b9SMiklos Szeredi return head;
127607e77dcaSMiklos Szeredi }
127707e77dcaSMiklos Szeredi
fuse_read_single_forget(struct fuse_iqueue * fiq,struct fuse_copy_state * cs,size_t nbytes)1278fd22d62eSMiklos Szeredi static int fuse_read_single_forget(struct fuse_iqueue *fiq,
127907e77dcaSMiklos Szeredi struct fuse_copy_state *cs,
128007e77dcaSMiklos Szeredi size_t nbytes)
128176e43c8cSEric Biggers __releases(fiq->lock)
128207e77dcaSMiklos Szeredi {
128307e77dcaSMiklos Szeredi int err;
12844388c5aaSVivek Goyal struct fuse_forget_link *forget = fuse_dequeue_forget(fiq, 1, NULL);
128507e77dcaSMiklos Szeredi struct fuse_forget_in arg = {
128602c048b9SMiklos Szeredi .nlookup = forget->forget_one.nlookup,
128707e77dcaSMiklos Szeredi };
128807e77dcaSMiklos Szeredi struct fuse_in_header ih = {
128907e77dcaSMiklos Szeredi .opcode = FUSE_FORGET,
129002c048b9SMiklos Szeredi .nodeid = forget->forget_one.nodeid,
12915de8acb4SMiklos Szeredi .unique = fuse_get_unique_locked(fiq),
129207e77dcaSMiklos Szeredi .len = sizeof(ih) + sizeof(arg),
129307e77dcaSMiklos Szeredi };
129407e77dcaSMiklos Szeredi
129576e43c8cSEric Biggers spin_unlock(&fiq->lock);
129607e77dcaSMiklos Szeredi kfree(forget);
129707e77dcaSMiklos Szeredi if (nbytes < ih.len)
129807e77dcaSMiklos Szeredi return -EINVAL;
129907e77dcaSMiklos Szeredi
130007e77dcaSMiklos Szeredi err = fuse_copy_one(cs, &ih, sizeof(ih));
130107e77dcaSMiklos Szeredi if (!err)
130207e77dcaSMiklos Szeredi err = fuse_copy_one(cs, &arg, sizeof(arg));
130307e77dcaSMiklos Szeredi fuse_copy_finish(cs);
130407e77dcaSMiklos Szeredi
130507e77dcaSMiklos Szeredi if (err)
130607e77dcaSMiklos Szeredi return err;
130707e77dcaSMiklos Szeredi
130807e77dcaSMiklos Szeredi return ih.len;
130907e77dcaSMiklos Szeredi }
131007e77dcaSMiklos Szeredi
fuse_read_batch_forget(struct fuse_iqueue * fiq,struct fuse_copy_state * cs,size_t nbytes)1311fd22d62eSMiklos Szeredi static int fuse_read_batch_forget(struct fuse_iqueue *fiq,
131202c048b9SMiklos Szeredi struct fuse_copy_state *cs, size_t nbytes)
131376e43c8cSEric Biggers __releases(fiq->lock)
131402c048b9SMiklos Szeredi {
131502c048b9SMiklos Szeredi int err;
131602c048b9SMiklos Szeredi unsigned max_forgets;
131702c048b9SMiklos Szeredi unsigned count;
131802c048b9SMiklos Szeredi struct fuse_forget_link *head;
131902c048b9SMiklos Szeredi struct fuse_batch_forget_in arg = { .count = 0 };
132002c048b9SMiklos Szeredi struct fuse_in_header ih = {
132102c048b9SMiklos Szeredi .opcode = FUSE_BATCH_FORGET,
13225de8acb4SMiklos Szeredi .unique = fuse_get_unique_locked(fiq),
132302c048b9SMiklos Szeredi .len = sizeof(ih) + sizeof(arg),
132402c048b9SMiklos Szeredi };
132502c048b9SMiklos Szeredi
132602c048b9SMiklos Szeredi if (nbytes < ih.len) {
132776e43c8cSEric Biggers spin_unlock(&fiq->lock);
132802c048b9SMiklos Szeredi return -EINVAL;
132902c048b9SMiklos Szeredi }
133002c048b9SMiklos Szeredi
133102c048b9SMiklos Szeredi max_forgets = (nbytes - ih.len) / sizeof(struct fuse_forget_one);
13324388c5aaSVivek Goyal head = fuse_dequeue_forget(fiq, max_forgets, &count);
133376e43c8cSEric Biggers spin_unlock(&fiq->lock);
133402c048b9SMiklos Szeredi
133502c048b9SMiklos Szeredi arg.count = count;
133602c048b9SMiklos Szeredi ih.len += count * sizeof(struct fuse_forget_one);
133702c048b9SMiklos Szeredi err = fuse_copy_one(cs, &ih, sizeof(ih));
133802c048b9SMiklos Szeredi if (!err)
133902c048b9SMiklos Szeredi err = fuse_copy_one(cs, &arg, sizeof(arg));
134002c048b9SMiklos Szeredi
134102c048b9SMiklos Szeredi while (head) {
134202c048b9SMiklos Szeredi struct fuse_forget_link *forget = head;
134302c048b9SMiklos Szeredi
134402c048b9SMiklos Szeredi if (!err) {
134502c048b9SMiklos Szeredi err = fuse_copy_one(cs, &forget->forget_one,
134602c048b9SMiklos Szeredi sizeof(forget->forget_one));
134702c048b9SMiklos Szeredi }
134802c048b9SMiklos Szeredi head = forget->next;
134902c048b9SMiklos Szeredi kfree(forget);
135002c048b9SMiklos Szeredi }
135102c048b9SMiklos Szeredi
135202c048b9SMiklos Szeredi fuse_copy_finish(cs);
135302c048b9SMiklos Szeredi
135402c048b9SMiklos Szeredi if (err)
135502c048b9SMiklos Szeredi return err;
135602c048b9SMiklos Szeredi
135702c048b9SMiklos Szeredi return ih.len;
135802c048b9SMiklos Szeredi }
135902c048b9SMiklos Szeredi
fuse_read_forget(struct fuse_conn * fc,struct fuse_iqueue * fiq,struct fuse_copy_state * cs,size_t nbytes)1360fd22d62eSMiklos Szeredi static int fuse_read_forget(struct fuse_conn *fc, struct fuse_iqueue *fiq,
1361fd22d62eSMiklos Szeredi struct fuse_copy_state *cs,
136202c048b9SMiklos Szeredi size_t nbytes)
136376e43c8cSEric Biggers __releases(fiq->lock)
136402c048b9SMiklos Szeredi {
1365f88996a9SMiklos Szeredi if (fc->minor < 16 || fiq->forget_list_head.next->next == NULL)
1366fd22d62eSMiklos Szeredi return fuse_read_single_forget(fiq, cs, nbytes);
136702c048b9SMiklos Szeredi else
1368fd22d62eSMiklos Szeredi return fuse_read_batch_forget(fiq, cs, nbytes);
136902c048b9SMiklos Szeredi }
137002c048b9SMiklos Szeredi
1371a4d27e75SMiklos Szeredi /*
1372334f485dSMiklos Szeredi * Read a single request into the userspace filesystem's buffer. This
1373334f485dSMiklos Szeredi * function waits until a request is available, then removes it from
1374334f485dSMiklos Szeredi * the pending list and copies request data to userspace buffer. If
1375f9a2842eSMiklos Szeredi * no reply is needed (FORGET) or request has been aborted or there
1376f9a2842eSMiklos Szeredi * was an error during the copying then it's finished by calling
137704ec5af0SStefan Hajnoczi * fuse_request_end(). Otherwise add it to the processing list, and set
1378334f485dSMiklos Szeredi * the 'sent' flag.
1379334f485dSMiklos Szeredi */
fuse_dev_do_read(struct fuse_dev * fud,struct file * file,struct fuse_copy_state * cs,size_t nbytes)1380c3696046SMiklos Szeredi static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
1381c3021629SMiklos Szeredi struct fuse_copy_state *cs, size_t nbytes)
1382334f485dSMiklos Szeredi {
138382cbdcd3SMiklos Szeredi ssize_t err;
1384c3696046SMiklos Szeredi struct fuse_conn *fc = fud->fc;
1385f88996a9SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq;
1386c3696046SMiklos Szeredi struct fuse_pqueue *fpq = &fud->pq;
1387334f485dSMiklos Szeredi struct fuse_req *req;
1388d4993774SMiklos Szeredi struct fuse_args *args;
1389334f485dSMiklos Szeredi unsigned reqsize;
1390be2ff42cSKirill Tkhai unsigned int hash;
1391334f485dSMiklos Szeredi
13921fb027d7SKirill Smelkov /*
13931fb027d7SKirill Smelkov * Require sane minimum read buffer - that has capacity for fixed part
13941fb027d7SKirill Smelkov * of any request header + negotiated max_write room for data.
13951fb027d7SKirill Smelkov *
13961fb027d7SKirill Smelkov * Historically libfuse reserves 4K for fixed header room, but e.g.
13971fb027d7SKirill Smelkov * GlusterFS reserves only 80 bytes
13981fb027d7SKirill Smelkov *
13991fb027d7SKirill Smelkov * = `sizeof(fuse_in_header) + sizeof(fuse_write_in)`
14001fb027d7SKirill Smelkov *
14011fb027d7SKirill Smelkov * which is the absolute minimum any sane filesystem should be using
14021fb027d7SKirill Smelkov * for header room.
14031fb027d7SKirill Smelkov */
14041fb027d7SKirill Smelkov if (nbytes < max_t(size_t, FUSE_MIN_READ_BUFFER,
14051fb027d7SKirill Smelkov sizeof(struct fuse_in_header) +
14061fb027d7SKirill Smelkov sizeof(struct fuse_write_in) +
14071fb027d7SKirill Smelkov fc->max_write))
14081fb027d7SKirill Smelkov return -EINVAL;
14091fb027d7SKirill Smelkov
14101d3d752bSMiklos Szeredi restart:
141176e43c8cSEric Biggers for (;;) {
141276e43c8cSEric Biggers spin_lock(&fiq->lock);
141376e43c8cSEric Biggers if (!fiq->connected || request_pending(fiq))
141476e43c8cSEric Biggers break;
141576e43c8cSEric Biggers spin_unlock(&fiq->lock);
1416e5ac1d1eSJeff Dike
141776e43c8cSEric Biggers if (file->f_flags & O_NONBLOCK)
141876e43c8cSEric Biggers return -EAGAIN;
141976e43c8cSEric Biggers err = wait_event_interruptible_exclusive(fiq->waitq,
14205250921bSMiklos Szeredi !fiq->connected || request_pending(fiq));
14215250921bSMiklos Szeredi if (err)
142276e43c8cSEric Biggers return err;
142376e43c8cSEric Biggers }
14245250921bSMiklos Szeredi
14253b7008b2SSzymon Lukasz if (!fiq->connected) {
1426eb98e3bdSMiklos Szeredi err = fc->aborted ? -ECONNABORTED : -ENODEV;
1427334f485dSMiklos Szeredi goto err_unlock;
14283b7008b2SSzymon Lukasz }
1429334f485dSMiklos Szeredi
1430f88996a9SMiklos Szeredi if (!list_empty(&fiq->interrupts)) {
1431f88996a9SMiklos Szeredi req = list_entry(fiq->interrupts.next, struct fuse_req,
1432a4d27e75SMiklos Szeredi intr_entry);
1433fd22d62eSMiklos Szeredi return fuse_read_interrupt(fiq, cs, nbytes, req);
1434a4d27e75SMiklos Szeredi }
1435a4d27e75SMiklos Szeredi
1436f88996a9SMiklos Szeredi if (forget_pending(fiq)) {
1437f88996a9SMiklos Szeredi if (list_empty(&fiq->pending) || fiq->forget_batch-- > 0)
1438fd22d62eSMiklos Szeredi return fuse_read_forget(fc, fiq, cs, nbytes);
143907e77dcaSMiklos Szeredi
1440f88996a9SMiklos Szeredi if (fiq->forget_batch <= -8)
1441f88996a9SMiklos Szeredi fiq->forget_batch = 16;
144207e77dcaSMiklos Szeredi }
144307e77dcaSMiklos Szeredi
1444f88996a9SMiklos Szeredi req = list_entry(fiq->pending.next, struct fuse_req, list);
144533e14b4dSMiklos Szeredi clear_bit(FR_PENDING, &req->flags);
1446ef759258SMiklos Szeredi list_del_init(&req->list);
144776e43c8cSEric Biggers spin_unlock(&fiq->lock);
14484ce60812SMiklos Szeredi
1449d4993774SMiklos Szeredi args = req->args;
1450d4993774SMiklos Szeredi reqsize = req->in.h.len;
14515d6d3a30SMiklos Szeredi
14521d3d752bSMiklos Szeredi /* If request is too large, reply with an error and restart the read */
1453c3021629SMiklos Szeredi if (nbytes < reqsize) {
14541d3d752bSMiklos Szeredi req->out.h.error = -EIO;
14551d3d752bSMiklos Szeredi /* SETXATTR is special, since it may contain too large data */
1456d4993774SMiklos Szeredi if (args->opcode == FUSE_SETXATTR)
14571d3d752bSMiklos Szeredi req->out.h.error = -E2BIG;
14588f622e94SMax Reitz fuse_request_end(req);
14591d3d752bSMiklos Szeredi goto restart;
14601d3d752bSMiklos Szeredi }
146145a91cb1SMiklos Szeredi spin_lock(&fpq->lock);
146280ef0867SMiklos Szeredi /*
146380ef0867SMiklos Szeredi * Must not put request on fpq->io queue after having been shut down by
146480ef0867SMiklos Szeredi * fuse_abort_conn()
146580ef0867SMiklos Szeredi */
146680ef0867SMiklos Szeredi if (!fpq->connected) {
146780ef0867SMiklos Szeredi req->out.h.error = err = -ECONNABORTED;
146880ef0867SMiklos Szeredi goto out_end;
146980ef0867SMiklos Szeredi
147080ef0867SMiklos Szeredi }
147182cbdcd3SMiklos Szeredi list_add(&req->list, &fpq->io);
147245a91cb1SMiklos Szeredi spin_unlock(&fpq->lock);
1473c3021629SMiklos Szeredi cs->req = req;
1474d4993774SMiklos Szeredi err = fuse_copy_one(cs, &req->in.h, sizeof(req->in.h));
1475334f485dSMiklos Szeredi if (!err)
1476d4993774SMiklos Szeredi err = fuse_copy_args(cs, args->in_numargs, args->in_pages,
1477d4993774SMiklos Szeredi (struct fuse_arg *) args->in_args, 0);
1478c3021629SMiklos Szeredi fuse_copy_finish(cs);
147945a91cb1SMiklos Szeredi spin_lock(&fpq->lock);
1480825d6d33SMiklos Szeredi clear_bit(FR_LOCKED, &req->flags);
1481e96edd94SMiklos Szeredi if (!fpq->connected) {
1482eb98e3bdSMiklos Szeredi err = fc->aborted ? -ECONNABORTED : -ENODEV;
148382cbdcd3SMiklos Szeredi goto out_end;
1484c9c9d7dfSMiklos Szeredi }
1485334f485dSMiklos Szeredi if (err) {
1486334f485dSMiklos Szeredi req->out.h.error = -EIO;
148782cbdcd3SMiklos Szeredi goto out_end;
1488334f485dSMiklos Szeredi }
1489825d6d33SMiklos Szeredi if (!test_bit(FR_ISREPLY, &req->flags)) {
149082cbdcd3SMiklos Szeredi err = reqsize;
149182cbdcd3SMiklos Szeredi goto out_end;
149282cbdcd3SMiklos Szeredi }
1493be2ff42cSKirill Tkhai hash = fuse_req_hash(req->in.h.unique);
1494be2ff42cSKirill Tkhai list_move_tail(&req->list, &fpq->processing[hash]);
1495bc78abbdSKirill Tkhai __fuse_get_request(req);
14968f7bb368SMiklos Szeredi set_bit(FR_SENT, &req->flags);
14974c316f2fSMiklos Szeredi spin_unlock(&fpq->lock);
14988f7bb368SMiklos Szeredi /* matches barrier in request_wait_answer() */
14998f7bb368SMiklos Szeredi smp_mb__after_atomic();
1500825d6d33SMiklos Szeredi if (test_bit(FR_INTERRUPTED, &req->flags))
15018f622e94SMax Reitz queue_interrupt(req);
15028f622e94SMax Reitz fuse_put_request(req);
150382cbdcd3SMiklos Szeredi
1504334f485dSMiklos Szeredi return reqsize;
1505334f485dSMiklos Szeredi
150682cbdcd3SMiklos Szeredi out_end:
150777cd9d48SMiklos Szeredi if (!test_bit(FR_PRIVATE, &req->flags))
150882cbdcd3SMiklos Szeredi list_del_init(&req->list);
150945a91cb1SMiklos Szeredi spin_unlock(&fpq->lock);
15108f622e94SMax Reitz fuse_request_end(req);
151182cbdcd3SMiklos Szeredi return err;
151282cbdcd3SMiklos Szeredi
1513334f485dSMiklos Szeredi err_unlock:
151476e43c8cSEric Biggers spin_unlock(&fiq->lock);
1515334f485dSMiklos Szeredi return err;
1516334f485dSMiklos Szeredi }
1517334f485dSMiklos Szeredi
fuse_dev_open(struct inode * inode,struct file * file)151894e4fe2cSTom Van Braeckel static int fuse_dev_open(struct inode *inode, struct file *file)
151994e4fe2cSTom Van Braeckel {
152094e4fe2cSTom Van Braeckel /*
152194e4fe2cSTom Van Braeckel * The fuse device's file's private_data is used to hold
152294e4fe2cSTom Van Braeckel * the fuse_conn(ection) when it is mounted, and is used to
152394e4fe2cSTom Van Braeckel * keep track of whether the file has been mounted already.
152494e4fe2cSTom Van Braeckel */
152594e4fe2cSTom Van Braeckel file->private_data = NULL;
152694e4fe2cSTom Van Braeckel return 0;
152794e4fe2cSTom Van Braeckel }
152894e4fe2cSTom Van Braeckel
fuse_dev_read(struct kiocb * iocb,struct iov_iter * to)1529fbdbaccaSAl Viro static ssize_t fuse_dev_read(struct kiocb *iocb, struct iov_iter *to)
1530c3021629SMiklos Szeredi {
1531c3021629SMiklos Szeredi struct fuse_copy_state cs;
1532c3021629SMiklos Szeredi struct file *file = iocb->ki_filp;
1533cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(file);
1534cc080e9eSMiklos Szeredi
1535cc080e9eSMiklos Szeredi if (!fud)
1536c3021629SMiklos Szeredi return -EPERM;
1537c3021629SMiklos Szeredi
1538fcb14cb1SAl Viro if (!user_backed_iter(to))
1539fbdbaccaSAl Viro return -EINVAL;
1540c3021629SMiklos Szeredi
1541dc00809aSMiklos Szeredi fuse_copy_init(&cs, 1, to);
1542fbdbaccaSAl Viro
1543c3696046SMiklos Szeredi return fuse_dev_do_read(fud, file, &cs, iov_iter_count(to));
1544c3021629SMiklos Szeredi }
1545c3021629SMiklos Szeredi
fuse_dev_splice_read(struct file * in,loff_t * ppos,struct pipe_inode_info * pipe,size_t len,unsigned int flags)1546c3021629SMiklos Szeredi static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
1547c3021629SMiklos Szeredi struct pipe_inode_info *pipe,
1548c3021629SMiklos Szeredi size_t len, unsigned int flags)
1549c3021629SMiklos Szeredi {
1550d82718e3SAl Viro int total, ret;
1551c3021629SMiklos Szeredi int page_nr = 0;
1552c3021629SMiklos Szeredi struct pipe_buffer *bufs;
1553c3021629SMiklos Szeredi struct fuse_copy_state cs;
1554cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(in);
1555cc080e9eSMiklos Szeredi
1556cc080e9eSMiklos Szeredi if (!fud)
1557c3021629SMiklos Szeredi return -EPERM;
1558c3021629SMiklos Szeredi
15596718b6f8SDavid Howells bufs = kvmalloc_array(pipe->max_usage, sizeof(struct pipe_buffer),
15606da2ec56SKees Cook GFP_KERNEL);
1561c3021629SMiklos Szeredi if (!bufs)
1562c3021629SMiklos Szeredi return -ENOMEM;
1563c3021629SMiklos Szeredi
1564dc00809aSMiklos Szeredi fuse_copy_init(&cs, 1, NULL);
1565c3021629SMiklos Szeredi cs.pipebufs = bufs;
1566c3021629SMiklos Szeredi cs.pipe = pipe;
1567c3696046SMiklos Szeredi ret = fuse_dev_do_read(fud, in, &cs, len);
1568c3021629SMiklos Szeredi if (ret < 0)
1569c3021629SMiklos Szeredi goto out;
1570c3021629SMiklos Szeredi
157100a7d398SLinus Torvalds if (pipe_buf_usage(pipe) + cs.nr_segs > pipe->max_usage) {
1572c3021629SMiklos Szeredi ret = -EIO;
1573d82718e3SAl Viro goto out;
1574c3021629SMiklos Szeredi }
1575c3021629SMiklos Szeredi
1576d82718e3SAl Viro for (ret = total = 0; page_nr < cs.nr_segs; total += ret) {
157728a625cbSMiklos Szeredi /*
157828a625cbSMiklos Szeredi * Need to be careful about this. Having buf->ops in module
157928a625cbSMiklos Szeredi * code can Oops if the buffer persists after module unload.
158028a625cbSMiklos Szeredi */
1581d82718e3SAl Viro bufs[page_nr].ops = &nosteal_pipe_buf_ops;
158284588a93SMiklos Szeredi bufs[page_nr].flags = 0;
1583d82718e3SAl Viro ret = add_to_pipe(pipe, &bufs[page_nr++]);
1584d82718e3SAl Viro if (unlikely(ret < 0))
1585d82718e3SAl Viro break;
1586c3021629SMiklos Szeredi }
1587d82718e3SAl Viro if (total)
1588d82718e3SAl Viro ret = total;
1589c3021629SMiklos Szeredi out:
1590c3021629SMiklos Szeredi for (; page_nr < cs.nr_segs; page_nr++)
159109cbfeafSKirill A. Shutemov put_page(bufs[page_nr].page);
1592c3021629SMiklos Szeredi
1593d6d931adSAndrey Ryabinin kvfree(bufs);
1594c3021629SMiklos Szeredi return ret;
1595c3021629SMiklos Szeredi }
1596c3021629SMiklos Szeredi
fuse_notify_poll(struct fuse_conn * fc,unsigned int size,struct fuse_copy_state * cs)159795668a69STejun Heo static int fuse_notify_poll(struct fuse_conn *fc, unsigned int size,
159895668a69STejun Heo struct fuse_copy_state *cs)
159995668a69STejun Heo {
160095668a69STejun Heo struct fuse_notify_poll_wakeup_out outarg;
1601f6d47a17SMiklos Szeredi int err = -EINVAL;
160295668a69STejun Heo
160395668a69STejun Heo if (size != sizeof(outarg))
1604f6d47a17SMiklos Szeredi goto err;
160595668a69STejun Heo
160695668a69STejun Heo err = fuse_copy_one(cs, &outarg, sizeof(outarg));
160795668a69STejun Heo if (err)
1608f6d47a17SMiklos Szeredi goto err;
160995668a69STejun Heo
1610f6d47a17SMiklos Szeredi fuse_copy_finish(cs);
161195668a69STejun Heo return fuse_notify_poll_wakeup(fc, &outarg);
1612f6d47a17SMiklos Szeredi
1613f6d47a17SMiklos Szeredi err:
1614f6d47a17SMiklos Szeredi fuse_copy_finish(cs);
1615f6d47a17SMiklos Szeredi return err;
161695668a69STejun Heo }
161795668a69STejun Heo
fuse_notify_inval_inode(struct fuse_conn * fc,unsigned int size,struct fuse_copy_state * cs)16183b463ae0SJohn Muir static int fuse_notify_inval_inode(struct fuse_conn *fc, unsigned int size,
16193b463ae0SJohn Muir struct fuse_copy_state *cs)
16203b463ae0SJohn Muir {
16213b463ae0SJohn Muir struct fuse_notify_inval_inode_out outarg;
16223b463ae0SJohn Muir int err = -EINVAL;
16233b463ae0SJohn Muir
16243b463ae0SJohn Muir if (size != sizeof(outarg))
16253b463ae0SJohn Muir goto err;
16263b463ae0SJohn Muir
16273b463ae0SJohn Muir err = fuse_copy_one(cs, &outarg, sizeof(outarg));
16283b463ae0SJohn Muir if (err)
16293b463ae0SJohn Muir goto err;
16303b463ae0SJohn Muir fuse_copy_finish(cs);
16313b463ae0SJohn Muir
16323b463ae0SJohn Muir down_read(&fc->killsb);
1633fcee216bSMax Reitz err = fuse_reverse_inval_inode(fc, outarg.ino,
16343b463ae0SJohn Muir outarg.off, outarg.len);
16353b463ae0SJohn Muir up_read(&fc->killsb);
16363b463ae0SJohn Muir return err;
16373b463ae0SJohn Muir
16383b463ae0SJohn Muir err:
16393b463ae0SJohn Muir fuse_copy_finish(cs);
16403b463ae0SJohn Muir return err;
16413b463ae0SJohn Muir }
16423b463ae0SJohn Muir
fuse_notify_inval_entry(struct fuse_conn * fc,unsigned int size,struct fuse_copy_state * cs)16433b463ae0SJohn Muir static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size,
16443b463ae0SJohn Muir struct fuse_copy_state *cs)
16453b463ae0SJohn Muir {
16463b463ae0SJohn Muir struct fuse_notify_inval_entry_out outarg;
16472412085dSBernd Schubert int err;
16482412085dSBernd Schubert char *buf = NULL;
16493b463ae0SJohn Muir struct qstr name;
16503b463ae0SJohn Muir
1651b2d82ee3SFang Wenqi err = -EINVAL;
16523b463ae0SJohn Muir if (size < sizeof(outarg))
16533b463ae0SJohn Muir goto err;
16543b463ae0SJohn Muir
16553b463ae0SJohn Muir err = fuse_copy_one(cs, &outarg, sizeof(outarg));
16563b463ae0SJohn Muir if (err)
16573b463ae0SJohn Muir goto err;
16583b463ae0SJohn Muir
16593b463ae0SJohn Muir err = -ENAMETOOLONG;
1660*27992ef8SBernd Schubert if (outarg.namelen > fc->name_max)
16613b463ae0SJohn Muir goto err;
16623b463ae0SJohn Muir
1663c2183d1eSMiklos Szeredi err = -EINVAL;
1664c2183d1eSMiklos Szeredi if (size != sizeof(outarg) + outarg.namelen + 1)
1665c2183d1eSMiklos Szeredi goto err;
1666c2183d1eSMiklos Szeredi
16672412085dSBernd Schubert err = -ENOMEM;
16682412085dSBernd Schubert buf = kzalloc(outarg.namelen + 1, GFP_KERNEL);
16692412085dSBernd Schubert if (!buf)
16702412085dSBernd Schubert goto err;
16712412085dSBernd Schubert
16723b463ae0SJohn Muir name.name = buf;
16733b463ae0SJohn Muir name.len = outarg.namelen;
16743b463ae0SJohn Muir err = fuse_copy_one(cs, buf, outarg.namelen + 1);
16753b463ae0SJohn Muir if (err)
16763b463ae0SJohn Muir goto err;
16773b463ae0SJohn Muir fuse_copy_finish(cs);
16783b463ae0SJohn Muir buf[outarg.namelen] = 0;
16793b463ae0SJohn Muir
16803b463ae0SJohn Muir down_read(&fc->killsb);
16814f8d3702SMiklos Szeredi err = fuse_reverse_inval_entry(fc, outarg.parent, 0, &name, outarg.flags);
1682451d0f59SJohn Muir up_read(&fc->killsb);
1683451d0f59SJohn Muir kfree(buf);
1684451d0f59SJohn Muir return err;
1685451d0f59SJohn Muir
1686451d0f59SJohn Muir err:
1687451d0f59SJohn Muir kfree(buf);
1688451d0f59SJohn Muir fuse_copy_finish(cs);
1689451d0f59SJohn Muir return err;
1690451d0f59SJohn Muir }
1691451d0f59SJohn Muir
fuse_notify_delete(struct fuse_conn * fc,unsigned int size,struct fuse_copy_state * cs)1692451d0f59SJohn Muir static int fuse_notify_delete(struct fuse_conn *fc, unsigned int size,
1693451d0f59SJohn Muir struct fuse_copy_state *cs)
1694451d0f59SJohn Muir {
1695451d0f59SJohn Muir struct fuse_notify_delete_out outarg;
16962412085dSBernd Schubert int err;
16972412085dSBernd Schubert char *buf = NULL;
1698451d0f59SJohn Muir struct qstr name;
1699451d0f59SJohn Muir
1700451d0f59SJohn Muir err = -EINVAL;
1701451d0f59SJohn Muir if (size < sizeof(outarg))
1702451d0f59SJohn Muir goto err;
1703451d0f59SJohn Muir
1704451d0f59SJohn Muir err = fuse_copy_one(cs, &outarg, sizeof(outarg));
1705451d0f59SJohn Muir if (err)
1706451d0f59SJohn Muir goto err;
1707451d0f59SJohn Muir
1708451d0f59SJohn Muir err = -ENAMETOOLONG;
1709*27992ef8SBernd Schubert if (outarg.namelen > fc->name_max)
1710451d0f59SJohn Muir goto err;
1711451d0f59SJohn Muir
1712451d0f59SJohn Muir err = -EINVAL;
1713451d0f59SJohn Muir if (size != sizeof(outarg) + outarg.namelen + 1)
1714451d0f59SJohn Muir goto err;
1715451d0f59SJohn Muir
17162412085dSBernd Schubert err = -ENOMEM;
17172412085dSBernd Schubert buf = kzalloc(outarg.namelen + 1, GFP_KERNEL);
17182412085dSBernd Schubert if (!buf)
17192412085dSBernd Schubert goto err;
17202412085dSBernd Schubert
1721451d0f59SJohn Muir name.name = buf;
1722451d0f59SJohn Muir name.len = outarg.namelen;
1723451d0f59SJohn Muir err = fuse_copy_one(cs, buf, outarg.namelen + 1);
1724451d0f59SJohn Muir if (err)
1725451d0f59SJohn Muir goto err;
1726451d0f59SJohn Muir fuse_copy_finish(cs);
1727451d0f59SJohn Muir buf[outarg.namelen] = 0;
1728451d0f59SJohn Muir
1729451d0f59SJohn Muir down_read(&fc->killsb);
17304f8d3702SMiklos Szeredi err = fuse_reverse_inval_entry(fc, outarg.parent, outarg.child, &name, 0);
17313b463ae0SJohn Muir up_read(&fc->killsb);
1732b2d82ee3SFang Wenqi kfree(buf);
17333b463ae0SJohn Muir return err;
17343b463ae0SJohn Muir
17353b463ae0SJohn Muir err:
1736b2d82ee3SFang Wenqi kfree(buf);
17373b463ae0SJohn Muir fuse_copy_finish(cs);
17383b463ae0SJohn Muir return err;
17393b463ae0SJohn Muir }
17403b463ae0SJohn Muir
fuse_notify_store(struct fuse_conn * fc,unsigned int size,struct fuse_copy_state * cs)1741a1d75f25SMiklos Szeredi static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
1742a1d75f25SMiklos Szeredi struct fuse_copy_state *cs)
1743a1d75f25SMiklos Szeredi {
1744a1d75f25SMiklos Szeredi struct fuse_notify_store_out outarg;
1745a1d75f25SMiklos Szeredi struct inode *inode;
1746a1d75f25SMiklos Szeredi struct address_space *mapping;
1747a1d75f25SMiklos Szeredi u64 nodeid;
1748a1d75f25SMiklos Szeredi int err;
1749a1d75f25SMiklos Szeredi pgoff_t index;
1750a1d75f25SMiklos Szeredi unsigned int offset;
1751a1d75f25SMiklos Szeredi unsigned int num;
1752a1d75f25SMiklos Szeredi loff_t file_size;
1753a1d75f25SMiklos Szeredi loff_t end;
1754a1d75f25SMiklos Szeredi
1755a1d75f25SMiklos Szeredi err = -EINVAL;
1756a1d75f25SMiklos Szeredi if (size < sizeof(outarg))
1757a1d75f25SMiklos Szeredi goto out_finish;
1758a1d75f25SMiklos Szeredi
1759a1d75f25SMiklos Szeredi err = fuse_copy_one(cs, &outarg, sizeof(outarg));
1760a1d75f25SMiklos Szeredi if (err)
1761a1d75f25SMiklos Szeredi goto out_finish;
1762a1d75f25SMiklos Szeredi
1763a1d75f25SMiklos Szeredi err = -EINVAL;
1764a1d75f25SMiklos Szeredi if (size - sizeof(outarg) != outarg.size)
1765a1d75f25SMiklos Szeredi goto out_finish;
1766a1d75f25SMiklos Szeredi
1767a1d75f25SMiklos Szeredi nodeid = outarg.nodeid;
1768a1d75f25SMiklos Szeredi
1769a1d75f25SMiklos Szeredi down_read(&fc->killsb);
1770a1d75f25SMiklos Szeredi
1771a1d75f25SMiklos Szeredi err = -ENOENT;
1772fcee216bSMax Reitz inode = fuse_ilookup(fc, nodeid, NULL);
1773a1d75f25SMiklos Szeredi if (!inode)
1774a1d75f25SMiklos Szeredi goto out_up_killsb;
1775a1d75f25SMiklos Szeredi
1776a1d75f25SMiklos Szeredi mapping = inode->i_mapping;
177709cbfeafSKirill A. Shutemov index = outarg.offset >> PAGE_SHIFT;
177809cbfeafSKirill A. Shutemov offset = outarg.offset & ~PAGE_MASK;
1779a1d75f25SMiklos Szeredi file_size = i_size_read(inode);
1780a1d75f25SMiklos Szeredi end = outarg.offset + outarg.size;
1781a1d75f25SMiklos Szeredi if (end > file_size) {
1782a1d75f25SMiklos Szeredi file_size = end;
1783d347739aSMiklos Szeredi fuse_write_update_attr(inode, file_size, outarg.size);
1784a1d75f25SMiklos Szeredi }
1785a1d75f25SMiklos Szeredi
1786a1d75f25SMiklos Szeredi num = outarg.size;
1787a1d75f25SMiklos Szeredi while (num) {
17888807f117SJosef Bacik struct folio *folio;
1789a1d75f25SMiklos Szeredi struct page *page;
1790a1d75f25SMiklos Szeredi unsigned int this_num;
1791a1d75f25SMiklos Szeredi
17928807f117SJosef Bacik folio = filemap_grab_folio(mapping, index);
17938807f117SJosef Bacik err = PTR_ERR(folio);
17948807f117SJosef Bacik if (IS_ERR(folio))
1795a1d75f25SMiklos Szeredi goto out_iput;
1796a1d75f25SMiklos Szeredi
17978807f117SJosef Bacik page = &folio->page;
17988807f117SJosef Bacik this_num = min_t(unsigned, num, folio_size(folio) - offset);
1799a1d75f25SMiklos Szeredi err = fuse_copy_page(cs, &page, offset, this_num, 0);
18008807f117SJosef Bacik if (!folio_test_uptodate(folio) && !err && offset == 0 &&
18018807f117SJosef Bacik (this_num == folio_size(folio) || file_size == end)) {
18028807f117SJosef Bacik folio_zero_segment(folio, this_num, folio_size(folio));
18038807f117SJosef Bacik folio_mark_uptodate(folio);
18043c0da3d1SJann Horn }
18058807f117SJosef Bacik folio_unlock(folio);
18068807f117SJosef Bacik folio_put(folio);
1807a1d75f25SMiklos Szeredi
1808a1d75f25SMiklos Szeredi if (err)
1809a1d75f25SMiklos Szeredi goto out_iput;
1810a1d75f25SMiklos Szeredi
1811a1d75f25SMiklos Szeredi num -= this_num;
1812a1d75f25SMiklos Szeredi offset = 0;
1813a1d75f25SMiklos Szeredi index++;
1814a1d75f25SMiklos Szeredi }
1815a1d75f25SMiklos Szeredi
1816a1d75f25SMiklos Szeredi err = 0;
1817a1d75f25SMiklos Szeredi
1818a1d75f25SMiklos Szeredi out_iput:
1819a1d75f25SMiklos Szeredi iput(inode);
1820a1d75f25SMiklos Szeredi out_up_killsb:
1821a1d75f25SMiklos Szeredi up_read(&fc->killsb);
1822a1d75f25SMiklos Szeredi out_finish:
1823a1d75f25SMiklos Szeredi fuse_copy_finish(cs);
1824a1d75f25SMiklos Szeredi return err;
1825a1d75f25SMiklos Szeredi }
1826a1d75f25SMiklos Szeredi
182775b399ddSMiklos Szeredi struct fuse_retrieve_args {
182875b399ddSMiklos Szeredi struct fuse_args_pages ap;
182975b399ddSMiklos Szeredi struct fuse_notify_retrieve_in inarg;
183075b399ddSMiklos Szeredi };
183175b399ddSMiklos Szeredi
fuse_retrieve_end(struct fuse_mount * fm,struct fuse_args * args,int error)1832fcee216bSMax Reitz static void fuse_retrieve_end(struct fuse_mount *fm, struct fuse_args *args,
183375b399ddSMiklos Szeredi int error)
18342d45ba38SMiklos Szeredi {
183575b399ddSMiklos Szeredi struct fuse_retrieve_args *ra =
183675b399ddSMiklos Szeredi container_of(args, typeof(*ra), ap.args);
183775b399ddSMiklos Szeredi
1838448895dfSJoanne Koong release_pages(ra->ap.folios, ra->ap.num_folios);
183975b399ddSMiklos Szeredi kfree(ra);
18402d45ba38SMiklos Szeredi }
18412d45ba38SMiklos Szeredi
fuse_retrieve(struct fuse_mount * fm,struct inode * inode,struct fuse_notify_retrieve_out * outarg)1842fcee216bSMax Reitz static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
18432d45ba38SMiklos Szeredi struct fuse_notify_retrieve_out *outarg)
18442d45ba38SMiklos Szeredi {
18452d45ba38SMiklos Szeredi int err;
18462d45ba38SMiklos Szeredi struct address_space *mapping = inode->i_mapping;
18472d45ba38SMiklos Szeredi pgoff_t index;
18482d45ba38SMiklos Szeredi loff_t file_size;
18492d45ba38SMiklos Szeredi unsigned int num;
18502d45ba38SMiklos Szeredi unsigned int offset;
18510157443cSGeert Uytterhoeven size_t total_len = 0;
1852448895dfSJoanne Koong unsigned int num_pages, cur_pages = 0;
1853fcee216bSMax Reitz struct fuse_conn *fc = fm->fc;
185475b399ddSMiklos Szeredi struct fuse_retrieve_args *ra;
185575b399ddSMiklos Szeredi size_t args_size = sizeof(*ra);
185675b399ddSMiklos Szeredi struct fuse_args_pages *ap;
185775b399ddSMiklos Szeredi struct fuse_args *args;
18582d45ba38SMiklos Szeredi
185909cbfeafSKirill A. Shutemov offset = outarg->offset & ~PAGE_MASK;
18604d53dc99SMaxim Patlasov file_size = i_size_read(inode);
18614d53dc99SMaxim Patlasov
18627640682eSKirill Smelkov num = min(outarg->size, fc->max_write);
18634d53dc99SMaxim Patlasov if (outarg->offset > file_size)
18644d53dc99SMaxim Patlasov num = 0;
18654d53dc99SMaxim Patlasov else if (outarg->offset + num > file_size)
18664d53dc99SMaxim Patlasov num = file_size - outarg->offset;
18674d53dc99SMaxim Patlasov
18684d53dc99SMaxim Patlasov num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
18695da784ccSConstantine Shulyupin num_pages = min(num_pages, fc->max_pages);
18704d53dc99SMaxim Patlasov
187168bfb7ebSJoanne Koong args_size += num_pages * (sizeof(ap->folios[0]) + sizeof(ap->descs[0]));
18722d45ba38SMiklos Szeredi
187375b399ddSMiklos Szeredi ra = kzalloc(args_size, GFP_KERNEL);
187475b399ddSMiklos Szeredi if (!ra)
187575b399ddSMiklos Szeredi return -ENOMEM;
187675b399ddSMiklos Szeredi
187775b399ddSMiklos Szeredi ap = &ra->ap;
1878448895dfSJoanne Koong ap->folios = (void *) (ra + 1);
187968bfb7ebSJoanne Koong ap->descs = (void *) (ap->folios + num_pages);
188075b399ddSMiklos Szeredi
188175b399ddSMiklos Szeredi args = &ap->args;
188275b399ddSMiklos Szeredi args->nodeid = outarg->nodeid;
188375b399ddSMiklos Szeredi args->opcode = FUSE_NOTIFY_REPLY;
18847ccd86baSBernd Schubert args->in_numargs = 3;
188575b399ddSMiklos Szeredi args->in_pages = true;
188675b399ddSMiklos Szeredi args->end = fuse_retrieve_end;
18872d45ba38SMiklos Szeredi
188809cbfeafSKirill A. Shutemov index = outarg->offset >> PAGE_SHIFT;
18892d45ba38SMiklos Szeredi
1890448895dfSJoanne Koong while (num && cur_pages < num_pages) {
189171e10dc2SJosef Bacik struct folio *folio;
18922d45ba38SMiklos Szeredi unsigned int this_num;
18932d45ba38SMiklos Szeredi
189471e10dc2SJosef Bacik folio = filemap_get_folio(mapping, index);
189571e10dc2SJosef Bacik if (IS_ERR(folio))
18962d45ba38SMiklos Szeredi break;
18972d45ba38SMiklos Szeredi
189809cbfeafSKirill A. Shutemov this_num = min_t(unsigned, num, PAGE_SIZE - offset);
1899448895dfSJoanne Koong ap->folios[ap->num_folios] = folio;
190068bfb7ebSJoanne Koong ap->descs[ap->num_folios].offset = offset;
190168bfb7ebSJoanne Koong ap->descs[ap->num_folios].length = this_num;
1902448895dfSJoanne Koong ap->num_folios++;
1903448895dfSJoanne Koong cur_pages++;
19042d45ba38SMiklos Szeredi
1905c9e67d48SMiklos Szeredi offset = 0;
19062d45ba38SMiklos Szeredi num -= this_num;
19072d45ba38SMiklos Szeredi total_len += this_num;
190848706d0aSMiklos Szeredi index++;
19092d45ba38SMiklos Szeredi }
191075b399ddSMiklos Szeredi ra->inarg.offset = outarg->offset;
191175b399ddSMiklos Szeredi ra->inarg.size = total_len;
19127ccd86baSBernd Schubert fuse_set_zero_arg0(args);
19137ccd86baSBernd Schubert args->in_args[1].size = sizeof(ra->inarg);
19147ccd86baSBernd Schubert args->in_args[1].value = &ra->inarg;
19157ccd86baSBernd Schubert args->in_args[2].size = total_len;
19162d45ba38SMiklos Szeredi
1917fcee216bSMax Reitz err = fuse_simple_notify_reply(fm, args, outarg->notify_unique);
191875b399ddSMiklos Szeredi if (err)
1919fcee216bSMax Reitz fuse_retrieve_end(fm, args, err);
19202d45ba38SMiklos Szeredi
19212d45ba38SMiklos Szeredi return err;
19222d45ba38SMiklos Szeredi }
19232d45ba38SMiklos Szeredi
fuse_notify_retrieve(struct fuse_conn * fc,unsigned int size,struct fuse_copy_state * cs)19242d45ba38SMiklos Szeredi static int fuse_notify_retrieve(struct fuse_conn *fc, unsigned int size,
19252d45ba38SMiklos Szeredi struct fuse_copy_state *cs)
19262d45ba38SMiklos Szeredi {
19272d45ba38SMiklos Szeredi struct fuse_notify_retrieve_out outarg;
1928fcee216bSMax Reitz struct fuse_mount *fm;
19292d45ba38SMiklos Szeredi struct inode *inode;
1930fcee216bSMax Reitz u64 nodeid;
19312d45ba38SMiklos Szeredi int err;
19322d45ba38SMiklos Szeredi
19332d45ba38SMiklos Szeredi err = -EINVAL;
19342d45ba38SMiklos Szeredi if (size != sizeof(outarg))
19352d45ba38SMiklos Szeredi goto copy_finish;
19362d45ba38SMiklos Szeredi
19372d45ba38SMiklos Szeredi err = fuse_copy_one(cs, &outarg, sizeof(outarg));
19382d45ba38SMiklos Szeredi if (err)
19392d45ba38SMiklos Szeredi goto copy_finish;
19402d45ba38SMiklos Szeredi
19412d45ba38SMiklos Szeredi fuse_copy_finish(cs);
19422d45ba38SMiklos Szeredi
19432d45ba38SMiklos Szeredi down_read(&fc->killsb);
19442d45ba38SMiklos Szeredi err = -ENOENT;
1945fcee216bSMax Reitz nodeid = outarg.nodeid;
19462d45ba38SMiklos Szeredi
1947fcee216bSMax Reitz inode = fuse_ilookup(fc, nodeid, &fm);
19482d45ba38SMiklos Szeredi if (inode) {
1949fcee216bSMax Reitz err = fuse_retrieve(fm, inode, &outarg);
19502d45ba38SMiklos Szeredi iput(inode);
19512d45ba38SMiklos Szeredi }
19522d45ba38SMiklos Szeredi up_read(&fc->killsb);
19532d45ba38SMiklos Szeredi
19542d45ba38SMiklos Szeredi return err;
19552d45ba38SMiklos Szeredi
19562d45ba38SMiklos Szeredi copy_finish:
19572d45ba38SMiklos Szeredi fuse_copy_finish(cs);
19582d45ba38SMiklos Szeredi return err;
19592d45ba38SMiklos Szeredi }
19602d45ba38SMiklos Szeredi
1961760eac73SZhao Chen /*
1962760eac73SZhao Chen * Resending all processing queue requests.
1963760eac73SZhao Chen *
1964760eac73SZhao Chen * During a FUSE daemon panics and failover, it is possible for some inflight
1965760eac73SZhao Chen * requests to be lost and never returned. As a result, applications awaiting
1966760eac73SZhao Chen * replies would become stuck forever. To address this, we can use notification
1967760eac73SZhao Chen * to trigger resending of these pending requests to the FUSE daemon, ensuring
1968760eac73SZhao Chen * they are properly processed again.
1969760eac73SZhao Chen *
1970760eac73SZhao Chen * Please note that this strategy is applicable only to idempotent requests or
1971760eac73SZhao Chen * if the FUSE daemon takes careful measures to avoid processing duplicated
1972760eac73SZhao Chen * non-idempotent requests.
1973760eac73SZhao Chen */
fuse_resend(struct fuse_conn * fc)1974760eac73SZhao Chen static void fuse_resend(struct fuse_conn *fc)
1975760eac73SZhao Chen {
1976760eac73SZhao Chen struct fuse_dev *fud;
1977760eac73SZhao Chen struct fuse_req *req, *next;
1978760eac73SZhao Chen struct fuse_iqueue *fiq = &fc->iq;
1979760eac73SZhao Chen LIST_HEAD(to_queue);
1980760eac73SZhao Chen unsigned int i;
1981760eac73SZhao Chen
1982760eac73SZhao Chen spin_lock(&fc->lock);
1983760eac73SZhao Chen if (!fc->connected) {
1984760eac73SZhao Chen spin_unlock(&fc->lock);
1985760eac73SZhao Chen return;
1986760eac73SZhao Chen }
1987760eac73SZhao Chen
1988760eac73SZhao Chen list_for_each_entry(fud, &fc->devices, entry) {
1989760eac73SZhao Chen struct fuse_pqueue *fpq = &fud->pq;
1990760eac73SZhao Chen
1991760eac73SZhao Chen spin_lock(&fpq->lock);
1992760eac73SZhao Chen for (i = 0; i < FUSE_PQ_HASH_SIZE; i++)
1993760eac73SZhao Chen list_splice_tail_init(&fpq->processing[i], &to_queue);
1994760eac73SZhao Chen spin_unlock(&fpq->lock);
1995760eac73SZhao Chen }
1996760eac73SZhao Chen spin_unlock(&fc->lock);
1997760eac73SZhao Chen
1998760eac73SZhao Chen list_for_each_entry_safe(req, next, &to_queue, list) {
199942815f8aSHou Tao set_bit(FR_PENDING, &req->flags);
200024601487SHou Tao clear_bit(FR_SENT, &req->flags);
20019e7f5296SZhao Chen /* mark the request as resend request */
20029e7f5296SZhao Chen req->in.h.unique |= FUSE_UNIQUE_RESEND;
2003760eac73SZhao Chen }
2004760eac73SZhao Chen
2005760eac73SZhao Chen spin_lock(&fiq->lock);
200697f30876SJoanne Koong if (!fiq->connected) {
200797f30876SJoanne Koong spin_unlock(&fiq->lock);
200897f30876SJoanne Koong list_for_each_entry(req, &to_queue, list)
200997f30876SJoanne Koong clear_bit(FR_PENDING, &req->flags);
201092270d07SBernd Schubert fuse_dev_end_requests(&to_queue);
201197f30876SJoanne Koong return;
201297f30876SJoanne Koong }
2013760eac73SZhao Chen /* iq and pq requests are both oldest to newest */
2014760eac73SZhao Chen list_splice(&to_queue, &fiq->pending);
20155de8acb4SMiklos Szeredi fuse_dev_wake_and_unlock(fiq);
2016760eac73SZhao Chen }
2017760eac73SZhao Chen
fuse_notify_resend(struct fuse_conn * fc)2018760eac73SZhao Chen static int fuse_notify_resend(struct fuse_conn *fc)
2019760eac73SZhao Chen {
2020760eac73SZhao Chen fuse_resend(fc);
2021760eac73SZhao Chen return 0;
2022760eac73SZhao Chen }
2023760eac73SZhao Chen
fuse_notify(struct fuse_conn * fc,enum fuse_notify_code code,unsigned int size,struct fuse_copy_state * cs)20248599396bSTejun Heo static int fuse_notify(struct fuse_conn *fc, enum fuse_notify_code code,
20258599396bSTejun Heo unsigned int size, struct fuse_copy_state *cs)
20268599396bSTejun Heo {
20270d278362SMiklos Szeredi /* Don't try to move pages (yet) */
20280d278362SMiklos Szeredi cs->move_pages = 0;
20290d278362SMiklos Szeredi
20308599396bSTejun Heo switch (code) {
203195668a69STejun Heo case FUSE_NOTIFY_POLL:
203295668a69STejun Heo return fuse_notify_poll(fc, size, cs);
203395668a69STejun Heo
20343b463ae0SJohn Muir case FUSE_NOTIFY_INVAL_INODE:
20353b463ae0SJohn Muir return fuse_notify_inval_inode(fc, size, cs);
20363b463ae0SJohn Muir
20373b463ae0SJohn Muir case FUSE_NOTIFY_INVAL_ENTRY:
20383b463ae0SJohn Muir return fuse_notify_inval_entry(fc, size, cs);
20393b463ae0SJohn Muir
2040a1d75f25SMiklos Szeredi case FUSE_NOTIFY_STORE:
2041a1d75f25SMiklos Szeredi return fuse_notify_store(fc, size, cs);
2042a1d75f25SMiklos Szeredi
20432d45ba38SMiklos Szeredi case FUSE_NOTIFY_RETRIEVE:
20442d45ba38SMiklos Szeredi return fuse_notify_retrieve(fc, size, cs);
20452d45ba38SMiklos Szeredi
2046451d0f59SJohn Muir case FUSE_NOTIFY_DELETE:
2047451d0f59SJohn Muir return fuse_notify_delete(fc, size, cs);
2048451d0f59SJohn Muir
2049760eac73SZhao Chen case FUSE_NOTIFY_RESEND:
2050760eac73SZhao Chen return fuse_notify_resend(fc);
2051760eac73SZhao Chen
20528599396bSTejun Heo default:
2053f6d47a17SMiklos Szeredi fuse_copy_finish(cs);
20548599396bSTejun Heo return -EINVAL;
20558599396bSTejun Heo }
20568599396bSTejun Heo }
20578599396bSTejun Heo
2058334f485dSMiklos Szeredi /* Look up request on processing list by unique ID */
fuse_request_find(struct fuse_pqueue * fpq,u64 unique)205938213365SBernd Schubert struct fuse_req *fuse_request_find(struct fuse_pqueue *fpq, u64 unique)
2060334f485dSMiklos Szeredi {
2061be2ff42cSKirill Tkhai unsigned int hash = fuse_req_hash(unique);
2062334f485dSMiklos Szeredi struct fuse_req *req;
206305726acaSDong Fang
2064be2ff42cSKirill Tkhai list_for_each_entry(req, &fpq->processing[hash], list) {
20653a5358d1SKirill Tkhai if (req->in.h.unique == unique)
2066334f485dSMiklos Szeredi return req;
2067334f485dSMiklos Szeredi }
2068334f485dSMiklos Szeredi return NULL;
2069334f485dSMiklos Szeredi }
2070334f485dSMiklos Szeredi
fuse_copy_out_args(struct fuse_copy_state * cs,struct fuse_args * args,unsigned nbytes)2071d0f9c62aSBernd Schubert int fuse_copy_out_args(struct fuse_copy_state *cs, struct fuse_args *args,
2072334f485dSMiklos Szeredi unsigned nbytes)
2073334f485dSMiklos Szeredi {
2074f773a7c2SBernd Schubert
2075f773a7c2SBernd Schubert unsigned int reqsize = 0;
2076f773a7c2SBernd Schubert
2077f773a7c2SBernd Schubert /*
2078f773a7c2SBernd Schubert * Uring has all headers separated from args - args is payload only
2079f773a7c2SBernd Schubert */
2080f773a7c2SBernd Schubert if (!cs->is_uring)
2081f773a7c2SBernd Schubert reqsize = sizeof(struct fuse_out_header);
2082334f485dSMiklos Szeredi
208314d46d7aSStefan Hajnoczi reqsize += fuse_len_args(args->out_numargs, args->out_args);
2084334f485dSMiklos Szeredi
2085d4993774SMiklos Szeredi if (reqsize < nbytes || (reqsize > nbytes && !args->out_argvar))
2086334f485dSMiklos Szeredi return -EINVAL;
2087334f485dSMiklos Szeredi else if (reqsize > nbytes) {
2088d4993774SMiklos Szeredi struct fuse_arg *lastarg = &args->out_args[args->out_numargs-1];
2089334f485dSMiklos Szeredi unsigned diffsize = reqsize - nbytes;
2090d4993774SMiklos Szeredi
2091334f485dSMiklos Szeredi if (diffsize > lastarg->size)
2092334f485dSMiklos Szeredi return -EINVAL;
2093334f485dSMiklos Szeredi lastarg->size -= diffsize;
2094334f485dSMiklos Szeredi }
2095d4993774SMiklos Szeredi return fuse_copy_args(cs, args->out_numargs, args->out_pages,
2096d4993774SMiklos Szeredi args->out_args, args->page_zeroing);
2097334f485dSMiklos Szeredi }
2098334f485dSMiklos Szeredi
2099334f485dSMiklos Szeredi /*
2100334f485dSMiklos Szeredi * Write a single reply to a request. First the header is copied from
2101334f485dSMiklos Szeredi * the write buffer. The request is then searched on the processing
2102334f485dSMiklos Szeredi * list by the unique ID found in the header. If found, then remove
2103334f485dSMiklos Szeredi * it from the list and copy the rest of the buffer to the request.
210404ec5af0SStefan Hajnoczi * The request is finished by calling fuse_request_end().
2105334f485dSMiklos Szeredi */
fuse_dev_do_write(struct fuse_dev * fud,struct fuse_copy_state * cs,size_t nbytes)2106c3696046SMiklos Szeredi static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
2107dd3bb14fSMiklos Szeredi struct fuse_copy_state *cs, size_t nbytes)
2108334f485dSMiklos Szeredi {
2109334f485dSMiklos Szeredi int err;
2110c3696046SMiklos Szeredi struct fuse_conn *fc = fud->fc;
2111c3696046SMiklos Szeredi struct fuse_pqueue *fpq = &fud->pq;
2112334f485dSMiklos Szeredi struct fuse_req *req;
2113334f485dSMiklos Szeredi struct fuse_out_header oh;
2114334f485dSMiklos Szeredi
21157407a10dSKirill Tkhai err = -EINVAL;
2116334f485dSMiklos Szeredi if (nbytes < sizeof(struct fuse_out_header))
21177407a10dSKirill Tkhai goto out;
2118334f485dSMiklos Szeredi
2119dd3bb14fSMiklos Szeredi err = fuse_copy_one(cs, &oh, sizeof(oh));
2120334f485dSMiklos Szeredi if (err)
21217407a10dSKirill Tkhai goto copy_finish;
21228599396bSTejun Heo
2123334f485dSMiklos Szeredi err = -EINVAL;
21248599396bSTejun Heo if (oh.len != nbytes)
21257407a10dSKirill Tkhai goto copy_finish;
21268599396bSTejun Heo
21278599396bSTejun Heo /*
21288599396bSTejun Heo * Zero oh.unique indicates unsolicited notification message
21298599396bSTejun Heo * and error contains notification code.
21308599396bSTejun Heo */
21318599396bSTejun Heo if (!oh.unique) {
2132dd3bb14fSMiklos Szeredi err = fuse_notify(fc, oh.error, nbytes - sizeof(oh), cs);
21337407a10dSKirill Tkhai goto out;
21348599396bSTejun Heo }
21358599396bSTejun Heo
21368599396bSTejun Heo err = -EINVAL;
213749221cf8SMiklos Szeredi if (oh.error <= -512 || oh.error > 0)
21387407a10dSKirill Tkhai goto copy_finish;
2139334f485dSMiklos Szeredi
214045a91cb1SMiklos Szeredi spin_lock(&fpq->lock);
21417407a10dSKirill Tkhai req = NULL;
21427407a10dSKirill Tkhai if (fpq->connected)
214338213365SBernd Schubert req = fuse_request_find(fpq, oh.unique & ~FUSE_INT_REQ_BIT);
21447407a10dSKirill Tkhai
21457407a10dSKirill Tkhai err = -ENOENT;
21467407a10dSKirill Tkhai if (!req) {
21477407a10dSKirill Tkhai spin_unlock(&fpq->lock);
21487407a10dSKirill Tkhai goto copy_finish;
21497407a10dSKirill Tkhai }
2150334f485dSMiklos Szeredi
21513a5358d1SKirill Tkhai /* Is it an interrupt reply ID? */
21523a5358d1SKirill Tkhai if (oh.unique & FUSE_INT_REQ_BIT) {
2153d2d2d4fbSKirill Tkhai __fuse_get_request(req);
215445a91cb1SMiklos Szeredi spin_unlock(&fpq->lock);
215545a91cb1SMiklos Szeredi
21567407a10dSKirill Tkhai err = 0;
21577407a10dSKirill Tkhai if (nbytes != sizeof(struct fuse_out_header))
2158a4d27e75SMiklos Szeredi err = -EINVAL;
21597407a10dSKirill Tkhai else if (oh.error == -ENOSYS)
2160a4d27e75SMiklos Szeredi fc->no_interrupt = 1;
2161a4d27e75SMiklos Szeredi else if (oh.error == -EAGAIN)
21628f622e94SMax Reitz err = queue_interrupt(req);
21637407a10dSKirill Tkhai
21648f622e94SMax Reitz fuse_put_request(req);
2165a4d27e75SMiklos Szeredi
21667407a10dSKirill Tkhai goto copy_finish;
2167a4d27e75SMiklos Szeredi }
2168a4d27e75SMiklos Szeredi
216933e14b4dSMiklos Szeredi clear_bit(FR_SENT, &req->flags);
21703a2b5b9cSMiklos Szeredi list_move(&req->list, &fpq->io);
2171334f485dSMiklos Szeredi req->out.h = oh;
2172825d6d33SMiklos Szeredi set_bit(FR_LOCKED, &req->flags);
217345a91cb1SMiklos Szeredi spin_unlock(&fpq->lock);
2174dd3bb14fSMiklos Szeredi cs->req = req;
2175d4993774SMiklos Szeredi if (!req->args->page_replace)
2176ce534fb0SMiklos Szeredi cs->move_pages = 0;
2177334f485dSMiklos Szeredi
2178d4993774SMiklos Szeredi if (oh.error)
2179d4993774SMiklos Szeredi err = nbytes != sizeof(oh) ? -EINVAL : 0;
2180d4993774SMiklos Szeredi else
2181d0f9c62aSBernd Schubert err = fuse_copy_out_args(cs, req->args, nbytes);
2182dd3bb14fSMiklos Szeredi fuse_copy_finish(cs);
2183334f485dSMiklos Szeredi
218445a91cb1SMiklos Szeredi spin_lock(&fpq->lock);
2185825d6d33SMiklos Szeredi clear_bit(FR_LOCKED, &req->flags);
2186e96edd94SMiklos Szeredi if (!fpq->connected)
2187334f485dSMiklos Szeredi err = -ENOENT;
21880d8e84b0SMiklos Szeredi else if (err)
2189334f485dSMiklos Szeredi req->out.h.error = -EIO;
219077cd9d48SMiklos Szeredi if (!test_bit(FR_PRIVATE, &req->flags))
2191f377cb79SMiklos Szeredi list_del_init(&req->list);
219245a91cb1SMiklos Szeredi spin_unlock(&fpq->lock);
219346c34a34SMiklos Szeredi
21948f622e94SMax Reitz fuse_request_end(req);
21957407a10dSKirill Tkhai out:
2196334f485dSMiklos Szeredi return err ? err : nbytes;
2197334f485dSMiklos Szeredi
21987407a10dSKirill Tkhai copy_finish:
2199dd3bb14fSMiklos Szeredi fuse_copy_finish(cs);
22007407a10dSKirill Tkhai goto out;
2201334f485dSMiklos Szeredi }
2202334f485dSMiklos Szeredi
fuse_dev_write(struct kiocb * iocb,struct iov_iter * from)2203fbdbaccaSAl Viro static ssize_t fuse_dev_write(struct kiocb *iocb, struct iov_iter *from)
2204dd3bb14fSMiklos Szeredi {
2205dd3bb14fSMiklos Szeredi struct fuse_copy_state cs;
2206cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(iocb->ki_filp);
2207cc080e9eSMiklos Szeredi
2208cc080e9eSMiklos Szeredi if (!fud)
2209dd3bb14fSMiklos Szeredi return -EPERM;
2210dd3bb14fSMiklos Szeredi
2211fcb14cb1SAl Viro if (!user_backed_iter(from))
2212fbdbaccaSAl Viro return -EINVAL;
2213dd3bb14fSMiklos Szeredi
2214dc00809aSMiklos Szeredi fuse_copy_init(&cs, 0, from);
2215fbdbaccaSAl Viro
2216c3696046SMiklos Szeredi return fuse_dev_do_write(fud, &cs, iov_iter_count(from));
2217dd3bb14fSMiklos Szeredi }
2218dd3bb14fSMiklos Szeredi
fuse_dev_splice_write(struct pipe_inode_info * pipe,struct file * out,loff_t * ppos,size_t len,unsigned int flags)2219dd3bb14fSMiklos Szeredi static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
2220dd3bb14fSMiklos Szeredi struct file *out, loff_t *ppos,
2221dd3bb14fSMiklos Szeredi size_t len, unsigned int flags)
2222dd3bb14fSMiklos Szeredi {
2223ebb0f38bSLinus Torvalds unsigned int head, tail, count;
2224dd3bb14fSMiklos Szeredi unsigned nbuf;
2225dd3bb14fSMiklos Szeredi unsigned idx;
2226dd3bb14fSMiklos Szeredi struct pipe_buffer *bufs;
2227dd3bb14fSMiklos Szeredi struct fuse_copy_state cs;
2228cc080e9eSMiklos Szeredi struct fuse_dev *fud;
2229dd3bb14fSMiklos Szeredi size_t rem;
2230dd3bb14fSMiklos Szeredi ssize_t ret;
2231dd3bb14fSMiklos Szeredi
2232cc080e9eSMiklos Szeredi fud = fuse_get_dev(out);
2233cc080e9eSMiklos Szeredi if (!fud)
2234dd3bb14fSMiklos Szeredi return -EPERM;
2235dd3bb14fSMiklos Szeredi
2236a2477b0eSAndrey Ryabinin pipe_lock(pipe);
2237a2477b0eSAndrey Ryabinin
22388cefc107SDavid Howells head = pipe->head;
22398cefc107SDavid Howells tail = pipe->tail;
2240ebb0f38bSLinus Torvalds count = pipe_occupancy(head, tail);
22418cefc107SDavid Howells
22428cefc107SDavid Howells bufs = kvmalloc_array(count, sizeof(struct pipe_buffer), GFP_KERNEL);
2243a2477b0eSAndrey Ryabinin if (!bufs) {
2244a2477b0eSAndrey Ryabinin pipe_unlock(pipe);
2245dd3bb14fSMiklos Szeredi return -ENOMEM;
2246a2477b0eSAndrey Ryabinin }
2247dd3bb14fSMiklos Szeredi
2248dd3bb14fSMiklos Szeredi nbuf = 0;
2249dd3bb14fSMiklos Szeredi rem = 0;
2250ebb0f38bSLinus Torvalds for (idx = tail; !pipe_empty(head, idx) && rem < len; idx++)
2251ebb0f38bSLinus Torvalds rem += pipe_buf(pipe, idx)->len;
2252dd3bb14fSMiklos Szeredi
2253dd3bb14fSMiklos Szeredi ret = -EINVAL;
225415fab63eSMatthew Wilcox if (rem < len)
225515fab63eSMatthew Wilcox goto out_free;
2256dd3bb14fSMiklos Szeredi
2257dd3bb14fSMiklos Szeredi rem = len;
2258dd3bb14fSMiklos Szeredi while (rem) {
2259dd3bb14fSMiklos Szeredi struct pipe_buffer *ibuf;
2260dd3bb14fSMiklos Szeredi struct pipe_buffer *obuf;
2261dd3bb14fSMiklos Szeredi
2262ebb0f38bSLinus Torvalds if (WARN_ON(nbuf >= count || pipe_empty(head, tail)))
22630e9fb6f1SVasily Averin goto out_free;
22640e9fb6f1SVasily Averin
2265ebb0f38bSLinus Torvalds ibuf = pipe_buf(pipe, tail);
2266dd3bb14fSMiklos Szeredi obuf = &bufs[nbuf];
2267dd3bb14fSMiklos Szeredi
2268dd3bb14fSMiklos Szeredi if (rem >= ibuf->len) {
2269dd3bb14fSMiklos Szeredi *obuf = *ibuf;
2270dd3bb14fSMiklos Szeredi ibuf->ops = NULL;
22718cefc107SDavid Howells tail++;
22728cefc107SDavid Howells pipe->tail = tail;
2273dd3bb14fSMiklos Szeredi } else {
227415fab63eSMatthew Wilcox if (!pipe_buf_get(pipe, ibuf))
227515fab63eSMatthew Wilcox goto out_free;
227615fab63eSMatthew Wilcox
2277dd3bb14fSMiklos Szeredi *obuf = *ibuf;
2278dd3bb14fSMiklos Szeredi obuf->flags &= ~PIPE_BUF_FLAG_GIFT;
2279dd3bb14fSMiklos Szeredi obuf->len = rem;
2280dd3bb14fSMiklos Szeredi ibuf->offset += obuf->len;
2281dd3bb14fSMiklos Szeredi ibuf->len -= obuf->len;
2282dd3bb14fSMiklos Szeredi }
2283dd3bb14fSMiklos Szeredi nbuf++;
2284dd3bb14fSMiklos Szeredi rem -= obuf->len;
2285dd3bb14fSMiklos Szeredi }
2286dd3bb14fSMiklos Szeredi pipe_unlock(pipe);
2287dd3bb14fSMiklos Szeredi
2288dc00809aSMiklos Szeredi fuse_copy_init(&cs, 0, NULL);
2289dd3bb14fSMiklos Szeredi cs.pipebufs = bufs;
22906c09e94aSAl Viro cs.nr_segs = nbuf;
2291dd3bb14fSMiklos Szeredi cs.pipe = pipe;
2292dd3bb14fSMiklos Szeredi
2293ce534fb0SMiklos Szeredi if (flags & SPLICE_F_MOVE)
2294ce534fb0SMiklos Szeredi cs.move_pages = 1;
2295ce534fb0SMiklos Szeredi
2296c3696046SMiklos Szeredi ret = fuse_dev_do_write(fud, &cs, len);
2297dd3bb14fSMiklos Szeredi
22989509941eSJann Horn pipe_lock(pipe);
229915fab63eSMatthew Wilcox out_free:
2300712a9510SMiklos Szeredi for (idx = 0; idx < nbuf; idx++) {
2301712a9510SMiklos Szeredi struct pipe_buffer *buf = &bufs[idx];
2302712a9510SMiklos Szeredi
2303712a9510SMiklos Szeredi if (buf->ops)
2304712a9510SMiklos Szeredi pipe_buf_release(pipe, buf);
2305712a9510SMiklos Szeredi }
23069509941eSJann Horn pipe_unlock(pipe);
2307a779638cSMiklos Szeredi
2308d6d931adSAndrey Ryabinin kvfree(bufs);
2309dd3bb14fSMiklos Szeredi return ret;
2310dd3bb14fSMiklos Szeredi }
2311dd3bb14fSMiklos Szeredi
fuse_dev_poll(struct file * file,poll_table * wait)2312076ccb76SAl Viro static __poll_t fuse_dev_poll(struct file *file, poll_table *wait)
2313334f485dSMiklos Szeredi {
2314a9a08845SLinus Torvalds __poll_t mask = EPOLLOUT | EPOLLWRNORM;
2315f88996a9SMiklos Szeredi struct fuse_iqueue *fiq;
2316cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(file);
2317cc080e9eSMiklos Szeredi
2318cc080e9eSMiklos Szeredi if (!fud)
2319a9a08845SLinus Torvalds return EPOLLERR;
2320334f485dSMiklos Szeredi
2321cc080e9eSMiklos Szeredi fiq = &fud->fc->iq;
2322f88996a9SMiklos Szeredi poll_wait(file, &fiq->waitq, wait);
2323334f485dSMiklos Szeredi
232476e43c8cSEric Biggers spin_lock(&fiq->lock);
2325e16714d8SMiklos Szeredi if (!fiq->connected)
2326a9a08845SLinus Torvalds mask = EPOLLERR;
2327f88996a9SMiklos Szeredi else if (request_pending(fiq))
2328a9a08845SLinus Torvalds mask |= EPOLLIN | EPOLLRDNORM;
232976e43c8cSEric Biggers spin_unlock(&fiq->lock);
2330334f485dSMiklos Szeredi
2331334f485dSMiklos Szeredi return mask;
2332334f485dSMiklos Szeredi }
2333334f485dSMiklos Szeredi
233434061750SKirill Tkhai /* Abort all requests on the given list (pending or processing) */
fuse_dev_end_requests(struct list_head * head)233592270d07SBernd Schubert void fuse_dev_end_requests(struct list_head *head)
2336334f485dSMiklos Szeredi {
2337334f485dSMiklos Szeredi while (!list_empty(head)) {
2338334f485dSMiklos Szeredi struct fuse_req *req;
2339334f485dSMiklos Szeredi req = list_entry(head->next, struct fuse_req, list);
2340334f485dSMiklos Szeredi req->out.h.error = -ECONNABORTED;
234133e14b4dSMiklos Szeredi clear_bit(FR_SENT, &req->flags);
2342f377cb79SMiklos Szeredi list_del_init(&req->list);
23438f622e94SMax Reitz fuse_request_end(req);
2344334f485dSMiklos Szeredi }
2345334f485dSMiklos Szeredi }
2346334f485dSMiklos Szeredi
end_polls(struct fuse_conn * fc)2347357ccf2bSBryan Green static void end_polls(struct fuse_conn *fc)
2348357ccf2bSBryan Green {
2349357ccf2bSBryan Green struct rb_node *p;
2350357ccf2bSBryan Green
2351357ccf2bSBryan Green p = rb_first(&fc->polled_files);
2352357ccf2bSBryan Green
2353357ccf2bSBryan Green while (p) {
2354357ccf2bSBryan Green struct fuse_file *ff;
2355357ccf2bSBryan Green ff = rb_entry(p, struct fuse_file, polled_node);
2356357ccf2bSBryan Green wake_up_interruptible_all(&ff->poll_wait);
2357357ccf2bSBryan Green
2358357ccf2bSBryan Green p = rb_next(p);
2359357ccf2bSBryan Green }
2360357ccf2bSBryan Green }
2361357ccf2bSBryan Green
236269a53bf2SMiklos Szeredi /*
236369a53bf2SMiklos Szeredi * Abort all requests.
236469a53bf2SMiklos Szeredi *
2365b716d425SMiklos Szeredi * Emergency exit in case of a malicious or accidental deadlock, or just a hung
2366b716d425SMiklos Szeredi * filesystem.
236769a53bf2SMiklos Szeredi *
2368b716d425SMiklos Szeredi * The same effect is usually achievable through killing the filesystem daemon
2369b716d425SMiklos Szeredi * and all users of the filesystem. The exception is the combination of an
2370b716d425SMiklos Szeredi * asynchronous request and the tricky deadlock (see
237172ef5e52SMauro Carvalho Chehab * Documentation/filesystems/fuse.rst).
237269a53bf2SMiklos Szeredi *
2373b716d425SMiklos Szeredi * Aborting requests under I/O goes as follows: 1: Separate out unlocked
2374b716d425SMiklos Szeredi * requests, they should be finished off immediately. Locked requests will be
2375b716d425SMiklos Szeredi * finished after unlock; see unlock_request(). 2: Finish off the unlocked
2376b716d425SMiklos Szeredi * requests. It is possible that some request will finish before we can. This
2377b716d425SMiklos Szeredi * is OK, the request will in that case be removed from the list before we touch
2378b716d425SMiklos Szeredi * it.
237969a53bf2SMiklos Szeredi */
fuse_abort_conn(struct fuse_conn * fc)2380eb98e3bdSMiklos Szeredi void fuse_abort_conn(struct fuse_conn *fc)
238169a53bf2SMiklos Szeredi {
2382f88996a9SMiklos Szeredi struct fuse_iqueue *fiq = &fc->iq;
2383f88996a9SMiklos Szeredi
2384d7133114SMiklos Szeredi spin_lock(&fc->lock);
238569a53bf2SMiklos Szeredi if (fc->connected) {
2386c3696046SMiklos Szeredi struct fuse_dev *fud;
2387b716d425SMiklos Szeredi struct fuse_req *req, *next;
238875f3ee4cSMiklos Szeredi LIST_HEAD(to_end);
2389be2ff42cSKirill Tkhai unsigned int i;
2390b716d425SMiklos Szeredi
23910f6439f6SJoanne Koong if (fc->timeout.req_timeout)
23920f6439f6SJoanne Koong cancel_delayed_work(&fc->timeout.work);
23930f6439f6SJoanne Koong
239463825b4eSKirill Tkhai /* Background queuing checks fc->connected under bg_lock */
239563825b4eSKirill Tkhai spin_lock(&fc->bg_lock);
239669a53bf2SMiklos Szeredi fc->connected = 0;
239763825b4eSKirill Tkhai spin_unlock(&fc->bg_lock);
239863825b4eSKirill Tkhai
23999759bd51SMiklos Szeredi fuse_set_initialized(fc);
2400c3696046SMiklos Szeredi list_for_each_entry(fud, &fc->devices, entry) {
2401c3696046SMiklos Szeredi struct fuse_pqueue *fpq = &fud->pq;
2402c3696046SMiklos Szeredi
240345a91cb1SMiklos Szeredi spin_lock(&fpq->lock);
2404e96edd94SMiklos Szeredi fpq->connected = 0;
24053a2b5b9cSMiklos Szeredi list_for_each_entry_safe(req, next, &fpq->io, list) {
2406b716d425SMiklos Szeredi req->out.h.error = -ECONNABORTED;
2407b716d425SMiklos Szeredi spin_lock(&req->waitq.lock);
2408b716d425SMiklos Szeredi set_bit(FR_ABORTED, &req->flags);
240977cd9d48SMiklos Szeredi if (!test_bit(FR_LOCKED, &req->flags)) {
241077cd9d48SMiklos Szeredi set_bit(FR_PRIVATE, &req->flags);
241187114373SMiklos Szeredi __fuse_get_request(req);
241275f3ee4cSMiklos Szeredi list_move(&req->list, &to_end);
241377cd9d48SMiklos Szeredi }
2414b716d425SMiklos Szeredi spin_unlock(&req->waitq.lock);
2415b716d425SMiklos Szeredi }
2416be2ff42cSKirill Tkhai for (i = 0; i < FUSE_PQ_HASH_SIZE; i++)
2417be2ff42cSKirill Tkhai list_splice_tail_init(&fpq->processing[i],
2418be2ff42cSKirill Tkhai &to_end);
241945a91cb1SMiklos Szeredi spin_unlock(&fpq->lock);
2420c3696046SMiklos Szeredi }
2421ae2dffa3SKirill Tkhai spin_lock(&fc->bg_lock);
2422ae2dffa3SKirill Tkhai fc->blocked = 0;
242341f98274SMiklos Szeredi fc->max_background = UINT_MAX;
242441f98274SMiklos Szeredi flush_bg_queue(fc);
2425ae2dffa3SKirill Tkhai spin_unlock(&fc->bg_lock);
24268c91189aSMiklos Szeredi
242776e43c8cSEric Biggers spin_lock(&fiq->lock);
24288c91189aSMiklos Szeredi fiq->connected = 0;
242975f3ee4cSMiklos Szeredi list_for_each_entry(req, &fiq->pending, list)
2430a8a86d78STahsin Erdogan clear_bit(FR_PENDING, &req->flags);
243175f3ee4cSMiklos Szeredi list_splice_tail_init(&fiq->pending, &to_end);
24328c91189aSMiklos Szeredi while (forget_pending(fiq))
24334388c5aaSVivek Goyal kfree(fuse_dequeue_forget(fiq, 1, NULL));
243476e43c8cSEric Biggers wake_up_all(&fiq->waitq);
243576e43c8cSEric Biggers spin_unlock(&fiq->lock);
24368c91189aSMiklos Szeredi kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
2437ee314a87SMiklos Szeredi end_polls(fc);
2438ee314a87SMiklos Szeredi wake_up_all(&fc->blocked_waitq);
2439ee314a87SMiklos Szeredi spin_unlock(&fc->lock);
24408c91189aSMiklos Szeredi
244192270d07SBernd Schubert fuse_dev_end_requests(&to_end);
24424a9bfb9bSBernd Schubert
24434a9bfb9bSBernd Schubert /*
24444a9bfb9bSBernd Schubert * fc->lock must not be taken to avoid conflicts with io-uring
24454a9bfb9bSBernd Schubert * locks
24464a9bfb9bSBernd Schubert */
24474a9bfb9bSBernd Schubert fuse_uring_abort(fc);
2448ee314a87SMiklos Szeredi } else {
2449d7133114SMiklos Szeredi spin_unlock(&fc->lock);
245069a53bf2SMiklos Szeredi }
2451ee314a87SMiklos Szeredi }
245208cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_abort_conn);
245369a53bf2SMiklos Szeredi
fuse_wait_aborted(struct fuse_conn * fc)2454b8f95e5dSMiklos Szeredi void fuse_wait_aborted(struct fuse_conn *fc)
2455b8f95e5dSMiklos Szeredi {
24562d84a2d1SMiklos Szeredi /* matches implicit memory barrier in fuse_drop_waiting() */
24572d84a2d1SMiklos Szeredi smp_mb();
2458b8f95e5dSMiklos Szeredi wait_event(fc->blocked_waitq, atomic_read(&fc->num_waiting) == 0);
24594a9bfb9bSBernd Schubert
24604a9bfb9bSBernd Schubert fuse_uring_wait_stopped_queues(fc);
2461b8f95e5dSMiklos Szeredi }
2462b8f95e5dSMiklos Szeredi
fuse_dev_release(struct inode * inode,struct file * file)246308cbf542STejun Heo int fuse_dev_release(struct inode *inode, struct file *file)
2464334f485dSMiklos Szeredi {
2465cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(file);
2466cc080e9eSMiklos Szeredi
2467cc080e9eSMiklos Szeredi if (fud) {
2468cc080e9eSMiklos Szeredi struct fuse_conn *fc = fud->fc;
2469c3696046SMiklos Szeredi struct fuse_pqueue *fpq = &fud->pq;
247045ff350bSMiklos Szeredi LIST_HEAD(to_end);
2471be2ff42cSKirill Tkhai unsigned int i;
2472cc080e9eSMiklos Szeredi
247345ff350bSMiklos Szeredi spin_lock(&fpq->lock);
2474c3696046SMiklos Szeredi WARN_ON(!list_empty(&fpq->io));
2475be2ff42cSKirill Tkhai for (i = 0; i < FUSE_PQ_HASH_SIZE; i++)
2476be2ff42cSKirill Tkhai list_splice_init(&fpq->processing[i], &to_end);
247745ff350bSMiklos Szeredi spin_unlock(&fpq->lock);
247845ff350bSMiklos Szeredi
247992270d07SBernd Schubert fuse_dev_end_requests(&to_end);
248045ff350bSMiklos Szeredi
2481c3696046SMiklos Szeredi /* Are we the last open device? */
2482c3696046SMiklos Szeredi if (atomic_dec_and_test(&fc->dev_count)) {
2483f88996a9SMiklos Szeredi WARN_ON(fc->iq.fasync != NULL);
2484eb98e3bdSMiklos Szeredi fuse_abort_conn(fc);
2485c3696046SMiklos Szeredi }
2486cc080e9eSMiklos Szeredi fuse_dev_free(fud);
2487385a17bfSJeff Dike }
2488334f485dSMiklos Szeredi return 0;
2489334f485dSMiklos Szeredi }
249008cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_dev_release);
2491334f485dSMiklos Szeredi
fuse_dev_fasync(int fd,struct file * file,int on)2492385a17bfSJeff Dike static int fuse_dev_fasync(int fd, struct file *file, int on)
2493385a17bfSJeff Dike {
2494cc080e9eSMiklos Szeredi struct fuse_dev *fud = fuse_get_dev(file);
2495cc080e9eSMiklos Szeredi
2496cc080e9eSMiklos Szeredi if (!fud)
2497a87046d8SMiklos Szeredi return -EPERM;
2498385a17bfSJeff Dike
2499385a17bfSJeff Dike /* No locking - fasync_helper does its own locking */
2500cc080e9eSMiklos Szeredi return fasync_helper(fd, file, on, &fud->fc->iq.fasync);
2501385a17bfSJeff Dike }
2502385a17bfSJeff Dike
fuse_device_clone(struct fuse_conn * fc,struct file * new)250300c570f4SMiklos Szeredi static int fuse_device_clone(struct fuse_conn *fc, struct file *new)
250400c570f4SMiklos Szeredi {
2505cc080e9eSMiklos Szeredi struct fuse_dev *fud;
2506cc080e9eSMiklos Szeredi
250700c570f4SMiklos Szeredi if (new->private_data)
250800c570f4SMiklos Szeredi return -EINVAL;
250900c570f4SMiklos Szeredi
25100cd1eb9aSVivek Goyal fud = fuse_dev_alloc_install(fc);
2511cc080e9eSMiklos Szeredi if (!fud)
2512cc080e9eSMiklos Szeredi return -ENOMEM;
2513cc080e9eSMiklos Szeredi
2514cc080e9eSMiklos Szeredi new->private_data = fud;
2515c3696046SMiklos Szeredi atomic_inc(&fc->dev_count);
251600c570f4SMiklos Szeredi
251700c570f4SMiklos Szeredi return 0;
251800c570f4SMiklos Szeredi }
251900c570f4SMiklos Szeredi
fuse_dev_ioctl_clone(struct file * file,__u32 __user * argp)2520aed91831SAmir Goldstein static long fuse_dev_ioctl_clone(struct file *file, __u32 __user *argp)
252100c570f4SMiklos Szeredi {
2522f8425c93SAlessio Balsini int res;
252300c570f4SMiklos Szeredi int oldfd;
2524f8425c93SAlessio Balsini struct fuse_dev *fud = NULL;
252500c570f4SMiklos Szeredi
2526aed91831SAmir Goldstein if (get_user(oldfd, argp))
25274a892c0fSAl Viro return -EFAULT;
252800c570f4SMiklos Szeredi
25298152f820SAl Viro CLASS(fd, f)(oldfd);
25308152f820SAl Viro if (fd_empty(f))
25314a892c0fSAl Viro return -EINVAL;
25324a892c0fSAl Viro
25338ed1f0e2SJann Horn /*
25348ed1f0e2SJann Horn * Check against file->f_op because CUSE
25358ed1f0e2SJann Horn * uses the same ioctl handler.
25368ed1f0e2SJann Horn */
25371da91ea8SAl Viro if (fd_file(f)->f_op == file->f_op)
25381da91ea8SAl Viro fud = fuse_get_dev(fd_file(f));
253900c570f4SMiklos Szeredi
25404a892c0fSAl Viro res = -EINVAL;
2541cc080e9eSMiklos Szeredi if (fud) {
254200c570f4SMiklos Szeredi mutex_lock(&fuse_mutex);
2543f8425c93SAlessio Balsini res = fuse_device_clone(fud->fc, file);
254400c570f4SMiklos Szeredi mutex_unlock(&fuse_mutex);
254500c570f4SMiklos Szeredi }
2546aed91831SAmir Goldstein
2547f8425c93SAlessio Balsini return res;
254800c570f4SMiklos Szeredi }
254900c570f4SMiklos Szeredi
fuse_dev_ioctl_backing_open(struct file * file,struct fuse_backing_map __user * argp)255044350256SAmir Goldstein static long fuse_dev_ioctl_backing_open(struct file *file,
255144350256SAmir Goldstein struct fuse_backing_map __user *argp)
255244350256SAmir Goldstein {
255344350256SAmir Goldstein struct fuse_dev *fud = fuse_get_dev(file);
255444350256SAmir Goldstein struct fuse_backing_map map;
255544350256SAmir Goldstein
255644350256SAmir Goldstein if (!fud)
255744350256SAmir Goldstein return -EPERM;
255844350256SAmir Goldstein
255944350256SAmir Goldstein if (!IS_ENABLED(CONFIG_FUSE_PASSTHROUGH))
256044350256SAmir Goldstein return -EOPNOTSUPP;
256144350256SAmir Goldstein
256244350256SAmir Goldstein if (copy_from_user(&map, argp, sizeof(map)))
256344350256SAmir Goldstein return -EFAULT;
256444350256SAmir Goldstein
256544350256SAmir Goldstein return fuse_backing_open(fud->fc, &map);
256644350256SAmir Goldstein }
256744350256SAmir Goldstein
fuse_dev_ioctl_backing_close(struct file * file,__u32 __user * argp)256844350256SAmir Goldstein static long fuse_dev_ioctl_backing_close(struct file *file, __u32 __user *argp)
256944350256SAmir Goldstein {
257044350256SAmir Goldstein struct fuse_dev *fud = fuse_get_dev(file);
257144350256SAmir Goldstein int backing_id;
257244350256SAmir Goldstein
257344350256SAmir Goldstein if (!fud)
257444350256SAmir Goldstein return -EPERM;
257544350256SAmir Goldstein
257644350256SAmir Goldstein if (!IS_ENABLED(CONFIG_FUSE_PASSTHROUGH))
257744350256SAmir Goldstein return -EOPNOTSUPP;
257844350256SAmir Goldstein
257944350256SAmir Goldstein if (get_user(backing_id, argp))
258044350256SAmir Goldstein return -EFAULT;
258144350256SAmir Goldstein
258244350256SAmir Goldstein return fuse_backing_close(fud->fc, backing_id);
258344350256SAmir Goldstein }
258444350256SAmir Goldstein
fuse_dev_ioctl(struct file * file,unsigned int cmd,unsigned long arg)2585aed91831SAmir Goldstein static long fuse_dev_ioctl(struct file *file, unsigned int cmd,
2586aed91831SAmir Goldstein unsigned long arg)
2587aed91831SAmir Goldstein {
2588aed91831SAmir Goldstein void __user *argp = (void __user *)arg;
2589aed91831SAmir Goldstein
2590aed91831SAmir Goldstein switch (cmd) {
2591aed91831SAmir Goldstein case FUSE_DEV_IOC_CLONE:
2592aed91831SAmir Goldstein return fuse_dev_ioctl_clone(file, argp);
2593aed91831SAmir Goldstein
259444350256SAmir Goldstein case FUSE_DEV_IOC_BACKING_OPEN:
259544350256SAmir Goldstein return fuse_dev_ioctl_backing_open(file, argp);
259644350256SAmir Goldstein
259744350256SAmir Goldstein case FUSE_DEV_IOC_BACKING_CLOSE:
259844350256SAmir Goldstein return fuse_dev_ioctl_backing_close(file, argp);
259944350256SAmir Goldstein
2600aed91831SAmir Goldstein default:
2601aed91831SAmir Goldstein return -ENOTTY;
2602aed91831SAmir Goldstein }
2603aed91831SAmir Goldstein }
2604aed91831SAmir Goldstein
26054b6f5d20SArjan van de Ven const struct file_operations fuse_dev_operations = {
2606334f485dSMiklos Szeredi .owner = THIS_MODULE,
260794e4fe2cSTom Van Braeckel .open = fuse_dev_open,
2608fbdbaccaSAl Viro .read_iter = fuse_dev_read,
2609c3021629SMiklos Szeredi .splice_read = fuse_dev_splice_read,
2610fbdbaccaSAl Viro .write_iter = fuse_dev_write,
2611dd3bb14fSMiklos Szeredi .splice_write = fuse_dev_splice_write,
2612334f485dSMiklos Szeredi .poll = fuse_dev_poll,
2613334f485dSMiklos Szeredi .release = fuse_dev_release,
2614385a17bfSJeff Dike .fasync = fuse_dev_fasync,
261500c570f4SMiklos Szeredi .unlocked_ioctl = fuse_dev_ioctl,
26161832f2d8SArnd Bergmann .compat_ioctl = compat_ptr_ioctl,
2617786412a7SBernd Schubert #ifdef CONFIG_FUSE_IO_URING
2618786412a7SBernd Schubert .uring_cmd = fuse_uring_cmd,
2619786412a7SBernd Schubert #endif
2620334f485dSMiklos Szeredi };
262108cbf542STejun Heo EXPORT_SYMBOL_GPL(fuse_dev_operations);
2622334f485dSMiklos Szeredi
2623334f485dSMiklos Szeredi static struct miscdevice fuse_miscdevice = {
2624334f485dSMiklos Szeredi .minor = FUSE_MINOR,
2625334f485dSMiklos Szeredi .name = "fuse",
2626334f485dSMiklos Szeredi .fops = &fuse_dev_operations,
2627334f485dSMiklos Szeredi };
2628334f485dSMiklos Szeredi
fuse_dev_init(void)2629334f485dSMiklos Szeredi int __init fuse_dev_init(void)
2630334f485dSMiklos Szeredi {
2631334f485dSMiklos Szeredi int err = -ENOMEM;
2632334f485dSMiklos Szeredi fuse_req_cachep = kmem_cache_create("fuse_request",
2633334f485dSMiklos Szeredi sizeof(struct fuse_req),
263420c2df83SPaul Mundt 0, 0, NULL);
2635334f485dSMiklos Szeredi if (!fuse_req_cachep)
2636334f485dSMiklos Szeredi goto out;
2637334f485dSMiklos Szeredi
2638334f485dSMiklos Szeredi err = misc_register(&fuse_miscdevice);
2639334f485dSMiklos Szeredi if (err)
2640334f485dSMiklos Szeredi goto out_cache_clean;
2641334f485dSMiklos Szeredi
2642334f485dSMiklos Szeredi return 0;
2643334f485dSMiklos Szeredi
2644334f485dSMiklos Szeredi out_cache_clean:
2645334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep);
2646334f485dSMiklos Szeredi out:
2647334f485dSMiklos Szeredi return err;
2648334f485dSMiklos Szeredi }
2649334f485dSMiklos Szeredi
fuse_dev_cleanup(void)2650334f485dSMiklos Szeredi void fuse_dev_cleanup(void)
2651334f485dSMiklos Szeredi {
2652334f485dSMiklos Szeredi misc_deregister(&fuse_miscdevice);
2653334f485dSMiklos Szeredi kmem_cache_destroy(fuse_req_cachep);
2654334f485dSMiklos Szeredi }
2655