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