[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