]> granicus.if.org Git - zfs/commitdiff
Implement -t option to zpool create for temporary pool names
authorRichard Yao <ryao@gentoo.org>
Fri, 20 Jun 2014 23:00:11 +0000 (19:00 -0400)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 30 Sep 2014 17:46:59 +0000 (10:46 -0700)
Creating virtual machines that have their rootfs on ZFS on hosts that
have their rootfs on ZFS causes SPA namespace collisions when the
standard name rpool is used. The solution is either to give each guest
pool a name unique to the host, which is not always desireable, or boot
a VM environment containing an ISO image to install it, which is
cumbersome.

26b42f3f9d03f85cc7966dc2fe4dfe9216601b0e introduced `zpool import -t
...` to simplify situations where a host must access a guest's pool when
there is a SPA namespace conflict. We build upon that to introduce
`zpool import -t tname ...`. That allows us to create a pool whose
in-core name is tname, but whose on-disk name is the normal name
specified.

This simplifies the creation of machine images that use a rootfs on ZFS.
That benefits not only real world deployments, but also ZFSOnLinux
development by decreasing the time needed to perform rootfs on ZFS
experiments.

Signed-off-by: Richard Yao <ryao@gentoo.org>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Issue #2417

cmd/zpool/zpool_main.c
include/sys/fs/zfs.h
lib/libzfs/libzfs_pool.c
man/man8/zpool.8
module/zcommon/zpool_prop.c
module/zfs/spa.c

index 13577d13c53fdb0e90f0efee8767a1de7b5dc2bb..ff54db8d2be6f711ddea9c1f5858274bcac9bbc7 100644 (file)
@@ -822,7 +822,7 @@ zpool_do_create(int argc, char **argv)
        char *propval;
 
        /* check options */
-       while ((c = getopt(argc, argv, ":fndR:m:o:O:")) != -1) {
+       while ((c = getopt(argc, argv, ":fndR:m:o:O:t:")) != -1) {
                switch (c) {
                case 'f':
                        force = B_TRUE;
@@ -895,6 +895,26 @@ zpool_do_create(int argc, char **argv)
                                goto errout;
                        }
                        break;
+               case 't':
+                       /*
+                        * Sanity check temporary pool name.
+                        */
+                       if (strchr(optarg, '/') != NULL) {
+                               (void) fprintf(stderr, gettext("cannot create "
+                                   "'%s': invalid character '/' in temporary "
+                                   "name\n"), optarg);
+                               (void) fprintf(stderr, gettext("use 'zfs "
+                                   "create' to create a dataset\n"));
+                               goto errout;
+                       }
+
+                       if (add_prop_list(zpool_prop_to_name(
+                           ZPOOL_PROP_TNAME), optarg, &props, B_TRUE))
+                               goto errout;
+                       if (add_prop_list_default(zpool_prop_to_name(
+                           ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
+                               goto errout;
+                       break;
                case ':':
                        (void) fprintf(stderr, gettext("missing argument for "
                            "'%c' option\n"), optopt);
index 24ad768c0ac56841289265e25e1d4a30d2c5fe89..477d98daa173338a70d638259428c6117a5b8af7 100644 (file)
@@ -196,6 +196,7 @@ typedef enum {
        ZPOOL_PROP_FREEING,
        ZPOOL_PROP_FRAGMENTATION,
        ZPOOL_PROP_LEAKED,
+       ZPOOL_PROP_TNAME,
        ZPOOL_NUM_PROPS
 } zpool_prop_t;
 
index b94974b83f2f9d5838fac5f30197bc59280f01c0..fe26abeb72357edfd8392300fc0897a75c5eb626 100644 (file)
@@ -710,6 +710,15 @@ zpool_valid_proplist(libzfs_handle_t *hdl, const char *poolname,
                                goto error;
                        }
                        break;
+               case ZPOOL_PROP_TNAME:
+                       if (!flags.create) {
+                               zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+                                   "property '%s' can only be set at "
+                                   "creation time"), propname);
+                               (void) zfs_error(hdl, EZFS_BADPROP, errbuf);
+                               goto error;
+                       }
+                       break;
                }
        }
 
index ecf898cbdbfeadd24492430ab710c7415c2cb159..00c19305a63a3746a23ee18763587798589484f3 100644 (file)
@@ -42,7 +42,7 @@ zpool \- configures ZFS storage pools
 .LP
 .nf
 \fBzpool create\fR [\fB-fnd\fR] [\fB-o\fR \fIproperty=value\fR] ... [\fB-O\fR \fIfile-system-property=value\fR]
-     ... [\fB-m\fR \fImountpoint\fR] [\fB-R\fR \fIroot\fR] \fIpool\fR \fIvdev\fR ...
+     ... [\fB-m\fR \fImountpoint\fR] [\fB-R\fR \fIroot\fR] [\fB-t\fR \fItname\fR] \fIpool\fR \fIvdev\fR ...
 .fi
 
 .LP
@@ -920,7 +920,7 @@ Clears device errors in a pool. If no arguments are specified, all device errors
 .ne 2
 .mk
 .na
-\fB\fBzpool create\fR [\fB-fnd\fR] [\fB-o\fR \fIproperty=value\fR] ... [\fB-O\fR \fIfile-system-property=value\fR] ... [\fB-m\fR \fImountpoint\fR] [\fB-R\fR \fIroot\fR] \fIpool\fR \fIvdev\fR ...\fR
+\fB\fBzpool create\fR [\fB-fnd\fR] [\fB-o\fR \fIproperty=value\fR] ... [\fB-O\fR \fIfile-system-property=value\fR] ... [\fB-m\fR \fImountpoint\fR] [\fB-R\fR \fIroot\fR] [\fB-t\fR \fItname\fR] \fIpool\fR \fIvdev\fR ...\fR
 .ad
 .sp .6
 .RS 4n
@@ -1013,6 +1013,17 @@ Equivalent to "-o cachefile=none,altroot=\fIroot\fR"
 Sets the mount point for the root dataset. The default mount point is "/\fIpool\fR" or "\fBaltroot\fR/\fIpool\fR" if \fBaltroot\fR is specified. The mount point must be an absolute path, "\fBlegacy\fR", or "\fBnone\fR". For more information on dataset mount points, see \fBzfs\fR(8).
 .RE
 
+.sp
+.ne 2
+.mk
+.na
+\fB\fB-t\fR \fItname\fR\fR
+.ad
+.sp .6
+.RS 4n
+Sets the in-core pool name to "\fBtname\fR" while the on-disk name will be the name specified as the pool name "\fBpool\fR". This will set the default cachefile property to none. This is intended to handle name space collisions when creating pools for other systems, such as virtual machines or physical machines whose pools live on network block devices.
+.RE
+
 .RE
 
 .sp
index 6bde4f471a186a7a6371dd50c2e678a203572124..e5f69c8152d46a9d32ad6d5489a1ae6d2a934b93 100644 (file)
@@ -131,6 +131,8 @@ zpool_prop_init(void)
        /* hidden properties */
        zprop_register_hidden(ZPOOL_PROP_NAME, "name", PROP_TYPE_STRING,
            PROP_READONLY, ZFS_TYPE_POOL, "NAME");
+       zprop_register_hidden(ZPOOL_PROP_TNAME, "tname", PROP_TYPE_STRING,
+           PROP_ONETIME, ZFS_TYPE_POOL, "TNAME");
 }
 
 /*
index 62887122d5e496844d0a1cfcf70555f6b0062797..d96bda3fa8b31c488b43341ea72cd9d19adc1b9b 100644 (file)
@@ -3496,12 +3496,17 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
        boolean_t has_features;
        nvpair_t *elem;
        int c;
+       char *poolname;
+       nvlist_t *nvl;
+
+       if (nvlist_lookup_string(props, "tname", &poolname) != 0)
+               poolname = (char *)pool;
 
        /*
         * If this pool already exists, return failure.
         */
        mutex_enter(&spa_namespace_lock);
-       if (spa_lookup(pool) != NULL) {
+       if (spa_lookup(poolname) != NULL) {
                mutex_exit(&spa_namespace_lock);
                return (SET_ERROR(EEXIST));
        }
@@ -3509,9 +3514,12 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
        /*
         * Allocate a new spa_t structure.
         */
+       nvl = fnvlist_alloc();
+       fnvlist_add_string(nvl, ZPOOL_CONFIG_POOL_NAME, pool);
        (void) nvlist_lookup_string(props,
            zpool_prop_to_name(ZPOOL_PROP_ALTROOT), &altroot);
-       spa = spa_add(pool, NULL, altroot);
+       spa = spa_add(poolname, nvl, altroot);
+       fnvlist_free(nvl);
        spa_activate(spa, spa_mode_global);
 
        if (props && (error = spa_prop_validate(spa, props))) {
@@ -3521,6 +3529,12 @@ spa_create(const char *pool, nvlist_t *nvroot, nvlist_t *props,
                return (error);
        }
 
+       /*
+        * Temporary pool names should never be written to disk.
+        */
+       if (poolname != pool)
+               spa->spa_import_flags |= ZFS_IMPORT_TEMP_NAME;
+
        has_features = B_FALSE;
        for (elem = nvlist_next_nvpair(props, NULL);
            elem != NULL; elem = nvlist_next_nvpair(props, elem)) {