diff --git a/sys/kern/kern_iosched.c b/sys/kern/kern_iosched.c --- a/sys/kern/kern_iosched.c +++ b/sys/kern/kern_iosched.c @@ -87,7 +87,18 @@ /* be careful of interger overflows */ bytes = (int64_t)td->td_iosdata.iowbytes * delta / (hz * 10); td->td_iosdata.iowbytes -= bytes; - ioscpu[gd->gd_cpuid].iowbytes -= bytes; + /* + * DF-0245: td->td_iosdata.iowbytes migrates with the + * thread, but ioscpu[] is per-cpu. If the thread + * accumulated weight on another cpu, this cpu's counter + * may hold less than `bytes'; clamping prevents the + * size_t subtraction from underflowing to SIZE_T_MAX and + * wrecking the throttle factor. + */ + if (ioscpu[gd->gd_cpuid].iowbytes >= bytes) + ioscpu[gd->gd_cpuid].iowbytes -= bytes; + else + ioscpu[gd->gd_cpuid].iowbytes = 0; iostotal -= bytes; } @@ -114,7 +125,10 @@ if ((bytes = td->td_iosdata.iowbytes) != 0) { td->td_iosdata.iowbytes = 0; - ioscpu[gd->gd_cpuid].iowbytes -= bytes; + if (ioscpu[gd->gd_cpuid].iowbytes >= bytes) + ioscpu[gd->gd_cpuid].iowbytes -= bytes; + else + ioscpu[gd->gd_cpuid].iowbytes = 0; } }