* Fix a lock leak in the eject/load ioctls. It did return directly without

unlocking the device again, causing deadlocks after unmounting a USB mass
  storage device.
* Synchronize on close again, but this time with proper locking of the device.
* Restructured usb_disk_synchronize() a bit and updated comments.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28934 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2009-01-18 14:30:03 +00:00
parent 4650eca258
commit 8311b012d1
@@ -480,27 +480,29 @@ status_t
usb_disk_synchronize(device_lun *lun, bool force) usb_disk_synchronize(device_lun *lun, bool force)
{ {
if (lun->device->sync_support == 0) { if (lun->device->sync_support == 0) {
// this device repeatedly reported an illegal request when syncing // this device reported an illegal request when syncing or repeatedly
// it obviously does really not support this command... // returned an other error, it apparently does not support syncing...
return B_UNSUPPORTED; return B_UNSUPPORTED;
} }
if (lun->should_sync || force) { if (!lun->should_sync && !force)
status_t result = usb_disk_operation(lun, SCSI_SYNCHRONIZE_CACHE_10, return B_OK;
10, 0, 0, NULL, NULL, false);
status_t result = usb_disk_operation(lun, SCSI_SYNCHRONIZE_CACHE_10, 10,
0, 0, NULL, NULL, false);
if (result == B_OK) {
lun->device->sync_support = SYNC_SUPPORT_RELOAD;
lun->should_sync = false; lun->should_sync = false;
return B_OK;
if (result == B_OK)
lun->device->sync_support = SYNC_SUPPORT_RELOAD;
else if (result == B_DEV_INVALID_IOCTL)
lun->device->sync_support = 0;
else
lun->device->sync_support--;
return result;
} }
return B_OK; if (result == B_DEV_INVALID_IOCTL)
lun->device->sync_support = 0;
else
lun->device->sync_support--;
return result;
} }
@@ -814,6 +816,14 @@ static status_t
usb_disk_close(void *cookie) usb_disk_close(void *cookie)
{ {
TRACE("close()\n"); TRACE("close()\n");
device_lun *lun = (device_lun *)cookie;
disk_device *device = lun->device;
mutex_lock(&device->lock);
if (!device->removed)
usb_disk_synchronize(lun, false);
mutex_unlock(&device->lock);
return B_OK; return B_OK;
} }
@@ -827,9 +837,9 @@ usb_disk_free(void *cookie)
device_lun *lun = (device_lun *)cookie; device_lun *lun = (device_lun *)cookie;
disk_device *device = lun->device; disk_device *device = lun->device;
device->open_count--; device->open_count--;
if (device->removed && device->open_count == 0) { if (device->open_count == 0 && device->removed) {
// we can simply free the device here as it has been removed from the // we can simply free the device here as it has been removed from
// device list in the device removed notification hook // the device list in the device removed notification hook
usb_disk_free_device_and_luns(device); usb_disk_free_device_and_luns(device);
} }
@@ -885,12 +895,14 @@ usb_disk_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
break; break;
case B_EJECT_DEVICE: case B_EJECT_DEVICE:
return usb_disk_operation(lun, SCSI_START_STOP_UNIT_6, 6, 0, 2, result = usb_disk_operation(lun, SCSI_START_STOP_UNIT_6, 6, 0, 2,
NULL, NULL, false); NULL, NULL, false);
break;
case B_LOAD_MEDIA: case B_LOAD_MEDIA:
return usb_disk_operation(lun, SCSI_START_STOP_UNIT_6, 6, 0, 3, result = usb_disk_operation(lun, SCSI_START_STOP_UNIT_6, 6, 0, 3,
NULL, NULL, false); NULL, NULL, false);
break;
default: default:
TRACE_ALWAYS("unhandled ioctl %ld\n", op); TRACE_ALWAYS("unhandled ioctl %ld\n", op);