diff options
Diffstat (limited to 'fs/ext4/extents.c')
| -rw-r--r-- | fs/ext4/extents.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 7097b0f680e6..a61873808f76 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -2835,6 +2835,9 @@ again: | |||
| 2835 | err = -EIO; | 2835 | err = -EIO; |
| 2836 | break; | 2836 | break; |
| 2837 | } | 2837 | } |
| 2838 | /* Yield here to deal with large extent trees. | ||
| 2839 | * Should be a no-op if we did IO above. */ | ||
| 2840 | cond_resched(); | ||
| 2838 | if (WARN_ON(i + 1 > depth)) { | 2841 | if (WARN_ON(i + 1 > depth)) { |
| 2839 | err = -EIO; | 2842 | err = -EIO; |
| 2840 | break; | 2843 | break; |
| @@ -4261,8 +4264,8 @@ got_allocated_blocks: | |||
| 4261 | /* not a good idea to call discard here directly, | 4264 | /* not a good idea to call discard here directly, |
| 4262 | * but otherwise we'd need to call it every free() */ | 4265 | * but otherwise we'd need to call it every free() */ |
| 4263 | ext4_discard_preallocations(inode); | 4266 | ext4_discard_preallocations(inode); |
| 4264 | ext4_free_blocks(handle, inode, NULL, ext4_ext_pblock(&newex), | 4267 | ext4_free_blocks(handle, inode, NULL, newblock, |
| 4265 | ext4_ext_get_actual_len(&newex), fb_flags); | 4268 | EXT4_C2B(sbi, allocated_clusters), fb_flags); |
| 4266 | goto out2; | 4269 | goto out2; |
| 4267 | } | 4270 | } |
| 4268 | 4271 | ||
| @@ -4382,8 +4385,9 @@ out2: | |||
| 4382 | } | 4385 | } |
| 4383 | 4386 | ||
| 4384 | out3: | 4387 | out3: |
| 4385 | trace_ext4_ext_map_blocks_exit(inode, flags, map, err ? err : allocated); | 4388 | trace_ext4_ext_map_blocks_exit(inode, flags, map, |
| 4386 | 4389 | err ? err : allocated); | |
| 4390 | ext4_es_lru_add(inode); | ||
| 4387 | return err ? err : allocated; | 4391 | return err ? err : allocated; |
| 4388 | } | 4392 | } |
| 4389 | 4393 | ||
| @@ -4405,9 +4409,20 @@ void ext4_ext_truncate(handle_t *handle, struct inode *inode) | |||
| 4405 | 4409 | ||
| 4406 | last_block = (inode->i_size + sb->s_blocksize - 1) | 4410 | last_block = (inode->i_size + sb->s_blocksize - 1) |
| 4407 | >> EXT4_BLOCK_SIZE_BITS(sb); | 4411 | >> EXT4_BLOCK_SIZE_BITS(sb); |
| 4412 | retry: | ||
| 4408 | err = ext4_es_remove_extent(inode, last_block, | 4413 | err = ext4_es_remove_extent(inode, last_block, |
| 4409 | EXT_MAX_BLOCKS - last_block); | 4414 | EXT_MAX_BLOCKS - last_block); |
| 4415 | if (err == ENOMEM) { | ||
| 4416 | cond_resched(); | ||
| 4417 | congestion_wait(BLK_RW_ASYNC, HZ/50); | ||
| 4418 | goto retry; | ||
| 4419 | } | ||
| 4420 | if (err) { | ||
| 4421 | ext4_std_error(inode->i_sb, err); | ||
| 4422 | return; | ||
| 4423 | } | ||
| 4410 | err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1); | 4424 | err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1); |
| 4425 | ext4_std_error(inode->i_sb, err); | ||
| 4411 | } | 4426 | } |
| 4412 | 4427 | ||
| 4413 | static void ext4_falloc_update_inode(struct inode *inode, | 4428 | static void ext4_falloc_update_inode(struct inode *inode, |
