From waddlesplash <waddlesplash@xxxxxxxxx>:
waddlesplash has uploaded this change for review. (
https://review.haiku-os.org/c/haiku/+/2744 ;)
Change subject: nvme_disk: Avoid doing I/O larger than the maximum size, if
possible.
......................................................................
nvme_disk: Avoid doing I/O larger than the maximum size, if possible.
libnvme can break up transfers that are too large, but to do so,
it allocates one nvme_request struct (of which it has a large,
but finite, pool) per segment. Since we are already iterating
over "vecs", we might as well cut off transfers after they
would otherwise go over the limit.
Individual IOVs that are too large are left alone, though;
libnvme can still handle this. But at least we no longer try
to do all I/O in one go.
Tested in a similar manner to the previous commit.
---
M src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp
1 file changed, 15 insertions(+), 2 deletions(-)
git pull ssh://git.haiku-os.org:22/haiku refs/changes/44/2744/1
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 eec22b7..3a347fb 100644
--- a/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp
+++ b/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp
@@ -86,6 +86,7 @@
struct nvme_ns* ns;
uint64 capacity;
uint32 block_size;
+ uint32 max_io_blocks;
status_t media_status;
struct qpair_info {
@@ -264,6 +265,7 @@
// of the block size.
restrictions.max_segment_count = (NVME_MAX_SGL_DESCRIPTORS / 2);
restrictions.max_transfer_size = cstat.max_xfer_size;
+ info->max_io_blocks = cstat.max_xfer_size / nsstat.sector_size;
err = info->dma_resource.Init(restrictions, B_PAGE_SIZE, buffers,
buffers);
if (err != 0) {
@@ -743,14 +745,25 @@
return status;
}
+ const uint32 max_io_blocks = handle->info->max_io_blocks;
int32 remaining = nvme_request.iovec_count;
while (remaining > 0) {
nvme_request.iovec_count = min_c(remaining,
NVME_MAX_SGL_DESCRIPTORS / 2);
nvme_request.lba_count = 0;
- for (int i = 0; i < nvme_request.iovec_count; i++)
- nvme_request.lba_count += (nvme_request.iovecs[i].size
/ block_size);
+ for (int i = 0; i < nvme_request.iovec_count; i++) {
+ int32 vec_lba_count = (nvme_request.iovecs[i].size /
block_size);
+ if (nvme_request.lba_count > 0
+ && (nvme_request.lba_count +
vec_lba_count) > max_io_blocks) {
+ // We already have a nonzero length, and adding
this vec would
+ // make us go over (or we already are over.)
Stop adding.
+ nvme_request.iovec_count = i;
+ break;
+ }
+
+ nvme_request.lba_count += vec_lba_count;
+ }
status = do_nvme_io_request(handle->info, &nvme_request);
if (status != B_OK)
--
To view, visit https://review.haiku-os.org/c/haiku/+/2744
To unsubscribe, or for help writing mail filters, visit
https://review.haiku-os.org/settings
Gerrit-Project: haiku
Gerrit-Branch: master
Gerrit-Change-Id: I53777cac023d53b2b80faf1b71a521618f2208f7
Gerrit-Change-Number: 2744
Gerrit-PatchSet: 1
Gerrit-Owner: waddlesplash <waddlesplash@xxxxxxxxx>
Gerrit-MessageType: newchange