[prev in list] [next in list] [prev in thread] [next in thread]
List: haiku-commits
Subject: [haiku-commits] haiku: hrev55662 - src/add-ons/kernel/drivers/disk/nvme
From: waddlesplash <waddlesplash () gmail ! com>
Date: 2021-11-23 22:58:14
Message-ID: 20211123225814.336873F7A5 () turing ! freelists ! org
[Download RAW message or body]
hrev55662 adds 2 changesets to branch 'master'
old head: 3ff0d7a8824398aa1713a61ad692a731bb5e525f
new head: 750ed8dd4136fb19dd8876bad087848e5c31e33e
overview: https://git.haiku-os.org/haiku/log/?qt=range&q=750ed8dd4136+%5E3ff0d7a88243
----------------------------------------------------------------------------
ab2a1b20e388: nvme_disk: Add a missing CALLED() and another assert.
750ed8dd4136: nvme_disk: Implement TRIM.
Only lightly tested (in QEMU with qcow2 images: it seems to work
and not to discard actual data.) Use with caution!
[ Augustin Cavalier <waddlesplash@gmail.com> ]
----------------------------------------------------------------------------
1 file changed, 77 insertions(+)
.../kernel/drivers/disk/nvme/nvme_disk.cpp | 77 ++++++++++++++++++++
############################################################################
Commit: ab2a1b20e388496029cb64b946e6a8796425e506
URL: https://git.haiku-os.org/haiku/commit/?id=ab2a1b20e388
Author: Augustin Cavalier <waddlesplash@gmail.com>
Date: Tue Nov 23 22:53:57 2021 UTC
nvme_disk: Add a missing CALLED() and another assert.
----------------------------------------------------------------------------
diff --git a/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp \
b/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp index 0cd732ad8b..5222978ab7 \
100644
--- a/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp
+++ b/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp
@@ -155,6 +155,7 @@ nvme_disk_init_device(void* _info, void** _cookie)
{
CALLED();
nvme_disk_driver_info* info = (nvme_disk_driver_info*)_info;
+ ASSERT(info->ctrlr == NULL);
pci_device_module_info* pci;
pci_device* pcidev;
@@ -838,6 +839,7 @@ nvme_disk_write(void* cookie, off_t pos, const void* buffer, \
size_t* length) static status_t
nvme_disk_flush(nvme_disk_driver_info* info)
{
+ CALLED();
status_t status = EINPROGRESS;
qpair_info* qpinfo = get_qpair(info);
############################################################################
Revision: hrev55662
Commit: 750ed8dd4136fb19dd8876bad087848e5c31e33e
URL: https://git.haiku-os.org/haiku/commit/?id=750ed8dd4136
Author: Augustin Cavalier <waddlesplash@gmail.com>
Date: Tue Nov 23 22:54:31 2021 UTC
nvme_disk: Implement TRIM.
Only lightly tested (in QEMU with qcow2 images: it seems to work
and not to discard actual data.) Use with caution!
----------------------------------------------------------------------------
diff --git a/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp \
b/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp index 5222978ab7..65fbf67d51 \
100644
--- a/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp
+++ b/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp
@@ -853,6 +853,77 @@ nvme_disk_flush(nvme_disk_driver_info* info)
}
+static status_t
+nvme_disk_trim(nvme_disk_driver_info* info, fs_trim_data* trimData)
+{
+ CALLED();
+ trimData->trimmed_size = 0;
+
+ const off_t deviceSize = info->capacity * info->block_size; // in bytes
+ if (deviceSize < 0)
+ return B_BAD_VALUE;
+
+ STATIC_ASSERT(sizeof(deviceSize) <= sizeof(uint64));
+ ASSERT(deviceSize >= 0);
+
+ // Do not trim past device end.
+ for (uint32 i = 0; i < trimData->range_count; i++) {
+ uint64 offset = trimData->ranges[i].offset;
+ uint64& size = trimData->ranges[i].size;
+
+ if (offset >= (uint64)deviceSize)
+ return B_BAD_VALUE;
+ size = std::min(size, (uint64)deviceSize - offset);
+ }
+
+ // We need contiguous memory for the DSM ranges.
+ nvme_dsm_range* dsmRanges = (nvme_dsm_range*)nvme_mem_alloc_node(
+ trimData->range_count * sizeof(nvme_dsm_range), 0, 0, NULL);
+ if (dsmRanges == NULL)
+ return B_NO_MEMORY;
+ CObjectDeleter<void, void, nvme_free> dsmRangesDeleter(dsmRanges);
+
+ uint64 trimmingSize = 0;
+ for (uint32 i = 0; i < trimData->range_count; i++) {
+ uint64 offset = trimData->ranges[i].offset;
+ uint64 length = trimData->ranges[i].size;
+
+ // Round up offset and length to the block size.
+ // (Some space at the beginning and end may thus not be trimmed.)
+ offset = ROUNDUP(offset, info->block_size);
+ length -= offset - trimData->ranges[i].offset;
+ length = ROUNDDOWN(length, info->block_size);
+
+ if (length == 0)
+ continue;
+ if ((length / info->block_size) > UINT32_MAX)
+ length = uint64(UINT32_MAX) * info->block_size;
+ // TODO: Break into smaller trim ranges!
+
+ TRACE("trim %" B_PRIu64 " bytes from %" B_PRIu64 "\n", length, offset);
+
+ dsmRanges[i].attributes = 0;
+ dsmRanges[i].length = length / info->block_size;
+ dsmRanges[i].starting_lba = offset / info->block_size;
+
+ trimmingSize += dsmRanges[i].length;
+ }
+
+ status_t status = EINPROGRESS;
+ qpair_info* qpair = get_qpair(info);
+ if (nvme_ns_deallocate(info->ns, qpair->qpair, dsmRanges, trimData->range_count,
+ (nvme_cmd_cb)io_finished_callback, &status) != 0)
+ return B_IO_ERROR;
+
+ await_status(info, qpair->qpair, status);
+ if (status != B_OK)
+ return status;
+
+ trimData->trimmed_size = trimmingSize;
+ return B_OK;
+}
+
+
static status_t
nvme_disk_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
{
@@ -914,6 +985,10 @@ nvme_disk_ioctl(void* cookie, uint32 op, void* buffer, size_t \
length)
case B_FLUSH_DRIVE_CACHE:
return nvme_disk_flush(info);
+
+ case B_TRIM_DEVICE:
+ ASSERT(IS_KERNEL_ADDRESS(buffer));
+ return nvme_disk_trim(info, (fs_trim_data*)buffer);
}
return B_DEV_INVALID_IOCTL;
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic