diff options
Diffstat (limited to 'fs/ext4/mballoc.c')
-rw-r--r-- | fs/ext4/mballoc.c | 157 |
1 files changed, 79 insertions, 78 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 381ac565786a..328ea9cec57b 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -947,6 +947,85 @@ out: | |||
947 | } | 947 | } |
948 | 948 | ||
949 | /* | 949 | /* |
950 | * lock the group_info alloc_sem of all the groups | ||
951 | * belonging to the same buddy cache page. This | ||
952 | * make sure other parallel operation on the buddy | ||
953 | * cache doesn't happen whild holding the buddy cache | ||
954 | * lock | ||
955 | */ | ||
956 | static int ext4_mb_get_buddy_cache_lock(struct super_block *sb, | ||
957 | ext4_group_t group) | ||
958 | { | ||
959 | int i; | ||
960 | int block, pnum; | ||
961 | int blocks_per_page; | ||
962 | int groups_per_page; | ||
963 | ext4_group_t ngroups = ext4_get_groups_count(sb); | ||
964 | ext4_group_t first_group; | ||
965 | struct ext4_group_info *grp; | ||
966 | |||
967 | blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize; | ||
968 | /* | ||
969 | * the buddy cache inode stores the block bitmap | ||
970 | * and buddy information in consecutive blocks. | ||
971 | * So for each group we need two blocks. | ||
972 | */ | ||
973 | block = group * 2; | ||
974 | pnum = block / blocks_per_page; | ||
975 | first_group = pnum * blocks_per_page / 2; | ||
976 | |||
977 | groups_per_page = blocks_per_page >> 1; | ||
978 | if (groups_per_page == 0) | ||
979 | groups_per_page = 1; | ||
980 | /* read all groups the page covers into the cache */ | ||
981 | for (i = 0; i < groups_per_page; i++) { | ||
982 | |||
983 | if ((first_group + i) >= ngroups) | ||
984 | break; | ||
985 | grp = ext4_get_group_info(sb, first_group + i); | ||
986 | /* take all groups write allocation | ||
987 | * semaphore. This make sure there is | ||
988 | * no block allocation going on in any | ||
989 | * of that groups | ||
990 | */ | ||
991 | down_write_nested(&grp->alloc_sem, i); | ||
992 | } | ||
993 | return i; | ||
994 | } | ||
995 | |||
996 | static void ext4_mb_put_buddy_cache_lock(struct super_block *sb, | ||
997 | ext4_group_t group, int locked_group) | ||
998 | { | ||
999 | int i; | ||
1000 | int block, pnum; | ||
1001 | int blocks_per_page; | ||
1002 | ext4_group_t first_group; | ||
1003 | struct ext4_group_info *grp; | ||
1004 | |||
1005 | blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize; | ||
1006 | /* | ||
1007 | * the buddy cache inode stores the block bitmap | ||
1008 | * and buddy information in consecutive blocks. | ||
1009 | * So for each group we need two blocks. | ||
1010 | */ | ||
1011 | block = group * 2; | ||
1012 | pnum = block / blocks_per_page; | ||
1013 | first_group = pnum * blocks_per_page / 2; | ||
1014 | /* release locks on all the groups */ | ||
1015 | for (i = 0; i < locked_group; i++) { | ||
1016 | |||
1017 | grp = ext4_get_group_info(sb, first_group + i); | ||
1018 | /* take all groups write allocation | ||
1019 | * semaphore. This make sure there is | ||
1020 | * no block allocation going on in any | ||
1021 | * of that groups | ||
1022 | */ | ||
1023 | up_write(&grp->alloc_sem); | ||
1024 | } | ||
1025 | |||
1026 | } | ||
1027 | |||
1028 | /* | ||
950 | * Locking note: This routine calls ext4_mb_init_cache(), which takes the | 1029 | * Locking note: This routine calls ext4_mb_init_cache(), which takes the |
951 | * block group lock of all groups for this page; do not hold the BG lock when | 1030 | * block group lock of all groups for this page; do not hold the BG lock when |
952 | * calling this routine! | 1031 | * calling this routine! |
@@ -1923,84 +2002,6 @@ static int ext4_mb_good_group(struct ext4_allocation_context *ac, | |||
1923 | return 0; | 2002 | return 0; |
1924 | } | 2003 | } |
1925 | 2004 | ||
1926 | /* | ||
1927 | * lock the group_info alloc_sem of all the groups | ||
1928 | * belonging to the same buddy cache page. This | ||
1929 | * make sure other parallel operation on the buddy | ||
1930 | * cache doesn't happen whild holding the buddy cache | ||
1931 | * lock | ||
1932 | */ | ||
1933 | int ext4_mb_get_buddy_cache_lock(struct super_block *sb, ext4_group_t group) | ||
1934 | { | ||
1935 | int i; | ||
1936 | int block, pnum; | ||
1937 | int blocks_per_page; | ||
1938 | int groups_per_page; | ||
1939 | ext4_group_t ngroups = ext4_get_groups_count(sb); | ||
1940 | ext4_group_t first_group; | ||
1941 | struct ext4_group_info *grp; | ||
1942 | |||
1943 | blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize; | ||
1944 | /* | ||
1945 | * the buddy cache inode stores the block bitmap | ||
1946 | * and buddy information in consecutive blocks. | ||
1947 | * So for each group we need two blocks. | ||
1948 | */ | ||
1949 | block = group * 2; | ||
1950 | pnum = block / blocks_per_page; | ||
1951 | first_group = pnum * blocks_per_page / 2; | ||
1952 | |||
1953 | groups_per_page = blocks_per_page >> 1; | ||
1954 | if (groups_per_page == 0) | ||
1955 | groups_per_page = 1; | ||
1956 | /* read all groups the page covers into the cache */ | ||
1957 | for (i = 0; i < groups_per_page; i++) { | ||
1958 | |||
1959 | if ((first_group + i) >= ngroups) | ||
1960 | break; | ||
1961 | grp = ext4_get_group_info(sb, first_group + i); | ||
1962 | /* take all groups write allocation | ||
1963 | * semaphore. This make sure there is | ||
1964 | * no block allocation going on in any | ||
1965 | * of that groups | ||
1966 | */ | ||
1967 | down_write_nested(&grp->alloc_sem, i); | ||
1968 | } | ||
1969 | return i; | ||
1970 | } | ||
1971 | |||
1972 | void ext4_mb_put_buddy_cache_lock(struct super_block *sb, | ||
1973 | ext4_group_t group, int locked_group) | ||
1974 | { | ||
1975 | int i; | ||
1976 | int block, pnum; | ||
1977 | int blocks_per_page; | ||
1978 | ext4_group_t first_group; | ||
1979 | struct ext4_group_info *grp; | ||
1980 | |||
1981 | blocks_per_page = PAGE_CACHE_SIZE / sb->s_blocksize; | ||
1982 | /* | ||
1983 | * the buddy cache inode stores the block bitmap | ||
1984 | * and buddy information in consecutive blocks. | ||
1985 | * So for each group we need two blocks. | ||
1986 | */ | ||
1987 | block = group * 2; | ||
1988 | pnum = block / blocks_per_page; | ||
1989 | first_group = pnum * blocks_per_page / 2; | ||
1990 | /* release locks on all the groups */ | ||
1991 | for (i = 0; i < locked_group; i++) { | ||
1992 | |||
1993 | grp = ext4_get_group_info(sb, first_group + i); | ||
1994 | /* take all groups write allocation | ||
1995 | * semaphore. This make sure there is | ||
1996 | * no block allocation going on in any | ||
1997 | * of that groups | ||
1998 | */ | ||
1999 | up_write(&grp->alloc_sem); | ||
2000 | } | ||
2001 | |||
2002 | } | ||
2003 | |||
2004 | static noinline_for_stack int | 2005 | static noinline_for_stack int |
2005 | ext4_mb_regular_allocator(struct ext4_allocation_context *ac) | 2006 | ext4_mb_regular_allocator(struct ext4_allocation_context *ac) |
2006 | { | 2007 | { |