From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=209.85.219.49 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1793972223; b=LxC+06e9qr24ct41k21F7KJGkKsnYvLq+iTaunKZcloSvku4KbKsUxfxhis+NkCHFmoT z2BAyz9b+T5o78Cfo+5t+rktP38GF7b8C2y6g9JXAaFWb7nfEs50pTUn7IkHNyDJU+Vnc uxubKxpe5/oByCriWKlZVS9Z1THGYlIS4vZH1Fg4VsmiqT6aBNF2SX7TkC3pp7Nsl6jbA NbwRj+sVQDwSXvF+BW/0BBdHW3aw8bX34BZrgKzAtMa7ZCa5Deq+dM/33a4uBBatkztnu ciufy+1cvyFmDR+9Bpqse76FDxnITaihDslP9s0KJ9MxhnzhVxDVLDl9rfN1Keajkxw== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793972223; h=DMARC-Filter:Received:DKIM-Signature:X-Google-DKIM-Signature: X-Forwarded-Encrypted:X-Gm-Message-State:X-Gm-Gg:X-Received:Received: From:Date:Subject:MIME-Version:Content-Type:Content-Transfer-Encoding: Message-Id:References:In-Reply-To:To:Cc:X-Mailer: X-Developer-Signature:X-Developer-Key; bh=R22Hkg58AODA+U2Qc/D03rkLftDWo9zEEkg5H+BLiYE=; b=ZUTT42949jNAqiKBm8NPyaI/UpajjIZKiDjQB1MnkH9AzUC4BBIld5pZyBfMGrhaQAHy VtwSy56daS/vTACWiNMz7/UkjY17m7gPNJA1yc0HCnvpf5brTVDvvr1xumoAsiuZOB/kA zn92kSCHhpScfI+mE4EU9I5sBUA/7tM+QrJ0+Xgx/ioomPKUWVpILysVXZxkZaXyQA+9Y UXdCTo1c5VfgX1bvswB4PNjNs8HzMRfAyd0TWONU7BCPg3/7brtswMjUXQOu4wFqgCU7y w2E+LANaaJLXQTXPoZbC7p1aqyrza7Z4cpLtguLmMuGJkBo62H0Ic1IHk7oLjqRrrCw== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none header.from=toxicpanda.com; spf=pass smtp.mailfrom=toxicpanda.com; dkim=pass header.d=toxicpanda.com header.i=@toxicpanda.com header.a=rsa-sha256 header.s=google header.b=gkWNNu78; arc=none smtp.remote-ip=209.85.219.49 Received: from mail-qv1-f49.google.com (mail-qv1-f49.google.com [209.85.219.49]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A4173606A333 for ; Fri, 6 Nov 2026 13:37:02 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org A4173606A333 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=toxicpanda.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key, unprotected) header.d=toxicpanda.com header.i=@toxicpanda.com header.a=rsa-sha256 header.s=google header.b=gkWNNu78 Received: by mail-qv1-f49.google.com with SMTP id 6a1803df08f44-91c60e30054so6771056d6.1 for ; Fri, 06 Nov 2026 05:37:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda.com; s=google; t=1793972221; x=1794577021; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=R22Hkg58AODA+U2Qc/D03rkLftDWo9zEEkg5H+BLiYE=; b=gkWNNu78khkp2N7JJzNw53OIVvJ8eQ5FFYZDHuquu9acu4HQLITZ6DV74RUI3eTFjB gINFXaPzBbO3l06TUdPY7eNhpvCgTP7NRMk1aAKAxvBog3XyaP7BjSFN1I6OdNPi9Zkw eQ2wKzfQptD3t3P5A9b3qjpkYMbAJhrs0uJPBb3L1d1AVWmZfqT5PIIcl31vz+My7RLH 1WVOtQmjbc+6COqdaEIyebDCTaREyh5Cqv/xiP4xeX0KO26184ygoCvKZJzSJ9ihtAK3 7p4juAISXuw7pdAuTQ/T0/oLXH76vCjtkXve8yrCnDCmptT0kFMEBwEScuDMKf/xnYG1 KiWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1793972221; x=1794577021; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=R22Hkg58AODA+U2Qc/D03rkLftDWo9zEEkg5H+BLiYE=; b=BS4WoXntX43WM5BKuxskGHVqkEVDwOc6l+lBsBCxpiD59z5MpprZJk2zJ2K+e0AW79 hkyoLhXM+BvQMg8WdJm7K5W5mVwVvjmMv/iu6V3RLv05P78ZHqoOgFTR4bBGFyBJVqFm 25bVJOR+bI0h5YUkDR7MgAxXEfb6r5Ahra62vaJUru5CY/dY6kmzsdGKpJjFndwbJ2+a ci3K/fi2eDo2PwALFoQ5o5SC6B6+DaSpESWLLHKYNaPXZpE0oR4/34dm6K8VLnLKUrcB bAu13s+7oyd5OPVaVvUzZBDMVM1gaqeZUx/njER6AkHkdgQHS3rg6wG55blxFVXy12cA wrAw== X-Forwarded-Encrypted: i=1; AL+hErGIX2Kfg4Owi+ESbj9HMVxiwRorv9flLDIzArzBUmLLCTUo/i7geiwj+1YQ34GaNgpjwV8UEzimV+/TVtU=@vger.kernel.org X-Gm-Message-State: APuU4Z/xAa/ri2xRxNWZTIjmXVCfdPiEdh6Bao5W53bTkT/Szdiev8Lc RH80YhdhogPZkyGN39Gkh6JDwO0U4s83lSjIotwft8XdzL3JZ99bGiAiK1znu4OioA332xFWB1t 8T1FM2TAq1w== X-Gm-Gg: AYBFou3vqwhTx8mSOccxNy3VfAUpAIjYniGO2PmEdvymaZ8LWan63d7NjJFPbmMKtkM KOPO2G7TGeINO5Oc0zUnf0nyTNPJ+oJ+sn61POm2FavYsQ+MZX7vlysuRBCfs8d4wgCkeIsj5mX +ExNAjbQ8x90Knzotio0hR5S0jvpXXLsE6VW2l8+7T7k03d1sggj4R5yQTlS7lQCF7z+j/ZZs9Z xGsfz6WKDNZmvgVjnlKb+vzd2/TcKfldbGtqdZuEVB6qtq3Z0t718YPd/V7pDYGwamuQjGQZqFy c/PKhKX2eVNEOX3BYoV/Q2R23cu/R1tokMayoD34mUtUFNbgA540XDxJP+QLw/e5dwUtXOT6zbJ R5KwGUF9+lvbnruwq0PyJUMIXbUGMtANFtgzm1101HCqLkbgjcUr9tqRXcb050pxfxNBEsp1384 QJRRs1P9FsXVwulfyoGGyw9+5Ix5JqTHRjmYimKInqilebDq7mMyExq0cdC9tN3twlQlY+4Hs6e aWK71dQJ4hCKhxgAKdk56ZKdE717Q8mobeJFtCVNY8K2eYHxof3PKfkqdJ4wcrcXE5L2RCMnExN F322mYapzcj56YSlU+tGT66M8mv67k8D94t3mnWwYN006wQOz1PEkRMAKGgvOS3t7zo= X-Received: by 2002:a05:6214:4b13:b0:91e:87a9:beec with SMTP id 6a1803df08f44-91ea88636fcmr30751606d6.0.1793972221400; Fri, 06 Nov 2026 05:37:01 -0800 (PST) Received: from toxicpanda.com ([153.61.196.254]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-91ea6a638a7sm20768656d6.22.2026.11.06.05.37.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 06 Nov 2026 05:37:00 -0800 (PST) From: Josef Bacik Date: Fri, 06 Nov 2026 13:36:43 +0000 Subject: [PATCH v4 1/8] ovl: expand fsync mount options X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20261106-b4-ovl-containerized-sync-v4-1-6ddde0b7dd8a@toxicpanda.com> References: <20261106-b4-ovl-containerized-sync-v4-0-6ddde0b7dd8a@toxicpanda.com> In-Reply-To: <20261106-b4-ovl-containerized-sync-v4-0-6ddde0b7dd8a@toxicpanda.com> To: Miklos Szeredi , Amir Goldstein , Christian Brauner Cc: Alexander Viro , Jan Kara , Christoph Hellwig , Chris Mason , Chengguang Xu , linux-unionfs@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Josef Bacik X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=openssh-sha256; t=1793972217; l=12726; i=josef@toxicpanda.com; h=from:subject:message-id; bh=zAKuXkDringwd4Kp10q8DoNDDNPh2S1hdJ7wVREgXkc=; b=U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgUBr36M/n0nWN0DNbnxwzIiCZez6MG JiruuNaSCI/zXsAAAAGcGF0YXR0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5AAAA QBEq63KkvULzXOvOmdf6QM0AQwvVzv6RQQRMA6HSdDHk3tRfhv5HCaFAycFgvNFc+vi2wIChMr4 qukNlOF7OGgs= X-Developer-Key: i=josef@toxicpanda.com; a=openssh; fpr=SHA256:C8kOX2QUJCMqnCX+KEeoqRAjLo9L+ELOSH2NSAJHqGA From: Amir Goldstein 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 Signed-off-by: Josef Bacik --- 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 #include #include +#include #include #include #include @@ -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