diff options
Diffstat (limited to 'cmd/zfs/zfs_main.c')
-rw-r--r-- | cmd/zfs/zfs_main.c | 114 |
1 files changed, 92 insertions, 22 deletions
diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index 0ebd16f6d..53b76e25d 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -254,9 +254,9 @@ get_usage(zfs_help_t idx) return (gettext("\tclone [-p] [-o property=value] ... " "<snapshot> <filesystem|volume>\n")); case HELP_CREATE: - return (gettext("\tcreate [-p] [-o property=value] ... " + return (gettext("\tcreate [-Pnpv] [-o property=value] ... " "<filesystem>\n" - "\tcreate [-ps] [-b blocksize] [-o property=value] ... " + "\tcreate [-Pnpsv] [-b blocksize] [-o property=value] ... " "-V <size> <volume>\n")); case HELP_DESTROY: return (gettext("\tdestroy [-fnpRrv] <filesystem|volume>\n" @@ -867,8 +867,8 @@ usage: } /* - * zfs create [-p] [-o prop=value] ... fs - * zfs create [-ps] [-b blocksize] [-o prop=value] ... -V vol size + * zfs create [-Pnpv] [-o prop=value] ... fs + * zfs create [-Pnpsv] [-b blocksize] [-o prop=value] ... -V vol size * * Create a new dataset. This command can be used to create filesystems * and volumes. Snapshot creation is handled by 'zfs snapshot'. @@ -880,16 +880,29 @@ usage: * SPA_VERSION_REFRESERVATION, we set a refreservation instead. * * The '-p' flag creates all the non-existing ancestors of the target first. + * + * The '-n' flag is no-op (dry run) mode. This will perform a user-space sanity + * check of arguments and properties, but does not check for permissions, + * available space, etc. + * + * The '-v' flag is for verbose output. + * + * The '-P' flag is used for parseable output. It implies '-v'. */ static int zfs_do_create(int argc, char **argv) { zfs_type_t type = ZFS_TYPE_FILESYSTEM; + zpool_handle_t *zpool_handle = NULL; + nvlist_t *real_props = NULL; uint64_t volsize = 0; int c; boolean_t noreserve = B_FALSE; boolean_t bflag = B_FALSE; boolean_t parents = B_FALSE; + boolean_t dryrun = B_FALSE; + boolean_t verbose = B_FALSE; + boolean_t parseable = B_FALSE; int ret = 1; nvlist_t *props; uint64_t intval; @@ -898,7 +911,7 @@ zfs_do_create(int argc, char **argv) nomem(); /* check options */ - while ((c = getopt(argc, argv, ":V:b:so:p")) != -1) { + while ((c = getopt(argc, argv, ":PV:b:nso:pv")) != -1) { switch (c) { case 'V': type = ZFS_TYPE_VOLUME; @@ -914,6 +927,10 @@ zfs_do_create(int argc, char **argv) nomem(); volsize = intval; break; + case 'P': + verbose = B_TRUE; + parseable = B_TRUE; + break; case 'p': parents = B_TRUE; break; @@ -931,6 +948,9 @@ zfs_do_create(int argc, char **argv) intval) != 0) nomem(); break; + case 'n': + dryrun = B_TRUE; + break; case 'o': if (!parseprop(props, optarg)) goto error; @@ -938,6 +958,9 @@ zfs_do_create(int argc, char **argv) case 's': noreserve = B_TRUE; break; + case 'v': + verbose = B_TRUE; + break; case ':': (void) fprintf(stderr, gettext("missing size " "argument\n")); @@ -969,14 +992,9 @@ zfs_do_create(int argc, char **argv) goto badusage; } - if (type == ZFS_TYPE_VOLUME && !noreserve) { - zpool_handle_t *zpool_handle; - nvlist_t *real_props = NULL; - uint64_t spa_version; + if (dryrun || (type == ZFS_TYPE_VOLUME && !noreserve)) { + char msg[ZFS_MAX_DATASET_NAME_LEN * 2]; char *p; - zfs_prop_t resv_prop; - char *strval; - char msg[1024]; if ((p = strchr(argv[0], '/')) != NULL) *p = '\0'; @@ -985,25 +1003,31 @@ zfs_do_create(int argc, char **argv) *p = '/'; if (zpool_handle == NULL) goto error; - spa_version = zpool_get_prop_int(zpool_handle, - ZPOOL_PROP_VERSION, NULL); - if (spa_version >= SPA_VERSION_REFRESERVATION) - resv_prop = ZFS_PROP_REFRESERVATION; - else - resv_prop = ZFS_PROP_RESERVATION; (void) snprintf(msg, sizeof (msg), + dryrun ? gettext("cannot verify '%s'") : gettext("cannot create '%s'"), argv[0]); if (props && (real_props = zfs_valid_proplist(g_zfs, type, props, 0, NULL, zpool_handle, B_TRUE, msg)) == NULL) { zpool_close(zpool_handle); goto error; } + } + + if (type == ZFS_TYPE_VOLUME && !noreserve) { + uint64_t spa_version; + zfs_prop_t resv_prop; + char *strval; + + spa_version = zpool_get_prop_int(zpool_handle, + ZPOOL_PROP_VERSION, NULL); + if (spa_version >= SPA_VERSION_REFRESERVATION) + resv_prop = ZFS_PROP_REFRESERVATION; + else + resv_prop = ZFS_PROP_RESERVATION; volsize = zvol_volsize_to_reservation(zpool_handle, volsize, real_props); - nvlist_free(real_props); - zpool_close(zpool_handle); if (nvlist_lookup_string(props, zfs_prop_to_name(resv_prop), &strval) != 0) { @@ -1014,6 +1038,10 @@ zfs_do_create(int argc, char **argv) } } } + if (zpool_handle != NULL) { + zpool_close(zpool_handle); + nvlist_free(real_props); + } if (parents && zfs_name_valid(argv[0], type)) { /* @@ -1025,8 +1053,50 @@ zfs_do_create(int argc, char **argv) ret = 0; goto error; } - if (zfs_create_ancestors(g_zfs, argv[0]) != 0) - goto error; + if (verbose) { + (void) printf(parseable ? "create_ancestors\t%s\n" : + dryrun ? "would create ancestors of %s\n" : + "create ancestors of %s\n", argv[0]); + } + if (!dryrun) { + if (zfs_create_ancestors(g_zfs, argv[0]) != 0) { + goto error; + } + } + } + + if (verbose) { + nvpair_t *nvp = NULL; + (void) printf(parseable ? "create\t%s\n" : + dryrun ? "would create %s\n" : "create %s\n", argv[0]); + while ((nvp = nvlist_next_nvpair(props, nvp)) != NULL) { + uint64_t uval; + char *sval; + + switch (nvpair_type(nvp)) { + case DATA_TYPE_UINT64: + VERIFY0(nvpair_value_uint64(nvp, &uval)); + (void) printf(parseable ? + "property\t%s\t%llu\n" : "\t%s=%llu\n", + nvpair_name(nvp), (u_longlong_t)uval); + break; + case DATA_TYPE_STRING: + VERIFY0(nvpair_value_string(nvp, &sval)); + (void) printf(parseable ? + "property\t%s\t%s\n" : "\t%s=%s\n", + nvpair_name(nvp), sval); + break; + default: + (void) fprintf(stderr, "property '%s' " + "has illegal type %d\n", + nvpair_name(nvp), nvpair_type(nvp)); + abort(); + } + } + } + if (dryrun) { + ret = 0; + goto error; } /* pass to libzfs */ |