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.c89
1 files changed, 38 insertions, 51 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 668d82e494dd..c2b004e29ad8 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -2785,6 +2785,28 @@ int ext4_ext_writepage_trans_blocks(struct inode *inode, int num)
2785 return needed; 2785 return needed;
2786} 2786}
2787 2787
2788static void ext4_falloc_update_inode(struct inode *inode,
2789 int mode, loff_t new_size, int update_ctime)
2790{
2791 struct timespec now;
2792
2793 if (update_ctime) {
2794 now = current_fs_time(inode->i_sb);
2795 if (!timespec_equal(&inode->i_ctime, &now))
2796 inode->i_ctime = now;
2797 }
2798 /*
2799 * Update only when preallocation was requested beyond
2800 * the file size.
2801 */
2802 if (!(mode & FALLOC_FL_KEEP_SIZE) &&
2803 new_size > i_size_read(inode)) {
2804 i_size_write(inode, new_size);
2805 EXT4_I(inode)->i_disksize = new_size;
2806 }
2807
2808}
2809
2788/* 2810/*
2789 * preallocate space for a file. This implements ext4's fallocate inode 2811 * preallocate space for a file. This implements ext4's fallocate inode
2790 * operation, which gets called from sys_fallocate system call. 2812 * operation, which gets called from sys_fallocate system call.
@@ -2796,8 +2818,8 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
2796{ 2818{
2797 handle_t *handle; 2819 handle_t *handle;
2798 ext4_lblk_t block; 2820 ext4_lblk_t block;
2821 loff_t new_size;
2799 unsigned long max_blocks; 2822 unsigned long max_blocks;
2800 ext4_fsblk_t nblocks = 0;
2801 int ret = 0; 2823 int ret = 0;
2802 int ret2 = 0; 2824 int ret2 = 0;
2803 int retries = 0; 2825 int retries = 0;
@@ -2816,9 +2838,12 @@ long ext4_fallocate(struct inode *inode, int mode, loff_t offset, loff_t len)
2816 return -ENODEV; 2838 return -ENODEV;
2817 2839
2818 block = offset >> blkbits; 2840 block = offset >> blkbits;
2841 /*
2842 * We can't just convert len to max_blocks because
2843 * If blocksize = 4096 offset = 3072 and len = 2048
2844 */
2819 max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits) 2845 max_blocks = (EXT4_BLOCK_ALIGN(len + offset, blkbits) >> blkbits)
2820 - block; 2846 - block;
2821
2822 /* 2847 /*
2823 * credits to insert 1 extent into extent tree + buffers to be able to 2848 * credits to insert 1 extent into extent tree + buffers to be able to
2824 * modify 1 super block, 1 block bitmap and 1 group descriptor. 2849 * modify 1 super block, 1 block bitmap and 1 group descriptor.
@@ -2834,7 +2859,6 @@ retry:
2834 ret = PTR_ERR(handle); 2859 ret = PTR_ERR(handle);
2835 break; 2860 break;
2836 } 2861 }
2837
2838 ret = ext4_get_blocks_wrap(handle, inode, block, 2862 ret = ext4_get_blocks_wrap(handle, inode, block,
2839 max_blocks, &map_bh, 2863 max_blocks, &map_bh,
2840 EXT4_CREATE_UNINITIALIZED_EXT, 0); 2864 EXT4_CREATE_UNINITIALIZED_EXT, 0);
@@ -2850,61 +2874,24 @@ retry:
2850 ret2 = ext4_journal_stop(handle); 2874 ret2 = ext4_journal_stop(handle);
2851 break; 2875 break;
2852 } 2876 }
2853 if (ret > 0) { 2877 if ((block + ret) >= (EXT4_BLOCK_ALIGN(offset + len,
2854 /* check wrap through sign-bit/zero here */ 2878 blkbits) >> blkbits))
2855 if ((block + ret) < 0 || (block + ret) < block) { 2879 new_size = offset + len;
2856 ret = -EIO; 2880 else
2857 ext4_mark_inode_dirty(handle, inode); 2881 new_size = (block + ret) << blkbits;
2858 ret2 = ext4_journal_stop(handle);
2859 break;
2860 }
2861 if (buffer_new(&map_bh) && ((block + ret) >
2862 (EXT4_BLOCK_ALIGN(i_size_read(inode), blkbits)
2863 >> blkbits)))
2864 nblocks = nblocks + ret;
2865 }
2866
2867 /* Update ctime if new blocks get allocated */
2868 if (nblocks) {
2869 struct timespec now;
2870
2871 now = current_fs_time(inode->i_sb);
2872 if (!timespec_equal(&inode->i_ctime, &now))
2873 inode->i_ctime = now;
2874 }
2875 2882
2883 ext4_falloc_update_inode(inode, mode, new_size,
2884 buffer_new(&map_bh));
2876 ext4_mark_inode_dirty(handle, inode); 2885 ext4_mark_inode_dirty(handle, inode);
2877 ret2 = ext4_journal_stop(handle); 2886 ret2 = ext4_journal_stop(handle);
2878 if (ret2) 2887 if (ret2)
2879 break; 2888 break;
2880 } 2889 }
2881 2890 if (ret == -ENOSPC &&
2882 if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) 2891 ext4_should_retry_alloc(inode->i_sb, &retries)) {
2892 ret = 0;
2883 goto retry; 2893 goto retry;
2884
2885 /*
2886 * Time to update the file size.
2887 * Update only when preallocation was requested beyond the file size.
2888 */
2889 if (!(mode & FALLOC_FL_KEEP_SIZE) &&
2890 (offset + len) > i_size_read(inode)) {
2891 if (ret > 0) {
2892 /*
2893 * if no error, we assume preallocation succeeded
2894 * completely
2895 */
2896 i_size_write(inode, offset + len);
2897 EXT4_I(inode)->i_disksize = i_size_read(inode);
2898 } else if (ret < 0 && nblocks) {
2899 /* Handle partial allocation scenario */
2900 loff_t newsize;
2901
2902 newsize = (nblocks << blkbits) + i_size_read(inode);
2903 i_size_write(inode, EXT4_BLOCK_ALIGN(newsize, blkbits));
2904 EXT4_I(inode)->i_disksize = i_size_read(inode);
2905 }
2906 } 2894 }
2907
2908 mutex_unlock(&inode->i_mutex); 2895 mutex_unlock(&inode->i_mutex);
2909 return ret > 0 ? ret2 : ret; 2896 return ret > 0 ? ret2 : ret;
2910} 2897}