Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4792ba1f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull btrfs fixes from David Sterba:
 "Two regression fixes:

   - hangs caused by a missing barrier in the locking code

   - memory leaks of extent_state due to bad handling of a cached
     pointer"

* tag 'for-5.3-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
  btrfs: fix extent_state leak in btrfs_lock_and_flush_ordered_range
  btrfs: Fix deadlock caused by missing memory barrier
parents 863fa888 a3b46b86
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -346,9 +346,12 @@ void btrfs_tree_unlock(struct extent_buffer *eb)
	if (blockers) {
		btrfs_assert_no_spinning_writers(eb);
		eb->blocking_writers--;
		/* Use the lighter barrier after atomic */
		smp_mb__after_atomic();
		cond_wake_up_nomb(&eb->write_lock_wq);
		/*
		 * We need to order modifying blocking_writers above with
		 * actually waking up the sleepers to ensure they see the
		 * updated value of blocking_writers
		 */
		cond_wake_up(&eb->write_lock_wq);
	} else {
		btrfs_assert_spinning_writers_put(eb);
		write_unlock(&eb->lock);
+6 −5
Original line number Diff line number Diff line
@@ -985,13 +985,14 @@ void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree,
					struct extent_state **cached_state)
{
	struct btrfs_ordered_extent *ordered;
	struct extent_state *cachedp = NULL;
	struct extent_state *cache = NULL;
	struct extent_state **cachedp = &cache;

	if (cached_state)
		cachedp = *cached_state;
		cachedp = cached_state;

	while (1) {
		lock_extent_bits(tree, start, end, &cachedp);
		lock_extent_bits(tree, start, end, cachedp);
		ordered = btrfs_lookup_ordered_range(inode, start,
						     end - start + 1);
		if (!ordered) {
@@ -1001,10 +1002,10 @@ void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree,
			 * aren't exposing it outside of this function
			 */
			if (!cached_state)
				refcount_dec(&cachedp->refs);
				refcount_dec(&cache->refs);
			break;
		}
		unlock_extent_cached(tree, start, end, &cachedp);
		unlock_extent_cached(tree, start, end, cachedp);
		btrfs_start_ordered_extent(&inode->vfs_inode, ordered, 1);
		btrfs_put_ordered_extent(ordered);
	}