summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
authorSerapheim Dimitropoulos <serapheim.dimitro@delphix.com>2016-12-16 14:11:29 -0800
committerPrakash Surya <prakash.surya@delphix.com>2018-03-14 09:49:34 -0700
commit8671400134a11c848244896ca51a7db4d0f69da4 (patch)
treeaa6bf256f74f184f8bc40eae05449e40bf482be3 /usr/src/lib
parent5f5913bb83405db87f982abee80162a479d363af (diff)
downloadillumos-joyent-8671400134a11c848244896ca51a7db4d0f69da4.tar.gz
9166 zfs storage pool checkpoint
Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: John Kennedy <john.kennedy@delphix.com> Reviewed by: Dan Kimmel <dan.kimmel@delphix.com> Approved by: Richard Lowe <richlowe@richlowe.net>
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/libzfs/common/libzfs.h7
-rw-r--r--usr/src/lib/libzfs/common/libzfs_pool.c43
-rw-r--r--usr/src/lib/libzfs/common/libzfs_util.c29
-rw-r--r--usr/src/lib/libzfs/common/mapfile-vers2
-rw-r--r--usr/src/lib/libzfs_core/common/libzfs_core.c68
-rw-r--r--usr/src/lib/libzfs_core/common/libzfs_core.h3
-rw-r--r--usr/src/lib/libzfs_core/common/mapfile-vers9
7 files changed, 158 insertions, 3 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h
index 5011f923d2..80603104ac 100644
--- a/usr/src/lib/libzfs/common/libzfs.h
+++ b/usr/src/lib/libzfs/common/libzfs.h
@@ -131,6 +131,11 @@ typedef enum zfs_error {
EZFS_POOLREADONLY, /* pool is in read-only mode */
EZFS_SCRUB_PAUSED, /* scrub currently paused */
EZFS_NO_PENDING, /* cannot cancel, no operation is pending */
+ EZFS_CHECKPOINT_EXISTS, /* checkpoint exists */
+ EZFS_DISCARDING_CHECKPOINT, /* currently discarding a checkpoint */
+ EZFS_NO_CHECKPOINT, /* pool has no checkpoint */
+ EZFS_DEVRM_IN_PROGRESS, /* a device is currently being removed */
+ EZFS_VDEV_TOO_BIG, /* a device is too big to be used */
EZFS_UNKNOWN
} zfs_error_t;
@@ -417,6 +422,8 @@ extern int zfs_ioctl(libzfs_handle_t *, int, struct zfs_cmd *);
extern int zpool_get_physpath(zpool_handle_t *, char *, size_t);
extern void zpool_explain_recover(libzfs_handle_t *, const char *, int,
nvlist_t *);
+extern int zpool_checkpoint(zpool_handle_t *);
+extern int zpool_discard_checkpoint(zpool_handle_t *);
/*
* Basic handle manipulations. These functions do not create or destroy the
diff --git a/usr/src/lib/libzfs/common/libzfs_pool.c b/usr/src/lib/libzfs/common/libzfs_pool.c
index 01f6b0d8ac..8afb70f839 100644
--- a/usr/src/lib/libzfs/common/libzfs_pool.c
+++ b/usr/src/lib/libzfs/common/libzfs_pool.c
@@ -317,6 +317,7 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len,
break;
case ZPOOL_PROP_BOOTSIZE:
case ZPOOL_PROP_EXPANDSZ:
+ case ZPOOL_PROP_CHECKPOINT:
if (intval == 0) {
(void) strlcpy(buf, "-", len);
} else if (literal) {
@@ -1281,6 +1282,48 @@ zpool_destroy(zpool_handle_t *zhp, const char *log_str)
}
/*
+ * Create a checkpoint in the given pool.
+ */
+int
+zpool_checkpoint(zpool_handle_t *zhp)
+{
+ libzfs_handle_t *hdl = zhp->zpool_hdl;
+ char msg[1024];
+ int error;
+
+ error = lzc_pool_checkpoint(zhp->zpool_name);
+ if (error != 0) {
+ (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
+ "cannot checkpoint '%s'"), zhp->zpool_name);
+ (void) zpool_standard_error(hdl, error, msg);
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * Discard the checkpoint from the given pool.
+ */
+int
+zpool_discard_checkpoint(zpool_handle_t *zhp)
+{
+ libzfs_handle_t *hdl = zhp->zpool_hdl;
+ char msg[1024];
+ int error;
+
+ error = lzc_pool_checkpoint_discard(zhp->zpool_name);
+ if (error != 0) {
+ (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN,
+ "cannot discard checkpoint in '%s'"), zhp->zpool_name);
+ (void) zpool_standard_error(hdl, error, msg);
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
* Add the given vdevs to the pool. The caller must have already performed the
* necessary verification to ensure that the vdev specification is well-formed.
*/
diff --git a/usr/src/lib/libzfs/common/libzfs_util.c b/usr/src/lib/libzfs/common/libzfs_util.c
index afa991d5a1..c73485acfe 100644
--- a/usr/src/lib/libzfs/common/libzfs_util.c
+++ b/usr/src/lib/libzfs/common/libzfs_util.c
@@ -22,7 +22,7 @@
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
+ * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
* Copyright (c) 2017 Datto Inc.
*/
@@ -238,6 +238,17 @@ libzfs_error_description(libzfs_handle_t *hdl)
case EZFS_NO_PENDING:
return (dgettext(TEXT_DOMAIN, "operation is not "
"in progress"));
+ case EZFS_CHECKPOINT_EXISTS:
+ return (dgettext(TEXT_DOMAIN, "checkpoint exists"));
+ case EZFS_DISCARDING_CHECKPOINT:
+ return (dgettext(TEXT_DOMAIN, "currently discarding "
+ "checkpoint"));
+ case EZFS_NO_CHECKPOINT:
+ return (dgettext(TEXT_DOMAIN, "checkpoint does not exist"));
+ case EZFS_DEVRM_IN_PROGRESS:
+ return (dgettext(TEXT_DOMAIN, "device removal in progress"));
+ case EZFS_VDEV_TOO_BIG:
+ return (dgettext(TEXT_DOMAIN, "device exceeds supported size"));
case EZFS_UNKNOWN:
return (dgettext(TEXT_DOMAIN, "unknown error"));
default:
@@ -487,7 +498,21 @@ zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...)
case ENOTACTIVE:
zfs_verror(hdl, EZFS_NO_PENDING, fmt, ap);
break;
-
+ case ZFS_ERR_CHECKPOINT_EXISTS:
+ zfs_verror(hdl, EZFS_CHECKPOINT_EXISTS, fmt, ap);
+ break;
+ case ZFS_ERR_DISCARDING_CHECKPOINT:
+ zfs_verror(hdl, EZFS_DISCARDING_CHECKPOINT, fmt, ap);
+ break;
+ case ZFS_ERR_NO_CHECKPOINT:
+ zfs_verror(hdl, EZFS_NO_CHECKPOINT, fmt, ap);
+ break;
+ case ZFS_ERR_DEVRM_IN_PROGRESS:
+ zfs_verror(hdl, EZFS_DEVRM_IN_PROGRESS, fmt, ap);
+ break;
+ case ZFS_ERR_VDEV_TOO_BIG:
+ zfs_verror(hdl, EZFS_VDEV_TOO_BIG, fmt, ap);
+ break;
default:
zfs_error_aux(hdl, strerror(error));
zfs_verror(hdl, EZFS_UNKNOWN, fmt, ap);
diff --git a/usr/src/lib/libzfs/common/mapfile-vers b/usr/src/lib/libzfs/common/mapfile-vers
index 3f86f32934..5b7817304f 100644
--- a/usr/src/lib/libzfs/common/mapfile-vers
+++ b/usr/src/lib/libzfs/common/mapfile-vers
@@ -180,12 +180,14 @@ SYMBOL_VERSION SUNWprivate_1.1 {
zfs_userquota_prop_prefixes;
zfs_zpl_version_map;
zpool_add;
+ zpool_checkpoint;
zpool_clear;
zpool_clear_label;
zpool_close;
zpool_create;
zpool_destroy;
zpool_disable_datasets;
+ zpool_discard_checkpoint;
zpool_dump_ddt;
zpool_enable_datasets;
zpool_expand_proplist;
diff --git a/usr/src/lib/libzfs_core/common/libzfs_core.c b/usr/src/lib/libzfs_core/common/libzfs_core.c
index 7f3162168c..d09304fbbb 100644
--- a/usr/src/lib/libzfs_core/common/libzfs_core.c
+++ b/usr/src/lib/libzfs_core/common/libzfs_core.c
@@ -952,6 +952,74 @@ lzc_channel_program(const char *pool, const char *program, uint64_t instrlimit,
}
/*
+ * Creates a checkpoint for the specified pool.
+ *
+ * If this function returns 0 the pool was successfully checkpointed.
+ *
+ * This method may also return:
+ *
+ * ZFS_ERR_CHECKPOINT_EXISTS
+ * The pool already has a checkpoint. A pools can only have one
+ * checkpoint at most, at any given time.
+ *
+ * ZFS_ERR_DISCARDING_CHECKPOINT
+ * ZFS is in the middle of discarding a checkpoint for this pool.
+ * The pool can be checkpointed again once the discard is done.
+ *
+ * ZFS_DEVRM_IN_PROGRESS
+ * A vdev is currently being removed. The pool cannot be
+ * checkpointed until the device removal is done.
+ *
+ * ZFS_VDEV_TOO_BIG
+ * One or more top-level vdevs exceed the maximum vdev size
+ * supported for this feature.
+ */
+int
+lzc_pool_checkpoint(const char *pool)
+{
+ int error;
+
+ nvlist_t *result = NULL;
+ nvlist_t *args = fnvlist_alloc();
+
+ error = lzc_ioctl(ZFS_IOC_POOL_CHECKPOINT, pool, args, &result);
+
+ fnvlist_free(args);
+ fnvlist_free(result);
+
+ return (error);
+}
+
+/*
+ * Discard the checkpoint from the specified pool.
+ *
+ * If this function returns 0 the checkpoint was successfully discarded.
+ *
+ * This method may also return:
+ *
+ * ZFS_ERR_NO_CHECKPOINT
+ * The pool does not have a checkpoint.
+ *
+ * ZFS_ERR_DISCARDING_CHECKPOINT
+ * ZFS is already in the middle of discarding the checkpoint.
+ */
+int
+lzc_pool_checkpoint_discard(const char *pool)
+{
+ int error;
+
+ nvlist_t *result = NULL;
+ nvlist_t *args = fnvlist_alloc();
+
+ error = lzc_ioctl(ZFS_IOC_POOL_DISCARD_CHECKPOINT, pool, args, &result);
+
+ fnvlist_free(args);
+ fnvlist_free(result);
+
+ return (error);
+}
+
+/*
* Executes a read-only channel program.
*
* A read-only channel program works programmatically the same way as a
diff --git a/usr/src/lib/libzfs_core/common/libzfs_core.h b/usr/src/lib/libzfs_core/common/libzfs_core.h
index c702660f00..8c6743f503 100644
--- a/usr/src/lib/libzfs_core/common/libzfs_core.h
+++ b/usr/src/lib/libzfs_core/common/libzfs_core.h
@@ -92,6 +92,9 @@ int lzc_channel_program(const char *, const char *, uint64_t,
int lzc_channel_program_nosync(const char *, const char *, uint64_t,
uint64_t, nvlist_t *, nvlist_t **);
+int lzc_pool_checkpoint(const char *);
+int lzc_pool_checkpoint_discard(const char *);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/lib/libzfs_core/common/mapfile-vers b/usr/src/lib/libzfs_core/common/mapfile-vers
index 324819149f..7f63f041b6 100644
--- a/usr/src/lib/libzfs_core/common/mapfile-vers
+++ b/usr/src/lib/libzfs_core/common/mapfile-vers
@@ -19,7 +19,7 @@
# CDDL HEADER END
#
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+# Copyright (c) 2012, 2017 by Delphix. All rights reserved.
# Copyright 2017 RackTop Systems.
#
# MAPFILE HEADER START
@@ -37,6 +37,13 @@
$mapfile_version 2
+SYMBOL_VERSION ILLUMOS_0.2 {
+ global:
+
+ lzc_pool_checkpoint;
+ lzc_pool_checkpoint_discard;
+} ILLUMOS_0.1;
+
SYMBOL_VERSION ILLUMOS_0.1 {
global: