]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/vfs/vfs_disk_conditioner.c
xnu-7195.50.7.100.1.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_disk_conditioner.c
index 7df2f287beb907fe2e2c376246f03103d22deee9..846170a8922e828e88fdefa520e8ff487fbde2e1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2016-2020 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  *
@@ -124,9 +124,19 @@ disk_conditioner_delay(buf_t bp, int extents, int total_size, uint64_t already_e
        }
 
        // scale access time by (distance in blocks from previous I/O / maximum blocks)
-       access_time_scale = weighted_scale_factor((double)blkdiff / BLK_MAX(mp));
+       access_time_scale = weighted_scale_factor((double)blkdiff / (double)BLK_MAX(mp));
+       if (__builtin_isnan(access_time_scale)) {
+               return;
+       }
        // most cases should pass in extents==1 for optimal delay calculation, otherwise just multiply delay by extents
-       delay_usec = (uint64_t)(((uint64_t)extents * info->access_time_usec) * access_time_scale);
+       double temp = (((double)extents * (double)info->access_time_usec) * access_time_scale);
+       if (temp <= 0) {
+               delay_usec = 0;
+       } else if (temp >= (double)(18446744073709549568ULL)) { /* highest 64-bit unsigned integer representable as a double */
+               delay_usec = UINT64_MAX;
+       } else {
+               delay_usec = (uint64_t)temp;
+       }
 
        if (info->read_throughput_mbps && (bp->b_flags & B_READ)) {
                delay_usec += (uint64_t)(total_size / ((double)(info->read_throughput_mbps * 1024 * 1024 / 8) / USEC_PER_SEC));
@@ -153,7 +163,8 @@ disk_conditioner_delay(buf_t bp, int extents, int total_size, uint64_t already_e
 
        while (delay_usec) {
                microuptime(&start);
-               delay(delay_usec);
+               assert(delay_usec <= INT_MAX);
+               delay((int)delay_usec);
                microuptime(&elapsed);
                timevalsub(&elapsed, &start);
                if (elapsed.tv_sec * USEC_PER_SEC < delay_usec) {