Skip to content

Commit 97e1044

Browse files
Usama Arifgregkh
authored andcommitted
block: invalidate cached plug timestamp after task switch
commit fad156c upstream. blk_time_get_ns() caches ktime_get_ns() in current->plug->cur_ktime and marks the task with PF_BLOCK_TS. That cache is only valid while the task keeps running; if the task is switched out, wall-clock time advances and the cached value must not be reused when the task runs again. The existing invalidation covers explicit plug flushes through __blk_flush_plug(), and the schedule() / rtmutex paths through sched_update_worker(). It does not cover in-kernel preemption paths such as preempt_schedule(), preempt_schedule_notrace(), and preempt_schedule_irq(), which enter __schedule(SM_PREEMPT) directly and return without calling sched_update_worker(). As a result, a task preempted while holding a plug with PF_BLOCK_TS set can reuse a stale plug->cur_ktime after it is scheduled back in. blk-iocost then consumes that stale timestamp through ioc_now(), producing stale vnow values for throttle decisions, and through ioc_rqos_done(), inflating on-queue time and feeding false missed-QoS samples into vrate adjustment. Move the schedule-side invalidation to finish_task_switch(), which runs for the scheduled-in task after every actual context switch regardless of which schedule entry point was used. Keep __blk_flush_plug() as the explicit flush/finish-plug invalidation path, and remove only the PF_BLOCK_TS handling from sched_update_worker(). Fixes: 06b23f9 ("block: update cached timestamp post schedule/preemption") Cc: stable@vger.kernel.org Signed-off-by: Usama Arif <usama.arif@linux.dev> Link: https://patch.msgid.link/20260616141604.328820-3-usama.arif@linux.dev Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 99e6c71 commit 97e1044

2 files changed

Lines changed: 14 additions & 14 deletions

File tree

include/linux/blkdev.h

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,16 +1187,12 @@ static inline void blk_flush_plug(struct blk_plug *plug, bool async)
11871187
__blk_flush_plug(plug, async);
11881188
}
11891189

1190-
/*
1191-
* tsk == current here
1192-
*/
1193-
static inline void blk_plug_invalidate_ts(struct task_struct *tsk)
1190+
static __always_inline void blk_plug_invalidate_ts(void)
11941191
{
1195-
struct blk_plug *plug = tsk->plug;
1196-
1197-
if (plug)
1198-
plug->cur_ktime = 0;
1199-
current->flags &= ~PF_BLOCK_TS;
1192+
if (unlikely(current->flags & PF_BLOCK_TS)) {
1193+
current->plug->cur_ktime = 0;
1194+
current->flags &= ~PF_BLOCK_TS;
1195+
}
12001196
}
12011197

12021198
int blkdev_issue_flush(struct block_device *bdev);
@@ -1222,7 +1218,7 @@ static inline void blk_flush_plug(struct blk_plug *plug, bool async)
12221218
{
12231219
}
12241220

1225-
static inline void blk_plug_invalidate_ts(struct task_struct *tsk)
1221+
static inline void blk_plug_invalidate_ts(void)
12261222
{
12271223
}
12281224

kernel/sched/core.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5206,6 +5206,12 @@ static struct rq *finish_task_switch(struct task_struct *prev)
52065206
*/
52075207
kmap_local_sched_in();
52085208

5209+
/*
5210+
* Any cached block-layer timestamp (plug->cur_ktime) is stale now,
5211+
* invalidate it.
5212+
*/
5213+
blk_plug_invalidate_ts();
5214+
52095215
fire_sched_in_preempt_notifiers(current);
52105216
/*
52115217
* When switching through a kernel thread, the loop in
@@ -7000,12 +7006,10 @@ static inline void sched_submit_work(struct task_struct *tsk)
70007006

70017007
static void sched_update_worker(struct task_struct *tsk)
70027008
{
7003-
if (tsk->flags & (PF_WQ_WORKER | PF_IO_WORKER | PF_BLOCK_TS)) {
7004-
if (tsk->flags & PF_BLOCK_TS)
7005-
blk_plug_invalidate_ts(tsk);
7009+
if (tsk->flags & (PF_WQ_WORKER | PF_IO_WORKER)) {
70067010
if (tsk->flags & PF_WQ_WORKER)
70077011
wq_worker_running(tsk);
7008-
else if (tsk->flags & PF_IO_WORKER)
7012+
else
70097013
io_wq_worker_running(tsk);
70107014
}
70117015
}

0 commit comments

Comments
 (0)