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, Josef Bacik <josef@toxicpanda.com>
Subject: [PATCH v4 1/8] ovl: expand fsync mount options
Date: Fri, 06 Nov 2026 13:36:43 +0000 [thread overview]
Message-ID: <20261106-b4-ovl-containerized-sync-v4-1-6ddde0b7dd8a@toxicpanda.com> (raw)
In-Reply-To: <20261106-b4-ovl-containerized-sync-v4-0-6ddde0b7dd8a@toxicpanda.com>
From: Amir Goldstein <amir73il@gmail.com>
The fsync mount option currently accepts three values:
"volatile", "strict" and "auto".
All other "enum" mount options have "on" and "off" values and this is
used by the generic _check_overlay_feature helper in fstests to probe
for support for enabling overlayfs features.
This commit adds support for values "on", "off" and "relaxed" and makes
the value of "auto" depend on a kconfig/module option fsync_auto.
The value of "off" behaves almost the same as "volatile", not
persisting changes to upper layer, but it does not create the directory
"$workdir/work/incompat/volatile", which prevents a mount cycle of a
volatile overlayfs. Some users requested to opt-out of this guard rail.
With upperdir on tmpfs, overlayfs now falls back to "fsync=off", because
the other fsync modes are futile on tmpfs.
The new value "relaxed" is a preparation for not syncing the entire
upper fs on syncfs(2) and unmount and instead tracking and syncing only
the upper inodes modified by this overlayfs.
The value of "on" is the traditional overlayfs behavior and it behaves
the same as the current value "auto", releasing the value of "auto" to
differ by the kconfig/module option fsync_auto.
By default, with kconfig/module option fsync_auto=Y, the meaning of the
value "auto" is that filesystems that support RENAME_WHITEOUT default to
"relaxed" and filesystems that do not support RENAME_WHITEOUT default to
the traditional "fsync=on".
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
Documentation/filesystems/overlayfs.rst | 36 ++++++++++++++++++++++++++++-----
fs/overlayfs/Kconfig | 21 +++++++++++++++++++
fs/overlayfs/overlayfs.h | 24 +++++++++++++++++++---
fs/overlayfs/params.c | 18 +++++++++++++----
fs/overlayfs/params.h | 2 ++
fs/overlayfs/super.c | 22 ++++++++++++++++++--
6 files changed, 109 insertions(+), 14 deletions(-)
diff --git a/Documentation/filesystems/overlayfs.rst b/Documentation/filesystems/overlayfs.rst
index 16c35b491dad..1a59500834a1 100644
--- a/Documentation/filesystems/overlayfs.rst
+++ b/Documentation/filesystems/overlayfs.rst
@@ -826,27 +826,53 @@ The fsync during copy up only guarantees that if a copy up is observed
after a crash, the observed data is not zeroes or intermediate values
from the copy up staging area.
+Traditionally, syncfs(2) and unmount of an overlay sync the entire upper
+filesystem, including the dirty data of other overlays that share it.
+Overlayfs can be told to only write back the files that were modified
+through the overlay, and then ask the upper filesystem to commit its
+metadata.
+
On traditional local filesystems with a single journal (e.g. ext4, xfs),
fsync on a file also persists the parent directory changes, because they
are usually modified in the same transaction, so metadata durability during
-data copy up effectively comes for free. Overlayfs further limits risk by
-disallowing network filesystems as upper layer.
+data copy up and the persistence of other upper changes such as whiteouts
+effectively come for free. Other filesystems (e.g. ubifs) require an explicit
+fsync(2) on the copied up files and directories to persist their metadata.
Overlayfs can be tuned to prefer performance or durability when storing
to the underlying upper layer. This is controlled by the "fsync" mount
option, which supports these values:
-- "auto": (default)
+- "volatile": [*]
+ Prefer performance over durability (see `Volatile mount`_)
+- "off":
+ Same as "volatile", but does not prevent mounting the overlay again
+ after unmount (see `Volatile mount`_)
+- "relaxed":
Call fsync(2) on upper file before completion of data copy up.
No explicit fsync(2) on directory or metadata-only copy up.
+ syncfs(2) and unmount only write back the files that were modified
+ through the overlay.
+- "auto": (default)
+ "relaxed" if the upper filesystem supports RENAME_WHITEOUT,
+ otherwise "on".
+- "on":
+ syncfs(2) syncs the entire upper filesystem.
+ Copy up behaves like "relaxed".
- "strict":
+ syncfs(2) syncs the entire upper filesystem.
Call fsync(2) on upper file and directories before completion of any
copy up.
-- "volatile": [*]
- Prefer performance over durability (see `Volatile mount`_)
[*] The mount option "volatile" is an alias to "fsync=volatile".
+The default is "fsync=on" instead of "fsync=auto" with the module option
+"fsync_auto=N" or with the kernel config option
+CONFIG_OVERLAY_FS_FSYNC_AUTO=n.
+
+If the upper filesystem has no writeback (e.g. tmpfs), a non-default mode
+falls back to "fsync=off".
+
Volatile mount
--------------
diff --git a/fs/overlayfs/Kconfig b/fs/overlayfs/Kconfig
index 2ac67e04a6fb..f1b2f3784c76 100644
--- a/fs/overlayfs/Kconfig
+++ b/fs/overlayfs/Kconfig
@@ -108,6 +108,27 @@ config OVERLAY_FS_XINO_AUTO
If unsure, say N.
+config OVERLAY_FS_FSYNC_AUTO
+ bool "Overlayfs: auto select the fsync mode by default"
+ default y
+ depends on OVERLAY_FS
+ help
+ If this config option is enabled then overlay filesystems will use
+ "fsync=auto" by default, which selects "fsync=relaxed" if the upper
+ filesystem supports RENAME_WHITEOUT and "fsync=on" otherwise.
+ With "fsync=relaxed", syncfs(2) and unmount of an overlay only write
+ back the files that were modified through the overlay, instead of
+ syncing the entire upper filesystem.
+
+ If this config option is disabled then overlay filesystems will use
+ "fsync=on" by default. It is still possible to change the default
+ with the "fsync_auto" module option or on a filesystem instance
+ basis with the "fsync" mount option.
+
+ For more information, see Documentation/filesystems/overlayfs.rst
+
+ If unsure, say Y.
+
config OVERLAY_FS_METACOPY
bool "Overlayfs: turn on metadata only copy up feature by default"
depends on OVERLAY_FS
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 92da556598da..5b1a097ce543 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -102,8 +102,11 @@ enum {
};
enum {
+ OVL_FSYNC_OFF,
OVL_FSYNC_VOLATILE,
+ OVL_FSYNC_RELAXED,
OVL_FSYNC_AUTO,
+ OVL_FSYNC_ON,
OVL_FSYNC_STRICT,
};
@@ -660,7 +663,8 @@ static inline bool ovl_xino_warn(struct ovl_fs *ofs)
static inline bool ovl_should_sync(struct ovl_fs *ofs)
{
- return ofs->config.fsync_mode != OVL_FSYNC_VOLATILE;
+ return ofs->config.fsync_mode != OVL_FSYNC_OFF &&
+ ofs->config.fsync_mode != OVL_FSYNC_VOLATILE;
}
static inline bool ovl_should_sync_metadata(struct ovl_fs *ofs)
@@ -668,9 +672,23 @@ static inline bool ovl_should_sync_metadata(struct ovl_fs *ofs)
return ofs->config.fsync_mode == OVL_FSYNC_STRICT;
}
-static inline bool ovl_is_volatile(struct ovl_config *config)
+/*
+ * With fsync=relaxed, track the files that were modified through the overlay,
+ * so that syncfs(2) and unmount only write back those.
+ */
+static inline bool ovl_tracks_dirty(struct ovl_fs *ofs)
+{
+ return ofs->config.fsync_mode == OVL_FSYNC_RELAXED;
+}
+
+/*
+ * With fsync=relaxed, syncfs(2) and unmount only write back the files that were
+ * modified through the overlay. Otherwise they sync the entire upper
+ * filesystem.
+ */
+static inline bool ovl_should_sync_upper_fs(struct ovl_fs *ofs)
{
- return config->fsync_mode == OVL_FSYNC_VOLATILE;
+ return ovl_should_sync(ofs) && !ovl_tracks_dirty(ofs);
}
/*
diff --git a/fs/overlayfs/params.c b/fs/overlayfs/params.c
index 5a15e5478a6b..549fc1e83ac9 100644
--- a/fs/overlayfs/params.c
+++ b/fs/overlayfs/params.c
@@ -28,6 +28,11 @@ module_param_named(xino_auto, ovl_xino_auto_def, bool, 0644);
MODULE_PARM_DESC(xino_auto,
"Auto enable xino feature");
+static bool ovl_fsync_auto_def = IS_ENABLED(CONFIG_OVERLAY_FS_FSYNC_AUTO);
+module_param_named(fsync_auto, ovl_fsync_auto_def, bool, 0644);
+MODULE_PARM_DESC(fsync_auto,
+ "Default to fsync=auto instead of fsync=on");
+
static bool ovl_index_def = IS_ENABLED(CONFIG_OVERLAY_FS_INDEX);
module_param_named(index, ovl_index_def, bool, 0644);
MODULE_PARM_DESC(index,
@@ -142,8 +147,11 @@ static int ovl_verity_mode_def(void)
}
static const struct constant_table ovl_parameter_fsync[] = {
+ { "off", OVL_FSYNC_OFF },
{ "volatile", OVL_FSYNC_VOLATILE },
+ { "relaxed", OVL_FSYNC_RELAXED },
{ "auto", OVL_FSYNC_AUTO },
+ { "on", OVL_FSYNC_ON },
{ "strict", OVL_FSYNC_STRICT },
{}
};
@@ -153,9 +161,9 @@ static const char *ovl_fsync_mode(struct ovl_config *config)
return ovl_parameter_fsync[config->fsync_mode].name;
}
-static int ovl_fsync_mode_def(void)
+int ovl_fsync_mode_def(void)
{
- return OVL_FSYNC_AUTO;
+ return ovl_fsync_auto_def ? OVL_FSYNC_AUTO : OVL_FSYNC_ON;
}
const struct fs_parameter_spec ovl_parameter_spec[] = {
@@ -689,9 +697,11 @@ static int ovl_parse_param(struct fs_context *fc, struct fs_parameter *param)
break;
case Opt_fsync:
config->fsync_mode = result.uint_32;
+ ctx->set.fsync = true;
break;
case Opt_volatile:
config->fsync_mode = OVL_FSYNC_VOLATILE;
+ ctx->set.fsync = true;
break;
case Opt_userxattr:
config->userxattr = true;
@@ -896,8 +906,8 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
config->index = false;
}
- if (!config->upperdir && ovl_is_volatile(config)) {
- pr_info("option \"volatile\" is meaningless in a non-upper mount, ignoring it.\n");
+ if (!config->upperdir && set.fsync) {
+ pr_info("options \"fsync\" and \"volatile\" are meaningless in a non-upper mount, ignoring them.\n");
config->fsync_mode = ovl_fsync_mode_def();
}
diff --git a/fs/overlayfs/params.h b/fs/overlayfs/params.h
index ffd53cdd8482..5f3572b270f3 100644
--- a/fs/overlayfs/params.h
+++ b/fs/overlayfs/params.h
@@ -15,6 +15,7 @@ struct ovl_opt_set {
bool redirect;
bool nfs_export;
bool index;
+ bool fsync;
};
#define OVL_MAX_STACK 500
@@ -42,3 +43,4 @@ int ovl_fs_params_verify(const struct ovl_fs_context *ctx,
struct ovl_config *config);
int ovl_show_options(struct seq_file *m, struct dentry *dentry);
const char *ovl_xino_mode(struct ovl_config *config);
+int ovl_fsync_mode_def(void);
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 19b6d54c4500..81da70fd53a6 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -15,6 +15,7 @@
#include <linux/seq_file.h>
#include <linux/posix_acl_xattr.h>
#include <linux/exportfs.h>
+#include <linux/backing-dev.h>
#include <linux/file.h>
#include <linux/fs_context.h>
#include <linux/fs_parser.h>
@@ -737,6 +738,11 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
if (!rename_whiteout)
pr_warn("upper fs does not support RENAME_WHITEOUT.\n");
+ /* fsync=auto that is not resolved to fsync=relaxed means fsync=on */
+ if (ofs->config.fsync_mode == OVL_FSYNC_AUTO && rename_whiteout &&
+ mnt->mnt_sb->s_bdi != &noop_backing_dev_info)
+ ofs->config.fsync_mode = OVL_FSYNC_RELAXED;
+
/*
* Check if upper/work fs supports (trusted|user).overlay.* xattr
*/
@@ -789,9 +795,9 @@ static int ovl_make_workdir(struct super_block *sb, struct ovl_fs *ofs,
/*
* For volatile mount, create a incompat/volatile/dirty file to keep
- * track of it.
+ * track of it. fsync=off allows mounting the overlay again.
*/
- if (ovl_is_volatile(&ofs->config)) {
+ if (ofs->config.fsync_mode == OVL_FSYNC_VOLATILE) {
err = ovl_create_volatile_dirty(ofs);
if (err < 0) {
pr_err("Failed to create volatile/dirty file.\n");
@@ -1456,6 +1462,18 @@ static int ovl_fill_super_creds(struct fs_context *fc, struct super_block *sb)
return err;
upper_sb = ovl_upper_mnt(ofs)->mnt_sb;
+ /*
+ * An upper fs without writeback has nothing to sync and nothing
+ * to lose, so every fsync mode behaves like fsync=off. Keep the
+ * default mode, which is not shown in mountinfo.
+ */
+ if (upper_sb->s_bdi == &noop_backing_dev_info &&
+ ofs->config.fsync_mode != ovl_fsync_mode_def() &&
+ ofs->config.fsync_mode != OVL_FSYNC_OFF) {
+ pr_warn("upper fs does not support writeback, falling back to fsync=off.\n");
+ ofs->config.fsync_mode = OVL_FSYNC_OFF;
+ }
+
if (!ovl_should_sync(ofs)) {
ofs->errseq = errseq_sample(&upper_sb->s_wb_err);
if (errseq_check(&upper_sb->s_wb_err, ofs->errseq)) {
--
2.55.0
next prev parent reply other threads:[~2026-11-06 13:37 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-06 13:36 [PATCH v4 0/8] ovl: only sync what was written through the overlay Josef Bacik
2026-11-06 13:36 ` Josef Bacik [this message]
2026-11-06 13:36 ` [PATCH v4 2/8] ovl: setup overlayfs' private bdi Josef Bacik
2026-11-06 13:36 ` [PATCH v4 3/8] ovl: make the root inode appear hashed Josef Bacik
2026-11-06 13:36 ` [PATCH v4 4/8] ovl: mark the overlay inode dirty on modification Josef Bacik
2026-11-06 13:36 ` [PATCH v4 5/8] ovl: implement overlayfs' own ->write_inode operation Josef Bacik
2026-11-06 13:36 ` [PATCH v4 6/8] ovl: cache dirty overlayfs' inode Josef Bacik
2026-11-06 13:36 ` [PATCH v4 7/8] ovl: handle lazytime on the upper filesystem Josef Bacik
2026-11-06 13:36 ` [PATCH v4 8/8] 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=20261106-b4-ovl-containerized-sync-v4-1-6ddde0b7dd8a@toxicpanda.com \
--to=josef@toxicpanda.com \
--cc=amir73il@gmail.com \
--cc=brauner@kernel.org \
--cc=cgxu519@mykernel.net \
--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®