mballoc: fix hot spins after err_freebuddy and err_freemeta
PATCH 1/1 mballoc: fix hot spins after err_freebuddy and err_freemeta
ext4_mb_init_backend() has a variable i of type ext4_group_t. which is typedefined in include/linux/ext4_fs_i.h:34 to unsigned long. Since unsigned, i >= 0 is always true, so fix hot spins after err_freebuddy and err_freemeta.
---
fs/ext4/mballoc.c +5 -5
@@ -2618,14 +2618,14 @@ static int ext4_mb_init_backend(struct super_block *sb)return 0 ; err_freebuddy: -while (i >=0 ) { +do {kfree (ext4_get_group_info (sb, i)); - i--; - } - i = num_meta_group_infos; + }while (i-- !=0 ); + i = num_meta_group_infos -1 ; err_freemeta: -while (--i >=0 ) +do {kfree (sbi->s_group_info[i]); + }while (i-- !=0 );iput (sbi->s_buddy_cache); err_freesgi:kfree (sbi->s_group_info);
fs/ext4/mballoc.c static int ext4_mb_init_backend(struct super_block *sb) · line 2618
Quoted 12 lines · Roel Kluin
ext4_mb_init_backend()has a variable i of typeext4_group_t. which is typedefined ininclude/linux/ext4_fs_i.h:34to unsigned long. Since unsigned, i >= 0 is always true, so fix hot spins aftererr_freebuddyanderr_freemeta.Signed-off-by Roel Kluin <[email protected]>---
fs/ext4/mballoc.c +0
-0@@ -2618,14 +2618,14 @@ static int ext4_mb_init_backend(struct super_block *sb)return 0 ;
The function needs more changes. For ex:
2279 if (meta_group_info[j] == NULL) {
2280 printk(KERN_ERR "EXT4-fs: can't allocate buddy mem\n"); 2281 i--; 2282 goto err_freebuddy;
2283 }
That decrement i--; could result in bad value if i == 0;.
Quoted 8 lines
fs/ext4/mballoc.c +1
-4err_freebuddy: -while (i >=0 ) { + do { kfree(ext4_get_group_info(sb, i)); - i--; - } - i = num_meta_group_infos;
fs/ext4/mballoc.c static int ext4_mb_init_backend(struct super_block *sb) · line 2631
Quoted 10 lines
fs/ext4/mballoc.c +4
-1+ }while (i-- !=0 ); + i = num_meta_group_infos -1 ; err_freemeta: -while (--i >=0 ) +do {kfree (sbi->s_group_info[i]); + }while (i-- !=0 );iput (sbi->s_buddy_cache); err_freesgi:kfree (sbi->s_group_info);
-aneesh
PATCH v2 1/1 mballoc: fix hot spins after err_freebuddy and err_freemeta
Quoted 9 lines · Aneesh Kumar K.V
The function needs more changes. For ex:
2279 if (meta_group_info[j] == NULL) {
2280 printk(KERN_ERR "EXT4-fs: can't allocate buddy mem\n"); 2281 i--; 2282 goto err_freebuddy;2283 }
That decrement i--; could result in bad value if i == 0;.
Thanks Aneesh,
---
ext4_mb_init_backend() has a variable i of type ext4_group_t. which is typedefined in include/linux/ext4_fs_i.h:34 to unsigned long. Since unsigned, i >= 0 is always true, so fix hot spins after err_freebuddy and err_freemeta.
Also when meta_group_info cannot be allocated prevent a decrement of i when zero.
---
fs/ext4/mballoc.c +12 -7
@@ -2572,8 +2572,13 @@ static int ext4_mb_init_backend(struct super_block *sb) meta_group_info[j] =kzalloc (len,GFP_KERNEL );if (meta_group_info[j] ==NULL ) {printk (KERN_ERR "EXT4-fs: can't allocate buddy mem\n" ); - i--; - goto err_freebuddy; +if (i !=0 ) { + i--; + goto err_freebuddy; + }else { + i = num_meta_group_infos -1 ; + goto err_freemeta; + } } desc =ext4_get_group_desc (sb, i,NULL );if (desc ==NULL ) {
@@ -2618,14 +2623,14 @@ static int ext4_mb_init_backend(struct super_block *sb)return 0 ; err_freebuddy: -while (i >=0 ) { +do {kfree (ext4_get_group_info (sb, i)); - i--; - } - i = num_meta_group_infos; + }while (i-- !=0 ); + i = num_meta_group_infos -1 ; err_freemeta: -while (--i >=0 ) +do {kfree (sbi->s_group_info[i]); + }while (i-- !=0 );iput (sbi->s_buddy_cache); err_freesgi:kfree (sbi->s_group_info);
Quoted 53 lines · Roel Kluin
Quoted 9 lines · Aneesh Kumar K.V
The function needs more changes. For ex:
2279 if (meta_group_info[j] == NULL) {
2280 printk(KERN_ERR "EXT4-fs: can't allocate buddy mem\n"); 2281 i--; 2282 goto err_freebuddy;2283 }
That decrement i--; could result in bad value if i == 0;.
Thanks Aneesh,
---Signed-off-by Roel Kluin <[email protected]>
ext4_mb_init_backend()has a variable i of typeext4_group_t. which is typedefined ininclude/linux/ext4_fs_i.h:34to unsigned long. Since unsigned, i >= 0 is always true, so fix hot spins aftererr_freebuddyanderr_freemeta.
Also whenmeta_group_infocannot be allocated prevent a decrement of i when zero.Signed-off-by Roel Kluin <[email protected]>---
fs/ext4/mballoc.c +8
-6@@ -2572,8 +2572,13 @@ static int ext4_mb_init_backend(struct super_block *sb) meta_group_info[j] =kzalloc (len,GFP_KERNEL );if (meta_group_info[j] ==NULL ) {printk (KERN_ERR "EXT4-fs: can't allocate buddy mem\n" ); - i--; - goto err_freebuddy; +if (i !=0 ) { + i--; + goto err_freebuddy; + }else { + i = num_meta_group_infos -1 ; + goto err_freemeta; + } } desc =ext4_get_group_desc (sb, i,NULL );if (desc ==NULL ) {@@ -2618,14 +2623,14 @@ static int ext4_mb_init_backend(struct super_block *sb)return 0 ; err_freebuddy: -while (i >=0 ) { + do { kfree(ext4_get_group_info(sb, i)); - i--; - } - i = num_meta_group_infos;
fs/ext4/mballoc.c static int ext4_mb_init_backend(struct super_block *sb) · line 2636
Quoted 10 lines
fs/ext4/mballoc.c +4
-1+ }while (i-- !=0 ); + i = num_meta_group_infos -1 ; err_freemeta: -while (--i >=0 ) +do {kfree (sbi->s_group_info[i]); + }while (i-- !=0 );iput (sbi->s_buddy_cache); err_freesgi:kfree (sbi->s_group_info);
Won't this also have a memory corruption ? Let's say we fail in the first loop itslef. That's with i = 0, and since we are using kmalloc. we may find sbi->s_group_info[0] having some random values. So the kfree can crash. Why not a simple change like below ?
fs/ext4/mballoc.c +3 -2
@@ -2223,7 +2223,7 @@ static noinline void ext4_mb_store_history(struct ext4_allocation_context *ac)static int ext4_mb_init_backend (struct super_block *sb) { -ext4_group_t i; +long i;/* should be able to store group number */ int j, len, metalen;struct ext4_sb_info *sbi =EXT4_SB (sb); int num_meta_group_infos =
@@ -2257,6 +2257,7 @@ static int ext4_mb_init_backend(struct super_block *sb)if (meta_group_info ==NULL ) {printk (KERN_ERR "EXT4-fs: can't allocate mem for a " "buddy group\n" ); + i--; goto err_freemeta; } sbi->s_group_info[i] = meta_group_info;
@@ -2328,7 +2329,7 @@ err_freebuddy:kfree (ext4_get_group_info (sb, i)); i--; } - i = num_meta_group_infos; + i = num_meta_group_infos -1 ; err_freemeta:while (--i >=0 )kfree (sbi->s_group_info[i]);
Quoted 61 lines · Aneesh Kumar K.V
Quoted 60 lines · Roel Kluin
Quoted 9 lines · Aneesh Kumar K.V
The function needs more changes. For ex:
2279 if (meta_group_info[j] == NULL) {
2280 printk(KERN_ERR "EXT4-fs: can't allocate buddy mem\n"); 2281 i--; 2282 goto err_freebuddy;2283 }
That decrement i--; could result in bad value if i == 0;.
Thanks Aneesh,
---Signed-off-by Roel Kluin <[email protected]>
ext4_mb_init_backend()has a variable i of typeext4_group_t. which is typedefined ininclude/linux/ext4_fs_i.h:34to unsigned long. Since unsigned, i >= 0 is always true, so fix hot spins aftererr_freebuddyanderr_freemeta.
Also whenmeta_group_infocannot be allocated prevent a decrement of i when zero.Signed-off-by Roel Kluin <[email protected]>---
fs/ext4/mballoc.c +12
-7@@ -2572,8 +2572,13 @@ static int ext4_mb_init_backend(struct super_block *sb) meta_group_info[j] =kzalloc (len,GFP_KERNEL );if (meta_group_info[j] ==NULL ) {printk (KERN_ERR "EXT4-fs: can't allocate buddy mem\n" ); - i--; - goto err_freebuddy; +if (i !=0 ) { + i--; + goto err_freebuddy; + }else { + i = num_meta_group_infos -1 ; + goto err_freemeta; + } } desc =ext4_get_group_desc (sb, i,NULL );if (desc ==NULL ) {@@ -2618,14 +2623,14 @@ static int ext4_mb_init_backend(struct super_block *sb)return 0 ; err_freebuddy: -while (i >=0 ) { +do {kfree (ext4_get_group_info (sb, i)); - i--; - } - i = num_meta_group_infos; + }while (i-- !=0 ); + i = num_meta_group_infos -1 ; err_freemeta: -while (--i >=0 ) +do {kfree (sbi->s_group_info[i]); + }while (i-- !=0 );iput (sbi->s_buddy_cache);
Quoted 9 lines
fs/ext4/mballoc.c static int ext4_mb_init_backend(struct super_block *sb) · line 2636
Quoted 3 lines
fs/ext4/mballoc.c +0
-0err_freesgi:kfree (sbi->s_group_info);Won't this also have a memory corruption ? Let's say we fail in the first loop itslef. That's with i = 0, and since we are using kmalloc. we may find sbi->s_group_info[0] having some random values. So the kfree can crash. Why not a simple change like below ?
Updated one.
fs/ext4/mballoc.c +6 -3
@@ -2223,7 +2223,7 @@ static noinline void ext4_mb_store_history(struct ext4_allocation_context *ac)static int ext4_mb_init_backend (struct super_block *sb) { -ext4_group_t i; +long i;/* should be able to store group number */ int j, len, metalen;struct ext4_sb_info *sbi =EXT4_SB (sb); int num_meta_group_infos =
@@ -2257,6 +2257,7 @@ static int ext4_mb_init_backend(struct super_block *sb)if (meta_group_info ==NULL ) {printk (KERN_ERR "EXT4-fs: can't allocate mem for a " "buddy group\n" ); + i--; goto err_freemeta; } sbi->s_group_info[i] = meta_group_info;
@@ -2328,10 +2329,12 @@ err_freebuddy:kfree (ext4_get_group_info (sb, i)); i--; } - i = num_meta_group_infos; + i = num_meta_group_infos -1 ; err_freemeta: -while (--i >=0 ) +while (i >=0 ) {kfree (sbi->s_group_info[i]); + i--; + }iput (sbi->s_buddy_cache); err_freesgi:kfree (sbi->s_group_info);
Quoted 14 lines · Aneesh Kumar K.V
Quoted 12 lines · Aneesh Kumar K.V
Quoted 11 lines · Roel Kluin
Quoted 9 lines · Aneesh Kumar K.V
The function needs more changes. For ex:
2279 if (meta_group_info[j] == NULL) {
2280 printk(KERN_ERR "EXT4-fs: can't allocate buddy mem\n"); 2281 i--; 2282 goto err_freebuddy;2283 }
That decrement i--; could result in bad value if i == 0;.
Quoted 8 lines
Quoted 5 lines
Won't this also have a memory corruption ? Let's say we fail in the first loop itslef. That's with i = 0, and since we are using kmalloc. we may find sbi->s_group_info[0] having some random values. So the kfree can crash. Why not a simple change like below ?
Updated one.
Won't this work as well?
---
In ext4_mb_init_backend() 'i' is of type ext4_group_t. Since unsigned, i >= 0 is always true, so fix hot spins after err_freebuddy: and -meta: and prevent decrements when zero.
---
fs/ext4/mballoc.c +3 -5
@@ -2572,13 +2572,13 @@ static int ext4_mb_init_backend(struct super_block *sb) meta_group_info[j] =kzalloc (len,GFP_KERNEL );if (meta_group_info[j] ==NULL ) {printk (KERN_ERR "EXT4-fs: can't allocate buddy mem\n" ); - i--; goto err_freebuddy; } desc =ext4_get_group_desc (sb, i,NULL );if (desc ==NULL ) {printk (KERN_ERR "EXT4-fs: can't read descriptor %lu\n" , i); + i++; goto err_freebuddy; }memset (meta_group_info[j],0 , len);
@@ -2618,13 +2618,11 @@ static int ext4_mb_init_backend(struct super_block *sb)return 0 ; err_freebuddy: -while (i >=0 ) { +while (i-- >0 )kfree (ext4_get_group_info (sb, i)); - i--; - } i = num_meta_group_infos; err_freemeta: -while (--i >=0 ) +while (i-- >0 )kfree (sbi->s_group_info[i]);iput (sbi->s_buddy_cache); err_freesgi: