Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+12 -8
+6 -3
fs/btrfs/locking.c
··· 346 346 if (blockers) { 347 347 btrfs_assert_no_spinning_writers(eb); 348 348 eb->blocking_writers--; 349 - /* Use the lighter barrier after atomic */ 350 - smp_mb__after_atomic(); 351 - cond_wake_up_nomb(&eb->write_lock_wq); 349 + /* 350 + * We need to order modifying blocking_writers above with 351 + * actually waking up the sleepers to ensure they see the 352 + * updated value of blocking_writers 353 + */ 354 + cond_wake_up(&eb->write_lock_wq); 352 355 } else { 353 356 btrfs_assert_spinning_writers_put(eb); 354 357 write_unlock(&eb->lock);
+6 -5
fs/btrfs/ordered-data.c
··· 985 985 struct extent_state **cached_state) 986 986 { 987 987 struct btrfs_ordered_extent *ordered; 988 - struct extent_state *cachedp = NULL; 988 + struct extent_state *cache = NULL; 989 + struct extent_state **cachedp = &cache; 989 990 990 991 if (cached_state) 991 - cachedp = *cached_state; 992 + cachedp = cached_state; 992 993 993 994 while (1) { 994 - lock_extent_bits(tree, start, end, &cachedp); 995 + lock_extent_bits(tree, start, end, cachedp); 995 996 ordered = btrfs_lookup_ordered_range(inode, start, 996 997 end - start + 1); 997 998 if (!ordered) { ··· 1002 1001 * aren't exposing it outside of this function 1003 1002 */ 1004 1003 if (!cached_state) 1005 - refcount_dec(&cachedp->refs); 1004 + refcount_dec(&cache->refs); 1006 1005 break; 1007 1006 } 1008 - unlock_extent_cached(tree, start, end, &cachedp); 1007 + unlock_extent_cached(tree, start, end, cachedp); 1009 1008 btrfs_start_ordered_extent(&inode->vfs_inode, ordered, 1); 1010 1009 btrfs_put_ordered_extent(ordered); 1011 1010 }