From nobody Tue Sep 29 14:54:45 2026 Received: from mail-pj1-f54.google.com (mail-pj1-f54.google.com [209.85.216.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DD4E548A8C1 for ; Thu, 6 Aug 2026 18:14:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786040079; cv=none; b=tXRerFjgc7g9n7bi12w6JdzRcIvc2FSQLifdsAVH3rfGOeeEO+7hKygRvxcDqEzTp4QLdieAeVoUB0Iyy7GFKdJRHvCjLCHKYdeklJVJlKlIkCOxuqg+ic1HzEtgqoSK3EcJ4rGv8PjFEE7JRnyXaHdWqvFp4F66ZD6lVICb4ic= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786040079; c=relaxed/simple; bh=CTBDXnVpz3NeNQmXCM72CfFSdfzstVzoozVZ7Cs4NhA=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=AbPYQPpN8caO6Um+lAMW/dEQv0ar1vHR0gWi80ntbBBxGlExZ9ILvIoPI+Wf44On2kNU7XtsvPctoirdNm49pZveGFeddJ5baSQijfR4b9pEfGiRZdIUohRII1nWdEqBpsqNcqe2rtay0wcEjJLWx8s7qfso9nWVAYftjec8WVk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=B6aw65cy; arc=none smtp.client-ip=209.85.216.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="B6aw65cy" Received: by mail-pj1-f54.google.com with SMTP id 98e67ed59e1d1-38dfe910e9dso2556200a91.3 for ; Thu, 06 Aug 2026 11:14:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786040077; x=1786644877; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=aJqg201eKHgYEDuPwlB67S8npmOvy/EUxknw6PZVQzs=; b=B6aw65cy9B95nAHg22KlCfCnopmkZCK1M8pqm+lTJz0D8Mpqvv4kP63LzN+hhUrx8H vaq7JWqFJ7QtJESdj+xRr6LPKe+VJ0pu01FDgbBF5xPKljUUE2MAUBpuyBehuylZIQJ2 dhiginjbrwQ1hptiaIdtB6vHih8SkLZ/KMAUajDuwimFHCiJNYHxosviWzYqfCVWcu7N 6ce5TLT5hLhQVA1Fu0STZEufLPkjUXKhMGGyAidsj0LHUdQw/DJV3rEVNKCYNmM10LSa 7wJoXSYNPohPvsHL27qs0itB6aHkQ1qGOn8H/+TaCNXj/wFrE+dKz2Mu6SYPqKxVKXv6 1h1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786040077; x=1786644877; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=aJqg201eKHgYEDuPwlB67S8npmOvy/EUxknw6PZVQzs=; b=tLf5SB/KWJFz5jdasZ2i2xIyxCwLf/euLWyvhgzF5LJsRssxqjzri1W7juDv3o96Lp mFWdJiejxmv3SMnLi4we+0DkETGd35Dan7KwbUhYz3F8ZoZAAswTtXtGBVNHqT76iX4m 1cn6DcQZyVAGxPEvXXbuCZ5iaU8udtqXQr5qsDli2eVaJ8fDOsBrG6UqEB3LaX8gqzrB oHzZk11hKJ0VEHExiJ6FaiL/buTBLMkk4dsQAMRC4/3nBKWYGWLEU0WBaYLMBKiAHNFw Vc41UO3GOYGedqzLKp2D//85898hJPCKE0g/qXBS7Z5aAQxHKd5tdhnrEcuB6Ywc9kk2 Zb8w== X-Forwarded-Encrypted: i=1; AHgh+RqLd6TRENlXRto8Bi37OZvG2JriZUABAV2+bclLbUQFY+8qwlj6y5CaduyS2lFCjiKkf1u7u0qL5u3t8/c=@vger.kernel.org X-Gm-Message-State: AOJu0YxVwR/JgL0K2spZB0bdxeBD+fKb1/43pd1VNLJTLE1n0nj1KigB f//moLjP2sTF8TN+FhcIc8e1MetC+BJ/75PZ82ypsGVaWwL3HOa9CFXW X-Gm-Gg: AR+sD12EDv00e9P29UF2D5UY1Tq3pasHyaDb6Wbj4e8HclvBA+VM0QHHoBuYxrq5/3W BADXaHS5AUjVZX+b7cMbzVyUfrjG5KpoAnv//ZCVHtPNfl1jfDKbVAQ+3tBjkUJ6dMF36CIpo/X ONiPz3CwtrITNj9y3Cd8G92wOXmhf6x15FUxajulynSWGNy4hpqnVumRXyWFAMKwa9/P4zcBBvx yiHzVxg85uQXyl/dQzKBlvX7+4vuY4NnBXAwORDgE/TZgb4UPs5EOZy3Mcnf3KJfKtTkV1qHNQ5 tmgwzgBCAvzbpoBpHbilFxS93wlS1in34DOFRvbWOeEZCxnLuwurCILRNMHoJ2iAcR6CJJti5HD XyDB0wLVb2WmWKKh2JosUuWbCmzOvlbO1OqFJGyqZyc2WZMKxRwp0HQaQZ8D/ayUvG3PyActxxt 5pdkrhmCGnmDIwcTh7eZwE6SN8pbWGV6HfrbjF3hckF3umQ8BOKpQUKGXXDK7Q51SUn4DJjdpJ/ alVJ36fchmQahu/hP5UbM2XyzWZYYJKlfP5q+9m7/gy/na+v+yWTBM= X-Received: by 2002:a17:90b:2785:b0:37d:ee77:78ac with SMTP id 98e67ed59e1d1-3903c5e70c3mr16701307a91.19.1786040077001; Thu, 06 Aug 2026 11:14:37 -0700 (PDT) Received: from carrot.taila25129.ts.net (madb688455.ap.nuro.jp. [219.104.132.85]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-39085f5c9a5sm1937546a91.15.2026.08.06.11.14.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Aug 2026 11:14:36 -0700 (PDT) From: Ryusuke Konishi To: Viacheslav Dubeyko Cc: Zhan Xusheng , Zhan Xusheng , linux-nilfs , LKML , syzbot+5957361606d7b750b874@syzkaller.appspotmail.com, syzkaller-bugs@googlegroups.com Subject: [PATCH v2] nilfs2: suppress false positive WARN_ONs for sufile after an FS error Date: Fri, 7 Aug 2026 03:13:39 +0900 Message-ID: <20260806181433.43460-1-konishi.ryusuke@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" After applying the commit associated with the Fixes tag, metadata file buffers can be evicted from memory even after being marked dirty. Consequently, operations such as rolling back sufile changes upon error - which modify the buffer and were previously assumed incapable of failure - can now fail. This behavior causes syzbot to trigger a WARN_ON check immediately following sufile function calls within the log writer. Resolve this issue by introducing a macro, nilfs_sufile_warn_on_error(), which uses WARN_ONCE to report unexpected errors only when the filesystem has not degraded to read-only mode, returning -EIO or -EROFS accordingly. Replace existing WARN_ON checks for unexpected errors following sufile operations with this new macro. Additionally, for nilfs_segctor_truncate_segments() - where an error must be propagated to halt log writing if a sufile operation fails - modify the function to return the error code appropriately. Reported-by: syzbot+5957361606d7b750b874@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=3D5957361606d7b750b874 Fixes: 8c26c4e2694a ("nilfs2: fix issue with flush kernel thread after remo= unt in RO mode because of driver's internal error or metadata corruption") Cc: # Warning suppression primarily; will req= uest backport individually if needed Signed-off-by: Ryusuke Konishi --- v2: Fix nilfs_sufile_warn_on_error() macro to correctly return _err instead of the boolean result of unlikely(_err), and add unlikely() to the return value check in nilfs_segctor_truncate_segments(). (Thanks to Zhan Xusheng for pointing out the macro bug). Hi Viacheslav, Please apply this for the next cycle at your convenience. This fixes an issue where a WARN_ON check is triggered by sufile functions within the log writer after the filesystem degrades to read-only mode. This is a false-positive warning reported by syzbot this June (and likely reported previously as well), which can occur as a normal consequence after degradation. This v2 patch fixes a macro bug pointed out, where the final expression incorrectly normalized the return value. Thanks, Ryusuke Konishi fs/nilfs2/segment.c | 36 ++++++++++++++++++++---------------- fs/nilfs2/sufile.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 16 deletions(-) diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 2189267894d2..5896fdae5669 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -1433,7 +1433,7 @@ static int nilfs_segctor_extend_segments(struct nilfs= _sc_info *sci, failed: list_for_each_entry(segbuf, &list, sb_list) { ret =3D nilfs_sufile_free(sufile, segbuf->sb_nextnum); - WARN_ON(ret); /* never fails */ + nilfs_sufile_warn_on_error(sufile, ret); } nilfs_destroy_logs(&list); return err; @@ -1449,7 +1449,7 @@ static void nilfs_free_incomplete_logs(struct list_he= ad *logs, segbuf =3D NILFS_FIRST_SEGBUF(logs); if (nilfs->ns_nextnum !=3D segbuf->sb_nextnum) { ret =3D nilfs_sufile_free(sufile, segbuf->sb_nextnum); - WARN_ON(ret); /* never fails */ + nilfs_sufile_warn_on_error(sufile, ret); } if (atomic_read(&segbuf->sb_err)) { /* Case 1: The first segment failed */ @@ -1468,7 +1468,7 @@ static void nilfs_free_incomplete_logs(struct list_he= ad *logs, list_for_each_entry_continue(segbuf, logs, sb_list) { if (prev->sb_nextnum !=3D segbuf->sb_nextnum) { ret =3D nilfs_sufile_free(sufile, segbuf->sb_nextnum); - WARN_ON(ret); /* never fails */ + nilfs_sufile_warn_on_error(sufile, ret); } if (atomic_read(&segbuf->sb_err) && segbuf->sb_segnum !=3D nilfs->ns_nextnum) @@ -1491,7 +1491,7 @@ static void nilfs_segctor_update_segusage(struct nilf= s_sc_info *sci, ret =3D nilfs_sufile_set_segment_usage(sufile, segbuf->sb_segnum, live_blocks, sci->sc_seg_ctime); - WARN_ON(ret); /* always succeed because the segusage is dirty */ + nilfs_sufile_warn_on_error(sufile, ret); } } =20 @@ -1504,28 +1504,32 @@ static void nilfs_cancel_segusage(struct list_head = *logs, struct inode *sufile) ret =3D nilfs_sufile_set_segment_usage(sufile, segbuf->sb_segnum, segbuf->sb_pseg_start - segbuf->sb_fseg_start, 0); - WARN_ON(ret); /* always succeed because the segusage is dirty */ + nilfs_sufile_warn_on_error(sufile, ret); =20 list_for_each_entry_continue(segbuf, logs, sb_list) { ret =3D nilfs_sufile_set_segment_usage(sufile, segbuf->sb_segnum, 0, 0); - WARN_ON(ret); /* always succeed */ + nilfs_sufile_warn_on_error(sufile, ret); } } =20 -static void nilfs_segctor_truncate_segments(struct nilfs_sc_info *sci, - struct nilfs_segment_buffer *last, - struct inode *sufile) +static int nilfs_segctor_truncate_segments(struct nilfs_sc_info *sci, + struct nilfs_segment_buffer *last, + struct inode *sufile) { struct nilfs_segment_buffer *segbuf =3D last; - int ret; + int ret, err =3D 0; =20 list_for_each_entry_continue(segbuf, &sci->sc_segbufs, sb_list) { sci->sc_segbuf_nblocks -=3D segbuf->sb_rest_blocks; - ret =3D nilfs_sufile_free(sufile, segbuf->sb_nextnum); - WARN_ON(ret); + + ret =3D nilfs_sufile_warn_on_error( + sufile, nilfs_sufile_free(sufile, segbuf->sb_nextnum)); + if (unlikely(ret) && err !=3D -EROFS) + err =3D ret; } nilfs_truncate_logs(&sci->sc_segbufs, last); + return err; } =20 =20 @@ -1564,7 +1568,7 @@ static int nilfs_segctor_collect(struct nilfs_sc_info= *sci, sci->sc_freesegs, sci->sc_nfreesegs, NULL); - WARN_ON(err); /* do not happen */ + nilfs_sufile_warn_on_error(nilfs->ns_sufile, err); sci->sc_stage.flags &=3D ~NILFS_CF_SUFREED; } =20 @@ -1576,8 +1580,8 @@ static int nilfs_segctor_collect(struct nilfs_sc_info= *sci, sci->sc_stage =3D prev_stage; } nilfs_segctor_zeropad_segsum(sci); - nilfs_segctor_truncate_segments(sci, sci->sc_curseg, nilfs->ns_sufile); - return 0; + err =3D nilfs_segctor_truncate_segments(sci, sci->sc_curseg, + nilfs->ns_sufile); =20 failed: return err; @@ -1878,7 +1882,7 @@ static void nilfs_segctor_abort_construction(struct n= ilfs_sc_info *sci, sci->sc_freesegs, sci->sc_nfreesegs, NULL); - WARN_ON(ret); /* do not happen */ + nilfs_sufile_warn_on_error(nilfs->ns_sufile, ret); } =20 nilfs_destroy_logs(&logs); diff --git a/fs/nilfs2/sufile.h b/fs/nilfs2/sufile.h index cd6f28ab3521..5888ed479c8b 100644 --- a/fs/nilfs2/sufile.h +++ b/fs/nilfs2/sufile.h @@ -10,6 +10,7 @@ #ifndef _NILFS_SUFILE_H #define _NILFS_SUFILE_H =20 +#include #include #include #include "mdt.h" @@ -54,6 +55,33 @@ int nilfs_sufile_read(struct super_block *sb, size_t sus= ize, struct nilfs_inode *raw_inode, struct inode **inodep); int nilfs_sufile_trim_fs(struct inode *sufile, struct fstrim_range *range); =20 +/** + * nilfs_sufile_warn_on_error - warn on unexpected sufile error + * @sufile: inode of segment usage file + * @err: status code returned by a sufile function + * + * Even if buffer heads of blocks containing segment usage entries have + * been dirtied in advance by calling functions such as + * nilfs_sufile_mark_dirty() or nilfs_sufile_{alloc,free}(), those buffers + * can be discarded from memory after the file system detects corruption a= nd + * degrades to read-only mode, which may cause sufile operations, including + * cancel operations, to return errors. nilfs_sufile_warn_on_error() is u= sed + * to detect unexpected errors other than during read-only degradation. + * + * Return: 0 if @err is 0, %-EROFS if in read-only degraded mode, and %-EIO + * otherwise. + */ +#define nilfs_sufile_warn_on_error(sufile, err) \ + ({ \ + int _err =3D (err); \ + \ + if (unlikely(_err)) \ + _err =3D WARN_ONCE(!sb_rdonly((sufile)->i_sb), \ + "unexpected sufile error %d\n", _err) ? \ + -EIO : -EROFS; \ + _err; \ + }) + /** * nilfs_sufile_scrap - make a segment garbage * @sufile: inode of segment usage file --=20 2.43.0