diff options
-rw-r--r-- | fs/ext4/extents.c | 46 |
1 files changed, 29 insertions, 17 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 46b5c9fdc96..cd0c7ed0677 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -2569,10 +2569,10 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, | |||
2569 | { | 2569 | { |
2570 | struct super_block *sb = inode->i_sb; | 2570 | struct super_block *sb = inode->i_sb; |
2571 | int depth = ext_depth(inode); | 2571 | int depth = ext_depth(inode); |
2572 | struct ext4_ext_path *path; | 2572 | struct ext4_ext_path *path = NULL; |
2573 | ext4_fsblk_t partial_cluster = 0; | 2573 | ext4_fsblk_t partial_cluster = 0; |
2574 | handle_t *handle; | 2574 | handle_t *handle; |
2575 | int i, err; | 2575 | int i = 0, err; |
2576 | 2576 | ||
2577 | ext_debug("truncate since %u to %u\n", start, end); | 2577 | ext_debug("truncate since %u to %u\n", start, end); |
2578 | 2578 | ||
@@ -2605,8 +2605,12 @@ again: | |||
2605 | } | 2605 | } |
2606 | depth = ext_depth(inode); | 2606 | depth = ext_depth(inode); |
2607 | ex = path[depth].p_ext; | 2607 | ex = path[depth].p_ext; |
2608 | if (!ex) | 2608 | if (!ex) { |
2609 | ext4_ext_drop_refs(path); | ||
2610 | kfree(path); | ||
2611 | path = NULL; | ||
2609 | goto cont; | 2612 | goto cont; |
2613 | } | ||
2610 | 2614 | ||
2611 | ee_block = le32_to_cpu(ex->ee_block); | 2615 | ee_block = le32_to_cpu(ex->ee_block); |
2612 | 2616 | ||
@@ -2636,8 +2640,6 @@ again: | |||
2636 | if (err < 0) | 2640 | if (err < 0) |
2637 | goto out; | 2641 | goto out; |
2638 | } | 2642 | } |
2639 | ext4_ext_drop_refs(path); | ||
2640 | kfree(path); | ||
2641 | } | 2643 | } |
2642 | cont: | 2644 | cont: |
2643 | 2645 | ||
@@ -2646,19 +2648,27 @@ cont: | |||
2646 | * after i_size and walking into the tree depth-wise. | 2648 | * after i_size and walking into the tree depth-wise. |
2647 | */ | 2649 | */ |
2648 | depth = ext_depth(inode); | 2650 | depth = ext_depth(inode); |
2649 | path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), GFP_NOFS); | 2651 | if (path) { |
2650 | if (path == NULL) { | 2652 | int k = i = depth; |
2651 | ext4_journal_stop(handle); | 2653 | while (--k > 0) |
2652 | return -ENOMEM; | 2654 | path[k].p_block = |
2653 | } | 2655 | le16_to_cpu(path[k].p_hdr->eh_entries)+1; |
2654 | path[0].p_depth = depth; | 2656 | } else { |
2655 | 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); | ||
2656 | 2665 | ||
2657 | if (ext4_ext_check(inode, path[0].p_hdr, depth)) { | 2666 | if (ext4_ext_check(inode, path[0].p_hdr, depth)) { |
2658 | err = -EIO; | 2667 | err = -EIO; |
2659 | goto out; | 2668 | goto out; |
2669 | } | ||
2660 | } | 2670 | } |
2661 | i = err = 0; | 2671 | err = 0; |
2662 | 2672 | ||
2663 | while (i >= 0 && err == 0) { | 2673 | while (i >= 0 && err == 0) { |
2664 | if (i == depth) { | 2674 | if (i == depth) { |
@@ -2772,8 +2782,10 @@ cont: | |||
2772 | out: | 2782 | out: |
2773 | ext4_ext_drop_refs(path); | 2783 | ext4_ext_drop_refs(path); |
2774 | kfree(path); | 2784 | kfree(path); |
2775 | if (err == -EAGAIN) | 2785 | if (err == -EAGAIN) { |
2786 | path = NULL; | ||
2776 | goto again; | 2787 | goto again; |
2788 | } | ||
2777 | ext4_journal_stop(handle); | 2789 | ext4_journal_stop(handle); |
2778 | 2790 | ||
2779 | return err; | 2791 | return err; |