1 Subject: [PATCH] ext4: Add periodic superblock update check
3 This patch introduces a mechanism to periodically check and update
4 the superblock within the ext4 file system. The main purpose of this
5 patch is to keep the disk superblock up to date. The update will be
6 performed if more than one hour has passed since the last update, and
7 if more than 16MB of data have been written to disk.
9 This check and update is performed within the ext4_journal_commit_callback
10 function, ensuring that the superblock is written while the disk is
11 active, rather than based on a timer that may trigger during disk idle
14 Signed-off-by: Vitaliy Kuznetsov <vk.en.mail@gmail.com>
16 fs/ext4/super.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++
18 2 files changed, 50 insertions(+), 1 deletion(-)
20 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
21 index 82da5cc6..758a5b08 100644
24 @@ -440,6 +440,55 @@ static int block_device_ejected(struct super_block *sb)
25 return bdi->dev == NULL;
28 +#define EXT4_SB_REFRESH_INTERVAL_SEC (3600) /* seconds (1 hour) */
29 +#define EXT4_SB_REFRESH_INTERVAL_KB (16384) /* kilobytes (16MB) */
32 + * The ext4_maybe_update_superblock() function checks and updates the
33 + * superblock if needed.
35 + * This function is designed to update the on-disk superblock only under
36 + * certain conditions to prevent excessive disk writes and unnecessary
37 + * waking of the disk from sleep. The superblock will be updated if:
38 + * 1. More than an hour has passed since the last superblock update, and
39 + * 2. More than 16MB have been written since the last superblock update.
41 + * @sb: The superblock
43 +static void ext4_maybe_update_superblock(struct super_block *sb)
45 + struct ext4_sb_info *sbi = EXT4_SB(sb);
46 + struct ext4_super_block *es = sbi->s_es;
49 + __u64 lifetime_write_kbytes;
55 + now = ktime_get_real_seconds();
56 + last_update = ext4_get_tstamp(es, s_wtime);
58 + if (likely(now - last_update < EXT4_SB_REFRESH_INTERVAL_SEC))
61 + lifetime_write_kbytes = sbi->s_kbytes_written +
62 + ((part_stat_read(sb->s_bdev, sectors[STAT_WRITE]) -
63 + sbi->s_sectors_written_start) >> 1);
65 + /* Get the number of kilobytes not written to disk to account
66 + * for statistics and compare with a multiple of 16 MB. This
67 + * is used to determine when the next superblock commit should
68 + * occur (i.e. not more often than once per 16MB if there was
69 + * less written in an hour).
71 + diff_size = lifetime_write_kbytes - le64_to_cpu(es->s_kbytes_written);
73 + if (diff_size > EXT4_SB_REFRESH_INTERVAL_KB)
74 + schedule_work(&EXT4_SB(sb)->s_error_work);
77 static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
79 struct super_block *sb = journal->j_private;
80 @@ -450,6 +499,7 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
81 BUG_ON(txn->t_state == T_FINISHED);
83 ext4_process_freed_data(sb, txn->t_tid);
84 + ext4_maybe_update_superblock(sb);
86 spin_lock(&sbi->s_md_lock);
87 while (!list_empty(&txn->t_private_list)) {
88 diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
89 index cfac5a2e..76f2f6ae 100644
92 @@ -651,4 +651,3 @@ void ext4_exit_sysfs(void)
93 remove_proc_entry(proc_dirname, NULL);
94 ext4_proc_root = NULL;