Index: lib/libbe/be.c =================================================================== --- lib/libbe/be.c +++ lib/libbe/be.c @@ -104,6 +104,32 @@ return (0); } +/* Validate a root filesystem by verifying that every child dataset + * is has a mountpoint of '/' (minus altroot) or 'none'. + */ +static int +be_validate_rootfs_cb(zfs_handle_t *zfs_hdl, void *data) +{ + libbe_handle_t *lbh; + char *mountpoint; + char zfs_mnt[BE_MAXPATHLEN]; + + lbh = (libbe_handle_t *)data; + + if(zfs_prop_get(zfs_hdl, ZFS_PROP_MOUNTPOINT, zfs_mnt, BE_MAXPATHLEN, NULL, + NULL, 0, 1)) + return (1); + + if (strcmp("none", zfs_mnt) == 0) + return (0); + + mountpoint = zfs_mnt + lbh->altroot_len; + if (strcmp("/", mountpoint) == 0 || strcmp("", mountpoint) == 0) + return (0); + + return (1); +} + /* * Initializes the libbe context to operate in the root boot environment * dataset, for example, zroot/ROOT. @@ -113,11 +139,13 @@ { char altroot[MAXPATHLEN]; libbe_handle_t *lbh; + zfs_handle_t *zhdl; char *poolname, *pos; int pnamelen; lbh = NULL; poolname = pos = NULL; + zhdl = NULL; if ((lbh = calloc(1, sizeof(libbe_handle_t))) == NULL) goto err; @@ -144,19 +172,21 @@ } else strlcpy(lbh->root, root, sizeof(lbh->root)); - if ((pos = strchr(lbh->root, '/')) == NULL) - goto err; - - pnamelen = pos - lbh->root; - poolname = malloc(pnamelen + 1); - if (poolname == NULL) - goto err; + if ((pos = strchr(lbh->root, '/')) == NULL) { + if(root == NULL || (lbh->active_phandle = zpool_open(lbh->lzh, lbh->root)) == NULL) + goto err; + } else { + pnamelen = pos - lbh->root; + poolname = malloc(pnamelen + 1); + if (poolname == NULL) + goto err; - strlcpy(poolname, lbh->root, pnamelen + 1); - if ((lbh->active_phandle = zpool_open(lbh->lzh, poolname)) == NULL) - goto err; - free(poolname); - poolname = NULL; + strlcpy(poolname, lbh->root, pnamelen + 1); + if ((lbh->active_phandle = zpool_open(lbh->lzh, poolname)) == NULL) + goto err; + free(poolname); + poolname = NULL; + } if (zpool_get_prop(lbh->active_phandle, ZPOOL_PROP_BOOTFS, lbh->bootfs, sizeof(lbh->bootfs), NULL, true) != 0) @@ -167,11 +197,20 @@ strcmp(altroot, "-") != 0) lbh->altroot_len = strlen(altroot); + /* Validate child filesystems, to make sure they are mountpoint '/' or 'none' */ + zhdl = zfs_open(lbh->lzh, lbh->root, ZFS_TYPE_FILESYSTEM); + if(zfs_iter_filesystems(zhdl, be_validate_rootfs_cb, lbh)) + goto err; + + zfs_close(zhdl); + return (lbh); err: if (lbh != NULL) { if (lbh->active_phandle != NULL) zpool_close(lbh->active_phandle); + if (zhdl != NULL) + zfs_close(zhdl); if (lbh->lzh != NULL) libzfs_fini(lbh->lzh); free(lbh);