* Re: [RFC v5 6/7] ext4: fast commit: add lock_updates tracepoint
From: Li Chen @ 2026-03-25 6:16 UTC (permalink / raw)
To: Steven Rostedt
Cc: Zhang Yi, Theodore Ts'o, Andreas Dilger, Masami Hiramatsu,
Mathieu Desnoyers, linux-ext4, linux-kernel, linux-trace-kernel,
Vineeth Remanan Pillai
In-Reply-To: <20260317122149.5d07132a@gandalf.local.home>
Hi Steven,
Thank you for your review, and I apologize for my delayed response.
---- On Wed, 18 Mar 2026 00:21:29 +0800 Steven Rostedt <rostedt@goodmis.org> wrote ---
> On Tue, 17 Mar 2026 16:46:21 +0800
> Li Chen <me@linux.beauty> wrote:
>
> > Commit-time fast commit snapshots run under jbd2_journal_lock_updates(),
> > so it is useful to quantify the time spent with updates locked and to
> > understand why snapshotting can fail.
> >
> > Add a new tracepoint, ext4_fc_lock_updates, reporting the time spent in
> > the updates-locked window along with the number of snapshotted inodes
> > and ranges. Record the first snapshot failure reason in a stable snap_err
> > field for tooling.
> >
> > Signed-off-by: Li Chen <me@linux.beauty>
> > ---
> > fs/ext4/ext4.h | 15 ++++++++
> > fs/ext4/fast_commit.c | 71 +++++++++++++++++++++++++++++--------
> > include/trace/events/ext4.h | 61 +++++++++++++++++++++++++++++++
> > 3 files changed, 132 insertions(+), 15 deletions(-)
> >
> > diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> > index 68a64fa0be926..b9e146f3dd9e4 100644
> > --- a/fs/ext4/ext4.h
> > +++ b/fs/ext4/ext4.h
> > @@ -1037,6 +1037,21 @@ enum {
> >
> > struct ext4_fc_inode_snap;
> >
> > +/*
> > + * Snapshot failure reasons for ext4_fc_lock_updates tracepoint.
> > + * Keep these stable for tooling.
> > + */
> > +enum ext4_fc_snap_err {
> > + EXT4_FC_SNAP_ERR_NONE = 0,
> > + EXT4_FC_SNAP_ERR_ES_MISS = 1,
> > + EXT4_FC_SNAP_ERR_ES_DELAYED = 2,
> > + EXT4_FC_SNAP_ERR_ES_OTHER = 3,
> > + EXT4_FC_SNAP_ERR_INODES_CAP = 4,
> > + EXT4_FC_SNAP_ERR_RANGES_CAP = 5,
> > + EXT4_FC_SNAP_ERR_NOMEM = 6,
> > + EXT4_FC_SNAP_ERR_INODE_LOC = 7,
>
> You don't need to explicitly state the assignments, the enum will increment
> them without them.
Agree.
> > +};
> > +
> > /*
> > * fourth extended file system inode data in memory
> > */
> > diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
> > index d1eefee609120..4929e2990b292 100644
> > --- a/fs/ext4/fast_commit.c
> > +++ b/fs/ext4/fast_commit.c
> > @@ -193,6 +193,12 @@ static struct kmem_cache *ext4_fc_range_cachep;
> > #define EXT4_FC_SNAPSHOT_MAX_INODES 1024
> > #define EXT4_FC_SNAPSHOT_MAX_RANGES 2048
> >
> > +static inline void ext4_fc_set_snap_err(int *snap_err, int err)
> > +{
> > + if (snap_err && *snap_err == EXT4_FC_SNAP_ERR_NONE)
> > + *snap_err = err;
> > +}
> > +
> > static void ext4_end_buffer_io_sync(struct buffer_head *bh, int uptodate)
> > {
> > BUFFER_TRACE(bh, "");
> > @@ -983,11 +989,12 @@ static void ext4_fc_free_inode_snap(struct inode *inode)
> > static int ext4_fc_snapshot_inode_data(struct inode *inode,
> > struct list_head *ranges,
> > unsigned int nr_ranges_total,
> > - unsigned int *nr_rangesp)
> > + unsigned int *nr_rangesp,
> > + int *snap_err)
> > {
> > struct ext4_inode_info *ei = EXT4_I(inode);
> > - unsigned int nr_ranges = 0;
> > ext4_lblk_t start_lblk, end_lblk, cur_lblk;
> > + unsigned int nr_ranges = 0;
> >
> > spin_lock(&ei->i_fc_lock);
> > if (ei->i_fc_lblk_len == 0) {
> > @@ -1010,11 +1017,16 @@ static int ext4_fc_snapshot_inode_data(struct inode *inode,
> > struct ext4_fc_range *range;
> > ext4_lblk_t len;
> >
> > - if (!ext4_es_lookup_extent(inode, cur_lblk, NULL, &es, NULL))
> > + if (!ext4_es_lookup_extent(inode, cur_lblk, NULL, &es, NULL)) {
> > + ext4_fc_set_snap_err(snap_err, EXT4_FC_SNAP_ERR_ES_MISS);
> > return -EAGAIN;
> > + }
> >
> > - if (ext4_es_is_delayed(&es))
> > + if (ext4_es_is_delayed(&es)) {
> > + ext4_fc_set_snap_err(snap_err,
> > + EXT4_FC_SNAP_ERR_ES_DELAYED);
> > return -EAGAIN;
> > + }
> >
> > len = es.es_len - (cur_lblk - es.es_lblk);
> > if (len > end_lblk - cur_lblk + 1)
> > @@ -1024,12 +1036,17 @@ static int ext4_fc_snapshot_inode_data(struct inode *inode,
> > continue;
> > }
> >
> > - if (nr_ranges_total + nr_ranges >= EXT4_FC_SNAPSHOT_MAX_RANGES)
> > + if (nr_ranges_total + nr_ranges >= EXT4_FC_SNAPSHOT_MAX_RANGES) {
> > + ext4_fc_set_snap_err(snap_err,
> > + EXT4_FC_SNAP_ERR_RANGES_CAP);
> > return -E2BIG;
> > + }
> >
> > range = kmem_cache_alloc(ext4_fc_range_cachep, GFP_NOFS);
> > - if (!range)
> > + if (!range) {
> > + ext4_fc_set_snap_err(snap_err, EXT4_FC_SNAP_ERR_NOMEM);
> > return -ENOMEM;
> > + }
> > nr_ranges++;
> >
> > range->lblk = cur_lblk;
> > @@ -1054,6 +1071,7 @@ static int ext4_fc_snapshot_inode_data(struct inode *inode,
> > range->len = max;
> > } else {
> > kmem_cache_free(ext4_fc_range_cachep, range);
> > + ext4_fc_set_snap_err(snap_err, EXT4_FC_SNAP_ERR_ES_OTHER);
> > return -EAGAIN;
> > }
> >
> > @@ -1070,7 +1088,7 @@ static int ext4_fc_snapshot_inode_data(struct inode *inode,
> >
> > static int ext4_fc_snapshot_inode(struct inode *inode,
> > unsigned int nr_ranges_total,
> > - unsigned int *nr_rangesp)
> > + unsigned int *nr_rangesp, int *snap_err)
> > {
> > struct ext4_inode_info *ei = EXT4_I(inode);
> > struct ext4_fc_inode_snap *snap;
> > @@ -1082,8 +1100,10 @@ static int ext4_fc_snapshot_inode(struct inode *inode,
> > int alloc_ctx;
> >
> > ret = ext4_get_inode_loc_noio(inode, &iloc);
> > - if (ret)
> > + if (ret) {
> > + ext4_fc_set_snap_err(snap_err, EXT4_FC_SNAP_ERR_INODE_LOC);
> > return ret;
> > + }
> >
> > if (ext4_test_inode_flag(inode, EXT4_INODE_INLINE_DATA))
> > inode_len = EXT4_INODE_SIZE(inode->i_sb);
> > @@ -1092,6 +1112,7 @@ static int ext4_fc_snapshot_inode(struct inode *inode,
> >
> > snap = kmalloc(struct_size(snap, inode_buf, inode_len), GFP_NOFS);
> > if (!snap) {
> > + ext4_fc_set_snap_err(snap_err, EXT4_FC_SNAP_ERR_NOMEM);
> > brelse(iloc.bh);
> > return -ENOMEM;
> > }
> > @@ -1102,7 +1123,7 @@ static int ext4_fc_snapshot_inode(struct inode *inode,
> > brelse(iloc.bh);
> >
> > ret = ext4_fc_snapshot_inode_data(inode, &ranges, nr_ranges_total,
> > - &nr_ranges);
> > + &nr_ranges, snap_err);
> > if (ret) {
> > kfree(snap);
> > ext4_fc_free_ranges(&ranges);
> > @@ -1203,7 +1224,10 @@ static int ext4_fc_alloc_snapshot_inodes(struct super_block *sb,
> > unsigned int *nr_inodesp);
> >
> > static int ext4_fc_snapshot_inodes(journal_t *journal, struct inode **inodes,
> > - unsigned int inodes_size)
> > + unsigned int inodes_size,
> > + unsigned int *nr_inodesp,
> > + unsigned int *nr_rangesp,
> > + int *snap_err)
> > {
> > struct super_block *sb = journal->j_private;
> > struct ext4_sb_info *sbi = EXT4_SB(sb);
> > @@ -1221,6 +1245,8 @@ static int ext4_fc_snapshot_inodes(journal_t *journal, struct inode **inodes,
> > alloc_ctx = ext4_fc_lock(sb);
> > list_for_each_entry(iter, &sbi->s_fc_q[FC_Q_MAIN], i_fc_list) {
> > if (i >= inodes_size) {
> > + ext4_fc_set_snap_err(snap_err,
> > + EXT4_FC_SNAP_ERR_INODES_CAP);
> > ret = -E2BIG;
> > goto unlock;
> > }
> > @@ -1244,6 +1270,8 @@ static int ext4_fc_snapshot_inodes(journal_t *journal, struct inode **inodes,
> > continue;
> >
> > if (i >= inodes_size) {
> > + ext4_fc_set_snap_err(snap_err,
> > + EXT4_FC_SNAP_ERR_INODES_CAP);
> > ret = -E2BIG;
> > goto unlock;
> > }
> > @@ -1268,16 +1296,20 @@ static int ext4_fc_snapshot_inodes(journal_t *journal, struct inode **inodes,
> > unsigned int inode_ranges = 0;
> >
> > ret = ext4_fc_snapshot_inode(inodes[idx], nr_ranges,
> > - &inode_ranges);
> > + &inode_ranges, snap_err);
> > if (ret)
> > break;
> > nr_ranges += inode_ranges;
> > }
> >
> > + if (nr_inodesp)
> > + *nr_inodesp = i;
> > + if (nr_rangesp)
> > + *nr_rangesp = nr_ranges;
> > return ret;
> > }
> >
> > -static int ext4_fc_perform_commit(journal_t *journal)
> > +static int ext4_fc_perform_commit(journal_t *journal, tid_t commit_tid)
> > {
> > struct super_block *sb = journal->j_private;
> > struct ext4_sb_info *sbi = EXT4_SB(sb);
> > @@ -1286,10 +1318,15 @@ static int ext4_fc_perform_commit(journal_t *journal)
> > struct inode *inode;
> > struct inode **inodes;
> > unsigned int inodes_size;
> > + unsigned int snap_inodes = 0;
> > + unsigned int snap_ranges = 0;
> > + int snap_err = EXT4_FC_SNAP_ERR_NONE;
> > struct blk_plug plug;
> > int ret = 0;
> > u32 crc = 0;
> > int alloc_ctx;
> > + ktime_t lock_start;
> > + u64 locked_ns;
> >
> > /*
> > * Step 1: Mark all inodes on s_fc_q[MAIN] with
> > @@ -1337,13 +1374,13 @@ static int ext4_fc_perform_commit(journal_t *journal)
> > if (ret)
> > return ret;
> >
> > -
> > ret = ext4_fc_alloc_snapshot_inodes(sb, &inodes, &inodes_size);
> > if (ret)
> > return ret;
> >
> > /* Step 4: Mark all inodes as being committed. */
> > jbd2_journal_lock_updates(journal);
> > + lock_start = ktime_get();
> > /*
> > * The journal is now locked. No more handles can start and all the
> > * previous handles are now drained. Snapshotting happens in this
> > @@ -1357,8 +1394,12 @@ static int ext4_fc_perform_commit(journal_t *journal)
> > }
> > ext4_fc_unlock(sb, alloc_ctx);
> >
> > - ret = ext4_fc_snapshot_inodes(journal, inodes, inodes_size);
> > + ret = ext4_fc_snapshot_inodes(journal, inodes, inodes_size,
> > + &snap_inodes, &snap_ranges, &snap_err);
> > jbd2_journal_unlock_updates(journal);
> > + locked_ns = ktime_to_ns(ktime_sub(ktime_get(), lock_start));
>
> If locked_ns is only used for the tracepoint, it should either be
> calculated in the tracepoint, or add:
>
> if (trace_ext4_fc_lock_updates_enabled()) {
> locked_ns = ktime_to_ns(ktime_sub(ktime_get(), lock_start));
Good catch!
> > + trace_ext4_fc_lock_updates(sb, commit_tid, locked_ns, snap_inodes,
> > + snap_ranges, ret, snap_err);
>
> }
>
> Note, we are going to also add a code to call the tracepoint directly, to
> remove the double static_branch.
>
> https://lore.kernel.org/all/20260312150523.2054552-1-vineeth@bitbyteword.org/
>
> But that code is still being worked on so you don't need to worry about it
> at the moment.
Thank you! I will monitor this patch set and incorporate it into future versions if possible.
>
> > kvfree(inodes);
> > if (ret)
> > return ret;
> > @@ -1563,7 +1604,7 @@ int ext4_fc_commit(journal_t *journal, tid_t commit_tid)
> > journal_ioprio = EXT4_DEF_JOURNAL_IOPRIO;
> > set_task_ioprio(current, journal_ioprio);
> > fc_bufs_before = (sbi->s_fc_bytes + bsize - 1) / bsize;
> > - ret = ext4_fc_perform_commit(journal);
> > + ret = ext4_fc_perform_commit(journal, commit_tid);
> > if (ret < 0) {
> > if (ret == -EAGAIN || ret == -E2BIG || ret == -ECANCELED)
> > status = EXT4_FC_STATUS_INELIGIBLE;
> > diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
> > index fd76d14c2776e..dc084f39b74ad 100644
> > --- a/include/trace/events/ext4.h
> > +++ b/include/trace/events/ext4.h
> > @@ -104,6 +104,26 @@ TRACE_DEFINE_ENUM(EXT4_FC_REASON_INODE_JOURNAL_DATA);
> > TRACE_DEFINE_ENUM(EXT4_FC_REASON_ENCRYPTED_FILENAME);
> > TRACE_DEFINE_ENUM(EXT4_FC_REASON_MAX);
> >
> > +#undef EM
> > +#undef EMe
> > +#define EM(a) TRACE_DEFINE_ENUM(EXT4_FC_SNAP_ERR_##a);
> > +#define EMe(a) TRACE_DEFINE_ENUM(EXT4_FC_SNAP_ERR_##a);
> > +
> > +#define TRACE_SNAP_ERR \
> > + EM(NONE) \
> > + EM(ES_MISS) \
> > + EM(ES_DELAYED) \
> > + EM(ES_OTHER) \
> > + EM(INODES_CAP) \
> > + EM(RANGES_CAP) \
> > + EM(NOMEM) \
> > + EMe(INODE_LOC)
> > +
> > +TRACE_SNAP_ERR
> > +
> > +#undef EM
> > +#undef EMe
> > +
> > #define show_fc_reason(reason) \
> > __print_symbolic(reason, \
> > { EXT4_FC_REASON_XATTR, "XATTR"}, \
> > @@ -2812,6 +2832,47 @@ TRACE_EVENT(ext4_fc_commit_stop,
> > __entry->num_fc_ineligible, __entry->nblks_agg, __entry->tid)
> > );
> >
> > +#define EM(a) { EXT4_FC_SNAP_ERR_##a, #a },
> > +#define EMe(a) { EXT4_FC_SNAP_ERR_##a, #a }
> > +
> > +TRACE_EVENT(ext4_fc_lock_updates,
> > + TP_PROTO(struct super_block *sb, tid_t commit_tid, u64 locked_ns,
> > + unsigned int nr_inodes, unsigned int nr_ranges, int err,
> > + int snap_err),
> > +
> > + TP_ARGS(sb, commit_tid, locked_ns, nr_inodes, nr_ranges, err, snap_err),
> > +
> > + TP_STRUCT__entry(/* entry */
> > + __field(dev_t, dev)
> > + __field(tid_t, tid)
> > + __field(u64, locked_ns)
> > + __field(unsigned int, nr_inodes)
> > + __field(unsigned int, nr_ranges)
> > + __field(int, err)
> > + __field(int, snap_err)
> > + ),
> > +
> > + TP_fast_assign(/* assign */
> > + __entry->dev = sb->s_dev;
> > + __entry->tid = commit_tid;
> > + __entry->locked_ns = locked_ns;
> > + __entry->nr_inodes = nr_inodes;
> > + __entry->nr_ranges = nr_ranges;
> > + __entry->err = err;
> > + __entry->snap_err = snap_err;
> > + ),
> > +
> > + TP_printk("dev %d,%d tid %u locked_ns %llu nr_inodes %u nr_ranges %u err %d snap_err %s",
> > + MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid,
> > + __entry->locked_ns, __entry->nr_inodes, __entry->nr_ranges,
> > + __entry->err, __print_symbolic(__entry->snap_err,
> > + TRACE_SNAP_ERR))
> > +);
> > +
> > +#undef EM
> > +#undef EMe
> > +#undef TRACE_SNAP_ERR
> > +
> > #define FC_REASON_NAME_STAT(reason) \
> > show_fc_reason(reason), \
> > __entry->fc_ineligible_rc[reason]
>
>
Regards,
Li
^ permalink raw reply
* [RFC] Proposal: provenance_time (ptime) — a settable timestamp for cross-filesystem migration
From: Sean Smith @ 2026-03-25 4:26 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-ext4, tytso, dsterba, david, brauner, osandov
[Email draft produced by AI agent. Reviewed, revised, and submitted by
Sean Smith.]
Hello,
I am writing as a user whose work is directly harmed by the absence
of a settable file creation timestamp in the Linux kernel. I am not a
kernel developer, but I believe this use case may help inform the
ongoing design discussion about btime semantics.
BACKGROUND
I am a disabled Medicaid recipient pursuing pro se civil rights
litigation against Tennessee's Medicaid program. I am building
a suite of AI tools for my litigation. These tools will include
an agentic document management system on Linux
(EndeavourOS/Arch).
My current workflow requires migrating terabytes of case law,
evidence, research, AI Harness project files, and other data
from NTFS (Windows) to Btrfs (Linux) and vice versa. These
documents span years of case history — some created as far
back as 2014.
I've used Windows exclusively for the past 20 years, and so I
have much to migrate. I am abandoning Windows because it has
repeatedly gotten in the way as I work in OpenCode and with
other AI tools. Linux offers a clearer path to using AI to
build a user-first future. My litigation relies upon my AI
agents and I developing effective AI tools and data systems.
This reliance makes the nonsense that has been going on with
Windows 11 an existential threat. People with disabilities
should not have to ask permission from the legal community or
corporations to have human rights; with an open-source suite
of AI litigation tools, they won't have to.
I provide the above context so that you may better understand
the importance of adopting my modest proposal.
When files are copied from NTFS to Btrfs, every file's creation
date is reset to the moment of the copy. The kernel provides no
syscall to restore the original creation timestamp. The result
is that files created in 2019 after transfer will report being
created in 2026.
For litigation evidence, file creation timestamps are provenance
metadata. They establish when a document first came into existence
as a digital file. Losing this metadata during a routine filesystem
migration is a forensic integrity failure — it destroys the timeline
that courts, investigators, and opposing counsel may rely on.
For humans and for AI agents, the loss of this metadata limits
how well they can navigate and retrieve from the corpus of
files.
THE PROBLEM AS I UNDERSTAND IT
Omar Sandoval submitted working patches in February 2019 (AT_UTIME_BTIME
for utimensat). They were not merged due to disagreement about whether
btime should be mutable.
The core dispute, as I understand it from the mailing list archives:
- Dave Chinner (XFS): btime is forensic metadata — the moment the
inode was allocated on this specific filesystem. Allowing it to
be changed destroys its value for filesystem forensic analysis.
- Ted Ts'o (ext4, March 2025): Proposed distinguishing "btime"
(forensic, immutable) from "crtime" (settable, for migration
and Windows compatibility).
- David Sterba (Btrfs): Acknowledged the need, has a WIP for a
Btrfs-specific ioctl to set otime. Noted btrfs send/receive
protocol v2 transmits otime but cannot write it.
Both sides have legitimate points. The impasse exists because one
field is being asked to serve two incompatible purposes.
PROPOSAL: provenance_time (ptime)
I propose a new timestamp concept: provenance_time, abbreviated ptime.
ptime is distinct from btime:
btime = "when was this inode born on THIS filesystem"
Forensic. Immutable. Set by the kernel at inode creation.
Valuable for filesystem forensic analysis and intrusion
detection. Dave Chinner's use case is preserved.
ptime = "when did this file's content first come into existence,
on any filesystem, as reported by the earliest known source"
User-settable. Designed for cross-filesystem migration,
backup/restore, and provenance tracking. Travels with
the file across copies.
This is similar to Ted Ts'o's btime/crtime split, but with clearer
semantics:
- "crtime" (creation time) is easily confused with "ctime" (change
time) and with btime itself. The word "creation" is ambiguous —
creation of the inode, or creation of the content?
- "ptime" (provenance time) is unambiguous. It explicitly
communicates: this timestamp records provenance — where and
when this file originated. It makes no claim about the local
inode's birth. It does not conflict with btime's forensic
meaning.
ptime fits naturally into the existing timestamp schema:
atime - access time
mtime - modification time
ctime - change time (metadata)
btime - birth time (inode, forensic, immutable)
ptime - provenance time (origin, settable, travels with file)
IMPLEMENTATION NOTES (from a user's perspective)
- ptime should be settable via utimensat() or a new dedicated
syscall, with appropriate privilege requirements (CAP_FOWNER
or similar).
- Filesystems that store a creation timestamp (ext4, btrfs, xfs,
ntfs, exfat) could optionally support ptime using an additional
inode field, or by allowing the existing crtime/otime field to
serve as ptime when a filesystem-specific flag is set (as Ted
suggested for ext4).
- Standard tools (cp, rsync, tar) could be updated to read and
write ptime, finally resolving the long-standing inability to
preserve creation timestamps during file migration on Linux.
- NTFS-originated filesystems could map their creation time to
ptime, making Windows-to-Linux migration seamless.
WHO THIS AFFECTS
This is not a niche concern. In researching this issue, I found:
- Backup/restore users (Duplicati, rsync, rclone all lose btime)
- Windows-to-Linux migrators frustrated by silent metadata loss
- Digital forensics professionals whose MACB timelines break
- Data archivists and media librarians
- Users with memory/accessibility needs who rely on creation
dates to track personal document timelines
- A developer on StackOverflow needing to process 1.3 million
files with preserved timestamps — no solution available
- A 7zip developer filing an issue (Feb 2026) documenting that
Linux extraction cannot preserve creation times
The common thread across these use cases is that the current
impasse — where btime's forensic semantics block any settable
timestamp — produces worse forensic outcomes than providing a
clearly-separated settable field would. The provenance data is
being destroyed precisely because there is no sanctioned place
to put it.
ptime resolves this by giving that data a home without
compromising btime's forensic meaning.
Thank you for considering this proposal.
Sincerely,
Sean Smith
DefendTheDisabled.org
^ permalink raw reply
* Re: [f2fs-dev] [GIT PULL] fsverity updates for 6.3
From: patchwork-bot+f2fs @ 2026-03-24 17:32 UTC (permalink / raw)
To: Eric Biggers
Cc: torvalds, fsverity, tytso, linux-kernel, linux-f2fs-devel,
linux-fscrypt, linux-fsdevel, linux-ext4, linux-btrfs
In-Reply-To: <Y/KLHT3zaA0QFhVJ@sol.localdomain>
Hello:
This pull request was applied to jaegeuk/f2fs.git (dev)
by Linus Torvalds <torvalds@linux-foundation.org>:
On Sun, 19 Feb 2023 12:48:29 -0800 you wrote:
> The following changes since commit 88603b6dc419445847923fcb7fe5080067a30f98:
>
> Linux 6.2-rc2 (2023-01-01 13:53:16 -0800)
>
> are available in the Git repository at:
>
> https://git.kernel.org/pub/scm/fs/fsverity/linux.git tags/fsverity-for-linus
>
> [...]
Here is the summary with links:
- [f2fs-dev,GIT,PULL] fsverity updates for 6.3
https://git.kernel.org/jaegeuk/f2fs/c/5ee8dbf54602
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH 12/41] fs: Drop sync_mapping_buffers() from __generic_file_fsync()
From: Christoph Hellwig @ 2026-03-24 15:54 UTC (permalink / raw)
To: Jan Kara
Cc: Christoph Hellwig, linux-fsdevel, linux-block, 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: <rsftk7gdlamfryksv63vhmewdi6etvvfyi6as5m2zs75ctvzkq@fnoiwumyfdsv>
On Tue, Mar 24, 2026 at 02:36:53PM +0100, Jan Kara wrote:
> Leaving the two implementations separate certainly works for me as well
> (that's why I've put that patch to the end because I've expected some
> discussions around it :)). Just the amount of common trivial calls you need
> to do (fdatawrite(), sync_inode_metadata(),
> file_check_and_advance_wb_err(), blkdev_issue_flush()) looked high enough
> to me to be worth merging the implementations. But I don't feel strongly
> either way.
I don't really feel either way, and I really should not micro-manage
the series either. So go for what you think works best. The important
part is to have the fsync changes early and to avoid hardcoding
buffer_head knowledge into libfs.c.
^ permalink raw reply
* Re: [bug report] e2fsprogs 1.47.4: mke2fs creates oversized orphan file for 1k blocksize (breaks mount)
From: Theodore Tso @ 2026-03-24 14:17 UTC (permalink / raw)
To: Baokun Li; +Cc: Yi Zhang, linux-ext4, linux-block, Shinichiro Kawasaki
In-Reply-To: <d7a82737-a293-4e72-b5e4-1c8492d06e8c@linux.alibaba.com>
I will be releasing an updated e2fsprogs 1.47.5 in the next day or two
to address this issue. Our apologies for the inconvenience.
- Ted
^ permalink raw reply
* Re: [PATCH 09/10] ext4: move zero partial block range functions out of active handle
From: Jan Kara @ 2026-03-24 13:56 UTC (permalink / raw)
To: Zhang Yi
Cc: Jan Kara, linux-ext4, linux-fsdevel, linux-kernel, tytso,
adilger.kernel, ojaswin, ritesh.list, libaokun, yi.zhang,
yizhang089, yangerkun, yukuai
In-Reply-To: <7fa8415e-199f-4e31-8b07-08f0f73d5b99@huaweicloud.com>
On Tue 24-03-26 11:10:13, Zhang Yi wrote:
> On 3/24/2026 4:17 AM, Jan Kara wrote:
> > On Tue 10-03-26 09:41:00, Zhang Yi wrote:
> >> From: Zhang Yi <yi.zhang@huawei.com>
> >>
> >> Move ext4_block_zero_eof() and ext4_zero_partial_blocks() calls out of
> >> the active handle context, making them independent operations. This is
> >> safe because it still ensures data is updated before metadata for
> >> data=ordered mode and data=journal mode because we still zero data and
> >> ordering data before modifying the metadata.
> >>
> >> This change is required for iomap infrastructure conversion because the
> >> iomap buffered I/O path does not use the same journal infrastructure for
> >> partial block zeroing. The lock ordering of folio lock and starting
> >> transactions is "folio lock -> transaction start", which is opposite of
> >> the current path. Therefore, zeroing partial blocks cannot be performed
> >> under the active handle.
> >>
> >> Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
> >
> > So in this patch you also move ext4_zero_partial_blocks() before the
> > transaction start in ext4_zero_range() and ext4_punch_hole(). However
> > cannot these operations in theory fail with error such as EDQUOT or ENOSPC
> > when they need to grow the extent tree as a result of the operation? In
> > that case we'd return such error but partial blocks are already zeroed out
> > which is a problem...
>
> Thank you for review this patch set!
>
> Let me see, I believe you are referring to the cases where
> ext4_xxx_remove_space() in ext4_punch_hole() and
> ext4_alloc_file_blocks() in ext4_zero_range() return normal error codes
> such as EDQUOT or ENOSPC.
Yes, I was referring to those.
> In ext4_punch_hole(), we first zero out the partial blocks at the
> beginning and end of the punch range, and then release the aligned
> blocks in the middle. If errors occur during the middle of the
> hole-punching operation, there will left some data in the middle of the
> punch range, this is weird. Conversely, if the zeroization is performed
> in sequence, the result is zeroization at the front and the retention of
> valid data at the rear, which is acceptable. right? Besides, this
> problem seems not occur in ext4_zero_range() because
> ext4_zero_partial_blocks() is still called after
> ext4_alloc_file_blocks() after this patch.
Indeed, I've got confused. Your patch is fine. Feel free to add:
Reviewed-by: Jan Kara <jack@suse.cz>
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH v5 1/2] jbd2: gracefully abort instead of panicking on unlocked buffer
From: Jan Kara @ 2026-03-24 13:52 UTC (permalink / raw)
To: Milos Nikic
Cc: jack, tytso, linux-ext4, linux-kernel, Zhang Yi, Andreas Dilger
In-Reply-To: <CAOeJtk8hrcM6NR73Xo5++aU_ZXyM8GvN7U44iA-rJdp0evhrpQ@mail.gmail.com>
Hello!
On Mon 23-03-26 14:50:00, Milos Nikic wrote:
> Just sending a gentle ping on this v5 series from March 4th.
> It looks like both patches have collected Reviewed-by tags from Jan,
> Andreas and Zhang.
>
> Please let me know if there is anything else you need from my side, or
> if this is good to be queued up in the ext4 tree for the next merge
> window.
Ted Tso is generally picking jbd2 patches. Since this is a cleanup, I
expect him to pick up this patch for the next merge window - i.e., in a
week or two :)
Honza
>
> Thanks, Milos
>
> On Wed, Mar 4, 2026 at 9:20 AM Milos Nikic <nikic.milos@gmail.com> wrote:
> >
> > In jbd2_journal_get_create_access(), if the caller passes an unlocked
> > buffer, the code currently triggers a fatal J_ASSERT.
> >
> > While an unlocked buffer here is a clear API violation and a bug in the
> > caller, crashing the entire system is an overly severe response. It brings
> > down the whole machine for a localized filesystem inconsistency.
> >
> > Replace the J_ASSERT with a WARN_ON_ONCE to capture the offending caller's
> > stack trace, and return an error (-EINVAL). This allows the journal to
> > gracefully abort the transaction, protecting data integrity without
> > causing a kernel panic.
> >
> > Signed-off-by: Milos Nikic <nikic.milos@gmail.com>
> > Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
> > Reviewed-by: Jan Kara <jack@suse.cz>
> > Reviewed-by: Andreas Dilger <adilger@dilger.ca>
> > ---
> > fs/jbd2/transaction.c | 7 ++++++-
> > 1 file changed, 6 insertions(+), 1 deletion(-)
> >
> > diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
> > index dca4b5d8aaaa..04d17a5f2a82 100644
> > --- a/fs/jbd2/transaction.c
> > +++ b/fs/jbd2/transaction.c
> > @@ -1302,7 +1302,12 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)
> > goto out;
> > }
> >
> > - J_ASSERT_JH(jh, buffer_locked(jh2bh(jh)));
> > + if (WARN_ON_ONCE(!buffer_locked(jh2bh(jh)))) {
> > + err = -EINVAL;
> > + spin_unlock(&jh->b_state_lock);
> > + jbd2_journal_abort(journal, err);
> > + goto out;
> > + }
> >
> > if (jh->b_transaction == NULL) {
> > /*
> > --
> > 2.53.0
> >
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH 12/41] fs: Drop sync_mapping_buffers() from __generic_file_fsync()
From: Jan Kara @ 2026-03-24 13:36 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jan Kara, linux-fsdevel, linux-block, 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: <acKO3NRw852FdGUO@infradead.org>
On Tue 24-03-26 06:17:16, Christoph Hellwig wrote:
> On Tue, Mar 24, 2026 at 01:34:57PM +0100, Jan Kara wrote:
> > I'm fine with simple_fsync() name for the helper with the trivial behavior
> > of writing out the mapping and the inode. Code wise this will look somewhat
> > different given what you've suggested for the last patch.
>
> Yeah, the pitfalls of going sequentially through the series :)
>
> But sketching this out I'm not even sure all this makes sense any more.
> Maybe instad of the allback we should just have a helper for checking the
> inode state like:
>
> static inline bool inode_need_fsync(struct inode *inode, bool datasync)
> {
> enum inode_state_flags_enum state = inode_state_read_once(inode);
>
> if (!(state & I_DIRTY_ALL))
> return false;
> if (datasync && !(state & I_DIRTY_DATASYNC))
> retun false;
> return true;
> }
>
> and otherwise just open code the calls int the two implementations
> without any callbacks, as it feels cleaner to avoid the entanglement.
Leaving the two implementations separate certainly works for me as well
(that's why I've put that patch to the end because I've expected some
discussions around it :)). Just the amount of common trivial calls you need
to do (fdatawrite(), sync_inode_metadata(),
file_check_and_advance_wb_err(), blkdev_issue_flush()) looked high enough
to me to be worth merging the implementations. But I don't feel strongly
either way.
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH 41/41] fs: Unify generic_file_fsync() with mmb methods
From: Jan Kara @ 2026-03-24 13:28 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jan Kara, linux-fsdevel, linux-block, 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: <acInjoDTJAz62eUp@infradead.org>
On Mon 23-03-26 22:56:30, Christoph Hellwig wrote:
> On Fri, Mar 20, 2026 at 02:41:36PM +0100, Jan Kara wrote:
> > Taking inode lock when writing out the inode seems pointless in
> > particular because there are lots of places (most notably sync(2) path)
> > that don't do that so hardly anything can depend on it.
>
> This is really something that needs to stand out clearly for bisecting
> and documentation. I.e. make this a patch on its own and preferably
> before all the other refactoring that already is affected by moving
> between the implementations at the beginning of the series.
>
> > So let's remove __generic_file_fsync() and use
> > generic_mmb_fsync_noflush() instead to reduce code duplication. Arguably
> > this leaks a bit of buffer_head knowledge into fs/libfs.c which is not
> > great but avoiding the duplication seems worth it.
>
> You could just pass a callback to the generic version. The cost of an
> indirect call should not matter compared to the rest of the fsync code.
> That would also be a nice thing before all the renaming, as that means
> we could add the version with the callback first to unify the
> implementations and then the file systems are switched away from
> the buffers fsync variant to explicitly pass a callback, or to not
> pass a callback when they currently get the default one.
OK, makes sense. I can put the patch removing inode_lock from
__generic_file_fsync() at the place in the series where we start
dealing with fsync handlers. Then I'd introduce fsync variant with the
callback and then convert filesystems. As I was thinking about it, it would
be natural for the callback to be called sync_metadata and handle
writeout of the metadata including the inode. That would actually simplify
life in the following series I wanted to write which will make sure that
fsync properly writes out & waits for the buffer head containing the inode
(currently if background flush work happens to write inode first, buffer
head is not written to the backing device during fsync). And if the
callback isn't provided, we'd just write out the inode. That sounds
reasonable to me.
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH 12/41] fs: Drop sync_mapping_buffers() from __generic_file_fsync()
From: Christoph Hellwig @ 2026-03-24 13:17 UTC (permalink / raw)
To: Jan Kara
Cc: Christoph Hellwig, linux-fsdevel, linux-block, 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: <ezdm6d34jqdrcohk7o6wycxvvlgtf6aqenwx5ffr3plfagdbzi@gibz7xwr6yhr>
On Tue, Mar 24, 2026 at 01:34:57PM +0100, Jan Kara wrote:
> I'm fine with simple_fsync() name for the helper with the trivial behavior
> of writing out the mapping and the inode. Code wise this will look somewhat
> different given what you've suggested for the last patch.
Yeah, the pitfalls of going sequentially through the series :)
But sketching this out I'm not even sure all this makes sense any more.
Maybe instad of the allback we should just have a helper for checking the
inode state like:
static inline bool inode_need_fsync(struct inode *inode, bool datasync)
{
enum inode_state_flags_enum state = inode_state_read_once(inode);
if (!(state & I_DIRTY_ALL))
return false;
if (datasync && !(state & I_DIRTY_DATASYNC))
retun false;
return true;
}
and otherwise just open code the calls int the two implementations
without any callbacks, as it feels cleaner to avoid the entanglement.
This helper might also be useful for other fs-specific implementations
later on.
^ permalink raw reply
* Re: [PATCH 20/41] fs: Ignore inode metadata buffers in inode_lru_isolate()
From: Jan Kara @ 2026-03-24 12:51 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jan Kara, linux-fsdevel, linux-block, 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: <acIkOmat4Y_M2SUC@infradead.org>
On Mon 23-03-26 22:42:18, Christoph Hellwig wrote:
> On Fri, Mar 20, 2026 at 02:41:15PM +0100, Jan Kara wrote:
> > There are only a few filesystems that use generic tracking of inode
> > metadata buffer heads. As such it is mostly pointless to verify such
> > attached buffer heads during inode reclaim. Drop the handling from
> > inode_lru_isolate().
>
> But the code isn't just verifying (which to me implies debug code),
> but doing actual work to remove the buffers. This does look like a
> behavior change to me, buf it is not due to previous patches or
> because it was dead code, it would help greatly to explain that here.
Right, I've rewritten the changelog to explain things better:
There are only a few filesystems that use generic tracking of inode
metadata buffer heads. As such the logic to reclaim tracked metadata
buffer heads in inode_lru_isolate() doesn't bring a benefit big enough
to justify intertwining of inode reclaim and metadata buffer head
tracking. Just treat tracked metadata buffer heads as any other metadata
filesystem has to properly clean up on inode eviction and stop handling
it in inode_lru_isolate(). As a result filesystems using generic
tracking of metadata buffer heads may now see dirty metadata buffers in
their .evict methods more often which can slow down inode reclaim but
given these filesystems aren't used in performance demanding setups we
should be fine.
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH 12/41] fs: Drop sync_mapping_buffers() from __generic_file_fsync()
From: Jan Kara @ 2026-03-24 12:34 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jan Kara, linux-fsdevel, linux-block, 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: <acIjxUzWFstarlwv@infradead.org>
On Mon 23-03-26 22:40:21, Christoph Hellwig wrote:
> On Fri, Mar 20, 2026 at 02:41:07PM +0100, Jan Kara wrote:
> > No filesystem calling __generic_file_fsync() uses metadata bh tracking.
> > Drop sync_mapping_buffers() call from __generic_file_fsync() as it's
> > pointless now.
>
> Given how much this changed, maybe rename it to simple_fsync now to
> provide an obvious breakage for anyone trying to use it? That name
> is probably also better as it's not all that generic.
I'm fine with simple_fsync() name for the helper with the trivial behavior
of writing out the mapping and the inode. Code wise this will look somewhat
different given what you've suggested for the last patch.
Honza
>
> >
> > Signed-off-by: Jan Kara <jack@suse.cz>
> > ---
> > fs/libfs.c | 8 ++------
> > 1 file changed, 2 insertions(+), 6 deletions(-)
> >
> > diff --git a/fs/libfs.c b/fs/libfs.c
> > index 74134ba2e8d1..548e119668df 100644
> > --- a/fs/libfs.c
> > +++ b/fs/libfs.c
> > @@ -1555,23 +1555,19 @@ int __generic_file_fsync(struct file *file, loff_t start, loff_t end,
> > {
> > struct inode *inode = file->f_mapping->host;
> > int err;
> > - int ret;
> > + int ret = 0;
> >
> > err = file_write_and_wait_range(file, start, end);
> > if (err)
> > return err;
> >
> > inode_lock(inode);
> > - ret = sync_mapping_buffers(inode->i_mapping);
> > if (!(inode_state_read_once(inode) & I_DIRTY_ALL))
> > goto out;
> > if (datasync && !(inode_state_read_once(inode) & I_DIRTY_DATASYNC))
> > goto out;
> >
> > - err = sync_inode_metadata(inode, 1);
> > - if (ret == 0)
> > - ret = err;
> > -
> > + ret = sync_inode_metadata(inode, 1);
> > out:
> > inode_unlock(inode);
> > /* check and advance again to catch errors after syncing out buffers */
> > --
> > 2.51.0
> >
> >
> ---end quoted text---
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH 08/41] udf: Switch to generic_buffers_fsync()
From: Jan Kara @ 2026-03-24 12:24 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Jan Kara, linux-fsdevel, linux-block, 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: <acIjQVRICiVBndVr@infradead.org>
On Mon 23-03-26 22:38:09, Christoph Hellwig wrote:
> On Fri, Mar 20, 2026 at 02:41:03PM +0100, Jan Kara wrote:
> > UDF uses metadata bh list attached to inode. Switch it to
> > generic_buffers_fsync() instead of generic_file_fsync().
>
> Can you explain this a bit more? Right now the only difference between
> generic_file_fsync and generic_buffers_fsync is that the former takes
> i_rwsem and the other does not. I'd expect the commit log to explain
> why dropping the lock is safe and desirable.
>
> Same for the other similar patches.
Yeah, I was a bit sloppy with the explanation here and put it only into the
last patch 41. If we move that patch early in the series, explanations
won't be needed which is a good thing I guess.
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [bug report] e2fsprogs 1.47.4: mke2fs creates oversized orphan file for 1k blocksize (breaks mount)
From: Baokun Li @ 2026-03-24 11:00 UTC (permalink / raw)
To: Yi Zhang
Cc: linux-ext4, linux-block, Shinichiro Kawasaki, Theodore Ts'o,
libaokun
In-Reply-To: <CAHj4cs8o5HExeOX2YCYrWH86iz4xwL52YtsJNV2YOyDPbyEffg@mail.gmail.com>
Hi,
On 3/24/26 8:54 AM, Yi Zhang wrote:
> Hi
>
> I'm reporting a regression in e2fsprogs-1.47.4 where mke2fs creates an
> orphan file[2] that exceeds the kernel's maximum allowed size for
> filesystems with a 1KB block size[1]. This causes subsequent mount
> operations to fail.
>
> This issue is currently causing blktests loop/007 to fail on latest
> Fedora. Downgrading to e2fsprogs 1.47.3 resolves the issue.
> And revert [3] fixed this issue, here is the reproducer[4].
>
> [1]
> Kernel limit for 1KB blocks: 512 * 1024 = 512 KB
> [2]
> Orphan file created by e2fsprogs 1.47.4: 1024 KB (1 MB)
> [3]
> 6f03c698 libext2fs: fix orphan file size > kernel limit with large blocksize
Refer to the discussion in [a], you can revert [3] and apply [b] to fix
this issue.
[a]:
https://lore.kernel.org/linux-ext4/d4d64000-6b55-449e-83bb-be438aaa5146@linux.alibaba.com/
[b]:
https://lore.kernel.org/linux-ext4/20251120135514.3013973-1-libaokun@huaweicloud.com/
Cheers,
Baokun
> [4]
> # dd if=/dev/zero of=test.img bs=1M count=1024
> # mkfs.ext4 -b 1024 test.img -F
> mke2fs 1.47.4 (6-Mar-2025)
> test.img contains a ext4 file system
> last mounted on Mon Mar 23 20:32:40 2026
> Discarding device blocks: done
> Creating filesystem with 1048576 1k blocks and 65536 inodes
> Filesystem UUID: 16683060-ed47-46cc-a040-c5e049785831
> Superblock backups stored on blocks:
> 8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409, 663553,
> 1024001
>
> Allocating group tables: done
> Writing inode tables: done
> Creating journal (16384 blocks): done
> Writing superblocks and filesystem accounting information: done
> # mount test.img /mnt
> mount: /mnt: fsconfig() failed: Structure needs cleaning.
> dmesg(1) may have more information after failed mount system call.
>
> # dmesg
> [ 5985.339637] loop0: detected capacity change from 0 to 2097152
> [ 5985.347473] EXT4-fs (loop0): orphan file too big: 1048576
> [ 5985.352939] EXT4-fs (loop0): mount failed
>
>
^ permalink raw reply
* [PATCH] doc: correct date in release notes
From: jinzhiguang @ 2026-03-24 9:12 UTC (permalink / raw)
To: tytso; +Cc: linux-ext4, jinzhiguang
Correct the date in the RelNotes/v1.47.4.txt from 2025 to 2026.
Signed-off-by: jinzhiguang <jinzhiguang@kylinos.cn>
---
doc/RelNotes/v1.47.4.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/doc/RelNotes/v1.47.4.txt b/doc/RelNotes/v1.47.4.txt
index 6e7e1c4c..6c78a2b2 100644
--- a/doc/RelNotes/v1.47.4.txt
+++ b/doc/RelNotes/v1.47.4.txt
@@ -1,4 +1,4 @@
-E2fsprogs 1.47.4 (March 6, 2025)
+E2fsprogs 1.47.4 (March 6, 2026)
================================
Updates/Fixes since v1.47.3:
--
2.53.0.windows.2
^ permalink raw reply related
* Re: [REGRESSION] fs/overlayfs/ext4: Severe jbd2 lock contention and journal starvation on concurrent copy-up (v6.6 -> v6.12)
From: Chenglong Tang @ 2026-03-24 8:28 UTC (permalink / raw)
To: Amir Goldstein
Cc: linux-unionfs, linux-ext4, linux-fsdevel, linux-kernel,
regressions, jack, Jan Kara, miklos, tytso, adilger.kernel, viro,
brauner, Kevin Berry, Robert Kolchmeyer, Deepa Dinamani, He Gao,
Fei Lv
In-Reply-To: <CAOQ4uxjuAfCJXGRchDf-7d+uCS+8=Du_Y8OzgX15w4-fOR_oHQ@mail.gmail.com>
Hi Amir,
You absolutely nailed it. Thank you.
Regarding the test, you are correct: the rm -rf happens in the Docker
build phase, so the timed test purely measures the burst creation of
the new __pycache__ directories and .pyc files on a clean slate.
I checked our environment, and metacopy is indeed disabled by default.
We generally keep it disabled for broader compatibility with various
container runtimes and user-namespace tooling that expect a full
copy-up.
To test your theory, I dynamically enabled it (echo Y >
/sys/module/overlay/parameters/metacopy) and re-ran the 20-container
concurrent test. The journal lock contention completely vanished, and
the times dropped from ~27 seconds back down to ~4.3 seconds, fully
restoring the 6.6 performance.
I am currently building a custom COS image with your suggested 1-line
patch (ctx.metadata_fsync = 0 && ...) to verify it on our 96-core test
rig. I highly expect it to be the root cause, and I will report back
with the benchmark results as soon as the build finishes.
Since we generally keep metacopy disabled for broader compatibility
with container tooling, your proposed patch to make metadata_fsync
opt-in would be a good fix for us.
Thanks again for the pointers!
Best,
Chenglong
On Tue, Mar 24, 2026 at 12:53 AM Amir Goldstein <amir73il@gmail.com> wrote:
>
> On Mon, Mar 23, 2026 at 11:03 PM Chenglong Tang
> <chenglongtang@google.com> wrote:
> >
> > Hi all,
>
> Hi Chenglong,
>
> >
> > We are tracking a severe performance regression in Google's
> > Container-Optimized OS (COS) that appeared when moving from the 6.6
> > LTS kernel to the 6.12 LTS kernel.
> >
> > Under concurrent CI workloads (specifically, many containers doing
> > Python package compilation / .pyc generation simultaneously), the 6.12
> > kernel suffers from massive jbd2 journal contention. Processes hang
> > for 20-30 seconds waiting for VFS locks and journal space. On 6.6, the
> > exact same workload completes in ~4 seconds.
> >
> > # Environment:
> > * Host FS: ext4 (backed by standard cloud block storage)
> > * Container FS: OverlayFS (Docker)
> > * Machine: n2d-highmem-96 (96 vCPU, high memory)
> > * Good Kernel: 6.6.87
> > * Bad Kernels: 6.12.55, 6.12.68
> >
> > # The Bottleneck
> > During the 20+ second hang, `cat /proc/<pid>/stack` reveals three
> > distinct groups of blocked processes thrashing on the jbd2 journal.
> > The OverlayFS copy-up mechanism seems to be generating so many
> > synchronous ext4 transactions that it exhausts the jbd2 transaction
> > buffers.
> >
> > 1. Journal Space Exhaustion (Waiting to start transaction):
> > [<0>] __jbd2_log_wait_for_space+0xa3/0x240
> > [<0>] start_this_handle+0x42d/0x8a0
> > [<0>] jbd2__journal_start+0x103/0x1e0
> > [<0>] __ext4_journal_start_sb+0x129/0x1c0
> > [<0>] __ext4_new_inode+0x7cd/0x1290
> > [<0>] ext4_create+0xbc/0x1b0
> > [<0>] vfs_create+0x192/0x250
> > [<0>] ovl_create_real+0xd5/0x170
> > [<0>] ovl_create_or_link+0x1d7/0x7f0
> >
> > 2. VFS Rename / Copy-up Contention (Blocked by the slow sync):
> > [<0>] lock_rename+0x29/0x50
> > [<0>] ovl_copy_up_flags+0x84c/0x12e0
> > [<0>] ovl_create_object+0x4a/0x120
> > [<0>] vfs_mkdir+0x1aa/0x260
> > [<0>] do_mkdirat+0xb9/0x240
> >
> > 3. Synchronous Flush Blocking:
> > [<0>] jbd2_log_wait_commit+0x107/0x150
> > [<0>] jbd2_journal_force_commit+0x9c/0xc0
> > [<0>] ext4_sync_file+0x278/0x310
> > [<0>] ovl_sync_file+0x2f/0x50
> > [<0>] ovl_copy_up_metadata+0x455/0x4b0
> >
> > # Minimal Reproducer
> > The issue is easily reproducible by triggering 20 concurrent cold
> > Python imports in Docker, which forces OverlayFS to copy-up the
> > `__pycache__` directories and write the `.pyc` files.
> >
> > ```bash
> > # 1. Build a clean image with no pre-compiled bytecode
> > cat << 'EOF' > Dockerfile
> > FROM python:3.10-slim
> > RUN pip install --quiet google-cloud-compute
> > RUN find /usr/local -type d -name "__pycache__" -exec rm -rf {} +
> > EOF
> > docker build -t clean-import-test .
> >
> > # 2. Fire 20 concurrent imports
> > for i in {1..20}; do
> > docker run --rm clean-import-test bash -c 'time python -c "import
> > google.cloud.compute_v1"' > clean_test_cold_$i.log 2>&1 &
> > done
> > wait
> > grep "real" clean_test_cold_*.log
> > ```
>
> I don't understand.
>
> You write that Python imports in Docker forces OverlayFS to copy-up the
> `__pycache__` directories, but the prep stage removes all the
> `__pycache__` directories.
>
> My guess would be that rm -rf __pycache__ would generate a lot of
> metadata copy ups, but you write that the issue occurs during the
> 2nd stage. Maybe I misunderstood.
>
> Please try to figure out which and how many copy up objects this translates to
> for directories, for files?
>
> >
> > On 6.6.87, all 20 containers finish in ~4.3s.
> > On 6.12.x, they hang and finish between 17s and 27s. Bypassing disk
> > writes completely mitigates the regression on 6.12 (using
> > PYTHONDONTWRITEBYTECODE=1), confirming it is an ext4/overlayfs I/O
> > contention issue rather than a CPU scheduling one.
> >
> > Because the regression spans from 6.6 to 6.12, bisection is quite
> > heavy. Before we initiate a full kernel bisect, does this symptom ring
> > a bell for any ext4 fast_commit, jbd2 locking, or OverlayFS
> > metacopy/sync changes introduced during this window?
> >
> > Any pointers or patches you'd like us to test would be greatly appreciated.
> >
>
> Very high suspect:
>
> 7d6899fb69d25 ovl: fsync after metadata copy-up
>
> As you can see from this discussion [1] this performance regression
> was somewhat anticipated:
>
> "Now we just need to hope that users won't come shouting about
> performance regressions."
>
> [1] https://lore.kernel.org/linux-unionfs/CAOQ4uxgKC1SgjMWre=fUb00v8rxtd6sQi-S+dxR8oDzAuiGu8g@mail.gmail.com/
>
> With metacopy disabled this change introduced fsyncs on metadata-only
> changes made my overlayfs which could generate a lot of journal stress
> and explain the regression.
>
> But we had not anticipated that workloads could be affected with
> metacopy disabled, because it was anticipated that data fsync
> would be the more significant bottleneck.
>
> Do your containers have metacopy enabled?
> If not, why not? Is it because metacopy is conflicting with some
> other overlayfs feature that you need like userxattr?
>
> Thinking out loud, I wonder if metadata copy up code would benefit from
> calling export_ops->commit_metadata() when supported by upper fs
> instead of open+vfs_fsync(), but I doubt if that would relieve journal stress
> in this case.
>
> Anyway, please see if forcing metadata_fsync off solves the regression
> and I will stage the original patch from Fei to make metadata_fsync
> opt-in.
>
> Thanks,
> Amir.
>
> --- a/fs/overlayfs/copy_up.c
> +++ b/fs/overlayfs/copy_up.c
> @@ -1154,7 +1154,7 @@ static int ovl_copy_up_one(struct dentry
> *parent, struct dentry *dentry,
> * that will hurt performance of workloads such as chown -R, so we
> * only fsync on data copyup as legacy behavior.
> */
> - ctx.metadata_fsync = !OVL_FS(dentry->d_sb)->config.metacopy &&
> + ctx.metadata_fsync = 0 && !OVL_FS(dentry->d_sb)->config.metacopy &&
> (S_ISREG(ctx.stat.mode) || S_ISDIR(ctx.stat.mode));
> ctx.metacopy = ovl_need_meta_copy_up(dentry, ctx.stat.mode, flags);
^ permalink raw reply
* Re: [REGRESSION] fs/overlayfs/ext4: Severe jbd2 lock contention and journal starvation on concurrent copy-up (v6.6 -> v6.12)
From: Amir Goldstein @ 2026-03-24 7:53 UTC (permalink / raw)
To: Chenglong Tang
Cc: linux-unionfs, linux-ext4, linux-fsdevel, linux-kernel,
regressions, jack, Jan Kara, miklos, tytso, adilger.kernel, viro,
brauner, Kevin Berry, Robert Kolchmeyer, Deepa Dinamani, He Gao,
Fei Lv
In-Reply-To: <CAOdxtTadAFH01Vui1FvWfcmQ8jH1O45owTzUcpYbNvBxnLeM7Q@mail.gmail.com>
On Mon, Mar 23, 2026 at 11:03 PM Chenglong Tang
<chenglongtang@google.com> wrote:
>
> Hi all,
Hi Chenglong,
>
> We are tracking a severe performance regression in Google's
> Container-Optimized OS (COS) that appeared when moving from the 6.6
> LTS kernel to the 6.12 LTS kernel.
>
> Under concurrent CI workloads (specifically, many containers doing
> Python package compilation / .pyc generation simultaneously), the 6.12
> kernel suffers from massive jbd2 journal contention. Processes hang
> for 20-30 seconds waiting for VFS locks and journal space. On 6.6, the
> exact same workload completes in ~4 seconds.
>
> # Environment:
> * Host FS: ext4 (backed by standard cloud block storage)
> * Container FS: OverlayFS (Docker)
> * Machine: n2d-highmem-96 (96 vCPU, high memory)
> * Good Kernel: 6.6.87
> * Bad Kernels: 6.12.55, 6.12.68
>
> # The Bottleneck
> During the 20+ second hang, `cat /proc/<pid>/stack` reveals three
> distinct groups of blocked processes thrashing on the jbd2 journal.
> The OverlayFS copy-up mechanism seems to be generating so many
> synchronous ext4 transactions that it exhausts the jbd2 transaction
> buffers.
>
> 1. Journal Space Exhaustion (Waiting to start transaction):
> [<0>] __jbd2_log_wait_for_space+0xa3/0x240
> [<0>] start_this_handle+0x42d/0x8a0
> [<0>] jbd2__journal_start+0x103/0x1e0
> [<0>] __ext4_journal_start_sb+0x129/0x1c0
> [<0>] __ext4_new_inode+0x7cd/0x1290
> [<0>] ext4_create+0xbc/0x1b0
> [<0>] vfs_create+0x192/0x250
> [<0>] ovl_create_real+0xd5/0x170
> [<0>] ovl_create_or_link+0x1d7/0x7f0
>
> 2. VFS Rename / Copy-up Contention (Blocked by the slow sync):
> [<0>] lock_rename+0x29/0x50
> [<0>] ovl_copy_up_flags+0x84c/0x12e0
> [<0>] ovl_create_object+0x4a/0x120
> [<0>] vfs_mkdir+0x1aa/0x260
> [<0>] do_mkdirat+0xb9/0x240
>
> 3. Synchronous Flush Blocking:
> [<0>] jbd2_log_wait_commit+0x107/0x150
> [<0>] jbd2_journal_force_commit+0x9c/0xc0
> [<0>] ext4_sync_file+0x278/0x310
> [<0>] ovl_sync_file+0x2f/0x50
> [<0>] ovl_copy_up_metadata+0x455/0x4b0
>
> # Minimal Reproducer
> The issue is easily reproducible by triggering 20 concurrent cold
> Python imports in Docker, which forces OverlayFS to copy-up the
> `__pycache__` directories and write the `.pyc` files.
>
> ```bash
> # 1. Build a clean image with no pre-compiled bytecode
> cat << 'EOF' > Dockerfile
> FROM python:3.10-slim
> RUN pip install --quiet google-cloud-compute
> RUN find /usr/local -type d -name "__pycache__" -exec rm -rf {} +
> EOF
> docker build -t clean-import-test .
>
> # 2. Fire 20 concurrent imports
> for i in {1..20}; do
> docker run --rm clean-import-test bash -c 'time python -c "import
> google.cloud.compute_v1"' > clean_test_cold_$i.log 2>&1 &
> done
> wait
> grep "real" clean_test_cold_*.log
> ```
I don't understand.
You write that Python imports in Docker forces OverlayFS to copy-up the
`__pycache__` directories, but the prep stage removes all the
`__pycache__` directories.
My guess would be that rm -rf __pycache__ would generate a lot of
metadata copy ups, but you write that the issue occurs during the
2nd stage. Maybe I misunderstood.
Please try to figure out which and how many copy up objects this translates to
for directories, for files?
>
> On 6.6.87, all 20 containers finish in ~4.3s.
> On 6.12.x, they hang and finish between 17s and 27s. Bypassing disk
> writes completely mitigates the regression on 6.12 (using
> PYTHONDONTWRITEBYTECODE=1), confirming it is an ext4/overlayfs I/O
> contention issue rather than a CPU scheduling one.
>
> Because the regression spans from 6.6 to 6.12, bisection is quite
> heavy. Before we initiate a full kernel bisect, does this symptom ring
> a bell for any ext4 fast_commit, jbd2 locking, or OverlayFS
> metacopy/sync changes introduced during this window?
>
> Any pointers or patches you'd like us to test would be greatly appreciated.
>
Very high suspect:
7d6899fb69d25 ovl: fsync after metadata copy-up
As you can see from this discussion [1] this performance regression
was somewhat anticipated:
"Now we just need to hope that users won't come shouting about
performance regressions."
[1] https://lore.kernel.org/linux-unionfs/CAOQ4uxgKC1SgjMWre=fUb00v8rxtd6sQi-S+dxR8oDzAuiGu8g@mail.gmail.com/
With metacopy disabled this change introduced fsyncs on metadata-only
changes made my overlayfs which could generate a lot of journal stress
and explain the regression.
But we had not anticipated that workloads could be affected with
metacopy disabled, because it was anticipated that data fsync
would be the more significant bottleneck.
Do your containers have metacopy enabled?
If not, why not? Is it because metacopy is conflicting with some
other overlayfs feature that you need like userxattr?
Thinking out loud, I wonder if metadata copy up code would benefit from
calling export_ops->commit_metadata() when supported by upper fs
instead of open+vfs_fsync(), but I doubt if that would relieve journal stress
in this case.
Anyway, please see if forcing metadata_fsync off solves the regression
and I will stage the original patch from Fei to make metadata_fsync
opt-in.
Thanks,
Amir.
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -1154,7 +1154,7 @@ static int ovl_copy_up_one(struct dentry
*parent, struct dentry *dentry,
* that will hurt performance of workloads such as chown -R, so we
* only fsync on data copyup as legacy behavior.
*/
- ctx.metadata_fsync = !OVL_FS(dentry->d_sb)->config.metacopy &&
+ ctx.metadata_fsync = 0 && !OVL_FS(dentry->d_sb)->config.metacopy &&
(S_ISREG(ctx.stat.mode) || S_ISDIR(ctx.stat.mode));
ctx.metacopy = ovl_need_meta_copy_up(dentry, ctx.stat.mode, flags);
^ permalink raw reply
* Re: [PATCH] ext4: skip split extent recovery on corruption
From: Ojaswin Mujoo @ 2026-03-24 7:51 UTC (permalink / raw)
To: hongao
Cc: tytso, adilger.kernel, jack, yi.zhang, linux-ext4, linux-kernel,
syzbot+1ffa5d865557e51cb604
In-Reply-To: <E4BAF530323E79C3+20260324014025.31601-1-hongao@uniontech.com>
On Tue, Mar 24, 2026 at 09:40:25AM +0800, hongao wrote:
> Hi Jan, Yi, Ojaswin,
>
> Thank you for reviewing the patch.
>
> I will send a v2 that moves the p_ext validation before
> ext4_ext_get_access(), as Yi suggested.
>
> Also, thanks for the Reviewed-by tags:
> Reviewed-by: Jan Kara <jack@suse.cz>
> Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
>
> Regarding Ojaswin's questions:
>
> I do not have a local reproducer at the moment. My analysis was based on
> the syzbot report, the crash trace, and code inspection.
>
> For the p_ext == NULL case, a successful ext4_find_extent() only means
> that we were able to walk the tree down to a leaf. It does not guarantee
> that the leaf still contains a valid extent entry for the target logical
> block.
>
> path[depth].p_ext is derived from the extent entries stored in that leaf.
> If the leaf metadata is already corrupted, ext4_find_extent() may still
> return a non-error path, but p_ext can be NULL because there is no usable
> extent entry there anymore.
>
> So in the corruption case, a valid path is not enough to continue the
> recovery path safely. Returning -EFSCORRUPTED is safer than
> dereferencing p_ext and crashing while trying to repair already-broken
> metadata.
Hmm so I looked a bit more and this path can lead to an empty extent:
ext4_ext_insert_extent():
...
// Creates an empty leaf with p_ext == 0
path = ext4_ext_create_new_leaf(handle, inode, mb_flags, gb_flags,
path, newext);
// Errors out
err = ext4_ext_get_access(handle, inode, path + depth);
if (err)
goto errout;
Checking ext4_ext_get_access()
Seems like it can return EROFS when journal is aborted or EIO if journal
detected some IO errors on backing device. I guess we have already
handled these by exiting early in your patch, but sure having an extra
check wont hurt.
Feel free to add:
Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
Regards,
Ojaswin
>
> Thanks,
> Hongao
^ permalink raw reply
* Re: [PATCH 41/41] fs: Unify generic_file_fsync() with mmb methods
From: Christoph Hellwig @ 2026-03-24 5:56 UTC (permalink / raw)
To: Jan Kara
Cc: linux-fsdevel, linux-block, 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: <20260320134100.20731-82-jack@suse.cz>
On Fri, Mar 20, 2026 at 02:41:36PM +0100, Jan Kara wrote:
> Taking inode lock when writing out the inode seems pointless in
> particular because there are lots of places (most notably sync(2) path)
> that don't do that so hardly anything can depend on it.
This is really something that needs to stand out clearly for bisecting
and documentation. I.e. make this a patch on its own and preferably
before all the other refactoring that already is affected by moving
between the implementations at the beginning of the series.
> So let's remove __generic_file_fsync() and use
> generic_mmb_fsync_noflush() instead to reduce code duplication. Arguably
> this leaks a bit of buffer_head knowledge into fs/libfs.c which is not
> great but avoiding the duplication seems worth it.
You could just pass a callback to the generic version. The cost of an
indirect call should not matter compared to the rest of the fsync code.
That would also be a nice thing before all the renaming, as that means
we could add the version with the callback first to unify the
implementations and then the file systems are switched away from
the buffers fsync variant to explicitly pass a callback, or to not
pass a callback when they currently get the default one.
^ permalink raw reply
* Re: [PATCH 31/41] fs: Provide functions for handling mapping_metadata_bhs directly
From: Christoph Hellwig @ 2026-03-24 5:51 UTC (permalink / raw)
To: Jan Kara
Cc: linux-fsdevel, linux-block, 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: <20260320134100.20731-72-jack@suse.cz>
On Fri, Mar 20, 2026 at 02:41:26PM +0100, Jan Kara wrote:
> As part of transition toward moving mapping_metadata_bhs to fs-private
> part of the inode, provide functions for operations on this list
> directly instead of going through the inode / mapping.
>
> Signed-off-by: Jan Kara <jack@suse.cz>
> ---
> fs/buffer.c | 93 +++++++++++++++++--------------------
> include/linux/buffer_head.h | 45 ++++++++++++++----
> 2 files changed, 80 insertions(+), 58 deletions(-)
>
> diff --git a/fs/buffer.c b/fs/buffer.c
> index c70f8027bdd1..43aca5b7969f 100644
> --- a/fs/buffer.c
> +++ b/fs/buffer.c
> @@ -467,31 +467,25 @@ EXPORT_SYMBOL(mark_buffer_async_write);
> * a successful fsync(). For example, ext2 indirect blocks need to be
> * written back and waited upon before fsync() returns.
> *
> - * The functions mark_buffer_dirty_inode(), fsync_inode_buffers(),
> - * mmb_has_buffers() and invalidate_inode_buffers() are provided for the
> - * management of a list of dependent buffers in mapping_metadata_bhs struct.
> + * The functions mmb_mark_buffer_dirty(), mmb_sync_buffers(), mmb_has_buffers()
> + * and mmb_invalidate_buffers() are provided for the management of a list of
> + * dependent buffers in mapping_metadata_bhs struct.
> *
> * The locking is a little subtle: The list of buffer heads is protected by
> * the lock in mapping_metadata_bhs so functions coming from bdev mapping
> * (such as try_to_free_buffers()) need to safely get to mapping_metadata_bhs
> * using RCU, grab the lock, verify we didn't race with somebody detaching the
> * bh / moving it to different inode and only then proceeding.
> - *
> - * FIXME: mark_buffer_dirty_inode() is a data-plane operation. It should
> - * take an address_space, not an inode. And it should be called
> - * mark_buffer_dirty_fsync() to clearly define why those buffers are being
> - * queued up.
> - *
> - * FIXME: mark_buffer_dirty_inode() doesn't need to add the buffer to the
> - * list if it is already on a list. Because if the buffer is on a list,
> - * it *must* already be on the right one. If not, the filesystem is being
> - * silly. This will save a ton of locking. But first we have to ensure
> - * that buffers are taken *off* the old inode's list when they are freed
> - * (presumably in truncate). That requires careful auditing of all
> - * filesystems (do it inside bforget()). It could also be done by bringing
> - * b_inode back.
> */
>
> +void mmb_init(struct mapping_metadata_bhs *mmb, struct address_space *mapping)
> +{
> + spin_lock_init(&mmb->lock);
> + INIT_LIST_HEAD(&mmb->list);
> + mmb->mapping = mapping;
> +}
> +EXPORT_SYMBOL(mmb_init);
> +
> static void __remove_assoc_queue(struct mapping_metadata_bhs *mmb,
> struct buffer_head *bh)
> {
> @@ -533,12 +527,12 @@ bool mmb_has_buffers(struct mapping_metadata_bhs *mmb)
> EXPORT_SYMBOL_GPL(mmb_has_buffers);
>
> /**
> - * sync_mapping_buffers - write out & wait upon a mapping's "associated" buffers
> - * @mapping: the mapping which wants those buffers written
> + * mmb_sync_buffers - write out & wait upon all buffers in a list
> + * @mmb: the list of buffers to write
> *
> - * Starts I/O against the buffers at mapping->i_metadata_bhs and waits upon
> - * that I/O. Basically, this is a convenience function for fsync(). @mapping
> - * is a file or directory which needs those buffers to be written for a
> + * Starts I/O against the buffers in the given list and waits upon
> + * that I/O. Basically, this is a convenience function for fsync(). @mmb is
> + * for a file or directory which needs those buffers to be written for a
> * successful fsync().
> *
> * We have conflicting pressures: we want to make sure that all
> @@ -553,9 +547,8 @@ EXPORT_SYMBOL_GPL(mmb_has_buffers);
> * buffer stays on our list until IO completes (at which point it can be
> * reaped).
> */
> -int sync_mapping_buffers(struct address_space *mapping)
> +int mmb_sync_buffers(struct mapping_metadata_bhs *mmb)
mmb and buffers in the same name feels a bit redundant.
mmc_sync_all? mapping_sync_buffers?
> +int generic_mmb_fsync_noflush(struct file *file,
> + struct mapping_metadata_bhs *mmb,
> + loff_t start, loff_t end, bool datasync)
mmb_fsync? mapping_buffers_fsync?
> +int generic_mmb_fsync(struct file *file, struct mapping_metadata_bhs *mmb,
> + loff_t start, loff_t end, bool datasync)
> {
> struct inode *inode = file->f_mapping->host;
> int ret;
>
> - ret = generic_buffers_fsync_noflush(file, start, end, datasync);
> + ret = generic_mmb_fsync_noflush(file, mmb, start, end, datasync);
> if (!ret)
> ret = blkdev_issue_flush(inode->i_sb->s_bdev);
> return ret;
> }
> -EXPORT_SYMBOL(generic_buffers_fsync);
> +EXPORT_SYMBOL(generic_mmb_fsync);
Same naming, but do we even need this function? One the
mapping_metadata_bhs has to be passed in, the file system needs a
wrapper anyway, at which point open coding the flush is not really
much of a burden.
^ permalink raw reply
* Re: [PATCH 30/41] fs: Switch inode_has_buffers() to take mapping_metadata_bhs
From: Christoph Hellwig @ 2026-03-24 5:48 UTC (permalink / raw)
To: Jan Kara
Cc: linux-fsdevel, linux-block, 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: <20260320134100.20731-71-jack@suse.cz>
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH 29/41] fs: Make bhs point to mapping_metadata_bhs
From: Christoph Hellwig @ 2026-03-24 5:48 UTC (permalink / raw)
To: Jan Kara
Cc: linux-fsdevel, linux-block, 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: <20260320134100.20731-70-jack@suse.cz>
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH 28/41] fs: Move metadata bhs tracking to a separate struct
From: Christoph Hellwig @ 2026-03-24 5:47 UTC (permalink / raw)
To: Jan Kara
Cc: linux-fsdevel, linux-block, 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: <20260320134100.20731-69-jack@suse.cz>
On Fri, Mar 20, 2026 at 02:41:23PM +0100, Jan Kara wrote:
> Instead of tracking metadata bhs for a mapping using i_private_list and
> i_private_lock we create a dedicated mapping_metadata_bhs struct for it.
s/we //g ?
> So far this struct is embedded in address_space but that will be
> switched for per-fs private inode parts later in the series. This also
> changes the locking from bdev mapping's i_private_lock to lock embedded
Instead of "to lock" I'd expect "to a new lock" or similar.
> + /*
> + * The locking dance is ugly here. We need to acquire lock
s/lock/the lock/
> + * protecting metadata bh list while possibly racing with bh
"the metadata bh list" (or spell out the field name without the "the").
Otherwise looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply
* Re: [PATCH 27/41] fs: Fold fsync_buffers_list() into sync_mapping_buffers()
From: Christoph Hellwig @ 2026-03-24 5:44 UTC (permalink / raw)
To: Jan Kara
Cc: linux-fsdevel, linux-block, 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: <20260320134100.20731-68-jack@suse.cz>
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
> - get_bh(bh);
> - mapping = bh->b_assoc_map;
> - __remove_assoc_queue(bh);
> - /* Avoid race with mark_buffer_dirty_inode() which does
> - * a lockless check and we rely on seeing the dirty bit */
> - smp_mb();
> - if (buffer_dirty(bh)) {
> - list_add(&bh->b_assoc_buffers,
> - &mapping->i_private_list);
> - bh->b_assoc_map = mapping;
> - }
> - spin_unlock(lock);
> - wait_on_buffer(bh);
> - if (!buffer_uptodate(bh))
> - err = -EIO;
> - brelse(bh);
> - spin_lock(lock);
> - }
> -
> - spin_unlock(lock);
> - return err;
> -}
> -
> /*
> * Invalidate any and all dirty buffers on a given inode. We are
> * probably unmounting the fs, but that doesn't mean we have already
> --
> 2.51.0
>
>
---end quoted text---
^ permalink raw reply
* Re: [PATCH 26/41] fs: Drop osync_buffers_list()
From: Christoph Hellwig @ 2026-03-24 5:44 UTC (permalink / raw)
To: Jan Kara
Cc: linux-fsdevel, linux-block, 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: <20260320134100.20731-67-jack@suse.cz>
Looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ 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