diff options
| author | Chao Yu <chao@kernel.org> | 2026-10-10 14:55:46 +0800 |
|---|---|---|
| committer | Jaegeuk Kim <jaegeuk@kernel.org> | 2026-10-13 18:45:04 +0000 |
| commit | a605d5d71a6d280c43c7ede9778dda63fb5c3f22 (patch) | |
| tree | 153828b8f548dcf02d506ce5e35ec30574b9803e /tools/lib/python | |
| parent | e4582e5f3b439228d4e900edcf8225aa89be32b4 (diff) | |
| download | linux-next-a605d5d71a6d280c43c7ede9778dda63fb5c3f22.tar.gz linux-next-a605d5d71a6d280c43c7ede9778dda63fb5c3f22.zip | |
f2fs: fix to use bio_in_atomic() in f2fs_read_end_io()
f2fs_read_end_io() uses "in_task() && !irqs_disabled()" to decide
whether it is safe to sleep, the result is passed down as @in_task to:
- f2fs_put_dic() -> f2fs_free_dic() -> f2fs_release_decomp_mem()
-> vm_unmap_ram(), which may sleep.
- f2fs_end_read_compressed_page() -> f2fs_cache_compressed_page()
-> f2fs_grab_cache() -> f2fs_lock_cache(), which may sleep in
wait_on_bit_lock().
However, the check still treats below task contexts as sleepable:
- with spinlock held via spin_lock(), i.e. preempt count != 0 while
irqs are enabled.
- with BH disabled via local_bh_disable().
- inside an RCU read lock on kernels with CONFIG_PREEMPTION.
- with any spinlock held on kernels without CONFIG_PREEMPT_COUNT.
So the "sleeping function called from invalid context" issue fixed by
commit 08a7efc5b02a ("f2fs: vm_unmap_ram() may be called from an
invalid context") can still be triggered.
The block layer provides bio_in_atomic() for exactly this purpose, it
checks rcu_preempt_depth() and preemptible(), and conservatively returns
true if CONFIG_PREEMPT_COUNT is disabled, let's use it instead. The
difference is as below:
old: intask = in_task() && !irqs_disabled()
new: intask = !bio_in_atomic()
Context | old intask | new intask
-------------------------------------+----------------+----------------
Hard IRQ / softirq | false | false
IRQs disabled | false | false
spin_lock() held, IRQs enabled | true (wrong) | false
BH disabled by local_bh_disable() | true (wrong) | false
RCU read lock (CONFIG_PREEMPTION) | true (wrong) | false
Spinlock held, w/o PREEMPT_COUNT | true (wrong) | false
Note that on kernels without CONFIG_PREEMPT_COUNT, bio_in_atomic()
always returns true, so dic freeing will always be offloaded to sbi->wq,
and compressed pages will not be cached in f2fs_read_end_io(); this is
the price of correctness, since there is no way to tell whether the
current context can sleep.
Cc: stable@kernel.org
Fixes: 08a7efc5b02a ("f2fs: vm_unmap_ram() may be called from an invalid context")
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'tools/lib/python')
0 files changed, 0 insertions, 0 deletions
