Opened 4 years ago

Closed 3 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)

IMG_0135.JPG (690.1 KB ) - added by vidrep 4 years ago.

Download all attachments as: .zip

Change History (12)

by vidrep, 4 years ago

Attachment: IMG_0135.JPG added

comment:1 by waddlesplash, 4 years ago

Cc: korli added
Component: - GeneralDrivers/Disk/SCSI
Summary: Crash when reading blank CD[scsi_cd] ASSERT FAILED: actualLength == fLength

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?

comment:2 by korli, 4 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 korli, 4 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:4 by waddlesplash, 4 years ago

Wouldn't it be clearer to use ROUNDDOWN()? Otherwise, looks good.

comment:5 by waddlesplash, 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 waddlesplash, 4 years ago

Blocking: 16177 added

comment:7 by diver, 4 years ago

Blocking: 16539 added

comment:8 by diver, 4 years ago

Blocking: 16514 added

comment:9 by mark_mcs, 3 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 korli, 3 years ago

Your way is definitely better. Thanks, I tested, adjusted and pushed for review: https://review.haiku-os.org/c/haiku/+/3451

comment:11 by waddlesplash, 3 years ago

Resolution: fixed
Status: newclosed

Fix merged in hrev54752.

Note: See TracTickets for help on using tickets.