From nobody Mon Oct 19 06:24:41 2026 X-Original-To: dev-commits-src-main@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 4j7QWG29k7z6vsJg for ; Mon, 19 Oct 2026 06:24:42 +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) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 4j7QWG0DH1z3PmW for ; Mon, 19 Oct 2026 06:24:42 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1792391082; 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=CriQceWPJhHXXAgU4mSO2cFQmucfbnLBPBs+q6XjBGE=; b=FXhJrd11Y5s+rdsCKeWtR1eURvxslCX/oM88zf1pzoclPaQiysm2iuQkYD257Mfa563MM9 w/rxUOhdY5EYUfXz7cDUnLoOZhyOicTucd4aPCHAWqUZA0lfyEHXRsvMfwUWBIKKT03z3x zSTFBbmSOfU4xA8RhpxH4pl3hSqkD4XOs5RyNYnyvTK6/KLiEFUQlmPZC6vw4zf3F0Cwcp akoVJOcKPLxpqbzAEHZK89gby+LFo8sXmtQFbj7V9ojRvlU0/CpRfk5jktM6FeEp+qJWQp VP0DhnuegIlGw/kLU4gnKaL+cOhQbPBXc7b0FbDXO+lKqKcmJu8umRrgR16mXw== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1792391082; b=O5w8+ilY5NXsTTbmJoDHQyZuzFzfINPU81GD2r3+GV7vRQx55im1JF9rQg36jvGl8DSPMV jzr5lUIATlGGjE7qY+FGW2SeyIH89kc2JKv58gv1WKX01xxXIc+GZ1cc9dogxA+/QVtsy9 118lcwiNFGXV2JbD5SknkaymzoUo0+IGF2hcTQkivk54qqZHnX+aN4MInkBq6IQefwcQN9 LO+hBrz2e7nsw+N+OpwBclzrfXCrxUYenGriK0Bwj2ecKAn2HepPDwGhr03AQwIHj3g7lB CibLhCzha8HN7cQOCleB81OMyMvNYzZj4jNyo/29CA1qCgClh1nQBtqv07za2Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1792391082; 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=CriQceWPJhHXXAgU4mSO2cFQmucfbnLBPBs+q6XjBGE=; b=PfbupjAaW+4dUBT9JhU5vXlgOSJeGJ4QrpLXNVYnxUe21AZn6iwR2Ox1HsLJsgIAINhqvU YGkjtKS36fmvUk8CFDTsOFBR1KQ2NoNEMjpr4cOb9olkWeGufmgTYLZS/bPVsBwBpR0vTo O8OwFxwpkrRBkkASanpJOnCg0oHWQ9rPDh4ryubXBeRsQN6eyXutq0HPcNB9wRe59O12Z7 Hk4INIEv+UOfk9DQDydPOhH96CVnPD5q8DIuuxJwB3A2csCLTkDEpnakcm4lEDMHX0mjL9 I0lyQLtSjpYo4Ilo25CHopEujH/659xNbEy9uS5pRdDnLoM3XH2n4Npvfzv2nQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4j7QWF69TXz1Nkl for ; Mon, 19 Oct 2026 06:24:41 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3296d by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 19 Oct 2026 06:24:41 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Warner Losh Subject: git: b991e2dd824c - main - nvmecontrol: support controller-wide sector sizes List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: Commit messages for the main branch of the src repository List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list 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: b991e2dd824cc6a120a346a183837875ff75b66d Auto-Submitted: auto-generated Date: Mon, 19 Oct 2026 06:24:41 +0000 Message-Id: <6ad5b7a9.3296d.7a6b8add@gitrepo.freebsd.org> The branch main has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=b991e2dd824cc6a120a346a183837875ff75b66d commit b991e2dd824cc6a120a346a183837875ff75b66d Author: Warner Losh AuthorDate: 2026-10-19 04:42:43 +0000 Commit: Warner Losh CommitDate: 2026-10-19 06:22:51 +0000 nvmecontrol: support controller-wide sector sizes Extend sector-size selection to controller-wide formats when every namespace has one compatible format index and matching effective metadata and protection settings. Reject ambiguous or inconsistent layouts so heterogeneous fleets can request a sector size without risking an unintended controller-wide format. Reviewed by: seuros, chuck Differential Revision: https://reviews.freebsd.org/D59834 --- sbin/nvmecontrol/format.c | 126 +++++++++++++++++++++++++++++++++-------- sbin/nvmecontrol/nvmecontrol.8 | 14 ++++- 2 files changed, 113 insertions(+), 27 deletions(-) diff --git a/sbin/nvmecontrol/format.c b/sbin/nvmecontrol/format.c index 53f2f0a1bb0a..ee0ecc34aeaa 100644 --- a/sbin/nvmecontrol/format.c +++ b/sbin/nvmecontrol/format.c @@ -112,18 +112,85 @@ CMD_COMMAND(format_cmd); /* End of tables for command line parsing */ +static int +find_lbaf(const struct nvme_namespace_data *nsd, uint32_t sector_size, + bool require_unique) +{ + uint32_t format; + int best, best_rp, i, lbads, matches, rp; + + lbads = fls(sector_size) - 1; + best = -1; + best_rp = 4; + matches = 0; + for (i = 0; i <= nsd->nlbaf; i++) { + format = nsd->lbaf[i]; + if (NVMEV(NVME_NS_DATA_LBAF_LBADS, format) != lbads || + NVMEV(NVME_NS_DATA_LBAF_MS, format) != + sector_size % (1U << lbads)) + continue; + matches++; + rp = NVMEV(NVME_NS_DATA_LBAF_RP, format); + if (rp < best_rp) { + best = i; + best_rp = rp; + } + } + if (require_unique && matches > 1) + return (-2); + return (best); +} + +static void +check_controller_namespace(int fd, uint32_t nsid, uint32_t sector_size, + int *lbaf, int *ms, int *pi, int *pil, bool *found) +{ + struct nvme_namespace_data nsd; + int fmt, ns_ms, ns_pi, ns_pil; + + if (read_namespace_data(fd, nsid, &nsd)) + errx(EX_IOERR, "Identify request failed for namespace %u", nsid); + fmt = find_lbaf(&nsd, sector_size, true); + if (fmt == -2) + errx(EX_USAGE, + "namespace %u has multiple formats for sector size %u", + nsid, sector_size); + if (fmt < 0) + errx(EX_USAGE, "namespace %u does not support sector size %u", + nsid, sector_size); + ns_ms = opt.ms == NONE ? + NVMEV(NVME_NS_DATA_FLBAS_EXTENDED, nsd.flbas) : opt.ms; + ns_pi = opt.pi == NONE ? + NVMEV(NVME_NS_DATA_DPS_MD_START, nsd.dps) : opt.pi; + ns_pil = opt.pil == NONE ? + NVMEV(NVME_NS_DATA_DPS_PIT, nsd.dps) : opt.pil; + if (!*found) { + *lbaf = fmt; + *ms = ns_ms; + *pi = ns_pi; + *pil = ns_pil; + *found = true; + } else if (*lbaf != fmt || *ms != ns_ms || *pi != ns_pi || + *pil != ns_pil) { + errx(EX_USAGE, + "namespace %u has incompatible format parameters", nsid); + } +} + static void format(const struct cmd *f, int argc, char *argv[]) { struct nvme_controller_data cd; struct nvme_namespace_data nsd; + struct nvme_ns_list nslist; struct nvme_pt_command pt; char *path; const char *target; - uint32_t nsid; + uint32_t nsid, scan_nsid; int lbaf, ms, pi, pil, ses, fd; - int best_rp, i, lbads; + u_int i; uint32_t sector_size; + bool done, found; if (arg_parse(argc, argv, f)) return; @@ -141,6 +208,8 @@ format(const struct cmd *f, int argc, char *argv[]) fprintf(stderr, "Only one of -f or -s may be specified\n"); arg_help(argc, argv, f); } + if (sector_size == 0) + errx(EX_USAGE, "sector size must be non-zero"); ms = opt.ms; pi = opt.pi; pil = opt.pil; @@ -166,8 +235,6 @@ format(const struct cmd *f, int argc, char *argv[]) open_dev(path, &fd, 1, 1); } free(path); - if (sector_size != NONE && nsid == NVME_GLOBAL_NAMESPACE_TAG) - errx(EX_USAGE, "sector size requires a namespace target"); /* Check that controller can execute this command. */ if (read_controller_data(fd, &cd)) @@ -190,26 +257,7 @@ format(const struct cmd *f, int argc, char *argv[]) if (read_namespace_data(fd, nsid, &nsd)) errx(EX_IOERR, "Identify request failed"); if (sector_size != NONE) { - if (sector_size == 0) - errx(EX_USAGE, "sector size must be non-zero"); - lbads = fls(sector_size) - 1; - lbaf = -1; - best_rp = 4; - for (i = 0; i <= nsd.nlbaf; i++) { - uint32_t format; - int rp; - - format = nsd.lbaf[i]; - if (NVMEV(NVME_NS_DATA_LBAF_LBADS, format) != lbads || - NVMEV(NVME_NS_DATA_LBAF_MS, format) != - sector_size % (1U << lbads)) - continue; - rp = NVMEV(NVME_NS_DATA_LBAF_RP, format); - if (rp < best_rp) { - lbaf = i; - best_rp = rp; - } - } + lbaf = find_lbaf(&nsd, sector_size, false); if (lbaf < 0) errx(EX_USAGE, "namespace does not support sector size %u", @@ -228,6 +276,36 @@ format(const struct cmd *f, int argc, char *argv[]) } else { /* We have no previous parameters, so default to zeroes. */ + if (sector_size != NONE) { + found = false; + if (cd.ver == 0) { + for (scan_nsid = 1; scan_nsid <= cd.nn; scan_nsid++) + check_controller_namespace(fd, scan_nsid, + sector_size, &lbaf, &ms, &pi, &pil, + &found); + } else { + scan_nsid = 0; + done = false; + while (!done) { + if (read_active_namespaces(fd, scan_nsid, + &nslist)) + errx(EX_IOERR, + "Identify request failed"); + for (i = 0; i < nitems(nslist.ns); i++) { + scan_nsid = nslist.ns[i]; + if (scan_nsid == 0) { + done = true; + break; + } + check_controller_namespace(fd, scan_nsid, + sector_size, &lbaf, &ms, &pi, &pil, + &found); + } + } + } + if (!found) + errx(EX_USAGE, "controller has no active namespaces"); + } if (lbaf < 0) lbaf = 0; if (ms < 0) diff --git a/sbin/nvmecontrol/nvmecontrol.8 b/sbin/nvmecontrol/nvmecontrol.8 index c80dac444774..793016652e73 100644 --- a/sbin/nvmecontrol/nvmecontrol.8 +++ b/sbin/nvmecontrol/nvmecontrol.8 @@ -517,10 +517,18 @@ Select the LBA format matching the specified total sector size. The data size is the largest power of two not greater than .Ar sector-size , and any remainder is the metadata size. -If multiple LBA formats match, the one with the best relative performance is +When formatting a namespace, the format with the best relative performance is selected, with the lowest format index used to break ties. -This option may only be used when formatting a namespace and is mutually -exclusive with +When formatting a controller, every active namespace must have exactly one +matching format, and that format must have the same index in every namespace. +The effective +.Ar mset , +.Ar pi , +and +.Ar pil +values must also match across all active namespaces. +Otherwise, the operation is rejected. +This option is mutually exclusive with .Fl f . .It Fl m Ar mset Metadata Setting.