From nobody Mon Sep 28 06:37:32 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 D30CB47253C for ; Tue, 25 Aug 2026 13:21:10 +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=1787664076; cv=none; b=awRsqwo43cIKvoOS6Bm/EX70YiquUi1F2/n888BzbtC3FU/M9tEThQqBFdWmSELVi5h8fJcasYT80bEJlHOgB42kccyUOCURCURJbDXJ97bVpd9KiefbGpz4QtEC+RoWYvqILmcqWac68WM0cnVqia6Kxnfjt7uKGJ8WF35WAx8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787664076; c=relaxed/simple; bh=gZJj56dXZ3m5mpuWg5Y32mLuivOuA0n2jQSSKK4Lf/g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RpvfTFxubu2G4W94hYavQ9DeBEy5XpGhonfrEtYhjdXkdNheG4n4PfA9hNo+M0DWdmmXEVp6ehNDelPvVpqRMpHnKR2mNVMXQNAO0fU1f0LCjyy/mAL3Q9QFL4X/M+49vlyXoY251iz9tmKXb2Ddao3dikLDN/rFqE1dF0Rehlc= 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=JuquKssl; 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="JuquKssl" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787664064; 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=b4i/vAlF7TVRLwxgQcCoqCNsYOQic8KZ0Txwd6Khtt8=; b=JuquKsslWPG6HXYVOA9VNnPldHe4cRK40aZGdLnV2r8B4/f7T7Kj/Ytifd5FCjvI1IqT9v xXGdJ9Tcmv0eujcifODbIZ3pokywrH4n41ePcVlIBorjLDqCBqDzqsxuLRq4gl++ovIeoq LAmNu8uiw41igPhDEzVP1NPIfdYeEoA= 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-373-yNrnZdQ8McWHxJjh7PxgbA-1; Tue, 25 Aug 2026 09:21:01 -0400 X-MC-Unique: yNrnZdQ8McWHxJjh7PxgbA-1 X-Mimecast-MFC-AGG-ID: yNrnZdQ8McWHxJjh7PxgbA_1787664058 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (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 208C6195F152; Tue, 25 Aug 2026 13:20:58 +0000 (UTC) Received: from warthog.com (unknown [10.44.32.15]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D57EC362; Tue, 25 Aug 2026 13:20:54 +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, Karl Mehltretter , stable@vger.kernel.org Subject: [PATCH v2 1/9] netfs: Fix uninitialized return value in netfs_unbuffered_write() Date: Tue, 25 Aug 2026 14:20:35 +0100 Message-ID: <20260825132045.1000787-2-dhowells@redhat.com> In-Reply-To: <20260825132045.1000787-1-dhowells@redhat.com> References: <20260825132045.1000787-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.6 on 10.30.177.95 Content-Type: text/plain; charset="utf-8" From: Karl Mehltretter If preparation of the first subrequest fails, netfs_unbuffered_write() exits its loop before ret is initialized. The empty-iterator check can do the same. For synchronous writes, netfs_unbuffered_write_iter_locked() may then return an unrelated error instead of wreq->error. This is reachable through CIFS if cifs_prepare_write() fails to reopen the file or obtain credits. Initialize ret to 0 so the caller returns wreq->error if no data was written, or the number of bytes already written otherwise. Found with Clang's -Wconditional-uninitialized. Fixes: a0b4c7a49137e ("netfs: Fix unbuffered/DIO writes to dispatch subrequ= ests in strict sequence") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-fable-5 Signed-off-by: Karl Mehltretter Signed-off-by: David Howells --- fs/netfs/direct_write.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/netfs/direct_write.c b/fs/netfs/direct_write.c index c16fbad286a1..b04019097ab8 100644 --- a/fs/netfs/direct_write.c +++ b/fs/netfs/direct_write.c @@ -95,7 +95,7 @@ static int netfs_unbuffered_write(struct netfs_io_request= *wreq) { struct netfs_io_subrequest *subreq =3D NULL; struct netfs_io_stream *stream =3D &wreq->io_streams[0]; - int ret; + int ret =3D 0; =20 _enter("%llx", wreq->len); From nobody Mon Sep 28 06:37:32 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 2B658473C8D for ; Tue, 25 Aug 2026 13:21:10 +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=1787664079; cv=none; b=pf+WSWCgar1KAI+L7nr6KWqppTWCGYZU4uRJNsgwKkQAM9dO4FS31XFwFQU00sAbaC351F3QA9J+7BHTSbjO272ZROwHJHhz+U8OowUOzOyM9fiXhs7oIY6I4PAQRaU12OK3dBUu/EW5saAYnV3H0YUZqV9SoYk+YtNz5L9KePc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787664079; c=relaxed/simple; bh=txJCVMXbXZvWlCXPrv6gBGpM1BgXhBKNdFGr0ZEG6w0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mNFfSODIXKoyPfcjEWkmEZtsoBtlYh8T3wKZo/fo8iuzjGbobrmPE06pl9BjYoKwiJtiZ6XUMad4djKuSTZDnSlJPmhRdCGyoaoWnWQ2yEf4/SgB73wJxnKMD/t6Ni9lIWu3KfwpYVqvs3N9K1xjmWXbnPBTHjJZ5C9O8MvBUzk= 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=LzbwA/uR; 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="LzbwA/uR" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787664069; 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=0CGY+glbrnxXmLvEdK2C6tXXpmZuhxXjkwnlUGFD0SY=; b=LzbwA/uR5wnGG7AddwVP0UJs4NDUtcyXWJ4dsGJHb7OF5KOQ9ItvaGyUA2WeITSCOVfI71 5mqYB//b/3HISibSBk/1Hl6DIWRQz43M8LrNMKztSX6KXyZ2GaQNPKNeu++3nPdhok+XWe LQTWQXL2YJQvDRV7D4UnenDTmR6fulo= 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-617-vs5-qZasO1i6JqHslCjySQ-1; Tue, 25 Aug 2026 09:21:06 -0400 X-MC-Unique: vs5-qZasO1i6JqHslCjySQ-1 X-Mimecast-MFC-AGG-ID: vs5-qZasO1i6JqHslCjySQ_1787664063 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-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C883719792FF; Tue, 25 Aug 2026 13:21:02 +0000 (UTC) Received: from warthog.com (unknown [10.44.32.15]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id EA50818005BA; Tue, 25 Aug 2026 13:20:59 +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 Subject: [PATCH v2 2/9] netfs: Fix unbuffered/DIO write partial transfer error return Date: Tue, 25 Aug 2026 14:20:36 +0100 Message-ID: <20260825132045.1000787-3-dhowells@redhat.com> In-Reply-To: <20260825132045.1000787-1-dhowells@redhat.com> References: <20260825132045.1000787-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 unbuffered/DIO write to return the amount of data transferred in preference to an error if a partial transfer has been achieved, and to prefer an error stashed in the request over the one returned by netfs_unbuffered_write() (likely -EINTR or -ERESTARTSYS). Fixes: a0b4c7a49137e ("netfs: Fix unbuffered/DIO writes to dispatch subrequ= ests in strict sequence") Link: https://sashiko.dev/#/patchset/20260824120224.504575-1-dhowells%40red= hat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/direct_write.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/fs/netfs/direct_write.c b/fs/netfs/direct_write.c index b04019097ab8..544a4243fc59 100644 --- a/fs/netfs/direct_write.c +++ b/fs/netfs/direct_write.c @@ -139,13 +139,11 @@ static int netfs_unbuffered_write(struct netfs_io_req= uest *wreq) if (test_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags)) { retry =3D true; } else if (test_bit(NETFS_SREQ_FAILED, &subreq->flags)) { - ret =3D subreq->error; - wreq->error =3D ret; + wreq->error =3D subreq->error; netfs_see_subrequest(subreq, netfs_sreq_trace_see_failed); subreq =3D NULL; break; } - ret =3D 0; =20 if (!retry) { netfs_unbuffered_write_collect(wreq, stream, subreq); @@ -288,11 +286,11 @@ ssize_t netfs_unbuffered_write_iter_locked(struct kio= cb *iocb, struct iov_iter * ret =3D -EIOCBQUEUED; } else { ret =3D netfs_unbuffered_write(wreq); - if (ret < 0) { - _debug("begin =3D %zd", ret); - } else { + if (wreq->transferred) { iocb->ki_pos +=3D wreq->transferred; - ret =3D wreq->transferred ?: wreq->error; + ret =3D wreq->transferred; + } else if (wreq->error) { + ret =3D wreq->error; } =20 netfs_put_request(wreq, netfs_rreq_trace_put_complete); From nobody Mon Sep 28 06:37:32 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 626894756B9 for ; Tue, 25 Aug 2026 13:21:19 +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=1787664084; cv=none; b=OFneDJ0N691Xb6eaEG9r8vENXfIbWti8r/BkWYi7fP9iEEerFCfxVqWTjG0PfjHll6+R2R9Rv8KCBBOfziRA7x/4SfEWBG5CzZShoz6PjtplGZywsU5uCIgJZ4O0ofmnuVd8hwMpDTvbZ2JKotUWkAVViOacuqKSVCVa7/5WZ4E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787664084; c=relaxed/simple; bh=IizGxEfTjfhZJVkwhDscGC2P/a5HlqU4Kr8qrccX6z4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Gufev8+kZWNnLLx4WL08GjQ7UJfGbTry7+qn1KXEy+S/awWKvMsiyR1qFctJyHbAn1FKewHKl1w1Ts2feIBOrvqjb2lenuCcT1OVOxlRm6FRamSVnE3j/5QGtTmIoCS0y1NjRXQREkdmjN929U5YfrCBWyC/dogSEnVkE/EiKA4= 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=gP5ivW8K; 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="gP5ivW8K" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787664076; 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=bPPEzvtBLG/nC8I1Bmob/2jRQbbQ9nOnJ6K+0h7yLO8=; b=gP5ivW8KM3fIDtJTndVWGf2i4ad4jd+kxGkh6EeJIWFG7/Fl63YsW3qVQHLLmwNgipRkCA axkuLJswHh0aQ+69u1Noc77LKa/eT7qPt129mnuK4AY1By5Fi1UXLcITPNVt5wcs2J68W+ HV3ZhpFH1AbzuL4ysCAN/QcNwUpQjjw= 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-280-_zNZWTFXOgqQRslZ6mI2LA-1; Tue, 25 Aug 2026 09:21:10 -0400 X-MC-Unique: _zNZWTFXOgqQRslZ6mI2LA-1 X-Mimecast-MFC-AGG-ID: _zNZWTFXOgqQRslZ6mI2LA_1787664068 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-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E2BAA1955D4D; Tue, 25 Aug 2026 13:21:07 +0000 (UTC) Received: from warthog.com (unknown [10.44.32.15]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 828501944EB6; Tue, 25 Aug 2026 13:21:04 +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 Subject: [PATCH v2 3/9] netfs: Fix error vs transferred passed to ->ki_complete() Date: Tue, 25 Aug 2026 14:20:37 +0100 Message-ID: <20260825132045.1000787-4-dhowells@redhat.com> In-Reply-To: <20260825132045.1000787-1-dhowells@redhat.com> References: <20260825132045.1000787-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_unbuffered_write_done() to pass the amount written to ->ki_complete() rather than the error in the event of a partially complete transfer. Fixes: a0b4c7a49137e ("netfs: Fix unbuffered/DIO writes to dispatch subrequ= ests in strict sequence") Link: https://sashiko.dev/#/patchset/20260824120224.504575-1-dhowells%40red= hat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/direct_write.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/netfs/direct_write.c b/fs/netfs/direct_write.c index 544a4243fc59..f7d7e1b54653 100644 --- a/fs/netfs/direct_write.c +++ b/fs/netfs/direct_write.c @@ -51,7 +51,7 @@ static void netfs_unbuffered_write_done(struct netfs_io_r= equest *wreq) wreq->iocb->ki_pos +=3D written; if (wreq->iocb->ki_complete) { trace_netfs_rreq(wreq, netfs_rreq_trace_ki_complete); - wreq->iocb->ki_complete(wreq->iocb, wreq->error ?: written); + wreq->iocb->ki_complete(wreq->iocb, written ?: wreq->error); } wreq->iocb =3D VFS_PTR_POISON; } From nobody Mon Sep 28 06:37:32 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 F1B0B4756CD for ; Tue, 25 Aug 2026 13:21:24 +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=1787664091; cv=none; b=Ap0Q62P8QG8Gk3zj8GBSf/OctnPVvxBJAgQZUvk0lqOtBe+EpiqRBCzsYHInFxsmXb+aeQKAaTKyEVn+YDVcP/Bk5CMp3FdcZhdTI/djeJvthsEkVrFA/8/Qy5MwGTkAxetb3qhAthb3F2acr+hJqbXzuuODzs1F4ZFTGRg9T5U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787664091; c=relaxed/simple; bh=TbyvXkUkP/iFkWLvIM6Uiy2D1Zai+6kwljmDrYii1Qs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=H/hpX332kCKklY/bXWUEPwwx7PNZcjtld0GCgzFPuLdvmNgKbeUaIODbKYHS0ccPhI5bzkq5Fo5ayDtk9wepOMU3qxGqVY2/MES6QltSPik+0mNgNCRXKuAMPHcuiqYoRIGqTr6Z8UeEo7hNk1Syb9XrHqJF/cfoyiuaszkLhD0= 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=V9gGDiO0; 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="V9gGDiO0" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787664078; 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=r3vRJq2sMz9APK4rZhV/g2MBBVrXWqzKAsYSWHku/NM=; b=V9gGDiO05GxdgmV0wYaFbJLFhx9MEmoqkMCFzgF5Sqr0CUtqrBWtzMG5zw6dfdtxk3a+mY UmSKHnlnPYXukn5MVyvK7OOn2zegoYLc7fpshw5XV8NGrfjK3hMHn5GVg/mkPLocvseQkU QnvGUq49iTErVaS+B/MaFOnJIgywsm0= 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-379-COh1v_XLNEeuzg5VEg3wcQ-1; Tue, 25 Aug 2026 09:21:15 -0400 X-MC-Unique: COh1v_XLNEeuzg5VEg3wcQ-1 X-Mimecast-MFC-AGG-ID: COh1v_XLNEeuzg5VEg3wcQ_1787664072 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (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 798B0189F070; Tue, 25 Aug 2026 13:21:12 +0000 (UTC) Received: from warthog.com (unknown [10.44.32.15]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 956517C5; Tue, 25 Aug 2026 13:21:09 +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 Subject: [PATCH v2 4/9] netfs: Fix i_size update for partial transfer Date: Tue, 25 Aug 2026 14:20:38 +0100 Message-ID: <20260825132045.1000787-5-dhowells@redhat.com> In-Reply-To: <20260825132045.1000787-1-dhowells@redhat.com> References: <20260825132045.1000787-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.6 on 10.30.177.95 Content-Type: text/plain; charset="utf-8" Fix netfs_unbuffered_write_done() to pass the amount written to netfs_update_i_size() in the event of a partial transfer that ends in an error. That said, it might be better for the filesystem to mark the inode data as invalid and recheck it in case something like a network error occurred that prevented the reply from the server from being received. Fixes: a0b4c7a49137e ("netfs: Fix unbuffered/DIO writes to dispatch subrequ= ests in strict sequence") Link: https://sashiko.dev/#/patchset/20260824120224.504575-1-dhowells%40red= hat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/direct_write.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/netfs/direct_write.c b/fs/netfs/direct_write.c index f7d7e1b54653..f33ccddaa826 100644 --- a/fs/netfs/direct_write.c +++ b/fs/netfs/direct_write.c @@ -21,7 +21,7 @@ static void netfs_unbuffered_write_done(struct netfs_io_r= equest *wreq) /* Okay, declare that all I/O is complete. */ trace_netfs_rreq(wreq, netfs_rreq_trace_write_done); =20 - if (!wreq->error) + if (wreq->transferred) netfs_update_i_size(ictx, &ictx->inode, wreq->start, wreq->transferred); =20 if (wreq->origin =3D=3D NETFS_DIO_WRITE && From nobody Mon Sep 28 06:37:32 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 435144749CB for ; Tue, 25 Aug 2026 13:21:26 +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=1787664096; cv=none; b=h4w2MUVrhB9n2kflQWpu8ATWSPVa5ddNEbfPO4XkqH64XPwo41ezIi1ychecMZcxV8+sioGHbzYbDUz4QPFjsKDot9na/quNAuJm52U599jWU3CRfVfsww3cFTf8sT+Vb3+aJuC6ZJb+jJBWK5vfTyHs91yYSWdxLSjLPkPKvTc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787664096; c=relaxed/simple; bh=FzRo1GPNzAWelnrKwWW+888gA+zU/UXIf9GDxf2VjrM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rn+x5FGVhik11bFBmDUL4YhsG0Yh8TeKygmT2KSEOCbVC8iSRmuzkdDiOw3TQLumfBlr7iEAD1KMUesAYMYGGzS5PSoM1LsILC6YYhfxviAlay1Wze0rO/z1hyqt22hrm3aqvmvqpCXXGGB9WBp66Gy4PjtoxKqWI3lqzEZdmBg= 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=dMTB0zP5; 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="dMTB0zP5" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787664082; 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=M/Qxd7N6jCXPKHznu5KtiQXyFK2J5SiupV4se6oGxR0=; b=dMTB0zP5Dc2Zf+iXWXwKAo8gQGjJVgTn0xLIJMZF7fYUkgiApQLJyrApEtKL7DlxImU2WC noUjd74HgKGprJksH+xBTPSoJ4UvQgdVCoug44hn7yw6IcBfSgya3XrUA8ntru+au+oVVD HTQK1UKAbXlXJPh2quLb68jzqnD3mY0= 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-638-VS0MFFZINZafYnIVEXtWbg-1; Tue, 25 Aug 2026 09:21:18 -0400 X-MC-Unique: VS0MFFZINZafYnIVEXtWbg-1 X-Mimecast-MFC-AGG-ID: VS0MFFZINZafYnIVEXtWbg_1787664077 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-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0DBAF1978F71; Tue, 25 Aug 2026 13:21:17 +0000 (UTC) Received: from warthog.com (unknown [10.44.32.15]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2ECAD1955F08; Tue, 25 Aug 2026 13:21:13 +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 Subject: [PATCH v2 5/9] netfs: Fix subreq ref leak Date: Tue, 25 Aug 2026 14:20:39 +0100 Message-ID: <20260825132045.1000787-6-dhowells@redhat.com> In-Reply-To: <20260825132045.1000787-1-dhowells@redhat.com> References: <20260825132045.1000787-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" Fix a subrequest ref leak in netfs_unbuffered_write() in the event that subreq->io_iter ends up zero length during preparation. Fixes: a0b4c7a49137e ("netfs: Fix unbuffered/DIO writes to dispatch subrequ= ests in strict sequence") Link: https://sashiko.dev/#/patchset/20260824120224.504575-1-dhowells%40red= hat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/direct_write.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/netfs/direct_write.c b/fs/netfs/direct_write.c index f33ccddaa826..fbcfadb232ee 100644 --- a/fs/netfs/direct_write.c +++ b/fs/netfs/direct_write.c @@ -121,8 +121,14 @@ static int netfs_unbuffered_write(struct netfs_io_requ= est *wreq) } =20 iov_iter_truncate(&subreq->io_iter, wreq->len - wreq->transferred); - if (!iov_iter_count(&subreq->io_iter)) + if (!iov_iter_count(&subreq->io_iter)) { + pr_warn("netfs: Unexpected zero-length iterator R=3D%08x\n", + wreq->debug_id); + __set_bit(NETFS_SREQ_FAILED, &subreq->flags); + netfs_write_subrequest_terminated(subreq, -EIO); + wreq->error =3D -EIO; break; + } =20 subreq->len =3D netfs_limit_iter(&subreq->io_iter, 0, stream->sreq_max_len, From nobody Mon Sep 28 06:37:32 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 444D14746AC for ; Tue, 25 Aug 2026 13:21:34 +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=1787664103; cv=none; b=Y3bjjuCvPRnkiRFiOVyPaCyzK0OpobjQ3+P1/jQkOh+ozg/I9DaUHsbWJLp4q/NVWtP5VCwED5KIfHnt6mRSdwttx8T6vDt8JDZSKksZYHevnK2glOKG321rIoC7DTkcGEhcbkbxb+kcZU4Mcrh7ScOcAx3TKI1dNfZKrRDLD+c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787664103; c=relaxed/simple; bh=tlt6nmEpLs/0fQ0gKQrkQ2eKLUpkaqhJC9uMzs2fx/4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LtPLUxS2gWuy0AhmSLJMrY1bxvhA0xztnL8hwUgdT/pwXywUtTVun2MtJ9vAeBuoqNu6FItARIZAgP5049Zst5KrtntA5vj9N3w5K0Ln7FRpTv1LiWBzL6/yIyBtPMMlJsTdi8FGTbM5ZyXaWX5wfPyup8HEa2TVlzty7jfnYio= 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=QJh0DYVN; 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="QJh0DYVN" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787664090; 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=vU4d2g10zNfL1YNAIJuqPoPe4woqc1v8GpKzEdoRnpE=; b=QJh0DYVN6Z9iqQZBPIO498UllccOBPiwx4w9jTciykoN56s4by7Yb7e4MnxLYwthWxYHqw QOh2+MdcFu3djsjdQJkZHNSCYU0x48NlLRnGNHqQKJHCOQ/O5oUyaJ4NNSGtX4pa8+8mzX 9loeBG1mSqFfVa/KG2vj8xRQNXnBaE8= 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-650-iJmeief9MHGExr93kMS1KA-1; Tue, 25 Aug 2026 09:21:24 -0400 X-MC-Unique: iJmeief9MHGExr93kMS1KA-1 X-Mimecast-MFC-AGG-ID: iJmeief9MHGExr93kMS1KA_1787664082 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 009BD1944D27; Tue, 25 Aug 2026 13:21:22 +0000 (UTC) Received: from warthog.com (unknown [10.44.32.15]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A0EEB1803A44; Tue, 25 Aug 2026 13:21:18 +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, Edward Adam Davis , syzbot+6a13fc77eb6f0802be2d@syzkaller.appspotmail.com Subject: [PATCH v2 6/9] netfs: break unbuffered write when netfs_alloc_subrequest() fails Date: Tue, 25 Aug 2026 14:20:40 +0100 Message-ID: <20260825132045.1000787-7-dhowells@redhat.com> In-Reply-To: <20260825132045.1000787-1-dhowells@redhat.com> References: <20260825132045.1000787-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" From: Edward Adam Davis syzbot reported a null-ptr-deref below [1] following a fault injection in netfs_alloc_subrequest(). [0] When netfs_alloc_subrequest() fails, subreq is NULL. Later, netfs_prepare_write() tries to initialize members of subreq(e.g., source), the issue in [1] is triggered. Let's handle the error of netfs_prepare_write() properly. [0] FAULT_INJECTION: forcing a failure. name failslab, interval 1, probability 0, space 0, times 0 Call Trace: netfs_alloc_subrequest+0x116/0x3f0 netfs_prepare_write+0x76/0x7b0 netfs_unbuffered_write+0x75c/0x2020 netfs_unbuffered_write_iter_locked+0x7d6/0xa80 netfs_unbuffered_write_iter+0x442/0x720 v9fs_file_write_iter+0xbf/0x100 vfs_write+0x6ac/0x1050 [1] KASAN: null-ptr-deref in range [0x00000000000000a8-0x00000000000000af] RIP: 0010:netfs_prepare_write+0xbc/0x7b0 fs/netfs/write_issue.c:173 Call Trace: netfs_unbuffered_write+0x75c/0x2020 fs/netfs/direct_write.c:111 netfs_unbuffered_write_iter_locked+0x7d6/0xa80 fs/netfs/direct_write.c:290 netfs_unbuffered_write_iter+0x442/0x720 fs/netfs/direct_write.c:382 v9fs_file_write_iter+0xbf/0x100 fs/9p/vfs_file.c:409 new_sync_write fs/read_write.c:595 [inline] [dhowells: Altered to put -ENOMEM into ret, not wreq->error] Fixes: 288ace2f57c9 ("netfs: New writeback implementation") Reported-by: syzbot+6a13fc77eb6f0802be2d@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=3D6a13fc77eb6f0802be2d Tested-by: syzbot+6a13fc77eb6f0802be2d@syzkaller.appspotmail.com Signed-off-by: Edward Adam Davis Signed-off-by: David Howells --- fs/netfs/direct_write.c | 4 ++++ fs/netfs/write_issue.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/fs/netfs/direct_write.c b/fs/netfs/direct_write.c index fbcfadb232ee..7173ce04bac6 100644 --- a/fs/netfs/direct_write.c +++ b/fs/netfs/direct_write.c @@ -110,6 +110,10 @@ static int netfs_unbuffered_write(struct netfs_io_requ= est *wreq) if (!subreq) { netfs_prepare_write(wreq, stream, wreq->start + wreq->transferred); subreq =3D stream->construct; + if (!subreq) { + ret =3D -ENOMEM; + break; + } stream->construct =3D NULL; } =20 diff --git a/fs/netfs/write_issue.c b/fs/netfs/write_issue.c index 2d9cfcd43658..851f6f93ad45 100644 --- a/fs/netfs/write_issue.c +++ b/fs/netfs/write_issue.c @@ -170,6 +170,8 @@ void netfs_prepare_write(struct netfs_io_request *wreq, rolling_buffer_make_space(&wreq->buffer, wreq->gfp); =20 subreq =3D netfs_alloc_subrequest(wreq); + if (!subreq) + return; subreq->source =3D stream->source; subreq->start =3D start; subreq->stream_nr =3D stream->stream_nr; From nobody Mon Sep 28 06:37:32 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 665B44749C8 for ; Tue, 25 Aug 2026 13:22:42 +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=1787664169; cv=none; b=RVMOwxh08k9n/h1OAlIzM5ApCu0KC21chMzbGKzeFc3gHz6K2GU3kwwOvsv5A6KdmFj4eb+a0RyG9YcLF3Tb7HvHy/D1h+yaPjT+ZmqFnLQOmg3y3e9Y7tGU82MreA3aqsa6LZloMPNueqWwRoJqk5TKG0st2D3NH5p+a7RP8oA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787664169; c=relaxed/simple; bh=BjURH8bwEAnSf7cBvL6SmtlelGQtfJbu6sYmimC4rdg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FL/R6WFlVJqFjTTcfyU3rkpYGlDbPdjZSejvwH1K+AJveaOJUpA51XMpfj2CWN6EefG3amlGJUvCYSEaXhiA+NEgieJoXkDD9w/r2b7zKXOAtfrh6kmZAVh9jtCBcuH4JT0Sx5bnkYC5hwCa0aETw4W7yLg9KZLVO4B2Ttib5y8= 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=VzqYPjy2; 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="VzqYPjy2" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787664159; 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=r9iZolUQoXRsjj7Xv9NSqZ4No1AkzqqiBCElDUTpjbA=; b=VzqYPjy27oTHZVfKF5vqfuyslyxj5SLqxvd8CSbRR+66TO7XkRSW2T1EShbyZDG/igMNKL Xx+Zjo7Hs4VtkldlmeWFjw2Kdk6TqNHHm4hILP5+XbebMMbsxk9abdRuE3b0Rgz5YgYrOX W/N5mNL8LbCyE+sJ2B15KM6iKv6seoE= 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-275-Wl32SQHQO_SZnzAOPr6cCQ-1; Tue, 25 Aug 2026 09:21:30 -0400 X-MC-Unique: Wl32SQHQO_SZnzAOPr6cCQ-1 X-Mimecast-MFC-AGG-ID: Wl32SQHQO_SZnzAOPr6cCQ_1787664089 Received: from mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.95]) (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 68D9E195DE0F; Tue, 25 Aug 2026 13:21:28 +0000 (UTC) Received: from warthog.com (unknown [10.44.32.15]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id E137A7D6; Tue, 25 Aug 2026 13:21:23 +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 , linux-mm@kvack.org Subject: [PATCH v2 7/9] netfs: Fix readahead synchronisation issues by loading all folios upfront Date: Tue, 25 Aug 2026 14:20:41 +0100 Message-ID: <20260825132045.1000787-8-dhowells@redhat.com> In-Reply-To: <20260825132045.1000787-1-dhowells@redhat.com> References: <20260825132045.1000787-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.6 on 10.30.177.95 Content-Type: text/plain; charset="utf-8" There are some synchronisation issues that derive from the app thread adding more folios to the rolling buffer whilst the collector thread is looking at them or trying to clear them, such as determining the setting of front_folio_order when the next folio hasn't been added yet, The reason for the rolling buffer approach is that loading the buffer upfront and then dropping all the refs just acquired is quite a slow operation, and loading progressively allows some of the cost to be deferred until after at least some of the I/O is started. Instead, a better way is to load all the folios into the rolling buffer upfront - and then drop the refs later, once the I/O is in progress. (Even better would be for the refs not to be there at all.) Fix this by changing the rolling buffer loader to load all the folios selected by the VM for readahead upfront into the folio queue. The folio queue is allocated a batch worth at a time as we don't know how many folios are involved (the readahead_control struct, alas, has a page count, not a folio count). The folio refs acquired from readahead are then dropped in bulk once the first subrequest is dispatched as it's quite a slow operation. The collector waits for NETFS_RREQ_NEED_PUT_RA_REFS to be cleared so that it doesn't unlock folios before the xarray has been scanned for them. This simplifies the buffer handling later and isn't noticeably slower as the xarray doesn't need to be modified and the folios are all already pre-locked. Fixes: ee4cdf7ba857 ("netfs: Speed up buffered reading") Link: https://sashiko.dev/#/patchset/20260824120224.504575-1-dhowells%40red= hat.com Signed-off-by: David Howells cc: Paulo Alcantara (Red Hat) cc: Matthew Wilcox cc: netfs@lists.linux.dev cc: linux-mm@kvack.org cc: linux-fsdevel@vger.kernel.org --- fs/netfs/buffered_read.c | 101 ++++++++++++++++++++------------- fs/netfs/internal.h | 1 + fs/netfs/misc.c | 19 +++++++ fs/netfs/read_collect.c | 7 +++ fs/netfs/read_retry.c | 7 +++ fs/netfs/rolling_buffer.c | 81 ++++++++++++++++---------- include/linux/netfs.h | 1 + include/linux/rolling_buffer.h | 6 +- include/trace/events/netfs.h | 3 + 9 files changed, 154 insertions(+), 72 deletions(-) diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index 7fdfa4f27e34..303fdce54fba 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -54,6 +54,42 @@ static void netfs_rreq_expand(struct netfs_io_request *r= req, } } =20 +/* + * Drop the folio refs acquired from the readahead API. + */ +static void netfs_bulk_drop_ra_refs(struct netfs_io_request *rreq) +{ + struct folio_batch fbatch; + struct folio *folio; + pgoff_t nr_pages =3D DIV_ROUND_UP(rreq->len, PAGE_SIZE); + pgoff_t first =3D rreq->start / PAGE_SIZE; + XA_STATE(xas, &rreq->mapping->i_pages, first); + + folio_batch_init(&fbatch); + + rcu_read_lock(); + + xas_for_each(&xas, folio, first + nr_pages - 1) { + if (xas_retry(&xas, folio)) + continue; + + if (!folio_batch_add(&fbatch, folio)) + folio_batch_release(&fbatch); + } + + rcu_read_unlock(); + folio_batch_release(&fbatch); + trace_netfs_rreq(rreq, netfs_rreq_trace_ra_put_ref); + clear_bit_unlock(NETFS_RREQ_NEED_PUT_RA_REFS, &rreq->flags); + wake_up(&rreq->waitq); +} + +static void netfs_maybe_bulk_drop_ra_refs(struct netfs_io_request *rreq) +{ + if (test_bit(NETFS_RREQ_NEED_PUT_RA_REFS, &rreq->flags)) + netfs_bulk_drop_ra_refs(rreq); +} + /* * Begin an operation, and fetch the stored zero point value from the cook= ie if * available. @@ -74,12 +110,8 @@ static int netfs_begin_cache_read(struct netfs_io_reque= st *rreq, struct netfs_in * * Returns the limited size if successful and -ENOMEM if insufficient memo= ry * available. - * - * [!] NOTE: This must be run in the same thread as ->issue_read() was cal= led - * in as we access the readahead_control struct. */ -static ssize_t netfs_prepare_read_iterator(struct netfs_io_subrequest *sub= req, - struct readahead_control *ractl) +static ssize_t netfs_prepare_read_iterator(struct netfs_io_subrequest *sub= req) { struct netfs_io_request *rreq =3D subreq->rreq; size_t rsize =3D subreq->len; @@ -87,30 +119,6 @@ static ssize_t netfs_prepare_read_iterator(struct netfs= _io_subrequest *subreq, if (subreq->source =3D=3D NETFS_DOWNLOAD_FROM_SERVER) rsize =3D umin(rsize, rreq->io_streams[0].sreq_max_len); =20 - if (ractl) { - /* If we don't have sufficient folios in the rolling buffer, - * extract a folioq's worth from the readahead region at a time - * into the buffer. Note that this acquires a ref on each page - * that we will need to release later - but we don't want to do - * that until after we've started the I/O. - */ - struct folio_batch put_batch; - - folio_batch_init(&put_batch); - while (rreq->submitted < subreq->start + rsize) { - ssize_t added; - - added =3D rolling_buffer_load_from_ra(&rreq->buffer, ractl, - &put_batch); - if (added < 0) { - folio_batch_release(&put_batch); - return added; - } - rreq->submitted +=3D added; - } - folio_batch_release(&put_batch); - } - subreq->len =3D rsize; if (unlikely(rreq->io_streams[0].sreq_max_segs)) { size_t limit =3D netfs_limit_iter(&rreq->buffer.iter, 0, rsize, @@ -208,8 +216,7 @@ static void netfs_issue_read(struct netfs_io_request *r= req, * slicing up the region to be read according to available cache blocks and * network rsize. */ -static void netfs_read_to_pagecache(struct netfs_io_request *rreq, - struct readahead_control *ractl) +static void netfs_read_to_pagecache(struct netfs_io_request *rreq) { unsigned long long start =3D rreq->start; ssize_t size =3D rreq->len; @@ -288,7 +295,7 @@ static void netfs_read_to_pagecache(struct netfs_io_req= uest *rreq, break; =20 issue: - slice =3D netfs_prepare_read_iterator(subreq, ractl); + slice =3D netfs_prepare_read_iterator(subreq); if (slice < 0) { ret =3D slice; netfs_cancel_read(subreq, ret); @@ -302,6 +309,7 @@ static void netfs_read_to_pagecache(struct netfs_io_req= uest *rreq, } =20 netfs_issue_read(rreq, subreq); + netfs_maybe_bulk_drop_ra_refs(rreq); =20 if (test_bit(NETFS_RREQ_PAUSE, &rreq->flags)) netfs_wait_for_paused_read(rreq); @@ -339,7 +347,8 @@ void netfs_readahead(struct readahead_control *ractl) { struct netfs_io_request *rreq; struct netfs_inode *ictx =3D netfs_inode(ractl->mapping->host); - unsigned long long start =3D readahead_pos(ractl); + ssize_t added; + uoff_t start =3D readahead_pos(ractl); size_t size =3D readahead_length(ractl); int ret; =20 @@ -360,11 +369,23 @@ void netfs_readahead(struct readahead_control *ractl) =20 netfs_rreq_expand(rreq, ractl); =20 - rreq->submitted =3D rreq->start; - if (rolling_buffer_init(&rreq->buffer, rreq->debug_id, ITER_DEST, rreq->g= fp) < 0) + /* Load the folios to be read into a bvecq chain. Note that this + * acquires a ref on each folio that we will need to release later - + * but we don't want to do that until after we've started the I/O. + */ + added =3D rolling_buffer_bulk_load_from_ra(&rreq->buffer, ractl, + rreq->debug_id, rreq->gfp); + if (added < 0) { + ret =3D added; goto cleanup_free; - netfs_read_to_pagecache(rreq, ractl); + } + __set_bit(NETFS_RREQ_NEED_PUT_RA_REFS, &rreq->flags); + + rreq->submitted =3D rreq->start + added; + rreq->cleaned_to =3D rreq->start; =20 + netfs_read_to_pagecache(rreq); + netfs_maybe_bulk_drop_ra_refs(rreq); return netfs_put_request(rreq, netfs_rreq_trace_put_return); =20 cleanup_free: @@ -457,7 +478,7 @@ static int netfs_read_gaps(struct file *file, struct fo= lio *folio) iov_iter_bvec(&rreq->buffer.iter, ITER_DEST, bvec, i, rreq->len); rreq->submitted =3D rreq->start + flen; =20 - netfs_read_to_pagecache(rreq, NULL); + netfs_read_to_pagecache(rreq); =20 ret =3D netfs_wait_for_read(rreq); if (ret >=3D 0) { @@ -532,7 +553,7 @@ int netfs_read_folio(struct file *file, struct folio *f= olio) if (ret < 0) goto discard; =20 - netfs_read_to_pagecache(rreq, NULL); + netfs_read_to_pagecache(rreq); ret =3D netfs_wait_for_read(rreq); netfs_put_request(rreq, netfs_rreq_trace_put_return); return ret < 0 ? ret : 0; @@ -689,7 +710,7 @@ int netfs_write_begin(struct netfs_inode *ctx, if (ret < 0) goto error_put; =20 - netfs_read_to_pagecache(rreq, NULL); + netfs_read_to_pagecache(rreq); ret =3D netfs_wait_for_read(rreq); netfs_put_request(rreq, netfs_rreq_trace_put_return); if (ret < 0) @@ -754,7 +775,7 @@ int netfs_prefetch_for_write(struct file *file, struct = folio *folio, if (ret < 0) goto error_put; =20 - netfs_read_to_pagecache(rreq, NULL); + netfs_read_to_pagecache(rreq); ret =3D netfs_wait_for_read(rreq); netfs_put_request(rreq, netfs_rreq_trace_put_return); return ret < 0 ? ret : 0; diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index 420ee7b26580..bd8b2d633f96 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -79,6 +79,7 @@ ssize_t netfs_wait_for_read(struct netfs_io_request *rreq= ); ssize_t netfs_wait_for_write(struct netfs_io_request *rreq); void netfs_wait_for_paused_read(struct netfs_io_request *rreq); void netfs_wait_for_paused_write(struct netfs_io_request *rreq); +void netfs_wait_for_put_ra_refs(struct netfs_io_request *rreq); =20 /* * objects.c diff --git a/fs/netfs/misc.c b/fs/netfs/misc.c index 5d554512ed23..f5c1c463f4ff 100644 --- a/fs/netfs/misc.c +++ b/fs/netfs/misc.c @@ -563,3 +563,22 @@ void netfs_wait_for_paused_write(struct netfs_io_reque= st *rreq) { return netfs_wait_for_pause(rreq, netfs_write_collection); } + +/* + * Wait for the readahead-acquired refs to be put. + */ +void netfs_wait_for_put_ra_refs(struct netfs_io_request *rreq) +{ + DEFINE_WAIT(myself); + + for (;;) { + trace_netfs_rreq(rreq, netfs_rreq_trace_wait_put_ra_refs); + prepare_to_wait(&rreq->waitq, &myself, TASK_UNINTERRUPTIBLE); + if (!test_bit(NETFS_RREQ_NEED_PUT_RA_REFS, &rreq->flags)) + break; + schedule(); + } + + trace_netfs_rreq(rreq, netfs_rreq_trace_waited_put_ra_refs); + finish_wait(&rreq->waitq, &myself); +} diff --git a/fs/netfs/read_collect.c b/fs/netfs/read_collect.c index 23660a590124..edf7cea7e2f9 100644 --- a/fs/netfs/read_collect.c +++ b/fs/netfs/read_collect.c @@ -118,6 +118,13 @@ static void netfs_read_unlock_folios(struct netfs_io_r= equest *rreq, slot =3D 0; } =20 + /* We have to wait for readahead refs to have been released before we + * can unlock any folios as the ref-dropper walks i_pages and the only + * thing preventing these folios from being removed is the folio lock. + */ + if (test_bit(NETFS_RREQ_NEED_PUT_RA_REFS, &rreq->flags)) + netfs_wait_for_put_ra_refs(rreq); + for (;;) { struct folio *folio; unsigned long long fpos, fend; diff --git a/fs/netfs/read_retry.c b/fs/netfs/read_retry.c index 2b42758e01ec..dd463a485139 100644 --- a/fs/netfs/read_retry.c +++ b/fs/netfs/read_retry.c @@ -292,6 +292,13 @@ void netfs_unlock_abandoned_read_pages(struct netfs_io= _request *rreq) { struct folio_queue *p; =20 + /* We have to wait for readahead refs to have been released before we + * can unlock any folios as the ref-dropper walks i_pages and the only + * thing preventing these folios from being removed is the folio lock. + */ + if (test_bit(NETFS_RREQ_NEED_PUT_RA_REFS, &rreq->flags)) + netfs_wait_for_put_ra_refs(rreq); + for (p =3D rreq->buffer.tail; p; p =3D p->next) { for (int slot =3D 0; slot < folioq_count(p); slot++) { struct folio *folio =3D folioq_folio(p, slot); diff --git a/fs/netfs/rolling_buffer.c b/fs/netfs/rolling_buffer.c index 8c0026836f9c..424e77a9a109 100644 --- a/fs/netfs/rolling_buffer.c +++ b/fs/netfs/rolling_buffer.c @@ -115,42 +115,65 @@ int rolling_buffer_make_space(struct rolling_buffer *= roll, gfp_t gfp) } =20 /* - * Decant the list of folios to read into a rolling buffer. + * Decant the entire list of folios to read into a rolling buffer. */ -ssize_t rolling_buffer_load_from_ra(struct rolling_buffer *roll, - struct readahead_control *ractl, - struct folio_batch *put_batch) +ssize_t rolling_buffer_bulk_load_from_ra(struct rolling_buffer *roll, + struct readahead_control *ractl, + unsigned int rreq_id, gfp_t gfp) { struct folio_queue *fq; - struct page **vec; - int nr, ix, to; - ssize_t size =3D 0; + ssize_t loaded =3D 0; =20 - if (rolling_buffer_make_space(roll, GFP_KERNEL) < 0) - return -ENOMEM; + while (ractl->_nr_pages - ractl->_batch_count > 0) { + unsigned int nr; =20 - fq =3D roll->head; - vec =3D (struct page **)fq->vec.folios; - nr =3D __readahead_batch(ractl, vec + folio_batch_count(&fq->vec), - folio_batch_space(&fq->vec)); - ix =3D fq->vec.nr; - to =3D ix + nr; - fq->vec.nr =3D to; - for (; ix < to; ix++) { - struct folio *folio =3D folioq_folio(fq, ix); - unsigned int order =3D folio_order(folio); - - fq->orders[ix] =3D order; - size +=3D PAGE_SIZE << order; - trace_netfs_folio(folio, netfs_folio_trace_read); - if (!folio_batch_add(put_batch, folio)) - folio_batch_release(put_batch); + /* Allocate a folioq to put some folios into and attach it to + * the rolling buffer. + */ + fq =3D netfs_folioq_alloc(rreq_id, gfp, + netfs_trace_folioq_make_space); + if (!fq) + goto nomem_unlock; + fq->prev =3D roll->head; + if (!roll->tail) + roll->tail =3D fq; + else + roll->head->next =3D fq; + roll->head =3D fq; + + /* Get a batch of folios and note their orders. */ + nr =3D __readahead_batch(ractl, (struct page **)fq->vec.folios, + folioq_nr_slots(fq)); + if (WARN_ON_ONCE(!nr)) + break; + fq->vec.nr =3D nr; + + for (int slot =3D 0; slot < nr; slot++) { + struct folio *folio =3D folioq_folio(fq, slot); + unsigned int order; + + order =3D folio_order(folio); + fq->orders[slot] =3D order; + loaded +=3D PAGE_SIZE << order; + trace_netfs_folio(folio, netfs_folio_trace_read); + } } - WRITE_ONCE(roll->iter.count, roll->iter.count + size); =20 - /* Store the counter after setting the slot. */ - smp_store_release(&roll->next_head_slot, to); - return size; + WRITE_ONCE(roll->iter.count, loaded); + iov_iter_folio_queue(&roll->iter, ITER_DEST, roll->tail, 0, 0, loaded); + return loaded; + +nomem_unlock: + for (fq =3D roll->tail; fq; fq =3D fq->next) { + for (int slot =3D 0; slot < folioq_count(fq); slot++) { + folio_unlock(fq->vec.folios[slot]); + folioq_mark(fq, slot); + } + } + rolling_buffer_clear(roll); + roll->head =3D NULL; + roll->tail =3D NULL; + return -ENOMEM; } =20 /* diff --git a/include/linux/netfs.h b/include/linux/netfs.h index f837a501008c..5c538d0c5d79 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -278,6 +278,7 @@ struct netfs_io_request { #define NETFS_RREQ_FOLIO_COPY_TO_CACHE 10 /* Copy current folio to cache f= rom read */ #define NETFS_RREQ_UPLOAD_TO_SERVER 11 /* Need to write to the server */ #define NETFS_RREQ_USE_IO_ITER 12 /* Use ->io_iter rather than ->i_pages = */ +#define NETFS_RREQ_NEED_PUT_RA_REFS 17 /* Need to put the folio refs RA ga= ve us */ #define NETFS_RREQ_USE_PGPRIV2 31 /* [DEPRECATED] Use PG_private_2 to mark * write to cache on read */ const struct netfs_request_ops *netfs_ops; diff --git a/include/linux/rolling_buffer.h b/include/linux/rolling_buffer.h index 9e5dad29669c..a97f7cfaacaa 100644 --- a/include/linux/rolling_buffer.h +++ b/include/linux/rolling_buffer.h @@ -45,9 +45,9 @@ struct rolling_buffer_snapshot { int rolling_buffer_init(struct rolling_buffer *roll, unsigned int rreq_id, unsigned int direction, gfp_t gfp); int rolling_buffer_make_space(struct rolling_buffer *roll, gfp_t gfp); -ssize_t rolling_buffer_load_from_ra(struct rolling_buffer *roll, - struct readahead_control *ractl, - struct folio_batch *put_batch); +ssize_t rolling_buffer_bulk_load_from_ra(struct rolling_buffer *roll, + struct readahead_control *ractl, + unsigned int rreq_id, gfp_t gfp); ssize_t rolling_buffer_append(struct rolling_buffer *roll, struct folio *f= olio, unsigned int flags, gfp_t gfp); struct folio_queue *rolling_buffer_delete_spent(struct rolling_buffer *rol= l); diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index 082cb03c6131..9bda9302be90 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -59,6 +59,7 @@ EM(netfs_rreq_trace_free, "FREE ") \ EM(netfs_rreq_trace_intr, "INTR ") \ EM(netfs_rreq_trace_ki_complete, "KI-CMPL") \ + EM(netfs_rreq_trace_ra_put_ref, "RA-PUT ") \ EM(netfs_rreq_trace_recollect, "RECLLCT") \ EM(netfs_rreq_trace_redirty, "REDIRTY") \ EM(netfs_rreq_trace_resubmit, "RESUBMT") \ @@ -70,9 +71,11 @@ EM(netfs_rreq_trace_unpause, "UNPAUSE") \ EM(netfs_rreq_trace_wait_ip, "WAIT-IP") \ EM(netfs_rreq_trace_wait_pause, "--PAUSED--") \ + EM(netfs_rreq_trace_wait_put_ra_refs, "WAIT-P-RA") \ EM(netfs_rreq_trace_wait_quiesce, "WAIT-QUIESCE") \ EM(netfs_rreq_trace_waited_ip, "DONE-IP") \ EM(netfs_rreq_trace_waited_pause, "--UNPAUSED--") \ + EM(netfs_rreq_trace_waited_put_ra_refs, "DONE-P-RA") \ EM(netfs_rreq_trace_waited_quiesce, "DONE-QUIESCE") \ EM(netfs_rreq_trace_wake_ip, "WAKE-IP") \ EM(netfs_rreq_trace_wake_queue, "WAKE-Q ") \ From nobody Mon Sep 28 06:37:32 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 6FBE94756D1 for ; Tue, 25 Aug 2026 13:21:48 +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=1787664121; cv=none; b=dLwNpS+DVrSDnxwjkZJBQtqzsSpfEIztEDsJN8lAfsGodjpE/YP0n5I7UusRwma6j4klSJNgy3ih03V0fX1Nv+CYlOlKCnfgrLpNHM5NhUKBcvtJxbx9QHI18nF/S0pi4l90LNWk5rSL4Pkq9QJWnOPUt6zEBIk37q/ZtLGJSNg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787664121; c=relaxed/simple; bh=TZIaDz2dLWeGDWLilArCDOaTIeHYHVdTLBE5S9fIPZM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=C2Z/WDrmXCxZzREjXCTKrdOx3XlkKoavdZlW7lhqlwt3y82uzRIO+ANdtVNdg/GmQW4BPJ3lh5jO4oepUUevsT/c0TgTJQCW9TlWnvH3+BNxcr06YiuQOEQvyVjDdzMn9udrb6LlPj9yDAVTSksttHGFSXNDCqoXyARYAC+eHH8= 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=VuFezs9+; 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="VuFezs9+" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787664101; 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=sw0E+cs1TZCBxJfCLdoN86ZS+WFKAcczQoxjTe7v77A=; b=VuFezs9+QGFaSrvCw0CKEwMxgiXTOEOzNcJfV5jxx5l2KEwLBctlHbReC2bvU5gYmtymVF SWYNCinLbSiQaymgglFz1LQkPOHqEZpKhpK5MBsoMObSWotcr2Ujp6n7YUJSnrLA9fnAWG ol/3AoNwexGMCS/07zEsd1tU9f1y5yk= 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-280-6iwVOOfPPCi8TbpMpm9duQ-1; Tue, 25 Aug 2026 09:21:37 -0400 X-MC-Unique: 6iwVOOfPPCi8TbpMpm9duQ-1 X-Mimecast-MFC-AGG-ID: 6iwVOOfPPCi8TbpMpm9duQ_1787664092 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-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id B5C1C195DBAA; Tue, 25 Aug 2026 13:21:32 +0000 (UTC) Received: from warthog.com (unknown [10.44.32.15]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 081981800346; Tue, 25 Aug 2026 13:21:29 +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 Subject: [PATCH v2 8/9] netfs: Fix read progress reporting Date: Tue, 25 Aug 2026 14:20:42 +0100 Message-ID: <20260825132045.1000787-9-dhowells@redhat.com> In-Reply-To: <20260825132045.1000787-1-dhowells@redhat.com> References: <20260825132045.1000787-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" For really big read RPC ops that span multiple folios, netfslib allows the filesystem to give progress notifications to wake up the collector thread to do a collection of folios that have now been fetched, even if the RPC is still ongoing, thereby allowing the application to make progress. This works by taking the current rreq->cleaned_to value (which indicates which folios have been unlocked) and adding the stashed size of the next folio to it. cleaned_to, however, is subject to 64-bit tearing on a 32-bit arch. Fix this by stashing the next progress notification point as a size_t (which won't tear) to be added to rreq->start (which won't change), with the collector thread calculating that from cleaned_to plus the next folio size. Further, however, if the folios are small, the collector thread gets constantly woken up - which has a negative performance impact on the system. Fix that too by setting a minimum trigger of 256KiB or the size of the folio at the front of the queue, whichever is larger. Also, make sure rreq->cleaned_to is initialised up front, along with rreq->collected_to and stream->collected_to. Fixes: e2d46f2ec332 ("netfs: Change the read result collector to only use o= ne work item") Link: https://sashiko.dev/#/patchset/20260804100224.2748935-1-dhowells%40re= dhat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/buffered_read.c | 2 ++ fs/netfs/internal.h | 1 + fs/netfs/objects.c | 32 ++++++++++++-------- fs/netfs/read_collect.c | 58 +++++++++++++++++++++++++++--------- fs/netfs/read_single.c | 2 ++ include/linux/netfs.h | 2 +- include/trace/events/netfs.h | 21 +++++++++++++ 7 files changed, 91 insertions(+), 27 deletions(-) diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index 303fdce54fba..a2a9d8c083f9 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -383,6 +383,7 @@ void netfs_readahead(struct readahead_control *ractl) =20 rreq->submitted =3D rreq->start + added; rreq->cleaned_to =3D rreq->start; + netfs_read_set_unlock_at(rreq); =20 netfs_read_to_pagecache(rreq); netfs_maybe_bulk_drop_ra_refs(rreq); @@ -408,6 +409,7 @@ static int netfs_create_singular_buffer(struct netfs_io= _request *rreq, struct fo if (added < 0) return added; rreq->submitted =3D rreq->start + added; + rreq->progress_at =3D added; return 0; } =20 diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index bd8b2d633f96..c734cad7063e 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -110,6 +110,7 @@ static inline void netfs_see_subrequest(struct netfs_io= _subrequest *subreq, /* * read_collect.c */ +void netfs_read_set_unlock_at(struct netfs_io_request *rreq); bool netfs_read_collection(struct netfs_io_request *rreq); void netfs_read_collection_worker(struct work_struct *work); void netfs_cancel_read(struct netfs_io_subrequest *subreq, int error); diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index 01461a74642d..7f6a3e912602 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -41,24 +41,32 @@ struct netfs_io_request *netfs_alloc_request(struct add= ress_space *mapping, =20 memset(rreq, 0, kmem_cache_size(cache)); INIT_WORK(&rreq->cleanup_work, netfs_free_request); - rreq->gfp =3D gfp; - rreq->start =3D start; - rreq->len =3D len; - rreq->origin =3D origin; - rreq->netfs_ops =3D ctx->ops; - rreq->mapping =3D mapping; - rreq->inode =3D inode; - rreq->i_size =3D i_size_read(inode); - rreq->debug_id =3D atomic_inc_return(&debug_ids); - rreq->wsize =3D INT_MAX; + rreq->gfp =3D gfp; + rreq->start =3D start; + rreq->collected_to =3D start; + rreq->cleaned_to =3D start; + rreq->len =3D len; + rreq->progress_at =3D 0; + rreq->origin =3D origin; + rreq->netfs_ops =3D ctx->ops; + rreq->mapping =3D mapping; + rreq->inode =3D inode; + rreq->i_size =3D i_size_read(inode); + rreq->debug_id =3D atomic_inc_return(&debug_ids); + rreq->wsize =3D INT_MAX; rreq->io_streams[0].sreq_max_len =3D ULONG_MAX; rreq->io_streams[0].sreq_max_segs =3D 0; spin_lock_init(&rreq->lock); - INIT_LIST_HEAD(&rreq->io_streams[0].subrequests); - INIT_LIST_HEAD(&rreq->io_streams[1].subrequests); init_waitqueue_head(&rreq->waitq); refcount_set(&rreq->ref, 2); =20 + for (int s =3D 0; s < NR_IO_STREAMS; s++) { + struct netfs_io_stream *stream =3D &rreq->io_streams[s]; + + INIT_LIST_HEAD(&stream->subrequests); + stream->collected_to =3D rreq->start; + } + if (origin =3D=3D NETFS_READAHEAD || origin =3D=3D NETFS_READPAGE || origin =3D=3D NETFS_READ_GAPS || diff --git a/fs/netfs/read_collect.c b/fs/netfs/read_collect.c index edf7cea7e2f9..8ba162cf568b 100644 --- a/fs/netfs/read_collect.c +++ b/fs/netfs/read_collect.c @@ -94,6 +94,35 @@ static void netfs_unlock_read_folio(struct netfs_io_requ= est *rreq, folioq_clear(folioq, slot); } =20 +/* + * Determine how much to gather before unlocking more folios. + */ +void netfs_read_set_unlock_at(struct netfs_io_request *rreq) +{ + struct folio_queue *folioq =3D rreq->buffer.tail; + unsigned int slot =3D rreq->buffer.first_tail_slot; + size_t cleaned_to =3D rreq->cleaned_to - rreq->start; + size_t progress_at =3D cleaned_to; + size_t minimum =3D 256 * 1024; + + while (progress_at < rreq->len) { + if (slot >=3D folioq_count(folioq)) { + folioq =3D folioq->next; + if (!folioq) + break; + slot =3D 0; + } + + progress_at +=3D folioq_folio_size(folioq, slot); + if (progress_at - cleaned_to >=3D minimum) + break; + slot++; + } + + WRITE_ONCE(rreq->progress_at, progress_at); + trace_netfs_read_progress_at(rreq); +} + /* * Unlock any folios we've finished with. */ @@ -112,7 +141,7 @@ static void netfs_read_unlock_folios(struct netfs_io_re= quest *rreq, if (slot >=3D folioq_nr_slots(folioq)) { folioq =3D rolling_buffer_delete_spent(&rreq->buffer); if (!folioq) { - rreq->front_folio_order =3D 0; + WRITE_ONCE(rreq->progress_at, ULONG_MAX); return; } slot =3D 0; @@ -127,8 +156,7 @@ static void netfs_read_unlock_folios(struct netfs_io_re= quest *rreq, =20 for (;;) { struct folio *folio; - unsigned long long fpos, fend; - unsigned int order; + unsigned long long fpos =3D rreq->cleaned_to, fend; size_t fsize; =20 if (*notes & COPY_TO_CACHE) @@ -140,9 +168,7 @@ static void netfs_read_unlock_folios(struct netfs_io_re= quest *rreq, rreq->debug_id, folio->index)) trace_netfs_folio(folio, netfs_folio_trace_not_locked); =20 - order =3D folioq_folio_order(folioq, slot); - rreq->front_folio_order =3D order; - fsize =3D PAGE_SIZE << order; + fsize =3D folioq_folio_size(folioq, slot); fpos =3D folio_pos(folio); fend =3D fpos + fsize; =20 @@ -153,7 +179,7 @@ static void netfs_read_unlock_folios(struct netfs_io_re= quest *rreq, break; =20 netfs_unlock_read_folio(rreq, folioq, slot); - WRITE_ONCE(rreq->cleaned_to, fpos + fsize); + WRITE_ONCE(rreq->cleaned_to, fend); *notes |=3D MADE_PROGRESS; =20 clear_bit(NETFS_RREQ_FOLIO_COPY_TO_CACHE, &rreq->flags); @@ -179,6 +205,8 @@ static void netfs_read_unlock_folios(struct netfs_io_re= quest *rreq, rreq->buffer.tail =3D folioq; done: rreq->buffer.first_tail_slot =3D slot; + + netfs_read_set_unlock_at(rreq); } =20 /* @@ -239,7 +267,7 @@ static void netfs_collect_read_results(struct netfs_io_= request *rreq) * subreqs. */ if (notes & BUFFERED) { - size_t fsize =3D PAGE_SIZE << rreq->front_folio_order; + uoff_t unlock_at =3D rreq->start + rreq->progress_at; =20 /* Clear the tail of a short read. */ if (!(notes & HIT_PENDING) && @@ -264,7 +292,7 @@ static void netfs_collect_read_results(struct netfs_io_= request *rreq) transferred =3D front->len; trace_netfs_rreq(rreq, netfs_rreq_trace_set_abandon); } - if (front->start + transferred >=3D rreq->cleaned_to + fsize || + if (front->start + transferred >=3D unlock_at || test_bit(NETFS_SREQ_HIT_EOF, &front->flags)) netfs_read_unlock_folios(rreq, ¬es); } else { @@ -484,20 +512,22 @@ void netfs_read_collection_worker(struct work_struct = *work) void netfs_read_subreq_progress(struct netfs_io_subrequest *subreq) { struct netfs_io_request *rreq =3D subreq->rreq; - struct netfs_io_stream *stream =3D &rreq->io_streams[0]; - size_t fsize =3D PAGE_SIZE << rreq->front_folio_order; - - trace_netfs_sreq(subreq, netfs_sreq_trace_progress); + struct netfs_io_stream *stream =3D &rreq->io_streams[subreq->stream_nr]; + size_t progress_at =3D READ_ONCE(rreq->progress_at); + uoff_t update_at =3D rreq->start + progress_at; + uoff_t transferred_to =3D subreq->start + subreq->transferred; =20 /* If we are at the head of the queue, wake up the collector, * getting a ref to it if we were the ones to do so. */ - if (subreq->start + subreq->transferred > rreq->cleaned_to + fsize && + if (progress_at !=3D ULONG_MAX && + transferred_to >=3D update_at && (rreq->origin =3D=3D NETFS_READAHEAD || rreq->origin =3D=3D NETFS_READPAGE || rreq->origin =3D=3D NETFS_READ_FOR_WRITE) && list_is_first(&subreq->rreq_link, &stream->subrequests) ) { + trace_netfs_sreq(subreq, netfs_sreq_trace_progress); __set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags); netfs_wake_collector(rreq); } diff --git a/fs/netfs/read_single.c b/fs/netfs/read_single.c index 8833550d2eb6..de67ac41548d 100644 --- a/fs/netfs/read_single.c +++ b/fs/netfs/read_single.c @@ -170,6 +170,8 @@ ssize_t netfs_read_single(struct inode *inode, struct f= ile *file, struct iov_ite if (IS_ERR(rreq)) return PTR_ERR(rreq); =20 + rreq->progress_at =3D rreq->len; + ret =3D netfs_single_begin_cache_read(rreq, ictx); if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) goto cleanup_free; diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 5c538d0c5d79..1cf2ef3ce18b 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -246,6 +246,7 @@ struct netfs_io_request { unsigned long long submitted; /* Amount submitted for I/O so far */ unsigned long long len; /* Length of the request */ size_t transferred; /* Amount to be indicated as transferred */ + size_t progress_at; /* Report read progress when hit this much read */ long error; /* 0 or error that occurred */ unsigned long long i_size; /* Size of the file */ unsigned long long start; /* Start position */ @@ -262,7 +263,6 @@ struct netfs_io_request { atomic_t subreq_counter; /* Next subreq->debug_index */ unsigned int nr_group_rel; /* Number of refs to release on ->group */ spinlock_t lock; /* Lock for queuing subreqs */ - unsigned char front_folio_order; /* Order (size) of front folio */ enum netfs_io_origin origin; /* Origin of the request */ bool direct_bv_unpin; /* T if direct_bv[] must be unpinned */ refcount_t ref; diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index 9bda9302be90..b5da315274ad 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -789,6 +789,27 @@ TRACE_EVENT(netfs_folioq, __print_symbolic(__entry->trace, netfs_folioq_traces)) ); =20 +TRACE_EVENT(netfs_read_progress_at, + TP_PROTO(const struct netfs_io_request *rreq), + + TP_ARGS(rreq), + + TP_STRUCT__entry( + __field(unsigned int, rreq) + __field(size_t, progress_at) + __field(size_t, cleaned_to) + ), + + TP_fast_assign( + __entry->rreq =3D rreq->debug_id; + __entry->cleaned_to =3D rreq->cleaned_to - rreq->start; + __entry->progress_at =3D rreq->progress_at; + ), + + TP_printk("R=3D%08x cln=3D%zx prg=3D%zx", + __entry->rreq, __entry->cleaned_to, __entry->progress_at) + ); + #undef EM #undef E_ #endif /* _TRACE_NETFS_H */ From nobody Mon Sep 28 06:37:32 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 6A63647277C for ; Tue, 25 Aug 2026 13:21:48 +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=1787664115; cv=none; b=TlXULvwJcDZs9QPEEejsVbMTiSauhT6Gipa9xUjGy8NvI/JFoFalBN6wNH27Y+AkuxINe3umTPCxgev3TIkrLZ/5FRGT11GpSHSgaxR1MAhnUG3x54CqeEhHyV45MmstTH7qoGVrPjxRpgQAQOSuvsL1KlvWqYIdeUp0vfbyFL0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787664115; c=relaxed/simple; bh=KZ6KryDoeo8J6srSXmaESOaWmDJlcHglaMBB60PNPQY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Bkfa0QSSmAtRrqEt9+1h3CxJmc5gsS8Fi5+vlpkz6S3GNe2DcYz5t+hdzx6Xai++6aHjSDYj2yTYn4rbt5DuAUaruLZC9khOQQEyO3dtQaa1m0jW9t7qSiO4kQ1jRgOIRnc8/wYyl7HXprJBOF67hdjtKM5W662gPnemNXgzesk= 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=UnqYwdMA; 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="UnqYwdMA" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787664103; 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=XdmER/0ot6k2e8DhxaTBmIQEr/pm9tQfzddtSKAfHwo=; b=UnqYwdMAzgS9z3vuEAzz7b+wu+vRq2ADjgs7+VpcYCBTJk5+JxWLXOfnNAyjoQHjyaD1zY Zw8OTohK4B7Utuq1aTrek3ByuIhBxoeBAqk00VVdx0IrQcTHF9g2mj3iJ1bKy+FuD+m52k xqm3wNA7IYpKqlHWNSmaO0b12KABxGI= 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-423-EEeaREptNamvUDN0wtyd7Q-1; Tue, 25 Aug 2026 09:21:38 -0400 X-MC-Unique: EEeaREptNamvUDN0wtyd7Q-1 X-Mimecast-MFC-AGG-ID: EEeaREptNamvUDN0wtyd7Q_1787664097 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 260A51935303; Tue, 25 Aug 2026 13:21:37 +0000 (UTC) Received: from warthog.com (unknown [10.44.32.15]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 6B9741803A44; Tue, 25 Aug 2026 13:21:34 +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 Subject: [PATCH v2 9/9] cachefiles: Fix potential UAF/KASAN warning Date: Tue, 25 Aug 2026 14:20:43 +0100 Message-ID: <20260825132045.1000787-10-dhowells@redhat.com> In-Reply-To: <20260825132045.1000787-1-dhowells@redhat.com> References: <20260825132045.1000787-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" Currently, trace_cachefiles_coherency() is being passed a pointer to a __be64 lain over the coherency data in struct cachefiles_xattr so that it can display the first 8 bytes. However, the data is of variable length and could even be 0 bytes. This could lead to a UAF or KASAN warning. Fix this by making sure the buffer has room for at least 8 bytes and that those 8 bytes are pre-cleared. Further, those bytes are not 8-byte aligned, so fix the tracepoint to extract the data as four 2-byte words (they are 2-byte aligned) and reassemble the __be64. The compiler will convert this into a single 8-byte load where the CPU supports it. Fixes: 229105e5cfd9 ("cachefiles: Add auxiliary data trace") Link: https://sashiko.dev/#/patchset/20260810144746.574036-1-dhowells%40red= hat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/cachefiles/xattr.c | 16 ++++++++-------- include/trace/events/cachefiles.h | 19 +++++++++++++++++-- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/fs/cachefiles/xattr.c b/fs/cachefiles/xattr.c index f8ae78b3f7b6..c70bf67e52b0 100644 --- a/fs/cachefiles/xattr.c +++ b/fs/cachefiles/xattr.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "internal.h" =20 #define CACHEFILES_COOKIE_TYPE_DATA 1 @@ -50,7 +51,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object = *object) =20 _enter("%x,#%d", object->debug_id, len); =20 - buf =3D kmalloc(sizeof(struct cachefiles_xattr) + len, GFP_KERNEL); + buf =3D kmalloc(sizeof(struct cachefiles_xattr) + max(len, sizeof(__be64)= ), GFP_KERNEL); if (!buf) return -ENOMEM; =20 @@ -60,6 +61,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object = *object) buf->content =3D object->content_info; if (test_bit(FSCACHE_COOKIE_LOCAL_WRITE, &object->cookie->flags)) buf->content =3D CACHEFILES_CONTENT_DIRTY; + put_unaligned_be64(0, (__be64 *)buf->data); if (len > 0) memcpy(buf->data, fscache_get_aux(object->cookie), len); =20 @@ -77,8 +79,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object = *object) trace_cachefiles_vfs_error(object, file_inode(file), ret, cachefiles_trace_setxattr_error); trace_cachefiles_coherency(object, file_inode(file)->i_ino, - be64_to_cpup((__be64 *)buf->data), - buf->content, + buf->data, buf->content, cachefiles_coherency_set_fail); if (ret !=3D -ENOMEM) cachefiles_io_error_obj( @@ -86,8 +87,7 @@ int cachefiles_set_object_xattr(struct cachefiles_object = *object) "Failed to set xattr with error %d", ret); } else { trace_cachefiles_coherency(object, file_inode(file)->i_ino, - be64_to_cpup((__be64 *)buf->data), - buf->content, + buf->data, buf->content, cachefiles_coherency_set_ok); } =20 @@ -110,9 +110,10 @@ int cachefiles_check_auxdata(struct cachefiles_object = *object, struct file *file int ret =3D -ESTALE; =20 tlen =3D sizeof(struct cachefiles_xattr) + len; - buf =3D kmalloc(tlen, GFP_KERNEL); + buf =3D kmalloc(sizeof(struct cachefiles_xattr) + max(len, sizeof(__be64)= ), GFP_KERNEL); if (!buf) return -ENOMEM; + put_unaligned_be64(0, (__be64 *)buf->data); =20 xlen =3D cachefiles_inject_read_error(); if (xlen =3D=3D 0) @@ -148,8 +149,7 @@ int cachefiles_check_auxdata(struct cachefiles_object *= object, struct file *file =20 out: trace_cachefiles_coherency(object, file_inode(file)->i_ino, - be64_to_cpup((__be64 *)buf->data), - buf->content, why); + buf->data, buf->content, why); kfree(buf); return ret; } diff --git a/include/trace/events/cachefiles.h b/include/trace/events/cache= files.h index 9259bc71049e..e3101410e8b2 100644 --- a/include/trace/events/cachefiles.h +++ b/include/trace/events/cachefiles.h @@ -372,7 +372,7 @@ TRACE_EVENT(cachefiles_rename, TRACE_EVENT(cachefiles_coherency, TP_PROTO(struct cachefiles_object *obj, ino_t ino, - u64 disk_aux, + const void *disk_aux, enum cachefiles_content content, enum cachefiles_coherency_trace why), =20 @@ -389,12 +389,27 @@ TRACE_EVENT(cachefiles_coherency, ), =20 TP_fast_assign( + union { + __be16 s[4]; + __be64 ll; + } x; + __entry->obj =3D obj->debug_id; __entry->why =3D why; __entry->content =3D content; __entry->ino =3D ino; __entry->aux =3D be64_to_cpup((__be64 *)obj->cookie->inline_aux); - __entry->disk_aux =3D disk_aux; + + /* cachefiles_xattr::data is 2-byte aligned but not 8-byte aligned. = */ + if (disk_aux) { + x.s[0] =3D ((__be16 *)disk_aux)[0]; + x.s[1] =3D ((__be16 *)disk_aux)[1]; + x.s[2] =3D ((__be16 *)disk_aux)[2]; + x.s[3] =3D ((__be16 *)disk_aux)[3]; + __entry->disk_aux =3D be64_to_cpu(x.ll); + } else { + __entry->disk_aux =3D 0; + } ), =20 TP_printk("o=3D%08x %s B=3D%llx c=3D%u aux=3D%llx dsk=3D%llx",