btrfs: don't miss async discards after scheduled work override
If btrfs_discard_schedule_work() is called with override=true, it sets delay anew regardless how much time is left until the timer should have fired. If delays are long (that can happen, for example, with low kbps_limit), they might get constantly overridden without having a chance to run the discard work. 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>
This commit is contained in:
parent
6e88f116bd
commit
df903e5d29
|
@ -469,6 +469,7 @@ struct btrfs_discard_ctl {
|
|||
struct btrfs_block_group *block_group;
|
||||
struct list_head discard_list[BTRFS_NR_DISCARD_LISTS];
|
||||
u64 prev_discard;
|
||||
u64 prev_discard_time;
|
||||
atomic_t discardable_extents;
|
||||
atomic64_t discardable_bytes;
|
||||
u64 max_discard_size;
|
||||
|
|
|
@ -381,6 +381,15 @@ void btrfs_discard_schedule_work(struct btrfs_discard_ctl *discard_ctl,
|
|||
delay = max(delay, bg_timeout);
|
||||
}
|
||||
|
||||
if (override && discard_ctl->prev_discard) {
|
||||
u64 elapsed = now - discard_ctl->prev_discard_time;
|
||||
|
||||
if (delay > elapsed)
|
||||
delay -= elapsed;
|
||||
else
|
||||
delay = 0;
|
||||
}
|
||||
|
||||
mod_delayed_work(discard_ctl->discard_workers,
|
||||
&discard_ctl->work, nsecs_to_jiffies(delay));
|
||||
}
|
||||
|
@ -465,7 +474,12 @@ 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)) {
|
||||
|
@ -685,6 +699,7 @@ void btrfs_discard_init(struct btrfs_fs_info *fs_info)
|
|||
INIT_LIST_HEAD(&discard_ctl->discard_list[i]);
|
||||
|
||||
discard_ctl->prev_discard = 0;
|
||||
discard_ctl->prev_discard_time = 0;
|
||||
atomic_set(&discard_ctl->discardable_extents, 0);
|
||||
atomic64_set(&discard_ctl->discardable_bytes, 0);
|
||||
discard_ctl->max_discard_size = BTRFS_ASYNC_DISCARD_DEFAULT_MAX_SIZE;
|
||||
|
|
Loading…
Reference in New Issue