diff options
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/mballoc.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 7311f25a88ea..1816eafb0a05 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -787,6 +787,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore) | |||
787 | struct inode *inode; | 787 | struct inode *inode; |
788 | char *data; | 788 | char *data; |
789 | char *bitmap; | 789 | char *bitmap; |
790 | struct ext4_group_info *grinfo; | ||
790 | 791 | ||
791 | mb_debug(1, "init page %lu\n", page->index); | 792 | mb_debug(1, "init page %lu\n", page->index); |
792 | 793 | ||
@@ -819,6 +820,18 @@ static int ext4_mb_init_cache(struct page *page, char *incore) | |||
819 | if (first_group + i >= ngroups) | 820 | if (first_group + i >= ngroups) |
820 | break; | 821 | break; |
821 | 822 | ||
823 | grinfo = ext4_get_group_info(sb, first_group + i); | ||
824 | /* | ||
825 | * If page is uptodate then we came here after online resize | ||
826 | * which added some new uninitialized group info structs, so | ||
827 | * we must skip all initialized uptodate buddies on the page, | ||
828 | * which may be currently in use by an allocating task. | ||
829 | */ | ||
830 | if (PageUptodate(page) && !EXT4_MB_GRP_NEED_INIT(grinfo)) { | ||
831 | bh[i] = NULL; | ||
832 | continue; | ||
833 | } | ||
834 | |||
822 | err = -EIO; | 835 | err = -EIO; |
823 | desc = ext4_get_group_desc(sb, first_group + i, NULL); | 836 | desc = ext4_get_group_desc(sb, first_group + i, NULL); |
824 | if (desc == NULL) | 837 | if (desc == NULL) |
@@ -871,26 +884,28 @@ static int ext4_mb_init_cache(struct page *page, char *incore) | |||
871 | } | 884 | } |
872 | 885 | ||
873 | /* wait for I/O completion */ | 886 | /* wait for I/O completion */ |
874 | for (i = 0; i < groups_per_page && bh[i]; i++) | 887 | for (i = 0; i < groups_per_page; i++) |
875 | wait_on_buffer(bh[i]); | 888 | if (bh[i]) |
889 | wait_on_buffer(bh[i]); | ||
876 | 890 | ||
877 | err = -EIO; | 891 | err = -EIO; |
878 | for (i = 0; i < groups_per_page && bh[i]; i++) | 892 | for (i = 0; i < groups_per_page; i++) |
879 | if (!buffer_uptodate(bh[i])) | 893 | if (bh[i] && !buffer_uptodate(bh[i])) |
880 | goto out; | 894 | goto out; |
881 | 895 | ||
882 | err = 0; | 896 | err = 0; |
883 | first_block = page->index * blocks_per_page; | 897 | first_block = page->index * blocks_per_page; |
884 | /* init the page */ | ||
885 | memset(page_address(page), 0xff, PAGE_CACHE_SIZE); | ||
886 | for (i = 0; i < blocks_per_page; i++) { | 898 | for (i = 0; i < blocks_per_page; i++) { |
887 | int group; | 899 | int group; |
888 | struct ext4_group_info *grinfo; | ||
889 | 900 | ||
890 | group = (first_block + i) >> 1; | 901 | group = (first_block + i) >> 1; |
891 | if (group >= ngroups) | 902 | if (group >= ngroups) |
892 | break; | 903 | break; |
893 | 904 | ||
905 | if (!bh[group - first_group]) | ||
906 | /* skip initialized uptodate buddy */ | ||
907 | continue; | ||
908 | |||
894 | /* | 909 | /* |
895 | * data carry information regarding this | 910 | * data carry information regarding this |
896 | * particular group in the format specified | 911 | * particular group in the format specified |
@@ -919,6 +934,8 @@ static int ext4_mb_init_cache(struct page *page, char *incore) | |||
919 | * incore got set to the group block bitmap below | 934 | * incore got set to the group block bitmap below |
920 | */ | 935 | */ |
921 | ext4_lock_group(sb, group); | 936 | ext4_lock_group(sb, group); |
937 | /* init the buddy */ | ||
938 | memset(data, 0xff, blocksize); | ||
922 | ext4_mb_generate_buddy(sb, data, incore, group); | 939 | ext4_mb_generate_buddy(sb, data, incore, group); |
923 | ext4_unlock_group(sb, group); | 940 | ext4_unlock_group(sb, group); |
924 | incore = NULL; | 941 | incore = NULL; |
@@ -948,7 +965,7 @@ static int ext4_mb_init_cache(struct page *page, char *incore) | |||
948 | 965 | ||
949 | out: | 966 | out: |
950 | if (bh) { | 967 | if (bh) { |
951 | for (i = 0; i < groups_per_page && bh[i]; i++) | 968 | for (i = 0; i < groups_per_page; i++) |
952 | brelse(bh[i]); | 969 | brelse(bh[i]); |
953 | if (bh != &bhs) | 970 | if (bh != &bhs) |
954 | kfree(bh); | 971 | kfree(bh); |