Re: [PATCH v2] block: invalidate cached plug timestamp after task switch

From: Usama Arif

Date: Fri Jun 12 2026 - 06:03:10 EST




On 12/06/2026 10:45, Peter Zijlstra wrote:
> On Fri, Jun 12, 2026 at 02:40:42AM -0700, Usama Arif wrote:
>
>> +static __always_inline void blk_plug_invalidate_ts(void)
>> {
>> + if (unlikely(current->flags & PF_BLOCK_TS)) {
>> + struct blk_plug *plug = current->plug;
>>
>> + if (plug)
>> + plug->cur_ktime = 0;
>> + current->flags &= ~PF_BLOCK_TS;
>> + }
>> }
>
> If you can guarantee PF_BLOCK_TS is only ever set when current->plug,
> this can be reduced further.

Thanks for the reviews!

The invariant holds at set time (the only set in blk_time_get_ns() is
gated by if (!plug)) and through the only legitimate plug clear in
blk_finish_plug() (which goes through __blk_flush_plug() that clears
PF_BLOCK_TS first).

However, copy_process() sets p->plug = NULL for the child but doesn't
strip PF_BLOCK_TS from the inherited flags.

I think the if(plug) is a good defensive check, but can also do the below
if you prefer?

diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 1c1fd31ce187..c285a4d9837d 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -1219,10 +1219,7 @@ static inline void blk_flush_plug(struct blk_plug *plug, bool async)
static __always_inline void blk_plug_invalidate_ts(void)
{
if (unlikely(current->flags & PF_BLOCK_TS)) {
- struct blk_plug *plug = current->plug;
-
- if (plug)
- plug->cur_ktime = 0;
+ current->plug->cur_ktime = 0;
current->flags &= ~PF_BLOCK_TS;
}
}
diff --git a/kernel/fork.c b/kernel/fork.c
index 892a95214c54..9a062149e0d8 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -2167,7 +2167,8 @@ __latent_entropy struct task_struct *copy_process(
goto bad_fork_cleanup_count;

delayacct_tsk_init(p); /* Must remain after dup_task_struct() */
- p->flags &= ~(PF_SUPERPRIV | PF_WQ_WORKER | PF_IDLE | PF_NO_SETAFFINITY);
+ p->flags &= ~(PF_SUPERPRIV | PF_WQ_WORKER | PF_IDLE | PF_NO_SETAFFINITY |
+ PF_BLOCK_TS);
p->flags |= PF_FORKNOEXEC;
INIT_LIST_HEAD(&p->children);
INIT_LIST_HEAD(&p->sibling);