]> git.ipfire.org Git - thirdparty/kernel/stable.git/commit
jffs2: GC deadlock reading a page that is used in jffs2_write_begin()
authorKyeong Yoo <kyeong.yoo@alliedtelesis.co.nz>
Tue, 4 Jul 2017 04:22:38 +0000 (16:22 +1200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 27 Jan 2022 07:47:38 +0000 (08:47 +0100)
commit02c04d12834a8bca1e54cdce3abc0bd93e0bd70a
tree68bbd1dc9ab939b317be05f6d42da369571b4001
parent79e66952fbbd64240f84c6ca4bc416c74248681b
jffs2: GC deadlock reading a page that is used in jffs2_write_begin()

[ Upstream commit aa39cc675799bc92da153af9a13d6f969c348e82 ]

GC task can deadlock in read_cache_page() because it may attempt
to release a page that is actually allocated by another task in
jffs2_write_begin().
The reason is that in jffs2_write_begin() there is a small window
a cache page is allocated for use but not set Uptodate yet.

This ends up with a deadlock between two tasks:
1) A task (e.g. file copy)
   - jffs2_write_begin() locks a cache page
   - jffs2_write_end() tries to lock "alloc_sem" from
 jffs2_reserve_space() <-- STUCK
2) GC task (jffs2_gcd_mtd3)
   - jffs2_garbage_collect_pass() locks "alloc_sem"
   - try to lock the same cache page in read_cache_page() <-- STUCK

So to avoid this deadlock, hold "alloc_sem" in jffs2_write_begin()
while reading data in a cache page.

Signed-off-by: Kyeong Yoo <kyeong.yoo@alliedtelesis.co.nz>
Signed-off-by: Richard Weinberger <richard@nod.at>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/jffs2/file.c