Skip to content

Commit

Permalink
btrfs: fix racy access to discard_ctl data
Browse files Browse the repository at this point in the history
Because only one discard worker may be running at any given point, it
could have been safe to modify ->prev_discard, etc. without
synchronization, if not for @override flag in
btrfs_discard_schedule_work() and delayed_work_pending() returning false
while workfn is running.

That may lead to torn reads of u64 for some architectures, but that's
not a big problem as only slightly affects the discard rate.

Suggested-by: Josef Bacik <josef@toxicpanda.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
  • Loading branch information
Pavel Begunkov authored and David Sterba committed Dec 18, 2020
1 parent ea9ed87 commit 1ea2872
Showing 1 changed file with 3 additions and 7 deletions.
10 changes: 3 additions & 7 deletions fs/btrfs/discard.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,13 +477,6 @@ static void btrfs_discard_workfn(struct work_struct *work)
discard_ctl->discard_extent_bytes += trimmed;
}

/*
* Updated without locks as this is inside the workfn and nothing else
* is reading the values
*/
discard_ctl->prev_discard = trimmed;
discard_ctl->prev_discard_time = ktime_get_ns();

/* Determine next steps for a block_group */
if (block_group->discard_cursor >= btrfs_block_group_end(block_group)) {
if (discard_state == BTRFS_DISCARD_BITMAPS) {
Expand All @@ -499,7 +492,10 @@ static void btrfs_discard_workfn(struct work_struct *work)
}
}

now = ktime_get_ns();
spin_lock(&discard_ctl->lock);
discard_ctl->prev_discard = trimmed;
discard_ctl->prev_discard_time = now;
discard_ctl->block_group = NULL;
spin_unlock(&discard_ctl->lock);

Expand Down

0 comments on commit 1ea2872

Please sign in to comment.