added 1 changeset to branch 'refs/remotes/axeld-github/trim' old head: 1c6edcdcdc8ab0b4a9ed79d2c0464e73ac8e0745 new head: a6ecf2a9d10d98245fe6346a1116aec5fc653f62 overview: https://github.com/axeld/haiku/compare/1c6edcd...a6ecf2a ---------------------------------------------------------------------------- a6ecf2a: This gets the trim command as WRITE SAME operation to SCSI * Neither hardware nor driver to test it; AHCI/IDE support is next on the table. [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ] ---------------------------------------------------------------------------- Commit: a6ecf2a9d10d98245fe6346a1116aec5fc653f62 Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> Date: Sun Aug 4 22:51:37 2013 UTC ---------------------------------------------------------------------------- 5 files changed, 93 insertions(+), 13 deletions(-) headers/private/drivers/scsi_periph.h | 11 +++-- .../drivers/disk/scsi/scsi_disk/scsi_disk.cpp | 39 ++++++++++++++-- src/add-ons/kernel/generic/scsi_periph/block.cpp | 47 ++++++++++++++++++-- .../kernel/generic/scsi_periph/scsi_periph.cpp | 5 ++- .../kernel/generic/scsi_periph/scsi_periph_int.h | 4 +- ---------------------------------------------------------------------------- diff --git a/headers/private/drivers/scsi_periph.h b/headers/private/drivers/scsi_periph.h index 03fd57e..b879521 100644 --- a/headers/private/drivers/scsi_periph.h +++ b/headers/private/drivers/scsi_periph.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2008, Haiku, Inc. All RightsReserved. + * Copyright 2004-2013, Haiku, Inc. All RightsReserved. * Copyright 2002/03, Thomas Kurschel. All rights reserved. * * Distributed under the terms of the MIT License. @@ -7,6 +7,7 @@ #ifndef _SCSI_PERIPH_H #define _SCSI_PERIPH_H + /*! Use this module to minimize work required to write a SCSI peripheral driver. @@ -114,6 +115,12 @@ typedef struct scsi_periph_interface { // request - ccb for this device; is used to talk to device status_t (*check_capacity)(scsi_periph_device device, scsi_ccb *request); + // synchronizes (flush) the device cache + err_res (*synchronize_cache)(scsi_periph_device device, scsi_ccb *request); + + status_t (*trim_device)(scsi_periph_device_info *device, scsi_ccb *request, + uint64 offset, uint64 numBlocks); + // *** removable media *** // to be called when a medium change is detected to block subsequent commands void (*media_changed)(scsi_periph_device device); @@ -128,8 +135,6 @@ typedef struct scsi_periph_interface { // returns: B_OK, B_DEV_MEDIA_CHANGE_REQUESTED, B_NO_MEMORY or // pending error reported by handle_get_error status_t (*get_media_status)(scsi_periph_handle handle); - // synchronizes (flush) the device cache - err_res(*synchronize_cache)(scsi_periph_device device, scsi_ccb *request); // compose device name consisting of prefix and path/target/LUN // (result must be freed by caller) diff --git a/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp b/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp index d3d13af..c566396 100644 --- a/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp @@ -1,9 +1,10 @@ /* - * Copyright 2008-2012, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx. + * Copyright 2008-2013, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx. * Copyright 2002/03, Thomas Kurschel. All rights reserved. * Distributed under the terms of the MIT License. */ + /*! Peripheral driver to handle any kind of SCSI disks, i.e. hard disk and floopy disks (ZIP etc.) @@ -93,7 +94,6 @@ get_geometry(das_handle* handle, device_geometry* geometry) if (status != B_OK) return status; - devfs_compute_geometry_size(geometry, info->capacity, info->block_size); geometry->device_type = B_DISK; @@ -153,6 +153,24 @@ synchronize_cache(das_driver_info *device) } +static status_t +trim_device(das_driver_info* device, off_t offset, off_t size) +{ + TRACE("trim_device()\n"); + + scsi_ccb* request = device->scsi->alloc_ccb(device->scsi_device); + if (request == NULL) + return B_NO_MEMORY; + + status_t status = sSCSIPeripheral->trim_device(device->scsi_periph_device, + request, offset / device->block_size, size / device->block_size); + + device->scsi->free_ccb(request); + + return status; +} + + static int log2(uint32 x) { @@ -385,6 +403,21 @@ das_ioctl(void* cookie, uint32 op, void* buffer, size_t length) case B_FLUSH_DRIVE_CACHE: return synchronize_cache(info); + case B_TRIM_DEVICE: + { + fs_trim_data trimData; + if (user_memcpy(&trimData, buffer, sizeof(fs_trim_data)) != B_OK) + return B_BAD_ADDRESS; + + status_t status = trim_device(info, trimData.offset, trimData.size); + if (status != B_OK) + return status; + + trimData.trimmed_size = trimData.size; + + return user_memcpy(buffer, &trimData, sizeof(fs_trim_data)); + } + default: return sSCSIPeripheral->ioctl(handle->scsi_periph_handle, op, buffer, length); @@ -649,7 +682,7 @@ struct driver_module_info sSCSIDiskDriver = { das_init_driver, das_uninit_driver, das_register_child_devices, - das_rescan_child_devices, + das_rescan_child_devices, NULL, // removed }; diff --git a/src/add-ons/kernel/generic/scsi_periph/block.cpp b/src/add-ons/kernel/generic/scsi_periph/block.cpp index 3b3ac63..0c6eb0d 100644 --- a/src/add-ons/kernel/generic/scsi_periph/block.cpp +++ b/src/add-ons/kernel/generic/scsi_periph/block.cpp @@ -1,12 +1,12 @@ /* - * Copyright 2004-2011, Haiku, Inc. All RightsReserved. + * Copyright 2004-2013, Haiku, Inc. All RightsReserved. * Copyright 2002-2003, Thomas Kurschel. All rights reserved. * * Distributed under the terms of the MIT License. */ -//! Handling of block device (currently, only a capacity check is provided) +//! Handling of block device #include "scsi_periph_int.h" @@ -59,10 +59,10 @@ periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *request) if (capacity == UINT_MAX) { mutex_unlock(&device->mutex); - + scsi_cmd_read_capacity_long *cmd = (scsi_cmd_read_capacity_long *)request->cdb; - + scsi_res_read_capacity_long capacityLongResult; request->data = (uint8*)&capacityLongResult; request->data_length = sizeof(capacityLongResult); @@ -114,3 +114,42 @@ periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *request) return res; } + +status_t +periph_trim_device(scsi_periph_device_info *device, scsi_ccb *request, + uint64 offset, uint64 numBlocks) +{ + err_res res; + int retries = 0; + + do { + request->flags = SCSI_DIR_OUT; + request->sort = offset; + request->timeout = device->std_timeout; + + scsi_cmd_wsame_16* cmd = (scsi_cmd_wsame_16*)request->cdb; + + memset(cmd, 0, sizeof(*cmd)); + cmd->opcode = SCSI_OP_WRITE_SAME_16; + cmd->unmap = 1; + cmd->lba = B_HOST_TO_BENDIAN_INT64(offset); + cmd->length = B_HOST_TO_BENDIAN_INT32(numBlocks); + + request->cdb_length = sizeof(*cmd); + + device->scsi->async_io(request); + + acquire_sem(request->completion_sem); + + // ask generic peripheral layer what to do now + res = periph_check_error(device, request); + } while ((res.action == err_act_retry && retries++ < 3) + || (res.action == err_act_many_retries && retries++ < 30)); + + // peripheral layer only creates "read" error + if (res.error_code == B_DEV_READ_ERROR) + return B_DEV_WRITE_ERROR; + + return res.error_code; +} + diff --git a/src/add-ons/kernel/generic/scsi_periph/scsi_periph.cpp b/src/add-ons/kernel/generic/scsi_periph/scsi_periph.cpp index c3b1663..7970698 100644 --- a/src/add-ons/kernel/generic/scsi_periph/scsi_periph.cpp +++ b/src/add-ons/kernel/generic/scsi_periph/scsi_periph.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004-2008, Haiku, Inc. All RightsReserved. + * Copyright 2004-2013, Haiku, Inc. All RightsReserved. * Copyright 2002-2003, Thomas Kurschel. All rights reserved. * * Distributed under the terms of the MIT License. @@ -135,12 +135,13 @@ static scsi_periph_interface sSCSIPeripheralModule = { periph_io, periph_ioctl, periph_check_capacity, + periph_synchronize_cache, + periph_trim_device, periph_media_changed_public, periph_check_error, periph_send_start_stop, periph_get_media_status, - periph_synchronize_cache, periph_compose_device_name }; diff --git a/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h b/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h index c7493a5..30df67a 100644 --- a/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h +++ b/src/add-ons/kernel/generic/scsi_periph/scsi_periph_int.h @@ -1,5 +1,5 @@ /* - * Copyright 2004-2008, Haiku, Inc. All Rights Reserved. + * Copyright 2004-2013, Haiku, Inc. All Rights Reserved. * Copyright 2002, Thomas Kurschel. All rights reserved. * Distributed under the terms of the MIT License. */ @@ -77,6 +77,8 @@ status_t periph_handle_free(scsi_periph_handle_info *handle); // block.c status_t periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *ccb); +status_t periph_trim_device(scsi_periph_device_info *device, scsi_ccb *request, + uint64 offset, uint64 numBlocks); // device.c