| From foo@baz Mon Apr 9 17:09:24 CEST 2018 |
| From: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> |
| Date: Sun, 21 May 2017 22:35:23 -0400 |
| Subject: ext4: handle the rest of ext4_mb_load_buddy() ENOMEM errors |
| |
| From: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> |
| |
| |
| [ Upstream commit 9651e6b2e20648d04d5e1fe6479a3056047e8781 ] |
| |
| I've got another report about breaking ext4 by ENOMEM error returned from |
| ext4_mb_load_buddy() caused by memory shortage in memory cgroup. |
| This time inside ext4_discard_preallocations(). |
| |
| This patch replaces ext4_error() with ext4_warning() where errors returned |
| from ext4_mb_load_buddy() are not fatal and handled by caller: |
| * ext4_mb_discard_group_preallocations() - called before generating ENOSPC, |
| we'll try to discard other group or return ENOSPC into user-space. |
| * ext4_trim_all_free() - just stop trimming and return ENOMEM from ioctl. |
| |
| Some callers cannot handle errors, thus __GFP_NOFAIL is used for them: |
| * ext4_discard_preallocations() |
| * ext4_mb_discard_lg_preallocations() |
| |
| Fixes: adb7ef600cc9 ("ext4: use __GFP_NOFAIL in ext4_free_blocks()") |
| Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> |
| Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/ext4/mballoc.c | 23 ++++++++++++++--------- |
| 1 file changed, 14 insertions(+), 9 deletions(-) |
| |
| --- a/fs/ext4/mballoc.c |
| +++ b/fs/ext4/mballoc.c |
| @@ -3877,7 +3877,8 @@ ext4_mb_discard_group_preallocations(str |
| |
| err = ext4_mb_load_buddy(sb, group, &e4b); |
| if (err) { |
| - ext4_error(sb, "Error loading buddy information for %u", group); |
| + ext4_warning(sb, "Error %d loading buddy information for %u", |
| + err, group); |
| put_bh(bitmap_bh); |
| return 0; |
| } |
| @@ -4034,10 +4035,11 @@ repeat: |
| BUG_ON(pa->pa_type != MB_INODE_PA); |
| group = ext4_get_group_number(sb, pa->pa_pstart); |
| |
| - err = ext4_mb_load_buddy(sb, group, &e4b); |
| + err = ext4_mb_load_buddy_gfp(sb, group, &e4b, |
| + GFP_NOFS|__GFP_NOFAIL); |
| if (err) { |
| - ext4_error(sb, "Error loading buddy information for %u", |
| - group); |
| + ext4_error(sb, "Error %d loading buddy information for %u", |
| + err, group); |
| continue; |
| } |
| |
| @@ -4293,11 +4295,14 @@ ext4_mb_discard_lg_preallocations(struct |
| spin_unlock(&lg->lg_prealloc_lock); |
| |
| list_for_each_entry_safe(pa, tmp, &discard_list, u.pa_tmp_list) { |
| + int err; |
| |
| group = ext4_get_group_number(sb, pa->pa_pstart); |
| - if (ext4_mb_load_buddy(sb, group, &e4b)) { |
| - ext4_error(sb, "Error loading buddy information for %u", |
| - group); |
| + err = ext4_mb_load_buddy_gfp(sb, group, &e4b, |
| + GFP_NOFS|__GFP_NOFAIL); |
| + if (err) { |
| + ext4_error(sb, "Error %d loading buddy information for %u", |
| + err, group); |
| continue; |
| } |
| ext4_lock_group(sb, group); |
| @@ -5117,8 +5122,8 @@ ext4_trim_all_free(struct super_block *s |
| |
| ret = ext4_mb_load_buddy(sb, group, &e4b); |
| if (ret) { |
| - ext4_error(sb, "Error in loading buddy " |
| - "information for %u", group); |
| + ext4_warning(sb, "Error %d loading buddy information for %u", |
| + ret, group); |
| return ret; |
| } |
| bitmap = e4b.bd_bitmap; |