[PATCH v2 01/10] ovl: setup overlayfs' private bdi

From: Josef Bacik

Date: Wed Oct 28 2026 - 21:09:53 EST


From: Chengguang Xu <charliecgxu@xxxxxxxxxxx>

Setup overlayfs' private bdi so that we can collect
overlayfs' own dirty inodes.

Signed-off-by: Chengguang Xu <charliecgxu@xxxxxxxxxxx>
[josef: only for an overlay that tracks dirty inodes, add
ovl_tracks_dirty()]
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
---
fs/overlayfs/overlayfs.h | 17 +++++++++++++++++
fs/overlayfs/super.c | 7 +++++++
2 files changed, 24 insertions(+)

diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 92da556598da..aa6c2d005a40 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/uuid.h>
#include <linux/fs.h>
+#include <linux/backing-dev.h>
#include <linux/fsverity.h>
#include <linux/namei.h>
#include <linux/posix_acl.h>
@@ -663,6 +664,22 @@ static inline bool ovl_should_sync(struct ovl_fs *ofs)
return ofs->config.fsync_mode != OVL_FSYNC_VOLATILE;
}

+/*
+ * Does this overlay track the upper inodes that are modified through it, so
+ * that syncfs() and unmount only have to sync those?
+ *
+ * There is nothing to track without an upper filesystem, and a volatile overlay
+ * never syncs. sync_filesystem() does not write any inodes of a filesystem
+ * that has no writeback, like tmpfs, and nothing ever clears their dirty flags.
+ */
+static inline bool ovl_tracks_dirty(struct ovl_fs *ofs)
+{
+ if (!ovl_upper_mnt(ofs) || !ovl_should_sync(ofs))
+ return false;
+
+ return ovl_upper_mnt(ofs)->mnt_sb->s_bdi != &noop_backing_dev_info;
+}
+
static inline bool ovl_should_sync_metadata(struct ovl_fs *ofs)
{
return ofs->config.fsync_mode == OVL_FSYNC_STRICT;
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 19b6d54c4500..ce3e30235ae9 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -1455,6 +1455,13 @@ static int ovl_fill_super_creds(struct fs_context *fc, struct super_block *sb)
if (err)
return err;

+ /* Dirty overlay inodes go on the lists of this bdi */
+ if (ovl_tracks_dirty(ofs)) {
+ err = super_setup_bdi(sb);
+ if (err)
+ return err;
+ }
+
upper_sb = ovl_upper_mnt(ofs)->mnt_sb;
if (!ovl_should_sync(ofs)) {
ofs->errseq = errseq_sample(&upper_sb->s_wb_err);

--
2.55.0