Skip to content

Commit

Permalink
btrfs: assert we are holding the reada_lock when releasing a readahea…
Browse files Browse the repository at this point in the history
…d zone

When we drop the last reference of a zone, we end up releasing it through
the callback reada_zone_release(), which deletes the zone from a device's
reada_zones radix tree. This tree is protected by the global readahead
lock at fs_info->reada_lock. Currently all places that are sure that they
are dropping the last reference on a zone, are calling kref_put() in a
critical section delimited by this lock, while all other places that are
sure they are not dropping the last reference, do not bother calling
kref_put() while holding that lock.

When working on the previous fix for hangs and use-after-frees in the
readahead code, my initial attempts were different and I actually ended
up having reada_zone_release() called when not holding the lock, which
resulted in weird and unexpected problems. So just add an assertion
there to detect such problem more quickly and make the dependency more
obvious.

Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Filipe Manana <fdmanana@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
  • Loading branch information
Filipe Manana authored and David Sterba committed Dec 8, 2020
1 parent aa8c1a4 commit a57ad68
Showing 1 changed file with 2 additions and 0 deletions.
2 changes: 2 additions & 0 deletions fs/btrfs/reada.c
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,8 @@ static void reada_zone_release(struct kref *kref)
{
struct reada_zone *zone = container_of(kref, struct reada_zone, refcnt);

lockdep_assert_held(&zone->device->fs_info->reada_lock);

radix_tree_delete(&zone->device->reada_zones,
zone->end >> PAGE_SHIFT);

Expand Down

0 comments on commit a57ad68

Please sign in to comment.