[RHEL7,COMMIT] ms/ext4: handle the rest of ext4_mb_load_buddy() ENOMEM errors

Submitted by Konstantin Khorenko on Oct. 30, 2019, 3:59 p.m.

Details

Message ID 201910301559.x9UFxTDR013607@finist-ce7.sw.ru
State New
Series "Series without cover letter"
Headers show

Commit Message

Konstantin Khorenko Oct. 30, 2019, 3:59 p.m.
The commit is pushed to "branch-rh7-3.10.0-1062.4.1.vz7.115.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-1062.4.1.vz7.115.3
------>
commit b7602ba4d47e1062ac362bf17b56de9c2aaa8d3b
Author: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
Date:   Wed Oct 30 18:59:29 2019 +0300

    ms/ext4: handle the rest of ext4_mb_load_buddy() ENOMEM errors
    
    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>
    
    https://jira.sw.ru/browse/PSBM-98265
    
    (cherry picked from commit 9651e6b2e20648d04d5e1fe6479a3056047e8781)
    Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
---
 fs/ext4/mballoc.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

Patch hide | download patch | download mbox

diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index d986d0f970d3..af8ffaaea324 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -3872,7 +3872,8 @@  ext4_mb_discard_group_preallocations(struct super_block *sb,
 
 	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;
 	}
@@ -4029,10 +4030,11 @@  void ext4_discard_preallocations(struct inode *inode)
 		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;
 		}
 
@@ -4287,11 +4289,14 @@  ext4_mb_discard_lg_preallocations(struct super_block *sb,
 	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);
@@ -5115,8 +5120,8 @@  ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
 
 	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;