A lockdep WARN is observed recently under the following steps:
1) Create a zoned TCMU device
2) Create a f2fs filesystem on the zoned TCMU device and mount it
3) Fill the filesystem with files and trigger GC
4) Unmout the filesystem
5) Remove the zoned TCMU device
The lockdep WARN indicates that a circular lock depedency formed by four
contexts, as described below.
a) TCMU device removal context:
- call del_gendisk() to get q->q_usage_counter
- call start_flush_work() to get work_completion of wb->dwork
b) f2fs writeback context:
- in wb_workfn(), which holds work_completion of wb->dwork
- call f2fs_balance_fs() to get sbi->gc_lock
c) f2fs vfs_write context:
- call f2fs_gc() to get sbi->gc_lock
- call f2fs_write_checkpoint() to get sbi->cp_global_sem
d) f2fs mount context:
- call recover_fsync_data() to get sbi->cp_global_sem
- call f2fs_check_and_fix_write_pointer() to call blkdev_report_zones()
that goes down to blk_mq_alloc_request and get q->q_usage_counter
To suppress the WARN, cut the dependency d) between sbi->cp_global_sem
and q->q_usage_counter. For that purpose, move the
f2fs_check_and_fix_write_pointer() call outside of the critical section
of sbi->cp_global_sem in f2fs_recovery_fsync_data(). This change is fine
because the write pointer fix operation only affects the main segments
and does not interact with the check point metadata. Furthermore,
conflicts between the write pointer fix operation and data/node flush
operations remain protected by SBI_POR_DOING.
Fixes: c426d99127b1 ("f2fs: Check write pointer consistency of open zones")
Signed-off-by: Shin'ichiro Kawasaki <[email protected]>
---
fs/f2fs/recovery.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index a26071f2b0bc..87fd6cd436fe 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -922,6 +922,8 @@ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool
check_only)
truncate_inode_pages_final(META_MAPPING(sbi));
}
+ f2fs_up_write_trace(&sbi->cp_global_sem, &lc);
+
/*
* If fsync data succeeds or there is no fsync data to recover,
* and the f2fs is not read only, check and fix zoned block devices'
@@ -933,8 +935,6 @@ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool
check_only)
if (!err)
clear_sbi_flag(sbi, SBI_POR_DOING);
- f2fs_up_write_trace(&sbi->cp_global_sem, &lc);
-
/* let's drop all the directory inodes for clean checkpoint */
destroy_fsync_dnodes(&dir_list, err);
--
2.49.0
_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel