aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2014-10-06 17:14:23 -0400
committerChris Mason <clm@fb.com>2014-11-20 20:14:25 -0500
commitfce2a4e6b2da1bcc03837aff53b5bcb02bee4cee (patch)
treea56d9f42f183f0952e1327090681fb120ffb4adb /fs/btrfs/inode.c
parent704de49d2be665be44933300f60023c889832fca (diff)
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/inode.c')
-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 fcb9a38fc9d3..ec68eaef05d7 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -814,6 +814,20 @@ retry:
814 ins.objectid, 814 ins.objectid,
815 ins.offset, async_extent->pages, 815 ins.offset, async_extent->pages,
816 async_extent->nr_pages); 816 async_extent->nr_pages);
817 if (ret) {
818 struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree;
819 struct page *p = async_extent->pages[0];
820 const u64 start = async_extent->start;
821 const u64 end = start + async_extent->ram_size - 1;
822
823 p->mapping = inode->i_mapping;
824 tree->ops->writepage_end_io_hook(p, start, end,
825 NULL, 0);
826 p->mapping = NULL;
827 extent_clear_unlock_delalloc(inode, start, end, NULL, 0,
828 PAGE_END_WRITEBACK |
829 PAGE_SET_ERROR);
830 }
817 alloc_hint = ins.objectid + ins.offset; 831 alloc_hint = ins.objectid + ins.offset;
818 kfree(async_extent); 832 kfree(async_extent);
819 if (ret) 833 if (ret)