Re: [PATCH v2] nilfs2: fix infinite loop in nilfs_clean_segments()
Viacheslav Dubeyko <[email protected]> Tue, 28 Jul 2026 16:43:22 -0700
| Newsgroups | org.kernel.vger.linux-nilfs,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On Fri, 2026-07-17 at 22:30 +0900, Ryusuke Konishi wrote: > On Fri, Jul 17, 2026 at 7:59=E2=80=AFPM Joshua Crofts wrote: > >=20 > > 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). > >=20 > > 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. > >=20 > > 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. > >=20 > > 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]> > > --- > > Changes in v2: > > - use `goto out_unlock` instead of break to prevent discard > > commands > > =C2=A0 from being sent > >=20 > > 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. > > --- > > =C2=A0fs/nilfs2/segment.c | 4 ++++ > > =C2=A01 file changed, 4 insertions(+) > >=20 > > diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c > > index 9332f5ac6..218926789 100644 > > --- a/fs/nilfs2/segment.c > > +++ b/fs/nilfs2/segment.c > > @@ -2561,6 +2561,10 @@ int nilfs_clean_segments(struct super_block > > *sb, struct nilfs_argv *argv, > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 break= ; > >=20 > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0 nilfs_warn(sb, "error %d cleaning segments", err); > > + > > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0 if (unlikely(err =3D=3D -EROFS)) > > +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 goto out_un= lock; > > + > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0 set_current_state(TASK_INTERRUPTIBLE); > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0 schedule_timeout(sci->sc_interval); > > =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 } > > -- > > 2.47.3 >=20 > Looks good. >=20 > Viacheslav, could you please pick this up for your queue? >=20 > Acked-by: Ryusuke Konishi <[email protected]> >=20 >=20 Applied. Thanks, Slava.