diff options
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r-- | fs/ext4/extents.c | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 91341ec6e06a..cd0c7ed06772 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -1891,11 +1891,10 @@ has_space: | |||
1891 | nearex->ee_len = newext->ee_len; | 1891 | nearex->ee_len = newext->ee_len; |
1892 | 1892 | ||
1893 | merge: | 1893 | merge: |
1894 | /* try to merge extents to the right */ | 1894 | /* try to merge extents */ |
1895 | if (!(flag & EXT4_GET_BLOCKS_PRE_IO)) | 1895 | if (!(flag & EXT4_GET_BLOCKS_PRE_IO)) |
1896 | ext4_ext_try_to_merge(inode, path, nearex); | 1896 | ext4_ext_try_to_merge(inode, path, nearex); |
1897 | 1897 | ||
1898 | /* try to merge extents to the left */ | ||
1899 | 1898 | ||
1900 | /* time to correct all indexes above */ | 1899 | /* time to correct all indexes above */ |
1901 | err = ext4_ext_correct_indexes(handle, inode, path); | 1900 | err = ext4_ext_correct_indexes(handle, inode, path); |
@@ -2570,10 +2569,10 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, | |||
2570 | { | 2569 | { |
2571 | struct super_block *sb = inode->i_sb; | 2570 | struct super_block *sb = inode->i_sb; |
2572 | int depth = ext_depth(inode); | 2571 | int depth = ext_depth(inode); |
2573 | struct ext4_ext_path *path; | 2572 | struct ext4_ext_path *path = NULL; |
2574 | ext4_fsblk_t partial_cluster = 0; | 2573 | ext4_fsblk_t partial_cluster = 0; |
2575 | handle_t *handle; | 2574 | handle_t *handle; |
2576 | int i, err; | 2575 | int i = 0, err; |
2577 | 2576 | ||
2578 | ext_debug("truncate since %u to %u\n", start, end); | 2577 | ext_debug("truncate since %u to %u\n", start, end); |
2579 | 2578 | ||
@@ -2606,8 +2605,12 @@ again: | |||
2606 | } | 2605 | } |
2607 | depth = ext_depth(inode); | 2606 | depth = ext_depth(inode); |
2608 | ex = path[depth].p_ext; | 2607 | ex = path[depth].p_ext; |
2609 | if (!ex) | 2608 | if (!ex) { |
2609 | ext4_ext_drop_refs(path); | ||
2610 | kfree(path); | ||
2611 | path = NULL; | ||
2610 | goto cont; | 2612 | goto cont; |
2613 | } | ||
2611 | 2614 | ||
2612 | ee_block = le32_to_cpu(ex->ee_block); | 2615 | ee_block = le32_to_cpu(ex->ee_block); |
2613 | 2616 | ||
@@ -2637,8 +2640,6 @@ again: | |||
2637 | if (err < 0) | 2640 | if (err < 0) |
2638 | goto out; | 2641 | goto out; |
2639 | } | 2642 | } |
2640 | ext4_ext_drop_refs(path); | ||
2641 | kfree(path); | ||
2642 | } | 2643 | } |
2643 | cont: | 2644 | cont: |
2644 | 2645 | ||
@@ -2647,19 +2648,27 @@ cont: | |||
2647 | * after i_size and walking into the tree depth-wise. | 2648 | * after i_size and walking into the tree depth-wise. |
2648 | */ | 2649 | */ |
2649 | depth = ext_depth(inode); | 2650 | depth = ext_depth(inode); |
2650 | path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), GFP_NOFS); | 2651 | if (path) { |
2651 | if (path == NULL) { | 2652 | int k = i = depth; |
2652 | ext4_journal_stop(handle); | 2653 | while (--k > 0) |
2653 | return -ENOMEM; | 2654 | path[k].p_block = |
2654 | } | 2655 | le16_to_cpu(path[k].p_hdr->eh_entries)+1; |
2655 | path[0].p_depth = depth; | 2656 | } else { |
2656 | path[0].p_hdr = ext_inode_hdr(inode); | 2657 | path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), |
2658 | GFP_NOFS); | ||
2659 | if (path == NULL) { | ||
2660 | ext4_journal_stop(handle); | ||
2661 | return -ENOMEM; | ||
2662 | } | ||
2663 | path[0].p_depth = depth; | ||
2664 | path[0].p_hdr = ext_inode_hdr(inode); | ||
2657 | 2665 | ||
2658 | if (ext4_ext_check(inode, path[0].p_hdr, depth)) { | 2666 | if (ext4_ext_check(inode, path[0].p_hdr, depth)) { |
2659 | err = -EIO; | 2667 | err = -EIO; |
2660 | goto out; | 2668 | goto out; |
2669 | } | ||
2661 | } | 2670 | } |
2662 | i = err = 0; | 2671 | err = 0; |
2663 | 2672 | ||
2664 | while (i >= 0 && err == 0) { | 2673 | while (i >= 0 && err == 0) { |
2665 | if (i == depth) { | 2674 | if (i == depth) { |
@@ -2773,8 +2782,10 @@ cont: | |||
2773 | out: | 2782 | out: |
2774 | ext4_ext_drop_refs(path); | 2783 | ext4_ext_drop_refs(path); |
2775 | kfree(path); | 2784 | kfree(path); |
2776 | if (err == -EAGAIN) | 2785 | if (err == -EAGAIN) { |
2786 | path = NULL; | ||
2777 | goto again; | 2787 | goto again; |
2788 | } | ||
2778 | ext4_journal_stop(handle); | 2789 | ext4_journal_stop(handle); |
2779 | 2790 | ||
2780 | return err; | 2791 | return err; |
@@ -4420,6 +4431,8 @@ retry: | |||
4420 | ext4_falloc_update_inode(inode, mode, new_size, | 4431 | ext4_falloc_update_inode(inode, mode, new_size, |
4421 | (map.m_flags & EXT4_MAP_NEW)); | 4432 | (map.m_flags & EXT4_MAP_NEW)); |
4422 | ext4_mark_inode_dirty(handle, inode); | 4433 | ext4_mark_inode_dirty(handle, inode); |
4434 | if ((file->f_flags & O_SYNC) && ret >= max_blocks) | ||
4435 | ext4_handle_sync(handle); | ||
4423 | ret2 = ext4_journal_stop(handle); | 4436 | ret2 = ext4_journal_stop(handle); |
4424 | if (ret2) | 4437 | if (ret2) |
4425 | break; | 4438 | break; |