Commit 4792ba1f authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'for-5.3-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux

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
...@@ -346,9 +346,12 @@ void btrfs_tree_unlock(struct extent_buffer *eb) ...@@ -346,9 +346,12 @@ void btrfs_tree_unlock(struct extent_buffer *eb)
if (blockers) { if (blockers) {
btrfs_assert_no_spinning_writers(eb); btrfs_assert_no_spinning_writers(eb);
eb->blocking_writers--; eb->blocking_writers--;
/* Use the lighter barrier after atomic */ /*
smp_mb__after_atomic(); * We need to order modifying blocking_writers above with
cond_wake_up_nomb(&eb->write_lock_wq); * actually waking up the sleepers to ensure they see the
* updated value of blocking_writers
*/
cond_wake_up(&eb->write_lock_wq);
} else { } else {
btrfs_assert_spinning_writers_put(eb); btrfs_assert_spinning_writers_put(eb);
write_unlock(&eb->lock); write_unlock(&eb->lock);
......
...@@ -985,13 +985,14 @@ void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree, ...@@ -985,13 +985,14 @@ void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree,
struct extent_state **cached_state) struct extent_state **cached_state)
{ {
struct btrfs_ordered_extent *ordered; struct btrfs_ordered_extent *ordered;
struct extent_state *cachedp = NULL; struct extent_state *cache = NULL;
struct extent_state **cachedp = &cache;
if (cached_state) if (cached_state)
cachedp = *cached_state; cachedp = cached_state;
while (1) { while (1) {
lock_extent_bits(tree, start, end, &cachedp); lock_extent_bits(tree, start, end, cachedp);
ordered = btrfs_lookup_ordered_range(inode, start, ordered = btrfs_lookup_ordered_range(inode, start,
end - start + 1); end - start + 1);
if (!ordered) { if (!ordered) {
...@@ -1001,10 +1002,10 @@ void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree, ...@@ -1001,10 +1002,10 @@ void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree,
* aren't exposing it outside of this function * aren't exposing it outside of this function
*/ */
if (!cached_state) if (!cached_state)
refcount_dec(&cachedp->refs); refcount_dec(&cache->refs);
break; 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_start_ordered_extent(&inode->vfs_inode, ordered, 1);
btrfs_put_ordered_extent(ordered); btrfs_put_ordered_extent(ordered);
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment