Commit 7bdcefc1 authored by Filipe Manana's avatar Filipe Manana Committed by Chris Mason

Btrfs: don't ignore compressed bio write errors

Our compressed bio write end callback was essentially ignoring the error
parameter. When a write error happens, it must pass a value of 0 to the
inode's write_page_end_io_hook callback, SetPageError on the respective
pages and set AS_EIO in the inode's mapping flags, so that a call to
filemap_fdatawait_range() / filemap_fdatawait() can find out that errors
happened (we surely don't want silent failures on fsync for example).
Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
Signed-off-by: default avatarChris Mason <clm@fb.com>
parent dec8f175
...@@ -224,16 +224,19 @@ static void end_compressed_bio_read(struct bio *bio, int err) ...@@ -224,16 +224,19 @@ static void end_compressed_bio_read(struct bio *bio, int err)
* Clear the writeback bits on all of the file * Clear the writeback bits on all of the file
* pages for a compressed write * pages for a compressed write
*/ */
static noinline void end_compressed_writeback(struct inode *inode, u64 start, static noinline void end_compressed_writeback(struct inode *inode,
unsigned long ram_size) const struct compressed_bio *cb)
{ {
unsigned long index = start >> PAGE_CACHE_SHIFT; unsigned long index = cb->start >> PAGE_CACHE_SHIFT;
unsigned long end_index = (start + ram_size - 1) >> PAGE_CACHE_SHIFT; unsigned long end_index = (cb->start + cb->len - 1) >> PAGE_CACHE_SHIFT;
struct page *pages[16]; struct page *pages[16];
unsigned long nr_pages = end_index - index + 1; unsigned long nr_pages = end_index - index + 1;
int i; int i;
int ret; int ret;
if (cb->errors)
mapping_set_error(inode->i_mapping, -EIO);
while (nr_pages > 0) { while (nr_pages > 0) {
ret = find_get_pages_contig(inode->i_mapping, index, ret = find_get_pages_contig(inode->i_mapping, index,
min_t(unsigned long, min_t(unsigned long,
...@@ -244,6 +247,8 @@ static noinline void end_compressed_writeback(struct inode *inode, u64 start, ...@@ -244,6 +247,8 @@ static noinline void end_compressed_writeback(struct inode *inode, u64 start,
continue; continue;
} }
for (i = 0; i < ret; i++) { for (i = 0; i < ret; i++) {
if (cb->errors)
SetPageError(pages[i]);
end_page_writeback(pages[i]); end_page_writeback(pages[i]);
page_cache_release(pages[i]); page_cache_release(pages[i]);
} }
...@@ -287,10 +292,11 @@ static void end_compressed_bio_write(struct bio *bio, int err) ...@@ -287,10 +292,11 @@ static void end_compressed_bio_write(struct bio *bio, int err)
tree->ops->writepage_end_io_hook(cb->compressed_pages[0], tree->ops->writepage_end_io_hook(cb->compressed_pages[0],
cb->start, cb->start,
cb->start + cb->len - 1, cb->start + cb->len - 1,
NULL, 1); NULL,
err ? 0 : 1);
cb->compressed_pages[0]->mapping = NULL; cb->compressed_pages[0]->mapping = NULL;
end_compressed_writeback(inode, cb->start, cb->len); end_compressed_writeback(inode, cb);
/* note, our inode could be gone now */ /* note, our inode could be gone now */
/* /*
......
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