Commit 9b8b7d35 authored by Amir Goldstein's avatar Amir Goldstein Committed by Theodore Ts'o

ext4: teach ext4_mb_init_cache() to skip uptodate buddy caches

After online resize which adds new groups, some of the groups
in a buddy page may be initialized and uptodate, while other
(new ones) may be uninitialized.

The indication for init of new block groups is when ext4_mb_init_cache()
is called with an uptodate buddy page. In this case, initialized groups
on that buddy page must be skipped when initializing the buddy cache.
Signed-off-by: default avatarAmir Goldstein <amir73il@users.sf.net>
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent 2de8807b
...@@ -787,6 +787,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore) ...@@ -787,6 +787,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
struct inode *inode; struct inode *inode;
char *data; char *data;
char *bitmap; char *bitmap;
struct ext4_group_info *grinfo;
mb_debug(1, "init page %lu\n", page->index); mb_debug(1, "init page %lu\n", page->index);
...@@ -819,6 +820,18 @@ static int ext4_mb_init_cache(struct page *page, char *incore) ...@@ -819,6 +820,18 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
if (first_group + i >= ngroups) if (first_group + i >= ngroups)
break; break;
grinfo = ext4_get_group_info(sb, first_group + i);
/*
* If page is uptodate then we came here after online resize
* which added some new uninitialized group info structs, so
* we must skip all initialized uptodate buddies on the page,
* which may be currently in use by an allocating task.
*/
if (PageUptodate(page) && !EXT4_MB_GRP_NEED_INIT(grinfo)) {
bh[i] = NULL;
continue;
}
err = -EIO; err = -EIO;
desc = ext4_get_group_desc(sb, first_group + i, NULL); desc = ext4_get_group_desc(sb, first_group + i, NULL);
if (desc == NULL) if (desc == NULL)
...@@ -871,26 +884,28 @@ static int ext4_mb_init_cache(struct page *page, char *incore) ...@@ -871,26 +884,28 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
} }
/* wait for I/O completion */ /* wait for I/O completion */
for (i = 0; i < groups_per_page && bh[i]; i++) for (i = 0; i < groups_per_page; i++)
wait_on_buffer(bh[i]); if (bh[i])
wait_on_buffer(bh[i]);
err = -EIO; err = -EIO;
for (i = 0; i < groups_per_page && bh[i]; i++) for (i = 0; i < groups_per_page; i++)
if (!buffer_uptodate(bh[i])) if (bh[i] && !buffer_uptodate(bh[i]))
goto out; goto out;
err = 0; err = 0;
first_block = page->index * blocks_per_page; first_block = page->index * blocks_per_page;
/* init the page */
memset(page_address(page), 0xff, PAGE_CACHE_SIZE);
for (i = 0; i < blocks_per_page; i++) { for (i = 0; i < blocks_per_page; i++) {
int group; int group;
struct ext4_group_info *grinfo;
group = (first_block + i) >> 1; group = (first_block + i) >> 1;
if (group >= ngroups) if (group >= ngroups)
break; break;
if (!bh[group - first_group])
/* skip initialized uptodate buddy */
continue;
/* /*
* data carry information regarding this * data carry information regarding this
* particular group in the format specified * particular group in the format specified
...@@ -919,6 +934,8 @@ static int ext4_mb_init_cache(struct page *page, char *incore) ...@@ -919,6 +934,8 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
* incore got set to the group block bitmap below * incore got set to the group block bitmap below
*/ */
ext4_lock_group(sb, group); ext4_lock_group(sb, group);
/* init the buddy */
memset(data, 0xff, blocksize);
ext4_mb_generate_buddy(sb, data, incore, group); ext4_mb_generate_buddy(sb, data, incore, group);
ext4_unlock_group(sb, group); ext4_unlock_group(sb, group);
incore = NULL; incore = NULL;
...@@ -948,7 +965,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore) ...@@ -948,7 +965,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore)
out: out:
if (bh) { if (bh) {
for (i = 0; i < groups_per_page && bh[i]; i++) for (i = 0; i < groups_per_page; i++)
brelse(bh[i]); brelse(bh[i]);
if (bh != &bhs) if (bh != &bhs)
kfree(bh); kfree(bh);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment