Re: [PATCH] nilfs2: fix infinite loop in nilfs_clean_segments()
Ryusuke Konishi <[email protected]> Fri, 17 Jul 2026 19:34:21 +0900
| Newsgroups | org.kernel.vger.linux-nilfs,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CAKFNMo=L6fQa54Nd+u4ySOeTAuWF36cgymYwdjKJpD_FLeXKfw@mail.gmail.com> |
On Fri, Jul 17, 2026 at 4:49=E2=80=AFPM Joshua Crofts wrote: > > syzbot reported a hung task in nilfs_transaction_begin(). This occurs > because the cleaner ioctl falls into an infinite loop if > nilfs_segctor_construct() repeatedly returns -EROFS (e.g. the device > is remounted as read-only after an I/O error). > > Currently in nilfs_clean_segments(), if err is non-zero, it logs the > error and sleeps but doesn't abort when it encounters a terminal error > like -EROFS. This causes the thread to loop forever. > > Fix this by breaking out of the loop if nilfs_segctor_construct() > returns -EROFS. This matches the behaviour in > nilfs_segctor_write_out(), which also handles -EROFS. > > Reported-by: [email protected] > Closes: https://syzkaller.appspot.com/bug?extid=3Dcae54346a70bbceeff2c > Fixes: 9ff05123e3bf ("nilfs2: segment constructor") > Assisted-by: gemini:gemini-3.1-pro > Signed-off-by: Joshua Crofts <[email protected]> > --- > As much as I've tried, syzbot is unable to test this and always fails > with "FATAL: Kernel too old". Nevertheless, I've tested the patch with > the same reproducer in QEMU and the system didn't hang. Thanks for the patch, Joshua! This fix correctly addresses the issue reported by syzbot. I have one request regarding the loop exit: Could you modify the patch to jump to the out_unlock label instead of using break? This is to prevent discard commands from being sent to the underlying block device when the operation has failed and the filesystem state has degraded to read-only. Thanks, Ryusuke Konishi > --- > fs/nilfs2/segment.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c > index 9332f5ac6..91d3bb314 100644 > --- a/fs/nilfs2/segment.c > +++ b/fs/nilfs2/segment.c > @@ -2561,6 +2561,9 @@ int nilfs_clean_segments(struct super_block *sb, st= ruct nilfs_argv *argv, > break; > > nilfs_warn(sb, "error %d cleaning segments", err); > + if (unlikely(err =3D=3D -EROFS)) > + break; > + > set_current_state(TASK_INTERRUPTIBLE); > schedule_timeout(sci->sc_interval); > } > -- > 2.47.3 >