Index: linux-4.18.0-80.1.2.el8_0/fs/ext4/ext4.h =================================================================== --- linux-4.18.0-80.1.2.el8_0.orig/fs/ext4/ext4.h +++ linux-4.18.0-80.1.2.el8_0/fs/ext4/ext4.h @@ -2555,6 +2555,8 @@ extern void ext4_end_bitmap_read(struct /* mballoc.c */ extern const struct file_operations ext4_seq_prealloc_table_fops; extern const struct seq_operations ext4_mb_seq_groups_ops; +extern const struct file_operations ext4_seq_mb_last_group_fops; +extern int ext4_mb_seq_last_start_seq_show(struct seq_file *m, void *v); extern long ext4_mb_stats; extern long ext4_mb_max_to_scan; extern int ext4_mb_init(struct super_block *); Index: linux-4.18.0-80.1.2.el8_0/fs/ext4/mballoc.c =================================================================== --- linux-4.18.0-80.1.2.el8_0.orig/fs/ext4/mballoc.c +++ linux-4.18.0-80.1.2.el8_0/fs/ext4/mballoc.c @@ -2459,6 +2459,65 @@ static struct kmem_cache *get_groupinfo_ return cachep; } +#define EXT4_MB_MAX_INPUT_STRING_SIZE 32 + +static ssize_t ext4_mb_last_group_write(struct file *file, + const char __user *buf, + size_t cnt, loff_t *pos) +{ + char dummy[EXT4_MB_MAX_INPUT_STRING_SIZE + 1]; + struct super_block *sb = PDE_DATA(file_inode(file)); + struct ext4_sb_info *sbi = EXT4_SB(sb); + unsigned long val; + char *end; + + if (cnt > EXT4_MB_MAX_INPUT_STRING_SIZE) + return -EINVAL; + if (copy_from_user(dummy, buf, cnt)) + return -EFAULT; + dummy[cnt] = '\0'; + val = simple_strtoul(dummy, &end, 0); + if (dummy == end) + return -EINVAL; + if (val >= ext4_get_groups_count(sb)) + return -ERANGE; + spin_lock(&sbi->s_md_lock); + sbi->s_mb_last_group = val; + sbi->s_mb_last_start = 0; + spin_unlock(&sbi->s_md_lock); + return cnt; +} + +static int ext4_mb_seq_last_group_seq_show(struct seq_file *m, void *v) +{ + struct ext4_sb_info *sbi = EXT4_SB(m->private); + + seq_printf(m , "%ld\n", sbi->s_mb_last_group); + return 0; +} + +static int ext4_mb_seq_last_group_open(struct inode *inode, struct file *file) +{ + return single_open(file, ext4_mb_seq_last_group_seq_show, PDE_DATA(inode)); +} + +const struct file_operations ext4_seq_mb_last_group_fops = { + .owner = THIS_MODULE, + .open = ext4_mb_seq_last_group_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, + .write = ext4_mb_last_group_write, +}; + +int ext4_mb_seq_last_start_seq_show(struct seq_file *m, void *v) +{ + struct ext4_sb_info *sbi = EXT4_SB(m->private); + + seq_printf(m , "%ld\n", sbi->s_mb_last_start); + return 0; +} + /* * Allocate the top-level s_group_info array for the specified number * of groups Index: linux-4.18.0-80.1.2.el8_0/fs/ext4/sysfs.c =================================================================== --- linux-4.18.0-80.1.2.el8_0.orig/fs/ext4/sysfs.c +++ linux-4.18.0-80.1.2.el8_0/fs/ext4/sysfs.c @@ -393,6 +393,10 @@ int ext4_register_sysfs(struct super_blo &ext4_mb_seq_groups_ops, sb); proc_create_data("prealloc_table", S_IRUGO, sbi->s_proc, &ext4_seq_prealloc_table_fops, sb); + proc_create_data("mb_last_group", S_IRUGO, sbi->s_proc, + &ext4_seq_mb_last_group_fops, sb); + proc_create_single_data("mb_last_start", S_IRUGO, sbi->s_proc, + ext4_mb_seq_last_start_seq_show, sb); } return 0; }