From: Usama Arif <usama.arif@linux.dev>
To: Phillip Lougher <phillip@squashfs.org.uk>,
Andrew Morton <akpm@linux-foundation.org>,
linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org
Cc: brauner@kernel.org, hannes@cmpxchg.org, shakeel.butt@linux.dev,
jlayton@kernel.org, boris@bur.io, riel@surriel.com,
kernel-team@meta.com
Subject: Re: [PATCH v2] squashfs: avoid thundering-herd cache wakeups
Date: Mon, 10 Aug 2026 11:30:28 +0100 [thread overview]
Message-ID: <23a6115a-b508-4601-a304-04d05fce9426@linux.dev> (raw)
In-Reply-To: <f03dc086-220f-4aca-92ce-dd3184a100a6@squashfs.org.uk>
On 09/08/2026 23:43, Phillip Lougher wrote:
>
>
> On 07/08/2026 18:24, Usama Arif wrote:
>> squashfs_cache_get() puts a task to sleep when its block is not cached
>> and every cache entry is busy. Those sleeps are non-exclusive, so the
>> nr_exclusive == 1 budget squashfs_cache_put() has always passed to
>> wake_up() is inert and one release makes every waiter runnable. A wakee
>> only returns to squashfs_cache_get() if it observes cache->unused before
>> the entry is reclaimed; later wakees see zero and re-queue inside
>> wait_event() without rescanning. One freed entry satisfies exactly one
>> capacity waiter, so waking the rest is waste.
>>
>> On a Meta production host serving a Python web application from a
>> packaged squashfs image, a 30-second trace caught 1,045,132
>> cache-release wake calls and 19,511,556 wakeups: 18.7 per release,
>> although each release added only one reusable cache entry. This was
>> causing significant spikes in CPU usage.
>>
>> Make the waits exclusive, enqueueing while still holding cache->lock so
>> that a concurrent lookup either sees the waiter queued or the waiter
>> sees the block that lookup publishes. Two things follow.
>>
>> A wakee cannot be assumed to consume the entry it was woken for: it may
>> find its own block published meanwhile, share that entry, and leave the
>> freed one unclaimed. So a wakee which shares hands its wakeup on to the
>> next waiter, as commit 0ddad21d3e99 ("pipe: use exclusive waits when
>> reading or writing") does with wake_next_reader.
>>
>> And a waiter can now sleep through a publication of the very block it
>> wants, which the old broadcast gave it repeated chances to notice. So
>> waiters are keyed by block: publishing wakes every waiter for that block
>> (nr_exclusive == 0), freeing an entry wakes one. That needs a custom
>> wake callback, like wake_page_function() in mm/filemap.c, which also
>> records which wakeup arrived so the handoff only fires for a capacity
>> wakee.
>>
>> Broadcast is kept where more than one task can proceed - every waiter
>> for a published block, and the wake_up_all() on entry->wait_queue - at
>> the cost of walking the queue under wait_queue.lock to test the key.
>> Waiters are now served FIFO with a scheduling round trip per handoff
>> hop, so per-waiter latency changes; the filebench run below is 4x
>> oversubscribed, where that should hurt most.
>>
>> Measured on a 32-CPU VM against a read-only squashfs (gzip,
>> DECOMP_MULTI_PERCPU, FILE_DIRECT, default 8 metadata / 3 fragment cache
>> entries) staged in tmpfs, page cache dropped each iteration to force
>> cold decompression:
>>
>> elbencho, 64 threads
>> metadata stat 700 -> 1320 files/s 1.9x
>> small-file read 40 -> 60 MiB/s 1.5x
>>
>> filebench, 128 threads, open+read+stat+close (mean of 3x 30s)
>> throughput 11,314 -> 25,186 ops/s 2.2x
>> sched:sched_wakeup 27.0 -> 4.55 per op 5.9x fewer
>> context switches 37.2 -> 7.64 per op 4.9x fewer
>>
>> Wakeups and context switches are per operation, since the two runs did
>> 2.2x different amounts of work. Workloads which never queue for a cache
>> entry gain no wakeups.
>>
>> Signed-off-by: Usama Arif <usama.arif@linux.dev>
>> ---
>> fs/squashfs/cache.c | 114 +++++++++++++++++++++++++++++++++--
>> fs/squashfs/squashfs_fs_sb.h | 9 +++
>> 2 files changed, 117 insertions(+), 6 deletions(-)
>
> Very nice performance improvement. Thanks.
>
> Reviewed-by: Phillip Lougher <phillip@squashfs.org.uk>
>
Thanks Phillip!
Regards,
Usama
prev parent reply other threads:[~2026-08-10 10:30 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-07 17:24 [PATCH v2] squashfs: avoid thundering-herd cache wakeups Usama Arif
2026-08-09 22:43 ` Phillip Lougher
2026-08-10 10:30 ` Usama Arif [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=23a6115a-b508-4601-a304-04d05fce9426@linux.dev \
--to=usama.arif@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=boris@bur.io \
--cc=brauner@kernel.org \
--cc=hannes@cmpxchg.org \
--cc=jlayton@kernel.org \
--cc=kernel-team@meta.com \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=phillip@squashfs.org.uk \
--cc=riel@surriel.com \
--cc=shakeel.butt@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.