Commit 093e6e36 authored by Yongqiang Yang's avatar Yongqiang Yang Committed by Theodore Ts'o

ext4: correctly handle pages w/o buffers in ext4_discard_partial_buffers()

If a page has been read into memory and never been written, it has no
buffers, but we should handle the page in truncate or punch hole.

VFS code of writing operations has handled holes correctly, so this
patch removes the code handling holes in writing operations.
Signed-off-by: default avatarYongqiang Yang <xiaoqiangnk@gmail.com>
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
Cc: stable@kernel.org
parent 13a79a47
...@@ -2390,7 +2390,6 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, ...@@ -2390,7 +2390,6 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
pgoff_t index; pgoff_t index;
struct inode *inode = mapping->host; struct inode *inode = mapping->host;
handle_t *handle; handle_t *handle;
loff_t page_len;
index = pos >> PAGE_CACHE_SHIFT; index = pos >> PAGE_CACHE_SHIFT;
...@@ -2437,13 +2436,6 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, ...@@ -2437,13 +2436,6 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping,
*/ */
if (pos + len > inode->i_size) if (pos + len > inode->i_size)
ext4_truncate_failed_write(inode); ext4_truncate_failed_write(inode);
} else {
page_len = pos & (PAGE_CACHE_SIZE - 1);
if (page_len > 0) {
ret = ext4_discard_partial_page_buffers_no_lock(handle,
inode, page, pos - page_len, page_len,
EXT4_DISCARD_PARTIAL_PG_ZERO_UNMAPPED);
}
} }
if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) if (ret == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries))
...@@ -2486,7 +2478,6 @@ static int ext4_da_write_end(struct file *file, ...@@ -2486,7 +2478,6 @@ static int ext4_da_write_end(struct file *file,
loff_t new_i_size; loff_t new_i_size;
unsigned long start, end; unsigned long start, end;
int write_mode = (int)(unsigned long)fsdata; int write_mode = (int)(unsigned long)fsdata;
loff_t page_len;
if (write_mode == FALL_BACK_TO_NONDELALLOC) { if (write_mode == FALL_BACK_TO_NONDELALLOC) {
if (ext4_should_order_data(inode)) { if (ext4_should_order_data(inode)) {
...@@ -2535,16 +2526,6 @@ static int ext4_da_write_end(struct file *file, ...@@ -2535,16 +2526,6 @@ static int ext4_da_write_end(struct file *file,
} }
ret2 = generic_write_end(file, mapping, pos, len, copied, ret2 = generic_write_end(file, mapping, pos, len, copied,
page, fsdata); page, fsdata);
page_len = PAGE_CACHE_SIZE -
((pos + copied - 1) & (PAGE_CACHE_SIZE - 1));
if (page_len > 0) {
ret = ext4_discard_partial_page_buffers_no_lock(handle,
inode, page, pos + copied - 1, page_len,
EXT4_DISCARD_PARTIAL_PG_ZERO_UNMAPPED);
}
copied = ret2; copied = ret2;
if (ret2 < 0) if (ret2 < 0)
ret = ret2; ret = ret2;
...@@ -3206,26 +3187,8 @@ int ext4_discard_partial_page_buffers_no_lock(handle_t *handle, ...@@ -3206,26 +3187,8 @@ int ext4_discard_partial_page_buffers_no_lock(handle_t *handle,
iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits); iblock = index << (PAGE_CACHE_SHIFT - inode->i_sb->s_blocksize_bits);
if (!page_has_buffers(page)) { if (!page_has_buffers(page))
/* create_empty_buffers(page, blocksize, 0);
* If the range to be discarded covers a partial block
* we need to get the page buffers. This is because
* partial blocks cannot be released and the page needs
* to be updated with the contents of the block before
* we write the zeros on top of it.
*/
if ((from & (blocksize - 1)) ||
((from + length) & (blocksize - 1))) {
create_empty_buffers(page, blocksize, 0);
} else {
/*
* If there are no partial blocks,
* there is nothing to update,
* so we can return now
*/
return 0;
}
}
/* Find the buffer that contains "offset" */ /* Find the buffer that contains "offset" */
bh = page_buffers(page); bh = page_buffers(page);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment