diff options
| author | Serapheim Dimitropoulos <serapheim.dimitro@delphix.com> | 2016-12-16 14:11:29 -0800 |
|---|---|---|
| committer | Prakash Surya <prakash.surya@delphix.com> | 2018-03-14 09:49:34 -0700 |
| commit | 8671400134a11c848244896ca51a7db4d0f69da4 (patch) | |
| tree | aa6bf256f74f184f8bc40eae05449e40bf482be3 /usr/src/lib | |
| parent | 5f5913bb83405db87f982abee80162a479d363af (diff) | |
| download | illumos-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.h | 7 | ||||
| -rw-r--r-- | usr/src/lib/libzfs/common/libzfs_pool.c | 43 | ||||
| -rw-r--r-- | usr/src/lib/libzfs/common/libzfs_util.c | 29 | ||||
| -rw-r--r-- | usr/src/lib/libzfs/common/mapfile-vers | 2 | ||||
| -rw-r--r-- | usr/src/lib/libzfs_core/common/libzfs_core.c | 68 | ||||
| -rw-r--r-- | usr/src/lib/libzfs_core/common/libzfs_core.h | 3 | ||||
| -rw-r--r-- | usr/src/lib/libzfs_core/common/mapfile-vers | 9 |
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: |
