From nobody Fri Dec 02 18:38:19 2022 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 4NP1sm1Xqpz4hvPD; Fri, 2 Dec 2022 18:38:20 +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 4NP1sm10lGz44DJ; Fri, 2 Dec 2022 18:38:20 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1670006300; 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=6p2Kh1j11c11dtfDTNwlBRYSqVURWdDDfB0qOdG+Cao=; b=ot0Z5dAEvUBjlQNx7bPbH0oMGOX0pZpeK0EurmS6M8VX+2uzoRuBlukGT1k+mXp259nTdC 1IeZursyxg8QIOG4xh4gIZw2L+lI0ovHks+OWKTHTpBuKCc61N6VUyV2rCJkSHge5GB10N d0rrb7/dBlo6nQkaYiujU6fquKGnfBpIkaUYo0UV7uVf/j6FC5ClyhfOueqpNxYuZPTkxz XBL+BQYk9X40CG4ljyJHkc5sOUVayqUoxDbp4TOj8mMT3BqCV6h0ZLk8uaDVCxpuagVLGt mjTkyph2FG4uawEZzMXW55B9c1/2KtNDFODEA50JG0kXmv/N45jj777THheyfA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1670006300; 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=6p2Kh1j11c11dtfDTNwlBRYSqVURWdDDfB0qOdG+Cao=; b=GBAepMCocBunHWv5Nq6In1BuO523IzdKcDHJpE7xGugLi6y4VKAUDkiFujWTDsB5l8Uadd Bx2ZD+df3pIENTsWOSciZTyOMM6zPymLdngomjapdwi3JPPknM+4pDxyvGgq4NJFncUJ0v w0ZkcFEE+bTcPFF9fKw2rQrWkrEaeIQKh+H34203h8mA6y8aP9mROtgUQkXoVTDDPn2D7r HSXZenRLB4xJWbY/YFfvYRu/Ewu6UsvEFdA8xOrQVDhIwBmOXVoC4WiyrJ2mng4h1j5ayP Za0kgCIvJLebTqfVmxdNffubcGKMzBVGncCbDW7NB1MgecXrQgHhdYjPDsx4bg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1670006300; a=rsa-sha256; cv=none; b=Am32kgA0Nc03itXIEG2q0xNHMgf0sR20S9L9pkq7G+3SFcDow5svGgAte1BU2/ckjedAGQ dYWq8CTRCXttbSoPON7mlafVCmIj7lmlUTDFLE9wZTXJjvq4vDgjzEOiSu9vZpJU644913 hN0nT6AeKCzE6EeofBlba/KoSpW1qyYVl3mqlnxs3lcis/oEr0UaWOChtt35Dz4pkbdwzG N/0iXlRRC4VKRhPNNtfyqR2Mt0CD+tdhMdROaqv/Y7oPIpyQcscqdFQBHW1j8MoWEt4u0r 1MveiejW/dD3EQjdqRYPjWn+g0we26uYPi+GM+TMWD5oeNqSq1tqCpzoep7M2w== 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 4NP1sl6xGxzQQ8; Fri, 2 Dec 2022 18:38:19 +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 2B2IcJH5077421; Fri, 2 Dec 2022 18:38:19 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 2B2IcJYT077420; Fri, 2 Dec 2022 18:38:19 GMT (envelope-from git) Date: Fri, 2 Dec 2022 18:38:19 GMT Message-Id: <202212021838.2B2IcJYT077420@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Warner Losh Subject: git: 7685e8d97a22 - main - kboot: Enhance hostdisk List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@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: 7685e8d97a22ae4b58243d6ef67569ea5bcbc988 Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=7685e8d97a22ae4b58243d6ef67569ea5bcbc988 commit 7685e8d97a22ae4b58243d6ef67569ea5bcbc988 Author: Warner Losh AuthorDate: 2022-12-02 18:28:08 +0000 Commit: Warner Losh CommitDate: 2022-12-02 18:31:26 +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 --- 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 *