Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F157215995
D24920.id75970.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
22 KB
Referenced Files
None
Subscribers
None
D24920.id75970.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D24920: zfs: add to bootloader option to rewind the ZFS checkpoint.
Attached
Detach File
Event Timeline
Log In to Comment