libbe: recursively promote deep BE datasets

beadm will recursively promote deep BE datasets. In order to match the
beadm behavior, we need to recursively iterate over child filesystems
and promote them along the way.

This patch further refines the work from D40903, completing the fix for
promotion.

Reviewed by:	kevans, rew
Sponsored by:	Rubicon Communications, LLC ("Netgate")
Differential Revision:	https://reviews.freebsd.org/D40972
This commit is contained in:
R. Christian McDonald
2023-07-17 14:06:28 -05:00
committed by Kyle Evans
parent 89f361f742
commit 4b426cf3a4
2 changed files with 36 additions and 16 deletions
+31 -9
View File
@@ -1266,12 +1266,38 @@ be_deactivate(libbe_handle_t *lbh, const char *ds, bool temporary)
return (0); return (0);
} }
static int
be_zfs_promote_cb(zfs_handle_t *zhp, void *data)
{
char origin[BE_MAXPATHLEN];
bool *found_origin = (bool *)data;
int err;
if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof(origin),
NULL, NULL, 0, true) == 0) {
*found_origin = true;
err = zfs_promote(zhp);
if (err)
return (err);
}
return (zfs_iter_filesystems(zhp, be_zfs_promote_cb, data));
}
static int
be_zfs_promote(zfs_handle_t *zhp, bool *found_origin)
{
*found_origin = false;
return (be_zfs_promote_cb(zhp, (void *)found_origin));
}
int int
be_activate(libbe_handle_t *lbh, const char *bootenv, bool temporary) be_activate(libbe_handle_t *lbh, const char *bootenv, bool temporary)
{ {
char be_path[BE_MAXPATHLEN], origin[BE_MAXPATHLEN]; char be_path[BE_MAXPATHLEN];
zfs_handle_t *zhp; zfs_handle_t *zhp;
int err; int err;
bool found_origin;
be_root_concat(lbh, bootenv, be_path); be_root_concat(lbh, bootenv, be_path);
@@ -1297,19 +1323,15 @@ be_activate(libbe_handle_t *lbh, const char *bootenv, bool temporary)
if (zhp == NULL) if (zhp == NULL)
return (-1); return (-1);
if (zfs_prop_get(zhp, ZFS_PROP_ORIGIN, origin, sizeof(origin), err = be_zfs_promote(zhp, &found_origin);
NULL, NULL, 0, 1) != 0) {
zfs_close(zhp);
break;
}
err = zfs_promote(zhp);
zfs_close(zhp); zfs_close(zhp);
if (!found_origin)
break;
if (err) if (err)
break; return (err);
} }
if (err) if (err)
return (-1); return (-1);
} }
+5 -7
View File
@@ -528,7 +528,6 @@ bectl_jail_cleanup()
atf_test_case bectl_promotion cleanup atf_test_case bectl_promotion cleanup
bectl_promotion_head() bectl_promotion_head()
{ {
atf_set "descr" "Check bectl promotion upon activation" atf_set "descr" "Check bectl promotion upon activation"
atf_set "require.user" root atf_set "require.user" root
} }
@@ -550,7 +549,7 @@ bectl_promotion_body()
mount=${cwd}/mnt mount=${cwd}/mnt
root=${mount}/root root=${mount}/root
bectl_create_setup ${zpool} ${disk} ${mount} bectl_create_deep_setup ${zpool} ${disk} ${mount}
atf_check mkdir -p ${root} atf_check mkdir -p ${root}
# Sleeps interspersed to workaround some naming quirks; notably, # Sleeps interspersed to workaround some naming quirks; notably,
@@ -560,23 +559,22 @@ bectl_promotion_body()
# with the same name, and the promotion will fail. # with the same name, and the promotion will fail.
atf_check bectl -r ${zpool}/ROOT rename default A atf_check bectl -r ${zpool}/ROOT rename default A
sleep 1 sleep 1
atf_check bectl -r ${zpool}/ROOT create -e A B atf_check bectl -r ${zpool}/ROOT create -r -e A B
sleep 1 sleep 1
atf_check bectl -r ${zpool}/ROOT create -e B C atf_check bectl -r ${zpool}/ROOT create -r -e B C
# C should be a clone of B to start with # C should be a clone of B to start with
atf_check -o not-inline:"-" zfs list -H -o origin ${zpool}/ROOT/C atf_check -o not-inline:"-" zfs list -Hr -o origin ${zpool}/ROOT/C
# Activating it should then promote it all the way out of clone-hood. # Activating it should then promote it all the way out of clone-hood.
# This entails two promotes internally, as the first would promote it to # This entails two promotes internally, as the first would promote it to
# a snapshot of A before finally promoting it the second time out of # a snapshot of A before finally promoting it the second time out of
# clone status. # clone status.
atf_check -o not-empty bectl -r ${zpool}/ROOT activate C atf_check -o not-empty bectl -r ${zpool}/ROOT activate C
atf_check -o inline:"-\n" zfs list -H -o origin ${zpool}/ROOT/C atf_check -o inline:"-\n-\n" zfs list -Hr -o origin ${zpool}/ROOT/C
} }
bectl_promotion_cleanup() bectl_promotion_cleanup()
{ {
bectl_cleanup $(get_zpool_name) bectl_cleanup $(get_zpool_name)
} }