diff options
author | Theodore Ts'o <tytso@mit.edu> | 2009-05-14 13:57:08 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2009-05-14 13:57:08 -0400 |
commit | 2ac3b6e00acb46406c993d57921f86a594aafe08 (patch) | |
tree | 51f8a245caa53776fb9617973742ffc81023e007 | |
parent | 2fa3cdfb319055fd8b25abdafa413e16f00ad493 (diff) |
ext4: Clean up ext4_get_blocks() so it does not depend on bh_result->b_state
The ext4_get_blocks() function was depending on the value of
bh_result->b_state as an input parameter to decide whether or not
update the delalloc accounting statistics by calling
ext4_da_update_reserve_space(). We now use a separate flag,
EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE, to requests this update, so that
all callers of ext4_get_blocks() can clear map_bh.b_state before
calling ext4_get_blocks() without worrying about any consistency
issues.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
-rw-r--r-- | fs/ext4/ext4.h | 15 | ||||
-rw-r--r-- | fs/ext4/inode.c | 56 |
2 files changed, 41 insertions, 30 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 17feb4ac633a..d164f1294e5f 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -318,16 +318,21 @@ struct ext4_new_group_data { | |||
318 | */ | 318 | */ |
319 | /* Allocate any needed blocks and/or convert an unitialized | 319 | /* Allocate any needed blocks and/or convert an unitialized |
320 | extent to be an initialized ext4 */ | 320 | extent to be an initialized ext4 */ |
321 | #define EXT4_GET_BLOCKS_CREATE 1 | 321 | #define EXT4_GET_BLOCKS_CREATE 0x0001 |
322 | /* Request the creation of an unitialized extent */ | 322 | /* Request the creation of an unitialized extent */ |
323 | #define EXT4_GET_BLOCKS_UNINIT_EXT 2 | 323 | #define EXT4_GET_BLOCKS_UNINIT_EXT 0x0002 |
324 | #define EXT4_GET_BLOCKS_CREATE_UNINIT_EXT (EXT4_GET_BLOCKS_UNINIT_EXT|\ | 324 | #define EXT4_GET_BLOCKS_CREATE_UNINIT_EXT (EXT4_GET_BLOCKS_UNINIT_EXT|\ |
325 | EXT4_GET_BLOCKS_CREATE) | 325 | EXT4_GET_BLOCKS_CREATE) |
326 | /* Update the ext4_inode_info i_disksize field */ | 326 | /* Update the ext4_inode_info i_disksize field */ |
327 | #define EXT4_GET_BLOCKS_EXTEND_DISKSIZE 4 | 327 | #define EXT4_GET_BLOCKS_EXTEND_DISKSIZE 0x0004 |
328 | /* Caller is from the delayed allocation writeout path, | 328 | /* Caller is from the delayed allocation writeout path, |
329 | so the filesystem blocks have already been accounted for */ | 329 | so set the magic i_delalloc_reserve_flag after taking the |
330 | #define EXT4_GET_BLOCKS_DELALLOC_RESERVE 8 | 330 | inode allocation semaphore for */ |
331 | #define EXT4_GET_BLOCKS_DELALLOC_RESERVE 0x0008 | ||
332 | /* Call ext4_da_update_reserve_space() after successfully | ||
333 | allocating the blocks */ | ||
334 | #define EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE 0x0010 | ||
335 | |||
331 | 336 | ||
332 | /* | 337 | /* |
333 | * ioctl commands | 338 | * ioctl commands |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index bfe50a22363b..d7b7480682b9 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -1234,16 +1234,15 @@ int ext4_get_blocks(handle_t *handle, struct inode *inode, sector_t block, | |||
1234 | } | 1234 | } |
1235 | } | 1235 | } |
1236 | 1236 | ||
1237 | if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) { | 1237 | if (flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) |
1238 | EXT4_I(inode)->i_delalloc_reserved_flag = 0; | 1238 | EXT4_I(inode)->i_delalloc_reserved_flag = 0; |
1239 | /* | 1239 | |
1240 | * Update reserved blocks/metadata blocks | 1240 | /* |
1241 | * after successful block allocation | 1241 | * Update reserved blocks/metadata blocks after successful |
1242 | * which were deferred till now | 1242 | * block allocation which had been deferred till now. |
1243 | */ | 1243 | */ |
1244 | if ((retval > 0) && buffer_delay(bh)) | 1244 | if ((retval > 0) && (flags & EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE)) |
1245 | ext4_da_update_reserve_space(inode, retval); | 1245 | ext4_da_update_reserve_space(inode, retval); |
1246 | } | ||
1247 | 1246 | ||
1248 | up_write((&EXT4_I(inode)->i_data_sem)); | 1247 | up_write((&EXT4_I(inode)->i_data_sem)); |
1249 | return retval; | 1248 | return retval; |
@@ -2015,7 +2014,7 @@ static void ext4_print_free_blocks(struct inode *inode) | |||
2015 | */ | 2014 | */ |
2016 | static int mpage_da_map_blocks(struct mpage_da_data *mpd) | 2015 | static int mpage_da_map_blocks(struct mpage_da_data *mpd) |
2017 | { | 2016 | { |
2018 | int err, blks; | 2017 | int err, blks, get_blocks_flags; |
2019 | struct buffer_head new; | 2018 | struct buffer_head new; |
2020 | sector_t next = mpd->b_blocknr; | 2019 | sector_t next = mpd->b_blocknr; |
2021 | unsigned max_blocks = mpd->b_size >> mpd->inode->i_blkbits; | 2020 | unsigned max_blocks = mpd->b_size >> mpd->inode->i_blkbits; |
@@ -2040,23 +2039,30 @@ static int mpage_da_map_blocks(struct mpage_da_data *mpd) | |||
2040 | BUG_ON(!handle); | 2039 | BUG_ON(!handle); |
2041 | 2040 | ||
2042 | /* | 2041 | /* |
2043 | * We need to make sure the BH_Delay flag is passed down to | 2042 | * Call ext4_get_blocks() to allocate any delayed allocation |
2044 | * ext4_da_get_block_write(), since it calls ext4_get_blocks() | 2043 | * blocks, or to convert an uninitialized extent to be |
2045 | * with the EXT4_GET_BLOCKS_DELALLOC_RESERVE flag. This flag | 2044 | * initialized (in the case where we have written into |
2046 | * causes ext4_get_blocks() to call | 2045 | * one or more preallocated blocks). |
2047 | * ext4_da_update_reserve_space() if the passed buffer head | 2046 | * |
2048 | * has the BH_Delay flag set. In the future, once we clean up | 2047 | * We pass in the magic EXT4_GET_BLOCKS_DELALLOC_RESERVE to |
2049 | * the interfaces to ext4_get_blocks(), we should pass in a | 2048 | * indicate that we are on the delayed allocation path. This |
2050 | * separate flag which requests that the delayed allocation | 2049 | * affects functions in many different parts of the allocation |
2051 | * statistics should be updated, instead of depending on the | 2050 | * call path. This flag exists primarily because we don't |
2052 | * state information getting passed down via the map_bh's | 2051 | * want to change *many* call functions, so ext4_get_blocks() |
2053 | * state bitmasks plus the magic | 2052 | * will set the magic i_delalloc_reserved_flag once the |
2054 | * EXT4_GET_BLOCKS_DELALLOC_RESERVE flag. | 2053 | * inode's allocation semaphore is taken. |
2054 | * | ||
2055 | * If the blocks in questions were delalloc blocks, set | ||
2056 | * EXT4_GET_BLOCKS_DELALLOC_RESERVE so the delalloc accounting | ||
2057 | * variables are updated after the blocks have been allocated. | ||
2055 | */ | 2058 | */ |
2056 | new.b_state = mpd->b_state & (1 << BH_Delay); | 2059 | new.b_state = 0; |
2060 | get_blocks_flags = (EXT4_GET_BLOCKS_CREATE | | ||
2061 | EXT4_GET_BLOCKS_DELALLOC_RESERVE); | ||
2062 | if (mpd->b_state & (1 << BH_Delay)) | ||
2063 | get_blocks_flags |= EXT4_GET_BLOCKS_UPDATE_RESERVE_SPACE; | ||
2057 | blks = ext4_get_blocks(handle, mpd->inode, next, max_blocks, | 2064 | blks = ext4_get_blocks(handle, mpd->inode, next, max_blocks, |
2058 | &new, EXT4_GET_BLOCKS_CREATE| | 2065 | &new, get_blocks_flags); |
2059 | EXT4_GET_BLOCKS_DELALLOC_RESERVE); | ||
2060 | if (blks < 0) { | 2066 | if (blks < 0) { |
2061 | err = blks; | 2067 | err = blks; |
2062 | /* | 2068 | /* |