diff options
Diffstat (limited to 'fs/ext4/inode.c')
| -rw-r--r-- | fs/ext4/inode.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index e91f978c7f12..2a9ffd528dd1 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -1149,6 +1149,7 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block, | |||
| 1149 | int retval; | 1149 | int retval; |
| 1150 | 1150 | ||
| 1151 | clear_buffer_mapped(bh); | 1151 | clear_buffer_mapped(bh); |
| 1152 | clear_buffer_unwritten(bh); | ||
| 1152 | 1153 | ||
| 1153 | /* | 1154 | /* |
| 1154 | * Try to see if we can get the block without requesting | 1155 | * Try to see if we can get the block without requesting |
| @@ -1179,6 +1180,18 @@ int ext4_get_blocks_wrap(handle_t *handle, struct inode *inode, sector_t block, | |||
| 1179 | return retval; | 1180 | return retval; |
| 1180 | 1181 | ||
| 1181 | /* | 1182 | /* |
| 1183 | * When we call get_blocks without the create flag, the | ||
| 1184 | * BH_Unwritten flag could have gotten set if the blocks | ||
| 1185 | * requested were part of a uninitialized extent. We need to | ||
| 1186 | * clear this flag now that we are committed to convert all or | ||
| 1187 | * part of the uninitialized extent to be an initialized | ||
| 1188 | * extent. This is because we need to avoid the combination | ||
| 1189 | * of BH_Unwritten and BH_Mapped flags being simultaneously | ||
| 1190 | * set on the buffer_head. | ||
| 1191 | */ | ||
| 1192 | clear_buffer_unwritten(bh); | ||
| 1193 | |||
| 1194 | /* | ||
| 1182 | * New blocks allocate and/or writing to uninitialized extent | 1195 | * New blocks allocate and/or writing to uninitialized extent |
| 1183 | * will possibly result in updating i_data, so we take | 1196 | * will possibly result in updating i_data, so we take |
| 1184 | * the write lock of i_data_sem, and call get_blocks() | 1197 | * the write lock of i_data_sem, and call get_blocks() |
| @@ -2297,6 +2310,10 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, | |||
| 2297 | struct buffer_head *bh_result, int create) | 2310 | struct buffer_head *bh_result, int create) |
| 2298 | { | 2311 | { |
| 2299 | int ret = 0; | 2312 | int ret = 0; |
| 2313 | sector_t invalid_block = ~((sector_t) 0xffff); | ||
| 2314 | |||
| 2315 | if (invalid_block < ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es)) | ||
| 2316 | invalid_block = ~0; | ||
| 2300 | 2317 | ||
| 2301 | BUG_ON(create == 0); | 2318 | BUG_ON(create == 0); |
| 2302 | BUG_ON(bh_result->b_size != inode->i_sb->s_blocksize); | 2319 | BUG_ON(bh_result->b_size != inode->i_sb->s_blocksize); |
| @@ -2318,11 +2335,18 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock, | |||
| 2318 | /* not enough space to reserve */ | 2335 | /* not enough space to reserve */ |
| 2319 | return ret; | 2336 | return ret; |
| 2320 | 2337 | ||
| 2321 | map_bh(bh_result, inode->i_sb, 0); | 2338 | map_bh(bh_result, inode->i_sb, invalid_block); |
| 2322 | set_buffer_new(bh_result); | 2339 | set_buffer_new(bh_result); |
| 2323 | set_buffer_delay(bh_result); | 2340 | set_buffer_delay(bh_result); |
| 2324 | } else if (ret > 0) { | 2341 | } else if (ret > 0) { |
| 2325 | bh_result->b_size = (ret << inode->i_blkbits); | 2342 | bh_result->b_size = (ret << inode->i_blkbits); |
| 2343 | /* | ||
| 2344 | * With sub-block writes into unwritten extents | ||
| 2345 | * we also need to mark the buffer as new so that | ||
| 2346 | * the unwritten parts of the buffer gets correctly zeroed. | ||
| 2347 | */ | ||
| 2348 | if (buffer_unwritten(bh_result)) | ||
| 2349 | set_buffer_new(bh_result); | ||
| 2326 | ret = 0; | 2350 | ret = 0; |
| 2327 | } | 2351 | } |
| 2328 | 2352 | ||
