zpool_main.c revision 88ecc943b4eb72f7c4fbbd8435997b85ef171fc3
2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A * These libumem hooks provide a reasonable set of defaults for the allocator's 2N/A * debugging facilities. 2N/A return (
"default,verbose");
/* $UMEM_DEBUG setting */ 2N/A return (
"fail,contents");
/* $UMEM_LOGGING setting */ 2N/A * Master command table. Each ZFS command has a name, associated function, and 2N/A * usage message. The usage messages need to be internationalized, so we have 2N/A * to have a function to return the usage message based on a command index. 2N/A * These commands are organized according to how they are displayed in the usage 2N/A * message. An empty command (one with a NULL name) indicates an empty line in 2N/A * the generic usage message. 2N/A return (
gettext(
"\tadd [-fn] <pool> <vdev> ...\n"));
2N/A return (
gettext(
"\tcreate [-fn] [-o property=value] ... \n" 2N/A "\t [-O file-system-property=value] ... \n" 2N/A "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
2N/A return (
gettext(
"\thistory [-il] [<pool>] ...\n"));
2N/A "\timport [-o mntopts] [-o property=value] ... \n" 2N/A "\t [-d dir | -c cachefile] [-D] [-f] [-R root] -a\n" 2N/A "\timport [-o mntopts] [-o property=value] ... \n" 2N/A "\t [-d dir | -c cachefile] [-D] [-f] [-R root] " 2N/A "<pool | id> [newpool]\n"));
2N/A return (
gettext(
"\tiostat [-v] [-T d|u] [pool] ... [interval " 2N/A return (
gettext(
"\tlist [-H] [-o property[,...]] " 2N/A return (
gettext(
"\toffline [-t] <pool> <device> ...\n"));
2N/A return (
gettext(
"\tonline <pool> <device> ...\n"));
2N/A return (
gettext(
"\tremove <pool> <device> ...\n"));
2N/A "\tupgrade [-V version] <-a | pool ...>\n"));
2N/A return (
gettext(
"\tget <\"all\" | property[,...]> " 2N/A return (
gettext(
"\tset <property=value> <pool> \n"));
2N/A * Callback routine that will print out a pool property value. 2N/A * Display usage message. If we're inside a command, display only the usage for 2N/A * that command. Otherwise, iterate over the entire command table and display 2N/A * a complete usage message. 2N/A gettext(
"where 'command' is one of the following:\n\n"));
gettext(
"\nthe following properties are supported:\n"));
"PROPERTY",
"EDIT",
"VALUES");
/* Iterate over all properties */ * See comments at end of main(). (
void)
printf(
"dumping core by request\n");
* Add a property pair (name, string-value) into a property nvlist. gettext(
"internal error: out of memory\n"));
"not a valid pool property\n"),
propname);
"specified multiple times\n"),
propname);
"error: out of memory\n"));
* zpool add [-fn] <pool> <vdev> ... * -f Force addition of devices, even if they appear in use * -n Do not add the devices, but display the resulting layout if * 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 /* get pool name and check number of arguments */ /* pass off to get_vdev_spec for processing */ /* print original main pool and new tree */ /* Do the same for the logs */ * zpool remove <pool> <vdev> ... * Removes the given vdev from the pool. Currently, this only supports removing * spares and cache devices from the pool. Eventually, we'll want to support * removing leaf vdevs (as an alias for 'detach') as well as toplevel vdevs. /* get pool name and check number of arguments */ for (i =
1; i <
argc; i++) {
* zpool create [-fn] [-o property=value] ... * [-O file-system-property=value] ... * [-R root] [-m mountpoint] <pool> <dev> ... * -f Force creation, even if devices appear in use * -n Do not create the pool, but display the resulting layout if it * -R Create a pool under an alternate root * -m Set default mountpoint for the root dataset. By default it's * -O Set fsproperty=value in the pool's root file system * Creates the named pool according to the given vdev specification. The * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once * we get the nvlist back from get_vdev_spec(), we either print out the contents * (if '-n' was specified), or pass it to libzfs to do the creation. /* get pool name and check number of arguments */ * As a special case, check for use of '/' in the name, and direct the * user to use 'zfs create' instead. "character '/' in pool name\n"),
poolname);
/* pass off to get_vdev_spec for bulk processing */ /* make_root_vdev() allows 0 toplevel children if there are spares */ "specification: at least one toplevel vdev must be " "must be an absolute path\n"),
altroot);
* Check the validity of the mountpoint and direct the user to use the * '-m' mountpoint option if it looks like its in use. "'%s': must be an absolute path, 'legacy', or " "option to provide a different default\n"));
"'%s' exists and is not empty\n"),
buf);
* For a dry run invocation, print out a basic message and run * through all the vdevs in the list and print out in an * -f Forcefully unmount any datasets * Destroy the given pool. Automatically unmounts any datasets in the pool. * As a special case, check for use of '/' in the name, and * direct the user to use 'zfs destroy' instead. * zpool export [-f] <pool> ... * -f Forcefully unmount datasets * Export the given pools. By default, the command will attempt to cleanly * unmount any active datasets within the pool. If the '-f' flag is specified, * then the datasets will be forcefully unmounted. for (i = 0; i <
argc; i++) {
* Given a vdev configuration, determine the maximum width needed for the device * Print out configuration state as requested by status_callback. * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for "resilvered" :
"repaired");
/* Don't print logs or holes here */ * Print the configuration of an exported pool. Iterate over all vdevs in the * pool, printing out the name and status for each one. * Logs are recorded as top level vdevs in the main pool child array * but with "is_log" set to 1. We use either print_status_config() or * print_import_config() to print the top level logs then any log * children (eg mirrored slogs) are printed recursively - which * works because only the top level vdev is marked "is_log" * Display the status for the given pool. "older on-disk version.\n"));
"incompatible version.\n"));
* No other status can be seen when importing pools. * Print out an action according to the overall state of the pool. "imported using its name or numeric identifier, " "though\n\tsome features will not be available " "without an explicit 'zpool upgrade'.\n"));
"imported using its name or numeric " "identifier and\n\tthe '-f' flag.\n"));
"imported using its name or numeric " "despite missing or damaged devices. The\n\tfault " "tolerance of the pool may be compromised if imported.\n"));
"imported. Access the pool on a system running " "newer\n\tsoftware, or recreate the pool from " "imported. Attach the missing\n\tdevices and try " "imported due to damaged devices or data.\n"));
* If the state is "closed" or "can't open", and the aux state "but can be imported using the '-Df' flags.\n"));
"another system, but can be imported using\n\t" "be part of this pool, though their\n\texact " "configuration cannot be determined.\n"));
* Perform the import for the given configuration. This passes the heavy * lifting off to zpool_import_props(), and then mounts the datasets contained "is formatted using a newer ZFS version\n"),
name);
"'%s': pool may be in use from other " "system, it was last accessed by %s " "pool may be in use from other system\n"),
name);
* zpool import [-d dir] [-D] * import [-o mntopts] [-o prop=value] ... [-R root] [-D] * [-d dir | -c cachefile] [-f] -a * import [-o mntopts] [-o prop=value] ... [-R root] [-D] * [-d dir | -c cachefile] [-f] <pool | id> [newpool] * -c Read pool information from a cachefile instead of searching * -d Scan in a specific directory, other than /dev/dsk. More than * one directory can be specified using multiple '-d' options. * -D Scan for previously destroyed pools or import all or only * specified destroyed pools. * -R Temporarily import the pool, with all mountpoints relative to * the given root. The pool will remain exported when the machine * -f Force import, even if it appears that the pool is active. * -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. In other words, it does verbatim * -a Import all pools found. * -o Set property=value and/or temporary mount options (without '='). * The import command scans for pools to import, and import pools based on pool * name and GUID. The pool can also be renamed as part of the import process. /* check argument count */ * Check for the SYS_CONFIG privilege. We do this explicitly * here because otherwise any attempt to discover pools will "discover pools: permission denied\n"));
* Depending on the arguments given, we do one of the following: * <none> Iterate through all pools and display information about * -a Iterate through all pools and try to import each one. * <id> Find the pool that corresponds to the given GUID/pool * name and import that one. * -D Above options applies only to destroyed pools. * It's OK to search by guid even if searchguid is 0. "no such pool available\n"),
argv[0]);
* At this point we have a list of import candidate configs. Even if * we were searching by pool name or guid, we still need to * post-process the list to deal with pool state and possible * We are searching for a pool based on name. "cannot import '%s': more than " "import by numeric ID instead\n"));
* Search for a pool by guid. * If we were searching for a specific pool, verify that we found a * pool, and then do the import. "no such pool available\n"),
argv[0]);
* If we were just looking for pools, report an error if none were gettext(
"no pools available to import\n"));
(
void)
printf(
" ----- ----- ----- ----- ----- -----\n");
(
void)
printf(
"%*s capacity operations bandwidth\n",
(
void)
printf(
"%-*s used avail read write read write\n",
* Display a single statistic. * Print out all the statistics for the given vdev. This can either be the * toplevel configuration, or called recursively. If 'name' is NULL, then this * is a verbose output, and we don't want to display the toplevel pool stats. /* only toplevel vdevs have capacity stats */ * Include level 2 ARC devices in iostat output (
void)
printf(
"%-*s - - - - - " * If the pool has disappeared, remove it from the list and continue. * Callback to print out the iostats for the given pool. * Print out the statistics for the pool. * The width must fall into the range [10,38]. The upper limit is the * maximum we can have and still fit in 80 columns. * zpool iostat [-T d|u] [-v] [pool] ... [interval [count]] * -T Display a timestamp in date(1) or Unix format * -v Display statistics for individual vdevs * This command can be tricky because we want to be able to deal with pool * processing is handled by the pool_list_* routines in zpool_iter.c. We rely * on pool_list_update() to detect the addition of new pools. Configuration * changes are all handled within libzfs. * Determine if the last argument is an integer or a pool name * Ignore the last parameter * If this is not a valid number, just plow on. The * user will get a more informative error message later * If the last argument is also an integer, then we have both a count * Ignore the last parameter * Construct the list of all interesting pools. * Enter the main iostat loop. * Refresh all statistics. This is done as an explicit step * before calculating the maximum name width, so that any * configuration changes are properly accounted for. * Iterate over all pools to determine the maximum width * for the pool / device name column across all pools. * If it's the first time, or verbose mode, print the header. * If there's more than one pool, and we're not in verbose mode * (which prints a separator for us), then print a separator. * Flush the output so that redirection to a file isn't buffered * Given a list of columns to display, output appropriate headers for each one. * Given a pool and a list of properties, print out all the properties according * to the described layout. * If this is being called in scripted mode, or if this is the * last column and it is left-justified, don't include a width * Generic callback function to list a pool. * zpool list [-H] [-o prop[,prop]*] [pool] ... * -H Scripted mode. Don't display headers, and separate properties * -o List of properties to display. Defaults to * "name,size,used,available,capacity,health,altroot" * List all pools in the system, whether or not they're healthy. Output space * statistics for each one, as well as health status summary. "name,size,used,available,capacity,health,altroot";
/* get pool name and check number of arguments */ gettext(
"missing <device> specification\n"));
gettext(
"missing <new_device> specification\n"));
* zpool replace [-f] <pool> <device> <new_device> * -f Force attach, even if <new_device> appears to be in use. * Replace <device> with <new_device>. * zpool attach [-f] <pool> <device> <new_device> * -f Force attach, even if <new_device> appears to be in use. * Attach <new_device> to the mirror containing <device>. If <device> is not * part of a mirror, then <device> will be transformed into a mirror of * <device> and <new_device>. In either case, <new_device> will begin life * with a DTL of [0, now], and will immediately begin to resilver itself. * zpool detach [-f] <pool> <device> * -f Force detach of <device>, even if DTLs argue against it * Detach a device from a mirror. The operation will be refused if <device> * is the last device in the mirror, or if the DTLs indicate that this device * has the only valid copy of some data. /* get pool name and check number of arguments */ gettext(
"missing <device> specification\n"));
* zpool online <pool> <device> ... /* get pool name and check number of arguments */ for (i =
1; i <
argc; i++) {
"onlined, but remains in faulted state\n"),
"clear' to restore a faulted " "replace' to replace devices " "that are no longer present\n"));
* zpool offline [-ft] <pool> <device> ... * -f Force the device into the offline state, even if doing * so would appear to compromise pool availability. * -t Only take the device off-line temporarily. The offline * state will not be persistent across reboots. /* get pool name and check number of arguments */ for (i =
1; i <
argc; i++) {
* zpool clear <pool> [device] * Clear all errors associated with a pool or a particular device. * zpool scrub [-s] <pool> ... * -s Stop. Stops any in-progress scrub. * Print out detailed scrub status. * If there's never been a scrub, there's not much to say. (
void)
printf(
gettext(
"%s in progress for %lluh%um, %.2f%% done, " (
void)
printf(
"errors: List of errors unavailable " "(insufficient privileges)\n");
(
void)
printf(
"errors: Permanent errors have been " "detected in the following files:\n\n");
* Display a summary of pool status. Displays a summary such as: * reason: One or more devices ... * When given the '-v' option, we print out the complete config. If the '-e' * option is specified, then we print out error rate information as well. * If we were given 'zpool status -x', only report those pools with "be opened. Sufficient replicas exist for\n\tthe pool to " "continue functioning in a degraded state.\n"));
"online it using 'zpool online'.\n"));
"be opened. There are insufficient\n\treplicas for the " "pool to continue functioning.\n"));
"online it using 'zpool online'.\n"));
"be used because the label is missing or\n\tinvalid. " "Sufficient replicas exist for the pool to continue\n\t" "functioning in a degraded state.\n"));
"be used because the label is missing \n\tor invalid. " "There are insufficient replicas for the pool to " "continue\n\tfunctioning.\n"));
"from a backup source.\n"));
"experienced an unrecoverable error. An\n\tattempt was " "made to correct the error. Applications are " "to be replaced, and clear the errors\n\tusing " "'zpool clear' or replace the device with 'zpool " "been taken offline by the administrator.\n\tSufficient " "replicas exist for the pool to continue functioning in " "a\n\tdegraded state.\n"));
"'zpool online' or replace the device with\n\t'zpool " "been removed by the administrator.\n\tSufficient " "replicas exist for the pool to continue functioning in " "a\n\tdegraded state.\n"));
"'zpool online' or replace the device with\n\t'zpool " "currently being resilvered. The pool will\n\tcontinue " "to function, possibly in a degraded state.\n"));
"experienced an error resulting in data\n\tcorruption. " "Applications may be affected.\n"));
"if possible. Otherwise restore the\n\tentire pool from " "and the pool cannot be opened.\n"));
"from a backup source.\n"));
"older on-disk format. The pool can\n\tstill be used, but " "some features are unavailable.\n"));
"upgrade'. Once this is done, the\n\tpool will no longer " "be accessible on older software versions.\n"));
"newer, incompatible on-disk version.\n\tThe pool cannot " "be accessed on this system.\n"));
"running more recent software, or\n\trestore the pool from " "faulted in response to persistent errors.\n\tSufficient " "replicas exist for the pool to continue functioning " "in a\n\tdegraded state.\n"));
"or use 'zpool clear' to mark the device\n\trepaired.\n"));
"faulted in response to persistent errors. There are " "insufficient replicas for the pool to\n\tcontinue " "from a backup source. Manually marking the device\n" "\trepaired using 'zpool clear' may allow some data " "faulted in response to IO failures.\n"));
"are connected, then run 'zpool clear'.\n"));
"\tWaiting for adminstrator intervention to fix the " "device(s) and run 'zpool online',\n" "\tor ignore the intent log records by running " * The remaining errors can't actually be generated, yet. "NAME",
"STATE",
"READ",
"WRITE",
"CKSUM");
* If the approximate error count is small, get a * precise count by fetching the entire log and * uniquifying the results. "errors, use '-v' for a list\n"),
* zpool status [-vx] [pool] ... * -v Display complete error logs * -x Display only pools with potential problems * Describes the health status of all pools or some subset. "out of date, and can be upgraded. After " "being\nupgraded, these pools will no " "longer be accessible by older software " "formatted using a newer software version and\n" "cannot be accessed on the current system.\n\n"));
"Pool 'log' must be renamed using export and import" "using more current version '%llu'.\n"),
"from version %llu to version %llu\n\n"),
* zpool upgrade [-V version] <-a | pool ...> * With no arguments, display downrev'd ZFS pool available for upgrade. * Individual pools can be upgraded by specifying the pool, and '-a' will "incompatible with other arguments\n"));
"incompatible with other arguments\n"));
"be used along with a pool name\n"));
(
void)
printf(
"--- -----------------------------------------" "(replicated metadata)\n"));
"version, including supported releases, see:\n\n"));
"using this version.\n"));
"for a list of available versions and " "their associated\nfeatures.\n"));
"filesystem version upgrade",
* Print out the command history for a specific pool. /* is it an internal event or a standard event? */ "[internal %s txg:%lld] %s",
* Displays the history of commands that modified pools. * Skip the special fake placeholder. This will also skip * over the name property when 'all' is specified. "property=value argument\n"));
"initialize ZFS library\n"));
* Make sure the user has specified some command. * Run the appropriate command. * 'freeze' is a vile debugging abomination, so we treat * The 'ZFS_ABORT' environment variable causes us to dump core on exit * for the purposes of running ::findleaks. (
void)
printf(
"dumping core by request\n");