aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cddl/contrib/opensolaris/cmd/zpool/zpool.816
-rw-r--r--cddl/contrib/opensolaris/cmd/zpool/zpool_main.c45
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h2
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c21
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c34
-rw-r--r--cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h3
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c43
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h1
8 files changed, 154 insertions, 11 deletions
diff --git a/cddl/contrib/opensolaris/cmd/zpool/zpool.8 b/cddl/contrib/opensolaris/cmd/zpool/zpool.8
index 811baf39babd..6880f822d3f3 100644
--- a/cddl/contrib/opensolaris/cmd/zpool/zpool.8
+++ b/cddl/contrib/opensolaris/cmd/zpool/zpool.8
@@ -193,6 +193,9 @@
.Ar ...
.Op Ar interval Op Ar count
.Nm
+.Cm sync
+.Oo Ar pool Oc Ns ...
+.Nm
.Cm upgrade
.Op Fl v
.Nm
@@ -1915,6 +1918,19 @@ block size or disabled features will not be included.
.El
.It Xo
.Nm
+.Cm sync
+.Oo Ar pool Oc Ns ...
+.Xc
+Forces all in-core dirty data to be written to the primary pool storage and
+not the ZIL.
+It will also update administrative information including quota reporting.
+Without arguments,
+.Nm zpool Cm sync
+will sync all pools on the system.
+Otherwise, it will only sync the specified
+.Ar pool .
+.It Xo
+.Nm
.Cm upgrade
.Op Fl v
.Xc
diff --git a/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c b/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
index 52ee96f81f61..d3f179c5cb16 100644
--- a/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
+++ b/cddl/contrib/opensolaris/cmd/zpool/zpool_main.c
@@ -100,6 +100,8 @@ static int zpool_do_history(int, char **);
static int zpool_do_get(int, char **);
static int zpool_do_set(int, char **);
+static int zpool_do_sync(int, char **);
+
/*
* These libumem hooks provide a reasonable set of defaults for the allocator's
* debugging facilities.
@@ -144,6 +146,7 @@ typedef enum {
HELP_GET,
HELP_SET,
HELP_SPLIT,
+ HELP_SYNC,
HELP_REGUID,
HELP_REOPEN
} zpool_help_t;
@@ -200,6 +203,7 @@ static zpool_command_t command_table[] = {
{ "history", zpool_do_history, HELP_HISTORY },
{ "get", zpool_do_get, HELP_GET },
{ "set", zpool_do_set, HELP_SET },
+ { "sync", zpool_do_sync, HELP_SYNC },
};
#define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
@@ -285,6 +289,8 @@ get_usage(zpool_help_t idx)
"[<device> ...]\n"));
case HELP_REGUID:
return (gettext("\treguid <pool>\n"));
+ case HELP_SYNC:
+ return (gettext("\tsync [pool] ...\n"));
}
abort();
@@ -2648,6 +2654,45 @@ error:
return (err ? 1 : 0);
}
+/*
+ * zpool sync [-f] [pool] ...
+ *
+ * -f (undocumented) force uberblock (and config including zpool cache file)
+ * update.
+ *
+ * Sync the specified pool(s).
+ * Without arguments "zpool sync" will sync all pools.
+ * This command initiates TXG sync(s) and will return after the TXG(s) commit.
+ *
+ */
+static int
+zpool_do_sync(int argc, char **argv)
+{
+ int ret;
+ boolean_t force = B_FALSE;
+
+ /* check options */
+ while ((ret = getopt(argc, argv, "f")) != -1) {
+ switch (ret) {
+ case 'f':
+ force = B_TRUE;
+ break;
+ case '?':
+ (void) fprintf(stderr, gettext("invalid option '%c'\n"),
+ optopt);
+ usage(B_FALSE);
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ /* if argc == 0 we will execute zpool_sync_one on all pools */
+ ret = for_each_pool(argc, argv, B_FALSE, NULL, zpool_sync_one, &force);
+
+ return (ret);
+}
+
typedef struct iostat_cbdata {
boolean_t cb_verbose;
int cb_namewidth;
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
index c0e235476fed..aeae6e3822a3 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs.h
@@ -271,6 +271,8 @@ extern int zpool_clear(zpool_handle_t *, const char *, nvlist_t *);
extern int zpool_reguid(zpool_handle_t *);
extern int zpool_reopen(zpool_handle_t *);
+extern int zpool_sync_one(zpool_handle_t *, void *);
+
extern int zpool_vdev_online(zpool_handle_t *, const char *, int,
vdev_state_t *);
extern int zpool_vdev_offline(zpool_handle_t *, const char *, boolean_t);
diff --git a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
index dfb2198b7c75..153fda241188 100644
--- a/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
+++ b/cddl/contrib/opensolaris/lib/libzfs/common/libzfs_pool.c
@@ -3515,6 +3515,27 @@ zpool_reopen(zpool_handle_t *zhp)
return (zpool_standard_error(hdl, errno, msg));
}
+/* call into libzfs_core to execute the sync IOCTL per pool */
+int
+zpool_sync_one(zpool_handle_t *zhp, void *data)
+{
+ int ret;
+ libzfs_handle_t *hdl = zpool_get_handle(zhp);
+ const char *pool_name = zpool_get_name(zhp);
+ boolean_t *force = data;
+ nvlist_t *innvl = fnvlist_alloc();
+
+ fnvlist_add_boolean_value(innvl, "force", *force);
+ if ((ret = lzc_sync(pool_name, innvl, NULL)) != 0) {
+ nvlist_free(innvl);
+ return (zpool_standard_error_fmt(hdl, ret,
+ dgettext(TEXT_DOMAIN, "sync '%s' failed"), pool_name));
+ }
+ nvlist_free(innvl);
+
+ return (0);
+}
+
/*
* Convert from a devid string to a path.
*/
diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c
index 4f5054fbd084..cd5767e69b9b 100644
--- a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c
+++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.c
@@ -24,6 +24,7 @@
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2017 RackTop Systems.
+ * Copyright (c) 2017 Datto Inc.
*/
/*
@@ -137,16 +138,17 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name,
{
zfs_cmd_t zc = { 0 };
int error = 0;
- char *packed;
+ char *packed = NULL;
#ifdef __FreeBSD__
nvlist_t *oldsource;
#endif
- size_t size;
+ size_t size = 0;
ASSERT3S(g_refcount, >, 0);
VERIFY3S(g_fd, !=, -1);
- (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
+ if (name != NULL)
+ (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
#ifdef __FreeBSD__
if (zfs_ioctl_version == ZFS_IOCVER_UNDEF)
@@ -160,9 +162,11 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name,
}
#endif
- packed = fnvlist_pack(source, &size);
- zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed;
- zc.zc_nvlist_src_size = size;
+ if (source != NULL) {
+ packed = fnvlist_pack(source, &size);
+ zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed;
+ zc.zc_nvlist_src_size = size;
+ }
if (resultp != NULL) {
*resultp = NULL;
@@ -463,6 +467,18 @@ lzc_exists(const char *dataset)
}
/*
+ * outnvl is unused.
+ * It was added to preserve the function signature in case it is
+ * needed in the future.
+ */
+/*ARGSUSED*/
+int
+lzc_sync(const char *pool_name, nvlist_t *innvl, nvlist_t **outnvl)
+{
+ return (lzc_ioctl(ZFS_IOC_POOL_SYNC, pool_name, innvl, NULL));
+}
+
+/*
* Create "user holds" on snapshots. If there is a hold on a snapshot,
* the snapshot can not be destroyed. (However, it can be marked for deletion
* by lzc_destroy_snaps(defer=B_TRUE).)
@@ -562,11 +578,7 @@ lzc_release(nvlist_t *holds, nvlist_t **errlist)
int
lzc_get_holds(const char *snapname, nvlist_t **holdsp)
{
- int error;
- nvlist_t *innvl = fnvlist_alloc();
- error = lzc_ioctl(ZFS_IOC_GET_HOLDS, snapname, innvl, holdsp);
- fnvlist_free(innvl);
- return (error);
+ return (lzc_ioctl(ZFS_IOC_GET_HOLDS, snapname, NULL, holdsp));
}
/*
diff --git a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h
index 44deb7af7be0..97d7ce81d8ab 100644
--- a/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h
+++ b/cddl/contrib/opensolaris/lib/libzfs_core/common/libzfs_core.h
@@ -23,6 +23,7 @@
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2013 by Martin Matuska <mm@FreeBSD.org>. All rights reserved.
* Copyright 2017 RackTop Systems.
+ * Copyright (c) 2017 Datto Inc.
*/
#ifndef _LIBZFS_CORE_H
@@ -91,6 +92,8 @@ boolean_t lzc_exists(const char *);
int lzc_rollback(const char *, char *, int);
int lzc_rollback_to(const char *, const char *);
+int lzc_sync(const char *, nvlist_t *, nvlist_t **);
+
int lzc_rename(const char *, const char *);
int lzc_destroy(const char *);
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
index b85a473f9c50..c76c3543644c 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
@@ -5836,6 +5836,7 @@ zfs_ioc_hold(const char *pool, nvlist_t *args, nvlist_t *errlist)
static int
zfs_ioc_get_holds(const char *snapname, nvlist_t *args, nvlist_t *outnvl)
{
+ ASSERT3P(args, ==, NULL);
return (dsl_dataset_get_holds(snapname, outnvl));
}
@@ -6134,6 +6135,44 @@ out:
return (error);
}
+/*
+ * Sync the currently open TXG to disk for the specified pool.
+ * This is somewhat similar to 'zfs_sync()'.
+ * For cases that do not result in error this ioctl will wait for
+ * the currently open TXG to commit before returning back to the caller.
+ *
+ * innvl: {
+ * "force" -> when true, force uberblock update even if there is no dirty data.
+ * In addition this will cause the vdev configuration to be written
+ * out including updating the zpool cache file. (boolean_t)
+ * }
+ *
+ * onvl is unused
+ */
+/* ARGSUSED */
+static int
+zfs_ioc_pool_sync(const char *pool, nvlist_t *innvl, nvlist_t *onvl)
+{
+ int err;
+ boolean_t force;
+ spa_t *spa;
+
+ if ((err = spa_open(pool, &spa, FTAG)) != 0)
+ return (err);
+
+ force = fnvlist_lookup_boolean_value(innvl, "force");
+ if (force) {
+ spa_config_enter(spa, SCL_CONFIG, FTAG, RW_WRITER);
+ vdev_config_dirty(spa->spa_root_vdev);
+ spa_config_exit(spa, SCL_CONFIG, FTAG);
+ }
+ txg_wait_synced(spa_get_dsl(spa), 0);
+
+ spa_close(spa, FTAG);
+
+ return (err);
+}
+
static zfs_ioc_vec_t zfs_ioc_vec[ZFS_IOC_LAST - ZFS_IOC_FIRST];
static void
@@ -6324,6 +6363,10 @@ zfs_ioctl_init(void)
zfs_ioc_pool_initialize, zfs_secpolicy_config, POOL_NAME,
POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE, B_TRUE);
+ zfs_ioctl_register("sync", ZFS_IOC_POOL_SYNC,
+ zfs_ioc_pool_sync, zfs_secpolicy_none, POOL_NAME,
+ POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_FALSE, B_FALSE);
+
/* IOCTLS that use the legacy function signature */
zfs_ioctl_register_legacy(ZFS_IOC_POOL_FREEZE, zfs_ioc_pool_freeze,
diff --git a/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h b/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h
index 35e537f2094d..c328c82164b6 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h
+++ b/sys/cddl/contrib/opensolaris/uts/common/sys/fs/zfs.h
@@ -1016,6 +1016,7 @@ typedef enum zfs_ioc {
ZFS_IOC_POOL_CHECKPOINT,
ZFS_IOC_POOL_DISCARD_CHECKPOINT,
ZFS_IOC_POOL_INITIALIZE,
+ ZFS_IOC_POOL_SYNC,
ZFS_IOC_LAST
} zfs_ioc_t;