diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/ext4.h | 2 | ||||
-rw-r--r-- | fs/ext4/inode.c | 33 |
2 files changed, 33 insertions, 2 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 2f310d1839ed..c48f9db5b96b 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -1825,6 +1825,8 @@ extern int ext4_writepage_trans_blocks(struct inode *); | |||
1825 | extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks); | 1825 | extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks); |
1826 | extern int ext4_block_truncate_page(handle_t *handle, | 1826 | extern int ext4_block_truncate_page(handle_t *handle, |
1827 | struct address_space *mapping, loff_t from); | 1827 | struct address_space *mapping, loff_t from); |
1828 | extern int ext4_block_zero_page_range(handle_t *handle, | ||
1829 | struct address_space *mapping, loff_t from, loff_t length); | ||
1828 | extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); | 1830 | extern int ext4_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); |
1829 | extern qsize_t *ext4_get_reserved_space(struct inode *inode); | 1831 | extern qsize_t *ext4_get_reserved_space(struct inode *inode); |
1830 | extern void ext4_da_update_reserve_space(struct inode *inode, | 1832 | extern void ext4_da_update_reserve_space(struct inode *inode, |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index aef864b725d3..fbe11e676624 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -3914,9 +3914,30 @@ void ext4_set_aops(struct inode *inode) | |||
3914 | int ext4_block_truncate_page(handle_t *handle, | 3914 | int ext4_block_truncate_page(handle_t *handle, |
3915 | struct address_space *mapping, loff_t from) | 3915 | struct address_space *mapping, loff_t from) |
3916 | { | 3916 | { |
3917 | unsigned offset = from & (PAGE_CACHE_SIZE-1); | ||
3918 | unsigned length; | ||
3919 | unsigned blocksize; | ||
3920 | struct inode *inode = mapping->host; | ||
3921 | |||
3922 | blocksize = inode->i_sb->s_blocksize; | ||
3923 | length = blocksize - (offset & (blocksize - 1)); | ||
3924 | |||
3925 | return ext4_block_zero_page_range(handle, mapping, from, length); | ||
3926 | } | ||
3927 | |||
3928 | /* | ||
3929 | * ext4_block_zero_page_range() zeros out a mapping of length 'length' | ||
3930 | * starting from file offset 'from'. The range to be zero'd must | ||
3931 | * be contained with in one block. If the specified range exceeds | ||
3932 | * the end of the block it will be shortened to end of the block | ||
3933 | * that cooresponds to 'from' | ||
3934 | */ | ||
3935 | int ext4_block_zero_page_range(handle_t *handle, | ||
3936 | struct address_space *mapping, loff_t from, loff_t length) | ||
3937 | { | ||
3917 | ext4_fsblk_t index = from >> PAGE_CACHE_SHIFT; | 3938 | ext4_fsblk_t index = from >> PAGE_CACHE_SHIFT; |
3918 | unsigned offset = from & (PAGE_CACHE_SIZE-1); | 3939 | unsigned offset = from & (PAGE_CACHE_SIZE-1); |
3919 | unsigned blocksize, length, pos; | 3940 | unsigned blocksize, max, pos; |
3920 | ext4_lblk_t iblock; | 3941 | ext4_lblk_t iblock; |
3921 | struct inode *inode = mapping->host; | 3942 | struct inode *inode = mapping->host; |
3922 | struct buffer_head *bh; | 3943 | struct buffer_head *bh; |
@@ -3929,7 +3950,15 @@ int ext4_block_truncate_page(handle_t *handle, | |||
3929 | return -EINVAL; | 3950 | return -EINVAL; |
3930 | 3951 | ||
3931 | blocksize = inode->i_sb->s_blocksize; | 3952 | blocksize = inode->i_sb->s_blocksize; |
3932 | length = blocksize - (offset & (blocksize - 1)); | 3953 | max = blocksize - (offset & (blocksize - 1)); |
3954 | |||
3955 | /* | ||
3956 | * correct length if it does not fall between | ||
3957 | * 'from' and the end of the block | ||
3958 | */ | ||
3959 | if (length > max || length < 0) | ||
3960 | length = max; | ||
3961 | |||
3933 | iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); | 3962 | iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); |
3934 | 3963 | ||
3935 | if (!page_has_buffers(page)) | 3964 | if (!page_has_buffers(page)) |