:: commit 5f421d27d5d57f9f26659e39dc5a8146fe1e2f4c

Mintsuki <mintsuki@protonmail.com> — 2026-02-05 09:18

parents: e84c1a5ccc

lib/part: Clamp xfer_size to remaining sectors in volume in cache_blocks()

Do this rather than retrying over and over which can cause hangs on certain machines besides it being uglier code.

It also fixes an issue where the block cache will be incomplete if decrementing xfer_size, without checks for that.
diff --git a/common/lib/part.s2.c b/common/lib/part.s2.c
index 35d14856..ab9b3d54 100644
--- a/common/lib/part.s2.c
+++ b/common/lib/part.s2.c
@@ -44,25 +44,23 @@ static bool cache_block(struct volume *volume, uint64_t block) {
         return false;
     }
 
-    for (;;) {
-        int ret = disk_read_sectors(volume, volume->cache,
-                           read_sector,
-                           xfer_size);
-
-        switch (ret) {
-            case DISK_NO_MEDIA:
-                return false;
-            case DISK_SUCCESS:
-                goto disk_success;
-        }
-
-        xfer_size--;
-        if (xfer_size == 0) {
+    // Clamp xfer_size to remaining sectors in volume
+    if (volume->sect_count != (uint64_t)-1) {
+        uint64_t end_sector = first_sect + volume->sect_count / (volume->sector_size / 512);
+        if (read_sector >= end_sector) {
             return false;
         }
+        uint64_t remaining = end_sector - read_sector;
+        if (xfer_size > remaining) {
+            xfer_size = remaining;
+        }
+    }
+
+    int ret = disk_read_sectors(volume, volume->cache, read_sector, xfer_size);
+    if (ret != DISK_SUCCESS) {
+        return false;
     }
 
-disk_success:
     volume->cache_status = CACHE_READY;
     volume->cached_block = block;
 
tab: 248 wrap: offon