1796 "ZFS HOLD" should not be used when doing "ZFS SEND" from a read-only pool 2871 support for __ZFS_POOL_RESTRICT used by ZFS test suite 2903 zfs destroy -d does not work 2957 zfs destroy -R/r sometimes fails when removing defer-destroyed snapshot Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: George Wilson <george.wilson@delphix.com> Approved by: Eric Schrock <Eric.Schrock@delphix.com> References: https://www.illumos.org/issues/1796 https://www.illumos.org/issues/2871 https://www.illumos.org/issues/2903 https://www.illumos.org/issues/2957 Ported by: Martin Matuska <martin@matuska.org> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
This commit is contained in:
parent
db49968e5c
commit
e956d65106
|
@ -1066,7 +1066,7 @@ snapshot_to_nvl_cb(zfs_handle_t *zhp, void *arg)
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
/* Check for clones. */
|
/* Check for clones. */
|
||||||
if (!cb->cb_doclones) {
|
if (!cb->cb_doclones && !cb->cb_defer_destroy) {
|
||||||
cb->cb_target = zhp;
|
cb->cb_target = zhp;
|
||||||
cb->cb_first = B_TRUE;
|
cb->cb_first = B_TRUE;
|
||||||
err = zfs_iter_dependents(zhp, B_TRUE,
|
err = zfs_iter_dependents(zhp, B_TRUE,
|
||||||
|
|
|
@ -301,6 +301,48 @@ zpool_refresh_stats(zpool_handle_t *zhp, boolean_t *missing)
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the __ZFS_POOL_RESTRICT environment variable is set we only iterate over
|
||||||
|
* pools it lists.
|
||||||
|
*
|
||||||
|
* This is an undocumented feature for use during testing only.
|
||||||
|
*
|
||||||
|
* This function returns B_TRUE if the pool should be skipped
|
||||||
|
* during iteration.
|
||||||
|
*/
|
||||||
|
static boolean_t
|
||||||
|
check_restricted(const char *poolname)
|
||||||
|
{
|
||||||
|
static boolean_t initialized = B_FALSE;
|
||||||
|
static char *restricted = NULL;
|
||||||
|
|
||||||
|
const char *cur, *end;
|
||||||
|
int len, namelen;
|
||||||
|
|
||||||
|
if (!initialized) {
|
||||||
|
initialized = B_TRUE;
|
||||||
|
restricted = getenv("__ZFS_POOL_RESTRICT");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NULL == restricted)
|
||||||
|
return (B_FALSE);
|
||||||
|
|
||||||
|
cur = restricted;
|
||||||
|
namelen = strlen(poolname);
|
||||||
|
do {
|
||||||
|
end = strchr(cur, ' ');
|
||||||
|
len = (NULL == end) ? strlen(cur) : (end - cur);
|
||||||
|
|
||||||
|
if (len == namelen && 0 == strncmp(cur, poolname, len)) {
|
||||||
|
return (B_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
cur += (len + 1);
|
||||||
|
} while (NULL != end);
|
||||||
|
|
||||||
|
return (B_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterate over all pools in the system.
|
* Iterate over all pools in the system.
|
||||||
*/
|
*/
|
||||||
|
@ -324,6 +366,9 @@ zpool_iter(libzfs_handle_t *hdl, zpool_iter_f func, void *data)
|
||||||
for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL;
|
for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL;
|
||||||
cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) {
|
cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) {
|
||||||
|
|
||||||
|
if (check_restricted(cn->cn_name))
|
||||||
|
continue;
|
||||||
|
|
||||||
if (zpool_open_silent(hdl, cn->cn_name, &zhp) != 0) {
|
if (zpool_open_silent(hdl, cn->cn_name, &zhp) != 0) {
|
||||||
hdl->libzfs_pool_iter--;
|
hdl->libzfs_pool_iter--;
|
||||||
return (-1);
|
return (-1);
|
||||||
|
@ -359,6 +404,9 @@ zfs_iter_root(libzfs_handle_t *hdl, zfs_iter_f func, void *data)
|
||||||
for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL;
|
for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL;
|
||||||
cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) {
|
cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) {
|
||||||
|
|
||||||
|
if (check_restricted(cn->cn_name))
|
||||||
|
continue;
|
||||||
|
|
||||||
if ((zhp = make_dataset_handle(hdl, cn->cn_name)) == NULL)
|
if ((zhp = make_dataset_handle(hdl, cn->cn_name)) == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -3118,7 +3118,8 @@ zfs_create(libzfs_handle_t *hdl, const char *path, zfs_type_t type,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Destroys the given dataset. The caller must make sure that the filesystem
|
* Destroys the given dataset. The caller must make sure that the filesystem
|
||||||
* isn't mounted, and that there are no active dependents.
|
* isn't mounted, and that there are no active dependents. If the file system
|
||||||
|
* does not exist this function does nothing.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
|
zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
|
||||||
|
@ -3137,7 +3138,8 @@ zfs_destroy(zfs_handle_t *zhp, boolean_t defer)
|
||||||
}
|
}
|
||||||
|
|
||||||
zc.zc_defer_destroy = defer;
|
zc.zc_defer_destroy = defer;
|
||||||
if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY, &zc) != 0) {
|
if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY, &zc) != 0 &&
|
||||||
|
errno != ENOENT) {
|
||||||
return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
|
return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
|
||||||
dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
|
dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
|
||||||
zhp->zfs_name));
|
zhp->zfs_name));
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2011 by Delphix. All rights reserved.
|
* Copyright (c) 2012 by Delphix. All rights reserved.
|
||||||
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
* Copyright (c) 2012 Pawel Jakub Dawidek <pawel@dawidek.net>.
|
||||||
* All rights reserved
|
* All rights reserved
|
||||||
*/
|
*/
|
||||||
|
@ -1308,7 +1308,6 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
|
||||||
avl_tree_t *fsavl = NULL;
|
avl_tree_t *fsavl = NULL;
|
||||||
static uint64_t holdseq;
|
static uint64_t holdseq;
|
||||||
int spa_version;
|
int spa_version;
|
||||||
boolean_t holdsnaps = B_FALSE;
|
|
||||||
pthread_t tid;
|
pthread_t tid;
|
||||||
int pipefd[2];
|
int pipefd[2];
|
||||||
dedup_arg_t dda = { 0 };
|
dedup_arg_t dda = { 0 };
|
||||||
|
@ -1331,11 +1330,6 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!flags->dryrun && zfs_spa_version(zhp, &spa_version) == 0 &&
|
|
||||||
spa_version >= SPA_VERSION_USERREFS &&
|
|
||||||
(flags->doall || flags->replicate))
|
|
||||||
holdsnaps = B_TRUE;
|
|
||||||
|
|
||||||
if (flags->dedup && !flags->dryrun) {
|
if (flags->dedup && !flags->dryrun) {
|
||||||
featureflags |= (DMU_BACKUP_FEATURE_DEDUP |
|
featureflags |= (DMU_BACKUP_FEATURE_DEDUP |
|
||||||
DMU_BACKUP_FEATURE_DEDUPPROPS);
|
DMU_BACKUP_FEATURE_DEDUPPROPS);
|
||||||
|
@ -1456,7 +1450,18 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
|
||||||
sdd.filter_cb_arg = cb_arg;
|
sdd.filter_cb_arg = cb_arg;
|
||||||
if (debugnvp)
|
if (debugnvp)
|
||||||
sdd.debugnv = *debugnvp;
|
sdd.debugnv = *debugnvp;
|
||||||
if (holdsnaps) {
|
|
||||||
|
/*
|
||||||
|
* Some flags require that we place user holds on the datasets that are
|
||||||
|
* being sent so they don't get destroyed during the send. We can skip
|
||||||
|
* this step if the pool is imported read-only since the datasets cannot
|
||||||
|
* be destroyed.
|
||||||
|
*/
|
||||||
|
if (!flags->dryrun && !zpool_get_prop_int(zfs_get_pool_handle(zhp),
|
||||||
|
ZPOOL_PROP_READONLY, NULL) &&
|
||||||
|
zfs_spa_version(zhp, &spa_version) == 0 &&
|
||||||
|
spa_version >= SPA_VERSION_USERREFS &&
|
||||||
|
(flags->doall || flags->replicate)) {
|
||||||
++holdseq;
|
++holdseq;
|
||||||
(void) snprintf(sdd.holdtag, sizeof (sdd.holdtag),
|
(void) snprintf(sdd.holdtag, sizeof (sdd.holdtag),
|
||||||
".send-%d-%llu", getpid(), (u_longlong_t)holdseq);
|
".send-%d-%llu", getpid(), (u_longlong_t)holdseq);
|
||||||
|
|
Loading…
Reference in New Issue