kernel - Fix intermediate value overflows in badjiosched() and bwillwrite()
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 20 Aug 2010 05:38:11 +0000 (22:38 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 20 Aug 2010 05:38:11 +0000 (22:38 -0700)
* Fix overflows which can skew our write limiting heuristics and cause
  the buffer daemons to flush too much dirty data at once.

sys/kern/kern_iosched.c

index 9a9a40e..145e477 100644 (file)
@@ -87,15 +87,19 @@ badjiosched(thread_t td, size_t bytes)
                td->td_iosdata.lastticks = ticks;
                if (delta < 0 || delta > hz * 10)
                        delta = hz * 10;
+               /* 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;
                iostotal -= bytes;
        }
+
+       /* be careful of interger overflows */
        if (iostotal > 0)
-               factor = td->td_iosdata.iowbytes * 100 / iostotal;
+               factor = (int64_t)td->td_iosdata.iowbytes * 100 / iostotal;
        else
                factor = 50;
+
        if (delta && (iosched_debug & 1)) {
                kprintf("proc %12s (%-5d) factor %3d (%zd/%zd)\n",
                        td->td_comm,
@@ -130,8 +134,9 @@ bwillwrite(int bytes)
 
        count = bd_heatup();
        if (count > 0) {
+               /* be careful of interger overflows */
                factor = badjiosched(curthread, (size_t)bytes);
-               count = hidirtybufspace * factor / 100;
+               count = hidirtybufspace / 100 * factor;
                bd_wait(count);
        }
 }