From 505b9a5c3142645f9601394cd178414428531c4a Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Mon, 25 Aug 2025 17:02:03 -0400 Subject: [PATCH] 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 Tested-by: Commit checker robot --- .../drivers/disk/usb/usb_disk/usb_disk.cpp | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.cpp b/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.cpp index 01b33f9b47..b7a7843517 100644 --- a/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/usb/usb_disk/usb_disk.cpp @@ -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);