From nobody Sun Sep 27 00:39:09 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 9A3CE46D543 for ; Thu, 27 Aug 2026 13:43: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=1787838209; cv=none; b=SBKMNd1SfbHxfI58KrBQzuOqoEmSNjBsbj+0I7yZ0EZAQZPRu0N15V/6qxgzHIDahqs2hhL0TwRvL47utZAOF6kC5IUT2CiOW/Cvdi6i83R3SGhllUW9JH0Z49HCNV0wFN4Ea2Pof0AFwIrEvi/EKsyb1RDQdVZHK8pRpp/mFwE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787838209; c=relaxed/simple; bh=gZJj56dXZ3m5mpuWg5Y32mLuivOuA0n2jQSSKK4Lf/g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UwuH/MtWF89239I9FP71vAN/kdJVRgkgt8Aq/jmykaKMmIYBSJNeC8Ogc0aPv5vidfwHt/+CXhyEO6/nTURTNEZIMBKwYQ6nolnjXNw+MRMbptsF2Vh8Xy2hPzesaEG5PqVtFoVJ9QzcqwcjnxqNxSlA6UOc20FNfGFWBSHqKfc= 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=Y1fZVGuM; 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="Y1fZVGuM" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787838204; 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=Y1fZVGuMSGmAT5yjdDdT2K/Agxv8B6cMDUApssRiIjXMY5OMntkOm3cSti0nSKSfgkfD4H CtW2B93Czc1V9vOOEHhGidZ2m2FgXxeMo06flkoX7+HoeeGuw2aG/Jzy0paEdY6R87fLdt DZXGq6TUs8u2AXUlXgcaAPQVJpOHB3I= 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-180-6h6MssDMNJ6Amlr5BcUnew-1; Thu, 27 Aug 2026 09:43:18 -0400 X-MC-Unique: 6h6MssDMNJ6Amlr5BcUnew-1 X-Mimecast-MFC-AGG-ID: 6h6MssDMNJ6Amlr5BcUnew_1787838197 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-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 52F0D1802166; Thu, 27 Aug 2026 13:43:16 +0000 (UTC) Received: from warthog.com (unknown [10.22.88.47]) by mx-prod-int-10.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 36A8E423; Thu, 27 Aug 2026 13:43: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, Karl Mehltretter , stable@vger.kernel.org Subject: [PATCH v4 01/10] netfs: Fix uninitialized return value in netfs_unbuffered_write() Date: Thu, 27 Aug 2026 14:42:54 +0100 Message-ID: <20260827134304.2075713-2-dhowells@redhat.com> In-Reply-To: <20260827134304.2075713-1-dhowells@redhat.com> References: <20260827134304.2075713-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 Acked-by: Paulo Alcantara --- 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 Sun Sep 27 00:39:09 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 ED3FF378D92 for ; Thu, 27 Aug 2026 13:43:26 +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=1787838209; cv=none; b=uQeUjAjzFQAwYPMibytN8T7uawV7UkphkouWva0TGKKsLw+JPpgFBhEWh5OFLtYSE7LVS7SK3NK1hDytcwHlwLKqCeOmEF4huuT6PDXoCRIIOUT7IdUDYn1UEhBnWT5qgBYw8v8MbNrGof2j1/qPMsSv0L/jspXx8AA4XtUy18Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787838209; c=relaxed/simple; bh=txJCVMXbXZvWlCXPrv6gBGpM1BgXhBKNdFGr0ZEG6w0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BaYLo7uhNcpIbH/3mmuJuirGGWzW4Ccx8vqrnB95GCbOx/2gb1a2foe06k8h/V/CulK85CNoq+/wBOPaCiCItp1M9omMcQPmYnosJRMgjnMpY6DEhm+JkrFI7An+WY0TDOJR0MwSvp3iQE0v7xF4ny2AcIjWuD+ixs9xFWw50ew= 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=XIfaX1Ys; 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="XIfaX1Ys" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787838205; 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=XIfaX1Ysocd8hdbcifGqiSaRUaSb9CMJwPpuFuH2DMQYkI876ySdHiM7DnDJ4lcH/bNq/I K4XupOHCZm4i/f0kjWFRVpT1VOZEHXWOL9+80mwkZmwFiPL35CjoZFgGhMFfJz+NyJ+Ul7 a6kKljZ05HebE1DjrHVXnxnwax4F+8s= 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-677-GLyhZIivMGyir14htsIE-g-1; Thu, 27 Aug 2026 09:43:22 -0400 X-MC-Unique: GLyhZIivMGyir14htsIE-g-1 X-Mimecast-MFC-AGG-ID: GLyhZIivMGyir14htsIE-g_1787838200 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 0D02B19775D7; Thu, 27 Aug 2026 13:43:20 +0000 (UTC) Received: from warthog.com (unknown [10.22.88.47]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 70A5A1800348; Thu, 27 Aug 2026 13:43:17 +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 v4 02/10] netfs: Fix unbuffered/DIO write partial transfer error return Date: Thu, 27 Aug 2026 14:42:55 +0100 Message-ID: <20260827134304.2075713-3-dhowells@redhat.com> In-Reply-To: <20260827134304.2075713-1-dhowells@redhat.com> References: <20260827134304.2075713-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 Acked-by: Paulo Alcantara --- 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 Sun Sep 27 00:39:09 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 08F754734E4 for ; Thu, 27 Aug 2026 13:43:28 +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=1787838211; cv=none; b=jekSkhuYPtloG+LoL8LvmWQn8VITBbe/hwuI0G1DSR0sIdojWvb4LU2BKMK+DKmXAzvcd8gYkBYbMwvv7YTllBFQXiX42eFxf6xNEIbl+RykAC2BtIJn14auGrHSKP2upc6vmSC07t3uJJGj7u3rluo0KlpH+RWbwfBGmEv0Ezo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787838211; c=relaxed/simple; bh=IizGxEfTjfhZJVkwhDscGC2P/a5HlqU4Kr8qrccX6z4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qoyU1UAXMchHLjf8tqlunsxkx+ssKSalv5QQZX5i1IsjUpd9lZOoWPOLMF9GRgefBi/2JX7qAXLIFM7Ppy+/xTiiz5/uWuRZZvXaPaSlakqs6a/TY2l5Jb8cYOJTGIN4MQsKQpwExMXPs0NeN9V3Cw+U+xqAi9IUeTvaorRPIxA= 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=Wq+9OnDY; 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="Wq+9OnDY" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787838207; 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=Wq+9OnDYlT8JHY+VCzlJOek68euChJ/bLi0tjaOY0Adl2cx7BrQyPoKnnSg2iYdOUT//mb SsnQkRB0Vb+xQm2W012wAc83+wS9MU/qICibto09bJd+SYF5xA3qPqFCNaXFZJ4wkDen+Y NdXhPasu1yC2LVijx6MRtx9jwjpkgUo= 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-657-XRizu61CPsuLjMwlmWSQMA-1; Thu, 27 Aug 2026 09:43:25 -0400 X-MC-Unique: XRizu61CPsuLjMwlmWSQMA-1 X-Mimecast-MFC-AGG-ID: XRizu61CPsuLjMwlmWSQMA_1787838204 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-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5C8A41862D74; Thu, 27 Aug 2026 13:43:23 +0000 (UTC) Received: from warthog.com (unknown [10.22.88.47]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 42F131955F70; Thu, 27 Aug 2026 13:43:21 +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 v4 03/10] netfs: Fix error vs transferred passed to ->ki_complete() Date: Thu, 27 Aug 2026 14:42:56 +0100 Message-ID: <20260827134304.2075713-4-dhowells@redhat.com> In-Reply-To: <20260827134304.2075713-1-dhowells@redhat.com> References: <20260827134304.2075713-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 Acked-by: Paulo Alcantara --- 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 Sun Sep 27 00:39:09 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 0849F476077 for ; Thu, 27 Aug 2026 13:43:33 +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=1787838216; cv=none; b=sntLDN/7LNQdkubpb2yJ+4/aMQ/eWbnkMyTkpJwsxgsyjsD+bD8dqp2qlOXCeVvjeoBEjW8aUE84kEXese97YdveMzNBPErR7dknlxK/4nyYgPfDWDdjtE0sbyTA9WmwW0HaoUvAgjuQ+Jxi/OJaBieF2NqhQcZ4NVwuzk2U4QA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787838216; c=relaxed/simple; bh=TbyvXkUkP/iFkWLvIM6Uiy2D1Zai+6kwljmDrYii1Qs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=n/eTPFgh4iFqYbopZBmnwa6GKeatN7STzCLRmtviC2bWXHgMzyenA+0W2itAF6zOFLH5ZfJuP3rkvONKEpEvUjlp9c5z5XU8oiXBNI0k52TSSCYSPwsqfvaOR7uiaNOHpZGPHTWlTUaTJwbKN4NpuTPXca13qGDh3dSvvoXevMY= 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=c+JlEP7H; 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="c+JlEP7H" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787838212; 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=c+JlEP7HImzg+7n5PSudaVhKaqkM6IvGT2utiFT9UlNIjd58mAFMg89f6teN65DNEO4AW1 OZ5vAW+35FK+V/FBeaS6a6MS9RXusep7V6fiTjic8rz3udPcwyYeP6JgxVrvCO8tp6dupk Zx8bCoIoJIsEMHOx6DDAVpRL5hsMOPY= 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-679-MJxsoGYQNcC3GaxZhbknZw-1; Thu, 27 Aug 2026 09:43:29 -0400 X-MC-Unique: MJxsoGYQNcC3GaxZhbknZw-1 X-Mimecast-MFC-AGG-ID: MJxsoGYQNcC3GaxZhbknZw_1787838206 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 AAC65195411F; Thu, 27 Aug 2026 13:43:26 +0000 (UTC) Received: from warthog.com (unknown [10.22.88.47]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id B83DC1800641; Thu, 27 Aug 2026 13:43:24 +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 v4 04/10] netfs: Fix i_size update for partial transfer Date: Thu, 27 Aug 2026 14:42:57 +0100 Message-ID: <20260827134304.2075713-5-dhowells@redhat.com> In-Reply-To: <20260827134304.2075713-1-dhowells@redhat.com> References: <20260827134304.2075713-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_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 Acked-by: Paulo Alcantara --- 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 Sun Sep 27 00:39:09 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 2FF5A476CCA for ; Thu, 27 Aug 2026 13:43:36 +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=1787838218; cv=none; b=dSno7A30Z2bw9Fz1ydsmUNR0kpQOsbcoL+O+1xlwMmSWwZXYn2wS6FaFqiewgalqFSY0BgpHVjii/GHqM/x+1Dj/o3K00T+Kpt73MwYrFsUt+upbctQzITJfC9aglGC/hLelWdtjZIAOXyLRaEYExJz3w/7KrI8ZMCfFPXeQRHg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787838218; c=relaxed/simple; bh=FzRo1GPNzAWelnrKwWW+888gA+zU/UXIf9GDxf2VjrM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BPpVSpTpY27pzzyHEepzAgYGDkYtIT5SRxxCZ36RtYnquj6UadFnT8kyTl3u3bgnI2VWDBbzK3mPdFlEKkrQr3YdHICv9ELrSofVk2XEs/5ov8J9LzocHzB9AKvSNWSaqsnrGpDcxpXb+2W1Z01nESNbWpLf7bKyhwv2SjjD3T4= 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=iJyxD68v; 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="iJyxD68v" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787838215; 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=iJyxD68v5SGjdnaz9kClzJaMMJnqNo8DGblAYjNR+k58LCY4IELS6p5KE8dGMCdVdHu7Vm snFCgLkGZ8LHRDGbMQcf6J19gWCpIKa/EPi7Ku+MssE3RQ8Vl1ehHaEj0BX24e/4cmm7xx HIfKttFfB7MmZSFDFeESlRcUX9Rj8AQ= 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-61-O9VHSz7CMhm4q9U19GEbqg-1; Thu, 27 Aug 2026 09:43:31 -0400 X-MC-Unique: O9VHSz7CMhm4q9U19GEbqg-1 X-Mimecast-MFC-AGG-ID: O9VHSz7CMhm4q9U19GEbqg_1787838210 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-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2D45B1933EAE; Thu, 27 Aug 2026 13:43:30 +0000 (UTC) Received: from warthog.com (unknown [10.22.88.47]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 0DA6F1800346; Thu, 27 Aug 2026 13:43:27 +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 v4 05/10] netfs: Fix subreq ref leak Date: Thu, 27 Aug 2026 14:42:58 +0100 Message-ID: <20260827134304.2075713-6-dhowells@redhat.com> In-Reply-To: <20260827134304.2075713-1-dhowells@redhat.com> References: <20260827134304.2075713-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 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 Acked-by: Paulo Alcantara --- 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 Sun Sep 27 00:39:09 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 8544A4734EA for ; Thu, 27 Aug 2026 13:43:42 +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=1787838225; cv=none; b=suX0NZ+tFawdHHRRZ2806SS4bzCEIRVYhRSo2XFpHLQ8/mN+AJGqBFpw+Tjs2VMDUkPgcGtqXxV2mwpCIWMDI9ddWGjsyWL+ubm5j+Ixq4tv5jhaF4FdzVB6H+RnLOhkM152vP+smVJHQr1Rhh/k06ihdQHAUJ7qgipj3JEU+tc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787838225; c=relaxed/simple; bh=QrdzqNcCR9iFFgQpRU6lHGZ+NgG7PoA+HmJTAzSrA4Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jry+BBPKLO3GI+ktuiWZiiQutfspJxFxRwYQCzz+FPApO4MlQU1pA8CUHciRCdzP7SwGymtTJNaJ8+xT8NzBIQ7YBPV+zOn1TboffeGle1yS44/WSS93qi31fLsQ4FxmWkaaE09f+CZZDswVqrVc/BUWse1vtJxeVXNUnCRDUAc= 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=CqDRAFba; 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="CqDRAFba" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787838220; 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=P2pt6wnBqtVDYBV6sOHnn+X/jyNpYuj5XG1JqmENcwc=; b=CqDRAFbakkeRMZP5TR2qE4L4bgzw+y1Nh0YzEjpBLXKsziFEeKv6Uo2cO+ixHXUIhoHSfo xG0BUOIUJcG6kCBI7ui4STaVF/pfJzp8LFWTnL59kYxh8kLnFj4vYRdz9oQ7lL6/+F0+hr THEq8L14oMXA8/YNMoSMKxnH6qUlWsg= 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-492-FTJ01tnfM8KUUf-3Qc-ZNA-1; Thu, 27 Aug 2026 09:43:35 -0400 X-MC-Unique: FTJ01tnfM8KUUf-3Qc-ZNA-1 X-Mimecast-MFC-AGG-ID: FTJ01tnfM8KUUf-3Qc-ZNA_1787838213 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-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 90B83185CEA2; Thu, 27 Aug 2026 13:43:33 +0000 (UTC) Received: from warthog.com (unknown [10.22.88.47]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 489F018005AD; Thu, 27 Aug 2026 13:43:31 +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 v4 06/10] netfs: break unbuffered write when netfs_alloc_subrequest() fails Date: Thu, 27 Aug 2026 14:42:59 +0100 Message-ID: <20260827134304.2075713-7-dhowells@redhat.com> In-Reply-To: <20260827134304.2075713-1-dhowells@redhat.com> References: <20260827134304.2075713-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" 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] 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 Acked-by: Paulo Alcantara --- fs/netfs/direct_write.c | 5 +++++ fs/netfs/write_issue.c | 2 ++ 2 files changed, 7 insertions(+) diff --git a/fs/netfs/direct_write.c b/fs/netfs/direct_write.c index fbcfadb232ee..2361277416c7 100644 --- a/fs/netfs/direct_write.c +++ b/fs/netfs/direct_write.c @@ -110,6 +110,11 @@ 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) { + wreq->error =3D -ENOMEM; + 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 Sun Sep 27 00:39:09 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 1FF6F4734E2 for ; Thu, 27 Aug 2026 13:43:44 +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=1787838229; cv=none; b=NNizKxgLsvcqUANMkKJx1nHrnwkyzKKJH/Iurxpg2cweMDbOGw9ksu3G/v/WuhjszRbkTI9j9LnAP1/kUSo+Jtxt/B4T8NGIqqjuXSnzahyiH/VqP3F91SL9HUKv3Rqjnjs36ikWA/KSx7jwy+chm/BVARniRuaT+NpjjQh6mnA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787838229; c=relaxed/simple; bh=BjURH8bwEAnSf7cBvL6SmtlelGQtfJbu6sYmimC4rdg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JqETYpGIEMCYUuBFfRgRChTOMpIw4wpmEpSHEnpL9rreD7sOReDmsp1IIzgOXl68jSUjPGZD8GYDUBxf0Ib2pUiIS0wAiHi01EugfPf2TQGoOLiknpxhZlx3kdoKKFw8b4nRptyidcc+pySef726rXMY8Cm91qyb9RywhXGPMSM= 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=JCqae6r1; 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="JCqae6r1" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787838223; 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=JCqae6r1toJ0Ga4Dam5lXNLenXz+iAI7AGpdueoKwpAtLAPBDhsbBhfojol79726Gif1Sy WYdEBFHWgm9WGD4GHbF9xgMOhWUVIVjb14HuAqvewbJNRlNRj5Q/1PGzEIDUY9zaRUzNWD Fq9KkEk13mk/BDZZm6kZfslNFFrcT8o= 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-461-OSezVYWxOt-e2M6gmcCOig-1; Thu, 27 Aug 2026 09:43:39 -0400 X-MC-Unique: OSezVYWxOt-e2M6gmcCOig-1 X-Mimecast-MFC-AGG-ID: OSezVYWxOt-e2M6gmcCOig_1787838218 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-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5E43519540D8; Thu, 27 Aug 2026 13:43:37 +0000 (UTC) Received: from warthog.com (unknown [10.22.88.47]) by mx-prod-int-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C40081800348; Thu, 27 Aug 2026 13:43: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, Matthew Wilcox , linux-mm@kvack.org Subject: [PATCH v4 07/10] netfs: Fix readahead synchronisation issues by loading all folios upfront Date: Thu, 27 Aug 2026 14:43:00 +0100 Message-ID: <20260827134304.2075713-8-dhowells@redhat.com> In-Reply-To: <20260827134304.2075713-1-dhowells@redhat.com> References: <20260827134304.2075713-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" 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 Acked-by: Paulo Alcantara --- 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 Sun Sep 27 00:39:09 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 88555474276 for ; Thu, 27 Aug 2026 13:43: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=1787838235; cv=none; b=X7fsn6QzhULyn6GlikwNuozMUCrNAkxSWpkGEgczLtpobD0AtMC4pAEt0WZPxjfYDa7oIfAIR+HNOt+GYAqLRB5FlU0E7Z+8H1rZlcOXRGTZrxSR0ntPXunsDTBNlMUOxNA/aDhWWTnaKf3fdGfpk+qa36mCWB7NeZ+9tXYiDJQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787838235; c=relaxed/simple; bh=Yl/ZJh+3Psc+1DNGg2+MOGLRRNee16kloe3LE5AXueQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sFKCf+LvpjSmQYvDRvXrOT8zQLCTNBENIufEcXOEk9ckx2AVJFSXAcGyqe2b/M3sO8SXZdp+s9auKaMG9pU7PI3B4af7qM85yWePuS8Np63laPso2lSn1EK96a9Dme3eFYcvlghNvs7M5+4XBD2c104bptZoCCWT/kbooBInTC4= 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=G3xQSwkP; 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="G3xQSwkP" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787838227; 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=ba/IvlZYTqtQmrVqBAZRpLdnEkK4DVMXNxD+HrUDFj0=; b=G3xQSwkPAdsVjkmVsGhEChye0ufK9S9g5tM6594jSpQCPF4uJMBls9sl7CgiP63qIIQAds 4BU+03tQHHmgRWenn0u41K+86aWzkRUCE+aafxJTlP7XzJpLqZTzCSXkPHdnl8ksmYD7x6 Y8VC/tPnkcdMjySZCIHx2+WIZvRiOIs= 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-401-iXnNCPd4NvKf-DrzHFunqA-1; Thu, 27 Aug 2026 09:43:43 -0400 X-MC-Unique: iXnNCPd4NvKf-DrzHFunqA-1 X-Mimecast-MFC-AGG-ID: iXnNCPd4NvKf-DrzHFunqA_1787838222 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 D3634195DE3B; Thu, 27 Aug 2026 13:43:41 +0000 (UTC) Received: from warthog.com (unknown [10.22.88.47]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 91B353000223; Thu, 27 Aug 2026 13:43:38 +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 v4 08/10] netfs: Mark folios with COPY_TO_CACHE whilst issuing subreqs Date: Thu, 27 Aug 2026 14:43:01 +0100 Message-ID: <20260827134304.2075713-9-dhowells@redhat.com> In-Reply-To: <20260827134304.2075713-1-dhowells@redhat.com> References: <20260827134304.2075713-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" Mark folios with NETFS_FOLIO_COPY_TO_CACHE whilst issuing subreqs rather th= an when collecting them. This means that the collector thread doesn't have to try and keep track of which subreqs contribute to which folios - and thus which folios will need to be copied to the cache because at least one byte wasn't in the cache. Instead, this is marked on the folios up front and the collector need only consider the folios. For PG_private_2-using filesystems, PG_private_2 is set instead of NETFS_FOLIO_COPY_TO_CACHE, but otherwise it works the same. The NETFS_RREQ_COPY_TO_CACHE is replaced with NETFS_RREQ_CANCEL_CACHING, wh= ich is now set if caching fails somewhere, thereby causing the collection thread to cancel the copy-to-cache marks on the remaining folios. 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 Acked-by: Paulo Alcantara --- fs/netfs/buffered_read.c | 61 +++++++++++++++++++++++++++++++- fs/netfs/internal.h | 1 + fs/netfs/read_collect.c | 67 ++++++++++++++++++++++-------------- fs/netfs/read_pgpriv2.c | 15 ++++---- fs/netfs/read_retry.c | 6 +++- include/linux/netfs.h | 2 +- include/trace/events/netfs.h | 6 ++-- 7 files changed, 121 insertions(+), 37 deletions(-) diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index 303fdce54fba..16d4db776f6a 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -211,6 +211,56 @@ static void netfs_issue_read(struct netfs_io_request *= rreq, } } =20 +/* + * Mark folios that we want to copy to the cache. For filesystems that use + * netfslib fully, we set folio->private to NETFS_FOLIO_COPY_TO_CACHE; + * otherwise we set the deprecated PG_private_2. + */ +static void netfs_mark_copy_to_cache(struct netfs_io_request *rreq, + struct folio_queue **fq, + unsigned int *offset, + int *slot, + size_t len, + bool copy) +{ + while (len > 0) { + struct folio *folio; + size_t fsize, overlap; + + if (!*fq) + break; + if (*slot >=3D folioq_count(*fq)) { + *fq =3D (*fq)->next; + *slot =3D 0; + *offset =3D 0; + continue; + } + + /* Determine how much the subreq overlaps the folio, if at all. */ + fsize =3D folioq_folio_size(*fq, *slot); + overlap =3D min(len, fsize - *offset); + + if (overlap > 0 && copy) { + folio =3D folioq_folio(*fq, *slot); + if (unlikely(test_bit(NETFS_RREQ_USE_PGPRIV2, &rreq->flags))) { + if (!folio_test_private_2(folio)) + folio_start_private_2(folio); + } else { + if (!folio_get_private(folio)) + folio_attach_private(folio, NETFS_FOLIO_COPY_TO_CACHE); + } + trace_netfs_folio(folio, netfs_folio_trace_mark_copy); + } + + len -=3D overlap; + *offset +=3D overlap; + if (*offset >=3D fsize) { + *slot +=3D 1; + *offset =3D 0; + } + } +} + /* * Perform a read to the pagecache from a series of sources of different t= ypes, * slicing up the region to be read according to available cache blocks and @@ -218,9 +268,11 @@ static void netfs_issue_read(struct netfs_io_request *= rreq, */ static void netfs_read_to_pagecache(struct netfs_io_request *rreq) { + struct folio_queue *fq =3D rreq->buffer.tail; unsigned long long start =3D rreq->start; + unsigned int offset =3D 0; ssize_t size =3D rreq->len; - int ret =3D 0; + int ret =3D 0, slot =3D 0; =20 do { struct netfs_io_subrequest *subreq; @@ -308,6 +360,13 @@ static void netfs_read_to_pagecache(struct netfs_io_re= quest *rreq) set_bit(NETFS_RREQ_ALL_QUEUED, &rreq->flags); } =20 + if (fq) { + /* See if the cache indicated this should be cached. */ + bool copy =3D test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags); + + netfs_mark_copy_to_cache(rreq, &fq, &slot, &offset, slice, copy); + } + netfs_issue_read(rreq, subreq); netfs_maybe_bulk_drop_ra_refs(rreq); =20 diff --git a/fs/netfs/internal.h b/fs/netfs/internal.h index bd8b2d633f96..dfe7939f35f3 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_cancel_copy_to_cache(struct netfs_io_request *rreq, struct foli= o *folio); 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/read_collect.c b/fs/netfs/read_collect.c index edf7cea7e2f9..12a786be1ea2 100644 --- a/fs/netfs/read_collect.c +++ b/fs/netfs/read_collect.c @@ -19,7 +19,6 @@ #define MADE_PROGRESS 0x04 /* Made progress cleaning up a stream or the fo= lio set */ #define BUFFERED 0x08 /* The pagecache needs cleaning up */ #define NEED_RETRY 0x10 /* A front op requests retrying */ -#define COPY_TO_CACHE 0x40 /* Need to copy subrequest to cache */ #define ABANDON_SREQ 0x80 /* Need to abandon untransferred part of subrequ= est */ =20 /* @@ -34,6 +33,30 @@ static void netfs_clear_unread(struct netfs_io_subreques= t *subreq) __set_bit(NETFS_SREQ_HIT_EOF, &subreq->flags); } =20 +/* + * Cancel the copy-to-cache mark on a folio. + */ +void netfs_cancel_copy_to_cache(struct netfs_io_request *rreq, struct foli= o *folio) +{ + if (!test_bit(NETFS_RREQ_USE_PGPRIV2, &rreq->flags)) { + if (folio_get_private(folio) =3D=3D NETFS_FOLIO_COPY_TO_CACHE) { + folio_detach_private(folio); + trace_netfs_folio(folio, netfs_folio_trace_cancel_copy); + } else if (netfs_folio_group(folio) =3D=3D NETFS_FOLIO_COPY_TO_CACHE) { + struct netfs_folio *finfo =3D netfs_folio_info(folio); + + finfo->netfs_group =3D NULL; + trace_netfs_folio(folio, netfs_folio_trace_cancel_copy); + } + } else { + // TODO: Use of PG_private_2 is deprecated. + if (folio_test_private_2(folio)) { + folio_end_private_2(folio); + trace_netfs_folio(folio, netfs_folio_trace_cancel_copy); + } + } +} + /* * Flush, mark and unlock a folio that's now completely read. If we want = to * cache the folio, we set the group to NETFS_FOLIO_COPY_TO_CACHE, mark it @@ -48,37 +71,37 @@ static void netfs_unlock_read_folio(struct netfs_io_req= uest *rreq, =20 if (unlikely(folio_pos(folio) < rreq->abandon_to)) { trace_netfs_folio(folio, netfs_folio_trace_abandon); + netfs_cancel_copy_to_cache(rreq, folio); goto just_unlock; } =20 flush_dcache_folio(folio); folio_mark_uptodate(folio); =20 - if (!test_bit(NETFS_RREQ_USE_PGPRIV2, &rreq->flags)) { - finfo =3D netfs_folio_info(folio); - if (finfo) { - trace_netfs_folio(folio, netfs_folio_trace_filled_gaps); - if (finfo->netfs_group) - folio_change_private(folio, finfo->netfs_group); - else - folio_detach_private(folio); - kfree(finfo); - } + if (unlikely(test_bit(NETFS_RREQ_CANCEL_CACHING, &rreq->flags))) + netfs_cancel_copy_to_cache(rreq, folio); =20 - if (test_bit(NETFS_RREQ_FOLIO_COPY_TO_CACHE, &rreq->flags)) { - if (!WARN_ON_ONCE(folio_get_private(folio) !=3D NULL)) { - trace_netfs_folio(folio, netfs_folio_trace_copy_to_cache); - folio_attach_private(folio, NETFS_FOLIO_COPY_TO_CACHE); - folio_mark_dirty(folio); - } + if (!test_bit(NETFS_RREQ_USE_PGPRIV2, &rreq->flags)) { + if (netfs_folio_group(folio) =3D=3D NETFS_FOLIO_COPY_TO_CACHE) { + trace_netfs_folio(folio, netfs_folio_trace_sched_copy); + folio_mark_dirty(folio); } else { + finfo =3D netfs_folio_info(folio); + if (finfo) { + trace_netfs_folio(folio, netfs_folio_trace_filled_gaps); + if (finfo->netfs_group) + folio_change_private(folio, finfo->netfs_group); + else + folio_detach_private(folio); + kfree(finfo); + } trace_netfs_folio(folio, netfs_folio_trace_read_done); } =20 folioq_clear(folioq, slot); } else { // TODO: Use of PG_private_2 is deprecated. - if (test_bit(NETFS_RREQ_FOLIO_COPY_TO_CACHE, &rreq->flags)) + if (folio_test_private_2(folio)) netfs_pgpriv2_copy_to_cache(rreq, folio); } =20 @@ -131,9 +154,6 @@ static void netfs_read_unlock_folios(struct netfs_io_re= quest *rreq, unsigned int order; size_t fsize; =20 - if (*notes & COPY_TO_CACHE) - set_bit(NETFS_RREQ_FOLIO_COPY_TO_CACHE, &rreq->flags); - folio =3D folioq_folio(folioq, slot); if (WARN_ONCE(!folio_test_locked(folio), "R=3D%08x: folio %lx is not locked\n", @@ -156,8 +176,6 @@ static void netfs_read_unlock_folios(struct netfs_io_re= quest *rreq, WRITE_ONCE(rreq->cleaned_to, fpos + fsize); *notes |=3D MADE_PROGRESS; =20 - clear_bit(NETFS_RREQ_FOLIO_COPY_TO_CACHE, &rreq->flags); - /* Clean up the head folioq. If we clear an entire folioq, then * we can get rid of it provided it's not also the tail folioq * being filled by the issuer. @@ -255,9 +273,6 @@ static void netfs_collect_read_results(struct netfs_io_= request *rreq) stream->collected_to =3D front->start + transferred; rreq->collected_to =3D stream->collected_to; =20 - if (test_bit(NETFS_SREQ_COPY_TO_CACHE, &front->flags)) - notes |=3D COPY_TO_CACHE; - if (test_bit(NETFS_SREQ_FAILED, &front->flags)) { rreq->abandon_to =3D front->start + front->len; front->transferred =3D front->len; diff --git a/fs/netfs/read_pgpriv2.c b/fs/netfs/read_pgpriv2.c index c31190993b76..a4b7bb88cbdb 100644 --- a/fs/netfs/read_pgpriv2.c +++ b/fs/netfs/read_pgpriv2.c @@ -54,8 +54,8 @@ static void netfs_pgpriv2_copy_folio(struct netfs_io_requ= est *creq, struct folio =20 /* Attach the folio to the rolling buffer. */ if (rolling_buffer_append(&creq->buffer, folio, 0, creq->gfp) < 0) { + set_bit(NETFS_RREQ_CANCEL_CACHING, &creq->flags); folio_end_private_2(folio); - clear_bit(NETFS_RREQ_FOLIO_COPY_TO_CACHE, &creq->flags); return; } =20 @@ -122,13 +122,14 @@ static struct netfs_io_request *netfs_pgpriv2_begin_c= opy_to_cache( netfs_put_failed_request(creq); cancel: rreq->copy_to_cache =3D ERR_PTR(-ENOBUFS); - clear_bit(NETFS_RREQ_FOLIO_COPY_TO_CACHE, &rreq->flags); + set_bit(NETFS_RREQ_CANCEL_CACHING, &rreq->flags); return ERR_PTR(-ENOBUFS); } =20 /* * [DEPRECATED] Mark page as requiring copy-to-cache using PG_private_2 an= d add - * it to the copy write request. + * it to the copy write request. PG_private_2 should already be set on the + * folio. */ void netfs_pgpriv2_copy_to_cache(struct netfs_io_request *rreq, struct fol= io *folio) { @@ -136,11 +137,13 @@ void netfs_pgpriv2_copy_to_cache(struct netfs_io_requ= est *rreq, struct folio *fo =20 if (!creq) creq =3D netfs_pgpriv2_begin_copy_to_cache(rreq, folio); - if (IS_ERR(creq)) + if (IS_ERR(creq)) { + set_bit(NETFS_RREQ_CANCEL_CACHING, &rreq->flags); + netfs_cancel_copy_to_cache(rreq, folio); return; + } =20 - trace_netfs_folio(folio, netfs_folio_trace_copy_to_cache); - folio_start_private_2(folio); + trace_netfs_folio(folio, netfs_folio_trace_pgpriv2_copy); netfs_pgpriv2_copy_folio(creq, folio); } =20 diff --git a/fs/netfs/read_retry.c b/fs/netfs/read_retry.c index dd463a485139..4f6a36c6e214 100644 --- a/fs/netfs/read_retry.c +++ b/fs/netfs/read_retry.c @@ -303,7 +303,11 @@ void netfs_unlock_abandoned_read_pages(struct netfs_io= _request *rreq) for (int slot =3D 0; slot < folioq_count(p); slot++) { struct folio *folio =3D folioq_folio(p, slot); =20 - if (folio && !folioq_is_marked2(p, slot)) { + if (!folio) + continue; + netfs_cancel_copy_to_cache(rreq, folio); + + if (!folioq_is_marked2(p, slot)) { if (folio =3D=3D rreq->no_unlock_folio && test_bit(NETFS_RREQ_NO_UNLOCK_FOLIO, &rreq->flags)) { diff --git a/include/linux/netfs.h b/include/linux/netfs.h index 5c538d0c5d79..9881f4afdc0c 100644 --- a/include/linux/netfs.h +++ b/include/linux/netfs.h @@ -275,7 +275,7 @@ struct netfs_io_request { #define NETFS_RREQ_SHORT_TRANSFER 5 /* Set if we have a short transfer */ #define NETFS_RREQ_OFFLOAD_COLLECTION 8 /* Offload collection to workqueue= */ #define NETFS_RREQ_NO_UNLOCK_FOLIO 9 /* Don't unlock no_unlock_folio on co= mpletion */ -#define NETFS_RREQ_FOLIO_COPY_TO_CACHE 10 /* Copy current folio to cache f= rom read */ +#define NETFS_RREQ_CANCEL_CACHING 10 /* Set to cancel caching */ #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 */ diff --git a/include/trace/events/netfs.h b/include/trace/events/netfs.h index 9bda9302be90..a22084813cb5 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -198,7 +198,6 @@ EM(netfs_folio_trace_clear_cc, "clear-cc") \ EM(netfs_folio_trace_clear_g, "clear-g") \ EM(netfs_folio_trace_clear_s, "clear-s") \ - EM(netfs_folio_trace_copy_to_cache, "mark-copy") \ EM(netfs_folio_trace_end_copy, "end-copy") \ EM(netfs_folio_trace_filled_gaps, "filled-gaps") \ EM(netfs_folio_trace_invalidate_all, "inval-all") \ @@ -209,16 +208,19 @@ EM(netfs_folio_trace_kill_cc, "kill-cc") \ EM(netfs_folio_trace_kill_g, "kill-g") \ EM(netfs_folio_trace_kill_s, "kill-s") \ + EM(netfs_folio_trace_mark_copy, "mark-copy") \ EM(netfs_folio_trace_mkwrite, "mkwrite") \ EM(netfs_folio_trace_mkwrite_plus, "mkwrite+") \ - EM(netfs_folio_trace_not_under_wback, "!wback") \ EM(netfs_folio_trace_not_locked, "!locked") \ + EM(netfs_folio_trace_not_under_wback, "!wback") \ + EM(netfs_folio_trace_pgpriv2_copy, "pgpriv2-copy") \ EM(netfs_folio_trace_put, "put") \ EM(netfs_folio_trace_read, "read") \ EM(netfs_folio_trace_read_done, "read-done") \ EM(netfs_folio_trace_read_gaps, "read-gaps") \ EM(netfs_folio_trace_read_unlock, "read-unlock") \ EM(netfs_folio_trace_redirtied, "redirtied") \ + EM(netfs_folio_trace_sched_copy, "sched-copy") \ EM(netfs_folio_trace_store, "store") \ EM(netfs_folio_trace_store_copy, "store-copy") \ EM(netfs_folio_trace_store_plus, "store+") \ From nobody Sun Sep 27 00:39:09 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 220EA4746CA for ; Thu, 27 Aug 2026 13:43:53 +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=1787838237; cv=none; b=RDCCx4fwASVTSrLFJR01GFoDm2bc7VI1XMZdy/IA0wCeTFKajRwUOOi0DWAQ/Fycul3HtErFFnIYrzyVNZaT9skefK03SKRcWboU6HAgvNPSE0VIop2Pw6MjwKXqQ51fo9Qz7GDqv03JYpCSLQZ/zySGE41Bd9qrqiiEmBna9PM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787838237; c=relaxed/simple; bh=0mobak5QqjgREbMH1mDdUbtzl9J7d6FkzrWJahFuw7I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Vi52MIUOXoRW+C36rmKDOr2LiftNiL8K9/GWVxMzew6VbjXtk6opCu6sBiSLlbGH6KgAa4vxUKccwQIXfrziIKeLGaEs0WDxWk0FdjUxkTHs+XKLOs9TS1VmHJ/6k2GNHYmSCQIeAHLJdIN4cMQIJV8JHnIo5StEgMvxkH8+luE= 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=UygUftJb; 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="UygUftJb" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787838230; 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=Wdrsb/Alr4yIBhJotIsv0BSFS8eHSY1j2tUPpgQ1yY8=; b=UygUftJbkXW6sPHcZ8Ts3zpa4r3bnQEx7YOjrkGvbX6ns7kCWv81WcUlyFY3ExzBpbwPzG C+nUzhQEHFh93NtkjoSTfm4G2LS2ZcYzEs6kuzlnUo9hxeW0Q8r8/LNFnXfKGMPwW5u86b mxgRQeUPKr/MJMcA2dJQS+br0x1GwtM= 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-54-SD5-bgrTMAGCS9QZnUimBw-1; Thu, 27 Aug 2026 09:43:46 -0400 X-MC-Unique: SD5-bgrTMAGCS9QZnUimBw-1 X-Mimecast-MFC-AGG-ID: SD5-bgrTMAGCS9QZnUimBw_1787838225 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 0B382180267E; Thu, 27 Aug 2026 13:43:45 +0000 (UTC) Received: from warthog.com (unknown [10.22.88.47]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 1448C3000223; Thu, 27 Aug 2026 13:43:42 +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 v4 09/10] netfs: Fix read progress reporting Date: Thu, 27 Aug 2026 14:43:02 +0100 Message-ID: <20260827134304.2075713-10-dhowells@redhat.com> In-Reply-To: <20260827134304.2075713-1-dhowells@redhat.com> References: <20260827134304.2075713-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" 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. Note that this has an issue that different subreqs have different need-to-be-cached properties; this is solved by a preceding patch that marks the property on the folios whilst issuing subreqs rather than when collecting them. 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 Acked-by: Paulo Alcantara --- fs/netfs/buffered_read.c | 2 ++ fs/netfs/internal.h | 1 + fs/netfs/objects.c | 32 +++++++++++++-------- fs/netfs/read_collect.c | 54 ++++++++++++++++++++++++++++-------- fs/netfs/read_single.c | 2 ++ include/linux/netfs.h | 2 +- include/trace/events/netfs.h | 21 ++++++++++++++ 7 files changed, 89 insertions(+), 25 deletions(-) diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index 16d4db776f6a..424df70a5c30 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -442,6 +442,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); @@ -467,6 +468,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 dfe7939f35f3..c79c8e69d60c 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -111,6 +111,7 @@ static inline void netfs_see_subrequest(struct netfs_io= _subrequest *subreq, * read_collect.c */ void netfs_cancel_copy_to_cache(struct netfs_io_request *rreq, struct foli= o *folio); +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 12a786be1ea2..5cf22087d243 100644 --- a/fs/netfs/read_collect.c +++ b/fs/netfs/read_collect.c @@ -117,6 +117,35 @@ static void netfs_unlock_read_folio(struct netfs_io_re= quest *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. */ @@ -135,7 +164,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, rreq->len); return; } slot =3D 0; @@ -151,7 +180,6 @@ static void netfs_read_unlock_folios(struct netfs_io_re= quest *rreq, for (;;) { struct folio *folio; unsigned long long fpos, fend; - unsigned int order; size_t fsize; =20 folio =3D folioq_folio(folioq, slot); @@ -160,9 +188,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 @@ -197,6 +223,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 /* @@ -257,7 +285,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) && @@ -279,7 +307,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 { @@ -499,20 +527,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 < rreq->len && + 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 9881f4afdc0c..b4dd32863dd4 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 a22084813cb5..3fec3e8f91c8 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -791,6 +791,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 Sun Sep 27 00:39:09 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 2E71C477E31 for ; Thu, 27 Aug 2026 13:43:55 +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=1787838239; cv=none; b=SKCAe2ujqdXS6y/09pK0Zj8akr8Mkz3Q2XQvD/Zcq0v4wJLo40XuIyBvED83Hwni2eG0XyjxmeBFm884ZAFzJuOcEP2dFjhJ9uR9+M7LYRalg2OWGDe0OpD6XG27YcZeJ8mCvK6urga35k6zF9um4txznUw2/xUs9y8Im6O4A8A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787838239; c=relaxed/simple; bh=KZ6KryDoeo8J6srSXmaESOaWmDJlcHglaMBB60PNPQY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=D+9qOew2/6g1TYgqbDwtjDcfFKsJK1J59ZQdOhFWZg2njmn4DP32qmH3wIWLA/0o0vaStsbYGVGnV3oCIgBxt6J6KNARLWM7x31ckVcuTbFVXqavNQa2WqmdsKsl8q49bBlILm/b9EBQcuNArYcgCb6ViTw3UrzL8g5ZAlyPoYU= 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=Ww0GbC4F; 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="Ww0GbC4F" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787838232; 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=Ww0GbC4FhsFQjN6g8RPfL7lzBpqUQpEmIsaS9A6oTdoklvnNGjtiqUYOqf90WElkQSKKIP GfbipbRJFjF3vdBeJPigGbSsxUjjeJz6BJdvE22PhICYDZa+VI10NQ3U7NJiG0oZ5BTM2U kZli7QaaNdjjsYl/nsW6SaYlw828ExI= 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-443-uPXFaiIvOyiwbIf1andFVg-1; Thu, 27 Aug 2026 09:43:49 -0400 X-MC-Unique: uPXFaiIvOyiwbIf1andFVg-1 X-Mimecast-MFC-AGG-ID: uPXFaiIvOyiwbIf1andFVg_1787838228 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 34981192E246; Thu, 27 Aug 2026 13:43:48 +0000 (UTC) Received: from warthog.com (unknown [10.22.88.47]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 3F5F81955F0A; Thu, 27 Aug 2026 13:43: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 Subject: [PATCH v4 10/10] cachefiles: Fix potential UAF/KASAN warning Date: Thu, 27 Aug 2026 14:43:03 +0100 Message-ID: <20260827134304.2075713-11-dhowells@redhat.com> In-Reply-To: <20260827134304.2075713-1-dhowells@redhat.com> References: <20260827134304.2075713-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" 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 Acked-by: Paulo Alcantara --- 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",