On Jul 31, 2023, at 6:25 AM, Vitaliy Kuznetsov <vk.en.mail@xxxxxxxxx> wrote: > > This patch introduces a mechanism to periodically check and update > the superblock within the ext4 file system. The main purpose of this > patch is to keep the disk superblock up to date. The update will be > performed if more than one hour has passed since the last update, and > if more than 16MB of data have been written to disk. > > This check and update is performed within the ext4_journal_commit_callback > function, ensuring that the superblock is written while the disk is > active, rather than based on a timer that may trigger during disk idle > periods. > > Discussion https://www.spinics.net/lists/linux-ext4/msg85865.html > > Signed-off-by: Vitaliy Kuznetsov <vk.en.mail@xxxxxxxxx> Thanks for sending the patch. Reviewed-by: Andreas Dilger <adilger@xxxxxxxxx> > --- > fs/ext4/super.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ > fs/ext4/sysfs.c | 4 ++-- > 2 files changed, 54 insertions(+), 2 deletions(-) > > diff --git a/fs/ext4/super.c b/fs/ext4/super.c > index c94ebf704616..2159e9705404 100644 > --- a/fs/ext4/super.c > +++ b/fs/ext4/super.c > @@ -433,6 +433,57 @@ static time64_t __ext4_get_tstamp(__le32 *lo, __u8 *hi) > #define ext4_get_tstamp(es, tstamp) \ > __ext4_get_tstamp(&(es)->tstamp, &(es)->tstamp ## _hi) > > +#define EXT4_SB_REFRESH_INTERVAL_SEC (3600) /* seconds (1 hour) */ > +#define EXT4_SB_REFRESH_INTERVAL_KB (16384) /* kilobytes (16MB) */ > + > +/* > + * The ext4_maybe_update_superblock() function checks and updates the > + * superblock if needed. > + * > + * This function is designed to update the on-disk superblock only under > + * certain conditions to prevent excessive disk writes and unnecessary > + * waking of the disk from sleep. The superblock will be updated if: > + * 1. More than an hour has passed since the last superblock update, and > + * 2. More than 16MB have been written since the last superblock update. > + * > + * @sb: The superblock > + */ > +static void ext4_maybe_update_superblock(struct super_block *sb) > +{ > + struct ext4_sb_info *sbi = EXT4_SB(sb); > + struct ext4_super_block *es = sbi->s_es; > + journal_t *journal = sbi->s_journal; > + time64_t now; > + __u64 last_update; > + __u64 lifetime_write_kbytes; > + __u64 diff_size; > + > + if (sb_rdonly(sb) || !(sb->s_flags & SB_ACTIVE) || > + !journal || (journal->j_flags & JBD2_UNMOUNT)) > + return; > + > + now = ktime_get_real_seconds(); > + last_update = ext4_get_tstamp(es, s_wtime); > + > + if (likely(now - last_update < EXT4_SB_REFRESH_INTERVAL_SEC)) > + return; > + > + lifetime_write_kbytes = sbi->s_kbytes_written + > + ((part_stat_read(sb->s_bdev, sectors[STAT_WRITE]) - > + sbi->s_sectors_written_start) >> 1); > + > + /* Get the number of kilobytes not written to disk to account > + * for statistics and compare with a multiple of 16 MB. This > + * is used to determine when the next superblock commit should > + * occur (i.e. not more often than once per 16MB if there was > + * less written in an hour). > + */ > + diff_size = lifetime_write_kbytes - le64_to_cpu(es->s_kbytes_written); > + > + if (diff_size > EXT4_SB_REFRESH_INTERVAL_KB) > + schedule_work(&EXT4_SB(sb)->s_error_work); > +} > + > /* > * The del_gendisk() function uninitializes the disk-specific data > * structures, including the bdi structure, without telling anyone > @@ -459,6 +510,7 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn) > BUG_ON(txn->t_state == T_FINISHED); > > ext4_process_freed_data(sb, txn->t_tid); > + ext4_maybe_update_superblock(sb); > > spin_lock(&sbi->s_md_lock); > while (!list_empty(&txn->t_private_list)) { > diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c > index 6d332dff79dd..9f334de4f636 100644 > --- a/fs/ext4/sysfs.c > +++ b/fs/ext4/sysfs.c > @@ -515,7 +515,8 @@ static const struct kobj_type ext4_feat_ktype = { > > void ext4_notify_error_sysfs(struct ext4_sb_info *sbi) > { > - sysfs_notify(&sbi->s_kobj, NULL, "errors_count"); > + if (sbi->s_add_error_count > 0) > + sysfs_notify(&sbi->s_kobj, NULL, "errors_count"); > } > > static struct kobject *ext4_root; > @@ -605,4 +606,3 @@ void ext4_exit_sysfs(void) > remove_proc_entry(proc_dirname, NULL); > ext4_proc_root = NULL; > } > - > -- Cheers, Andreas
Attachment:
signature.asc
Description: Message signed with OpenPGP