From nobody Mon Sep 28 08:54:52 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 23089288C2D for ; Mon, 24 Aug 2026 12:02:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787572964; cv=none; b=nVcEgxoB2pQNhd1nDuMk+QIxUAN9/MbtY5rinCAoZdxaTANr2TDv0K+3bZL5yVJoMXMYhJ3bNSZYNw1fjAr3hGue/FLvvfG9n+CIHtivX5z20b0PwE53z4gIJgvc9JEC0JOeuWyo9SEKvvsbxEheaiV07RMmPVhq15pAZdY82bA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787572964; c=relaxed/simple; bh=gZJj56dXZ3m5mpuWg5Y32mLuivOuA0n2jQSSKK4Lf/g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fEKaplGLj9HHPQy5+MLrFlggiqs1ZGuv2fr/Hw1wIjFTHYmCBciONvSkp2RgrARbvn5n+5zdQ2u8lu3+Vut5x7xBBOXWI0SNfEz405Je0LVRCOg8vN4+WPQvywIx0Np5xv0cCcZwGSudkSW7WAMSOjjPSnND47zY6uJbZuB07zQ= 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=YaUUyk/z; 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="YaUUyk/z" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787572962; 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=YaUUyk/ztEtGfVKnYUNV27WnzbjEr7J+byS0bZhfS3QqG1Tpg6TMG4lGsVq14dJbTLugRu KXfp1+N7K+0PzDgzyMJgpJHaGsI8zt1+jcOjVMp2sDMeJcArToz7hudSkJAxrhCb+ykns1 J5ESQH96NXlrokuKqZbqYBWXfEGMVBk= 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-QKIZ5IQHPW2M0-MoD0otjw-1; Mon, 24 Aug 2026 08:02:37 -0400 X-MC-Unique: QKIZ5IQHPW2M0-MoD0otjw-1 X-Mimecast-MFC-AGG-ID: QKIZ5IQHPW2M0-MoD0otjw_1787572956 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 2192A19540C5; Mon, 24 Aug 2026 12:02:36 +0000 (UTC) Received: from warthog.com (unknown [10.44.32.15]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7F8A11800257; Mon, 24 Aug 2026 12:02:32 +0000 (UTC) From: David Howells To: Christian Brauner Cc: David Howells , Paulo Alcantara , netfs@lists.linux.dev, linux-afs@lists.infradead.org, linux-cifs@vger.kernel.org, ceph-devel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Karl Mehltretter , stable@vger.kernel.org Subject: [PATCH 1/3] netfs: Fix uninitialized return value in netfs_unbuffered_write() Date: Mon, 24 Aug 2026 13:02:20 +0100 Message-ID: <20260824120224.504575-2-dhowells@redhat.com> In-Reply-To: <20260824120224.504575-1-dhowells@redhat.com> References: <20260824120224.504575-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Content-Type: text/plain; charset="utf-8" From: Karl Mehltretter If preparation of the first subrequest fails, netfs_unbuffered_write() exits its loop before ret is initialized. The empty-iterator check can do the same. For synchronous writes, netfs_unbuffered_write_iter_locked() may then return an unrelated error instead of wreq->error. This is reachable through CIFS if cifs_prepare_write() fails to reopen the file or obtain credits. Initialize ret to 0 so the caller returns wreq->error if no data was written, or the number of bytes already written otherwise. Found with Clang's -Wconditional-uninitialized. Fixes: a0b4c7a49137e ("netfs: Fix unbuffered/DIO writes to dispatch subrequ= ests in strict sequence") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-fable-5 Signed-off-by: Karl Mehltretter Signed-off-by: David Howells --- fs/netfs/direct_write.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/netfs/direct_write.c b/fs/netfs/direct_write.c index c16fbad286a1..b04019097ab8 100644 --- a/fs/netfs/direct_write.c +++ b/fs/netfs/direct_write.c @@ -95,7 +95,7 @@ static int netfs_unbuffered_write(struct netfs_io_request= *wreq) { struct netfs_io_subrequest *subreq =3D NULL; struct netfs_io_stream *stream =3D &wreq->io_streams[0]; - int ret; + int ret =3D 0; =20 _enter("%llx", wreq->len); From nobody Mon Sep 28 08:54:52 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 1A5E94189CC for ; Mon, 24 Aug 2026 12:02:47 +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=1787572969; cv=none; b=DyBAXMIKG9ZpnPHmrDQBTERj1nRYjsoNyoB/ECnxdCvi87VMAZjTs/hV/8k4A6bQsZxYyrxaKUoP7DAIgTdnFs49Lf5VrA97VP6B7fQlmcKIClmElFaW/Aq0W8uCkXlIKu2FYfOgOT7Et2BFBCyS2bAEng8Wcb1bPwlz/L+pfYw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787572969; c=relaxed/simple; bh=iURkUWmXNqdrO5vzPkm+gyumrPcUezjSMTqyZ65/fMg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HdiMnYzEViSF/vI9N/wU9hn4rI25uKJtUn2zqVzCFWgBGnW5hpYqRTg+vqCrq8Ad1QIk2jUcYMbWAnaf3jGAeKLePvBJThR5Bu0VaQCiiKWE9dEJeKAnM4Yi0bhbikzX0oAGOMnpysxAOPG+pV9lr5T05u/6v1Il79CvBrG9zxI= 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=Ogn0/nYZ; 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="Ogn0/nYZ" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787572966; 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=t/Vnaq263uFXisfUC8xRe+FUG1J3lRybpMK7FQGmnfk=; b=Ogn0/nYZeiJ8WvVB9XxmLZFuwzW34PMp+Q+MvyeSwUFLqrbP+tmnFRn7eKqF1Revh5Gs7p SvxDOCWs3WJm4sAdTwgWY7Bd37VYik5H4FLXol6Tg07/CX/3BVCl0Fss56BZvuoiObnvRx FzT0osMX0v2RQZ9r1ZGrUrsqS8nSJS8= 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-172-aaniOsKqOiK68GyNTVbk6g-1; Mon, 24 Aug 2026 08:02:42 -0400 X-MC-Unique: aaniOsKqOiK68GyNTVbk6g-1 X-Mimecast-MFC-AGG-ID: aaniOsKqOiK68GyNTVbk6g_1787572961 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-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id A045B1830727; Mon, 24 Aug 2026 12:02:40 +0000 (UTC) Received: from warthog.com (unknown [10.44.32.15]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id B9DC81800605; Mon, 24 Aug 2026 12:02:37 +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 2/3] netfs: Fix read progress reporting Date: Mon, 24 Aug 2026 13:02:21 +0100 Message-ID: <20260824120224.504575-3-dhowells@redhat.com> In-Reply-To: <20260824120224.504575-1-dhowells@redhat.com> References: <20260824120224.504575-1-dhowells@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 Content-Type: text/plain; charset="utf-8" For really big read RPC ops that span multiple folios, netfslib allows the filesystem to give progress notifications to wake up the collector thread to do a collection of folios that have now been fetched, even if the RPC is still ongoing, thereby allowing the application to make progress. This works by taking the current rreq->cleaned_to value (which indicates which folios have been unlocked) and adding the stashed size of the next folio to it. cleaned_to, however, is subject to 64-bit tearing on a 32-bit arch. Fix this by stashing the next progress notification point as a size_t (which won't tear) to be added to rreq->start (which won't change), with the collector thread calculating that from cleaned_to plus the next folio size. Further, however, if the folios are small, the collector thread gets constantly woken up - which has a negative performance impact on the system. Fix that too by setting a minimum trigger of 256KiB or the size of the folio at the front of the queue, whichever is larger. Also, make sure rreq->cleaned_to is initialised up front, along with rreq->collected_to and stream->collected_to. Fixes: e2d46f2ec332 ("netfs: Change the read result collector to only use o= ne work item") Link: https://sashiko.dev/#/patchset/20260804100224.2748935-1-dhowells%40re= dhat.com Signed-off-by: David Howells cc: Paulo Alcantara cc: netfs@lists.linux.dev cc: linux-fsdevel@vger.kernel.org --- fs/netfs/buffered_read.c | 4 +++ fs/netfs/internal.h | 1 + fs/netfs/objects.c | 32 ++++++++++++-------- fs/netfs/read_collect.c | 58 +++++++++++++++++++++++++++--------- fs/netfs/read_single.c | 2 ++ include/linux/netfs.h | 2 +- include/trace/events/netfs.h | 21 +++++++++++++ 7 files changed, 93 insertions(+), 27 deletions(-) diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c index 7fdfa4f27e34..3c32ef41a27f 100644 --- a/fs/netfs/buffered_read.c +++ b/fs/netfs/buffered_read.c @@ -106,6 +106,9 @@ static ssize_t netfs_prepare_read_iterator(struct netfs= _io_subrequest *subreq, folio_batch_release(&put_batch); return added; } + + if (!rreq->progress_at) + netfs_read_set_unlock_at(rreq); rreq->submitted +=3D added; } folio_batch_release(&put_batch); @@ -387,6 +390,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 420ee7b26580..f92281a611de 100644 --- a/fs/netfs/internal.h +++ b/fs/netfs/internal.h @@ -109,6 +109,7 @@ static inline void netfs_see_subrequest(struct netfs_io= _subrequest *subreq, /* * read_collect.c */ +void netfs_read_set_unlock_at(struct netfs_io_request *rreq); bool netfs_read_collection(struct netfs_io_request *rreq); void netfs_read_collection_worker(struct work_struct *work); void netfs_cancel_read(struct netfs_io_subrequest *subreq, int error); diff --git a/fs/netfs/objects.c b/fs/netfs/objects.c index 01461a74642d..7f6a3e912602 100644 --- a/fs/netfs/objects.c +++ b/fs/netfs/objects.c @@ -41,24 +41,32 @@ struct netfs_io_request *netfs_alloc_request(struct add= ress_space *mapping, =20 memset(rreq, 0, kmem_cache_size(cache)); INIT_WORK(&rreq->cleanup_work, netfs_free_request); - rreq->gfp =3D gfp; - rreq->start =3D start; - rreq->len =3D len; - rreq->origin =3D origin; - rreq->netfs_ops =3D ctx->ops; - rreq->mapping =3D mapping; - rreq->inode =3D inode; - rreq->i_size =3D i_size_read(inode); - rreq->debug_id =3D atomic_inc_return(&debug_ids); - rreq->wsize =3D INT_MAX; + rreq->gfp =3D gfp; + rreq->start =3D start; + rreq->collected_to =3D start; + rreq->cleaned_to =3D start; + rreq->len =3D len; + rreq->progress_at =3D 0; + rreq->origin =3D origin; + rreq->netfs_ops =3D ctx->ops; + rreq->mapping =3D mapping; + rreq->inode =3D inode; + rreq->i_size =3D i_size_read(inode); + rreq->debug_id =3D atomic_inc_return(&debug_ids); + rreq->wsize =3D INT_MAX; rreq->io_streams[0].sreq_max_len =3D ULONG_MAX; rreq->io_streams[0].sreq_max_segs =3D 0; spin_lock_init(&rreq->lock); - INIT_LIST_HEAD(&rreq->io_streams[0].subrequests); - INIT_LIST_HEAD(&rreq->io_streams[1].subrequests); init_waitqueue_head(&rreq->waitq); refcount_set(&rreq->ref, 2); =20 + for (int s =3D 0; s < NR_IO_STREAMS; s++) { + struct netfs_io_stream *stream =3D &rreq->io_streams[s]; + + INIT_LIST_HEAD(&stream->subrequests); + stream->collected_to =3D rreq->start; + } + if (origin =3D=3D NETFS_READAHEAD || origin =3D=3D NETFS_READPAGE || origin =3D=3D NETFS_READ_GAPS || diff --git a/fs/netfs/read_collect.c b/fs/netfs/read_collect.c index 23660a590124..723b479ef606 100644 --- a/fs/netfs/read_collect.c +++ b/fs/netfs/read_collect.c @@ -94,6 +94,35 @@ static void netfs_unlock_read_folio(struct netfs_io_requ= est *rreq, folioq_clear(folioq, slot); } =20 +/* + * Determine how much to gather before unlocking more folios. + */ +void netfs_read_set_unlock_at(struct netfs_io_request *rreq) +{ + struct folio_queue *folioq =3D rreq->buffer.tail; + unsigned int slot =3D rreq->buffer.first_tail_slot; + size_t cleaned_to =3D rreq->cleaned_to - rreq->start; + size_t progress_at =3D cleaned_to; + size_t minimum =3D 256 * 1024; + + while (progress_at < rreq->len) { + if (slot >=3D folioq_nr_slots(folioq)) { + folioq =3D folioq->next; + if (!folioq) + break; + slot =3D 0; + } + + progress_at +=3D folioq_folio_size(folioq, slot); + if (progress_at - cleaned_to >=3D minimum) + break; + slot++; + } + + WRITE_ONCE(rreq->progress_at, progress_at); + trace_netfs_read_progress_at(rreq); +} + /* * Unlock any folios we've finished with. */ @@ -112,7 +141,7 @@ static void netfs_read_unlock_folios(struct netfs_io_re= quest *rreq, if (slot >=3D folioq_nr_slots(folioq)) { folioq =3D rolling_buffer_delete_spent(&rreq->buffer); if (!folioq) { - rreq->front_folio_order =3D 0; + WRITE_ONCE(rreq->progress_at, ULONG_MAX); return; } slot =3D 0; @@ -120,8 +149,7 @@ static void netfs_read_unlock_folios(struct netfs_io_re= quest *rreq, =20 for (;;) { struct folio *folio; - unsigned long long fpos, fend; - unsigned int order; + unsigned long long fpos =3D rreq->cleaned_to, fend; size_t fsize; =20 if (*notes & COPY_TO_CACHE) @@ -133,9 +161,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 @@ -146,7 +172,7 @@ static void netfs_read_unlock_folios(struct netfs_io_re= quest *rreq, break; =20 netfs_unlock_read_folio(rreq, folioq, slot); - WRITE_ONCE(rreq->cleaned_to, fpos + fsize); + WRITE_ONCE(rreq->cleaned_to, fend); *notes |=3D MADE_PROGRESS; =20 clear_bit(NETFS_RREQ_FOLIO_COPY_TO_CACHE, &rreq->flags); @@ -172,6 +198,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 /* @@ -232,7 +260,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) && @@ -257,7 +285,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 { @@ -477,20 +505,22 @@ void netfs_read_collection_worker(struct work_struct = *work) void netfs_read_subreq_progress(struct netfs_io_subrequest *subreq) { struct netfs_io_request *rreq =3D subreq->rreq; - struct netfs_io_stream *stream =3D &rreq->io_streams[0]; - size_t fsize =3D PAGE_SIZE << rreq->front_folio_order; - - trace_netfs_sreq(subreq, netfs_sreq_trace_progress); + struct netfs_io_stream *stream =3D &rreq->io_streams[subreq->stream_nr]; + size_t progress_at =3D READ_ONCE(rreq->progress_at); + uoff_t update_at =3D rreq->start + progress_at; + uoff_t transferred_to =3D subreq->start + subreq->transferred; =20 /* If we are at the head of the queue, wake up the collector, * getting a ref to it if we were the ones to do so. */ - if (subreq->start + subreq->transferred > rreq->cleaned_to + fsize && + if (progress_at !=3D ULONG_MAX && + transferred_to >=3D update_at && (rreq->origin =3D=3D NETFS_READAHEAD || rreq->origin =3D=3D NETFS_READPAGE || rreq->origin =3D=3D NETFS_READ_FOR_WRITE) && list_is_first(&subreq->rreq_link, &stream->subrequests) ) { + trace_netfs_sreq(subreq, netfs_sreq_trace_progress); __set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags); netfs_wake_collector(rreq); } diff --git a/fs/netfs/read_single.c b/fs/netfs/read_single.c index 8833550d2eb6..de67ac41548d 100644 --- a/fs/netfs/read_single.c +++ b/fs/netfs/read_single.c @@ -170,6 +170,8 @@ ssize_t netfs_read_single(struct inode *inode, struct f= ile *file, struct iov_ite if (IS_ERR(rreq)) return PTR_ERR(rreq); =20 + rreq->progress_at =3D rreq->len; + ret =3D netfs_single_begin_cache_read(rreq, ictx); if (ret =3D=3D -ENOMEM || ret =3D=3D -EINTR || ret =3D=3D -ERESTARTSYS) goto cleanup_free; diff --git a/include/linux/netfs.h b/include/linux/netfs.h index f837a501008c..a8702bd52d3a 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 082cb03c6131..8ec10c076875 100644 --- a/include/trace/events/netfs.h +++ b/include/trace/events/netfs.h @@ -786,6 +786,27 @@ TRACE_EVENT(netfs_folioq, __print_symbolic(__entry->trace, netfs_folioq_traces)) ); =20 +TRACE_EVENT(netfs_read_progress_at, + TP_PROTO(const struct netfs_io_request *rreq), + + TP_ARGS(rreq), + + TP_STRUCT__entry( + __field(unsigned int, rreq) + __field(size_t, progress_at) + __field(size_t, cleaned_to) + ), + + TP_fast_assign( + __entry->rreq =3D rreq->debug_id; + __entry->cleaned_to =3D rreq->cleaned_to - rreq->start; + __entry->progress_at =3D rreq->progress_at; + ), + + TP_printk("R=3D%08x cln=3D%zx prg=3D%zx", + __entry->rreq, __entry->cleaned_to, __entry->progress_at) + ); + #undef EM #undef E_ #endif /* _TRACE_NETFS_H */ From nobody Mon Sep 28 08:54:52 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 1A44241A547 for ; Mon, 24 Aug 2026 12:02:52 +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=1787572973; cv=none; b=brTF4hwahvsnJ0++o2aG8pm5/27y0hiXqQUJ90zSTZXsYXTqWNG4/Nz2fUbwptAvmRzDVWPC/svNwIsUZnAEbfyGBj8LoiZuwfutFbGmLNzoKsVDfavFaIWwvIirC2sXwt9Vcm6hpNJrUH4yZJ3PD5Qn6jGFcUG+RCZjSJ6yObw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787572973; c=relaxed/simple; bh=QrVxkC1qUai+LkpCyw0Tz6tntuP4Wpe1tMlKeqdSWwU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rBvw7d1kmUgwM3GZ+EBSw3R1GeFlPa8OBbtuogD+2ALitnD554q/XwNRcKfp3ywIHcOfNX+bpFxfoDgLnT+BBSU6aiqTrVS3VCV6poNXci0A0DM0iF1VKp37pYYKFK4HftEa436O+AiKXk1ZUysH6YpNzZOZ7igfVErGrx1RQ7E= 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=En2dOkDy; 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="En2dOkDy" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1787572971; 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=hoJL241RSoxtycntHxJVxwYZyJBhwGJRmdZEHBFJJr0=; b=En2dOkDyk7vkvvOUPc4perAv3NEh6qoXsFYb924Woc/ErWzJUKKhatmMZ9EZYZgyGqzzPY X2VIzG+iOrKzM5OnV1lGASlt4ZUCc2Fx+HfaFN/7msal//EyN33FssMsZ47zJrLlWCDoNj gaJR+aVjOYfeua0cBHXgZ+CHO2WMrn4= 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-634-PXsIUWAfMBqM0Rgk4A1ljw-1; Mon, 24 Aug 2026 08:02:46 -0400 X-MC-Unique: PXsIUWAfMBqM0Rgk4A1ljw-1 X-Mimecast-MFC-AGG-ID: PXsIUWAfMBqM0Rgk4A1ljw_1787572965 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 1665C1977038; Mon, 24 Aug 2026 12:02:45 +0000 (UTC) Received: from warthog.com (unknown [10.44.32.15]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 3D7851955F07; Mon, 24 Aug 2026 12:02: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 3/3] cachefiles: Fix potential UAF/KASAN warning Date: Mon, 24 Aug 2026 13:02:22 +0100 Message-ID: <20260824120224.504575-4-dhowells@redhat.com> In-Reply-To: <20260824120224.504575-1-dhowells@redhat.com> References: <20260824120224.504575-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 --- 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..92990cfdcca7 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) + min(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) + min(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..927338f8fe85 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 not 64-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",