summaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2014-10-06 22:14:23 +0100
committerChris Mason <clm@fb.com>2014-11-20 17:14:25 -0800
commitfce2a4e6b2da1bcc03837aff53b5bcb02bee4cee (patch)
treea56d9f42f183f0952e1327090681fb120ffb4adb /fs/btrfs
parent704de49d2be665be44933300f60023c889832fca (diff)
downloadop-kernel-dev-fce2a4e6b2da1bcc03837aff53b5bcb02bee4cee.zip
op-kernel-dev-fce2a4e6b2da1bcc03837aff53b5bcb02bee4cee.tar.gz
Btrfs: fix hang on compressed write error
In inode.c:submit_compressed_extents(), before calling btrfs_submit_compressed_write() we start writeback for all pages, clear their dirty flag, unlock them, etc, but if btrfs_submit_compressed_write() fails (at the moment it can only fail with -ENOMEM), we never end the writeback on the pages, so any filemap_fdatawait_range() call will hang forever. We were also not calling the writepage end io hook, which means the corresponding ordered extent will never complete and all its waiters will block forever, such as a full fsync (via btrfs_wait_ordered_range()). Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/inode.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index fcb9a38..ec68eaef 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -814,6 +814,20 @@ retry:
ins.objectid,
ins.offset, async_extent->pages,
async_extent->nr_pages);
+ if (ret) {
+ struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree;
+ struct page *p = async_extent->pages[0];
+ const u64 start = async_extent->start;
+ const u64 end = start + async_extent->ram_size - 1;
+
+ p->mapping = inode->i_mapping;
+ tree->ops->writepage_end_io_hook(p, start, end,
+ NULL, 0);
+ p->mapping = NULL;
+ extent_clear_unlock_delalloc(inode, start, end, NULL, 0,
+ PAGE_END_WRITEBACK |
+ PAGE_SET_ERROR);
+ }
alloc_hint = ins.objectid + ins.offset;
kfree(async_extent);
if (ret)
OpenPOWER on IntegriCloud