aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/extents.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r--fs/ext4/extents.c67
1 files changed, 51 insertions, 16 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 228eeaf2dccf..ee611daf0748 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -2631,11 +2631,21 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
2631 struct ext4_extent *ex2 = NULL; 2631 struct ext4_extent *ex2 = NULL;
2632 struct ext4_extent *ex3 = NULL; 2632 struct ext4_extent *ex3 = NULL;
2633 struct ext4_extent_header *eh; 2633 struct ext4_extent_header *eh;
2634 ext4_lblk_t ee_block; 2634 ext4_lblk_t ee_block, eof_block;
2635 unsigned int allocated, ee_len, depth; 2635 unsigned int allocated, ee_len, depth;
2636 ext4_fsblk_t newblock; 2636 ext4_fsblk_t newblock;
2637 int err = 0; 2637 int err = 0;
2638 int ret = 0; 2638 int ret = 0;
2639 int may_zeroout;
2640
2641 ext_debug("ext4_ext_convert_to_initialized: inode %lu, logical"
2642 "block %llu, max_blocks %u\n", inode->i_ino,
2643 (unsigned long long)iblock, max_blocks);
2644
2645 eof_block = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
2646 inode->i_sb->s_blocksize_bits;
2647 if (eof_block < iblock + max_blocks)
2648 eof_block = iblock + max_blocks;
2639 2649
2640 depth = ext_depth(inode); 2650 depth = ext_depth(inode);
2641 eh = path[depth].p_hdr; 2651 eh = path[depth].p_hdr;
@@ -2644,16 +2654,23 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
2644 ee_len = ext4_ext_get_actual_len(ex); 2654 ee_len = ext4_ext_get_actual_len(ex);
2645 allocated = ee_len - (iblock - ee_block); 2655 allocated = ee_len - (iblock - ee_block);
2646 newblock = iblock - ee_block + ext_pblock(ex); 2656 newblock = iblock - ee_block + ext_pblock(ex);
2657
2647 ex2 = ex; 2658 ex2 = ex;
2648 orig_ex.ee_block = ex->ee_block; 2659 orig_ex.ee_block = ex->ee_block;
2649 orig_ex.ee_len = cpu_to_le16(ee_len); 2660 orig_ex.ee_len = cpu_to_le16(ee_len);
2650 ext4_ext_store_pblock(&orig_ex, ext_pblock(ex)); 2661 ext4_ext_store_pblock(&orig_ex, ext_pblock(ex));
2651 2662
2663 /*
2664 * It is safe to convert extent to initialized via explicit
2665 * zeroout only if extent is fully insde i_size or new_size.
2666 */
2667 may_zeroout = ee_block + ee_len <= eof_block;
2668
2652 err = ext4_ext_get_access(handle, inode, path + depth); 2669 err = ext4_ext_get_access(handle, inode, path + depth);
2653 if (err) 2670 if (err)
2654 goto out; 2671 goto out;
2655 /* If extent has less than 2*EXT4_EXT_ZERO_LEN zerout directly */ 2672 /* If extent has less than 2*EXT4_EXT_ZERO_LEN zerout directly */
2656 if (ee_len <= 2*EXT4_EXT_ZERO_LEN) { 2673 if (ee_len <= 2*EXT4_EXT_ZERO_LEN && may_zeroout) {
2657 err = ext4_ext_zeroout(inode, &orig_ex); 2674 err = ext4_ext_zeroout(inode, &orig_ex);
2658 if (err) 2675 if (err)
2659 goto fix_extent_len; 2676 goto fix_extent_len;
@@ -2684,7 +2701,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
2684 if (allocated > max_blocks) { 2701 if (allocated > max_blocks) {
2685 unsigned int newdepth; 2702 unsigned int newdepth;
2686 /* If extent has less than EXT4_EXT_ZERO_LEN zerout directly */ 2703 /* If extent has less than EXT4_EXT_ZERO_LEN zerout directly */
2687 if (allocated <= EXT4_EXT_ZERO_LEN) { 2704 if (allocated <= EXT4_EXT_ZERO_LEN && may_zeroout) {
2688 /* 2705 /*
2689 * iblock == ee_block is handled by the zerouout 2706 * iblock == ee_block is handled by the zerouout
2690 * at the beginning. 2707 * at the beginning.
@@ -2760,7 +2777,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
2760 ex3->ee_len = cpu_to_le16(allocated - max_blocks); 2777 ex3->ee_len = cpu_to_le16(allocated - max_blocks);
2761 ext4_ext_mark_uninitialized(ex3); 2778 ext4_ext_mark_uninitialized(ex3);
2762 err = ext4_ext_insert_extent(handle, inode, path, ex3, 0); 2779 err = ext4_ext_insert_extent(handle, inode, path, ex3, 0);
2763 if (err == -ENOSPC) { 2780 if (err == -ENOSPC && may_zeroout) {
2764 err = ext4_ext_zeroout(inode, &orig_ex); 2781 err = ext4_ext_zeroout(inode, &orig_ex);
2765 if (err) 2782 if (err)
2766 goto fix_extent_len; 2783 goto fix_extent_len;
@@ -2784,8 +2801,10 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
2784 * update the extent length after successful insert of the 2801 * update the extent length after successful insert of the
2785 * split extent 2802 * split extent
2786 */ 2803 */
2787 orig_ex.ee_len = cpu_to_le16(ee_len - 2804 ee_len -= ext4_ext_get_actual_len(ex3);
2788 ext4_ext_get_actual_len(ex3)); 2805 orig_ex.ee_len = cpu_to_le16(ee_len);
2806 may_zeroout = ee_block + ee_len <= eof_block;
2807
2789 depth = newdepth; 2808 depth = newdepth;
2790 ext4_ext_drop_refs(path); 2809 ext4_ext_drop_refs(path);
2791 path = ext4_ext_find_extent(inode, iblock, path); 2810 path = ext4_ext_find_extent(inode, iblock, path);
@@ -2809,7 +2828,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
2809 * otherwise give the extent a chance to merge to left 2828 * otherwise give the extent a chance to merge to left
2810 */ 2829 */
2811 if (le16_to_cpu(orig_ex.ee_len) <= EXT4_EXT_ZERO_LEN && 2830 if (le16_to_cpu(orig_ex.ee_len) <= EXT4_EXT_ZERO_LEN &&
2812 iblock != ee_block) { 2831 iblock != ee_block && may_zeroout) {
2813 err = ext4_ext_zeroout(inode, &orig_ex); 2832 err = ext4_ext_zeroout(inode, &orig_ex);
2814 if (err) 2833 if (err)
2815 goto fix_extent_len; 2834 goto fix_extent_len;
@@ -2878,7 +2897,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
2878 goto out; 2897 goto out;
2879insert: 2898insert:
2880 err = ext4_ext_insert_extent(handle, inode, path, &newex, 0); 2899 err = ext4_ext_insert_extent(handle, inode, path, &newex, 0);
2881 if (err == -ENOSPC) { 2900 if (err == -ENOSPC && may_zeroout) {
2882 err = ext4_ext_zeroout(inode, &orig_ex); 2901 err = ext4_ext_zeroout(inode, &orig_ex);
2883 if (err) 2902 if (err)
2884 goto fix_extent_len; 2903 goto fix_extent_len;
@@ -2938,14 +2957,21 @@ static int ext4_split_unwritten_extents(handle_t *handle,
2938 struct ext4_extent *ex2 = NULL; 2957 struct ext4_extent *ex2 = NULL;
2939 struct ext4_extent *ex3 = NULL; 2958 struct ext4_extent *ex3 = NULL;
2940 struct ext4_extent_header *eh; 2959 struct ext4_extent_header *eh;
2941 ext4_lblk_t ee_block; 2960 ext4_lblk_t ee_block, eof_block;
2942 unsigned int allocated, ee_len, depth; 2961 unsigned int allocated, ee_len, depth;
2943 ext4_fsblk_t newblock; 2962 ext4_fsblk_t newblock;
2944 int err = 0; 2963 int err = 0;
2964 int may_zeroout;
2965
2966 ext_debug("ext4_split_unwritten_extents: inode %lu, logical"
2967 "block %llu, max_blocks %u\n", inode->i_ino,
2968 (unsigned long long)iblock, max_blocks);
2969
2970 eof_block = (inode->i_size + inode->i_sb->s_blocksize - 1) >>
2971 inode->i_sb->s_blocksize_bits;
2972 if (eof_block < iblock + max_blocks)
2973 eof_block = iblock + max_blocks;
2945 2974
2946 ext_debug("ext4_split_unwritten_extents: inode %lu,"
2947 "iblock %llu, max_blocks %u\n", inode->i_ino,
2948 (unsigned long long)iblock, max_blocks);
2949 depth = ext_depth(inode); 2975 depth = ext_depth(inode);
2950 eh = path[depth].p_hdr; 2976 eh = path[depth].p_hdr;
2951 ex = path[depth].p_ext; 2977 ex = path[depth].p_ext;
@@ -2953,12 +2979,19 @@ static int ext4_split_unwritten_extents(handle_t *handle,
2953 ee_len = ext4_ext_get_actual_len(ex); 2979 ee_len = ext4_ext_get_actual_len(ex);
2954 allocated = ee_len - (iblock - ee_block); 2980 allocated = ee_len - (iblock - ee_block);
2955 newblock = iblock - ee_block + ext_pblock(ex); 2981 newblock = iblock - ee_block + ext_pblock(ex);
2982
2956 ex2 = ex; 2983 ex2 = ex;
2957 orig_ex.ee_block = ex->ee_block; 2984 orig_ex.ee_block = ex->ee_block;
2958 orig_ex.ee_len = cpu_to_le16(ee_len); 2985 orig_ex.ee_len = cpu_to_le16(ee_len);
2959 ext4_ext_store_pblock(&orig_ex, ext_pblock(ex)); 2986 ext4_ext_store_pblock(&orig_ex, ext_pblock(ex));
2960 2987
2961 /* 2988 /*
2989 * It is safe to convert extent to initialized via explicit
2990 * zeroout only if extent is fully insde i_size or new_size.
2991 */
2992 may_zeroout = ee_block + ee_len <= eof_block;
2993
2994 /*
2962 * If the uninitialized extent begins at the same logical 2995 * If the uninitialized extent begins at the same logical
2963 * block where the write begins, and the write completely 2996 * block where the write begins, and the write completely
2964 * covers the extent, then we don't need to split it. 2997 * covers the extent, then we don't need to split it.
@@ -2992,7 +3025,7 @@ static int ext4_split_unwritten_extents(handle_t *handle,
2992 ex3->ee_len = cpu_to_le16(allocated - max_blocks); 3025 ex3->ee_len = cpu_to_le16(allocated - max_blocks);
2993 ext4_ext_mark_uninitialized(ex3); 3026 ext4_ext_mark_uninitialized(ex3);
2994 err = ext4_ext_insert_extent(handle, inode, path, ex3, flags); 3027 err = ext4_ext_insert_extent(handle, inode, path, ex3, flags);
2995 if (err == -ENOSPC) { 3028 if (err == -ENOSPC && may_zeroout) {
2996 err = ext4_ext_zeroout(inode, &orig_ex); 3029 err = ext4_ext_zeroout(inode, &orig_ex);
2997 if (err) 3030 if (err)
2998 goto fix_extent_len; 3031 goto fix_extent_len;
@@ -3016,8 +3049,10 @@ static int ext4_split_unwritten_extents(handle_t *handle,
3016 * update the extent length after successful insert of the 3049 * update the extent length after successful insert of the
3017 * split extent 3050 * split extent
3018 */ 3051 */
3019 orig_ex.ee_len = cpu_to_le16(ee_len - 3052 ee_len -= ext4_ext_get_actual_len(ex3);
3020 ext4_ext_get_actual_len(ex3)); 3053 orig_ex.ee_len = cpu_to_le16(ee_len);
3054 may_zeroout = ee_block + ee_len <= eof_block;
3055
3021 depth = newdepth; 3056 depth = newdepth;
3022 ext4_ext_drop_refs(path); 3057 ext4_ext_drop_refs(path);
3023 path = ext4_ext_find_extent(inode, iblock, path); 3058 path = ext4_ext_find_extent(inode, iblock, path);
@@ -3063,7 +3098,7 @@ static int ext4_split_unwritten_extents(handle_t *handle,
3063 goto out; 3098 goto out;
3064insert: 3099insert:
3065 err = ext4_ext_insert_extent(handle, inode, path, &newex, flags); 3100 err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
3066 if (err == -ENOSPC) { 3101 if (err == -ENOSPC && may_zeroout) {
3067 err = ext4_ext_zeroout(inode, &orig_ex); 3102 err = ext4_ext_zeroout(inode, &orig_ex);
3068 if (err) 3103 if (err)
3069 goto fix_extent_len; 3104 goto fix_extent_len;