trim: Target SCSI UNMAP command instead of WRITE SAME.

* The UNMAP command is theoretically much faster, as it can get many block
  ranges instead of just a single range.
* Furthermore, the ATA TRIM command resembles it much better.
* Therefore, fs_trim_data now gets an array of ranges, and we use SCSI UNMAP
  to trim.
* Updated BFS code to collect array ranges to fully support the new
  fs_trim_data possibilities.
This commit is contained in:
Axel Dörfler
2013-11-07 19:03:47 +01:00
parent 960c56aea5
commit 99086aa323
13 changed files with 249 additions and 64 deletions
+35 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2004-2010, 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.
@@ -185,6 +185,8 @@
#define SCSI_OP_WRITE_BUFFER 0x3b
#define SCSI_OP_READ_BUFFER 0x3c
#define SCSI_OP_CHANGE_DEFINITION 0x40
#define SCSI_OP_WRITE_SAME_10 0x41
#define SCSI_OP_UNMAP 0x42
#define SCSI_OP_READ_SUB_CHANNEL 0x42
#define SCSI_OP_READ_TOC 0x43
#define SCSI_OP_PLAY_MSF 0x47
@@ -457,7 +459,38 @@ typedef struct scsi_cmd_wsame_16 {
);
uint8 control;
} _PACKED scsi_cmd_wsame_16;
// UNMAP
typedef struct scsi_cmd_unmap {
uint8 opcode;
LBITFIELD8_2(
anchor : 1,
_reserved1_7 : 7
);
uint32 _reserved1;
LBITFIELD8_2(
group_number : 5,
_reserved5_7 : 3
);
uint16 length;
uint8 control;
} _PACKED scsi_cmd_unmap;
struct scsi_unmap_block_descriptor {
uint64 lba;
uint32 block_count;
uint32 _reserved1;
} _PACKED;
struct scsi_unmap_parameter_list {
uint16 data_length;
uint16 block_data_length;
uint32 _reserved1;
struct scsi_unmap_block_descriptor blocks[1];
} _PACKED;
// REQUEST SENSE
+5 -1
View File
@@ -72,6 +72,10 @@ typedef struct scsi_periph_callbacks {
void (*media_changed)(periph_device_cookie cookie, scsi_ccb *request);
} scsi_periph_callbacks;
typedef struct scsi_block_range {
uint64 offset;
uint64 size;
} scsi_block_range;
// functions provided by this module
typedef struct scsi_periph_interface {
@@ -119,7 +123,7 @@ typedef struct scsi_periph_interface {
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);
scsi_block_range* ranges, uint32 rangeCount);
// *** removable media ***
// to be called when a medium change is detected to block subsequent commands