]> git.hungrycats.org Git - linux/commitdiff
Btrfs: wake up extent state waiters on unlock through clear_extent_bits
authorFilipe Manana <fdmanana@suse.com>
Thu, 14 May 2015 19:41:07 +0000 (20:41 +0100)
committerZygo Blaxell <zblaxell@serenity.furryterror.org>
Tue, 30 Jun 2015 23:57:08 +0000 (19:57 -0400)
When we clear an extent state's EXTENT_LOCKED bit with clear_extent_bits()
through free_io_failure(), we weren't waking up any tasks waiting for the
extent's state EXTENT_LOCKED bit, leading to an hang.

So make sure clear_extent_bits() ends up waking up any waiters if the
bit EXTENT_LOCKED is supplied by its callers.

Zygo Blaxell was experiencing such hangs at inode eviction time after
file unlinks. Thanks to him for a set of scripts to reproduce the issue.

Reported-by: Zygo Blaxell <ce3g8jdj@umail.furryterror.org>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: Liu Bo <bo.li.liu@oracle.com>
Signed-off-by: Chris Mason <clm@fb.com>
(cherry picked from commit 0f31871f4411b5c0d42fb4403dec83a21a96100b)
(cherry picked from commit de82f2cfbbfe95ae2f690c9877f46368a6219c2d)

fs/btrfs/extent_io.c

index c32d226bfeccbb28f25f2f417fa9e57b14411136..856c2e8ea6acd8b03f0eae1de196fc120529b5e9 100644 (file)
@@ -1277,7 +1277,12 @@ int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
 int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
                      unsigned bits, gfp_t mask)
 {
-       return clear_extent_bit(tree, start, end, bits, 0, 0, NULL, mask);
+       int wake = 0;
+
+       if (bits & EXTENT_LOCKED)
+               wake = 1;
+
+       return clear_extent_bit(tree, start, end, bits, wake, 0, NULL, mask);
 }
 
 int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end,