mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Josef Bacik <josef@toxicpanda.com>
To: Miklos Szeredi <miklos@szeredi.hu>,
	Amir Goldstein <amir73il@gmail.com>,
	 Christian Brauner <brauner@kernel.org>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>, Jan Kara <jack@suse.cz>,
	 Christoph Hellwig <hch@infradead.org>,
	Chris Mason <mason@kernel.org>,
	 Chengguang Xu <cgxu519@mykernel.net>,
	linux-unionfs@vger.kernel.org,  linux-fsdevel@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	 Chengguang Xu <charliecgxu@tencent.com>,
	Josef Bacik <josef@toxicpanda.com>
Subject: [PATCH v2 00/10] ovl: only sync what was written through the overlay
Date: Thu, 29 Oct 2026 01:09:14 +0000	[thread overview]
Message-ID: <20261029-b4-ovl-containerized-sync-v2-0-4e9f08e4a052@toxicpanda.com> (raw)

v1: https://lore.kernel.org/all/20261027-b4-ovl-containerized-sync-v1-0-802e512379a6@toxicpanda.com/

Jan, Amir suggested I ask you to look at the writeback and lazytime
parts again, that's patches 4 to 6 and 9.

v1->v2:
- Dropped the superblock flag and the ext4, xfs and btrfs patches. This
  is all in overlayfs now and works the same on any upper file system.
  (Christoph, Amir)
- Upper inodes without an overlay inode get a fake one that goes on the
  dirty list, patches 7 to 9.
- The periodic flusher pass doesn't write the upper inode any more, and
  syncfs() doesn't make ext4 commit per inode.
- Record write errors in s_wb_err of the overlay.
- Make the root inode appear hashed so it can be on the dirty list,
  don't mark unhashed inodes dirty, read i_writecount with acquire.
  (Sashiko)
- Left alone: dirtied_time_when isn't set for an overlay inode that gets
  I_DIRTY_TIME from ->write_inode(). It only matters for the 12 hour
  expiry, where the upper file system writes the timestamps on its own.
  (Sashiko)
- Rewrote my commit messages. (Christoph)

What it does now:

sync_filesystem() writes every inode on a dirty list, calls ->sync_fs()
and writes the block device. Only the first step is expensive, because
of other people's data. So overlayfs writes the upper inodes that were
modified through this overlay and does the other two steps as they are.
No file system has to promise anything for that.

Upper inodes with an overlay inode are tracked as in v1. The rest,
whiteouts, index entries, the work directories, are caught in the
ovl_do_*() helpers, which know what upper inodes they touch. If the VFS
considers such an inode dirty it gets a fake overlay inode, hashed by
the upper inode like a trap inode, and from there it's an ordinary dirty
overlay inode.

Things I know about:

 - An upper inode can have an overlay inode and a fake one. After
   creating 2000 files and a chown -R of another 2000 there are twice as
   many overlay inodes cached on ext4 and ext2, and 1.5 times as many on
   xfs and btrfs. The fake ones can be reclaimed once they're written.
 - With nobody else's data to skip syncfs() gets a bit slower, after the
   above it went from 49ms to 62ms on ext4 and from 96ms to 154ms on
   xfs.
 - ext2 and jfs can dirty the inode of the quota file from ->sync_fs(),
   that now waits for the flusher of the upper file system.
 - On a file system without a journal the neighbours' unwritten inodes
   show up as bitmap and count differences in fsck after a crash.

The testing is the same as for v1, now also on ext4 without a journal
and on ext2 with [2] applied. syncfs() goes from 226-268ms to 45-50ms
and unmount from 114-238ms to 37-43ms, on all five. fstests with
-overlay gives the same results with and without the series on ext4 and
on xfs.

[2] https://lore.kernel.org/r/20261027-b4-ext2-dirsync-v1-1-3dcd012d518d@toxicpanda.com

--- Original email (v1) ---

Hello,

This picks up Chengguang Xu's "implement containerized syncfs for
overlayfs", last posted as RFC V6 in November 2021 [1].

syncfs() on an overlay and unmounting one call sync_filesystem() on the
upper file system, so they write every dirty inode on it no matter who
dirtied it. We run a lot of containers on one upper file system, and
stopping one of them writes out the dirty data of all the others. That
can take a very long time, and s_umount of the upper file system is held
the whole time, so anything that wants it exclusively queues up and then
everybody else queues up behind that.

With this an overlay only writes the upper inodes that were changed
through it, and then has the upper file system commit its metadata.

The V6 discussion ended with a direction but no V7, so that's what I
tried to follow:

 - V6 kept every overlay inode with an upper inode dirty for good. Jan
   and Amir didn't like the cost of walking them. Now an overlay inode
   is marked dirty when the upper inode is changed, mostly from
   ovl_copyattr() as Amir and Miklos suggested.
 - It never looks at the dirty flags of the upper inode, Miklos pointed
   out that they're cleared when writeback starts.
 - ->write_inode() goes through write_inode_now() on the upper inode,
   and keeps the overlay inode dirty while the upper inode is open for
   writing, which covers shared mappings.
 - V6 marked the inodes DONTCACHE, which Jan was worried about. This
   goes back to the v5 patch that keeps dirty overlay inodes cached.

One thing is new. V6 called wait_sb_inodes() on the upper file system to
catch writeback that was started but not finished, which waits for
everybody's writeback. Instead ->write_inode() keeps the overlay inode
dirty while the upper inode has pages tagged dirty or under writeback.
The tags don't have the problem the inode flags have, the writeback tag
is set before the dirty tag is cleared. So a clean overlay inode means
its data is on disk, and syncfs() only waits for its own inodes.

That takes care of the data. Metadata is harder, a lot of what is
changed on the upper file system has no overlay inode that could be on
the dirty list: the root of the overlay isn't hashed, and whiteouts,
index entries, the work directories and their parent have none. File
systems that log their metadata don't care, ->sync_fs() commits it. ext2
does, there a whiteout was gone after a crash. I first had overlayfs
write all of those itself and kept finding more of them, the last one
was the link count of the shared whiteout when a whiteout is removed.

So patch 1 adds a superblock flag, SB_I_OVL_USE_SYNC_FS, by which a file
system says that ->sync_fs() commits all of its metadata, and patches 2
to 4 set it for ext4 with a journal, xfs and btrfs. Without the flag on
the upper file system nothing changes, no inode is marked dirty and
syncfs() and unmount call sync_filesystem() like they always did.

Patches 5, 7, 8 and 10 are Chengguang's with changes noted in them,
patches 6 and 9 are new. I dropped Jan's Reviewed-by tags from V6 since
the patches changed.

lazytime on the upper file system needs its own handling. The flusher
leaves the timestamps in memory for up to 12 hours, so the overlay inode
can't be clean, but it can't stay dirty and pinned for that long either.
Patch 9 gives it I_DIRTY_TIME like the upper inode has, and forwards
->sync_lazytime() to the upper inode.

Things I know about:

 - An overlay inode that loses its last reference while it is dirty is
   kept until it has been written and then sits on the LRU, like with
   any other file system. Clean and unlinked ones are still freed right
   away.
 - Every overlay on such an upper file system gets a bdi.
 - I haven't measured syncfs() with a very large number of dirty inodes.

For testing I put several overlays on one upper file system and dirty
192M next to the overlay under test, through another overlay and
directly. Then syncfs() or unmount the one overlay, copy the block
device as it is at that moment, mount the copy, and check that
everything that was changed through the overlay is in it and that the
192M aren't. That passes with ext4, xfs and btrfs as the upper file
system. With KASAN and lockdep on, syncfs() goes from 239-284ms to
45-48ms and unmount from 126-234ms to 39-44ms. With ext2 and ext4
without a journal the 192M are written as before.

fstests with -overlay, the auto groups of generic and overlay, gives the
same results with and without the series on ext4 and on xfs.

[1] https://lore.kernel.org/r/20211122030038.1938875-1-cgxu519@mykernel.net

Thanks,

Josef

---
Changes in v2:
- Link to v1: https://patch.msgid.link/20261027-b4-ovl-containerized-sync-v1-0-802e512379a6@toxicpanda.com

---
Chengguang Xu (4):
      ovl: setup overlayfs' private bdi
      ovl: implement overlayfs' own ->write_inode operation
      ovl: cache dirty overlayfs' inode
      ovl: implement containerized syncfs for overlayfs

Josef Bacik (6):
      ovl: make the root inode appear hashed
      ovl: mark the overlay inode dirty on modification
      ovl: handle lazytime on the upper filesystem
      ovl: look up overlay inodes with a key structure
      ovl: pass the ovl_fs to ovl_do_rename_rd()
      ovl: put modified upper inodes on the dirty list

 fs/overlayfs/copy_up.c   |   9 ++-
 fs/overlayfs/dir.c       |  11 +--
 fs/overlayfs/file.c      |   7 +-
 fs/overlayfs/inode.c     | 185 ++++++++++++++++++++++++++++++++++++++++++++---
 fs/overlayfs/overlayfs.h | 147 ++++++++++++++++++++++++++++++++-----
 fs/overlayfs/ovl_entry.h |   2 +
 fs/overlayfs/params.c    |  14 +---
 fs/overlayfs/super.c     | 175 +++++++++++++++++++++++++++++++++++++++++---
 fs/overlayfs/util.c      | 108 ++++++++++++++++++++++++++-
 9 files changed, 598 insertions(+), 60 deletions(-)
---
base-commit: 2c8a968b488c134d05ccefff890270ac8ab899a8
change-id: 20261026-b4-ovl-containerized-sync-149bed1afe9a


             reply	other threads:[~2026-10-29  1:09 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-29  1:09 Josef Bacik [this message]
2026-10-29  1:09 ` [PATCH v2 01/10] ovl: setup overlayfs' private bdi Josef Bacik
2026-10-29  1:09 ` [PATCH v2 02/10] ovl: make the root inode appear hashed Josef Bacik
2026-10-29  1:09 ` [PATCH v2 03/10] ovl: mark the overlay inode dirty on modification Josef Bacik
2026-10-29  1:09 ` [PATCH v2 04/10] ovl: implement overlayfs' own ->write_inode operation Josef Bacik
2026-10-29  1:09 ` [PATCH v2 05/10] ovl: cache dirty overlayfs' inode Josef Bacik
2026-10-29  1:09 ` [PATCH v2 06/10] ovl: handle lazytime on the upper filesystem Josef Bacik
2026-10-29  1:09 ` [PATCH v2 07/10] ovl: look up overlay inodes with a key structure Josef Bacik
2026-10-29  1:09 ` [PATCH v2 08/10] ovl: pass the ovl_fs to ovl_do_rename_rd() Josef Bacik
2026-10-29  1:09 ` [PATCH v2 09/10] ovl: put modified upper inodes on the dirty list Josef Bacik
2026-10-29  1:09 ` [PATCH v2 10/10] ovl: implement containerized syncfs for overlayfs Josef Bacik

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261029-b4-ovl-containerized-sync-v2-0-4e9f08e4a052@toxicpanda.com \
    --to=josef@toxicpanda.com \
    --cc=amir73il@gmail.com \
    --cc=brauner@kernel.org \
    --cc=cgxu519@mykernel.net \
    --cc=charliecgxu@tencent.com \
    --cc=hch@infradead.org \
    --cc=jack@suse.cz \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-unionfs@vger.kernel.org \
    --cc=mason@kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®