From 4ab5187d38a9eb708cbf41296decf933a52fb378 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Mon, 19 Nov 2018 16:47:21 +0000 Subject: [PATCH] libbe(3): Handle non-ZFS rootfs better If rootfs isn't ZFS, current version will emit an error claiming so and fail to initialize libbe. As a consumer, bectl -r (undocumented) can be specified to operate on a BE independently of whether on a UFS or ZFS root. Unbreak this for the UFS case by only erroring out the init if we can't determine a ZFS dataset for rootfs and no BE root was specified. Consumers of libbe should take care to ensure that rootfs is non-empty if they're trying to use it, because this could certainly be the case. Some check is needed before zfs_path_to_zhandle because it will unconditionally emit to stderr if the path isn't a ZFS filesystem, which is unhelpful for our purposes. This should also unbreak the bectl(8) tests on a UFS root, as is the case in Jenkins' -test runs. MFC after: 3 days --- lib/libbe/be.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/libbe/be.c b/lib/libbe/be.c index d084702bedce..be073eed9a8e 100644 --- a/lib/libbe/be.c +++ b/lib/libbe/be.c @@ -58,8 +58,22 @@ static int be_create_child_cloned(libbe_handle_t *lbh, const char *active); static int be_locate_rootfs(libbe_handle_t *lbh) { + struct statfs sfs; + struct extmnttab entry; zfs_handle_t *zfs; + /* + * Check first if root is ZFS; if not, we'll bail on rootfs capture. + * Unfortunately needed because zfs_path_to_zhandle will emit to + * stderr if / isn't actually a ZFS filesystem, which we'd like + * to avoid. + */ + if (statfs("/", &sfs) == 0) { + statfs2mnttab(&sfs, &entry); + if (strcmp(entry.mnt_fstype, MNTTYPE_ZFS) != 0) + return (1); + } else + return (1); zfs = zfs_path_to_zhandle(lbh->lzh, "/", ZFS_TYPE_FILESYSTEM); if (zfs == NULL) return (1); @@ -93,8 +107,11 @@ libbe_init(const char *root) * Grab rootfs, we'll work backwards from there if an optional BE root * has not been passed in. */ - if (be_locate_rootfs(lbh) != 0) - goto err; + if (be_locate_rootfs(lbh) != 0) { + if (root == NULL) + goto err; + *lbh->rootfs = '\0'; + } if (root == NULL) { /* Strip off the final slash from rootfs to get the be root */ strlcpy(lbh->root, lbh->rootfs, sizeof(lbh->root));