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;
