usb_disk: Lock memory before acquiring device locks.

Otherwise, if we are locking memory that's mapped from this
same usb_disk device, we'll cause a double lock.

Should fix #19715. But really, we should probably be using
an IOScheduler here, so the next commit will implement that.

Change-Id: Icd62955338ef66444ec6a14e0310f60061456d8f
Reviewed-on: https://review.haiku-os.org/c/haiku/+/9610
Reviewed-by: waddlesplash <[email protected]>
Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
Augustin Cavalier
2025-08-27 16:56:11 +00:00
committed by waddlesplash
parent fb6c279a24
commit 505b9a5c31
@@ -1817,19 +1817,12 @@ usb_disk_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
static status_t
usb_disk_bounced_io(device_lun *lun, io_request *request)
{
ASSERT(request->Buffer()->IsPhysical() || request->Buffer()->IsMemoryLocked());
DMAResource* dmaResource = get_dma_resource(lun->device, lun->block_size);
if (dmaResource == NULL)
return B_NO_INIT;
if (!request->Buffer()->IsPhysical()) {
status_t status = request->Buffer()->LockMemory(request->TeamID(), request->IsWrite());
if (status != B_OK) {
TRACE_ALWAYS("failed to lock memory: %s\n", strerror(status));
return status;
}
// SetStatusAndNotify() takes care of unlocking memory if necessary.
}
status_t status = B_OK;
while (request->RemainingBytes() > 0) {
IOOperation operation;
@@ -1919,6 +1912,17 @@ usb_disk_io(void *cookie, io_request *request)
device_lun *lun = (device_lun *)cookie;
disk_device *device = lun->device;
const bool needsBounce = usb_disk_needs_bounce(lun, request);
if (needsBounce && !request->Buffer()->IsPhysical()) {
status_t status = request->Buffer()->LockMemory(request->TeamID(), request->IsWrite());
if (status != B_OK) {
TRACE_ALWAYS("failed to lock memory: %s\n", strerror(status));
return status;
}
// SetStatusAndNotify() takes care of unlocking memory if necessary.
}
RecursiveLocker ioLocker(device->io_lock);
MutexLocker deviceLocker(device->lock);
@@ -1926,7 +1930,7 @@ usb_disk_io(void *cookie, io_request *request)
return B_DEV_NOT_READY;
status_t status;
if (!usb_disk_needs_bounce(lun, request)) {
if (!needsBounce) {
status = usb_disk_direct_io(lun, request);
} else {
status = usb_disk_bounced_io(lun, request);