]> git.proxmox.com Git - mirror_zfs-debian.git/commitdiff
Imported Upstream version 0.6.5.6
authorAron Xu <aron@debian.org>
Wed, 23 Mar 2016 23:19:11 +0000 (07:19 +0800)
committerAron Xu <aron@debian.org>
Wed, 23 Mar 2016 23:19:11 +0000 (07:19 +0800)
36 files changed:
META
cmd/zdb/zdb.c
cmd/zpool/zpool_main.c
configure
include/libzfs.h
include/sys/spa_impl.h
include/sys/zvol.h
lib/libefi/rdwr_efi.c
lib/libspl/include/sys/isa_defs.h
lib/libzfs/libzfs.pc
lib/libzfs/libzfs_core.pc
lib/libzfs/libzfs_pool.c
lib/libzfs/libzfs_util.c
lib/libzpool/kernel.c
man/man8/zpool.8
module/avl/zavl.mod.c [new file with mode: 0644]
module/nvpair/znvpair.mod.c [new file with mode: 0644]
module/unicode/zunicode.mod.c [new file with mode: 0644]
module/zcommon/zcommon.mod.c [new file with mode: 0644]
module/zfs/dmu_object.c
module/zfs/dmu_objset.c
module/zfs/dmu_send.c
module/zfs/dmu_traverse.c
module/zfs/dsl_dataset.c
module/zfs/dsl_destroy.c
module/zfs/dsl_dir.c
module/zfs/spa.c
module/zfs/zfs.mod.c [new file with mode: 0644]
module/zfs/zfs_ioctl.c
module/zfs/zpl_inode.c
module/zfs/zvol.c
module/zpios/zpios.mod.c [new file with mode: 0644]
rpm/generic/zfs-kmod.spec.in
rpm/generic/zfs.spec.in
rpm/redhat/zfs.spec.in
scripts/zconfig.sh

diff --git a/META b/META
index ea5d64457a29aeef005a8d37a0805fe9989f385f..8d4c3520893557809d977b9a6d85ee28e546402f 100644 (file)
--- a/META
+++ b/META
@@ -1,7 +1,7 @@
 Meta:         1
 Name:         zfs
 Branch:       1.0
-Version:      0.6.5.5
+Version:      0.6.5.6
 Release:      1
 Release-Tags: relext
 License:      CDDL
index 56f56700fc10058f642df2a818ecb8731e7dd0ed..59a0b1b687e2693459cd1d3d654d64bccf31f507 100644 (file)
@@ -3357,8 +3357,10 @@ zdb_read_block(char *thing, spa_t *spa)
                                continue;
 
                        p = &flagstr[i + 1];
-                       if (bit == ZDB_FLAG_PRINT_BLKPTR)
+                       if (bit == ZDB_FLAG_PRINT_BLKPTR) {
                                blkptr_offset = strtoull(p, &p, 16);
+                               i = p - &flagstr[i + 1];
+                       }
                        if (*p != ':' && *p != '\0') {
                                (void) printf("***Invalid flag arg: '%s'\n", s);
                                free(dup);
index aa9b21dadf0c7b7a75c33bc77c917322717caf20..8f6916acea0085d6bd196d08d7f0a75bb41d96c3 100644 (file)
@@ -207,7 +207,7 @@ static const char *
 get_usage(zpool_help_t idx) {
        switch (idx) {
        case HELP_ADD:
-               return (gettext("\tadd [-fn] [-o property=value] "
+               return (gettext("\tadd [-fgLnP] [-o property=value] "
                    "<pool> <vdev> ...\n"));
        case HELP_ATTACH:
                return (gettext("\tattach [-f] [-o property=value] "
@@ -237,12 +237,12 @@ get_usage(zpool_help_t idx) {
                    "[-R root] [-F [-n]]\n"
                    "\t    <pool | id> [newpool]\n"));
        case HELP_IOSTAT:
-               return (gettext("\tiostat [-v] [-T d|u] [-y] [pool] ... "
+               return (gettext("\tiostat [-gLPvy] [-T d|u] [pool] ... "
                    "[interval [count]]\n"));
        case HELP_LABELCLEAR:
                return (gettext("\tlabelclear [-f] <vdev>\n"));
        case HELP_LIST:
-               return (gettext("\tlist [-Hv] [-o property[,...]] "
+               return (gettext("\tlist [-gHLPv] [-o property[,...]] "
                    "[-T d|u] [pool] ... [interval [count]]\n"));
        case HELP_OFFLINE:
                return (gettext("\toffline [-t] <pool> <device> ...\n"));
@@ -258,8 +258,8 @@ get_usage(zpool_help_t idx) {
        case HELP_SCRUB:
                return (gettext("\tscrub [-s] <pool> ...\n"));
        case HELP_STATUS:
-               return (gettext("\tstatus [-vxD] [-T d|u] [pool] ... [interval "
-                   "[count]]\n"));
+               return (gettext("\tstatus [-gLPvxD] [-T d|u] [pool] ... "
+                   "[interval [count]]\n"));
        case HELP_UPGRADE:
                return (gettext("\tupgrade\n"
                    "\tupgrade -v\n"
@@ -272,7 +272,7 @@ get_usage(zpool_help_t idx) {
        case HELP_SET:
                return (gettext("\tset <property=value> <pool> \n"));
        case HELP_SPLIT:
-               return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
+               return (gettext("\tsplit [-gLnP] [-R altroot] [-o mntopts]\n"
                    "\t    [-o property=value] <pool> <newpool> "
                    "[<device> ...]\n"));
        case HELP_REGUID:
@@ -371,7 +371,7 @@ usage(boolean_t requested)
 
 void
 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
-    boolean_t print_logs)
+    boolean_t print_logs, int name_flags)
 {
        nvlist_t **child;
        uint_t c, children;
@@ -392,9 +392,9 @@ print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
                if ((is_log && !print_logs) || (!is_log && print_logs))
                        continue;
 
-               vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
+               vname = zpool_vdev_name(g_zfs, zhp, child[c], name_flags);
                print_vdev_tree(zhp, vname, child[c], indent + 2,
-                   B_FALSE);
+                   B_FALSE, name_flags);
                free(vname);
        }
 }
@@ -502,12 +502,15 @@ add_prop_list_default(const char *propname, char *propval, nvlist_t **props,
 }
 
 /*
- * zpool add [-fn] [-o property=value] <pool> <vdev> ...
+ * zpool add [-fgLnP] [-o property=value] <pool> <vdev> ...
  *
  *     -f      Force addition of devices, even if they appear in use
+ *     -g      Display guid for individual vdev name.
+ *     -L      Follow links when resolving vdev path name.
  *     -n      Do not add the devices, but display the resulting layout if
  *             they were to be added.
  *     -o      Set property=value.
+ *     -P      Display full path for vdev name.
  *
  * Adds the given vdevs to 'pool'.  As with create, the bulk of this work is
  * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
@@ -518,6 +521,7 @@ zpool_do_add(int argc, char **argv)
 {
        boolean_t force = B_FALSE;
        boolean_t dryrun = B_FALSE;
+       int name_flags = 0;
        int c;
        nvlist_t *nvroot;
        char *poolname;
@@ -528,11 +532,17 @@ zpool_do_add(int argc, char **argv)
        char *propval;
 
        /* check options */
-       while ((c = getopt(argc, argv, "fno:")) != -1) {
+       while ((c = getopt(argc, argv, "fgLno:P")) != -1) {
                switch (c) {
                case 'f':
                        force = B_TRUE;
                        break;
+               case 'g':
+                       name_flags |= VDEV_NAME_GUID;
+                       break;
+               case 'L':
+                       name_flags |= VDEV_NAME_FOLLOW_LINKS;
+                       break;
                case 'n':
                        dryrun = B_TRUE;
                        break;
@@ -549,6 +559,9 @@ zpool_do_add(int argc, char **argv)
                            (add_prop_list(optarg, propval, &props, B_TRUE)))
                                usage(B_FALSE);
                        break;
+               case 'P':
+                       name_flags |= VDEV_NAME_PATH;
+                       break;
                case '?':
                        (void) fprintf(stderr, gettext("invalid option '%c'\n"),
                            optopt);
@@ -606,15 +619,19 @@ zpool_do_add(int argc, char **argv)
                    "configuration:\n"), zpool_get_name(zhp));
 
                /* print original main pool and new tree */
-               print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
-               print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
+               print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE,
+                   name_flags);
+               print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE, name_flags);
 
                /* Do the same for the logs */
                if (num_logs(poolnvroot) > 0) {
-                       print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
-                       print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
+                       print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE,
+                           name_flags);
+                       print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE,
+                           name_flags);
                } else if (num_logs(nvroot) > 0) {
-                       print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
+                       print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE,
+                           name_flags);
                }
 
                /* Do the same for the caches */
@@ -624,7 +641,7 @@ zpool_do_add(int argc, char **argv)
                        (void) printf(gettext("\tcache\n"));
                        for (c = 0; c < l2children; c++) {
                                vname = zpool_vdev_name(g_zfs, NULL,
-                                   l2child[c], B_FALSE);
+                                   l2child[c], name_flags);
                                (void) printf("\t  %s\n", vname);
                                free(vname);
                        }
@@ -635,7 +652,7 @@ zpool_do_add(int argc, char **argv)
                                (void) printf(gettext("\tcache\n"));
                        for (c = 0; c < l2children; c++) {
                                vname = zpool_vdev_name(g_zfs, NULL,
-                                   l2child[c], B_FALSE);
+                                   l2child[c], name_flags);
                                (void) printf("\t  %s\n", vname);
                                free(vname);
                        }
@@ -1082,9 +1099,9 @@ zpool_do_create(int argc, char **argv)
                (void) printf(gettext("would create '%s' with the "
                    "following layout:\n\n"), poolname);
 
-               print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
+               print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE, 0);
                if (num_logs(nvroot) > 0)
-                       print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
+                       print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE, 0);
 
                ret = 0;
        } else {
@@ -1311,13 +1328,15 @@ zpool_do_export(int argc, char **argv)
  * name column.
  */
 static int
-max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
+max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max,
+    int name_flags)
 {
-       char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
+       char *name;
        nvlist_t **child;
        uint_t c, children;
        int ret;
 
+       name = zpool_vdev_name(g_zfs, zhp, nv, name_flags | VDEV_NAME_TYPE_ID);
        if (strlen(name) + depth > max)
                max = strlen(name) + depth;
 
@@ -1327,7 +1346,7 @@ max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
            &child, &children) == 0) {
                for (c = 0; c < children; c++)
                        if ((ret = max_width(zhp, child[c], depth + 2,
-                           max)) > max)
+                           max, name_flags)) > max)
                                max = ret;
        }
 
@@ -1335,7 +1354,7 @@ max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
            &child, &children) == 0) {
                for (c = 0; c < children; c++)
                        if ((ret = max_width(zhp, child[c], depth + 2,
-                           max)) > max)
+                           max, name_flags)) > max)
                                max = ret;
        }
 
@@ -1343,11 +1362,10 @@ max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
            &child, &children) == 0) {
                for (c = 0; c < children; c++)
                        if ((ret = max_width(zhp, child[c], depth + 2,
-                           max)) > max)
+                           max, name_flags)) > max)
                                max = ret;
        }
 
-
        return (max);
 }
 
@@ -1399,9 +1417,9 @@ find_spare(zpool_handle_t *zhp, void *data)
 /*
  * Print out configuration state as requested by status_callback.
  */
-void
+static void
 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
-    int namewidth, int depth, boolean_t isspare)
+    int namewidth, int depth, boolean_t isspare, int name_flags)
 {
        nvlist_t **child;
        uint_t c, children;
@@ -1537,20 +1555,21 @@ print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
                    &ishole);
                if (islog || ishole)
                        continue;
-               vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
+               vname = zpool_vdev_name(g_zfs, zhp, child[c],
+                   name_flags | VDEV_NAME_TYPE_ID);
                print_status_config(zhp, vname, child[c],
-                   namewidth, depth + 2, isspare);
+                   namewidth, depth + 2, isspare, name_flags);
                free(vname);
        }
 }
 
-
 /*
  * Print the configuration of an exported pool.  Iterate over all vdevs in the
  * pool, printing out the name and status for each one.
  */
-void
-print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
+static void
+print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth,
+    int name_flags)
 {
        nvlist_t **child;
        uint_t c, children;
@@ -1615,8 +1634,10 @@ print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
                if (is_log)
                        continue;
 
-               vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
-               print_import_config(vname, child[c], namewidth, depth + 2);
+               vname = zpool_vdev_name(g_zfs, NULL, child[c],
+                   name_flags | VDEV_NAME_TYPE_ID);
+               print_import_config(vname, child[c], namewidth, depth + 2,
+                   name_flags);
                free(vname);
        }
 
@@ -1624,7 +1645,8 @@ print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
            &child, &children) == 0) {
                (void) printf(gettext("\tcache\n"));
                for (c = 0; c < children; c++) {
-                       vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
+                       vname = zpool_vdev_name(g_zfs, NULL, child[c],
+                           name_flags);
                        (void) printf("\t  %s\n", vname);
                        free(vname);
                }
@@ -1634,7 +1656,8 @@ print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
            &child, &children) == 0) {
                (void) printf(gettext("\tspares\n"));
                for (c = 0; c < children; c++) {
-                       vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
+                       vname = zpool_vdev_name(g_zfs, NULL, child[c],
+                           name_flags);
                        (void) printf("\t  %s\n", vname);
                        free(vname);
                }
@@ -1650,7 +1673,8 @@ print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
  * works because only the top level vdev is marked "is_log"
  */
 static void
-print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose)
+print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose,
+    int name_flags)
 {
        uint_t c, children;
        nvlist_t **child;
@@ -1669,12 +1693,14 @@ print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose)
                    &is_log);
                if (!is_log)
                        continue;
-               name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
+               name = zpool_vdev_name(g_zfs, zhp, child[c],
+                   name_flags | VDEV_NAME_TYPE_ID);
                if (verbose)
                        print_status_config(zhp, name, child[c], namewidth,
-                           2, B_FALSE);
+                           2, B_FALSE, name_flags);
                else
-                       print_import_config(name, child[c], namewidth, 2);
+                       print_import_config(name, child[c], namewidth, 2,
+                           name_flags);
                free(name);
        }
 }
@@ -1923,13 +1949,13 @@ show_import(nvlist_t *config)
 
        (void) printf(gettext(" config:\n\n"));
 
-       namewidth = max_width(NULL, nvroot, 0, 0);
+       namewidth = max_width(NULL, nvroot, 0, 0, 0);
        if (namewidth < 10)
                namewidth = 10;
 
-       print_import_config(name, nvroot, namewidth, 0);
+       print_import_config(name, nvroot, namewidth, 0, 0);
        if (num_logs(nvroot) > 0)
-               print_logs(NULL, nvroot, namewidth, B_FALSE);
+               print_logs(NULL, nvroot, namewidth, B_FALSE, 0);
 
        if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
                (void) printf(gettext("\n\tAdditional devices are known to "
@@ -2438,6 +2464,7 @@ error:
 
 typedef struct iostat_cbdata {
        boolean_t cb_verbose;
+       int cb_name_flags;
        int cb_namewidth;
        int cb_iteration;
        zpool_list_t *cb_list;
@@ -2560,7 +2587,8 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
                if (ishole || islog)
                        continue;
 
-               vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
+               vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
+                   cb->cb_name_flags);
                print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
                    newchild[c], cb, depth + 2);
                free(vname);
@@ -2581,7 +2609,7 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
 
                        if (islog) {
                                vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
-                                   B_FALSE);
+                                   cb->cb_name_flags);
                                print_vdev_stats(zhp, vname, oldnv ?
                                    oldchild[c] : NULL, newchild[c],
                                    cb, depth + 2);
@@ -2607,7 +2635,7 @@ print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
                    "-\n", cb->cb_namewidth, "cache");
                for (c = 0; c < children; c++) {
                        vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
-                           B_FALSE);
+                           cb->cb_name_flags);
                        print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
                            newchild[c], cb, depth + 2);
                        free(vname);
@@ -2700,7 +2728,7 @@ get_namewidth(zpool_handle_t *zhp, void *data)
                        cb->cb_namewidth = strlen(zpool_get_name(zhp));
                else
                        cb->cb_namewidth = max_width(zhp, nvroot, 0,
-                           cb->cb_namewidth);
+                           cb->cb_namewidth, cb->cb_name_flags);
        }
 
        /*
@@ -2800,8 +2828,11 @@ get_timestamp_arg(char c)
 }
 
 /*
- * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]]
+ * zpool iostat [-gLPv] [-T d|u] [pool] ... [interval [count]]
  *
+ *     -g      Display guid for individual vdev name.
+ *     -L      Follow links when resolving vdev path name.
+ *     -P      Display full path for vdev name.
  *     -v      Display statistics for individual vdevs
  *     -T      Display a timestamp in date(1) or Unix format
  *
@@ -2821,11 +2852,23 @@ zpool_do_iostat(int argc, char **argv)
        zpool_list_t *list;
        boolean_t verbose = B_FALSE;
        boolean_t omit_since_boot = B_FALSE;
-       iostat_cbdata_t cb;
+       boolean_t guid = B_FALSE;
+       boolean_t follow_links = B_FALSE;
+       boolean_t full_name = B_FALSE;
+       iostat_cbdata_t cb = { 0 };
 
        /* check options */
-       while ((c = getopt(argc, argv, "T:vy")) != -1) {
+       while ((c = getopt(argc, argv, "gLPT:vy")) != -1) {
                switch (c) {
+               case 'g':
+                       guid = B_TRUE;
+                       break;
+               case 'L':
+                       follow_links = B_TRUE;
+                       break;
+               case 'P':
+                       full_name = B_TRUE;
+                       break;
                case 'T':
                        get_timestamp_arg(*optarg);
                        break;
@@ -2870,6 +2913,12 @@ zpool_do_iostat(int argc, char **argv)
         */
        cb.cb_list = list;
        cb.cb_verbose = verbose;
+       if (guid)
+               cb.cb_name_flags |= VDEV_NAME_GUID;
+       if (follow_links)
+               cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
+       if (full_name)
+               cb.cb_name_flags |= VDEV_NAME_PATH;
        cb.cb_iteration = 0;
        cb.cb_namewidth = 0;
 
@@ -2953,6 +3002,7 @@ zpool_do_iostat(int argc, char **argv)
 
 typedef struct list_cbdata {
        boolean_t       cb_verbose;
+       int             cb_name_flags;
        int             cb_namewidth;
        boolean_t       cb_scripted;
        zprop_list_t    *cb_proplist;
@@ -3128,6 +3178,9 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
        uint_t c, children;
        char *vname;
        boolean_t scripted = cb->cb_scripted;
+       uint64_t islog = B_FALSE;
+       boolean_t haslog = B_FALSE;
+       char *dashes = "%-*s      -      -      -         -      -      -\n";
 
        verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
            (uint64_t **)&vs, &c) == 0);
@@ -3178,24 +3231,51 @@ print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
                    ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
                        continue;
 
-               vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
+               if (nvlist_lookup_uint64(child[c],
+                   ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) {
+                       haslog = B_TRUE;
+                       continue;
+               }
+
+               vname = zpool_vdev_name(g_zfs, zhp, child[c],
+                   cb->cb_name_flags);
                print_list_stats(zhp, vname, child[c], cb, depth + 2);
                free(vname);
        }
 
-       /*
-        * Include level 2 ARC devices in iostat output
-        */
+       if (haslog == B_TRUE) {
+               /* LINTED E_SEC_PRINTF_VAR_FMT */
+               (void) printf(dashes, cb->cb_namewidth, "log");
+               for (c = 0; c < children; c++) {
+                       if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
+                           &islog) != 0 || !islog)
+                               continue;
+                       vname = zpool_vdev_name(g_zfs, zhp, child[c],
+                           cb->cb_name_flags);
+                       print_list_stats(zhp, vname, child[c], cb, depth + 2);
+                       free(vname);
+               }
+       }
+
        if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
-           &child, &children) != 0)
-               return;
+           &child, &children) == 0 && children > 0) {
+               /* LINTED E_SEC_PRINTF_VAR_FMT */
+               (void) printf(dashes, cb->cb_namewidth, "cache");
+               for (c = 0; c < children; c++) {
+                       vname = zpool_vdev_name(g_zfs, zhp, child[c],
+                           cb->cb_name_flags);
+                       print_list_stats(zhp, vname, child[c], cb, depth + 2);
+                       free(vname);
+               }
+       }
 
-       if (children > 0) {
-               (void) printf("%-*s      -      -      -      -      -      "
-                   "-\n", cb->cb_namewidth, "cache");
+       if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
+           &children) == 0 && children > 0) {
+               /* LINTED E_SEC_PRINTF_VAR_FMT */
+               (void) printf(dashes, cb->cb_namewidth, "spare");
                for (c = 0; c < children; c++) {
                        vname = zpool_vdev_name(g_zfs, zhp, child[c],
-                           B_FALSE);
+                           cb->cb_name_flags);
                        print_list_stats(zhp, vname, child[c], cb, depth + 2);
                        free(vname);
                }
@@ -3227,13 +3307,16 @@ list_callback(zpool_handle_t *zhp, void *data)
 }
 
 /*
- * zpool list [-H] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
+ * zpool list [-gHLP] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
  *
+ *     -g      Display guid for individual vdev name.
  *     -H      Scripted mode.  Don't display headers, and separate properties
  *             by a single tab.
+ *     -L      Follow links when resolving vdev path name.
  *     -o      List of properties to display.  Defaults to
  *             "name,size,allocated,free,expandsize,fragmentation,capacity,"
  *             "dedupratio,health,altroot"
+ *     -P      Display full path for vdev name.
  *     -T      Display a timestamp in date(1) or Unix format
  *
  * List all pools in the system, whether or not they're healthy.  Output space
@@ -3254,14 +3337,23 @@ zpool_do_list(int argc, char **argv)
        boolean_t first = B_TRUE;
 
        /* check options */
-       while ((c = getopt(argc, argv, ":Ho:T:v")) != -1) {
+       while ((c = getopt(argc, argv, ":gHLo:PT:v")) != -1) {
                switch (c) {
+               case 'g':
+                       cb.cb_name_flags |= VDEV_NAME_GUID;
+                       break;
                case 'H':
                        cb.cb_scripted = B_TRUE;
                        break;
+               case 'L':
+                       cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
+                       break;
                case 'o':
                        props = optarg;
                        break;
+               case 'P':
+                       cb.cb_name_flags |= VDEV_NAME_PATH;
+                       break;
                case 'T':
                        get_timestamp_arg(*optarg);
                        break;
@@ -3517,13 +3609,16 @@ zpool_do_detach(int argc, char **argv)
 }
 
 /*
- * zpool split [-n] [-o prop=val] ...
+ * zpool split [-gLnP] [-o prop=val] ...
  *             [-o mntopt] ...
  *             [-R altroot] <pool> <newpool> [<device> ...]
  *
+ *     -g      Display guid for individual vdev name.
+ *     -L      Follow links when resolving vdev path name.
  *     -n      Do not split the pool, but display the resulting layout if
  *             it were to be split.
  *     -o      Set property=value, or set mount options.
+ *     -P      Display full path for vdev name.
  *     -R      Mount the split-off pool under an alternate root.
  *
  * Splits the named pool and gives it the new pool name.  Devices to be split
@@ -3547,10 +3642,17 @@ zpool_do_split(int argc, char **argv)
 
        flags.dryrun = B_FALSE;
        flags.import = B_FALSE;
+       flags.name_flags = 0;
 
        /* check options */
-       while ((c = getopt(argc, argv, ":R:no:")) != -1) {
+       while ((c = getopt(argc, argv, ":gLR:no:P")) != -1) {
                switch (c) {
+               case 'g':
+                       flags.name_flags |= VDEV_NAME_GUID;
+                       break;
+               case 'L':
+                       flags.name_flags |= VDEV_NAME_FOLLOW_LINKS;
+                       break;
                case 'R':
                        flags.import = B_TRUE;
                        if (add_prop_list(
@@ -3578,6 +3680,9 @@ zpool_do_split(int argc, char **argv)
                                mntopts = optarg;
                        }
                        break;
+               case 'P':
+                       flags.name_flags |= VDEV_NAME_PATH;
+                       break;
                case ':':
                        (void) fprintf(stderr, gettext("missing argument for "
                            "'%c' option\n"), optopt);
@@ -3625,7 +3730,8 @@ zpool_do_split(int argc, char **argv)
                if (flags.dryrun) {
                        (void) printf(gettext("would create '%s' with the "
                            "following layout:\n\n"), newpool);
-                       print_vdev_tree(NULL, newpool, config, 0, B_FALSE);
+                       print_vdev_tree(NULL, newpool, config, 0, B_FALSE,
+                           flags.name_flags);
                }
                nvlist_free(config);
        }
@@ -4031,6 +4137,7 @@ zpool_do_scrub(int argc, char **argv)
 
 typedef struct status_cbdata {
        int             cb_count;
+       int             cb_name_flags;
        boolean_t       cb_allpools;
        boolean_t       cb_verbose;
        boolean_t       cb_explain;
@@ -4187,7 +4294,7 @@ print_error_log(zpool_handle_t *zhp)
 
 static void
 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
-    int namewidth)
+    int namewidth, int name_flags)
 {
        uint_t i;
        char *name;
@@ -4198,16 +4305,16 @@ print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
        (void) printf(gettext("\tspares\n"));
 
        for (i = 0; i < nspares; i++) {
-               name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE);
+               name = zpool_vdev_name(g_zfs, zhp, spares[i], name_flags);
                print_status_config(zhp, name, spares[i],
-                   namewidth, 2, B_TRUE);
+                   namewidth, 2, B_TRUE, name_flags);
                free(name);
        }
 }
 
 static void
 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
-    int namewidth)
+    int namewidth, int name_flags)
 {
        uint_t i;
        char *name;
@@ -4218,9 +4325,9 @@ print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
        (void) printf(gettext("\tcache\n"));
 
        for (i = 0; i < nl2cache; i++) {
-               name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE);
+               name = zpool_vdev_name(g_zfs, zhp, l2cache[i], name_flags);
                print_status_config(zhp, name, l2cache[i],
-                   namewidth, 2, B_FALSE);
+                   namewidth, 2, B_FALSE, name_flags);
                free(name);
        }
 }
@@ -4562,7 +4669,7 @@ status_callback(zpool_handle_t *zhp, void *data)
                    ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
                print_scan_status(ps);
 
-               namewidth = max_width(zhp, nvroot, 0, 0);
+               namewidth = max_width(zhp, nvroot, 0, 0, cbp->cb_name_flags);
                if (namewidth < 10)
                        namewidth = 10;
 
@@ -4570,17 +4677,20 @@ status_callback(zpool_handle_t *zhp, void *data)
                (void) printf(gettext("\t%-*s  %-8s %5s %5s %5s\n"), namewidth,
                    "NAME", "STATE", "READ", "WRITE", "CKSUM");
                print_status_config(zhp, zpool_get_name(zhp), nvroot,
-                   namewidth, 0, B_FALSE);
+                   namewidth, 0, B_FALSE, cbp->cb_name_flags);
 
                if (num_logs(nvroot) > 0)
-                       print_logs(zhp, nvroot, namewidth, B_TRUE);
+                       print_logs(zhp, nvroot, namewidth, B_TRUE,
+                           cbp->cb_name_flags);
                if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
                    &l2cache, &nl2cache) == 0)
-                       print_l2cache(zhp, l2cache, nl2cache, namewidth);
+                       print_l2cache(zhp, l2cache, nl2cache, namewidth,
+                               cbp->cb_name_flags);
 
                if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
                    &spares, &nspares) == 0)
-                       print_spares(zhp, spares, nspares, namewidth);
+                       print_spares(zhp, spares, nspares, namewidth,
+                           cbp->cb_name_flags);
 
                if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
                    &nerr) == 0) {
@@ -4628,8 +4738,11 @@ status_callback(zpool_handle_t *zhp, void *data)
 }
 
 /*
- * zpool status [-vx] [-T d|u] [pool] ... [interval [count]]
+ * zpool status [-gLPvx] [-T d|u] [pool] ... [interval [count]]
  *
+ *     -g      Display guid for individual vdev name.
+ *     -L      Follow links when resolving vdev path name.
+ *     -P      Display full path for vdev name.
  *     -v      Display complete error logs
  *     -x      Display only pools with potential problems
  *     -D      Display dedup status (undocumented)
@@ -4646,8 +4759,17 @@ zpool_do_status(int argc, char **argv)
        status_cbdata_t cb = { 0 };
 
        /* check options */
-       while ((c = getopt(argc, argv, "vxDT:")) != -1) {
+       while ((c = getopt(argc, argv, "gLPvxDT:")) != -1) {
                switch (c) {
+               case 'g':
+                       cb.cb_name_flags |= VDEV_NAME_GUID;
+                       break;
+               case 'L':
+                       cb.cb_name_flags |= VDEV_NAME_FOLLOW_LINKS;
+                       break;
+               case 'P':
+                       cb.cb_name_flags |= VDEV_NAME_PATH;
+                       break;
                case 'v':
                        cb.cb_verbose = B_TRUE;
                        break;
index 28e1c2d05342ad227f351f1fd3f12fa6b99d150d..d56482bd3834d9acd474c42577ade054b45540d7 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.68 for zfs 0.6.5.5.
+# Generated by GNU Autoconf 2.68 for zfs 0.6.5.6.
 #
 #
 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@@ -567,8 +567,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='zfs'
 PACKAGE_TARNAME='zfs'
-PACKAGE_VERSION='0.6.5.5'
-PACKAGE_STRING='zfs 0.6.5.5'
+PACKAGE_VERSION='0.6.5.6'
+PACKAGE_STRING='zfs 0.6.5.6'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -1401,7 +1401,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures zfs 0.6.5.5 to adapt to many kinds of systems.
+\`configure' configures zfs 0.6.5.6 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1472,7 +1472,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of zfs 0.6.5.5:";;
+     short | recursive ) echo "Configuration of zfs 0.6.5.6:";;
    esac
   cat <<\_ACEOF
 
@@ -1607,7 +1607,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-zfs configure 0.6.5.5
+zfs configure 0.6.5.6
 generated by GNU Autoconf 2.68
 
 Copyright (C) 2010 Free Software Foundation, Inc.
@@ -1972,7 +1972,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by zfs $as_me 0.6.5.5, which was
+It was created by zfs $as_me 0.6.5.6, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   $ $0 $@
@@ -3099,7 +3099,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='zfs'
- VERSION='0.6.5.5'
+ VERSION='0.6.5.6'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -32326,7 +32326,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by zfs $as_me 0.6.5.5, which was
+This file was extended by zfs $as_me 0.6.5.6, which was
 generated by GNU Autoconf 2.68.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -32392,7 +32392,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-zfs config.status 0.6.5.5
+zfs config.status 0.6.5.6
 configured by $0, generated by GNU Autoconf 2.68,
   with options \\"\$ac_cs_config\\"
 
index db8ee7167e1789b730efe133d3b19364c861be37..26847e0653e0401e723bea0297025246696d6c88 100644 (file)
@@ -248,6 +248,7 @@ typedef struct splitflags {
 
        /* after splitting, import the pool */
        int import : 1;
+       int name_flags;
 } splitflags_t;
 
 /*
@@ -406,8 +407,15 @@ struct zfs_cmd;
 
 extern const char *zfs_history_event_names[];
 
+typedef enum {
+       VDEV_NAME_PATH          = 1 << 0,
+       VDEV_NAME_GUID          = 1 << 1,
+       VDEV_NAME_FOLLOW_LINKS  = 1 << 2,
+       VDEV_NAME_TYPE_ID       = 1 << 3,
+} vdev_name_t;
+
 extern char *zpool_vdev_name(libzfs_handle_t *, zpool_handle_t *, nvlist_t *,
-    boolean_t verbose);
+    int name_flags);
 extern int zpool_upgrade(zpool_handle_t *, uint64_t);
 extern int zpool_get_history(zpool_handle_t *, nvlist_t **);
 extern int zpool_history_unpack(char *, uint64_t, uint64_t *,
index 0b49c7147b1086c840c06b1bcbfb93bcfd28fed9..5176eb84842cd109480c360622eebfcfeec8fcdd 100644 (file)
@@ -23,6 +23,7 @@
  * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
+ * Copyright (c) 2016 Actifio, Inc. All rights reserved.
  */
 
 #ifndef _SYS_SPA_IMPL_H
@@ -252,6 +253,7 @@ struct spa {
        uint64_t        spa_deadman_synctime;   /* deadman expiration timer */
        uint64_t        spa_errata;             /* errata issues detected */
        spa_stats_t     spa_stats;              /* assorted spa statistics */
+       taskq_t         *spa_zvol_taskq;        /* Taskq for minor managment */
 
        /*
         * spa_refcount & spa_config_lock must be the last elements
index 898e2352156b29ff3f1d4d4805031dd688c85901..c3e386f0b79e2e222c2944be53d895055737993b 100644 (file)
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016 Actifio, Inc. All rights reserved.
  */
 
 #ifndef        _SYS_ZVOL_H
 #define        ZVOL_OBJ                1ULL
 #define        ZVOL_ZAP_OBJ            2ULL
 
-#ifdef _KERNEL
+extern void zvol_create_minors(spa_t *spa, const char *name, boolean_t async);
+extern void zvol_remove_minors(spa_t *spa, const char *name, boolean_t async);
+extern void zvol_rename_minors(spa_t *spa, const char *oldname,
+    const char *newname, boolean_t async);
 
+#ifdef _KERNEL
 extern int zvol_check_volsize(uint64_t volsize, uint64_t blocksize);
 extern int zvol_check_volblocksize(const char *name, uint64_t volblocksize);
 extern int zvol_get_stats(objset_t *os, nvlist_t *nv);
 extern boolean_t zvol_is_zvol(const char *);
 extern void zvol_create_cb(objset_t *os, void *arg, cred_t *cr, dmu_tx_t *tx);
-extern int zvol_create_minor(const char *name);
-extern int zvol_create_minors(const char *name);
-extern int zvol_remove_minor(const char *name);
-extern void zvol_remove_minors(const char *name);
-extern void zvol_rename_minors(const char *oldname, const char *newname);
 extern int zvol_set_volsize(const char *, uint64_t);
 extern int zvol_set_volblocksize(const char *, uint64_t);
-extern int zvol_set_snapdev(const char *, uint64_t);
+extern int zvol_set_snapdev(const char *, zprop_source_t, uint64_t);
 
 extern int zvol_init(void);
 extern void zvol_fini(void);
-
 #endif /* _KERNEL */
 #endif /* _SYS_ZVOL_H */
index 785cfe63b2962bd1b53f34c8fe4f121ccd154a5f..06d4dd66d45233ba1beb48d7d5337af02265871a 100644 (file)
@@ -88,7 +88,7 @@ struct dk_map2  default_vtoc_map[NDKMAP] = {
 #if defined(_SUNOS_VTOC_16)
 
 #if defined(i386) || defined(__amd64) || defined(__arm) || \
-    defined(__powerpc) || defined(__sparc)
+    defined(__powerpc) || defined(__sparc) || defined(__s390__)
        {       V_BOOT,         V_UNMNT },              /* i - 8 */
        {       V_ALTSCTR,      0       },              /* j - 9 */
 
index 60c6a3bf96e906246a8c070cf0c3db39bf4e3c36..61f4cd96a93d0476da4f1a336d8de9a62f9ff309 100644 (file)
@@ -157,7 +157,22 @@ extern "C" {
 #endif
 #endif
 
-#else /* Currently x86_64, i386, arm, powerpc, and sparc are supported */
+/* s390 arch specific defines */
+#elif defined(__s390__)
+#if defined(__s390x__)
+#if !defined(_LP64)
+#define        _LP64
+#endif
+#else
+#if !defined(_ILP32)
+#define        _ILP32
+#endif
+#endif
+
+#define        _BIG_ENDIAN
+#define        _SUNOS_VTOC_16
+
+#else /* Currently x86_64, i386, arm, powerpc, s390, and sparc are supported */
 #error "Unsupported ISA type"
 #endif
 
index ee1c6c6ed9080d675287481f8f634e69f6f55f85..349ba8f48296cc4d8da2ad2ef356acd4d3dd7fcf 100644 (file)
@@ -5,7 +5,7 @@ includedir=${prefix}/include
 
 Name: libzfs
 Description: LibZFS library
-Version: 0.6.5.5
+Version: 0.6.5.6
 URL: http://zfsonlinux.org
 Requires: libzfs_core
 Cflags: -I${includedir}/libzfs -I${includedir}/libspl
index 04fea8e59c1b2333a54e9900281bc40227aab7e6..b7ec4a4a81ad661389071bd47ba78b83138d7e63 100644 (file)
@@ -5,7 +5,7 @@ includedir=${prefix}/include
 
 Name: libzfs_core
 Description: LibZFS core library
-Version: 0.6.5.5
+Version: 0.6.5.6
 URL: http://zfsonlinux.org
 Cflags: -I${includedir}/libzfs -I${includedir}/libspl
 Libs: -L${libdir} -lzfs_core
index a730a94e081a262143aabb67fb4918889e0972db..456015e59eb589496a87ebfe95716b30d31350ee 100644 (file)
@@ -1378,8 +1378,7 @@ zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot)
                                zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                                    "device '%s' contains an EFI label and "
                                    "cannot be used on root pools."),
-                                   zpool_vdev_name(hdl, NULL, spares[s],
-                                   B_FALSE));
+                                   zpool_vdev_name(hdl, NULL, spares[s], 0));
                                return (zfs_error(hdl, EZFS_POOL_NOTSUP, msg));
                        }
                }
@@ -1700,7 +1699,7 @@ print_vdev_tree(libzfs_handle_t *hdl, const char *name, nvlist_t *nv,
                return;
 
        for (c = 0; c < children; c++) {
-               vname = zpool_vdev_name(hdl, NULL, child[c], B_TRUE);
+               vname = zpool_vdev_name(hdl, NULL, child[c], VDEV_NAME_TYPE_ID);
                print_vdev_tree(hdl, vname, child[c], indent + 2);
                free(vname);
        }
@@ -2688,7 +2687,7 @@ zpool_vdev_attach(zpool_handle_t *zhp,
        verify(nvlist_lookup_nvlist(zpool_get_config(zhp, NULL),
            ZPOOL_CONFIG_VDEV_TREE, &config_root) == 0);
 
-       if ((newname = zpool_vdev_name(NULL, NULL, child[0], B_FALSE)) == NULL)
+       if ((newname = zpool_vdev_name(NULL, NULL, child[0], 0)) == NULL)
                return (-1);
 
        /*
@@ -2879,11 +2878,11 @@ find_vdev_entry(zpool_handle_t *zhp, nvlist_t **mchild, uint_t mchildren,
        for (mc = 0; mc < mchildren; mc++) {
                uint_t sc;
                char *mpath = zpool_vdev_name(zhp->zpool_hdl, zhp,
-                   mchild[mc], B_FALSE);
+                   mchild[mc], 0);
 
                for (sc = 0; sc < schildren; sc++) {
                        char *spath = zpool_vdev_name(zhp->zpool_hdl, zhp,
-                           schild[sc], B_FALSE);
+                           schild[sc], 0);
                        boolean_t result = (strcmp(mpath, spath) == 0);
 
                        free(spath);
@@ -3424,21 +3423,34 @@ strip_partition(libzfs_handle_t *hdl, char *path)
  */
 char *
 zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
-    boolean_t verbose)
+    int name_flags)
 {
-       char *path, *devid, *type;
+       char *path, *devid, *type, *env;
        uint64_t value;
        char buf[PATH_BUF_LEN];
        char tmpbuf[PATH_BUF_LEN];
        vdev_stat_t *vs;
        uint_t vsc;
 
-       if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
-           &value) == 0) {
-               verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
-                   &value) == 0);
-               (void) snprintf(buf, sizeof (buf), "%llu",
-                   (u_longlong_t)value);
+       env = getenv("ZPOOL_VDEV_NAME_PATH");
+       if (env && (strtoul(env, NULL, 0) > 0 ||
+           !strncasecmp(env, "YES", 3) || !strncasecmp(env, "ON", 2)))
+               name_flags |= VDEV_NAME_PATH;
+
+       env = getenv("ZPOOL_VDEV_NAME_GUID");
+       if (env && (strtoul(env, NULL, 0) > 0 ||
+           !strncasecmp(env, "YES", 3) || !strncasecmp(env, "ON", 2)))
+               name_flags |= VDEV_NAME_GUID;
+
+       env = getenv("ZPOOL_VDEV_NAME_FOLLOW_LINKS");
+       if (env && (strtoul(env, NULL, 0) > 0 ||
+           !strncasecmp(env, "YES", 3) || !strncasecmp(env, "ON", 2)))
+               name_flags |= VDEV_NAME_FOLLOW_LINKS;
+
+       if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT, &value) == 0 ||
+           name_flags & VDEV_NAME_GUID) {
+               nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &value);
+               (void) snprintf(buf, sizeof (buf), "%llu", (u_longlong_t)value);
                path = buf;
        } else if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
                /*
@@ -3479,11 +3491,21 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
                                devid_str_free(newdevid);
                }
 
+               if (name_flags & VDEV_NAME_FOLLOW_LINKS) {
+                       char *rp = realpath(path, NULL);
+                       if (rp) {
+                               strlcpy(buf, rp, sizeof (buf));
+                               path = buf;
+                               free(rp);
+                       }
+               }
+
                /*
                 * For a block device only use the name.
                 */
                verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
-               if (strcmp(type, VDEV_TYPE_DISK) == 0) {
+               if ((strcmp(type, VDEV_TYPE_DISK) == 0) &&
+                   !(name_flags & VDEV_NAME_PATH)) {
                        path = strrchr(path, '/');
                        path++;
                }
@@ -3491,8 +3513,8 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
                /*
                 * Remove the partition from the path it this is a whole disk.
                 */
-               if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK,
-                   &value) == 0 && value) {
+               if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_WHOLE_DISK, &value)
+                   == 0 && value && !(name_flags & VDEV_NAME_PATH)) {
                        return (strip_partition(hdl, path));
                }
        } else {
@@ -3514,7 +3536,7 @@ zpool_vdev_name(libzfs_handle_t *hdl, zpool_handle_t *zhp, nvlist_t *nv,
                 * We identify each top-level vdev by using a <type-id>
                 * naming convention.
                 */
-               if (verbose) {
+               if (name_flags & VDEV_NAME_TYPE_ID) {
                        uint64_t id;
 
                        verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_ID,
index 678eeadc0414d032453fbb7ff33ab03142d9c6eb..ccace2d207879b5780f2febd3428cd08db304060 100644 (file)
@@ -1024,16 +1024,18 @@ zfs_strcmp_pathname(char *name, char *cmp, int wholedisk)
        int path_len, cmp_len;
        char path_name[MAXPATHLEN];
        char cmp_name[MAXPATHLEN];
-       char *dir;
+       char *dir, *dup;
 
        /* Strip redundant slashes if one exists due to ZPOOL_IMPORT_PATH */
        memset(cmp_name, 0, MAXPATHLEN);
-       dir = strtok(cmp, "/");
+       dup = strdup(cmp);
+       dir = strtok(dup, "/");
        while (dir) {
                strcat(cmp_name, "/");
                strcat(cmp_name, dir);
                dir = strtok(NULL, "/");
        }
+       free(dup);
 
        if (name[0] != '/')
                return (zfs_strcmp_shortname(name, cmp_name, wholedisk));
index a451026999c5657facc6d0ea55a75b8f631ba3e2..f1ce8b34afbad32bf988f54238933adcb326fb0e 100644 (file)
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016 Actifio, Inc. All rights reserved.
  */
 
 #include <assert.h>
@@ -1322,3 +1323,24 @@ spl_fstrans_check(void)
 {
        return (0);
 }
+
+void
+zvol_create_minors(spa_t *spa, const char *name, boolean_t async)
+{
+}
+
+void
+zvol_remove_minor(spa_t *spa, const char *name, boolean_t async)
+{
+}
+
+void
+zvol_remove_minors(spa_t *spa, const char *name, boolean_t async)
+{
+}
+
+void
+zvol_rename_minors(spa_t *spa, const char *oldname, const char *newname,
+    boolean_t async)
+{
+}
index 062b5ae290d07a87eae146e4c144df4ac756f450..bd7d69434b9ee9e69a44c8772f1cd69d17606f24 100644 (file)
@@ -26,7 +26,7 @@ zpool \- configures ZFS storage pools
 
 .LP
 .nf
-\fBzpool add\fR [\fB-fn\fR] [\fB-o\fR \fIproperty=value\fR] \fIpool\fR \fIvdev\fR ...
+\fBzpool add\fR [\fB-fgLnP\fR] [\fB-o\fR \fIproperty=value\fR] \fIpool\fR \fIvdev\fR ...
 .fi
 
 .LP
@@ -94,7 +94,7 @@ zpool \- configures ZFS storage pools
 
 .LP
 .nf
-\fBzpool iostat\fR [\fB-T\fR d | u ] [\fB-v\fR] [\fB-y\fR] [\fIpool\fR] ... [\fIinterval\fR[\fIcount\fR]]
+\fBzpool iostat\fR [\fB-T\fR d | u ] [\fB-gLPvy\fR] [\fIpool\fR] ... [\fIinterval\fR[\fIcount\fR]]
 .fi
 
 .LP
@@ -104,7 +104,7 @@ zpool \- configures ZFS storage pools
 
 .LP
 .nf
-\fBzpool list\fR [\fB-T\fR d | u ] [\fB-Hv\fR] [\fB-o\fR \fIproperty\fR[,...]] [\fIpool\fR] ...
+\fBzpool list\fR [\fB-T\fR d | u ] [\fB-HgLPv\fR] [\fB-o\fR \fIproperty\fR[,...]] [\fIpool\fR] ...
      [\fIinterval\fR[\fIcount\fR]]
 .fi
 
@@ -150,12 +150,12 @@ zpool \- configures ZFS storage pools
 
 .LP
 .nf
-\fBzpool split\fR [\fB-n\fR] [\fB-R\fR \fIaltroot\fR] [\fB-o\fR \fIproperty=value\fR] \fIpool\fR \fInewpool\fR [\fIdevice\fR ...]
+\fBzpool split\fR [\fB-gLnP\fR] [\fB-R\fR \fIaltroot\fR] [\fB-o\fR \fIproperty=value\fR] \fIpool\fR \fInewpool\fR [\fIdevice\fR ...]
 .fi
 
 .LP
 .nf
-\fBzpool status\fR [\fB-xvD\fR] [\fB-T\fR d | u] [\fIpool\fR] ... [\fIinterval\fR [\fIcount\fR]]
+\fBzpool status\fR [\fB-gLPvxD\fR] [\fB-T\fR d | u] [\fIpool\fR] ... [\fIinterval\fR [\fIcount\fR]]
 .fi
 
 .LP
@@ -836,7 +836,7 @@ Displays a help message.
 .ne 2
 .mk
 .na
-\fB\fBzpool add\fR [\fB-fn\fR] [\fB-o\fR \fIproperty=value\fR] \fIpool\fR \fIvdev\fR ...\fR
+\fB\fBzpool add\fR [\fB-fgLnP\fR] [\fB-o\fR \fIproperty=value\fR] \fIpool\fR \fIvdev\fR ...\fR
 .ad
 .sp .6
 .RS 4n
@@ -852,6 +852,28 @@ Adds the specified virtual devices to the given pool. The \fIvdev\fR specificati
 Forces use of \fBvdev\fRs, even if they appear in use or specify a conflicting replication level. Not all devices can be overridden in this manner.
 .RE
 
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-g\fR\fR
+.ad
+.RS 6n
+.rt
+Display vdev GUIDs instead of the normal device names. These GUIDs can be used in place of device names for the zpool detach/offline/remove/replace commands.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-L\fR\fR
+.ad
+.RS 6n
+.rt
+Display real paths for vdevs resolving all symbolic links. This can be used to look up the current block device name regardless of the /dev/disk/ path used to open it.
+.RE
+
 .sp
 .ne 2
 .mk
@@ -863,6 +885,17 @@ Forces use of \fBvdev\fRs, even if they appear in use or specify a conflicting r
 Displays the configuration that would be used without actually adding the \fBvdev\fRs. The actual pool creation can still fail due to insufficient privileges or device sharing.
 .RE
 
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-P\fR\fR
+.ad
+.RS 6n
+.rt
+Display full paths for vdevs instead of only the last component of the path.  This can be used in conjunction with the \fB-L\fR flag.
+.RE
+
 .sp
 .ne 2
 .mk
@@ -1608,7 +1641,7 @@ Allows a pool to import when there is a missing log device.
 .ne 2
 .mk
 .na
-\fB\fBzpool iostat\fR [\fB-T\fR \fBd\fR | \fBu\fR] [\fB-v\fR] [\fB-y\fR] [\fIpool\fR] ... [\fIinterval\fR[\fIcount\fR]]\fR
+\fB\fBzpool iostat\fR [\fB-T\fR \fBd\fR | \fBu\fR] [\fB-gLPvy\fR] [\fIpool\fR] ... [\fIinterval\fR[\fIcount\fR]]\fR
 .ad
 .sp .6
 .RS 4n
@@ -1626,6 +1659,39 @@ Display a time stamp.
 Specify \fBu\fR for a printed representation of the internal representation of time. See \fBtime\fR(2). Specify \fBd\fR for standard date format. See \fBdate\fR(1).
 .RE
 
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-g\fR\fR
+.ad
+.RS 12n
+.rt
+Display vdev GUIDs instead of the normal device names. These GUIDs can be used in place of device names for the zpool detach/offline/remove/replace commands.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-L\fR\fR
+.ad
+.RS 12n
+.rt
+Display real paths for vdevs resolving all symbolic links. This can be used to look up the current block device name regardless of the /dev/disk/ path used to open it.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-P\fR\fR
+.ad
+.RS 12n
+.rt
+Display full paths for vdevs instead of only the last component of the path.  This can be used in conjunction with the \fB-L\fR flag.
+.RE
+
 .sp
 .ne 2
 .mk
@@ -1676,7 +1742,7 @@ Treat exported or foreign devices as inactive.
 .ne 2
 .mk
 .na
-\fB\fBzpool list\fR [\fB-T\fR \fBd\fR | \fBu\fR] [\fB-Hv\fR] [\fB-o\fR \fIprops\fR[,...]] [\fIpool\fR] ... [\fIinterval\fR[\fIcount\fR]]\fR
+\fB\fBzpool list\fR [\fB-T\fR \fBd\fR | \fBu\fR] [\fB-HgLPv\fR] [\fB-o\fR \fIprops\fR[,...]] [\fIpool\fR] ... [\fIinterval\fR[\fIcount\fR]]\fR
 .ad
 .sp .6
 .RS 4n
@@ -1692,6 +1758,39 @@ Lists the given pools along with a health status and space usage. If no \fIpools
 Scripted mode. Do not display headers, and separate fields by a single tab instead of arbitrary space.
 .RE
 
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-g\fR\fR
+.ad
+.RS 12n
+.rt
+Display vdev GUIDs instead of the normal device names. These GUIDs can be used in place of device names for the zpool detach/offline/remove/replace commands.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-L\fR\fR
+.ad
+.RS 12n
+.rt
+Display real paths for vdevs resolving all symbolic links. This can be used to look up the current block device name regardless of the /dev/disk/ path used to open it.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-P\fR\fR
+.ad
+.RS 12n
+.rt
+Display full paths for vdevs instead of only the last component of the path.  This can be used in conjunction with the \fB-L\fR flag.
+.RE
+
 .ne 2
 .mk
 .na
@@ -1886,7 +1985,7 @@ Sets the given property on the specified pool. See the "Properties" section for
 .ne 2
 .mk
 .na
-\fBzpool split\fR [\fB-n\fR] [\fB-R\fR \fIaltroot\fR] [\fB-o\fR \fIproperty=value\fR] \fIpool\fR \fInewpool\fR [\fIdevice\fR ...]
+\fBzpool split\fR [\fB-gLnP\fR] [\fB-R\fR \fIaltroot\fR] [\fB-o\fR \fIproperty=value\fR] \fIpool\fR \fInewpool\fR [\fIdevice\fR ...]
 .ad
 .sp .6
 .RS 4n
@@ -1894,6 +1993,28 @@ Split devices off \fIpool\fR creating \fInewpool\fR. All \fBvdev\fRs in \fIpool\
 
 The optional \fIdevice\fR specification causes the specified device(s) to be included in the new pool and, should any devices remain unspecified, the last device in each mirror is used as would be by default.
 
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-g\fR\fR
+.ad
+.RS 6n
+.rt
+Display vdev GUIDs instead of the normal device names. These GUIDs can be used in place of device names for the zpool detach/offline/remove/replace commands.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-L\fR\fR
+.ad
+.RS 6n
+.rt
+Display real paths for vdevs resolving all symbolic links. This can be used to look up the current block device name regardless of the /dev/disk/ path used to open it.
+.RE
+
 .sp
 .ne 2
 .mk
@@ -1905,6 +2026,17 @@ The optional \fIdevice\fR specification causes the specified device(s) to be inc
 Do dry run, do not actually perform the split. Print out the expected configuration of \fInewpool\fR.
 .RE
 
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-P\fR\fR
+.ad
+.RS 6n
+.rt
+Display full paths for vdevs instead of only the last component of the path.  This can be used in conjunction with the \fB-L\fR flag.
+.RE
+
 .sp
 .ne 2
 .mk
@@ -1933,22 +2065,45 @@ Sets the specified property for \fInewpool\fR. See the “Properties” section
 .ne 2
 .mk
 .na
-\fBzpool status\fR [\fB-xvD\fR] [\fB-T\fR d | u] [\fIpool\fR] ... [\fIinterval\fR [\fIcount\fR]]
+\fBzpool status\fR [\fB-gLPvxD\fR] [\fB-T\fR d | u] [\fIpool\fR] ... [\fIinterval\fR [\fIcount\fR]]
 .ad
 .sp .6
 .RS 4n
 Displays the detailed health status for the given pools. If no \fIpool\fR is specified, then the status of each pool in the system is displayed. For more information on pool and device health, see the "Device Failure and Recovery" section.
 .sp
 If a scrub or resilver is in progress, this command reports the percentage done and the estimated time to completion. Both of these are only approximate, because the amount of data in the pool and the other workloads on the system can change.
+
 .sp
 .ne 2
 .mk
 .na
-\fB\fB-x\fR\fR
+\fB\fB-g\fR\fR
 .ad
 .RS 12n
-.rt  
-Only display status for pools that are exhibiting errors or are otherwise unavailable. Warnings about pools not using the latest on-disk format will not be included.
+.rt
+Display vdev GUIDs instead of the normal device names. These GUIDs can be used innplace of device names for the zpool detach/offline/remove/replace commands.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-L\fR\fR
+.ad
+.RS 12n
+.rt
+Display real paths for vdevs resolving all symbolic links. This can be used to look up the current block device name regardless of the /dev/disk/ path used to open it.
+.RE
+
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-P\fR\fR
+.ad
+.RS 12n
+.rt
+Display full paths for vdevs instead of only the last component of the path.  This can be used in conjunction with the \fB-L\fR flag.
 .RE
 
 .sp
@@ -1962,6 +2117,17 @@ Only display status for pools that are exhibiting errors or are otherwise unavai
 Displays verbose data error information, printing out a complete list of all data errors since the last complete pool scrub.
 .RE
 
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-x\fR\fR
+.ad
+.RS 12n
+.rt
+Only display status for pools that are exhibiting errors or are otherwise unavailable. Warnings about pools not using the latest on-disk format will not be included.
+.RE
+
 .sp
 .ne 2
 .mk
@@ -2401,6 +2567,17 @@ Cause \fBzpool\fR to dump core on exit for the purposes of running \fB::findleak
 .B "ZPOOL_IMPORT_PATH"
 The search path for devices or files to use with the pool. This is a colon-separated list of directories in which \fBzpool\fR looks for device nodes and files.
 Similar to the \fB-d\fR option in \fIzpool import\fR.
+.TP
+.B "ZPOOL_VDEV_NAME_GUID"
+Cause \fBzpool\fR subcommands to output vdev guids by default.  This behavior
+is identical to the \fBzpool status -g\fR command line option.
+.TP
+.B "ZPOOL_VDEV_NAME_FOLLOW_LINKS"
+Cause \fBzpool\fR subcommands to follow links for vdev names by default.  This behavior is identical to the \fBzpool status -L\fR command line option.
+.TP
+.B "ZPOOL_VDEV_NAME_PATH"
+Cause \fBzpool\fR subcommands to output full vdev path names by default.  This
+behavior is identical to the \fBzpool status -p\fR command line option.
 
 .SH SEE ALSO
 .sp
diff --git a/module/avl/zavl.mod.c b/module/avl/zavl.mod.c
new file mode 100644 (file)
index 0000000..062c559
--- /dev/null
@@ -0,0 +1,32 @@
+#include <linux/module.h>
+#include <linux/vermagic.h>
+#include <linux/compiler.h>
+
+MODULE_INFO(vermagic, VERMAGIC_STRING);
+
+struct module __this_module
+__attribute__((section(".gnu.linkonce.this_module"))) = {
+ .name = KBUILD_MODNAME,
+ .init = init_module,
+#ifdef CONFIG_MODULE_UNLOAD
+ .exit = cleanup_module,
+#endif
+ .arch = MODULE_ARCH_INIT,
+};
+
+static const struct modversion_info ____versions[]
+__used
+__attribute__((section("__versions"))) = {
+       { 0x51198477, "module_layout" },
+       { 0xbc32eee7, "spl_panic" },
+       { 0xe52592a, "panic" },
+       { 0xb4390f9a, "mcount" },
+};
+
+static const char __module_depends[]
+__used
+__attribute__((section(".modinfo"))) =
+"depends=spl";
+
+
+MODULE_INFO(srcversion, "C188A8AF7758C6D5506AE88");
diff --git a/module/nvpair/znvpair.mod.c b/module/nvpair/znvpair.mod.c
new file mode 100644 (file)
index 0000000..9c37d77
--- /dev/null
@@ -0,0 +1,42 @@
+#include <linux/module.h>
+#include <linux/vermagic.h>
+#include <linux/compiler.h>
+
+MODULE_INFO(vermagic, VERMAGIC_STRING);
+
+struct module __this_module
+__attribute__((section(".gnu.linkonce.this_module"))) = {
+ .name = KBUILD_MODNAME,
+ .init = init_module,
+#ifdef CONFIG_MODULE_UNLOAD
+ .exit = cleanup_module,
+#endif
+ .arch = MODULE_ARCH_INIT,
+};
+
+static const struct modversion_info ____versions[]
+__used
+__attribute__((section("__versions"))) = {
+       { 0x51198477, "module_layout" },
+       { 0x349cba85, "strchr" },
+       { 0x25ec1b28, "strlen" },
+       { 0xab140103, "spl_kmem_alloc" },
+       { 0xbc32eee7, "spl_panic" },
+       { 0xe2d5255a, "strcmp" },
+       { 0xde0bdcff, "memset" },
+       { 0xb4390f9a, "mcount" },
+       { 0x85abc85f, "strncmp" },
+       { 0xdae80439, "spl_vmem_alloc" },
+       { 0x82fe53e1, "ddi_strtol" },
+       { 0xddd4a3d3, "xdrmem_create" },
+       { 0xa3a5be95, "memmove" },
+       { 0x80c3f220, "spl_kmem_free" },
+};
+
+static const char __module_depends[]
+__used
+__attribute__((section(".modinfo"))) =
+"depends=spl";
+
+
+MODULE_INFO(srcversion, "3BD67F56FE7BC46673DD6A6");
diff --git a/module/unicode/zunicode.mod.c b/module/unicode/zunicode.mod.c
new file mode 100644 (file)
index 0000000..88cda5e
--- /dev/null
@@ -0,0 +1,34 @@
+#include <linux/module.h>
+#include <linux/vermagic.h>
+#include <linux/compiler.h>
+
+MODULE_INFO(vermagic, VERMAGIC_STRING);
+
+struct module __this_module
+__attribute__((section(".gnu.linkonce.this_module"))) = {
+ .name = KBUILD_MODNAME,
+ .init = init_module,
+#ifdef CONFIG_MODULE_UNLOAD
+ .exit = cleanup_module,
+#endif
+ .arch = MODULE_ARCH_INIT,
+};
+
+static const struct modversion_info ____versions[]
+__used
+__attribute__((section("__versions"))) = {
+       { 0x51198477, "module_layout" },
+       { 0x25ec1b28, "strlen" },
+       { 0xe2d5255a, "strcmp" },
+       { 0xb4390f9a, "mcount" },
+       { 0x85abc85f, "strncmp" },
+       { 0xf0fdf6cb, "__stack_chk_fail" },
+};
+
+static const char __module_depends[]
+__used
+__attribute__((section(".modinfo"))) =
+"depends=";
+
+
+MODULE_INFO(srcversion, "5DC8CE3A830A36341CDAF7F");
diff --git a/module/zcommon/zcommon.mod.c b/module/zcommon/zcommon.mod.c
new file mode 100644 (file)
index 0000000..465d241
--- /dev/null
@@ -0,0 +1,54 @@
+#include <linux/module.h>
+#include <linux/vermagic.h>
+#include <linux/compiler.h>
+
+MODULE_INFO(vermagic, VERMAGIC_STRING);
+
+struct module __this_module
+__attribute__((section(".gnu.linkonce.this_module"))) = {
+ .name = KBUILD_MODNAME,
+ .init = init_module,
+#ifdef CONFIG_MODULE_UNLOAD
+ .exit = cleanup_module,
+#endif
+ .arch = MODULE_ARCH_INIT,
+};
+
+static const struct modversion_info ____versions[]
+__used
+__attribute__((section("__versions"))) = {
+       { 0x51198477, "module_layout" },
+       { 0x4c4fef19, "kernel_stack" },
+       { 0x25ec1b28, "strlen" },
+       { 0xab140103, "spl_kmem_alloc" },
+       { 0x167e7f9d, "__get_user_1" },
+       { 0xbc32eee7, "spl_panic" },
+       { 0xe2d5255a, "strcmp" },
+       { 0x4f8b5ddb, "_copy_to_user" },
+       { 0xee8843fa, "nvpair_value_uint64" },
+       { 0x11089ac7, "_ctype" },
+       { 0xa1c76e0a, "_cond_resched" },
+       { 0xb4390f9a, "mcount" },
+       { 0x85abc85f, "strncmp" },
+       { 0x9ca95a0e, "sort" },
+       { 0xd42a96fa, "nvpair_name" },
+       { 0x1bfac311, "nvlist_lookup_nvlist" },
+       { 0x5d6e0bba, "nvlist_lookup_uint64" },
+       { 0xd0920999, "nvpair_value_uint32" },
+       { 0x29c88b11, "nvlist_next_nvpair" },
+       { 0x82027a4c, "cmn_err" },
+       { 0x50720c5f, "snprintf" },
+       { 0xec1cce40, "nvlist_lookup_nvlist_array" },
+       { 0xa3a5be95, "memmove" },
+       { 0x80c3f220, "spl_kmem_free" },
+       { 0x4f6b400b, "_copy_from_user" },
+       { 0xa66a6969, "nvpair_value_nvlist" },
+};
+
+static const char __module_depends[]
+__used
+__attribute__((section(".modinfo"))) =
+"depends=spl,znvpair";
+
+
+MODULE_INFO(srcversion, "D94B05FC2B3769899B59647");
index c0e8d7b7fed3aac172316f94993dfd666d76ac4f..177162f9365d5f60d33c4ac5a227eb0e825fdb66 100644 (file)
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2013, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2013, 2015 by Delphix. All rights reserved.
  * Copyright 2014 HybridCluster. All rights reserved.
  */
 
@@ -50,6 +50,12 @@ dmu_object_alloc(objset_t *os, dmu_object_type_t ot, int blocksize,
                 * reasonably sparse (at most 1/4 full).  Look from the
                 * beginning once, but after that keep looking from here.
                 * If we can't find one, just keep going from here.
+                *
+                * Note that dmu_traverse depends on the behavior that we use
+                * multiple blocks of the dnode object before going back to
+                * reuse objects.  Any change to this algorithm should preserve
+                * that property or find another solution to the issues
+                * described in traverse_visitbp.
                 */
                if (P2PHASE(object, L2_dnode_count) == 0) {
                        uint64_t offset = restarted ? object << DNODE_SHIFT : 0;
index 779b3bb789aad6a3476279f6778895a01f0e3782..f2d492ebf0c3e702b9bf3bc6d7cd27d25d066d7e 100644 (file)
@@ -26,6 +26,7 @@
  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
  * Copyright (c) 2015 Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2015, STRATO AG, Inc. All rights reserved.
+ * Copyright (c) 2016 Actifio, Inc. All rights reserved.
  */
 
 /* Portions Copyright 2010 Robert Milkowski */
@@ -900,6 +901,8 @@ dmu_objset_create_sync(void *arg, dmu_tx_t *tx)
        }
 
        spa_history_log_internal_ds(ds, "create", tx, "");
+       zvol_create_minors(dp->dp_spa, doca->doca_name, B_TRUE);
+
        dsl_dataset_rele(ds, FTAG);
        dsl_dir_rele(pdd, FTAG);
 }
@@ -993,6 +996,7 @@ dmu_objset_clone_sync(void *arg, dmu_tx_t *tx)
        dsl_dataset_name(origin, namebuf);
        spa_history_log_internal_ds(ds, "clone", tx,
            "origin=%s (%llu)", namebuf, origin->ds_object);
+       zvol_create_minors(dp->dp_spa, doca->doca_clone, B_TRUE);
        dsl_dataset_rele(ds, FTAG);
        dsl_dataset_rele(origin, FTAG);
        dsl_dir_rele(pdd, FTAG);
index b2d844eb42561523037f47451ff2a4a50db20c38..6a349c6600d123c41f4b82b89abbc47b20978da4 100644 (file)
@@ -24,6 +24,7 @@
  * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
  * Copyright (c) 2014, Joyent, Inc. All rights reserved.
  * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2016 Actifio, Inc. All rights reserved.
  */
 
 #include <sys/dmu.h>
@@ -53,6 +54,7 @@
 #include <sys/blkptr.h>
 #include <sys/dsl_bookmark.h>
 #include <sys/zfeature.h>
+#include <sys/zvol.h>
 
 /* Set this tunable to TRUE to replace corrupt data with 0x2f5baddb10c */
 int zfs_send_corrupt_data = B_FALSE;
@@ -2162,6 +2164,7 @@ dmu_recv_end_sync(void *arg, dmu_tx_t *tx)
                dsl_dataset_phys(ds)->ds_flags &= ~DS_FLAG_INCONSISTENT;
        }
        drc->drc_newsnapobj = dsl_dataset_phys(drc->drc_ds)->ds_prev_snap_obj;
+       zvol_create_minors(dp->dp_spa, drc->drc_tofs, B_TRUE);
        /*
         * Release the hold from dmu_recv_begin.  This must be done before
         * we return to open context, so that when we free the dataset's dnode,
index 12d099bfd414fb546f4c0364dc637d8724168ffe..cdb29b622182ce16803931df782303678703ef06 100644 (file)
@@ -20,7 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
+ * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
  */
 
 #include <sys/zfs_context.h>
@@ -61,6 +61,7 @@ typedef struct traverse_data {
        uint64_t td_hole_birth_enabled_txg;
        blkptr_cb_t *td_func;
        void *td_arg;
+       boolean_t td_realloc_possible;
 } traverse_data_t;
 
 static int traverse_dnode(traverse_data_t *td, const dnode_phys_t *dnp,
@@ -228,18 +229,30 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
 
        if (bp->blk_birth == 0) {
                /*
-                * Since this block has a birth time of 0 it must be a
-                * hole created before the SPA_FEATURE_HOLE_BIRTH
-                * feature was enabled.  If SPA_FEATURE_HOLE_BIRTH
-                * was enabled before the min_txg for this traveral we
-                * know the hole must have been created before the
-                * min_txg for this traveral, so we can skip it. If
-                * SPA_FEATURE_HOLE_BIRTH was enabled after the min_txg
-                * for this traveral we cannot tell if the hole was
-                * created before or after the min_txg for this
-                * traversal, so we cannot skip it.
+                * Since this block has a birth time of 0 it must be one of
+                * two things: a hole created before the
+                * SPA_FEATURE_HOLE_BIRTH feature was enabled, or a hole
+                * which has always been a hole in an object.
+                *
+                * If a file is written sparsely, then the unwritten parts of
+                * the file were "always holes" -- that is, they have been
+                * holes since this object was allocated.  However, we (and
+                * our callers) can not necessarily tell when an object was
+                * allocated.  Therefore, if it's possible that this object
+                * was freed and then its object number reused, we need to
+                * visit all the holes with birth==0.
+                *
+                * If it isn't possible that the object number was reused,
+                * then if SPA_FEATURE_HOLE_BIRTH was enabled before we wrote
+                * all the blocks we will visit as part of this traversal,
+                * then this hole must have always existed, so we can skip
+                * it.  We visit blocks born after (exclusive) td_min_txg.
+                *
+                * Note that the meta-dnode cannot be reallocated.
                 */
-               if (td->td_hole_birth_enabled_txg < td->td_min_txg)
+               if ((!td->td_realloc_possible ||
+                       zb->zb_object == DMU_META_DNODE_OBJECT) &&
+                       td->td_hole_birth_enabled_txg <= td->td_min_txg)
                        return (0);
        } else if (bp->blk_birth <= td->td_min_txg) {
                return (0);
@@ -347,6 +360,15 @@ traverse_visitbp(traverse_data_t *td, const dnode_phys_t *dnp,
 
                prefetch_dnode_metadata(td, mdnp, zb->zb_objset,
                    DMU_META_DNODE_OBJECT);
+               /*
+                * See the block comment above for the goal of this variable.
+                * If the maxblkid of the meta-dnode is 0, then we know that
+                * we've never had more than DNODES_PER_BLOCK objects in the
+                * dataset, which means we can't have reused any object ids.
+                */
+               if (osp->os_meta_dnode.dn_maxblkid == 0)
+                       td->td_realloc_possible = B_FALSE;
+
                if (arc_buf_size(buf) >= sizeof (objset_phys_t)) {
                        prefetch_dnode_metadata(td, gdnp, zb->zb_objset,
                            DMU_GROUPUSED_OBJECT);
@@ -530,12 +552,13 @@ traverse_impl(spa_t *spa, dsl_dataset_t *ds, uint64_t objset, blkptr_t *rootbp,
        td->td_pfd = pd;
        td->td_flags = flags;
        td->td_paused = B_FALSE;
+       td->td_realloc_possible = (txg_start == 0 ? B_FALSE : B_TRUE);
 
        if (spa_feature_is_active(spa, SPA_FEATURE_HOLE_BIRTH)) {
                VERIFY(spa_feature_enabled_txg(spa,
                    SPA_FEATURE_HOLE_BIRTH, &td->td_hole_birth_enabled_txg));
        } else {
-               td->td_hole_birth_enabled_txg = 0;
+               td->td_hole_birth_enabled_txg = UINT64_MAX;
        }
 
        pd->pd_flags = flags;
index 2168f28941ed826bb10ce29eadac63b3d6d5578c..a06388566e4f93f6039d810c4ef4c3f1a5831eb7 100644 (file)
@@ -24,6 +24,7 @@
  * Copyright (c) 2014, Joyent, Inc. All rights reserved.
  * Copyright (c) 2014 RackTop Systems.
  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
+ * Copyright (c) 2016 Actifio, Inc. All rights reserved.
  */
 
 #include <sys/dmu_objset.h>
@@ -1376,6 +1377,7 @@ dsl_dataset_snapshot_sync(void *arg, dmu_tx_t *tx)
                        dsl_props_set_sync_impl(ds->ds_prev,
                            ZPROP_SRC_LOCAL, ddsa->ddsa_props, tx);
                }
+               zvol_create_minors(dp->dp_spa, nvpair_name(pair), B_TRUE);
                dsl_dataset_rele(ds, FTAG);
        }
 }
@@ -1450,16 +1452,6 @@ dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
                fnvlist_free(suspended);
        }
 
-#ifdef _KERNEL
-       if (error == 0) {
-               for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
-                   pair = nvlist_next_nvpair(snaps, pair)) {
-                       char *snapname = nvpair_name(pair);
-                       zvol_create_minors(snapname);
-               }
-       }
-#endif
-
        return (error);
 }
 
@@ -1870,6 +1862,8 @@ dsl_dataset_rename_snapshot_sync_impl(dsl_pool_t *dp,
        VERIFY0(zap_add(dp->dp_meta_objset,
            dsl_dataset_phys(hds)->ds_snapnames_zapobj,
            ds->ds_snapname, 8, 1, &ds->ds_object, tx));
+       zvol_rename_minors(dp->dp_spa, ddrsa->ddrsa_oldsnapname,
+           ddrsa->ddrsa_newsnapname, B_TRUE);
 
        dsl_dataset_rele(ds, FTAG);
        return (0);
@@ -1898,11 +1892,6 @@ int
 dsl_dataset_rename_snapshot(const char *fsname,
     const char *oldsnapname, const char *newsnapname, boolean_t recursive)
 {
-#ifdef _KERNEL
-       char *oldname, *newname;
-#endif
-       int error;
-
        dsl_dataset_rename_snapshot_arg_t ddrsa;
 
        ddrsa.ddrsa_fsname = fsname;
@@ -1910,22 +1899,9 @@ dsl_dataset_rename_snapshot(const char *fsname,
        ddrsa.ddrsa_newsnapname = newsnapname;
        ddrsa.ddrsa_recursive = recursive;
 
-       error = dsl_sync_task(fsname, dsl_dataset_rename_snapshot_check,
+       return (dsl_sync_task(fsname, dsl_dataset_rename_snapshot_check,
            dsl_dataset_rename_snapshot_sync, &ddrsa,
-           1, ZFS_SPACE_CHECK_RESERVED);
-
-       if (error)
-           return (SET_ERROR(error));
-
-#ifdef _KERNEL
-       oldname = kmem_asprintf("%s@%s", fsname, oldsnapname);
-       newname = kmem_asprintf("%s@%s", fsname, newsnapname);
-       zvol_rename_minors(oldname, newname);
-       strfree(newname);
-       strfree(oldname);
-#endif
-
-       return (0);
+           1, ZFS_SPACE_CHECK_RESERVED));
 }
 
 /*
index 0e2238f99e5176862b74e0b5ff5347f7c0cd7c06..34d076e9f2ae2859493a062f444119eb677f22d9 100644 (file)
@@ -23,6 +23,7 @@
  * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
  * Copyright (c) 2013 Steven Hartland. All rights reserved.
  * Copyright (c) 2013 by Joyent, Inc. All rights reserved.
+ * Copyright (c) 2016 Actifio, Inc. All rights reserved.
  */
 
 #include <sys/zfs_context.h>
@@ -40,6 +41,7 @@
 #include <sys/zfs_ioctl.h>
 #include <sys/dsl_deleg.h>
 #include <sys/dmu_impl.h>
+#include <sys/zvol.h>
 
 typedef struct dmu_snapshots_destroy_arg {
        nvlist_t *dsda_snaps;
@@ -243,9 +245,6 @@ dsl_dataset_remove_clones_key(dsl_dataset_t *ds, uint64_t mintxg, dmu_tx_t *tx)
 void
 dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx)
 {
-#ifdef ZFS_DEBUG
-       int err;
-#endif
        int after_branch_point = FALSE;
        dsl_pool_t *dp = ds->ds_dir->dd_pool;
        objset_t *mos = dp->dp_meta_objset;
@@ -438,6 +437,7 @@ dsl_destroy_snapshot_sync_impl(dsl_dataset_t *ds, boolean_t defer, dmu_tx_t *tx)
 #ifdef ZFS_DEBUG
        {
                uint64_t val;
+               int err;
 
                err = dsl_dataset_snap_lookup(ds_head,
                    ds->ds_snapname, &val);
@@ -487,6 +487,7 @@ dsl_destroy_snapshot_sync(void *arg, dmu_tx_t *tx)
                VERIFY0(dsl_dataset_hold(dp, nvpair_name(pair), FTAG, &ds));
 
                dsl_destroy_snapshot_sync_impl(ds, dsda->dsda_defer, tx);
+               zvol_remove_minors(dp->dp_spa, nvpair_name(pair), B_TRUE);
                dsl_dataset_rele(ds, FTAG);
        }
 }
@@ -881,6 +882,7 @@ dsl_destroy_head_sync(void *arg, dmu_tx_t *tx)
 
        VERIFY0(dsl_dataset_hold(dp, ddha->ddha_name, FTAG, &ds));
        dsl_destroy_head_sync_impl(ds, tx);
+       zvol_remove_minors(dp->dp_spa, ddha->ddha_name, B_TRUE);
        dsl_dataset_rele(ds, FTAG);
 }
 
index ba6c24486463cb3819b1678d5b33738de3375875..762e2e5ff23043c48dbc244b6f8421a3a89e55d5 100644 (file)
@@ -24,6 +24,7 @@
  * Copyright (c) 2013 Martin Matuska. All rights reserved.
  * Copyright (c) 2014 Joyent, Inc. All rights reserved.
  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
+ * Copyright (c) 2016 Actifio, Inc. All rights reserved.
  */
 
 #include <sys/dmu.h>
@@ -1913,9 +1914,8 @@ dsl_dir_rename_sync(void *arg, dmu_tx_t *tx)
        VERIFY0(zap_add(mos, dsl_dir_phys(newparent)->dd_child_dir_zapobj,
            dd->dd_myname, 8, 1, &dd->dd_object, tx));
 
-#ifdef _KERNEL
-       zvol_rename_minors(ddra->ddra_oldname, ddra->ddra_newname);
-#endif
+       zvol_rename_minors(dp->dp_spa, ddra->ddra_oldname,
+           ddra->ddra_newname, B_TRUE);
 
        dsl_prop_notify_all(dd);
 
index b4831a724c36554deb249c32391063616621d099..4468cdf88a9960715acd79daa3369f3cb00211f7 100644 (file)
@@ -24,6 +24,7 @@
  * Copyright (c) 2013 by Delphix. All rights reserved.
  * Copyright (c) 2013, 2014, Nexenta Systems, Inc.  All rights reserved.
  * Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
+ * Copyright (c) 2016 Actifio, Inc. All rights reserved.
  */
 
 /*
@@ -1131,6 +1132,24 @@ spa_activate(spa_t *spa, int mode)
        avl_create(&spa->spa_errlist_last,
            spa_error_entry_compare, sizeof (spa_error_entry_t),
            offsetof(spa_error_entry_t, se_avl));
+
+       /*
+        * This taskq is used to perform zvol-minor-related tasks
+        * asynchronously. This has several advantages, including easy
+        * resolution of various deadlocks (zfsonlinux bug #3681).
+        *
+        * The taskq must be single threaded to ensure tasks are always
+        * processed in the order in which they were dispatched.
+        *
+        * A taskq per pool allows one to keep the pools independent.
+        * This way if one pool is suspended, it will not impact another.
+        *
+        * The preferred location to dispatch a zvol minor task is a sync
+        * task. In this context, there is easy access to the spa_t and minimal
+        * error handling is required because the sync task must succeed.
+        */
+       spa->spa_zvol_taskq = taskq_create("z_zvol", 1, defclsyspri,
+           1, INT_MAX, 0);
 }
 
 /*
@@ -1149,6 +1168,11 @@ spa_deactivate(spa_t *spa)
 
        spa_evicting_os_wait(spa);
 
+       if (spa->spa_zvol_taskq) {
+               taskq_destroy(spa->spa_zvol_taskq);
+               spa->spa_zvol_taskq = NULL;
+       }
+
        txg_list_destroy(&spa->spa_vdev_txg_list);
 
        list_destroy(&spa->spa_config_dirty_list);
@@ -3083,10 +3107,8 @@ spa_open_common(const char *pool, spa_t **spapp, void *tag, nvlist_t *nvpolicy,
                mutex_exit(&spa_namespace_lock);
        }
 
-#ifdef _KERNEL
        if (firstopen)
-               zvol_create_minors(spa->spa_name);
-#endif
+               zvol_create_minors(spa, spa_name(spa), B_TRUE);
 
        *spapp = spa;
 
@@ -4206,10 +4228,7 @@ spa_import(char *pool, nvlist_t *config, nvlist_t *props, uint64_t flags)
 
        mutex_exit(&spa_namespace_lock);
        spa_history_log_version(spa, "import");
-
-#ifdef _KERNEL
-       zvol_create_minors(pool);
-#endif
+       zvol_create_minors(spa, pool, B_TRUE);
 
        return (0);
 }
@@ -4344,6 +4363,10 @@ spa_export_common(char *pool, int new_state, nvlist_t **oldconfig,
        spa_open_ref(spa, FTAG);
        mutex_exit(&spa_namespace_lock);
        spa_async_suspend(spa);
+       if (spa->spa_zvol_taskq) {
+               zvol_remove_minors(spa, spa_name(spa), B_TRUE);
+               taskq_wait(spa->spa_zvol_taskq);
+       }
        mutex_enter(&spa_namespace_lock);
        spa_close(spa, FTAG);
 
diff --git a/module/zfs/zfs.mod.c b/module/zfs/zfs.mod.c
new file mode 100644 (file)
index 0000000..9e0b227
--- /dev/null
@@ -0,0 +1,474 @@
+#include <linux/module.h>
+#include <linux/vermagic.h>
+#include <linux/compiler.h>
+
+MODULE_INFO(vermagic, VERMAGIC_STRING);
+
+struct module __this_module
+__attribute__((section(".gnu.linkonce.this_module"))) = {
+ .name = KBUILD_MODNAME,
+ .init = init_module,
+#ifdef CONFIG_MODULE_UNLOAD
+ .exit = cleanup_module,
+#endif
+ .arch = MODULE_ARCH_INIT,
+};
+
+static const struct modversion_info ____versions[]
+__used
+__attribute__((section("__versions"))) = {
+       { 0x51198477, "module_layout" },
+       { 0xdd4acab1, "vn_fsync" },
+       { 0x9937746a, "d_path" },
+       { 0x13be9977, "nvlist_add_boolean_array" },
+       { 0x9a1dfd65, "strpbrk" },
+       { 0xb7d1325e, "nvlist_add_int32" },
+       { 0x6cc650a4, "zfs_prop_get_type" },
+       { 0x6ae12453, "__kstat_install" },
+       { 0x1c90ea0e, "nvlist_add_int64" },
+       { 0x36198a4d, "nvpair_value_string" },
+       { 0x405c1144, "get_seconds" },
+       { 0x8d8996ce, "z_uncompress" },
+       { 0x4c327173, "alloc_disk" },
+       { 0x34eccc79, "generic_getxattr" },
+       { 0x8b484c4c, "fnvlist_lookup_nvpair" },
+       { 0xcf47e212, "fnvlist_add_int32" },
+       { 0x26b64321, "call_usermodehelper_setfns" },
+       { 0xf5893abf, "up_read" },
+       { 0x8f20556d, "blk_cleanup_queue" },
+       { 0xaada9d55, "zfs_prop_init" },
+       { 0xb41ea00a, "nvlist_add_uint8_array" },
+       { 0xeae36f92, "blk_queue_io_opt" },
+       { 0xdc89486b, "zfs_name_to_prop" },
+       { 0xdb347c7a, "call_usermodehelper_exec" },
+       { 0x3a3b4efc, "generic_file_llseek" },
+       { 0xda48c2e6, "__mark_inode_dirty" },
+       { 0xd4bf55ff, "u8_validate" },
+       { 0x3228f0a3, "d_invalidate" },
+       { 0x21b5a134, "__set_page_dirty_nobuffers" },
+       { 0xf2f1ef64, "fnvlist_alloc" },
+       { 0xadaabe1b, "pv_lock_ops" },
+       { 0x349cba85, "strchr" },
+       { 0x9191a98c, "nvlist_add_uint32_array" },
+       { 0xce291afa, "bio_alloc" },
+       { 0x150ddbd2, "kstat_runq_enter" },
+       { 0x370dbc79, "__remove_inode_hash" },
+       { 0x2fe3ab3e, "get_gendisk" },
+       { 0x3ec8886f, "param_ops_int" },
+       { 0x1403a15e, "taskq_member" },
+       { 0xb0364551, "zio_arena" },
+       { 0xf5dea0d6, "nvpair_value_int64_array" },
+       { 0x25ec1b28, "strlen" },
+       { 0xd0ee38b8, "schedule_timeout_uninterruptible" },
+       { 0x8205f265, "crhold" },
+       { 0x3a9b6fb9, "blk_unregister_region" },
+       { 0xb37f3106, "d_set_d_op" },
+       { 0xaaf57193, "blk_queue_max_hw_sectors" },
+       { 0x1efe1f66, "vn_close" },
+       { 0xa6867664, "filemap_write_and_wait_range" },
+       { 0x4ff1c9bc, "populate_rootfs_wait" },
+       { 0x16916efb, "nvlist_prev_nvpair" },
+       { 0x19295e53, "taskq_create" },
+       { 0x1ba29031, "zfs_component_namecheck" },
+       { 0xffc19dde, "elevator_change" },
+       { 0x89a7204c, "kill_anon_super" },
+       { 0x3f38bd50, "crgetruid" },
+       { 0x6a4152d5, "nvlist_add_uint64" },
+       { 0x6363ef50, "fnvlist_pack_free" },
+       { 0xd0799edd, "posix_acl_to_xattr" },
+       { 0xd14a7eb5, "vn_getattr" },
+       { 0xed8dac48, "nvlist_pack" },
+       { 0xbd100793, "cpu_online_mask" },
+       { 0x79aa04a2, "get_random_bytes" },
+       { 0x67053080, "current_kernel_time" },
+       { 0xf4f0a175, "avl_nearest" },
+       { 0xab140103, "spl_kmem_alloc" },
+       { 0x5d16cdc5, "nvlist_exists" },
+       { 0xd0bd878, "seq_puts" },
+       { 0x80c478fd, "rootdir" },
+       { 0xa850554e, "vn_seek" },
+       { 0x73a78bc4, "downgrade_write" },
+       { 0xcb98e344, "truncate_inode_pages_range" },
+       { 0x2e93154b, "generic_file_open" },
+       { 0xacf4d843, "match_strdup" },
+       { 0xffff91e3, "taskq_init_ent" },
+       { 0x3f69d73b, "test_set_page_writeback" },
+       { 0xefc4da17, "kobj_close_file" },
+       { 0xcf24ceff, "nvlist_remove" },
+       { 0xcd69282b, "__lock_page" },
+       { 0xb54533f7, "usecs_to_jiffies" },
+       { 0x581b3ff3, "zpool_prop_get_type" },
+       { 0xa483a8c3, "zfs_prop_to_name" },
+       { 0x63bdf5f0, "crgetngroups" },
+       { 0xf7fb002a, "kobj_get_filesize" },
+       { 0xd6f70ea0, "nvlist_empty" },
+       { 0x187c0510, "nvpair_value_int64" },
+       { 0x21a7d814, "seq_printf" },
+       { 0xac095684, "zfs_prop_inheritable" },
+       { 0xb6c2717d, "fnvlist_lookup_uint64" },
+       { 0x44e9a829, "match_token" },
+       { 0x582829a0, "avl_last" },
+       { 0xf4e84391, "nvlist_add_nvlist" },
+       { 0xb205e7ee, "nvpair_value_uint16_array" },
+       { 0x8e4c2658, "crgetgroups" },
+       { 0x7cb40d78, "avl_insert_here" },
+       { 0xf3e29ae0, "zpool_prop_to_name" },
+       { 0x64913468, "nvpair_value_uint8_array" },
+       { 0x305105e, "end_writeback" },
+       { 0xba2adaf, "mutex_unlock" },
+       { 0x407478e1, "nvpair_value_uint32_array" },
+       { 0x85df9b6c, "strsep" },
+       { 0xccc94e8, "nvlist_lookup_string" },
+       { 0x4704f678, "vn_rdwr" },
+       { 0xb05ef89e, "fnvlist_add_uint64" },
+       { 0x80336cc4, "generic_read_dir" },
+       { 0x1083f24f, "zfs_prop_valid_for_type" },
+       { 0x5be9e34a, "zfs_prop_setonce" },
+       { 0x76e8f609, "igrab" },
+       { 0x76ad2c09, "fnvlist_size" },
+       { 0x58b765b9, "pool_namecheck" },
+       { 0x47c7b0d2, "cpu_number" },
+       { 0x75fb8325, "generic_setxattr" },
+       { 0xafe82e10, "strcspn" },
+       { 0x3b251083, "mount_nodev" },
+       { 0x84000109, "path_get" },
+       { 0xa5894c2a, "redirty_page_for_writepage" },
+       { 0x91715312, "sprintf" },
+       { 0x8eb0a41f, "tsd_destroy" },
+       { 0xb8e71471, "spl_kmem_cache_free" },
+       { 0xbc32eee7, "spl_panic" },
+       { 0xcc13e034, "nv_alloc_init" },
+       { 0x50ea1952, "nvlist_add_int16_array" },
+       { 0x7d11c268, "jiffies" },
+       { 0x6ccdbacb, "lookup_bdev" },
+       { 0x6fba9cae, "truncate_setsize" },
+       { 0x31eb4278, "mutex_trylock" },
+       { 0x57a6ccd0, "down_read" },
+       { 0xe2d5255a, "strcmp" },
+       { 0x35225ea3, "down_write_trylock" },
+       { 0xb3d0550d, "end_page_writeback" },
+       { 0x8a4cbe5a, "cv_timedwait_hires" },
+       { 0xde9360ba, "totalram_pages" },
+       { 0xaa65a555, "kmem_asprintf" },
+       { 0x42585bc5, "nvlist_add_string_array" },
+       { 0x1d06c4ac, "u8_strcmp" },
+       { 0xd416eac3, "nvlist_xalloc" },
+       { 0xcfb24408, "nvpair_value_int32" },
+       { 0x786ba98a, "crgetuid" },
+       { 0xf2cb0b79, "uio_prefaultpages" },
+       { 0xba3e2d71, "zone_get_hostid" },
+       { 0xd1bf81d6, "invalidate_bdev" },
+       { 0x6395be94, "__init_waitqueue_head" },
+       { 0x4f8b5ddb, "_copy_to_user" },
+       { 0x3c7cdc13, "avl_remove" },
+       { 0x528f1f4e, "nvpair_value_int8_array" },
+       { 0xe24d3a97, "jiffies_64" },
+       { 0xee8843fa, "nvpair_value_uint64" },
+       { 0xc98d2e5d, "blk_queue_max_segments" },
+       { 0x106b6ba8, "taskq_destroy" },
+       { 0x6d0aba34, "wait_for_completion" },
+       { 0x72aa82c6, "param_ops_charp" },
+       { 0xb11fa1ce, "strlcat" },
+       { 0x45fe0d68, "inode_owner_or_capable" },
+       { 0x114258fb, "misc_register" },
+       { 0x7023fd74, "zfs_spa_version_map" },
+       { 0x66cb0ee2, "nvpair_value_uint64_array" },
+       { 0xaba3870c, "kern_path" },
+       { 0xde0bdcff, "memset" },
+       { 0x8b78128, "spl_kmem_cache_destroy" },
+       { 0xbd256438, "nvlist_lookup_nvpair" },
+       { 0x81c1c2b2, "vmem_size" },
+       { 0xbc9dddde, "taskq_wait_id" },
+       { 0x4f6584e1, "vn_getf" },
+       { 0x516b8b85, "nvlist_add_int8_array" },
+       { 0x79a0ecea, "d_add_ci" },
+       { 0xc810362f, "strdup" },
+       { 0x852e6c79, "blk_alloc_queue" },
+       { 0x26cd2d80, "fnvlist_num_pairs" },
+       { 0x22c35c6c, "fnvpair_value_nvlist" },
+       { 0xe9ba039d, "avl_destroy" },
+       { 0x11089ac7, "_ctype" },
+       { 0xd9977d8, "fletcher_4_incremental_native" },
+       { 0x8f64aa4, "_raw_spin_unlock_irqrestore" },
+       { 0x69371301, "current_task" },
+       { 0x143fcac6, "__cv_signal" },
+       { 0x7b6047b1, "avl_numnodes" },
+       { 0x6127b911, "kstat_waitq_exit" },
+       { 0x882c1dc4, "check_disk_change" },
+       { 0x2d004b80, "current_fs_time" },
+       { 0x87ebeb76, "__mutex_init" },
+       { 0x27e1a049, "printk" },
+       { 0xeba677bd, "posix_acl_chmod" },
+       { 0x30da4fbf, "fnvlist_free" },
+       { 0xe6b9d3c4, "find_lock_page" },
+       { 0xeb69fdd8, "d_obtain_alias" },
+       { 0x2fa5a500, "memcmp" },
+       { 0x90cc07c8, "blk_queue_max_discard_sectors" },
+       { 0x9d9024f7, "del_gendisk" },
+       { 0x68a9f991, "nvlist_add_uint16_array" },
+       { 0xa4cec62, "nv_fixed_ops" },
+       { 0x6a36f138, "zpool_prop_feature" },
+       { 0xd04b4649, "crgetfsgid" },
+       { 0xf2048734, "bio_add_page" },
+       { 0xe8856dea, "nvlist_remove_nvpair" },
+       { 0x35b9d4a6, "nvlist_add_nvlist_array" },
+       { 0x75a78768, "nvlist_alloc" },
+       { 0xa26a953e, "fletcher_2_byteswap" },
+       { 0x27655c15, "zfs_allocatable_devs" },
+       { 0xf7eb91ff, "d_alloc_root" },
+       { 0xe52592a, "panic" },
+       { 0xe2fd64d6, "nvpair_value_hrtime" },
+       { 0xa1c76e0a, "_cond_resched" },
+       { 0xb940ee11, "taskq_wait" },
+       { 0x7ec9bfbc, "strncpy" },
+       { 0x70f7c090, "__kstat_set_raw_ops" },
+       { 0xb4390f9a, "mcount" },
+       { 0x422932ac, "nvlist_lookup_int32" },
+       { 0x9e5f923c, "blkdev_get_by_path" },
+       { 0x5da5c9c6, "security_inode_init_security" },
+       { 0x8b19c37b, "check_disk_size_change" },
+       { 0x11edcd4c, "blk_register_region" },
+       { 0x85abc85f, "strncmp" },
+       { 0x672144bd, "strlcpy" },
+       { 0xbf8ba54a, "vprintk" },
+       { 0xafe1db9d, "mutex_lock" },
+       { 0xe5318fa0, "write_cache_pages" },
+       { 0xa340453c, "system_taskq" },
+       { 0x13401075, "taskq_dispatch" },
+       { 0xc8f88566, "nvpair_value_uint16" },
+       { 0x9f1dd1aa, "avl_insert" },
+       { 0x732cbdd2, "avl_is_empty" },
+       { 0xcb99edb0, "posix_acl_equiv_mode" },
+       { 0x5bb6ad4b, "spl_vmem_zalloc" },
+       { 0x71a50dbc, "register_blkdev" },
+       { 0x9b4571df, "nvpair_value_int32_array" },
+       { 0x79cca7cb, "uioskip" },
+       { 0x30cc3621, "insert_inode_locked" },
+       { 0xb3db5628, "avl_create" },
+       { 0xafa476dd, "nvpair_value_int8" },
+       { 0x90782bf3, "nvlist_add_string" },
+       { 0x13f6f973, "wait_on_page_bit" },
+       { 0x5559ab10, "zfs_deleg_whokey" },
+       { 0x4223cbc0, "uiocopy" },
+       { 0x7a82be45, "unlock_page" },
+       { 0x3b4ceb4a, "up_write" },
+       { 0x5318e74d, "shrink_dcache_sb" },
+       { 0x1ebbfffd, "ddi_copyout" },
+       { 0xe6e3b875, "down_write" },
+       { 0xcc762837, "kstat_waitq_enter" },
+       { 0x52252d43, "get_disk" },
+       { 0x6d601403, "crgetgid" },
+       { 0x64623de, "kmem_vasprintf" },
+       { 0x618628e6, "avl_destroy_nodes" },
+       { 0xd16645b6, "fnvlist_add_nvlist" },
+       { 0x89f2142a, "nvpair_value_nvlist_array" },
+       { 0xdb9e2c22, "posix_acl_create" },
+       { 0xd42a96fa, "nvpair_name" },
+       { 0x52778ec7, "vcmn_err" },
+       { 0x7c0a143, "bio_endio" },
+       { 0x920ca817, "bio_put" },
+       { 0xf41bf8b5, "generic_removexattr" },
+       { 0x1b7b5809, "__cv_broadcast" },
+       { 0x3323ccb1, "tsd_get" },
+       { 0xfcb16c49, "mark_page_accessed" },
+       { 0x180d429, "nvlist_add_int64_array" },
+       { 0x53bddca5, "taskq_dispatch_ent" },
+       { 0x61651be, "strcat" },
+       { 0x27277915, "vm_stat" },
+       { 0xd1346eaa, "avl_first" },
+       { 0x5cbae8f4, "crgetfsuid" },
+       { 0x1bc61496, "nvpair_value_int16_array" },
+       { 0xb5a459dc, "unregister_blkdev" },
+       { 0x24208ad1, "__cv_wait_io" },
+       { 0xb428a99c, "zfs_deleg_verify_nvlist" },
+       { 0x87b743ea, "inode_init_once" },
+       { 0x1bfac311, "nvlist_lookup_nvlist" },
+       { 0x7479525e, "fnvlist_add_uint64_array" },
+       { 0x9d9f80c4, "nvlist_free" },
+       { 0x5eb99327, "simple_getattr" },
+       { 0x50c5246d, "nvlist_add_uint8" },
+       { 0x5d6e0bba, "nvlist_lookup_uint64" },
+       { 0xaeefe7de, "submit_bio" },
+       { 0xc6cbbc89, "capable" },
+       { 0x31eaf145, "init_task" },
+       { 0xb1c3a01a, "oops_in_progress" },
+       { 0x9f984513, "strrchr" },
+       { 0x351c2576, "z_compress_level" },
+       { 0x901bfc1a, "ilookup" },
+       { 0x81376bfd, "vn_remove" },
+       { 0xb0030d43, "blkdev_put" },
+       { 0xc50bab05, "unregister_shrinker" },
+       { 0xe8adb6d8, "nvpair_value_boolean_value" },
+       { 0x81483072, "nvlist_add_uint16" },
+       { 0x9e3e7c5, "simple_dir_operations" },
+       { 0xeaa8f57, "generic_file_mmap" },
+       { 0x12a38747, "usleep_range" },
+       { 0x6ae07d22, "__cv_wait" },
+       { 0x17980bc5, "crfree" },
+       { 0x34fdc162, "nvlist_unpack" },
+       { 0x62dbf439, "blk_queue_make_request" },
+       {  0x1e77f, "nvlist_add_int32_array" },
+       { 0x1ef1f75f, "posix_acl_valid" },
+       { 0xaeab70e4, "zfs_prop_default_numeric" },
+       { 0xfce9b49e, "uiomove" },
+       { 0xc54a86a3, "blk_queue_physical_block_size" },
+       { 0x10006f1f, "nvlist_lookup_nv_alloc" },
+       { 0xf7b48661, "vn_set_pwd" },
+       { 0xcb59902f, "nvlist_lookup_byte_array" },
+       { 0xf0fdf6cb, "__stack_chk_fail" },
+       { 0xb9249d16, "cpu_possible_mask" },
+       { 0x3bd1b1f6, "msecs_to_jiffies" },
+       { 0xfe56e2a4, "nvpair_value_int16" },
+       { 0xcc8e80f8, "kstat_runq_exit" },
+       { 0x1000e51, "schedule" },
+       { 0x958b84e3, "tsd_create" },
+       { 0x667ba081, "spl_kmem_cache_create" },
+       { 0x20173f35, "taskq_wait_outstanding" },
+       { 0x5295f485, "posix_acl_from_xattr" },
+       { 0x85261be0, "__kstat_create" },
+       { 0xaebbec7c, "kobj_read_file" },
+       { 0x5b2da8a8, "put_disk" },
+       { 0xffa90716, "unlock_new_inode" },
+       { 0x2bbdb1d2, "nvlist_add_uint32" },
+       { 0x6da84db2, "deactivate_super" },
+       { 0x7274e02f, "bdi_setup_and_register" },
+       { 0x447bea0b, "fnvpair_value_uint64" },
+       { 0x2e36ff5c, "nvlist_remove_all" },
+       { 0x6dc38171, "fnvlist_add_boolean" },
+       { 0xd94959c7, "fletcher_4_native" },
+       { 0x5e95b1cd, "current_umask" },
+       { 0xb948e867, "zfs_prop_userquota" },
+       { 0xd0920999, "nvpair_value_uint32" },
+       { 0xc5ca5da8, "nvlist_merge" },
+       { 0xdae80439, "spl_vmem_alloc" },
+       { 0xdeea79ca, "nvlist_add_int8" },
+       { 0xd22ed5e2, "spl_kmem_cache_alloc" },
+       { 0x6b63f55e, "heap_arena" },
+       { 0x1e60b5ba, "clear_page_dirty_for_io" },
+       { 0xc6956d59, "inode_change_ok" },
+       { 0xa3a77c69, "down_read_trylock" },
+       { 0x65f3602b, "vn_releasef" },
+       { 0x82384b7, "path_put" },
+       { 0x4b88e0e9, "zpool_get_rewind_policy" },
+       { 0x360e492b, "__cv_init" },
+       { 0xd52bf1ce, "_raw_spin_lock" },
+       { 0x2168361b, "fnvlist_add_nvlist_array" },
+       { 0xff3980bf, "read_cache_pages" },
+       { 0xb6445021, "zpool_prop_init" },
+       { 0x9327f5ce, "_raw_spin_lock_irqsave" },
+       { 0xe9167510, "fnvpair_value_string" },
+       { 0xe52947e7, "__phys_addr" },
+       { 0x7521d525, "fnvlist_lookup_string" },
+       { 0x1b8f1d1e, "strfree" },
+       { 0x9e7bdafa, "register_filesystem" },
+       { 0xdafb8f63, "zpool_name_to_prop" },
+       { 0x29c88b11, "nvlist_next_nvpair" },
+       { 0x10f2eb76, "vsnprintf" },
+       { 0x443890f9, "u8_textprep_str" },
+       { 0x659a64d0, "call_usermodehelper_setup" },
+       { 0x16d71b69, "__cv_wait_sig" },
+       { 0x88163724, "zfs_prop_user" },
+       { 0x2c0fbe10, "vn_open" },
+       { 0xa456b044, "zfs_prop_readonly" },
+       { 0x82027a4c, "cmn_err" },
+       { 0xff40513c, "avl_find" },
+       { 0xc43ab895, "nvlist_add_boolean_value" },
+       { 0xe6990065, "fletcher_4_incremental_byteswap" },
+       { 0x506746b6, "getrawmonotonic" },
+       { 0x2e99f25f, "__cv_timedwait_sig" },
+       { 0x8dfdd77d, "fnvpair_value_int32" },
+       { 0x4c82bcb5, "nvlist_add_byte" },
+       { 0x5c5fd5f1, "iput" },
+       { 0xa0ed48c9, "fnvlist_lookup_nvlist" },
+       { 0x6db955bf, "nvpair_type" },
+       { 0xd2c3d1c4, "ddi_copyin" },
+       { 0x1285cb78, "tsd_set" },
+       { 0x3896a905, "__thread_exit" },
+       { 0x37a0cba, "kfree" },
+       { 0x531d58c3, "zpool_prop_index_to_string" },
+       { 0xd234c7f7, "nvlist_add_nvpair" },
+       { 0x236c8c64, "memcpy" },
+       { 0x3799704a, "spl_kmem_cache_set_move" },
+       { 0x5ecf6f91, "vn_mode_to_vtype" },
+       { 0xea8a6c75, "param_ops_long" },
+       { 0xe3e12c4f, "d_splice_alias" },
+       { 0x9518b623, "register_shrinker" },
+       { 0xe1f620de, "add_disk" },
+       { 0x4b2cb038, "zfs_prop_index_to_string" },
+       { 0xd1c1752d, "zfs_zpl_version_map" },
+       { 0x434773c9, "avl_walk" },
+       { 0xf715d7e4, "fletcher_4_byteswap" },
+       { 0x86f43149, "zfs_userquota_prop_prefixes" },
+       { 0xf68905fd, "ddi_strtoull" },
+       { 0x45dd41aa, "generic_readlink" },
+       { 0xa2fb3ea8, "put_page" },
+       { 0x5aa48f01, "bdi_destroy" },
+       { 0x4cbbd171, "__bitmap_weight" },
+       { 0x4b69abe5, "nvpair_value_byte" },
+       { 0x6811efbd, "nvlist_size" },
+       { 0xd7e6464c, "fletcher_2_native" },
+       { 0x3d6d97a2, "ioctl_by_bdev" },
+       { 0x670fde39, "fnvlist_pack" },
+       { 0x5cc844b3, "unregister_filesystem" },
+       { 0x6cfc93ad, "init_special_inode" },
+       { 0x9f46de9, "kobj_open_file" },
+       { 0x4e7a84e6, "avl_add" },
+       { 0x185936d6, "groupmember" },
+       { 0x4ea06afa, "nvlist_add_byte_array" },
+       { 0x4b06d2e7, "complete" },
+       { 0x50720c5f, "snprintf" },
+       { 0x3a1aa9fb, "bdget" },
+       { 0x7be1c89e, "blk_queue_max_segment_size" },
+       { 0xd433d2cb, "__kstat_delete" },
+       { 0xa3de192d, "fnvlist_add_string" },
+       { 0x504be4f9, "nvlist_add_int16" },
+       { 0xec1cce40, "nvlist_lookup_nvlist_array" },
+       { 0x4ccb2dda, "new_inode" },
+       { 0xa3a5be95, "memmove" },
+       { 0x43c69f9a, "zpool_prop_default_numeric" },
+       { 0xae5d807c, "vmalloc_to_page" },
+       { 0x80c3f220, "spl_kmem_free" },
+       { 0x8eb2664d, "fnvlist_remove_nvpair" },
+       { 0x6edb75cf, "follow_down_one" },
+       { 0x7466fa85, "spl_kmem_cache_reap_now" },
+       { 0xaa9db9bb, "nvlist_add_uint64_array" },
+       { 0xf473f2ff, "blkdev_get" },
+       { 0xc236e29a, "zfs_prop_default_string" },
+       { 0xbaa28806, "simple_dir_inode_operations" },
+       { 0x1500ba78, "__thread_create" },
+       { 0x778a305, "spl_vmem_free" },
+       { 0x4f6b400b, "_copy_from_user" },
+       { 0xb3e56341, "taskq_cancel_id" },
+       { 0xa2c56c31, "param_ops_ulong" },
+       { 0xfad8deb5, "nv_alloc_fini" },
+       { 0xc3fe87c8, "param_ops_uint" },
+       { 0x19471135, "bdget_disk" },
+       { 0xa66a6969, "nvpair_value_nvlist" },
+       { 0xdfb0b5e5, "misc_deregister" },
+       { 0xf91d3b5a, "nvlist_dup" },
+       { 0x62c31a0, "bdput" },
+       { 0x9c679abb, "d_instantiate" },
+       { 0x2a6e6109, "__init_rwsem" },
+       { 0xec031267, "taskq_dispatch_delay" },
+       { 0x2821e0b2, "nvlist_lookup_uint64_array" },
+       { 0x85524b8b, "p0" },
+       { 0x59fe72f0, "__cv_destroy" },
+       { 0x38dbd03a, "dataset_namecheck" },
+       { 0x5fb4b61d, "fnvlist_dup" },
+       { 0x8b50312f, "generic_fillattr" },
+       { 0x2e1cae5a, "vn_openat" },
+       { 0xe914e41e, "strcpy" },
+       { 0xda6b5415, "set_disk_ro" },
+       { 0x9dcb88fc, "spl_kmem_zalloc" },
+       { 0x75907276, "kmem_debugging" },
+       { 0xc3ff0fa1, "nvpair_value_uint8" },
+       { 0xdb7958d9, "taskq_empty_ent" },
+};
+
+static const char __module_depends[]
+__used
+__attribute__((section(".modinfo"))) =
+"depends=spl,znvpair,zcommon,zunicode,zavl";
+
+
+MODULE_INFO(srcversion, "6D4A581C24AFCEC615C1511");
index d026e92d693426337f482da5264dc4216c801664..12d275049570af48804242b37138d81031f14ffb 100644 (file)
@@ -30,6 +30,7 @@
  * Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
  * Copyright (c) 2013 Steven Hartland. All rights reserved.
  * Copyright (c) 2014, Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2016 Actifio, Inc. All rights reserved.
  */
 
 /*
@@ -1500,8 +1501,7 @@ zfs_ioc_pool_destroy(zfs_cmd_t *zc)
        int error;
        zfs_log_history(zc);
        error = spa_destroy(zc->zc_name);
-       if (error == 0)
-               zvol_remove_minors(zc->zc_name);
+
        return (error);
 }
 
@@ -1553,8 +1553,7 @@ zfs_ioc_pool_export(zfs_cmd_t *zc)
 
        zfs_log_history(zc);
        error = spa_export(zc->zc_name, NULL, force, hardforce);
-       if (error == 0)
-               zvol_remove_minors(zc->zc_name);
+
        return (error);
 }
 
@@ -2395,7 +2394,7 @@ zfs_prop_set_special(const char *dsname, zprop_source_t source,
                err = zvol_set_volsize(dsname, intval);
                break;
        case ZFS_PROP_SNAPDEV:
-               err = zvol_set_snapdev(dsname, intval);
+               err = zvol_set_snapdev(dsname, source, intval);
                break;
        case ZFS_PROP_VERSION:
        {
@@ -3189,12 +3188,6 @@ zfs_ioc_create(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
                if (error != 0)
                        (void) dsl_destroy_head(fsname);
        }
-
-#ifdef _KERNEL
-       if (error == 0 && type == DMU_OST_ZVOL)
-               zvol_create_minors(fsname);
-#endif
-
        return (error);
 }
 
@@ -3237,12 +3230,6 @@ zfs_ioc_clone(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
                if (error != 0)
                        (void) dsl_destroy_head(fsname);
        }
-
-#ifdef _KERNEL
-       if (error == 0)
-               zvol_create_minors(fsname);
-#endif
-
        return (error);
 }
 
@@ -3305,11 +3292,6 @@ zfs_ioc_snapshot(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
 
        error = dsl_dataset_snapshot(snaps, props, outnvl);
 
-#ifdef _KERNEL
-       if (error == 0)
-               zvol_create_minors(poolname);
-#endif
-
        return (error);
 }
 
@@ -3435,7 +3417,6 @@ zfs_ioc_destroy_snaps(const char *poolname, nvlist_t *innvl, nvlist_t *outnvl)
        for (pair = nvlist_next_nvpair(snaps, NULL); pair != NULL;
            pair = nvlist_next_nvpair(snaps, pair)) {
                (void) zfs_unmount_snap(nvpair_name(pair));
-               (void) zvol_remove_minor(nvpair_name(pair));
        }
 
        return (dsl_destroy_snapshots_nvl(snaps, defer, outnvl));
@@ -3561,8 +3542,7 @@ zfs_ioc_destroy(zfs_cmd_t *zc)
                err = dsl_destroy_snapshot(zc->zc_name, zc->zc_defer_destroy);
        else
                err = dsl_destroy_head(zc->zc_name);
-       if (zc->zc_objset_type == DMU_OST_ZVOL && err == 0)
-               (void) zvol_remove_minor(zc->zc_name);
+
        return (err);
 }
 
@@ -4128,11 +4108,6 @@ zfs_ioc_recv(zfs_cmd_t *zc)
        }
 #endif
 
-#ifdef _KERNEL
-       if (error == 0)
-               zvol_create_minors(tofs);
-#endif
-
        /*
         * On error, restore the original props.
         */
@@ -6018,16 +5993,16 @@ _init(void)
                return (error);
        }
 
+       if ((error = -zvol_init()) != 0)
+               return (error);
+
        spa_init(FREAD | FWRITE);
        zfs_init();
 
-       if ((error = -zvol_init()) != 0)
-               goto out1;
-
        zfs_ioctl_init();
 
        if ((error = zfs_attach()) != 0)
-               goto out2;
+               goto out;
 
        tsd_create(&zfs_fsyncer_key, NULL);
        tsd_create(&rrw_tsd_key, rrw_tsd_destroy);
@@ -6043,11 +6018,10 @@ _init(void)
 
        return (0);
 
-out2:
-       (void) zvol_fini();
-out1:
+out:
        zfs_fini();
        spa_fini();
+       (void) zvol_fini();
        printk(KERN_NOTICE "ZFS: Failed to Load ZFS Filesystem v%s-%s%s"
            ", rc = %d\n", ZFS_META_VERSION, ZFS_META_RELEASE,
            ZFS_DEBUG_STR, error);
@@ -6059,9 +6033,9 @@ static void __exit
 _fini(void)
 {
        zfs_detach();
-       zvol_fini();
        zfs_fini();
        spa_fini();
+       zvol_fini();
 
        tsd_destroy(&zfs_fsyncer_key);
        tsd_destroy(&rrw_tsd_key);
index bd0d5129c1f380f5bc09ca410aa6656fea9e8bef..cbdab7d3003b9ad93c9bbfe0b384b74b1a9717a0 100644 (file)
@@ -31,6 +31,7 @@
 #include <sys/dmu_objset.h>
 #include <sys/vfs.h>
 #include <sys/zpl.h>
+#include <sys/file.h>
 
 
 static struct dentry *
@@ -44,13 +45,26 @@ zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
        struct inode *ip;
        int error;
        fstrans_cookie_t cookie;
+       pathname_t *ppn = NULL;
+       pathname_t pn;
+       int zfs_flags = 0;
+       zfs_sb_t *zsb = dentry->d_sb->s_fs_info;
 
        if (dlen(dentry) > ZFS_MAXNAMELEN)
                return (ERR_PTR(-ENAMETOOLONG));
 
        crhold(cr);
        cookie = spl_fstrans_mark();
-       error = -zfs_lookup(dir, dname(dentry), &ip, 0, cr, NULL, NULL);
+
+       /* If we are a case insensitive fs, we need the real name */
+       if (zsb->z_case == ZFS_CASE_INSENSITIVE) {
+               zfs_flags = FIGNORECASE;
+               pn.pn_bufsize = ZFS_MAXNAMELEN;
+               pn.pn_buf = kmem_zalloc(ZFS_MAXNAMELEN, KM_SLEEP);
+               ppn = &pn;
+       }
+
+       error = -zfs_lookup(dir, dname(dentry), &ip, zfs_flags, cr, NULL, ppn);
        spl_fstrans_unmark(cookie);
        ASSERT3S(error, <=, 0);
        crfree(cr);
@@ -63,13 +77,39 @@ zpl_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
        spin_unlock(&dentry->d_lock);
 
        if (error) {
+               /*
+                * If we have a case sensitive fs, we do not want to
+                * insert negative entries, so return NULL for ENOENT.
+                * Fall through if the error is not ENOENT. Also free memory.
+                */
+               if (ppn) {
+                       kmem_free(pn.pn_buf, ZFS_MAXNAMELEN);
+                       if (error == -ENOENT)
+                               return (NULL);
+               }
+
                if (error == -ENOENT)
                        return (d_splice_alias(NULL, dentry));
                else
                        return (ERR_PTR(error));
        }
 
-       return (d_splice_alias(ip, dentry));
+       /*
+        * If we are case insensitive, call the correct function
+        * to install the name.
+        */
+       if (ppn) {
+               struct dentry *new_dentry;
+               struct qstr ci_name;
+
+               ci_name.name = pn.pn_buf;
+               ci_name.len = strlen(pn.pn_buf);
+               new_dentry = d_add_ci(dentry, ip, &ci_name);
+               kmem_free(pn.pn_buf, ZFS_MAXNAMELEN);
+               return (new_dentry);
+       } else {
+               return (d_splice_alias(ip, dentry));
+       }
 }
 
 void
@@ -177,10 +217,19 @@ zpl_unlink(struct inode *dir, struct dentry *dentry)
        cred_t *cr = CRED();
        int error;
        fstrans_cookie_t cookie;
+       zfs_sb_t *zsb = dentry->d_sb->s_fs_info;
 
        crhold(cr);
        cookie = spl_fstrans_mark();
        error = -zfs_remove(dir, dname(dentry), cr);
+
+       /*
+        * For a CI FS we must invalidate the dentry to prevent the
+        * creation of negative entries.
+        */
+       if (error == 0 && zsb->z_case == ZFS_CASE_INSENSITIVE)
+               d_invalidate(dentry);
+
        spl_fstrans_unmark(cookie);
        crfree(cr);
        ASSERT3S(error, <=, 0);
@@ -228,10 +277,19 @@ zpl_rmdir(struct inode * dir, struct dentry *dentry)
        cred_t *cr = CRED();
        int error;
        fstrans_cookie_t cookie;
+       zfs_sb_t *zsb = dentry->d_sb->s_fs_info;
 
        crhold(cr);
        cookie = spl_fstrans_mark();
        error = -zfs_rmdir(dir, dname(dentry), NULL, cr, 0);
+
+       /*
+        * For a CI FS we must invalidate the dentry to prevent the
+        * creation of negative entries.
+        */
+       if (error == 0 && zsb->z_case == ZFS_CASE_INSENSITIVE)
+               d_invalidate(dentry);
+
        spl_fstrans_unmark(cookie);
        crfree(cr);
        ASSERT3S(error, <=, 0);
index 613b47ef92fb362dadc0a3598f839203582e5a87..a7a79e6ddbe8dad6300124fcdb556bf99e58571f 100644 (file)
  *
  * Volumes are persistent through reboot and module load.  No user command
  * needs to be run before opening and using a device.
+ *
+ * Copyright (c) 2016 Actifio, Inc. All rights reserved.
  */
 
 #include <sys/dbuf.h>
 #include <sys/dmu_traverse.h>
 #include <sys/dsl_dataset.h>
 #include <sys/dsl_prop.h>
+#include <sys/dsl_dir.h>
 #include <sys/zap.h>
 #include <sys/zfeature.h>
 #include <sys/zil_impl.h>
+#include <sys/dmu_tx.h>
 #include <sys/zio.h>
 #include <sys/zfs_rlock.h>
 #include <sys/zfs_znode.h>
+#include <sys/spa_impl.h>
 #include <sys/zvol.h>
 #include <linux/blkdev_compat.h>
 
@@ -78,6 +83,23 @@ typedef struct zvol_state {
        list_node_t             zv_next;        /* next zvol_state_t linkage */
 } zvol_state_t;
 
+typedef enum {
+       ZVOL_ASYNC_CREATE_MINORS,
+       ZVOL_ASYNC_REMOVE_MINORS,
+       ZVOL_ASYNC_RENAME_MINORS,
+       ZVOL_ASYNC_SET_SNAPDEV,
+       ZVOL_ASYNC_MAX
+} zvol_async_op_t;
+
+typedef struct {
+       zvol_async_op_t op;
+       char pool[MAXNAMELEN];
+       char name1[MAXNAMELEN];
+       char name2[MAXNAMELEN];
+       zprop_source_t source;
+       uint64_t snapdev;
+} zvol_task_t;
+
 #define        ZVOL_RDONLY     0x1
 
 /*
@@ -599,6 +621,8 @@ zvol_write(struct bio *bio)
        dmu_tx_t *tx;
        rl_t *rl;
 
+       ASSERT(zv && zv->zv_open_count > 0);
+
        if (bio->bi_rw & VDEV_REQ_FLUSH)
                zil_commit(zv->zv_zilog, ZVOL_OBJ);
 
@@ -647,6 +671,8 @@ zvol_discard(struct bio *bio)
        int error;
        rl_t *rl;
 
+       ASSERT(zv && zv->zv_open_count > 0);
+
        if (end > zv->zv_volsize)
                return (SET_ERROR(EIO));
 
@@ -691,10 +717,11 @@ zvol_read(struct bio *bio)
        int error;
        rl_t *rl;
 
+       ASSERT(zv && zv->zv_open_count > 0);
+
        if (len == 0)
                return (0);
 
-
        rl = zfs_range_lock(&zv->zv_znode, offset, len, RL_READER);
 
        error = dmu_read_bio(zv->zv_objset, ZVOL_OBJ, bio);
@@ -874,54 +901,27 @@ zvol_first_open(zvol_state_t *zv)
 {
        objset_t *os;
        uint64_t volsize;
-       int locked = 0;
        int error;
        uint64_t ro;
 
-       /*
-        * In all other cases the spa_namespace_lock is taken before the
-        * bdev->bd_mutex lock.  But in this case the Linux __blkdev_get()
-        * function calls fops->open() with the bdev->bd_mutex lock held.
-        *
-        * To avoid a potential lock inversion deadlock we preemptively
-        * try to take the spa_namespace_lock().  Normally it will not
-        * be contended and this is safe because spa_open_common() handles
-        * the case where the caller already holds the spa_namespace_lock.
-        *
-        * When it is contended we risk a lock inversion if we were to
-        * block waiting for the lock.  Luckily, the __blkdev_get()
-        * function allows us to return -ERESTARTSYS which will result in
-        * bdev->bd_mutex being dropped, reacquired, and fops->open() being
-        * called again.  This process can be repeated safely until both
-        * locks are acquired.
-        */
-       if (!mutex_owned(&spa_namespace_lock)) {
-               locked = mutex_tryenter(&spa_namespace_lock);
-               if (!locked)
-                       return (-SET_ERROR(ERESTARTSYS));
-       }
-
-       error = dsl_prop_get_integer(zv->zv_name, "readonly", &ro, NULL);
-       if (error)
-               goto out_mutex;
-
        /* lie and say we're read-only */
        error = dmu_objset_own(zv->zv_name, DMU_OST_ZVOL, 1, zvol_tag, &os);
        if (error)
-               goto out_mutex;
+               return (SET_ERROR(-error));
+
+       zv->zv_objset = os;
+
+       error = dsl_prop_get_integer(zv->zv_name, "readonly", &ro, NULL);
+       if (error)
+               goto out_owned;
 
        error = zap_lookup(os, ZVOL_ZAP_OBJ, "size", 8, 1, &volsize);
-       if (error) {
-               dmu_objset_disown(os, zvol_tag);
-               goto out_mutex;
-       }
+       if (error)
+               goto out_owned;
 
-       zv->zv_objset = os;
        error = dmu_bonus_hold(os, ZVOL_OBJ, zvol_tag, &zv->zv_dbuf);
-       if (error) {
-               dmu_objset_disown(os, zvol_tag);
-               goto out_mutex;
-       }
+       if (error)
+               goto out_owned;
 
        set_capacity(zv->zv_disk, volsize >> 9);
        zv->zv_volsize = volsize;
@@ -936,9 +936,11 @@ zvol_first_open(zvol_state_t *zv)
                zv->zv_flags &= ~ZVOL_RDONLY;
        }
 
-out_mutex:
-       if (locked)
-               mutex_exit(&spa_namespace_lock);
+out_owned:
+       if (error) {
+               dmu_objset_disown(os, zvol_tag);
+               zv->zv_objset = NULL;
+       }
 
        return (SET_ERROR(-error));
 }
@@ -967,12 +969,12 @@ zvol_last_close(zvol_state_t *zv)
 static int
 zvol_open(struct block_device *bdev, fmode_t flag)
 {
-       zvol_state_t *zv = bdev->bd_disk->private_data;
+       zvol_state_t *zv;
        int error = 0, drop_mutex = 0;
 
        /*
         * If the caller is already holding the mutex do not take it
-        * again, this will happen as part of zvol_create_minor().
+        * again, this will happen as part of zvol_create_minor_impl().
         * Once add_disk() is called the device is live and the kernel
         * will attempt to open it to read the partition information.
         */
@@ -981,7 +983,17 @@ zvol_open(struct block_device *bdev, fmode_t flag)
                drop_mutex = 1;
        }
 
-       ASSERT3P(zv, !=, NULL);
+       /*
+        * Obtain a copy of private_data under the lock to make sure
+        * that either the result of zvol_freeg() setting
+        * bdev->bd_disk->private_data to NULL is observed, or zvol_free()
+        * is not called on this zv because of the positive zv_open_count.
+        */
+       zv = bdev->bd_disk->private_data;
+       if (zv == NULL) {
+               error = -ENXIO;
+               goto out_mutex;
+       }
 
        if (zv->zv_open_count == 0) {
                error = zvol_first_open(zv);
@@ -996,6 +1008,8 @@ zvol_open(struct block_device *bdev, fmode_t flag)
 
        zv->zv_open_count++;
 
+       check_disk_change(bdev);
+
 out_open_count:
        if (zv->zv_open_count == 0)
                zvol_last_close(zv);
@@ -1004,8 +1018,6 @@ out_mutex:
        if (drop_mutex)
                mutex_exit(&zvol_state_lock);
 
-       check_disk_change(bdev);
-
        return (SET_ERROR(error));
 }
 
@@ -1019,16 +1031,16 @@ zvol_release(struct gendisk *disk, fmode_t mode)
        zvol_state_t *zv = disk->private_data;
        int drop_mutex = 0;
 
+       ASSERT(zv && zv->zv_open_count > 0);
+
        if (!mutex_owned(&zvol_state_lock)) {
                mutex_enter(&zvol_state_lock);
                drop_mutex = 1;
        }
 
-       if (zv->zv_open_count > 0) {
-               zv->zv_open_count--;
-               if (zv->zv_open_count == 0)
-                       zvol_last_close(zv);
-       }
+       zv->zv_open_count--;
+       if (zv->zv_open_count == 0)
+               zvol_last_close(zv);
 
        if (drop_mutex)
                mutex_exit(&zvol_state_lock);
@@ -1045,8 +1057,7 @@ zvol_ioctl(struct block_device *bdev, fmode_t mode,
        zvol_state_t *zv = bdev->bd_disk->private_data;
        int error = 0;
 
-       if (zv == NULL)
-               return (SET_ERROR(-ENXIO));
+       ASSERT(zv && zv->zv_open_count > 0);
 
        switch (cmd) {
        case BLKFLSBUF:
@@ -1080,6 +1091,8 @@ static int zvol_media_changed(struct gendisk *disk)
 {
        zvol_state_t *zv = disk->private_data;
 
+       ASSERT(zv && zv->zv_open_count > 0);
+
        return (zv->zv_changed);
 }
 
@@ -1087,6 +1100,8 @@ static int zvol_revalidate_disk(struct gendisk *disk)
 {
        zvol_state_t *zv = disk->private_data;
 
+       ASSERT(zv && zv->zv_open_count > 0);
+
        zv->zv_changed = 0;
        set_capacity(zv->zv_disk, zv->zv_volsize >> 9);
 
@@ -1103,7 +1118,11 @@ static int
 zvol_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
        zvol_state_t *zv = bdev->bd_disk->private_data;
-       sector_t sectors = get_capacity(zv->zv_disk);
+       sector_t sectors;
+
+       ASSERT(zv && zv->zv_open_count > 0);
+
+       sectors = get_capacity(zv->zv_disk);
 
        if (sectors > 2048) {
                geo->heads = 16;
@@ -1260,9 +1279,14 @@ out_kmem:
 static void
 zvol_free(zvol_state_t *zv)
 {
+       ASSERT(MUTEX_HELD(&zvol_state_lock));
+       ASSERT(zv->zv_open_count == 0);
+
        avl_destroy(&zv->zv_znode.z_range_avl);
        mutex_destroy(&zv->zv_znode.z_range_lock);
 
+       zv->zv_disk->private_data = NULL;
+
        del_gendisk(zv->zv_disk);
        blk_cleanup_queue(zv->zv_queue);
        put_disk(zv->zv_disk);
@@ -1270,31 +1294,13 @@ zvol_free(zvol_state_t *zv)
        kmem_free(zv, sizeof (zvol_state_t));
 }
 
+/*
+ * Create a block device minor node and setup the linkage between it
+ * and the specified volume.  Once this function returns the block
+ * device is live and ready for use.
+ */
 static int
-__zvol_snapdev_hidden(const char *name)
-{
-       uint64_t snapdev;
-       char *parent;
-       char *atp;
-       int error = 0;
-
-       parent = kmem_alloc(MAXPATHLEN, KM_SLEEP);
-       (void) strlcpy(parent, name, MAXPATHLEN);
-
-       if ((atp = strrchr(parent, '@')) != NULL) {
-               *atp = '\0';
-               error = dsl_prop_get_integer(parent, "snapdev", &snapdev, NULL);
-               if ((error == 0) && (snapdev == ZFS_SNAPDEV_HIDDEN))
-                       error = SET_ERROR(ENODEV);
-       }
-
-       kmem_free(parent, MAXPATHLEN);
-
-       return (SET_ERROR(error));
-}
-
-static int
-__zvol_create_minor(const char *name, boolean_t ignore_snapdev)
+zvol_create_minor_impl(const char *name)
 {
        zvol_state_t *zv;
        objset_t *os;
@@ -1304,7 +1310,7 @@ __zvol_create_minor(const char *name, boolean_t ignore_snapdev)
        unsigned minor = 0;
        int error = 0;
 
-       ASSERT(MUTEX_HELD(&zvol_state_lock));
+       mutex_enter(&zvol_state_lock);
 
        zv = zvol_find_by_name(name);
        if (zv) {
@@ -1312,12 +1318,6 @@ __zvol_create_minor(const char *name, boolean_t ignore_snapdev)
                goto out;
        }
 
-       if (ignore_snapdev == B_FALSE) {
-               error = __zvol_snapdev_hidden(name);
-               if (error)
-                       goto out;
-       }
-
        doi = kmem_alloc(sizeof (dmu_object_info_t), KM_SLEEP);
 
        error = dmu_objset_own(name, DMU_OST_ZVOL, B_TRUE, zvol_tag, &os);
@@ -1395,69 +1395,26 @@ out:
 
        if (error == 0) {
                zvol_insert(zv);
+               /*
+                * Drop the lock to prevent deadlock with sys_open() ->
+                * zvol_open(), which first takes bd_disk->bd_mutex and then
+                * takes zvol_state_lock, whereas this code path first takes
+                * zvol_state_lock, and then takes bd_disk->bd_mutex.
+                */
+               mutex_exit(&zvol_state_lock);
                add_disk(zv->zv_disk);
+       } else {
+               mutex_exit(&zvol_state_lock);
        }
 
        return (SET_ERROR(error));
 }
 
-/*
- * Create a block device minor node and setup the linkage between it
- * and the specified volume.  Once this function returns the block
- * device is live and ready for use.
- */
-int
-zvol_create_minor(const char *name)
-{
-       int error;
-
-       mutex_enter(&zvol_state_lock);
-       error = __zvol_create_minor(name, B_FALSE);
-       mutex_exit(&zvol_state_lock);
-
-       return (SET_ERROR(error));
-}
-
-static int
-__zvol_remove_minor(const char *name)
-{
-       zvol_state_t *zv;
-
-       ASSERT(MUTEX_HELD(&zvol_state_lock));
-
-       zv = zvol_find_by_name(name);
-       if (zv == NULL)
-               return (SET_ERROR(ENXIO));
-
-       if (zv->zv_open_count > 0)
-               return (SET_ERROR(EBUSY));
-
-       zvol_remove(zv);
-       zvol_free(zv);
-
-       return (0);
-}
-
-/*
- * Remove a block device minor node for the specified volume.
- */
-int
-zvol_remove_minor(const char *name)
-{
-       int error;
-
-       mutex_enter(&zvol_state_lock);
-       error = __zvol_remove_minor(name);
-       mutex_exit(&zvol_state_lock);
-
-       return (SET_ERROR(error));
-}
-
 /*
  * Rename a block device minor mode for the specified volume.
  */
 static void
-__zvol_rename_minor(zvol_state_t *zv, const char *newname)
+zvol_rename_minor(zvol_state_t *zv, const char *newname)
 {
        int readonly = get_disk_ro(zv->zv_disk);
 
@@ -1477,25 +1434,124 @@ __zvol_rename_minor(zvol_state_t *zv, const char *newname)
        set_disk_ro(zv->zv_disk, readonly);
 }
 
+
+/*
+ * Mask errors to continue dmu_objset_find() traversal
+ */
+static int
+zvol_create_snap_minor_cb(const char *dsname, void *arg)
+{
+       const char *name = (const char *)arg;
+
+       ASSERT0(MUTEX_HELD(&spa_namespace_lock));
+
+       /* skip the designated dataset */
+       if (name && strcmp(dsname, name) == 0)
+               return (0);
+
+       /* at this point, the dsname should name a snapshot */
+       if (strchr(dsname, '@') == 0) {
+               dprintf("zvol_create_snap_minor_cb(): "
+                       "%s is not a shapshot name\n", dsname);
+       } else {
+               (void) zvol_create_minor_impl(dsname);
+       }
+
+       return (0);
+}
+
+/*
+ * Mask errors to continue dmu_objset_find() traversal
+ */
 static int
 zvol_create_minors_cb(const char *dsname, void *arg)
 {
-       (void) zvol_create_minor(dsname);
+       uint64_t snapdev;
+       int error;
+
+       ASSERT0(MUTEX_HELD(&spa_namespace_lock));
+
+       error = dsl_prop_get_integer(dsname, "snapdev", &snapdev, NULL);
+       if (error)
+               return (0);
+
+       /*
+        * Given the name and the 'snapdev' property, create device minor nodes
+        * with the linkages to zvols/snapshots as needed.
+        * If the name represents a zvol, create a minor node for the zvol, then
+        * check if its snapshots are 'visible', and if so, iterate over the
+        * snapshots and create device minor nodes for those.
+        */
+       if (strchr(dsname, '@') == 0) {
+               /* create minor for the 'dsname' explicitly */
+               error = zvol_create_minor_impl(dsname);
+               if ((error == 0 || error == EEXIST) &&
+                   (snapdev == ZFS_SNAPDEV_VISIBLE)) {
+                       fstrans_cookie_t cookie = spl_fstrans_mark();
+                       /*
+                        * traverse snapshots only, do not traverse children,
+                        * and skip the 'dsname'
+                        */
+                       error = dmu_objset_find((char *)dsname,
+                           zvol_create_snap_minor_cb, (void *)dsname,
+                           DS_FIND_SNAPSHOTS);
+                       spl_fstrans_unmark(cookie);
+               }
+       } else {
+               dprintf("zvol_create_minors_cb(): %s is not a zvol name\n",
+                       dsname);
+       }
 
        return (0);
 }
 
 /*
- * Create minors for specified dataset including children and snapshots.
+ * Create minors for the specified dataset, including children and snapshots.
+ * Pay attention to the 'snapdev' property and iterate over the snapshots
+ * only if they are 'visible'. This approach allows one to assure that the
+ * snapshot metadata is read from disk only if it is needed.
+ *
+ * The name can represent a dataset to be recursively scanned for zvols and
+ * their snapshots, or a single zvol snapshot. If the name represents a
+ * dataset, the scan is performed in two nested stages:
+ * - scan the dataset for zvols, and
+ * - for each zvol, create a minor node, then check if the zvol's snapshots
+ *   are 'visible', and only then iterate over the snapshots if needed
+ *
+ * If the name represents a snapshot, a check is perfromed if the snapshot is
+ * 'visible' (which also verifies that the parent is a zvol), and if so,
+ * a minor node for that snapshot is created.
  */
-int
-zvol_create_minors(const char *name)
+static int
+zvol_create_minors_impl(const char *name)
 {
        int error = 0;
+       fstrans_cookie_t cookie;
+       char *atp, *parent;
+
+       if (zvol_inhibit_dev)
+               return (0);
+
+       parent = kmem_alloc(MAXPATHLEN, KM_SLEEP);
+       (void) strlcpy(parent, name, MAXPATHLEN);
+
+       if ((atp = strrchr(parent, '@')) != NULL) {
+               uint64_t snapdev;
+
+               *atp = '\0';
+               error = dsl_prop_get_integer(parent, "snapdev",
+                   &snapdev, NULL);
+
+               if (error == 0 && snapdev == ZFS_SNAPDEV_VISIBLE)
+                       error = zvol_create_minor_impl(name);
+       } else {
+               cookie = spl_fstrans_mark();
+               error = dmu_objset_find(parent, zvol_create_minors_cb,
+                   NULL, DS_FIND_CHILDREN);
+               spl_fstrans_unmark(cookie);
+       }
 
-       if (!zvol_inhibit_dev)
-               error = dmu_objset_find((char *)name, zvol_create_minors_cb,
-                   NULL, DS_FIND_CHILDREN | DS_FIND_SNAPSHOTS);
+       kmem_free(parent, MAXPATHLEN);
 
        return (SET_ERROR(error));
 }
@@ -1503,8 +1559,8 @@ zvol_create_minors(const char *name)
 /*
  * Remove minors for specified dataset including children and snapshots.
  */
-void
-zvol_remove_minors(const char *name)
+static void
+zvol_remove_minors_impl(const char *name)
 {
        zvol_state_t *zv, *zv_next;
        int namelen = ((name) ? strlen(name) : 0);
@@ -1519,9 +1575,45 @@ zvol_remove_minors(const char *name)
 
                if (name == NULL || strcmp(zv->zv_name, name) == 0 ||
                    (strncmp(zv->zv_name, name, namelen) == 0 &&
-                   zv->zv_name[namelen] == '/')) {
+                   (zv->zv_name[namelen] == '/' ||
+                   zv->zv_name[namelen] == '@'))) {
+
+                       /* If in use, leave alone */
+                       if (zv->zv_open_count > 0)
+                               continue;
+
+                       zvol_remove(zv);
+                       zvol_free(zv);
+               }
+       }
+
+       mutex_exit(&zvol_state_lock);
+}
+
+/* Remove minor for this specific snapshot only */
+static void
+zvol_remove_minor_impl(const char *name)
+{
+       zvol_state_t *zv, *zv_next;
+
+       if (zvol_inhibit_dev)
+               return;
+
+       if (strchr(name, '@') == NULL)
+               return;
+
+       mutex_enter(&zvol_state_lock);
+
+       for (zv = list_head(&zvol_state_list); zv != NULL; zv = zv_next) {
+               zv_next = list_next(&zvol_state_list, zv);
+
+               if (strcmp(zv->zv_name, name) == 0) {
+                       /* If in use, leave alone */
+                       if (zv->zv_open_count > 0)
+                               continue;
                        zvol_remove(zv);
                        zvol_free(zv);
+                       break;
                }
        }
 
@@ -1531,8 +1623,8 @@ zvol_remove_minors(const char *name)
 /*
  * Rename minors for specified dataset including children and snapshots.
  */
-void
-zvol_rename_minors(const char *oldname, const char *newname)
+static void
+zvol_rename_minors_impl(const char *oldname, const char *newname)
 {
        zvol_state_t *zv, *zv_next;
        int oldnamelen, newnamelen;
@@ -1550,15 +1642,19 @@ zvol_rename_minors(const char *oldname, const char *newname)
        for (zv = list_head(&zvol_state_list); zv != NULL; zv = zv_next) {
                zv_next = list_next(&zvol_state_list, zv);
 
+               /* If in use, leave alone */
+               if (zv->zv_open_count > 0)
+                       continue;
+
                if (strcmp(zv->zv_name, oldname) == 0) {
-                       __zvol_rename_minor(zv, newname);
+                       zvol_rename_minor(zv, newname);
                } else if (strncmp(zv->zv_name, oldname, oldnamelen) == 0 &&
                    (zv->zv_name[oldnamelen] == '/' ||
                    zv->zv_name[oldnamelen] == '@')) {
                        snprintf(name, MAXNAMELEN, "%s%c%s", newname,
                            zv->zv_name[oldnamelen],
                            zv->zv_name + oldnamelen + 1);
-                       __zvol_rename_minor(zv, name);
+                       zvol_rename_minor(zv, name);
                }
        }
 
@@ -1567,33 +1663,227 @@ zvol_rename_minors(const char *oldname, const char *newname)
        kmem_free(name, MAXNAMELEN);
 }
 
+typedef struct zvol_snapdev_cb_arg {
+       uint64_t snapdev;
+} zvol_snapdev_cb_arg_t;
+
 static int
-snapdev_snapshot_changed_cb(const char *dsname, void *arg) {
-       uint64_t snapdev = *(uint64_t *) arg;
+zvol_set_snapdev_cb(const char *dsname, void *param) {
+       zvol_snapdev_cb_arg_t *arg = param;
 
        if (strchr(dsname, '@') == NULL)
                return (0);
 
-       switch (snapdev) {
+       switch (arg->snapdev) {
                case ZFS_SNAPDEV_VISIBLE:
-                       mutex_enter(&zvol_state_lock);
-                       (void) __zvol_create_minor(dsname, B_TRUE);
-                       mutex_exit(&zvol_state_lock);
+                       (void) zvol_create_minor_impl(dsname);
                        break;
                case ZFS_SNAPDEV_HIDDEN:
-                       (void) zvol_remove_minor(dsname);
+                       (void) zvol_remove_minor_impl(dsname);
                        break;
        }
 
        return (0);
 }
 
+static void
+zvol_set_snapdev_impl(char *name, uint64_t snapdev)
+{
+       zvol_snapdev_cb_arg_t arg = {snapdev};
+       fstrans_cookie_t cookie = spl_fstrans_mark();
+       /*
+        * The zvol_set_snapdev_sync() sets snapdev appropriately
+        * in the dataset hierarchy. Here, we only scan snapshots.
+        */
+       dmu_objset_find(name, zvol_set_snapdev_cb, &arg, DS_FIND_SNAPSHOTS);
+       spl_fstrans_unmark(cookie);
+}
+
+static zvol_task_t *
+zvol_task_alloc(zvol_async_op_t op, const char *name1, const char *name2,
+    uint64_t snapdev)
+{
+       zvol_task_t *task;
+       char *delim;
+
+       /* Never allow tasks on hidden names. */
+       if (name1[0] == '$')
+               return (NULL);
+
+       task = kmem_zalloc(sizeof (zvol_task_t), KM_SLEEP);
+       task->op = op;
+       task->snapdev = snapdev;
+       delim = strchr(name1, '/');
+       strlcpy(task->pool, name1, delim ? (delim - name1 + 1) : MAXNAMELEN);
+
+       strlcpy(task->name1, name1, MAXNAMELEN);
+       if (name2 != NULL)
+               strlcpy(task->name2, name2, MAXNAMELEN);
+
+       return (task);
+}
+
+static void
+zvol_task_free(zvol_task_t *task)
+{
+       kmem_free(task, sizeof (zvol_task_t));
+}
+
+/*
+ * The worker thread function performed asynchronously.
+ */
+static void
+zvol_task_cb(void *param)
+{
+       zvol_task_t *task = (zvol_task_t *)param;
+
+       switch (task->op) {
+       case ZVOL_ASYNC_CREATE_MINORS:
+               (void) zvol_create_minors_impl(task->name1);
+               break;
+       case ZVOL_ASYNC_REMOVE_MINORS:
+               zvol_remove_minors_impl(task->name1);
+               break;
+       case ZVOL_ASYNC_RENAME_MINORS:
+               zvol_rename_minors_impl(task->name1, task->name2);
+               break;
+       case ZVOL_ASYNC_SET_SNAPDEV:
+               zvol_set_snapdev_impl(task->name1, task->snapdev);
+               break;
+       default:
+               VERIFY(0);
+               break;
+       }
+
+       zvol_task_free(task);
+}
+
+typedef struct zvol_set_snapdev_arg {
+       const char *zsda_name;
+       uint64_t zsda_value;
+       zprop_source_t zsda_source;
+       dmu_tx_t *zsda_tx;
+} zvol_set_snapdev_arg_t;
+
+/*
+ * Sanity check the dataset for safe use by the sync task.  No additional
+ * conditions are imposed.
+ */
+static int
+zvol_set_snapdev_check(void *arg, dmu_tx_t *tx)
+{
+       zvol_set_snapdev_arg_t *zsda = arg;
+       dsl_pool_t *dp = dmu_tx_pool(tx);
+       dsl_dir_t *dd;
+       int error;
+
+       error = dsl_dir_hold(dp, zsda->zsda_name, FTAG, &dd, NULL);
+       if (error != 0)
+               return (error);
+
+       dsl_dir_rele(dd, FTAG);
+
+       return (error);
+}
+
+static int
+zvol_set_snapdev_sync_cb(dsl_pool_t *dp, dsl_dataset_t *ds, void *arg)
+{
+       zvol_set_snapdev_arg_t *zsda = arg;
+       char dsname[MAXNAMELEN];
+       zvol_task_t *task;
+
+       dsl_dataset_name(ds, dsname);
+       dsl_prop_set_sync_impl(ds, zfs_prop_to_name(ZFS_PROP_SNAPDEV),
+           zsda->zsda_source, sizeof (zsda->zsda_value), 1,
+           &zsda->zsda_value, zsda->zsda_tx);
+
+       task = zvol_task_alloc(ZVOL_ASYNC_SET_SNAPDEV, dsname,
+           NULL, zsda->zsda_value);
+       if (task == NULL)
+               return (0);
+
+       (void) taskq_dispatch(dp->dp_spa->spa_zvol_taskq, zvol_task_cb,
+               task, TQ_SLEEP);
+       return (0);
+}
+
+/*
+ * Traverse all child snapshot datasets and apply snapdev appropriately.
+ */
+static void
+zvol_set_snapdev_sync(void *arg, dmu_tx_t *tx)
+{
+       zvol_set_snapdev_arg_t *zsda = arg;
+       dsl_pool_t *dp = dmu_tx_pool(tx);
+       dsl_dir_t *dd;
+
+       VERIFY0(dsl_dir_hold(dp, zsda->zsda_name, FTAG, &dd, NULL));
+       zsda->zsda_tx = tx;
+
+       dmu_objset_find_dp(dp, dd->dd_object, zvol_set_snapdev_sync_cb,
+           zsda, DS_FIND_CHILDREN);
+
+       dsl_dir_rele(dd, FTAG);
+}
+
 int
-zvol_set_snapdev(const char *dsname, uint64_t snapdev) {
-       (void) dmu_objset_find((char *) dsname, snapdev_snapshot_changed_cb,
-               &snapdev, DS_FIND_SNAPSHOTS | DS_FIND_CHILDREN);
-       /* caller should continue to modify snapdev property */
-       return (-1);
+zvol_set_snapdev(const char *ddname, zprop_source_t source, uint64_t snapdev)
+{
+       zvol_set_snapdev_arg_t zsda;
+
+       zsda.zsda_name = ddname;
+       zsda.zsda_source = source;
+       zsda.zsda_value = snapdev;
+
+       return (dsl_sync_task(ddname, zvol_set_snapdev_check,
+           zvol_set_snapdev_sync, &zsda, 0, ZFS_SPACE_CHECK_NONE));
+}
+
+void
+zvol_create_minors(spa_t *spa, const char *name, boolean_t async)
+{
+       zvol_task_t *task;
+       taskqid_t id;
+
+       task = zvol_task_alloc(ZVOL_ASYNC_CREATE_MINORS, name, NULL, ~0ULL);
+       if (task == NULL)
+               return;
+
+       id = taskq_dispatch(spa->spa_zvol_taskq, zvol_task_cb, task, TQ_SLEEP);
+       if ((async == B_FALSE) && (id != 0))
+               taskq_wait_id(spa->spa_zvol_taskq, id);
+}
+
+void
+zvol_remove_minors(spa_t *spa, const char *name, boolean_t async)
+{
+       zvol_task_t *task;
+       taskqid_t id;
+
+       task = zvol_task_alloc(ZVOL_ASYNC_REMOVE_MINORS, name, NULL, ~0ULL);
+       if (task == NULL)
+               return;
+
+       id = taskq_dispatch(spa->spa_zvol_taskq, zvol_task_cb, task, TQ_SLEEP);
+       if ((async == B_FALSE) && (id != 0))
+               taskq_wait_id(spa->spa_zvol_taskq, id);
+}
+
+void
+zvol_rename_minors(spa_t *spa, const char *name1, const char *name2,
+    boolean_t async)
+{
+       zvol_task_t *task;
+       taskqid_t id;
+
+       task = zvol_task_alloc(ZVOL_ASYNC_RENAME_MINORS, name1, name2, ~0ULL);
+       if (task == NULL)
+               return;
+
+       id = taskq_dispatch(spa->spa_zvol_taskq, zvol_task_cb, task, TQ_SLEEP);
+       if ((async == B_FALSE) && (id != 0))
+               taskq_wait_id(spa->spa_zvol_taskq, id);
 }
 
 int
@@ -1603,7 +1893,6 @@ zvol_init(void)
 
        list_create(&zvol_state_list, sizeof (zvol_state_t),
            offsetof(zvol_state_t, zv_next));
-
        mutex_init(&zvol_state_lock, NULL, MUTEX_DEFAULT, NULL);
 
        error = register_blkdev(zvol_major, ZVOL_DRIVER);
@@ -1627,11 +1916,13 @@ out:
 void
 zvol_fini(void)
 {
-       zvol_remove_minors(NULL);
+       zvol_remove_minors_impl(NULL);
+
        blk_unregister_region(MKDEV(zvol_major, 0), 1UL << MINORBITS);
        unregister_blkdev(zvol_major, ZVOL_DRIVER);
-       mutex_destroy(&zvol_state_lock);
+
        list_destroy(&zvol_state_list);
+       mutex_destroy(&zvol_state_lock);
 }
 
 module_param(zvol_inhibit_dev, uint, 0644);
diff --git a/module/zpios/zpios.mod.c b/module/zpios/zpios.mod.c
new file mode 100644 (file)
index 0000000..bc848b5
--- /dev/null
@@ -0,0 +1,88 @@
+#include <linux/module.h>
+#include <linux/vermagic.h>
+#include <linux/compiler.h>
+
+MODULE_INFO(vermagic, VERMAGIC_STRING);
+
+struct module __this_module
+__attribute__((section(".gnu.linkonce.this_module"))) = {
+ .name = KBUILD_MODNAME,
+ .init = init_module,
+#ifdef CONFIG_MODULE_UNLOAD
+ .exit = cleanup_module,
+#endif
+ .arch = MODULE_ARCH_INIT,
+};
+
+static const struct modversion_info ____versions[]
+__used
+__attribute__((section("__versions"))) = {
+       { 0x51198477, "module_layout" },
+       { 0x3a8fb147, "dmu_tx_hold_free" },
+       { 0x6b85513b, "dmu_objset_create" },
+       { 0x4d73bbca, "dmu_object_set_blocksize" },
+       { 0x26b64321, "call_usermodehelper_setfns" },
+       { 0xdb347c7a, "call_usermodehelper_exec" },
+       { 0xadaabe1b, "pv_lock_ops" },
+       { 0xbf479b07, "dmu_tx_abort" },
+       { 0x4ff1c9bc, "populate_rootfs_wait" },
+       { 0xc8b57c27, "autoremove_wake_function" },
+       { 0x79aa04a2, "get_random_bytes" },
+       { 0x67053080, "current_kernel_time" },
+       { 0x71642c98, "dmu_tx_wait" },
+       { 0xab140103, "spl_kmem_alloc" },
+       { 0xba2adaf, "mutex_unlock" },
+       { 0xd3b65d9d, "kthread_create_on_node" },
+       { 0xbc32eee7, "spl_panic" },
+       { 0x4040455, "dmu_tx_commit" },
+       { 0x6395be94, "__init_waitqueue_head" },
+       { 0x4f8b5ddb, "_copy_to_user" },
+       { 0x114258fb, "misc_register" },
+       { 0xde0bdcff, "memset" },
+       { 0x69371301, "current_task" },
+       { 0x87ebeb76, "__mutex_init" },
+       { 0x27e1a049, "printk" },
+       { 0x4ebec927, "kthread_stop" },
+       { 0x81034537, "dmu_objset_disown" },
+       { 0xa1c76e0a, "_cond_resched" },
+       { 0x7ec9bfbc, "strncpy" },
+       { 0xb4390f9a, "mcount" },
+       { 0xafe1db9d, "mutex_lock" },
+       { 0x5bb6ad4b, "spl_vmem_zalloc" },
+       { 0x6357a5a8, "dmu_write" },
+       { 0x952664c5, "do_exit" },
+       { 0x7da403ec, "dsl_destroy_head" },
+       { 0x699a8466, "dmu_objset_own" },
+       { 0x8c51c50b, "dmu_object_free" },
+       { 0xf0fdf6cb, "__stack_chk_fail" },
+       { 0xd62c833f, "schedule_timeout" },
+       { 0x1000e51, "schedule" },
+       { 0x252f790a, "dmu_object_alloc" },
+       { 0xdae80439, "spl_vmem_alloc" },
+       { 0xcfa37f55, "wake_up_process" },
+       { 0xcd992a36, "dmu_tx_create" },
+       { 0xd52bf1ce, "_raw_spin_lock" },
+       { 0xcf21d241, "__wake_up" },
+       { 0x659a64d0, "call_usermodehelper_setup" },
+       { 0x236c8c64, "memcpy" },
+       { 0x5c8b5ce8, "prepare_to_wait" },
+       { 0xfa66f77c, "finish_wait" },
+       { 0xf005a1c7, "dmu_tx_assign" },
+       { 0x50720c5f, "snprintf" },
+       { 0x80c3f220, "spl_kmem_free" },
+       { 0xe55595ee, "dmu_read" },
+       { 0x778a305, "spl_vmem_free" },
+       { 0x4f6b400b, "_copy_from_user" },
+       { 0x2482e688, "vsprintf" },
+       { 0xdfb0b5e5, "misc_deregister" },
+       { 0xa296a969, "dmu_tx_hold_write" },
+       { 0x9dcb88fc, "spl_kmem_zalloc" },
+};
+
+static const char __module_depends[]
+__used
+__attribute__((section(".modinfo"))) =
+"depends=zfs,spl";
+
+
+MODULE_INFO(srcversion, "6224A8554C1154556C8A26B");
index 48d9f4ff62cad6bde7317b410be3f185e7ed2f45..3840604d1d2f76ecd2dde4f0d63f6f9a49c4f5e3 100644 (file)
@@ -186,6 +186,18 @@ chmod u+x ${RPM_BUILD_ROOT}%{kmodinstdir_prefix}/*/extra/*/*/*
 rm -rf $RPM_BUILD_ROOT
 
 %changelog
+* Tue Mar 22 2016 Ned Bass <bass6@llnl.gov> - 0.6.5.6-1
+- Remove artificial architecture restrictions in packaging
+- Add support for s390[x] zfsonlinux/zfs#4425
+- Handle negative dentries in case insensitive filesystem zfsonlinux/zfs#4243
+- Fix casesensitivity=insensitive deadlock zfsonlinux/zfs#4136
+- Correctly parse zdb -R flag arguments zfsonlinux/zfs#4304
+- Fix lock order inversion with zvol_open() zfsonlinux/zfs#3681
+- Add support for asynchronous zvol minor operations zfsonlinux/zfs#2217
+- Make zvol minor functionality more robust zfsonlinux/zfs#4344
+- Prevent zpool_find_vdev() from truncating vdev path zfsonlinux/zfs#4312
+- Add -gLP to zpool subcommands for alt vdev names zfsonlinux/zfs#4341
+- Fix zpool list -v output for spares and log devices zfsonlinux/zfs#4313
 * Wed Mar 9 2016 Ned Bass <bass6@llnl.gov> - 0.6.5.5-1
 - Linux 4.5 compatibility zfsonlinux/zfs#4228
 - Create working debuginfo packages on Red Hat zfsonlinux/zfs#4224
index 41419e6d60977f05ee22ce9c08b7230fb3536a80..55289df7d5c8139f754d68ad516d4504a3556fd9 100644 (file)
@@ -69,11 +69,6 @@ License:        @ZFS_META_LICENSE@
 URL:            http://zfsonlinux.org/
 Source0:        %{name}-%{version}.tar.gz
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-ExclusiveArch:  i386 i686 x86_64
-
-# May build but untested on ppc/ppc64
-ExcludeArch:    ppc ppc64
-
 Requires:       spl = %{version}
 Requires:       libzpool2 = %{version}
 Requires:       libnvpair1 = %{version}
@@ -332,6 +327,18 @@ exit 0
 %endif
 
 %changelog
+* Tue Mar 22 2016 Ned Bass <bass6@llnl.gov> - 0.6.5.6-1
+- Remove artificial architecture restrictions in packaging
+- Add support for s390[x] zfsonlinux/zfs#4425
+- Handle negative dentries in case insensitive filesystem zfsonlinux/zfs#4243
+- Fix casesensitivity=insensitive deadlock zfsonlinux/zfs#4136
+- Correctly parse zdb -R flag arguments zfsonlinux/zfs#4304
+- Fix lock order inversion with zvol_open() zfsonlinux/zfs#3681
+- Add support for asynchronous zvol minor operations zfsonlinux/zfs#2217
+- Make zvol minor functionality more robust zfsonlinux/zfs#4344
+- Prevent zpool_find_vdev() from truncating vdev path zfsonlinux/zfs#4312
+- Add -gLP to zpool subcommands for alt vdev names zfsonlinux/zfs#4341
+- Fix zpool list -v output for spares and log devices zfsonlinux/zfs#4313
 * Wed Mar 9 2016 Ned Bass <bass6@llnl.gov> - 0.6.5.5-1
 - Linux 4.5 compatibility zfsonlinux/zfs#4228
 - Create working debuginfo packages on Red Hat zfsonlinux/zfs#4224
index 41419e6d60977f05ee22ce9c08b7230fb3536a80..55289df7d5c8139f754d68ad516d4504a3556fd9 100644 (file)
@@ -69,11 +69,6 @@ License:        @ZFS_META_LICENSE@
 URL:            http://zfsonlinux.org/
 Source0:        %{name}-%{version}.tar.gz
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-ExclusiveArch:  i386 i686 x86_64
-
-# May build but untested on ppc/ppc64
-ExcludeArch:    ppc ppc64
-
 Requires:       spl = %{version}
 Requires:       libzpool2 = %{version}
 Requires:       libnvpair1 = %{version}
@@ -332,6 +327,18 @@ exit 0
 %endif
 
 %changelog
+* Tue Mar 22 2016 Ned Bass <bass6@llnl.gov> - 0.6.5.6-1
+- Remove artificial architecture restrictions in packaging
+- Add support for s390[x] zfsonlinux/zfs#4425
+- Handle negative dentries in case insensitive filesystem zfsonlinux/zfs#4243
+- Fix casesensitivity=insensitive deadlock zfsonlinux/zfs#4136
+- Correctly parse zdb -R flag arguments zfsonlinux/zfs#4304
+- Fix lock order inversion with zvol_open() zfsonlinux/zfs#3681
+- Add support for asynchronous zvol minor operations zfsonlinux/zfs#2217
+- Make zvol minor functionality more robust zfsonlinux/zfs#4344
+- Prevent zpool_find_vdev() from truncating vdev path zfsonlinux/zfs#4312
+- Add -gLP to zpool subcommands for alt vdev names zfsonlinux/zfs#4341
+- Fix zpool list -v output for spares and log devices zfsonlinux/zfs#4313
 * Wed Mar 9 2016 Ned Bass <bass6@llnl.gov> - 0.6.5.5-1
 - Linux 4.5 compatibility zfsonlinux/zfs#4228
 - Create working debuginfo packages on Red Hat zfsonlinux/zfs#4224
index 45ccf62ed02baaff3025ac56c1e53cee92bf0848..1908dc1d691963f58d904d5df9a6d766569824b7 100755 (executable)
@@ -217,15 +217,26 @@ test_3() {
        zconfig_zvol_device_stat 10 ${POOL_NAME} ${FULL_ZVOL_NAME} \
            ${FULL_SNAP_NAME} ${FULL_CLONE_NAME} || fail 11
 
+       # Toggle the snapdev and observe snapshot device links toggled
+       ${ZFS} set snapdev=hidden ${FULL_ZVOL_NAME} || fail 12
+       
+       zconfig_zvol_device_stat 7 ${POOL_NAME} ${FULL_ZVOL_NAME} \
+           "invalid" ${FULL_CLONE_NAME} || fail 13
+
+       ${ZFS} set snapdev=visible ${FULL_ZVOL_NAME} || fail 14
+
+       zconfig_zvol_device_stat 10 ${POOL_NAME} ${FULL_ZVOL_NAME} \
+           ${FULL_SNAP_NAME} ${FULL_CLONE_NAME} || fail 15
+
        # Destroy the pool and consequently the devices
-       ${ZPOOL_CREATE_SH} -p ${POOL_NAME} -c lo-raidz2 -d || fail 12
+       ${ZPOOL_CREATE_SH} -p ${POOL_NAME} -c lo-raidz2 -d || fail 16
 
        # verify the devices were removed
        zconfig_zvol_device_stat 0 ${POOL_NAME} ${FULL_ZVOL_NAME} \
-           ${FULL_SNAP_NAME} ${FULL_CLONE_NAME} || fail 13
+           ${FULL_SNAP_NAME} ${FULL_CLONE_NAME} || fail 17
 
-       ${ZFS_SH} -u || fail 14
-       rm -f ${TMP_CACHE} || fail 15
+       ${ZFS_SH} -u || fail 18
+       rm -f ${TMP_CACHE} || fail 19
 
        pass
 }