1f1434857SMiklos Szeredi // SPDX-License-Identifier: GPL-2.0-only 2f1434857SMiklos Szeredi 3f1434857SMiklos Szeredi #include "dev.h" 4f1434857SMiklos Szeredi #include "sysctl.h" 5f1434857SMiklos Szeredi #include "fuse_dev_i.h" 6f1434857SMiklos Szeredi #include "dev_uring_i.h" 7f1434857SMiklos Szeredi 8f1434857SMiklos Szeredi /* Frequency (in seconds) of request timeout checks, if opted into */ 9f1434857SMiklos Szeredi #define FUSE_TIMEOUT_TIMER_FREQ 15 10f1434857SMiklos Szeredi 11f1434857SMiklos Szeredi /* Frequency (in jiffies) of request timeout checks, if opted into */ 12f1434857SMiklos Szeredi static const unsigned long fuse_timeout_timer_freq = 13f1434857SMiklos Szeredi secs_to_jiffies(FUSE_TIMEOUT_TIMER_FREQ); 14f1434857SMiklos Szeredi 15f1434857SMiklos Szeredi /* 16f1434857SMiklos Szeredi * Default timeout (in seconds) for the server to reply to a request 17f1434857SMiklos Szeredi * before the connection is aborted, if no timeout was specified on mount. 18f1434857SMiklos Szeredi * 19f1434857SMiklos Szeredi * Exported via sysctl 20f1434857SMiklos Szeredi */ 21f1434857SMiklos Szeredi unsigned int fuse_default_req_timeout; 22f1434857SMiklos Szeredi 23f1434857SMiklos Szeredi /* 24f1434857SMiklos Szeredi * Max timeout (in seconds) for the server to reply to a request before 25f1434857SMiklos Szeredi * the connection is aborted. 26f1434857SMiklos Szeredi * 27f1434857SMiklos Szeredi * Exported via sysctl 28f1434857SMiklos Szeredi */ 29f1434857SMiklos Szeredi unsigned int fuse_max_req_timeout; 30f1434857SMiklos Szeredi 3156b4332eSMiklos Szeredi bool fuse_request_expired(struct fuse_chan *fch, struct list_head *list) 32f1434857SMiklos Szeredi { 33f1434857SMiklos Szeredi struct fuse_req *req; 34f1434857SMiklos Szeredi 35f1434857SMiklos Szeredi req = list_first_entry_or_null(list, struct fuse_req, list); 36f1434857SMiklos Szeredi if (!req) 37f1434857SMiklos Szeredi return false; 3856b4332eSMiklos Szeredi return time_is_before_jiffies(req->create_time + fch->timeout.req_timeout); 39f1434857SMiklos Szeredi } 40f1434857SMiklos Szeredi 4156b4332eSMiklos Szeredi static bool fuse_fpq_processing_expired(struct fuse_chan *fch, struct list_head *processing) 42f1434857SMiklos Szeredi { 43f1434857SMiklos Szeredi int i; 44f1434857SMiklos Szeredi 45f1434857SMiklos Szeredi for (i = 0; i < FUSE_PQ_HASH_SIZE; i++) 4656b4332eSMiklos Szeredi if (fuse_request_expired(fch, &processing[i])) 47f1434857SMiklos Szeredi return true; 48f1434857SMiklos Szeredi 49f1434857SMiklos Szeredi return false; 50f1434857SMiklos Szeredi } 51f1434857SMiklos Szeredi 52f1434857SMiklos Szeredi /* 53f1434857SMiklos Szeredi * Check if any requests aren't being completed by the time the request timeout 54f1434857SMiklos Szeredi * elapses. To do so, we: 55f1434857SMiklos Szeredi * - check the fiq pending list 56f1434857SMiklos Szeredi * - check the bg queue 57f1434857SMiklos Szeredi * - check the fpq io and processing lists 58f1434857SMiklos Szeredi * 59f1434857SMiklos Szeredi * To make this fast, we only check against the head request on each list since 60f1434857SMiklos Szeredi * these are generally queued in order of creation time (eg newer requests get 61f1434857SMiklos Szeredi * queued to the tail). We might miss a few edge cases (eg requests transitioning 62f1434857SMiklos Szeredi * between lists, re-sent requests at the head of the pending list having a 63f1434857SMiklos Szeredi * later creation time than other requests on that list, etc.) but that is fine 64f1434857SMiklos Szeredi * since if the request never gets fulfilled, it will eventually be caught. 65f1434857SMiklos Szeredi */ 66f1434857SMiklos Szeredi static void fuse_check_timeout(struct work_struct *work) 67f1434857SMiklos Szeredi { 68f1434857SMiklos Szeredi struct delayed_work *dwork = to_delayed_work(work); 6956b4332eSMiklos Szeredi struct fuse_chan *fch = container_of(dwork, struct fuse_chan, timeout.work); 7056b4332eSMiklos Szeredi struct fuse_iqueue *fiq = &fch->iq; 71f1434857SMiklos Szeredi struct fuse_dev *fud; 72f1434857SMiklos Szeredi struct fuse_pqueue *fpq; 73f1434857SMiklos Szeredi bool expired = false; 74f1434857SMiklos Szeredi 7556b4332eSMiklos Szeredi if (!atomic_read(&fch->num_waiting)) 76f1434857SMiklos Szeredi goto out; 77f1434857SMiklos Szeredi 78f1434857SMiklos Szeredi spin_lock(&fiq->lock); 7956b4332eSMiklos Szeredi expired = fuse_request_expired(fch, &fiq->pending); 80f1434857SMiklos Szeredi spin_unlock(&fiq->lock); 81f1434857SMiklos Szeredi if (expired) 82*4eeb5e6cSMiklos Szeredi goto chan_abort; 83f1434857SMiklos Szeredi 8456b4332eSMiklos Szeredi spin_lock(&fch->bg_lock); 8556b4332eSMiklos Szeredi expired = fuse_request_expired(fch, &fch->bg_queue); 8656b4332eSMiklos Szeredi spin_unlock(&fch->bg_lock); 87f1434857SMiklos Szeredi if (expired) 88*4eeb5e6cSMiklos Szeredi goto chan_abort; 89f1434857SMiklos Szeredi 9056b4332eSMiklos Szeredi spin_lock(&fch->lock); 9156b4332eSMiklos Szeredi if (!fch->connected) { 9256b4332eSMiklos Szeredi spin_unlock(&fch->lock); 93f1434857SMiklos Szeredi return; 94f1434857SMiklos Szeredi } 9556b4332eSMiklos Szeredi list_for_each_entry(fud, &fch->devices, entry) { 96f1434857SMiklos Szeredi fpq = &fud->pq; 97f1434857SMiklos Szeredi spin_lock(&fpq->lock); 9856b4332eSMiklos Szeredi if (fuse_request_expired(fch, &fpq->io) || 9956b4332eSMiklos Szeredi fuse_fpq_processing_expired(fch, fpq->processing)) { 100f1434857SMiklos Szeredi spin_unlock(&fpq->lock); 10156b4332eSMiklos Szeredi spin_unlock(&fch->lock); 102*4eeb5e6cSMiklos Szeredi goto chan_abort; 103f1434857SMiklos Szeredi } 104f1434857SMiklos Szeredi 105f1434857SMiklos Szeredi spin_unlock(&fpq->lock); 106f1434857SMiklos Szeredi } 10756b4332eSMiklos Szeredi spin_unlock(&fch->lock); 108f1434857SMiklos Szeredi 10956b4332eSMiklos Szeredi if (fuse_uring_request_expired(fch)) 110*4eeb5e6cSMiklos Szeredi goto chan_abort; 111f1434857SMiklos Szeredi 112f1434857SMiklos Szeredi out: 11356b4332eSMiklos Szeredi queue_delayed_work(system_percpu_wq, &fch->timeout.work, 114f1434857SMiklos Szeredi fuse_timeout_timer_freq); 115f1434857SMiklos Szeredi return; 116f1434857SMiklos Szeredi 117*4eeb5e6cSMiklos Szeredi chan_abort: 118*4eeb5e6cSMiklos Szeredi fuse_chan_abort(fch, false); 119f1434857SMiklos Szeredi } 120f1434857SMiklos Szeredi 12156b4332eSMiklos Szeredi static void set_request_timeout(struct fuse_chan *fch, unsigned int timeout) 122f1434857SMiklos Szeredi { 12356b4332eSMiklos Szeredi fch->timeout.req_timeout = secs_to_jiffies(timeout); 12456b4332eSMiklos Szeredi INIT_DELAYED_WORK(&fch->timeout.work, fuse_check_timeout); 12556b4332eSMiklos Szeredi queue_delayed_work(system_percpu_wq, &fch->timeout.work, 126f1434857SMiklos Szeredi fuse_timeout_timer_freq); 127f1434857SMiklos Szeredi } 128f1434857SMiklos Szeredi 12956b4332eSMiklos Szeredi void fuse_init_server_timeout(struct fuse_chan *fch, unsigned int timeout) 130f1434857SMiklos Szeredi { 131f1434857SMiklos Szeredi if (!timeout && !fuse_max_req_timeout && !fuse_default_req_timeout) 132f1434857SMiklos Szeredi return; 133f1434857SMiklos Szeredi 134f1434857SMiklos Szeredi if (!timeout) 135f1434857SMiklos Szeredi timeout = fuse_default_req_timeout; 136f1434857SMiklos Szeredi 137f1434857SMiklos Szeredi if (fuse_max_req_timeout) { 138f1434857SMiklos Szeredi if (timeout) 139f1434857SMiklos Szeredi timeout = min(fuse_max_req_timeout, timeout); 140f1434857SMiklos Szeredi else 141f1434857SMiklos Szeredi timeout = fuse_max_req_timeout; 142f1434857SMiklos Szeredi } 143f1434857SMiklos Szeredi 144f1434857SMiklos Szeredi timeout = max(FUSE_TIMEOUT_TIMER_FREQ, timeout); 145f1434857SMiklos Szeredi 14656b4332eSMiklos Szeredi set_request_timeout(fch, timeout); 147f1434857SMiklos Szeredi } 148f1434857SMiklos Szeredi 149