Index: head/sbin/bectl/bectl.c =================================================================== --- head/sbin/bectl/bectl.c +++ head/sbin/bectl/bectl.c @@ -184,7 +184,8 @@ static int bectl_cmd_create(int argc, char *argv[]) { - char *atpos, *bootenv, *snapname, *source; + char snapshot[BE_MAXPATHLEN]; + char *atpos, *bootenv, *snapname; int err, opt; bool recursive; @@ -214,6 +215,8 @@ } bootenv = *argv; + + err = BE_ERR_SUCCESS; if ((atpos = strchr(bootenv, '@')) != NULL) { /* * This is the "create a snapshot variant". No new boot @@ -221,24 +224,22 @@ */ *atpos++ = '\0'; err = be_snapshot(be, bootenv, atpos, recursive, NULL); - } else if (snapname != NULL) { - if (strchr(snapname, '@') != NULL) - err = be_create_from_existing_snap(be, bootenv, - snapname); - else - err = be_create_from_existing(be, bootenv, snapname); } else { - if ((snapname = strchr(bootenv, '@')) != NULL) { - *(snapname++) = '\0'; - if ((err = be_snapshot(be, be_active_path(be), - snapname, true, NULL)) != BE_ERR_SUCCESS) - fprintf(stderr, "failed to create snapshot\n"); - asprintf(&source, "%s@%s", be_active_path(be), snapname); - err = be_create_from_existing_snap(be, bootenv, - source); - return (err); - } else - err = be_create(be, bootenv); + if (snapname == NULL) + /* Create from currently booted BE */ + err = be_snapshot(be, be_active_path(be), NULL, + recursive, snapshot); + else if (strchr(snapname, '@') != NULL) + /* Create from given snapshot */ + strlcpy(snapshot, snapname, sizeof(snapshot)); + else + /* Create from given BE */ + err = be_snapshot(be, snapname, NULL, recursive, + snapshot); + + if (err == BE_ERR_SUCCESS) + err = be_create_depth(be, bootenv, snapshot, + recursive == true ? -1 : 0); } switch (err) { Index: head/sbin/bectl/tests/bectl_test.sh =================================================================== --- head/sbin/bectl/tests/bectl_test.sh +++ head/sbin/bectl/tests/bectl_test.sh @@ -99,11 +99,35 @@ mount=${cwd}/mnt bectl_create_setup ${zpool} ${disk} ${mount} + + # Create a child dataset that will be used to test creation + # of recursive and non-recursive boot environments. + atf_check zfs create -o mountpoint=/usr -o canmount=noauto \ + ${zpool}/ROOT/default/usr + # Test standard creation, creation of a snapshot, and creation from a # snapshot. atf_check bectl -r ${zpool}/ROOT create -e default default2 atf_check bectl -r ${zpool}/ROOT create default2@test_snap atf_check bectl -r ${zpool}/ROOT create -e default2@test_snap default3 + + # Test standard creation, creation of a snapshot, and creation from a + # snapshot for recursive boot environments. + atf_check bectl -r ${zpool}/ROOT create -r -e default recursive + atf_check bectl -r ${zpool}/ROOT create -r recursive@test_snap + atf_check bectl -r ${zpool}/ROOT create -r -e recursive@test_snap recursive-snap + + # Test that non-recursive boot environments have no child datasets. + atf_check -e not-empty -s not-exit:0 \ + zfs list "${zpool}/ROOT/default2/usr" + atf_check -e not-empty -s not-exit:0 \ + zfs list "${zpool}/ROOT/default3/usr" + + # Test that recursive boot environments have child datasets. + atf_check -o not-empty \ + zfs list "${zpool}/ROOT/recursive/usr" + atf_check -o not-empty \ + zfs list "${zpool}/ROOT/recursive-snap/usr" } bectl_create_cleanup() {