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
@@ -20,8 +20,10 @@
// TODO: temporary solution as long as there is no public I/O requests API
#ifndef BFS_SHELL
# include <io_requests.h>
# include <util/fs_trim_support.h>
#endif
#define BFS_IO_SIZE 65536
@@ -623,19 +625,32 @@ bfs_ioctl(fs_volume* _volume, fs_vnode* _node, void* _cookie, uint32 cmd,
Volume* volume = (Volume*)_volume->private_volume;
switch (cmd) {
#ifndef BFS_SHELL
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 = volume->Allocator().Trim(trimData.offset,
trimData.size, trimData.trimmed_size);
fs_trim_data* trimData;
status_t status = copy_trim_data_from_user(buffer, bufferLength,
trimData);
if (status != B_OK)
return status;
return user_memcpy(buffer, &trimData, sizeof(fs_trim_data));
MemoryDeleter deleter(trimData);
trimData->trimmed_size = 0;
for (uint32 i = 0; i < trimData->range_count; i++) {
uint64 trimmedSize = 0;
status_t status = volume->Allocator().Trim(
trimData->ranges[i].offset, trimData->ranges[i].size,
trimmedSize);
if (status != B_OK)
return status;
trimData->trimmed_size += trimmedSize;
}
return copy_trim_data_to_user(buffer, trimData);
}
#endif
case BFS_IOCTL_VERSION:
{