Whamcloud - gitweb
LU-16298 ldiskfs: Periodically write ldiskfs superblock
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / rhel9 / ext4-add-periodic-superblock-update.patch
1 From 45c922115d9e44c0d62fd2012ccb4d020bbe8edc Mon Sep 17 00:00:00 2001
2 From: "Vitaliy Kuznetsov" <vk.en.mail@gmail.com>
3 Date: Thu, 15 Jun 2023 11:17:14 +0300
4 Subject: [PATCH] ext4: Add periodic superblock update check
5
6 This patch introduces a mechanism to periodically check and update
7 the superblock within the ext4 file system. The main purpose of this
8 patch is to keep the disk superblock up to date. The update will be
9 performed if more than one hour has passed since the last update, and
10 if more than 16MB of data have been written to disk.
11
12 This check and update is performed within the ext4_journal_commit_callback
13 function, ensuring that the superblock is written while the disk is
14 active, rather than based on a timer that may trigger during disk idle
15 periods.
16
17 Signed-off-by: Vitaliy Kuznetsov <vk.en.mail@gmail.com>
18 ---
19  fs/ext4/super.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++
20  fs/ext4/sysfs.c |  4 ++--
21  2 files changed, 52 insertions(+), 2 deletions(-)
22
23 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
24 index dfa09a277b56..0d2bf85cee34 100644
25 --- a/fs/ext4/super.c
26 +++ b/fs/ext4/super.c
27 @@ -439,6 +439,55 @@ static int block_device_ejected(struct super_block *sb)
28         return bdi->dev == NULL;
29  }
30
31 +#define EXT4_SB_REFRESH_INTERVAL_SEC (3600) /* seconds (1 hour) */
32 +#define EXT4_SB_REFRESH_INTERVAL_KB (16384) /* kilobytes (16MB) */
33 +
34 +/*
35 + * The ext4_maybe_update_superblock() function checks and updates the
36 + * superblock if needed.
37 + *
38 + * This function is designed to update the on-disk superblock only under
39 + * certain conditions to prevent excessive disk writes and unnecessary
40 + * waking of the disk from sleep. The superblock will be updated if:
41 + * 1. More than an hour has passed since the last superblock update, and
42 + * 2. More than 16MB have been written since the last superblock update.
43 + *
44 + * @sb: The superblock
45 + */
46 +static void ext4_maybe_update_superblock(struct super_block *sb)
47 +{
48 +       struct ext4_sb_info *sbi = EXT4_SB(sb);
49 +       struct ext4_super_block *es = sbi->s_es;
50 +       time64_t now;
51 +       __u64 last_update;
52 +       __u64 lifetime_write_kbytes;
53 +       __u64 diff_size;
54 +
55 +       if (sb_rdonly(sb))
56 +               return;
57 +
58 +       now = ktime_get_real_seconds();
59 +       last_update = ext4_get_tstamp(es, s_wtime);
60 +
61 +       if (likely(now - last_update < EXT4_SB_REFRESH_INTERVAL_SEC))
62 +               return;
63 +
64 +       lifetime_write_kbytes = sbi->s_kbytes_written +
65 +               ((part_stat_read(sb->s_bdev, sectors[STAT_WRITE]) -
66 +                 sbi->s_sectors_written_start) >> 1);
67 +
68 +       /* Get the number of kilobytes not written to disk to account
69 +        * for statistics and compare with a multiple of 16 MB. This
70 +        * is used to determine when the next superblock commit should
71 +        * occur (i.e. not more often than once per 16MB if there was
72 +        * less written in an hour).
73 +        */
74 +       diff_size = lifetime_write_kbytes - le64_to_cpu(es->s_kbytes_written);
75 +
76 +       if (diff_size > EXT4_SB_REFRESH_INTERVAL_KB)
77 +               schedule_work(&EXT4_SB(sb)->s_error_work);
78 +}
79 +
80  static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
81  {
82         struct super_block              *sb = journal->j_private;
83 @@ -449,6 +498,7 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
84         BUG_ON(txn->t_state == T_FINISHED);
85
86         ext4_process_freed_data(sb, txn->t_tid);
87 +       ext4_maybe_update_superblock(sb);
88
89         spin_lock(&sbi->s_md_lock);
90         while (!list_empty(&txn->t_private_list)) {
91 diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
92 index 2314f7446592..a7219cc2fdc5 100644
93 --- a/fs/ext4/sysfs.c
94 +++ b/fs/ext4/sysfs.c
95 @@ -508,7 +508,8 @@ static struct kobj_type ext4_feat_ktype = {
96
97  void ext4_notify_error_sysfs(struct ext4_sb_info *sbi)
98  {
99 -       sysfs_notify(&sbi->s_kobj, NULL, "errors_count");
100 +       if (sbi->s_add_error_count > 0)
101 +               sysfs_notify(&sbi->s_kobj, NULL, "errors_count");
102  }
103
104  static struct kobject *ext4_root;
105 @@ -598,4 +599,3 @@ void ext4_exit_sysfs(void)
106         remove_proc_entry(proc_dirname, NULL);
107         ext4_proc_root = NULL;
108  }
109 -
110 --