Skip to content

Commit

Permalink
btrfs: handle page locking in btrfs_page_end_writer_lock with no writers
Browse files Browse the repository at this point in the history
There are several call sites of extent_clear_unlock_delalloc() which get
@locked_page = NULL.
So that extent_clear_unlock_delalloc() will try to call
process_one_page() to unlock every page even the first page is not
locked by btrfs_page_start_writer_lock().

This will trigger an ASSERT() in btrfs_subpage_end_and_test_writer() as
previously we require every page passed to
btrfs_subpage_end_and_test_writer() to be locked by
btrfs_page_start_writer_lock().

But compression path doesn't go that way.

Thankfully it's not hard to distinguish page locked by lock_page() and
btrfs_page_start_writer_lock().

So do the check in btrfs_subpage_end_and_test_writer() so now it can
handle both cases well.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
  • Loading branch information
Qu Wenruo authored and David Sterba committed Oct 26, 2021
1 parent e55a0de commit 164674a
Showing 1 changed file with 10 additions and 0 deletions.
10 changes: 10 additions & 0 deletions fs/btrfs/subpage.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,16 @@ bool btrfs_subpage_end_and_test_writer(const struct btrfs_fs_info *fs_info,

btrfs_subpage_assert(fs_info, page, start, len);

/*
* We have call sites passing @lock_page into
* extent_clear_unlock_delalloc() for compression path.
*
* This @locked_page is locked by plain lock_page(), thus its
* subpage::writers is 0. Handle them in a special way.
*/
if (atomic_read(&subpage->writers) == 0)
return true;

ASSERT(atomic_read(&subpage->writers) >= nbits);
return atomic_sub_and_test(nbits, &subpage->writers);
}
Expand Down

0 comments on commit 164674a

Please sign in to comment.