diff options
author | Brian Behlendorf <[email protected]> | 2009-08-18 11:43:27 -0700 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2009-08-18 11:43:27 -0700 |
commit | 45d1cae3b8c949ecc391dd7a5b81963b34c71c29 (patch) | |
tree | 69b1f860eb1f9b1ebdef392760814c5cc089f345 /cmd | |
parent | 9babb37438b58e77bad04e820d5702e15b79e6a6 (diff) |
Rebase master to b121
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/zdb/zdb.c | 3 | ||||
-rw-r--r-- | cmd/zfs/zfs_iter.c | 2 | ||||
-rw-r--r-- | cmd/zfs/zfs_main.c | 151 | ||||
-rw-r--r-- | cmd/zpool/zpool_main.c | 34 | ||||
-rw-r--r-- | cmd/zpool/zpool_vdev.c | 47 | ||||
-rw-r--r-- | cmd/ztest/ztest.c | 18 |
6 files changed, 211 insertions, 44 deletions
diff --git a/cmd/zdb/zdb.c b/cmd/zdb/zdb.c index a310fc38b..292bb519a 100644 --- a/cmd/zdb/zdb.c +++ b/cmd/zdb/zdb.c @@ -818,6 +818,8 @@ dump_dsl_dataset(objset_t *os, uint64_t object, void *data, size_t size) (u_longlong_t)ds->ds_snapnames_zapobj); (void) printf("\t\tnum_children = %llu\n", (u_longlong_t)ds->ds_num_children); + (void) printf("\t\tuserrefs_obj = %llu\n", + (u_longlong_t)ds->ds_userrefs_obj); (void) printf("\t\tcreation_time = %s", ctime(&crtime)); (void) printf("\t\tcreation_txg = %llu\n", (u_longlong_t)ds->ds_creation_txg); @@ -1049,6 +1051,7 @@ static object_viewer_t *object_viewer[DMU_OT_NUMTYPES] = { dump_zap, /* DSL scrub queue */ dump_zap, /* ZFS user/group used */ dump_zap, /* ZFS user/group quota */ + dump_zap, /* snapshot refcount tags */ }; static void diff --git a/cmd/zfs/zfs_iter.c b/cmd/zfs/zfs_iter.c index ca5c2b232..04dd2bdeb 100644 --- a/cmd/zfs/zfs_iter.c +++ b/cmd/zfs/zfs_iter.c @@ -362,7 +362,7 @@ zfs_for_each(int argc, char **argv, int flags, zfs_type_t types, cb.cb_types = types; cb.cb_depth_limit = limit; /* - * If cb_proplist is provided then in the zfs_handles created we + * If cb_proplist is provided then in the zfs_handles created we * retain only those properties listed in cb_proplist and sortcol. * The rest are pruned. So, the caller should make sure that no other * properties other than those listed in cb_proplist/sortcol are diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index 0752a4772..1fbd8bc65 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -80,6 +80,8 @@ static int zfs_do_receive(int argc, char **argv); static int zfs_do_promote(int argc, char **argv); static int zfs_do_userspace(int argc, char **argv); static int zfs_do_python(int argc, char **argv); +static int zfs_do_hold(int argc, char **argv); +static int zfs_do_release(int argc, char **argv); /* * Enable a reasonable set of defaults for libumem debugging on DEBUG builds. @@ -121,7 +123,10 @@ typedef enum { HELP_ALLOW, HELP_UNALLOW, HELP_USERSPACE, - HELP_GROUPSPACE + HELP_GROUPSPACE, + HELP_HOLD, + HELP_HOLDS, + HELP_RELEASE } zfs_help_t; typedef struct zfs_command { @@ -169,6 +174,10 @@ static zfs_command_t command_table[] = { { "allow", zfs_do_python, HELP_ALLOW }, { NULL }, { "unallow", zfs_do_python, HELP_UNALLOW }, + { NULL }, + { "hold", zfs_do_hold, HELP_HOLD }, + { "holds", zfs_do_python, HELP_HOLDS }, + { "release", zfs_do_release, HELP_RELEASE }, }; #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0])) @@ -189,7 +198,8 @@ get_usage(zfs_help_t idx) "-V <size> <volume>\n")); case HELP_DESTROY: return (gettext("\tdestroy [-rRf] " - "<filesystem|volume|snapshot>\n")); + "<filesystem|volume|snapshot>\n" + "\tdestroy -d [-r] <filesystem|volume|snapshot>\n")); case HELP_GET: return (gettext("\tget [-rHp] [-d max] " "[-o field[,...]] [-s source[,...]]\n" @@ -236,7 +246,7 @@ get_usage(zfs_help_t idx) return (gettext("\tunmount [-f] " "<-a | filesystem|mountpoint>\n")); case HELP_UNSHARE: - return (gettext("\tunshare [-f] " + return (gettext("\tunshare " "<-a | filesystem|mountpoint>\n")); case HELP_ALLOW: return (gettext("\tallow <filesystem|volume>\n" @@ -266,6 +276,12 @@ get_usage(zfs_help_t idx) return (gettext("\tgroupspace [-hniHpU] [-o field[,...]] " "[-sS field] ... [-t type[,...]]\n" "\t <filesystem|snapshot>\n")); + case HELP_HOLD: + return (gettext("\thold [-r] <tag> <snapshot> ...\n")); + case HELP_HOLDS: + return (gettext("\tholds [-r] <snapshot> ...\n")); + case HELP_RELEASE: + return (gettext("\trelease [-r] <tag> <snapshot> ...\n")); } abort(); @@ -769,11 +785,13 @@ badusage: } /* - * zfs destroy [-rf] <fs, snap, vol> + * zfs destroy [-rRf] <fs, snap, vol> + * zfs destroy -d [-r] <fs, snap, vol> * * -r Recursively destroy all children * -R Recursively destroy all dependents, including clones * -f Force unmounting of any dependents + * -d If we can't destroy now, mark for deferred destruction * * Destroys the given dataset. By default, it will unmount any filesystems, * and refuse to destroy a dataset that has any dependents. A dependent can @@ -789,6 +807,7 @@ typedef struct destroy_cbdata { boolean_t cb_closezhp; zfs_handle_t *cb_target; char *cb_snapname; + boolean_t cb_defer_destroy; } destroy_cbdata_t; /* @@ -869,7 +888,7 @@ destroy_callback(zfs_handle_t *zhp, void *data) * Bail out on the first error. */ if (zfs_unmount(zhp, NULL, cbp->cb_force ? MS_FORCE : 0) != 0 || - zfs_destroy(zhp) != 0) { + zfs_destroy(zhp, cbp->cb_defer_destroy) != 0) { zfs_close(zhp); return (-1); } @@ -923,8 +942,11 @@ zfs_do_destroy(int argc, char **argv) char *cp; /* check options */ - while ((c = getopt(argc, argv, "frR")) != -1) { + while ((c = getopt(argc, argv, "dfrR")) != -1) { switch (c) { + case 'd': + cb.cb_defer_destroy = B_TRUE; + break; case 'f': cb.cb_force = 1; break; @@ -956,6 +978,9 @@ zfs_do_destroy(int argc, char **argv) usage(B_FALSE); } + if (cb.cb_defer_destroy && cb.cb_doclones) + usage(B_FALSE); + /* * If we are doing recursive destroy of a snapshot, then the * named snapshot may not exist. Go straight to libzfs. @@ -977,7 +1002,7 @@ zfs_do_destroy(int argc, char **argv) } } - ret = zfs_destroy_snaps(zhp, cp); + ret = zfs_destroy_snaps(zhp, cp, cb.cb_defer_destroy); zfs_close(zhp); if (ret) { (void) fprintf(stderr, @@ -986,7 +1011,6 @@ zfs_do_destroy(int argc, char **argv) return (ret != 0); } - /* Open the given dataset */ if ((zhp = zfs_open(g_zfs, argv[0], ZFS_TYPE_DATASET)) == NULL) return (1); @@ -1014,15 +1038,15 @@ zfs_do_destroy(int argc, char **argv) * Check for any dependents and/or clones. */ cb.cb_first = B_TRUE; - if (!cb.cb_doclones && + if (!cb.cb_doclones && !cb.cb_defer_destroy && zfs_iter_dependents(zhp, B_TRUE, destroy_check_dependent, &cb) != 0) { zfs_close(zhp); return (1); } - if (cb.cb_error || - zfs_iter_dependents(zhp, B_FALSE, destroy_callback, &cb) != 0) { + if (cb.cb_error || (!cb.cb_defer_destroy && + (zfs_iter_dependents(zhp, B_FALSE, destroy_callback, &cb) != 0))) { zfs_close(zhp); return (1); } @@ -1035,7 +1059,6 @@ zfs_do_destroy(int argc, char **argv) if (destroy_callback(zhp, &cb) != 0) return (1); - return (0); } @@ -1613,7 +1636,7 @@ zfs_do_upgrade(int argc, char **argv) (void) printf(gettext(" 1 Initial ZFS filesystem version\n")); (void) printf(gettext(" 2 Enhanced directory entries\n")); (void) printf(gettext(" 3 Case insensitive and File system " - "unique identifer (FUID)\n")); + "unique identifier (FUID)\n")); (void) printf(gettext(" 4 userquota, groupquota " "properties\n")); (void) printf(gettext("\nFor more information on a particular " @@ -2651,6 +2674,108 @@ zfs_do_receive(int argc, char **argv) return (err != 0); } +static int +zfs_do_hold_rele_impl(int argc, char **argv, boolean_t holding) +{ + int errors = 0; + int i; + const char *tag; + boolean_t recursive = B_FALSE; + int c; + int (*func)(zfs_handle_t *, const char *, const char *, boolean_t); + + /* check options */ + while ((c = getopt(argc, argv, "r")) != -1) { + switch (c) { + case 'r': + recursive = B_TRUE; + break; + case '?': + (void) fprintf(stderr, gettext("invalid option '%c'\n"), + optopt); + usage(B_FALSE); + } + } + + argc -= optind; + argv += optind; + + /* check number of arguments */ + if (argc < 2) + usage(B_FALSE); + + tag = argv[0]; + --argc; + ++argv; + + if (holding) { + if (tag[0] == '.') { + /* tags starting with '.' are reserved for libzfs */ + (void) fprintf(stderr, + gettext("tag may not start with '.'\n")); + usage(B_FALSE); + } + func = zfs_hold; + } else { + func = zfs_release; + } + + for (i = 0; i < argc; ++i) { + zfs_handle_t *zhp; + char parent[ZFS_MAXNAMELEN]; + const char *delim; + char *path = argv[i]; + + delim = strchr(path, '@'); + if (delim == NULL) { + (void) fprintf(stderr, + gettext("'%s' is not a snapshot\n"), path); + ++errors; + continue; + } + (void) strncpy(parent, path, delim - path); + parent[delim - path] = '\0'; + + zhp = zfs_open(g_zfs, parent, + ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME); + if (zhp == NULL) { + ++errors; + continue; + } + if (func(zhp, delim+1, tag, recursive) != 0) + ++errors; + zfs_close(zhp); + } + + return (errors != 0); +} + +/* + * zfs hold [-r] <tag> <snap> ... + * + * -r Recursively hold + * + * Apply a user-hold with the given tag to the list of snapshots. + */ +static int +zfs_do_hold(int argc, char **argv) +{ + return (zfs_do_hold_rele_impl(argc, argv, B_TRUE)); +} + +/* + * zfs release [-r] <tag> <snap> ... + * + * -r Recursively release + * + * Release a user-hold with the given tag from the list of snapshots. + */ +static int +zfs_do_release(int argc, char **argv) +{ + return (zfs_do_hold_rele_impl(argc, argv, B_FALSE)); +} + typedef struct get_all_cbdata { zfs_handle_t **cb_handles; size_t cb_alloc; diff --git a/cmd/zpool/zpool_main.c b/cmd/zpool/zpool_main.c index c8a33df4d..c9b092e44 100644 --- a/cmd/zpool/zpool_main.c +++ b/cmd/zpool/zpool_main.c @@ -1469,7 +1469,7 @@ show_import(nvlist_t *config) */ static int do_import(nvlist_t *config, const char *newname, const char *mntopts, - int force, nvlist_t *props, boolean_t allowfaulted) + int force, nvlist_t *props, boolean_t do_verbatim) { zpool_handle_t *zhp; char *name; @@ -1522,14 +1522,14 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts, } } - if (zpool_import_props(g_zfs, config, newname, props, - allowfaulted) != 0) + if (zpool_import_props(g_zfs, config, newname, props, do_verbatim) != 0) return (1); if (newname != NULL) name = (char *)newname; - verify((zhp = zpool_open_canfail(g_zfs, name)) != NULL); + if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL) + return (1); if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL && zpool_enable_datasets(zhp, mntopts, 0) != 0) { @@ -1566,7 +1566,8 @@ do_import(nvlist_t *config, const char *newname, const char *mntopts, * -F Import even in the presence of faulted vdevs. This is an * intentionally undocumented option for testing purposes, and * treats the pool configuration as complete, leaving any bad - * vdevs in the FAULTED state. + * vdevs in the FAULTED state. In other words, it does verbatim + * import. * * -a Import all pools found. * @@ -1595,7 +1596,7 @@ zpool_do_import(int argc, char **argv) nvlist_t *found_config; nvlist_t *props = NULL; boolean_t first; - boolean_t allow_faulted = B_FALSE; + boolean_t do_verbatim = B_FALSE; uint64_t pool_state; char *cachefile = NULL; @@ -1628,7 +1629,7 @@ zpool_do_import(int argc, char **argv) do_force = B_TRUE; break; case 'F': - allow_faulted = B_TRUE; + do_verbatim = B_TRUE; break; case 'o': if ((propval = strchr(optarg, '=')) != NULL) { @@ -1778,7 +1779,7 @@ zpool_do_import(int argc, char **argv) if (do_all) err |= do_import(config, NULL, mntopts, - do_force, props, allow_faulted); + do_force, props, do_verbatim); else show_import(config); } else if (searchname != NULL) { @@ -1826,7 +1827,7 @@ zpool_do_import(int argc, char **argv) err = B_TRUE; } else { err |= do_import(found_config, argc == 1 ? NULL : - argv[1], mntopts, do_force, props, allow_faulted); + argv[1], mntopts, do_force, props, do_verbatim); } } @@ -3117,6 +3118,17 @@ status_callback(zpool_handle_t *zhp, void *data) "replace'.\n")); break; + case ZPOOL_STATUS_REMOVED_DEV: + (void) printf(gettext("status: One or more devices has " + "been removed by the administrator.\n\tSufficient " + "replicas exist for the pool to continue functioning in " + "a\n\tdegraded state.\n")); + (void) printf(gettext("action: Online the device using " + "'zpool online' or replace the device with\n\t'zpool " + "replace'.\n")); + break; + + case ZPOOL_STATUS_RESILVERING: (void) printf(gettext("status: One or more devices is " "currently being resilvered. The pool will\n\tcontinue " @@ -3539,6 +3551,8 @@ zpool_do_upgrade(int argc, char **argv) (void) printf(gettext(" 14 passthrough-x aclinherit\n")); (void) printf(gettext(" 15 user/group space accounting\n")); (void) printf(gettext(" 16 stmf property support\n")); + (void) printf(gettext(" 17 Triple-parity RAID-Z\n")); + (void) printf(gettext(" 18 snapshot user holds\n")); (void) printf(gettext("For more information on a particular " "version, including supported releases, see:\n\n")); (void) printf("http://www.opensolaris.org/os/community/zfs/" @@ -3624,6 +3638,8 @@ char *hist_event_table[LOG_END] = { "refquota set", "refreservation set", "pool scrub done", + "user hold", + "user release", }; /* diff --git a/cmd/zpool/zpool_vdev.c b/cmd/zpool/zpool_vdev.c index 10007c149..621519197 100644 --- a/cmd/zpool/zpool_vdev.c +++ b/cmd/zpool/zpool_vdev.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -67,6 +67,7 @@ #include <libdiskmgt.h> #include <libintl.h> #include <libnvpair.h> +#include <limits.h> #include <stdio.h> #include <string.h> #include <unistd.h> @@ -1093,20 +1094,35 @@ check_in_use(nvlist_t *config, nvlist_t *nv, int force, int isreplacing, } static const char * -is_grouping(const char *type, int *mindev) +is_grouping(const char *type, int *mindev, int *maxdev) { - if (strcmp(type, "raidz") == 0 || strcmp(type, "raidz1") == 0) { - if (mindev != NULL) - *mindev = 2; - return (VDEV_TYPE_RAIDZ); - } + if (strncmp(type, "raidz", 5) == 0) { + const char *p = type + 5; + char *end; + long nparity; + + if (*p == '\0') { + nparity = 1; + } else if (*p == '0') { + return (NULL); /* no zero prefixes allowed */ + } else { + errno = 0; + nparity = strtol(p, &end, 10); + if (errno != 0 || nparity < 1 || nparity >= 255 || + *end != '\0') + return (NULL); + } - if (strcmp(type, "raidz2") == 0) { if (mindev != NULL) - *mindev = 3; + *mindev = nparity + 1; + if (maxdev != NULL) + *maxdev = 255; return (VDEV_TYPE_RAIDZ); } + if (maxdev != NULL) + *maxdev = INT_MAX; + if (strcmp(type, "mirror") == 0) { if (mindev != NULL) *mindev = 2; @@ -1144,7 +1160,7 @@ nvlist_t * construct_spec(int argc, char **argv) { nvlist_t *nvroot, *nv, **top, **spares, **l2cache; - int t, toplevels, mindev, nspares, nlogs, nl2cache; + int t, toplevels, mindev, maxdev, nspares, nlogs, nl2cache; const char *type; uint64_t is_log; boolean_t seen_logs; @@ -1166,7 +1182,7 @@ construct_spec(int argc, char **argv) * If it's a mirror or raidz, the subsequent arguments are * its leaves -- until we encounter the next mirror or raidz. */ - if ((type = is_grouping(argv[0], &mindev)) != NULL) { + if ((type = is_grouping(argv[0], &mindev, &maxdev)) != NULL) { nvlist_t **child = NULL; int c, children = 0; @@ -1223,7 +1239,7 @@ construct_spec(int argc, char **argv) } for (c = 1; c < argc; c++) { - if (is_grouping(argv[c], NULL) != NULL) + if (is_grouping(argv[c], NULL, NULL) != NULL) break; children++; child = realloc(child, @@ -1243,6 +1259,13 @@ construct_spec(int argc, char **argv) return (NULL); } + if (children > maxdev) { + (void) fprintf(stderr, gettext("invalid vdev " + "specification: %s supports no more than " + "%d devices\n"), argv[0], maxdev); + return (NULL); + } + argc -= c; argv += c; diff --git a/cmd/ztest/ztest.c b/cmd/ztest/ztest.c index 746db0c07..5f49fd5a0 100644 --- a/cmd/ztest/ztest.c +++ b/cmd/ztest/ztest.c @@ -479,7 +479,7 @@ process_options(int argc, char **argv) zopt_raidz = MAX(1, value); break; case 'R': - zopt_raidz_parity = MIN(MAX(value, 1), 2); + zopt_raidz_parity = MIN(MAX(value, 1), 3); break; case 'd': zopt_datasets = MAX(1, value); @@ -1387,7 +1387,7 @@ ztest_destroy_cb(char *name, void *arg) /* * Destroy the dataset. */ - error = dmu_objset_destroy(name); + error = dmu_objset_destroy(name, B_FALSE); if (error) { (void) dmu_objset_open(name, DMU_OST_OTHER, DS_MODE_USER | DS_MODE_READONLY, &os); @@ -1560,7 +1560,7 @@ ztest_dmu_objset_create_destroy(ztest_args_t *za) zil_close(zilog); dmu_objset_close(os); - error = dmu_objset_destroy(name); + error = dmu_objset_destroy(name, B_FALSE); if (error) fatal(0, "dmu_objset_destroy(%s) = %d", name, error); @@ -1583,7 +1583,7 @@ ztest_dmu_snapshot_create_destroy(ztest_args_t *za) (void) snprintf(snapname, 100, "%s@%llu", osname, (u_longlong_t)za->za_instance); - error = dmu_objset_destroy(snapname); + error = dmu_objset_destroy(snapname, B_FALSE); if (error != 0 && error != ENOENT) fatal(0, "dmu_objset_destroy() = %d", error); error = dmu_objset_snapshot(osname, strchr(snapname, '@')+1, @@ -1614,19 +1614,19 @@ ztest_dsl_dataset_cleanup(char *osname, uint64_t curval) (void) snprintf(clone2name, 100, "%s/c2_%llu", osname, curval); (void) snprintf(snap3name, 100, "%s@s3_%llu", clone1name, curval); - error = dmu_objset_destroy(clone2name); + error = dmu_objset_destroy(clone2name, B_FALSE); if (error && error != ENOENT) fatal(0, "dmu_objset_destroy(%s) = %d", clone2name, error); - error = dmu_objset_destroy(snap3name); + error = dmu_objset_destroy(snap3name, B_FALSE); if (error && error != ENOENT) fatal(0, "dmu_objset_destroy(%s) = %d", snap3name, error); - error = dmu_objset_destroy(snap2name); + error = dmu_objset_destroy(snap2name, B_FALSE); if (error && error != ENOENT) fatal(0, "dmu_objset_destroy(%s) = %d", snap2name, error); - error = dmu_objset_destroy(clone1name); + error = dmu_objset_destroy(clone1name, B_FALSE); if (error && error != ENOENT) fatal(0, "dmu_objset_destroy(%s) = %d", clone1name, error); - error = dmu_objset_destroy(snap1name); + error = dmu_objset_destroy(snap1name, B_FALSE); if (error && error != ENOENT) fatal(0, "dmu_objset_destroy(%s) = %d", snap1name, error); } |