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 for (;;) { 2191 set_current_state(TASK_INTERRUPTIBLE); 2192 2193 if (atomic_read(&wait_req.done)) { 2194 err = wait_req.err; 2195 break; ··· 2213 return err; 2214 } 2215 2216 - static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err) 2217 { 2218 struct nilfs_segctor_wait_request *wrq, *n; 2219 unsigned long flags; ··· 2221 spin_lock_irqsave(&sci->sc_wait_request.lock, flags); 2222 list_for_each_entry_safe(wrq, n, &sci->sc_wait_request.head, wq.entry) { 2223 if (!atomic_read(&wrq->done) && 2224 - nilfs_cnt32_ge(sci->sc_seq_done, wrq->seq)) { 2225 wrq->err = err; 2226 atomic_set(&wrq->done, 1); 2227 } ··· 2370 if (mode == SC_LSEG_SR) { 2371 sci->sc_state &= ~NILFS_SEGCTOR_COMMIT; 2372 sci->sc_seq_done = sci->sc_seq_accepted; 2373 - nilfs_segctor_wakeup(sci, err); 2374 sci->sc_flush_request = 0; 2375 } else { 2376 if (mode == SC_FLUSH_FILE) ··· 2753 flag = ((sci->sc_state & NILFS_SEGCTOR_COMMIT) || sci->sc_flush_request 2754 || sci->sc_seq_request != sci->sc_seq_done); 2755 spin_unlock(&sci->sc_state_lock); 2756 2757 if (flush_work(&sci->sc_iput_work)) 2758 flag = true;
··· 2190 for (;;) { 2191 set_current_state(TASK_INTERRUPTIBLE); 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 + 2201 if (atomic_read(&wait_req.done)) { 2202 err = wait_req.err; 2203 break; ··· 2205 return err; 2206 } 2207 2208 + static void nilfs_segctor_wakeup(struct nilfs_sc_info *sci, int err, bool force) 2209 { 2210 struct nilfs_segctor_wait_request *wrq, *n; 2211 unsigned long flags; ··· 2213 spin_lock_irqsave(&sci->sc_wait_request.lock, flags); 2214 list_for_each_entry_safe(wrq, n, &sci->sc_wait_request.head, wq.entry) { 2215 if (!atomic_read(&wrq->done) && 2216 + (force || nilfs_cnt32_ge(sci->sc_seq_done, wrq->seq))) { 2217 wrq->err = err; 2218 atomic_set(&wrq->done, 1); 2219 } ··· 2362 if (mode == SC_LSEG_SR) { 2363 sci->sc_state &= ~NILFS_SEGCTOR_COMMIT; 2364 sci->sc_seq_done = sci->sc_seq_accepted; 2365 + nilfs_segctor_wakeup(sci, err, false); 2366 sci->sc_flush_request = 0; 2367 } else { 2368 if (mode == SC_FLUSH_FILE) ··· 2745 flag = ((sci->sc_state & NILFS_SEGCTOR_COMMIT) || sci->sc_flush_request 2746 || sci->sc_seq_request != sci->sc_seq_done); 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); 2755 2756 if (flush_work(&sci->sc_iput_work)) 2757 flag = true;