diff options
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 57 |
1 files changed, 30 insertions, 27 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index a9a9b9b77e8e..8b7564dfacdf 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -917,7 +917,7 @@ err_out: | |||
917 | static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode, | 917 | static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode, |
918 | ext4_lblk_t iblock, unsigned int maxblocks, | 918 | ext4_lblk_t iblock, unsigned int maxblocks, |
919 | struct buffer_head *bh_result, | 919 | struct buffer_head *bh_result, |
920 | int create, int extend_disksize) | 920 | int flags) |
921 | { | 921 | { |
922 | int err = -EIO; | 922 | int err = -EIO; |
923 | ext4_lblk_t offsets[4]; | 923 | ext4_lblk_t offsets[4]; |
@@ -934,7 +934,7 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode, | |||
934 | 934 | ||
935 | 935 | ||
936 | J_ASSERT(!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)); | 936 | J_ASSERT(!(EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL)); |
937 | J_ASSERT(handle != NULL || create == 0); | 937 | J_ASSERT(handle != NULL || (flags & EXT4_GET_BLOCKS_CREATE) == 0); |
938 | depth = ext4_block_to_path(inode, iblock, offsets, | 938 | depth = ext4_block_to_path(inode, iblock, offsets, |
939 | &blocks_to_boundary); | 939 | &blocks_to_boundary); |
940 | 940 | ||
@@ -963,7 +963,7 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode, | |||
963 | } | 963 | } |
964 | 964 | ||
965 | /* Next simple case - plain lookup or failed read of indirect block */ | 965 | /* Next simple case - plain lookup or failed read of indirect block */ |
966 | if (!create || err == -EIO) | 966 | if ((flags & EXT4_GET_BLOCKS_CREATE) == 0 || err == -EIO) |
967 | goto cleanup; | 967 | goto cleanup; |
968 | 968 | ||
969 | /* | 969 | /* |
@@ -1002,7 +1002,7 @@ static int ext4_ind_get_blocks(handle_t *handle, struct inode *inode, | |||
1002 | * protect it if you're about to implement concurrent | 1002 | * protect it if you're about to implement concurrent |
1003 | * ext4_get_block() -bzzz | 1003 | * ext4_get_block() -bzzz |
1004 | */ | 1004 | */ |
1005 | if (!err && extend_disksize) { | 1005 | if (!err && (flags & EXT4_GET_BLOCKS_EXTEND_DISKSIZE)) { |
1006 | disksize = ((loff_t) iblock + count) << inode->i_blkbits; | 1006 | disksize = ((loff_t) iblock + count) << inode->i_blkbits; |
1007 | if (disksize > i_size_read(inode)) | 1007 | if (disksize > i_size_read(inode)) |
1008 | disksize = i_size_read(inode); | 1008 | disksize = i_size_read(inode); |
@@ -1144,7 +1144,7 @@ static void ext4_da_update_reserve_space(struct inode *inode, int used) | |||
1144 | */ | 1144 | */ |
1145 | int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block, | 1145 | int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block, |
1146 | unsigned int max_blocks, struct buffer_head *bh, | 1146 | unsigned int max_blocks, struct buffer_head *bh, |
1147 | int create, int extend_disksize, int flag) | 1147 | int flags) |
1148 | { | 1148 | { |
1149 | int retval; | 1149 | int retval; |
1150 | 1150 | ||
@@ -1158,15 +1158,15 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block, | |||
1158 | down_read((&EXT4_I(inode)->i_data_sem)); | 1158 | down_read((&EXT4_I(inode)->i_data_sem)); |
1159 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { | 1159 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { |
1160 | retval = ext4_ext_get_blocks(handle, inode, block, max_blocks, | 1160 | retval = ext4_ext_get_blocks(handle, inode, block, max_blocks, |
1161 | bh, 0, 0); | 1161 | bh, 0); |
1162 | } else { | 1162 | } else { |
1163 | retval = ext4_ind_get_blocks(handle, inode, block, max_blocks, | 1163 | retval = ext4_ind_get_blocks(handle, inode, block, max_blocks, |
1164 | bh, 0, 0); | 1164 | bh, 0); |
1165 | } | 1165 | } |
1166 | up_read((&EXT4_I(inode)->i_data_sem)); | 1166 | up_read((&EXT4_I(inode)->i_data_sem)); |
1167 | 1167 | ||
1168 | /* If it is only a block(s) look up */ | 1168 | /* If it is only a block(s) look up */ |
1169 | if (!create) | 1169 | if ((flags & EXT4_GET_BLOCKS_CREATE) == 0) |
1170 | return retval; | 1170 | return retval; |
1171 | 1171 | ||
1172 | /* | 1172 | /* |
@@ -1205,7 +1205,7 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block, | |||
1205 | * let the underlying get_block() function know to | 1205 | * let the underlying get_block() function know to |
1206 | * avoid double accounting | 1206 | * avoid double accounting |
1207 | */ | 1207 | */ |
1208 | if (flag) | 1208 | if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) |
1209 | EXT4_I(inode)->i_delalloc_reserved_flag = 1; | 1209 | EXT4_I(inode)->i_delalloc_reserved_flag = 1; |
1210 | /* | 1210 | /* |
1211 | * We need to check for EXT4 here because migrate | 1211 | * We need to check for EXT4 here because migrate |
@@ -1213,10 +1213,10 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block, | |||
1213 | */ | 1213 | */ |
1214 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { | 1214 | if (EXT4_I(inode)->i_flags & EXT4_EXTENTS_FL) { |
1215 | retval = ext4_ext_get_blocks(handle, inode, block, max_blocks, | 1215 | retval = ext4_ext_get_blocks(handle, inode, block, max_blocks, |
1216 | bh, create, extend_disksize); | 1216 | bh, flags); |
1217 | } else { | 1217 | } else { |
1218 | retval = ext4_ind_get_blocks(handle, inode, block, | 1218 | retval = ext4_ind_get_blocks(handle, inode, block, |
1219 | max_blocks, bh, create, extend_disksize); | 1219 | max_blocks, bh, flags); |
1220 | 1220 | ||
1221 | if (retval > 0 && buffer_new(bh)) { | 1221 | if (retval > 0 && buffer_new(bh)) { |
1222 | /* | 1222 | /* |
@@ -1229,7 +1229,7 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block, | |||
1229 | } | 1229 | } |
1230 | } | 1230 | } |
1231 | 1231 | ||
1232 | if (flag) { | 1232 | if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) { |
1233 | EXT4_I(inode)->i_delalloc_reserved_flag = 0; | 1233 | EXT4_I(inode)->i_delalloc_reserved_flag = 0; |
1234 | /* | 1234 | /* |
1235 | * Update reserved blocks/metadata blocks | 1235 | * Update reserved blocks/metadata blocks |
@@ -1269,7 +1269,7 @@ int ext4_get_block(struct inode *inode, sector_t iblock, | |||
1269 | } | 1269 | } |
1270 | 1270 | ||
1271 | ret = ext4_get_blocks(handle, inode, iblock, max_blocks, bh_result, | 1271 | ret = ext4_get_blocks(handle, inode, iblock, max_blocks, bh_result, |
1272 | create, 0, 0); | 1272 | create ? EXT4_GET_BLOCKS_CREATE : 0); |
1273 | if (ret > 0) { | 1273 | if (ret > 0) { |
1274 | bh_result->b_size = (ret << inode->i_blkbits); | 1274 | bh_result->b_size = (ret << inode->i_blkbits); |
1275 | ret = 0; | 1275 | ret = 0; |
@@ -1288,16 +1288,19 @@ struct buffer_head *ext4_getblk(handle_t *handle, struct inode *inode, | |||
1288 | { | 1288 | { |
1289 | struct buffer_head dummy; | 1289 | struct buffer_head dummy; |
1290 | int fatal = 0, err; | 1290 | int fatal = 0, err; |
1291 | int flags = EXT4_GET_BLOCKS_EXTEND_DISKSIZE; | ||
1291 | 1292 | ||
1292 | J_ASSERT(handle != NULL || create == 0); | 1293 | J_ASSERT(handle != NULL || create == 0); |
1293 | 1294 | ||
1294 | dummy.b_state = 0; | 1295 | dummy.b_state = 0; |
1295 | dummy.b_blocknr = -1000; | 1296 | dummy.b_blocknr = -1000; |
1296 | buffer_trace_init(&dummy.b_history); | 1297 | buffer_trace_init(&dummy.b_history); |
1297 | err = ext4_get_blocks(handle, inode, block, 1, &dummy, create, 1, 0); | 1298 | if (create) |
1299 | flags |= EXT4_GET_BLOCKS_CREATE; | ||
1300 | err = ext4_get_blocks(handle, inode, block, 1, &dummy, flags); | ||
1298 | /* | 1301 | /* |
1299 | * ext4_get_blocks() returns number of blocks | 1302 | * ext4_get_blocks() returns number of blocks mapped. 0 in |
1300 | * mapped. 0 in case of a HOLE. | 1303 | * case of a HOLE. |
1301 | */ | 1304 | */ |
1302 | if (err > 0) { | 1305 | if (err > 0) { |
1303 | if (err > 1) | 1306 | if (err > 1) |
@@ -1997,7 +2000,6 @@ static void ext4_print_free_blocks(struct inode *inode) | |||
1997 | return; | 2000 | return; |
1998 | } | 2001 | } |
1999 | 2002 | ||
2000 | #define EXT4_DELALLOC_RSVED 1 | ||
2001 | static int ext4_da_get_block_write(struct inode *inode, sector_t iblock, | 2003 | static int ext4_da_get_block_write(struct inode *inode, sector_t iblock, |
2002 | struct buffer_head *bh_result) | 2004 | struct buffer_head *bh_result) |
2003 | { | 2005 | { |
@@ -2009,7 +2011,8 @@ static int ext4_da_get_block_write(struct inode *inode, sector_t iblock, | |||
2009 | handle = ext4_journal_current_handle(); | 2011 | handle = ext4_journal_current_handle(); |
2010 | BUG_ON(!handle); | 2012 | BUG_ON(!handle); |
2011 | ret = ext4_get_blocks(handle, inode, iblock, max_blocks, | 2013 | ret = ext4_get_blocks(handle, inode, iblock, max_blocks, |
2012 | bh_result, 1, 0, EXT4_DELALLOC_RSVED); | 2014 | bh_result, EXT4_GET_BLOCKS_CREATE| |
2015 | EXT4_GET_BLOCKS_DELALLOC_RESERVE); | ||
2013 | if (ret <= 0) | 2016 | if (ret <= 0) |
2014 | return ret; | 2017 | return ret; |
2015 | 2018 | ||
@@ -2065,16 +2068,17 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) | |||
2065 | return 0; | 2068 | return 0; |
2066 | /* | 2069 | /* |
2067 | * We need to make sure the BH_Delay flag is passed down to | 2070 | * We need to make sure the BH_Delay flag is passed down to |
2068 | * ext4_da_get_block_write(), since it calls | 2071 | * ext4_da_get_block_write(), since it calls ext4_get_blocks() |
2069 | * ext4_get_blocks() with the EXT4_DELALLOC_RSVED flag. | 2072 | * with the EXT4_GET_BLOCKS_DELALLOC_RESERVE flag. This flag |
2070 | * This flag causes ext4_get_blocks() to call | 2073 | * causes ext4_get_blocks() to call |
2071 | * ext4_da_update_reserve_space() if the passed buffer head | 2074 | * ext4_da_update_reserve_space() if the passed buffer head |
2072 | * has the BH_Delay flag set. In the future, once we clean up | 2075 | * has the BH_Delay flag set. In the future, once we clean up |
2073 | * the interfaces to ext4_get_blocks(), we should pass in | 2076 | * the interfaces to ext4_get_blocks(), we should pass in a |
2074 | * a separate flag which requests that the delayed allocation | 2077 | * separate flag which requests that the delayed allocation |
2075 | * statistics should be updated, instead of depending on the | 2078 | * statistics should be updated, instead of depending on the |
2076 | * state information getting passed down via the map_bh's | 2079 | * state information getting passed down via the map_bh's |
2077 | * state bitmasks plus the magic EXT4_DELALLOC_RSVED flag. | 2080 | * state bitmasks plus the magic |
2081 | * EXT4_GET_BLOCKS_DELALLOC_RESERVE flag. | ||
2078 | */ | 2082 | */ |
2079 | new.b_state = mpd->b_state & (1 << BH_Delay); | 2083 | new.b_state = mpd->b_state & (1 << BH_Delay); |
2080 | new.b_blocknr = 0; | 2084 | new.b_blocknr = 0; |
@@ -2362,7 +2366,7 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, | |||
2362 | * preallocated blocks are unmapped but should treated | 2366 | * preallocated blocks are unmapped but should treated |
2363 | * the same as allocated blocks. | 2367 | * the same as allocated blocks. |
2364 | */ | 2368 | */ |
2365 | ret = ext4_get_blocks(NULL, inode, iblock, 1, bh_result, 0, 0, 0); | 2369 | ret = ext4_get_blocks(NULL, inode, iblock, 1, bh_result, 0); |
2366 | if ((ret == 0) && !buffer_delay(bh_result)) { | 2370 | if ((ret == 0) && !buffer_delay(bh_result)) { |
2367 | /* the block isn't (pre)allocated yet, let's reserve space */ | 2371 | /* the block isn't (pre)allocated yet, let's reserve space */ |
2368 | /* | 2372 | /* |
@@ -2406,8 +2410,7 @@ static int ext4_normal_get_block_write(struct inode *inode, sector_t iblock, | |||
2406 | * we don't want to do block allocation in writepage | 2410 | * we don't want to do block allocation in writepage |
2407 | * so call get_block_wrap with create = 0 | 2411 | * so call get_block_wrap with create = 0 |
2408 | */ | 2412 | */ |
2409 | ret = ext4_get_blocks(NULL, inode, iblock, max_blocks, | 2413 | ret = ext4_get_blocks(NULL, inode, iblock, max_blocks, bh_result, 0); |
2410 | bh_result, 0, 0, 0); | ||
2411 | if (ret > 0) { | 2414 | if (ret > 0) { |
2412 | bh_result->b_size = (ret << inode->i_blkbits); | 2415 | bh_result->b_size = (ret << inode->i_blkbits); |
2413 | ret = 0; | 2416 | ret = 0; |