* Re: [PATCH 19/32] ntfs3: Drop pointless sync_mapping_buffers() call
From: Jan Kara @ 2026-03-05 16:26 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jan Kara, linux-fsdevel, Christian Brauner, Al Viro, linux-ext4,
Ted Tso, Tigran A. Aivazian, David Sterba, OGAWA Hirofumi,
Muchun Song, Oscar Salvador, David Hildenbrand, linux-mm,
linux-aio, Benjamin LaHaise, Konstantin Komarov, ntfs3
In-Reply-To: <aag2nTROMNra7t6l@infradead.org>
On Wed 04-03-26 05:41:49, Christoph Hellwig wrote:
>
> Can you move the various cleanups that don't really depend on any of
> the refactoring to the front of the list? i.e., drop all the useless
> code first before doing real changes?
Yeah, good idea. Done.
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH 17/32] fs: Move metadata bhs tracking to a separate struct
From: Jan Kara @ 2026-03-05 16:39 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jan Kara, linux-fsdevel, Christian Brauner, Al Viro, linux-ext4,
Ted Tso, Tigran A. Aivazian, David Sterba, OGAWA Hirofumi,
Muchun Song, Oscar Salvador, David Hildenbrand, linux-mm,
linux-aio, Benjamin LaHaise
In-Reply-To: <aag2URb_D0h--RKX@infradead.org>
On Wed 04-03-26 05:40:33, Christoph Hellwig wrote:
> On Tue, Mar 03, 2026 at 11:34:06AM +0100, Jan Kara wrote:
> > +static void remove_assoc_queue(struct buffer_head *bh)
> > +{
> > + struct address_space *mapping;
> > + struct mapping_metadata_bhs *mmb;
> > +
> > + /*
> > + * The locking dance is ugly here. We need to acquire lock
> > + * protecting metadata bh list while possibly racing with bh
> > + * being removed from the list or moved to a different one. We
> > + * use RCU to pin mapping_metadata_bhs in memory to
> > + * opportunistically acquire the lock and then recheck the bh
> > + * didn't move under us.
> > + */
>
> Should the buffer_head simply have a pointer to the metadata bh list,
> as that would avoid all this and keep a lot of the references to the
> list self-contained?
Yes, after some thinking that should be doable if we then add pointer to
address_space to struct mapping_metadata_bhs. I'll try how the patches are
going to look like.
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH 17/32] fs: Move metadata bhs tracking to a separate struct
From: Jan Kara @ 2026-03-05 16:42 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jan Kara, linux-fsdevel, Christian Brauner, Al Viro, linux-ext4,
Ted Tso, Tigran A. Aivazian, David Sterba, OGAWA Hirofumi,
Muchun Song, Oscar Salvador, David Hildenbrand, linux-mm,
linux-aio, Benjamin LaHaise
In-Reply-To: <aag1vDoCVwAlIKPq@infradead.org>
On Wed 04-03-26 05:38:04, Christoph Hellwig wrote:
> Maybe just call the structure buffer_head_list at it really just is a
> totall generic list of buffer heads with a lock?
Well, since we'll be adding pointer to address_space there and eventually I
need to add a pointer to the buffer_head containing the inode to fix a bug
that fsync(2) now doesn't properly persist the inode metadata for all these
filesystems (but I didn't want to clutter this series with that fix), I
think a special name is warranted.
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH v2 2/2] resize: fix memory leak when exiting normally
From: Theodore Tso @ 2026-03-05 17:38 UTC (permalink / raw)
To: Wu Guanghao; +Cc: linux-ext4, adilger.kernel, djwong, yangyun50
In-Reply-To: <20251121033612.2423536-3-wuguanghao3@huawei.com>
On Fri, Nov 21, 2025 at 11:36:12AM +0800, Wu Guanghao wrote:
> The main() function only releases fs when it exits through the errout or
> success_exit labels. When completes normally, it does not release fs.
>
> Signed-off-by: Wu Guanghao <wuguanghao3@huawei.com>
I'm guessing you only tested the online resize code path?
if (mount_flags & EXT2_MF_MOUNTED) {
retval = online_resize_fs(fs, mtpt, &new_size, flags);
} else {
...
retval = resize_fs(fs, &new_size, flags,
((flags & RESIZE_PERCENT_COMPLETE) ?
resize_progress_func : 0));
}
The reason why I ask this is that resize_fs() frees fs on the success path:
rfs->old_fs = fs;
...
ext2fs_free(rfs->old_fs);
... although if we return when an error, we do *not* free ext2fs_free(rfs->old_fs).
So if you were to test with this applied when resizing a non-mounted
file system, I believe you'd get a double free failure.
Cheers,
- Ted
^ permalink raw reply
* Re: [PATCH 24/24] fs: remove simple_nosetlease()
From: Jeff Layton @ 2026-03-05 19:25 UTC (permalink / raw)
To: Mike Snitzer
Cc: Luis de Bethencourt, Salah Triki, Nicolas Pitre,
Christoph Hellwig, Jan Kara, Anders Larsen, Alexander Viro,
Christian Brauner, David Sterba, Chris Mason, Gao Xiang, Chao Yu,
Yue Hu, Jeffle Xu, Sandeep Dhavale, Hongbo Li, Chunhai Guo,
Jan Kara, Theodore Ts'o, Andreas Dilger, Jaegeuk Kim,
OGAWA Hirofumi, David Woodhouse, Richard Weinberger,
Dave Kleikamp, Ryusuke Konishi, Viacheslav Dubeyko,
Konstantin Komarov, Mark Fasheh, Joel Becker, Joseph Qi,
Mike Marshall, Martin Brandenburg, Miklos Szeredi, Amir Goldstein,
Phillip Lougher, Carlos Maiolino, Hugh Dickins, Baolin Wang,
Andrew Morton, Namjae Jeon, Sungjong Seo, Yuezhang Mo,
Chuck Lever, Alexander Aring, Andreas Gruenbacher,
Jonathan Corbet, Matthew Wilcox (Oracle), Eric Van Hensbergen,
Latchesar Ionkov, Dominique Martinet, Christian Schoenebeck,
Xiubo Li, Ilya Dryomov, Trond Myklebust, Anna Schumaker,
Steve French, Paulo Alcantara, Ronnie Sahlberg, Shyam Prasad N,
Tom Talpey, Bharath SM, Hans de Goede, linux-kernel,
linux-fsdevel, linux-btrfs, linux-erofs, linux-ext4,
linux-f2fs-devel, linux-mtd, jfs-discussion, linux-nilfs, ntfs3,
ocfs2-devel, devel, linux-unionfs, linux-xfs, linux-mm, gfs2,
linux-doc, v9fs, ceph-devel, linux-nfs, linux-cifs,
samba-technical
In-Reply-To: <aaiyWlJelhHju741@kernel.org>
On Wed, 2026-03-04 at 17:29 -0500, Mike Snitzer wrote:
> On Wed, Mar 04, 2026 at 11:59:32AM -0500, Jeff Layton wrote:
> > On Wed, 2026-02-25 at 12:58 -0500, Mike Snitzer wrote:
> > > On Thu, Jan 08, 2026 at 12:13:19PM -0500, Jeff Layton wrote:
> > > > Setting ->setlease() to a NULL pointer now has the same effect as
> > > > setting it to simple_nosetlease(). Remove all of the setlease
> > > > file_operations that are set to simple_nosetlease, and the function
> > > > itself.
> > > >
> > > > Signed-off-by: Jeff Layton <jlayton@kernel.org>
> > > > ---
> > > > fs/9p/vfs_dir.c | 2 --
> > > > fs/9p/vfs_file.c | 2 --
> > > > fs/ceph/dir.c | 2 --
> > > > fs/ceph/file.c | 1 -
> > > > fs/fuse/dir.c | 1 -
> > > > fs/gfs2/file.c | 2 --
> > > > fs/libfs.c | 18 ------------------
> > > > fs/nfs/dir.c | 1 -
> > > > fs/nfs/file.c | 1 -
> > > > fs/smb/client/cifsfs.c | 1 -
> > > > fs/vboxsf/dir.c | 1 -
> > > > fs/vboxsf/file.c | 1 -
> > > > include/linux/fs.h | 1 -
> > > > 13 files changed, 34 deletions(-)
> > > >
> > >
> > > <snip>
> > >
> > > > diff --git a/fs/libfs.c b/fs/libfs.c
> > > > index 697c6d5fc12786c036f0086886297fb5cd52ae00..f1860dff86f2703266beecf31e9d2667af7a9684 100644
> > > > --- a/fs/libfs.c
> > > > +++ b/fs/libfs.c
> > > > @@ -1699,24 +1699,6 @@ struct inode *alloc_anon_inode(struct super_block *s)
> > > > }
> > > > EXPORT_SYMBOL(alloc_anon_inode);
> > > >
> > > > -/**
> > > > - * simple_nosetlease - generic helper for prohibiting leases
> > > > - * @filp: file pointer
> > > > - * @arg: type of lease to obtain
> > > > - * @flp: new lease supplied for insertion
> > > > - * @priv: private data for lm_setup operation
> > > > - *
> > > > - * Generic helper for filesystems that do not wish to allow leases to be set.
> > > > - * All arguments are ignored and it just returns -EINVAL.
> > > > - */
> > > > -int
> > > > -simple_nosetlease(struct file *filp, int arg, struct file_lease **flp,
> > > > - void **priv)
> > > > -{
> > > > - return -EINVAL;
> > > > -}
> > > > -EXPORT_SYMBOL(simple_nosetlease);
> > > > -
> > > > /**
> > > > * simple_get_link - generic helper to get the target of "fast" symlinks
> > > > * @dentry: not used here
> > > > diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
> > > > index 71df279febf797880ded19e45528c3df4cea2dde..23a78a742b619dea8b76ddf28f4f59a1c8a015e2 100644
> > > > --- a/fs/nfs/dir.c
> > > > +++ b/fs/nfs/dir.c
> > > > @@ -66,7 +66,6 @@ const struct file_operations nfs_dir_operations = {
> > > > .open = nfs_opendir,
> > > > .release = nfs_closedir,
> > > > .fsync = nfs_fsync_dir,
> > > > - .setlease = simple_nosetlease,
> > > > };
> > > >
> > > > const struct address_space_operations nfs_dir_aops = {
> > > > diff --git a/fs/nfs/file.c b/fs/nfs/file.c
> > > > index d020aab40c64ebda30d130b6acee1b9194621457..9d269561961825f88529551b0f0287920960ac62 100644
> > > > --- a/fs/nfs/file.c
> > > > +++ b/fs/nfs/file.c
> > > > @@ -962,7 +962,6 @@ const struct file_operations nfs_file_operations = {
> > > > .splice_read = nfs_file_splice_read,
> > > > .splice_write = iter_file_splice_write,
> > > > .check_flags = nfs_check_flags,
> > > > - .setlease = simple_nosetlease,
> > > > .fop_flags = FOP_DONTCACHE,
> > > > };
> > > > EXPORT_SYMBOL_GPL(nfs_file_operations);
> > >
> > > Hey Jeff,
> > >
> > > I've noticed an NFS reexport regression in v6.19 and now v7.0-rc1
> > > (similar but different due to your series that requires opt-in via
> > > .setlease).
> > >
> > > Bisect first pointed out this commit:
> > > 10dcd5110678 nfs: properly disallow delegation requests on directories
> > >
> > > And now with v7.0-rc1 its the fact that NFS doesn't provide .setlease
> > > so lstat() on parent dir (of file that I touch) gets -EINVAL.
> > >
> > > So its a confluence of NFS's dir delegations and your setlease changes.
> > >
> > > If I reexport NFSv4.2 filesystem in terms of NFSv4.1, the regression
> > > is seen by doing (lstat reproducer that gemini spit out for me is
> > > attached):
> > >
> > > $ touch /mnt/share41/test
> > > $ strace ./lstat /mnt/share41
> > > ...
> > > lstat("/mnt/share41", 0x7ffec0d79920) = -1 EINVAL (Invalid argument)
> > >
> > > If I immediately re-run it works:
> > > ...
> > > lstat("/mnt/share41", {st_mode=S_IFDIR|0777, st_size=4096, ...}) = 0
> > >
> > > I'm not sure what the proper fix is yet, but I feel like you've missed
> > > that NFS itself can be (re)exported?
> > >
> > >
> >
> > My apologies. I missed seeing this last week.
> >
> > That's a very simple reproducer! That's very strange behavior,
> > especially since NFS4 does provide a setlease operation:
> >
> > const struct file_operations nfs4_file_operations = {
> > [...]
> > .setlease = nfs4_setlease,
> > [...]
> > };
>
> Huh, not sure how I missed nfs4_setlease...
>
> > I'm not sure why this would cause lstat() to return -EINVAL.
>
> Likewise, especially given nfs4_setlease
>
> > What's happening on the wire when this occurs?
> >
> > I'll plan to take a look here soon either way.
>
> I'll have to revisit myself, been a bit.
>
> Will let you know.
>
Thanks. I just tested your reproducer. I have a nfsv4.2 mount on one
host that is reexported, and mounted the reexport on a different host
with "-o vers=4.1".
It seems to work for me. It's possible I don't have something set up
the same way though:
$ touch /mnt/scratch/test ; ./lstat /mnt/scratch/test
Information for: /mnt/scratch/test
---------------------------
File Size: 0 bytes
Number of Links: 1
File inode: 272
File Type: Regular File
--
Jeff Layton <jlayton@kernel.org>
^ permalink raw reply
* Re: [PATCH v1] jbd2: check transaction state before stopping handle
From: yebin (H) @ 2026-03-06 1:20 UTC (permalink / raw)
To: liubaolin, tytso, jack; +Cc: linux-ext4, linux-kernel, wangguanyu, Baolin Liu
In-Reply-To: <e52f326a-8da2-457f-8aee-5729373b9582@163.com>
On 2026/3/5 21:11, liubaolin wrote:
>> Dear maintainers and community,
>>
>> Our customer reported a kernel crash issue. The kernel crashes in
>> stop_this_handle() with:
>> J_ASSERT(atomic_read(&transaction->t_updates) > 0);
>>
>> Crash stack:
>> Call trace:
>> stop_this_handle+0x148/0x158
>> jbd2_journal_stop+0x198/0x388
>> __ext4_journal_stop+0x70/0xf0
>> ext4_create+0x12c/0x188
>> ...
>>
>> From the vmcore dump, I found that handle->h_transaction->t_updates is
>> 0 and handle->h_transaction->t_state is T_FINISHED. This means the
>> handle is still bound to a transaction that has already completed.
>>
>> In the JBD2 commit process, once a transaction enters T_LOCKED state,
>> the commit thread waits for all associated handles to complete
>> (t_updates becomes 0). After T_LOCKED completes, the transaction
>> transitions to T_FLUSH, T_COMMIT, and eventually T_FINISHED. At this
>> point, t_updates is legitimately 0, and there should be no active
>> handles bound to this transaction.
>>
>> This appears to be a low-probability race condition that occurs under
>> high concurrency scenarios. The crash happened during ext4_create(),
I'm curious about what race condition causes this?
>> and at some rare timing point during the execution, a handle ended up
>> bound to a transaction that had already completed. The symptom is
>> clear: a handle is bound to a T_FINISHED transaction with t_updates == 0.
>>
>> To prevent this, I added a transaction state check in both
>> jbd2_journal_stop() and jbd2__journal_restart() before calling
>> stop_this_handle().
>> If the transaction is not in T_RUNNING or T_LOCKED state (i.e., it's
>> in T_FLUSH or later states), I clear handle->h_transaction, clear
>> current->journal_info if needed, restore the memalloc_nofs context,
>> and skip calling stop_this_handle(). This is a defensive check to
>> handle the edge case where a handle is bound to a transaction in an
>> invalid state.
>>
If this state occurs, there must be something wrong somewhere.
Assertions should also be added to detect such anomalies. I think
directly skipping the assertion check is not a good way to solve the
problem.
>> Please let me know if you have any questions or concerns.
>>
>> Best regards,
>> Baolin Liu
>
>
>
> 在 2026/3/5 20:57, Baolin Liu 写道:
>>
>> Add others
>>
>>
>>
>>
>>
>> At 2026-03-05 20:54:02, "Baolin Liu" <liubaolin12138@163.com> wrote:
>>> From: Baolin Liu <liubaolin@kylinos.cn>
>>>
>>> When a transaction enters T_FLUSH or later states,
>>> handle->h_transaction may still point to it.
>>> If jbd2_journal_stop() or jbd2__journal_restart() is called,
>>> stop_this_handle() checks t_updates > 0, but t_updates is
>>> already 0 for these states, causing a kernel BUG.
>>>
>>> Fix by checking transaction->t_state in jbd2_journal_stop()
>>> and jbd2__journal_restart() before calling stop_this_handle().
>>> If the transaction is not in T_RUNNING or T_LOCKED state,
>>> clear handle->h_transaction and skip stop_this_handle().
>>>
>>> Crash stack:
>>> Call trace:
>>> stop_this_handle+0x148/0x158
>>> jbd2_journal_stop+0x198/0x388
>>> __ext4_journal_stop+0x70/0xf0
>>> ext4_create+0x12c/0x188
>>> lookup_open+0x214/0x6d8
>>> do_last+0x364/0x878
>>> path_openat+0x6c/0x280
>>> do_filp_open+0x70/0xe8
>>> do_sys_open+0x178/0x200
>>> sys_openat+0x3c/0x50
>>> el0_svc_naked+0x44/0x48
>>>
>>> Signed-off-by: Baolin Liu <liubaolin@kylinos.cn>
>>> ---
>>> fs/jbd2/transaction.c | 25 +++++++++++++++++++++++--
>>> 1 file changed, 23 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
>>> index dca4b5d8aaaa..3779382dbb80 100644
>>> --- a/fs/jbd2/transaction.c
>>> +++ b/fs/jbd2/transaction.c
>>> @@ -772,14 +772,25 @@ int jbd2__journal_restart(handle_t *handle, int
>>> nblocks, int revoke_records,
>>> journal = transaction->t_journal;
>>> tid = transaction->t_tid;
>>>
>>> + jbd2_debug(2, "restarting handle %p\n", handle);
>>> +
>>> + /* Check if transaction is in invalid state */
>>> + if (transaction->t_state != T_RUNNING &&
>>> + transaction->t_state != T_LOCKED) {
>>> + if (current->journal_info == handle)
>>> + current->journal_info = NULL;
>>> + handle->h_transaction = NULL;
>>> + memalloc_nofs_restore(handle->saved_alloc_context);
>>> + goto skip_stop;
>>> + }
>>> +
>>> /*
>>> * First unlink the handle from its current transaction, and
>>> start the
>>> * commit on that.
>>> */
>>> - jbd2_debug(2, "restarting handle %p\n", handle);
>>> stop_this_handle(handle);
>>> handle->h_transaction = NULL;
>>> -
>>> +skip_stop:
>>> /*
>>> * TODO: If we use READ_ONCE / WRITE_ONCE for j_commit_request we
>>> can
>>> * get rid of pointless j_state_lock traffic like this.
>>> @@ -1856,6 +1867,16 @@ int jbd2_journal_stop(handle_t *handle)
>>> memalloc_nofs_restore(handle->saved_alloc_context);
>>> goto free_and_exit;
>>> }
>>> + /* Check if transaction is in invalid state */
>>> + if (transaction->t_state != T_RUNNING &&
>>> + transaction->t_state != T_LOCKED) {
>>> + if (current->journal_info == handle)
>>> + current->journal_info = NULL;
>>> + handle->h_transaction = NULL;
>>> + memalloc_nofs_restore(handle->saved_alloc_context);
>>> + goto free_and_exit;
>>> + }
>>> +
>>> journal = transaction->t_journal;
>>> tid = transaction->t_tid;
>>>
>>> --
>>> 2.39.2
>
>
>
> .
>
^ permalink raw reply
* [PATCH v5] ext4: avoid infinite loops caused by residual data
From: Edward Adam Davis @ 2026-03-06 1:31 UTC (permalink / raw)
To: jack
Cc: brauner, eadavis, linux-ext4, linux-fsdevel, linux-kernel,
syzbot+1659aaaaa8d9d11265d7, syzkaller-bugs, viro
In-Reply-To: <agn2b2tn4h3whokr262gca5s6eoautng2u2vt6535w7myuyk6x@6kgv6h7pco5g>
On the mkdir/mknod path, when mapping logical blocks to physical blocks,
if inserting a new extent into the extent tree fails (in this example,
because the file system disabled the huge file feature when marking the
inode as dirty), ext4_ext_map_blocks() only calls ext4_free_blocks() to
reclaim the physical block without deleting the corresponding data in
the extent tree. This causes subsequent mkdir operations to reference
the previously reclaimed physical block number again, even though this
physical block is already being used by the xattr block. Therefore, a
situation arises where both the directory and xattr are using the same
buffer head block in memory simultaneously.
The above causes ext4_xattr_block_set() to enter an infinite loop about
"inserted" and cannot release the inode lock, ultimately leading to the
143s blocking problem mentioned in [1].
If the metadata is corrupted, then trying to remove some extent space
can do even more harm. Also in case EXT4_GET_BLOCKS_DELALLOC_RESERVE
was passed, remove space wrongly update quota information.
Jan Kara suggests distinguishing between two cases:
1) The error is ENOSPC or EDQUOT - in this case the filesystem is fully
consistent and we must maintain its consistency including all the
accounting. However these errors can happen only early before we've
inserted the extent into the extent tree. So current code works correctly
for this case.
2) Some other error - this means metadata is corrupted. We should strive to
do as few modifications as possible to limit damage. So I'd just skip
freeing of allocated blocks.
[1]
INFO: task syz.0.17:5995 blocked for more than 143 seconds.
Call Trace:
inode_lock_nested include/linux/fs.h:1073 [inline]
__start_dirop fs/namei.c:2923 [inline]
start_dirop fs/namei.c:2934 [inline]
Reported-by: syzbot+512459401510e2a9a39f@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=1659aaaaa8d9d11265d7
Tested-by: syzbot+1659aaaaa8d9d11265d7@syzkaller.appspotmail.com
Reported-by: syzbot+1659aaaaa8d9d11265d7@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=512459401510e2a9a39f
Tested-by: syzbot+1659aaaaa8d9d11265d7@syzkaller.appspotmail.com
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
---
v1 -> v2: fix ci reported issues
v2 -> v3: new fix for removing residual data and update subject and coments
v3 -> v4: filtering already allocated blocks and update comments
v4 -> v5: don't touch corrupted data and update comments
fs/ext4/extents.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index ae3804f36535..4779da94f816 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4457,9 +4457,13 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
path = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
if (IS_ERR(path)) {
err = PTR_ERR(path);
- if (allocated_clusters) {
+ /*
+ * Gracefully handle out of space conditions. If the filesystem
+ * is inconsistent, we'll just leak allocated blocks to avoid
+ * causing even more damage.
+ */
+ if (allocated_clusters && (err == -EDQUOT || err == -ENOSPC)) {
int fb_flags = 0;
-
/*
* free data blocks we just allocated.
* not a good idea to call discard here directly,
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v3 02/12] audit: widen ino fields to u64
From: Paul Moore @ 2026-03-06 3:09 UTC (permalink / raw)
To: Jeff Layton
Cc: Alexander Viro, Christian Brauner, Jan Kara, Steven Rostedt,
Masami Hiramatsu, Mathieu Desnoyers, Dan Williams, Eric Biggers,
Theodore Y. Ts'o, Muchun Song, Oscar Salvador,
David Hildenbrand, David Howells, Paulo Alcantara, Andreas Dilger,
Jan Kara, Jaegeuk Kim, Chao Yu, Trond Myklebust, Anna Schumaker,
Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Steve French, Ronnie Sahlberg, Shyam Prasad N, Bharath SM,
Alexander Aring, Ryusuke Konishi, Viacheslav Dubeyko,
Eric Van Hensbergen, Latchesar Ionkov, Dominique Martinet,
Christian Schoenebeck, David Sterba, Marc Dionne, Ian Kent,
Luis de Bethencourt, Salah Triki, Tigran A. Aivazian,
Ilya Dryomov, Alex Markuze, Jan Harkes, coda, Nicolas Pitre,
Tyler Hicks, Amir Goldstein, Christoph Hellwig,
John Paul Adrian Glaubitz, Yangtao Li, Mikulas Patocka,
David Woodhouse, Richard Weinberger, Dave Kleikamp,
Konstantin Komarov, Mark Fasheh, Joel Becker, Joseph Qi,
Mike Marshall, Martin Brandenburg, Miklos Szeredi, Anders Larsen,
Zhihao Cheng, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
John Johansen, James Morris, Serge E. Hallyn, Mimi Zohar,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Fan Wu,
Stephen Smalley, Ondrej Mosnacek, Casey Schaufler, Alex Deucher,
Christian König, David Airlie, Simona Vetter, Sumit Semwal,
Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Jakub Kicinski, Simon Horman, Oleg Nesterov,
Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
Ian Rogers, Adrian Hunter, James Clark, Darrick J. Wong,
Martin Schiller, Eric Paris, Joerg Reuter, Marcel Holtmann,
Johan Hedberg, Luiz Augusto von Dentz, Oliver Hartkopp,
Marc Kleine-Budde, David Ahern, Neal Cardwell, Steffen Klassert,
Herbert Xu, Remi Denis-Courmont, Marcelo Ricardo Leitner,
Xin Long, Magnus Karlsson, Maciej Fijalkowski, Stanislav Fomichev,
Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
John Fastabend, linux-fsdevel, linux-kernel, linux-trace-kernel,
nvdimm, fsverity, linux-mm, netfs, linux-ext4, linux-f2fs-devel,
linux-nfs, linux-cifs, samba-technical, linux-nilfs, v9fs,
linux-afs, autofs, ceph-devel, codalist, ecryptfs, linux-mtd,
jfs-discussion, ntfs3, ocfs2-devel, devel, linux-unionfs,
apparmor, linux-security-module, linux-integrity, selinux,
amd-gfx, dri-devel, linux-media, linaro-mm-sig, netdev,
linux-perf-users, linux-fscrypt, linux-xfs, linux-hams, linux-x25,
audit, linux-bluetooth, linux-can, linux-sctp, bpf
In-Reply-To: <20260304-iino-u64-v3-2-2257ad83d372@kernel.org>
On Wed, Mar 4, 2026 at 10:33 AM Jeff Layton <jlayton@kernel.org> wrote:
>
> inode->i_ino is being widened from unsigned long to u64. The audit
> subsystem uses unsigned long ino in struct fields, function parameters,
> and local variables that store inode numbers from arbitrary filesystems.
> On 32-bit platforms this truncates inode numbers that exceed 32 bits,
> which will cause incorrect audit log entries and broken watch/mark
> comparisons.
>
> Widen all audit ino fields, parameters, and locals to u64, and update
> the inode format string from %lu to %llu to match.
>
> Signed-off-by: Jeff Layton <jlayton@kernel.org>
> ---
> include/linux/audit.h | 2 +-
> kernel/audit.h | 13 ++++++-------
> kernel/audit_fsnotify.c | 4 ++--
> kernel/audit_watch.c | 12 ++++++------
> kernel/auditsc.c | 4 ++--
> 5 files changed, 17 insertions(+), 18 deletions(-)
Acked-by: Paul Moore <paul@paul-moore.com>
--
paul-moore.com
^ permalink raw reply
* [BUG] kernel BUG in ext4_do_writepages
From: Xianying Wang @ 2026-03-06 5:42 UTC (permalink / raw)
To: tytso; +Cc: adilger.kernel, linux-ext4, linux-kernel
Hi,
I would like to report a kernel BUG triggered by a syzkaller
reproducer in the ext4 filesystem writeback path.
The issue was originally observed on Linux 6.19.0-rc8 and can also be
reproduced on Linux 7.0-rc2. The crash occurs in the ext4 writeback
routine while the background writeback worker is flushing dirty pages
to disk.
During the crash, the filesystem reports that no free blocks are
available while dirty pages and reserved blocks still exist. Under
this condition, the writeback worker continues processing pending
writeback operations and eventually reaches an internal consistency
check inside the ext4 writeback routine, which triggers a kernel BUG.
Based on the execution context, the issue appears to be related to the
interaction between delayed allocation and the writeback mechanism
when the filesystem runs out of available blocks. When the writeback
thread attempts to flush dirty pages in this state, ext4 enters an
unexpected internal state that causes the BUG to be triggered.
This can be reproduced on:
HEAD commit:
11439c4635edd669ae435eec308f4ab8a0804808
report: https://pastebin.com/raw/dNFvCatE
console output : https://pastebin.com/raw/LAPYKL5P
kernel config : https://pastebin.com/7hk2cU0G
C reproducer :https://pastebin.com/raw/v07yFCWP
Let me know if you need more details or testing.
Best regards,
Xianying
^ permalink raw reply
* Re: [PATCH v3 4/4] jbd2: store jinode dirty range in PAGE_SIZE units
From: Li Chen @ 2026-03-06 5:44 UTC (permalink / raw)
To: Jan Kara
Cc: Theodore Ts'o, Mark Fasheh, linux-ext4, ocfs2-devel, Jan Kara,
linux-kernel
In-Reply-To: <jekg3rqfscaashwrnzisjjwpcyep2d4w6niyiahcastic4gmcz@3lgz3oqsfavk>
Hi Jan,
---- On Tue, 03 Mar 2026 17:01:28 +0800 Jan Kara <jack@suse.cz> wrote ---
> On Mon 02-03-26 19:27:13, Jan Kara wrote:
> > On Tue 24-02-26 17:24:33, Li Chen wrote:
> > > jbd2_inode fields are updated under journal->j_list_lock, but some paths
> > > read them without holding the lock (e.g. fast commit helpers and ordered
> > > truncate helpers).
> > >
> > > READ_ONCE() alone is not sufficient for the dirty range fields when they
> > > are stored as loff_t because 32-bit platforms can observe torn loads.
> > > Store the dirty range in PAGE_SIZE units as pgoff_t instead.
> > >
> > > Use READ_ONCE() on the read side and WRITE_ONCE() on the write side for the
> > > dirty range and i_flags to match the existing lockless access pattern.
> > >
> > > Suggested-by: Jan Kara <jack@suse.cz>
> > > Reviewed-by: Jan Kara <jack@suse.cz>
> > > Signed-off-by: Li Chen <me@linux.beauty>
> > ...
> > > @@ -2654,15 +2655,20 @@ static int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *jinode,
> > > jbd2_debug(4, "Adding inode %lu, tid:%d\n", jinode->i_vfs_inode->i_ino,
> > > transaction->t_tid);
> > >
> > > + start_page = (pgoff_t)(start_byte >> PAGE_SHIFT);
> > > + end_page = (pgoff_t)(end_byte >> PAGE_SHIFT);
> >
> > MAX_LFS_SIZE on 32-bit is ULONG_MAX << PAGE_SHIFT and that's maximum file
> > size. So we could do here end_page = DIV_ROUND_UP(end_byte, PAGE_SIZE) and
> > just use end_page as exclusive end of a range to flush and get rid of
> > special JBD2_INODE_DIRTY_RANGE_NONE value.
> >
> > The problem with the scheme you use is that files of MAX_LFS_SIZE would be
> > treated as having empty flush range...
>
> Or perhaps even easier might be to set start_page to ULONG_MAX and end_page
> to 0 and use start_page > end_page as an indication of empty range.
Great idea! Thanks for the detailed review.
I will update the range handling to avoid the sentinel collision.
Regards,
Li
^ permalink raw reply
* [PATCH v4 0/4] jbd2/ext4/ocfs2: lockless jinode dirty range
From: Li Chen @ 2026-03-06 8:56 UTC (permalink / raw)
To: Theodore Ts'o, Jan Kara, Mark Fasheh, linux-ext4, ocfs2-devel
Cc: Andreas Dilger, Joel Becker, Joseph Qi, linux-kernel
This series makes the jbd2_inode dirty range tracking safe for lockless
reads in jbd2 and filesystem callbacks used by ext4 and ocfs2.
Some paths access jinode fields without holding journal->j_list_lock
(e.g. fast commit helpers and ordered truncate helpers). v1 used READ_ONCE()
on i_dirty_start/end, but Matthew pointed out that loff_t can be torn on
32-bit platforms, and Jan suggested storing the dirty range in PAGE_SIZE
units as pgoff_t.
With this series, jbd2 stores the dirty range as page indexes and uses
READ_ONCE()/WRITE_ONCE() for lockless access. ext4 and ocfs2 use the new
jbd2_jinode_get_dirty_range() accessor which converts the page-based range
back to byte offsets for writeback.
This is based on Jan's suggestion in the review of the ext4 jinode
publication race fix. [1]
Changes since v3:
- Store i_dirty_end_page as an exclusive end page and drop the sentinel.
- Publish end_page before start_page and treat start_page >= end_page as
empty.
Changes since v2:
- Add jbd2_jinode_get_dirty_range() accessor and convert ext4/ocfs2 to use it
before switching the underlying representation (per Andreas).
- Rename the dirty range fields to i_dirty_start_page/end_page to make the
PAGE_SIZE units explicit and avoid silent unit mismatches when bisecting.
Changes since v1:
- Store i_dirty_start/end in PAGE_SIZE units (pgoff_t) to avoid torn loads on
32-bit (pointed out by Matthew, suggested by Jan).
- Use WRITE_ONCE() for i_dirty_* / i_flags updates in jbd2 (per Jan).
- Drop pointless READ_ONCE() on i_vfs_inode in jbd2_wait_inode_data (per Jan).
- Convert ext4/ocfs2 callbacks to translate page range to byte offsets.
[1]: https://lore.kernel.org/all/4jxwogttddiaoqbstlgou5ox6zs27ngjjz5ukrxafm2z5ijxod@so4eqnykiegj/
v3: https://lore.kernel.org/all/20260224092434.202122-1-me@linux.beauty/
v2: https://lore.kernel.org/all/20260219114645.778338-1-me@linux.beauty/
v1: https://lore.kernel.org/all/20260130031232.60780-1-me@linux.beauty/
Li Chen (4):
jbd2: add jinode dirty range accessors
ext4: use jbd2 jinode dirty range accessor
ocfs2: use jbd2 jinode dirty range accessor
jbd2: store jinode dirty range in PAGE_SIZE units
fs/ext4/inode.c | 10 ++++++--
fs/ext4/super.c | 16 +++++++++----
fs/jbd2/commit.c | 55 +++++++++++++++++++++++++++++++++----------
fs/jbd2/journal.c | 5 ++--
fs/jbd2/transaction.c | 21 +++++++++++------
fs/ocfs2/journal.c | 9 +++++--
include/linux/jbd2.h | 38 ++++++++++++++++++++++++------
7 files changed, 115 insertions(+), 39 deletions(-)
--
2.53.0
^ permalink raw reply
* [PATCH v4 1/4] jbd2: add jinode dirty range accessors
From: Li Chen @ 2026-03-06 8:56 UTC (permalink / raw)
To: Theodore Ts'o, Jan Kara, Mark Fasheh, linux-ext4, ocfs2-devel,
Jan Kara, linux-kernel
Cc: Andreas Dilger, Li Chen
In-Reply-To: <20260306085643.465275-1-me@linux.beauty>
Provide a helper to fetch jinode dirty ranges in bytes. This lets
filesystem callbacks avoid depending on the internal representation,
preparing for a later conversion to page units.
Suggested-by: Andreas Dilger <adilger@dilger.ca>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Li Chen <me@linux.beauty>
---
Changes since v3:
- Add Reviewed-by: Jan Kara.
Changes since v2:
- New patch: add jbd2_jinode_get_dirty_range() helper.
include/linux/jbd2.h | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index a53a00d36228c..64392baf5f4b4 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -445,6 +445,20 @@ struct jbd2_inode {
loff_t i_dirty_end;
};
+static inline bool jbd2_jinode_get_dirty_range(const struct jbd2_inode *jinode,
+ loff_t *start, loff_t *end)
+{
+ loff_t start_byte = jinode->i_dirty_start;
+ loff_t end_byte = jinode->i_dirty_end;
+
+ if (!end_byte)
+ return false;
+
+ *start = start_byte;
+ *end = end_byte;
+ return true;
+}
+
struct jbd2_revoke_table_s;
/**
--
2.53.0
^ permalink raw reply related
* [PATCH v4 2/4] ext4: use jbd2 jinode dirty range accessor
From: Li Chen @ 2026-03-06 8:56 UTC (permalink / raw)
To: Theodore Ts'o, Jan Kara, Mark Fasheh, linux-ext4, ocfs2-devel,
Andreas Dilger, linux-kernel
Cc: Li Chen
In-Reply-To: <20260306085643.465275-1-me@linux.beauty>
ext4 journal commit callbacks access jbd2_inode dirty range fields without
holding journal->j_list_lock.
Use jbd2_jinode_get_dirty_range() to get the range in bytes, and read
i_transaction with READ_ONCE() in the redirty check.
Suggested-by: Jan Kara <jack@suse.cz>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Li Chen <me@linux.beauty>
---
Changes since v3:
- No changes.
Changes since v2:
- Use jbd2_jinode_get_dirty_range() instead of direct i_dirty_* reads.
- Drop per-caller page->byte conversion (now handled by the accessor).
Changes since v1:
- Convert the jinode dirty range from PAGE_SIZE units (pgoff_t) back to byte
offsets before passing it to writeback.
fs/ext4/inode.c | 10 ++++++++--
fs/ext4/super.c | 16 +++++++++++-----
2 files changed, 19 insertions(+), 7 deletions(-)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index da96db5f23450..f87d35bda9276 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3031,17 +3031,23 @@ static int ext4_writepages(struct address_space *mapping,
int ext4_normal_submit_inode_data_buffers(struct jbd2_inode *jinode)
{
+ loff_t range_start, range_end;
struct writeback_control wbc = {
.sync_mode = WB_SYNC_ALL,
.nr_to_write = LONG_MAX,
- .range_start = jinode->i_dirty_start,
- .range_end = jinode->i_dirty_end,
};
struct mpage_da_data mpd = {
.inode = jinode->i_vfs_inode,
.wbc = &wbc,
.can_map = 0,
};
+
+ if (!jbd2_jinode_get_dirty_range(jinode, &range_start, &range_end))
+ return 0;
+
+ wbc.range_start = range_start;
+ wbc.range_end = range_end;
+
return ext4_do_writepages(&mpd);
}
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 69eb63dde9839..685951cd58394 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -521,6 +521,7 @@ static bool ext4_journalled_writepage_needs_redirty(struct jbd2_inode *jinode,
{
struct buffer_head *bh, *head;
struct journal_head *jh;
+ transaction_t *trans = READ_ONCE(jinode->i_transaction);
bh = head = folio_buffers(folio);
do {
@@ -539,7 +540,7 @@ static bool ext4_journalled_writepage_needs_redirty(struct jbd2_inode *jinode,
*/
jh = bh2jh(bh);
if (buffer_dirty(bh) ||
- (jh && (jh->b_transaction != jinode->i_transaction ||
+ (jh && (jh->b_transaction != trans ||
jh->b_next_transaction)))
return true;
} while ((bh = bh->b_this_page) != head);
@@ -550,15 +551,20 @@ static bool ext4_journalled_writepage_needs_redirty(struct jbd2_inode *jinode,
static int ext4_journalled_submit_inode_data_buffers(struct jbd2_inode *jinode)
{
struct address_space *mapping = jinode->i_vfs_inode->i_mapping;
+ loff_t range_start, range_end;
struct writeback_control wbc = {
- .sync_mode = WB_SYNC_ALL,
+ .sync_mode = WB_SYNC_ALL,
.nr_to_write = LONG_MAX,
- .range_start = jinode->i_dirty_start,
- .range_end = jinode->i_dirty_end,
- };
+ };
struct folio *folio = NULL;
int error;
+ if (!jbd2_jinode_get_dirty_range(jinode, &range_start, &range_end))
+ return 0;
+
+ wbc.range_start = range_start;
+ wbc.range_end = range_end;
+
/*
* writeback_iter() already checks for dirty pages and calls
* folio_clear_dirty_for_io(), which we want to write protect the
--
2.53.0
^ permalink raw reply related
* [PATCH v4 3/4] ocfs2: use jbd2 jinode dirty range accessor
From: Li Chen @ 2026-03-06 8:56 UTC (permalink / raw)
To: Theodore Ts'o, Jan Kara, Mark Fasheh, linux-ext4, ocfs2-devel,
Joel Becker, Joseph Qi, linux-kernel
Cc: Li Chen
In-Reply-To: <20260306085643.465275-1-me@linux.beauty>
ocfs2 journal commit callback reads jbd2_inode dirty range fields without
holding journal->j_list_lock.
Use jbd2_jinode_get_dirty_range() to get the range in bytes.
Suggested-by: Jan Kara <jack@suse.cz>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Li Chen <me@linux.beauty>
---
Changes since v3:
- Add Reviewed-by: Jan Kara.
Changes since v2:
- Use jbd2_jinode_get_dirty_range() instead of direct i_dirty_* reads.
- Drop per-caller page->byte conversion (now handled by the accessor).
fs/ocfs2/journal.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index 85239807dec78..68c2f567e6e1b 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -902,8 +902,13 @@ int ocfs2_journal_alloc(struct ocfs2_super *osb)
static int ocfs2_journal_submit_inode_data_buffers(struct jbd2_inode *jinode)
{
- return filemap_fdatawrite_range(jinode->i_vfs_inode->i_mapping,
- jinode->i_dirty_start, jinode->i_dirty_end);
+ struct address_space *mapping = jinode->i_vfs_inode->i_mapping;
+ loff_t range_start, range_end;
+
+ if (!jbd2_jinode_get_dirty_range(jinode, &range_start, &range_end))
+ return 0;
+
+ return filemap_fdatawrite_range(mapping, range_start, range_end);
}
int ocfs2_journal_init(struct ocfs2_super *osb, int *dirty)
--
2.53.0
^ permalink raw reply related
* [PATCH v4 4/4] jbd2: store jinode dirty range in PAGE_SIZE units
From: Li Chen @ 2026-03-06 8:56 UTC (permalink / raw)
To: Theodore Ts'o, Jan Kara, Mark Fasheh, linux-ext4, ocfs2-devel,
Jan Kara, linux-kernel
Cc: Li Chen
In-Reply-To: <20260306085643.465275-1-me@linux.beauty>
jbd2_inode fields are updated under journal->j_list_lock, but some paths
read them without holding the lock (e.g. fast commit helpers and ordered
truncate helpers).
READ_ONCE() alone is not sufficient for the dirty range fields when they
are stored as loff_t because 32-bit platforms can observe torn loads.
Store the dirty range in PAGE_SIZE units as pgoff_t instead.
Represent the dirty range end as an exclusive end page. This avoids a
special sentinel value and keeps MAX_LFS_FILESIZE on 32-bit representable.
Publish a new dirty range by updating end_page before start_page, and
treat start_page >= end_page as empty in the accessor for robustness.
Use READ_ONCE() on the read side and WRITE_ONCE() on the write side for the
dirty range and i_flags to match the existing lockless access pattern.
Suggested-by: Jan Kara <jack@suse.cz>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Li Chen <me@linux.beauty>
---
Changes since v3:
- Store i_dirty_end_page as an exclusive end page and drop the sentinel.
- Publish end_page before start_page and treat start_page >= end_page as
empty in the accessor.
- Document the empty-range encoding and publication ordering in comments.
Changes since v2:
- Rename i_dirty_start/end to i_dirty_start_page/end_page.
- Use jbd2_jinode_get_dirty_range() for byte conversions in commit paths.
fs/jbd2/commit.c | 55 +++++++++++++++++++++++++++++++++----------
fs/jbd2/journal.c | 5 ++--
fs/jbd2/transaction.c | 21 +++++++++++------
include/linux/jbd2.h | 34 ++++++++++++++++----------
4 files changed, 80 insertions(+), 35 deletions(-)
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 7203d2d2624d7..8cf61e7185c44 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -180,7 +180,13 @@ static int journal_wait_on_commit_record(journal_t *journal,
/* Send all the data buffers related to an inode */
int jbd2_submit_inode_data(journal_t *journal, struct jbd2_inode *jinode)
{
- if (!jinode || !(jinode->i_flags & JI_WRITE_DATA))
+ unsigned long flags;
+
+ if (!jinode)
+ return 0;
+
+ flags = READ_ONCE(jinode->i_flags);
+ if (!(flags & JI_WRITE_DATA))
return 0;
trace_jbd2_submit_inode_data(jinode->i_vfs_inode);
@@ -191,12 +197,30 @@ EXPORT_SYMBOL(jbd2_submit_inode_data);
int jbd2_wait_inode_data(journal_t *journal, struct jbd2_inode *jinode)
{
- if (!jinode || !(jinode->i_flags & JI_WAIT_DATA) ||
- !jinode->i_vfs_inode || !jinode->i_vfs_inode->i_mapping)
+ struct address_space *mapping;
+ struct inode *inode;
+ unsigned long flags;
+ loff_t start_byte, end_byte;
+
+ if (!jinode)
+ return 0;
+
+ flags = READ_ONCE(jinode->i_flags);
+ if (!(flags & JI_WAIT_DATA))
+ return 0;
+
+ inode = jinode->i_vfs_inode;
+ if (!inode)
+ return 0;
+
+ mapping = inode->i_mapping;
+ if (!mapping)
+ return 0;
+
+ if (!jbd2_jinode_get_dirty_range(jinode, &start_byte, &end_byte))
return 0;
return filemap_fdatawait_range_keep_errors(
- jinode->i_vfs_inode->i_mapping, jinode->i_dirty_start,
- jinode->i_dirty_end);
+ mapping, start_byte, end_byte);
}
EXPORT_SYMBOL(jbd2_wait_inode_data);
@@ -218,7 +242,8 @@ static int journal_submit_data_buffers(journal_t *journal,
list_for_each_entry(jinode, &commit_transaction->t_inode_list, i_list) {
if (!(jinode->i_flags & JI_WRITE_DATA))
continue;
- jinode->i_flags |= JI_COMMIT_RUNNING;
+ WRITE_ONCE(jinode->i_flags,
+ jinode->i_flags | JI_COMMIT_RUNNING);
spin_unlock(&journal->j_list_lock);
/* submit the inode data buffers. */
trace_jbd2_submit_inode_data(jinode->i_vfs_inode);
@@ -229,7 +254,8 @@ static int journal_submit_data_buffers(journal_t *journal,
}
spin_lock(&journal->j_list_lock);
J_ASSERT(jinode->i_transaction == commit_transaction);
- jinode->i_flags &= ~JI_COMMIT_RUNNING;
+ WRITE_ONCE(jinode->i_flags,
+ jinode->i_flags & ~JI_COMMIT_RUNNING);
smp_mb();
wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING);
}
@@ -240,10 +266,13 @@ static int journal_submit_data_buffers(journal_t *journal,
int jbd2_journal_finish_inode_data_buffers(struct jbd2_inode *jinode)
{
struct address_space *mapping = jinode->i_vfs_inode->i_mapping;
+ loff_t start_byte, end_byte;
+
+ if (!jbd2_jinode_get_dirty_range(jinode, &start_byte, &end_byte))
+ return 0;
return filemap_fdatawait_range_keep_errors(mapping,
- jinode->i_dirty_start,
- jinode->i_dirty_end);
+ start_byte, end_byte);
}
/*
@@ -262,7 +291,7 @@ static int journal_finish_inode_data_buffers(journal_t *journal,
list_for_each_entry(jinode, &commit_transaction->t_inode_list, i_list) {
if (!(jinode->i_flags & JI_WAIT_DATA))
continue;
- jinode->i_flags |= JI_COMMIT_RUNNING;
+ WRITE_ONCE(jinode->i_flags, jinode->i_flags | JI_COMMIT_RUNNING);
spin_unlock(&journal->j_list_lock);
/* wait for the inode data buffers writeout. */
if (journal->j_finish_inode_data_buffers) {
@@ -272,7 +301,7 @@ static int journal_finish_inode_data_buffers(journal_t *journal,
}
cond_resched();
spin_lock(&journal->j_list_lock);
- jinode->i_flags &= ~JI_COMMIT_RUNNING;
+ WRITE_ONCE(jinode->i_flags, jinode->i_flags & ~JI_COMMIT_RUNNING);
smp_mb();
wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING);
}
@@ -288,8 +317,8 @@ static int journal_finish_inode_data_buffers(journal_t *journal,
&jinode->i_transaction->t_inode_list);
} else {
jinode->i_transaction = NULL;
- jinode->i_dirty_start = 0;
- jinode->i_dirty_end = 0;
+ WRITE_ONCE(jinode->i_dirty_start_page, 0);
+ WRITE_ONCE(jinode->i_dirty_end_page, 0);
}
}
spin_unlock(&journal->j_list_lock);
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index c973162d5b316..0bf09aa900277 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -3020,8 +3020,8 @@ void jbd2_journal_init_jbd_inode(struct jbd2_inode *jinode, struct inode *inode)
jinode->i_next_transaction = NULL;
jinode->i_vfs_inode = inode;
jinode->i_flags = 0;
- jinode->i_dirty_start = 0;
- jinode->i_dirty_end = 0;
+ jinode->i_dirty_start_page = 0;
+ jinode->i_dirty_end_page = 0;
INIT_LIST_HEAD(&jinode->i_list);
}
@@ -3178,4 +3178,3 @@ MODULE_DESCRIPTION("Generic filesystem journal-writing module");
MODULE_LICENSE("GPL");
module_init(journal_init);
module_exit(journal_exit);
-
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index dca4b5d8aaaa3..17709ecdd22c0 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -2646,6 +2646,7 @@ static int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *jinode,
{
transaction_t *transaction = handle->h_transaction;
journal_t *journal;
+ pgoff_t start_page, end_page;
if (is_handle_aborted(handle))
return -EROFS;
@@ -2654,15 +2655,21 @@ static int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *jinode,
jbd2_debug(4, "Adding inode %lu, tid:%d\n", jinode->i_vfs_inode->i_ino,
transaction->t_tid);
+ start_page = (pgoff_t)(start_byte >> PAGE_SHIFT);
+ end_page = (pgoff_t)(end_byte >> PAGE_SHIFT) + 1;
+
spin_lock(&journal->j_list_lock);
- jinode->i_flags |= flags;
+ WRITE_ONCE(jinode->i_flags, jinode->i_flags | flags);
- if (jinode->i_dirty_end) {
- jinode->i_dirty_start = min(jinode->i_dirty_start, start_byte);
- jinode->i_dirty_end = max(jinode->i_dirty_end, end_byte);
+ if (jinode->i_dirty_start_page != jinode->i_dirty_end_page) {
+ WRITE_ONCE(jinode->i_dirty_start_page,
+ min(jinode->i_dirty_start_page, start_page));
+ WRITE_ONCE(jinode->i_dirty_end_page,
+ max(jinode->i_dirty_end_page, end_page));
} else {
- jinode->i_dirty_start = start_byte;
- jinode->i_dirty_end = end_byte;
+ /* Publish a new non-empty range by making end visible first. */
+ WRITE_ONCE(jinode->i_dirty_end_page, end_page);
+ WRITE_ONCE(jinode->i_dirty_start_page, start_page);
}
/* Is inode already attached where we need it? */
@@ -2739,7 +2746,7 @@ int jbd2_journal_begin_ordered_truncate(journal_t *journal,
int ret = 0;
/* This is a quick check to avoid locking if not necessary */
- if (!jinode->i_transaction)
+ if (!READ_ONCE(jinode->i_transaction))
goto out;
/* Locks are here just to force reading of recent values, it is
* enough that the transaction was not committing before we started
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index 64392baf5f4b4..7e785aa6d35d6 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -429,33 +429,43 @@ struct jbd2_inode {
unsigned long i_flags;
/**
- * @i_dirty_start:
+ * @i_dirty_start_page:
+ *
+ * Dirty range start in PAGE_SIZE units.
+ *
+ * The dirty range is empty if @i_dirty_start_page is greater than or
+ * equal to @i_dirty_end_page.
*
- * Offset in bytes where the dirty range for this inode starts.
* [j_list_lock]
*/
- loff_t i_dirty_start;
+ pgoff_t i_dirty_start_page;
/**
- * @i_dirty_end:
+ * @i_dirty_end_page:
+ *
+ * Dirty range end in PAGE_SIZE units (exclusive).
*
- * Inclusive offset in bytes where the dirty range for this inode
- * ends. [j_list_lock]
+ * [j_list_lock]
*/
- loff_t i_dirty_end;
+ pgoff_t i_dirty_end_page;
};
+/*
+ * Lockless readers treat start_page >= end_page as an empty range.
+ * Writers publish a new non-empty range by storing i_dirty_end_page before
+ * i_dirty_start_page.
+ */
static inline bool jbd2_jinode_get_dirty_range(const struct jbd2_inode *jinode,
loff_t *start, loff_t *end)
{
- loff_t start_byte = jinode->i_dirty_start;
- loff_t end_byte = jinode->i_dirty_end;
+ pgoff_t start_page = READ_ONCE(jinode->i_dirty_start_page);
+ pgoff_t end_page = READ_ONCE(jinode->i_dirty_end_page);
- if (!end_byte)
+ if (start_page >= end_page)
return false;
- *start = start_byte;
- *end = end_byte;
+ *start = (loff_t)start_page << PAGE_SHIFT;
+ *end = ((loff_t)end_page << PAGE_SHIFT) - 1;
return true;
}
--
2.53.0
^ permalink raw reply related
* Re: [PATCH v3 00/12] vfs: change inode->i_ino from unsigned long to u64
From: Christian Brauner @ 2026-03-06 9:09 UTC (permalink / raw)
To: Jeff Layton
Cc: Christian Brauner, linux-fsdevel, linux-kernel,
linux-trace-kernel, nvdimm, fsverity, linux-mm, netfs, linux-ext4,
linux-f2fs-devel, linux-nfs, linux-cifs, samba-technical,
linux-nilfs, v9fs, linux-afs, autofs, ceph-devel, codalist,
ecryptfs, linux-mtd, jfs-discussion, ntfs3, ocfs2-devel, devel,
linux-unionfs, apparmor, linux-security-module, linux-integrity,
selinux, amd-gfx, dri-devel, linux-media, linaro-mm-sig, netdev,
linux-perf-users, linux-fscrypt, linux-xfs, linux-hams, linux-x25,
audit, linux-bluetooth, linux-can, linux-sctp, bpf,
Alexander Viro, Jan Kara, Steven Rostedt, Masami Hiramatsu,
Mathieu Desnoyers, Dan Williams, Eric Biggers,
Theodore Y. Ts'o, Muchun Song, Oscar Salvador,
David Hildenbrand, David Howells, Paulo Alcantara, Andreas Dilger,
Jan Kara, Jaegeuk Kim, Chao Yu, Trond Myklebust, Anna Schumaker,
Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Steve French, Ronnie Sahlberg, Shyam Prasad N, Bharath SM,
Alexander Aring, Ryusuke Konishi, Viacheslav Dubeyko,
Eric Van Hensbergen, Latchesar Ionkov, Dominique Martinet,
Christian Schoenebeck, David Sterba, Marc Dionne, Ian Kent,
Luis de Bethencourt, Salah Triki, Tigran A. Aivazian,
Ilya Dryomov, Alex Markuze, Jan Harkes, coda, Nicolas Pitre,
Tyler Hicks, Amir Goldstein, Christoph Hellwig,
John Paul Adrian Glaubitz, Yangtao Li, Mikulas Patocka,
David Woodhouse, Richard Weinberger, Dave Kleikamp,
Konstantin Komarov, Mark Fasheh, Joel Becker, Joseph Qi,
Mike Marshall, Martin Brandenburg, Miklos Szeredi, Anders Larsen,
Zhihao Cheng, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
John Johansen, Paul Moore, James Morris, Serge E. Hallyn,
Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Fan Wu,
Stephen Smalley, Ondrej Mosnacek, Casey Schaufler, Alex Deucher,
Christian König, David Airlie, Simona Vetter, Sumit Semwal,
Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Jakub Kicinski, Simon Horman, Oleg Nesterov,
Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Mark Rutland, Alexander Shishkin, Jiri Olsa,
Ian Rogers, Adrian Hunter, James Clark, Darrick J. Wong,
Martin Schiller, Eric Paris, Joerg Reuter, Marcel Holtmann,
Johan Hedberg, Luiz Augusto von Dentz, Oliver Hartkopp,
Marc Kleine-Budde, David Ahern, Neal Cardwell, Steffen Klassert,
Herbert Xu, Remi Denis-Courmont, Marcelo Ricardo Leitner,
Xin Long, Magnus Karlsson, Maciej Fijalkowski, Stanislav Fomichev,
Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
John Fastabend
In-Reply-To: <20260304-iino-u64-v3-0-2257ad83d372@kernel.org>
On Wed, 04 Mar 2026 10:32:30 -0500, Jeff Layton wrote:
> Christian said [1] to "just do it" when I proposed this, so here we are!
>
> For historical reasons, the inode->i_ino field is an unsigned long,
> which means that it's 32 bits on 32 bit architectures. This has caused a
> number of filesystems to implement hacks to hash a 64-bit identifier
> into a 32-bit field, and deprives us of a universal identifier field for
> an inode.
>
> [...]
This series makes me happy. We've been talking about this conversion for
a while and I'm thankful that you did this work. Without the automation
available this probably wouldn't have happened as quickly as it did now.
Let's see what bits and pieces it missed.
---
Applied to the vfs-7.1.kino branch of the vfs/vfs.git tree.
Patches in the vfs-7.1.kino branch should appear in linux-next soon.
Please report any outstanding bugs that were missed during review in a
new review to the original patch series allowing us to drop it.
It's encouraged to provide Acked-bys and Reviewed-bys even though the
patch has now been applied. If possible patch trailers will be updated.
Note that commit hashes shown below are subject to change due to rebase,
trailer updates or similar. If in doubt, please check the listed branch.
tree: https://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs.git
branch: vfs-7.1.kino
[01/12] vfs: widen inode hash/lookup functions to u64
https://git.kernel.org/vfs/vfs/c/2412a9fa518a
[02/12] audit: widen ino fields to u64
https://git.kernel.org/vfs/vfs/c/a5e863be4d02
[03/12] net: change sock.sk_ino and sock_i_ino() to u64
https://git.kernel.org/vfs/vfs/c/c21144a0a33f
[04/12] vfs: widen trace event i_ino fields to u64
https://git.kernel.org/vfs/vfs/c/5e5c380870b2
[05/12] cachefiles: widen trace event i_ino fields to u64
https://git.kernel.org/vfs/vfs/c/25291f67aad7
[06/12] ext2: widen trace event i_ino fields to u64
https://git.kernel.org/vfs/vfs/c/797d04a355e3
[07/12] hugetlbfs: widen trace event i_ino fields to u64
https://git.kernel.org/vfs/vfs/c/3c976fb36a9a
[08/12] zonefs: widen trace event i_ino fields to u64
https://git.kernel.org/vfs/vfs/c/988f68c01b3a
[09/12] ext4: widen trace event i_ino fields to u64
https://git.kernel.org/vfs/vfs/c/1c1427c79bc2
[10/12] f2fs: widen trace event i_ino fields to u64
https://git.kernel.org/vfs/vfs/c/6e62bf74bd8a
[11/12] nilfs2: widen trace event i_ino fields to u64
https://git.kernel.org/vfs/vfs/c/6ce73711525a
[12/12] treewide: change inode->i_ino from unsigned long to u64
https://git.kernel.org/vfs/vfs/c/af82d143e869
^ permalink raw reply
* Re: [PATCH v1] jbd2: check transaction state before stopping handle
From: liubaolin @ 2026-03-06 9:19 UTC (permalink / raw)
To: Jan Kara; +Cc: tytso, jack, linux-ext4, linux-kernel, wangguanyu, Baolin Liu
In-Reply-To: <cqmzdae2mou7gjt2ljcymji6jqwmca6lu2kwkeeo3buzohvbo3@4eq2xhgm7cej>
Dear Honza,
Thank you for your feedback. Yes, the BUG is exactly at:
J_ASSERT(atomic_read(&transaction->t_updates) > 0)
> Dear Honza,
>
> Thank you for your feedback. Yes, the BUG is exactly at:
> J_ASSERT(atomic_read(&transaction->t_updates) > 0)
>
> I understand your concern that this shouldn't happen in normal operation. However, from the vmcore dump, we can confirm that:
> - handle->h_transaction->t_updates == 0
> - handle->h_transaction->t_state == T_FINISHED
> - The crash occurred in stop_this_handle() when it tried to assert t_updates > 0
>
> This is a real crash that happened in production. The crash stack shows it occurred during ext4_create(), and the process name was MemTableFlushTh.
>
> I understand you want us to find and fix the root cause. I've reviewed the code but haven't found an obvious bug from the code that would cause this issue.
> However, I suspect the issue might be related to credit exhaustion during ext4_create() that triggers a handle restart,
> but this is just speculation and I'm still studying the code to confirm.
>
> This crash only occurred once in production and we haven't been able to reproduce it. The crash happened under high concurrency, and appears to be timing-dependent.
> I will continue to investigate the code and try to find a way to reproduce this issue to identify the root cause.
>
> The patch I proposed is a defensive check to prevent the kernel BUG when this edge case occurs.
>
> If you have any thoughts on where to look for the root cause, I'd really appreciate any suggestions.
>
> Best regards,
> Baolin Liu
> Dear Honza,
>
> Thank you for your feedback. Yes, the BUG is exactly at:
> J_ASSERT(atomic_read(&transaction->t_updates) > 0)
>
> I understand your concern that this shouldn't happen in normal operation. However, from the vmcore dump, we can confirm that:
> - handle->h_transaction->t_updates == 0
> - handle->h_transaction->t_state == T_FINISHED
> - The crash occurred in stop_this_handle() when it tried to assert t_updates > 0
>
> This is a real crash that happened in production. The crash stack shows it occurred during ext4_create(), and the process name was MemTableFlushTh.
>
> I understand you want us to find and fix the root cause. I've reviewed the code but haven't found an obvious bug from the code that would cause this issue.
> However, I suspect the issue might be related to credit exhaustion during ext4_create() that triggers a handle restart,
> but this is just speculation and I'm still studying the code to confirm.
>
> This crash only occurred once in production and we haven't been able to reproduce it. The crash happened under high concurrency, and appears to be timing-dependent.
> I will continue to investigate the code and try to find a way to reproduce this issue to identify the root cause.
>
> The patch I proposed is a defensive check to prevent the kernel BUG when this edge case occurs.
>
> If you have any thoughts on where to look for the root cause, I'd really appreciate any suggestions.
>
> Best regards,
> Baolin Liu
在 2026/3/5 21:08, Jan Kara 写道:
> On Thu 05-03-26 20:57:18, Baolin Liu wrote:
>> At 2026-03-05 20:54:02, "Baolin Liu" <liubaolin12138@163.com> wrote:
>>> From: Baolin Liu <liubaolin@kylinos.cn>
>>>
>>> When a transaction enters T_FLUSH or later states,
>>> handle->h_transaction may still point to it.
>>> If jbd2_journal_stop() or jbd2__journal_restart() is called,
>>> stop_this_handle() checks t_updates > 0, but t_updates is
>>> already 0 for these states, causing a kernel BUG.
>
> Which bug please? Do you mean
>
> J_ASSERT(atomic_read(&transaction->t_updates) > 0)
>
> ? Anyway this just doesn't make sense. When stop_this_handle() the caller
> is holding t_updates reference which stop_this_handle() is supposed to drop
> and the transaction should never transition past T_LOCKED state. If you
> have a handle that's pointing to a transaction past T_LOCKED state, there's
> a bug somewhere and that bug needs to be fixed, not paper over it like you
> do in this patch. More details about reproducer etc. would be useful.
>
> Honza
>
>>>
>>> Fix by checking transaction->t_state in jbd2_journal_stop()
>>> and jbd2__journal_restart() before calling stop_this_handle().
>>> If the transaction is not in T_RUNNING or T_LOCKED state,
>>> clear handle->h_transaction and skip stop_this_handle().
>>>
>>> Crash stack:
>>> Call trace:
>>> stop_this_handle+0x148/0x158
>>> jbd2_journal_stop+0x198/0x388
>>> __ext4_journal_stop+0x70/0xf0
>>> ext4_create+0x12c/0x188
>>> lookup_open+0x214/0x6d8
>>> do_last+0x364/0x878
>>> path_openat+0x6c/0x280
>>> do_filp_open+0x70/0xe8
>>> do_sys_open+0x178/0x200
>>> sys_openat+0x3c/0x50
>>> el0_svc_naked+0x44/0x48
>>>
>>> Signed-off-by: Baolin Liu <liubaolin@kylinos.cn>
>>> ---
>>> fs/jbd2/transaction.c | 25 +++++++++++++++++++++++--
>>> 1 file changed, 23 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
>>> index dca4b5d8aaaa..3779382dbb80 100644
>>> --- a/fs/jbd2/transaction.c
>>> +++ b/fs/jbd2/transaction.c
>>> @@ -772,14 +772,25 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, int revoke_records,
>>> journal = transaction->t_journal;
>>> tid = transaction->t_tid;
>>>
>>> + jbd2_debug(2, "restarting handle %p\n", handle);
>>> +
>>> + /* Check if transaction is in invalid state */
>>> + if (transaction->t_state != T_RUNNING &&
>>> + transaction->t_state != T_LOCKED) {
>>> + if (current->journal_info == handle)
>>> + current->journal_info = NULL;
>>> + handle->h_transaction = NULL;
>>> + memalloc_nofs_restore(handle->saved_alloc_context);
>>> + goto skip_stop;
>>> + }
>>> +
>>> /*
>>> * First unlink the handle from its current transaction, and start the
>>> * commit on that.
>>> */
>>> - jbd2_debug(2, "restarting handle %p\n", handle);
>>> stop_this_handle(handle);
>>> handle->h_transaction = NULL;
>>> -
>>> +skip_stop:
>>> /*
>>> * TODO: If we use READ_ONCE / WRITE_ONCE for j_commit_request we can
>>> * get rid of pointless j_state_lock traffic like this.
>>> @@ -1856,6 +1867,16 @@ int jbd2_journal_stop(handle_t *handle)
>>> memalloc_nofs_restore(handle->saved_alloc_context);
>>> goto free_and_exit;
>>> }
>>> + /* Check if transaction is in invalid state */
>>> + if (transaction->t_state != T_RUNNING &&
>>> + transaction->t_state != T_LOCKED) {
>>> + if (current->journal_info == handle)
>>> + current->journal_info = NULL;
>>> + handle->h_transaction = NULL;
>>> + memalloc_nofs_restore(handle->saved_alloc_context);
>>> + goto free_and_exit;
>>> + }
>>> +
>>> journal = transaction->t_journal;
>>> tid = transaction->t_tid;
>>>
>>> --
>>> 2.39.2
^ permalink raw reply
* Re: [PATCH v3] ext4: fix mballoc-test.c is not compiled when EXT4_KUNIT_TESTS=M
From: Ojaswin Mujoo @ 2026-03-06 9:55 UTC (permalink / raw)
To: Ye Bin; +Cc: tytso, adilger.kernel, linux-ext4, jack
In-Reply-To: <20260227065514.2365063-1-yebin@huaweicloud.com>
On Fri, Feb 27, 2026 at 02:55:14PM +0800, Ye Bin wrote:
> From: Ye Bin <yebin10@huawei.com>
>
> Now, only EXT4_KUNIT_TESTS=Y testcase will be compiled in 'mballoc.c'.
> To solve this issue, the ext4 test code needs to be decoupled. The ext4
> test module is compiled into a separate module.
>
> Reported-by: ChenXiaoSong <chenxiaosong@kylinos.cn>
> Closes: https://patchwork.kernel.org/project/cifs-client/patch/20260118091313.1988168-2-chenxiaosong.chenxiaosong@linux.dev/
> Fixes: 7c9fa399a369 ("ext4: add first unit test for ext4_mb_new_blocks_simple in mballoc")
> Signed-off-by: Ye Bin <yebin10@huawei.com>
Hi Ye,
From my testing I can see that EXPORT_SYMBOL_FOR_MODULE() doesn't
resepect the namespace restriction if EXT4_KUNIT_TESTS=y but I think
that should be okay.
The patch otherwise looks good. Feel free to add:
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
One thing, recently added extents-test.c is also having the same issue where
it doesn't work when compiled as module. Would you be willing to fix it
as well?
Regards,
ojaswin
^ permalink raw reply
* Re: [PATCH v1] jbd2: check transaction state before stopping handle
From: liubaolin @ 2026-03-06 10:00 UTC (permalink / raw)
To: yebin (H), tytso, jack; +Cc: linux-ext4, linux-kernel, wangguanyu, Baolin Liu
In-Reply-To: <69AA2BF5.3000403@huawei.com>
> Dear yebin,
>
> Thank you for your feedback.
>
> From the crash, we can see this issue was triggered by the MemTableFlushTh process.
> I agree with your point that if this state occurs, there must be something wrong somewhere.
> Once we find and fix the root cause, we should add J_ASSERT((transaction->t_state == T_RUNNING) || (transaction->t_state == T_LOCKED)) to detect such anomalies, rather than directly skipping the assertion check.
>
> I will continue to investigate the root cause and try to find a way to reproduce this issue.
> If you have any thoughts or suggestions on this problem, I'd be happy to discuss.
>
> Best regards,
> Baolin Liu
在 2026/3/6 9:20, yebin (H) 写道:
>
>
> On 2026/3/5 21:11, liubaolin wrote:
>>> Dear maintainers and community,
>>>
>>> Our customer reported a kernel crash issue. The kernel crashes in
>>> stop_this_handle() with:
>>> J_ASSERT(atomic_read(&transaction->t_updates) > 0);
>>>
>>> Crash stack:
>>> Call trace:
>>> stop_this_handle+0x148/0x158
>>> jbd2_journal_stop+0x198/0x388
>>> __ext4_journal_stop+0x70/0xf0
>>> ext4_create+0x12c/0x188
>>> ...
>>>
>>> From the vmcore dump, I found that handle->h_transaction->t_updates is
>>> 0 and handle->h_transaction->t_state is T_FINISHED. This means the
>>> handle is still bound to a transaction that has already completed.
>>>
>>> In the JBD2 commit process, once a transaction enters T_LOCKED state,
>>> the commit thread waits for all associated handles to complete
>>> (t_updates becomes 0). After T_LOCKED completes, the transaction
>>> transitions to T_FLUSH, T_COMMIT, and eventually T_FINISHED. At this
>>> point, t_updates is legitimately 0, and there should be no active
>>> handles bound to this transaction.
>>>
>>> This appears to be a low-probability race condition that occurs under
>>> high concurrency scenarios. The crash happened during ext4_create(),
> I'm curious about what race condition causes this?
>
>>> and at some rare timing point during the execution, a handle ended up
>>> bound to a transaction that had already completed. The symptom is
>>> clear: a handle is bound to a T_FINISHED transaction with t_updates
>>> == 0.
>>>
>>> To prevent this, I added a transaction state check in both
>>> jbd2_journal_stop() and jbd2__journal_restart() before calling
>>> stop_this_handle().
>>> If the transaction is not in T_RUNNING or T_LOCKED state (i.e., it's
>>> in T_FLUSH or later states), I clear handle->h_transaction, clear
>>> current->journal_info if needed, restore the memalloc_nofs context,
>>> and skip calling stop_this_handle(). This is a defensive check to
>>> handle the edge case where a handle is bound to a transaction in an
>>> invalid state.
>>>
> If this state occurs, there must be something wrong somewhere.
> Assertions should also be added to detect such anomalies. I think
> directly skipping the assertion check is not a good way to solve the
> problem.
>>> Please let me know if you have any questions or concerns.
>>>
>>> Best regards,
>>> Baolin Liu
>>
>>
>>
>> 在 2026/3/5 20:57, Baolin Liu 写道:
>>>
>>> Add others
>>>
>>>
>>>
>>>
>>>
>>> At 2026-03-05 20:54:02, "Baolin Liu" <liubaolin12138@163.com> wrote:
>>>> From: Baolin Liu <liubaolin@kylinos.cn>
>>>>
>>>> When a transaction enters T_FLUSH or later states,
>>>> handle->h_transaction may still point to it.
>>>> If jbd2_journal_stop() or jbd2__journal_restart() is called,
>>>> stop_this_handle() checks t_updates > 0, but t_updates is
>>>> already 0 for these states, causing a kernel BUG.
>>>>
>>>> Fix by checking transaction->t_state in jbd2_journal_stop()
>>>> and jbd2__journal_restart() before calling stop_this_handle().
>>>> If the transaction is not in T_RUNNING or T_LOCKED state,
>>>> clear handle->h_transaction and skip stop_this_handle().
>>>>
>>>> Crash stack:
>>>> Call trace:
>>>> stop_this_handle+0x148/0x158
>>>> jbd2_journal_stop+0x198/0x388
>>>> __ext4_journal_stop+0x70/0xf0
>>>> ext4_create+0x12c/0x188
>>>> lookup_open+0x214/0x6d8
>>>> do_last+0x364/0x878
>>>> path_openat+0x6c/0x280
>>>> do_filp_open+0x70/0xe8
>>>> do_sys_open+0x178/0x200
>>>> sys_openat+0x3c/0x50
>>>> el0_svc_naked+0x44/0x48
>>>>
>>>> Signed-off-by: Baolin Liu <liubaolin@kylinos.cn>
>>>> ---
>>>> fs/jbd2/transaction.c | 25 +++++++++++++++++++++++--
>>>> 1 file changed, 23 insertions(+), 2 deletions(-)
>>>>
>>>> diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
>>>> index dca4b5d8aaaa..3779382dbb80 100644
>>>> --- a/fs/jbd2/transaction.c
>>>> +++ b/fs/jbd2/transaction.c
>>>> @@ -772,14 +772,25 @@ int jbd2__journal_restart(handle_t *handle, int
>>>> nblocks, int revoke_records,
>>>> journal = transaction->t_journal;
>>>> tid = transaction->t_tid;
>>>>
>>>> + jbd2_debug(2, "restarting handle %p\n", handle);
>>>> +
>>>> + /* Check if transaction is in invalid state */
>>>> + if (transaction->t_state != T_RUNNING &&
>>>> + transaction->t_state != T_LOCKED) {
>>>> + if (current->journal_info == handle)
>>>> + current->journal_info = NULL;
>>>> + handle->h_transaction = NULL;
>>>> + memalloc_nofs_restore(handle->saved_alloc_context);
>>>> + goto skip_stop;
>>>> + }
>>>> +
>>>> /*
>>>> * First unlink the handle from its current transaction, and
>>>> start the
>>>> * commit on that.
>>>> */
>>>> - jbd2_debug(2, "restarting handle %p\n", handle);
>>>> stop_this_handle(handle);
>>>> handle->h_transaction = NULL;
>>>> -
>>>> +skip_stop:
>>>> /*
>>>> * TODO: If we use READ_ONCE / WRITE_ONCE for j_commit_request we
>>>> can
>>>> * get rid of pointless j_state_lock traffic like this.
>>>> @@ -1856,6 +1867,16 @@ int jbd2_journal_stop(handle_t *handle)
>>>> memalloc_nofs_restore(handle->saved_alloc_context);
>>>> goto free_and_exit;
>>>> }
>>>> + /* Check if transaction is in invalid state */
>>>> + if (transaction->t_state != T_RUNNING &&
>>>> + transaction->t_state != T_LOCKED) {
>>>> + if (current->journal_info == handle)
>>>> + current->journal_info = NULL;
>>>> + handle->h_transaction = NULL;
>>>> + memalloc_nofs_restore(handle->saved_alloc_context);
>>>> + goto free_and_exit;
>>>> + }
>>>> +
>>>> journal = transaction->t_journal;
>>>> tid = transaction->t_tid;
>>>>
>>>> --
>>>> 2.39.2
>>
>>
>>
>> .
>>
^ permalink raw reply
* Re: [PATCH e2fsprogs] e2fsck: preen inline data no attr
From: Andreas Dilger @ 2026-03-06 11:16 UTC (permalink / raw)
To: Daniel Tang; +Cc: linux-ext4, Theodore Tso, Darrick J. Wong
In-Reply-To: <3188418.mvXUDI8C0e@daniel-desktop3>
On Mar 4, 2026, at 06:56, Daniel Tang <danielzgtg.opensource@gmail.com> wrote:
>
> I don't like being forcibly dropped into an emergency shell to truncate
> pidfiles and other temporary files every time my tablet uncleanly shuts
> down.
>
> This seems safe. The only thing that should be erased is the size.
> The removed inline data flag is remembered by the extent flag being
> absent. There is no data to lose because there are no extents/blocks,
> and the system.data attribute is already diagnosed missing.
>
> Signed-off-by: Daniel Tang <danielzgtg.opensource@gmail.com>
> Link: https://github.com/tytso/e2fsprogs/pull/268
This seems pretty safe.
Reviewed-by: Andreas Dilger <adilger@dilger.ca <mailto:adilger@dilger.ca>>
> ---
> e2fsck/problem.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/e2fsck/problem.c b/e2fsck/problem.c
> index e433281f..e6f055f2 100644
> --- a/e2fsck/problem.c
> +++ b/e2fsck/problem.c
> @@ -1170,7 +1170,7 @@ static struct e2fsck_problem problem_table[] = {
> { PR_1_INLINE_DATA_NO_ATTR,
> /* xgettext:no-c-format */
> N_("@i %i has INLINE_DATA_FL flag but @a not found. "),
> - PROMPT_TRUNCATE, 0, 0, 0, 0 },
> + PROMPT_TRUNCATE, PR_PREEN_OK, 0, 0, 0 },
>
> /* Special (device/socket/fifo) file (inode num) has extents
> * or inline-data flag set */
> --
> 2.51.0
>
>
>
>
>
^ permalink raw reply
* Re: [PATCH v2 1/4] mm: Remove stray references to struct pagevec
From: Lorenzo Stoakes (Oracle) @ 2026-03-06 11:42 UTC (permalink / raw)
To: Tal Zussman
Cc: David Howells, Marc Dionne, Jaegeuk Kim, Chao Yu, Andrew Morton,
David Hildenbrand, Lorenzo Stoakes, Liam R. Howlett,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Chris Li, Kairui Song, Kemeng Shi, Nhat Pham, Baoquan He,
Barry Song, Matthew Wilcox, Dan Williams, Jan Kara,
Alexander Viro, Christian Brauner, Theodore Ts'o,
Andreas Dilger, Paulo Alcantara, Trond Myklebust, Anna Schumaker,
Mark Fasheh, Joel Becker, Joseph Qi, Steve French,
Ronnie Sahlberg, Shyam Prasad N, Tom Talpey, Bharath SM,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Chris Mason, David Sterba, Ilya Dryomov,
Alex Markuze, Viacheslav Dubeyko, Andreas Gruenbacher,
Muchun Song, Oscar Salvador, Ryusuke Konishi, Darrick J. Wong,
Chuck Lever, Jeff Layton, NeilBrown, Olga Kornievskaia, Dai Ngo,
Jason Gunthorpe, John Hubbard, Peter Xu, Johannes Weiner,
Roman Gushchin, Shakeel Butt, Jann Horn, Pedro Falcato,
Brendan Jackman, Zi Yan, Hugh Dickins, Baolin Wang,
Axel Rasmussen, Yuanchu Xie, Wei Xu, Qi Zheng, linux-afs,
linux-kernel, linux-f2fs-devel, linux-mm, linux-fsdevel, nvdimm,
linux-ext4, netfs, linux-nfs, ocfs2-devel, linux-cifs,
samba-technical, dri-devel, intel-gfx, linux-btrfs, ceph-devel,
gfs2, linux-nilfs, linux-xfs, cgroups
In-Reply-To: <20260225-pagevec_cleanup-v2-1-716868cc2d11@columbia.edu>
On Wed, Feb 25, 2026 at 06:44:25PM -0500, Tal Zussman wrote:
> struct pagevec was removed in commit 1e0877d58b1e ("mm: remove struct
> pagevec"). Remove remaining forward declarations and change
> __folio_batch_release()'s declaration to match its definition.
>
> Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> Acked-by: David Hildenbrand (Arm) <david@kernel.org>
> Acked-by: Chris Li <chrisl@kernel.org>
> Signed-off-by: Tal Zussman <tz2294@columbia.edu>
LGTM, so:
Reviewed-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
> ---
> fs/afs/internal.h | 1 -
> fs/f2fs/f2fs.h | 2 --
> include/linux/pagevec.h | 2 +-
> include/linux/swap.h | 2 --
> 4 files changed, 1 insertion(+), 6 deletions(-)
>
> diff --git a/fs/afs/internal.h b/fs/afs/internal.h
> index 009064b8d661..599353c33337 100644
> --- a/fs/afs/internal.h
> +++ b/fs/afs/internal.h
> @@ -31,7 +31,6 @@
>
> #define AFS_CELL_MAX_ADDRS 15
>
> -struct pagevec;
> struct afs_call;
> struct afs_vnode;
> struct afs_server_probe;
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index bb34e864d0ef..d9e8531a5301 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -28,8 +28,6 @@
> #include <linux/fscrypt.h>
> #include <linux/fsverity.h>
>
> -struct pagevec;
> -
> #ifdef CONFIG_F2FS_CHECK_FS
> #define f2fs_bug_on(sbi, condition) BUG_ON(condition)
> #else
> diff --git a/include/linux/pagevec.h b/include/linux/pagevec.h
> index 63be5a451627..007affabf335 100644
> --- a/include/linux/pagevec.h
> +++ b/include/linux/pagevec.h
> @@ -93,7 +93,7 @@ static inline struct folio *folio_batch_next(struct folio_batch *fbatch)
> return fbatch->folios[fbatch->i++];
> }
>
> -void __folio_batch_release(struct folio_batch *pvec);
> +void __folio_batch_release(struct folio_batch *fbatch);
>
> static inline void folio_batch_release(struct folio_batch *fbatch)
> {
> diff --git a/include/linux/swap.h b/include/linux/swap.h
> index 0effe3cc50f5..4b1f13b5bbad 100644
> --- a/include/linux/swap.h
> +++ b/include/linux/swap.h
> @@ -20,8 +20,6 @@ struct notifier_block;
>
> struct bio;
>
> -struct pagevec;
> -
> #define SWAP_FLAG_PREFER 0x8000 /* set if swap priority specified */
> #define SWAP_FLAG_PRIO_MASK 0x7fff
> #define SWAP_FLAG_DISCARD 0x10000 /* enable discard for swap */
>
> --
> 2.39.5
>
^ permalink raw reply
* Re: [PATCH v2 2/4] fs: Remove unncessary pagevec.h includes
From: Lorenzo Stoakes (Oracle) @ 2026-03-06 11:43 UTC (permalink / raw)
To: Tal Zussman
Cc: David Howells, Marc Dionne, Jaegeuk Kim, Chao Yu, Andrew Morton,
David Hildenbrand, Lorenzo Stoakes, Liam R. Howlett,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Chris Li, Kairui Song, Kemeng Shi, Nhat Pham, Baoquan He,
Barry Song, Matthew Wilcox, Dan Williams, Jan Kara,
Alexander Viro, Christian Brauner, Theodore Ts'o,
Andreas Dilger, Paulo Alcantara, Trond Myklebust, Anna Schumaker,
Mark Fasheh, Joel Becker, Joseph Qi, Steve French,
Ronnie Sahlberg, Shyam Prasad N, Tom Talpey, Bharath SM,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Chris Mason, David Sterba, Ilya Dryomov,
Alex Markuze, Viacheslav Dubeyko, Andreas Gruenbacher,
Muchun Song, Oscar Salvador, Ryusuke Konishi, Darrick J. Wong,
Chuck Lever, Jeff Layton, NeilBrown, Olga Kornievskaia, Dai Ngo,
Jason Gunthorpe, John Hubbard, Peter Xu, Johannes Weiner,
Roman Gushchin, Shakeel Butt, Jann Horn, Pedro Falcato,
Brendan Jackman, Zi Yan, Hugh Dickins, Baolin Wang,
Axel Rasmussen, Yuanchu Xie, Wei Xu, Qi Zheng, linux-afs,
linux-kernel, linux-f2fs-devel, linux-mm, linux-fsdevel, nvdimm,
linux-ext4, netfs, linux-nfs, ocfs2-devel, linux-cifs,
samba-technical, dri-devel, intel-gfx, linux-btrfs, ceph-devel,
gfs2, linux-nilfs, linux-xfs, cgroups
In-Reply-To: <20260225-pagevec_cleanup-v2-2-716868cc2d11@columbia.edu>
On Wed, Feb 25, 2026 at 06:44:26PM -0500, Tal Zussman wrote:
> Remove unused pagevec.h includes from .c files. These were found with
> the following command:
>
> grep -rl '#include.*pagevec\.h' --include='*.c' | while read f; do
> grep -qE 'PAGEVEC_SIZE|folio_batch' "$f" || echo "$f"
> done
>
> There are probably more removal candidates in .h files, but those are
> more complex to analyze.
>
> Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Nice, LGTM so:
Reviewed-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
> ---
> fs/afs/write.c | 1 -
> fs/dax.c | 1 -
> fs/ext4/file.c | 1 -
> fs/ext4/page-io.c | 1 -
> fs/ext4/readpage.c | 1 -
> fs/f2fs/file.c | 1 -
> fs/mpage.c | 1 -
> fs/netfs/buffered_write.c | 1 -
> fs/nfs/blocklayout/blocklayout.c | 1 -
> fs/nfs/dir.c | 1 -
> fs/ocfs2/refcounttree.c | 1 -
> fs/smb/client/connect.c | 1 -
> fs/smb/client/file.c | 1 -
> 13 files changed, 13 deletions(-)
>
> diff --git a/fs/afs/write.c b/fs/afs/write.c
> index 93ad86ff3345..fcfed9d24e0a 100644
> --- a/fs/afs/write.c
> +++ b/fs/afs/write.c
> @@ -10,7 +10,6 @@
> #include <linux/fs.h>
> #include <linux/pagemap.h>
> #include <linux/writeback.h>
> -#include <linux/pagevec.h>
> #include <linux/netfs.h>
> #include <trace/events/netfs.h>
> #include "internal.h"
> diff --git a/fs/dax.c b/fs/dax.c
> index b78cff9c91b3..a5237169b467 100644
> --- a/fs/dax.c
> +++ b/fs/dax.c
> @@ -15,7 +15,6 @@
> #include <linux/memcontrol.h>
> #include <linux/mm.h>
> #include <linux/mutex.h>
> -#include <linux/pagevec.h>
> #include <linux/sched.h>
> #include <linux/sched/signal.h>
> #include <linux/uio.h>
> diff --git a/fs/ext4/file.c b/fs/ext4/file.c
> index f1dc5ce791a7..5e02f6cf653e 100644
> --- a/fs/ext4/file.c
> +++ b/fs/ext4/file.c
> @@ -27,7 +27,6 @@
> #include <linux/dax.h>
> #include <linux/filelock.h>
> #include <linux/quotaops.h>
> -#include <linux/pagevec.h>
> #include <linux/uio.h>
> #include <linux/mman.h>
> #include <linux/backing-dev.h>
> diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
> index a8c95eee91b7..98da200d11c8 100644
> --- a/fs/ext4/page-io.c
> +++ b/fs/ext4/page-io.c
> @@ -16,7 +16,6 @@
> #include <linux/string.h>
> #include <linux/buffer_head.h>
> #include <linux/writeback.h>
> -#include <linux/pagevec.h>
> #include <linux/mpage.h>
> #include <linux/namei.h>
> #include <linux/uio.h>
> diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
> index 830f3b8a321f..3c7aabde719c 100644
> --- a/fs/ext4/readpage.c
> +++ b/fs/ext4/readpage.c
> @@ -43,7 +43,6 @@
> #include <linux/mpage.h>
> #include <linux/writeback.h>
> #include <linux/backing-dev.h>
> -#include <linux/pagevec.h>
>
> #include "ext4.h"
> #include <trace/events/ext4.h>
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index c8a2f17a8f11..c6b6a1465d08 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -17,7 +17,6 @@
> #include <linux/compat.h>
> #include <linux/uaccess.h>
> #include <linux/mount.h>
> -#include <linux/pagevec.h>
> #include <linux/uio.h>
> #include <linux/uuid.h>
> #include <linux/file.h>
> diff --git a/fs/mpage.c b/fs/mpage.c
> index 7dae5afc2b9e..e5285fbfcf09 100644
> --- a/fs/mpage.c
> +++ b/fs/mpage.c
> @@ -28,7 +28,6 @@
> #include <linux/mm_inline.h>
> #include <linux/writeback.h>
> #include <linux/backing-dev.h>
> -#include <linux/pagevec.h>
> #include "internal.h"
>
> /*
> diff --git a/fs/netfs/buffered_write.c b/fs/netfs/buffered_write.c
> index 22a4d61631c9..05ea5b0cc0e8 100644
> --- a/fs/netfs/buffered_write.c
> +++ b/fs/netfs/buffered_write.c
> @@ -10,7 +10,6 @@
> #include <linux/mm.h>
> #include <linux/pagemap.h>
> #include <linux/slab.h>
> -#include <linux/pagevec.h>
> #include "internal.h"
>
> static void __netfs_set_group(struct folio *folio, struct netfs_group *netfs_group)
> diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
> index cb0a645aeb50..11f9f69cde61 100644
> --- a/fs/nfs/blocklayout/blocklayout.c
> +++ b/fs/nfs/blocklayout/blocklayout.c
> @@ -36,7 +36,6 @@
> #include <linux/namei.h>
> #include <linux/bio.h> /* struct bio */
> #include <linux/prefetch.h>
> -#include <linux/pagevec.h>
>
> #include "../pnfs.h"
> #include "../nfs4session.h"
> diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
> index 2402f57c8e7d..0d276441206b 100644
> --- a/fs/nfs/dir.c
> +++ b/fs/nfs/dir.c
> @@ -32,7 +32,6 @@
> #include <linux/nfs_fs.h>
> #include <linux/nfs_mount.h>
> #include <linux/pagemap.h>
> -#include <linux/pagevec.h>
> #include <linux/namei.h>
> #include <linux/mount.h>
> #include <linux/swap.h>
> diff --git a/fs/ocfs2/refcounttree.c b/fs/ocfs2/refcounttree.c
> index c1cdececdfa4..b4acd081bbc4 100644
> --- a/fs/ocfs2/refcounttree.c
> +++ b/fs/ocfs2/refcounttree.c
> @@ -31,7 +31,6 @@
> #include <linux/blkdev.h>
> #include <linux/slab.h>
> #include <linux/writeback.h>
> -#include <linux/pagevec.h>
> #include <linux/swap.h>
> #include <linux/security.h>
> #include <linux/string.h>
> diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
> index 33dfe116ca52..9e57812b7b95 100644
> --- a/fs/smb/client/connect.c
> +++ b/fs/smb/client/connect.c
> @@ -20,7 +20,6 @@
> #include <linux/delay.h>
> #include <linux/completion.h>
> #include <linux/kthread.h>
> -#include <linux/pagevec.h>
> #include <linux/freezer.h>
> #include <linux/namei.h>
> #include <linux/uuid.h>
> diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
> index 18f31d4eb98d..853ce1817810 100644
> --- a/fs/smb/client/file.c
> +++ b/fs/smb/client/file.c
> @@ -15,7 +15,6 @@
> #include <linux/stat.h>
> #include <linux/fcntl.h>
> #include <linux/pagemap.h>
> -#include <linux/pagevec.h>
> #include <linux/writeback.h>
> #include <linux/task_io_accounting_ops.h>
> #include <linux/delay.h>
>
> --
> 2.39.5
>
^ permalink raw reply
* Re: [PATCH v2 3/4] folio_batch: Rename pagevec.h to folio_batch.h
From: Lorenzo Stoakes (Oracle) @ 2026-03-06 11:43 UTC (permalink / raw)
To: Tal Zussman
Cc: David Howells, Marc Dionne, Jaegeuk Kim, Chao Yu, Andrew Morton,
David Hildenbrand, Lorenzo Stoakes, Liam R. Howlett,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Chris Li, Kairui Song, Kemeng Shi, Nhat Pham, Baoquan He,
Barry Song, Matthew Wilcox, Dan Williams, Jan Kara,
Alexander Viro, Christian Brauner, Theodore Ts'o,
Andreas Dilger, Paulo Alcantara, Trond Myklebust, Anna Schumaker,
Mark Fasheh, Joel Becker, Joseph Qi, Steve French,
Ronnie Sahlberg, Shyam Prasad N, Tom Talpey, Bharath SM,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Chris Mason, David Sterba, Ilya Dryomov,
Alex Markuze, Viacheslav Dubeyko, Andreas Gruenbacher,
Muchun Song, Oscar Salvador, Ryusuke Konishi, Darrick J. Wong,
Chuck Lever, Jeff Layton, NeilBrown, Olga Kornievskaia, Dai Ngo,
Jason Gunthorpe, John Hubbard, Peter Xu, Johannes Weiner,
Roman Gushchin, Shakeel Butt, Jann Horn, Pedro Falcato,
Brendan Jackman, Zi Yan, Hugh Dickins, Baolin Wang,
Axel Rasmussen, Yuanchu Xie, Wei Xu, Qi Zheng, linux-afs,
linux-kernel, linux-f2fs-devel, linux-mm, linux-fsdevel, nvdimm,
linux-ext4, netfs, linux-nfs, ocfs2-devel, linux-cifs,
samba-technical, dri-devel, intel-gfx, linux-btrfs, ceph-devel,
gfs2, linux-nilfs, linux-xfs, cgroups
In-Reply-To: <20260225-pagevec_cleanup-v2-3-716868cc2d11@columbia.edu>
On Wed, Feb 25, 2026 at 06:44:27PM -0500, Tal Zussman wrote:
> struct pagevec was removed in commit 1e0877d58b1e ("mm: remove struct
> pagevec"). Rename include/linux/pagevec.h to reflect reality and update
> includes tree-wide. Add the new filename to MAINTAINERS explicitly, as
> it no longer matches the "include/linux/page[-_]*" pattern in MEMORY
> MANAGEMENT - CORE.
>
> Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Nice, thanks for this! LGTM, so:
Reviewed-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
> ---
> MAINTAINERS | 1 +
> drivers/gpu/drm/drm_gem.c | 2 +-
> drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 2 +-
> drivers/gpu/drm/i915/gt/intel_gtt.h | 2 +-
> drivers/gpu/drm/i915/i915_gpu_error.c | 2 +-
> fs/btrfs/compression.c | 2 +-
> fs/btrfs/extent_io.c | 2 +-
> fs/btrfs/tests/extent-io-tests.c | 2 +-
> fs/buffer.c | 2 +-
> fs/ceph/addr.c | 2 +-
> fs/ext4/inode.c | 2 +-
> fs/f2fs/checkpoint.c | 2 +-
> fs/f2fs/compress.c | 2 +-
> fs/f2fs/data.c | 2 +-
> fs/f2fs/node.c | 2 +-
> fs/gfs2/aops.c | 2 +-
> fs/hugetlbfs/inode.c | 2 +-
> fs/nilfs2/btree.c | 2 +-
> fs/nilfs2/page.c | 2 +-
> fs/nilfs2/segment.c | 2 +-
> fs/ramfs/file-nommu.c | 2 +-
> include/linux/{pagevec.h => folio_batch.h} | 8 ++++----
> include/linux/folio_queue.h | 2 +-
> include/linux/iomap.h | 2 +-
> include/linux/sunrpc/svc.h | 2 +-
> include/linux/writeback.h | 2 +-
> mm/filemap.c | 2 +-
> mm/gup.c | 2 +-
> mm/memcontrol.c | 2 +-
> mm/mlock.c | 2 +-
> mm/page-writeback.c | 2 +-
> mm/page_alloc.c | 2 +-
> mm/shmem.c | 2 +-
> mm/swap.c | 2 +-
> mm/swap_state.c | 2 +-
> mm/truncate.c | 2 +-
> mm/vmscan.c | 2 +-
> 37 files changed, 40 insertions(+), 39 deletions(-)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index e4572a36afd2..f50421e65cb1 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -16664,6 +16664,7 @@ L: linux-mm@kvack.org
> S: Maintained
> W: http://www.linux-mm.org
> T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
> +F: include/linux/folio_batch.h
> F: include/linux/gfp.h
> F: include/linux/gfp_types.h
> F: include/linux/highmem.h
> diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> index 891c3bff5ae0..dc4534fb175c 100644
> --- a/drivers/gpu/drm/drm_gem.c
> +++ b/drivers/gpu/drm/drm_gem.c
> @@ -38,7 +38,7 @@
> #include <linux/mman.h>
> #include <linux/module.h>
> #include <linux/pagemap.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/sched/mm.h>
> #include <linux/shmem_fs.h>
> #include <linux/slab.h>
> diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
> index c6c64ba29bc4..07025b547c94 100644
> --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
> +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
> @@ -3,7 +3,7 @@
> * Copyright © 2014-2016 Intel Corporation
> */
>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/shmem_fs.h>
> #include <linux/swap.h>
> #include <linux/uio.h>
> diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h b/drivers/gpu/drm/i915/gt/intel_gtt.h
> index 9d3a3ad567a0..b54ee4f25af1 100644
> --- a/drivers/gpu/drm/i915/gt/intel_gtt.h
> +++ b/drivers/gpu/drm/i915/gt/intel_gtt.h
> @@ -19,7 +19,7 @@
> #include <linux/io-mapping.h>
> #include <linux/kref.h>
> #include <linux/mm.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/scatterlist.h>
> #include <linux/workqueue.h>
>
> diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
> index a99b4e45d26c..ffe5f24594c9 100644
> --- a/drivers/gpu/drm/i915/i915_gpu_error.c
> +++ b/drivers/gpu/drm/i915/i915_gpu_error.c
> @@ -31,7 +31,7 @@
> #include <linux/debugfs.h>
> #include <linux/highmem.h>
> #include <linux/nmi.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/scatterlist.h>
> #include <linux/string_helpers.h>
> #include <linux/utsname.h>
> diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c
> index 790518a8c803..dbc634d10ad3 100644
> --- a/fs/btrfs/compression.c
> +++ b/fs/btrfs/compression.c
> @@ -8,7 +8,7 @@
> #include <linux/file.h>
> #include <linux/fs.h>
> #include <linux/pagemap.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/highmem.h>
> #include <linux/kthread.h>
> #include <linux/time.h>
> diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
> index 744a1fff6eef..c373d113f1e7 100644
> --- a/fs/btrfs/extent_io.c
> +++ b/fs/btrfs/extent_io.c
> @@ -11,7 +11,7 @@
> #include <linux/blkdev.h>
> #include <linux/swap.h>
> #include <linux/writeback.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/prefetch.h>
> #include <linux/fsverity.h>
> #include "extent_io.h"
> diff --git a/fs/btrfs/tests/extent-io-tests.c b/fs/btrfs/tests/extent-io-tests.c
> index a0187d6163df..b2aacf846c8b 100644
> --- a/fs/btrfs/tests/extent-io-tests.c
> +++ b/fs/btrfs/tests/extent-io-tests.c
> @@ -4,7 +4,7 @@
> */
>
> #include <linux/pagemap.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/sched.h>
> #include <linux/slab.h>
> #include <linux/sizes.h>
> diff --git a/fs/buffer.c b/fs/buffer.c
> index 22b43642ba57..f3122160ee2d 100644
> --- a/fs/buffer.c
> +++ b/fs/buffer.c
> @@ -45,7 +45,7 @@
> #include <linux/bitops.h>
> #include <linux/mpage.h>
> #include <linux/bit_spinlock.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/sched/mm.h>
> #include <trace/events/block.h>
> #include <linux/fscrypt.h>
> diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
> index e87b3bb94ee8..2803511d86ef 100644
> --- a/fs/ceph/addr.c
> +++ b/fs/ceph/addr.c
> @@ -7,7 +7,7 @@
> #include <linux/swap.h>
> #include <linux/pagemap.h>
> #include <linux/slab.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/task_io_accounting_ops.h>
> #include <linux/signal.h>
> #include <linux/iversion.h>
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 396dc3a5d16b..58f982885187 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -29,7 +29,7 @@
> #include <linux/string.h>
> #include <linux/buffer_head.h>
> #include <linux/writeback.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/mpage.h>
> #include <linux/rmap.h>
> #include <linux/namei.h>
> diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
> index 6dd39b7de11a..0143365c07dc 100644
> --- a/fs/f2fs/checkpoint.c
> +++ b/fs/f2fs/checkpoint.c
> @@ -11,7 +11,7 @@
> #include <linux/writeback.h>
> #include <linux/blkdev.h>
> #include <linux/f2fs_fs.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/swap.h>
> #include <linux/kthread.h>
> #include <linux/delayacct.h>
> diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
> index 8c76400ba631..614e00b8ffdc 100644
> --- a/fs/f2fs/compress.c
> +++ b/fs/f2fs/compress.c
> @@ -13,7 +13,7 @@
> #include <linux/lzo.h>
> #include <linux/lz4.h>
> #include <linux/zstd.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
>
> #include "f2fs.h"
> #include "node.h"
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 338df7a2aea6..90e8ef625d82 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -10,7 +10,7 @@
> #include <linux/sched/mm.h>
> #include <linux/mpage.h>
> #include <linux/writeback.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/blkdev.h>
> #include <linux/bio.h>
> #include <linux/blk-crypto.h>
> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> index 74992fd9c9b6..ba0272314528 100644
> --- a/fs/f2fs/node.c
> +++ b/fs/f2fs/node.c
> @@ -10,7 +10,7 @@
> #include <linux/mpage.h>
> #include <linux/sched/mm.h>
> #include <linux/blkdev.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/swap.h>
>
> #include "f2fs.h"
> diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
> index e79ad087512a..dae3dc4ee6f7 100644
> --- a/fs/gfs2/aops.c
> +++ b/fs/gfs2/aops.c
> @@ -10,7 +10,7 @@
> #include <linux/completion.h>
> #include <linux/buffer_head.h>
> #include <linux/pagemap.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/mpage.h>
> #include <linux/fs.h>
> #include <linux/writeback.h>
> diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
> index 22c799000edb..2ec3e4231252 100644
> --- a/fs/hugetlbfs/inode.c
> +++ b/fs/hugetlbfs/inode.c
> @@ -25,7 +25,7 @@
> #include <linux/ctype.h>
> #include <linux/backing-dev.h>
> #include <linux/hugetlb.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/fs_parser.h>
> #include <linux/mman.h>
> #include <linux/slab.h>
> diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c
> index dd0c8e560ef6..b400cfcdc803 100644
> --- a/fs/nilfs2/btree.c
> +++ b/fs/nilfs2/btree.c
> @@ -10,7 +10,7 @@
> #include <linux/slab.h>
> #include <linux/string.h>
> #include <linux/errno.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include "nilfs.h"
> #include "page.h"
> #include "btnode.h"
> diff --git a/fs/nilfs2/page.c b/fs/nilfs2/page.c
> index 56c4da417b6a..a9d8aa65416f 100644
> --- a/fs/nilfs2/page.c
> +++ b/fs/nilfs2/page.c
> @@ -14,7 +14,7 @@
> #include <linux/page-flags.h>
> #include <linux/list.h>
> #include <linux/highmem.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/gfp.h>
> #include "nilfs.h"
> #include "page.h"
> diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
> index 098a3bd103e0..6d62de64a309 100644
> --- a/fs/nilfs2/segment.c
> +++ b/fs/nilfs2/segment.c
> @@ -19,7 +19,7 @@
> #include <linux/freezer.h>
> #include <linux/kthread.h>
> #include <linux/crc32.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/slab.h>
> #include <linux/sched/signal.h>
>
> diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c
> index 0f8e838ece07..2f79bcb89d2e 100644
> --- a/fs/ramfs/file-nommu.c
> +++ b/fs/ramfs/file-nommu.c
> @@ -14,7 +14,7 @@
> #include <linux/string.h>
> #include <linux/backing-dev.h>
> #include <linux/ramfs.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/mman.h>
> #include <linux/sched.h>
> #include <linux/slab.h>
> diff --git a/include/linux/pagevec.h b/include/linux/folio_batch.h
> similarity index 95%
> rename from include/linux/pagevec.h
> rename to include/linux/folio_batch.h
> index 007affabf335..a2f3d3043f7e 100644
> --- a/include/linux/pagevec.h
> +++ b/include/linux/folio_batch.h
> @@ -1,13 +1,13 @@
> /* SPDX-License-Identifier: GPL-2.0 */
> /*
> - * include/linux/pagevec.h
> + * include/linux/folio_batch.h
> *
> * In many places it is efficient to batch an operation up against multiple
> * folios. A folio_batch is a container which is used for that.
> */
>
> -#ifndef _LINUX_PAGEVEC_H
> -#define _LINUX_PAGEVEC_H
> +#ifndef _LINUX_FOLIO_BATCH_H
> +#define _LINUX_FOLIO_BATCH_H
>
> #include <linux/types.h>
>
> @@ -102,4 +102,4 @@ static inline void folio_batch_release(struct folio_batch *fbatch)
> }
>
> void folio_batch_remove_exceptionals(struct folio_batch *fbatch);
> -#endif /* _LINUX_PAGEVEC_H */
> +#endif /* _LINUX_FOLIO_BATCH_H */
> diff --git a/include/linux/folio_queue.h b/include/linux/folio_queue.h
> index adab609c972e..0d3765fa9d1d 100644
> --- a/include/linux/folio_queue.h
> +++ b/include/linux/folio_queue.h
> @@ -14,7 +14,7 @@
> #ifndef _LINUX_FOLIO_QUEUE_H
> #define _LINUX_FOLIO_QUEUE_H
>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/mm.h>
>
> /*
> diff --git a/include/linux/iomap.h b/include/linux/iomap.h
> index 99b7209dabd7..4551613cea2f 100644
> --- a/include/linux/iomap.h
> +++ b/include/linux/iomap.h
> @@ -9,7 +9,7 @@
> #include <linux/types.h>
> #include <linux/mm_types.h>
> #include <linux/blkdev.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
>
> struct address_space;
> struct fiemap_extent_info;
> diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
> index 4dc14c7a711b..a11acf5cd63b 100644
> --- a/include/linux/sunrpc/svc.h
> +++ b/include/linux/sunrpc/svc.h
> @@ -20,7 +20,7 @@
> #include <linux/lwq.h>
> #include <linux/wait.h>
> #include <linux/mm.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/kthread.h>
>
> /*
> diff --git a/include/linux/writeback.h b/include/linux/writeback.h
> index e530112c4b3a..62552a2ce5b9 100644
> --- a/include/linux/writeback.h
> +++ b/include/linux/writeback.h
> @@ -11,7 +11,7 @@
> #include <linux/flex_proportions.h>
> #include <linux/backing-dev-defs.h>
> #include <linux/blk_types.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
>
> struct bio;
>
> diff --git a/mm/filemap.c b/mm/filemap.c
> index 6cd7974d4ada..63f256307fdd 100644
> --- a/mm/filemap.c
> +++ b/mm/filemap.c
> @@ -31,7 +31,7 @@
> #include <linux/hash.h>
> #include <linux/writeback.h>
> #include <linux/backing-dev.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/security.h>
> #include <linux/cpuset.h>
> #include <linux/hugetlb.h>
> diff --git a/mm/gup.c b/mm/gup.c
> index 8e7dc2c6ee73..ad9ded39609c 100644
> --- a/mm/gup.c
> +++ b/mm/gup.c
> @@ -18,7 +18,7 @@
> #include <linux/hugetlb.h>
> #include <linux/migrate.h>
> #include <linux/mm_inline.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/sched/mm.h>
> #include <linux/shmem_fs.h>
>
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index db59fad3503f..51508573963d 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -34,7 +34,7 @@
> #include <linux/shmem_fs.h>
> #include <linux/hugetlb.h>
> #include <linux/pagemap.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/vm_event_item.h>
> #include <linux/smp.h>
> #include <linux/page-flags.h>
> diff --git a/mm/mlock.c b/mm/mlock.c
> index 2f699c3497a5..1a92d16f3684 100644
> --- a/mm/mlock.c
> +++ b/mm/mlock.c
> @@ -13,7 +13,7 @@
> #include <linux/swap.h>
> #include <linux/swapops.h>
> #include <linux/pagemap.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/pagewalk.h>
> #include <linux/mempolicy.h>
> #include <linux/syscalls.h>
> diff --git a/mm/page-writeback.c b/mm/page-writeback.c
> index 601a5e048d12..1009bb042ba4 100644
> --- a/mm/page-writeback.c
> +++ b/mm/page-writeback.c
> @@ -33,7 +33,7 @@
> #include <linux/sysctl.h>
> #include <linux/cpu.h>
> #include <linux/syscalls.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/timer.h>
> #include <linux/sched/rt.h>
> #include <linux/sched/signal.h>
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index d88c8c67ac0b..74b603872f34 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -31,7 +31,7 @@
> #include <linux/sysctl.h>
> #include <linux/cpu.h>
> #include <linux/cpuset.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/memory_hotplug.h>
> #include <linux/nodemask.h>
> #include <linux/vmstat.h>
> diff --git a/mm/shmem.c b/mm/shmem.c
> index cfed6c3ff853..149fdb051170 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -61,7 +61,7 @@ static struct vfsmount *shm_mnt __ro_after_init;
> #include <linux/slab.h>
> #include <linux/backing-dev.h>
> #include <linux/writeback.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/percpu_counter.h>
> #include <linux/falloc.h>
> #include <linux/splice.h>
> diff --git a/mm/swap.c b/mm/swap.c
> index bb19ccbece46..2e517ede6561 100644
> --- a/mm/swap.c
> +++ b/mm/swap.c
> @@ -20,7 +20,7 @@
> #include <linux/swap.h>
> #include <linux/mman.h>
> #include <linux/pagemap.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/init.h>
> #include <linux/export.h>
> #include <linux/mm_inline.h>
> diff --git a/mm/swap_state.c b/mm/swap_state.c
> index 32d9d877bda8..a0c64db2b275 100644
> --- a/mm/swap_state.c
> +++ b/mm/swap_state.c
> @@ -15,7 +15,7 @@
> #include <linux/leafops.h>
> #include <linux/init.h>
> #include <linux/pagemap.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/backing-dev.h>
> #include <linux/blkdev.h>
> #include <linux/migrate.h>
> diff --git a/mm/truncate.c b/mm/truncate.c
> index 12467c1bd711..df0b7a7e6aff 100644
> --- a/mm/truncate.c
> +++ b/mm/truncate.c
> @@ -17,7 +17,7 @@
> #include <linux/export.h>
> #include <linux/pagemap.h>
> #include <linux/highmem.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/task_io_accounting_ops.h>
> #include <linux/shmem_fs.h>
> #include <linux/rmap.h>
> diff --git a/mm/vmscan.c b/mm/vmscan.c
> index 7effd01a7828..7e921dbe2373 100644
> --- a/mm/vmscan.c
> +++ b/mm/vmscan.c
> @@ -44,7 +44,7 @@
> #include <linux/sysctl.h>
> #include <linux/memory-tiers.h>
> #include <linux/oom.h>
> -#include <linux/pagevec.h>
> +#include <linux/folio_batch.h>
> #include <linux/prefetch.h>
> #include <linux/printk.h>
> #include <linux/dax.h>
>
> --
> 2.39.5
>
^ permalink raw reply
* Re: [PATCH v2 4/4] folio_batch: Rename PAGEVEC_SIZE to FOLIO_BATCH_SIZE
From: Lorenzo Stoakes (Oracle) @ 2026-03-06 11:45 UTC (permalink / raw)
To: Tal Zussman
Cc: David Howells, Marc Dionne, Jaegeuk Kim, Chao Yu, Andrew Morton,
David Hildenbrand, Lorenzo Stoakes, Liam R. Howlett,
Vlastimil Babka, Mike Rapoport, Suren Baghdasaryan, Michal Hocko,
Chris Li, Kairui Song, Kemeng Shi, Nhat Pham, Baoquan He,
Barry Song, Matthew Wilcox, Dan Williams, Jan Kara,
Alexander Viro, Christian Brauner, Theodore Ts'o,
Andreas Dilger, Paulo Alcantara, Trond Myklebust, Anna Schumaker,
Mark Fasheh, Joel Becker, Joseph Qi, Steve French,
Ronnie Sahlberg, Shyam Prasad N, Tom Talpey, Bharath SM,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Chris Mason, David Sterba, Ilya Dryomov,
Alex Markuze, Viacheslav Dubeyko, Andreas Gruenbacher,
Muchun Song, Oscar Salvador, Ryusuke Konishi, Darrick J. Wong,
Chuck Lever, Jeff Layton, NeilBrown, Olga Kornievskaia, Dai Ngo,
Jason Gunthorpe, John Hubbard, Peter Xu, Johannes Weiner,
Roman Gushchin, Shakeel Butt, Jann Horn, Pedro Falcato,
Brendan Jackman, Zi Yan, Hugh Dickins, Baolin Wang,
Axel Rasmussen, Yuanchu Xie, Wei Xu, Qi Zheng, linux-afs,
linux-kernel, linux-f2fs-devel, linux-mm, linux-fsdevel, nvdimm,
linux-ext4, netfs, linux-nfs, ocfs2-devel, linux-cifs,
samba-technical, dri-devel, intel-gfx, linux-btrfs, ceph-devel,
gfs2, linux-nilfs, linux-xfs, cgroups
In-Reply-To: <20260225-pagevec_cleanup-v2-4-716868cc2d11@columbia.edu>
On Wed, Feb 25, 2026 at 06:44:28PM -0500, Tal Zussman wrote:
> struct pagevec no longer exists. Rename the macro appropriately.
>
> Signed-off-by: Tal Zussman <tz2294@columbia.edu>
Nice thanks for this! LGTM, so:
Reviewed-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
> ---
> fs/btrfs/extent_io.c | 4 ++--
> include/linux/folio_batch.h | 6 +++---
> include/linux/folio_queue.h | 6 +++---
> mm/shmem.c | 4 ++--
> mm/swap.c | 2 +-
> mm/swap_state.c | 2 +-
> mm/truncate.c | 6 +++---
> 7 files changed, 15 insertions(+), 15 deletions(-)
>
> diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
> index c373d113f1e7..d82ca509503f 100644
> --- a/fs/btrfs/extent_io.c
> +++ b/fs/btrfs/extent_io.c
> @@ -2095,13 +2095,13 @@ static void buffer_tree_tag_for_writeback(struct btrfs_fs_info *fs_info,
> struct eb_batch {
> unsigned int nr;
> unsigned int cur;
> - struct extent_buffer *ebs[PAGEVEC_SIZE];
> + struct extent_buffer *ebs[FOLIO_BATCH_SIZE];
> };
>
> static inline bool eb_batch_add(struct eb_batch *batch, struct extent_buffer *eb)
> {
> batch->ebs[batch->nr++] = eb;
> - return (batch->nr < PAGEVEC_SIZE);
> + return (batch->nr < FOLIO_BATCH_SIZE);
> }
>
> static inline void eb_batch_init(struct eb_batch *batch)
> diff --git a/include/linux/folio_batch.h b/include/linux/folio_batch.h
> index a2f3d3043f7e..b45946adc50b 100644
> --- a/include/linux/folio_batch.h
> +++ b/include/linux/folio_batch.h
> @@ -12,7 +12,7 @@
> #include <linux/types.h>
>
> /* 31 pointers + header align the folio_batch structure to a power of two */
> -#define PAGEVEC_SIZE 31
> +#define FOLIO_BATCH_SIZE 31
>
> struct folio;
>
> @@ -29,7 +29,7 @@ struct folio_batch {
> unsigned char nr;
> unsigned char i;
> bool percpu_pvec_drained;
> - struct folio *folios[PAGEVEC_SIZE];
> + struct folio *folios[FOLIO_BATCH_SIZE];
> };
>
> /**
> @@ -58,7 +58,7 @@ static inline unsigned int folio_batch_count(const struct folio_batch *fbatch)
>
> static inline unsigned int folio_batch_space(const struct folio_batch *fbatch)
> {
> - return PAGEVEC_SIZE - fbatch->nr;
> + return FOLIO_BATCH_SIZE - fbatch->nr;
> }
>
> /**
> diff --git a/include/linux/folio_queue.h b/include/linux/folio_queue.h
> index 0d3765fa9d1d..f6d5f1f127c9 100644
> --- a/include/linux/folio_queue.h
> +++ b/include/linux/folio_queue.h
> @@ -29,12 +29,12 @@
> */
> struct folio_queue {
> struct folio_batch vec; /* Folios in the queue segment */
> - u8 orders[PAGEVEC_SIZE]; /* Order of each folio */
> + u8 orders[FOLIO_BATCH_SIZE]; /* Order of each folio */
> struct folio_queue *next; /* Next queue segment or NULL */
> struct folio_queue *prev; /* Previous queue segment of NULL */
> unsigned long marks; /* 1-bit mark per folio */
> unsigned long marks2; /* Second 1-bit mark per folio */
> -#if PAGEVEC_SIZE > BITS_PER_LONG
> +#if FOLIO_BATCH_SIZE > BITS_PER_LONG
> #error marks is not big enough
> #endif
> unsigned int rreq_id;
> @@ -70,7 +70,7 @@ static inline void folioq_init(struct folio_queue *folioq, unsigned int rreq_id)
> */
> static inline unsigned int folioq_nr_slots(const struct folio_queue *folioq)
> {
> - return PAGEVEC_SIZE;
> + return FOLIO_BATCH_SIZE;
> }
>
> /**
> diff --git a/mm/shmem.c b/mm/shmem.c
> index 149fdb051170..5e7dcf5bc5d3 100644
> --- a/mm/shmem.c
> +++ b/mm/shmem.c
> @@ -1113,7 +1113,7 @@ static void shmem_undo_range(struct inode *inode, loff_t lstart, uoff_t lend,
> pgoff_t start = (lstart + PAGE_SIZE - 1) >> PAGE_SHIFT;
> pgoff_t end = (lend + 1) >> PAGE_SHIFT;
> struct folio_batch fbatch;
> - pgoff_t indices[PAGEVEC_SIZE];
> + pgoff_t indices[FOLIO_BATCH_SIZE];
> struct folio *folio;
> bool same_folio;
> long nr_swaps_freed = 0;
> @@ -1510,7 +1510,7 @@ static int shmem_unuse_inode(struct inode *inode, unsigned int type)
> struct address_space *mapping = inode->i_mapping;
> pgoff_t start = 0;
> struct folio_batch fbatch;
> - pgoff_t indices[PAGEVEC_SIZE];
> + pgoff_t indices[FOLIO_BATCH_SIZE];
> int ret = 0;
>
> do {
> diff --git a/mm/swap.c b/mm/swap.c
> index 2e517ede6561..78b4aa811fc6 100644
> --- a/mm/swap.c
> +++ b/mm/swap.c
> @@ -1018,7 +1018,7 @@ EXPORT_SYMBOL(folios_put_refs);
> void release_pages(release_pages_arg arg, int nr)
> {
> struct folio_batch fbatch;
> - int refs[PAGEVEC_SIZE];
> + int refs[FOLIO_BATCH_SIZE];
> struct encoded_page **encoded = arg.encoded_pages;
> int i;
>
> diff --git a/mm/swap_state.c b/mm/swap_state.c
> index a0c64db2b275..6313b59d7eab 100644
> --- a/mm/swap_state.c
> +++ b/mm/swap_state.c
> @@ -385,7 +385,7 @@ void free_folio_and_swap_cache(struct folio *folio)
> void free_pages_and_swap_cache(struct encoded_page **pages, int nr)
> {
> struct folio_batch folios;
> - unsigned int refs[PAGEVEC_SIZE];
> + unsigned int refs[FOLIO_BATCH_SIZE];
>
> folio_batch_init(&folios);
> for (int i = 0; i < nr; i++) {
> diff --git a/mm/truncate.c b/mm/truncate.c
> index df0b7a7e6aff..2931d66c16d0 100644
> --- a/mm/truncate.c
> +++ b/mm/truncate.c
> @@ -369,7 +369,7 @@ void truncate_inode_pages_range(struct address_space *mapping,
> pgoff_t start; /* inclusive */
> pgoff_t end; /* exclusive */
> struct folio_batch fbatch;
> - pgoff_t indices[PAGEVEC_SIZE];
> + pgoff_t indices[FOLIO_BATCH_SIZE];
> pgoff_t index;
> int i;
> struct folio *folio;
> @@ -534,7 +534,7 @@ EXPORT_SYMBOL(truncate_inode_pages_final);
> unsigned long mapping_try_invalidate(struct address_space *mapping,
> pgoff_t start, pgoff_t end, unsigned long *nr_failed)
> {
> - pgoff_t indices[PAGEVEC_SIZE];
> + pgoff_t indices[FOLIO_BATCH_SIZE];
> struct folio_batch fbatch;
> pgoff_t index = start;
> unsigned long ret;
> @@ -672,7 +672,7 @@ int folio_unmap_invalidate(struct address_space *mapping, struct folio *folio,
> int invalidate_inode_pages2_range(struct address_space *mapping,
> pgoff_t start, pgoff_t end)
> {
> - pgoff_t indices[PAGEVEC_SIZE];
> + pgoff_t indices[FOLIO_BATCH_SIZE];
> struct folio_batch fbatch;
> pgoff_t index;
> int i;
>
> --
> 2.39.5
>
^ permalink raw reply
* Re: [PATCH v3 01/12] vfs: widen inode hash/lookup functions to u64
From: Jeff Layton @ 2026-03-06 12:03 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Alexander Viro, Christian Brauner, Jan Kara, Steven Rostedt,
Masami Hiramatsu, Mathieu Desnoyers, Dan Williams, Eric Biggers,
Theodore Y. Ts'o, Muchun Song, Oscar Salvador,
David Hildenbrand, David Howells, Paulo Alcantara, Andreas Dilger,
Jan Kara, Jaegeuk Kim, Chao Yu, Trond Myklebust, Anna Schumaker,
Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey,
Steve French, Ronnie Sahlberg, Shyam Prasad N, Bharath SM,
Alexander Aring, Ryusuke Konishi, Viacheslav Dubeyko,
Eric Van Hensbergen, Latchesar Ionkov, Dominique Martinet,
Christian Schoenebeck, David Sterba, Marc Dionne, Ian Kent,
Luis de Bethencourt, Salah Triki, Tigran A. Aivazian,
Ilya Dryomov, Alex Markuze, Jan Harkes, coda, Nicolas Pitre,
Tyler Hicks, Amir Goldstein, John Paul Adrian Glaubitz,
Yangtao Li, Mikulas Patocka, David Woodhouse, Richard Weinberger,
Dave Kleikamp, Konstantin Komarov, Mark Fasheh, Joel Becker,
Joseph Qi, Mike Marshall, Martin Brandenburg, Miklos Szeredi,
Anders Larsen, Zhihao Cheng, Damien Le Moal, Naohiro Aota,
Johannes Thumshirn, John Johansen, Paul Moore, James Morris,
Serge E. Hallyn, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
Eric Snowberg, Fan Wu, Stephen Smalley, Ondrej Mosnacek,
Casey Schaufler, Alex Deucher, Christian König, David Airlie,
Simona Vetter, Sumit Semwal, Eric Dumazet, Kuniyuki Iwashima,
Paolo Abeni, Willem de Bruijn, David S. Miller, Jakub Kicinski,
Simon Horman, Oleg Nesterov, Peter Zijlstra, Ingo Molnar,
Arnaldo Carvalho de Melo, Namhyung Kim, Mark Rutland,
Alexander Shishkin, Jiri Olsa, Ian Rogers, Adrian Hunter,
James Clark, Darrick J. Wong, Martin Schiller, Eric Paris,
Joerg Reuter, Marcel Holtmann, Johan Hedberg,
Luiz Augusto von Dentz, Oliver Hartkopp, Marc Kleine-Budde,
David Ahern, Neal Cardwell, Steffen Klassert, Herbert Xu,
Remi Denis-Courmont, Marcelo Ricardo Leitner, Xin Long,
Magnus Karlsson, Maciej Fijalkowski, Stanislav Fomichev,
Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
John Fastabend, linux-fsdevel, linux-kernel, linux-trace-kernel,
nvdimm, fsverity, linux-mm, netfs, linux-ext4, linux-f2fs-devel,
linux-nfs, linux-cifs, samba-technical, linux-nilfs, v9fs,
linux-afs, autofs, ceph-devel, codalist, ecryptfs, linux-mtd,
jfs-discussion, ntfs3, ocfs2-devel, devel, linux-unionfs,
apparmor, linux-security-module, linux-integrity, selinux,
amd-gfx, dri-devel, linux-media, linaro-mm-sig, netdev,
linux-perf-users, linux-fscrypt, linux-xfs, linux-hams, linux-x25,
audit, linux-bluetooth, linux-can, linux-sctp, bpf
In-Reply-To: <aamSFgXhrORAJLBC@infradead.org>
On Thu, 2026-03-05 at 06:24 -0800, Christoph Hellwig wrote:
> > extern struct inode *ilookup5_nowait(struct super_block *sb,
> > - unsigned long hashval, int (*test)(struct inode *, void *),
> > + u64 hashval, int (*test)(struct inode *, void *),
> > void *data, bool *isnew);
> > -extern struct inode *ilookup5(struct super_block *sb, unsigned long hashval,
> > +extern struct inode *ilookup5(struct super_block *sb, u64 hashval,
> > int (*test)(struct inode *, void *), void *data);
>
> ...
>
> Can you please drop all these pointless externs while you're at it?
>
I was planning to do that, but then Christian merged it!
I'll do a patch on top of this that does this in the range of fs.h that
the patch touches. Christian can throw it on top of the series, and
that shouldn't be too bad for backports.
> Otherwise looks good:
>
> Reviewed-by: Christoph Hellwig <hch@lst.de>
Thanks for the review!
--
Jeff Layton <jlayton@kernel.org>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox