All of lore.kernel.org
 help / color / mirror / Atom feed
From: Qu Wenruo <wqu@suse.com>
To: fy15309206903@gmail.com, Nick Terrell <terrelln@fb.com>,
	David Sterba <dsterba@suse.com>, Chris Mason <clm@fb.com>
Cc: linux-btrfs@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] btrfs: zstd: fix lost wakeup when waiting for a workspace
Date: Sat, 22 Aug 2026 17:31:26 +0930	[thread overview]
Message-ID: <217f5236-e34d-46bb-97d7-2429f7a74ff6@suse.com> (raw)
In-Reply-To: <20260821-btrfs-zstd-lost-wakeup-v1-1-84f358d4ea67@gmail.com>



在 2026/8/22 03:20, FAN YE via B4 Relay 写道:
> From: FAN YE <fy15309206903@gmail.com>
> 
> A writer can sleep forever in zstd_get_workspace() even though a workspace
> is free.  When zstd_alloc_workspace() fails, the task is queued on
> zwsm->wait and schedules unconditionally, never re-testing the pool.
> zstd_put_workspace() publishes the workspace and then calls cond_wake_up(),
> which only wakes when a sleeper is already visible, so a workspace returned
> between the failed allocation and prepare_to_wait() wakes nobody.  The
> window is wide: zstd_alloc_workspace() goes through kvmalloc() and may
> enter reclaim.
> 
> Only a max level workspace triggers the wakeup and one is deliberately kept
> allocated as the fallback every waiter waits for, so once its wakeup is
> lost the writer stays in TASK_UNINTERRUPTIBLE until some other task happens
> to return one.  Re-check the pool after prepare_to_wait() has published the
> waiter, and use the workspace if one turned up.
> 
> Fixes: 3f93aef535c8 ("btrfs: add zstd compression level support")
> Assisted-by: Claude:claude-opus-5
> Signed-off-by: FAN YE <fy15309206903@gmail.com>
> ---
> Reproduced under QEMU/TCG: CONFIG_FAULT_INJECTION_STACKTRACE_FILTER forces
> zstd_alloc_workspace() to fail exactly once and widens the pre-wait window
> to 400ms while six concurrent zstd:15 writers race it. Unpatched, a
> btrfs-delalloc kworker hangs in zstd_get_workspace()'s schedule() (hung_task
> warning, >120s); the identical race against the patched code does not hang.
> Compile-tested (W=1, x86_64 defconfig + CONFIG_BTRFS_FS=y).
> ---
>   fs/btrfs/zstd.c | 11 ++++++++++-
>   1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/fs/btrfs/zstd.c b/fs/btrfs/zstd.c
> index 86919293fd54..cb15cbd737c4 100644
> --- a/fs/btrfs/zstd.c
> +++ b/fs/btrfs/zstd.c
> @@ -307,8 +307,17 @@ struct list_head *zstd_get_workspace(struct btrfs_fs_info *fs_info, int level)
>   		DEFINE_WAIT(wait);
>   
>   		prepare_to_wait(&zwsm->wait, &wait, TASK_UNINTERRUPTIBLE);
> -		schedule();
> +		/*
> +		 * Re-check after being queued: zstd_put_workspace() only
> +		 * wakes a queue that already has a sleeper, so a workspace
> +		 * returned since the failed allocation woke nobody.
> +		 */
> +		ws = zstd_find_workspace(fs_info, level);
> +		if (!ws)
> +			schedule();
>   		finish_wait(&zwsm->wait, &wait);
> +		if (ws)
> +			return ws;

This doesn't work.

         Thread A (last ws holder)  |       Thread B (new ws user)
-----------------------------------+--------------------------------
zstd_put_workspace()               |
|                                  | zstd_get_workspace()
|                                  | |- zstd_find_workspace()
|                                  | |  No WS found
|                                  | |
|                                  | |- zstd_alloc_workspace()
|                                  | |  Allocation failure
|                                  | |
|                                  | |- zstd_find_workspace()
|                                  | |  Still no WS found
|- spin_lock_bh()                  | |
|- spin_unlock_bh()                | |
|- cond_wake_up()                  | |
    No one is waiting               | |- prepare_to_wait()
                                    | |- schedule()
                                    | |- finish_wait()

This is the typical LLM behavior, if your human brain can not examine 
every possibly wrong conclusion/fix from LLM, LLM will only waste time 
of everyone.
>   
>   		goto again;
>   	}
> 
> ---
> base-commit: 531ed942bb0df04f6747983fecdedce76a22d07f
> change-id: 20260821-btrfs-zstd-lost-wakeup-0b0ee88ed52f
> 
> Best regards,
> --
> FAN YE <fy15309206903@gmail.com>
> 
> 
> 


  parent reply	other threads:[~2026-08-22  8:01 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-21 17:50 [PATCH] btrfs: zstd: fix lost wakeup when waiting for a workspace FAN YE
2026-08-21 17:50 ` FAN YE via B4 Relay
2026-08-21 22:12 ` Qu Wenruo
2026-08-22  8:01 ` Qu Wenruo [this message]
2026-08-22  9:37   ` old king
2026-08-27  8:40 ` Qu Wenruo

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=217f5236-e34d-46bb-97d7-2429f7a74ff6@suse.com \
    --to=wqu@suse.com \
    --cc=clm@fb.com \
    --cc=dsterba@suse.com \
    --cc=fy15309206903@gmail.com \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=terrelln@fb.com \
    /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.