Illumos #1796, #2871, #2903, #2957
authorChristopher Siden <chris.siden@delphix.com>
Thu, 12 Jul 2012 12:32:45 +0000 (05:32 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Thu, 23 Aug 2012 17:40:02 +0000 (10:40 -0700)
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>
cmd/zfs/zfs_main.c
lib/libzfs/libzfs_config.c
lib/libzfs/libzfs_dataset.c
lib/libzfs/libzfs_sendrecv.c

index d185a31..1cb2ac9 100644 (file)
@@ -1066,7 +1066,7 @@ snapshot_to_nvl_cb(zfs_handle_t *zhp, void *arg)
        int err = 0;
 
        /* Check for clones. */
-       if (!cb->cb_doclones) {
+       if (!cb->cb_doclones && !cb->cb_defer_destroy) {
                cb->cb_target = zhp;
                cb->cb_first = B_TRUE;
                err = zfs_iter_dependents(zhp, B_TRUE,
index f1ddac9..b36dee1 100644 (file)
@@ -302,6 +302,48 @@ zpool_refresh_stats(zpool_handle_t *zhp, boolean_t *missing)
 }
 
 /*
+ * 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.
  */
 int
@@ -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;
            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) {
                        hdl->libzfs_pool_iter--;
                        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;
            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)
                        continue;
 
index f216291..8c463cd 100644 (file)
@@ -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
- * 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
 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;
-       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,
                    dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
                    zhp->zfs_name));
index 0702ba0..c5d963a 100644 (file)
@@ -21,7 +21,7 @@
 
 /*
  * 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>.
  * All rights reserved
  */
@@ -1308,7 +1308,6 @@ zfs_send(zfs_handle_t *zhp, const char *fromsnap, const char *tosnap,
        avl_tree_t *fsavl = NULL;
        static uint64_t holdseq;
        int spa_version;
-       boolean_t holdsnaps = B_FALSE;
        pthread_t tid;
        int pipefd[2];
        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) {
                featureflags |= (DMU_BACKUP_FEATURE_DEDUP |
                    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;
        if (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;
                (void) snprintf(sdd.holdtag, sizeof (sdd.holdtag),
                    ".send-%d-%llu", getpid(), (u_longlong_t)holdseq);