diff options
author | Gui Hecheng <guihc.fnst@cn.fujitsu.com> | 2014-11-10 15:36:08 +0800 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2014-11-20 17:20:08 -0800 |
commit | 321592427c0146126aadfab8a9b663de1875c9f4 (patch) | |
tree | 7cf8d8427168e4410b369d67555a0c5c3efd96aa /net/can | |
parent | 5f5bc6b1e2d5a6f827bc860ef2dc5b6f365d1339 (diff) |
btrfs: fix dead lock while running replace and defrag concurrently
This can be reproduced by fstests: btrfs/070
The scenario is like the following:
replace worker thread defrag thread
--------------------- -------------
copy_nocow_pages_worker btrfs_defrag_file
copy_nocow_pages_for_inode ...
btrfs_writepages
|A| lock_extent_bits extent_write_cache_pages
|B| lock_page
__extent_writepage
... writepage_delalloc
find_lock_delalloc_range
|B| lock_extent_bits
find_or_create_page
pagecache_get_page
|A| lock_page
This leads to an ABBA pattern deadlock. To fix it,
o we just change it to an AABB pattern which means to @unlock_extent_bits()
before we @lock_page(), and in this way the @extent_read_full_page_nolock()
is no longer in an locked context, so change it back to @extent_read_full_page()
to regain protection.
o Since we @unlock_extent_bits() earlier, then before @write_page_nocow(),
the extent may not really point at the physical block we want, so we
have to check it before write.
Signed-off-by: Gui Hecheng <guihc.fnst@cn.fujitsu.com>
Tested-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'net/can')
0 files changed, 0 insertions, 0 deletions