Page MenuHomeFreeBSD

D24920.id75970.diff
No OneTemporary

D24920.id75970.diff

Index: head/stand/efi/loader/main.c
===================================================================
--- head/stand/efi/loader/main.c
+++ head/stand/efi/loader/main.c
@@ -269,7 +269,7 @@
currdev.root_guid = 0;
set_currdev_devdesc((struct devdesc *)&currdev);
devname = efi_fmtdev(&currdev);
- init_zfs_bootenv(devname);
+ init_zfs_boot_options(devname);
rv = sanity_check_currdev();
if (rv) {
Index: head/stand/i386/loader/main.c
===================================================================
--- head/stand/i386/loader/main.c
+++ head/stand/i386/loader/main.c
@@ -363,7 +363,7 @@
#ifdef LOADER_ZFS_SUPPORT
if (new_currdev.dd.d_dev->dv_type == DEVT_ZFS)
- init_zfs_bootenv(zfs_fmtdev(&new_currdev));
+ init_zfs_boot_options(zfs_fmtdev(&new_currdev));
#endif
env_setenv("currdev", EV_VOLATILE, i386_fmtdev(&new_currdev),
Index: head/stand/libsa/zfs/libzfs.h
===================================================================
--- head/stand/libsa/zfs/libzfs.h
+++ head/stand/libsa/zfs/libzfs.h
@@ -123,7 +123,7 @@
int zfs_probe_dev(const char *devname, uint64_t *pool_guid);
int zfs_list(const char *name);
uint64_t ldi_get_size(void *);
-void init_zfs_bootenv(const char *currdev);
+void init_zfs_boot_options(const char *currdev);
int zfs_bootenv(const char *name);
int zfs_belist_add(const char *name, uint64_t __unused);
int zfs_set_env(void);
Index: head/stand/libsa/zfs/zfs.c
===================================================================
--- head/stand/libsa/zfs/zfs.c
+++ head/stand/libsa/zfs/zfs.c
@@ -60,7 +60,10 @@
static int zfs_stat(struct open_file *f, struct stat *sb);
static int zfs_readdir(struct open_file *f, struct dirent *d);
-static void zfs_bootenv_initial(const char *);
+static void zfs_bootenv_initial(const char *envname, spa_t *spa,
+ const char *name, const char *dsname, int checkpoint);
+static void zfs_checkpoints_initial(spa_t *spa, const char *name,
+ const char *dsname);
struct devsw zfs_dev;
@@ -1077,16 +1080,16 @@
return (buf);
}
-int
-zfs_list(const char *name)
+static int
+split_devname(const char *name, char *poolname, size_t size,
+ const char **dsnamep)
{
- static char poolname[ZFS_MAXNAMELEN];
- uint64_t objid;
- spa_t *spa;
- const char *dsname;
- int len;
- int rv;
+ const char *dsname;
+ size_t len;
+ ASSERT(name != NULL);
+ ASSERT(poolname != NULL);
+
len = strlen(name);
dsname = strchr(name, '/');
if (dsname != NULL) {
@@ -1094,9 +1097,30 @@
dsname++;
} else
dsname = "";
- memcpy(poolname, name, len);
- poolname[len] = '\0';
+ if (len + 1 > size)
+ return (EINVAL);
+
+ strlcpy(poolname, name, len + 1);
+
+ if (dsnamep != NULL)
+ *dsnamep = dsname;
+
+ return (0);
+}
+
+int
+zfs_list(const char *name)
+{
+ static char poolname[ZFS_MAXNAMELEN];
+ uint64_t objid;
+ spa_t *spa;
+ const char *dsname;
+ int rv;
+
+ if (split_devname(name, poolname, sizeof(poolname), &dsname) != 0)
+ return (EINVAL);
+
spa = spa_find_by_name(poolname);
if (!spa)
return (ENXIO);
@@ -1108,10 +1132,13 @@
}
void
-init_zfs_bootenv(const char *currdev_in)
+init_zfs_boot_options(const char *currdev_in)
{
+ char poolname[ZFS_MAXNAMELEN];
char *beroot, *currdev;
+ spa_t *spa;
int currdev_len;
+ const char *dsname;
currdev = NULL;
currdev_len = strlen(currdev_in);
@@ -1124,6 +1151,7 @@
return;
/* Remove the trailing : */
currdev[currdev_len - 1] = '\0';
+
setenv("zfs_be_active", currdev, 1);
setenv("zfs_be_currpage", "1", 1);
/* Remove the last element (current bootenv) */
@@ -1132,49 +1160,71 @@
beroot[0] = '\0';
beroot = strchr(currdev, ':') + 1;
setenv("zfs_be_root", beroot, 1);
- zfs_bootenv_initial(beroot);
+
+ if (split_devname(beroot, poolname, sizeof(poolname), &dsname) != 0)
+ return;
+
+ spa = spa_find_by_name(poolname);
+ if (spa == NULL)
+ return;
+
+ zfs_bootenv_initial("bootenvs", spa, beroot, dsname, 0);
+ zfs_checkpoints_initial(spa, beroot, dsname);
+
free(currdev);
}
static void
-zfs_bootenv_initial(const char *name)
+zfs_checkpoints_initial(spa_t *spa, const char *name, const char *dsname)
{
- char poolname[ZFS_MAXNAMELEN], *dsname;
- char envname[32], envval[256];
+ char envname[32];
+
+ if (spa->spa_uberblock_checkpoint.ub_checkpoint_txg != 0) {
+ snprintf(envname, sizeof(envname), "zpool_checkpoint");
+ setenv(envname, name, 1);
+
+ spa->spa_uberblock = &spa->spa_uberblock_checkpoint;
+ spa->spa_mos = &spa->spa_mos_checkpoint;
+
+ zfs_bootenv_initial("bootenvs_check", spa, name, dsname, 1);
+
+ spa->spa_uberblock = &spa->spa_uberblock_master;
+ spa->spa_mos = &spa->spa_mos_master;
+ }
+}
+
+static void
+zfs_bootenv_initial(const char *envprefix, spa_t *spa, const char *rootname,
+ const char *dsname, int checkpoint)
+{
+ char envname[32], envval[256];
uint64_t objid;
- spa_t *spa;
- int bootenvs_idx, len, rv;
+ int bootenvs_idx, rv;
SLIST_INIT(&zfs_be_head);
zfs_env_count = 0;
- len = strlen(name);
- dsname = strchr(name, '/');
- if (dsname != NULL) {
- len = dsname - name;
- dsname++;
- } else
- dsname = "";
- strlcpy(poolname, name, len + 1);
- spa = spa_find_by_name(poolname);
- if (spa == NULL)
- return;
+
rv = zfs_lookup_dataset(spa, dsname, &objid);
if (rv != 0)
return;
+
rv = zfs_callback_dataset(spa, objid, zfs_belist_add);
bootenvs_idx = 0;
/* Populate the initial environment variables */
SLIST_FOREACH_SAFE(zfs_be, &zfs_be_head, entries, zfs_be_tmp) {
/* Enumerate all bootenvs for general usage */
- snprintf(envname, sizeof(envname), "bootenvs[%d]", bootenvs_idx);
- snprintf(envval, sizeof(envval), "zfs:%s/%s", name, zfs_be->name);
+ snprintf(envname, sizeof(envname), "%s[%d]",
+ envprefix, bootenvs_idx);
+ snprintf(envval, sizeof(envval), "zfs:%s%s/%s",
+ checkpoint ? "!" : "", rootname, zfs_be->name);
rv = setenv(envname, envval, 1);
if (rv != 0)
break;
bootenvs_idx++;
}
+ snprintf(envname, sizeof(envname), "%s_count", envprefix);
snprintf(envval, sizeof(envval), "%d", bootenvs_idx);
- setenv("bootenvs_count", envval, 1);
+ setenv(envname, envval, 1);
/* Clean up the SLIST of ZFS BEs */
while (!SLIST_EMPTY(&zfs_be_head)) {
@@ -1183,19 +1233,17 @@
free(zfs_be->name);
free(zfs_be);
}
-
- return;
-
}
int
zfs_bootenv(const char *name)
{
- static char poolname[ZFS_MAXNAMELEN], *dsname, *root;
+ char poolname[ZFS_MAXNAMELEN], *root;
+ const char *dsname;
char becount[4];
uint64_t objid;
spa_t *spa;
- int len, rv, pages, perpage, currpage;
+ int rv, pages, perpage, currpage;
if (name == NULL)
return (EINVAL);
@@ -1209,16 +1257,10 @@
SLIST_INIT(&zfs_be_head);
zfs_env_count = 0;
- len = strlen(name);
- dsname = strchr(name, '/');
- if (dsname != NULL) {
- len = dsname - name;
- dsname++;
- } else
- dsname = "";
- memcpy(poolname, name, len);
- poolname[len] = '\0';
+ if (split_devname(name, poolname, sizeof(poolname), &dsname) != 0)
+ return (EINVAL);
+
spa = spa_find_by_name(poolname);
if (!spa)
return (ENXIO);
@@ -1307,7 +1349,7 @@
ctr++;
continue;
}
-
+
snprintf(envname, sizeof(envname), "bootenvmenu_caption[%d]", zfs_env_index);
snprintf(envval, sizeof(envval), "%s", zfs_be->name);
rv = setenv(envname, envval, 1);
@@ -1340,7 +1382,7 @@
}
}
-
+
for (; zfs_env_index <= ZFS_BE_LAST; zfs_env_index++) {
snprintf(envname, sizeof(envname), "bootenvmenu_caption[%d]", zfs_env_index);
(void)unsetenv(envname);
Index: head/stand/libsa/zfs/zfsimpl.c
===================================================================
--- head/stand/libsa/zfs/zfsimpl.c
+++ head/stand/libsa/zfs/zfsimpl.c
@@ -699,7 +699,7 @@
vic = &vdev->vdev_indirect_config;
vdev->v_mapping = vdev_indirect_mapping_open(spa,
- &spa->spa_mos, vic->vic_mapping_object);
+ spa->spa_mos, vic->vic_mapping_object);
}
vdev_indirect_remap(vdev, offset, bytes, &zio);
@@ -1347,6 +1347,8 @@
free(spa);
return (NULL);
}
+ spa->spa_uberblock = &spa->spa_uberblock_master;
+ spa->spa_mos = &spa->spa_mos_master;
spa->spa_guid = guid;
spa->spa_root_vdev = vdev_create(guid, NULL);
if (spa->spa_root_vdev == NULL) {
@@ -1883,7 +1885,7 @@
* the best uberblock and then we can actually access
* the contents of the pool.
*/
- vdev_uberblock_load(vdev, &spa->spa_uberblock);
+ vdev_uberblock_load(vdev, spa->spa_uberblock);
if (spap != NULL)
*spap = spa;
@@ -2409,8 +2411,9 @@
if (zh->zap_magic != ZAP_MAGIC)
return (EIO);
- if ((rc = fzap_check_size(integer_size, num_integers)) != 0)
+ if ((rc = fzap_check_size(integer_size, num_integers)) != 0) {
return (rc);
+ }
z.zap_block_shift = ilog2(bsize);
z.zap_phys = zh;
@@ -2766,7 +2769,7 @@
p = &name[sizeof(name) - 1];
*p = '\0';
- if (objset_get_dnode(spa, &spa->spa_mos, objnum, &dataset)) {
+ if (objset_get_dnode(spa, spa->spa_mos, objnum, &dataset)) {
printf("ZFS: can't find dataset %ju\n", (uintmax_t)objnum);
return (EIO);
}
@@ -2774,7 +2777,7 @@
dir_obj = ds->ds_dir_obj;
for (;;) {
- if (objset_get_dnode(spa, &spa->spa_mos, dir_obj, &dir) != 0)
+ if (objset_get_dnode(spa, spa->spa_mos, dir_obj, &dir) != 0)
return (EIO);
dd = (dsl_dir_phys_t *)&dir.dn_bonus;
@@ -2783,12 +2786,12 @@
if (parent_obj == 0)
break;
- if (objset_get_dnode(spa, &spa->spa_mos, parent_obj,
+ if (objset_get_dnode(spa, spa->spa_mos, parent_obj,
&parent) != 0)
return (EIO);
dd = (dsl_dir_phys_t *)&parent.dn_bonus;
child_dir_zapobj = dd->dd_child_dir_zapobj;
- if (objset_get_dnode(spa, &spa->spa_mos, child_dir_zapobj,
+ if (objset_get_dnode(spa, spa->spa_mos, child_dir_zapobj,
&child_dir_zap) != 0)
return (EIO);
if (zap_rlookup(spa, &child_dir_zap, component, dir_obj) != 0)
@@ -2820,7 +2823,7 @@
dsl_dir_phys_t *dd;
const char *p, *q;
- if (objset_get_dnode(spa, &spa->spa_mos,
+ if (objset_get_dnode(spa, spa->spa_mos,
DMU_POOL_DIRECTORY_OBJECT, &dir))
return (EIO);
if (zap_lookup(spa, &dir, DMU_POOL_ROOT_DATASET, sizeof (dir_obj),
@@ -2829,7 +2832,7 @@
p = name;
for (;;) {
- if (objset_get_dnode(spa, &spa->spa_mos, dir_obj, &dir))
+ if (objset_get_dnode(spa, spa->spa_mos, dir_obj, &dir))
return (EIO);
dd = (dsl_dir_phys_t *)&dir.dn_bonus;
@@ -2850,7 +2853,7 @@
}
child_dir_zapobj = dd->dd_child_dir_zapobj;
- if (objset_get_dnode(spa, &spa->spa_mos, child_dir_zapobj,
+ if (objset_get_dnode(spa, spa->spa_mos, child_dir_zapobj,
&child_dir_zap) != 0)
return (EIO);
@@ -2873,21 +2876,21 @@
dsl_dataset_phys_t *ds;
dsl_dir_phys_t *dd;
- if (objset_get_dnode(spa, &spa->spa_mos, objnum, &dataset)) {
+ if (objset_get_dnode(spa, spa->spa_mos, objnum, &dataset)) {
printf("ZFS: can't find dataset %ju\n", (uintmax_t)objnum);
return (EIO);
}
ds = (dsl_dataset_phys_t *)&dataset.dn_bonus;
dir_obj = ds->ds_dir_obj;
- if (objset_get_dnode(spa, &spa->spa_mos, dir_obj, &dir)) {
+ if (objset_get_dnode(spa, spa->spa_mos, dir_obj, &dir)) {
printf("ZFS: can't find dirobj %ju\n", (uintmax_t)dir_obj);
return (EIO);
}
dd = (dsl_dir_phys_t *)&dir.dn_bonus;
child_dir_zapobj = dd->dd_child_dir_zapobj;
- if (objset_get_dnode(spa, &spa->spa_mos, child_dir_zapobj,
+ if (objset_get_dnode(spa, spa->spa_mos, child_dir_zapobj,
&child_dir_zap) != 0) {
printf("ZFS: can't find child zap %ju\n", (uintmax_t)dir_obj);
return (EIO);
@@ -2908,7 +2911,7 @@
size_t size;
int err;
- err = objset_get_dnode(spa, &spa->spa_mos, objnum, &dataset);
+ err = objset_get_dnode(spa, spa->spa_mos, objnum, &dataset);
if (err != 0) {
printf("ZFS: can't find dataset %ju\n", (uintmax_t)objnum);
return (err);
@@ -2916,7 +2919,7 @@
ds = (dsl_dataset_phys_t *)&dataset.dn_bonus;
dir_obj = ds->ds_dir_obj;
- err = objset_get_dnode(spa, &spa->spa_mos, dir_obj, &dir);
+ err = objset_get_dnode(spa, spa->spa_mos, dir_obj, &dir);
if (err != 0) {
printf("ZFS: can't find dirobj %ju\n", (uintmax_t)dir_obj);
return (err);
@@ -2924,7 +2927,7 @@
dd = (dsl_dir_phys_t *)&dir.dn_bonus;
child_dir_zapobj = dd->dd_child_dir_zapobj;
- err = objset_get_dnode(spa, &spa->spa_mos, child_dir_zapobj,
+ err = objset_get_dnode(spa, spa->spa_mos, child_dir_zapobj,
&child_dir_zap);
if (err != 0) {
printf("ZFS: can't find child zap %ju\n", (uintmax_t)dir_obj);
@@ -2962,7 +2965,7 @@
dnode_phys_t dataset;
dsl_dataset_phys_t *ds;
- if (objset_get_dnode(spa, &spa->spa_mos, objnum, &dataset)) {
+ if (objset_get_dnode(spa, spa->spa_mos, objnum, &dataset)) {
printf("ZFS: can't find dataset %ju\n", (uintmax_t)objnum);
return (EIO);
}
@@ -2992,7 +2995,7 @@
/*
* Start with the MOS directory object.
*/
- if (objset_get_dnode(spa, &spa->spa_mos,
+ if (objset_get_dnode(spa, spa->spa_mos,
DMU_POOL_DIRECTORY_OBJECT, &dir)) {
printf("ZFS: can't read MOS object directory\n");
return (EIO);
@@ -3003,7 +3006,7 @@
*/
if (zap_lookup(spa, &dir, DMU_POOL_PROPS,
sizeof(props), 1, &props) == 0 &&
- objset_get_dnode(spa, &spa->spa_mos, props, &propdir) == 0 &&
+ objset_get_dnode(spa, spa->spa_mos, props, &propdir) == 0 &&
zap_lookup(spa, &propdir, "bootfs",
sizeof(bootfs), 1, &bootfs) == 0 && bootfs != 0) {
*objid = bootfs;
@@ -3014,7 +3017,7 @@
*/
if (zap_lookup(spa, &dir, DMU_POOL_ROOT_DATASET,
sizeof(root), 1, &root) ||
- objset_get_dnode(spa, &spa->spa_mos, root, &dir)) {
+ objset_get_dnode(spa, spa->spa_mos, root, &dir)) {
printf("ZFS: can't find root dsl_dir\n");
return (EIO);
}
@@ -3085,7 +3088,7 @@
size_t size;
int rc;
- if ((rc = objset_get_dnode(spa, &spa->spa_mos, DMU_OT_OBJECT_DIRECTORY,
+ if ((rc = objset_get_dnode(spa, spa->spa_mos, DMU_OT_OBJECT_DIRECTORY,
&dir)) != 0)
return (rc);
if ((rc = zap_lookup(spa, &dir, DMU_POOL_FEATURES_FOR_READ,
@@ -3097,7 +3100,7 @@
return (0);
}
- if ((rc = objset_get_dnode(spa, &spa->spa_mos, objnum, &dir)) != 0)
+ if ((rc = objset_get_dnode(spa, spa->spa_mos, objnum, &dir)) != 0)
return (rc);
if (dir.dn_type != DMU_OTN_ZAP_METADATA)
@@ -3131,7 +3134,7 @@
unsigned char *nv;
*value = NULL;
- if ((rc = objset_get_dnode(spa, &spa->spa_mos, obj, &dir)) != 0)
+ if ((rc = objset_get_dnode(spa, spa->spa_mos, obj, &dir)) != 0)
return (rc);
if (dir.dn_type != DMU_OT_PACKED_NVLIST &&
dir.dn_bonustype != DMU_OT_PACKED_NVLIST_SIZE) {
@@ -3160,22 +3163,23 @@
static int
zfs_spa_init(spa_t *spa)
{
+ struct uberblock checkpoint;
dnode_phys_t dir;
uint64_t config_object;
nvlist_t *nvlist;
int rc;
- if (zio_read(spa, &spa->spa_uberblock.ub_rootbp, &spa->spa_mos)) {
+ if (zio_read(spa, &spa->spa_uberblock->ub_rootbp, spa->spa_mos)) {
printf("ZFS: can't read MOS of pool %s\n", spa->spa_name);
return (EIO);
}
- if (spa->spa_mos.os_type != DMU_OST_META) {
+ if (spa->spa_mos->os_type != DMU_OST_META) {
printf("ZFS: corrupted MOS of pool %s\n", spa->spa_name);
return (EIO);
}
- if (objset_get_dnode(spa, &spa->spa_mos, DMU_POOL_DIRECTORY_OBJECT,
- &dir)) {
+ if (objset_get_dnode(spa, &spa->spa_mos_master,
+ DMU_POOL_DIRECTORY_OBJECT, &dir)) {
printf("ZFS: failed to read pool %s directory object\n",
spa->spa_name);
return (EIO);
@@ -3200,6 +3204,20 @@
rc = load_nvlist(spa, config_object, &nvlist);
if (rc != 0)
return (rc);
+
+ rc = zap_lookup(spa, &dir, DMU_POOL_ZPOOL_CHECKPOINT,
+ sizeof(uint64_t), sizeof(checkpoint) / sizeof(uint64_t),
+ &checkpoint);
+ if (rc == 0 && checkpoint.ub_checkpoint_txg != 0) {
+ memcpy(&spa->spa_uberblock_checkpoint, &checkpoint,
+ sizeof(checkpoint));
+ if (zio_read(spa, &spa->spa_uberblock_checkpoint.ub_rootbp,
+ &spa->spa_mos_checkpoint)) {
+ printf("ZFS: can not read checkpoint data.\n");
+ return (EIO);
+ }
+ }
+
/*
* Update vdevs from MOS config. Note, we do skip encoding bytes
* here. See also vdev_label_read_config().
Index: head/stand/lua/core.lua
===================================================================
--- head/stand/lua/core.lua
+++ head/stand/lua/core.lua
@@ -38,6 +38,8 @@
local default_single_user = false
local default_verbose = false
+local bootenv_list = "bootenvs"
+
local function composeLoaderCmd(cmd_name, argstr)
if argstr ~= nil then
cmd_name = cmd_name .. " " .. argstr
@@ -270,7 +272,7 @@
end
function core.bootenvList()
- local bootenv_count = tonumber(loader.getenv("bootenvs_count"))
+ local bootenv_count = tonumber(loader.getenv(bootenv_list .. "_count"))
local bootenvs = {}
local curenv
local envcount = 0
@@ -281,7 +283,12 @@
end
-- Currently selected bootenv is always first/default
- curenv = core.bootenvDefault()
+ -- On the rewinded list the bootenv may not exists
+ if core.isRewinded() then
+ curenv = core.bootenvDefaultRewinded()
+ else
+ curenv = core.bootenvDefault()
+ end
if curenv ~= nil then
envcount = envcount + 1
bootenvs[envcount] = curenv
@@ -289,7 +296,7 @@
end
for curenv_idx = 0, bootenv_count - 1 do
- curenv = loader.getenv("bootenvs[" .. curenv_idx .. "]")
+ curenv = loader.getenv(bootenv_list .. "[" .. curenv_idx .. "]")
if curenv ~= nil and unique[curenv] == nil then
envcount = envcount + 1
bootenvs[envcount] = curenv
@@ -297,6 +304,40 @@
end
end
return bootenvs
+end
+
+function core.isCheckpointed()
+ return loader.getenv("zpool_checkpoint") ~= nil
+end
+
+function core.bootenvDefaultRewinded()
+ local defname = "zfs:!" .. string.sub(core.bootenvDefault(), 5)
+ local bootenv_count = tonumber("bootenvs_check_count")
+
+ if bootenv_count == nil or bootenv_count <= 0 then
+ return defname
+ end
+
+ for curenv_idx = 0, bootenv_count - 1 do
+ curenv = loader.getenv("bootenvs_check[" .. curenv_idx .. "]")
+ if curenv == defname then
+ return defname
+ end
+ end
+
+ return loader.getenv("bootenvs_check[0]")
+end
+
+function core.isRewinded()
+ return bootenv_list == "bootenvs_check"
+end
+
+function core.changeRewindCheckpoint()
+ if core.isRewinded() then
+ bootenv_list = "bootenvs"
+ else
+ bootenv_list = "bootenvs_check"
+ end
end
function core.setDefaults()
Index: head/stand/lua/menu.lua
===================================================================
--- head/stand/lua/menu.lua
+++ head/stand/lua/menu.lua
@@ -132,6 +132,9 @@
},
{
entry_type = core.MENU_ENTRY,
+ visible = function()
+ return core.isRewinded() == false
+ end,
name = function()
return color.highlight("b") .. "ootfs: " ..
core.bootenvDefault()
@@ -250,6 +253,7 @@
},
menu_entries.kernel_options,
menu_entries.boot_options,
+ menu_entries.zpool_checkpoints,
menu_entries.boot_envs,
menu_entries.chainload,
}
@@ -333,6 +337,32 @@
name = "Boot " .. color.highlight("O") .. "ptions",
submenu = menu.boot_options,
alias = {"o", "O"},
+ },
+ zpool_checkpoints = {
+ entry_type = core.MENU_ENTRY,
+ name = function()
+ rewind = "No"
+ if core.isRewinded() then
+ rewind = "Yes"
+ end
+ return "Rewind ZFS " .. color.highlight("C") ..
+ "heckpoint: " .. rewind
+ end,
+ func = function()
+ core.changeRewindCheckpoint()
+ if core.isRewinded() then
+ bootenvSet(
+ core.bootenvDefaultRewinded())
+ else
+ bootenvSet(core.bootenvDefault())
+ end
+ config.setCarouselIndex("be_active", 1)
+ end,
+ visible = function()
+ return core.isZFSBoot() and
+ core.isCheckpointed()
+ end,
+ alias = {"c", "C"},
},
boot_envs = {
entry_type = core.MENU_SUBMENU,
Index: head/sys/cddl/boot/zfs/zfsimpl.h
===================================================================
--- head/sys/cddl/boot/zfs/zfsimpl.h
+++ head/sys/cddl/boot/zfs/zfsimpl.h
@@ -1351,6 +1351,7 @@
#define DMU_POOL_REMOVING "com.delphix:removing"
#define DMU_POOL_OBSOLETE_BPOBJ "com.delphix:obsolete_bpobj"
#define DMU_POOL_CONDENSING_INDIRECT "com.delphix:condensing_indirect"
+#define DMU_POOL_ZPOOL_CHECKPOINT "com.delphix:zpool_checkpoint"
#define ZAP_MAGIC 0x2F52AB2ABULL
@@ -1814,12 +1815,17 @@
char *spa_name; /* pool name */
uint64_t spa_guid; /* pool guid */
uint64_t spa_txg; /* most recent transaction */
- struct uberblock spa_uberblock; /* best uberblock so far */
+ struct uberblock *spa_uberblock; /* best uberblock so far */
vdev_t *spa_root_vdev; /* toplevel vdev container */
- objset_phys_t spa_mos; /* MOS for this pool */
+ objset_phys_t *spa_mos; /* MOS for this pool */
zio_cksum_salt_t spa_cksum_salt; /* secret salt for cksum */
void *spa_cksum_tmpls[ZIO_CHECKSUM_FUNCTIONS];
boolean_t spa_with_log; /* this pool has log */
+
+ struct uberblock spa_uberblock_master; /* best uberblock so far */
+ objset_phys_t spa_mos_master; /* MOS for this pool */
+ struct uberblock spa_uberblock_checkpoint; /* checkpoint uberblock */
+ objset_phys_t spa_mos_checkpoint; /* Checkpoint MOS */
} spa_t;
/* IO related arguments. */
Index: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
===================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c
@@ -5719,7 +5719,7 @@
}
int
-spa_import_rootpool(const char *name)
+spa_import_rootpool(const char *name, bool checkpointrewind)
{
spa_t *spa;
vdev_t *rvd, *bvd, *avd = NULL;
@@ -5778,6 +5778,9 @@
}
spa->spa_is_root = B_TRUE;
spa->spa_import_flags = ZFS_IMPORT_VERBATIM;
+ if (checkpointrewind) {
+ spa->spa_import_flags |= ZFS_IMPORT_CHECKPOINT;
+ }
/*
* Build up a vdev tree based on the boot device's label config.
Index: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h
===================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h
@@ -643,7 +643,7 @@
#ifdef illumos
extern int spa_import_rootpool(char *devpath, char *devid);
#else
-extern int spa_import_rootpool(const char *name);
+extern int spa_import_rootpool(const char *name, bool checkpointrewind);
#endif
extern int spa_import(const char *pool, nvlist_t *config, nvlist_t *props,
uint64_t flags);
Index: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
===================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c
@@ -1783,6 +1783,18 @@
return (0);
}
+static void
+fetch_osname_options(char *name, bool *checkpointrewind)
+{
+
+ if (name[0] == '!') {
+ *checkpointrewind = true;
+ memmove(name, name + 1, strlen(name));
+ } else {
+ *checkpointrewind = false;
+ }
+}
+
/*ARGSUSED*/
static int
zfs_mount(vfs_t *vfsp)
@@ -1793,6 +1805,7 @@
char *osname;
int error = 0;
int canwrite;
+ bool checkpointrewind;
#ifdef illumos
if (mvp->v_type != VDIR)
@@ -1836,6 +1849,7 @@
secpolicy_fs_mount_clearopts(cr, vfsp);
}
#endif /* illumos */
+ fetch_osname_options(osname, &checkpointrewind);
/*
* Check for mount privilege?
@@ -1921,7 +1935,7 @@
error = getpoolname(osname, pname);
if (error == 0)
- error = spa_import_rootpool(pname);
+ error = spa_import_rootpool(pname, checkpointrewind);
if (error)
goto out;
}

File Metadata

Mime Type
text/plain
Expires
Wed, May 20, 10:13 AM (2 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33325717
Default Alt Text
D24920.id75970.diff (22 KB)

Event Timeline