Whamcloud - gitweb
LU-17888 osd-ldiskfs: osd_scrub_refresh_mapping deadlock
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / ubuntu20.04.3 / ext4-add-periodic-superblock-update.patch
1 Subject: [PATCH] ext4: Add periodic superblock update check
2
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.
8
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
12 periods.
13
14 Signed-off-by: Vitaliy Kuznetsov <vk.en.mail@gmail.com>
15 ---
16  fs/ext4/super.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++
17  fs/ext4/sysfs.c |  1 -
18  2 files changed, 50 insertions(+), 1 deletion(-)
19
20 diff --git a/fs/ext4/super.c b/fs/ext4/super.c
21 index 82da5cc6..758a5b08 100644
22 --- a/fs/ext4/super.c
23 +++ b/fs/ext4/super.c
24 @@ -440,6 +440,55 @@ static int block_device_ejected(struct super_block *sb)
25         return bdi->dev == NULL;
26  }
27  
28 +#define EXT4_SB_REFRESH_INTERVAL_SEC (3600) /* seconds (1 hour) */
29 +#define EXT4_SB_REFRESH_INTERVAL_KB (16384) /* kilobytes (16MB) */
30 +
31 +/*
32 + * The ext4_maybe_update_superblock() function checks and updates the
33 + * superblock if needed.
34 + *
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.
40 + *
41 + * @sb: The superblock
42 + */
43 +static void ext4_maybe_update_superblock(struct super_block *sb)
44 +{
45 +       struct ext4_sb_info *sbi = EXT4_SB(sb);
46 +       struct ext4_super_block *es = sbi->s_es;
47 +       time64_t now;
48 +       __u64 last_update;
49 +       __u64 lifetime_write_kbytes;
50 +       __u64 diff_size;
51 +
52 +       if (sb_rdonly(sb))
53 +               return;
54 +
55 +       now = ktime_get_real_seconds();
56 +       last_update = ext4_get_tstamp(es, s_wtime);
57 +
58 +       if (likely(now - last_update < EXT4_SB_REFRESH_INTERVAL_SEC))
59 +               return;
60 +
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);
64 +
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).
70 +        */
71 +       diff_size = lifetime_write_kbytes - le64_to_cpu(es->s_kbytes_written);
72 +
73 +       if (diff_size > EXT4_SB_REFRESH_INTERVAL_KB)
74 +               schedule_work(&EXT4_SB(sb)->s_error_work);
75 +}
76 +
77  static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
78  {
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);
82  
83         ext4_process_freed_data(sb, txn->t_tid);
84 +       ext4_maybe_update_superblock(sb);
85  
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
90 --- a/fs/ext4/sysfs.c
91 +++ b/fs/ext4/sysfs.c
92 @@ -651,4 +651,3 @@ void ext4_exit_sysfs(void)
93         remove_proc_entry(proc_dirname, NULL);
94         ext4_proc_root = NULL;
95  }
96 -
97 -- 
98 2.25.1
99