From nobody Sat Jun 20 04:57:26 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 C8E2838947F for ; Mon, 20 Apr 2026 08:37:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674249; cv=none; b=pGOMiqQR3LluRk4od5iy4qX8FYkLfKddz6d/l9S3HEFFNNqB5w76KWpFXsVNa6Ca5A37HphJ0TqEiLB7vwehCYlDbjwhDImzb5wVxyfJV6aNRSQM2y58SJ/yPCpe97nz4e4YA6qU15dQydasfbzqPunWd2R2GlsZpCztiaEFrxo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674249; c=relaxed/simple; bh=JE6CsI55nIe/za2bQ2wM//e11Vro+GT7jie6/v4Wuw4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=opshoNGoYcrIOs0FCYu49Kn8nYzxR+Fms2sZlrN3BnPGcjo0vV9p2e+TwkpaOkMtHOKoZFxNi7IerE7C3uttO+avolVbAoXPb7bipm6QR8RDd8hMtNn18Ke+kpT7n5a+I1TfyDSITZK2WjiNtATNZgJ6ioSZkovd0LxsCVBlAJw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=E4cxiIXt; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="E4cxiIXt" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1776674246; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ksxJg5s1e4rqCiU0anjwW0Drg+bXTRaHFQWcy6sTuKQ=; b=E4cxiIXtYynsA7c8JNXuIvjPb2fd8gB21VWQC2eCrdXzF9DttOtUFBPXyZQe9WoWonYp/7 y+xMozfd7HxF8SMaF1XiAjUKwl07kb4pCtvhyrp823j7F6r7msRmB54ynpQH9BTsP3upPH l6jwpP4neDaHZAUbyWuQENNf31LjHV8= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-332-tjVoit6wNru8srkOeHIZeQ-1; Mon, 20 Apr 2026 04:37:21 -0400 X-MC-Unique: tjVoit6wNru8srkOeHIZeQ-1 X-Mimecast-MFC-AGG-ID: tjVoit6wNru8srkOeHIZeQ_1776674239 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 83B9018005A8; Mon, 20 Apr 2026 08:37:19 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.48.17]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 247B3195608E; Mon, 20 Apr 2026 08:37:14 +0000 (UTC) From: David Howells To: Christian Brauner Cc: David Howells , Paulo Alcantara , netfs@lists.linux.dev, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Steve French , Matthew Wilcox Subject: [PATCH 01/11] netfs: Fix early put of sink folio in netfs_read_gaps() Date: Mon, 20 Apr 2026 09:36:52 +0100 Message-ID: <20260420083705.1009074-2-dhowells@redhat.com> In-Reply-To: <20260420083705.1009074-1-dhowells@redhat.com> References: <20260420083705.1009074-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Fix netfs_read_gaps() to release the sink page it uses after waiting for the request to complete. The way the sink page is used is that an ITER_BVEC-class iterator is created that has the gaps from the target folio at either end, but has the sink page tiled over the middle so that a single read op can fill in both gaps. The bug was found by KASAN detecting a UAF on the generic/075 xfstest in the cifsd kernel thread that handles reception of data from the TCP socket: BUG: KASAN: use-after-free in _copy_to_iter+0x48a/0xa20 Write of size 885 at addr ffff888107f92000 by task cifsd/1285 CPU: 2 UID: 0 PID: 1285 Comm: cifsd Not tainted 7.0.0 #6 PREEMPT(lazy) Call Trace: dump_stack_lvl+0x5d/0x80 print_report+0x17f/0x4f1 kasan_report+0x100/0x1e0 kasan_check_range+0x10f/0x1e0 __asan_memcpy+0x3c/0x60 _copy_to_iter+0x48a/0xa20 __skb_datagram_iter+0x2c9/0x430 skb_copy_datagram_iter+0x6e/0x160 tcp_recvmsg_locked+0xce0/0x1130 tcp_recvmsg+0xeb/0x300 inet_recvmsg+0xcf/0x3a0 sock_recvmsg+0xea/0x100 cifs_readv_from_socket+0x3a6/0x4d0 [cifs] cifs_read_iter_from_socket+0xdd/0x130 [cifs] cifs_readv_receive+0xaad/0xb10 [cifs] cifs_demultiplex_thread+0x1148/0x1740 [cifs] kthread+0x1cf/0x210 Fixes: ee4cdf7ba857 ("netfs: Speed up buffered reading") Reported-by: Steve French Signed-off-by: David Howells cc: Paulo Alcantara cc: Matthew Wilcox cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/buffered_read.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index c23173a061e8..dc50690fdd44 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -459,9 +459,6 @@ static int netfs_read_gaps(struct file *file, struct fo= lio *folio) =20 netfs_read_to_pagecache(rreq, NULL); =20 - if (sink) - folio_put(sink); - ret =3D netfs_wait_for_read(rreq); if (ret >=3D 0) { folio_detach_private(folio); @@ -471,6 +468,9 @@ static int netfs_read_gaps(struct file *file, struct fo= lio *folio) flush_dcache_folio(folio); folio_mark_uptodate(folio); } + + if (sink) + folio_put(sink); folio_unlock(folio); netfs_put_request(rreq, netfs_rreq_trace_put_return); return ret < 0 ? ret : 0; From nobody Sat Jun 20 04:57:26 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 DD14238B159 for ; Mon, 20 Apr 2026 08:37:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674254; cv=none; b=dRsy961vtOPdIlOowvaQY4ArGszIQ4nAxGosHQ8U7t4l55+AOT1s/humx/JsJ/ErgfNknBtcgW4pR27Ya+W1jRcxwOr0Sp2O2oM3t3AsnGtxVD39BU0dBHHt+JYLCjXo8Tm4o2zELJ2ToPBJi4afJZjwreXJ+yV2xi6ylrPFMlY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674254; c=relaxed/simple; bh=rNCuGEe+cUkbJVv0l2fZwrYWlgVSaWB6ya+QriIWRmU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pvXhi+/NEkI5fT+HTYfZHznpcmD8tAFNqt5hgddO/0NglYEV7VsQqmUBPpkBsOXCvoPlI+zsigliLBoMiTjxY4ZkyjRWGZ5f7D06ALI8Wg2z60V6zIOKmhES7AuADvRShNWM6Rar4GUltILzVOxcuHvm4gZ6lYowTxPo+NB7QuY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=CjqUElnd; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="CjqUElnd" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1776674252; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=oYjLbr3bROmxtkNCAMr+RVTMxNJEUY0LOnKnAfK28Pw=; b=CjqUElndoLEL3y4XPsJVNKOqOiHFIuCpmzLxcWy53va6gHoM9Bb879yUZA2K7UFGrwUCaL AR4039SARiKCp7QUA3vhV5Xm3TFC47lEK4BlQcmNHutir6jEKFL/PMEDBcTBLTdGNxq7Be LUUWNxmxqV8rzoQm8LAOgvHRU1iZTLc= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-659-v2fYY0HbOlOf4XvvOzKBmg-1; Mon, 20 Apr 2026 04:37:27 -0400 X-MC-Unique: v2fYY0HbOlOf4XvvOzKBmg-1 X-Mimecast-MFC-AGG-ID: v2fYY0HbOlOf4XvvOzKBmg_1776674245 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id DBBC4180034D; Mon, 20 Apr 2026 08:37:24 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.48.17]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 4C5973000C15; Mon, 20 Apr 2026 08:37:20 +0000 (UTC) From: David Howells To: Christian Brauner Cc: David Howells , Paulo Alcantara , netfs@lists.linux.dev, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Matthew Wilcox Subject: [PATCH 02/11] netfs: Fix leak of request in netfs_write_begin() error handling Date: Mon, 20 Apr 2026 09:36:53 +0100 Message-ID: <20260420083705.1009074-3-dhowells@redhat.com> In-Reply-To: <20260420083705.1009074-1-dhowells@redhat.com> References: <20260420083705.1009074-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Fix netfs_write_begin() to not leak our ref on the request in the event that we get an error from netfs_wait_for_read(). Fixes: 4090b31422a6 ("netfs: Add a function to consolidate beginning a read= ") Closes: https://sashiko.dev/#/patchset/20260414082004.3756080-1-dhowells%40= redhat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: Matthew Wilcox cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/buffered_read.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index dc50690fdd44..51caad535438 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -688,7 +688,7 @@ int netfs_write_begin(struct netfs_inode *ctx, netfs_read_to_pagecache(rreq, NULL); ret =3D netfs_wait_for_read(rreq); if (ret < 0) - goto error; + goto error_put; netfs_put_request(rreq, netfs_rreq_trace_put_return); =20 have_folio: From nobody Sat Jun 20 04:57:26 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 441D5388E55 for ; Mon, 20 Apr 2026 08:37:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674258; cv=none; b=GNiWMF1ImtkIRh+za0zOdlpqPovps4gR+PrrV+2YHCnYIgYqGn5fyBjQZmKIEIdpz73u1rxkrQ1qdifWE5y3XIj0z6gCfsmQi0a+apOEmANq8YIIfvWPz+vFlXoTHHJPgDSgb4tXY3YLU873l+xwF0AVN5OS0X5AnnucjF2AMpU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674258; c=relaxed/simple; bh=Mueh1+AhgGs/BauhuJNGcBUyo52NSt02ZynYIE1e/os=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SkyejPlKgVi0RGZyMqPIgo7pN7G/a4VLo1vvotnLmP2XvknrkKVyBALPklnzKD73wqw9Apf/63kV2p+sQROgcZhiHxEAt2jqbaLwNgdUVLNrpUAWKVvepkk+/LilCSSmiT3FwdEQZNEta1ThOycBqVnGbCFgKeIbDi4hlxxpyUg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=W4BHB2RD; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="W4BHB2RD" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1776674256; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RxAt8h3Z5s//UgNA1V43SWKyEAFpFt5qMrF31FeEFDE=; b=W4BHB2RD2e6FO2caVljvNFPhVBTvG7oBavwqe+Yg+oL1065mrIS4sePF2Y1cqFect5Eyte e+UFroh8OydVABvrse0x011VrYUpQQLxqnu9JQG+k206dalugviv2fvFhisQjW3NgfWWm9 nUtBD0DBHlf5rHTpKFqr1LLYiBNtwBg= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-201-x4HYGNN4MX-KuWrsWdkrPA-1; Mon, 20 Apr 2026 04:37:33 -0400 X-MC-Unique: x4HYGNN4MX-KuWrsWdkrPA-1 X-Mimecast-MFC-AGG-ID: x4HYGNN4MX-KuWrsWdkrPA_1776674251 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 960F21956065; Mon, 20 Apr 2026 08:37:30 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.48.17]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7AB033000C15; Mon, 20 Apr 2026 08:37:26 +0000 (UTC) From: David Howells To: Christian Brauner Cc: David Howells , Paulo Alcantara , netfs@lists.linux.dev, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Viacheslav Dubeyko , Matthew Wilcox Subject: [PATCH 03/11] netfs: Fix potential UAF in netfs_unlock_abandoned_read_pages() Date: Mon, 20 Apr 2026 09:36:54 +0100 Message-ID: <20260420083705.1009074-4-dhowells@redhat.com> In-Reply-To: <20260420083705.1009074-1-dhowells@redhat.com> References: <20260420083705.1009074-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" netfs_unlock_abandoned_read_pages(rreq) accesses the index of the folios it is wanting to unlock and compares that to rreq->no_unlock_folio so that it doesn't unlock a folio being read for netfs_perform_write() or netfs_write_begin(). However, given that netfs_unlock_abandoned_read_pages() is called _after_ NETFS_RREQ_IN_PROGRESS is cleared, the one folio that it's not allowed to dereference is the one specified by ->no_unlock_folio as ownership immediately reverts to the caller. Fix this by storing the folio pointer instead and using that rather than the index. Also fix netfs_unlock_read_folio() where the same applies. Fixes: ee4cdf7ba857 ("netfs: Speed up buffered reading") Closes: https://sashiko.dev/#/patchset/20260414082004.3756080-1-dhowells%40= redhat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: Viacheslav Dubeyko cc: Matthew Wilcox cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/buffered_read.c | 4 ++-- fs/netfs/read_collect.c | 2 +- fs/netfs/read_retry.c | 2 +- include/linux/netfs.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index 51caad535438..b4d271538f75 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -670,7 +670,7 @@ int netfs_write_begin(struct netfs_inode *ctx, ret =3D PTR_ERR(rreq); goto error; } - rreq->no_unlock_folio =3D folio->index; + rreq->no_unlock_folio =3D folio; __set_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags); =20 ret =3D netfs_begin_cache_read(rreq, ctx); @@ -736,7 +736,7 @@ int netfs_prefetch_for_write(struct file *file, struct = folio *folio, goto error; } =20 - rreq->no_unlock_folio =3D folio->index; + rreq->no_unlock_folio =3D folio; __set_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags); ret =3D netfs_begin_cache_read(rreq, ctx); if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) diff --git a/fs/netfs/read_collect.c b/fs/netfs/read_collect.c index e5f6665b3341..eae067e3eaa5 100644 --- a/fs/netfs/read_collect.c +++ b/fs/netfs/read_collect.c @@ -83,7 +83,7 @@ static void netfs_unlock_read_folio(struct netfs_io_reque= st *rreq, } =20 just_unlock: - if (folio->index =3D=3D rreq->no_unlock_folio && + if (folio =3D=3D rreq->no_unlock_folio && test_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags)) { _debug("no unlock"); } else { diff --git a/fs/netfs/read_retry.c b/fs/netfs/read_retry.c index 68fc869513ef..999177426141 100644 --- a/fs/netfs/read_retry.c +++ b/fs/netfs/read_retry.c @@ -288,7 +288,7 @@ void netfs_unlock_abandoned_read_pages(struct netfs_io_= request *rreq) struct folio *folio =3D folioq_folio(p, slot); =20 if (folio && !folioq_is_marked2(p, slot)) { - if (folio->index =3D=3D rreq->no_unlock_folio && + if (folio =3D=3D rreq->no_unlock_folio && test_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags)) { _debug("no unlock"); diff --git a/include/linux/netfs.h b/include/linux/netfs.h index ba17ac5bf356..62a528f90666 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -252,7 +252,7 @@ struct netfs_io_request { unsigned long long collected_to; /* Point we've collected to */ unsigned long long cleaned_to; /* Position we've cleaned folios to */ unsigned long long abandon_to; /* Position to abandon folios to */ - pgoff_t no_unlock_folio; /* Don't unlock this folio after read */ + const struct folio *no_unlock_folio; /* Don't unlock this folio after rea= d */ unsigned int direct_bv_count; /* Number of elements in direct_bv[] */ unsigned int debug_id; unsigned int rsize; /* Maximum read size (0 for none) */ From nobody Sat Jun 20 04:57:26 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 9CDD238F62B for ; Mon, 20 Apr 2026 08:37:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674265; cv=none; b=WeVffYTmS62klzffMBLSCzsSfmQ+Gh1/Xf25Eyo43sdgFaqKfK14jsEhVEAhfxCbBoUc7TxAY+/CGoHaTdwbit9Skh9kkyUEy1tuvu3AS8UROXkkU+KwbjgnGofnmHXzdvZ5KZLVmU/pVRiAhA42AQeTo53JqSNcBj5jVoR+9iw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674265; c=relaxed/simple; bh=ZGvl6pwK8hhI6Z7/+zjDuc7j0IK6cFQmA5My4ZDgo6s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mdso5ZcQhRiz33rmLlxNV8as2kwSX6GpJf43r34x94hEdBTnTjhSEXEFGRQ7CXMPVkwDxiWzplfOMFPRHuXHUWARYg3cFYb2lqUbqbNFfsR/vN6D+hHUgfoPk8cg3cF8gVIU2VbPYOanxaX71Nm71/kA56GDLjItcf70UhnWWYU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=aRxWqJLw; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="aRxWqJLw" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1776674262; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=k8mwXPbUAnJI1Gm/W783qf7sgkpvXeGSln2ciNPV49w=; b=aRxWqJLwGwb1sqjX11PsoR4XsJmEFLj6eTDmUYoBz6LAUKtSqr2d3gKzzw6xVpz3NrM0Dw oIbQmNgJ2s6nrVrz0+FBkvkrm7VuS6GgPR6DyHtZIpcPgVRujBfavmOm7wn+gkaI7V9bkn vOr2HQDLYGVMRyrxpKYy1U5H8negdoY= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-225-666PritQM6uNZi4hHI4WUA-1; Mon, 20 Apr 2026 04:37:37 -0400 X-MC-Unique: 666PritQM6uNZi4hHI4WUA-1 X-Mimecast-MFC-AGG-ID: 666PritQM6uNZi4hHI4WUA_1776674256 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6744D18003FC; Mon, 20 Apr 2026 08:37:35 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.48.17]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 5288819560AB; Mon, 20 Apr 2026 08:37:32 +0000 (UTC) From: David Howells To: Christian Brauner Cc: David Howells , Paulo Alcantara , netfs@lists.linux.dev, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Matthew Wilcox Subject: [PATCH 04/11] netfs: Fix potential uninitialised var in netfs_extract_user_iter() Date: Mon, 20 Apr 2026 09:36:55 +0100 Message-ID: <20260420083705.1009074-5-dhowells@redhat.com> In-Reply-To: <20260420083705.1009074-1-dhowells@redhat.com> References: <20260420083705.1009074-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 Content-Type: text/plain; charset="utf-8" In netfs_extract_user_iter(), if it's given a zero-length iterator, it will fall through the loop without setting ret, and so the error handling behaviour will be undefined, depending on whether ret happens to be negative. The value of ret then propagates back up the callstack. Fix this by presetting ret to 0. Fixes: 85dd2c8ff368 ("netfs: Add a function to extract a UBUF or IOVEC into= a BVEC iterator") Closes: https://sashiko.dev/#/patchset/20260414082004.3756080-1-dhowells%40= redhat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: Matthew Wilcox cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/iterator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/netfs/iterator.c b/fs/netfs/iterator.c index adca78747f23..429e4396e1b0 100644 --- a/fs/netfs/iterator.c +++ b/fs/netfs/iterator.c @@ -43,7 +43,7 @@ ssize_t netfs_extract_user_iter(struct iov_iter *orig, si= ze_t orig_len, unsigned int max_pages; unsigned int npages =3D 0; unsigned int i; - ssize_t ret; + ssize_t ret =3D 0; size_t count =3D orig_len, offset, len; size_t bv_size, pg_size; From nobody Sat Jun 20 04:57:26 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 BE30D38F643 for ; Mon, 20 Apr 2026 08:37:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674267; cv=none; b=bt+sh1XUzbCKjQJHK048OLPqpV0obfqO7grShLvA5aPiE3f0vNMw2RoDtdo2D1rAqJkB40v8bZQPtQfdmLLPUyrgd1PwGqSk6BqqA6CTHi3FbDTUIJSfsQbEM2TJaXzF9rVwzmgOP5HJR+fWZIK+fsWaEzAbzXQETUP8C7nW6qk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674267; c=relaxed/simple; bh=pqehrGUvFhKSXNHxOH4q0/fAGSySis+WX/zGELva8lg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CdKBC4ktxBAhk6K5n4YtmqY5RfTnWb5wVWQxoAL2zPJuCpT1BD9FSOM9cAErTEEm3d39m1AoIlWZKoUZv6yKku9NNaqyh1q5rybIrwRV+n5QyE1KT0s1kjuKQejbIi2AYmOCagjFwWoF5Pqc2vOcYaGMasvwAQKa55i9jbpbEf8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=gFDikoa3; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="gFDikoa3" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1776674265; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=fwIrRp2mzgM5XL791ck6rIOO1IU+DN7HcZOIJ0dzRVg=; b=gFDikoa3kJeVaSbCnclUJ2jV8dIX1MdE+imZEs2JY2pZycxda3wbZu3SBoY8ObO9x/4L0C r2YZWbQ0N8jVUA/Qqvb9LoDmJ8FFJif3JvyTbs+ZbNHIf/NvFdZjHmNGMc5yZmqF7F3DDi 2GrQVZ3R01tIEzT9C0TyEEQZb2TANd8= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-590-k2Zpn1AXPlyv3OwQPQQxSg-1; Mon, 20 Apr 2026 04:37:41 -0400 X-MC-Unique: k2Zpn1AXPlyv3OwQPQQxSg-1 X-Mimecast-MFC-AGG-ID: k2Zpn1AXPlyv3OwQPQQxSg_1776674260 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0FCDE1956048; Mon, 20 Apr 2026 08:37:40 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.48.17]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 1EC6C1800351; Mon, 20 Apr 2026 08:37:36 +0000 (UTC) From: David Howells To: Christian Brauner Cc: David Howells , Paulo Alcantara , netfs@lists.linux.dev, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Matthew Wilcox Subject: [PATCH 05/11] netfs: Fix partial invalidation of streaming-write folio Date: Mon, 20 Apr 2026 09:36:56 +0100 Message-ID: <20260420083705.1009074-6-dhowells@redhat.com> In-Reply-To: <20260420083705.1009074-1-dhowells@redhat.com> References: <20260420083705.1009074-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Content-Type: text/plain; charset="utf-8" In netfs_invalidate_folio(), if the region of a partial invalidation overlaps the front (but not all) of a dirty write cached in a streaming write page (dirty, but not uptodate, with the dirty region tracked by a netfs_folio struct), the function modifies the dirty region - but incorrectly as it moves the region forward by setting the start to the start, not the end, of the invalidation region. Fix this by setting finfo->dirty_offset to the end of the invalidation region (iend). Fixes: cce6bfa6ca0e ("netfs: Fix trimming of streaming-write folios in netf= s_inval_folio()") Closes: https://sashiko.dev/#/patchset/20260414082004.3756080-1-dhowells%40= redhat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: Matthew Wilcox cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/misc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/netfs/misc.c b/fs/netfs/misc.c index e386cf31eb1e..8b457124b0e3 100644 --- a/fs/netfs/misc.c +++ b/fs/netfs/misc.c @@ -255,7 +255,7 @@ void netfs_invalidate_folio(struct folio *folio, size_t= offset, size_t length) goto erase_completely; /* Move the start of the data. */ finfo->dirty_len =3D fend - iend; - finfo->dirty_offset =3D offset; + finfo->dirty_offset =3D iend; trace_netfs_folio(folio, netfs_folio_trace_invalidate_front); return; } From nobody Sat Jun 20 04:57:26 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 B5A35389116 for ; Mon, 20 Apr 2026 08:37:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674272; cv=none; b=qgy6gTHLCuuXpvOATs17GEPuAMYEr+GGTR5LG5UQj75IKylDC7AOiXdXF8mFiVr6lcP3Y/hfgDOsRp0eoVDtAq38+3AyT6KCvD9J6H6K7qKV6YciAoQmMqD8gqSEAReEEuG8OzTpREaA/TJ8eFyE5MxgGaD3lbk0NMgeOVghCdw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674272; c=relaxed/simple; bh=mtHnEjvRwJ+xdJf8DIqVxDhrtVHQt4N+eCpgfUIB8lY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kk4qSiGXglsyv5WKsTtI2sZwLBnuRENVKvDnberIcAkjEz/BhHTuw1pE3r1ZiyOIcLA05k54qyjLxhOsAhBSKwsg6LGzulYWzEFG/wrCsFTNIA2CF5OcX80CPuYhGLilE0BLvD1tXgGIrRg4oswiGcFoiBKbSIS5D+44dy8VSt0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=illMLO2Q; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="illMLO2Q" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1776674269; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Ob6xCMZuqNEj/Bt5UZPBU1fDVm9Ru5OkhDx15MsP/Ik=; b=illMLO2QZvs3U5kF0jpOjn31jN5AEmGPsNag1Z1GGqVzjG6Q/V87SKSwr91ZWtmgjVv3Jw zzjTyxxrABhFl3Y5ThAxbFUW/7ddLIMwtF4kx5UjF4aZsMEzEpw09kFEPNzoxpCkgwKgUf M5xcIWGK8AS11lQTPC+3eLXvFFsIOK0= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-63-G8XKq8e8P8akCl28AhsOsg-1; Mon, 20 Apr 2026 04:37:46 -0400 X-MC-Unique: G8XKq8e8P8akCl28AhsOsg-1 X-Mimecast-MFC-AGG-ID: G8XKq8e8P8akCl28AhsOsg_1776674264 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id B0F7819560A3; Mon, 20 Apr 2026 08:37:44 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.48.17]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A4663195608E; Mon, 20 Apr 2026 08:37:41 +0000 (UTC) From: David Howells To: Christian Brauner Cc: David Howells , Paulo Alcantara , netfs@lists.linux.dev, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Matthew Wilcox Subject: [PATCH 06/11] netfs: Fix the trace displayed for the total overwrite of a streamed write Date: Mon, 20 Apr 2026 09:36:57 +0100 Message-ID: <20260420083705.1009074-7-dhowells@redhat.com> In-Reply-To: <20260420083705.1009074-1-dhowells@redhat.com> References: <20260420083705.1009074-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Change netfs_perform_write() to carry the trace value in a variable and emit it later to make it easier to select the value displayed. Fix the display of netfs_streaming_write_cont in the "folio_now_filled:" section. It should only be set to that if we come from the section that filled in a gap in an already streamed write (and would otherwise display netfs_streaming_write_cont). If it came from the bit that just overwrites the entire folio (which would ordinarily display netfs_whole_folio_modify), make it display netfs_whole_folio_modify_filled instead. Fixes: 1bfeb53e990b ("netfs: Fix streaming write being overwritten") Closes: https://sashiko.dev/#/patchset/20260414082004.3756080-1-dhowells%40= redhat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: Matthew Wilcox cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/buffered_write.c | 27 ++++++++++++++++----------- include/trace/events/netfs.h | 1 + 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c index 6399141b4f0a..de82eb6ed473 100644 --- a/fs/netfs/buffered_write.c +++ b/fs/netfs/buffered_write.c @@ -150,6 +150,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct = iov_iter *iter, } =20 do { + enum netfs_folio_trace trace; struct netfs_folio *finfo; struct netfs_group *group; unsigned long long fpos; @@ -223,7 +224,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct = iov_iter *iter, if (unlikely(copied =3D=3D 0)) goto copy_failed; netfs_set_group(folio, netfs_group); - trace_netfs_folio(folio, netfs_folio_is_uptodate); + trace =3D netfs_folio_is_uptodate; goto copied; } =20 @@ -239,7 +240,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct = iov_iter *iter, folio_zero_segment(folio, offset + copied, flen); __netfs_set_group(folio, netfs_group); folio_mark_uptodate(folio); - trace_netfs_folio(folio, netfs_modify_and_clear); + trace =3D netfs_modify_and_clear; goto copied; } =20 @@ -247,11 +248,13 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struc= t iov_iter *iter, if (!maybe_trouble && offset =3D=3D 0 && part >=3D flen) { copied =3D copy_folio_from_iter_atomic(folio, offset, part, iter); if (likely(copied =3D=3D part)) { - if (finfo) + if (finfo) { + trace =3D netfs_whole_folio_modify_filled; goto folio_now_filled; + } __netfs_set_group(folio, netfs_group); folio_mark_uptodate(folio); - trace_netfs_folio(folio, netfs_whole_folio_modify); + trace =3D netfs_whole_folio_modify; goto copied; } if (copied =3D=3D 0) @@ -273,7 +276,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct = iov_iter *iter, if (copied > finfo->dirty_len) finfo->dirty_len =3D copied; finfo->dirty_offset =3D 0; - trace_netfs_folio(folio, netfs_whole_folio_modify_efault); + trace =3D netfs_whole_folio_modify_efault; goto copied; } =20 @@ -299,7 +302,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct = iov_iter *iter, if (unlikely(copied =3D=3D 0)) goto copy_failed; netfs_set_group(folio, netfs_group); - trace_netfs_folio(folio, netfs_just_prefetch); + trace =3D netfs_just_prefetch; goto copied; } =20 @@ -313,7 +316,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct = iov_iter *iter, if (offset =3D=3D 0 && copied =3D=3D flen) { __netfs_set_group(folio, netfs_group); folio_mark_uptodate(folio); - trace_netfs_folio(folio, netfs_streaming_filled_page); + trace =3D netfs_streaming_filled_page; goto copied; } =20 @@ -328,7 +331,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct = iov_iter *iter, finfo->dirty_len =3D copied; folio_attach_private(folio, (void *)((unsigned long)finfo | NETFS_FOLIO_INFO)); - trace_netfs_folio(folio, netfs_streaming_write); + trace =3D netfs_streaming_write; goto copied; } =20 @@ -341,9 +344,11 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct= iov_iter *iter, if (unlikely(copied =3D=3D 0)) goto copy_failed; finfo->dirty_len +=3D copied; - if (finfo->dirty_offset =3D=3D 0 && finfo->dirty_len =3D=3D flen) + if (finfo->dirty_offset =3D=3D 0 && finfo->dirty_len =3D=3D flen) { + trace =3D netfs_streaming_cont_filled_page; goto folio_now_filled; - trace_netfs_folio(folio, netfs_streaming_write_cont); + } + trace =3D netfs_streaming_write_cont; goto copied; } =20 @@ -364,8 +369,8 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct = iov_iter *iter, folio_detach_private(folio); folio_mark_uptodate(folio); kfree(finfo); - trace_netfs_folio(folio, netfs_streaming_cont_filled_page); copied: + trace_netfs_folio(folio, trace); flush_dcache_folio(folio); =20 /* Update the inode size if we moved the EOF marker */ diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index ee7fea84f055..67f6d56c94ce 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -178,6 +178,7 @@ EM(netfs_just_prefetch, "mod-prefetch") \ EM(netfs_whole_folio_modify, "mod-whole-f") \ EM(netfs_whole_folio_modify_efault, "mod-whole-f!") \ + EM(netfs_whole_folio_modify_filled, "mod-whole-f+") \ EM(netfs_modify_and_clear, "mod-n-clear") \ EM(netfs_streaming_write, "mod-streamw") \ EM(netfs_streaming_write_cont, "mod-streamw+") \ From nobody Sat Jun 20 04:57:26 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 ADC593921D8 for ; Mon, 20 Apr 2026 08:38:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674284; cv=none; b=ln/CzZaU2ua0OYCsoFVBfBsXgcLmJxu+YRmndebHgl0grWOj+QvPx/VaNwbvO5y78UQ5kCmbyKgTjwWd1p/hYkSjx1ez0chsKHmC6niUFOsbxLWcircLezVsniHL1oISVePTiFjlbx6/CRDCxUlrfOEcqOxEzPyHHxzgX+g9S+8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674284; c=relaxed/simple; bh=/KQmIgTJOCbv3hSfJO6jdQBY7LkyB0snaK0Rln8lc44=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ofewa8UrwDn6i1foF8K1zg1WPxNAlQuVuadrJ6h/IqLEFEJreQE7ennvxB/reahaSA/eO873svASQaB8shIUeb9IySHt9yBcaNRIh9xIgz9XfZGf6HjKbwKLhIYLxhpSkkh3vFdWfYfEZM/eUHUfHueyQU3NLyuvTxmvho7tguA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=NBhoRCYy; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="NBhoRCYy" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1776674281; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=9ftIxL41sEcAmEulwDX61ztIHIDAalQGRDwa5IsOQFo=; b=NBhoRCYyw3mrujoJDEIPk2of3QRfu77pntsvw62Y4WJgKAu5Na2M8ZZnThrwydcAlOxGY6 QpK9Hv9BV2sVlsUsuXLCbPpQxYf9/jsgP6oJb4FXic3Ccp31zCSb9L0Z8zfcigpXdfR9LK BapzN0q9cGVLD5IsusGiGz43xytmFDQ= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-404--ZYaFUxaOtG8rCXPe9qVwg-1; Mon, 20 Apr 2026 04:37:51 -0400 X-MC-Unique: -ZYaFUxaOtG8rCXPe9qVwg-1 X-Mimecast-MFC-AGG-ID: -ZYaFUxaOtG8rCXPe9qVwg_1776674269 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D09631800578; Mon, 20 Apr 2026 08:37:49 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.48.17]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 6AB753000C20; Mon, 20 Apr 2026 08:37:46 +0000 (UTC) From: David Howells To: Christian Brauner Cc: David Howells , Paulo Alcantara , netfs@lists.linux.dev, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Matthew Wilcox Subject: [PATCH 07/11] netfs: Fix folio->private handling in netfs_perform_write() Date: Mon, 20 Apr 2026 09:36:58 +0100 Message-ID: <20260420083705.1009074-8-dhowells@redhat.com> In-Reply-To: <20260420083705.1009074-1-dhowells@redhat.com> References: <20260420083705.1009074-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Under some circumstances, netfs_perform_write() doesn't correctly manipulate folio->private between NULL, NETFS_FOLIO_COPY_TO_CACHE, pointing to a group and pointing to a netfs_folio struct, leading to potential multiple attachments of private data with associated folio ref leaks and also leaks of netfs_folio structs or netfs_group refs. Fix this by consolidating the place at which a folio is marked uptodate in one place and having that look at what's attached to folio->private and decide how to clean it up and then set the new group. Also, the content shouldn't be flushed if group is NULL, even if a group is specified in the netfs_group parameter, as that would be the case for a new folio. A filesystem should always specify netfs_group or never specify netfs_group. The Sashiko auto-review tool noted that it was theoretically possible that the fpos >=3D ctx->zero_point section might leak if it modified a streaming write folio. This is unlikely, but with a network filesystem, third party changes can happen. It also pointed out that __netfs_set_group() would leak if called multiple times on the same folio from the "whole folio modify section". Fixes: 8f52de0077ba ("netfs: Reduce number of conditional branches in netfs= _perform_write()") Closes: https://sashiko.dev/#/patchset/20260414082004.3756080-1-dhowells%40= redhat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: Matthew Wilcox cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/buffered_write.c | 77 +++++++++++++++++++++--------------- include/trace/events/netfs.h | 2 + 2 files changed, 48 insertions(+), 31 deletions(-) diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c index de82eb6ed473..0ca8e922790d 100644 --- a/fs/netfs/buffered_write.c +++ b/fs/netfs/buffered_write.c @@ -13,12 +13,6 @@ #include #include "internal.h" =20 -static void __netfs_set_group(struct folio *folio, struct netfs_group *net= fs_group) -{ - if (netfs_group) - folio_attach_private(folio, netfs_get_group(netfs_group)); -} - static void netfs_set_group(struct folio *folio, struct netfs_group *netfs= _group) { void *priv =3D folio_get_private(folio); @@ -158,6 +152,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct = iov_iter *iter, size_t offset; /* Offset into pagecache folio */ size_t part; /* Bytes to write to folio */ size_t copied; /* Bytes copied from user */ + void *priv; =20 offset =3D pos & (max_chunk - 1); part =3D min(max_chunk - offset, iov_iter_count(iter)); @@ -213,8 +208,9 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct = iov_iter *iter, finfo =3D netfs_folio_info(folio); group =3D netfs_folio_group(folio); =20 - if (unlikely(group !=3D netfs_group) && - group !=3D NETFS_FOLIO_COPY_TO_CACHE) + if (unlikely(group) && + group !=3D NETFS_FOLIO_COPY_TO_CACHE && + group !=3D netfs_group) goto flush_content; =20 if (folio_test_uptodate(folio)) { @@ -238,24 +234,22 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struc= t iov_iter *iter, if (unlikely(copied =3D=3D 0)) goto copy_failed; folio_zero_segment(folio, offset + copied, flen); - __netfs_set_group(folio, netfs_group); - folio_mark_uptodate(folio); - trace =3D netfs_modify_and_clear; - goto copied; + if (finfo) + trace =3D netfs_modify_and_clear_rm_finfo; + else + trace =3D netfs_modify_and_clear; + goto mark_uptodate; } =20 /* See if we can write a whole folio in one go. */ if (!maybe_trouble && offset =3D=3D 0 && part >=3D flen) { copied =3D copy_folio_from_iter_atomic(folio, offset, part, iter); if (likely(copied =3D=3D part)) { - if (finfo) { + if (finfo) trace =3D netfs_whole_folio_modify_filled; - goto folio_now_filled; - } - __netfs_set_group(folio, netfs_group); - folio_mark_uptodate(folio); - trace =3D netfs_whole_folio_modify; - goto copied; + else + trace =3D netfs_whole_folio_modify; + goto mark_uptodate; } if (copied =3D=3D 0) goto copy_failed; @@ -271,8 +265,10 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct= iov_iter *iter, * accept the partial write. */ finfo->dirty_len +=3D finfo->dirty_offset; - if (finfo->dirty_len =3D=3D flen) - goto folio_now_filled; + if (finfo->dirty_len =3D=3D flen) { + trace =3D netfs_whole_folio_modify_filled_efault; + goto mark_uptodate; + } if (copied > finfo->dirty_len) finfo->dirty_len =3D copied; finfo->dirty_offset =3D 0; @@ -306,6 +302,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct = iov_iter *iter, goto copied; } =20 + /* Do a streaming write on a folio that has nothing in it yet. */ if (!finfo) { ret =3D -EIO; if (WARN_ON(folio_get_private(folio))) @@ -314,10 +311,8 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct= iov_iter *iter, if (unlikely(copied =3D=3D 0)) goto copy_failed; if (offset =3D=3D 0 && copied =3D=3D flen) { - __netfs_set_group(folio, netfs_group); - folio_mark_uptodate(folio); trace =3D netfs_streaming_filled_page; - goto copied; + goto mark_uptodate; } =20 finfo =3D kzalloc_obj(*finfo); @@ -346,7 +341,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct = iov_iter *iter, finfo->dirty_len +=3D copied; if (finfo->dirty_offset =3D=3D 0 && finfo->dirty_len =3D=3D flen) { trace =3D netfs_streaming_cont_filled_page; - goto folio_now_filled; + goto mark_uptodate; } trace =3D netfs_streaming_write_cont; goto copied; @@ -362,13 +357,33 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struc= t iov_iter *iter, goto out; continue; =20 - folio_now_filled: - if (finfo->netfs_group) - folio_change_private(folio, finfo->netfs_group); - else - folio_detach_private(folio); + /* Mark a folio as being up to data when we've filled it + * completely. If the folio has a group attached, then it must + * be the same group, otherwise we should have flushed it out + * above. We have to get rid of the netfs_folio struct if + * there was one. + */ + mark_uptodate: + priv =3D folio_get_private(folio); + if (likely(priv =3D=3D netfs_group)) { + /* Already set correctly; no change required. */ + } else if (priv =3D=3D NETFS_FOLIO_COPY_TO_CACHE) { + if (!netfs_group) + folio_detach_private(folio); + else + folio_change_private(folio, netfs_get_group(netfs_group)); + } else if (!priv) { + folio_attach_private(folio, netfs_get_group(netfs_group)); + } else { + WARN_ON_ONCE(!finfo); + if (netfs_group) + /* finfo->netfs_group has a ref */ + folio_change_private(folio, netfs_group); + else + folio_detach_private(folio); + kfree(finfo); + } folio_mark_uptodate(folio); - kfree(finfo); copied: trace_netfs_folio(folio, trace); flush_dcache_folio(folio); diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index 67f6d56c94ce..1f5e3a5af08a 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -179,7 +179,9 @@ EM(netfs_whole_folio_modify, "mod-whole-f") \ EM(netfs_whole_folio_modify_efault, "mod-whole-f!") \ EM(netfs_whole_folio_modify_filled, "mod-whole-f+") \ + EM(netfs_whole_folio_modify_filled_efault, "mod-whole-f+!") \ EM(netfs_modify_and_clear, "mod-n-clear") \ + EM(netfs_modify_and_clear_rm_finfo, "mod-n-clear+") \ EM(netfs_streaming_write, "mod-streamw") \ EM(netfs_streaming_write_cont, "mod-streamw+") \ EM(netfs_flush_content, "flush") \ From nobody Sat Jun 20 04:57:26 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 060B4389E05 for ; Mon, 20 Apr 2026 08:37:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674281; cv=none; b=MqeQ35J9np/538CjghtjpERuRR4GimUncQMbOYVYoCQh9M5T3Zt09f0U6+zYUt5cEu748wl3WBqxgDMGe3BQ7gzwmLw5qr6nm/04tZrRE1822zTVTMqZ6OxQn5dXB8ZpbDkVqniuZn8ZW2NxM1bjHK9/c4TQmIe5eAMVnEMsecA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674281; c=relaxed/simple; bh=GGDFb5ISDq+aR8ATjSzxtl5omBuaGFifLzzJCHqEBkw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=VP77kL6kuiuq3S5whdmKlYQjEUWZ8aYkC77+tGYexqzZwBb3HlzFefuu8HwKZhv+O+qb4a7ppWaDDqLH00qcayxIc3LGyxTC8nHeVe4VottRb/4EJgsxe5EfOKDKDoso9fOMCosIm2nxMTxwxjC/NE7ilTQZVfKgOOZ72HQlEwA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=h86SMyOQ; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="h86SMyOQ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1776674279; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OThphTeJ4h2mrXd17LwJkpBdeaA+i2LzOzBKWtPenbI=; b=h86SMyOQXboDEAqaggqxx69A1R7Dh+FA8hM/62mVoUkwA5XvPm/xT4dIxu6LV93hz0r7SN c3F6nNlbbReO9bl0ZGSWBtwXo/HKPn4N7VxDC4JfSzIBmDVWX0sck2JeBKSYcfS95YuFZ5 F/JAcrCzbgSsfbCAjpknr47MM4lfsw0= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-467-sRAaOMn4OZqrasR8f5rHrA-1; Mon, 20 Apr 2026 04:37:56 -0400 X-MC-Unique: sRAaOMn4OZqrasR8f5rHrA-1 X-Mimecast-MFC-AGG-ID: sRAaOMn4OZqrasR8f5rHrA_1776674274 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8668C1955F0E; Mon, 20 Apr 2026 08:37:54 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.48.17]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 8BC801800660; Mon, 20 Apr 2026 08:37:51 +0000 (UTC) From: David Howells To: Christian Brauner Cc: David Howells , Paulo Alcantara , netfs@lists.linux.dev, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Matthew Wilcox Subject: [PATCH 08/11] netfs: Fix group handling in netfs_read_gaps() Date: Mon, 20 Apr 2026 09:36:59 +0100 Message-ID: <20260420083705.1009074-9-dhowells@redhat.com> In-Reply-To: <20260420083705.1009074-1-dhowells@redhat.com> References: <20260420083705.1009074-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Content-Type: text/plain; charset="utf-8" Fix netfs_read_gaps() to not discard the group information from the netfs_folio struct after successfully reading the gaps. This is still needed to write back the dirty data. Fixes: d259cfb7dd32 ("netfs: Fix read-gaps to remove netfs_folio from fille= d folio") Closes: https://sashiko.dev/#/patchset/20260414082004.3756080-1-dhowells%40= redhat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: Matthew Wilcox cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/buffered_read.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index b4d271538f75..98bfec0af0e1 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -461,8 +461,10 @@ static int netfs_read_gaps(struct file *file, struct f= olio *folio) =20 ret =3D netfs_wait_for_read(rreq); if (ret >=3D 0) { - folio_detach_private(folio); - netfs_put_group(group); + if (group) + folio_change_private(folio, group); + else + folio_detach_private(folio); kfree(finfo); trace_netfs_folio(folio, netfs_folio_trace_filled_gaps); flush_dcache_folio(folio); From nobody Sat Jun 20 04:57:26 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 894E338F645 for ; Mon, 20 Apr 2026 08:38:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674288; cv=none; b=sMWoTvAHQkhN45DvIYk0byYITFr0h6u5kzlOOLzGDZYYOT2kw9YPwXeRvWagBjMDBZschW3w2QGyt2CwsEI7+WW3tMOJe1TZRcKgMXwC1LdREss9yQbJzBloe9emrV1rm+LucKOG4QxuEPH0VwTMFB8qfiypGX+K9RPw3L0ImfQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674288; c=relaxed/simple; bh=M4G7CQ90pI0guOT8qdXsIFfuTO8z4pu+AYho3qmmbvI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p/IOp8sskbACNLCYqer1zjJQTHMiWWasw1ZqO/HdTN6byU3Gzcc8kIO6x7fdHTdXTQc9u8qbMQLJ5fKJN9W8dl5J4b40ZQ6Ffkp6SyOuEzXWtmBnJTgyJW0ZjFQlnKEdpLqC1NyNNH81zUlv8nbziEjm4dh6APwfLDQYmyWMG8w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Flanvbd+; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Flanvbd+" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1776674284; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=I5D+Oxw+ox5fGkrZ90uYeUrfVkAZVJhvtSK5/NHTQNY=; b=Flanvbd+URjrKPkgWzggWPUB/KQz+N5EcqtdCCSIqnepbm4DgKCNg3WQgYdamDjCPhYMAr UYF6CaEtiRqRXLODypY1m6vISQxo89lcxbOUjF4CMXm5c4MuxXn+Gb12NSK5WyaU7uc9Fo AxtJxlEDxa+HZVhICrqV6l2ZbNhcjVE= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-156-684tbrelMNmXQAwFCRwFlA-1; Mon, 20 Apr 2026 04:38:01 -0400 X-MC-Unique: 684tbrelMNmXQAwFCRwFlA-1 X-Mimecast-MFC-AGG-ID: 684tbrelMNmXQAwFCRwFlA_1776674279 Received: from mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 649701800473; Mon, 20 Apr 2026 08:37:59 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.48.17]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 289F81801481; Mon, 20 Apr 2026 08:37:55 +0000 (UTC) From: David Howells To: Christian Brauner Cc: David Howells , Paulo Alcantara , netfs@lists.linux.dev, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Matthew Wilcox Subject: [PATCH 09/11] netfs: Fix potential for tearing in ->remote_i_size and ->zero_point Date: Mon, 20 Apr 2026 09:37:00 +0100 Message-ID: <20260420083705.1009074-10-dhowells@redhat.com> In-Reply-To: <20260420083705.1009074-1-dhowells@redhat.com> References: <20260420083705.1009074-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.93 Content-Type: text/plain; charset="utf-8" Fix potential tearing in using ->remote_i_size and ->zero_point by copying i_size_read() and i_size_write() and using the same seqcount as for i_size. Fixes: 4058f742105e ("netfs: Keep track of the actual remote file size") Fixes: 100ccd18bb41 ("netfs: Optimise away reads above the point at which t= here can be no data") Closes: https://sashiko.dev/#/patchset/20260414082004.3756080-1-dhowells%40= redhat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: Matthew Wilcox cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/9p/vfs_inode.c | 2 +- fs/9p/vfs_inode_dotl.c | 4 +- fs/afs/inode.c | 8 +- fs/afs/write.c | 2 +- fs/netfs/buffered_read.c | 5 +- fs/netfs/buffered_write.c | 2 +- fs/netfs/direct_write.c | 4 +- fs/netfs/misc.c | 13 +- fs/netfs/write_collect.c | 3 +- fs/smb/client/cifsfs.c | 24 +-- fs/smb/client/cifssmb.c | 2 +- fs/smb/client/file.c | 9 +- fs/smb/client/inode.c | 9 +- fs/smb/client/readdir.c | 3 +- fs/smb/client/smb2ops.c | 16 +- fs/smb/client/smb2pdu.c | 2 +- include/linux/netfs.h | 299 ++++++++++++++++++++++++++++++++++++-- 17 files changed, 348 insertions(+), 59 deletions(-) diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index d1508b1fe109..b13156ac2f1f 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -1141,7 +1141,7 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *= inode, mode |=3D inode->i_mode & ~S_IALLUGO; inode->i_mode =3D mode; =20 - v9inode->netfs.remote_i_size =3D stat->length; + netfs_write_remote_i_size(&v9inode->netfs, stat->length); if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE)) v9fs_i_size_write(inode, stat->length); /* not real number of blocks, but 512 byte ones ... */ diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 71796a89bcf4..81d6150a8ae4 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -634,7 +634,7 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct = inode *inode, mode |=3D inode->i_mode & ~S_IALLUGO; inode->i_mode =3D mode; =20 - v9inode->netfs.remote_i_size =3D stat->st_size; + netfs_write_remote_i_size(&v9inode->netfs, stat->st_size); if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE)) v9fs_i_size_write(inode, stat->st_size); inode->i_blocks =3D stat->st_blocks; @@ -664,7 +664,7 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct = inode *inode, } if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE) && stat->st_result_mask & P9_STATS_SIZE) { - v9inode->netfs.remote_i_size =3D stat->st_size; + netfs_write_remote_i_size(&v9inode->netfs, stat->st_size); v9fs_i_size_write(inode, stat->st_size); } if (stat->st_result_mask & P9_STATS_BLOCKS) diff --git a/fs/afs/inode.c b/fs/afs/inode.c index a5173434f786..06e25e1b12df 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -343,11 +343,11 @@ static void afs_apply_status(struct afs_operation *op, * idea of what the size should be that's not the same as * what's on the server. */ - vnode->netfs.remote_i_size =3D status->size; + netfs_write_remote_i_size(&vnode->netfs, status->size); if (change_size || status->size > i_size_read(inode)) { afs_set_i_size(vnode, status->size); if (unexpected_jump) - vnode->netfs.zero_point =3D status->size; + netfs_write_zero_point(&vnode->netfs, status->size); inode_set_ctime_to_ts(inode, t); inode_set_atime_to_ts(inode, t); } @@ -709,7 +709,7 @@ int afs_getattr(struct mnt_idmap *idmap, const struct p= ath *path, * it, but we need to give userspace the server's size. */ if (S_ISDIR(inode->i_mode)) - stat->size =3D vnode->netfs.remote_i_size; + stat->size =3D netfs_read_remote_i_size(&vnode->netfs); } while (read_seqretry(&vnode->cb_lock, seq)); =20 return 0; @@ -889,7 +889,7 @@ int afs_setattr(struct mnt_idmap *idmap, struct dentry = *dentry, */ if (!(attr->ia_valid & (supported & ~ATTR_SIZE & ~ATTR_MTIME)) && attr->ia_size < i_size && - attr->ia_size > vnode->netfs.remote_i_size) { + attr->ia_size > netfs_read_remote_i_size(&vnode->netfs)) { truncate_setsize(inode, attr->ia_size); netfs_resize_file(&vnode->netfs, size, false); fscache_resize_cookie(afs_vnode_cache(vnode), diff --git a/fs/afs/write.c b/fs/afs/write.c index 93ad86ff3345..a82ad996dc22 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c @@ -143,7 +143,7 @@ static void afs_issue_write_worker(struct work_struct *= work) afs_begin_vnode_operation(op); =20 op->store.write_iter =3D &subreq->io_iter; - op->store.i_size =3D umax(pos + len, vnode->netfs.remote_i_size); + op->store.i_size =3D umax(pos + len, netfs_read_remote_i_size(&vnode->net= fs)); op->mtime =3D inode_get_mtime(&vnode->netfs.inode); =20 afs_wait_for_operation(op); diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index 98bfec0af0e1..4d6dfcffba78 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -236,7 +236,8 @@ static void netfs_read_to_pagecache(struct netfs_io_req= uest *rreq, source =3D netfs_cache_prepare_read(rreq, subreq, rreq->i_size); subreq->source =3D source; if (source =3D=3D NETFS_DOWNLOAD_FROM_SERVER) { - unsigned long long zp =3D umin(ictx->zero_point, rreq->i_size); + unsigned long long zero_point =3D netfs_read_zero_point(ictx); + unsigned long long zp =3D umin(zero_point, rreq->i_size); size_t len =3D subreq->len; =20 if (unlikely(rreq->origin =3D=3D NETFS_READ_SINGLE)) @@ -252,7 +253,7 @@ static void netfs_read_to_pagecache(struct netfs_io_req= uest *rreq, pr_err("ZERO-LEN READ: R=3D%08x[%x] l=3D%zx/%zx s=3D%llx z=3D%llx i=3D= %llx", rreq->debug_id, subreq->debug_index, subreq->len, size, - subreq->start, ictx->zero_point, rreq->i_size); + subreq->start, zero_point, rreq->i_size); break; } subreq->len =3D len; diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c index 0ca8e922790d..c840f5448178 100644 --- a/fs/netfs/buffered_write.c +++ b/fs/netfs/buffered_write.c @@ -228,7 +228,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct = iov_iter *iter, * server would just return a block of zeros or a short read if * we try to read it. */ - if (fpos >=3D ctx->zero_point) { + if (fpos >=3D netfs_read_zero_point(ctx)) { folio_zero_segment(folio, 0, offset); copied =3D copy_folio_from_iter_atomic(folio, offset, part, iter); if (unlikely(copied =3D=3D 0)) diff --git a/fs/netfs/direct_write.c b/fs/netfs/direct_write.c index f9ab69de3e29..96c1dad04168 100644 --- a/fs/netfs/direct_write.c +++ b/fs/netfs/direct_write.c @@ -376,8 +376,8 @@ ssize_t netfs_unbuffered_write_iter(struct kiocb *iocb,= struct iov_iter *from) if (ret < 0) goto out; end =3D iocb->ki_pos + iov_iter_count(from); - if (end > ictx->zero_point) - ictx->zero_point =3D end; + if (end > netfs_read_zero_point(ictx)) + netfs_write_zero_point(ictx, end); =20 fscache_invalidate(netfs_i_cookie(ictx), NULL, i_size_read(inode), FSCACHE_INVAL_DIO_WRITE); diff --git a/fs/netfs/misc.c b/fs/netfs/misc.c index 8b457124b0e3..1f09733e50a8 100644 --- a/fs/netfs/misc.c +++ b/fs/netfs/misc.c @@ -221,8 +221,8 @@ void netfs_invalidate_folio(struct folio *folio, size_t= offset, size_t length) unsigned long long fpos =3D folio_pos(folio), end; =20 end =3D umin(fpos + flen, i_size); - if (fpos < i_size && end > ctx->zero_point) - ctx->zero_point =3D end; + if (fpos < i_size && end > netfs_read_zero_point(ctx)) + netfs_write_zero_point(ctx, end); } =20 folio_wait_private_2(folio); /* [DEPRECATED] */ @@ -297,14 +297,15 @@ EXPORT_SYMBOL(netfs_invalidate_folio); bool netfs_release_folio(struct folio *folio, gfp_t gfp) { struct netfs_inode *ctx =3D netfs_inode(folio_inode(folio)); - unsigned long long end; + unsigned long long remote_i_size, zero_point, end; =20 if (folio_test_dirty(folio)) return false; =20 - end =3D umin(folio_next_pos(folio), ctx->remote_i_size); - if (end > ctx->zero_point) - ctx->zero_point =3D end; + netfs_read_sizes(ctx, &remote_i_size, &zero_point); + end =3D umin(folio_next_pos(folio), remote_i_size); + if (end > zero_point) + netfs_write_zero_point(ctx, end); =20 if (folio_test_private(folio)) return false; diff --git a/fs/netfs/write_collect.c b/fs/netfs/write_collect.c index b194447f4b11..4718e5174d65 100644 --- a/fs/netfs/write_collect.c +++ b/fs/netfs/write_collect.c @@ -69,8 +69,7 @@ int netfs_folio_written_back(struct folio *folio) unsigned long long fend; =20 fend =3D folio_pos(folio) + finfo->dirty_offset + finfo->dirty_len; - if (fend > ictx->zero_point) - ictx->zero_point =3D fend; + netfs_push_back_zero_point(ictx, fend); =20 folio_detach_private(folio); group =3D finfo->netfs_group; diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c index 2025739f070a..382dccbc3507 100644 --- a/fs/smb/client/cifsfs.c +++ b/fs/smb/client/cifsfs.c @@ -471,7 +471,8 @@ cifs_alloc_inode(struct super_block *sb) spin_lock_init(&cifs_inode->writers_lock); cifs_inode->writers =3D 0; cifs_inode->netfs.inode.i_blkbits =3D 14; /* 2**14 =3D CIFS_MAX_MSGSIZE = */ - cifs_inode->netfs.remote_i_size =3D 0; + cifs_inode->netfs._remote_i_size =3D 0; + cifs_inode->netfs._zero_point =3D 0; cifs_inode->uniqueid =3D 0; cifs_inode->createtime =3D 0; cifs_inode->epoch =3D 0; @@ -1340,7 +1341,7 @@ static loff_t cifs_remap_file_range(struct file *src_= file, loff_t off, struct cifsFileInfo *smb_file_src =3D src_file->private_data; struct cifsFileInfo *smb_file_target =3D dst_file->private_data; struct cifs_tcon *target_tcon, *src_tcon; - unsigned long long destend, fstart, fend, old_size, new_size; + unsigned long long destend, fstart, fend, old_size, new_size, zero_point; unsigned int xid; int rc; =20 @@ -1384,7 +1385,7 @@ static loff_t cifs_remap_file_range(struct file *src_= file, loff_t off, * Advance the EOF marker after the flush above to the end of the range * if it's short of that. */ - if (src_cifsi->netfs.remote_i_size < off + len) { + if (netfs_read_remote_i_size(&src_cifsi->netfs) < off + len) { rc =3D cifs_precopy_set_eof(src_inode, src_cifsi, src_tcon, xid, off + l= en); if (rc < 0) goto unlock; @@ -1405,9 +1406,10 @@ static loff_t cifs_remap_file_range(struct file *src= _file, loff_t off, rc =3D cifs_flush_folio(target_inode, destend, &fstart, &fend, false); if (rc) goto unlock; - if (fend > target_cifsi->netfs.zero_point) - target_cifsi->netfs.zero_point =3D fend + 1; - old_size =3D target_cifsi->netfs.remote_i_size; + + netfs_read_sizes(&target_cifsi->netfs, &old_size, &zero_point); + if (fend > zero_point) + netfs_write_zero_point(&target_cifsi->netfs, fend + 1); =20 /* Discard all the folios that overlap the destination region. */ cifs_dbg(FYI, "about to discard pages %llx-%llx\n", fstart, fend); @@ -1439,8 +1441,8 @@ static loff_t cifs_remap_file_range(struct file *src_= file, loff_t off, rc =3D -EINVAL; } } - if (rc =3D=3D 0 && new_size > target_cifsi->netfs.zero_point) - target_cifsi->netfs.zero_point =3D new_size; + if (rc =3D=3D 0) + netfs_push_back_zero_point(&target_cifsi->netfs, new_size); } =20 /* force revalidate of size and timestamps of target file now @@ -1511,7 +1513,7 @@ ssize_t cifs_file_copychunk_range(unsigned int xid, * Advance the EOF marker after the flush above to the end of the range * if it's short of that. */ - if (src_cifsi->netfs.remote_i_size < off + len) { + if (netfs_read_remote_i_size(&src_cifsi->netfs) < off + len) { rc =3D cifs_precopy_set_eof(src_inode, src_cifsi, src_tcon, xid, off + l= en); if (rc < 0) goto unlock; @@ -1539,8 +1541,8 @@ ssize_t cifs_file_copychunk_range(unsigned int xid, fscache_resize_cookie(cifs_inode_cookie(target_inode), i_size_read(target_inode)); } - if (rc > 0 && destoff + rc > target_cifsi->netfs.zero_point) - target_cifsi->netfs.zero_point =3D destoff + rc; + if (rc > 0) + netfs_push_back_zero_point(&target_cifsi->netfs, destoff + rc); } =20 file_accessed(src_file); diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c index 3990a9012264..102dd9dde760 100644 --- a/fs/smb/client/cifssmb.c +++ b/fs/smb/client/cifssmb.c @@ -1538,7 +1538,7 @@ cifs_readv_callback(struct TCP_Server_Info *server, s= truct mid_q_entry *mid) } else { size_t trans =3D rdata->subreq.transferred + rdata->got_bytes; if (trans < rdata->subreq.len && - rdata->subreq.start + trans >=3D ictx->remote_i_size) { + rdata->subreq.start + trans >=3D netfs_read_remote_i_size(ictx)) { rdata->result =3D 0; __set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags); } else if (rdata->got_bytes > 0) { diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c index 5d5b49468aff..ec1b1198642c 100644 --- a/fs/smb/client/file.c +++ b/fs/smb/client/file.c @@ -2502,16 +2502,19 @@ void cifs_write_subrequest_terminated(struct cifs_i= o_subrequest *wdata, ssize_t { struct netfs_io_request *wreq =3D wdata->rreq; struct netfs_inode *ictx =3D netfs_inode(wreq->inode); + unsigned long long remote_i_size, zero_point; loff_t wrend; =20 if (result > 0) { + netfs_read_sizes(ictx, &remote_i_size, &zero_point); + wrend =3D wdata->subreq.start + wdata->subreq.transferred + result; =20 - if (wrend > ictx->zero_point && + if (wrend > zero_point && (wdata->rreq->origin =3D=3D NETFS_UNBUFFERED_WRITE || wdata->rreq->origin =3D=3D NETFS_DIO_WRITE)) - ictx->zero_point =3D wrend; - if (wrend > ictx->remote_i_size) + netfs_write_zero_point(ictx, wrend); + if (wrend > remote_i_size) netfs_resize_file(ictx, wrend, true); } =20 diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c index 24040909d184..4189741d63fe 100644 --- a/fs/smb/client/inode.c +++ b/fs/smb/client/inode.c @@ -119,7 +119,7 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_= fattr *fattr) fattr->cf_mtime =3D timestamp_truncate(fattr->cf_mtime, inode); mtime =3D inode_get_mtime(inode); if (timespec64_equal(&mtime, &fattr->cf_mtime) && - cifs_i->netfs.remote_i_size =3D=3D fattr->cf_eof) { + netfs_read_remote_i_size(&cifs_i->netfs) =3D=3D fattr->cf_eof) { cifs_dbg(FYI, "%s: inode %llu is unchanged\n", __func__, cifs_i->uniqueid); return; @@ -174,7 +174,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fa= ttr *fattr, return -ESTALE; } if (inode_state_read_once(inode) & I_NEW) - CIFS_I(inode)->netfs.zero_point =3D fattr->cf_eof; + netfs_write_zero_point(&CIFS_I(inode)->netfs, fattr->cf_eof); =20 cifs_revalidate_cache(inode, fattr); =20 @@ -212,7 +212,7 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fa= ttr *fattr, else clear_bit(CIFS_INO_DELETE_PENDING, &cifs_i->flags); =20 - cifs_i->netfs.remote_i_size =3D fattr->cf_eof; + netfs_write_remote_i_size(&cifs_i->netfs, fattr->cf_eof); /* * Can't safely change the file size here if the client is writing to * it due to potential races. @@ -2772,7 +2772,8 @@ cifs_revalidate_mapping(struct inode *inode) if (cifs_sb_flags(cifs_sb) & CIFS_MOUNT_RW_CACHE) goto skip_invalidate; =20 - cifs_inode->netfs.zero_point =3D cifs_inode->netfs.remote_i_size; + netfs_write_zero_point(&cifs_inode->netfs, + netfs_read_remote_i_size(&cifs_inode->netfs)); rc =3D filemap_invalidate_inode(inode, true, 0, LLONG_MAX); if (rc) { cifs_dbg(VFS, "%s: invalidate inode %p failed with rc %d\n", diff --git a/fs/smb/client/readdir.c b/fs/smb/client/readdir.c index be22bbc4a65a..d88682e89ec0 100644 --- a/fs/smb/client/readdir.c +++ b/fs/smb/client/readdir.c @@ -143,7 +143,8 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *n= ame, fattr->cf_rdev =3D inode->i_rdev; fattr->cf_uid =3D inode->i_uid; fattr->cf_gid =3D inode->i_gid; - fattr->cf_eof =3D CIFS_I(inode)->netfs.remote_i_size; + fattr->cf_eof =3D + netfs_read_remote_i_size(&CIFS_I(inode)->netfs); fattr->cf_symlink_target =3D NULL; } else { CIFS_I(inode)->time =3D 0; diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 509fcea28a42..5550d9c55ab2 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -3398,7 +3398,7 @@ static long smb3_zero_range(struct file *file, struct= cifs_tcon *tcon, filemap_invalidate_lock(inode->i_mapping); =20 i_size =3D i_size_read(inode); - remote_size =3D ictx->remote_i_size; + remote_size =3D netfs_read_remote_i_size(ictx); if (offset + len >=3D remote_size && offset < i_size) { unsigned long long top =3D umin(offset + len, i_size); =20 @@ -3433,8 +3433,8 @@ static long smb3_zero_range(struct file *file, struct= cifs_tcon *tcon, if (rc >=3D 0) { truncate_setsize(inode, new_size); netfs_resize_file(&cifsi->netfs, new_size, true); - if (offset < cifsi->netfs.zero_point) - cifsi->netfs.zero_point =3D offset; + if (offset < netfs_read_zero_point(&cifsi->netfs)) + netfs_write_zero_point(&cifsi->netfs, offset); fscache_resize_cookie(cifs_inode_cookie(inode), new_size); } } @@ -3500,13 +3500,13 @@ static long smb3_punch_hole(struct file *file, stru= ct cifs_tcon *tcon, * EOF update will end up in the wrong place. */ i_size =3D i_size_read(inode); - remote_i_size =3D netfs_inode(inode)->remote_i_size; + remote_i_size =3D netfs_read_remote_i_size(netfs_inode(inode)); if (end > remote_i_size && i_size > remote_i_size) { unsigned long long extend_to =3D umin(end, i_size); rc =3D SMB2_set_eof(xid, tcon, cfile->fid.persistent_fid, cfile->fid.volatile_fid, cfile->pid, extend_to); if (rc >=3D 0) - netfs_inode(inode)->remote_i_size =3D extend_to; + netfs_write_remote_i_size(netfs_inode(inode), extend_to); } =20 unlock: @@ -3788,7 +3788,7 @@ static long smb3_collapse_range(struct file *file, st= ruct cifs_tcon *tcon, goto out_2; =20 truncate_pagecache_range(inode, off, old_eof); - ictx->zero_point =3D old_eof; + netfs_write_zero_point(ictx, old_eof); netfs_wait_for_outstanding_io(inode); =20 rc =3D smb2_copychunk_range(xid, cfile, cfile, off + len, @@ -3806,7 +3806,7 @@ static long smb3_collapse_range(struct file *file, st= ruct cifs_tcon *tcon, =20 truncate_setsize(inode, new_eof); netfs_resize_file(&cifsi->netfs, new_eof, true); - ictx->zero_point =3D new_eof; + netfs_write_zero_point(ictx, new_eof); fscache_resize_cookie(cifs_inode_cookie(inode), new_eof); out_2: filemap_invalidate_unlock(inode->i_mapping); @@ -3855,7 +3855,7 @@ static long smb3_insert_range(struct file *file, stru= ct cifs_tcon *tcon, rc =3D smb2_copychunk_range(xid, cfile, cfile, off, count, off + len); if (rc < 0) goto out_2; - cifsi->netfs.zero_point =3D new_eof; + netfs_write_zero_point(&cifsi->netfs, new_eof); =20 rc =3D smb3_zero_data(file, tcon, off, len, xid); if (rc < 0) diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c index 5188218c25be..8892fdd39474 100644 --- a/fs/smb/client/smb2pdu.c +++ b/fs/smb/client/smb2pdu.c @@ -4709,7 +4709,7 @@ smb2_readv_callback(struct TCP_Server_Info *server, s= truct mid_q_entry *mid) } else { size_t trans =3D rdata->subreq.transferred + rdata->got_bytes; if (trans < rdata->subreq.len && - rdata->subreq.start + trans >=3D ictx->remote_i_size) { + rdata->subreq.start + trans >=3D netfs_read_remote_i_size(ictx)) { __set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags); rdata->result =3D 0; } diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 62a528f90666..d72bc2f11734 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -62,8 +62,8 @@ struct netfs_inode { struct fscache_cookie *cache; #endif struct mutex wb_lock; /* Writeback serialisation */ - loff_t remote_i_size; /* Size of the remote file */ - loff_t zero_point; /* Size after which we assume there's no data + loff_t _remote_i_size; /* Size of the remote file */ + loff_t _zero_point; /* Size after which we assume there's no data * on the server */ atomic_t io_count; /* Number of outstanding reqs */ unsigned long flags; @@ -474,6 +474,260 @@ static inline struct netfs_inode *netfs_inode(struct = inode *inode) return container_of(inode, struct netfs_inode, inode); } =20 +/** + * netfs_read_remote_i_size - Read remote_i_size safely + * @ictx: The inode context to access + * + * Read remote_i_size safely without the potential for tearing on 32-bit + * arches. + * + * NOTE: in a 32bit arch with a preemptable kernel and an UP compile the + * i_size_read/write must be atomic with respect to the local cpu (unlike = with + * preempt disabled), but they don't need to be atomic with respect to oth= er + * cpus like in true SMP (so they need either to either locally disable irq + * around the read or for example on x86 they can be still implemented as a + * cmpxchg8b without the need of the lock prefix). For SMP compiles and 6= 4bit + * archs it makes no difference if preempt is enabled or not. + */ +static inline unsigned long long netfs_read_remote_i_size(const struct net= fs_inode *ictx) +{ + unsigned long long remote_i_size; + +#if BITS_PER_LONG=3D=3D32 && defined(CONFIG_SMP) + const struct inode *inode =3D &ictx->inode; + unsigned int seq; + + do { + seq =3D read_seqcount_begin(&inode->i_size_seqcount); + remote_i_size =3D ictx->_remote_i_size; + } while (read_seqcount_retry(&inode->i_size_seqcount, seq)); +#elif BITS_PER_LONG=3D=3D32 && defined(CONFIG_PREEMPTION) + preempt_disable(); + remote_i_size =3D ictx->_remote_i_size; + preempt_enable(); +#else + /* Pairs with smp_store_release() in netfs_write_remote_i_size() */ + remote_i_size =3D smp_load_acquire(&ictx->_remote_i_size); +#endif + return remote_i_size; +} + +/* + * netfs_write_remote_i_size - Set remote_i_size safely + * @ictx: The inode context to access + * @remote_i_size: The new value for the size of the file on the server + * + * Set remote_i_size safely without the potential for tearing on 32-bit ar= ches. + * + * NOTE: unlike netfs_read_remote_i_size(), netfs_write_remote_i_size() do= es + * need locking around it (normally i_rwsem), otherwise on 32bit/SMP an up= date + * of i_size_seqcount can be lost, resulting in subsequent i_size_read() c= alls + * spinning forever. + */ +static inline void netfs_write_remote_i_size(struct netfs_inode *ictx, + unsigned long long remote_i_size) +{ +#if BITS_PER_LONG=3D=3D32 && defined(CONFIG_SMP) + struct inode *inode =3D &ictx->inode; + + preempt_disable(); + write_seqcount_begin(&inode->i_size_seqcount); + ictx->_remote_i_size =3D remote_i_size; + write_seqcount_end(&inode->i_size_seqcount); + preempt_enable(); +#elif BITS_PER_LONG=3D=3D32 && defined(CONFIG_PREEMPTION) + preempt_disable(); + ictx->_remote_i_size =3D remote_i_size; + preempt_enable(); +#else + /* + * Pairs with smp_load_acquire() in netfs_read_remote_i_size() to + * ensure changes related to inode size (such as page contents) are + * visible before we see the changed inode size. + */ + smp_store_release(&ictx->_remote_i_size, remote_i_size); +#endif +} + +/** + * netfs_read_zero_point - Read zero_point safely + * @ictx: The inode context to access + * + * Read zero_point safely without the potential for tearing on 32-bit + * arches. + * + * NOTE: in a 32bit arch with a preemptable kernel and an UP compile the + * i_size_read/write must be atomic with respect to the local cpu (unlike = with + * preempt disabled), but they don't need to be atomic with respect to oth= er + * cpus like in true SMP (so they need either to either locally disable irq + * around the read or for example on x86 they can be still implemented as a + * cmpxchg8b without the need of the lock prefix). For SMP compiles and 6= 4bit + * archs it makes no difference if preempt is enabled or not. + */ +static inline unsigned long long netfs_read_zero_point(const struct netfs_= inode *ictx) +{ + unsigned long long zero_point; + +#if BITS_PER_LONG=3D=3D32 && defined(CONFIG_SMP) + const struct inode *inode =3D &ictx->inode; + unsigned int seq; + + do { + seq =3D read_seqcount_begin(&inode->i_size_seqcount); + zero_point =3D ictx->_zero_point; + } while (read_seqcount_retry(&inode->i_size_seqcount, seq)); +#elif BITS_PER_LONG=3D=3D32 && defined(CONFIG_PREEMPTION) + preempt_disable(); + zero_point =3D ictx->_zero_point; + preempt_enable(); +#else + /* Pairs with smp_store_release() in netfs_write_zero_point() */ + zero_point =3D smp_load_acquire(&ictx->_zero_point); +#endif + return zero_point; +} + +/* + * netfs_write_zero_point - Set zero_point safely + * @ictx: The inode context to access + * @zero_point: The new value for the point beyond which the server has no= data + * + * Set zero_point safely without the potential for tearing on 32-bit arche= s. + * + * NOTE: unlike netfs_read_zero_point(), netfs_write_zero_point() does need + * locking around it (normally i_rwsem), otherwise on 32bit/SMP an update = of + * i_size_seqcount can be lost, resulting in subsequent read calls spinning + * forever. + */ +static inline void netfs_write_zero_point(struct netfs_inode *ictx, + unsigned long long zero_point) +{ +#if BITS_PER_LONG=3D=3D32 && defined(CONFIG_SMP) + struct inode *inode =3D &ictx->inode; + + preempt_disable(); + write_seqcount_begin(&inode->i_size_seqcount); + ictx->_zero_point =3D zero_point; + write_seqcount_end(&inode->i_size_seqcount); + preempt_enable(); +#elif BITS_PER_LONG=3D=3D32 && defined(CONFIG_PREEMPTION) + preempt_disable(); + ictx->_zero_point =3D zero_point; + preempt_enable(); +#else + /* + * Pairs with smp_load_acquire() in netfs_read_zero_point() to + * ensure changes related to inode size (such as page contents) are + * visible before we see the changed inode size. + */ + smp_store_release(&ictx->_zero_point, zero_point); +#endif +} + +/** + * netfs_push_back_zero_point - Push back the zero point if unknown data n= ow beyond it + * ictx: The inode context to access + * to: The end of a new region of unknown data + * + * Move back the zero_point if we cause a region of unknown data to appear + * beyond it (such as doing a copy_file_range). + */ +static inline void netfs_push_back_zero_point(struct netfs_inode *ictx, + unsigned long long to) +{ + if (to > netfs_read_zero_point(ictx)) + netfs_write_zero_point(ictx, to); +} + +/** + * netfs_read_sizes - Read remote_i_size and zero_point safely + * @ictx: The inode context to access + * @remote_i_size: Where to return the size of the file on the server + * @zero_point: Where to return the the point beyond which the server has = no data + * + * Read remote_i_size and zero_point safely without the potential for tear= ing + * on 32-bit arches. + * + * NOTE: in a 32bit arch with a preemptable kernel and an UP compile the + * i_size_read/write must be atomic with respect to the local cpu (unlike = with + * preempt disabled), but they don't need to be atomic with respect to oth= er + * cpus like in true SMP (so they need either to either locally disable irq + * around the read or for example on x86 they can be still implemented as a + * cmpxchg8b without the need of the lock prefix). For SMP compiles and 6= 4bit + * archs it makes no difference if preempt is enabled or not. + */ +static inline void netfs_read_sizes(const struct netfs_inode *ictx, + unsigned long long *remote_i_size, + unsigned long long *zero_point) +{ +#if BITS_PER_LONG=3D=3D32 && defined(CONFIG_SMP) + const struct inode *inode =3D &ictx->inode; + unsigned int seq; + + do { + seq =3D read_seqcount_begin(&inode->i_size_seqcount); + *remote_i_size =3D ictx->_remote_i_size; + *zero_point =3D ictx->_zero_point; + } while (read_seqcount_retry(&inode->i_size_seqcount, seq)); + return zero_point; +#elif BITS_PER_LONG=3D=3D32 && defined(CONFIG_PREEMPTION) + unsigned long long zero_point; + + preempt_disable(); + *remote_i_size =3D ictx->_remote_i_size; + *zero_point =3D ictx->_zero_point; + preempt_enable(); +#else + /* Pairs with smp_store_release() in netfs_write_zero_point() */ + *remote_i_size =3D smp_load_acquire(&ictx->_remote_i_size); + *zero_point =3D smp_load_acquire(&ictx->_zero_point); +#endif +} + +/* + * netfs_write_sizes - Set remote_i_size and zero_point safely + * @ictx: The inode context to access + * @remote_i_size: The new value for the size of the file on the server + * @zero_point: The new value for the point beyond which the server has no= data + * + * Set both remote_i_size and zero_point safely without the potential for + * tearing on 32-bit arches. + * + * NOTE: unlike netfs_read_zero_point(), netfs_write_zero_point() does need + * locking around it (normally i_rwsem), otherwise on 32bit/SMP an update = of + * i_size_seqcount can be lost, resulting in subsequent read calls spinning + * forever. + */ +static inline void netfs_write_sizes(struct netfs_inode *ictx, + unsigned long long remote_i_size, + unsigned long long zero_point) +{ +#if BITS_PER_LONG=3D=3D32 && defined(CONFIG_SMP) + struct inode *inode =3D &ictx->inode; + + preempt_disable(); + write_seqcount_begin(&inode->i_size_seqcount); + ictx->_remote_i_size =3D remote_i_size; + ictx->_zero_point =3D zero_point; + write_seqcount_end(&inode->i_size_seqcount); + preempt_enable(); +#elif BITS_PER_LONG=3D=3D32 && defined(CONFIG_PREEMPTION) + preempt_disable(); + ictx->_remote_i_size =3D remote_i_size; + ictx->_zero_point =3D zero_point; + preempt_enable(); +#else + /* + * Pairs with smp_load_acquire() in netfs_read_remote_i_size and + * netfs_read_zero_point() to ensure changes related to inode size + * (such as page contents) are visible before we see the changed inode + * size. + */ + smp_store_release(&ictx->_remote_i_size, remote_i_size); + smp_store_release(&ictx->_zero_point, zero_point); +#endif +} + /** * netfs_inode_init - Initialise a netfslib inode context * @ctx: The netfs inode to initialise @@ -488,8 +742,8 @@ static inline void netfs_inode_init(struct netfs_inode = *ctx, bool use_zero_point) { ctx->ops =3D ops; - ctx->remote_i_size =3D i_size_read(&ctx->inode); - ctx->zero_point =3D LLONG_MAX; + ctx->_remote_i_size =3D i_size_read(&ctx->inode); + ctx->_zero_point =3D LLONG_MAX; ctx->flags =3D 0; atomic_set(&ctx->io_count, 0); #if IS_ENABLED(CONFIG_FSCACHE) @@ -498,7 +752,7 @@ static inline void netfs_inode_init(struct netfs_inode = *ctx, mutex_init(&ctx->wb_lock); /* ->releasepage() drives zero_point */ if (use_zero_point) { - ctx->zero_point =3D ctx->remote_i_size; + ctx->_zero_point =3D ctx->_remote_i_size; mapping_set_release_always(ctx->inode.i_mapping); } } @@ -511,13 +765,40 @@ static inline void netfs_inode_init(struct netfs_inod= e *ctx, * * Inform the netfs lib that a file got resized so that it can adjust its = state. */ -static inline void netfs_resize_file(struct netfs_inode *ctx, loff_t new_i= _size, +static inline void netfs_resize_file(struct netfs_inode *ictx, + unsigned long long new_i_size, bool changed_on_server) { +#if BITS_PER_LONG=3D=3D32 && defined(CONFIG_SMP) + struct inode *inode =3D &ictx->inode; + + preempt_disable(); + write_seqcount_begin(&inode->i_size_seqcount); + if (changed_on_server) + ictx->_remote_i_size =3D new_i_size; + if (new_i_size < ictx->_zero_point) + ictx->_zero_point =3D new_i_size; + write_seqcount_end(&inode->i_size_seqcount); + preempt_enable(); +#elif BITS_PER_LONG=3D=3D32 && defined(CONFIG_PREEMPTION) + preempt_disable(); if (changed_on_server) - ctx->remote_i_size =3D new_i_size; - if (new_i_size < ctx->zero_point) - ctx->zero_point =3D new_i_size; + ictx->_remote_i_size =3D new_i_size; + if (new_i_size < ictx->_zero_point) + ictx->_zero_point =3D new_i_size; + preempt_enable(); +#else + /* + * Pairs with smp_load_acquire() in netfs_read_remote_i_size and + * netfs_read_zero_point() to ensure changes related to inode size + * (such as page contents) are visible before we see the changed inode + * size. + */ + if (changed_on_server) + smp_store_release(&ictx->_remote_i_size, new_i_size); + if (new_i_size < ictx->_zero_point) + smp_store_release(&ictx->_zero_point, new_i_size); +#endif } =20 /** From nobody Sat Jun 20 04:57:26 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (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 23C333932F9 for ; Mon, 20 Apr 2026 08:38:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674291; cv=none; b=LHOzfrY88YVHdOAduFmWuBIB7o8S33OjYCmfNxyUa5Oq3FSewxvTAwpgN5f7NvAcGnETcsnXWzCpVwPMgRX4PHlhQbbWG9DSc+LP3mLUrvkcpvex80spL4saJ9yzqE5i1fQDwaymc7GAGB9G13Es9oneTk6LoXcvBDTNljzEu+4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674291; c=relaxed/simple; bh=iWEKgr0fPS2LBwyZw/FU46u4D7VN/HA2cp40fXv2VUw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=EWiVdGMFBdZuaO5EatH19EIJ3PaRg7l/G2EiWiLgy3O0baHVhjcQ7RiE/DmSucCcKD3MiF9wUFAFZsaX40gjqT9mx+TF0gUy7UP20K8fUQ80nBQwc3QXCXTTxQG4JZ7Nf32EIhViJcEygwKUf82qoTBNpa4PwrGaZUiXmGeDHlo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=AeWzjOyz; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="AeWzjOyz" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1776674289; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=73kY/18lwrFclzGx58kIFewTdVs+3oxIn+HO6KCOAHs=; b=AeWzjOyzuf0IAFSuwqWkZCFrDWprgBLvoxZ31Gvw77fHMrX8E119nDq+Wpr/anXmqCp3oL TYgIxuBpbvGdkY59CnHDMHPyrdfbzh9oAq33ZamcFKwv/7miwR1488UH2nqZmKHEezuudA vDaUWFPi9vownif4O5s32r+1e/YuH6w= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-279-rfE_8BV6PwedqQ7uh3JVAw-1; Mon, 20 Apr 2026 04:38:05 -0400 X-MC-Unique: rfE_8BV6PwedqQ7uh3JVAw-1 X-Mimecast-MFC-AGG-ID: rfE_8BV6PwedqQ7uh3JVAw_1776674284 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 115EA195609F; Mon, 20 Apr 2026 08:38:04 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.48.17]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 1BDB8195608E; Mon, 20 Apr 2026 08:38:00 +0000 (UTC) From: David Howells To: Christian Brauner Cc: David Howells , Paulo Alcantara , netfs@lists.linux.dev, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Matthew Wilcox Subject: [PATCH 10/11] netfs: Fix comment about write-streaming avoidance Date: Mon, 20 Apr 2026 09:37:01 +0100 Message-ID: <20260420083705.1009074-11-dhowells@redhat.com> In-Reply-To: <20260420083705.1009074-1-dhowells@redhat.com> References: <20260420083705.1009074-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" In netfs_perform_write(), there used to be a section in which write-streaming was avoided if either the fd is open O_RDWR or fscaching is enabled, but the former was removed as netfs_read_folio() can now fill in the gaps rather then flushing, but the comment was not updated. Fix the comment to match. Fixes: eac38f8a2b85 ("netfs: Fix write streaming disablement if fd open O_R= DWR") Closes: https://sashiko.dev/#/patchset/20260414082004.3756080-1-dhowells%40= redhat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: Matthew Wilcox cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/buffered_write.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c index c840f5448178..2abf451c38f6 100644 --- a/fs/netfs/buffered_write.c +++ b/fs/netfs/buffered_write.c @@ -278,9 +278,7 @@ ssize_t netfs_perform_write(struct kiocb *iocb, struct = iov_iter *iter, =20 /* We don't want to do a streaming write on a file that loses * caching service temporarily because the backing store got - * culled and we don't really want to get a streaming write on - * a file that's open for reading as ->read_folio() then has to - * be able to flush it. + * culled. */ if (netfs_is_cache_enabled(ctx)) { if (finfo) { From nobody Sat Jun 20 04:57:26 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (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 4A968394471 for ; Mon, 20 Apr 2026 08:38:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674295; cv=none; b=fmN63IeXIebD2/VMj2Uwcd9eEp/ok4hkGWg1d7H7Ca8rpXqSfmESLGKuBe0J27C0omEYVuQVjwAHyJIMl+0B3Rn2wijeG2FkVRjYCvB7JfYiyBGjR6Q/PN2bqzIBhCn5WwTj8wD5G/vaYacCQHM6d07qar2J69WYZBnC6xD9r4I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776674295; c=relaxed/simple; bh=UEd2DPy5Oydn8gPnoSJEViWZQyJhuKPr8I6vUBK9yqU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UV1IiCEuWp37mEdvLGnelvT3NkDWIhOQXnTMIAgY06sF7MZvqcgII0z1jDHFolYFrIh8pzMAPuvwPW3m0yBCuYQZ3YG7lTpPtLTZN7HmPs9TFFDgPVPnrpDmstLUf7X8inVjyaYGWy8UES9q+WoiF2toUD6Gw/Xky1tT96vDfHs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=LrD+pbjp; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="LrD+pbjp" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1776674293; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=i/iqAtL+28tWt3sinE2J51vlI+HAUHWznAcDahw6A20=; b=LrD+pbjpGfFMM572bL9Mu+nciojAwYsENF6a3TLX7QhGBiZcYtMD8bDRZraJQFC09hMehh h1BWQBXy66UpxrRl70PUpa4DGTJes60OSXnyp16aAkCksoW46NjdJPYZ+esZGPKjsJlUUd u31Hsn0AozroFSRDglfokVPcZHunkzk= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-68-V5spEUY1NImn6v35llKtVg-1; Mon, 20 Apr 2026 04:38:10 -0400 X-MC-Unique: V5spEUY1NImn6v35llKtVg-1 X-Mimecast-MFC-AGG-ID: V5spEUY1NImn6v35llKtVg_1776674288 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id BB68D19560B1; Mon, 20 Apr 2026 08:38:08 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.44.48.17]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id BCB953000C15; Mon, 20 Apr 2026 08:38:05 +0000 (UTC) From: David Howells To: Christian Brauner Cc: David Howells , Paulo Alcantara , netfs@lists.linux.dev, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Matthew Wilcox Subject: [PATCH 11/11] netfs: Fix netfs_read_folio() to wait on writeback Date: Mon, 20 Apr 2026 09:37:02 +0100 Message-ID: <20260420083705.1009074-12-dhowells@redhat.com> In-Reply-To: <20260420083705.1009074-1-dhowells@redhat.com> References: <20260420083705.1009074-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 Content-Type: text/plain; charset="utf-8" Fix netfs_read_folio() to wait for an ongoing writeback to complete so that it can trust the dirty flag and whatever is attached to folio->private (folio->private may get cleaned up by the collector before it clears the writeback flag). Fixes: ee4cdf7ba857 ("netfs: Speed up buffered reading") Closes: https://sashiko.dev/#/patchset/20260414082004.3756080-1-dhowells%40= redhat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: Matthew Wilcox cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/buffered_read.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index 4d6dfcffba78..dcfe51eec266 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -506,6 +506,8 @@ int netfs_read_folio(struct file *file, struct folio *f= olio) struct netfs_inode *ctx =3D netfs_inode(mapping->host); int ret; =20 + folio_wait_writeback(folio); + if (folio_test_dirty(folio)) return netfs_read_gaps(file, folio);