From nobody Tue Jan 24 22:13:36 2023 X-Original-To: dev-commits-src-branches@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 4P1h7j4x8yz3bgDc; Tue, 24 Jan 2023 22:13:37 +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 "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4P1h7j1ts2z3HQx; Tue, 24 Jan 2023 22:13:37 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1674598417; 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=FFuZJayBp3ibYwae2w5XpLHM2JC+5GKqOBwUAwcRSxQ=; b=TTbOW5420POo5lG5xeME0Yy8eJ1ihMsDtZNrnzRsnmP+QW1IrmQiqKPO3jF/GydlDf9/Q1 AqDk4VcxpLfCTshaGgJXQbXu5T4sDIaBbuUBnXK+Xga88bSfW+UQiKZiRC7DzDw71UWfbX 1BUgphDvxi2XFuivBfa92e5fkVdkWSGW4pTzMlPwnOUxGKfzmkgKLjTC+a2BsjKBIX6wj4 /cN0kYk5HQgTCWZj5Bgb1vF12X6FQDFDIcWUGqqhpFTGyRKT3XEgBwSkx5e9FT6qcN1mv8 1EHtthNBesxpsDQ+ejrgG9fTXwOz1hKUKffkp8fdSokSxubSBO3O4SnXvZOi4A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1674598417; 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=FFuZJayBp3ibYwae2w5XpLHM2JC+5GKqOBwUAwcRSxQ=; b=M49XDZ+vt3c++lHpGijB5cVFoMObWiCUUdbjSW/t3iSL3nwVvkCcaVCgtIpKHL+5VbC9Kw nyJPZNlx5dytnH+4jRIqp0Mt2/RnXSHjNtOMD1l06J68R1GDhI5TTIELmscz0gTyqxVbDQ OFgIFENsqdZRkvnlTbsj5mcVk6k5fTJKqgmFGew/tthcgJ77+MN2clNBzp9A4QXSL6DOrR 41HS+XRdEs1l8E+xmCRAKYGSHCX+7r1Ksb8MZNl29ggrfAHhgMt2LLok0SVsyaJJnT3t8q 10I6dSViC3C00Yl8V4SI2JIz5udNYITzQhKKk5FW7uLa/coiW9AfUm7lkefYKw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1674598417; a=rsa-sha256; cv=none; b=yKpu7Ugqu2/czK43BYaIuFOhga8mIN+POZjSQhQA/faIFzjfrYnQBSLU+6yR+0BKSO90tv 1gjqG2dyXXpPgX9S3FlHXdP9i0AKlDBqabi+8xfQts9hIyQ4LRSg5SH6QmqOlZTehoP58V IP1PaYIQmA0KMa+3fwwtrcNHetaLsnQKmGPrRME7/JqhVVGBWvw0TnZJ51GVvFUom40EZH Ojx/CnUdLfqznqRv8W8B2YLHJxReV45n1qD/J1KVrNv+trz2BQANJ5c3bhEYPv7HKPKStg foTZKUEIl8h3tG2OFeEktQ0MbPpMU1DzF7Kc8eNXISC21GGIOM+WzqBhD1ORqQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (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 did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4P1h7j0hnVzQYt; Tue, 24 Jan 2023 22:13:37 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 30OMDb8C088670; Tue, 24 Jan 2023 22:13:37 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 30OMDaG9088669; Tue, 24 Jan 2023 22:13:36 GMT (envelope-from git) Date: Tue, 24 Jan 2023 22:13:36 GMT Message-Id: <202301242213.30OMDaG9088669@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Warner Losh Subject: git: 0e78599a5b58 - stable/13 - kboot: Enhance hostdisk List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-branches@freebsd.org X-BeenThere: dev-commits-src-branches@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/stable/13 X-Git-Reftype: branch X-Git-Commit: 0e78599a5b58684eae89f7bfb24da599c2ad8ec1 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch stable/13 has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=0e78599a5b58684eae89f7bfb24da599c2ad8ec1 commit 0e78599a5b58684eae89f7bfb24da599c2ad8ec1 Author: Warner Losh AuthorDate: 2022-12-02 18:28:08 +0000 Commit: Warner Losh CommitDate: 2023-01-24 21:49:41 +0000 kboot: Enhance hostdisk Added missing functionality to allow us to boot off of things like /dev/nvme0n1p2 successfully. And to list all available devices and partitions with 'lsdev'. Sponsored by: Netflix (cherry picked from commit 7685e8d97a22ae4b58243d6ef67569ea5bcbc988) --- stand/kboot/hostdisk.c | 192 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 185 insertions(+), 7 deletions(-) diff --git a/stand/kboot/hostdisk.c b/stand/kboot/hostdisk.c index 852785497989..d83161f5bfee 100644 --- a/stand/kboot/hostdisk.c +++ b/stand/kboot/hostdisk.c @@ -53,9 +53,163 @@ struct devsw hostdisk = { .dv_fmtdev = hostdisk_fmtdev, }; +/* + * We need to walk through the /sys/block directories looking for + * block devices that we can use. + */ +#define SYSBLK "/sys/block" + +typedef STAILQ_HEAD(, hdinfo) hdinfo_list_t; +typedef struct hdinfo { + STAILQ_ENTRY(hdinfo) hd_link; /* link in device list */ + hdinfo_list_t hd_children; + struct hdinfo *hd_parent; + const char *hd_name; + uint64_t hd_size; + uint64_t hd_sectors; + uint64_t hd_sectorsize; + int hd_flags; +} hdinfo_t; + +static hdinfo_list_t hdinfo = STAILQ_HEAD_INITIALIZER(hdinfo); + +typedef bool fef_cb_t(struct host_dirent64 *, void *); +#define FEF_RECURSIVE 1 + +static bool +foreach_file(const char *dir, fef_cb_t cb, void *argp, u_int flags) +{ + char dents[2048]; + int fd, dentsize; + struct host_dirent64 *dent; + + fd = host_open(dir, O_RDONLY, 0); + if (fd < 0) { + printf("Can't open %s\n", dir);/* XXX */ + return (false); + } + while (1) { + dentsize = host_getdents64(fd, dents, sizeof(dents)); + if (dentsize <= 0) + break; + for (dent = (struct host_dirent64 *)dents; + (char *)dent < dents + dentsize; + dent = (struct host_dirent64 *)((void *)dent + dent->d_reclen)) { + if (!cb(dent, argp)) + break; + } + } + host_close(fd); + return (true); +} + +static void +hostdisk_add_part(struct hdinfo *hd, const char *drv, uint64_t secs) +{ + struct hdinfo *md; + + printf("hd %s adding %s %ju\n", hd->hd_name, drv, (uintmax_t)secs); + if ((md = calloc(1, sizeof(*md))) == NULL) + return; + md->hd_name = strdup(drv); + md->hd_sectors = secs; + md->hd_sectorsize = hd->hd_sectorsize; + md->hd_size = md->hd_sectors * md->hd_sectorsize; + md->hd_parent = hd; + STAILQ_INSERT_TAIL(&hd->hd_children, md, hd_link); +} + +static bool +hostdisk_one_part(struct host_dirent64 *dent, void *argp) +{ + struct hdinfo *hd = argp; + char szfn[1024]; + uint64_t sz; + + if (strncmp(dent->d_name, hd->hd_name, strlen(hd->hd_name)) != 0) + return (true); + /* Find out how big this is -- no size not a disk */ + snprintf(szfn, sizeof(szfn), "%s/%s/%s/size", SYSBLK, + hd->hd_name, dent->d_name); + if (!file2u64(szfn, &sz)) + return true; + hostdisk_add_part(hd, dent->d_name, sz); + return true; +} + +static void +hostdisk_add_parts(struct hdinfo *hd) +{ + char fn[1024]; + + snprintf(fn, sizeof(fn), "%s/%s", SYSBLK, hd->hd_name); + foreach_file(fn, hostdisk_one_part, hd, 0); +} + +static void +hostdisk_add_drive(const char *drv, uint64_t secs) +{ + struct hdinfo *hd; + char fn[1024]; + + if ((hd = calloc(1, sizeof(*hd))) == NULL) + return; + hd->hd_name = strdup(drv); + hd->hd_sectors = secs; + snprintf(fn, sizeof(fn), "%s/%s/queue/hw_sector_size", + SYSBLK, drv); + if (!file2u64(fn, &hd->hd_sectorsize)) + goto err; + hd->hd_size = hd->hd_sectors * hd->hd_sectorsize; + hd->hd_flags = 0; + STAILQ_INIT(&hd->hd_children); + printf("/dev/%s: %ju %ju %ju\n", + drv, hd->hd_size, hd->hd_sectors, hd->hd_sectorsize); + STAILQ_INSERT_TAIL(&hdinfo, hd, hd_link); + hostdisk_add_parts(hd); + return; +err: + free(hd); + return; +} + +static bool +hostdisk_one_disk(struct host_dirent64 *dent, void *argp __unused) +{ + char szfn[1024]; + uint64_t sz; + + /* + * Skip . and .. + */ + if (strcmp(dent->d_name, ".") == 0 || + strcmp(dent->d_name, "..") == 0) + return (true); + + /* Find out how big this is -- no size not a disk */ + snprintf(szfn, sizeof(szfn), "%s/%s/size", SYSBLK, + dent->d_name); + if (!file2u64(szfn, &sz)) + return (true); + hostdisk_add_drive(dent->d_name, sz); + return (true); +} + +static void +hostdisk_find_block_devices(void) +{ + /* + * Start here XXX open SYSBLK, walk through all directories, keep the + * ones that return a size and a 'block' device when we 'stat' it. Try + * to avoid partitions and only do raw devices. + */ + foreach_file(SYSBLK, hostdisk_one_disk, NULL, 0); +} + static int hostdisk_init(void) { + hostdisk_find_block_devices(); return (0); } @@ -67,15 +221,17 @@ hostdisk_strategy(void *devdata, int flag, daddr_t dblk, size_t size, struct devdesc *desc = devdata; daddr_t pos; int n; + int64_t off; uint64_t res; uint32_t posl, posh; pos = dblk * 512; - posl = pos & 0xffffffff; - posh = (pos >> 32) & 0xffffffff; - if (host_llseek(desc->d_unit, posh, posl, &res, 0) < 0) { - printf("Seek error\n"); + posl = pos & 0xffffffffu; + posh = (pos >> 32) & 0xffffffffu; + if ((off = host_llseek(desc->d_unit, posh, posl, &res, 0)) < 0) { + printf("Seek error on fd %d to %ju (dblk %ju) returns %jd\n", + desc->d_unit, (uintmax_t)pos, (uintmax_t)dblk, (intmax_t)off); return (EIO); } n = host_read(desc->d_unit, buf, size); @@ -98,7 +254,6 @@ hostdisk_open(struct open_file *f, ...) va_end(vl); desc->d_unit = host_open(desc->d_opendata, O_RDONLY, 0); - if (desc->d_unit <= 0) { printf("hostdisk_open: couldn't open %s: %d\n", (char *)desc->d_opendata, desc->d_unit); @@ -128,13 +283,36 @@ static int hostdisk_print(int verbose) { char line[80]; + hdinfo_t *hd, *md; + int ret = 0; printf("%s devices:", hostdisk.dv_name); if (pager_output("\n") != 0) return (1); - snprintf(line, sizeof(line), " /dev%d: Host disk\n", 0); - return (pager_output(line)); + STAILQ_FOREACH(hd, &hdinfo, hd_link) { + snprintf(line, sizeof(line), + " /dev/%s: %ju X %ju: %ju bytes\n", + hd->hd_name, + (uintmax_t)hd->hd_sectors, + (uintmax_t)hd->hd_sectorsize, + (uintmax_t)hd->hd_size); + if ((ret = pager_output(line)) != 0) + break; + STAILQ_FOREACH(md, &hd->hd_children, hd_link) { + snprintf(line, sizeof(line), + " /dev/%s: %ju X %ju: %ju bytes\n", + md->hd_name, + (uintmax_t)md->hd_sectors, + (uintmax_t)md->hd_sectorsize, + (uintmax_t)md->hd_size); + if ((ret = pager_output(line)) != 0) + goto done; + } + } + +done: + return (ret); } static char *