parent
f00af48295
commit
7f85a9adfc
|
@ -5811,7 +5811,7 @@ zdb_count_block(zdb_cb_t *zcb, zilog_t *zilog, const blkptr_t *bp,
|
|||
/*
|
||||
* 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. The ZIL currently doesn't have
|
||||
* 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.
|
||||
*/
|
||||
|
@ -6849,7 +6849,8 @@ chain_map_count_blocks(spa_t *spa, zdb_cb_t *zbc)
|
|||
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);
|
||||
chain_map_count_blk_cb, chain_map_count_lr_cb,
|
||||
zbc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8210,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)
|
||||
{
|
||||
|
@ -8291,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");
|
||||
}
|
||||
|
|
|
@ -391,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 -L pool] "
|
||||
"[-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"
|
||||
|
@ -1181,8 +1182,7 @@ zpool_do_add(int argc, char **argv)
|
|||
|
||||
/* pass off to make_root_vdev for processing */
|
||||
nvroot = make_root_vdev(zhp, props, !check_inuse,
|
||||
check_replication, B_FALSE, dryrun, has_shared_log, argc,
|
||||
argv);
|
||||
check_replication, B_FALSE, dryrun, has_shared_log, argc, argv);
|
||||
if (nvroot == NULL) {
|
||||
zpool_close(zhp);
|
||||
return (1);
|
||||
|
@ -3667,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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3679,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++;
|
||||
|
@ -6814,8 +6832,8 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
|
|||
|
||||
if (!printed) {
|
||||
/* LINTED E_SEC_PRINTF_VAR_FMT */
|
||||
(void) printf(dashes, depth + 2, "", 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],
|
||||
|
@ -6829,7 +6847,8 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
|
|||
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");
|
||||
(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);
|
||||
|
@ -8082,31 +8101,36 @@ struct recycle_data {
|
|||
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), rd->dryrun, &nvl);
|
||||
int err = lzc_recycle(zpool_get_name(zhp), NULL, rd->dryrun, &nvl);
|
||||
if (err)
|
||||
return (err);
|
||||
if (rd->verbose) {
|
||||
printf("Cleaned up%s: [", rd->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");
|
||||
}
|
||||
if (rd->verbose)
|
||||
print_recycle_info(nvl, rd->dryrun);
|
||||
nvlist_free(nvl);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* zpool recycle <pool> ...
|
||||
* zpool recycle [-a] [-n] [-v] <pool> [pool]...
|
||||
*
|
||||
* Cleans up chain maps for non-attached client pools
|
||||
*/
|
||||
|
@ -8115,9 +8139,10 @@ 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, "nv")) != -1) {
|
||||
while ((c = getopt(argc, argv, "nva")) != -1) {
|
||||
switch (c) {
|
||||
case 'n':
|
||||
rd.dryrun = B_TRUE;
|
||||
|
@ -8125,6 +8150,9 @@ zpool_do_recycle(int argc, char **argv)
|
|||
case 'v':
|
||||
rd.verbose = B_TRUE;
|
||||
break;
|
||||
case 'a':
|
||||
doall = B_TRUE;
|
||||
break;
|
||||
case '?':
|
||||
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
|
||||
optopt);
|
||||
|
@ -8138,10 +8166,44 @@ zpool_do_recycle(int argc, char **argv)
|
|||
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);
|
||||
}
|
||||
|
||||
return (for_each_pool(argc, argv, B_TRUE, NULL, ZFS_TYPE_POOL,
|
||||
B_FALSE, recycle_callback, &rd));
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
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;
|
||||
|
|
|
@ -346,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
|
||||
|
|
|
@ -156,13 +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 *, boolean_t, 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
|
||||
|
|
|
@ -1522,6 +1522,8 @@ typedef enum zfs_ioc {
|
|||
ZFS_IOC_POOL_SCRUB, /* 0x5a57 */
|
||||
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.
|
||||
|
@ -1752,9 +1754,21 @@ typedef enum {
|
|||
#define ZPOOL_PREFETCH_TYPE "prefetch_type"
|
||||
|
||||
/*
|
||||
* The following name is used when invoking ZFS_IOC_POOL_RECYCLE.
|
||||
* 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
|
||||
|
|
|
@ -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);
|
||||
|
@ -1233,7 +1233,9 @@ 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(spa_t *spa, boolean_t dryrun, nvlist_t *outnvl);
|
||||
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);
|
||||
|
|
|
@ -228,6 +228,8 @@ typedef struct spa_zil_update_head {
|
|||
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 {
|
||||
|
@ -235,6 +237,11 @@ typedef struct spa_zil_update {
|
|||
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;
|
||||
|
@ -244,6 +251,7 @@ typedef struct spa_chain_map_os {
|
|||
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;
|
||||
|
||||
|
@ -256,7 +264,7 @@ struct spa {
|
|||
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 */
|
||||
avl_node_t spa_client_avl;
|
||||
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 */
|
||||
|
@ -279,6 +287,11 @@ struct spa {
|
|||
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 */
|
||||
|
@ -338,7 +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 */
|
||||
boolean_t spa_pool_type; /* normal or object-based */
|
||||
spa_pool_type_t spa_pool_type;
|
||||
|
||||
/* in-flight verification bytes */
|
||||
uint64_t spa_load_verify_bytes;
|
||||
|
@ -517,7 +530,7 @@ struct spa {
|
|||
/* Only used if type is shared log */
|
||||
kmutex_t spa_chain_map_lock;
|
||||
avl_tree_t spa_chain_map;
|
||||
avl_tree_t spa_registered_clients;
|
||||
list_t spa_registered_clients;
|
||||
|
||||
/* Only used during syncing context if using shared log */
|
||||
kmutex_t spa_zil_map_lock;
|
||||
|
|
|
@ -599,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,
|
||||
|
|
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
|
@ -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
|
@ -1929,11 +1929,37 @@ lzc_get_bootenv(const char *pool, nvlist_t **outnvl)
|
|||
}
|
||||
|
||||
int
|
||||
lzc_recycle(const char *pool, boolean_t dryrun, nvlist_t **outnvl)
|
||||
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'/>
|
||||
|
|
|
@ -180,8 +180,8 @@ For more information, see the
|
|||
section.
|
||||
.It Sy shared log
|
||||
A separate ZFS storage pool used as a shared intent log device.
|
||||
Only one shared log can specified at pool creation or import, and a normal log
|
||||
device cannot also be specified.
|
||||
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.
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
@ -559,7 +562,8 @@ dsl_pool_create(spa_t *spa, nvlist_t *zplprops __attribute__((unused)),
|
|||
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, 0, 0,
|
||||
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,
|
||||
|
|
355
module/zfs/spa.c
355
module/zfs/spa.c
|
@ -1725,6 +1725,19 @@ get_shared_log_pool(nvlist_t *config, spa_t **out)
|
|||
mutex_enter(&result->spa_chain_map_lock);
|
||||
mutex_exit(&spa_shared_log_lock);
|
||||
*out = result;
|
||||
|
||||
avl_tree_t *t = &result->spa_chain_map;
|
||||
spa_chain_map_pool_t *search_scmp = kmem_zalloc(sizeof (*search_scmp),
|
||||
KM_SLEEP);
|
||||
if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid))
|
||||
return (0);
|
||||
|
||||
search_scmp->scmp_guid = guid;
|
||||
spa_chain_map_pool_t *result_scmp = avl_find(t, search_scmp, NULL);
|
||||
kmem_free(search_scmp, sizeof (*search_scmp));
|
||||
if (!result_scmp) {
|
||||
return (ESRCH);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -1734,22 +1747,29 @@ extern metaslab_ops_t *metaslab_allocator(spa_t *shared_log);
|
|||
* Activate an uninitialized pool.
|
||||
*/
|
||||
static int
|
||||
spa_activate(spa_t *spa, nvlist_t *config, spa_mode_t mode)
|
||||
spa_activate(spa_t *spa, nvlist_t *config, spa_mode_t mode, boolean_t creating)
|
||||
{
|
||||
metaslab_ops_t *msp = metaslab_allocator(spa);
|
||||
ASSERT(spa->spa_state == POOL_STATE_UNINITIALIZED);
|
||||
boolean_t missing_logs = spa->spa_import_flags & ZFS_IMPORT_MISSING_LOG;
|
||||
|
||||
int error = 0;
|
||||
spa_t *shared_log = NULL;
|
||||
if (strcmp(spa->spa_name, TRYIMPORT_NAME) != 0 &&
|
||||
(error = get_shared_log_pool(config, &shared_log)) != 0) {
|
||||
// We handle this case in spa_check_for_missing_logs
|
||||
if (error == ENOENT &&
|
||||
(spa->spa_import_flags & ZFS_IMPORT_MISSING_LOG)) {
|
||||
// We handle the ENOENT case in spa_check_for_missing_logs
|
||||
if (missing_logs && (error == ENOENT || error == ESRCH)) {
|
||||
spa->spa_discarding_shared_log = B_TRUE;
|
||||
error = 0;
|
||||
} else {
|
||||
return (error);
|
||||
}
|
||||
if (error == ESRCH) {
|
||||
if (creating)
|
||||
error = 0;
|
||||
else
|
||||
mutex_exit(&shared_log->spa_chain_map_lock);
|
||||
}
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
|
||||
spa->spa_state = POOL_STATE_ACTIVE;
|
||||
|
@ -1758,7 +1778,7 @@ spa_activate(spa_t *spa, nvlist_t *config, spa_mode_t mode)
|
|||
|
||||
spa->spa_normal_class = metaslab_class_create(spa, msp);
|
||||
if (shared_log != NULL) {
|
||||
avl_add(&shared_log->spa_registered_clients, spa);
|
||||
list_insert_tail(&shared_log->spa_registered_clients, spa);
|
||||
mutex_exit(&shared_log->spa_chain_map_lock);
|
||||
|
||||
spa->spa_log_class = metaslab_class_create(spa,
|
||||
|
@ -1840,6 +1860,12 @@ spa_activate(spa_t *spa, nvlist_t *config, spa_mode_t mode)
|
|||
avl_create(&spa->spa_zil_map,
|
||||
spa_zil_update_head_compare, sizeof (spa_zil_update_head_t),
|
||||
offsetof(spa_zil_update_head_t, szuh_avl));
|
||||
if (spa->spa_uses_shared_log) {
|
||||
spa_zil_update_head_t *entry = kmem_zalloc(sizeof (*entry),
|
||||
KM_SLEEP);
|
||||
entry->szuh_force = B_TRUE;
|
||||
avl_add(&spa->spa_zil_map, entry);
|
||||
}
|
||||
|
||||
spa_activate_os(spa);
|
||||
|
||||
|
@ -1960,7 +1986,7 @@ spa_deactivate(spa_t *spa)
|
|||
spa_t *shared_log;
|
||||
if ((shared_log = spa_get_shared_log_pool(spa)) != NULL) {
|
||||
mutex_enter(&shared_log->spa_chain_map_lock);
|
||||
avl_remove(&shared_log->spa_registered_clients, spa);
|
||||
list_remove(&shared_log->spa_registered_clients, spa);
|
||||
mutex_exit(&shared_log->spa_chain_map_lock);
|
||||
}
|
||||
metaslab_class_destroy(spa->spa_log_class);
|
||||
|
@ -2655,7 +2681,6 @@ static int
|
|||
spa_check_for_missing_logs(spa_t *spa)
|
||||
{
|
||||
vdev_t *rvd = spa->spa_root_vdev;
|
||||
uint64_t guid;
|
||||
|
||||
/*
|
||||
* If we're doing a normal import, then build up any additional
|
||||
|
@ -2702,10 +2727,7 @@ spa_check_for_missing_logs(spa_t *spa)
|
|||
vdev_dbgmsg_print_tree(rvd, 2);
|
||||
return (SET_ERROR(ENXIO));
|
||||
}
|
||||
} else if (nvlist_lookup_uint64(spa->spa_config,
|
||||
ZPOOL_CONFIG_SHARED_LOG_POOL, &guid)) {
|
||||
if (spa_uses_shared_log(spa))
|
||||
return (0);
|
||||
} else if (spa->spa_discarding_shared_log) {
|
||||
spa_set_log_state(spa, SPA_LOG_CLEAR);
|
||||
spa_load_note(spa, "shared log pool is "
|
||||
"missing, ZIL is dropped.");
|
||||
|
@ -4106,6 +4128,7 @@ spa_ld_parse_config(spa_t *spa, spa_import_type_t type)
|
|||
parse = (type == SPA_IMPORT_EXISTING ?
|
||||
VDEV_ALLOC_LOAD : VDEV_ALLOC_SPLIT);
|
||||
error = spa_config_parse(spa, &rvd, nvtree, NULL, 0, parse);
|
||||
spa_set_pool_type(spa);
|
||||
spa_config_exit(spa, SCL_ALL, FTAG);
|
||||
|
||||
if (error != 0) {
|
||||
|
@ -4484,6 +4507,7 @@ spa_ld_trusted_config(spa_t *spa, spa_import_type_t type,
|
|||
error);
|
||||
return (spa_vdev_err(rvd, VDEV_AUX_CORRUPT_DATA, error));
|
||||
}
|
||||
spa_set_pool_type(spa);
|
||||
|
||||
/*
|
||||
* Vdev paths in the MOS may be obsolete. If the untrusted config was
|
||||
|
@ -4776,7 +4800,7 @@ spa_ld_check_features(spa_t *spa, boolean_t *missing_feat_writep)
|
|||
struct load_chain_map_arg {
|
||||
blkptr_t *bp;
|
||||
spa_t *spa;
|
||||
int *error;
|
||||
uint64_t *error;
|
||||
};
|
||||
|
||||
static int
|
||||
|
@ -4818,11 +4842,11 @@ load_chain_map_cb(void *arg)
|
|||
kmem_free(lcmca, sizeof (*lcmca));
|
||||
}
|
||||
|
||||
static int
|
||||
noinline static int
|
||||
spa_load_chain_map(spa_t *spa)
|
||||
{
|
||||
int error = 0;
|
||||
int dispatch_error = 0;
|
||||
uint64_t dispatch_error = 0;
|
||||
uint64_t chain_map_zap = spa->spa_dsl_pool->dp_chain_map_obj;
|
||||
if (!spa_is_shared_log(spa))
|
||||
return (error);
|
||||
|
@ -4831,34 +4855,49 @@ spa_load_chain_map(spa_t *spa)
|
|||
zap_cursor_t zc;
|
||||
zap_attribute_t attr;
|
||||
objset_t *os = spa->spa_dsl_pool->dp_meta_objset;
|
||||
spa_zil_chain_map_value_t *szcmv = kmem_alloc(sizeof (*szcmv),
|
||||
KM_SLEEP);
|
||||
for (zap_cursor_init(&zc, os, chain_map_zap);
|
||||
zap_cursor_retrieve(&zc, &attr) == 0; zap_cursor_advance(&zc)) {
|
||||
uint64_t pool_guid = ((uint64_t *)attr.za_name)[0];
|
||||
uint64_t os_guid = ((uint64_t *)attr.za_name)[1];
|
||||
error = zap_lookup_uint64(os, chain_map_zap,
|
||||
(uint64_t *)attr.za_name, 2, sizeof (uint64_t),
|
||||
sizeof (*szcmv) / sizeof (uint64_t),
|
||||
szcmv);
|
||||
if (error != 0) {
|
||||
break;
|
||||
}
|
||||
avl_index_t where;
|
||||
spa_chain_map_pool_t search;
|
||||
search.scmp_guid = pool_guid;
|
||||
spa_chain_map_pool_t *pool_entry = avl_find(&spa->spa_chain_map,
|
||||
&search, &where);
|
||||
spa_chain_map_pool_t *pool_entry =
|
||||
avl_find(&spa->spa_chain_map, &search, &where);
|
||||
if (pool_entry == NULL) {
|
||||
pool_entry = kmem_alloc(sizeof (*pool_entry), KM_SLEEP);
|
||||
pool_entry = kmem_alloc(sizeof (*pool_entry),
|
||||
KM_SLEEP);
|
||||
pool_entry->scmp_guid = pool_guid;
|
||||
avl_create(&pool_entry->scmp_os_tree,
|
||||
spa_chain_map_os_compare,
|
||||
sizeof (spa_chain_map_os_t),
|
||||
offsetof(spa_chain_map_os_t, scmo_avl));
|
||||
strlcpy(pool_entry->scmp_name,
|
||||
szcmv->szcmv_pool_name, ZFS_MAX_DATASET_NAME_LEN);
|
||||
avl_insert(&spa->spa_chain_map, pool_entry, where);
|
||||
}
|
||||
|
||||
if (os_guid == 0) {
|
||||
/*
|
||||
* This is the dummy marker to make sure we know about
|
||||
* the pool; no need to add an os-specific entry
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
spa_chain_map_os_t *os_entry = kmem_alloc(sizeof (*os_entry),
|
||||
KM_SLEEP);
|
||||
os_entry->scmo_id = os_guid;
|
||||
error = zap_lookup_uint64(os, chain_map_zap,
|
||||
(uint64_t *)attr.za_name, 2, sizeof (uint64_t),
|
||||
sizeof (blkptr_t) / sizeof (uint64_t),
|
||||
&os_entry->scmo_chain_head);
|
||||
if (error != 0) {
|
||||
break;
|
||||
}
|
||||
os_entry->scmo_chain_head = szcmv->szcmv_bp;
|
||||
avl_add(&pool_entry->scmp_os_tree, os_entry);
|
||||
struct load_chain_map_arg *arg = kmem_alloc(sizeof (*arg),
|
||||
KM_SLEEP);
|
||||
|
@ -4868,6 +4907,7 @@ spa_load_chain_map(spa_t *spa)
|
|||
(void) taskq_dispatch(spa->spa_chain_map_taskq,
|
||||
load_chain_map_cb, arg, TQ_SLEEP);
|
||||
}
|
||||
kmem_free(szcmv, sizeof (*szcmv));
|
||||
|
||||
if (error != 0) {
|
||||
void *cookie = NULL;
|
||||
|
@ -5299,6 +5339,13 @@ spa_ld_claim_log_blocks(spa_t *spa)
|
|||
(void) dmu_objset_find_dp(dp, dp->dp_root_dir_obj,
|
||||
zil_claim, tx, DS_FIND_CHILDREN);
|
||||
dmu_tx_commit(tx);
|
||||
} else if (spa_get_log_state(spa) == SPA_LOG_CLEAR) {
|
||||
ASSERT(spa->spa_discarding_shared_log);
|
||||
tx = dmu_tx_create_assigned(dp, spa_first_txg(spa));
|
||||
(void) dmu_objset_find_dp(dp, dp->dp_root_dir_obj,
|
||||
zil_clear, tx, DS_FIND_CHILDREN);
|
||||
dmu_tx_commit(tx);
|
||||
spa->spa_discarding_shared_log = B_FALSE;
|
||||
}
|
||||
|
||||
spa->spa_claiming = B_FALSE;
|
||||
|
@ -5346,7 +5393,7 @@ spa_ld_prepare_for_reload(spa_t *spa)
|
|||
|
||||
spa_unload(spa);
|
||||
spa_deactivate(spa);
|
||||
VERIFY0(spa_activate(spa, spa->spa_config, mode));
|
||||
VERIFY0(spa_activate(spa, spa->spa_config, mode, B_FALSE));
|
||||
|
||||
/*
|
||||
* We save the value of spa_async_suspended as it gets reset to 0 by
|
||||
|
@ -5924,7 +5971,7 @@ spa_load_retry(spa_t *spa, spa_load_state_t state)
|
|||
|
||||
spa->spa_load_max_txg = spa->spa_uberblock.ub_txg - 1;
|
||||
|
||||
VERIFY0(spa_activate(spa, spa->spa_config, mode));
|
||||
VERIFY0(spa_activate(spa, spa->spa_config, mode, B_FALSE));
|
||||
spa_async_suspend(spa);
|
||||
|
||||
spa_load_note(spa, "spa_load_retry: rewind, max txg: %llu",
|
||||
|
@ -6091,7 +6138,8 @@ spa_open_common(const char *pool, spa_t **spapp, const void *tag,
|
|||
if (policy.zlp_rewind & ZPOOL_DO_REWIND)
|
||||
state = SPA_LOAD_RECOVER;
|
||||
|
||||
error = spa_activate(spa, spa->spa_config, spa_mode_global);
|
||||
error = spa_activate(spa, spa->spa_config, spa_mode_global,
|
||||
B_FALSE);
|
||||
if (error != 0) {
|
||||
spa_remove(spa);
|
||||
if (locked)
|
||||
|
@ -6701,7 +6749,7 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
|
|||
zpool_prop_to_name(ZPOOL_PROP_ALTROOT), &altroot);
|
||||
spa = spa_add(poolname, nvl, altroot);
|
||||
fnvlist_free(nvl);
|
||||
error = spa_activate(spa, nvroot, spa_mode_global);
|
||||
error = spa_activate(spa, nvroot, spa_mode_global, B_TRUE);
|
||||
if (error != 0) {
|
||||
spa_remove(spa);
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
|
@ -6743,15 +6791,8 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
|
|||
}
|
||||
}
|
||||
|
||||
if (!has_shared_log && spa_uses_shared_log(spa)) {
|
||||
spa_deactivate(spa);
|
||||
spa_remove(spa);
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
return (SET_ERROR(ENOTSUP));
|
||||
}
|
||||
|
||||
if (!has_shared_log && fnvlist_lookup_boolean(nvroot,
|
||||
ZPOOL_CONFIG_IS_SHARED_LOG)) {
|
||||
if (!has_shared_log && (spa_uses_shared_log(spa) ||
|
||||
fnvlist_lookup_boolean(nvroot, ZPOOL_CONFIG_IS_SHARED_LOG))) {
|
||||
spa_deactivate(spa);
|
||||
spa_remove(spa);
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
|
@ -6808,6 +6849,8 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
|
|||
spa_config_enter(spa, SCL_ALL, FTAG, RW_WRITER);
|
||||
|
||||
error = spa_config_parse(spa, &rvd, nvroot, NULL, 0, VDEV_ALLOC_ADD);
|
||||
if (error == 0)
|
||||
spa_set_pool_type(spa);
|
||||
|
||||
ASSERT(error != 0 || rvd != NULL);
|
||||
ASSERT(error != 0 || spa->spa_root_vdev == rvd);
|
||||
|
@ -7050,7 +7093,7 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags)
|
|||
return (0);
|
||||
}
|
||||
|
||||
error = spa_activate(spa, config, mode);
|
||||
error = spa_activate(spa, config, mode, B_FALSE);
|
||||
if (error != 0) {
|
||||
spa_remove(spa);
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
|
@ -7211,7 +7254,17 @@ spa_tryimport(nvlist_t *tryconfig)
|
|||
mutex_enter(&spa_namespace_lock);
|
||||
spa = spa_add(name, tryconfig, NULL);
|
||||
kmem_free(name, MAXPATHLEN);
|
||||
error = spa_activate(spa, tryconfig, SPA_MODE_READ);
|
||||
|
||||
/*
|
||||
* spa_import() relies on a pool config fetched by spa_try_import()
|
||||
* for spare/cache devices. Import flags are not passed to
|
||||
* spa_tryimport(), which makes it return early due to a missing log
|
||||
* device and missing retrieving the cache device and spare eventually.
|
||||
* Passing ZFS_IMPORT_MISSING_LOG to spa_tryimport() makes it fetch
|
||||
* the correct configuration regardless of the missing log device.
|
||||
*/
|
||||
spa->spa_import_flags |= ZFS_IMPORT_MISSING_LOG;
|
||||
error = spa_activate(spa, tryconfig, SPA_MODE_READ, B_FALSE);
|
||||
if (error != 0) {
|
||||
spa_remove(spa);
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
|
@ -7239,16 +7292,6 @@ spa_tryimport(nvlist_t *tryconfig)
|
|||
spa->spa_config_source = SPA_CONFIG_SRC_SCAN;
|
||||
}
|
||||
|
||||
/*
|
||||
* spa_import() relies on a pool config fetched by spa_try_import()
|
||||
* for spare/cache devices. Import flags are not passed to
|
||||
* spa_tryimport(), which makes it return early due to a missing log
|
||||
* device and missing retrieving the cache device and spare eventually.
|
||||
* Passing ZFS_IMPORT_MISSING_LOG to spa_tryimport() makes it fetch
|
||||
* the correct configuration regardless of the missing log device.
|
||||
*/
|
||||
spa->spa_import_flags |= ZFS_IMPORT_MISSING_LOG;
|
||||
|
||||
error = spa_load(spa, SPA_LOAD_TRYIMPORT, SPA_IMPORT_EXISTING);
|
||||
|
||||
/*
|
||||
|
@ -7269,7 +7312,6 @@ spa_tryimport(nvlist_t *tryconfig)
|
|||
uint64_t shared_log_guid;
|
||||
if (nvlist_lookup_uint64(tryconfig,
|
||||
ZPOOL_CONFIG_SHARED_LOG_POOL, &shared_log_guid) == 0) {
|
||||
zfs_dbgmsg("in tryimport: got %llu", (unsigned long long) shared_log_guid);
|
||||
fnvlist_add_uint64(config, ZPOOL_CONFIG_SHARED_LOG_POOL,
|
||||
shared_log_guid);
|
||||
}
|
||||
|
@ -7335,7 +7377,7 @@ spa_tryimport(nvlist_t *tryconfig)
|
|||
*/
|
||||
static int
|
||||
spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
|
||||
boolean_t force, boolean_t hardforce)
|
||||
boolean_t force, boolean_t hardforce, nvlist_t *outnvl)
|
||||
{
|
||||
int error = 0;
|
||||
spa_t *spa;
|
||||
|
@ -7355,7 +7397,19 @@ spa_export_common(const char *pool, int new_state, nvlist_t **oldconfig,
|
|||
|
||||
if (spa_is_shared_log(spa)) {
|
||||
mutex_enter(&spa->spa_chain_map_lock);
|
||||
if (avl_numnodes(&spa->spa_registered_clients) != 0) {
|
||||
if (!list_is_empty(&spa->spa_registered_clients)) {
|
||||
if (outnvl != NULL) {
|
||||
spa_t *client;
|
||||
list_t *l = &spa->spa_registered_clients;
|
||||
nvlist_t *clients = fnvlist_alloc();
|
||||
for (client = list_head(l); client != NULL;
|
||||
client = list_next(l, client)) {
|
||||
fnvlist_add_boolean(clients,
|
||||
spa_name(client));
|
||||
}
|
||||
fnvlist_add_nvlist(outnvl,
|
||||
ZPOOL_SHARED_LOG_CLIENTS, clients);
|
||||
}
|
||||
mutex_exit(&spa->spa_chain_map_lock);
|
||||
mutex_exit(&spa_namespace_lock);
|
||||
return (SET_ERROR(EBUSY));
|
||||
|
@ -7539,10 +7593,10 @@ fail:
|
|||
* Destroy a storage pool.
|
||||
*/
|
||||
int
|
||||
spa_destroy(const char *pool)
|
||||
spa_destroy(const char *pool, nvlist_t *outnvl)
|
||||
{
|
||||
return (spa_export_common(pool, POOL_STATE_DESTROYED, NULL,
|
||||
B_FALSE, B_FALSE));
|
||||
B_FALSE, B_FALSE, outnvl));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -7550,10 +7604,10 @@ spa_destroy(const char *pool)
|
|||
*/
|
||||
int
|
||||
spa_export(const char *pool, nvlist_t **oldconfig, boolean_t force,
|
||||
boolean_t hardforce)
|
||||
boolean_t hardforce, nvlist_t *outnvl)
|
||||
{
|
||||
return (spa_export_common(pool, POOL_STATE_EXPORTED, oldconfig,
|
||||
force, hardforce));
|
||||
force, hardforce, outnvl));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -7564,7 +7618,7 @@ int
|
|||
spa_reset(const char *pool)
|
||||
{
|
||||
return (spa_export_common(pool, POOL_STATE_UNINITIALIZED, NULL,
|
||||
B_FALSE, B_FALSE));
|
||||
B_FALSE, B_FALSE, NULL));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -8840,7 +8894,7 @@ spa_vdev_split_mirror(spa_t *spa, const char *newname, nvlist_t *config,
|
|||
if (zio_injection_enabled)
|
||||
zio_handle_panic_injection(spa, FTAG, 1);
|
||||
|
||||
VERIFY0(spa_activate(newspa, config, spa_mode_global));
|
||||
VERIFY0(spa_activate(newspa, config, spa_mode_global, B_TRUE));
|
||||
spa_async_suspend(newspa);
|
||||
|
||||
/*
|
||||
|
@ -8959,7 +9013,7 @@ spa_vdev_split_mirror(spa_t *spa, const char *newname, nvlist_t *config,
|
|||
/* if we're not going to mount the filesystems in userland, export */
|
||||
if (exp)
|
||||
error = spa_export_common(newname, POOL_STATE_EXPORTED, NULL,
|
||||
B_FALSE, B_FALSE);
|
||||
B_FALSE, B_FALSE, NULL);
|
||||
|
||||
return (error);
|
||||
|
||||
|
@ -11464,6 +11518,7 @@ spa_chain_map_update(spa_t *spa)
|
|||
spa_chain_map_os_compare,
|
||||
sizeof (spa_chain_map_os_t),
|
||||
offsetof(spa_chain_map_os_t, scmo_avl));
|
||||
strcpy(pool_entry->scmp_name, spa_name(spa));
|
||||
avl_insert(&target->spa_chain_map, pool_entry, where);
|
||||
}
|
||||
avl_tree_t *target_tree = &pool_entry->scmp_os_tree;
|
||||
|
@ -11484,17 +11539,37 @@ spa_chain_map_update(spa_t *spa)
|
|||
list_create(&local_frees, sizeof (spa_zil_update_t),
|
||||
offsetof(spa_zil_update_t, szu_list));
|
||||
spa_zil_update_head_t *node;
|
||||
uint64_t buf[2];
|
||||
buf[0] = spa_guid(spa);
|
||||
for (node = avl_first(t); node; node = AVL_NEXT(t, node)) {
|
||||
uint64_t keybuf[2];
|
||||
keybuf[0] = spa_guid(spa);
|
||||
spa_zil_chain_map_value_t szcmv = {0};
|
||||
strcpy(szcmv.szcmv_pool_name, spa_name(spa));
|
||||
for (node = avl_first(t); node; ) {
|
||||
uint64_t guid = node->szuh_id;
|
||||
|
||||
if (node->szuh_force) {
|
||||
ASSERT0(node->szuh_id);
|
||||
ASSERT(BP_IS_HOLE(&node->szuh_chain_head));
|
||||
keybuf[1] = 0;
|
||||
int res = zap_add_uint64(target_mos, chain_map_zap,
|
||||
keybuf, sizeof (keybuf) / sizeof (uint64_t),
|
||||
sizeof (uint64_t), sizeof (szcmv) /
|
||||
sizeof (uint64_t), (uint64_t *)&szcmv, tx);
|
||||
IMPLY(res != 0, res == EEXIST);
|
||||
spa_zil_update_head_t *next = AVL_NEXT(t, node);
|
||||
avl_remove(t, node);
|
||||
kmem_free(node, sizeof (*node));
|
||||
node = next;
|
||||
continue;
|
||||
}
|
||||
|
||||
list_t *l = &node->szuh_list;
|
||||
spa_zil_update_t *szu = list_head(l);
|
||||
if (!node->szuh_set || szu == NULL ||
|
||||
BP_IS_HOLE(&node->szuh_chain_head)) {
|
||||
node = AVL_NEXT(t, node);
|
||||
continue;
|
||||
}
|
||||
buf[1] = guid;
|
||||
keybuf[1] = guid;
|
||||
spa_chain_map_os_t osearch;
|
||||
osearch.scmo_id = guid;
|
||||
spa_chain_map_os_t *os_entry = avl_find(target_tree,
|
||||
|
@ -11524,18 +11599,21 @@ spa_chain_map_update(spa_t *spa)
|
|||
os_entry->scmo_id = guid;
|
||||
os_entry->scmo_chain_head = node->szuh_chain_head;
|
||||
avl_insert(&pool_entry->scmp_os_tree, os_entry, where);
|
||||
blkptr_t *bp = &os_entry->scmo_chain_head;
|
||||
szcmv.szcmv_bp = os_entry->scmo_chain_head;
|
||||
|
||||
zap_add_uint64(target_mos, chain_map_zap, buf, 2,
|
||||
sizeof (uint64_t), sizeof (*bp) / sizeof (uint64_t),
|
||||
bp, tx);
|
||||
VERIFY0(zap_add_uint64(target_mos, chain_map_zap,
|
||||
keybuf, sizeof (keybuf) / sizeof (uint64_t),
|
||||
sizeof (uint64_t), sizeof (szcmv) /
|
||||
sizeof (uint64_t), (uint64_t *)&szcmv, tx));
|
||||
} else {
|
||||
os_entry->scmo_chain_head = node->szuh_chain_head;
|
||||
blkptr_t *bp = &os_entry->scmo_chain_head;
|
||||
zap_update_uint64(target_mos, chain_map_zap, buf, 2,
|
||||
sizeof (uint64_t), sizeof (*bp) / sizeof (uint64_t),
|
||||
bp, tx);
|
||||
szcmv.szcmv_bp = os_entry->scmo_chain_head;
|
||||
VERIFY0(zap_update_uint64(target_mos, chain_map_zap,
|
||||
keybuf, sizeof (keybuf) / sizeof (uint64_t),
|
||||
sizeof (uint64_t), sizeof (szcmv) /
|
||||
sizeof (uint64_t), (uint64_t *)&szcmv, tx));
|
||||
}
|
||||
node = AVL_NEXT(t, node);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -11561,9 +11639,10 @@ spa_chain_map_update(spa_t *spa)
|
|||
avl_remove(target_tree, tree_entry);
|
||||
kmem_free(tree_entry, sizeof (*tree_entry));
|
||||
|
||||
buf[1] = entry->zde_guid;
|
||||
keybuf[1] = entry->zde_guid;
|
||||
kmem_free(entry, sizeof (*entry));
|
||||
zap_remove_uint64(target_mos, chain_map_zap, buf, 2, tx);
|
||||
VERIFY0(zap_remove_uint64(target_mos, chain_map_zap, keybuf, 2,
|
||||
tx));
|
||||
}
|
||||
|
||||
mutex_exit(&target->spa_chain_map_lock);
|
||||
|
@ -11653,55 +11732,111 @@ spa_zil_header_mask(spa_t *spa, blkptr_t *bp)
|
|||
*bp = masked;
|
||||
}
|
||||
|
||||
static int
|
||||
spa_recycle_one(spa_t *spa, spa_chain_map_pool_t *entry, boolean_t dryrun,
|
||||
nvlist_t *outnvl)
|
||||
{
|
||||
int err = 0;
|
||||
uint64_t guid = entry->scmp_guid;
|
||||
spa_t *search = kmem_zalloc(sizeof (spa_t), KM_SLEEP);
|
||||
search->spa_config_guid = guid;
|
||||
|
||||
spa_t *client;
|
||||
list_t *l = &spa->spa_registered_clients;
|
||||
for (client = list_head(l); client != NULL;
|
||||
client = list_next(l, client)) {
|
||||
if (spa_const_guid(client) == entry->scmp_guid)
|
||||
break;
|
||||
}
|
||||
if (!client) {
|
||||
fnvlist_add_uint64(outnvl, entry->scmp_name, guid);
|
||||
}
|
||||
if (dryrun || client) {
|
||||
return (err);
|
||||
}
|
||||
|
||||
uint64_t chain_map_zap = spa->spa_dsl_pool->dp_chain_map_obj;
|
||||
dmu_tx_t *tx = dmu_tx_create_mos(spa->spa_dsl_pool);
|
||||
dmu_tx_hold_zap(tx, chain_map_zap, B_TRUE, NULL);
|
||||
dmu_tx_assign(tx, TXG_WAIT);
|
||||
uint64_t keybuf[2];
|
||||
keybuf[0] = entry->scmp_guid;
|
||||
|
||||
avl_tree_t *os_tree = &entry->scmp_os_tree;
|
||||
spa_chain_map_os_t *os = NULL;
|
||||
void *cookie = NULL;
|
||||
while ((os = avl_destroy_nodes(os_tree, &cookie))) {
|
||||
struct spa_chain_map_free_cb_arg arg;
|
||||
arg.smcfca_end = NULL;
|
||||
arg.smcfca_guid = os->scmo_id;
|
||||
arg.smcfca_txg = spa->spa_syncing_txg;
|
||||
(void) zil_parse_raw(spa, &os->scmo_chain_head,
|
||||
spa_chain_map_free_blk_cb, spa_chain_map_free_lr_cb, &arg);
|
||||
|
||||
keybuf[1] = os->scmo_id;
|
||||
zap_remove_uint64(spa->spa_dsl_pool->dp_meta_objset,
|
||||
chain_map_zap, keybuf, sizeof (keybuf) / sizeof (uint64_t),
|
||||
tx);
|
||||
kmem_free(os, sizeof (*os));
|
||||
}
|
||||
dmu_tx_commit(tx);
|
||||
avl_destroy(&entry->scmp_os_tree);
|
||||
kmem_free(search, sizeof (*search));
|
||||
|
||||
avl_remove(&spa->spa_chain_map, entry);
|
||||
kmem_free(entry, sizeof (*entry));
|
||||
return (err);
|
||||
}
|
||||
|
||||
int
|
||||
spa_recycle(spa_t *spa, boolean_t dryrun, nvlist_t *outnvl)
|
||||
spa_recycle_all(spa_t *spa, boolean_t dryrun, nvlist_t *outnvl)
|
||||
{
|
||||
int err = 0;
|
||||
if (!spa_is_shared_log(spa)) {
|
||||
return (SET_ERROR(ENOTSUP));
|
||||
}
|
||||
|
||||
spa_t *search = kmem_zalloc(sizeof (spa_t), KM_SLEEP);
|
||||
mutex_enter(&spa->spa_chain_map_lock);
|
||||
avl_tree_t *t = &spa->spa_chain_map;
|
||||
spa_chain_map_pool_t *entry = avl_first(t);
|
||||
while (entry != NULL) {
|
||||
uint64_t guid = entry->scmp_guid;
|
||||
search->spa_config_guid = guid;
|
||||
spa_t *client = avl_find(&spa->spa_registered_clients, search,
|
||||
NULL);
|
||||
spa_chain_map_pool_t *next = AVL_NEXT(t, entry);
|
||||
if (!client) {
|
||||
char buf[64];
|
||||
snprintf(buf, sizeof (buf), "%llu", (u_longlong_t)guid);
|
||||
fnvlist_add_boolean(outnvl, buf);
|
||||
}
|
||||
if (dryrun || client) {
|
||||
entry = next;
|
||||
continue;
|
||||
}
|
||||
avl_tree_t *os_tree = &entry->scmp_os_tree;
|
||||
spa_chain_map_os_t *os = NULL;
|
||||
void *cookie = NULL;
|
||||
while ((os = avl_destroy_nodes(os_tree, &cookie))) {
|
||||
struct spa_chain_map_free_cb_arg arg;
|
||||
arg.smcfca_end = NULL;
|
||||
arg.smcfca_guid = os->scmo_id;
|
||||
arg.smcfca_txg = spa->spa_syncing_txg;
|
||||
int this_err = zil_parse_raw(spa, &os->scmo_chain_head,
|
||||
spa_chain_map_free_blk_cb,
|
||||
spa_chain_map_free_lr_cb, &arg);
|
||||
if (this_err != 0 && err == 0)
|
||||
err = this_err;
|
||||
kmem_free(os, sizeof (*os));
|
||||
}
|
||||
avl_remove(t, entry);
|
||||
avl_destroy(&entry->scmp_os_tree);
|
||||
kmem_free(entry, sizeof (*entry));
|
||||
|
||||
int this_err = spa_recycle_one(spa, entry, dryrun, outnvl);
|
||||
if (this_err != 0 && err == 0)
|
||||
err = this_err;
|
||||
|
||||
entry = next;
|
||||
}
|
||||
mutex_exit(&spa->spa_chain_map_lock);
|
||||
kmem_free(search, sizeof (*search));
|
||||
return (err);
|
||||
}
|
||||
|
||||
int
|
||||
spa_recycle_clients(spa_t *spa, nvlist_t *clients, boolean_t dryrun,
|
||||
nvlist_t *outnvl)
|
||||
{
|
||||
int err = 0;
|
||||
if (!spa_is_shared_log(spa)) {
|
||||
return (SET_ERROR(ENOTSUP));
|
||||
}
|
||||
mutex_enter(&spa->spa_chain_map_lock);
|
||||
for (nvpair_t *pair = nvlist_next_nvpair(clients, NULL);
|
||||
pair != NULL; pair = nvlist_next_nvpair(clients, pair)) {
|
||||
avl_tree_t *t = &spa->spa_chain_map;
|
||||
spa_chain_map_pool_t *entry = avl_first(t);
|
||||
while (entry != NULL) {
|
||||
spa_chain_map_pool_t *next = AVL_NEXT(t, entry);
|
||||
|
||||
if (strcmp(entry->scmp_name, nvpair_name(pair)) != 0) {
|
||||
entry = next;
|
||||
continue;
|
||||
}
|
||||
|
||||
err = spa_recycle_one(spa, entry, dryrun, outnvl);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_exit(&spa->spa_chain_map_lock);
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
|
|
@ -482,6 +482,7 @@ spa_uses_shared_log(const spa_t *spa)
|
|||
return (spa->spa_uses_shared_log);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ==========================================================================
|
||||
* SPA config locking
|
||||
|
@ -825,8 +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));
|
||||
avl_create(&spa->spa_registered_clients, spa_guid_compare,
|
||||
sizeof (spa_t), offsetof(spa_t, spa_client_avl));
|
||||
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));
|
||||
|
||||
|
@ -931,7 +932,7 @@ spa_remove(spa_t *spa)
|
|||
|
||||
avl_destroy(&spa->spa_metaslabs_by_flushed);
|
||||
avl_destroy(&spa->spa_sm_logs_by_txg);
|
||||
avl_destroy(&spa->spa_registered_clients);
|
||||
list_destroy(&spa->spa_registered_clients);
|
||||
list_destroy(&spa->spa_log_summary);
|
||||
list_destroy(&spa->spa_config_list);
|
||||
list_destroy(&spa->spa_leaf_list);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
@ -7103,6 +7145,7 @@ error:
|
|||
|
||||
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
|
||||
|
@ -7111,6 +7154,7 @@ 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);
|
||||
|
@ -7120,9 +7164,14 @@ zfs_ioc_pool_recycle(const char *pool, nvlist_t *innvl, nvlist_t *outnvl)
|
|||
&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);
|
||||
}
|
||||
|
||||
err = spa_recycle(spa, dryrun, outnvl);
|
||||
|
||||
spa_close(spa, FTAG);
|
||||
|
||||
|
@ -7435,6 +7484,16 @@ zfs_ioctl_init(void)
|
|||
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,
|
||||
|
|
|
@ -453,7 +453,8 @@ zil_kstat_values_update(zil_kstat_values_t *zs, zil_sums_t *zil_sums)
|
|||
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)
|
||||
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}}}};
|
||||
|
@ -468,7 +469,7 @@ zil_parse_raw_impl(spa_t *spa, const blkptr_t *bp,
|
|||
* parse function frees the block, we still have next_blk so we
|
||||
* can continue the chain.
|
||||
*/
|
||||
int read_error = zil_read_log_block(spa, B_FALSE, zio_flags,
|
||||
int read_error = zil_read_log_block(spa, decrypt, zio_flags,
|
||||
&blk, &next_blk, &lrp, &end, &abuf);
|
||||
|
||||
error = parse_blk_func(spa, &blk, arg);
|
||||
|
@ -502,13 +503,17 @@ zil_parse_raw_impl(spa_t *spa, const blkptr_t *bp,
|
|||
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,
|
||||
0));
|
||||
ZIO_FLAG_SPECULATIVE | ZIO_FLAG_SCRUB, B_FALSE));
|
||||
}
|
||||
|
||||
struct parse_arg {
|
||||
|
@ -517,7 +522,6 @@ struct parse_arg {
|
|||
zil_parse_lr_func_t *parse_lr_func;
|
||||
void *arg;
|
||||
uint64_t txg;
|
||||
boolean_t decrypt;
|
||||
uint64_t blk_seq;
|
||||
uint64_t claim_blk_seq;
|
||||
uint64_t claim_lr_seq;
|
||||
|
@ -594,7 +598,6 @@ zil_parse(zilog_t *zilog, zil_parse_blk_func_t *parse_blk_func,
|
|||
arg2.parse_blk_func = parse_blk_func;
|
||||
arg2.parse_lr_func = parse_lr_func;
|
||||
arg2.txg = txg;
|
||||
arg2.decrypt = decrypt;
|
||||
arg2.zilog = zilog;
|
||||
arg2.error = 0;
|
||||
arg2.blk_seq = 0;
|
||||
|
@ -615,7 +618,7 @@ zil_parse(zilog_t *zilog, zil_parse_blk_func_t *parse_blk_func,
|
|||
zil_bp_tree_init(zilog);
|
||||
|
||||
int error = zil_parse_raw_impl(zilog->zl_io_spa, &zh->zh_log,
|
||||
parse_blk_wrapper, parse_lr_wrapper, &arg2, zio_flags);
|
||||
parse_blk_wrapper, parse_lr_wrapper, &arg2, zio_flags, decrypt);
|
||||
|
||||
// If this happens, we got an error from zil_read_log_block_spa
|
||||
if (error != 0 && error != EINTR && claimed) {
|
||||
|
@ -1212,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)
|
||||
{
|
||||
|
|
|
@ -930,7 +930,7 @@ 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_005_pos', 'shared_log_006_neg', 'shared_log_007_pos', 'shared_log_008_pos']
|
||||
tags = ['functional', 'shared_log']
|
||||
|
||||
[tests/functional/slog]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1953,6 +1953,8 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
|||
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 \
|
||||
|
|
|
@ -29,6 +29,10 @@
|
|||
|
||||
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
|
||||
|
|
|
@ -23,9 +23,8 @@
|
|||
# Copyright (c) 2023 by Delphix. All rights reserved.
|
||||
#
|
||||
|
||||
export LOGPOOL="${TESTPOOL}_log"
|
||||
IFS=' ' read -r -a array <<< "$DISKS"
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
export DISK0="${array[0]}"
|
||||
export DISK1="${array[1]}"
|
||||
export DISK2="${array[2]}"
|
||||
export LOGPOOL="${TESTPOOL}_log"
|
||||
read -r DISK0 DISK1 DISK2 _ <<<"$DISKS"
|
||||
export DISK0 DISK1 DISK2
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
|
||||
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
|
||||
|
|
|
@ -44,5 +44,7 @@ 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."
|
||||
|
|
|
@ -55,5 +55,7 @@ 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."
|
||||
|
|
|
@ -58,5 +58,7 @@ 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."
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
# 3. Export client and provider
|
||||
# 4. Import client with -m
|
||||
# 5. Export client
|
||||
# 6. Import client with -m and new pool
|
||||
# 6. Import client with -m and new provider
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
@ -63,5 +63,8 @@ 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."
|
||||
|
|
|
@ -31,9 +31,14 @@
|
|||
# Negative shared log testing.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create shared log pool & client
|
||||
# 2. Write some data to the client pool
|
||||
# 3. Scrub client and provider pools
|
||||
# 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"
|
||||
|
|
|
@ -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."
|
Loading…
Reference in New Issue