Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

nilfs2: fix state management in error path of log writing function

After commit a694291a6211 ("nilfs2: separate wait function from
nilfs_segctor_write") was applied, the log writing function
nilfs_segctor_do_construct() was able to issue I/O requests continuously
even if user data blocks were split into multiple logs across segments,
but two potential flaws were introduced in its error handling.

First, if nilfs_segctor_begin_construction() fails while creating the
second or subsequent logs, the log writing function returns without
calling nilfs_segctor_abort_construction(), so the writeback flag set on
pages/folios will remain uncleared. This causes page cache operations to
hang waiting for the writeback flag. For example,
truncate_inode_pages_final(), which is called via nilfs_evict_inode() when
an inode is evicted from memory, will hang.

Second, the NILFS_I_COLLECTED flag set on normal inodes remain uncleared.
As a result, if the next log write involves checkpoint creation, that's
fine, but if a partial log write is performed that does not, inodes with
NILFS_I_COLLECTED set are erroneously removed from the "sc_dirty_files"
list, and their data and b-tree blocks may not be written to the device,
corrupting the block mapping.

Fix these issues by uniformly calling nilfs_segctor_abort_construction()
on failure of each step in the loop in nilfs_segctor_do_construct(),
having it clean up logs and segment usages according to progress, and
correcting the conditions for calling nilfs_redirty_inodes() to ensure
that the NILFS_I_COLLECTED flag is cleared.

Link: https://lkml.kernel.org/r/20240814101119.4070-1-konishi.ryusuke@gmail.com
Fixes: a694291a6211 ("nilfs2: separate wait function from nilfs_segctor_write")
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Tested-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Ryusuke Konishi and committed by
Andrew Morton
6576dd66 5787fcaa

+6 -4
+6 -4
fs/nilfs2/segment.c
··· 1812 1812 nilfs_abort_logs(&logs, ret ? : err); 1813 1813 1814 1814 list_splice_tail_init(&sci->sc_segbufs, &logs); 1815 + if (list_empty(&logs)) 1816 + return; /* if the first segment buffer preparation failed */ 1817 + 1815 1818 nilfs_cancel_segusage(&logs, nilfs->ns_sufile); 1816 1819 nilfs_free_incomplete_logs(&logs, nilfs); 1817 1820 ··· 2059 2056 2060 2057 err = nilfs_segctor_begin_construction(sci, nilfs); 2061 2058 if (unlikely(err)) 2062 - goto out; 2059 + goto failed; 2063 2060 2064 2061 /* Update time stamp */ 2065 2062 sci->sc_seg_ctime = ktime_get_real_seconds(); ··· 2123 2120 return err; 2124 2121 2125 2122 failed_to_write: 2126 - if (sci->sc_stage.flags & NILFS_CF_IFILE_STARTED) 2127 - nilfs_redirty_inodes(&sci->sc_dirty_files); 2128 - 2129 2123 failed: 2124 + if (mode == SC_LSEG_SR && nilfs_sc_cstage_get(sci) >= NILFS_ST_IFILE) 2125 + nilfs_redirty_inodes(&sci->sc_dirty_files); 2130 2126 if (nilfs_doing_gc()) 2131 2127 nilfs_redirty_inodes(&sci->sc_gc_inodes); 2132 2128 nilfs_segctor_abort_construction(sci, nilfs, err);