[haiku-commits] haiku: hrev54909 - src/add-ons/kernel/drivers/disk/mmc docs/develop/drivers/disk src/system/kernel/device_manager src/add-ons/kernel/drivers/disk/scsi/scsi_disk src/add-ons/kernel/drivers/disk/virtual/ram_disk

  • From: Adrien Destugues <pulkomandy@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sat, 23 Jan 2021 12:21:02 +0000 (UTC)

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);*/
        }


Other related posts:

  • » [haiku-commits] haiku: hrev54909 - src/add-ons/kernel/drivers/disk/mmc docs/develop/drivers/disk src/system/kernel/device_manager src/add-ons/kernel/drivers/disk/scsi/scsi_disk src/add-ons/kernel/drivers/disk/virtual/ram_disk - Adrien Destugues