From nobody Fri Oct 2 02:30:16 2026 Received: from mail-pl1-f174.google.com (mail-pl1-f174.google.com [209.85.214.174]) (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 DABAA41B8CD for ; Thu, 6 Aug 2026 09:03:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786006997; cv=none; b=BMVyqdNIANjCGz//aBvjOmDqGv/Qwg9R4wtU5k+6WJ0JUeAw9Ppo3DuhSUk53UEc39ZUgnlyPrOeY22LGTrvr5ABmzzHLijDcpgyfYKxVbU1iH9YBJfA1WelNUbjVJmvlXsdRXkqHOeu7BWb3YarEDMadu3UVIdFckcUqVImx4Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786006997; c=relaxed/simple; bh=vlmYr8FZdam9m8IeQB9okPpPJXNoGZskZHh8i3FJGok=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=KSysql8SNgs4FrH2D0DU48cSbVmv3i0wdJklAUyI5wyp7E0PCsZVVKfBfWNEFJFDdqLSpTtlMCWrhh+Un/ACxYRruug3HM2GG4Lf+hZwVhKsL4ChWmcNNumwOuomj4fGJPx7M5+LkJGfvqA7zEAlSJoqJ/iTAKmzaZL973f99po= 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=XSzZcaev; arc=none smtp.client-ip=209.85.214.174 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="XSzZcaev" Received: by mail-pl1-f174.google.com with SMTP id d9443c01a7336-2cea3004256so24611665ad.0 for ; Thu, 06 Aug 2026 02:03:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1786006995; x=1786611795; 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=8OhdDnLO8z1OVTh7Cja/MEj5ZqrQfY51g7lPg1wFyPw=; b=XSzZcaevg5r+LEn1kLBox4BnAuNcZ8zYlmZpB20iQwh/2Hi/engXTEgfLII3OtJlYI q3p5EbgXV9vFVNN0vmKEoqniW565YRzpDKDqIi8MBb/cRgnr/CPT3mi3A26ooctuaqHk ESAERb8/ShhpxVKcFCm85KLQqBoMhkL3x/qcIl9dE285eAkI2v71FZq2tmx7fZvIqN7A R/Pgenvc4tJGn+p1DBw7zesAAb4FJZLqciStG4Z1BQ+b+fBqGQBKZEWW64qZmCtu7lyh YBKhB62o47NHiXRVxIt7r0ZBnsc4MOhlNDCM82XYwlDD/iAT2Voj9XtRn2RStDvwN+E+ zgmg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786006995; x=1786611795; 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=8OhdDnLO8z1OVTh7Cja/MEj5ZqrQfY51g7lPg1wFyPw=; b=TM6wXWvDBJxOMEt9aVrXJU3WWnzj9hWWPYDEvRnS0AYWRcOExI3Qv6MWwkaBYk0a+u G32Zi24lVYePzkV4CITBfO7w8/bl1SojWjvcBr3kIwLKRKZtLiQ5zPNLR3fCCx7Y1JWG A166gF5aWlBMknSuyad6bXAL1pAuZj31a+IX6emqyvT5AhiZz0xXtMUkMH7ic/qmuldK ppyIqmoxTIxOQEXDokvvWFNRL/xLeTg5Qn6YDRJN9WNiXh/lQZ+YLBtghoyu5/i/lOkz V7AvmwhWWHBcH3T54y6++1wovsJQeMxa0jQnj06T+hKt97fLSrV4fb5SIjuMnpSFpxTN /S2g== X-Forwarded-Encrypted: i=1; AHgh+RpeIu+x2zJZ+mnUl1cMLZuxt96ZmKEFNOEqjTKraKjMZmk/ve3QBYiaNzXvC5IQZ6cxIzYKzIhK+vXFozs=@vger.kernel.org X-Gm-Message-State: AOJu0YwPpgIWZWVrJaEtONiuPEZTGHnUVJ5sD+6kMaO0wlPpQanpaDhw uTw+e4M5h7KAChvaAmdwejG1y22/DeHL0njtA7qW4DRI/K/7PhzezGP6 X-Gm-Gg: AR+sD10b+kPgfoe/0d0LCtl5qycHFRNwrsU8l++oIfjcL8aXitwYCAA1e4yYCNnqMSi 3CO2kQDFUBl+6SmcDD5TDGKjYH8qq9PFBWYrmet5TOcLFbsK1LG/vk6RLL8l5KcTXa8uQuZfg2M nqHhRGPofplsg2RDOK410cEDVbK9vWEvPy6UBi2BrCtgeUULIBxfNVEwBJOsvZqqjxlucCTC2JN esgCiYnFZ/WkOXUUFsJIJzVnuONalu4yvzx28YaSfLR1X0YbJrHQe3SotE4/dvwPCX2kbjr023a AwOqIik8q+IrGeFTfhdtrEyfZOh1Olghgogk9pRh5eeGgr8DP0Ldlzbv4mjVbpbaQCMAUJLCw/J cwjBpG5Knd+vMTa78quGHuWNgJ97kbL/91ZM1rWOzN+BIQl9bDL6J0z5f3kX8SaqMGIMJNhNFjy 1YDnk8P+FAIThzKqBvQPAaS2JgrYS1m9n16VNEZvcolBwQ6T3GJKU/VxkTu5qK5l56QR8y81B4U j7UimeV2A+rnI9bz8cB0fD1q0R3evPQ X-Received: by 2002:a17:903:3201:b0:2d0:401c:2ebb with SMTP id d9443c01a7336-2d0ca7125cemr166761795ad.4.1786006995091; Thu, 06 Aug 2026 02:03:15 -0700 (PDT) Received: from carrot.taila25129.ts.net (madb688455.ap.nuro.jp. [219.104.132.85]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2d0aa4bbc5csm27965115ad.62.2026.08.06.02.03.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Aug 2026 02:03:14 -0700 (PDT) From: Ryusuke Konishi To: Viacheslav Dubeyko Cc: linux-nilfs , LKML , syzbot+5957361606d7b750b874@syzkaller.appspotmail.com, syzkaller-bugs@googlegroups.com Subject: [PATCH] nilfs2: suppress false positive WARN_ONs for sufile after an FS error Date: Thu, 6 Aug 2026 18:02:00 +0900 Message-ID: <20260806090311.32633-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 --- 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. 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..4345b4a226e8 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 (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..a2e05d9584a0 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; \ + unlikely(_err); \ + }) + /** * nilfs_sufile_scrap - make a segment garbage * @sufile: inode of segment usage file --=20 2.43.0