hrev54909 adds 2 changesets to branch 'master'
old head: a43b8d4634556794d90b9263f330c31641b97eaa
new head: 2028d6386c678e65fa33233b07e012e25717cc24
overview:
https://git.haiku-os.org/haiku/log/?qt=range&q=2028d6386c67+%5Ea43b8d463455
----------------------------------------------------------------------------
cef80a1fb7ed: devfs: translate partition offsets in B_TRIM_DEVICE
Fixes bfs part of #10336. Untested on SATA (don't have a testing drive
to sacrifice) but working fine on SD/MMC.
This requires moving the copy from kernel to userland into the devfs. As
a result the code in the disk drivers becomes a bit simpler.
Also add some documentation for the common ioctls to implement for a
disk device.
Change-Id: Ie84b6a1d293828d33902a64b3c9d4b19aa6eacb1
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3640
Reviewed-by: Jérôme Duval <jerome.duval@xxxxxxxxx>
2028d6386c67: mmc_disk: implement B_TRIM_DEVICE
Change-Id: Ib08a1e196441f35550fe221b912332b4803a04b4
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3641
Reviewed-by: Jérôme Duval <jerome.duval@xxxxxxxxx>
[ Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> ]
----------------------------------------------------------------------------
9 files changed, 184 insertions(+), 34 deletions(-)
docs/develop/drivers/disk/ioctls.txt | 42 ++++++++++
headers/os/drivers/Drivers.h | 4 +-
headers/private/drivers/mmc.h | 5 ++
headers/private/kernel/util/fs_trim_support.h | 2 +
src/add-ons/kernel/busses/mmc/sdhci_pci.cpp | 3 +
src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp | 84 +++++++++++++++++++-
.../drivers/disk/scsi/scsi_disk/scsi_disk.cpp | 16 +---
.../drivers/disk/virtual/ram_disk/ram_disk.cpp | 16 +---
src/system/kernel/device_manager/devfs.cpp | 46 +++++++++--
############################################################################
Commit: cef80a1fb7edf58f8050d2ac32c8c36e000c2163
URL: https://git.haiku-os.org/haiku/commit/?id=cef80a1fb7ed
Author: Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date: Sun Jan 17 16:46:05 2021 UTC
Committer: Adrien Destugues <pulkomandy@xxxxxxxxx>
Commit-Date: Sat Jan 23 12:20:59 2021 UTC
Ticket: https://dev.haiku-os.org/ticket/10336
devfs: translate partition offsets in B_TRIM_DEVICE
Fixes bfs part of #10336. Untested on SATA (don't have a testing drive
to sacrifice) but working fine on SD/MMC.
This requires moving the copy from kernel to userland into the devfs. As
a result the code in the disk drivers becomes a bit simpler.
Also add some documentation for the common ioctls to implement for a
disk device.
Change-Id: Ie84b6a1d293828d33902a64b3c9d4b19aa6eacb1
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3640
Reviewed-by: Jérôme Duval <jerome.duval@xxxxxxxxx>
----------------------------------------------------------------------------
diff --git a/docs/develop/drivers/disk/ioctls.txt
b/docs/develop/drivers/disk/ioctls.txt
new file mode 100644
index 0000000000..1f6a3e3adc
--- /dev/null
+++ b/docs/develop/drivers/disk/ioctls.txt
@@ -0,0 +1,42 @@
+Here is a list of ioctls usually implemented by disk devices.
+
+B_GET_DEVICE_SIZE
+
+The parameter is a size_t and is filled with the disk size in bytes.
+This is limited to 4GB and not very useful. B_GET_GEOMETRY is used instead.
+
+B_GET_GEOMETRY
+
+The parameter is a device_geometry structure to be filled with the device
geometry.
+
+B_GET_ICON_NAME
+
+Deprecated. Get the name of an icon to use. The icons are hardcoded in Tracker.
+
+B_GET_VECTOR_ICON
+
+The parameter is a device_icon structure to be populated with the icon data in
HVIF format.
+This icon is then used to show the disk in Tracker, for example.
+
+B_EJECT_DEVICE
+
+Eject the device (for removable devices).
+
+B_LOAD_MEDIA
+
+Load the device (reverse of eject) if possible.
+
+B_FLUSH_DRIVE_CACHE
+
+Make sure all data is stored on persistent storage and not in caches
(including any caching inside
+the device)
+
+B_TRIM_DEVICE
+
+The parameter is an fs_trim_data structure. It is guaranteed to be in kernel
memory because
+the partition manager pre-processes requests coming from userland and makes
sure no sectors
+are outside the partition range for a specific partition device.
+
+Mark the listed areas on disk as unused, allowing future reads to these areas
to return
+random data or read errors. Flash memory devices (SSD, MMC, ...) may use this
information
+to optimize their internal storage.
diff --git a/headers/os/drivers/Drivers.h b/headers/os/drivers/Drivers.h
index a854305b38..a8b4d7f788 100644
--- a/headers/os/drivers/Drivers.h
+++ b/headers/os/drivers/Drivers.h
@@ -175,8 +175,8 @@ typedef struct {
uint32 range_count;
uint64 trimmed_size; /* filled on return */
struct range {
- uint64 offset; /* offset (in bytes) */
- uint64 size;
+ off_t offset; /* offset (in bytes) */
+ off_t size;
} ranges[1];
} fs_trim_data;
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 05246eb063..0d6b1188df 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
@@ -418,18 +418,10 @@ das_ioctl(void* cookie, uint32 op, void* buffer, size_t
length)
#if 0
case B_TRIM_DEVICE:
{
- fs_trim_data* trimData;
- MemoryDeleter deleter;
- status_t status = get_trim_data_from_user(buffer,
length, deleter,
- trimData);
- if (status != B_OK)
- return status;
-
- status = trim_device(info, trimData);
- if (status != B_OK)
- return status;
-
- return copy_trim_data_to_user(buffer, trimData);
+ // We know the buffer is kernel-side because it has been
+ // preprocessed in devfs
+ ASSERT(IS_KERNEL_ADDRESS(buffer));
+ return trim_device(info, (fs_trim_data*)buffer);
}
#endif
diff --git a/src/add-ons/kernel/drivers/disk/virtual/ram_disk/ram_disk.cpp
b/src/add-ons/kernel/drivers/disk/virtual/ram_disk/ram_disk.cpp
index fdb3200be9..280e370abb 100644
--- a/src/add-ons/kernel/drivers/disk/virtual/ram_disk/ram_disk.cpp
+++ b/src/add-ons/kernel/drivers/disk/virtual/ram_disk/ram_disk.cpp
@@ -1474,18 +1474,10 @@ ram_disk_raw_device_control(void* _cookie, uint32 op,
void* buffer,
case B_TRIM_DEVICE:
{
- fs_trim_data* trimData;
- MemoryDeleter deleter;
- status_t status = get_trim_data_from_user(buffer,
length, deleter,
- trimData);
- if (status != B_OK)
- return status;
-
- status = device->Trim(trimData);
- if (status != B_OK)
- return status;
-
- return copy_trim_data_to_user(buffer, trimData);
+ // We know the buffer is kernel-side because it has been
+ // preprocessed in devfs
+ ASSERT(IS_KERNEL_ADDRESS(buffer));
+ return device->Trim((fs_trim_data*)buffer);
}
case RAM_DISK_IOCTL_INFO:
diff --git a/src/system/kernel/device_manager/devfs.cpp
b/src/system/kernel/device_manager/devfs.cpp
index 65b9ce7cc6..17a0730c06 100644
--- a/src/system/kernel/device_manager/devfs.cpp
+++ b/src/system/kernel/device_manager/devfs.cpp
@@ -33,6 +33,7 @@
#include <lock.h>
#include <Notifications.h>
#include <util/AutoLock.h>
+#include <util/fs_trim_support.h>
#include <vfs.h>
#include <vm/vm.h>
#include <wait_for_objects.h>
@@ -493,14 +494,14 @@ err1:
}
-static inline void
+template<typename size_type> static inline void
translate_partition_access(devfs_partition* partition, off_t& offset,
- size_t& size)
+ size_type& size)
{
ASSERT(offset >= 0);
ASSERT(offset < partition->info.size);
- size = (size_t)min_c((off_t)size, partition->info.size - offset);
+ size = (size_type)min_c((off_t)size, partition->info.size - offset);
offset += partition->info.offset;
}
@@ -1214,7 +1215,8 @@ devfs_read(fs_volume* _volume, fs_vnode* _vnode, void*
_cookie, off_t pos,
if (pos >= vnode->stream.u.dev.partition->info.size)
return B_BAD_VALUE;
- translate_partition_access(vnode->stream.u.dev.partition, pos,
*_length);
+ translate_partition_access(vnode->stream.u.dev.partition, pos,
+ *_length);
}
if (*_length == 0)
@@ -1246,7 +1248,8 @@ devfs_write(fs_volume* _volume, fs_vnode* _vnode, void*
_cookie, off_t pos,
if (pos >= vnode->stream.u.dev.partition->info.size)
return B_BAD_VALUE;
- translate_partition_access(vnode->stream.u.dev.partition, pos,
*_length);
+ translate_partition_access(vnode->stream.u.dev.partition, pos,
+ *_length);
}
if (*_length == 0)
@@ -1460,6 +1463,39 @@ devfs_ioctl(fs_volume* _volume, fs_vnode* _vnode, void*
_cookie, uint32 op,
return user_memcpy(buffer, &geometry,
sizeof(device_geometry));
}
+ case B_TRIM_DEVICE:
+ {
+ struct devfs_partition* partition
+ = vnode->stream.u.dev.partition;
+
+ fs_trim_data* trimData;
+ MemoryDeleter deleter;
+ status_t status =
get_trim_data_from_user(buffer, length,
+ deleter, trimData);
+ if (status != B_OK)
+ return status;
+
+ if (partition != NULL) {
+ // If there is a partition, offset all
ranges according
+ // to the partition start.
+ for (uint32 i = 0; i <
trimData->range_count; i++) {
+
translate_partition_access(partition,
+
trimData->ranges[i].offset,
+
trimData->ranges[i].size);
+ }
+ }
+
+ status = vnode->stream.u.dev.device->Control(
+ cookie->device_cookie, op, trimData,
length);
+
+ // Copy the data back to userland (it contains
the number of
+ // trimmed bytes)
+ if (status == B_OK)
+ status = copy_trim_data_to_user(buffer,
trimData);
+
+ return status;
+ }
+
case B_GET_DRIVER_FOR_DEVICE:
{
#if 0
############################################################################
Revision: hrev54909
Commit: 2028d6386c678e65fa33233b07e012e25717cc24
URL: https://git.haiku-os.org/haiku/commit/?id=2028d6386c67
Author: Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date: Sun Jan 17 14:22:52 2021 UTC
Committer: Adrien Destugues <pulkomandy@xxxxxxxxx>
Commit-Date: Sat Jan 23 12:20:59 2021 UTC
mmc_disk: implement B_TRIM_DEVICE
Change-Id: Ib08a1e196441f35550fe221b912332b4803a04b4
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3641
Reviewed-by: Jérôme Duval <jerome.duval@xxxxxxxxx>
----------------------------------------------------------------------------
diff --git a/headers/private/drivers/mmc.h b/headers/private/drivers/mmc.h
index 8d3780e122..e8434c4171 100644
--- a/headers/private/drivers/mmc.h
+++ b/headers/private/drivers/mmc.h
@@ -49,6 +49,11 @@ enum SD_COMMANDS {
SD_WRITE_SINGLE_BLOCK = 24,
SD_WRITE_MULTIPLE_BLOCKS = 25,
+ // Erase commands, class 5
+ SD_ERASE_WR_BLK_START = 32,
+ SD_ERASE_WR_BLK_END = 33,
+ SD_ERASE = 38,
+
// Application specific commands, class 8
SD_APP_CMD = 55,
diff --git a/headers/private/kernel/util/fs_trim_support.h
b/headers/private/kernel/util/fs_trim_support.h
index 22e6f9ac41..317929faa9 100644
--- a/headers/private/kernel/util/fs_trim_support.h
+++ b/headers/private/kernel/util/fs_trim_support.h
@@ -6,7 +6,9 @@
#define _FS_TRIM_SUPPORT_H
+#include <AutoDeleter.h>
#include <KernelExport.h>
+#include <SupportDefs.h>
#include <kernel.h>
#include <syscall_restart.h>
diff --git a/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp
b/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp
index ae9831496f..748bacdf5f 100644
--- a/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp
+++ b/src/add-ons/kernel/busses/mmc/sdhci_pci.cpp
@@ -213,6 +213,7 @@ SdhciBus::ExecuteCommand(uint8_t command, uint32_t
argument, uint32_t* response)
replyType = Command::kR6Type;
break;
case SD_SELECT_DESELECT_CARD:
+ case SD_ERASE:
replyType = Command::kR1bType;
break;
case SD_SEND_IF_COND:
@@ -225,6 +226,8 @@ SdhciBus::ExecuteCommand(uint8_t command, uint32_t
argument, uint32_t* response)
replyType = Command::kR1Type | Command::kDataPresent;
break;
case SD_APP_CMD:
+ case SD_ERASE_WR_BLK_START:
+ case SD_ERASE_WR_BLK_END:
case SD_SET_BUS_WIDTH: // SD Application command
replyType = Command::kR1Type;
break;
diff --git a/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp
b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp
index 2fec95e5aa..66a66b5ce4 100644
--- a/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp
+++ b/src/add-ons/kernel/drivers/disk/mmc/mmc_disk.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright 2018-2020 Haiku, Inc. All rights reserved.
+ * Copyright 2018-2021 Haiku, Inc. All rights reserved.
* Copyright 2020, Viveris Technologies.
* Distributed under the terms of the MIT License.
*
@@ -23,8 +23,10 @@
#include <drivers/KernelExport.h>
#include <drivers/Drivers.h>
#include <kernel/OS.h>
+#include <util/fs_trim_support.h>
+
+#include <AutoDeleter.h>
-// #include <fs/devfs.h>
#define TRACE_MMC_DISK
#ifdef TRACE_MMC_DISK
@@ -39,6 +41,9 @@
#define MMC_DISK_DEVICE_MODULE_NAME "drivers/disk/mmc/mmc_disk/device_v1"
#define MMC_DEVICE_ID_GENERATOR "mmc/device_id"
+
+static const uint32 kBlockSize = 512; // FIXME get it from the CSD
+
static device_manager_info* sDeviceManager;
@@ -237,7 +242,6 @@ mmc_disk_init_driver(device_node* node, void** cookie)
else
info->flags = kIoCommandOffsetAsSectors;
- static const uint32 kBlockSize = 512; // FIXME get it from the CSD
status_t error;
static const uint32 kDMAResourceBufferCount = 16;
@@ -475,6 +479,73 @@ mmc_block_io(void* cookie, io_request* request)
}
+static status_t
+mmc_block_trim(mmc_disk_driver_info* info, fs_trim_data* trimData)
+{
+ enum {
+ kEraseModeErase = 0, // force to actually erase the data
+ kEraseModeDiscard = 1,
+ // just mark the data as unused for internal wear
leveling
+ // algorithms
+ kEraseModeFullErase = 2, // erase the whole card
+ };
+ TRACE("trim_device()\n");
+
+ uint64 trimmedSize = 0;
+ status_t result = B_OK;
+ for (uint32 i = 0; i < trimData->range_count; i++) {
+ off_t offset = trimData->ranges[i].offset;
+ off_t length = trimData->ranges[i].size;
+
+ // Round up offset and length to multiple of the sector size
+ // The offset is rounded up, so some space may be left
+ // (not trimmed) at the start of the range.
+ offset = ROUNDUP(offset, kBlockSize);
+ // Adjust the length for the possibly skipped range
+ length -= trimData->ranges[i].offset - offset;
+ // The length is rounded down, so some space at the end may also
+ // be left (not trimmed).
+ length &= ~(kBlockSize - 1);
+
+ if (length == 0) {
+ trimmedSize += trimData->ranges[i].size;
+ continue;
+ }
+
+ TRACE("trim %" B_PRIdOFF " bytes from %" B_PRIdOFF "\n",
+ length, offset);
+
+ ASSERT(offset % kBlockSize == 0);
+ ASSERT(length % kBlockSize == 0);
+
+ if (info->flags & kIoCommandOffsetAsSectors) {
+ offset /= kBlockSize;
+ length /= kBlockSize;
+ }
+
+ uint32_t response;
+ result = info->mmc->execute_command(info->parent,
info->parentCookie,
+ info->rca, SD_ERASE_WR_BLK_START, offset, &response);
+ if (result != B_OK)
+ break;
+ result = info->mmc->execute_command(info->parent,
info->parentCookie,
+ info->rca, SD_ERASE_WR_BLK_END, offset + length,
&response);
+ if (result != B_OK)
+ break;
+ result = info->mmc->execute_command(info->parent,
info->parentCookie,
+ info->rca, SD_ERASE, kEraseModeDiscard, &response);
+ if (result != B_OK)
+ break;
+
+ trimmedSize += trimData->ranges[i].size;
+ }
+
+ trimData->trimmed_size = trimmedSize;
+
+ return result;
+}
+
+
static status_t
mmc_block_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
{
@@ -550,6 +621,13 @@ mmc_block_ioctl(void* cookie, uint32 op, void* buffer,
size_t length)
return user_memcpy(buffer, &iconData,
sizeof(device_icon));
}
+ case B_TRIM_DEVICE:
+ {
+ // We know the buffer is kernel-side because it has been
+ // preprocessed in devfs
+ return mmc_block_trim(info, (fs_trim_data*)buffer);
+ }
+
/*case B_FLUSH_DRIVE_CACHE:
return synchronize_cache(info);*/
}