Skip to content

Commit a3b46b8

Browse files
naotakdave
authored andcommitted
btrfs: fix extent_state leak in btrfs_lock_and_flush_ordered_range
btrfs_lock_and_flush_ordered_range() loads given "*cached_state" into cachedp, which, in general, is NULL. Then, lock_extent_bits() updates "cachedp", but it never goes backs to the caller. Thus the caller still see its "cached_state" to be NULL and never free the state allocated under btrfs_lock_and_flush_ordered_range(). As a result, we will see massive state leak with e.g. fstests btrfs/005. Fix this bug by properly handling the pointers. Fixes: bd80d94 ("btrfs: Always use a cached extent_state in btrfs_lock_and_flush_ordered_range") Reviewed-by: Nikolay Borisov <[email protected]> Signed-off-by: Naohiro Aota <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 6e7ca09 commit a3b46b8

File tree

1 file changed

+6
-5
lines changed

1 file changed

+6
-5
lines changed

fs/btrfs/ordered-data.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -985,13 +985,14 @@ void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree,
985985
struct extent_state **cached_state)
986986
{
987987
struct btrfs_ordered_extent *ordered;
988-
struct extent_state *cachedp = NULL;
988+
struct extent_state *cache = NULL;
989+
struct extent_state **cachedp = &cache;
989990

990991
if (cached_state)
991-
cachedp = *cached_state;
992+
cachedp = cached_state;
992993

993994
while (1) {
994-
lock_extent_bits(tree, start, end, &cachedp);
995+
lock_extent_bits(tree, start, end, cachedp);
995996
ordered = btrfs_lookup_ordered_range(inode, start,
996997
end - start + 1);
997998
if (!ordered) {
@@ -1001,10 +1002,10 @@ void btrfs_lock_and_flush_ordered_range(struct extent_io_tree *tree,
10011002
* aren't exposing it outside of this function
10021003
*/
10031004
if (!cached_state)
1004-
refcount_dec(&cachedp->refs);
1005+
refcount_dec(&cache->refs);
10051006
break;
10061007
}
1007-
unlock_extent_cached(tree, start, end, &cachedp);
1008+
unlock_extent_cached(tree, start, end, cachedp);
10081009
btrfs_start_ordered_extent(&inode->vfs_inode, ordered, 1);
10091010
btrfs_put_ordered_extent(ordered);
10101011
}

0 commit comments

Comments
 (0)