diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c index 13577d13c53f..ff54db8d2be6 100644 --- a/cmd/zpool/zpool_main.c +++ b/cmd/zpool/zpool_main.c @@ -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); diff --git a/include/sys/fs/zfs.h b/include/sys/fs/zfs.h index 24ad768c0ac5..477d98daa173 100644 --- a/include/sys/fs/zfs.h +++ b/include/sys/fs/zfs.h @@ -196,6 +196,7 @@ typedef enum { ZPOOL_PROP_FREEING, ZPOOL_PROP_FRAGMENTATION, ZPOOL_PROP_LEAKED, + ZPOOL_PROP_TNAME, ZPOOL_NUM_PROPS } zpool_prop_t; diff --git a/lib/libzfs/libzfs_pool.c b/lib/libzfs/libzfs_pool.c index b94974b83f2f..fe26abeb7235 100644 --- a/lib/libzfs/libzfs_pool.c +++ b/lib/libzfs/libzfs_pool.c @@ -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; } } diff --git a/man/man8/zpool.8 b/man/man8/zpool.8 index ecf898cbdbfe..00c19305a63a 100644 --- a/man/man8/zpool.8 +++ b/man/man8/zpool.8 @@ -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 diff --git a/module/zcommon/zpool_prop.c b/module/zcommon/zpool_prop.c index 6bde4f471a18..e5f69c8152d4 100644 --- a/module/zcommon/zpool_prop.c +++ b/module/zcommon/zpool_prop.c @@ -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"); } /* diff --git a/module/zfs/spa.c b/module/zfs/spa.c index 62887122d5e4..d96bda3fa8b3 100644 --- a/module/zfs/spa.c +++ b/module/zfs/spa.c @@ -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)) {