]> git.hungrycats.org Git - linux/commitdiff
f2fs: fix to avoid potential deadloop in f2fs_fsync_node_pages()
authorChao Yu <chao@kernel.org>
Mon, 24 Aug 2026 13:17:29 +0000 (21:17 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Tue, 25 Aug 2026 02:04:36 +0000 (02:04 +0000)
There is potential deadloop in race condition:

Thread A Thread B
- fsync
 - f2fs_do_sync_file
  - f2fs_fsync_node_pages
   - last_fsync_dnode
    - folio_get(last_folio)
- f2fs_setattr
 - f2fs_truncate
  - f2fs_truncate_blocks
   - f2fs_do_truncate_blocks
    - f2fs_truncate_inode_blocks
     - truncate_dnode
      - truncate_node
       - invalidate_mapping_pages
        - folio->mapping = NULL
   - is_node_folio alwasy return false
   - atomic && !marked is always true,
     then goto retry

Cc: stable@kernel.org
Fixes: 608514deba38 ("f2fs: set fsync mark only for the last dnode")
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/node.c

index 968e5ed38816fe692aaed222acb4d7fc06c58281..86c2e67e43b6ae9502b2f410631a427851567c9f 100644 (file)
@@ -2016,6 +2016,11 @@ continue_unlock:
                f2fs_debug(sbi, "Retry to write fsync mark: ino=%u, idx=%lx",
                           ino, last_folio->index);
                folio_lock(last_folio);
+               if (unlikely(!is_node_folio(last_folio))) {
+                       f2fs_folio_put(last_folio, true);
+                       ret = -EAGAIN;
+                       goto out;
+               }
                f2fs_folio_wait_writeback(last_folio, NODE, true, true);
                folio_mark_dirty(last_folio);
                folio_unlock(last_folio);