nilfs2: fix potential hang in nilfs_detach_log_writer()

Syzbot has reported a potential hang in nilfs_detach_log_writer() called
during nilfs2 unmount.

Analysis revealed that this is because nilfs_segctor_sync(), which
synchronizes with the log writer thread, can be called after
nilfs_segctor_destroy() terminates that thread, as shown in the call trace
below:

nilfs_detach_log_writer
nilfs_segctor_destroy
nilfs_segctor_kill_thread --> Shut down log writer thread
flush_work
nilfs_iput_work_func
nilfs_dispose_list
iput
nilfs_evict_inode
nilfs_transaction_commit
nilfs_construct_segment (if inode needs sync)
nilfs_segctor_sync --> Attempt to synchronize with
log writer thread
*** DEADLOCK ***

Fix this issue by changing nilfs_segctor_sync() so that the log writer
thread returns normally without synchronizing after it terminates, and by
forcing tasks that are already waiting to complete once after the thread
terminates.

The skipped inode metadata flushout will then be processed together in the
subsequent cleanup work in nilfs_segctor_destroy().

Link: https://lkml.kernel.org/r/20240520132621.4054-4-konishi.ryusuke@gmail.com
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Reported-by: syzbot+e3973c409251e136fdd0@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=e3973c409251e136fdd0
Tested-by: Ryusuke Konishi <konishi.ryusuke@gmail.com>
Cc: <stable@vger.kernel.org>
Cc: "Bai, Shuangpeng" <sjb7183@psu.edu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by Ryusuke Konishi and committed by Andrew Morton eb85dace 936184ea

+18 -3
+18 -3
fs/nilfs2/segment.c
··· 2190 2190 for (;;) { 2191 2191 set_current_state(TASK_INTERRUPTIBLE); 2192 2192 2193 + /* 2194 + * Synchronize only while the log writer thread is alive. 2195 + * Leave flushing out after the log writer thread exits to 2196 + * the cleanup work in nilfs_segctor_destroy(). 2197 + */ 2198 + if (!sci->sc_task) 2199 + break; 2200 + 2193 2201 if (atomic_read(&wait_req.done)) { 2194 2202 err = wait_req.err; 2195 2203 break; ··· 2213 2205 return err; 2214 2206 } 2215 2207 2216 - static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err) 2208 + static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err, bool force) 2217 2209 { 2218 2210 struct nilfs_segctor_wait_request *wrq, *n; 2219 2211 unsigned long flags; ··· 2221 2213 spin_lock_irqsave(&sci->sc_wait_request.lock, flags); 2222 2214 list_for_each_entry_safe(wrq, n, &sci->sc_wait_request.head, wq.entry) { 2223 2215 if (!atomic_read(&wrq->done) && 2224 - nilfs_cnt32_ge(sci->sc_seq_done, wrq->seq)) { 2216 + (force || nilfs_cnt32_ge(sci->sc_seq_done, wrq->seq))) { 2225 2217 wrq->err = err; 2226 2218 atomic_set(&wrq->done, 1); 2227 2219 } ··· 2370 2362 if (mode == SC_LSEG_SR) { 2371 2363 sci->sc_state &= ~NILFS_SEGCTOR_COMMIT; 2372 2364 sci->sc_seq_done = sci->sc_seq_accepted; 2373 - nilfs_segctor_wakeup(sci, err); 2365 + nilfs_segctor_wakeup(sci, err, false); 2374 2366 sci->sc_flush_request = 0; 2375 2367 } else { 2376 2368 if (mode == SC_FLUSH_FILE) ··· 2753 2745 flag = ((sci->sc_state & NILFS_SEGCTOR_COMMIT) || sci->sc_flush_request 2754 2746 || sci->sc_seq_request != sci->sc_seq_done); 2755 2747 spin_unlock(&sci->sc_state_lock); 2748 + 2749 + /* 2750 + * Forcibly wake up tasks waiting in nilfs_segctor_sync(), which can 2751 + * be called from delayed iput() via nilfs_evict_inode() and can race 2752 + * with the above log writer thread termination. 2753 + */ 2754 + nilfs_segctor_wakeup(sci, 0, true); 2756 2755 2757 2756 if (flush_work(&sci->sc_iput_work)) 2758 2757 flag = true;