ext4: reduce unnecessary memory allocation in alloc_flex_gd()
authorBaokun Li <libaokun1@huawei.com>
Mon, 23 Oct 2023 01:30:57 +0000 (09:30 +0800)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 14 Dec 2023 15:54:47 +0000 (10:54 -0500)
When a large flex_bg file system is resized, the number of groups to be
added may be small, and a large amount of memory that will not be used will
be allocated. Therefore, resize_bg can be set to the size after the number
of new_group_data to be used is aligned upwards to the power of 2. This
does not affect the disk layout after online resize and saves some memory.

Signed-off-by: Baokun Li <libaokun1@huawei.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Link: https://lore.kernel.org/r/20231023013057.2117948-5-libaokun1@huawei.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
fs/ext4/resize.c

index e168a9f596001c299b8bf70b83c5b25b642cf44f..4d4a5a32e310d43bb57f6d8bd2561debe882b724 100644 (file)
@@ -235,8 +235,10 @@ struct ext4_new_flex_group_data {
  *
  * Returns NULL on failure otherwise address of the allocated structure.
  */
-static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned int flexbg_size)
+static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned int flexbg_size,
+                               ext4_group_t o_group, ext4_group_t n_group)
 {
+       ext4_group_t last_group;
        struct ext4_new_flex_group_data *flex_gd;
 
        flex_gd = kmalloc(sizeof(*flex_gd), GFP_NOFS);
@@ -248,6 +250,14 @@ static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned int flexbg_size)
        else
                flex_gd->resize_bg = flexbg_size;
 
+       /* Avoid allocating large 'groups' array if not needed */
+       last_group = o_group | (flex_gd->resize_bg - 1);
+       if (n_group <= last_group)
+               flex_gd->resize_bg = 1 << fls(n_group - o_group + 1);
+       else if (n_group - last_group < flex_gd->resize_bg)
+               flex_gd->resize_bg = 1 << max(fls(last_group - o_group + 1),
+                                             fls(n_group - last_group));
+
        flex_gd->groups = kmalloc_array(flex_gd->resize_bg,
                                        sizeof(struct ext4_new_group_data),
                                        GFP_NOFS);
@@ -2131,7 +2141,7 @@ retry:
        if (err)
                goto out;
 
-       flex_gd = alloc_flex_gd(flexbg_size);
+       flex_gd = alloc_flex_gd(flexbg_size, o_group, n_group);
        if (flex_gd == NULL) {
                err = -ENOMEM;
                goto out;