diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libzfs/libzfs_pool.c | 43 | ||||
-rw-r--r-- | lib/libzfs/libzfs_util.c | 29 | ||||
-rw-r--r-- | lib/libzfs_core/libzfs_core.c | 68 | ||||
-rw-r--r-- | lib/libzpool/Makefile.am | 1 | ||||
-rw-r--r-- | lib/libzpool/kernel.c | 2 |
5 files changed, 139 insertions, 4 deletions
diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index ef98b25bc..e8c0cdfe4 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -350,6 +350,7 @@ zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, break; case ZPOOL_PROP_EXPANDSZ: + case ZPOOL_PROP_CHECKPOINT: if (intval == 0) { (void) strlcpy(buf, "-", len); } else if (literal) { @@ -1380,6 +1381,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/lib/libzfs/libzfs_util.c b/lib/libzfs/libzfs_util.c index 855c72fab..a19b34415 100644 --- a/lib/libzfs/libzfs_util.c +++ b/lib/libzfs/libzfs_util.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, Joyent, Inc. All rights reserved. - * Copyright (c) 2011, 2014 by Delphix. All rights reserved. + * Copyright (c) 2011, 2017 by Delphix. All rights reserved. * Copyright 2016 Igor Kozhukhov <[email protected]> * Copyright (c) 2017 Datto Inc. */ @@ -264,6 +264,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_ACTIVE_POOL: return (dgettext(TEXT_DOMAIN, "pool is imported on a " "different host")); @@ -530,7 +541,21 @@ zpool_standard_error_fmt(libzfs_handle_t *hdl, int error, const char *fmt, ...) case EREMOTEIO: zfs_verror(hdl, EZFS_ACTIVE_POOL, 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/lib/libzfs_core/libzfs_core.c b/lib/libzfs_core/libzfs_core.c index 5a46042a4..ab2b70519 100644 --- a/lib/libzfs_core/libzfs_core.c +++ b/lib/libzfs_core/libzfs_core.c @@ -1143,6 +1143,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/lib/libzpool/Makefile.am b/lib/libzpool/Makefile.am index f2a7a00a8..58e3b6eec 100644 --- a/lib/libzpool/Makefile.am +++ b/lib/libzpool/Makefile.am @@ -92,6 +92,7 @@ KERNEL_C = \ skein_zfs.c \ spa.c \ spa_boot.c \ + spa_checkpoint.c \ spa_config.c \ spa_errlog.c \ spa_history.c \ diff --git a/lib/libzpool/kernel.c b/lib/libzpool/kernel.c index 1eaa51b9f..341548ac3 100644 --- a/lib/libzpool/kernel.c +++ b/lib/libzpool/kernel.c @@ -497,8 +497,6 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3) #ifdef __linux__ flags |= O_DIRECT; #endif - /* We shouldn't be writing to block devices in userspace */ - VERIFY(!(flags & FWRITE)); } if (flags & FCREAT) |