From nobody Fri Apr 3 11:10:27 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2770B2727FC; Mon, 23 Feb 2026 17:10:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771866619; cv=none; b=Qom+Hk4hkmFWSkttM4PAYmzC5ARklCpJF8EqGzG7SxRTgyxg1shACNqZzBLfJLat8743ycf6tDHITTYifwEuXQ9dH1e9U/Qskll+gA/g200+61MNM0v43YZBK1pahkqhe3x3G8fzBt/AtZuoaVi3Q0EPhYQLehQQjAwQwVaaPtw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771866619; c=relaxed/simple; bh=HgXUYRIJ3uMhjEi7JEY7sJBsQZ1d46lcqUMgcKlCt4U=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XocHaEPspAdD/WmX/FwYIWNQCVJiBpSW4F22O+uO1CwE7O5vt+fz+2gPV3pauiwbPvPpRQcj1GGnfDfnhaFxyZrycbLBARdWdRp+Ue9nGQxCBBdlypTdJQPERKMVKpbtxpV27hs3x83PRH5FGj3m+VuFbzc7fYAt9BfAC8yfDvk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iotOkam2; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="iotOkam2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ADB4DC19421; Mon, 23 Feb 2026 17:10:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771866618; bh=HgXUYRIJ3uMhjEi7JEY7sJBsQZ1d46lcqUMgcKlCt4U=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=iotOkam2ISt+FodG5GU2DJaX22tW5sTIIa45v1M36nCWqVQzJrMbGovaotFvuMKYr xUAIsFOg+sBDyXaAE6wF1dQ7nDpLZZvmAD7r9Gd9Bi7igavVeWo/XhgczlAh22wdPw yGNW508nnGIW3pTECNGp6A3lRUXOSAVNvNNETLeNlqT3fkqG/NEIXodWiJnp4g7+JE rwGyooTdJLZKB1TWhABNKXaIrltaN8YOTjW4h2qiSVI9vB3JMdQ6KaPNzYDYKRP9Fe xqP1Ostmm4M5JK6llKCyra7r22UMc4UHHRenS1b1UJKIV9yRrszq2wPbVeQuLBc7m3 YthtUY4vx1Fqw== From: Jeff Layton Date: Mon, 23 Feb 2026 12:09:58 -0500 Subject: [PATCH v2 1/4] sunrpc: fix cache_request leak in cache_release Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260223-sunrpc-cache-v2-1-91fc827c4d33@kernel.org> References: <20260223-sunrpc-cache-v2-0-91fc827c4d33@kernel.org> In-Reply-To: <20260223-sunrpc-cache-v2-0-91fc827c4d33@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , Trond Myklebust , Anna Schumaker Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton , NeilBrown X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=2648; i=jlayton@kernel.org; h=from:subject:message-id; bh=HgXUYRIJ3uMhjEi7JEY7sJBsQZ1d46lcqUMgcKlCt4U=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpnIn3YtioMuJ6isoY+vhVzeS4I7a0QwN9K1spA 79epzNIpSaJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaZyJ9wAKCRAADmhBGVaC FXgsD/9O3UtxRjNSCMdntB2K5fWq+vl4BX7xOJQRXf0GETa9GTchwJZ7ExEuMym98/QWbNdDoAw SIlKIexuBGY/7vM0UqrcKoWMr62NFZIqMZwbWSOEM3APIDwz0aU8n7iUjYPqKataOvgVAKscXqy Y7PAO+s/ajyjbLMU12b6LZm3S6o5s1Y43cOefS8uAAOLoS4IK2krrsGD2b8EOpnKkRKMXwrFV8Z XETJxoaPn787Gck8elWQPQb6zDQTiW5Y+4COyfSS3ytK0h1GN6twpjnaEc1vTsaxExqve8/yG4W N80BVRZ3o+52ooX04HYiV0s2CqF3+9OrKZgwRJRsfBX62EaS4v2uy1VEc/XnODHtzvXhI9ILw/Q nRSKbrR9wPZRLY8VaxA8QVIW3pVHIoA1KH54e1Sz4xBrYq7GhtZlLtoHgbohp+cT3gRHEwVIa2D GD3SJzUPxy8x4P764vX1B0e2lnfvpVD/wREwyko5SWwTpbuf1vaAFZoGwWdOL6vKlwARdVqCTxZ 2UXCtc6u1peKsF3CFecrOakK1vNOun9ALW7KBsQxvd0y8ZitKv8N2oJ64gwGcWCIwvCw3zqkvAr BAhBl9eh5Xec/xRq5bYkVENOQxaiFWXLbASCs9Y+hL75AEudBlD4kKHIaKT21fCXrO5rFOx9jpH sRQZV+8Iexv5gWw== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 When a reader's file descriptor is closed while in the middle of reading a cache_request (rp->offset !=3D 0), cache_release() decrements the request's readers count but never checks whether it should free the request. In cache_read(), when readers drops to 0 and CACHE_PENDING is clear, the cache_request is removed from the queue and freed along with its buffer and cache_head reference. cache_release() lacks this cleanup. The only other path that frees requests with readers =3D=3D 0 is cache_dequeue(), but it runs only when CACHE_PENDING transitions from set to clear. If that transition already happened while readers was still non-zero, cache_dequeue() will have skipped the request, and no subsequent call will clean it up. Add the same cleanup logic from cache_read() to cache_release(): after decrementing readers, check if it reached 0 with CACHE_PENDING clear, and if so, dequeue and free the cache_request. Reported-by: NeilBrown Signed-off-by: Jeff Layton --- net/sunrpc/cache.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index b82f7cde0c9be6071ee4040150672872e548161d..86b3fd5a429d77f7f917f398a02= cb7a5ff8dd1e0 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1062,14 +1062,25 @@ static int cache_release(struct inode *inode, struc= t file *filp, struct cache_reader *rp =3D filp->private_data; =20 if (rp) { + struct cache_request *rq =3D NULL; + spin_lock(&queue_lock); if (rp->offset) { struct cache_queue *cq; - for (cq=3D &rp->q; &cq->list !=3D &cd->queue; - cq =3D list_entry(cq->list.next, struct cache_queue, list)) + for (cq =3D &rp->q; &cq->list !=3D &cd->queue; + cq =3D list_entry(cq->list.next, + struct cache_queue, list)) if (!cq->reader) { - container_of(cq, struct cache_request, q) - ->readers--; + struct cache_request *cr =3D + container_of(cq, + struct cache_request, q); + cr->readers--; + if (cr->readers =3D=3D 0 && + !test_bit(CACHE_PENDING, + &cr->item->flags)) { + list_del(&cr->q.list); + rq =3D cr; + } break; } rp->offset =3D 0; @@ -1077,9 +1088,14 @@ static int cache_release(struct inode *inode, struct= file *filp, list_del(&rp->q.list); spin_unlock(&queue_lock); =20 + if (rq) { + cache_put(rq->item, cd); + kfree(rq->buf); + kfree(rq); + } + filp->private_data =3D NULL; kfree(rp); - } if (filp->f_mode & FMODE_WRITE) { atomic_dec(&cd->writers); --=20 2.53.0 From nobody Fri Apr 3 11:10:27 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5CA33328B7F; Mon, 23 Feb 2026 17:10:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771866620; cv=none; b=U3qxHtkZ++lVRZDVpZD6H9kzeQy0NnqQjq8CqEq3XJHEtj2eVrl0tneAQAICHOkcjLaKN/ZzFveFSZqVb/7HLf23naJtqYlZvpo5DZOKD4q9Xtih3iM/KZTD1WG7/WRZMFLjV5VxxNQxJOMSRodIANKs8cvOLP1N2b8MiueZIOM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771866620; c=relaxed/simple; bh=33/7X3KkyPQB6+MoF02KVKFM3QLZsp57v/whKSIPst0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=p+6PgjSXjw5r8BEZOIeNUTsnrLsXVXGc6lHJ30dwowRfF/6Hi4f+kaIcyKHh+IGhIfK+ozOLBccfjYjuEaSwFl04TC9KwjuWZla+LN0Ty5oqXsuRiNMc4HIUhLOEBj8/k5iS1X0+zQswKVQ3iyrEuXVmFiS54zSHHHZxmwS8/j4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=OPwdRWdm; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="OPwdRWdm" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EBC97C2BCAF; Mon, 23 Feb 2026 17:10:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771866619; bh=33/7X3KkyPQB6+MoF02KVKFM3QLZsp57v/whKSIPst0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=OPwdRWdmHM6Y/nRVj4OygNpTkDUUbmZ4waDUHA2OVR2ErtK9AlyPbSZqioGkXDUhh TI+78SWwWNbu3NlBF5U1qKS43ySR2rfEdkCYHI/h8J7QRCyqSEaRw3JLdJpKeWS6w/ pNWT/ZBhL7dLbW+UawrYX9Tm9w90Nh5b/j5UZQ6R6QcR6Sc+wA4RSipajfiDQnUA37 MqnEazRVItnx5eUnX0GOUQQ596slmGkKXZ6cvpBBspCTvnxMlLtZZwmN/39o6mSG/x SPfFlOheJRDY+ZRhO8SMCqwR4PEPtcJo32QKciSVCjfooG61iFQqVIU5lF+cf+cAQl r4Qok67jCLoHQ== From: Jeff Layton Date: Mon, 23 Feb 2026 12:09:59 -0500 Subject: [PATCH v2 2/4] sunrpc: convert queue_lock from global spinlock to per-cache-detail lock Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260223-sunrpc-cache-v2-2-91fc827c4d33@kernel.org> References: <20260223-sunrpc-cache-v2-0-91fc827c4d33@kernel.org> In-Reply-To: <20260223-sunrpc-cache-v2-0-91fc827c4d33@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , Trond Myklebust , Anna Schumaker Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=7368; i=jlayton@kernel.org; h=from:subject:message-id; bh=33/7X3KkyPQB6+MoF02KVKFM3QLZsp57v/whKSIPst0=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpnIn33oRpa7h3/u6/pYHwD8V4gO4D3dnAv6rXK YcP1KReqfWJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaZyJ9wAKCRAADmhBGVaC FY8ZD/9b/cH/Sciv4JTaVlZsY1wejPTdT5BZoenzdsDL9h2lmRDzyb3cKLN/Rx4qLKengGJh3kQ hQ/zM50eYDPKpXer57wnxuAp2AQY0NwUWQ7FizdFni2SamJgJvAjPZiGx93rD0/EK+MXxwTGEOQ KDnfrSpzBvJ8mPDPlkMoE9ZMRr2jvLOZACfg/9I6gDiBtH5xDtmXD4mGzQlhFb7GpnoWuE13D8H 0Qt+iKs285doqN6vVfat8u5qVH+5PEgZI0uPBJ9ApSFMmqwts1+tKDl7GonoTee6NPhyHCcxy9O Y6udBjkKPmlEI6fCrKmFIiOx9l8XhbyCzkklKNE7yDnt/HjHwdrxZln3G0BWwx2Z6NNUoPQ5IDR VcLKYN42hTXV8qUscA3X8qZb4bQ5hgtysmqA/209YGRJYdr+vK79aKqZQkdFYecIvtpkpngZj5H fLQj/sECeiXBiWu0tOv45R2K0mevEAyGZjucT+yQXzhWRvK773DI43Y0sdeiFK8EzB726QjxzaK qUmMM8Jj2cdgC7MJoQN9YY4lZOP4ftb2HVQg+8rhU4Fv4va9lz3NzZlsq3wtJRlhvDSw6w3IrXu OslOZrugR7fkNUluMZmxzFwLyAgYpNYVaekDpfDopeBL8e4hd0hJqFytMtoBuQsLcRPbxdDKK3b eAybM6b1wISHWbg== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 The global queue_lock serializes all upcall queue operations across every cache_detail instance. Convert it to a per-cache-detail spinlock so that different caches (e.g. auth.unix.ip vs nfsd.fh) no longer contend with each other on queue operations. Signed-off-by: Jeff Layton --- include/linux/sunrpc/cache.h | 1 + net/sunrpc/cache.c | 47 ++++++++++++++++++++++------------------= ---- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index e783132e481ff2593fdc5d323f7b3a08f85d4cd8..3d32dd1f7b05d35562d2064fed6= 9877b3950fb51 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -113,6 +113,7 @@ struct cache_detail { =20 /* fields for communication over channel */ struct list_head queue; + spinlock_t queue_lock; =20 atomic_t writers; /* how many time is /channel open */ time64_t last_close; /* if no writers, when did last close */ diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 86b3fd5a429d77f7f917f398a02cb7a5ff8dd1e0..1cfaae488c6c67a9797511804e4= bbba16bcc70ae 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -400,6 +400,7 @@ void sunrpc_init_cache_detail(struct cache_detail *cd) { spin_lock_init(&cd->hash_lock); INIT_LIST_HEAD(&cd->queue); + spin_lock_init(&cd->queue_lock); spin_lock(&cache_list_lock); cd->nextcheck =3D 0; cd->entries =3D 0; @@ -803,8 +804,6 @@ void cache_clean_deferred(void *owner) * */ =20 -static DEFINE_SPINLOCK(queue_lock); - struct cache_queue { struct list_head list; int reader; /* if 0, then request */ @@ -847,7 +846,7 @@ static ssize_t cache_read(struct file *filp, char __use= r *buf, size_t count, inode_lock(inode); /* protect against multiple concurrent * readers on this file */ again: - spin_lock(&queue_lock); + spin_lock(&cd->queue_lock); /* need to find next request */ while (rp->q.list.next !=3D &cd->queue && list_entry(rp->q.list.next, struct cache_queue, list) @@ -856,7 +855,7 @@ static ssize_t cache_read(struct file *filp, char __use= r *buf, size_t count, list_move(&rp->q.list, next); } if (rp->q.list.next =3D=3D &cd->queue) { - spin_unlock(&queue_lock); + spin_unlock(&cd->queue_lock); inode_unlock(inode); WARN_ON_ONCE(rp->offset); return 0; @@ -865,7 +864,7 @@ static ssize_t cache_read(struct file *filp, char __use= r *buf, size_t count, WARN_ON_ONCE(rq->q.reader); if (rp->offset =3D=3D 0) rq->readers++; - spin_unlock(&queue_lock); + spin_unlock(&cd->queue_lock); =20 if (rq->len =3D=3D 0) { err =3D cache_request(cd, rq); @@ -876,9 +875,9 @@ static ssize_t cache_read(struct file *filp, char __use= r *buf, size_t count, =20 if (rp->offset =3D=3D 0 && !test_bit(CACHE_PENDING, &rq->item->flags)) { err =3D -EAGAIN; - spin_lock(&queue_lock); + spin_lock(&cd->queue_lock); list_move(&rp->q.list, &rq->q.list); - spin_unlock(&queue_lock); + spin_unlock(&cd->queue_lock); } else { if (rp->offset + count > rq->len) count =3D rq->len - rp->offset; @@ -888,26 +887,26 @@ static ssize_t cache_read(struct file *filp, char __u= ser *buf, size_t count, rp->offset +=3D count; if (rp->offset >=3D rq->len) { rp->offset =3D 0; - spin_lock(&queue_lock); + spin_lock(&cd->queue_lock); list_move(&rp->q.list, &rq->q.list); - spin_unlock(&queue_lock); + spin_unlock(&cd->queue_lock); } err =3D 0; } out: if (rp->offset =3D=3D 0) { /* need to release rq */ - spin_lock(&queue_lock); + spin_lock(&cd->queue_lock); rq->readers--; if (rq->readers =3D=3D 0 && !test_bit(CACHE_PENDING, &rq->item->flags)) { list_del(&rq->q.list); - spin_unlock(&queue_lock); + spin_unlock(&cd->queue_lock); cache_put(rq->item, cd); kfree(rq->buf); kfree(rq); } else - spin_unlock(&queue_lock); + spin_unlock(&cd->queue_lock); } if (err =3D=3D -EAGAIN) goto again; @@ -988,7 +987,7 @@ static __poll_t cache_poll(struct file *filp, poll_tabl= e *wait, if (!rp) return mask; =20 - spin_lock(&queue_lock); + spin_lock(&cd->queue_lock); =20 for (cq=3D &rp->q; &cq->list !=3D &cd->queue; cq =3D list_entry(cq->list.next, struct cache_queue, list)) @@ -996,7 +995,7 @@ static __poll_t cache_poll(struct file *filp, poll_tabl= e *wait, mask |=3D EPOLLIN | EPOLLRDNORM; break; } - spin_unlock(&queue_lock); + spin_unlock(&cd->queue_lock); return mask; } =20 @@ -1011,7 +1010,7 @@ static int cache_ioctl(struct inode *ino, struct file= *filp, if (cmd !=3D FIONREAD || !rp) return -EINVAL; =20 - spin_lock(&queue_lock); + spin_lock(&cd->queue_lock); =20 /* only find the length remaining in current request, * or the length of the next request @@ -1024,7 +1023,7 @@ static int cache_ioctl(struct inode *ino, struct file= *filp, len =3D cr->len - rp->offset; break; } - spin_unlock(&queue_lock); + spin_unlock(&cd->queue_lock); =20 return put_user(len, (int __user *)arg); } @@ -1046,9 +1045,9 @@ static int cache_open(struct inode *inode, struct fil= e *filp, rp->offset =3D 0; rp->q.reader =3D 1; =20 - spin_lock(&queue_lock); + spin_lock(&cd->queue_lock); list_add(&rp->q.list, &cd->queue); - spin_unlock(&queue_lock); + spin_unlock(&cd->queue_lock); } if (filp->f_mode & FMODE_WRITE) atomic_inc(&cd->writers); @@ -1064,7 +1063,7 @@ static int cache_release(struct inode *inode, struct = file *filp, if (rp) { struct cache_request *rq =3D NULL; =20 - spin_lock(&queue_lock); + spin_lock(&cd->queue_lock); if (rp->offset) { struct cache_queue *cq; for (cq =3D &rp->q; &cq->list !=3D &cd->queue; @@ -1086,7 +1085,7 @@ static int cache_release(struct inode *inode, struct = file *filp, rp->offset =3D 0; } list_del(&rp->q.list); - spin_unlock(&queue_lock); + spin_unlock(&cd->queue_lock); =20 if (rq) { cache_put(rq->item, cd); @@ -1113,7 +1112,7 @@ static void cache_dequeue(struct cache_detail *detail= , struct cache_head *ch) struct cache_request *cr; LIST_HEAD(dequeued); =20 - spin_lock(&queue_lock); + spin_lock(&detail->queue_lock); list_for_each_entry_safe(cq, tmp, &detail->queue, list) if (!cq->reader) { cr =3D container_of(cq, struct cache_request, q); @@ -1126,7 +1125,7 @@ static void cache_dequeue(struct cache_detail *detail= , struct cache_head *ch) continue; list_move(&cr->q.list, &dequeued); } - spin_unlock(&queue_lock); + spin_unlock(&detail->queue_lock); while (!list_empty(&dequeued)) { cr =3D list_entry(dequeued.next, struct cache_request, q.list); list_del(&cr->q.list); @@ -1251,7 +1250,7 @@ static int cache_pipe_upcall(struct cache_detail *det= ail, struct cache_head *h) crq->buf =3D buf; crq->len =3D 0; crq->readers =3D 0; - spin_lock(&queue_lock); + spin_lock(&detail->queue_lock); if (test_bit(CACHE_PENDING, &h->flags)) { crq->item =3D cache_get(h); list_add_tail(&crq->q.list, &detail->queue); @@ -1259,7 +1258,7 @@ static int cache_pipe_upcall(struct cache_detail *det= ail, struct cache_head *h) } else /* Lost a race, no longer PENDING, so don't enqueue */ ret =3D -EAGAIN; - spin_unlock(&queue_lock); + spin_unlock(&detail->queue_lock); wake_up(&queue_wait); if (ret =3D=3D -EAGAIN) { kfree(buf); --=20 2.53.0 From nobody Fri Apr 3 11:10:27 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9046C328608; Mon, 23 Feb 2026 17:10:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771866621; cv=none; b=mOC83zJdJxX9M2pXJFUQR0VyhRl3SYoCMR5k/55zZnJ00E+wGABPq0qnUuMZGHNQrOyXvev2OiEs+ElnefvfT1QnJWzvqRjDZ9181/jB9KBCnMzfaEDxx6Q/flOKbncsHNcfrC6fA1XWX0LiV+daF6od7HlXbpSJpM/vN7dJWCM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771866621; c=relaxed/simple; bh=iBGTnjfk1/dGbsw0AeqIOOg9PivpMLxPlwAMF1EqA3Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=H0S/zW8S8PMC2stz0PGGyfo1etgA6TlmagMdlwVY1ymOctK2icno1iQVuVPc6Eic8M9+33Pu0OvyKQQY3ctgHfZ6xg/NFCxZvQexR4FkVr96rdnxNHMFWeJksezwrCOY42RM1CfLORRXml8TitynrWsLe66bz3FBZ4xxCO2NhHY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qqEcbMjf; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="qqEcbMjf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1AEFDC116D0; Mon, 23 Feb 2026 17:10:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771866621; bh=iBGTnjfk1/dGbsw0AeqIOOg9PivpMLxPlwAMF1EqA3Q=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qqEcbMjfz1GtZsY0LqH1u8bPZBb0Asbc4cKuEMzyu0xQb77Xhi3/KQKuo7Qga6JOy By+OTd9eIK15F7M5fN5hjcNhlzRugAhXIxfMhGFZrrAYZX0TDp2fctkjQQ+CEG4E9M ZqGXUeMHHeUIpd3/xb82bgrE4xxB6rW363DWsEPMzPaP3OmIKtvv5wB7jBrNmLcXoJ uVYXiIAXpsIs1PVCEhEfq8WJYDDDrTHBIg8cqUEL3cnUsUtT6hBj24yVEmjJVOOgiF NV4Oi3syuFHKHAfvirlM2o8fsFFYbkilIvJYY2fX9IMhy4GPCy/6onpFF30c6sE+yv I8Y4en+XV8xsg== From: Jeff Layton Date: Mon, 23 Feb 2026 12:10:00 -0500 Subject: [PATCH v2 3/4] sunrpc: convert queue_wait from global to per-cache-detail waitqueue Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260223-sunrpc-cache-v2-3-91fc827c4d33@kernel.org> References: <20260223-sunrpc-cache-v2-0-91fc827c4d33@kernel.org> In-Reply-To: <20260223-sunrpc-cache-v2-0-91fc827c4d33@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , Trond Myklebust , Anna Schumaker Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=2548; i=jlayton@kernel.org; h=from:subject:message-id; bh=iBGTnjfk1/dGbsw0AeqIOOg9PivpMLxPlwAMF1EqA3Q=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpnIn3Ci4860XifnM5rQrFGVZmHLtxuHCpa0mZX +spMGV0dOSJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaZyJ9wAKCRAADmhBGVaC FTF8EADXNzk2ezTn+jly5XOmD4zIbzPqPAgKpADWzvQMUtmg1nKLgt1raAJPe9C4ctFDZJqt6wt igiYUUY5jEvoQ9BVKd5b4ffqe68wpkGXMZn64x0CWq5tkSRGyKJhAQ0IyUms2PjPUhY47gWCvfY 08ri3vJxRlFxD8yNRe3WmDz2pGOmQQUasA5pU97+WPbfGKAFFnmRsTjTu8d5X5sALCpy36Re4DL CSMpTKq4wDu3hPaw+1Q8SgDwhScf7IWRzvyDK4D9MtMbIFmo5Hbbhx5pE86nhIqCAkJIxAp5A9e 6XAxbToNKbgi7MBGX++2KpZ/zpeIVkBXkrN0Cf3np0JLGPMKTf/62oQ7+nB3xM3uvLOcWq7PoSS t4KY0uIaIbDFWoDABJvIng/TzJXqw0TaetN6kwHaH8aOyeDkF02HXgPkjLU6YQWZka04zt3p5Ci 9cEs8Kiqy09o3y0R7C9Hk1BtcCmCR1FDrePRasWMGyhFxaogZBvdluApBmMxl5S5IltpO6Cq0op cJgQ7B2xmGy07y6srW5QRJ5bdXLWT33/+MXIqS2vSX89VcBUEjKcVRJCL0S8q9eOrO1Cpg8Zln2 FCVhyo8/4Bsubmqvu7YFS/w/foSBFTwv5QWxDPpP9m8W2aBZvVsgq6MamIGg3jUNMPeJ4SYxqLZ wWYF2hx2Vw0vtQg== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 The queue_wait waitqueue is currently a file-scoped global, so a wake_up for one cache_detail wakes pollers on all caches. Convert it to a per-cache-detail field so that only pollers on the relevant cache are woken. Signed-off-by: Jeff Layton --- include/linux/sunrpc/cache.h | 2 ++ net/sunrpc/cache.c | 7 +++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index 3d32dd1f7b05d35562d2064fed69877b3950fb51..031379efba24d40f64ce346cf10= 32261d4b98d05 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -16,6 +16,7 @@ #include #include #include +#include =20 /* * Each cache requires: @@ -114,6 +115,7 @@ struct cache_detail { /* fields for communication over channel */ struct list_head queue; spinlock_t queue_lock; + wait_queue_head_t queue_wait; =20 atomic_t writers; /* how many time is /channel open */ time64_t last_close; /* if no writers, when did last close */ diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 1cfaae488c6c67a9797511804e4bbba16bcc70ae..fd02dca1f07afec2f09c591037b= ac3ea3e8d7e17 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -401,6 +401,7 @@ void sunrpc_init_cache_detail(struct cache_detail *cd) spin_lock_init(&cd->hash_lock); INIT_LIST_HEAD(&cd->queue); spin_lock_init(&cd->queue_lock); + init_waitqueue_head(&cd->queue_wait); spin_lock(&cache_list_lock); cd->nextcheck =3D 0; cd->entries =3D 0; @@ -970,8 +971,6 @@ static ssize_t cache_write(struct file *filp, const cha= r __user *buf, return ret; } =20 -static DECLARE_WAIT_QUEUE_HEAD(queue_wait); - static __poll_t cache_poll(struct file *filp, poll_table *wait, struct cache_detail *cd) { @@ -979,7 +978,7 @@ static __poll_t cache_poll(struct file *filp, poll_tabl= e *wait, struct cache_reader *rp =3D filp->private_data; struct cache_queue *cq; =20 - poll_wait(filp, &queue_wait, wait); + poll_wait(filp, &cd->queue_wait, wait); =20 /* alway allow write */ mask =3D EPOLLOUT | EPOLLWRNORM; @@ -1259,7 +1258,7 @@ static int cache_pipe_upcall(struct cache_detail *det= ail, struct cache_head *h) /* Lost a race, no longer PENDING, so don't enqueue */ ret =3D -EAGAIN; spin_unlock(&detail->queue_lock); - wake_up(&queue_wait); + wake_up(&detail->queue_wait); if (ret =3D=3D -EAGAIN) { kfree(buf); kfree(crq); --=20 2.53.0 From nobody Fri Apr 3 11:10:27 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6672832B99C; Mon, 23 Feb 2026 17:10:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771866622; cv=none; b=oTH78BhmDCI3RlhSmObsGDW6JLI1cXoSewNGyxcNJdWY1qVLArsNc1yytgMBmPMq6chkuD6MTSQWuX5Ic0iuloVwbxGaGFaD4VgfhvIboAUb5BLlXEC6n/FyiVBUoBCppTuNJNvQcPVD1Q8T86gELqViPWLqKx58Rixlfl1NVSo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771866622; c=relaxed/simple; bh=dNeT2z5g6QrxREtVSzcWt3Mo1ZrVqGJUQrUAUu9NNCQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=W1egBMcT/lqjuuRqyxFypW21qDSppBBWYA1l+eUEEZjcwF13dxq/7451YT0UWGIN4Gngu+0mbfvkOHEUmxpizW958b88guoPfa1Tcr2yQVgnwXI/k30bXZJDXAjYyftkxLPSNDPijA7ADVWu2SIVZAn60XGAS8umDSS7Q210yCA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LwU/bjxy; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LwU/bjxy" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3D2D2C2BC9E; Mon, 23 Feb 2026 17:10:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771866622; bh=dNeT2z5g6QrxREtVSzcWt3Mo1ZrVqGJUQrUAUu9NNCQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=LwU/bjxyxwSJgXwMY1nlBUz4A8FR1A++tb9HfqVpKfS+LUt9rn/bNGOoV/wxeT5iO HLcaWVaokCjMUgd+Awe7NbxwMrJc/EQ9lVFKYfVMDawdnVWP8ouE+5ge5thBsj+pRZ h9ULPxPPa7manV1NB8145ApgdqReVlyXZ252NDfyr0JYCEYw4eqmgCXu8U4ZU8i09k GNVuk/GedNgRJvxHZjYnvXkzHoZOPDgmF90XaNDyhpMVxo4aM2MOih7+2G9wrE3U19 ZgKc2msZ/3/WM91GL4+vcDpKlUj/heUh0b3lDyM93rExrqS30irDIf/qriU8F6Wup7 z4/GerCAK8nVQ== From: Jeff Layton Date: Mon, 23 Feb 2026 12:10:01 -0500 Subject: [PATCH v2 4/4] sunrpc: split cache_detail queue into request and reader lists Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260223-sunrpc-cache-v2-4-91fc827c4d33@kernel.org> References: <20260223-sunrpc-cache-v2-0-91fc827c4d33@kernel.org> In-Reply-To: <20260223-sunrpc-cache-v2-0-91fc827c4d33@kernel.org> To: Chuck Lever , NeilBrown , Olga Kornievskaia , Dai Ngo , Tom Talpey , Trond Myklebust , Anna Schumaker Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org, Jeff Layton X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=10533; i=jlayton@kernel.org; h=from:subject:message-id; bh=dNeT2z5g6QrxREtVSzcWt3Mo1ZrVqGJUQrUAUu9NNCQ=; b=owEBbQKS/ZANAwAKAQAOaEEZVoIVAcsmYgBpnIn4UyxP/JnnMn9p7NxFBK3u7lDwZ6/sVNmkC lc+lZUZzhSJAjMEAAEKAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCaZyJ+AAKCRAADmhBGVaC FYK/EACurrSZplxEceCB+FxBYZwFi9i/HJoXHcGHARCKDSSVdtfvVZjz35hcK1VgLIoV268mZAL OcQX7pYJM7GX9siNoA9Y0Soz71SZkzQGhQu77zSOBmEwxPy4iu6+bqUvTa3/4v6ML+/FnFnu5So RSBQdA9f/A3xdq3saqs9bEFChFBPX8UHAvISZkiz3pAsrb2eq5eacOchs0p3hurWUn0ezNy0bSJ eJEBuRF1ak02xRcF2Fd6S4v4QMmoA09aTmTtJz627yghfYzxqHh3kMTHzMyChtBmdHjflqUENqw PfcQS61BfY0fjIgkUIvrBv+cXaBXHOsoiC+RavkNtLkLIUcFffJyZtGtigbRqoVZ9bA9GvTRCfI VLVUfSxxm268bldIOOStUL+V5g4KCg6a+Gfx3IEqVfIifA1AzRmY2EPESUA7RpQ77bpNBHiq9FR lqcUmiv5xZ6urdBVG+zHhFztUccul431sPraiPI8Y43qBojNqVb5Dls7/lAZDNGrvgI5+766E6Z PTlE3zft0nW0lYGoD97qrfUd2E4852bE2QYZBduJlHX8N3HRHMyMzXFIq1MujkMTToRHwnWz2S3 C6T/FcC7bJzvCm30HxXboTlC44gKuaRuxdxwX4v1pMl9HwvAMr8slJMqAOxeuYjw26Fo0Ojns5U b8XOCJaMYhJkWwQ== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Replace the single interleaved queue (which mixed cache_request and cache_reader entries distinguished by a ->reader flag) with two dedicated lists: cd->requests for upcall requests and cd->readers for open file handles. Readers now track their position via a monotonically increasing sequence number (next_seqno) rather than by their position in the shared list. Each cache_request is assigned a seqno when enqueued, and a new cache_next_request() helper finds the next request at or after a given seqno. This eliminates the cache_queue wrapper struct entirely, simplifies the reader-skipping loops in cache_read/cache_poll/cache_ioctl/ cache_release, and makes the data flow easier to reason about. Signed-off-by: Jeff Layton --- include/linux/sunrpc/cache.h | 4 +- net/sunrpc/cache.c | 143 ++++++++++++++++++---------------------= ---- 2 files changed, 62 insertions(+), 85 deletions(-) diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index 031379efba24d40f64ce346cf1032261d4b98d05..b1e595c2615bd4be4d9ad19f71a= 8f4d08bd74a9b 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -113,9 +113,11 @@ struct cache_detail { int entries; =20 /* fields for communication over channel */ - struct list_head queue; + struct list_head requests; + struct list_head readers; spinlock_t queue_lock; wait_queue_head_t queue_wait; + u64 next_seqno; =20 atomic_t writers; /* how many time is /channel open */ time64_t last_close; /* if no writers, when did last close */ diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index fd02dca1f07afec2f09c591037bac3ea3e8d7e17..7081c1214e6c3226f8ac82c8bc7= ff6c36f598744 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -399,9 +399,11 @@ static struct delayed_work cache_cleaner; void sunrpc_init_cache_detail(struct cache_detail *cd) { spin_lock_init(&cd->hash_lock); - INIT_LIST_HEAD(&cd->queue); + INIT_LIST_HEAD(&cd->requests); + INIT_LIST_HEAD(&cd->readers); spin_lock_init(&cd->queue_lock); init_waitqueue_head(&cd->queue_wait); + cd->next_seqno =3D 0; spin_lock(&cache_list_lock); cd->nextcheck =3D 0; cd->entries =3D 0; @@ -796,29 +798,20 @@ void cache_clean_deferred(void *owner) * On read, you get a full request, or block. * On write, an update request is processed. * Poll works if anything to read, and always allows write. - * - * Implemented by linked list of requests. Each open file has - * a ->private that also exists in this list. New requests are added - * to the end and may wakeup and preceding readers. - * New readers are added to the head. If, on read, an item is found with - * CACHE_UPCALLING clear, we free it from the list. - * */ =20 -struct cache_queue { - struct list_head list; - int reader; /* if 0, then request */ -}; struct cache_request { - struct cache_queue q; + struct list_head list; struct cache_head *item; - char * buf; + char *buf; int len; int readers; + u64 seqno; }; struct cache_reader { - struct cache_queue q; + struct list_head list; int offset; /* if non-0, we have a refcnt on next request */ + u64 next_seqno; }; =20 static int cache_request(struct cache_detail *detail, @@ -833,6 +826,17 @@ static int cache_request(struct cache_detail *detail, return PAGE_SIZE - len; } =20 +static struct cache_request * +cache_next_request(struct cache_detail *cd, u64 seqno) +{ + struct cache_request *rq; + + list_for_each_entry(rq, &cd->requests, list) + if (rq->seqno >=3D seqno) + return rq; + return NULL; +} + static ssize_t cache_read(struct file *filp, char __user *buf, size_t coun= t, loff_t *ppos, struct cache_detail *cd) { @@ -849,20 +853,13 @@ static ssize_t cache_read(struct file *filp, char __u= ser *buf, size_t count, again: spin_lock(&cd->queue_lock); /* need to find next request */ - while (rp->q.list.next !=3D &cd->queue && - list_entry(rp->q.list.next, struct cache_queue, list) - ->reader) { - struct list_head *next =3D rp->q.list.next; - list_move(&rp->q.list, next); - } - if (rp->q.list.next =3D=3D &cd->queue) { + rq =3D cache_next_request(cd, rp->next_seqno); + if (!rq) { spin_unlock(&cd->queue_lock); inode_unlock(inode); WARN_ON_ONCE(rp->offset); return 0; } - rq =3D container_of(rp->q.list.next, struct cache_request, q.list); - WARN_ON_ONCE(rq->q.reader); if (rp->offset =3D=3D 0) rq->readers++; spin_unlock(&cd->queue_lock); @@ -876,9 +873,7 @@ static ssize_t cache_read(struct file *filp, char __use= r *buf, size_t count, =20 if (rp->offset =3D=3D 0 && !test_bit(CACHE_PENDING, &rq->item->flags)) { err =3D -EAGAIN; - spin_lock(&cd->queue_lock); - list_move(&rp->q.list, &rq->q.list); - spin_unlock(&cd->queue_lock); + rp->next_seqno =3D rq->seqno + 1; } else { if (rp->offset + count > rq->len) count =3D rq->len - rp->offset; @@ -888,9 +883,7 @@ static ssize_t cache_read(struct file *filp, char __use= r *buf, size_t count, rp->offset +=3D count; if (rp->offset >=3D rq->len) { rp->offset =3D 0; - spin_lock(&cd->queue_lock); - list_move(&rp->q.list, &rq->q.list); - spin_unlock(&cd->queue_lock); + rp->next_seqno =3D rq->seqno + 1; } err =3D 0; } @@ -901,7 +894,7 @@ static ssize_t cache_read(struct file *filp, char __use= r *buf, size_t count, rq->readers--; if (rq->readers =3D=3D 0 && !test_bit(CACHE_PENDING, &rq->item->flags)) { - list_del(&rq->q.list); + list_del(&rq->list); spin_unlock(&cd->queue_lock); cache_put(rq->item, cd); kfree(rq->buf); @@ -976,7 +969,6 @@ static __poll_t cache_poll(struct file *filp, poll_tabl= e *wait, { __poll_t mask; struct cache_reader *rp =3D filp->private_data; - struct cache_queue *cq; =20 poll_wait(filp, &cd->queue_wait, wait); =20 @@ -988,12 +980,8 @@ static __poll_t cache_poll(struct file *filp, poll_tab= le *wait, =20 spin_lock(&cd->queue_lock); =20 - for (cq=3D &rp->q; &cq->list !=3D &cd->queue; - cq =3D list_entry(cq->list.next, struct cache_queue, list)) - if (!cq->reader) { - mask |=3D EPOLLIN | EPOLLRDNORM; - break; - } + if (cache_next_request(cd, rp->next_seqno)) + mask |=3D EPOLLIN | EPOLLRDNORM; spin_unlock(&cd->queue_lock); return mask; } @@ -1004,7 +992,7 @@ static int cache_ioctl(struct inode *ino, struct file = *filp, { int len =3D 0; struct cache_reader *rp =3D filp->private_data; - struct cache_queue *cq; + struct cache_request *rq; =20 if (cmd !=3D FIONREAD || !rp) return -EINVAL; @@ -1014,14 +1002,9 @@ static int cache_ioctl(struct inode *ino, struct fil= e *filp, /* only find the length remaining in current request, * or the length of the next request */ - for (cq=3D &rp->q; &cq->list !=3D &cd->queue; - cq =3D list_entry(cq->list.next, struct cache_queue, list)) - if (!cq->reader) { - struct cache_request *cr =3D - container_of(cq, struct cache_request, q); - len =3D cr->len - rp->offset; - break; - } + rq =3D cache_next_request(cd, rp->next_seqno); + if (rq) + len =3D rq->len - rp->offset; spin_unlock(&cd->queue_lock); =20 return put_user(len, (int __user *)arg); @@ -1042,10 +1025,10 @@ static int cache_open(struct inode *inode, struct f= ile *filp, return -ENOMEM; } rp->offset =3D 0; - rp->q.reader =3D 1; + rp->next_seqno =3D 0; =20 spin_lock(&cd->queue_lock); - list_add(&rp->q.list, &cd->queue); + list_add(&rp->list, &cd->readers); spin_unlock(&cd->queue_lock); } if (filp->f_mode & FMODE_WRITE) @@ -1064,26 +1047,21 @@ static int cache_release(struct inode *inode, struc= t file *filp, =20 spin_lock(&cd->queue_lock); if (rp->offset) { - struct cache_queue *cq; - for (cq =3D &rp->q; &cq->list !=3D &cd->queue; - cq =3D list_entry(cq->list.next, - struct cache_queue, list)) - if (!cq->reader) { - struct cache_request *cr =3D - container_of(cq, - struct cache_request, q); - cr->readers--; - if (cr->readers =3D=3D 0 && - !test_bit(CACHE_PENDING, - &cr->item->flags)) { - list_del(&cr->q.list); - rq =3D cr; - } - break; + struct cache_request *cr; + + cr =3D cache_next_request(cd, rp->next_seqno); + if (cr) { + cr->readers--; + if (cr->readers =3D=3D 0 && + !test_bit(CACHE_PENDING, + &cr->item->flags)) { + list_del(&cr->list); + rq =3D cr; } + } rp->offset =3D 0; } - list_del(&rp->q.list); + list_del(&rp->list); spin_unlock(&cd->queue_lock); =20 if (rq) { @@ -1107,27 +1085,24 @@ static int cache_release(struct inode *inode, struc= t file *filp, =20 static void cache_dequeue(struct cache_detail *detail, struct cache_head *= ch) { - struct cache_queue *cq, *tmp; - struct cache_request *cr; + struct cache_request *cr, *tmp; LIST_HEAD(dequeued); =20 spin_lock(&detail->queue_lock); - list_for_each_entry_safe(cq, tmp, &detail->queue, list) - if (!cq->reader) { - cr =3D container_of(cq, struct cache_request, q); - if (cr->item !=3D ch) - continue; - if (test_bit(CACHE_PENDING, &ch->flags)) - /* Lost a race and it is pending again */ - break; - if (cr->readers !=3D 0) - continue; - list_move(&cr->q.list, &dequeued); - } + list_for_each_entry_safe(cr, tmp, &detail->requests, list) { + if (cr->item !=3D ch) + continue; + if (test_bit(CACHE_PENDING, &ch->flags)) + /* Lost a race and it is pending again */ + break; + if (cr->readers !=3D 0) + continue; + list_move(&cr->list, &dequeued); + } spin_unlock(&detail->queue_lock); while (!list_empty(&dequeued)) { - cr =3D list_entry(dequeued.next, struct cache_request, q.list); - list_del(&cr->q.list); + cr =3D list_entry(dequeued.next, struct cache_request, list); + list_del(&cr->list); cache_put(cr->item, detail); kfree(cr->buf); kfree(cr); @@ -1245,14 +1220,14 @@ static int cache_pipe_upcall(struct cache_detail *d= etail, struct cache_head *h) return -EAGAIN; } =20 - crq->q.reader =3D 0; crq->buf =3D buf; crq->len =3D 0; crq->readers =3D 0; spin_lock(&detail->queue_lock); if (test_bit(CACHE_PENDING, &h->flags)) { crq->item =3D cache_get(h); - list_add_tail(&crq->q.list, &detail->queue); + crq->seqno =3D detail->next_seqno++; + list_add_tail(&crq->list, &detail->requests); trace_cache_entry_upcall(detail, h); } else /* Lost a race, no longer PENDING, so don't enqueue */ --=20 2.53.0