Opened 5 years ago
Closed 4 years ago
#16030 closed bug (fixed)
[scsi_cd] ASSERT FAILED: actualLength == fLength
Reported by: | vidrep | Owned by: | nobody |
---|---|---|---|
Priority: | normal | Milestone: | Unscheduled |
Component: | Drivers/Disk/SCSI | Version: | R1/Development |
Keywords: | Cc: | korli | |
Blocked By: | Blocking: | #16177, #16514, #16539 | |
Platform: | All |
Description
hrev54195 x86_64
Insert blank CD into optical drive Crash Photo attached
Attachments (1)
Change History (12)
by , 5 years ago
Attachment: | IMG_0135.JPG added |
---|
comment:1 by , 5 years ago
Cc: | added |
---|---|
Component: | - General → Drivers/Disk/SCSI |
Summary: | Crash when reading blank CD → [scsi_cd] ASSERT FAILED: actualLength == fLength |
comment:2 by , 5 years ago
The problem seems to be in IOCache.cpp. The request length is capped at the device capacity, but the vecs are not adjusted, hence the assert fails.
comment:3 by , 5 years ago
Maybe something like this?
diff --git a/src/system/kernel/device_manager/IOCache.cpp b/src/system/kernel/device_manager/IOCache.cpp index 7cd834b8a5..a7e1660dd6 100644 --- a/src/system/kernel/device_manager/IOCache.cpp +++ b/src/system/kernel/device_manager/IOCache.cpp @@ -529,7 +529,8 @@ IOCache::_TransferPages(size_t firstPage, size_t pageCount, bool isWrite, // prepare the I/O vecs size_t vecCount = 0; - size_t endPage = firstPage + pageCount; + size_t endPage = std::min(firstPage + pageCount, + (size_t)((fDeviceCapacity + B_PAGE_SIZE - 1) / B_PAGE_SIZE)); phys_addr_t vecsEndAddress = 0; for (size_t i = firstPage; i < endPage; i++) { phys_addr_t pageAddress
comment:5 by , 4 years ago
Actually, on closer inspection, it appears some other functions are already trimming endPage(), so perhaps the ones that are not, should be?
comment:6 by , 4 years ago
Blocking: | 16177 added |
---|
comment:7 by , 4 years ago
Blocking: | 16539 added |
---|
comment:8 by , 4 years ago
Blocking: | 16514 added |
---|
comment:9 by , 4 years ago
I went a slightly different way with this as I didn't think we could guarantee the storage medium was an exact multiple of B_PAGE_SIZE. I'm not too familiar with the format but aren't ISO 9660 sectors around 2KB (with metadata)?
I've been using this:
diff --git a/src/system/kernel/device_manager/IOCache.cpp b/src/system/kernel/device_manager/IOCache.cpp index 7cd834b8a5..5ce71436b5 100644 --- a/src/system/kernel/device_manager/IOCache.cpp +++ b/src/system/kernel/device_manager/IOCache.cpp @@ -545,6 +545,12 @@ IOCache::_TransferPages(size_t firstPage, size_t pageCount, bool isWrite, } } + // don't try to read past the end of the device just to fill a page. + // this makes sure that sum(fVecs[].length) == requestLength. + const generic_size_t lastPageFill = requestLength & (B_PAGE_SIZE-1); + if (lastPageFill > 0) + fVecs[vecCount-1].length -= B_PAGE_SIZE - lastPageFill; + // create a request for the transfer IORequest request; status_t error = request.Init(firstPageOffset, fVecs, vecCount,
comment:10 by , 4 years ago
Your way is definitely better. Thanks, I tested, adjusted and pushed for review: https://review.haiku-os.org/c/haiku/+/3451
This is a new assert I added in IORequest being triggered. CC korli: I don't know very much about scsi_cd; I will take a look tomorrow evening, but if you have time before then, I think you know more than I do?