From: Goldwyn Rodrigues <rgoldwyn@xxxxxxxx> While trying to release a page, the extent containing the page may be locked which would stop the page from being released. Wait for the extent lock to be cleared, if blocking is allowed and then clear the bits. While we are at it, clean the code of try_release_extent_state() to make it simpler. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@xxxxxxxx> --- fs/btrfs/extent_io.c | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index cceaf05aada2..a7c32276702d 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -4367,28 +4367,23 @@ static int try_release_extent_state(struct extent_io_tree *tree, { u64 start = page_offset(page); u64 end = start + PAGE_SIZE - 1; - int ret = 1; if (test_range_bit(tree, start, end, EXTENT_LOCKED, 0, NULL)) { - ret = 0; - } else { - /* - * at this point we can safely clear everything except the - * locked bit and the nodatasum bit - */ - ret = __clear_extent_bit(tree, start, end, - ~(EXTENT_LOCKED | EXTENT_NODATASUM), - 0, 0, NULL, mask, NULL); - - /* if clear_extent_bit failed for enomem reasons, - * we can't allow the release to continue. - */ - if (ret < 0) - ret = 0; - else - ret = 1; + if (!gfpflags_allow_blocking(mask)) + return 0; + wait_extent_bit(tree, start, end, EXTENT_LOCKED); } - return ret; + /* + * At this point we can safely clear everything except the locked and + * nodatasum bits. If clear_extent_bit failed due to -ENOMEM, + * don't allow release. + */ + if (__clear_extent_bit(tree, start, end, + ~(EXTENT_LOCKED | EXTENT_NODATASUM), 0, 0, + NULL, mask, NULL) < 0) + return 0; + + return 1; } /* -- 2.16.4