From nobody Thu Apr 09 23:38:09 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4fsGZp31FJz6YmvT for ; Thu, 09 Apr 2026 23:38:10 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R12" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4fsGZp0W1Mz3tsd for ; Thu, 09 Apr 2026 23:38:10 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1775777890; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Cjn/j9pmWpjNQNrohgH8N24BtODTE96kP92oaYezJfE=; b=ad8Ebv8c6OtQHwrL84jlXaD+vICwb1VM3xn7UpZo/T4FDBq1US5PM412jPGrmThO88Y+ss XtfuNOe/s9gI5IX1/992LUU9X63CzzGfoe4d80mys7sGDdfC3L9t9eFPpR57qKiY7+ukaF Da08E8tvxB/FKHDFCoRJzYbzhhGNUG3XU8XIXKMWFdkLHhhQ+W/loGf1HyBGFxWEc4Yk5F 2p5h79pBPRwkFPfa2SJNZ/a5KjTY6aHPz2C6S8l7c8WrrRQOUlHVVwdpxFABUtWWleoLw9 GneScsDg5lIGY853t4GrWya71JsFtJEAew2K6KWwGPxNnbyPEALMqRFVLGdFrQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1775777890; a=rsa-sha256; cv=none; b=d15yhbdT4VU7OG3JWBMdqC76KOklLOUlfhyz4efXNL0luJ7WNxxkjK8DIVscZrF8siC2xJ Iduh/ohRQd8inGvr+Euq1c64G7MyY1ZGstvk3ZRUp8FLoU/9PbPfG/anYyjaKxxfyNikuQ 24GdZqk0lVnTVFTekqd226UdauTT7MQk0MhInR26ALTT3ZhndFCfNRv40Ei+dTINJcxVrd BycwxIApIiS1RtCR3nJPg5+wONhpqD2R3whubboLMbQPYiG9pKyNzugiozUKzl9iTTTZhw UU/zjwgRnbgfiwmX9wwA2hV8pFknDhRPu5A7RZUVXXZSxOiyXx/ZUHb9GqQZvA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1775777890; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Cjn/j9pmWpjNQNrohgH8N24BtODTE96kP92oaYezJfE=; b=HgykY8DCHhBXBHbiCU5szrNve/vFPqVBYNPDJvIZNIuSoDmZ/f8u8DFvDjBTB9KmSec4lt muJeyw+mVqAcmQQChp2WveqkML3ToM3mxq7/NirNUcB/VLCkUrrWgfS0j7FFBDd1AgX9B6 9YUR4Zbr9eybKkV2UUYychxrS1SBo88Q83RdiVJ4300WdmUzr/qcJjgxc+1yr6TrhzelsV q5jyCfdXsFmGFSom3ERHKHw5bJnqheSIh4QRfDrPgcKYoMrCrqhaPEOaSvmGHXgXv+IOf5 BZpX+0vsKeJ0qhdpWBu66uL4f3godbAK7GFdBzXnDJJbYGrq0nabKdBhuF3nhw== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4fsGZn71ZCz40B for ; Thu, 09 Apr 2026 23:38:09 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 30492 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Thu, 09 Apr 2026 23:38:09 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Warner Losh Subject: git: 82ff1c334b97 - main - nvme: Allow larger user request sizes List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: imp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 82ff1c334b97e5b68e6330e90f0aa6ae0f6af9aa Auto-Submitted: auto-generated Date: Thu, 09 Apr 2026 23:38:09 +0000 Message-Id: <69d83861.30492.23c808d2@gitrepo.freebsd.org> The branch main has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=82ff1c334b97e5b68e6330e90f0aa6ae0f6af9aa commit 82ff1c334b97e5b68e6330e90f0aa6ae0f6af9aa Author: Warner Losh AuthorDate: 2026-04-09 16:18:31 +0000 Commit: Warner Losh CommitDate: 2026-04-09 23:37:21 +0000 nvme: Allow larger user request sizes We have a small buffer for pages on the stack, but if the user wants to do an I/O larger than this we currently fail w/o a way for the user to know the max size. It's not hard to allocate an array for the uncommon case of very large I/Os, and the performance advantage of the array is small in that case anyway. In addition, this allows firmware upgrades using the full transfer size of the device as a happy accident too. Sponsored by: Netflix Reviewed by: chs, chuck Differential Revision: https://reviews.freebsd.org/D55638 --- sys/dev/nvme/nvme_ctrlr.c | 48 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c index b75033300061..e5094e909a24 100644 --- a/sys/dev/nvme/nvme_ctrlr.c +++ b/sys/dev/nvme/nvme_ctrlr.c @@ -1345,30 +1345,52 @@ nvme_ctrlr_shared_handler(void *arg) #define NVME_MAX_PAGES (int)(1024 / sizeof(vm_page_t)) +static int +nvme_page_count(vm_offset_t start, size_t len) +{ + return atop(round_page(start + len) - trunc_page(start)); +} + static int nvme_user_ioctl_req(vm_offset_t addr, size_t len, bool is_read, - vm_page_t *upages, int max_pages, int *npagesp, struct nvme_request **req, + vm_page_t **upages, int max_pages, int *npagesp, struct nvme_request **req, nvme_cb_fn_t cb_fn, void *cb_arg) { vm_prot_t prot = VM_PROT_READ; - int err; + int err, npages; + vm_page_t *upages_us; + + upages_us = *upages; + npages = nvme_page_count(addr, len); + if (npages > atop(maxphys)) + return (EINVAL); + if (npages > NVME_MAX_PAGES) + upages_us = malloc(npages * sizeof(vm_page_t), M_NVME, + M_ZERO | M_WAITOK); if (is_read) prot |= VM_PROT_WRITE; /* Device will write to host memory */ err = vm_fault_hold_pages(&curproc->p_vmspace->vm_map, - addr, len, prot, upages, max_pages, npagesp); - if (err != 0) + addr, len, prot, upages_us, npages, npagesp); + if (err != 0) { + if (*upages != upages_us) + free(upages_us, M_NVME); return (err); + } *req = nvme_allocate_request_null(M_WAITOK, cb_fn, cb_arg); - (*req)->payload = memdesc_vmpages(upages, len, addr & PAGE_MASK); + (*req)->payload = memdesc_vmpages(upages_us, len, addr & PAGE_MASK); (*req)->payload_valid = true; + if (*upages != upages_us) + *upages = upages_us; return (0); } static void -nvme_user_ioctl_free(vm_page_t *pages, int npage) +nvme_user_ioctl_free(vm_page_t *pages, int npage, bool freeit) { vm_page_unhold_pages(pages, npage); + if (freeit) + free(pages, M_NVME); } static void @@ -1400,7 +1422,8 @@ nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctrlr, struct mtx *mtx; int ret = 0; int npages = 0; - vm_page_t upages[NVME_MAX_PAGES]; + vm_page_t upages_small[NVME_MAX_PAGES]; + vm_page_t *upages = upages_small; if (pt->len > 0) { if (pt->len > ctrlr->max_xfer_size) { @@ -1411,7 +1434,7 @@ nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctrlr, } if (is_user) { ret = nvme_user_ioctl_req((vm_offset_t)pt->buf, pt->len, - pt->is_read, upages, nitems(upages), &npages, &req, + pt->is_read, &upages, nitems(upages_small), &npages, &req, nvme_pt_done, pt); if (ret != 0) return (ret); @@ -1449,7 +1472,7 @@ nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctrlr, mtx_unlock(mtx); if (npages > 0) - nvme_user_ioctl_free(upages, npages); + nvme_user_ioctl_free(upages, npages, upages != upages_small); return (ret); } @@ -1477,7 +1500,8 @@ nvme_ctrlr_linux_passthru_cmd(struct nvme_controller *ctrlr, struct mtx *mtx; int ret = 0; int npages = 0; - vm_page_t upages[NVME_MAX_PAGES]; + vm_page_t upages_small[NVME_MAX_PAGES]; + vm_page_t *upages = upages_small; /* * We don't support metadata. @@ -1494,7 +1518,7 @@ nvme_ctrlr_linux_passthru_cmd(struct nvme_controller *ctrlr, } if (is_user) { ret = nvme_user_ioctl_req(npc->addr, npc->data_len, - npc->opcode & 0x1, upages, nitems(upages), &npages, + npc->opcode & 0x1, &upages, nitems(upages), &npages, &req, nvme_npc_done, npc); if (ret != 0) return (ret); @@ -1533,7 +1557,7 @@ nvme_ctrlr_linux_passthru_cmd(struct nvme_controller *ctrlr, mtx_unlock(mtx); if (npages > 0) - nvme_user_ioctl_free(upages, npages); + nvme_user_ioctl_free(upages, npages, upages != upages_small); return (ret); }