Merge 7f85a9adfc
into d4b5517ef9
This commit is contained in:
commit
fae924da12
121
cmd/zdb/zdb.c
121
cmd/zdb/zdb.c
|
@ -21,7 +21,7 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2019 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2024 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2014 Integros [integros.com]
|
||||
* Copyright 2016 Nexenta Systems, Inc.
|
||||
* Copyright (c) 2017, 2018 Lawrence Livermore National Security, LLC.
|
||||
|
@ -5790,6 +5790,7 @@ zdb_count_block(zdb_cb_t *zcb, zilog_t *zilog, const blkptr_t *bp,
|
|||
if (BP_GET_DEDUP(bp)) {
|
||||
ddt_t *ddt;
|
||||
ddt_entry_t *dde;
|
||||
ASSERT3P(zilog, ==, NULL);
|
||||
|
||||
ddt = ddt_select(zcb->zcb_spa, bp);
|
||||
ddt_enter(ddt);
|
||||
|
@ -5807,9 +5808,19 @@ zdb_count_block(zdb_cb_t *zcb, zilog_t *zilog, const blkptr_t *bp,
|
|||
ddt_exit(ddt);
|
||||
}
|
||||
|
||||
VERIFY3U(zio_wait(zio_claim(NULL, zcb->zcb_spa,
|
||||
/*
|
||||
* Theoretically, we could try to track leaks here, but it would
|
||||
* require also importing the shared log pool and processing the
|
||||
* chain map and space maps for it. ZDB currently doesn't have
|
||||
* much facility to support multiple pools at once, so we leave this
|
||||
* for future work.
|
||||
*/
|
||||
if (zilog && zilog->zl_spa != zilog->zl_io_spa)
|
||||
return;
|
||||
|
||||
VERIFY0(zio_wait(zio_claim(NULL, zcb->zcb_spa,
|
||||
refcnt ? 0 : spa_min_claim_txg(zcb->zcb_spa),
|
||||
bp, NULL, NULL, ZIO_FLAG_CANFAIL)), ==, 0);
|
||||
bp, NULL, NULL, ZIO_FLAG_CANFAIL)));
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -6802,6 +6813,48 @@ zdb_brt_entry_compare(const void *zcn1, const void *zcn2)
|
|||
return (cmp);
|
||||
}
|
||||
|
||||
static int
|
||||
chain_map_count_blk_cb(spa_t *spa, const blkptr_t *bp, void *arg)
|
||||
{
|
||||
(void) spa;
|
||||
zdb_cb_t *zbc = arg;
|
||||
zdb_count_block(zbc, NULL, bp, ZDB_OT_OTHER);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
chain_map_count_lr_cb(spa_t *spa, const lr_t *lrc, void *arg)
|
||||
{
|
||||
(void) spa;
|
||||
zdb_cb_t *zbc = arg;
|
||||
lr_write_t *lr = (lr_write_t *)lrc;
|
||||
blkptr_t *bp = &lr->lr_blkptr;
|
||||
if (lrc->lrc_txtype != TX_WRITE || BP_IS_HOLE(bp))
|
||||
return (0);
|
||||
zdb_count_block(zbc, NULL, bp, ZDB_OT_OTHER);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Count the blocks in the chain maps.
|
||||
*/
|
||||
static void
|
||||
chain_map_count_blocks(spa_t *spa, zdb_cb_t *zbc)
|
||||
{
|
||||
avl_tree_t *pool_t = &spa->spa_chain_map;
|
||||
|
||||
for (spa_chain_map_pool_t *pool_node = avl_first(pool_t);
|
||||
pool_node != NULL; pool_node = AVL_NEXT(pool_t, pool_node)) {
|
||||
avl_tree_t *os_t = &pool_node->scmp_os_tree;
|
||||
for (spa_chain_map_os_t *os_node = avl_first(os_t);
|
||||
os_node != NULL; os_node = AVL_NEXT(os_t, os_node)) {
|
||||
(void) zil_parse_raw(spa, &os_node->scmo_chain_head,
|
||||
chain_map_count_blk_cb, chain_map_count_lr_cb,
|
||||
zbc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
dump_block_stats(spa_t *spa)
|
||||
{
|
||||
|
@ -6865,6 +6918,10 @@ dump_block_stats(spa_t *spa)
|
|||
|
||||
deleted_livelists_count_blocks(spa, zcb);
|
||||
|
||||
if (spa_is_shared_log(spa)) {
|
||||
chain_map_count_blocks(spa, zcb);
|
||||
}
|
||||
|
||||
if (dump_opt['c'] > 1)
|
||||
flags |= TRAVERSE_PREFETCH_DATA;
|
||||
|
||||
|
@ -7219,7 +7276,7 @@ zdb_ddt_add_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
|
|||
zdb_ddt_entry_t *zdde, zdde_search;
|
||||
|
||||
if (zb->zb_level == ZB_DNODE_LEVEL || BP_IS_HOLE(bp) ||
|
||||
BP_IS_EMBEDDED(bp))
|
||||
BP_IS_EMBEDDED(bp) || (zilog && zilog->zl_spa != zilog->zl_io_spa))
|
||||
return (0);
|
||||
|
||||
if (dump_opt['S'] > 1 && zb->zb_level == ZB_ROOT_LEVEL) {
|
||||
|
@ -7990,6 +8047,8 @@ dump_mos_leaks(spa_t *spa)
|
|||
scip_next_mapping_object);
|
||||
mos_obj_refd(spa->spa_condensing_indirect_phys.
|
||||
scip_prev_obsolete_sm_object);
|
||||
if (spa_is_shared_log(spa))
|
||||
mos_obj_refd(spa->spa_dsl_pool->dp_chain_map_obj);
|
||||
if (spa->spa_condensing_indirect_phys.scip_next_mapping_object != 0) {
|
||||
vdev_indirect_mapping_t *vim =
|
||||
vdev_indirect_mapping_open(mos,
|
||||
|
@ -8152,6 +8211,57 @@ dump_log_spacemap_obsolete_stats(spa_t *spa)
|
|||
(u_longlong_t)lsos.lsos_total_entries);
|
||||
}
|
||||
|
||||
static void print_blkptr(const blkptr_t *bp)
|
||||
{
|
||||
char blkbuf[BP_SPRINTF_LEN];
|
||||
snprintf_blkptr(blkbuf, sizeof (blkbuf), bp);
|
||||
if (dump_opt['Z'] && BP_GET_COMPRESS(bp) == ZIO_COMPRESS_ZSTD)
|
||||
snprintf_zstd_header(spa, blkbuf, sizeof (blkbuf), bp);
|
||||
(void) printf("%s\n", blkbuf);
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
chain_map_dump_blk_cb(spa_t *spa, const blkptr_t *bp, void *arg)
|
||||
{
|
||||
(void) spa, (void) arg;
|
||||
printf("\t\t\tBP: ");
|
||||
print_blkptr(bp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
chain_map_dump_lr_cb(spa_t *spa, const lr_t *lrc, void *arg)
|
||||
{
|
||||
(void) spa, (void) arg;
|
||||
lr_write_t *lr = (lr_write_t *)lrc;
|
||||
blkptr_t *bp = &lr->lr_blkptr;
|
||||
printf("\t\t\tLR BP: ");
|
||||
print_blkptr(bp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_chain_map(spa_t *spa)
|
||||
{
|
||||
(void) printf("Chain map contents:\n");
|
||||
avl_tree_t *pool_t = &spa->spa_chain_map;
|
||||
|
||||
for (spa_chain_map_pool_t *pool_node = avl_first(pool_t);
|
||||
pool_node != NULL; pool_node = AVL_NEXT(pool_t, pool_node)) {
|
||||
avl_tree_t *os_t = &pool_node->scmp_os_tree;
|
||||
(void) printf("\tPool entry: %s\n", pool_node->scmp_name);
|
||||
for (spa_chain_map_os_t *os_node = avl_first(os_t);
|
||||
os_node != NULL; os_node = AVL_NEXT(os_t, os_node)) {
|
||||
(void) printf("\t\tObjset entry: %"PRIu64"\n\t\t\t",
|
||||
os_node->scmo_id);
|
||||
print_blkptr(&os_node->scmo_chain_head);
|
||||
(void) zil_parse_raw(spa, &os_node->scmo_chain_head,
|
||||
chain_map_dump_blk_cb, chain_map_dump_lr_cb, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dump_zpool(spa_t *spa)
|
||||
{
|
||||
|
@ -8233,6 +8343,9 @@ dump_zpool(spa_t *spa)
|
|||
(void) dmu_objset_find(spa_name(spa), dump_one_objset,
|
||||
NULL, DS_FIND_SNAPSHOTS | DS_FIND_CHILDREN);
|
||||
|
||||
if (spa_is_shared_log(spa))
|
||||
dump_chain_map(spa);
|
||||
|
||||
if (rc == 0 && !dump_opt['L'])
|
||||
rc = dump_mos_leaks(spa);
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ fatal(spa_t *spa, const void *tag, const char *fmt, ...)
|
|||
|
||||
if (spa != NULL) {
|
||||
spa_close(spa, tag);
|
||||
(void) spa_export(g_pool, NULL, B_TRUE, B_FALSE);
|
||||
(void) spa_export(g_pool, NULL, B_TRUE, B_FALSE, NULL);
|
||||
}
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
@ -1015,7 +1015,8 @@ main(int argc, char **argv)
|
|||
usage();
|
||||
}
|
||||
|
||||
if (!g_readonly && spa_export(g_pool, NULL, B_TRUE, B_FALSE) != 0) {
|
||||
if (!g_readonly && spa_export(g_pool, NULL, B_TRUE, B_FALSE,
|
||||
NULL) != 0) {
|
||||
fatal(NULL, FTAG, "pool export failed; "
|
||||
"changes may not be committed to disk\n");
|
||||
}
|
||||
|
|
|
@ -111,6 +111,7 @@ static int zpool_do_split(int, char **);
|
|||
static int zpool_do_initialize(int, char **);
|
||||
static int zpool_do_scrub(int, char **);
|
||||
static int zpool_do_resilver(int, char **);
|
||||
static int zpool_do_recycle(int, char **);
|
||||
static int zpool_do_trim(int, char **);
|
||||
|
||||
static int zpool_do_import(int, char **);
|
||||
|
@ -182,6 +183,7 @@ typedef enum {
|
|||
HELP_REMOVE,
|
||||
HELP_INITIALIZE,
|
||||
HELP_SCRUB,
|
||||
HELP_RECYCLE,
|
||||
HELP_RESILVER,
|
||||
HELP_TRIM,
|
||||
HELP_STATUS,
|
||||
|
@ -326,6 +328,7 @@ static zpool_command_t command_table[] = {
|
|||
{ "split", zpool_do_split, HELP_SPLIT },
|
||||
{ NULL },
|
||||
{ "initialize", zpool_do_initialize, HELP_INITIALIZE },
|
||||
{ "recycle", zpool_do_recycle, HELP_RECYCLE },
|
||||
{ "resilver", zpool_do_resilver, HELP_RESILVER },
|
||||
{ "scrub", zpool_do_scrub, HELP_SCRUB },
|
||||
{ "trim", zpool_do_trim, HELP_TRIM },
|
||||
|
@ -368,7 +371,8 @@ get_usage(zpool_help_t idx)
|
|||
case HELP_CLEAR:
|
||||
return (gettext("\tclear [[--power]|[-nF]] <pool> [device]\n"));
|
||||
case HELP_CREATE:
|
||||
return (gettext("\tcreate [-fnd] [-o property=value] ... \n"
|
||||
return (gettext("\tcreate [-fndL] [-l pool] ... \n"
|
||||
"\t [-o property=value] ... \n"
|
||||
"\t [-O file-system-property=value] ... \n"
|
||||
"\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
|
||||
case HELP_CHECKPOINT:
|
||||
|
@ -387,9 +391,10 @@ get_usage(zpool_help_t idx)
|
|||
"\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
|
||||
"[-R root] [-F [-n]] -a\n"
|
||||
"\timport [-o mntopts] [-o property=value] ... \n"
|
||||
"\t [-d dir | -c cachefile] [-D] [-l] [-f] [-m] [-N] "
|
||||
"[-R root] [-F [-n]]\n"
|
||||
"\t [--rewind-to-checkpoint] <pool | id> [newpool]\n"));
|
||||
"\t [-d dir | -c cachefile] [-D] [-l] [-f] "
|
||||
"[-m [-L pool]] [-N] [-R root]\n"
|
||||
"\t [-F [-n]] [--rewind-to-checkpoint] <pool | id> "
|
||||
"[newpool]\n"));
|
||||
case HELP_IOSTAT:
|
||||
return (gettext("\tiostat [[[-c [script1,script2,...]"
|
||||
"[-lq]]|[-rw]] [-T d | u] [-ghHLpPvy]\n"
|
||||
|
@ -422,6 +427,8 @@ get_usage(zpool_help_t idx)
|
|||
"[<device> ...]\n"));
|
||||
case HELP_SCRUB:
|
||||
return (gettext("\tscrub [-s | -p] [-w] [-e] <pool> ...\n"));
|
||||
case HELP_RECYCLE:
|
||||
return (gettext("\trecycle [-nv] <pool> ...\n"));
|
||||
case HELP_RESILVER:
|
||||
return (gettext("\tresilver <pool> ...\n"));
|
||||
case HELP_TRIM:
|
||||
|
@ -1169,10 +1176,13 @@ zpool_do_add(int argc, char **argv)
|
|||
&props, B_TRUE) == 0);
|
||||
}
|
||||
}
|
||||
uint64_t shared_log;
|
||||
boolean_t has_shared_log = nvlist_lookup_uint64(config,
|
||||
ZPOOL_CONFIG_SHARED_LOG_POOL, &shared_log) == 0;
|
||||
|
||||
/* pass off to make_root_vdev for processing */
|
||||
nvroot = make_root_vdev(zhp, props, !check_inuse,
|
||||
check_replication, B_FALSE, dryrun, argc, argv);
|
||||
check_replication, B_FALSE, dryrun, has_shared_log, argc, argv);
|
||||
if (nvroot == NULL) {
|
||||
zpool_close(zhp);
|
||||
return (1);
|
||||
|
@ -1632,9 +1642,11 @@ zpool_do_create(int argc, char **argv)
|
|||
nvlist_t *fsprops = NULL;
|
||||
nvlist_t *props = NULL;
|
||||
char *propval;
|
||||
zpool_handle_t *shared_log_pool = NULL;
|
||||
boolean_t is_shared_log = B_FALSE;
|
||||
|
||||
/* check options */
|
||||
while ((c = getopt(argc, argv, ":fndR:m:o:O:t:")) != -1) {
|
||||
while ((c = getopt(argc, argv, ":fndR:m:o:O:t:l:L")) != -1) {
|
||||
switch (c) {
|
||||
case 'f':
|
||||
force = B_TRUE;
|
||||
|
@ -1733,6 +1745,17 @@ zpool_do_create(int argc, char **argv)
|
|||
goto errout;
|
||||
tname = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
shared_log_pool = zpool_open(g_zfs, optarg);
|
||||
if (shared_log_pool == NULL) {
|
||||
(void) fprintf(stderr, gettext("could not open "
|
||||
"shared log pool '%s'"), optarg);
|
||||
goto errout;
|
||||
}
|
||||
break;
|
||||
case 'L':
|
||||
is_shared_log = B_TRUE;
|
||||
break;
|
||||
case ':':
|
||||
(void) fprintf(stderr, gettext("missing argument for "
|
||||
"'%c' option\n"), optopt);
|
||||
|
@ -1773,9 +1796,17 @@ zpool_do_create(int argc, char **argv)
|
|||
|
||||
/* pass off to make_root_vdev for bulk processing */
|
||||
nvroot = make_root_vdev(NULL, props, force, !force, B_FALSE, dryrun,
|
||||
argc - 1, argv + 1);
|
||||
shared_log_pool != NULL, argc - 1, argv + 1);
|
||||
if (nvroot == NULL)
|
||||
goto errout;
|
||||
if (shared_log_pool) {
|
||||
fnvlist_add_uint64(nvroot, ZPOOL_CONFIG_SHARED_LOG_POOL,
|
||||
fnvlist_lookup_uint64(zpool_get_config(shared_log_pool,
|
||||
NULL), ZPOOL_CONFIG_POOL_GUID));
|
||||
}
|
||||
|
||||
if (is_shared_log)
|
||||
fnvlist_add_boolean(nvroot, ZPOOL_CONFIG_IS_SHARED_LOG);
|
||||
|
||||
/* make_root_vdev() allows 0 toplevel children if there are spares */
|
||||
if (!zfs_allocatable_devs(nvroot)) {
|
||||
|
@ -2518,7 +2549,8 @@ vdev_health_check_cb(void *hdl_data, nvlist_t *nv, void *data)
|
|||
*/
|
||||
static void
|
||||
print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
|
||||
nvlist_t *nv, int depth, boolean_t isspare, vdev_rebuild_stat_t *vrs)
|
||||
nvlist_t *nv, int depth, boolean_t isspare, boolean_t recurse,
|
||||
vdev_rebuild_stat_t *vrs)
|
||||
{
|
||||
nvlist_t **child, *root;
|
||||
uint_t c, i, vsc, children;
|
||||
|
@ -2798,7 +2830,7 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
|
|||
|
||||
(void) printf("\n");
|
||||
|
||||
for (c = 0; c < children; c++) {
|
||||
for (c = 0; c < children && recurse; c++) {
|
||||
uint64_t islog = B_FALSE, ishole = B_FALSE;
|
||||
|
||||
/* Don't print logs or holes here */
|
||||
|
@ -2822,7 +2854,7 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
|
|||
vname = zpool_vdev_name(g_zfs, zhp, child[c],
|
||||
cb->cb_name_flags | VDEV_NAME_TYPE_ID);
|
||||
print_status_config(zhp, cb, vname, child[c], depth + 2,
|
||||
isspare, vrs);
|
||||
isspare, B_TRUE, vrs);
|
||||
free(vname);
|
||||
}
|
||||
}
|
||||
|
@ -2833,7 +2865,7 @@ print_status_config(zpool_handle_t *zhp, status_cbdata_t *cb, const char *name,
|
|||
*/
|
||||
static void
|
||||
print_import_config(status_cbdata_t *cb, const char *name, nvlist_t *nv,
|
||||
int depth)
|
||||
int depth, boolean_t recurse)
|
||||
{
|
||||
nvlist_t **child;
|
||||
uint_t c, children;
|
||||
|
@ -2899,7 +2931,7 @@ print_import_config(status_cbdata_t *cb, const char *name, nvlist_t *nv,
|
|||
}
|
||||
(void) printf("\n");
|
||||
|
||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
||||
if (!recurse || nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
||||
&child, &children) != 0)
|
||||
return;
|
||||
|
||||
|
@ -2915,7 +2947,7 @@ print_import_config(status_cbdata_t *cb, const char *name, nvlist_t *nv,
|
|||
|
||||
vname = zpool_vdev_name(g_zfs, NULL, child[c],
|
||||
cb->cb_name_flags | VDEV_NAME_TYPE_ID);
|
||||
print_import_config(cb, vname, child[c], depth + 2);
|
||||
print_import_config(cb, vname, child[c], depth + 2, B_TRUE);
|
||||
free(vname);
|
||||
}
|
||||
|
||||
|
@ -2996,13 +3028,70 @@ print_class_vdevs(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t *nv,
|
|||
cb->cb_name_flags | VDEV_NAME_TYPE_ID);
|
||||
if (cb->cb_print_status)
|
||||
print_status_config(zhp, cb, name, child[c], 2,
|
||||
B_FALSE, NULL);
|
||||
B_FALSE, B_TRUE, NULL);
|
||||
else
|
||||
print_import_config(cb, name, child[c], 2);
|
||||
print_import_config(cb, name, child[c], 2, B_TRUE);
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a pool with a matching GUID.
|
||||
*/
|
||||
typedef struct find_cbdata {
|
||||
uint64_t cb_guid;
|
||||
zpool_handle_t *cb_zhp;
|
||||
} find_cbdata_t;
|
||||
|
||||
static int
|
||||
find_pool(zpool_handle_t *zhp, void *data)
|
||||
{
|
||||
find_cbdata_t *cbp = data;
|
||||
|
||||
if (cbp->cb_guid ==
|
||||
zpool_get_prop_int(zhp, ZPOOL_PROP_GUID, NULL)) {
|
||||
cbp->cb_zhp = zhp;
|
||||
return (1);
|
||||
}
|
||||
|
||||
zpool_close(zhp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a pool GUID, find the matching pool.
|
||||
*/
|
||||
static zpool_handle_t *
|
||||
find_by_guid(libzfs_handle_t *zhdl, uint64_t pool_guid)
|
||||
{
|
||||
find_cbdata_t cb;
|
||||
cb.cb_guid = pool_guid;
|
||||
if (zpool_iter(zhdl, find_pool, &cb) != 1)
|
||||
return (NULL);
|
||||
|
||||
return (cb.cb_zhp);
|
||||
}
|
||||
|
||||
static void
|
||||
print_shared_log(zpool_handle_t *zhp, status_cbdata_t *cb,
|
||||
uint64_t shared_log_guid)
|
||||
{
|
||||
(void) printf(gettext("\tshared log\n"));
|
||||
zpool_handle_t *shared_log = find_by_guid(g_zfs, shared_log_guid);
|
||||
VERIFY(shared_log);
|
||||
nvlist_t *shared_log_config = zpool_get_config(shared_log, NULL);
|
||||
nvlist_t *nvroot;
|
||||
VERIFY0(nvlist_lookup_nvlist(shared_log_config, ZPOOL_CONFIG_VDEV_TREE,
|
||||
&nvroot));
|
||||
const char *name = zpool_get_name(shared_log);
|
||||
if (cb->cb_print_status)
|
||||
print_status_config(zhp, cb, name, nvroot, 2,
|
||||
B_FALSE, B_FALSE, NULL);
|
||||
else
|
||||
print_import_config(cb, name, nvroot, 2, B_FALSE);
|
||||
zpool_close(shared_log);
|
||||
}
|
||||
|
||||
/*
|
||||
* Display the status for the given pool.
|
||||
*/
|
||||
|
@ -3376,7 +3465,7 @@ show_import(nvlist_t *config, boolean_t report_error)
|
|||
if (cb.cb_namewidth < 10)
|
||||
cb.cb_namewidth = 10;
|
||||
|
||||
print_import_config(&cb, name, nvroot, 0);
|
||||
print_import_config(&cb, name, nvroot, 0, B_TRUE);
|
||||
|
||||
print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_DEDUP);
|
||||
print_class_vdevs(NULL, &cb, nvroot, VDEV_ALLOC_BIAS_SPECIAL);
|
||||
|
@ -3578,10 +3667,31 @@ import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags,
|
|||
uint_t npools = 0;
|
||||
|
||||
|
||||
int err = 0;
|
||||
nvpair_t *elem = NULL, *next = NULL;
|
||||
boolean_t first = B_TRUE;
|
||||
tpool_t *tp = NULL;
|
||||
if (import->do_all) {
|
||||
tp = tpool_create(1, 5 * sysconf(_SC_NPROCESSORS_ONLN),
|
||||
0, NULL);
|
||||
|
||||
elem = nvlist_next_nvpair(pools, NULL);
|
||||
next = nvlist_next_nvpair(pools, elem);
|
||||
|
||||
while (elem != NULL) {
|
||||
verify(nvpair_value_nvlist(elem, &config) == 0);
|
||||
if (fnvlist_lookup_boolean(config,
|
||||
ZPOOL_CONFIG_IS_SHARED_LOG)) {
|
||||
err = do_import(config, NULL, mntopts, props,
|
||||
flags, mount_tp_nthr);
|
||||
first = B_FALSE;
|
||||
fnvlist_remove_nvpair(pools, elem);
|
||||
}
|
||||
elem = next;
|
||||
next = nvlist_next_nvpair(pools, elem);
|
||||
}
|
||||
if (err != 0)
|
||||
return (err);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3590,9 +3700,6 @@ import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags,
|
|||
* post-process the list to deal with pool state and possible
|
||||
* duplicate names.
|
||||
*/
|
||||
int err = 0;
|
||||
nvpair_t *elem = NULL;
|
||||
boolean_t first = B_TRUE;
|
||||
if (!pool_specified && import->do_all) {
|
||||
while ((elem = nvlist_next_nvpair(pools, elem)) != NULL)
|
||||
npools++;
|
||||
|
@ -3694,6 +3801,11 @@ import_pools(nvlist_t *pools, nvlist_t *props, char *mntopts, int flags,
|
|||
"no such pool available\n"), orig_name);
|
||||
err = B_TRUE;
|
||||
} else {
|
||||
if (import->shared_log_guid) {
|
||||
fnvlist_add_uint64(found_config,
|
||||
ZPOOL_CONFIG_SHARED_LOG_POOL,
|
||||
import->shared_log_guid);
|
||||
}
|
||||
err |= do_import(found_config, new_name,
|
||||
mntopts, props, flags, mount_tp_nthr);
|
||||
}
|
||||
|
@ -3982,6 +4094,7 @@ zpool_do_import(int argc, char **argv)
|
|||
char *cachefile = NULL;
|
||||
importargs_t idata = { 0 };
|
||||
char *endptr;
|
||||
zpool_handle_t *shared_log_pool = NULL;
|
||||
|
||||
struct option long_options[] = {
|
||||
{"rewind-to-checkpoint", no_argument, NULL, CHECKPOINT_OPT},
|
||||
|
@ -3989,7 +4102,7 @@ zpool_do_import(int argc, char **argv)
|
|||
};
|
||||
|
||||
/* check options */
|
||||
while ((c = getopt_long(argc, argv, ":aCc:d:DEfFlmnNo:R:stT:VX",
|
||||
while ((c = getopt_long(argc, argv, ":aCc:d:DEfFlL:mnNo:R:stT:VX",
|
||||
long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
|
@ -4015,6 +4128,14 @@ zpool_do_import(int argc, char **argv)
|
|||
case 'l':
|
||||
flags |= ZFS_IMPORT_LOAD_KEYS;
|
||||
break;
|
||||
case 'L':
|
||||
shared_log_pool = zpool_open(g_zfs, optarg);
|
||||
if (shared_log_pool == NULL) {
|
||||
(void) fprintf(stderr, gettext("could not open "
|
||||
"shared log pool '%s'"), optarg);
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
flags |= ZFS_IMPORT_MISSING_LOG;
|
||||
break;
|
||||
|
@ -4087,6 +4208,16 @@ zpool_do_import(int argc, char **argv)
|
|||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (shared_log_pool != NULL && ! (flags & ZFS_IMPORT_MISSING_LOG)) {
|
||||
(void) fprintf(stderr, gettext("-L requires -m\n"));
|
||||
usage(B_FALSE);
|
||||
}
|
||||
|
||||
if (shared_log_pool != NULL && do_all) {
|
||||
(void) fprintf(stderr, gettext("-L is incompatible with -a\n"));
|
||||
usage(B_FALSE);
|
||||
}
|
||||
|
||||
if (cachefile && nsearch != 0) {
|
||||
(void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
|
||||
usage(B_FALSE);
|
||||
|
@ -4210,6 +4341,10 @@ zpool_do_import(int argc, char **argv)
|
|||
idata.policy = policy;
|
||||
idata.do_destroyed = do_destroyed;
|
||||
idata.do_all = do_all;
|
||||
if (shared_log_pool) {
|
||||
idata.shared_log_guid = fnvlist_lookup_uint64(zpool_get_config(
|
||||
shared_log_pool, NULL), ZPOOL_CONFIG_POOL_GUID);
|
||||
}
|
||||
|
||||
libpc_handle_t lpch = {
|
||||
.lpc_lib_handle = g_zfs,
|
||||
|
@ -6569,7 +6704,7 @@ print_one_column(zpool_prop_t prop, uint64_t value, const char *str,
|
|||
*/
|
||||
static void
|
||||
print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
|
||||
list_cbdata_t *cb, int depth, boolean_t isspare)
|
||||
list_cbdata_t *cb, int depth, boolean_t isspare, boolean_t recurse)
|
||||
{
|
||||
nvlist_t **child;
|
||||
vdev_stat_t *vs;
|
||||
|
@ -6577,7 +6712,7 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
|
|||
char *vname;
|
||||
boolean_t scripted = cb->cb_scripted;
|
||||
uint64_t islog = B_FALSE;
|
||||
const char *dashes = "%-*s - - - - "
|
||||
const char *dashes = "%*s%-*s - - - - "
|
||||
"- - - - -\n";
|
||||
|
||||
verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
|
||||
|
@ -6647,7 +6782,7 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
|
|||
(void) fputc('\n', stdout);
|
||||
}
|
||||
|
||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
||||
if (!recurse || nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
||||
&child, &children) != 0)
|
||||
return;
|
||||
|
||||
|
@ -6668,7 +6803,8 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
|
|||
|
||||
vname = zpool_vdev_name(g_zfs, zhp, child[c],
|
||||
cb->cb_name_flags | VDEV_NAME_TYPE_ID);
|
||||
print_list_stats(zhp, vname, child[c], cb, depth + 2, B_FALSE);
|
||||
print_list_stats(zhp, vname, child[c], cb, depth + 2, B_FALSE,
|
||||
B_TRUE);
|
||||
free(vname);
|
||||
}
|
||||
|
||||
|
@ -6696,27 +6832,45 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
|
|||
|
||||
if (!printed) {
|
||||
/* LINTED E_SEC_PRINTF_VAR_FMT */
|
||||
(void) printf(dashes, cb->cb_namewidth,
|
||||
class_name[n]);
|
||||
(void) printf(dashes, depth + 2, "",
|
||||
cb->cb_namewidth, class_name[n]);
|
||||
printed = B_TRUE;
|
||||
}
|
||||
vname = zpool_vdev_name(g_zfs, zhp, child[c],
|
||||
cb->cb_name_flags | VDEV_NAME_TYPE_ID);
|
||||
print_list_stats(zhp, vname, child[c], cb, depth + 2,
|
||||
B_FALSE);
|
||||
print_list_stats(zhp, vname, child[c], cb, depth + 4,
|
||||
B_FALSE, B_TRUE);
|
||||
free(vname);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t shared_log_guid;
|
||||
if (name == NULL && nvlist_lookup_uint64(zpool_get_config(zhp, NULL),
|
||||
ZPOOL_CONFIG_SHARED_LOG_POOL, &shared_log_guid) == 0) {
|
||||
(void) printf(dashes, depth + 2, "", cb->cb_namewidth,
|
||||
"shared log");
|
||||
zpool_handle_t *shared_log = find_by_guid(g_zfs,
|
||||
shared_log_guid);
|
||||
VERIFY(shared_log);
|
||||
nvlist_t *shared_log_config = zpool_get_config(shared_log,
|
||||
NULL);
|
||||
nvlist_t *nvroot;
|
||||
VERIFY0(nvlist_lookup_nvlist(shared_log_config,
|
||||
ZPOOL_CONFIG_VDEV_TREE, &nvroot));
|
||||
print_list_stats(shared_log, zpool_get_name(shared_log), nvroot,
|
||||
cb, depth + 4, B_FALSE, B_FALSE);
|
||||
zpool_close(shared_log);
|
||||
}
|
||||
|
||||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
|
||||
&child, &children) == 0 && children > 0) {
|
||||
/* LINTED E_SEC_PRINTF_VAR_FMT */
|
||||
(void) printf(dashes, cb->cb_namewidth, "cache");
|
||||
(void) printf(dashes, depth + 2, "", cb->cb_namewidth, "cache");
|
||||
for (c = 0; c < children; c++) {
|
||||
vname = zpool_vdev_name(g_zfs, zhp, child[c],
|
||||
cb->cb_name_flags);
|
||||
print_list_stats(zhp, vname, child[c], cb, depth + 2,
|
||||
B_FALSE);
|
||||
print_list_stats(zhp, vname, child[c], cb, depth + 4,
|
||||
B_FALSE, B_TRUE);
|
||||
free(vname);
|
||||
}
|
||||
}
|
||||
|
@ -6724,12 +6878,12 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
|
|||
if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
|
||||
&children) == 0 && children > 0) {
|
||||
/* LINTED E_SEC_PRINTF_VAR_FMT */
|
||||
(void) printf(dashes, cb->cb_namewidth, "spare");
|
||||
(void) printf(dashes, depth + 2, "", cb->cb_namewidth, "spare");
|
||||
for (c = 0; c < children; c++) {
|
||||
vname = zpool_vdev_name(g_zfs, zhp, child[c],
|
||||
cb->cb_name_flags);
|
||||
print_list_stats(zhp, vname, child[c], cb, depth + 2,
|
||||
B_TRUE);
|
||||
print_list_stats(zhp, vname, child[c], cb, depth + 4,
|
||||
B_TRUE, B_TRUE);
|
||||
free(vname);
|
||||
}
|
||||
}
|
||||
|
@ -6751,7 +6905,7 @@ list_callback(zpool_handle_t *zhp, void *data)
|
|||
config = zpool_get_config(zhp, NULL);
|
||||
verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
|
||||
&nvroot) == 0);
|
||||
print_list_stats(zhp, NULL, nvroot, cbp, 0, B_FALSE);
|
||||
print_list_stats(zhp, NULL, nvroot, cbp, 0, B_FALSE, B_TRUE);
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
@ -6908,7 +7062,7 @@ zpool_do_attach_or_replace(int argc, char **argv, int replacing)
|
|||
boolean_t rebuild = B_FALSE;
|
||||
boolean_t wait = B_FALSE;
|
||||
int c;
|
||||
nvlist_t *nvroot;
|
||||
nvlist_t *nvroot, *config;
|
||||
char *poolname, *old_disk, *new_disk;
|
||||
zpool_handle_t *zhp;
|
||||
nvlist_t *props = NULL;
|
||||
|
@ -6991,7 +7145,7 @@ zpool_do_attach_or_replace(int argc, char **argv, int replacing)
|
|||
return (1);
|
||||
}
|
||||
|
||||
if (zpool_get_config(zhp, NULL) == NULL) {
|
||||
if ((config = zpool_get_config(zhp, NULL)) == NULL) {
|
||||
(void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
|
||||
poolname);
|
||||
zpool_close(zhp);
|
||||
|
@ -7013,8 +7167,12 @@ zpool_do_attach_or_replace(int argc, char **argv, int replacing)
|
|||
}
|
||||
}
|
||||
|
||||
uint64_t shared_log;
|
||||
boolean_t has_shared_log = nvlist_lookup_uint64(config,
|
||||
ZPOOL_CONFIG_SHARED_LOG_POOL, &shared_log) == 0;
|
||||
|
||||
nvroot = make_root_vdev(zhp, props, force, B_FALSE, replacing, B_FALSE,
|
||||
argc, argv);
|
||||
has_shared_log, argc, argv);
|
||||
if (nvroot == NULL) {
|
||||
zpool_close(zhp);
|
||||
nvlist_free(props);
|
||||
|
@ -7938,6 +8096,116 @@ zpool_do_resilver(int argc, char **argv)
|
|||
B_FALSE, scrub_callback, &cb));
|
||||
}
|
||||
|
||||
struct recycle_data {
|
||||
boolean_t dryrun;
|
||||
boolean_t verbose;
|
||||
};
|
||||
|
||||
static void
|
||||
print_recycle_info(nvlist_t *nvl, boolean_t dryrun)
|
||||
{
|
||||
printf("Cleaned up%s: [", dryrun ? " (dry run)" : "");
|
||||
nvpair_t *elem = NULL;
|
||||
boolean_t first = B_TRUE;
|
||||
while ((elem = nvlist_next_nvpair(nvl, elem))) {
|
||||
printf("%s%s", first ? "" : ",\n\t", nvpair_name(elem));
|
||||
first = B_FALSE;
|
||||
}
|
||||
printf("]\n");
|
||||
}
|
||||
|
||||
static int
|
||||
recycle_callback(zpool_handle_t *zhp, void *data)
|
||||
{
|
||||
struct recycle_data *rd = data;
|
||||
nvlist_t *nvl;
|
||||
|
||||
int err = lzc_recycle(zpool_get_name(zhp), NULL, rd->dryrun, &nvl);
|
||||
if (err)
|
||||
return (err);
|
||||
if (rd->verbose)
|
||||
print_recycle_info(nvl, rd->dryrun);
|
||||
nvlist_free(nvl);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* zpool recycle [-a] [-n] [-v] <pool> [pool]...
|
||||
*
|
||||
* Cleans up chain maps for non-attached client pools
|
||||
*/
|
||||
int
|
||||
zpool_do_recycle(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
struct recycle_data rd = {0};
|
||||
boolean_t doall = B_FALSE;
|
||||
|
||||
/* check options */
|
||||
while ((c = getopt(argc, argv, "nva")) != -1) {
|
||||
switch (c) {
|
||||
case 'n':
|
||||
rd.dryrun = B_TRUE;
|
||||
zfs_fallthrough;
|
||||
case 'v':
|
||||
rd.verbose = B_TRUE;
|
||||
break;
|
||||
case 'a':
|
||||
doall = B_TRUE;
|
||||
break;
|
||||
case '?':
|
||||
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
|
||||
optopt);
|
||||
usage(B_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 1) {
|
||||
(void) fprintf(stderr, gettext("missing pool name argument\n"));
|
||||
usage(B_FALSE);
|
||||
} else if (argc == 1 && !doall) {
|
||||
(void) fprintf(stderr, gettext("missing client pools\n"));
|
||||
usage(B_FALSE);
|
||||
} else if (argc > 1 && doall) {
|
||||
(void) fprintf(stderr, gettext("specific client pools and "
|
||||
"do_all\n"));
|
||||
usage(B_FALSE);
|
||||
}
|
||||
|
||||
if (doall) {
|
||||
return (for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
|
||||
B_FALSE, recycle_callback, &rd));
|
||||
}
|
||||
|
||||
const char *pool = argv[0];
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
nvlist_t *clients = NULL;
|
||||
if (argc > 0)
|
||||
clients = fnvlist_alloc();
|
||||
while (argc > 0) {
|
||||
fnvlist_add_boolean(clients, argv[0]);
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
nvlist_t *nvl;
|
||||
int err = lzc_recycle(pool, clients, rd.dryrun, &nvl);
|
||||
if (clients)
|
||||
nvlist_free(clients);
|
||||
if (err)
|
||||
return (err);
|
||||
if (rd.verbose)
|
||||
print_recycle_info(nvl, rd.dryrun);
|
||||
nvlist_free(nvl);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* zpool trim [-d] [-r <rate>] [-c | -s] <pool> [<device> ...]
|
||||
*
|
||||
|
@ -8838,7 +9106,8 @@ print_spares(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **spares,
|
|||
for (i = 0; i < nspares; i++) {
|
||||
name = zpool_vdev_name(g_zfs, zhp, spares[i],
|
||||
cb->cb_name_flags);
|
||||
print_status_config(zhp, cb, name, spares[i], 2, B_TRUE, NULL);
|
||||
print_status_config(zhp, cb, name, spares[i], 2, B_TRUE, B_TRUE,
|
||||
NULL);
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
|
@ -8859,7 +9128,7 @@ print_l2cache(zpool_handle_t *zhp, status_cbdata_t *cb, nvlist_t **l2cache,
|
|||
name = zpool_vdev_name(g_zfs, zhp, l2cache[i],
|
||||
cb->cb_name_flags);
|
||||
print_status_config(zhp, cb, name, l2cache[i], 2,
|
||||
B_FALSE, NULL);
|
||||
B_FALSE, B_TRUE, NULL);
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
|
@ -9401,12 +9670,18 @@ status_callback(zpool_handle_t *zhp, void *data)
|
|||
printf("\n");
|
||||
|
||||
print_status_config(zhp, cbp, zpool_get_name(zhp), nvroot, 0,
|
||||
B_FALSE, NULL);
|
||||
B_FALSE, B_TRUE, NULL);
|
||||
|
||||
print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_DEDUP);
|
||||
print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_BIAS_SPECIAL);
|
||||
print_class_vdevs(zhp, cbp, nvroot, VDEV_ALLOC_CLASS_LOGS);
|
||||
|
||||
uint64_t shared_log_guid;
|
||||
if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_SHARED_LOG_POOL,
|
||||
&shared_log_guid) == 0) {
|
||||
print_shared_log(zhp, cbp, shared_log_guid);
|
||||
}
|
||||
|
||||
if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
|
||||
&l2cache, &nl2cache) == 0)
|
||||
print_l2cache(zhp, cbp, l2cache, nl2cache);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef ZPOOL_UTIL_H
|
||||
|
@ -57,8 +58,8 @@ char *zpool_get_cmd_search_path(void);
|
|||
*/
|
||||
|
||||
nvlist_t *make_root_vdev(zpool_handle_t *zhp, nvlist_t *props, int force,
|
||||
int check_rep, boolean_t replacing, boolean_t dryrun, int argc,
|
||||
char **argv);
|
||||
int check_rep, boolean_t replacing, boolean_t dryrun,
|
||||
boolean_t have_shlog, int argc, char **argv);
|
||||
nvlist_t *split_mirror_vdev(zpool_handle_t *zhp, char *newname,
|
||||
nvlist_t *props, splitflags_t flags, int argc, char **argv);
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013, 2023 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2016, 2017 Intel Corporation.
|
||||
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
|
||||
*/
|
||||
|
@ -1488,7 +1488,7 @@ draid_config_by_type(nvlist_t *nv, const char *type, uint64_t children)
|
|||
* because the program is just going to exit anyway.
|
||||
*/
|
||||
static nvlist_t *
|
||||
construct_spec(nvlist_t *props, int argc, char **argv)
|
||||
construct_spec(nvlist_t *props, boolean_t have_shlog, int argc, char **argv)
|
||||
{
|
||||
nvlist_t *nvroot, *nv, **top, **spares, **l2cache;
|
||||
int t, toplevels, mindev, maxdev, nspares, nlogs, nl2cache;
|
||||
|
@ -1735,6 +1735,12 @@ construct_spec(nvlist_t *props, int argc, char **argv)
|
|||
goto spec_out;
|
||||
}
|
||||
|
||||
if (seen_logs && have_shlog) {
|
||||
(void) fprintf(stderr, gettext("invalid vdev specification: "
|
||||
"cannot mix shared log and log devices"));
|
||||
goto spec_out;
|
||||
}
|
||||
|
||||
if (seen_logs && nlogs == 0) {
|
||||
(void) fprintf(stderr, gettext("invalid vdev specification: "
|
||||
"log requires at least 1 device\n"));
|
||||
|
@ -1779,7 +1785,8 @@ split_mirror_vdev(zpool_handle_t *zhp, char *newname, nvlist_t *props,
|
|||
uint_t c, children;
|
||||
|
||||
if (argc > 0) {
|
||||
if ((newroot = construct_spec(props, argc, argv)) == NULL) {
|
||||
if ((newroot = construct_spec(props, B_FALSE, argc, argv)) ==
|
||||
NULL) {
|
||||
(void) fprintf(stderr, gettext("Unable to build a "
|
||||
"pool from the specified devices\n"));
|
||||
return (NULL);
|
||||
|
@ -1853,7 +1860,8 @@ num_normal_vdevs(nvlist_t *nvroot)
|
|||
*/
|
||||
nvlist_t *
|
||||
make_root_vdev(zpool_handle_t *zhp, nvlist_t *props, int force, int check_rep,
|
||||
boolean_t replacing, boolean_t dryrun, int argc, char **argv)
|
||||
boolean_t replacing, boolean_t dryrun, boolean_t have_shlog, int argc,
|
||||
char **argv)
|
||||
{
|
||||
nvlist_t *newroot;
|
||||
nvlist_t *poolconfig = NULL;
|
||||
|
@ -1864,7 +1872,7 @@ make_root_vdev(zpool_handle_t *zhp, nvlist_t *props, int force, int check_rep,
|
|||
* that we have a valid specification, and that all devices can be
|
||||
* opened.
|
||||
*/
|
||||
if ((newroot = construct_spec(props, argc, argv)) == NULL)
|
||||
if ((newroot = construct_spec(props, have_shlog, argc, argv)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (zhp && ((poolconfig = zpool_get_config(zhp, NULL)) == NULL)) {
|
||||
|
|
12
cmd/ztest.c
12
cmd/ztest.c
|
@ -3048,7 +3048,7 @@ ztest_spa_create_destroy(ztest_ds_t *zd, uint64_t id)
|
|||
* an export concurrently.
|
||||
*/
|
||||
VERIFY0(spa_open(zo->zo_pool, &spa, FTAG));
|
||||
int error = spa_destroy(zo->zo_pool);
|
||||
int error = spa_destroy(zo->zo_pool, NULL);
|
||||
if (error != EBUSY && error != ZFS_ERR_EXPORT_IN_PROGRESS) {
|
||||
fatal(B_FALSE, "spa_destroy(%s) returned unexpected value %d",
|
||||
spa->spa_name, error);
|
||||
|
@ -3150,7 +3150,7 @@ ztest_spa_upgrade(ztest_ds_t *zd, uint64_t id)
|
|||
/*
|
||||
* Clean up from previous runs.
|
||||
*/
|
||||
(void) spa_destroy(name);
|
||||
(void) spa_destroy(name, NULL);
|
||||
|
||||
raidz_children = ztest_get_raidz_children(ztest_spa);
|
||||
|
||||
|
@ -3604,7 +3604,7 @@ ztest_split_pool(ztest_ds_t *zd, uint64_t id)
|
|||
}
|
||||
|
||||
/* clean up the old pool, if any */
|
||||
(void) spa_destroy("splitp");
|
||||
(void) spa_destroy("splitp", NULL);
|
||||
|
||||
spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
|
||||
|
||||
|
@ -7384,7 +7384,7 @@ ztest_spa_import_export(char *oldname, char *newname)
|
|||
/*
|
||||
* Clean up from previous runs.
|
||||
*/
|
||||
(void) spa_destroy(newname);
|
||||
(void) spa_destroy(newname, NULL);
|
||||
|
||||
/*
|
||||
* Get the pool's configuration and guid.
|
||||
|
@ -7405,7 +7405,7 @@ ztest_spa_import_export(char *oldname, char *newname)
|
|||
/*
|
||||
* Export it.
|
||||
*/
|
||||
VERIFY0(spa_export(oldname, &config, B_FALSE, B_FALSE));
|
||||
VERIFY0(spa_export(oldname, &config, B_FALSE, B_FALSE, NULL));
|
||||
|
||||
ztest_walk_pool_directory("pools after export");
|
||||
|
||||
|
@ -8556,7 +8556,7 @@ ztest_init(ztest_shared_t *zs)
|
|||
/*
|
||||
* Create the storage pool.
|
||||
*/
|
||||
(void) spa_destroy(ztest_opts.zo_pool);
|
||||
(void) spa_destroy(ztest_opts.zo_pool, NULL);
|
||||
ztest_shared->zs_vdev_next_leaf = 0;
|
||||
zs->zs_splits = 0;
|
||||
zs->zs_mirrors = ztest_opts.zo_mirrors;
|
||||
|
|
|
@ -159,6 +159,8 @@ typedef enum zfs_error {
|
|||
EZFS_SHAREFAILED, /* filesystem share failed */
|
||||
EZFS_RAIDZ_EXPAND_IN_PROGRESS, /* a raidz is currently expanding */
|
||||
EZFS_ASHIFT_MISMATCH, /* can't add vdevs with different ashifts */
|
||||
/* Operation cannot be performed on a shared log pool */
|
||||
EZFS_SHAREDLOG,
|
||||
EZFS_UNKNOWN
|
||||
} zfs_error_t;
|
||||
|
||||
|
@ -344,6 +346,7 @@ _LIBZFS_H uint64_t zpool_vdev_path_to_guid(zpool_handle_t *zhp,
|
|||
const char *path);
|
||||
|
||||
_LIBZFS_H const char *zpool_get_state_str(zpool_handle_t *);
|
||||
_LIBZFS_H zpool_handle_t *zpool_get_shared_log(zpool_handle_t *);
|
||||
|
||||
/*
|
||||
* Functions to manage pool properties
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012, 2020 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, 2023 by Delphix. All rights reserved.
|
||||
* Copyright 2017 RackTop Systems.
|
||||
* Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
|
||||
* Copyright (c) 2019 Datto Inc.
|
||||
|
@ -156,11 +156,18 @@ _LIBZFS_CORE_H int lzc_wait_fs(const char *, zfs_wait_activity_t, boolean_t *);
|
|||
_LIBZFS_CORE_H int lzc_set_bootenv(const char *, const nvlist_t *);
|
||||
_LIBZFS_CORE_H int lzc_get_bootenv(const char *, nvlist_t **);
|
||||
|
||||
_LIBZFS_CORE_H int lzc_recycle(const char *, nvlist_t *, boolean_t,
|
||||
nvlist_t **);
|
||||
|
||||
_LIBZFS_CORE_H int lzc_get_vdev_prop(const char *, nvlist_t *, nvlist_t **);
|
||||
_LIBZFS_CORE_H int lzc_set_vdev_prop(const char *, nvlist_t *, nvlist_t **);
|
||||
|
||||
_LIBZFS_CORE_H int lzc_scrub(zfs_ioc_t, const char *, nvlist_t *, nvlist_t **);
|
||||
|
||||
_LIBZFS_CORE_H int lzc_pool_destroy(const char *, const char *, nvlist_t **);
|
||||
_LIBZFS_CORE_H int lzc_pool_export(const char *, const char *, boolean_t,
|
||||
boolean_t, nvlist_t **);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -81,6 +81,7 @@ typedef struct importargs {
|
|||
nvlist_t *policy; /* load policy (max txg, rewind, etc.) */
|
||||
boolean_t do_destroyed;
|
||||
boolean_t do_all;
|
||||
uint64_t shared_log_guid;
|
||||
} importargs_t;
|
||||
|
||||
typedef struct libpc_handle {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2020 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2023 by Delphix. All rights reserved.
|
||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||
* Copyright 2014 HybridCluster. All rights reserved.
|
||||
|
@ -390,6 +390,7 @@ typedef struct dmu_buf {
|
|||
#define DMU_POOL_ZPOOL_CHECKPOINT "com.delphix:zpool_checkpoint"
|
||||
#define DMU_POOL_LOG_SPACEMAP_ZAP "com.delphix:log_spacemap_zap"
|
||||
#define DMU_POOL_DELETED_CLONES "com.delphix:deleted_clones"
|
||||
#define DMU_POOL_CHAIN_MAP_OBJ "com.delphix:chain_map_obj"
|
||||
|
||||
/*
|
||||
* Allocate an object from this objset. The range of object numbers
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
* Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, 2013 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_DMU_TX_H
|
||||
|
@ -154,6 +154,7 @@ void dmu_tx_wait(dmu_tx_t *tx);
|
|||
*/
|
||||
extern dmu_tx_t *dmu_tx_create_assigned(struct dsl_pool *dp, uint64_t txg);
|
||||
|
||||
dmu_tx_t *dmu_tx_create_mos(struct dsl_pool *dp);
|
||||
/*
|
||||
* These routines are only called by the DMU.
|
||||
*/
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013, 2023 by Delphix. All rights reserved.
|
||||
* Copyright 2016 Nexenta Systems, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -106,6 +106,7 @@ typedef struct dsl_pool {
|
|||
uint64_t dp_bptree_obj;
|
||||
uint64_t dp_empty_bpobj;
|
||||
bpobj_t dp_obsolete_bpobj;
|
||||
uint64_t dp_chain_map_obj;
|
||||
|
||||
struct dsl_scan *dp_scan;
|
||||
|
||||
|
|
|
@ -851,6 +851,8 @@ typedef struct zpool_load_policy {
|
|||
#define ZPOOL_CONFIG_EXPANSION_TIME "expansion_time" /* not stored */
|
||||
#define ZPOOL_CONFIG_REBUILD_STATS "org.openzfs:rebuild_stats"
|
||||
#define ZPOOL_CONFIG_COMPATIBILITY "compatibility"
|
||||
#define ZPOOL_CONFIG_SHARED_LOG_POOL "com.delphix:shared_log_pool"
|
||||
#define ZPOOL_CONFIG_IS_SHARED_LOG "com.delphix:is_shared_log"
|
||||
|
||||
/*
|
||||
* The persistent vdev state is stored as separate values rather than a single
|
||||
|
@ -1518,7 +1520,10 @@ typedef enum zfs_ioc {
|
|||
ZFS_IOC_VDEV_GET_PROPS, /* 0x5a55 */
|
||||
ZFS_IOC_VDEV_SET_PROPS, /* 0x5a56 */
|
||||
ZFS_IOC_POOL_SCRUB, /* 0x5a57 */
|
||||
ZFS_IOC_POOL_PREFETCH, /* 0x5a58 */
|
||||
ZFS_IOC_POOL_PREFETCH, /* 0x5158 */
|
||||
ZFS_IOC_POOL_RECYCLE, /* 0x5a59 */
|
||||
ZFS_IOC_POOL_DESTROY_NEW, /* 0x5a59 */
|
||||
ZFS_IOC_POOL_EXPORT_NEW, /* 0x5a5a */
|
||||
|
||||
/*
|
||||
* Per-platform (Optional) - 8/128 numbers reserved.
|
||||
|
@ -1748,6 +1753,23 @@ typedef enum {
|
|||
*/
|
||||
#define ZPOOL_PREFETCH_TYPE "prefetch_type"
|
||||
|
||||
/*
|
||||
* The following names are used when invoking ZFS_IOC_POOL_RECYCLE.
|
||||
*/
|
||||
#define ZPOOL_RECYCLE_DRYRUN "dryrun"
|
||||
#define ZPOOL_RECYCLE_CLIENTS "clients"
|
||||
|
||||
/*
|
||||
* The following are names used when invoking ZFS_IOC_POOL_EXPORT_NEW.
|
||||
*/
|
||||
#define ZPOOL_EXPORT_FORCE "force"
|
||||
#define ZPOOL_EXPORT_HARDFORCE "hardforce"
|
||||
|
||||
/*
|
||||
* Name that is used to convey client information for shared log pools.
|
||||
*/
|
||||
#define ZPOOL_SHARED_LOG_CLIENTS "clients"
|
||||
|
||||
/*
|
||||
* Flags for ZFS_IOC_VDEV_SET_STATE
|
||||
*/
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2023 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2017, Intel Corporation.
|
||||
*/
|
||||
|
||||
|
@ -37,14 +37,20 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum metaslab_type {
|
||||
METASLAB_TYPE_NORMAL,
|
||||
METASLAB_TYPE_VIRTUAL,
|
||||
} metaslab_type_t;
|
||||
|
||||
typedef struct metaslab_ops {
|
||||
const char *msop_name;
|
||||
uint64_t (*msop_alloc)(metaslab_t *, uint64_t);
|
||||
metaslab_type_t msop_type;
|
||||
} metaslab_ops_t;
|
||||
|
||||
|
||||
extern const metaslab_ops_t zfs_metaslab_ops;
|
||||
extern const metaslab_ops_t zfs_virtual_ops;
|
||||
|
||||
int metaslab_init(metaslab_group_t *, uint64_t, uint64_t, uint64_t,
|
||||
metaslab_t **);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011, 2019 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2023 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_METASLAB_IMPL_H
|
||||
|
@ -179,7 +179,15 @@ typedef struct metaslab_class_allocator {
|
|||
struct metaslab_class {
|
||||
kmutex_t mc_lock;
|
||||
spa_t *mc_spa;
|
||||
const metaslab_ops_t *mc_ops;
|
||||
const metaslab_ops_t *mc_ops;
|
||||
/*
|
||||
* If this field is set, this is a "virtual" metaslab class. In
|
||||
* actuality, the allocations will be done by the spa this is pointing
|
||||
* to, using another pool for our storage. This enables the shared
|
||||
* SLOG architecture. If this field is set, most of the other fields
|
||||
* in this metaslab class are not used, and should be unset.
|
||||
*/
|
||||
struct spa *mc_virtual;
|
||||
|
||||
/*
|
||||
* Track the number of metaslab groups that have been initialized
|
||||
|
|
|
@ -749,11 +749,11 @@ extern int spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
|
|||
extern int spa_import(char *pool, nvlist_t *config, nvlist_t *props,
|
||||
uint64_t flags);
|
||||
extern nvlist_t *spa_tryimport(nvlist_t *tryconfig);
|
||||
extern int spa_destroy(const char *pool);
|
||||
extern int spa_destroy(const char *pool, nvlist_t *ounvl);
|
||||
extern int spa_checkpoint(const char *pool);
|
||||
extern int spa_checkpoint_discard(const char *pool);
|
||||
extern int spa_export(const char *pool, nvlist_t **oldconfig, boolean_t force,
|
||||
boolean_t hardforce);
|
||||
boolean_t hardforce, nvlist_t *outnvl);
|
||||
extern int spa_reset(const char *pool);
|
||||
extern void spa_async_request(spa_t *spa, int flag);
|
||||
extern void spa_async_unrequest(spa_t *spa, int flag);
|
||||
|
@ -836,6 +836,8 @@ void spa_select_allocator(zio_t *zio);
|
|||
extern kmutex_t spa_namespace_lock;
|
||||
extern avl_tree_t spa_namespace_avl;
|
||||
extern kcondvar_t spa_namespace_cv;
|
||||
extern avl_tree_t spa_shared_log_avl;
|
||||
extern kmutex_t spa_shared_log_lock;
|
||||
|
||||
/*
|
||||
* SPA configuration functions in spa_config.c
|
||||
|
@ -1028,7 +1030,8 @@ extern void spa_altroot(spa_t *, char *, size_t);
|
|||
extern uint32_t spa_sync_pass(spa_t *spa);
|
||||
extern char *spa_name(spa_t *spa);
|
||||
extern uint64_t spa_guid(spa_t *spa);
|
||||
extern uint64_t spa_load_guid(spa_t *spa);
|
||||
extern uint64_t spa_const_guid(const spa_t *spa);
|
||||
extern uint64_t spa_load_guid(const spa_t *spa);
|
||||
extern uint64_t spa_last_synced_txg(spa_t *spa);
|
||||
extern uint64_t spa_first_txg(spa_t *spa);
|
||||
extern uint64_t spa_syncing_txg(spa_t *spa);
|
||||
|
@ -1123,7 +1126,8 @@ extern boolean_t spa_multihost(spa_t *spa);
|
|||
extern uint32_t spa_get_hostid(spa_t *spa);
|
||||
extern void spa_activate_allocation_classes(spa_t *, dmu_tx_t *);
|
||||
extern boolean_t spa_livelist_delete_check(spa_t *spa);
|
||||
|
||||
extern boolean_t spa_is_shared_log(const spa_t *spa);
|
||||
extern boolean_t spa_uses_shared_log(const spa_t *spa);
|
||||
extern boolean_t spa_mmp_remote_host_activity(spa_t *spa);
|
||||
|
||||
extern spa_mode_t spa_mode(spa_t *spa);
|
||||
|
@ -1221,6 +1225,17 @@ extern void spa_export_os(spa_t *spa);
|
|||
extern void spa_activate_os(spa_t *spa);
|
||||
extern void spa_deactivate_os(spa_t *spa);
|
||||
|
||||
extern void spa_zil_map_insert(spa_t *spa, objset_t *os,
|
||||
const blkptr_t *prev_bp, blkptr_t *bp);
|
||||
extern void spa_zil_map_set_final(spa_t *spa, objset_t *os, blkptr_t *bp);
|
||||
extern void spa_zil_delete(spa_t *spa, objset_t *os);
|
||||
extern void spa_zil_header_convert(spa_t *spa, objset_t *os, blkptr_t *bp);
|
||||
extern void spa_zil_header_mask(spa_t *spa, blkptr_t *bp);
|
||||
extern spa_t *spa_get_shared_log_pool(spa_t *spa);
|
||||
extern int spa_recycle_all(spa_t *spa, boolean_t dryrun, nvlist_t *outnvl);
|
||||
extern int spa_recycle_clients(spa_t *spa, nvlist_t *clients,
|
||||
boolean_t dryrun, nvlist_t *outnvl);
|
||||
|
||||
/* module param call functions */
|
||||
int param_set_deadman_ziotime(ZFS_MODULE_PARAM_ARGS);
|
||||
int param_set_deadman_synctime(ZFS_MODULE_PARAM_ARGS);
|
||||
|
|
|
@ -217,6 +217,44 @@ typedef enum spa_config_source {
|
|||
SPA_CONFIG_SRC_MOS /* MOS, but not always from right txg */
|
||||
} spa_config_source_t;
|
||||
|
||||
typedef enum spa_pool_type {
|
||||
SPA_TYPE_NORMAL = 0,
|
||||
SPA_TYPE_SHARED_LOG,
|
||||
} spa_pool_type_t;
|
||||
|
||||
typedef struct spa_zil_update_head {
|
||||
avl_node_t szuh_avl;
|
||||
list_t szuh_list;
|
||||
uint64_t szuh_id;
|
||||
blkptr_t szuh_chain_head;
|
||||
boolean_t szuh_set;
|
||||
// Only used for the special once-per-pool entry
|
||||
boolean_t szuh_force;
|
||||
} spa_zil_update_head_t;
|
||||
|
||||
typedef struct spa_zil_update {
|
||||
list_node_t szu_list;
|
||||
blkptr_t szu_chain_head;
|
||||
} spa_zil_update_t;
|
||||
|
||||
typedef struct spa_zil_chain_map_value {
|
||||
char szcmv_pool_name[ZFS_MAX_DATASET_NAME_LEN];
|
||||
blkptr_t szcmv_bp;
|
||||
} spa_zil_chain_map_value_t;
|
||||
|
||||
typedef struct spa_chain_map_os {
|
||||
avl_node_t scmo_avl;
|
||||
uint64_t scmo_id;
|
||||
blkptr_t scmo_chain_head;
|
||||
} spa_chain_map_os_t;
|
||||
|
||||
typedef struct spa_chain_map_pool {
|
||||
avl_node_t scmp_avl;
|
||||
uint64_t scmp_guid;
|
||||
char scmp_name[ZFS_MAX_DATASET_NAME_LEN];
|
||||
avl_tree_t scmp_os_tree;
|
||||
} spa_chain_map_pool_t;
|
||||
|
||||
struct spa {
|
||||
/*
|
||||
* Fields protected by spa_namespace_lock.
|
||||
|
@ -224,6 +262,9 @@ struct spa {
|
|||
char spa_name[ZFS_MAX_DATASET_NAME_LEN]; /* pool name */
|
||||
char *spa_comment; /* comment */
|
||||
avl_node_t spa_avl; /* node in spa_namespace_avl */
|
||||
avl_node_t spa_log_avl; /* node in spa_shared_log_avl */
|
||||
/* node in spa_registered_clients */
|
||||
list_node_t spa_client_node;
|
||||
nvlist_t *spa_config; /* last synced config */
|
||||
nvlist_t *spa_config_syncing; /* currently syncing config */
|
||||
nvlist_t *spa_config_splitting; /* config for splitting */
|
||||
|
@ -244,6 +285,13 @@ struct spa {
|
|||
boolean_t spa_is_initializing; /* true while opening pool */
|
||||
boolean_t spa_is_exporting; /* true while exporting pool */
|
||||
kthread_t *spa_export_thread; /* valid during pool export */
|
||||
/* true if pool's log device is shared log */
|
||||
boolean_t spa_uses_shared_log;
|
||||
/*
|
||||
* true if pool was imported with MISSING_LOGS and couldn't find
|
||||
* its shared log pool
|
||||
*/
|
||||
boolean_t spa_discarding_shared_log;
|
||||
kthread_t *spa_load_thread; /* loading, no namespace lock */
|
||||
metaslab_class_t *spa_normal_class; /* normal data class */
|
||||
metaslab_class_t *spa_log_class; /* intent log data class */
|
||||
|
@ -303,6 +351,7 @@ struct spa {
|
|||
boolean_t spa_extreme_rewind; /* rewind past deferred frees */
|
||||
kmutex_t spa_scrub_lock; /* resilver/scrub lock */
|
||||
uint64_t spa_scrub_inflight; /* in-flight scrub bytes */
|
||||
spa_pool_type_t spa_pool_type;
|
||||
|
||||
/* in-flight verification bytes */
|
||||
uint64_t spa_load_verify_bytes;
|
||||
|
@ -477,6 +526,17 @@ struct spa {
|
|||
*/
|
||||
spa_config_lock_t spa_config_lock[SCL_LOCKS]; /* config changes */
|
||||
zfs_refcount_t spa_refcount; /* number of opens */
|
||||
|
||||
/* Only used if type is shared log */
|
||||
kmutex_t spa_chain_map_lock;
|
||||
avl_tree_t spa_chain_map;
|
||||
list_t spa_registered_clients;
|
||||
|
||||
/* Only used during syncing context if using shared log */
|
||||
kmutex_t spa_zil_map_lock;
|
||||
avl_tree_t spa_zil_map;
|
||||
list_t spa_zil_deletes;
|
||||
taskq_t *spa_chain_map_taskq;
|
||||
};
|
||||
|
||||
extern char *spa_config_path;
|
||||
|
@ -495,6 +555,7 @@ extern void spa_set_deadman_ziotime(hrtime_t ns);
|
|||
extern const char *spa_history_zone(void);
|
||||
extern const char *zfs_active_allocator;
|
||||
extern int param_set_active_allocator_common(const char *val);
|
||||
extern void spa_set_pool_type(spa_t *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, 2023 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
/* Portions Copyright 2010 Robert Milkowski */
|
||||
|
@ -563,10 +563,15 @@ typedef int zil_parse_lr_func_t(zilog_t *zilog, const lr_t *lr, void *arg,
|
|||
typedef int zil_replay_func_t(void *arg1, void *arg2, boolean_t byteswap);
|
||||
typedef int zil_get_data_t(void *arg, uint64_t arg2, lr_write_t *lr, char *dbuf,
|
||||
struct lwb *lwb, zio_t *zio);
|
||||
typedef int zil_parse_raw_blk_func_t(spa_t *spa, const blkptr_t *bp, void *arg);
|
||||
typedef int zil_parse_raw_lr_func_t(spa_t *spa, const lr_t *lr, void *arg);
|
||||
|
||||
extern int zil_parse(zilog_t *zilog, zil_parse_blk_func_t *parse_blk_func,
|
||||
zil_parse_lr_func_t *parse_lr_func, void *arg, uint64_t txg,
|
||||
boolean_t decrypt);
|
||||
extern int zil_parse_raw(spa_t *spa, const blkptr_t *bp,
|
||||
zil_parse_raw_blk_func_t *parse_func,
|
||||
zil_parse_raw_lr_func_t *parse_lr_func, void *arg);
|
||||
|
||||
extern void zil_init(void);
|
||||
extern void zil_fini(void);
|
||||
|
@ -594,6 +599,8 @@ extern void zil_commit_impl(zilog_t *zilog, uint64_t oid);
|
|||
extern void zil_remove_async(zilog_t *zilog, uint64_t oid);
|
||||
|
||||
extern int zil_reset(const char *osname, void *txarg);
|
||||
extern int zil_clear(struct dsl_pool *dp,
|
||||
struct dsl_dataset *ds, void *txarg);
|
||||
extern int zil_claim(struct dsl_pool *dp,
|
||||
struct dsl_dataset *ds, void *txarg);
|
||||
extern int zil_check_log_chain(struct dsl_pool *dp,
|
||||
|
@ -620,6 +627,8 @@ extern void zil_sums_fini(zil_sums_t *zs);
|
|||
extern void zil_kstat_values_update(zil_kstat_values_t *zs,
|
||||
zil_sums_t *zil_sums);
|
||||
|
||||
extern boolean_t zil_shared_log(zilog_t *zl);
|
||||
|
||||
extern int zil_replay_disable;
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, 2023 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
/* Portions Copyright 2010 Robert Milkowski */
|
||||
|
@ -190,6 +190,7 @@ struct zilog {
|
|||
kmutex_t zl_lock; /* protects most zilog_t fields */
|
||||
struct dsl_pool *zl_dmu_pool; /* DSL pool */
|
||||
spa_t *zl_spa; /* handle for read/write log */
|
||||
spa_t *zl_io_spa; /* handle for read/write log */
|
||||
const zil_header_t *zl_header; /* log header buffer */
|
||||
objset_t *zl_os; /* object set we're logging */
|
||||
zil_get_data_t *zl_get_data; /* callback to get object content */
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2023 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2017, Intel Corporation.
|
||||
|
@ -82,6 +82,7 @@ typedef enum spa_feature {
|
|||
SPA_FEATURE_AVZ_V2,
|
||||
SPA_FEATURE_REDACTION_LIST_SPILL,
|
||||
SPA_FEATURE_RAIDZ_EXPANSION,
|
||||
SPA_FEATURE_SHARED_LOG,
|
||||
SPA_FEATURES
|
||||
} spa_feature_t;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -22,7 +22,7 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2019 Joyent, Inc.
|
||||
* Copyright (c) 2011, 2020 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2023 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
||||
* Copyright (c) 2013 Martin Matuska. All rights reserved.
|
||||
|
@ -3869,6 +3869,10 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
|
|||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"invalid property value(s) specified"));
|
||||
return (zfs_error(hdl, EZFS_BADPROP, errbuf));
|
||||
case EINVAL:
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"cannot create filesystem in shared log pool"));
|
||||
return (zfs_error(hdl, EZFS_SHAREDLOG, errbuf));
|
||||
#ifdef _ILP32
|
||||
case EOVERFLOW:
|
||||
/*
|
||||
|
|
|
@ -246,6 +246,39 @@ zpool_pool_state_to_name(pool_state_t state)
|
|||
return (gettext("UNKNOWN"));
|
||||
}
|
||||
|
||||
struct shared_log_cbdata {
|
||||
uint64_t guid;
|
||||
zpool_handle_t *shared_log_pool;
|
||||
};
|
||||
|
||||
static int
|
||||
shared_log_cb(zpool_handle_t *hdl, void *arg)
|
||||
{
|
||||
struct shared_log_cbdata *data = arg;
|
||||
if (fnvlist_lookup_uint64(hdl->zpool_config, ZPOOL_CONFIG_POOL_GUID) ==
|
||||
data->guid) {
|
||||
data->shared_log_pool = hdl;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
zpool_handle_t *
|
||||
zpool_get_shared_log(zpool_handle_t *zhp)
|
||||
{
|
||||
uint64_t guid;
|
||||
if (nvlist_lookup_uint64(zhp->zpool_config,
|
||||
ZPOOL_CONFIG_SHARED_LOG_POOL, &guid) != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
struct shared_log_cbdata data;
|
||||
data.guid = guid;
|
||||
int err = zpool_iter(zhp->zpool_hdl, shared_log_cb, &data);
|
||||
if (err != 0) {
|
||||
return (NULL);
|
||||
}
|
||||
return (data.shared_log_pool);
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a pool handle, return the pool health string ("ONLINE", "DEGRADED",
|
||||
* "SUSPENDED", etc).
|
||||
|
@ -272,6 +305,10 @@ zpool_get_state_str(zpool_handle_t *zhp)
|
|||
vdev_stat_t *vs = (vdev_stat_t *)fnvlist_lookup_uint64_array(
|
||||
nvroot, ZPOOL_CONFIG_VDEV_STATS, &vsc);
|
||||
str = zpool_state_to_name(vs->vs_state, vs->vs_aux);
|
||||
zpool_handle_t *shared_log = zpool_get_shared_log(zhp);
|
||||
if (vs->vs_state == VDEV_STATE_HEALTHY && shared_log != NULL) {
|
||||
str = zpool_get_state_str(shared_log);
|
||||
}
|
||||
}
|
||||
return (str);
|
||||
}
|
||||
|
@ -1681,23 +1718,48 @@ zpool_destroy(zpool_handle_t *zhp, const char *log_str)
|
|||
libzfs_handle_t *hdl = zhp->zpool_hdl;
|
||||
char errbuf[ERRBUFLEN];
|
||||
|
||||
if (zhp->zpool_state == POOL_STATE_ACTIVE &&
|
||||
(zfp = zfs_open(hdl, zhp->zpool_name, ZFS_TYPE_FILESYSTEM)) == NULL)
|
||||
return (-1);
|
||||
nvlist_t *outnvl;
|
||||
int err = lzc_pool_destroy(zhp->zpool_name, log_str, &outnvl);
|
||||
if (err == ZFS_ERR_IOC_CMD_UNAVAIL) {
|
||||
if (zhp->zpool_state == POOL_STATE_ACTIVE &&
|
||||
(zfp = zfs_open(hdl, zhp->zpool_name, ZFS_TYPE_FILESYSTEM))
|
||||
== NULL)
|
||||
return (-1);
|
||||
|
||||
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
|
||||
zc.zc_history = (uint64_t)(uintptr_t)log_str;
|
||||
(void) strlcpy(zc.zc_name, zhp->zpool_name,
|
||||
sizeof (zc.zc_name));
|
||||
zc.zc_history = (uint64_t)(uintptr_t)log_str;
|
||||
if (zfs_ioctl(hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0)
|
||||
err = errno;
|
||||
else
|
||||
err = 0;
|
||||
}
|
||||
|
||||
if (zfs_ioctl(hdl, ZFS_IOC_POOL_DESTROY, &zc) != 0) {
|
||||
if (err != 0) {
|
||||
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
|
||||
"cannot destroy '%s'"), zhp->zpool_name);
|
||||
|
||||
if (errno == EROFS) {
|
||||
if (err == EROFS) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"one or more devices is read only"));
|
||||
(void) zfs_error(hdl, EZFS_BADDEV, errbuf);
|
||||
} else if (err == EBUSY && outnvl != NULL) {
|
||||
nvlist_t *clients = fnvlist_lookup_nvlist(outnvl,
|
||||
ZPOOL_SHARED_LOG_CLIENTS);
|
||||
nvpair_t *elem = nvlist_next_nvpair(clients, NULL);
|
||||
char buf[ERRBUFLEN];
|
||||
int idx = snprintf(buf, ERRBUFLEN, "%s",
|
||||
nvpair_name(elem));
|
||||
while ((elem = nvlist_next_nvpair(clients, elem))
|
||||
!= NULL && idx < ERRBUFLEN) {
|
||||
idx += snprintf(buf + idx, ERRBUFLEN - idx,
|
||||
", %s", nvpair_name(elem));
|
||||
}
|
||||
zfs_error_aux(hdl, "pool has active clients: %s", buf);
|
||||
(void) zfs_error(hdl, EZFS_BUSY, errbuf);
|
||||
fnvlist_free(outnvl);
|
||||
} else {
|
||||
(void) zpool_standard_error(hdl, errno, errbuf);
|
||||
(void) zpool_standard_error(hdl, err, errbuf);
|
||||
}
|
||||
|
||||
if (zfp)
|
||||
|
@ -1897,27 +1959,52 @@ zpool_export_common(zpool_handle_t *zhp, boolean_t force, boolean_t hardforce,
|
|||
{
|
||||
zfs_cmd_t zc = {"\0"};
|
||||
|
||||
(void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name));
|
||||
zc.zc_cookie = force;
|
||||
zc.zc_guid = hardforce;
|
||||
zc.zc_history = (uint64_t)(uintptr_t)log_str;
|
||||
nvlist_t *outnvl;
|
||||
int err = lzc_pool_export(zhp->zpool_name, log_str, force, hardforce,
|
||||
&outnvl);
|
||||
if (err == ZFS_ERR_IOC_CMD_UNAVAIL) {
|
||||
|
||||
if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0) {
|
||||
switch (errno) {
|
||||
case EXDEV:
|
||||
zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN,
|
||||
"use '-f' to override the following errors:\n"
|
||||
"'%s' has an active shared spare which could be"
|
||||
" used by other pools once '%s' is exported."),
|
||||
zhp->zpool_name, zhp->zpool_name);
|
||||
return (zfs_error_fmt(zhp->zpool_hdl, EZFS_ACTIVE_SPARE,
|
||||
dgettext(TEXT_DOMAIN, "cannot export '%s'"),
|
||||
zhp->zpool_name));
|
||||
default:
|
||||
return (zpool_standard_error_fmt(zhp->zpool_hdl, errno,
|
||||
dgettext(TEXT_DOMAIN, "cannot export '%s'"),
|
||||
zhp->zpool_name));
|
||||
(void) strlcpy(zc.zc_name, zhp->zpool_name,
|
||||
sizeof (zc.zc_name));
|
||||
zc.zc_cookie = force;
|
||||
zc.zc_guid = hardforce;
|
||||
zc.zc_history = (uint64_t)(uintptr_t)log_str;
|
||||
|
||||
if (zfs_ioctl(zhp->zpool_hdl, ZFS_IOC_POOL_EXPORT, &zc) != 0)
|
||||
err = errno;
|
||||
else
|
||||
err = 0;
|
||||
}
|
||||
|
||||
if (err == EXDEV) {
|
||||
zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN,
|
||||
"use '-f' to override the following errors:\n"
|
||||
"'%s' has an active shared spare which could be"
|
||||
" used by other pools once '%s' is exported."),
|
||||
zhp->zpool_name, zhp->zpool_name);
|
||||
return (zfs_error_fmt(zhp->zpool_hdl, EZFS_ACTIVE_SPARE,
|
||||
dgettext(TEXT_DOMAIN, "cannot export '%s'"),
|
||||
zhp->zpool_name));
|
||||
} else if (err == EBUSY && outnvl != NULL) {
|
||||
libzfs_handle_t *hdl = zhp->zpool_hdl;
|
||||
nvlist_t *clients = fnvlist_lookup_nvlist(outnvl,
|
||||
ZPOOL_SHARED_LOG_CLIENTS);
|
||||
nvpair_t *elem = nvlist_next_nvpair(clients, NULL);
|
||||
char buf[ERRBUFLEN];
|
||||
int idx = snprintf(buf, ERRBUFLEN, "%s", nvpair_name(elem));
|
||||
while ((elem = nvlist_next_nvpair(clients, elem)) != NULL &&
|
||||
idx < ERRBUFLEN) {
|
||||
idx += snprintf(buf + idx, ERRBUFLEN - idx, ", %s",
|
||||
nvpair_name(elem));
|
||||
}
|
||||
fnvlist_free(outnvl);
|
||||
zfs_error_aux(hdl, "pool has active clients: %s", buf);
|
||||
return (zfs_error_fmt(hdl, EZFS_BUSY, dgettext(TEXT_DOMAIN,
|
||||
"cannot export '%s'"), zhp->zpool_name));
|
||||
} else if (err != 0) {
|
||||
return (zpool_standard_error_fmt(zhp->zpool_hdl, errno,
|
||||
dgettext(TEXT_DOMAIN, "cannot export '%s'"),
|
||||
zhp->zpool_name));
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
@ -2350,6 +2437,11 @@ zpool_import_props(libzfs_handle_t *hdl, nvlist_t *config, const char *newname,
|
|||
"the maximum allowable length"));
|
||||
(void) zfs_error(hdl, EZFS_NAMETOOLONG, desc);
|
||||
break;
|
||||
case ESRCH:
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"shared log pool no longer contains this client"));
|
||||
(void) zfs_error(hdl, EZFS_NOENT, desc);
|
||||
break;
|
||||
default:
|
||||
(void) zpool_standard_error(hdl, error, desc);
|
||||
zpool_explain_recover(hdl,
|
||||
|
|
|
@ -510,6 +510,10 @@ zpool_get_status(zpool_handle_t *zhp, const char **msgid,
|
|||
|
||||
zpool_status_t ret = check_status(zhp->zpool_config, B_FALSE, errata,
|
||||
compatibility);
|
||||
if (ret == ZPOOL_STATUS_OK && zpool_get_shared_log(zhp)) {
|
||||
ret = check_status(zpool_get_shared_log(zhp)->zpool_config,
|
||||
B_FALSE, errata, compatibility);
|
||||
}
|
||||
|
||||
if (msgid != NULL) {
|
||||
if (ret >= NMSGID)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2012, 2020 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, 2023 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
||||
* Copyright 2017 RackTop Systems.
|
||||
* Copyright (c) 2017 Open-E, Inc. All Rights Reserved.
|
||||
|
@ -1927,3 +1927,39 @@ lzc_get_bootenv(const char *pool, nvlist_t **outnvl)
|
|||
{
|
||||
return (lzc_ioctl(ZFS_IOC_GET_BOOTENV, pool, NULL, outnvl));
|
||||
}
|
||||
|
||||
int
|
||||
lzc_recycle(const char *pool, nvlist_t *clients, boolean_t dryrun,
|
||||
nvlist_t **outnvl)
|
||||
{
|
||||
nvlist_t *args = fnvlist_alloc();
|
||||
fnvlist_add_boolean_value(args, ZPOOL_RECYCLE_DRYRUN, dryrun);
|
||||
if (clients != NULL)
|
||||
fnvlist_add_nvlist(args, ZPOOL_RECYCLE_CLIENTS, clients);
|
||||
int err = lzc_ioctl(ZFS_IOC_POOL_RECYCLE, pool, args, outnvl);
|
||||
fnvlist_free(args);
|
||||
return (err);
|
||||
}
|
||||
|
||||
int
|
||||
lzc_pool_destroy(const char *pool, const char *log_str, nvlist_t **outnvl)
|
||||
{
|
||||
nvlist_t *args = fnvlist_alloc();
|
||||
fnvlist_add_string(args, ZPOOL_HIST_CMD, log_str);
|
||||
int err = lzc_ioctl(ZFS_IOC_POOL_DESTROY_NEW, pool, args, outnvl);
|
||||
fnvlist_free(args);
|
||||
return (err);
|
||||
}
|
||||
|
||||
int
|
||||
lzc_pool_export(const char *pool, const char *log_str, boolean_t force,
|
||||
boolean_t hardforce, nvlist_t **outnvl)
|
||||
{
|
||||
nvlist_t *args = fnvlist_alloc();
|
||||
fnvlist_add_string(args, ZPOOL_HIST_CMD, log_str);
|
||||
fnvlist_add_boolean_value(args, ZPOOL_EXPORT_FORCE, force);
|
||||
fnvlist_add_boolean_value(args, ZPOOL_EXPORT_HARDFORCE, hardforce);
|
||||
int err = lzc_ioctl(ZFS_IOC_POOL_EXPORT_NEW, pool, args, outnvl);
|
||||
fnvlist_free(args);
|
||||
return (err);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,67 @@
|
|||
</elf-function-symbols>
|
||||
<abi-instr address-size='64' path='lib/libzfsbootenv/lzbe_device.c' language='LANG_C99'>
|
||||
<type-decl name='char' size-in-bits='8' id='a84c031d'/>
|
||||
<type-decl name='int' size-in-bits='32' id='95e97e5e'/>
|
||||
<type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
|
||||
<type-decl name='void' id='48b5725f'/>
|
||||
<enum-decl name='lzbe_flags' id='2b77720b'>
|
||||
<underlying-type type-id='9cac1fee'/>
|
||||
<enumerator name='lzbe_add' value='0'/>
|
||||
<enumerator name='lzbe_replace' value='1'/>
|
||||
</enum-decl>
|
||||
<typedef-decl name='lzbe_flags_t' type-id='2b77720b' id='a1936f04'/>
|
||||
<pointer-type-def type-id='a84c031d' size-in-bits='64' id='26a90f95'/>
|
||||
<pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/>
|
||||
<qualified-type-def type-id='a84c031d' const='yes' id='9b45d938'/>
|
||||
<pointer-type-def type-id='9b45d938' size-in-bits='64' id='80f4b756'/>
|
||||
<function-decl name='lzbe_set_boot_device' mangled-name='lzbe_set_boot_device' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_set_boot_device'>
|
||||
<parameter type-id='80f4b756' name='pool'/>
|
||||
<parameter type-id='a1936f04' name='flag'/>
|
||||
<parameter type-id='80f4b756' name='device'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzbe_get_boot_device' mangled-name='lzbe_get_boot_device' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_get_boot_device'>
|
||||
<parameter type-id='80f4b756' name='pool'/>
|
||||
<parameter type-id='9b23c9ad' name='device'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='lib/libzfsbootenv/lzbe_pair.c' language='LANG_C99'>
|
||||
<type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
|
||||
<typedef-decl name='size_t' type-id='7359adad' id='b59d7dce'/>
|
||||
<pointer-type-def type-id='48b5725f' size-in-bits='64' id='eaa32e2f'/>
|
||||
<pointer-type-def type-id='eaa32e2f' size-in-bits='64' id='63e171df'/>
|
||||
<function-decl name='lzbe_nvlist_get' mangled-name='lzbe_nvlist_get' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_nvlist_get'>
|
||||
<parameter type-id='80f4b756' name='pool'/>
|
||||
<parameter type-id='80f4b756' name='key'/>
|
||||
<parameter type-id='63e171df' name='ptr'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzbe_nvlist_set' mangled-name='lzbe_nvlist_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_nvlist_set'>
|
||||
<parameter type-id='80f4b756' name='pool'/>
|
||||
<parameter type-id='80f4b756' name='key'/>
|
||||
<parameter type-id='eaa32e2f' name='ptr'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzbe_nvlist_free' mangled-name='lzbe_nvlist_free' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_nvlist_free'>
|
||||
<parameter type-id='eaa32e2f' name='ptr'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzbe_add_pair' mangled-name='lzbe_add_pair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_add_pair'>
|
||||
<parameter type-id='eaa32e2f' name='ptr'/>
|
||||
<parameter type-id='80f4b756' name='key'/>
|
||||
<parameter type-id='80f4b756' name='type'/>
|
||||
<parameter type-id='eaa32e2f' name='value'/>
|
||||
<parameter type-id='b59d7dce' name='size'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzbe_remove_pair' mangled-name='lzbe_remove_pair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_remove_pair'>
|
||||
<parameter type-id='eaa32e2f' name='ptr'/>
|
||||
<parameter type-id='80f4b756' name='key'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='lib/libzfsbootenv/lzbe_util.c' language='LANG_C99'>
|
||||
<array-type-def dimensions='1' type-id='a84c031d' size-in-bits='8' id='89feb1ec'>
|
||||
<subrange length='1' type-id='7359adad' id='52f813b4'/>
|
||||
</array-type-def>
|
||||
|
@ -25,55 +86,9 @@
|
|||
<class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
|
||||
<class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
|
||||
<class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
|
||||
<class-decl name='libzfs_handle' is-struct='yes' visibility='default' is-declaration-only='yes' id='c8a9d9d8'/>
|
||||
<class-decl name='zpool_handle' is-struct='yes' visibility='default' is-declaration-only='yes' id='67002a8a'/>
|
||||
<type-decl name='int' size-in-bits='32' id='95e97e5e'/>
|
||||
<type-decl name='long int' size-in-bits='64' id='bd54fe1a'/>
|
||||
<type-decl name='signed char' size-in-bits='8' id='28577a57'/>
|
||||
<type-decl name='unnamed-enum-underlying-type-32' is-anonymous='yes' size-in-bits='32' alignment-in-bits='32' id='9cac1fee'/>
|
||||
<type-decl name='unsigned int' size-in-bits='32' id='f0981eeb'/>
|
||||
<type-decl name='unsigned long int' size-in-bits='64' id='7359adad'/>
|
||||
<type-decl name='unsigned short int' size-in-bits='16' id='8efea9e5'/>
|
||||
<type-decl name='variadic parameter type' id='2c1145c5'/>
|
||||
<type-decl name='void' id='48b5725f'/>
|
||||
<typedef-decl name='zpool_handle_t' type-id='67002a8a' id='b1efc708'/>
|
||||
<typedef-decl name='libzfs_handle_t' type-id='c8a9d9d8' id='95942d0c'/>
|
||||
<enum-decl name='lzbe_flags' id='2b77720b'>
|
||||
<underlying-type type-id='9cac1fee'/>
|
||||
<enumerator name='lzbe_add' value='0'/>
|
||||
<enumerator name='lzbe_replace' value='1'/>
|
||||
</enum-decl>
|
||||
<typedef-decl name='lzbe_flags_t' type-id='2b77720b' id='a1936f04'/>
|
||||
<class-decl name='nvlist' size-in-bits='192' is-struct='yes' visibility='default' id='ac266fd9'>
|
||||
<data-member access='public' layout-offset-in-bits='0'>
|
||||
<var-decl name='nvl_version' type-id='3ff5601b' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='32'>
|
||||
<var-decl name='nvl_nvflag' type-id='8f92235e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='64'>
|
||||
<var-decl name='nvl_priv' type-id='9c313c2d' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='128'>
|
||||
<var-decl name='nvl_flag' type-id='8f92235e' visibility='default'/>
|
||||
</data-member>
|
||||
<data-member access='public' layout-offset-in-bits='160'>
|
||||
<var-decl name='nvl_pad' type-id='3ff5601b' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='nvlist_t' type-id='ac266fd9' id='8e8d4be3'/>
|
||||
<enum-decl name='boolean_t' naming-typedef-id='c19b74c3' id='f58c8277'>
|
||||
<underlying-type type-id='9cac1fee'/>
|
||||
<enumerator name='B_FALSE' value='0'/>
|
||||
<enumerator name='B_TRUE' value='1'/>
|
||||
</enum-decl>
|
||||
<typedef-decl name='boolean_t' type-id='f58c8277' id='c19b74c3'/>
|
||||
<typedef-decl name='int32_t' type-id='33f57a65' id='3ff5601b'/>
|
||||
<typedef-decl name='uint32_t' type-id='62f1140c' id='8f92235e'/>
|
||||
<typedef-decl name='uint64_t' type-id='8910171f' id='9c313c2d'/>
|
||||
<typedef-decl name='__int32_t' type-id='95e97e5e' id='33f57a65'/>
|
||||
<typedef-decl name='__uint32_t' type-id='f0981eeb' id='62f1140c'/>
|
||||
<typedef-decl name='__uint64_t' type-id='7359adad' id='8910171f'/>
|
||||
<typedef-decl name='__off_t' type-id='bd54fe1a' id='79989e9c'/>
|
||||
<typedef-decl name='__off64_t' type-id='bd54fe1a' id='724e4de6'/>
|
||||
<typedef-decl name='FILE' type-id='ec1ed955' id='aa12d1ba'/>
|
||||
|
@ -167,413 +182,15 @@
|
|||
<var-decl name='_unused2' type-id='664ac0b7' visibility='default'/>
|
||||
</data-member>
|
||||
</class-decl>
|
||||
<typedef-decl name='size_t' type-id='7359adad' id='b59d7dce'/>
|
||||
<pointer-type-def type-id='aa12d1ba' size-in-bits='64' id='822cd80b'/>
|
||||
<qualified-type-def type-id='822cd80b' restrict='yes' id='e75a27e9'/>
|
||||
<pointer-type-def type-id='ec1ed955' size-in-bits='64' id='dca988a5'/>
|
||||
<pointer-type-def type-id='a4036571' size-in-bits='64' id='570f8c59'/>
|
||||
<pointer-type-def type-id='bb4788fa' size-in-bits='64' id='cecf4ea7'/>
|
||||
<pointer-type-def type-id='010ae0b9' size-in-bits='64' id='e4c6fa61'/>
|
||||
<pointer-type-def type-id='79bd3751' size-in-bits='64' id='c65a1f29'/>
|
||||
<pointer-type-def type-id='a84c031d' size-in-bits='64' id='26a90f95'/>
|
||||
<pointer-type-def type-id='26a90f95' size-in-bits='64' id='9b23c9ad'/>
|
||||
<qualified-type-def type-id='9b23c9ad' restrict='yes' id='8c85230f'/>
|
||||
<qualified-type-def type-id='a84c031d' const='yes' id='9b45d938'/>
|
||||
<pointer-type-def type-id='9b45d938' size-in-bits='64' id='80f4b756'/>
|
||||
<qualified-type-def type-id='80f4b756' restrict='yes' id='9d26089a'/>
|
||||
<pointer-type-def type-id='80f4b756' size-in-bits='64' id='7d3cd834'/>
|
||||
<qualified-type-def type-id='8e8d4be3' const='yes' id='693c3853'/>
|
||||
<pointer-type-def type-id='693c3853' size-in-bits='64' id='22cce67b'/>
|
||||
<pointer-type-def type-id='95942d0c' size-in-bits='64' id='b0382bb3'/>
|
||||
<pointer-type-def type-id='8e8d4be3' size-in-bits='64' id='5ce45b60'/>
|
||||
<pointer-type-def type-id='5ce45b60' size-in-bits='64' id='857bb57e'/>
|
||||
<pointer-type-def type-id='9c313c2d' size-in-bits='64' id='5d6479ae'/>
|
||||
<pointer-type-def type-id='48b5725f' size-in-bits='64' id='eaa32e2f'/>
|
||||
<pointer-type-def type-id='b1efc708' size-in-bits='64' id='4c81de99'/>
|
||||
<class-decl name='_IO_codecvt' is-struct='yes' visibility='default' is-declaration-only='yes' id='a4036571'/>
|
||||
<class-decl name='_IO_marker' is-struct='yes' visibility='default' is-declaration-only='yes' id='010ae0b9'/>
|
||||
<class-decl name='_IO_wide_data' is-struct='yes' visibility='default' is-declaration-only='yes' id='79bd3751'/>
|
||||
<class-decl name='libzfs_handle' is-struct='yes' visibility='default' is-declaration-only='yes' id='c8a9d9d8'/>
|
||||
<class-decl name='zpool_handle' is-struct='yes' visibility='default' is-declaration-only='yes' id='67002a8a'/>
|
||||
<function-decl name='libzfs_init' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='b0382bb3'/>
|
||||
</function-decl>
|
||||
<function-decl name='libzfs_fini' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='b0382bb3'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='libzfs_error_description' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='b0382bb3'/>
|
||||
<return type-id='80f4b756'/>
|
||||
</function-decl>
|
||||
<function-decl name='zpool_open' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='b0382bb3'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='4c81de99'/>
|
||||
</function-decl>
|
||||
<function-decl name='zpool_close' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='4c81de99'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='zpool_set_bootenv' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='4c81de99'/>
|
||||
<parameter type-id='22cce67b'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='zpool_get_bootenv' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='4c81de99'/>
|
||||
<parameter type-id='857bb57e'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_free' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_lookup_uint64' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='22cce67b'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='5d6479ae'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_lookup_string' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='22cce67b'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='7d3cd834'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_exists' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='22cce67b'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='c19b74c3'/>
|
||||
</function-decl>
|
||||
<function-decl name='fnvlist_alloc' visibility='default' binding='global' size-in-bits='64'>
|
||||
<return type-id='5ce45b60'/>
|
||||
</function-decl>
|
||||
<function-decl name='fnvlist_free' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='fnvlist_add_uint64' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='9c313c2d'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='fnvlist_add_string' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='fnvlist_remove' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='free' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='eaa32e2f'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='strncmp' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='b59d7dce'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='strdup' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='26a90f95'/>
|
||||
</function-decl>
|
||||
<function-decl name='strlen' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='b59d7dce'/>
|
||||
</function-decl>
|
||||
<function-decl name='__fprintf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='e75a27e9'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='__asprintf_chk' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='8c85230f'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<parameter type-id='9d26089a'/>
|
||||
<parameter is-variadic='yes'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzbe_set_boot_device' mangled-name='lzbe_set_boot_device' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_set_boot_device'>
|
||||
<parameter type-id='80f4b756' name='pool'/>
|
||||
<parameter type-id='a1936f04' name='flag'/>
|
||||
<parameter type-id='80f4b756' name='device'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzbe_get_boot_device' mangled-name='lzbe_get_boot_device' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_get_boot_device'>
|
||||
<parameter type-id='80f4b756' name='pool'/>
|
||||
<parameter type-id='9b23c9ad' name='device'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='lib/libzfsbootenv/lzbe_pair.c' language='LANG_C99'>
|
||||
<type-decl name='short int' size-in-bits='16' id='a2185560'/>
|
||||
<type-decl name='unsigned char' size-in-bits='8' id='002ac4a6'/>
|
||||
<typedef-decl name='uchar_t' type-id='002ac4a6' id='d8bf0010'/>
|
||||
<typedef-decl name='uint_t' type-id='f0981eeb' id='3502e3ff'/>
|
||||
<typedef-decl name='int8_t' type-id='2171a512' id='ee31ee44'/>
|
||||
<typedef-decl name='int16_t' type-id='03896e23' id='23bd8cb5'/>
|
||||
<typedef-decl name='int64_t' type-id='0c9942d2' id='9da381c4'/>
|
||||
<typedef-decl name='uint8_t' type-id='c51d6389' id='b96825af'/>
|
||||
<typedef-decl name='uint16_t' type-id='253c2d2a' id='149c6638'/>
|
||||
<typedef-decl name='__int8_t' type-id='28577a57' id='2171a512'/>
|
||||
<typedef-decl name='__uint8_t' type-id='002ac4a6' id='c51d6389'/>
|
||||
<typedef-decl name='__int16_t' type-id='a2185560' id='03896e23'/>
|
||||
<typedef-decl name='__uint16_t' type-id='8efea9e5' id='253c2d2a'/>
|
||||
<typedef-decl name='__int64_t' type-id='bd54fe1a' id='0c9942d2'/>
|
||||
<qualified-type-def type-id='c19b74c3' const='yes' id='12373e33'/>
|
||||
<pointer-type-def type-id='12373e33' size-in-bits='64' id='c5f6c15b'/>
|
||||
<qualified-type-def type-id='80f4b756' const='yes' id='b99c00c9'/>
|
||||
<pointer-type-def type-id='b99c00c9' size-in-bits='64' id='13956559'/>
|
||||
<qualified-type-def type-id='23bd8cb5' const='yes' id='75f7b0c5'/>
|
||||
<pointer-type-def type-id='75f7b0c5' size-in-bits='64' id='a3eb883d'/>
|
||||
<qualified-type-def type-id='3ff5601b' const='yes' id='922df12b'/>
|
||||
<pointer-type-def type-id='922df12b' size-in-bits='64' id='1f526493'/>
|
||||
<qualified-type-def type-id='9da381c4' const='yes' id='f07b7694'/>
|
||||
<pointer-type-def type-id='f07b7694' size-in-bits='64' id='505bed1a'/>
|
||||
<qualified-type-def type-id='ee31ee44' const='yes' id='721c32d4'/>
|
||||
<pointer-type-def type-id='721c32d4' size-in-bits='64' id='a06445da'/>
|
||||
<qualified-type-def type-id='22cce67b' const='yes' id='d2816df0'/>
|
||||
<pointer-type-def type-id='d2816df0' size-in-bits='64' id='3bbfee2e'/>
|
||||
<qualified-type-def type-id='d8bf0010' const='yes' id='a9125480'/>
|
||||
<pointer-type-def type-id='a9125480' size-in-bits='64' id='d1db479e'/>
|
||||
<qualified-type-def type-id='149c6638' const='yes' id='b01a5ac8'/>
|
||||
<pointer-type-def type-id='b01a5ac8' size-in-bits='64' id='1b7d11c6'/>
|
||||
<qualified-type-def type-id='8f92235e' const='yes' id='b9930aae'/>
|
||||
<pointer-type-def type-id='b9930aae' size-in-bits='64' id='a6798dcc'/>
|
||||
<qualified-type-def type-id='9c313c2d' const='yes' id='c3b7ba7d'/>
|
||||
<pointer-type-def type-id='c3b7ba7d' size-in-bits='64' id='713a56f5'/>
|
||||
<qualified-type-def type-id='b96825af' const='yes' id='2b61797f'/>
|
||||
<pointer-type-def type-id='2b61797f' size-in-bits='64' id='9f7200cf'/>
|
||||
<pointer-type-def type-id='eaa32e2f' size-in-bits='64' id='63e171df'/>
|
||||
<function-decl name='nvlist_alloc' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='857bb57e'/>
|
||||
<parameter type-id='3502e3ff'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_dup' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='22cce67b'/>
|
||||
<parameter type-id='857bb57e'/>
|
||||
<parameter type-id='95e97e5e'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_boolean_value' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='c19b74c3'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_byte' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='d8bf0010'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_int8' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='ee31ee44'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_uint8' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='b96825af'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_int16' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='23bd8cb5'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_uint16' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='149c6638'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_int32' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='3ff5601b'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_uint32' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='8f92235e'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_int64' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='9da381c4'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_uint64' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='9c313c2d'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_string' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_nvlist' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='22cce67b'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_boolean_array' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='c5f6c15b'/>
|
||||
<parameter type-id='3502e3ff'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_byte_array' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='d1db479e'/>
|
||||
<parameter type-id='3502e3ff'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_int8_array' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='a06445da'/>
|
||||
<parameter type-id='3502e3ff'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_uint8_array' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='9f7200cf'/>
|
||||
<parameter type-id='3502e3ff'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_int16_array' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='a3eb883d'/>
|
||||
<parameter type-id='3502e3ff'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_uint16_array' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='1b7d11c6'/>
|
||||
<parameter type-id='3502e3ff'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_int32_array' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='1f526493'/>
|
||||
<parameter type-id='3502e3ff'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_uint32_array' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='a6798dcc'/>
|
||||
<parameter type-id='3502e3ff'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_int64_array' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='505bed1a'/>
|
||||
<parameter type-id='3502e3ff'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_uint64_array' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='713a56f5'/>
|
||||
<parameter type-id='3502e3ff'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_string_array' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='13956559'/>
|
||||
<parameter type-id='3502e3ff'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_add_nvlist_array' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='3bbfee2e'/>
|
||||
<parameter type-id='3502e3ff'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_remove_all' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='nvlist_lookup_nvlist' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='857bb57e'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='strcmp' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<parameter type-id='80f4b756'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzbe_nvlist_get' mangled-name='lzbe_nvlist_get' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_nvlist_get'>
|
||||
<parameter type-id='80f4b756' name='pool'/>
|
||||
<parameter type-id='80f4b756' name='key'/>
|
||||
<parameter type-id='63e171df' name='ptr'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzbe_nvlist_set' mangled-name='lzbe_nvlist_set' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_nvlist_set'>
|
||||
<parameter type-id='80f4b756' name='pool'/>
|
||||
<parameter type-id='80f4b756' name='key'/>
|
||||
<parameter type-id='eaa32e2f' name='ptr'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzbe_nvlist_free' mangled-name='lzbe_nvlist_free' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_nvlist_free'>
|
||||
<parameter type-id='eaa32e2f' name='ptr'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzbe_add_pair' mangled-name='lzbe_add_pair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_add_pair'>
|
||||
<parameter type-id='eaa32e2f' name='ptr'/>
|
||||
<parameter type-id='80f4b756' name='key'/>
|
||||
<parameter type-id='80f4b756' name='type'/>
|
||||
<parameter type-id='eaa32e2f' name='value'/>
|
||||
<parameter type-id='b59d7dce' name='size'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzbe_remove_pair' mangled-name='lzbe_remove_pair' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_remove_pair'>
|
||||
<parameter type-id='eaa32e2f' name='ptr'/>
|
||||
<parameter type-id='80f4b756' name='key'/>
|
||||
<return type-id='95e97e5e'/>
|
||||
</function-decl>
|
||||
</abi-instr>
|
||||
<abi-instr address-size='64' path='lib/libzfsbootenv/lzbe_util.c' language='LANG_C99'>
|
||||
<function-decl name='nvlist_print' visibility='default' binding='global' size-in-bits='64'>
|
||||
<parameter type-id='822cd80b'/>
|
||||
<parameter type-id='5ce45b60'/>
|
||||
<return type-id='48b5725f'/>
|
||||
</function-decl>
|
||||
<function-decl name='lzbe_bootenv_print' mangled-name='lzbe_bootenv_print' visibility='default' binding='global' size-in-bits='64' elf-symbol-id='lzbe_bootenv_print'>
|
||||
<parameter type-id='80f4b756' name='pool'/>
|
||||
<parameter type-id='80f4b756' name='nvlist'/>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
/*
|
||||
* Copyright 2015 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, 2024 by Delphix. All rights reserved.
|
||||
* Copyright 2015 RackTop Systems.
|
||||
* Copyright (c) 2016, Intel Corporation.
|
||||
* Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
|
||||
|
@ -635,6 +635,18 @@ get_configs(libpc_handle_t *hdl, pool_list_t *pl, boolean_t active_ok,
|
|||
ZPOOL_CONFIG_HOSTNAME, hostname);
|
||||
}
|
||||
|
||||
if (nvlist_lookup_uint64(tmp,
|
||||
ZPOOL_CONFIG_SHARED_LOG_POOL, &guid) == 0) {
|
||||
fnvlist_add_uint64(config,
|
||||
ZPOOL_CONFIG_SHARED_LOG_POOL, guid);
|
||||
}
|
||||
|
||||
if (fnvlist_lookup_boolean(tmp,
|
||||
ZPOOL_CONFIG_IS_SHARED_LOG)) {
|
||||
fnvlist_add_boolean(config,
|
||||
ZPOOL_CONFIG_IS_SHARED_LOG);
|
||||
}
|
||||
|
||||
config_seen = B_TRUE;
|
||||
}
|
||||
|
||||
|
@ -1511,6 +1523,11 @@ zpool_find_import_impl(libpc_handle_t *hdl, importargs_t *iarg,
|
|||
iarg->guid == this_guid;
|
||||
}
|
||||
if (matched) {
|
||||
if (iarg->shared_log_guid) {
|
||||
fnvlist_add_uint64(config,
|
||||
ZPOOL_CONFIG_SHARED_LOG_POOL,
|
||||
iarg->shared_log_guid);
|
||||
}
|
||||
/*
|
||||
* Verify all remaining entries can be opened
|
||||
* exclusively. This will prune all underlying
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
.\" CDDL HEADER END
|
||||
.\"
|
||||
.\" Copyright (c) 2007, Sun Microsystems, Inc. All Rights Reserved.
|
||||
.\" Copyright (c) 2012, 2018 by Delphix. All rights reserved.
|
||||
.\" Copyright (c) 2012, 2023 by Delphix. All rights reserved.
|
||||
.\" Copyright (c) 2012 Cyril Plisko. All Rights Reserved.
|
||||
.\" Copyright (c) 2017 Datto Inc.
|
||||
.\" Copyright (c) 2018 George Melikov. All Rights Reserved.
|
||||
|
@ -178,6 +178,13 @@ However, raidz vdev types are not supported for the intent log.
|
|||
For more information, see the
|
||||
.Sx Intent Log
|
||||
section.
|
||||
.It Sy shared log
|
||||
A separate ZFS storage pool used as a shared intent log device.
|
||||
Only one shared log can be specified at pool creation or import, and a normal
|
||||
log device cannot also be specified.
|
||||
For more information, see the
|
||||
.Sx Intent Log
|
||||
section.
|
||||
.It Sy dedup
|
||||
A device solely dedicated for deduplication tables.
|
||||
The redundancy of this device should match the redundancy of the other normal
|
||||
|
@ -395,6 +402,9 @@ In addition, log devices are imported and exported as part of the pool
|
|||
that contains them.
|
||||
Mirrored devices can be removed by specifying the top-level mirror vdev.
|
||||
.
|
||||
A shared log pool can be used as a log device; this pool can be used by
|
||||
several different "client" pools to provide easier management of space
|
||||
to be used for the intent log.
|
||||
.Ss Cache Devices
|
||||
Devices can be added to a storage pool as
|
||||
.Qq cache devices .
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
.\" CDDL HEADER END
|
||||
.\"
|
||||
.\" Copyright (c) 2007, Sun Microsystems, Inc. All Rights Reserved.
|
||||
.\" Copyright (c) 2012, 2018 by Delphix. All rights reserved.
|
||||
.\" Copyright (c) 2012, 2023 by Delphix. All rights reserved.
|
||||
.\" Copyright (c) 2012 Cyril Plisko. All Rights Reserved.
|
||||
.\" Copyright (c) 2017 Datto Inc.
|
||||
.\" Copyright (c) 2018 George Melikov. All Rights Reserved.
|
||||
|
@ -37,8 +37,9 @@
|
|||
.Sh SYNOPSIS
|
||||
.Nm zpool
|
||||
.Cm create
|
||||
.Op Fl dfn
|
||||
.Op Fl dfnL
|
||||
.Op Fl m Ar mountpoint
|
||||
.Op Fl l Ar pool
|
||||
.Oo Fl o Ar property Ns = Ns Ar value Oc Ns …
|
||||
.Oo Fl o Sy feature@ Ns Ar feature Ns = Ns Ar value Oc
|
||||
.Op Fl o Ar compatibility Ns = Ns Sy off Ns | Ns Sy legacy Ns | Ns Ar file Ns Oo , Ns Ar file Oc Ns …
|
||||
|
@ -167,6 +168,18 @@ Displays the configuration that would be used without actually creating the
|
|||
pool.
|
||||
The actual pool creation can still fail due to insufficient privileges or
|
||||
device sharing.
|
||||
.It Fl L
|
||||
Create the pool as a shared log pool.
|
||||
Shared log pools cannot have filesystems or ZVOLs created in them, but they
|
||||
can be used as a virtual log device by several other pools, allowing more
|
||||
efficient use of physical log devices.
|
||||
Only one shared log pool can be imported on the system at a given
|
||||
time.
|
||||
.It Fl l Ar pool
|
||||
Create the pool using the provided pool as the log device.
|
||||
The provided pool must be a shared log pool (created using the
|
||||
.Fl L
|
||||
flag), and no other log devices can be specified as part of the vdev tree.
|
||||
.It Fl o Ar property Ns = Ns Ar value
|
||||
Sets the given pool properties.
|
||||
See
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
.\" CDDL HEADER END
|
||||
.\"
|
||||
.\" Copyright (c) 2007, Sun Microsystems, Inc. All Rights Reserved.
|
||||
.\" Copyright (c) 2012, 2018 by Delphix. All rights reserved.
|
||||
.\" Copyright (c) 2012, 2023 by Delphix. All rights reserved.
|
||||
.\" Copyright (c) 2012 Cyril Plisko. All Rights Reserved.
|
||||
.\" Copyright (c) 2017 Datto Inc.
|
||||
.\" Copyright (c) 2018 George Melikov. All Rights Reserved.
|
||||
|
@ -50,8 +50,9 @@
|
|||
.Op Fl R Ar root
|
||||
.Nm zpool
|
||||
.Cm import
|
||||
.Op Fl Dflmt
|
||||
.Op Fl Dflt
|
||||
.Op Fl F Op Fl nTX
|
||||
.Op Fl m Op Fl L Ar pool
|
||||
.Op Fl -rewind-to-checkpoint
|
||||
.Op Fl c Ar cachefile Ns | Ns Fl d Ar dir Ns | Ns Ar device
|
||||
.Op Fl o Ar mntopts
|
||||
|
@ -256,8 +257,9 @@ health of your pool and should only be used as a last resort.
|
|||
.It Xo
|
||||
.Nm zpool
|
||||
.Cm import
|
||||
.Op Fl Dflmt
|
||||
.Op Fl Dflt
|
||||
.Op Fl F Op Fl nTX
|
||||
.Op Fl m Op Fl L Ar pool
|
||||
.Op Fl c Ar cachefile Ns | Ns Fl d Ar dir Ns | Ns Ar device
|
||||
.Op Fl o Ar mntopts
|
||||
.Oo Fl o Ar property Ns = Ns Ar value Oc Ns …
|
||||
|
@ -330,6 +332,12 @@ encrypted datasets will be left unavailable until the keys are loaded.
|
|||
.It Fl m
|
||||
Allows a pool to import when there is a missing log device.
|
||||
Recent transactions can be lost because the log device will be discarded.
|
||||
.It Fl L
|
||||
Causes the pool to switch to using the specified shared log pool when
|
||||
imported.
|
||||
Requires the
|
||||
.Fl m
|
||||
flag.
|
||||
.It Fl n
|
||||
Used with the
|
||||
.Fl F
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
.\"
|
||||
.\" CDDL HEADER START
|
||||
.\"
|
||||
.\" The contents of this file are subject to the terms of the
|
||||
.\" Common Development and Distribution License (the "License").
|
||||
.\" You may not use this file except in compliance with the License.
|
||||
.\"
|
||||
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
.\" or https://opensource.org/licenses/CDDL-1.0.
|
||||
.\" See the License for the specific language governing permissions
|
||||
.\" and limitations under the License.
|
||||
.\"
|
||||
.\" When distributing Covered Code, include this CDDL HEADER in each
|
||||
.\" file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
.\" If applicable, add the following below this CDDL HEADER, with the
|
||||
.\" fields enclosed by brackets "[]" replaced with your own identifying
|
||||
.\" information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
.\"
|
||||
.\" CDDL HEADER END
|
||||
.\"
|
||||
.\" Copyright (c) 2023 by Delphix. All rights reserved.
|
||||
.\"
|
||||
.Dd February 13, 2023
|
||||
.Dt ZPOOL-RECYCLE 8
|
||||
.Os
|
||||
.
|
||||
.Sh NAME
|
||||
.Nm zpool-recycle
|
||||
.Nd recycle space used by shared log ZIL chains
|
||||
.Sh SYNOPSIS
|
||||
.Nm zpool
|
||||
.Cm recycle
|
||||
.Op Fl n
|
||||
.Op Ar pool
|
||||
.
|
||||
.Sh DESCRIPTION
|
||||
Client pools (from
|
||||
.Nm zpool
|
||||
.Cm create
|
||||
.Fl l
|
||||
) store their ZIL logs on the shared log pool (from
|
||||
.Nm zpool
|
||||
.Cm create
|
||||
.Fl L
|
||||
).
|
||||
When a client pool is deleted with
|
||||
.Nm zpool
|
||||
.Cm destroy
|
||||
, any space used in the shared log pool is reclaimed.
|
||||
However, if a client pool is exported and will not be imported again
|
||||
(e.g. because the disks were damaged or removed), any space associated with
|
||||
it in the shared log pool remains allocated.
|
||||
.Nm zpool
|
||||
.Cm recycle
|
||||
will reclaim space in the shared log pool that is referenced by any
|
||||
non-imported client pools.
|
||||
These non-imported client pools will have their logs deleted; if they are
|
||||
subsequently imported,
|
||||
.Nm zpool
|
||||
.Cm import
|
||||
.Fl m
|
||||
will need to be used to ignore the missing logs, discarding any recent
|
||||
transactions.
|
||||
.
|
||||
.Sh OPTIONS
|
||||
.Bl -tag -width "-n"
|
||||
.It Fl n
|
||||
Do not actually perform any deletions, just print out the list of pool
|
||||
GUIDs that would be affected.
|
||||
.El
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2023 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Martin Matuska <mm@FreeBSD.org>. All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -246,6 +246,8 @@ spa_import_rootpool(const char *name, bool checkpointrewind)
|
|||
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
|
||||
error = spa_config_parse(spa, &rvd, nvtop, NULL, 0,
|
||||
VDEV_ALLOC_ROOTPOOL);
|
||||
if (error == 0)
|
||||
spa_set_pool_type(spa);
|
||||
spa_config_exit(spa, SCL_ALL, FTAG);
|
||||
if (error) {
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2011, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2023 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2014, Nexenta Systems, Inc. All rights reserved.
|
||||
|
@ -754,6 +754,11 @@ zpool_feature_init(void)
|
|||
"Support for raidz expansion",
|
||||
ZFEATURE_FLAG_MOS, ZFEATURE_TYPE_BOOLEAN, NULL, sfeatures);
|
||||
|
||||
zfeature_register(SPA_FEATURE_SHARED_LOG,
|
||||
"com.delphix:shared_log", "shared_log",
|
||||
"Support for shared log pools.", 0, ZFEATURE_TYPE_BOOLEAN, NULL,
|
||||
sfeatures);
|
||||
|
||||
zfs_mod_list_supported_free(sfeatures);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2020 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, 2023 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
|
||||
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
|
||||
|
@ -658,6 +658,8 @@ dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
|
|||
|
||||
if (ds == NULL || !ds->ds_is_snapshot)
|
||||
os->os_zil_header = os->os_phys->os_zil_header;
|
||||
if (spa_uses_shared_log(spa))
|
||||
spa_zil_header_convert(spa, os, &os->os_zil_header.zh_log);
|
||||
os->os_zil = zil_alloc(os, &os->os_zil_header);
|
||||
|
||||
for (i = 0; i < TXG_SIZE; i++) {
|
||||
|
@ -1192,6 +1194,9 @@ dmu_objset_create_check(void *arg, dmu_tx_t *tx)
|
|||
const char *tail;
|
||||
int error;
|
||||
|
||||
if (spa_is_shared_log(dp->dp_spa))
|
||||
return (SET_ERROR(EINVAL));
|
||||
|
||||
if (strchr(doca->doca_name, '@') != NULL)
|
||||
return (SET_ERROR(EINVAL));
|
||||
|
||||
|
@ -1720,6 +1725,10 @@ sync_meta_dnode_task(void *arg)
|
|||
*/
|
||||
zil_sync(os->os_zil, tx);
|
||||
os->os_phys->os_zil_header = os->os_zil_header;
|
||||
if (os->os_spa->spa_uses_shared_log) {
|
||||
spa_zil_header_mask(os->os_spa,
|
||||
&os->os_phys->os_zil_header.zh_log);
|
||||
}
|
||||
zio_nowait(soa->soa_zio);
|
||||
|
||||
mutex_destroy(&soa->soa_mutex);
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2012, 2017 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, 2023 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <sys/dmu.h>
|
||||
|
@ -75,6 +75,14 @@ dmu_tx_create_dd(dsl_dir_t *dd)
|
|||
return (tx);
|
||||
}
|
||||
|
||||
dmu_tx_t *
|
||||
dmu_tx_create_mos(dsl_pool_t *dp)
|
||||
{
|
||||
dmu_tx_t *tx = dmu_tx_create_dd(dp->dp_mos_dir);
|
||||
tx->tx_objset = dp->dp_meta_objset;
|
||||
return (tx);
|
||||
}
|
||||
|
||||
dmu_tx_t *
|
||||
dmu_tx_create(objset_t *os)
|
||||
{
|
||||
|
|
|
@ -726,7 +726,8 @@ kill_blkptr(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
|
|||
* It's a block in the intent log. It has no
|
||||
* accounting, so just free it.
|
||||
*/
|
||||
dsl_free(ka->tx->tx_pool, ka->tx->tx_txg, bp);
|
||||
if (!zil_shared_log(zilog))
|
||||
dsl_free(ka->tx->tx_pool, ka->tx->tx_txg, bp);
|
||||
} else {
|
||||
ASSERT(zilog == NULL);
|
||||
ASSERT3U(BP_GET_LOGICAL_BIRTH(bp), >,
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2012, 2022 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Martin Matuska. All rights reserved.
|
||||
* Copyright (c) 2014 Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
|
||||
|
@ -1303,7 +1303,7 @@ top_of_function:
|
|||
* refreservation values. Also, if checkrefquota is set, test if
|
||||
* allocating this space would exceed the dataset's refquota.
|
||||
*/
|
||||
if (first && tx->tx_objset) {
|
||||
if (first && tx->tx_objset && tx->tx_objset->os_dsl_dataset) {
|
||||
int error;
|
||||
dsl_dataset_t *ds = tx->tx_objset->os_dsl_dataset;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2020 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2023 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
||||
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
|
||||
* Copyright 2016 Nexenta Systems, Inc. All rights reserved.
|
||||
|
@ -170,6 +170,9 @@ static int zfs_zil_clean_taskq_nthr_pct = 100;
|
|||
static int zfs_zil_clean_taskq_minalloc = 1024;
|
||||
static int zfs_zil_clean_taskq_maxalloc = 1024 * 1024;
|
||||
|
||||
static unsigned int chain_map_zap_default_bs = 17;
|
||||
static unsigned int chain_map_zap_default_ibs = 15;
|
||||
|
||||
int
|
||||
dsl_pool_open_special_dir(dsl_pool_t *dp, const char *name, dsl_dir_t **ddp)
|
||||
{
|
||||
|
@ -360,6 +363,14 @@ dsl_pool_open(dsl_pool_t *dp)
|
|||
if (err)
|
||||
goto out;
|
||||
|
||||
if (spa_is_shared_log(dp->dp_spa)) {
|
||||
err = zap_lookup(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
|
||||
DMU_POOL_CHAIN_MAP_OBJ, sizeof (uint64_t), 1,
|
||||
&dp->dp_chain_map_obj);
|
||||
if (err != 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = dsl_scan_init(dp, dp->dp_tx.tx_open_txg);
|
||||
|
||||
out:
|
||||
|
@ -548,6 +559,17 @@ dsl_pool_create(spa_t *spa, nvlist_t *zplprops __attribute__((unused)),
|
|||
#endif
|
||||
dsl_dataset_rele_flags(ds, DS_HOLD_FLAG_DECRYPT, FTAG);
|
||||
|
||||
if (spa_is_shared_log(spa)) {
|
||||
dp->dp_chain_map_obj = zap_create_flags(dp->dp_meta_objset, 0,
|
||||
ZAP_FLAG_HASH64 | ZAP_FLAG_UINT64_KEY |
|
||||
ZAP_FLAG_PRE_HASHED_KEY, DMU_OTN_ZAP_METADATA,
|
||||
chain_map_zap_default_bs, chain_map_zap_default_ibs,
|
||||
DMU_OT_NONE, 0, tx);
|
||||
VERIFY0(zap_add(dp->dp_meta_objset, DMU_POOL_DIRECTORY_OBJECT,
|
||||
DMU_POOL_CHAIN_MAP_OBJ, sizeof (uint64_t), 1,
|
||||
&dp->dp_chain_map_obj, tx));
|
||||
}
|
||||
|
||||
dmu_tx_commit(tx);
|
||||
|
||||
rrw_exit(&dp->dp_config_rwlock, FTAG);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2019 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2023 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
|
||||
* Copyright (c) 2015, Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2017, Intel Corporation.
|
||||
|
@ -1660,6 +1660,12 @@ static metaslab_ops_t metaslab_allocators[] = {
|
|||
{ "new-dynamic", metaslab_ndf_alloc },
|
||||
};
|
||||
|
||||
const metaslab_ops_t zfs_virtual_ops = {
|
||||
"virtual",
|
||||
NULL,
|
||||
METASLAB_TYPE_VIRTUAL
|
||||
};
|
||||
|
||||
static int
|
||||
spa_find_allocator_byname(const char *val)
|
||||
{
|
||||
|
@ -2866,6 +2872,10 @@ metaslab_fini(metaslab_t *msp)
|
|||
range_tree_destroy(msp->ms_unflushed_frees);
|
||||
|
||||
for (int t = 0; t < TXG_SIZE; t++) {
|
||||
if (spa_is_shared_log(spa) &&
|
||||
spa_load_state(spa) != SPA_LOAD_NONE) {
|
||||
range_tree_vacate(msp->ms_allocating[t], NULL, NULL);
|
||||
}
|
||||
range_tree_destroy(msp->ms_allocating[t]);
|
||||
}
|
||||
for (int t = 0; t < TXG_DEFER_SIZE; t++) {
|
||||
|
@ -5845,6 +5855,19 @@ metaslab_alloc(spa_t *spa, metaslab_class_t *mc, uint64_t psize, blkptr_t *bp,
|
|||
int ndvas, uint64_t txg, blkptr_t *hintbp, int flags,
|
||||
zio_alloc_list_t *zal, zio_t *zio, int allocator)
|
||||
{
|
||||
if (mc->mc_ops->msop_type == METASLAB_TYPE_VIRTUAL) {
|
||||
ASSERT3P(mc->mc_virtual, !=, NULL);
|
||||
spa_t *target_spa = mc->mc_virtual;
|
||||
dmu_tx_t *tx = dmu_tx_create_mos(target_spa->spa_dsl_pool);
|
||||
VERIFY0(dmu_tx_assign(tx, TXG_WAIT | TXG_NOTHROTTLE));
|
||||
uint64_t target_txg = dmu_tx_get_txg(tx);
|
||||
int ret = metaslab_alloc(target_spa,
|
||||
spa_normal_class(target_spa), psize, bp, ndvas, target_txg,
|
||||
hintbp, flags, zal, zio, allocator);
|
||||
dmu_tx_commit(tx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
dva_t *dva = bp->blk_dva;
|
||||
dva_t *hintdva = (hintbp != NULL) ? hintbp->blk_dva : NULL;
|
||||
int error = 0;
|
||||
|
@ -5861,7 +5884,7 @@ metaslab_alloc(spa_t *spa, metaslab_class_t *mc, uint64_t psize, blkptr_t *bp,
|
|||
}
|
||||
|
||||
ASSERT(ndvas > 0 && ndvas <= spa_max_replication(spa));
|
||||
ASSERT(BP_GET_NDVAS(bp) == 0);
|
||||
ASSERT0(BP_GET_NDVAS(bp));
|
||||
ASSERT(hintbp == NULL || ndvas <= BP_GET_NDVAS(hintbp));
|
||||
ASSERT3P(zal, !=, NULL);
|
||||
|
||||
|
@ -5887,8 +5910,8 @@ metaslab_alloc(spa_t *spa, metaslab_class_t *mc, uint64_t psize, blkptr_t *bp,
|
|||
DVA_GET_VDEV(&dva[d]), zio, flags, allocator);
|
||||
}
|
||||
}
|
||||
ASSERT(error == 0);
|
||||
ASSERT(BP_GET_NDVAS(bp) == ndvas);
|
||||
ASSERT0(error);
|
||||
ASSERT3U(BP_GET_NDVAS(bp), ==, ndvas);
|
||||
|
||||
spa_config_exit(spa, SCL_ALLOC, FTAG);
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
* Use is subject to license terms.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2013, 2019 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2013, 2023 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2015, Nexenta Systems, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
|
@ -618,7 +618,7 @@ range_tree_verify_not_present(range_tree_t *rt, uint64_t off, uint64_t size)
|
|||
{
|
||||
range_seg_t *rs = range_tree_find(rt, off, size);
|
||||
if (rs != NULL)
|
||||
panic("segment already in tree; rs=%p", (void *)rs);
|
||||
panic("segment already in tree; rt=%px rs=%px", rt, (void *)rs);
|
||||
}
|
||||
|
||||
boolean_t
|
||||
|
|
1037
module/zfs/spa.c
1037
module/zfs/spa.c
File diff suppressed because it is too large
Load Diff
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2017 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2017, 2023 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -544,6 +544,10 @@ spa_checkpoint(const char *pool)
|
|||
error = spa_open(pool, &spa, FTAG);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
if (spa_uses_shared_log(spa) || spa_is_shared_log(spa)) {
|
||||
spa_close(spa, FTAG);
|
||||
return (SET_ERROR(ENOTSUP));
|
||||
}
|
||||
|
||||
mutex_enter(&spa->spa_vdev_top_lock);
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2011, 2020 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2023 by Delphix. All rights reserved.
|
||||
* Copyright 2017 Joyent, Inc.
|
||||
* Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
|
||||
*/
|
||||
|
@ -466,6 +466,11 @@ spa_config_generate(spa_t *spa, vdev_t *vd, uint64_t txg, int getstats)
|
|||
if (spa->spa_compatibility != NULL)
|
||||
fnvlist_add_string(config, ZPOOL_CONFIG_COMPATIBILITY,
|
||||
spa->spa_compatibility);
|
||||
if (spa->spa_uses_shared_log)
|
||||
fnvlist_add_uint64(config, ZPOOL_CONFIG_SHARED_LOG_POOL,
|
||||
spa_guid(spa_get_shared_log_pool(spa)));
|
||||
if (spa_is_shared_log(spa))
|
||||
fnvlist_add_boolean(config, ZPOOL_CONFIG_IS_SHARED_LOG);
|
||||
|
||||
hostid = spa_get_hostid(spa);
|
||||
if (hostid != 0)
|
||||
|
|
|
@ -238,6 +238,8 @@
|
|||
|
||||
avl_tree_t spa_namespace_avl;
|
||||
kmutex_t spa_namespace_lock;
|
||||
avl_tree_t spa_shared_log_avl;
|
||||
kmutex_t spa_shared_log_lock;
|
||||
kcondvar_t spa_namespace_cv;
|
||||
static const int spa_max_replication_override = SPA_DVAS_PER_BP;
|
||||
|
||||
|
@ -445,6 +447,42 @@ static int zfs_user_indirect_is_special = B_TRUE;
|
|||
*/
|
||||
static uint_t zfs_special_class_metadata_reserve_pct = 25;
|
||||
|
||||
void
|
||||
spa_set_pool_type(spa_t *spa)
|
||||
{
|
||||
ASSERT3P(spa->spa_root_vdev, !=, NULL);
|
||||
|
||||
/*
|
||||
* Must hold all of spa_config locks.
|
||||
*/
|
||||
ASSERT3U(spa_config_held(spa, SCL_ALL, RW_WRITER), ==, SCL_ALL);
|
||||
|
||||
if (fnvlist_lookup_boolean(spa->spa_config,
|
||||
ZPOOL_CONFIG_IS_SHARED_LOG)) {
|
||||
spa->spa_pool_type = SPA_TYPE_SHARED_LOG;
|
||||
avl_index_t where;
|
||||
mutex_enter(&spa_shared_log_lock);
|
||||
if (avl_find(&spa_shared_log_avl, spa, &where) == NULL)
|
||||
avl_insert(&spa_shared_log_avl, spa, where);
|
||||
mutex_exit(&spa_shared_log_lock);
|
||||
} else {
|
||||
spa->spa_pool_type = SPA_TYPE_NORMAL;
|
||||
}
|
||||
}
|
||||
|
||||
boolean_t
|
||||
spa_is_shared_log(const spa_t *spa)
|
||||
{
|
||||
return (spa->spa_pool_type == SPA_TYPE_SHARED_LOG);
|
||||
}
|
||||
|
||||
boolean_t
|
||||
spa_uses_shared_log(const spa_t *spa)
|
||||
{
|
||||
return (spa->spa_uses_shared_log);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ==========================================================================
|
||||
* SPA config locking
|
||||
|
@ -685,6 +723,15 @@ spa_log_sm_sort_by_txg(const void *va, const void *vb)
|
|||
return (TREE_CMP(a->sls_txg, b->sls_txg));
|
||||
}
|
||||
|
||||
static int
|
||||
spa_guid_compare(const void *a1, const void *a2)
|
||||
{
|
||||
const spa_t *s1 = a1;
|
||||
const spa_t *s2 = a2;
|
||||
|
||||
return (TREE_CMP(spa_const_guid(s1), spa_const_guid(s2)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Create an uninitialized spa_t with the given name. Requires
|
||||
* spa_namespace_lock. The caller must ensure that the spa_t doesn't already
|
||||
|
@ -714,6 +761,8 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
|
|||
mutex_init(&spa->spa_feat_stats_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
mutex_init(&spa->spa_flushed_ms_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
mutex_init(&spa->spa_activities_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
mutex_init(&spa->spa_chain_map_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
mutex_init(&spa->spa_zil_map_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
|
||||
cv_init(&spa->spa_async_cv, NULL, CV_DEFAULT, NULL);
|
||||
cv_init(&spa->spa_evicting_os_cv, NULL, CV_DEFAULT, NULL);
|
||||
|
@ -777,6 +826,8 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
|
|||
sizeof (metaslab_t), offsetof(metaslab_t, ms_spa_txg_node));
|
||||
avl_create(&spa->spa_sm_logs_by_txg, spa_log_sm_sort_by_txg,
|
||||
sizeof (spa_log_sm_t), offsetof(spa_log_sm_t, sls_node));
|
||||
list_create(&spa->spa_registered_clients, sizeof (spa_t),
|
||||
offsetof(spa_t, spa_client_node));
|
||||
list_create(&spa->spa_log_summary, sizeof (log_summary_entry_t),
|
||||
offsetof(log_summary_entry_t, lse_node));
|
||||
|
||||
|
@ -852,6 +903,12 @@ spa_remove(spa_t *spa)
|
|||
|
||||
avl_remove(&spa_namespace_avl, spa);
|
||||
|
||||
if (spa_is_shared_log(spa)) {
|
||||
mutex_enter(&spa_shared_log_lock);
|
||||
avl_remove(&spa_shared_log_avl, spa);
|
||||
mutex_exit(&spa_shared_log_lock);
|
||||
}
|
||||
|
||||
if (spa->spa_root)
|
||||
spa_strfree(spa->spa_root);
|
||||
|
||||
|
@ -875,6 +932,7 @@ spa_remove(spa_t *spa)
|
|||
|
||||
avl_destroy(&spa->spa_metaslabs_by_flushed);
|
||||
avl_destroy(&spa->spa_sm_logs_by_txg);
|
||||
list_destroy(&spa->spa_registered_clients);
|
||||
list_destroy(&spa->spa_log_summary);
|
||||
list_destroy(&spa->spa_config_list);
|
||||
list_destroy(&spa->spa_leaf_list);
|
||||
|
@ -916,6 +974,7 @@ spa_remove(spa_t *spa)
|
|||
mutex_destroy(&spa->spa_vdev_top_lock);
|
||||
mutex_destroy(&spa->spa_feat_stats_lock);
|
||||
mutex_destroy(&spa->spa_activities_lock);
|
||||
mutex_destroy(&spa->spa_chain_map_lock);
|
||||
|
||||
kmem_free(spa, sizeof (spa_t));
|
||||
}
|
||||
|
@ -1747,6 +1806,20 @@ spa_name(spa_t *spa)
|
|||
return (spa->spa_name);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
spa_const_guid(const spa_t *spa)
|
||||
{
|
||||
/*
|
||||
* If we fail to parse the config during spa_load(), we can go through
|
||||
* the error path (which posts an ereport) and end up here with no root
|
||||
* vdev. We stash the original pool guid in 'spa_config_guid' to handle
|
||||
* this case.
|
||||
*/
|
||||
if (spa->spa_root_vdev == NULL)
|
||||
return (spa->spa_config_guid);
|
||||
return (spa->spa_root_vdev->vdev_guid);
|
||||
}
|
||||
|
||||
uint64_t
|
||||
spa_guid(spa_t *spa)
|
||||
{
|
||||
|
@ -1776,7 +1849,7 @@ spa_guid(spa_t *spa)
|
|||
}
|
||||
|
||||
uint64_t
|
||||
spa_load_guid(spa_t *spa)
|
||||
spa_load_guid(const spa_t *spa)
|
||||
{
|
||||
/*
|
||||
* This is a GUID that exists solely as a reference for the
|
||||
|
@ -2535,6 +2608,7 @@ void
|
|||
spa_init(spa_mode_t mode)
|
||||
{
|
||||
mutex_init(&spa_namespace_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
mutex_init(&spa_shared_log_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
mutex_init(&spa_spare_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
mutex_init(&spa_l2cache_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
cv_init(&spa_namespace_cv, NULL, CV_DEFAULT, NULL);
|
||||
|
@ -2548,6 +2622,9 @@ spa_init(spa_mode_t mode)
|
|||
avl_create(&spa_l2cache_avl, spa_l2cache_compare, sizeof (spa_aux_t),
|
||||
offsetof(spa_aux_t, aux_avl));
|
||||
|
||||
avl_create(&spa_shared_log_avl, spa_guid_compare, sizeof (spa_t),
|
||||
offsetof(spa_t, spa_log_avl));
|
||||
|
||||
spa_mode_global = mode;
|
||||
|
||||
#ifndef _KERNEL
|
||||
|
@ -2623,6 +2700,7 @@ spa_fini(void)
|
|||
|
||||
cv_destroy(&spa_namespace_cv);
|
||||
mutex_destroy(&spa_namespace_lock);
|
||||
mutex_destroy(&spa_shared_log_lock);
|
||||
mutex_destroy(&spa_spare_lock);
|
||||
mutex_destroy(&spa_l2cache_lock);
|
||||
}
|
||||
|
@ -2635,7 +2713,8 @@ spa_fini(void)
|
|||
boolean_t
|
||||
spa_has_slogs(spa_t *spa)
|
||||
{
|
||||
return (spa->spa_log_class->mc_groups != 0);
|
||||
return (spa->spa_log_class->mc_groups != 0 ||
|
||||
spa->spa_log_class->mc_virtual != NULL);
|
||||
}
|
||||
|
||||
spa_log_state_t
|
||||
|
|
|
@ -332,7 +332,7 @@ zap_leaf_array_match(zap_leaf_t *l, zap_name_t *zn,
|
|||
if (zap_getflags(zn->zn_zap) & ZAP_FLAG_UINT64_KEY) {
|
||||
uint64_t *thiskey =
|
||||
kmem_alloc(array_numints * sizeof (*thiskey), KM_SLEEP);
|
||||
ASSERT(zn->zn_key_intlen == sizeof (*thiskey));
|
||||
ASSERT3S(zn->zn_key_intlen, ==, sizeof (*thiskey));
|
||||
|
||||
zap_leaf_array_read(l, chunk, sizeof (*thiskey), array_numints,
|
||||
sizeof (*thiskey), array_numints, thiskey);
|
||||
|
@ -342,7 +342,7 @@ zap_leaf_array_match(zap_leaf_t *l, zap_name_t *zn,
|
|||
return (match);
|
||||
}
|
||||
|
||||
ASSERT(zn->zn_key_intlen == 1);
|
||||
ASSERT3S(zn->zn_key_intlen, ==, 1);
|
||||
if (zn->zn_matchtype & MT_NORMALIZE) {
|
||||
char *thisname = kmem_alloc(array_numints, KM_SLEEP);
|
||||
|
||||
|
|
|
@ -353,19 +353,24 @@ zpl_earlier_version(const char *name, int version)
|
|||
}
|
||||
|
||||
static void
|
||||
zfs_log_history(zfs_cmd_t *zc)
|
||||
zfs_log_history_string(const char *pool, const char *buf)
|
||||
{
|
||||
spa_t *spa;
|
||||
char *buf;
|
||||
|
||||
if ((buf = history_str_get(zc)) == NULL)
|
||||
return;
|
||||
|
||||
if (spa_open(zc->zc_name, &spa, FTAG) == 0) {
|
||||
if (spa_open(pool, &spa, FTAG) == 0) {
|
||||
if (spa_version(spa) >= SPA_VERSION_ZPOOL_HISTORY)
|
||||
(void) spa_history_log(spa, buf);
|
||||
spa_close(spa, FTAG);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
zfs_log_history(zfs_cmd_t *zc)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
if ((buf = history_str_get(zc)) == NULL)
|
||||
return;
|
||||
zfs_log_history_string(zc->zc_name, buf);
|
||||
history_str_free(buf);
|
||||
}
|
||||
|
||||
|
@ -1502,7 +1507,7 @@ zfs_ioc_pool_create(zfs_cmd_t *zc)
|
|||
*/
|
||||
if (!error && (error = zfs_set_prop_nvlist(spa_name,
|
||||
ZPROP_SRC_LOCAL, rootprops, NULL)) != 0) {
|
||||
(void) spa_destroy(spa_name);
|
||||
(void) spa_destroy(spa_name, NULL);
|
||||
unload_wkey = B_FALSE; /* spa_destroy() unloads wrapping keys */
|
||||
}
|
||||
|
||||
|
@ -1521,7 +1526,23 @@ zfs_ioc_pool_destroy(zfs_cmd_t *zc)
|
|||
{
|
||||
int error;
|
||||
zfs_log_history(zc);
|
||||
error = spa_destroy(zc->zc_name);
|
||||
error = spa_destroy(zc->zc_name, NULL);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static const zfs_ioc_key_t zfs_keys_pool_destroy_new[] = {
|
||||
{ZPOOL_HIST_CMD, DATA_TYPE_STRING, 0},
|
||||
};
|
||||
|
||||
static int
|
||||
zfs_ioc_pool_destroy_new(const char *pool, nvlist_t *innvl, nvlist_t *outnvl)
|
||||
{
|
||||
int error;
|
||||
|
||||
zfs_log_history_string(pool, fnvlist_lookup_string(innvl,
|
||||
ZPOOL_HIST_CMD));
|
||||
error = spa_destroy(pool, outnvl);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
@ -1571,7 +1592,28 @@ zfs_ioc_pool_export(zfs_cmd_t *zc)
|
|||
boolean_t hardforce = (boolean_t)zc->zc_guid;
|
||||
|
||||
zfs_log_history(zc);
|
||||
error = spa_export(zc->zc_name, NULL, force, hardforce);
|
||||
error = spa_export(zc->zc_name, NULL, force, hardforce, NULL);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static const zfs_ioc_key_t zfs_keys_pool_export_new[] = {
|
||||
{ZPOOL_HIST_CMD, DATA_TYPE_STRING, 0},
|
||||
{ZPOOL_EXPORT_FORCE, DATA_TYPE_BOOLEAN_VALUE, 0},
|
||||
{ZPOOL_EXPORT_HARDFORCE, DATA_TYPE_BOOLEAN_VALUE, 0},
|
||||
};
|
||||
|
||||
static int
|
||||
zfs_ioc_pool_export_new(const char *pool, nvlist_t *innvl, nvlist_t *outnvl)
|
||||
{
|
||||
int error;
|
||||
|
||||
zfs_log_history_string(pool,
|
||||
fnvlist_lookup_string(innvl, ZPOOL_HIST_CMD));
|
||||
error = spa_export(pool, NULL,
|
||||
fnvlist_lookup_boolean_value(innvl, ZPOOL_EXPORT_FORCE),
|
||||
fnvlist_lookup_boolean_value(innvl, ZPOOL_EXPORT_HARDFORCE),
|
||||
outnvl);
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
@ -7101,6 +7143,41 @@ error:
|
|||
return (ret);
|
||||
}
|
||||
|
||||
static const zfs_ioc_key_t zfs_keys_pool_recycle[] = {
|
||||
{ZPOOL_RECYCLE_DRYRUN, DATA_TYPE_BOOLEAN_VALUE, 0},
|
||||
{ZPOOL_RECYCLE_CLIENTS, DATA_TYPE_NVLIST, ZK_OPTIONAL},
|
||||
};
|
||||
|
||||
static int
|
||||
zfs_ioc_pool_recycle(const char *pool, nvlist_t *innvl, nvlist_t *outnvl)
|
||||
{
|
||||
int err;
|
||||
boolean_t rc, dryrun = B_FALSE;
|
||||
spa_t *spa;
|
||||
nvlist_t *clients = NULL;
|
||||
|
||||
if ((err = spa_open(pool, &spa, FTAG)) != 0)
|
||||
return (err);
|
||||
|
||||
if (innvl) {
|
||||
err = nvlist_lookup_boolean_value(innvl, ZPOOL_RECYCLE_DRYRUN,
|
||||
&rc);
|
||||
if (err == 0)
|
||||
dryrun = rc;
|
||||
nvlist_lookup_nvlist(innvl, ZPOOL_RECYCLE_CLIENTS,
|
||||
&clients);
|
||||
}
|
||||
if (clients) {
|
||||
err = spa_recycle_clients(spa, clients, dryrun, outnvl);
|
||||
} else {
|
||||
err = spa_recycle_all(spa, dryrun, outnvl);
|
||||
}
|
||||
|
||||
spa_close(spa, FTAG);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static zfs_ioc_vec_t zfs_ioc_vec[ZFS_IOC_LAST - ZFS_IOC_FIRST];
|
||||
|
||||
static void
|
||||
|
@ -7402,6 +7479,21 @@ zfs_ioctl_init(void)
|
|||
POOL_CHECK_NONE, B_FALSE, B_FALSE,
|
||||
zfs_keys_get_props, ARRAY_SIZE(zfs_keys_get_props));
|
||||
|
||||
zfs_ioctl_register("zpool_recycle", ZFS_IOC_POOL_RECYCLE,
|
||||
zfs_ioc_pool_recycle, zfs_secpolicy_config, POOL_NAME,
|
||||
POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_FALSE, B_FALSE,
|
||||
zfs_keys_pool_recycle, ARRAY_SIZE(zfs_keys_pool_recycle));
|
||||
|
||||
zfs_ioctl_register("zpool_destroy_new", ZFS_IOC_POOL_DESTROY_NEW,
|
||||
zfs_ioc_pool_destroy_new, zfs_secpolicy_config, POOL_NAME,
|
||||
POOL_CHECK_SUSPENDED, B_FALSE, B_FALSE,
|
||||
zfs_keys_pool_destroy_new, ARRAY_SIZE(zfs_keys_pool_destroy_new));
|
||||
|
||||
zfs_ioctl_register("zpool_export_new", ZFS_IOC_POOL_EXPORT_NEW,
|
||||
zfs_ioc_pool_export_new, zfs_secpolicy_config, POOL_NAME,
|
||||
POOL_CHECK_SUSPENDED, B_FALSE, B_FALSE,
|
||||
zfs_keys_pool_export_new, ARRAY_SIZE(zfs_keys_pool_export_new));
|
||||
|
||||
/* IOCTLS that use the legacy function signature */
|
||||
|
||||
zfs_ioctl_register_legacy(ZFS_IOC_POOL_FREEZE, zfs_ioc_pool_freeze,
|
||||
|
|
388
module/zfs/zil.c
388
module/zfs/zil.c
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2023 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2014 Integros [integros.com]
|
||||
* Copyright (c) 2018 Datto Inc.
|
||||
*/
|
||||
|
@ -238,23 +238,16 @@ zil_kstats_global_update(kstat_t *ksp, int rw)
|
|||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a log block and make sure it's valid.
|
||||
*/
|
||||
static int
|
||||
zil_read_log_block(zilog_t *zilog, boolean_t decrypt, const blkptr_t *bp,
|
||||
blkptr_t *nbp, char **begin, char **end, arc_buf_t **abuf)
|
||||
zil_read_log_block(spa_t *spa, boolean_t decrypt, zio_flag_t zio_flags,
|
||||
const blkptr_t *bp, blkptr_t *nbp, char **begin, char **end,
|
||||
arc_buf_t **abuf)
|
||||
{
|
||||
zio_flag_t zio_flags = ZIO_FLAG_CANFAIL;
|
||||
|
||||
arc_flags_t aflags = ARC_FLAG_WAIT;
|
||||
zbookmark_phys_t zb;
|
||||
int error;
|
||||
|
||||
if (zilog->zl_header->zh_claim_txg == 0)
|
||||
zio_flags |= ZIO_FLAG_SPECULATIVE | ZIO_FLAG_SCRUB;
|
||||
|
||||
if (!(zilog->zl_header->zh_flags & ZIL_CLAIM_LR_SEQ_VALID))
|
||||
zio_flags |= ZIO_FLAG_SPECULATIVE;
|
||||
zio_flags |= ZIO_FLAG_CANFAIL;
|
||||
|
||||
if (!decrypt)
|
||||
zio_flags |= ZIO_FLAG_RAW;
|
||||
|
@ -262,7 +255,7 @@ zil_read_log_block(zilog_t *zilog, boolean_t decrypt, const blkptr_t *bp,
|
|||
SET_BOOKMARK(&zb, bp->blk_cksum.zc_word[ZIL_ZC_OBJSET],
|
||||
ZB_ZIL_OBJECT, ZB_ZIL_LEVEL, bp->blk_cksum.zc_word[ZIL_ZC_SEQ]);
|
||||
|
||||
error = arc_read(NULL, zilog->zl_spa, bp, arc_getbuf_func,
|
||||
error = arc_read(NULL, spa, bp, arc_getbuf_func,
|
||||
abuf, ZIO_PRIORITY_SYNC_READ, zio_flags, &aflags, &zb);
|
||||
|
||||
if (error == 0) {
|
||||
|
@ -346,7 +339,7 @@ zil_read_log_data(zilog_t *zilog, const lr_write_t *lr, void *wbuf)
|
|||
SET_BOOKMARK(&zb, dmu_objset_id(zilog->zl_os), lr->lr_foid,
|
||||
ZB_ZIL_LEVEL, lr->lr_offset / BP_GET_LSIZE(bp));
|
||||
|
||||
error = arc_read(NULL, zilog->zl_spa, bp, arc_getbuf_func, &abuf,
|
||||
error = arc_read(NULL, zilog->zl_io_spa, bp, arc_getbuf_func, &abuf,
|
||||
ZIO_PRIORITY_SYNC_READ, zio_flags, &aflags, &zb);
|
||||
|
||||
if (error == 0) {
|
||||
|
@ -453,6 +446,137 @@ zil_kstat_values_update(zil_kstat_values_t *zs, zil_sums_t *zil_sums)
|
|||
wmsum_value(&zil_sums->zil_itx_metaslab_slog_alloc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the intent log, and call parse_blk_func for each valid block within
|
||||
* and parse_lr_func for each valid record within.
|
||||
*/
|
||||
static int
|
||||
zil_parse_raw_impl(spa_t *spa, const blkptr_t *bp,
|
||||
zil_parse_raw_blk_func_t *parse_blk_func,
|
||||
zil_parse_raw_lr_func_t *parse_lr_func, void *arg, zio_flag_t zio_flags,
|
||||
boolean_t decrypt)
|
||||
{
|
||||
(void) parse_lr_func;
|
||||
blkptr_t next_blk = {{{{0}}}};
|
||||
int error = 0;
|
||||
|
||||
for (blkptr_t blk = *bp; !BP_IS_HOLE(&blk); blk = next_blk) {
|
||||
char *lrp, *end;
|
||||
arc_buf_t *abuf = NULL;
|
||||
|
||||
/*
|
||||
* We do the read before the parse function so that if the
|
||||
* parse function frees the block, we still have next_blk so we
|
||||
* can continue the chain.
|
||||
*/
|
||||
int read_error = zil_read_log_block(spa, decrypt, zio_flags,
|
||||
&blk, &next_blk, &lrp, &end, &abuf);
|
||||
|
||||
error = parse_blk_func(spa, &blk, arg);
|
||||
if (error != 0) {
|
||||
if (abuf)
|
||||
arc_buf_destroy(abuf, &abuf);
|
||||
break;
|
||||
}
|
||||
|
||||
if (read_error != 0) {
|
||||
if (abuf)
|
||||
arc_buf_destroy(abuf, &abuf);
|
||||
error = read_error;
|
||||
break;
|
||||
}
|
||||
|
||||
int reclen;
|
||||
for (; lrp < end; lrp += reclen) {
|
||||
lr_t *lr = (lr_t *)lrp;
|
||||
reclen = lr->lrc_reclen;
|
||||
ASSERT3U(reclen, >=, sizeof (lr_t));
|
||||
ASSERT3U(reclen, <=, end - lrp);
|
||||
|
||||
error = parse_lr_func(spa, lr, arg);
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
arc_buf_destroy(abuf, &abuf);
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Because we don't have access to the zilog_t, we cannot know when the chain
|
||||
* is supposed to end. As a result, all IOs need to be marked as speculative.
|
||||
*/
|
||||
int
|
||||
zil_parse_raw(spa_t *spa, const blkptr_t *bp,
|
||||
zil_parse_raw_blk_func_t *parse_blk_func,
|
||||
zil_parse_raw_lr_func_t *parse_lr_func, void *arg)
|
||||
{
|
||||
return (zil_parse_raw_impl(spa, bp, parse_blk_func, parse_lr_func, arg,
|
||||
ZIO_FLAG_SPECULATIVE | ZIO_FLAG_SCRUB, B_FALSE));
|
||||
}
|
||||
|
||||
struct parse_arg {
|
||||
zilog_t *zilog;
|
||||
zil_parse_blk_func_t *parse_blk_func;
|
||||
zil_parse_lr_func_t *parse_lr_func;
|
||||
void *arg;
|
||||
uint64_t txg;
|
||||
uint64_t blk_seq;
|
||||
uint64_t claim_blk_seq;
|
||||
uint64_t claim_lr_seq;
|
||||
uint64_t max_blk_seq;
|
||||
uint64_t max_lr_seq;
|
||||
uint64_t blk_count;
|
||||
uint64_t lr_count;
|
||||
int error;
|
||||
};
|
||||
|
||||
static int
|
||||
parse_blk_wrapper(spa_t *spa, const blkptr_t *bp, void *arg)
|
||||
{
|
||||
(void) spa;
|
||||
struct parse_arg *pa = arg;
|
||||
pa->blk_seq = bp->blk_cksum.zc_word[ZIL_ZC_SEQ];
|
||||
|
||||
if (pa->blk_seq > pa->claim_blk_seq)
|
||||
return (EINTR);
|
||||
int error = pa->parse_blk_func(pa->zilog, bp, pa->arg, pa->txg);
|
||||
if (error) {
|
||||
pa->error = error;
|
||||
return (EINTR);
|
||||
}
|
||||
|
||||
ASSERT3U(pa->max_blk_seq, <, pa->blk_seq);
|
||||
pa->max_blk_seq = pa->blk_seq;
|
||||
pa->blk_count++;
|
||||
|
||||
if (pa->max_lr_seq == pa->claim_lr_seq &&
|
||||
pa->max_blk_seq == pa->claim_blk_seq) {
|
||||
return (EINTR);
|
||||
}
|
||||
return (0);
|
||||
|
||||
}
|
||||
static int
|
||||
parse_lr_wrapper(spa_t *spa, const lr_t *lr, void *arg)
|
||||
{
|
||||
(void) spa;
|
||||
struct parse_arg *pa = arg;
|
||||
if (lr->lrc_seq > pa->claim_lr_seq)
|
||||
return (EINTR);
|
||||
|
||||
int error = pa->parse_lr_func(pa->zilog, lr, pa->arg, pa->txg);
|
||||
if (error != 0) {
|
||||
pa->error = error;
|
||||
return (EINTR);
|
||||
}
|
||||
ASSERT3U(pa->max_lr_seq, <, lr->lrc_seq);
|
||||
pa->max_lr_seq = lr->lrc_seq;
|
||||
pa->lr_count++;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the intent log, and call parse_func for each valid record within.
|
||||
*/
|
||||
|
@ -463,95 +587,57 @@ zil_parse(zilog_t *zilog, zil_parse_blk_func_t *parse_blk_func,
|
|||
{
|
||||
const zil_header_t *zh = zilog->zl_header;
|
||||
boolean_t claimed = !!zh->zh_claim_txg;
|
||||
uint64_t claim_blk_seq = claimed ? zh->zh_claim_blk_seq : UINT64_MAX;
|
||||
uint64_t claim_lr_seq = claimed ? zh->zh_claim_lr_seq : UINT64_MAX;
|
||||
uint64_t max_blk_seq = 0;
|
||||
uint64_t max_lr_seq = 0;
|
||||
uint64_t blk_count = 0;
|
||||
uint64_t lr_count = 0;
|
||||
blkptr_t blk, next_blk = {{{{0}}}};
|
||||
int error = 0;
|
||||
struct parse_arg arg2;
|
||||
arg2.claim_blk_seq = claimed ? zh->zh_claim_blk_seq : UINT64_MAX;
|
||||
arg2.claim_lr_seq = claimed ? zh->zh_claim_lr_seq : UINT64_MAX;
|
||||
arg2.max_blk_seq = 0;
|
||||
arg2.max_lr_seq = 0;
|
||||
arg2.blk_count = 0;
|
||||
arg2.lr_count = 0;
|
||||
arg2.arg = arg;
|
||||
arg2.parse_blk_func = parse_blk_func;
|
||||
arg2.parse_lr_func = parse_lr_func;
|
||||
arg2.txg = txg;
|
||||
arg2.zilog = zilog;
|
||||
arg2.error = 0;
|
||||
arg2.blk_seq = 0;
|
||||
|
||||
zio_flag_t zio_flags = 0;
|
||||
if (!claimed)
|
||||
zio_flags |= ZIO_FLAG_SPECULATIVE | ZIO_FLAG_SCRUB;
|
||||
|
||||
if (!(zh->zh_flags & ZIL_CLAIM_LR_SEQ_VALID))
|
||||
zio_flags |= ZIO_FLAG_SPECULATIVE;
|
||||
|
||||
/*
|
||||
* Old logs didn't record the maximum zh_claim_lr_seq.
|
||||
*/
|
||||
if (!(zh->zh_flags & ZIL_CLAIM_LR_SEQ_VALID))
|
||||
claim_lr_seq = UINT64_MAX;
|
||||
arg2.claim_lr_seq = UINT64_MAX;
|
||||
|
||||
/*
|
||||
* Starting at the block pointed to by zh_log we read the log chain.
|
||||
* For each block in the chain we strongly check that block to
|
||||
* ensure its validity. We stop when an invalid block is found.
|
||||
* For each block pointer in the chain we call parse_blk_func().
|
||||
* For each record in each valid block we call parse_lr_func().
|
||||
* If the log has been claimed, stop if we encounter a sequence
|
||||
* number greater than the highest claimed sequence number.
|
||||
*/
|
||||
zil_bp_tree_init(zilog);
|
||||
|
||||
for (blk = zh->zh_log; !BP_IS_HOLE(&blk); blk = next_blk) {
|
||||
uint64_t blk_seq = blk.blk_cksum.zc_word[ZIL_ZC_SEQ];
|
||||
int reclen;
|
||||
char *lrp, *end;
|
||||
arc_buf_t *abuf = NULL;
|
||||
int error = zil_parse_raw_impl(zilog->zl_io_spa, &zh->zh_log,
|
||||
parse_blk_wrapper, parse_lr_wrapper, &arg2, zio_flags, decrypt);
|
||||
|
||||
if (blk_seq > claim_blk_seq)
|
||||
break;
|
||||
// If this happens, we got an error from zil_read_log_block_spa
|
||||
if (error != 0 && error != EINTR && claimed) {
|
||||
char name[ZFS_MAX_DATASET_NAME_LEN];
|
||||
|
||||
error = parse_blk_func(zilog, &blk, arg, txg);
|
||||
if (error != 0)
|
||||
break;
|
||||
ASSERT3U(max_blk_seq, <, blk_seq);
|
||||
max_blk_seq = blk_seq;
|
||||
blk_count++;
|
||||
dmu_objset_name(zilog->zl_os, name);
|
||||
|
||||
if (max_lr_seq == claim_lr_seq && max_blk_seq == claim_blk_seq)
|
||||
break;
|
||||
|
||||
error = zil_read_log_block(zilog, decrypt, &blk, &next_blk,
|
||||
&lrp, &end, &abuf);
|
||||
if (error != 0) {
|
||||
if (abuf)
|
||||
arc_buf_destroy(abuf, &abuf);
|
||||
if (claimed) {
|
||||
char name[ZFS_MAX_DATASET_NAME_LEN];
|
||||
|
||||
dmu_objset_name(zilog->zl_os, name);
|
||||
|
||||
cmn_err(CE_WARN, "ZFS read log block error %d, "
|
||||
"dataset %s, seq 0x%llx\n", error, name,
|
||||
(u_longlong_t)blk_seq);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
for (; lrp < end; lrp += reclen) {
|
||||
lr_t *lr = (lr_t *)lrp;
|
||||
reclen = lr->lrc_reclen;
|
||||
ASSERT3U(reclen, >=, sizeof (lr_t));
|
||||
ASSERT3U(reclen, <=, end - lrp);
|
||||
if (lr->lrc_seq > claim_lr_seq) {
|
||||
arc_buf_destroy(abuf, &abuf);
|
||||
goto done;
|
||||
}
|
||||
|
||||
error = parse_lr_func(zilog, lr, arg, txg);
|
||||
if (error != 0) {
|
||||
arc_buf_destroy(abuf, &abuf);
|
||||
goto done;
|
||||
}
|
||||
ASSERT3U(max_lr_seq, <, lr->lrc_seq);
|
||||
max_lr_seq = lr->lrc_seq;
|
||||
lr_count++;
|
||||
}
|
||||
arc_buf_destroy(abuf, &abuf);
|
||||
cmn_err(CE_WARN, "ZFS read log block error %d, "
|
||||
"dataset %s, seq 0x%llx\n", error, name,
|
||||
(u_longlong_t)arg2.blk_seq);
|
||||
}
|
||||
done:
|
||||
|
||||
if (error == EINTR)
|
||||
error = arg2.error;
|
||||
zilog->zl_parse_error = error;
|
||||
zilog->zl_parse_blk_seq = max_blk_seq;
|
||||
zilog->zl_parse_lr_seq = max_lr_seq;
|
||||
zilog->zl_parse_blk_count = blk_count;
|
||||
zilog->zl_parse_lr_count = lr_count;
|
||||
zilog->zl_parse_blk_seq = arg2.max_blk_seq;
|
||||
zilog->zl_parse_lr_seq = arg2.max_lr_seq;
|
||||
zilog->zl_parse_blk_count = arg2.blk_count;
|
||||
zilog->zl_parse_lr_count = arg2.lr_count;
|
||||
|
||||
zil_bp_tree_fini(zilog);
|
||||
|
||||
|
@ -565,6 +651,8 @@ zil_clear_log_block(zilog_t *zilog, const blkptr_t *bp, void *tx,
|
|||
(void) tx;
|
||||
ASSERT(!BP_IS_HOLE(bp));
|
||||
|
||||
// We do not support checkpoints of shared log client pools.
|
||||
ASSERT(!zilog->zl_spa->spa_uses_shared_log);
|
||||
/*
|
||||
* As we call this function from the context of a rewind to a
|
||||
* checkpoint, each ZIL block whose txg is later than the txg
|
||||
|
@ -577,7 +665,7 @@ zil_clear_log_block(zilog_t *zilog, const blkptr_t *bp, void *tx,
|
|||
if (zil_bp_tree_add(zilog, bp) != 0)
|
||||
return (0);
|
||||
|
||||
zio_free(zilog->zl_spa, first_txg, bp);
|
||||
zio_free(zilog->zl_io_spa, first_txg, bp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -598,7 +686,8 @@ zil_claim_log_block(zilog_t *zilog, const blkptr_t *bp, void *tx,
|
|||
* If tx == NULL, just verify that the block is claimable.
|
||||
*/
|
||||
if (BP_IS_HOLE(bp) || BP_GET_LOGICAL_BIRTH(bp) < first_txg ||
|
||||
zil_bp_tree_add(zilog, bp) != 0)
|
||||
zil_bp_tree_add(zilog, bp) != 0 ||
|
||||
zilog->zl_spa != zilog->zl_io_spa)
|
||||
return (0);
|
||||
|
||||
return (zio_wait(zio_claim(NULL, zilog->zl_spa,
|
||||
|
@ -708,7 +797,8 @@ zil_free_log_block(zilog_t *zilog, const blkptr_t *bp, void *tx,
|
|||
{
|
||||
(void) claim_txg;
|
||||
|
||||
zio_free(zilog->zl_spa, dmu_tx_get_txg(tx), bp);
|
||||
if (!zilog->zl_spa->spa_uses_shared_log)
|
||||
zio_free(zilog->zl_spa, dmu_tx_get_txg(tx), bp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -725,7 +815,8 @@ zil_free_write(zilog_t *zilog, const lr_t *lrc, void *tx, uint64_t claim_txg)
|
|||
* If we previously claimed it, we need to free it.
|
||||
*/
|
||||
if (BP_GET_LOGICAL_BIRTH(bp) >= claim_txg &&
|
||||
zil_bp_tree_add(zilog, bp) == 0 && !BP_IS_HOLE(bp)) {
|
||||
zil_bp_tree_add(zilog, bp) == 0 && !BP_IS_HOLE(bp) &&
|
||||
!zilog->zl_spa->spa_uses_shared_log) {
|
||||
zio_free(zilog->zl_spa, dmu_tx_get_txg(tx), bp);
|
||||
}
|
||||
|
||||
|
@ -966,7 +1057,7 @@ zil_create(zilog_t *zilog)
|
|||
int error = 0;
|
||||
boolean_t slog = FALSE;
|
||||
dsl_dataset_t *ds = dmu_objset_ds(zilog->zl_os);
|
||||
|
||||
spa_t *spa = zilog->zl_spa;
|
||||
|
||||
/*
|
||||
* Wait for any previous destroy to complete.
|
||||
|
@ -990,14 +1081,23 @@ zil_create(zilog_t *zilog)
|
|||
txg = dmu_tx_get_txg(tx);
|
||||
|
||||
if (!BP_IS_HOLE(&blk)) {
|
||||
zio_free(zilog->zl_spa, txg, &blk);
|
||||
if (spa_uses_shared_log(spa)) {
|
||||
spa_zil_delete(spa, zilog->zl_os);
|
||||
} else {
|
||||
zio_free(spa, txg, &blk);
|
||||
}
|
||||
BP_ZERO(&blk);
|
||||
}
|
||||
|
||||
error = zio_alloc_zil(zilog->zl_spa, zilog->zl_os, txg, &blk,
|
||||
error = zio_alloc_zil(spa, zilog->zl_os, txg, &blk,
|
||||
ZIL_MIN_BLKSZ, &slog);
|
||||
if (error == 0)
|
||||
zil_init_log_chain(zilog, &blk);
|
||||
spa_zil_map_insert(spa, zilog->zl_os, NULL, &blk);
|
||||
if (spa_uses_shared_log(spa)) {
|
||||
spa_t *shared_log = spa_get_shared_log_pool(spa);
|
||||
txg_wait_synced(shared_log->spa_dsl_pool, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1018,9 +1118,8 @@ zil_create(zilog_t *zilog)
|
|||
* this until we write the first xattr log record because we
|
||||
* need to wait for the feature activation to sync out.
|
||||
*/
|
||||
if (spa_feature_is_enabled(zilog->zl_spa,
|
||||
SPA_FEATURE_ZILSAXATTR) && dmu_objset_type(zilog->zl_os) !=
|
||||
DMU_OST_ZVOL) {
|
||||
if (spa_feature_is_enabled(spa, SPA_FEATURE_ZILSAXATTR) &&
|
||||
dmu_objset_type(zilog->zl_os) != DMU_OST_ZVOL) {
|
||||
mutex_enter(&ds->ds_lock);
|
||||
ds->ds_feature_activation[SPA_FEATURE_ZILSAXATTR] =
|
||||
(void *)B_TRUE;
|
||||
|
@ -1036,7 +1135,7 @@ zil_create(zilog_t *zilog)
|
|||
*/
|
||||
zil_commit_activate_saxattr_feature(zilog);
|
||||
}
|
||||
IMPLY(spa_feature_is_enabled(zilog->zl_spa, SPA_FEATURE_ZILSAXATTR) &&
|
||||
IMPLY(spa_feature_is_enabled(spa, SPA_FEATURE_ZILSAXATTR) &&
|
||||
dmu_objset_type(zilog->zl_os) != DMU_OST_ZVOL,
|
||||
dsl_dataset_feature_is_active(ds, SPA_FEATURE_ZILSAXATTR));
|
||||
|
||||
|
@ -1088,11 +1187,14 @@ zil_destroy(zilog_t *zilog, boolean_t keep_first)
|
|||
if (!list_is_empty(&zilog->zl_lwb_list)) {
|
||||
ASSERT(zh->zh_claim_txg == 0);
|
||||
VERIFY(!keep_first);
|
||||
spa_zil_delete(zilog->zl_spa, zilog->zl_os);
|
||||
while ((lwb = list_remove_head(&zilog->zl_lwb_list)) != NULL) {
|
||||
if (lwb->lwb_buf != NULL)
|
||||
zio_buf_free(lwb->lwb_buf, lwb->lwb_sz);
|
||||
if (!BP_IS_HOLE(&lwb->lwb_blk))
|
||||
if (!BP_IS_HOLE(&lwb->lwb_blk) &&
|
||||
!spa_uses_shared_log(zilog->zl_spa)) {
|
||||
zio_free(zilog->zl_spa, txg, &lwb->lwb_blk);
|
||||
}
|
||||
zil_free_lwb(zilog, lwb);
|
||||
}
|
||||
} else if (!keep_first) {
|
||||
|
@ -1113,6 +1215,49 @@ zil_destroy_sync(zilog_t *zilog, dmu_tx_t *tx)
|
|||
zil_free_log_record, tx, zilog->zl_header->zh_claim_txg, B_FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function's only job is to clear the zil chain for the given dataset.
|
||||
* It is called when we're using a shared log pool and we import discarding
|
||||
* logs.
|
||||
*/
|
||||
int
|
||||
zil_clear(dsl_pool_t *dp, dsl_dataset_t *ds, void *txarg)
|
||||
{
|
||||
dmu_tx_t *tx = txarg;
|
||||
zilog_t *zilog;
|
||||
zil_header_t *zh;
|
||||
objset_t *os;
|
||||
int error;
|
||||
|
||||
ASSERT3U(spa_get_log_state(dp->dp_spa), ==, SPA_LOG_CLEAR);
|
||||
|
||||
error = dmu_objset_own_obj(dp, ds->ds_object,
|
||||
DMU_OST_ANY, B_FALSE, B_FALSE, FTAG, &os);
|
||||
if (error != 0) {
|
||||
/*
|
||||
* EBUSY indicates that the objset is inconsistent, in which
|
||||
* case it can not have a ZIL.
|
||||
*/
|
||||
if (error != EBUSY) {
|
||||
cmn_err(CE_WARN, "can't open objset for %llu, error %u",
|
||||
(unsigned long long)ds->ds_object, error);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
zilog = dmu_objset_zil(os);
|
||||
zh = zil_header_in_syncing_context(zilog);
|
||||
ASSERT3U(tx->tx_txg, ==, spa_first_txg(zilog->zl_spa));
|
||||
|
||||
BP_ZERO(&zh->zh_log);
|
||||
if (os->os_encrypted)
|
||||
os->os_next_write_raw[tx->tx_txg & TXG_MASK] = B_TRUE;
|
||||
dsl_dataset_dirty(dmu_objset_ds(os), tx);
|
||||
dmu_objset_disown(os, B_FALSE, FTAG);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
zil_claim(dsl_pool_t *dp, dsl_dataset_t *ds, void *txarg)
|
||||
{
|
||||
|
@ -1440,7 +1585,7 @@ zil_lwb_flush_vdevs_done(zio_t *zio)
|
|||
zil_commit_waiter_t *zcw;
|
||||
itx_t *itx;
|
||||
|
||||
spa_config_exit(zilog->zl_spa, SCL_STATE, lwb);
|
||||
spa_config_exit(zilog->zl_io_spa, SCL_STATE, lwb);
|
||||
|
||||
hrtime_t t = gethrtime() - lwb->lwb_issued_timestamp;
|
||||
|
||||
|
@ -1878,6 +2023,7 @@ static void
|
|||
zil_lwb_write_issue(zilog_t *zilog, lwb_t *lwb)
|
||||
{
|
||||
spa_t *spa = zilog->zl_spa;
|
||||
spa_t *io_spa = zilog->zl_io_spa;
|
||||
zil_chain_t *zilc;
|
||||
boolean_t slog;
|
||||
zbookmark_phys_t zb;
|
||||
|
@ -1893,7 +2039,7 @@ zil_lwb_write_issue(zilog_t *zilog, lwb_t *lwb)
|
|||
lwb->lwb_nused = lwb->lwb_nfilled;
|
||||
ASSERT3U(lwb->lwb_nused, <=, lwb->lwb_nmax);
|
||||
|
||||
lwb->lwb_root_zio = zio_root(spa, zil_lwb_flush_vdevs_done, lwb,
|
||||
lwb->lwb_root_zio = zio_root(io_spa, zil_lwb_flush_vdevs_done, lwb,
|
||||
ZIO_FLAG_CANFAIL);
|
||||
|
||||
/*
|
||||
|
@ -1926,7 +2072,7 @@ next_lwb:
|
|||
SET_BOOKMARK(&zb, lwb->lwb_blk.blk_cksum.zc_word[ZIL_ZC_OBJSET],
|
||||
ZB_ZIL_OBJECT, ZB_ZIL_LEVEL,
|
||||
lwb->lwb_blk.blk_cksum.zc_word[ZIL_ZC_SEQ]);
|
||||
lwb->lwb_write_zio = zio_rewrite(lwb->lwb_root_zio, spa, 0,
|
||||
lwb->lwb_write_zio = zio_rewrite(lwb->lwb_root_zio, io_spa, 0,
|
||||
&lwb->lwb_blk, lwb_abd, lwb->lwb_sz, zil_lwb_write_done,
|
||||
lwb, prio, ZIO_FLAG_CANFAIL, &zb);
|
||||
zil_lwb_add_block(lwb, &lwb->lwb_blk);
|
||||
|
@ -1975,11 +2121,14 @@ next_lwb:
|
|||
&slog);
|
||||
}
|
||||
if (error == 0) {
|
||||
ASSERT3U(BP_GET_LOGICAL_BIRTH(bp), ==, txg);
|
||||
IMPLY(spa == io_spa, BP_GET_LOGICAL_BIRTH(bp) == txg);
|
||||
BP_SET_CHECKSUM(bp, nlwb->lwb_slim ? ZIO_CHECKSUM_ZILOG2 :
|
||||
ZIO_CHECKSUM_ZILOG);
|
||||
VERIFY(zfs_blkptr_verify(io_spa, bp, BLK_CONFIG_NEEDED,
|
||||
BLK_VERIFY_HALT));
|
||||
bp->blk_cksum = lwb->lwb_blk.blk_cksum;
|
||||
bp->blk_cksum.zc_word[ZIL_ZC_SEQ]++;
|
||||
spa_zil_map_insert(spa, zilog->zl_os, &lwb->lwb_blk, bp);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1993,7 +2142,7 @@ next_lwb:
|
|||
mutex_exit(&zilog->zl_lwb_io_lock);
|
||||
dmu_tx_commit(tx);
|
||||
|
||||
spa_config_enter(spa, SCL_STATE, lwb, RW_READER);
|
||||
spa_config_enter(io_spa, SCL_STATE, lwb, RW_READER);
|
||||
|
||||
/*
|
||||
* We've completed all potentially blocking operations. Update the
|
||||
|
@ -3726,6 +3875,7 @@ zil_sync(zilog_t *zilog, dmu_tx_t *tx)
|
|||
*/
|
||||
zil_init_log_chain(zilog, &blk);
|
||||
zh->zh_log = blk;
|
||||
spa_zil_map_set_final(spa, zilog->zl_os, &blk);
|
||||
} else {
|
||||
/*
|
||||
* A destroyed ZIL chain can't contain any TX_SETSAXATTR
|
||||
|
@ -3736,7 +3886,11 @@ zil_sync(zilog_t *zilog, dmu_tx_t *tx)
|
|||
SPA_FEATURE_ZILSAXATTR))
|
||||
dsl_dataset_deactivate_feature(ds,
|
||||
SPA_FEATURE_ZILSAXATTR, tx);
|
||||
spa_zil_delete(spa, zilog->zl_os);
|
||||
}
|
||||
|
||||
mutex_exit(&zilog->zl_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
while ((lwb = list_head(&zilog->zl_lwb_list)) != NULL) {
|
||||
|
@ -3745,7 +3899,7 @@ zil_sync(zilog_t *zilog, dmu_tx_t *tx)
|
|||
lwb->lwb_alloc_txg > txg || lwb->lwb_max_txg > txg)
|
||||
break;
|
||||
list_remove(&zilog->zl_lwb_list, lwb);
|
||||
if (!BP_IS_HOLE(&lwb->lwb_blk))
|
||||
if (!BP_IS_HOLE(&lwb->lwb_blk) && !spa->spa_uses_shared_log)
|
||||
zio_free(spa, txg, &lwb->lwb_blk);
|
||||
zil_free_lwb(zilog, lwb);
|
||||
|
||||
|
@ -3757,6 +3911,7 @@ zil_sync(zilog_t *zilog, dmu_tx_t *tx)
|
|||
*/
|
||||
if (list_is_empty(&zilog->zl_lwb_list))
|
||||
BP_ZERO(&zh->zh_log);
|
||||
spa_zil_map_set_final(spa, zilog->zl_os, &zh->zh_log);
|
||||
}
|
||||
|
||||
mutex_exit(&zilog->zl_lock);
|
||||
|
@ -3845,6 +4000,13 @@ zil_alloc(objset_t *os, zil_header_t *zh_phys)
|
|||
zilog->zl_header = zh_phys;
|
||||
zilog->zl_os = os;
|
||||
zilog->zl_spa = dmu_objset_spa(os);
|
||||
zilog->zl_io_spa = spa_get_shared_log_pool(zilog->zl_spa);
|
||||
if (zilog->zl_io_spa == NULL) {
|
||||
zilog->zl_io_spa = zilog->zl_spa;
|
||||
} else {
|
||||
IMPLY(BP_IS_HOLE(&(zh_phys->zh_log)),
|
||||
BP_GET_LOGICAL_BIRTH(&zh_phys->zh_log) == 0);
|
||||
}
|
||||
zilog->zl_dmu_pool = dmu_objset_pool(os);
|
||||
zilog->zl_destroy_txg = TXG_INITIAL - 1;
|
||||
zilog->zl_logbias = dmu_objset_logbias(os);
|
||||
|
@ -3932,6 +4094,8 @@ zil_open(objset_t *os, zil_get_data_t *get_data, zil_sums_t *zil_sums)
|
|||
ASSERT3P(zilog->zl_get_data, ==, NULL);
|
||||
ASSERT3P(zilog->zl_last_lwb_opened, ==, NULL);
|
||||
ASSERT(list_is_empty(&zilog->zl_lwb_list));
|
||||
IMPLY(BP_IS_HOLE(&zilog->zl_header->zh_log),
|
||||
BP_GET_LOGICAL_BIRTH(&zilog->zl_header->zh_log) == 0);
|
||||
|
||||
zilog->zl_get_data = get_data;
|
||||
zilog->zl_sums = zil_sums;
|
||||
|
@ -4352,6 +4516,12 @@ zil_reset(const char *osname, void *arg)
|
|||
return (0);
|
||||
}
|
||||
|
||||
boolean_t
|
||||
zil_shared_log(zilog_t *zilog)
|
||||
{
|
||||
return (zilog->zl_spa != zilog->zl_io_spa);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(zil_alloc);
|
||||
EXPORT_SYMBOL(zil_free);
|
||||
EXPORT_SYMBOL(zil_open);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
*/
|
||||
/*
|
||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2022 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011, 2023 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
|
||||
* Copyright (c) 2017, Intel Corporation.
|
||||
* Copyright (c) 2019, 2023, 2024, Klara Inc.
|
||||
|
@ -3884,15 +3884,16 @@ zio_alloc_zil(spa_t *spa, objset_t *os, uint64_t txg, blkptr_t *new_bp,
|
|||
int flags = METASLAB_ZIL;
|
||||
int allocator = (uint_t)cityhash4(0, 0, 0,
|
||||
os->os_dsl_dataset->ds_object) % spa->spa_alloc_count;
|
||||
boolean_t must_slog = spa_uses_shared_log(spa);
|
||||
error = metaslab_alloc(spa, spa_log_class(spa), size, new_bp, 1,
|
||||
txg, NULL, flags, &io_alloc_list, NULL, allocator);
|
||||
*slog = (error == 0);
|
||||
if (error != 0) {
|
||||
*slog = (error == 0 || must_slog);
|
||||
if (error != 0 && !must_slog) {
|
||||
error = metaslab_alloc(spa, spa_embedded_log_class(spa), size,
|
||||
new_bp, 1, txg, NULL, flags,
|
||||
&io_alloc_list, NULL, allocator);
|
||||
}
|
||||
if (error != 0) {
|
||||
if (error != 0 && !must_slog) {
|
||||
error = metaslab_alloc(spa, spa_normal_class(spa), size,
|
||||
new_bp, 1, txg, NULL, flags,
|
||||
&io_alloc_list, NULL, allocator);
|
||||
|
|
|
@ -928,6 +928,11 @@ tests = ['scrub_mirror_001_pos', 'scrub_mirror_002_pos',
|
|||
'scrub_mirror_003_pos', 'scrub_mirror_004_pos']
|
||||
tags = ['functional', 'scrub_mirror']
|
||||
|
||||
[tests/functional/shared_log]
|
||||
tests = ['shared_log_001_pos', 'shared_log_002_pos', 'shared_log_003_pos', 'shared_log_004_pos',
|
||||
'shared_log_005_pos', 'shared_log_006_neg', 'shared_log_007_pos', 'shared_log_008_pos']
|
||||
tags = ['functional', 'shared_log']
|
||||
|
||||
[tests/functional/slog]
|
||||
tests = ['slog_001_pos', 'slog_002_pos', 'slog_003_pos', 'slog_004_pos',
|
||||
'slog_005_pos', 'slog_006_pos', 'slog_007_pos', 'slog_008_neg',
|
||||
|
|
|
@ -29,5 +29,4 @@ tests = ['sequential_writes', 'sequential_reads', 'sequential_reads_arc_cached',
|
|||
'sequential_reads_arc_cached_clone', 'sequential_reads_dbuf_cached',
|
||||
'random_reads', 'random_writes', 'random_readwrite', 'random_writes_zil',
|
||||
'random_readwrite_fixed']
|
||||
post =
|
||||
tags = ['perf', 'regression']
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018 by Delphix. All rights reserved.
|
||||
* Copyright (c) 2018, 2023 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -790,6 +790,18 @@ test_set_bootenv(const char *pool)
|
|||
nvlist_free(required);
|
||||
}
|
||||
|
||||
static void
|
||||
test_pool_recycle(const char *pool)
|
||||
{
|
||||
nvlist_t *required = fnvlist_alloc();
|
||||
|
||||
fnvlist_add_boolean_value(required, "dryrun", B_FALSE);
|
||||
|
||||
IOC_INPUT_TEST_WILD(ZFS_IOC_POOL_RECYCLE, pool, required, NULL, 0);
|
||||
|
||||
nvlist_free(required);
|
||||
}
|
||||
|
||||
static void
|
||||
zfs_ioc_input_tests(const char *pool)
|
||||
{
|
||||
|
@ -884,6 +896,8 @@ zfs_ioc_input_tests(const char *pool)
|
|||
|
||||
test_scrub(pool);
|
||||
|
||||
test_pool_recycle(pool);
|
||||
|
||||
/*
|
||||
* cleanup
|
||||
*/
|
||||
|
@ -1039,6 +1053,7 @@ validate_ioc_values(void)
|
|||
CHECK(ZFS_IOC_BASE + 83 == ZFS_IOC_WAIT);
|
||||
CHECK(ZFS_IOC_BASE + 84 == ZFS_IOC_WAIT_FS);
|
||||
CHECK(ZFS_IOC_BASE + 87 == ZFS_IOC_POOL_SCRUB);
|
||||
CHECK(ZFS_IOC_BASE + 88 == ZFS_IOC_POOL_RECYCLE);
|
||||
CHECK(ZFS_IOC_PLATFORM_BASE + 1 == ZFS_IOC_EVENTS_NEXT);
|
||||
CHECK(ZFS_IOC_PLATFORM_BASE + 2 == ZFS_IOC_EVENTS_CLEAR);
|
||||
CHECK(ZFS_IOC_PLATFORM_BASE + 3 == ZFS_IOC_EVENTS_SEEK);
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#
|
||||
# Copyright (c) 2009, Sun Microsystems Inc. All rights reserved.
|
||||
# Copyright (c) 2012, 2020, Delphix. All rights reserved.
|
||||
# Copyright (c) 2012, 2024, Delphix. All rights reserved.
|
||||
# Copyright (c) 2017, Tim Chase. All rights reserved.
|
||||
# Copyright (c) 2017, Nexenta Systems Inc. All rights reserved.
|
||||
# Copyright (c) 2017, Lawrence Livermore National Security LLC.
|
||||
|
@ -1586,10 +1586,10 @@ function create_pool #pool devs_list
|
|||
|
||||
if is_global_zone ; then
|
||||
[[ -d /$pool ]] && rm -rf /$pool
|
||||
log_must zpool create -f $pool $@
|
||||
zpool create -f $pool $@
|
||||
fi
|
||||
|
||||
return 0
|
||||
return $?
|
||||
}
|
||||
|
||||
# Return 0 if destroy successfully or the pool exists; $? otherwise
|
||||
|
|
|
@ -29,6 +29,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS = \
|
|||
perf/regression/sequential_reads.ksh \
|
||||
perf/regression/sequential_writes.ksh \
|
||||
perf/regression/setup.ksh \
|
||||
perf/regression/cleanup.ksh \
|
||||
\
|
||||
perf/scripts/prefetch_io.sh
|
||||
|
||||
|
@ -363,6 +364,8 @@ nobase_dist_datadir_zfs_tests_tests_DATA += \
|
|||
functional/rsend/rsend.kshlib \
|
||||
functional/scrub_mirror/default.cfg \
|
||||
functional/scrub_mirror/scrub_mirror_common.kshlib \
|
||||
functional/shared_log/shared_log.cfg \
|
||||
functional/shared_log/shared_log.kshlib \
|
||||
functional/slog/slog.cfg \
|
||||
functional/slog/slog.kshlib \
|
||||
functional/snapshot/snapshot.cfg \
|
||||
|
@ -1942,6 +1945,16 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
|||
functional/scrub_mirror/scrub_mirror_003_pos.ksh \
|
||||
functional/scrub_mirror/scrub_mirror_004_pos.ksh \
|
||||
functional/scrub_mirror/setup.ksh \
|
||||
functional/shared_log/cleanup.ksh \
|
||||
functional/shared_log/setup.ksh \
|
||||
functional/shared_log/shared_log_001_pos.ksh \
|
||||
functional/shared_log/shared_log_002_pos.ksh \
|
||||
functional/shared_log/shared_log_003_pos.ksh \
|
||||
functional/shared_log/shared_log_004_pos.ksh \
|
||||
functional/shared_log/shared_log_005_pos.ksh \
|
||||
functional/shared_log/shared_log_006_neg.ksh \
|
||||
functional/shared_log/shared_log_007_pos.ksh \
|
||||
functional/shared_log/shared_log_008_pos.ksh \
|
||||
functional/slog/cleanup.ksh \
|
||||
functional/slog/setup.ksh \
|
||||
functional/slog/slog_001_pos.ksh \
|
||||
|
|
|
@ -109,5 +109,6 @@ if is_linux || is_freebsd; then
|
|||
"feature@block_cloning"
|
||||
"feature@vdev_zaps_v2"
|
||||
"feature@raidz_expansion"
|
||||
"feature@shared_log"
|
||||
)
|
||||
fi
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/shared_log/shared_log.cfg
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
zpool import $LOGPOOL
|
||||
zpool import ${LOGPOOL}2
|
||||
zpool import $TESTPOOL
|
||||
zpool import $TESTPOOL2
|
||||
if datasetexists $TESTPOOL ; then
|
||||
log_must zpool destroy -f $TESTPOOL
|
||||
fi
|
||||
if datasetexists $TESTPOOL2 ; then
|
||||
log_must zpool destroy -f $TESTPOOL2
|
||||
fi
|
||||
if datasetexists $LOGPOOL ; then
|
||||
log_must zpool destroy -f $LOGPOOL
|
||||
fi
|
||||
if datasetexists ${LOGPOOL}2 ; then
|
||||
log_must zpool destroy -f ${LOGPOOL}2
|
||||
fi
|
||||
|
||||
log_pass
|
|
@ -0,0 +1,32 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/shared_log/shared_log.cfg
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
log_pass
|
|
@ -0,0 +1,30 @@
|
|||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
export LOGPOOL="${TESTPOOL}_log"
|
||||
read -r DISK0 DISK1 DISK2 _ <<<"$DISKS"
|
||||
export DISK0 DISK1 DISK2
|
|
@ -0,0 +1,47 @@
|
|||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
#
|
||||
# Copyright (c) 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
. $STF_SUITE/tests/functional/shared_log/shared_log.cfg
|
||||
|
||||
function cleanup
|
||||
{
|
||||
zpool import $LOGPOOL
|
||||
zpool import ${LOGPOOL}2
|
||||
zpool import -m $TESTPOOL
|
||||
zpool import -m $TESTPOOL2
|
||||
poolexists $TESTPOOL && destroy_pool $TESTPOOL
|
||||
poolexists $TESTPOOL2 && destroy_pool $TESTPOOL2
|
||||
poolexists $LOGPOOL && destroy_pool $LOGPOOL
|
||||
poolexists ${LOGPOOL}2 && destroy_pool ${LOGPOOL}2
|
||||
}
|
||||
|
||||
function verify_shared_log
|
||||
{
|
||||
local target="$1"
|
||||
local log_pool_name="$2"
|
||||
|
||||
zpool list -v $target | grep -A 1 "shared log" | tail -n 1 | grep "^ *$log_pool_name" >/dev/null
|
||||
return $?
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/shared_log/shared_log.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Creating a pool with a shared log succeeds.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create shared log pool
|
||||
# 2. Create client pool with shared log
|
||||
# 3. Display pool status
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
log_assert "Creating a pool with a shared log succeeds."
|
||||
log_onexit cleanup
|
||||
|
||||
log_must create_pool $LOGPOOL -L "$DISK0"
|
||||
log_must create_pool $TESTPOOL -l $LOGPOOL "$DISK1"
|
||||
log_must verify_shared_log $TESTPOOL $LOGPOOL
|
||||
verify_pool $LOGPOOL
|
||||
verify_pool $TESTPOOL
|
||||
|
||||
log_pass "Creating a pool with a shared log succeeds."
|
|
@ -0,0 +1,61 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/shared_log/shared_log.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Using a pool with a shared log device succeeds at basic operations.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create shared log pool & client
|
||||
# 2. Create sync=always fs on client
|
||||
# 3. Write data to fs
|
||||
# 4. Export & import client
|
||||
# 5. Write data to fs again
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
log_assert "Using a pool with a shared log device succeeds at basic operations."
|
||||
log_onexit cleanup
|
||||
|
||||
typeset FS="$TESTPOOL/fs"
|
||||
|
||||
log_must create_pool $LOGPOOL -L "$DISK0"
|
||||
log_must create_pool $TESTPOOL -l $LOGPOOL "$DISK1"
|
||||
log_must verify_shared_log $TESTPOOL $LOGPOOL
|
||||
log_must zfs create -o sync=always -o recordsize=8k $FS
|
||||
|
||||
mntpnt=$(get_prop mountpoint $FS)
|
||||
log_must dd if=/dev/urandom of="$mntpnt/f1" bs=8k count=128
|
||||
log_must zpool export $TESTPOOL
|
||||
log_must zpool import $TESTPOOL
|
||||
log_must dd if=/dev/urandom of="$mntpnt/f1" bs=8k count=128
|
||||
verify_pool $LOGPOOL
|
||||
verify_pool $TESTPOOL
|
||||
|
||||
log_pass "Using a pool with a shared log device succeeds at basic operations."
|
|
@ -0,0 +1,64 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/shared_log/shared_log.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Shared log pool can be exported and imported.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create shared log pool & client
|
||||
# 2. Write some data to the client pool
|
||||
# 3. Export client
|
||||
# 4. Export & import provider
|
||||
# 5. Import client
|
||||
# 6. Write data to client
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
log_assert "Shared log pool can be exported and imported."
|
||||
log_onexit cleanup
|
||||
|
||||
typeset FS="$TESTPOOL/fs"
|
||||
|
||||
log_must create_pool $LOGPOOL -L "$DISK0"
|
||||
log_must create_pool $TESTPOOL -l $LOGPOOL "$DISK1"
|
||||
log_must verify_shared_log $TESTPOOL $LOGPOOL
|
||||
log_must zfs create -o sync=always -o recordsize=8k $FS
|
||||
mntpnt=$(get_prop mountpoint $FS)
|
||||
|
||||
log_must dd if=/dev/urandom of="$mntpnt/f1" bs=8k count=128
|
||||
log_must zpool export $TESTPOOL
|
||||
log_must zpool export $LOGPOOL
|
||||
log_must zpool import $LOGPOOL
|
||||
log_must zpool import $TESTPOOL
|
||||
log_must dd if=/dev/urandom of="$mntpnt/f2" bs=8k count=128
|
||||
verify_pool $LOGPOOL
|
||||
verify_pool $TESTPOOL
|
||||
|
||||
log_pass "Shared log pool can be exported and imported."
|
|
@ -0,0 +1,70 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/shared_log/shared_log.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Client pools can be reimported without provider, with flag.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create shared log pools & client
|
||||
# 2. Write data to client
|
||||
# 3. Export client and provider
|
||||
# 4. Import client with -m
|
||||
# 5. Export client
|
||||
# 6. Import client with -m and new provider
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
log_assert "Client pools can be reimported without provider, with flag."
|
||||
log_onexit cleanup
|
||||
|
||||
typeset FS="$TESTPOOL/fs"
|
||||
|
||||
log_must create_pool $LOGPOOL -L "$DISK0"
|
||||
log_must create_pool ${LOGPOOL}2 -L "$DISK1"
|
||||
log_must create_pool $TESTPOOL -l $LOGPOOL "$DISK2"
|
||||
log_must verify_shared_log $TESTPOOL $LOGPOOL
|
||||
log_must zfs create -o sync=always -o recordsize=8k $FS
|
||||
mntpnt=$(get_prop mountpoint $FS)
|
||||
|
||||
log_must dd if=/dev/urandom of="$mntpnt/f1" bs=8k count=128
|
||||
log_must zpool export $TESTPOOL
|
||||
log_must zpool export $LOGPOOL
|
||||
log_must zpool import -m $TESTPOOL
|
||||
log_must dd if=/dev/urandom of="$mntpnt/f2" bs=8k count=128
|
||||
log_must zpool export $TESTPOOL
|
||||
log_must zpool import $LOGPOOL
|
||||
log_must zpool import -m -L ${LOGPOOL}2 $TESTPOOL
|
||||
log_must verify_shared_log $TESTPOOL ${LOGPOOL}2
|
||||
log_must dd if=/dev/urandom of="$mntpnt/f3" bs=8k count=128
|
||||
verify_pool $LOGPOOL
|
||||
verify_pool $LOGPOOL2
|
||||
verify_pool $TESTPOOL
|
||||
|
||||
log_pass "Client pools can be reimported without provider, with flag."
|
|
@ -0,0 +1,58 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/shared_log/shared_log.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Test scrub with client and provider pools.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create shared log pool & client
|
||||
# 2. Write some data to the client pool
|
||||
# 3. Scrub client and provider pools
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
log_assert "Test scrub with client and provider pools."
|
||||
log_onexit cleanup
|
||||
|
||||
typeset FS="$TESTPOOL/fs"
|
||||
|
||||
log_must create_pool $LOGPOOL -L "$DISK0"
|
||||
log_must create_pool $TESTPOOL -l $LOGPOOL "$DISK1"
|
||||
log_must verify_shared_log $TESTPOOL $LOGPOOL
|
||||
log_must zfs create -o sync=always -o recordsize=8k $FS
|
||||
mntpnt=$(get_prop mountpoint $FS)
|
||||
|
||||
log_must dd if=/dev/urandom of="$mntpnt/f1" bs=8k count=128
|
||||
log_must zpool scrub $LOGPOOL
|
||||
log_must zpool scrub $TESTPOOL
|
||||
log_must zpool wait -t scrub $LOGPOOL
|
||||
log_must zpool wait -t scrub $TESTPOOL
|
||||
|
||||
log_pass "Test scrub with client and provider pools."
|
|
@ -0,0 +1,78 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/shared_log/shared_log.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Negative shared log testing.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Attempt to create a client pool with a missing shared log pool
|
||||
# 2. Attempt to create a client pool with mis-named shared log pool
|
||||
# 3. Attempt to create a client pool with a shared log and a log device
|
||||
# 4. Attempt to use a client pool after the shared log has been destroyed
|
||||
# 5. Attempt to create a client pool when the feature is disabled
|
||||
# 6. Attempt to export/destroy an active shared log
|
||||
# 7. Attempt to reguid a client/log pool
|
||||
# 8. Attempt to checkpoint a client/log pool
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
log_assert "Negative shared log testing."
|
||||
log_onexit cleanup
|
||||
|
||||
log_mustnot create_pool $TESTPOOL -l $LOGPOOL "$DISK0"
|
||||
|
||||
log_must create_pool $TESTPOOL2 "$DISK2"
|
||||
log_mustnot create_pool $TESTPOOL -l $TESTPOOL2 "$DISK0"
|
||||
log_must zpool destroy $TESTPOOL2
|
||||
|
||||
log_must create_pool $LOGPOOL -L "$DISK0"
|
||||
log_mustnot create_pool $TESTPOOL -l "${LOGPOOL}2" "$DISK1"
|
||||
log_mustnot create_pool $TESTPOOL -l $LOGPOOL "$DISK1" log "$DISK2"
|
||||
|
||||
log_must create_pool ${LOGPOOL}2 -L "$DISK1"
|
||||
log_must zpool destroy ${LOGPOOL}2
|
||||
|
||||
typeset FS="$LOGPOOL/fs"
|
||||
log_mustnot zfs create -o sync=always -o recordsize=8k $FS
|
||||
|
||||
log_mustnot create_pool $TESTPOOL -l $LOGPOOL -o feature@shared_log=disabled "$DISK1"
|
||||
log_mustnot create_pool ${LOGPOOL}2 -L -o feature@shared_log=disabled "$DISK1"
|
||||
|
||||
log_must create_pool $TESTPOOL -l $LOGPOOL "$DISK1"
|
||||
log_mustnot zpool export $LOGPOOL
|
||||
log_mustnot zpool destroy $LOGPOOL
|
||||
|
||||
log_mustnot zpool reguid $LOGPOOL
|
||||
log_mustnot zpool reguid $TESTPOOL
|
||||
|
||||
log_mustnot zpool checkpoint $TESTPOOL
|
||||
log_mustnot zpool checkpoint $LOGPOOL
|
||||
|
||||
log_pass "Negative shared log testing."
|
|
@ -0,0 +1,51 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2024 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/shared_log/shared_log.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Test fault behavior of shared log pool
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create shared log pool & client
|
||||
# 2. Fault the provider pool
|
||||
# 3. Verify the client pool also faults
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
log_assert "Test fault behavior of shared log pools."
|
||||
log_onexit cleanup
|
||||
|
||||
typeset FS="$TESTPOOL/fs"
|
||||
|
||||
log_must create_pool $LOGPOOL -L "$DISK0"
|
||||
log_must create_pool $TESTPOOL -l $LOGPOOL "$DISK1"
|
||||
log_must zinject -d "$DISK0" -A degrade $LOGPOOL
|
||||
log_must eval "zpool status -e $TESTPOOL | grep DEGRADED"
|
||||
|
||||
log_pass "Test fault behavior of shared log pools."
|
|
@ -0,0 +1,81 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2024 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/tests/functional/shared_log/shared_log.kshlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Test zpool recycle
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create shared log pool & clients
|
||||
# 2. Verify zpool recycle -a doesn't recycle anything
|
||||
# 3. Export clients
|
||||
# 4. Verify zpool recycle -a recycles everything
|
||||
# 5. Re-add clients and export both
|
||||
# 6. Verify zpool recycle of a single client works as expected
|
||||
# 7. Re-add client and export it
|
||||
# 8. Verify zpool recycle of multiple clients works as expected
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
log_assert "Test zpool recycle."
|
||||
log_onexit cleanup
|
||||
|
||||
typeset FS="$TESTPOOL/fs"
|
||||
|
||||
log_must create_pool $LOGPOOL -L "$DISK0"
|
||||
log_must create_pool $TESTPOOL -l $LOGPOOL "$DISK1"
|
||||
log_must create_pool ${TESTPOOL}2 -l $LOGPOOL "$DISK2"
|
||||
log_must zfs create -o sync=always ${TESTPOOL}/fs
|
||||
log_must zfs create -o sync=always ${TESTPOOL}2/fs
|
||||
log_must dd if=/dev/urandom of=/${TESTPOOL}/fs/f1 bs=128k count=128
|
||||
log_must dd if=/dev/urandom of=/${TESTPOOL}2/fs/f1 bs=128k count=128
|
||||
log_must eval "zpool recycle -a -v $LOGPOOL | grep '\\[\\]' >/dev/null"
|
||||
|
||||
log_must zpool export $TESTPOOL
|
||||
log_must zpool export ${TESTPOOL}2
|
||||
log_must zpool recycle -a -v $LOGPOOL
|
||||
log_mustnot zpool import $TESTPOOL
|
||||
log_mustnot zpool import ${TESTPOOL}2
|
||||
|
||||
log_must zpool import -m -L $LOGPOOL $TESTPOOL
|
||||
log_must zpool import -m -L $LOGPOOL ${TESTPOOL}2
|
||||
log_must dd if=/dev/urandom of=/${TESTPOOL}/fs/f1 bs=128k count=128
|
||||
log_must zpool export $TESTPOOL
|
||||
log_must zpool export ${TESTPOOL}2
|
||||
log_must zpool recycle $LOGPOOL $TESTPOOL
|
||||
log_mustnot zpool import $TESTPOOL
|
||||
|
||||
log_must zpool import -m -L $LOGPOOL $TESTPOOL
|
||||
log_must dd if=/dev/urandom of=/${TESTPOOL}/fs/f1 bs=128k count=128
|
||||
log_must zpool export $TESTPOOL
|
||||
log_must zpool recycle $LOGPOOL $TESTPOOL ${TESTPOOL2}
|
||||
log_mustnot zpool import $TESTPOOL
|
||||
log_mustnot zpool import ${TESTPOOL}2
|
||||
|
||||
log_pass "Test zpool recycle."
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2015, 2021 by Delphix. All rights reserved.
|
||||
# Copyright (c) 2015, 2023 by Delphix. All rights reserved.
|
||||
# Copyright (c) 2016, Intel Corporation.
|
||||
#
|
||||
|
||||
|
@ -21,6 +21,7 @@ export PERF_RUNTIME=${PERF_RUNTIME:-'180'}
|
|||
export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
|
||||
export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
|
||||
export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
|
||||
export PERF_LOG_TYPES=${PERF_LOG_TYPES:-"none slog shared"}
|
||||
|
||||
# Default to JSON for fio output
|
||||
export PERF_FIO_FORMAT=${PERF_FIO_FORMAT:-'json'}
|
||||
|
@ -44,12 +45,13 @@ function get_suffix
|
|||
typeset threads=$1
|
||||
typeset sync=$2
|
||||
typeset iosize=$3
|
||||
typeset log_type=$4
|
||||
|
||||
typeset sync_str=$(get_sync_str $sync)
|
||||
typeset filesystems=$(get_nfilesystems)
|
||||
|
||||
typeset suffix="$sync_str.$iosize-ios"
|
||||
suffix="$suffix.$threads-threads.$filesystems-filesystems"
|
||||
suffix="$suffix.$threads-threads.$filesystems-filesystems.$log_type-log"
|
||||
echo $suffix
|
||||
}
|
||||
|
||||
|
@ -63,9 +65,10 @@ function do_fio_run_impl
|
|||
typeset threads_per_fs=$5
|
||||
typeset sync=$6
|
||||
typeset iosize=$7
|
||||
typeset log_type=$8
|
||||
|
||||
typeset sync_str=$(get_sync_str $sync)
|
||||
log_note "Running with $threads $sync_str threads, $iosize ios"
|
||||
log_note "Running with $threads $sync_str threads, $iosize ios with log $log_type"
|
||||
|
||||
if [[ -n $threads_per_fs && $threads_per_fs -ne 0 ]]; then
|
||||
log_must test $do_recreate
|
||||
|
@ -73,7 +76,7 @@ function do_fio_run_impl
|
|||
fi
|
||||
|
||||
if $do_recreate; then
|
||||
recreate_perf_pool
|
||||
recreate_perf_pool $log_type
|
||||
|
||||
#
|
||||
# A value of zero for "threads_per_fs" is "special", and
|
||||
|
@ -127,7 +130,7 @@ function do_fio_run_impl
|
|||
fi
|
||||
|
||||
# This will be part of the output filename.
|
||||
typeset suffix=$(get_suffix $threads $sync $iosize)
|
||||
typeset suffix=$(get_suffix $threads $sync $iosize $log_type)
|
||||
|
||||
# Start the data collection
|
||||
do_collect_scripts $suffix
|
||||
|
@ -168,20 +171,27 @@ function do_fio_run
|
|||
typeset script=$1
|
||||
typeset do_recreate=$2
|
||||
typeset clear_cache=$3
|
||||
typeset log_types=$4
|
||||
typeset threads threads_per_fs sync iosize
|
||||
|
||||
for threads in $PERF_NTHREADS; do
|
||||
for threads_per_fs in $PERF_NTHREADS_PER_FS; do
|
||||
for sync in $PERF_SYNC_TYPES; do
|
||||
for iosize in $PERF_IOSIZES; do
|
||||
do_fio_run_impl \
|
||||
$script \
|
||||
$do_recreate \
|
||||
$clear_cache \
|
||||
$threads \
|
||||
$threads_per_fs \
|
||||
$sync \
|
||||
$iosize
|
||||
for logtype in $log_types; do
|
||||
if [[ $sync == "0" && $logtype != "none" ]]; then
|
||||
continue
|
||||
fi
|
||||
do_fio_run_impl \
|
||||
$script \
|
||||
$do_recreate \
|
||||
$clear_cache \
|
||||
$threads \
|
||||
$threads_per_fs \
|
||||
$sync \
|
||||
$iosize \
|
||||
$logtype
|
||||
done
|
||||
done
|
||||
done
|
||||
done
|
||||
|
@ -286,8 +296,10 @@ function clear_zinject_delays
|
|||
#
|
||||
function recreate_perf_pool
|
||||
{
|
||||
typeset logtype=$1
|
||||
[[ -n $PERFPOOL ]] || log_fail "The \$PERFPOOL variable isn't set."
|
||||
|
||||
log_note "recreating $PERFPOOL with $logtype"
|
||||
#
|
||||
# In case there's been some "leaked" zinject delays, or if the
|
||||
# performance test injected some delays itself, we clear all
|
||||
|
@ -297,6 +309,23 @@ function recreate_perf_pool
|
|||
#
|
||||
clear_zinject_delays
|
||||
|
||||
if [[ $logtype == "none" ]]; then
|
||||
destroy_pool $PERFPOOL
|
||||
destroy_pool "${PERFPOOL}_log"
|
||||
create_pool $PERFPOOL $DISKS
|
||||
else
|
||||
typeset disks="${DISKS% *}"
|
||||
typeset log_disk="${DISKS##* }"
|
||||
if [[ $logtype == "slog" ]]; then
|
||||
destroy_pool $PERFPOOL
|
||||
destroy_pool "${PERFPOOL}_log"
|
||||
create_pool $PERFPOOL $disks log $log_disk
|
||||
else
|
||||
destroy_pool $PERFPOOL
|
||||
create_pool ${PERFPOOL}_log -L $log_disk
|
||||
create_pool $PERFPOOL -l ${PERFPOOL}_log $disks
|
||||
fi
|
||||
fi
|
||||
#
|
||||
# This function handles the case where the pool already exists,
|
||||
# and will destroy the previous pool and recreate a new pool.
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
#!/bin/ksh -p
|
||||
#
|
||||
# CDDL HEADER START
|
||||
#
|
||||
# The contents of this file are subject to the terms of the
|
||||
# Common Development and Distribution License (the "License").
|
||||
# You may not use this file except in compliance with the License.
|
||||
#
|
||||
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
||||
# or https://opensource.org/licenses/CDDL-1.0.
|
||||
# See the License for the specific language governing permissions
|
||||
# and limitations under the License.
|
||||
#
|
||||
# When distributing Covered Code, include this CDDL HEADER in each
|
||||
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
||||
# If applicable, add the following below this CDDL HEADER, with the
|
||||
# fields enclosed by brackets "[]" replaced with your own identifying
|
||||
# information: Portions Copyright [yyyy] [name of copyright owner]
|
||||
#
|
||||
# CDDL HEADER END
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 20236 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
if datasetexists $PERFPOOL ; then
|
||||
log_must destroy_pool $PERFPOOL
|
||||
fi
|
||||
if datasetexists ${PERFPOOL}_log ; then
|
||||
log_must destroy_pool ${PERFPOOL}_log
|
||||
fi
|
||||
|
||||
log_pass
|
|
@ -12,7 +12,7 @@
|
|||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2015, 2021 by Delphix. All rights reserved.
|
||||
# Copyright (c) 2015, 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
|
@ -45,55 +45,56 @@ function cleanup
|
|||
# kill fio and iostat
|
||||
pkill fio
|
||||
pkill iostat
|
||||
recreate_perf_pool
|
||||
}
|
||||
|
||||
trap "log_fail \"Measure IO stats during random read load\"" SIGTERM
|
||||
log_onexit cleanup
|
||||
|
||||
recreate_perf_pool
|
||||
populate_perf_filesystems
|
||||
for logtype in $PERF_LOG_TYPES; do
|
||||
recreate_perf_pool $logtype
|
||||
populate_perf_filesystems
|
||||
|
||||
# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
|
||||
export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
|
||||
# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
|
||||
export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
|
||||
|
||||
# Variables specific to this test for use by fio.
|
||||
export PERF_NTHREADS=${PERF_NTHREADS:-'16 32'}
|
||||
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
|
||||
export PERF_IOSIZES=${PERF_IOSIZES:-'8k'}
|
||||
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
|
||||
|
||||
# Layout the files to be used by the read tests. Create as many files as the
|
||||
# largest number of threads. An fio run with fewer threads will use a subset
|
||||
# of the available files.
|
||||
export NUMJOBS=$(get_max $PERF_NTHREADS)
|
||||
export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
|
||||
export DIRECTORY=$(get_directory)
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
|
||||
# Variables specific to this test for use by fio.
|
||||
export PERF_NTHREADS=${PERF_NTHREADS:-'16 32'}
|
||||
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
|
||||
export PERF_IOSIZES=${PERF_IOSIZES:-'8k'}
|
||||
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
|
||||
# Set up the scripts and output files that will log performance data.
|
||||
lun_list=$(pool_to_lun_list $PERFPOOL)
|
||||
log_note "Collecting backend IO stats with lun list $lun_list"
|
||||
if is_linux; then
|
||||
typeset perf_record_cmd="perf record -F 99 -a -g -q \
|
||||
-o /dev/stdout -- sleep ${PERF_RUNTIME}"
|
||||
|
||||
# Layout the files to be used by the read tests. Create as many files as the
|
||||
# largest number of threads. An fio run with fewer threads will use a subset
|
||||
# of the available files.
|
||||
export NUMJOBS=$(get_max $PERF_NTHREADS)
|
||||
export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
|
||||
export DIRECTORY=$(get_directory)
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
export collect_scripts=(
|
||||
"zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
|
||||
"vmstat -t 1" "vmstat"
|
||||
"mpstat -P ALL 1" "mpstat"
|
||||
"iostat -tdxyz 1" "iostat"
|
||||
"$perf_record_cmd" "perf"
|
||||
)
|
||||
else
|
||||
export collect_scripts=(
|
||||
"$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
|
||||
"vmstat -T d 1" "vmstat"
|
||||
"mpstat -T d 1" "mpstat"
|
||||
"iostat -T d -xcnz 1" "iostat"
|
||||
)
|
||||
fi
|
||||
|
||||
# Set up the scripts and output files that will log performance data.
|
||||
lun_list=$(pool_to_lun_list $PERFPOOL)
|
||||
log_note "Collecting backend IO stats with lun list $lun_list"
|
||||
if is_linux; then
|
||||
typeset perf_record_cmd="perf record -F 99 -a -g -q \
|
||||
-o /dev/stdout -- sleep ${PERF_RUNTIME}"
|
||||
|
||||
export collect_scripts=(
|
||||
"zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
|
||||
"vmstat -t 1" "vmstat"
|
||||
"mpstat -P ALL 1" "mpstat"
|
||||
"iostat -tdxyz 1" "iostat"
|
||||
"$perf_record_cmd" "perf"
|
||||
)
|
||||
else
|
||||
export collect_scripts=(
|
||||
"$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
|
||||
"vmstat -T d 1" "vmstat"
|
||||
"mpstat -T d 1" "mpstat"
|
||||
"iostat -T d -xcnz 1" "iostat"
|
||||
)
|
||||
fi
|
||||
|
||||
log_note "Random reads with settings: $(print_perf_settings)"
|
||||
do_fio_run random_reads.fio false true
|
||||
log_note "Random reads with settings: $(print_perf_settings)"
|
||||
do_fio_run random_reads.fio false true $logtype
|
||||
done
|
||||
log_pass "Measure IO stats during random read load"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2015, 2021 by Delphix. All rights reserved.
|
||||
# Copyright (c) 2015, 2022 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
|
@ -45,55 +45,56 @@ function cleanup
|
|||
# kill fio and iostat
|
||||
pkill fio
|
||||
pkill iostat
|
||||
recreate_perf_pool
|
||||
}
|
||||
|
||||
trap "log_fail \"Measure IO stats during random read load\"" SIGTERM
|
||||
log_onexit cleanup
|
||||
|
||||
recreate_perf_pool
|
||||
populate_perf_filesystems
|
||||
for logtype in $PERF_LOG_TYPES; do
|
||||
recreate_perf_pool $logtype
|
||||
populate_perf_filesystems
|
||||
|
||||
# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
|
||||
export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
|
||||
# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
|
||||
export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
|
||||
|
||||
# Variables specific to this test for use by fio.
|
||||
export PERF_NTHREADS=${PERF_NTHREADS:-'32 64'}
|
||||
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
|
||||
export PERF_IOSIZES='bssplit' # bssplit used instead of fixed sizes
|
||||
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
|
||||
|
||||
# Layout the files to be used by the readwrite tests. Create as many files
|
||||
# as the largest number of threads. An fio run with fewer threads will use
|
||||
# a subset of the available files.
|
||||
export NUMJOBS=$(get_max $PERF_NTHREADS)
|
||||
export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
|
||||
export DIRECTORY=$(get_directory)
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
|
||||
# Set up the scripts and output files that will log performance data.
|
||||
lun_list=$(pool_to_lun_list $PERFPOOL)
|
||||
log_note "Collecting backend IO stats with lun list $lun_list"
|
||||
if is_linux; then
|
||||
typeset perf_record_cmd="perf record -F 99 -a -g -q \
|
||||
-o /dev/stdout -- sleep ${PERF_RUNTIME}"
|
||||
|
||||
export collect_scripts=(
|
||||
"zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
|
||||
"vmstat -t 1" "vmstat"
|
||||
"mpstat -P ALL 1" "mpstat"
|
||||
"iostat -tdxyz 1" "iostat"
|
||||
"$perf_record_cmd" "perf"
|
||||
)
|
||||
else
|
||||
export collect_scripts=(
|
||||
"$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
|
||||
"vmstat -T d 1" "vmstat"
|
||||
"mpstat -T d 1" "mpstat"
|
||||
"iostat -T d -xcnz 1" "iostat"
|
||||
)
|
||||
fi
|
||||
|
||||
# Variables specific to this test for use by fio.
|
||||
export PERF_NTHREADS=${PERF_NTHREADS:-'32 64'}
|
||||
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
|
||||
export PERF_IOSIZES='bssplit' # bssplit used instead of fixed sizes
|
||||
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
|
||||
|
||||
# Layout the files to be used by the readwrite tests. Create as many files
|
||||
# as the largest number of threads. An fio run with fewer threads will use
|
||||
# a subset of the available files.
|
||||
export NUMJOBS=$(get_max $PERF_NTHREADS)
|
||||
export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
|
||||
export DIRECTORY=$(get_directory)
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
|
||||
# Set up the scripts and output files that will log performance data.
|
||||
lun_list=$(pool_to_lun_list $PERFPOOL)
|
||||
log_note "Collecting backend IO stats with lun list $lun_list"
|
||||
if is_linux; then
|
||||
typeset perf_record_cmd="perf record -F 99 -a -g -q \
|
||||
-o /dev/stdout -- sleep ${PERF_RUNTIME}"
|
||||
|
||||
export collect_scripts=(
|
||||
"zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
|
||||
"vmstat -t 1" "vmstat"
|
||||
"mpstat -P ALL 1" "mpstat"
|
||||
"iostat -tdxyz 1" "iostat"
|
||||
"$perf_record_cmd" "perf"
|
||||
)
|
||||
else
|
||||
export collect_scripts=(
|
||||
"$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
|
||||
"vmstat -T d 1" "vmstat"
|
||||
"mpstat -T d 1" "mpstat"
|
||||
"iostat -T d -xcnz 1" "iostat"
|
||||
)
|
||||
fi
|
||||
|
||||
log_note "Random reads and writes with settings: $(print_perf_settings)"
|
||||
do_fio_run random_readwrite.fio false true
|
||||
log_note "Random reads and writes with settings: $(print_perf_settings)"
|
||||
do_fio_run random_readwrite.fio false true $logtype
|
||||
done
|
||||
log_pass "Measure IO stats during random read and write load"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/ksh
|
||||
tests/zfs-tests/tests/perf/regression/random_readwrite_fixed.ksh#!/bin/ksh
|
||||
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2017, 2021 by Delphix. All rights reserved.
|
||||
# Copyright (c) 2017, 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
|
@ -35,57 +35,58 @@ function cleanup
|
|||
# kill fio and iostat
|
||||
pkill fio
|
||||
pkill iostat
|
||||
recreate_perf_pool
|
||||
}
|
||||
|
||||
trap "log_fail \"Measure IO stats during random read write load\"" SIGTERM
|
||||
log_onexit cleanup
|
||||
|
||||
recreate_perf_pool
|
||||
populate_perf_filesystems
|
||||
for logtype in $PERF_LOG_TYPES; do
|
||||
recreate_perf_pool $logtype
|
||||
populate_perf_filesystems
|
||||
|
||||
# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
|
||||
export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
|
||||
|
||||
# Variables specific to this test for use by fio.
|
||||
export PERF_NTHREADS=${PERF_NTHREADS:-'64 128'}
|
||||
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
|
||||
export PERF_IOSIZES=${PERF_IOSIZES:-'8k'}
|
||||
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'0 1'}
|
||||
|
||||
# Layout the files to be used by the readwrite tests. Create as many files
|
||||
# as the largest number of threads. An fio run with fewer threads will use
|
||||
# a subset of the available files.
|
||||
export NUMJOBS=$(get_max $PERF_NTHREADS)
|
||||
export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
|
||||
export DIRECTORY=$(get_directory)
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
|
||||
# Set up the scripts and output files that will log performance data.
|
||||
lun_list=$(pool_to_lun_list $PERFPOOL)
|
||||
log_note "Collecting backend IO stats with lun list $lun_list"
|
||||
if is_linux; then
|
||||
typeset perf_record_cmd="perf record -F 99 -a -g -q \
|
||||
-o /dev/stdout -- sleep ${PERF_RUNTIME}"
|
||||
|
||||
export collect_scripts=(
|
||||
"zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
|
||||
"vmstat -t 1" "vmstat"
|
||||
"mpstat -P ALL 1" "mpstat"
|
||||
"iostat -tdxyz 1" "iostat"
|
||||
"$perf_record_cmd" "perf"
|
||||
)
|
||||
else
|
||||
export collect_scripts=(
|
||||
"kstat zfs:0 1" "kstat"
|
||||
"vmstat -T d 1" "vmstat"
|
||||
"mpstat -T d 1" "mpstat"
|
||||
"iostat -T d -xcnz 1" "iostat"
|
||||
"dtrace -Cs $PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
|
||||
"dtrace -s $PERF_SCRIPTS/profile.d" "profile"
|
||||
)
|
||||
fi
|
||||
|
||||
# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
|
||||
export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
|
||||
|
||||
# Variables specific to this test for use by fio.
|
||||
export PERF_NTHREADS=${PERF_NTHREADS:-'64 128'}
|
||||
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
|
||||
export PERF_IOSIZES=${PERF_IOSIZES:-'8k'}
|
||||
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'0 1'}
|
||||
|
||||
# Layout the files to be used by the readwrite tests. Create as many files
|
||||
# as the largest number of threads. An fio run with fewer threads will use
|
||||
# a subset of the available files.
|
||||
export NUMJOBS=$(get_max $PERF_NTHREADS)
|
||||
export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
|
||||
export DIRECTORY=$(get_directory)
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
|
||||
# Set up the scripts and output files that will log performance data.
|
||||
lun_list=$(pool_to_lun_list $PERFPOOL)
|
||||
log_note "Collecting backend IO stats with lun list $lun_list"
|
||||
if is_linux; then
|
||||
typeset perf_record_cmd="perf record -F 99 -a -g -q \
|
||||
-o /dev/stdout -- sleep ${PERF_RUNTIME}"
|
||||
|
||||
export collect_scripts=(
|
||||
"zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
|
||||
"vmstat -t 1" "vmstat"
|
||||
"mpstat -P ALL 1" "mpstat"
|
||||
"iostat -tdxyz 1" "iostat"
|
||||
"$perf_record_cmd" "perf"
|
||||
)
|
||||
else
|
||||
export collect_scripts=(
|
||||
"kstat zfs:0 1" "kstat"
|
||||
"vmstat -T d 1" "vmstat"
|
||||
"mpstat -T d 1" "mpstat"
|
||||
"iostat -T d -xcnz 1" "iostat"
|
||||
"dtrace -Cs $PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
|
||||
"dtrace -s $PERF_SCRIPTS/profile.d" "profile"
|
||||
)
|
||||
fi
|
||||
|
||||
log_note "Random reads and writes with settings: $(print_perf_settings)"
|
||||
do_fio_run random_readwrite_fixed.fio false true
|
||||
log_note "Random reads and writes with settings: $(print_perf_settings)"
|
||||
do_fio_run random_readwrite_fixed.fio false true $logtype
|
||||
done
|
||||
log_pass "Measure IO stats during random read and write load"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2015, 2021 by Delphix. All rights reserved.
|
||||
# Copyright (c) 2015, 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
|
@ -44,14 +44,12 @@ function cleanup
|
|||
# kill fio and iostat
|
||||
pkill fio
|
||||
pkill iostat
|
||||
recreate_perf_pool
|
||||
}
|
||||
|
||||
trap "log_fail \"Measure IO stats during random read load\"" SIGTERM
|
||||
log_onexit cleanup
|
||||
|
||||
recreate_perf_pool
|
||||
populate_perf_filesystems
|
||||
recreate_perf_pool none
|
||||
|
||||
# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
|
||||
export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
|
||||
|
@ -86,5 +84,5 @@ else
|
|||
fi
|
||||
|
||||
log_note "Random writes with settings: $(print_perf_settings)"
|
||||
do_fio_run random_writes.fio true false
|
||||
do_fio_run random_writes.fio true false "$PERF_LOG_TYPES"
|
||||
log_pass "Measure IO stats during random write load"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2015, 2021 by Delphix. All rights reserved.
|
||||
# Copyright (c) 2015, 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
@ -26,21 +26,12 @@ function cleanup
|
|||
pkill fio
|
||||
pkill iostat
|
||||
|
||||
#
|
||||
# We're using many filesystems depending on the number of
|
||||
# threads for each test, and there's no good way to get a list
|
||||
# of all the filesystems that should be destroyed on cleanup
|
||||
# (i.e. the list of filesystems used for the last test ran).
|
||||
# Thus, we simply recreate the pool as a way to destroy all
|
||||
# filesystems and leave a fresh pool behind.
|
||||
#
|
||||
recreate_perf_pool
|
||||
}
|
||||
|
||||
trap "log_fail \"Measure IO stats during random write load\"" SIGTERM
|
||||
log_onexit cleanup
|
||||
|
||||
recreate_perf_pool
|
||||
recreate_perf_pool none
|
||||
|
||||
# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
|
||||
export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
|
||||
|
@ -82,5 +73,5 @@ else
|
|||
fi
|
||||
log_note \
|
||||
"ZIL specific random write workload with settings: $(print_perf_settings)"
|
||||
do_fio_run random_writes.fio true false
|
||||
do_fio_run random_writes.fio true false "$PERF_LOG_TYPES"
|
||||
log_pass "Measure IO stats during ZIL specific random write workload"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2015, 2021 by Delphix. All rights reserved.
|
||||
# Copyright (c) 2015, 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
|
@ -43,57 +43,59 @@ function cleanup
|
|||
# kill fio and iostat
|
||||
pkill fio
|
||||
pkill iostat
|
||||
recreate_perf_pool
|
||||
}
|
||||
|
||||
trap "log_fail \"Measure IO stats during random read load\"" SIGTERM
|
||||
log_onexit cleanup
|
||||
|
||||
recreate_perf_pool
|
||||
populate_perf_filesystems
|
||||
for logtype in $PERF_LOG_TYPES; do
|
||||
recreate_perf_pool $logtype
|
||||
populate_perf_filesystems
|
||||
|
||||
# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
|
||||
export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
|
||||
|
||||
# Variables specific to this test for use by fio.
|
||||
export PERF_NTHREADS=${PERF_NTHREADS:-'8 16'}
|
||||
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
|
||||
export PERF_IOSIZES=${PERF_IOSIZES:-'128k 1m'}
|
||||
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
|
||||
|
||||
# Layout the files to be used by the read tests. Create as many files as the
|
||||
# largest number of threads. An fio run with fewer threads will use a subset
|
||||
# of the available files.
|
||||
export NUMJOBS=$(get_max $PERF_NTHREADS)
|
||||
export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
|
||||
export DIRECTORY=$(get_directory)
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
|
||||
|
||||
# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
|
||||
export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
|
||||
# Set up the scripts and output files that will log performance data.
|
||||
lun_list=$(pool_to_lun_list $PERFPOOL)
|
||||
log_note "Collecting backend IO stats with lun list $lun_list"
|
||||
if is_linux; then
|
||||
typeset perf_record_cmd="perf record -F 99 -a -g -q \
|
||||
-o /dev/stdout -- sleep ${PERF_RUNTIME}"
|
||||
|
||||
# Variables specific to this test for use by fio.
|
||||
export PERF_NTHREADS=${PERF_NTHREADS:-'8 16'}
|
||||
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
|
||||
export PERF_IOSIZES=${PERF_IOSIZES:-'128k 1m'}
|
||||
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
|
||||
|
||||
# Layout the files to be used by the read tests. Create as many files as the
|
||||
# largest number of threads. An fio run with fewer threads will use a subset
|
||||
# of the available files.
|
||||
export NUMJOBS=$(get_max $PERF_NTHREADS)
|
||||
export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
|
||||
export DIRECTORY=$(get_directory)
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
|
||||
# Set up the scripts and output files that will log performance data.
|
||||
lun_list=$(pool_to_lun_list $PERFPOOL)
|
||||
log_note "Collecting backend IO stats with lun list $lun_list"
|
||||
if is_linux; then
|
||||
typeset perf_record_cmd="perf record -F 99 -a -g -q \
|
||||
-o /dev/stdout -- sleep ${PERF_RUNTIME}"
|
||||
|
||||
export collect_scripts=(
|
||||
"zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
|
||||
"$PERF_SCRIPTS/prefetch_io.sh $PERFPOOL 1" "prefetch"
|
||||
"vmstat -t 1" "vmstat"
|
||||
"mpstat -P ALL 1" "mpstat"
|
||||
"iostat -tdxyz 1" "iostat"
|
||||
"$perf_record_cmd" "perf"
|
||||
)
|
||||
else
|
||||
export collect_scripts=(
|
||||
"$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
|
||||
"$PERF_SCRIPTS/prefetch_io.d $PERFPOOL 1" "prefetch"
|
||||
"vmstat -T d 1" "vmstat"
|
||||
"mpstat -T d 1" "mpstat"
|
||||
"iostat -T d -xcnz 1" "iostat"
|
||||
)
|
||||
fi
|
||||
|
||||
log_note "Sequential reads with settings: $(print_perf_settings)"
|
||||
do_fio_run sequential_reads.fio false true
|
||||
export collect_scripts=(
|
||||
"zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
|
||||
"$PERF_SCRIPTS/prefetch_io.sh $PERFPOOL 1" "prefetch"
|
||||
"vmstat -t 1" "vmstat"
|
||||
"mpstat -P ALL 1" "mpstat"
|
||||
"iostat -tdxyz 1" "iostat"
|
||||
"$perf_record_cmd" "perf"
|
||||
)
|
||||
else
|
||||
export collect_scripts=(
|
||||
"$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
|
||||
"$PERF_SCRIPTS/prefetch_io.d $PERFPOOL 1" "prefetch"
|
||||
"vmstat -T d 1" "vmstat"
|
||||
"mpstat -T d 1" "mpstat"
|
||||
"iostat -T d -xcnz 1" "iostat"
|
||||
)
|
||||
fi
|
||||
|
||||
log_note "Sequential reads with settings: $(print_perf_settings)"
|
||||
do_fio_run sequential_reads.fio false true $logtype
|
||||
done
|
||||
log_pass "Measure IO stats during sequential read load"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2015, 2021 by Delphix. All rights reserved.
|
||||
# Copyright (c) 2015, 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
|
@ -35,57 +35,58 @@ function cleanup
|
|||
# kill fio and iostat
|
||||
pkill fio
|
||||
pkill iostat
|
||||
recreate_perf_pool
|
||||
}
|
||||
|
||||
trap "log_fail \"Measure IO stats during random read load\"" SIGTERM
|
||||
log_onexit cleanup
|
||||
|
||||
recreate_perf_pool
|
||||
populate_perf_filesystems
|
||||
for logtype in $PERF_LOG_TYPES; do
|
||||
recreate_perf_pool $logtype
|
||||
populate_perf_filesystems
|
||||
|
||||
# Make sure the working set can be cached in the arc. Aim for 1/2 of arc.
|
||||
export TOTAL_SIZE=$(($(get_max_arc_size) / 2))
|
||||
|
||||
# Variables specific to this test for use by fio.
|
||||
export PERF_NTHREADS=${PERF_NTHREADS:-'64 128'}
|
||||
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
|
||||
export PERF_IOSIZES=${PERF_IOSIZES:-'128k'}
|
||||
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
|
||||
|
||||
# Layout the files to be used by the read tests. Create as many files as the
|
||||
# largest number of threads. An fio run with fewer threads will use a subset
|
||||
# of the available files.
|
||||
export NUMJOBS=$(get_max $PERF_NTHREADS)
|
||||
export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
|
||||
export DIRECTORY=$(get_directory)
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
|
||||
# Set up the scripts and output files that will log performance data.
|
||||
lun_list=$(pool_to_lun_list $PERFPOOL)
|
||||
log_note "Collecting backend IO stats with lun list $lun_list"
|
||||
if is_linux; then
|
||||
typeset perf_record_cmd="perf record -F 99 -a -g -q \
|
||||
-o /dev/stdout -- sleep ${PERF_RUNTIME}"
|
||||
|
||||
# Make sure the working set can be cached in the arc. Aim for 1/2 of arc.
|
||||
export TOTAL_SIZE=$(($(get_max_arc_size) / 2))
|
||||
|
||||
# Variables specific to this test for use by fio.
|
||||
export PERF_NTHREADS=${PERF_NTHREADS:-'64 128'}
|
||||
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
|
||||
export PERF_IOSIZES=${PERF_IOSIZES:-'128k'}
|
||||
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
|
||||
|
||||
# Layout the files to be used by the read tests. Create as many files as the
|
||||
# largest number of threads. An fio run with fewer threads will use a subset
|
||||
# of the available files.
|
||||
export NUMJOBS=$(get_max $PERF_NTHREADS)
|
||||
export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
|
||||
export DIRECTORY=$(get_directory)
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
|
||||
# Set up the scripts and output files that will log performance data.
|
||||
lun_list=$(pool_to_lun_list $PERFPOOL)
|
||||
log_note "Collecting backend IO stats with lun list $lun_list"
|
||||
if is_linux; then
|
||||
typeset perf_record_cmd="perf record -F 99 -a -g -q \
|
||||
-o /dev/stdout -- sleep ${PERF_RUNTIME}"
|
||||
|
||||
export collect_scripts=(
|
||||
"zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
|
||||
"$PERF_SCRIPTS/prefetch_io.sh $PERFPOOL 1" "prefetch"
|
||||
"vmstat -t 1" "vmstat"
|
||||
"mpstat -P ALL 1" "mpstat"
|
||||
"iostat -tdxyz 1" "iostat"
|
||||
"$perf_record_cmd" "perf"
|
||||
)
|
||||
else
|
||||
export collect_scripts=(
|
||||
"$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
|
||||
"$PERF_SCRIPTS/prefetch_io.d $PERFPOOL 1" "prefetch"
|
||||
"vmstat -T d 1" "vmstat"
|
||||
"mpstat -T d 1" "mpstat"
|
||||
"iostat -T d -xcnz 1" "iostat"
|
||||
)
|
||||
fi
|
||||
|
||||
log_note "Sequential cached reads with settings: $(print_perf_settings)"
|
||||
do_fio_run sequential_reads.fio false false
|
||||
export collect_scripts=(
|
||||
"zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
|
||||
"$PERF_SCRIPTS/prefetch_io.sh $PERFPOOL 1" "prefetch"
|
||||
"vmstat -t 1" "vmstat"
|
||||
"mpstat -P ALL 1" "mpstat"
|
||||
"iostat -tdxyz 1" "iostat"
|
||||
"$perf_record_cmd" "perf"
|
||||
)
|
||||
else
|
||||
export collect_scripts=(
|
||||
"$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
|
||||
"$PERF_SCRIPTS/prefetch_io.d $PERFPOOL 1" "prefetch"
|
||||
"vmstat -T d 1" "vmstat"
|
||||
"mpstat -T d 1" "mpstat"
|
||||
"iostat -T d -xcnz 1" "iostat"
|
||||
)
|
||||
fi
|
||||
|
||||
log_note "Sequential cached reads with settings: $(print_perf_settings)"
|
||||
do_fio_run sequential_reads.fio false false $logtype
|
||||
done
|
||||
log_pass "Measure IO stats during sequential cached read load"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2015, 2021 by Delphix. All rights reserved.
|
||||
# Copyright (c) 2015, 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
|
@ -41,78 +41,79 @@ function cleanup
|
|||
# kill fio and iostat
|
||||
pkill fio
|
||||
pkill iostat
|
||||
recreate_perf_pool
|
||||
}
|
||||
|
||||
trap "log_fail \"Measure IO stats during random read load\"" SIGTERM
|
||||
log_onexit cleanup
|
||||
|
||||
recreate_perf_pool
|
||||
populate_perf_filesystems
|
||||
for logtype in $PERF_LOG_TYPES; do
|
||||
recreate_perf_pool $logtype
|
||||
populate_perf_filesystems
|
||||
|
||||
# Make sure the working set can be cached in the arc. Aim for 1/2 of arc.
|
||||
export TOTAL_SIZE=$(($(get_max_arc_size) / 2))
|
||||
# Make sure the working set can be cached in the arc. Aim for 1/2 of arc.
|
||||
export TOTAL_SIZE=$(($(get_max_arc_size) / 2))
|
||||
|
||||
# Variables specific to this test for use by fio.
|
||||
export PERF_NTHREADS=${PERF_NTHREADS:-'64 128'}
|
||||
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
|
||||
export PERF_IOSIZES=${PERF_IOSIZES:-'128k'}
|
||||
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
|
||||
|
||||
# Layout the files to be used by the read tests. Create as many files as the
|
||||
# largest number of threads. An fio run with fewer threads will use a subset
|
||||
# of the available files.
|
||||
export NUMJOBS=$(get_max $PERF_NTHREADS)
|
||||
export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
|
||||
export DIRECTORY=$(get_directory)
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
|
||||
#
|
||||
# Only a single filesystem is used by this test. To be defensive, we
|
||||
# double check that TESTFS only contains a single filesystem. We
|
||||
# wouldn't want to assume this was the case, and have it actually
|
||||
# contain multiple filesystem (causing cascading failures later).
|
||||
#
|
||||
log_must test $(get_nfilesystems) -eq 1
|
||||
|
||||
log_note "Creating snapshot, $TESTSNAP, of $TESTFS"
|
||||
create_snapshot $TESTFS $TESTSNAP
|
||||
log_note "Creating clone, $PERFPOOL/$TESTCLONE, from $TESTFS@$TESTSNAP"
|
||||
create_clone $TESTFS@$TESTSNAP $PERFPOOL/$TESTCLONE
|
||||
|
||||
#
|
||||
# We want to run FIO against the clone we created above, and not the
|
||||
# clone's originating filesystem. Thus, we override the default behavior
|
||||
# and explicitly set TESTFS to the clone.
|
||||
#
|
||||
export TESTFS=$PERFPOOL/$TESTCLONE
|
||||
|
||||
# Set up the scripts and output files that will log performance data.
|
||||
lun_list=$(pool_to_lun_list $PERFPOOL)
|
||||
log_note "Collecting backend IO stats with lun list $lun_list"
|
||||
if is_linux; then
|
||||
typeset perf_record_cmd="perf record -F 99 -a -g -q \
|
||||
-o /dev/stdout -- sleep ${PERF_RUNTIME}"
|
||||
|
||||
# Variables specific to this test for use by fio.
|
||||
export PERF_NTHREADS=${PERF_NTHREADS:-'64 128'}
|
||||
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
|
||||
export PERF_IOSIZES=${PERF_IOSIZES:-'128k'}
|
||||
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
|
||||
|
||||
# Layout the files to be used by the read tests. Create as many files as the
|
||||
# largest number of threads. An fio run with fewer threads will use a subset
|
||||
# of the available files.
|
||||
export NUMJOBS=$(get_max $PERF_NTHREADS)
|
||||
export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
|
||||
export DIRECTORY=$(get_directory)
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
|
||||
#
|
||||
# Only a single filesystem is used by this test. To be defensive, we
|
||||
# double check that TESTFS only contains a single filesystem. We
|
||||
# wouldn't want to assume this was the case, and have it actually
|
||||
# contain multiple filesystem (causing cascading failures later).
|
||||
#
|
||||
log_must test $(get_nfilesystems) -eq 1
|
||||
|
||||
log_note "Creating snapshot, $TESTSNAP, of $TESTFS"
|
||||
create_snapshot $TESTFS $TESTSNAP
|
||||
log_note "Creating clone, $PERFPOOL/$TESTCLONE, from $TESTFS@$TESTSNAP"
|
||||
create_clone $TESTFS@$TESTSNAP $PERFPOOL/$TESTCLONE
|
||||
|
||||
#
|
||||
# We want to run FIO against the clone we created above, and not the
|
||||
# clone's originating filesystem. Thus, we override the default behavior
|
||||
# and explicitly set TESTFS to the clone.
|
||||
#
|
||||
export TESTFS=$PERFPOOL/$TESTCLONE
|
||||
|
||||
# Set up the scripts and output files that will log performance data.
|
||||
lun_list=$(pool_to_lun_list $PERFPOOL)
|
||||
log_note "Collecting backend IO stats with lun list $lun_list"
|
||||
if is_linux; then
|
||||
typeset perf_record_cmd="perf record -F 99 -a -g -q \
|
||||
-o /dev/stdout -- sleep ${PERF_RUNTIME}"
|
||||
|
||||
export collect_scripts=(
|
||||
"zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
|
||||
"$PERF_SCRIPTS/prefetch_io.sh $PERFPOOL 1" "prefetch"
|
||||
"vmstat -t 1" "vmstat"
|
||||
"mpstat -P ALL 1" "mpstat"
|
||||
"iostat -tdxyz 1" "iostat"
|
||||
"$perf_record_cmd" "perf"
|
||||
)
|
||||
else
|
||||
export collect_scripts=(
|
||||
"$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
|
||||
"$PERF_SCRIPTS/prefetch_io.d $PERFPOOL 1" "prefetch"
|
||||
"vmstat -T d 1" "vmstat"
|
||||
"mpstat -T d 1" "mpstat"
|
||||
"iostat -T d -xcnz 1" "iostat"
|
||||
)
|
||||
fi
|
||||
|
||||
log_note "Sequential cached reads from $DIRECTORY with " \
|
||||
"ettings: $(print_perf_settings)"
|
||||
do_fio_run sequential_reads.fio false false
|
||||
export collect_scripts=(
|
||||
"zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
|
||||
"$PERF_SCRIPTS/prefetch_io.sh $PERFPOOL 1" "prefetch"
|
||||
"vmstat -t 1" "vmstat"
|
||||
"mpstat -P ALL 1" "mpstat"
|
||||
"iostat -tdxyz 1" "iostat"
|
||||
"$perf_record_cmd" "perf"
|
||||
)
|
||||
else
|
||||
export collect_scripts=(
|
||||
"$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
|
||||
"$PERF_SCRIPTS/prefetch_io.d $PERFPOOL 1" "prefetch"
|
||||
"vmstat -T d 1" "vmstat"
|
||||
"mpstat -T d 1" "mpstat"
|
||||
"iostat -T d -xcnz 1" "iostat"
|
||||
)
|
||||
fi
|
||||
|
||||
log_note "Sequential cached reads from $DIRECTORY with " \
|
||||
"settings: $(print_perf_settings)"
|
||||
do_fio_run sequential_reads.fio false false $logtype
|
||||
done
|
||||
log_pass "Measure IO stats during sequential cached read load"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2016, 2021 by Delphix. All rights reserved.
|
||||
# Copyright (c) 2016, 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
|
@ -39,59 +39,60 @@ function cleanup
|
|||
# kill fio and iostat
|
||||
pkill fio
|
||||
pkill iostat
|
||||
recreate_perf_pool
|
||||
}
|
||||
|
||||
trap "log_fail \"Measure IO stats during sequential read load\"" SIGTERM
|
||||
log_onexit cleanup
|
||||
|
||||
recreate_perf_pool
|
||||
populate_perf_filesystems
|
||||
for logtype in $PERF_LOG_TYPES; do
|
||||
recreate_perf_pool $logtype
|
||||
populate_perf_filesystems
|
||||
|
||||
# Ensure the working set can be cached in the dbuf cache.
|
||||
export TOTAL_SIZE=$(($(get_dbuf_cache_size) * 3 / 4))
|
||||
|
||||
# Variables specific to this test for use by fio.
|
||||
export PERF_NTHREADS=${PERF_NTHREADS:-'64'}
|
||||
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
|
||||
export PERF_IOSIZES=${PERF_IOSIZES:-'64k'}
|
||||
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
|
||||
|
||||
# Layout the files to be used by the read tests. Create as many files as the
|
||||
# largest number of threads. An fio run with fewer threads will use a subset
|
||||
# of the available files.
|
||||
export NUMJOBS=$(get_max $PERF_NTHREADS)
|
||||
export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
|
||||
export DIRECTORY=$(get_directory)
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
|
||||
# Set up the scripts and output files that will log performance data.
|
||||
lun_list=$(pool_to_lun_list $PERFPOOL)
|
||||
log_note "Collecting backend IO stats with lun list $lun_list"
|
||||
if is_linux; then
|
||||
typeset perf_record_cmd="perf record -F 99 -a -g -q \
|
||||
-o /dev/stdout -- sleep ${PERF_RUNTIME}"
|
||||
|
||||
# Ensure the working set can be cached in the dbuf cache.
|
||||
export TOTAL_SIZE=$(($(get_dbuf_cache_size) * 3 / 4))
|
||||
|
||||
# Variables specific to this test for use by fio.
|
||||
export PERF_NTHREADS=${PERF_NTHREADS:-'64'}
|
||||
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
|
||||
export PERF_IOSIZES=${PERF_IOSIZES:-'64k'}
|
||||
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
|
||||
|
||||
# Layout the files to be used by the read tests. Create as many files as the
|
||||
# largest number of threads. An fio run with fewer threads will use a subset
|
||||
# of the available files.
|
||||
export NUMJOBS=$(get_max $PERF_NTHREADS)
|
||||
export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
|
||||
export DIRECTORY=$(get_directory)
|
||||
log_must fio $FIO_SCRIPTS/mkfiles.fio
|
||||
|
||||
# Set up the scripts and output files that will log performance data.
|
||||
lun_list=$(pool_to_lun_list $PERFPOOL)
|
||||
log_note "Collecting backend IO stats with lun list $lun_list"
|
||||
if is_linux; then
|
||||
typeset perf_record_cmd="perf record -F 99 -a -g -q \
|
||||
-o /dev/stdout -- sleep ${PERF_RUNTIME}"
|
||||
|
||||
export collect_scripts=(
|
||||
"zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
|
||||
"$PERF_SCRIPTS/prefetch_io.sh $PERFPOOL 1" "prefetch"
|
||||
"vmstat -t 1" "vmstat"
|
||||
"mpstat -P ALL 1" "mpstat"
|
||||
"iostat -tdxyz 1" "iostat"
|
||||
"$perf_record_cmd" "perf"
|
||||
)
|
||||
else
|
||||
export collect_scripts=(
|
||||
"kstat zfs:0 1" "kstat"
|
||||
"vmstat -T d 1" "vmstat"
|
||||
"mpstat -T d 1" "mpstat"
|
||||
"iostat -T d -xcnz 1" "iostat"
|
||||
"dtrace -Cs $PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
|
||||
"dtrace -Cs $PERF_SCRIPTS/prefetch_io.d $PERFPOOL 1" "prefetch"
|
||||
"dtrace -s $PERF_SCRIPTS/profile.d" "profile"
|
||||
)
|
||||
fi
|
||||
|
||||
log_note "Sequential cached reads with settings: $(print_perf_settings)"
|
||||
do_fio_run sequential_reads.fio false false
|
||||
export collect_scripts=(
|
||||
"zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
|
||||
"$PERF_SCRIPTS/prefetch_io.sh $PERFPOOL 1" "prefetch"
|
||||
"vmstat -t 1" "vmstat"
|
||||
"mpstat -P ALL 1" "mpstat"
|
||||
"iostat -tdxyz 1" "iostat"
|
||||
"$perf_record_cmd" "perf"
|
||||
)
|
||||
else
|
||||
export collect_scripts=(
|
||||
"kstat zfs:0 1" "kstat"
|
||||
"vmstat -T d 1" "vmstat"
|
||||
"mpstat -T d 1" "mpstat"
|
||||
"iostat -T d -xcnz 1" "iostat"
|
||||
"dtrace -Cs $PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
|
||||
"dtrace -Cs $PERF_SCRIPTS/prefetch_io.d $PERFPOOL 1" "prefetch"
|
||||
"dtrace -s $PERF_SCRIPTS/profile.d" "profile"
|
||||
)
|
||||
fi
|
||||
|
||||
log_note "Sequential cached reads with settings: $(print_perf_settings)"
|
||||
do_fio_run sequential_reads.fio false false $logtype
|
||||
done
|
||||
log_pass "Measure IO stats during sequential cached read load"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#
|
||||
|
||||
#
|
||||
# Copyright (c) 2015, 2021 by Delphix. All rights reserved.
|
||||
# Copyright (c) 2015, 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
#
|
||||
|
@ -44,47 +44,48 @@ function cleanup
|
|||
# kill fio and iostat
|
||||
pkill fio
|
||||
pkill iostat
|
||||
recreate_perf_pool
|
||||
}
|
||||
|
||||
trap "log_fail \"Measure IO stats during random read load\"" SIGTERM
|
||||
log_onexit cleanup
|
||||
|
||||
recreate_perf_pool
|
||||
populate_perf_filesystems
|
||||
for logtype in $PERF_LOG_TYPES; do
|
||||
recreate_perf_pool $logtype
|
||||
populate_perf_filesystems
|
||||
|
||||
# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
|
||||
export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
|
||||
# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
|
||||
export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
|
||||
|
||||
# Variables specific to this test for use by fio.
|
||||
export PERF_NTHREADS=${PERF_NTHREADS:-'16 32'}
|
||||
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
|
||||
export PERF_IOSIZES=${PERF_IOSIZES:-'8k 1m'}
|
||||
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'0 1'}
|
||||
|
||||
# Set up the scripts and output files that will log performance data.
|
||||
lun_list=$(pool_to_lun_list $PERFPOOL)
|
||||
log_note "Collecting backend IO stats with lun list $lun_list"
|
||||
if is_linux; then
|
||||
typeset perf_record_cmd="perf record -F 99 -a -g -q \
|
||||
-o /dev/stdout -- sleep ${PERF_RUNTIME}"
|
||||
|
||||
export collect_scripts=(
|
||||
"zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
|
||||
"vmstat -t 1" "vmstat"
|
||||
"mpstat -P ALL 1" "mpstat"
|
||||
"iostat -tdxyz 1" "iostat"
|
||||
"$perf_record_cmd" "perf"
|
||||
)
|
||||
else
|
||||
export collect_scripts=(
|
||||
"$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
|
||||
"vmstat -T d 1" "vmstat"
|
||||
"mpstat -T d 1" "mpstat"
|
||||
"iostat -T d -xcnz 1" "iostat"
|
||||
)
|
||||
fi
|
||||
|
||||
# Variables specific to this test for use by fio.
|
||||
export PERF_NTHREADS=${PERF_NTHREADS:-'16 32'}
|
||||
export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
|
||||
export PERF_IOSIZES=${PERF_IOSIZES:-'8k 1m'}
|
||||
export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'0 1'}
|
||||
|
||||
# Set up the scripts and output files that will log performance data.
|
||||
lun_list=$(pool_to_lun_list $PERFPOOL)
|
||||
log_note "Collecting backend IO stats with lun list $lun_list"
|
||||
if is_linux; then
|
||||
typeset perf_record_cmd="perf record -F 99 -a -g -q \
|
||||
-o /dev/stdout -- sleep ${PERF_RUNTIME}"
|
||||
|
||||
export collect_scripts=(
|
||||
"zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
|
||||
"vmstat -t 1" "vmstat"
|
||||
"mpstat -P ALL 1" "mpstat"
|
||||
"iostat -tdxyz 1" "iostat"
|
||||
"$perf_record_cmd" "perf"
|
||||
)
|
||||
else
|
||||
export collect_scripts=(
|
||||
"$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
|
||||
"vmstat -T d 1" "vmstat"
|
||||
"mpstat -T d 1" "mpstat"
|
||||
"iostat -T d -xcnz 1" "iostat"
|
||||
)
|
||||
fi
|
||||
|
||||
log_note "Sequential writes with settings: $(print_perf_settings)"
|
||||
do_fio_run sequential_writes.fio true false
|
||||
log_note "Sequential writes with settings: $(print_perf_settings)"
|
||||
do_fio_run sequential_writes.fio true false $logtype
|
||||
done
|
||||
log_pass "Measure IO stats during sequential write load"
|
||||
|
|
Loading…
Reference in New Issue