|
@@ -815,7 +815,7 @@ static void mb_regenerate_buddy(struct ext4_buddy *e4b)
|
|
|
* 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 page *page, char *incore)
|
|
|
/* 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(struct super_block *sb,
|
|
|
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(struct super_block *sb,
|
|
|
|
|
|
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(struct ext4_buddy *e4b)
|
|
|
* 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_block *sb, ext4_group_t group)
|
|
|
* 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_block *sb, ext4_group_t group)
|
|
|
}
|
|
|
|
|
|
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_block *sb, ext4_group_t group)
|
|
|
}
|
|
|
/* 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 *sb, ext4_group_t group,
|
|
|
* 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 *sb, ext4_group_t group,
|
|
|
* 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 *sb, ext4_group_t group,
|
|
|
if (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)
|
|
@@ -2045,7 +2052,7 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac,
|
|
|
|
|
|
/* 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;
|
|
|
}
|
|
@@ -4804,7 +4811,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;
|
|
|
|
|
@@ -5211,7 +5220,7 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
|
|
|
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;
|
|
|
}
|