Patch "ext4: use __GFP_NOFAIL in ext4_free_blocks()" has been added to the 4.4-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
ext4: use __GFP_NOFAIL in ext4_free_blocks()
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
ext4-use-__gfp_nofail-in-ext4_free_blocks.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
adb7ef600cc9d9d15ecc934cc26af5c1379777dfMon Sep 17 00:00:00 2001
From: Konstantin Khlebnikov <[email protected]>
Date: Sun, 13 Mar 2016 17:29:06 -0400
Subject: ext4: use __GFP_NOFAIL in ext4_free_blocks()
From: Konstantin Khlebnikov <[email protected]>
commit adb7ef600cc9d9d15ecc934cc26af5c1379777df upstream.
This might be unexpected but pages allocated for sbi->s_buddy_cache are charged to current memory cgroup. So, GFP_NOFS allocation could fail if current task has been killed by OOM or if current memory cgroup has no free memory left. Block allocator cannot handle such failures here yet.
--- fs/ext4/mballoc.c | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-)
fs/ext4/mballoc.c +28 -19
@@ -815,7 +815,7 @@ static void mb_regenerate_buddy(struct e* for this page; do not hold this lock when calling this routine! */ -static int ext4_mb_init_cache (struct page *page,char *incore) +static int ext4_mb_init_cache (struct page *page,char *incore,gfp_t gfp) {ext4_group_t ngroups;int blocksize;
@@ -848,7 +848,7 @@ static int ext4_mb_init_cache(struct pag/* allocate buffer_heads to read bitmaps */ if (groups_per_page >1 ) { i =sizeof (struct buffer_head *) * groups_per_page; - bh =kzalloc (i,GFP_NOFS ); + bh =kzalloc (i, gfp);if (bh ==NULL ) { err = -ENOMEM ; goto out;
@@ -983,7 +983,7 @@ out:* are on the same page e4b->bd_buddy_page is NULL and return value is 0. */ static int ext4_mb_get_buddy_page_lock (struct super_block *sb, -ext4_group_t group,struct ext4_buddy *e4b) +ext4_group_t group,struct ext4_buddy *e4b,gfp_t gfp) {struct inode *inode =EXT4_SB (sb)->s_buddy_cache;int block, pnum, poff;
@@ -1002,7 +1002,7 @@ static int ext4_mb_get_buddy_page_lock(s block = group *2 ; pnum = block / blocks_per_page; poff = block % blocks_per_page; - page =find_or_create_page (inode->i_mapping, pnum,GFP_NOFS ); + page =find_or_create_page (inode->i_mapping, pnum, gfp);if (!page)return -ENOMEM ;BUG_ON (page->mapping != inode->i_mapping);
@@ -1016,7 +1016,7 @@ static int ext4_mb_get_buddy_page_lock(s block++; pnum = block / blocks_per_page; - page =find_or_create_page (inode->i_mapping, pnum,GFP_NOFS ); + page =find_or_create_page (inode->i_mapping, pnum, gfp);if (!page)return -ENOMEM ;BUG_ON (page->mapping != inode->i_mapping);
@@ -1042,7 +1042,7 @@ static void ext4_mb_put_buddy_page_lock(* calling this routine! */ static noinline_for_stack -int ext4_mb_init_group(struct super_block *sb, ext4_group_t group) +int ext4_mb_init_group(struct super_block *sb, ext4_group_t group, gfp_t gfp) {struct ext4_group_info *this_grp;
@@ -1062,7 +1062,7 @@ int ext4_mb_init_group(struct super_bloc* The call to ext4_mb_get_buddy_page_lock will mark the * page accessed. */ - ret =ext4_mb_get_buddy_page_lock (sb, group, &e4b); + ret =ext4_mb_get_buddy_page_lock (sb, group, &e4b, gfp);if (ret || !EXT4_MB_GRP_NEED_INIT (this_grp)) {/* * somebody initialized the group
@@ -1072,7 +1072,7 @@ int ext4_mb_init_group(struct super_bloc } page = e4b.bd_bitmap_page; - ret =ext4_mb_init_cache (page,NULL ); + ret =ext4_mb_init_cache (page,NULL , gfp);if (ret) goto err;if (!PageUptodate (page)) {
@@ -1091,7 +1091,7 @@ int ext4_mb_init_group(struct super_bloc }/* init buddy cache */ page = e4b.bd_buddy_page; - ret =ext4_mb_init_cache (page, e4b.bd_bitmap); + ret =ext4_mb_init_cache (page, e4b.bd_bitmap, gfp);if (ret) goto err;if (!PageUptodate (page)) {
@@ -1109,8 +1109,8 @@ err:* calling this routine! */ static noinline_for_stack int -ext4_mb_load_buddy (struct super_block *sb,ext4_group_t group, -struct ext4_buddy *e4b) +ext4_mb_load_buddy_gfp (struct super_block *sb,ext4_group_t group, +struct ext4_buddy *e4b,gfp_t gfp) {int blocks_per_page;int block;
@@ -1140,7 +1140,7 @@ ext4_mb_load_buddy(struct super_block *s* we need full data about the group * to make a good selection */ - ret =ext4_mb_init_group (sb, group); + ret =ext4_mb_init_group (sb, group, gfp);if (ret)return ret; }
@@ -1168,11 +1168,11 @@ ext4_mb_load_buddy(struct super_block *s* wait for it to initialize. */ page_cache_release (page); - page =find_or_create_page (inode->i_mapping, pnum,GFP_NOFS ); + page =find_or_create_page (inode->i_mapping, pnum, gfp);if (page) {BUG_ON (page->mapping != inode->i_mapping);if (!PageUptodate (page)) { - ret =ext4_mb_init_cache (page,NULL ); + ret =ext4_mb_init_cache (page,NULL , gfp);if (ret) {unlock_page (page); goto err;
@@ -1204,11 +1204,12 @@ ext4_mb_load_buddy(struct super_block *sif (page ==NULL || !PageUptodate (page)) {if (page)page_cache_release (page); - page =find_or_create_page (inode->i_mapping, pnum,GFP_NOFS ); + page =find_or_create_page (inode->i_mapping, pnum, gfp);if (page) {BUG_ON (page->mapping != inode->i_mapping);if (!PageUptodate (page)) { - ret =ext4_mb_init_cache (page, e4b->bd_bitmap); + ret =ext4_mb_init_cache (page, e4b->bd_bitmap, + gfp);if (ret) {unlock_page (page); goto err;
@@ -1247,6 +1248,12 @@ err:return ret; } +static int ext4_mb_load_buddy (struct super_block *sb,ext4_group_t group, +struct ext4_buddy *e4b) +{ +return ext4_mb_load_buddy_gfp (sb, group, e4b,GFP_NOFS ); +} +static void ext4_mb_unload_buddy (struct ext4_buddy *e4b) {if (e4b->bd_bitmap_page)
@@ -2047,7 +2054,7 @@ static int ext4_mb_good_group(struct ext/* We only do this if the grp has never been initialized */ if (unlikely (EXT4_MB_GRP_NEED_INIT (grp))) { -int ret =ext4_mb_init_group (ac->ac_sb, group); +int ret =ext4_mb_init_group (ac->ac_sb, group,GFP_NOFS );if (ret)return ret; }
@@ -4808,7 +4815,9 @@ do_more:#endif trace_ext4_mballoc_free (sb, inode, block_group, bit, count_clusters); - err =ext4_mb_load_buddy (sb, block_group, &e4b); +/* __GFP_NOFAIL: retry infinitely, ignore TIF_MEMDIE and memcg limit. */ + err =ext4_mb_load_buddy_gfp (sb, block_group, &e4b, +GFP_NOFS |__GFP_NOFAIL);if (err) goto error_return;
@@ -5210,7 +5219,7 @@ int ext4_trim_fs(struct super_block *sb, grp =ext4_get_group_info (sb, group);/* We only do this if the grp has never been initialized */ if (unlikely (EXT4_MB_GRP_NEED_INIT (grp))) { - ret =ext4_mb_init_group (sb, group); + ret =ext4_mb_init_group (sb, group,GFP_NOFS );if (ret)break ; }
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/ext4-use-__gfp_nofail-in-ext4_free_blocks.patch