Print this page
NEX-6088 ZFS scrub/resilver take excessively long due to issuing lots of random IO
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-5284 need to document and update default for import -t option
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Hans Rosenfeld <hans.rosenfeld@nexenta.com>
NEX-5795 Rename 'wrc' as 'wbc' in the source and in the tech docs
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
NEX-5745 WBC: Sometimes disabled instance never finish migration
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
NEX-5750 Time values for aggregated NFS server kstats should be normalized
Reviewed by: Dan Fields <dan.fields@nexenta.com>
NEX-5562 Trim timestamps incorrectly shown in UTC instead of local time
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-5064 On-demand trim should store operation start and stop time (lint fix)
Reviewed by: Jean McCormack <jean.mccormack@nexenta.com>
NEX-5064 On-demand trim should store operation start and stop time
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
NEX-5163 backport illumos 6027 EOL zulu (XVR-4000)
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
6027 EOL zulu (XVR-4000)
Reviewed by: Garrett D'Amore <garrett@damore.org>
Reviewed by: Peter Tribble <peter.tribble@gmail.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Approved by: Dan McDonald <danmcd@omniti.com>
NEX-5162 backport illumos 6507 i386 makecontext(3c) needs to 16-byte align the stack
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
6507 i386 makecontext(3c) needs to 16-byte align the stack
Reviewed by: Gordon Ross <gordon.w.ross@gmail.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Dan McDonald <danmcd@omniti.com>
NEX-5207 attempt to activate spare cores fmd
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-4934 Add capability to remove special vdev
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
NEX-4776 zpool(1M) coredumps on status when trimming a pool with log devices
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
6328 Fix cstyle errors in zfs codebase (fix studio)
6328 Fix cstyle errors in zfs codebase
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Alex Reece <alex@delphix.com>
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Jorgen Lundman <lundman@lundman.net>
Approved by: Robert Mustacchi <rm@joyent.com>
6047 SPARC boot should support feature@embedded_data
Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com>
Approved by: Dan McDonald <danmcd@omniti.com>
5959 clean up per-dataset feature count code
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: George Wilson <george@delphix.com>
Reviewed by: Alex Reece <alex@delphix.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
5669 altroot not set in zpool create when specified with -o
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <george@delphix.com>
Approved by: Dan McDonald <danmcd@omniti.com>
5767 fix several problems with zfs test suite
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Approved by: Gordon Ross <gwr@nexenta.com>
NEX-4476 WRC: Allow to use write back cache per tree of datasets
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
NEX-4336 zpool vdev-get with an unsuported prop name core dumps
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-3984 On-demand TRIM
Reviewed by: Alek Pinchuk <alek@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Conflicts:
usr/src/common/zfs/zpool_prop.c
usr/src/uts/common/sys/fs/zfs.h
NEX-3558 KRRP Integration
NEX-3165 need some dedup improvements
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
OS-195 itadm needs an easily parsable output mode
OS-207 SUP-817 causes lint warnings in zpool_main.c
Reviewed by: Alek Pinchuk <alek.pinchuk@nexena.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Albert Lee <albert.lee@nexenta.com>
OS-199 keep your tree clean (lint zpool_main.c)
SUP-817 Removed references to special device from man and help
Revert "SUP-817 Removed references to special device"
This reverts commit f8970e28f0d8bd6b69711722f341e3e1d0e1babf.
SUP-817 Removed references to special device
OS-132 zpool(1m) in scripting mode returns wrong exit code if no pools available
OS-103 handle CoS descriptor persistent references across vdev operations
OS-102 add man page info and tests for vdev/CoS properties and ZFS meta features
SUP-647 Long failover times dominated by zpool import times trigger client-side errors
Fix up some merges where we wanted the upstream version.
Make special vdev subtree topology the same as regular vdev subtree to simplify testcase setup
Fixup merge issues
Issue #26: partial scrub
Added partial scrub options:
-M for MOS only scrub
-m for metadata scrub
Issue #9: Support for persistent CoS/vdev attributes with feature flags
Support for feature flags for special tier
Contributors: Daniil Lunev, Boris Protopopov
Fixup merge results
re 13748 added zpool export -c option
zpool export -c command exports specified pool while keeping its latest
configuration in the cache file for subsequent zpool import -c.
re #13594 rb4488 Lint complaints fix
re #10054 #13409 rb4387 added parallel unmount for zpool export
re #8279 rb3915 need a mechanism to notify NMS about ZFS config changes (fix lint -courtesy of Yuri Pankov)
re #12584 rb4049 zfsxx latest code merge (fix lint - courtesy of Yuri Pankov)
re #12585 rb4049 ZFS++ work port - refactoring to improve separation of open/closed code, bug fixes, performance improvements - open code
re #8279 rb3915 need a mechanism to notify NMS about ZFS config changes (Opened code)
re #8346 rb2639 KT disk failures
ZFS plus work: special vdevs, cos, cos/vdev properties (fix lint)
Bug 11205: add missing libzfs_closed_stubs.c to fix opensource-only build.
ZFS plus work: special vdevs, cos, cos/vdev properties
re #6853 rb1787 remove references to sun.com
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/zpool/zpool_main.c
+++ new/usr/src/cmd/zpool/zpool_main.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 - * Copyright (c) 2011, 2018 by Delphix. All rights reserved.
24 + * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
25 25 * Copyright (c) 2012 by Frederik Wessels. All rights reserved.
26 + * Copyright (c) 2013 by Delphix. All rights reserved.
26 27 * Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
27 28 * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
28 29 * Copyright 2016 Nexenta Systems, Inc.
29 30 * Copyright (c) 2017 Datto Inc.
30 31 */
31 32
32 33 #include <assert.h>
33 34 #include <ctype.h>
34 35 #include <dirent.h>
35 36 #include <errno.h>
36 37 #include <fcntl.h>
37 38 #include <libgen.h>
38 39 #include <libintl.h>
39 40 #include <libuutil.h>
40 41 #include <locale.h>
41 42 #include <stdio.h>
42 43 #include <stdlib.h>
43 44 #include <string.h>
44 45 #include <strings.h>
45 46 #include <unistd.h>
46 47 #include <priv.h>
47 48 #include <pwd.h>
48 49 #include <zone.h>
49 50 #include <zfs_prop.h>
50 51 #include <sys/fs/zfs.h>
|
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
51 52 #include <sys/stat.h>
52 53
53 54 #include <libzfs.h>
54 55
55 56 #include "zpool_util.h"
56 57 #include "zfs_comutil.h"
57 58 #include "zfeature_common.h"
58 59
59 60 #include "statcommon.h"
60 61
62 +#ifndef MAX
63 +#define MAX(x, y) ((x) > (y) ? (x) : (y))
64 +#endif /* MAX */
65 +
61 66 static int zpool_do_create(int, char **);
62 67 static int zpool_do_destroy(int, char **);
63 68
64 69 static int zpool_do_add(int, char **);
65 70 static int zpool_do_remove(int, char **);
66 71 static int zpool_do_labelclear(int, char **);
67 72
68 73 static int zpool_do_list(int, char **);
69 74 static int zpool_do_iostat(int, char **);
70 75 static int zpool_do_status(int, char **);
71 76
72 77 static int zpool_do_online(int, char **);
73 78 static int zpool_do_offline(int, char **);
74 79 static int zpool_do_clear(int, char **);
|
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
75 80 static int zpool_do_reopen(int, char **);
76 81
77 82 static int zpool_do_reguid(int, char **);
78 83
79 84 static int zpool_do_attach(int, char **);
80 85 static int zpool_do_detach(int, char **);
81 86 static int zpool_do_replace(int, char **);
82 87 static int zpool_do_split(int, char **);
83 88
84 89 static int zpool_do_scrub(int, char **);
90 +static int zpool_do_trim(int, char **);
85 91
86 92 static int zpool_do_import(int, char **);
87 93 static int zpool_do_export(int, char **);
88 94
89 95 static int zpool_do_upgrade(int, char **);
90 96
91 97 static int zpool_do_history(int, char **);
92 98
93 99 static int zpool_do_get(int, char **);
94 100 static int zpool_do_set(int, char **);
95 101
102 +static int zpool_do_vdev_get(int, char **);
103 +static int zpool_do_vdev_set(int, char **);
104 +
105 +static int zpool_do_cos_alloc(int, char **);
106 +static int zpool_do_cos_free(int, char **);
107 +static int zpool_do_cos_list(int, char **);
108 +static int zpool_do_cos_get(int, char **);
109 +static int zpool_do_cos_set(int, char **);
110 +
111 +static boolean_t nexenta_meta_enable();
112 +
96 113 /*
97 114 * These libumem hooks provide a reasonable set of defaults for the allocator's
98 115 * debugging facilities.
99 116 */
100 117
101 118 #ifdef DEBUG
102 119 const char *
103 120 _umem_debug_init(void)
104 121 {
105 122 return ("default,verbose"); /* $UMEM_DEBUG setting */
106 123 }
107 124
108 125 const char *
109 126 _umem_logging_init(void)
110 127 {
111 128 return ("fail,contents"); /* $UMEM_LOGGING setting */
112 129 }
113 130 #endif
114 131
115 132 typedef enum {
116 133 HELP_ADD,
117 134 HELP_ATTACH,
118 135 HELP_CLEAR,
119 136 HELP_CREATE,
120 137 HELP_DESTROY,
121 138 HELP_DETACH,
122 139 HELP_EXPORT,
|
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
123 140 HELP_HISTORY,
124 141 HELP_IMPORT,
125 142 HELP_IOSTAT,
126 143 HELP_LABELCLEAR,
127 144 HELP_LIST,
128 145 HELP_OFFLINE,
129 146 HELP_ONLINE,
130 147 HELP_REPLACE,
131 148 HELP_REMOVE,
132 149 HELP_SCRUB,
150 + HELP_TRIM,
133 151 HELP_STATUS,
134 152 HELP_UPGRADE,
135 153 HELP_GET,
136 154 HELP_SET,
137 155 HELP_SPLIT,
138 156 HELP_REGUID,
139 - HELP_REOPEN
157 + HELP_REOPEN,
158 + HELP_VDEV_GET,
159 + HELP_VDEV_SET,
160 + HELP_COS_ALLOC,
161 + HELP_COS_FREE,
162 + HELP_COS_LIST,
163 + HELP_COS_GET,
164 + HELP_COS_SET
140 165 } zpool_help_t;
141 166
142 167
143 168 typedef struct zpool_command {
144 169 const char *name;
145 170 int (*func)(int, char **);
146 171 zpool_help_t usage;
147 172 } zpool_command_t;
148 173
149 174 /*
150 175 * Master command table. Each ZFS command has a name, associated function, and
151 176 * usage message. The usage messages need to be internationalized, so we have
152 177 * to have a function to return the usage message based on a command index.
153 178 *
154 179 * These commands are organized according to how they are displayed in the usage
155 180 * message. An empty command (one with a NULL name) indicates an empty line in
156 181 * the generic usage message.
157 182 */
158 183 static zpool_command_t command_table[] = {
159 184 { "create", zpool_do_create, HELP_CREATE },
160 185 { "destroy", zpool_do_destroy, HELP_DESTROY },
161 186 { NULL },
162 187 { "add", zpool_do_add, HELP_ADD },
163 188 { "remove", zpool_do_remove, HELP_REMOVE },
164 189 { NULL },
165 190 { "labelclear", zpool_do_labelclear, HELP_LABELCLEAR },
166 191 { NULL },
167 192 { "list", zpool_do_list, HELP_LIST },
168 193 { "iostat", zpool_do_iostat, HELP_IOSTAT },
169 194 { "status", zpool_do_status, HELP_STATUS },
170 195 { NULL },
171 196 { "online", zpool_do_online, HELP_ONLINE },
172 197 { "offline", zpool_do_offline, HELP_OFFLINE },
|
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
173 198 { "clear", zpool_do_clear, HELP_CLEAR },
174 199 { "reopen", zpool_do_reopen, HELP_REOPEN },
175 200 { NULL },
176 201 { "attach", zpool_do_attach, HELP_ATTACH },
177 202 { "detach", zpool_do_detach, HELP_DETACH },
178 203 { "replace", zpool_do_replace, HELP_REPLACE },
179 204 { "split", zpool_do_split, HELP_SPLIT },
180 205 { NULL },
181 206 { "scrub", zpool_do_scrub, HELP_SCRUB },
182 207 { NULL },
208 + { "trim", zpool_do_trim, HELP_TRIM },
209 + { NULL },
183 210 { "import", zpool_do_import, HELP_IMPORT },
184 211 { "export", zpool_do_export, HELP_EXPORT },
185 212 { "upgrade", zpool_do_upgrade, HELP_UPGRADE },
186 213 { "reguid", zpool_do_reguid, HELP_REGUID },
187 214 { NULL },
188 215 { "history", zpool_do_history, HELP_HISTORY },
189 216 { "get", zpool_do_get, HELP_GET },
190 217 { "set", zpool_do_set, HELP_SET },
218 + { "vdev-get", zpool_do_vdev_get, HELP_VDEV_GET },
219 + { "vdev-set", zpool_do_vdev_set, HELP_VDEV_SET },
220 + { "cos-alloc", zpool_do_cos_alloc, HELP_COS_ALLOC },
221 + { "cos-free", zpool_do_cos_free, HELP_COS_FREE },
222 + { "cos-list", zpool_do_cos_list, HELP_COS_LIST },
223 + { "cos-get", zpool_do_cos_get, HELP_COS_GET },
224 + { "cos-set", zpool_do_cos_set, HELP_COS_SET }
191 225 };
192 226
193 227 #define NCOMMAND (sizeof (command_table) / sizeof (command_table[0]))
194 228
195 229 static zpool_command_t *current_command;
196 230 static char history_str[HIS_MAX_RECORD_LEN];
197 231 static boolean_t log_history = B_TRUE;
198 232 static uint_t timestamp_fmt = NODATE;
199 233
200 234 static const char *
201 235 get_usage(zpool_help_t idx)
202 236 {
203 237 switch (idx) {
204 238 case HELP_ADD:
205 239 return (gettext("\tadd [-fn] <pool> <vdev> ...\n"));
206 240 case HELP_ATTACH:
207 241 return (gettext("\tattach [-f] <pool> <device> "
208 242 "<new-device>\n"));
209 243 case HELP_CLEAR:
210 244 return (gettext("\tclear [-nF] <pool> [device]\n"));
211 245 case HELP_CREATE:
212 246 return (gettext("\tcreate [-fnd] [-B] "
213 247 "[-o property=value] ... \n"
214 248 "\t [-O file-system-property=value] ... \n"
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
215 249 "\t [-m mountpoint] [-R root] <pool> <vdev> ...\n"));
216 250 case HELP_DESTROY:
217 251 return (gettext("\tdestroy [-f] <pool>\n"));
218 252 case HELP_DETACH:
219 253 return (gettext("\tdetach <pool> <device>\n"));
220 254 case HELP_EXPORT:
221 255 return (gettext("\texport [-f] <pool> ...\n"));
222 256 case HELP_HISTORY:
223 257 return (gettext("\thistory [-il] [<pool>] ...\n"));
224 258 case HELP_IMPORT:
225 - return (gettext("\timport [-d dir] [-D]\n"
259 + return (gettext("\timport [-d dir] [-D] [-t num]\n"
226 260 "\timport [-d dir | -c cachefile] [-F [-n]] <pool | id>\n"
227 261 "\timport [-o mntopts] [-o property=value] ... \n"
228 262 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
229 - "[-R root] [-F [-n]] -a\n"
263 + "[-R root] [-F [-n]] [-t num] -a\n"
230 264 "\timport [-o mntopts] [-o property=value] ... \n"
231 265 "\t [-d dir | -c cachefile] [-D] [-f] [-m] [-N] "
232 266 "[-R root] [-F [-n]]\n"
233 267 "\t <pool | id> [newpool]\n"));
234 268 case HELP_IOSTAT:
235 269 return (gettext("\tiostat [-v] [-T d|u] [pool] ... [interval "
236 270 "[count]]\n"));
237 271 case HELP_LABELCLEAR:
238 272 return (gettext("\tlabelclear [-f] <vdev>\n"));
239 273 case HELP_LIST:
240 274 return (gettext("\tlist [-Hp] [-o property[,...]] "
241 275 "[-T d|u] [pool] ... [interval [count]]\n"));
242 276 case HELP_OFFLINE:
243 277 return (gettext("\toffline [-t] <pool> <device> ...\n"));
244 278 case HELP_ONLINE:
245 279 return (gettext("\tonline <pool> <device> ...\n"));
246 280 case HELP_REPLACE:
247 281 return (gettext("\treplace [-f] <pool> <device> "
248 282 "[new-device]\n"));
249 283 case HELP_REMOVE:
250 - return (gettext("\tremove [-nps] <pool> <device> ...\n"));
284 + return (gettext("\tremove <pool> <device> ...\n"));
251 285 case HELP_REOPEN:
252 286 return (gettext("\treopen <pool>\n"));
253 287 case HELP_SCRUB:
254 - return (gettext("\tscrub [-s | -p] <pool> ...\n"));
288 + return (gettext("\tscrub [-m|-M|-p|-s] <pool> ...\n"));
289 + case HELP_TRIM:
290 + return (gettext("\ttrim [-s|-r <rate>] <pool> ...\n"));
255 291 case HELP_STATUS:
256 292 return (gettext("\tstatus [-vx] [-T d|u] [pool] ... [interval "
257 293 "[count]]\n"));
258 294 case HELP_UPGRADE:
259 295 return (gettext("\tupgrade\n"
260 296 "\tupgrade -v\n"
261 297 "\tupgrade [-V version] <-a | pool ...>\n"));
262 298 case HELP_GET:
263 299 return (gettext("\tget [-Hp] [-o \"all\" | field[,...]] "
264 300 "<\"all\" | property[,...]> <pool> ...\n"));
265 301 case HELP_SET:
266 302 return (gettext("\tset <property=value> <pool> \n"));
267 303 case HELP_SPLIT:
268 304 return (gettext("\tsplit [-n] [-R altroot] [-o mntopts]\n"
269 305 "\t [-o property=value] <pool> <newpool> "
270 306 "[<device> ...]\n"));
271 307 case HELP_REGUID:
272 308 return (gettext("\treguid <pool>\n"));
309 + case HELP_VDEV_GET:
310 + return (gettext("\tvdev-get <property | all> <pool> "
311 + "<vdev name | GUID>\n"));
312 + case HELP_VDEV_SET:
313 + return (gettext("\tvdev-set <property=value> <pool> "
314 + "<vdev name | GUID>\n"));
315 + case HELP_COS_ALLOC:
316 + return (gettext("\tcos-alloc <pool> <cos name | GUID>\n"));
317 + case HELP_COS_FREE:
318 + return (gettext("\tcos-free [-f] <pool> <cos name | GUID>\n"));
319 + case HELP_COS_LIST:
320 + return (gettext("\tcos-list <pool>\n"));
321 + case HELP_COS_GET:
322 + return (gettext("\tcos-get <property | all> <pool>"
323 + "<cos name | GUID>\n"));
324 + case HELP_COS_SET:
325 + return (gettext("\tcos-set <property=value> <pool>"
326 + "<cos name | GUID>\n"));
273 327 }
274 328
275 329 abort();
276 330 /* NOTREACHED */
277 331 }
332 +/*
333 + * Check if additional ZFS meta features are enabled.
334 + */
335 +static boolean_t
336 +nexenta_meta_enable()
337 +{
338 + if (getenv("nexenta_meta_enable") == NULL) {
339 + (void) fprintf(stderr, gettext("feature not enabled\n"));
340 + (void) fprintf(stderr,
341 + gettext("set nexenta_meta_enable to access\n"));
342 + return (B_FALSE);
343 + }
344 + return (B_TRUE);
345 +}
278 346
279 -
280 347 /*
281 348 * Callback routine that will print out a pool property value.
282 349 */
283 350 static int
284 351 print_prop_cb(int prop, void *cb)
285 352 {
286 353 FILE *fp = cb;
287 354
288 355 (void) fprintf(fp, "\t%-15s ", zpool_prop_to_name(prop));
289 356
290 357 if (zpool_prop_readonly(prop))
291 358 (void) fprintf(fp, " NO ");
292 359 else
293 360 (void) fprintf(fp, " YES ");
294 361
295 362 if (zpool_prop_values(prop) == NULL)
296 363 (void) fprintf(fp, "-\n");
297 364 else
298 365 (void) fprintf(fp, "%s\n", zpool_prop_values(prop));
299 366
300 367 return (ZPROP_CONT);
301 368 }
302 369
303 370 /*
304 371 * Display usage message. If we're inside a command, display only the usage for
305 372 * that command. Otherwise, iterate over the entire command table and display
306 373 * a complete usage message.
307 374 */
308 375 void
309 376 usage(boolean_t requested)
310 377 {
311 378 FILE *fp = requested ? stdout : stderr;
312 379
313 380 if (current_command == NULL) {
314 381 int i;
315 382
316 383 (void) fprintf(fp, gettext("usage: zpool command args ...\n"));
317 384 (void) fprintf(fp,
318 385 gettext("where 'command' is one of the following:\n\n"));
319 386
320 387 for (i = 0; i < NCOMMAND; i++) {
321 388 if (command_table[i].name == NULL)
322 389 (void) fprintf(fp, "\n");
323 390 else
324 391 (void) fprintf(fp, "%s",
325 392 get_usage(command_table[i].usage));
326 393 }
327 394 } else {
328 395 (void) fprintf(fp, gettext("usage:\n"));
329 396 (void) fprintf(fp, "%s", get_usage(current_command->usage));
330 397 }
331 398
332 399 if (current_command != NULL &&
333 400 ((strcmp(current_command->name, "set") == 0) ||
334 401 (strcmp(current_command->name, "get") == 0) ||
335 402 (strcmp(current_command->name, "list") == 0))) {
336 403
337 404 (void) fprintf(fp,
338 405 gettext("\nthe following properties are supported:\n"));
339 406
340 407 (void) fprintf(fp, "\n\t%-15s %s %s\n\n",
341 408 "PROPERTY", "EDIT", "VALUES");
342 409
343 410 /* Iterate over all properties */
344 411 (void) zprop_iter(print_prop_cb, fp, B_FALSE, B_TRUE,
345 412 ZFS_TYPE_POOL);
346 413
347 414 (void) fprintf(fp, "\t%-15s ", "feature@...");
348 415 (void) fprintf(fp, "YES disabled | enabled | active\n");
349 416
350 417 (void) fprintf(fp, gettext("\nThe feature@ properties must be "
351 418 "appended with a feature name.\nSee zpool-features(5).\n"));
352 419 }
353 420
354 421 /*
355 422 * See comments at end of main().
356 423 */
357 424 if (getenv("ZFS_ABORT") != NULL) {
358 425 (void) printf("dumping core by request\n");
359 426 abort();
360 427 }
361 428
362 429 exit(requested ? 0 : 2);
363 430 }
364 431
365 432 void
366 433 print_vdev_tree(zpool_handle_t *zhp, const char *name, nvlist_t *nv, int indent,
367 434 boolean_t print_logs)
368 435 {
369 436 nvlist_t **child;
370 437 uint_t c, children;
371 438 char *vname;
372 439
373 440 if (name != NULL)
374 441 (void) printf("\t%*s%s\n", indent, "", name);
375 442
376 443 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
377 444 &child, &children) != 0)
378 445 return;
379 446
380 447 for (c = 0; c < children; c++) {
381 448 uint64_t is_log = B_FALSE;
382 449
383 450 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
384 451 &is_log);
385 452 if ((is_log && !print_logs) || (!is_log && print_logs))
386 453 continue;
387 454
388 455 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
389 456 print_vdev_tree(zhp, vname, child[c], indent + 2,
390 457 B_FALSE);
391 458 free(vname);
392 459 }
393 460 }
394 461
395 462 static boolean_t
396 463 prop_list_contains_feature(nvlist_t *proplist)
397 464 {
398 465 nvpair_t *nvp;
399 466 for (nvp = nvlist_next_nvpair(proplist, NULL); NULL != nvp;
400 467 nvp = nvlist_next_nvpair(proplist, nvp)) {
401 468 if (zpool_prop_feature(nvpair_name(nvp)))
402 469 return (B_TRUE);
403 470 }
|
↓ open down ↓ |
114 lines elided |
↑ open up ↑ |
404 471 return (B_FALSE);
405 472 }
406 473
407 474 /*
408 475 * Add a property pair (name, string-value) into a property nvlist.
409 476 */
410 477 static int
411 478 add_prop_list(const char *propname, char *propval, nvlist_t **props,
412 479 boolean_t poolprop)
413 480 {
414 - zpool_prop_t prop = ZPOOL_PROP_INVAL;
481 + zpool_prop_t prop = ZPROP_INVAL;
415 482 zfs_prop_t fprop;
416 483 nvlist_t *proplist;
417 484 const char *normnm;
418 485 char *strval;
419 486
420 487 if (*props == NULL &&
421 488 nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
422 489 (void) fprintf(stderr,
423 490 gettext("internal error: out of memory\n"));
424 491 return (1);
425 492 }
426 493
427 494 proplist = *props;
428 495
429 496 if (poolprop) {
430 497 const char *vname = zpool_prop_to_name(ZPOOL_PROP_VERSION);
431 498
432 - if ((prop = zpool_name_to_prop(propname)) == ZPOOL_PROP_INVAL &&
499 + if ((prop = zpool_name_to_prop(propname)) == ZPROP_INVAL &&
433 500 !zpool_prop_feature(propname)) {
434 501 (void) fprintf(stderr, gettext("property '%s' is "
435 502 "not a valid pool property\n"), propname);
436 503 return (2);
437 504 }
438 505
439 506 /*
440 507 * feature@ properties and version should not be specified
441 508 * at the same time.
442 509 */
443 - if ((prop == ZPOOL_PROP_INVAL && zpool_prop_feature(propname) &&
510 + if ((prop == ZPROP_INVAL && zpool_prop_feature(propname) &&
444 511 nvlist_exists(proplist, vname)) ||
445 512 (prop == ZPOOL_PROP_VERSION &&
446 513 prop_list_contains_feature(proplist))) {
447 514 (void) fprintf(stderr, gettext("'feature@' and "
448 515 "'version' properties cannot be specified "
449 516 "together\n"));
450 517 return (2);
451 518 }
452 519
453 520
454 521 if (zpool_prop_feature(propname))
455 522 normnm = propname;
456 523 else
457 524 normnm = zpool_prop_to_name(prop);
458 525 } else {
459 526 if ((fprop = zfs_name_to_prop(propname)) != ZPROP_INVAL) {
460 527 normnm = zfs_prop_to_name(fprop);
461 528 } else {
462 529 normnm = propname;
463 530 }
464 531 }
465 532
466 533 if (nvlist_lookup_string(proplist, normnm, &strval) == 0 &&
467 534 prop != ZPOOL_PROP_CACHEFILE) {
468 535 (void) fprintf(stderr, gettext("property '%s' "
469 536 "specified multiple times\n"), propname);
470 537 return (2);
471 538 }
472 539
|
↓ open down ↓ |
19 lines elided |
↑ open up ↑ |
473 540 if (nvlist_add_string(proplist, normnm, propval) != 0) {
474 541 (void) fprintf(stderr, gettext("internal "
475 542 "error: out of memory\n"));
476 543 return (1);
477 544 }
478 545
479 546 return (0);
480 547 }
481 548
482 549 /*
550 + * Add a property pair (name, string-value) into a vdev property nvlist.
551 + */
552 +static int
553 +add_vdev_prop_list(const char *propname, char *propval, nvlist_t **props)
554 +{
555 + vdev_prop_t prop = ZPROP_INVAL;
556 + nvlist_t *proplist;
557 + const char *normnm;
558 +
559 + if (*props == NULL && nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
560 + (void) fprintf(stderr,
561 + gettext("internal error: out of memory\n"));
562 + return (1);
563 + }
564 +
565 + proplist = *props;
566 + if ((prop = vdev_name_to_prop(propname)) == ZPROP_INVAL) {
567 + (void) fprintf(stderr, gettext("property '%s' is "
568 + "not a valid vdev property\n"), propname);
569 + return (2);
570 + }
571 + normnm = vdev_prop_to_name(prop);
572 +
573 + if (nvlist_add_string(proplist, normnm, propval) != 0) {
574 + (void) fprintf(stderr, gettext("internal "
575 + "error: out of memory\n"));
576 + return (1);
577 + }
578 +
579 + return (0);
580 +}
581 +
582 +/*
583 + * Add a property pair (name, string-value) into a cos property nvlist.
584 + */
585 +static int
586 +add_cos_prop_list(const char *propname, char *propval, nvlist_t **props)
587 +{
588 + cos_prop_t prop = ZPROP_INVAL;
589 + nvlist_t *proplist;
590 + const char *normnm;
591 +
592 + if (*props == NULL && nvlist_alloc(props, NV_UNIQUE_NAME, 0) != 0) {
593 + (void) fprintf(stderr,
594 + gettext("internal error: out of memory\n"));
595 + return (1);
596 + }
597 +
598 + proplist = *props;
599 + if ((prop = cos_name_to_prop(propname)) == ZPROP_INVAL) {
600 + (void) fprintf(stderr, gettext("property '%s' is "
601 + "not a valid cos property\n"), propname);
602 + return (2);
603 + }
604 + normnm = cos_prop_to_name(prop);
605 +
606 + if (nvlist_add_string(proplist, normnm, propval) != 0) {
607 + (void) fprintf(stderr, gettext("internal "
608 + "error: out of memory\n"));
609 + return (1);
610 + }
611 +
612 + return (0);
613 +}
614 +
615 +/*
483 616 * zpool add [-fn] <pool> <vdev> ...
484 617 *
485 618 * -f Force addition of devices, even if they appear in use
486 619 * -n Do not add the devices, but display the resulting layout if
487 620 * they were to be added.
488 621 *
489 622 * Adds the given vdevs to 'pool'. As with create, the bulk of this work is
490 623 * handled by get_vdev_spec(), which constructs the nvlist needed to pass to
491 624 * libzfs.
492 625 */
493 626 int
494 627 zpool_do_add(int argc, char **argv)
495 628 {
496 629 boolean_t force = B_FALSE;
497 630 boolean_t dryrun = B_FALSE;
498 631 int c;
499 632 nvlist_t *nvroot;
500 633 char *poolname;
501 634 zpool_boot_label_t boot_type;
502 635 uint64_t boot_size;
503 636 int ret;
504 637 zpool_handle_t *zhp;
505 638 nvlist_t *config;
506 639
507 640 /* check options */
508 641 while ((c = getopt(argc, argv, "fn")) != -1) {
509 642 switch (c) {
510 643 case 'f':
511 644 force = B_TRUE;
512 645 break;
513 646 case 'n':
514 647 dryrun = B_TRUE;
515 648 break;
516 649 case '?':
517 650 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
518 651 optopt);
519 652 usage(B_FALSE);
520 653 }
521 654 }
522 655
523 656 argc -= optind;
524 657 argv += optind;
525 658
526 659 /* get pool name and check number of arguments */
527 660 if (argc < 1) {
528 661 (void) fprintf(stderr, gettext("missing pool name argument\n"));
529 662 usage(B_FALSE);
530 663 }
531 664 if (argc < 2) {
532 665 (void) fprintf(stderr, gettext("missing vdev specification\n"));
533 666 usage(B_FALSE);
534 667 }
535 668
536 669 poolname = argv[0];
537 670
538 671 argc--;
539 672 argv++;
540 673
541 674 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
542 675 return (1);
543 676
544 677 if ((config = zpool_get_config(zhp, NULL)) == NULL) {
545 678 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
546 679 poolname);
547 680 zpool_close(zhp);
548 681 return (1);
549 682 }
550 683
551 684 if (zpool_is_bootable(zhp))
552 685 boot_type = ZPOOL_COPY_BOOT_LABEL;
553 686 else
554 687 boot_type = ZPOOL_NO_BOOT_LABEL;
555 688
556 689 /* pass off to get_vdev_spec for processing */
557 690 boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
558 691 nvroot = make_root_vdev(zhp, force, !force, B_FALSE, dryrun,
559 692 boot_type, boot_size, argc, argv);
560 693 if (nvroot == NULL) {
561 694 zpool_close(zhp);
562 695 return (1);
563 696 }
564 697
565 698 if (dryrun) {
566 699 nvlist_t *poolnvroot;
567 700
568 701 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
569 702 &poolnvroot) == 0);
570 703
571 704 (void) printf(gettext("would update '%s' to the following "
572 705 "configuration:\n"), zpool_get_name(zhp));
573 706
574 707 /* print original main pool and new tree */
575 708 print_vdev_tree(zhp, poolname, poolnvroot, 0, B_FALSE);
576 709 print_vdev_tree(zhp, NULL, nvroot, 0, B_FALSE);
577 710
578 711 /* Do the same for the logs */
579 712 if (num_logs(poolnvroot) > 0) {
580 713 print_vdev_tree(zhp, "logs", poolnvroot, 0, B_TRUE);
581 714 print_vdev_tree(zhp, NULL, nvroot, 0, B_TRUE);
582 715 } else if (num_logs(nvroot) > 0) {
583 716 print_vdev_tree(zhp, "logs", nvroot, 0, B_TRUE);
584 717 }
585 718
586 719 ret = 0;
587 720 } else {
588 721 ret = (zpool_add(zhp, nvroot) != 0);
589 722 }
|
↓ open down ↓ |
97 lines elided |
↑ open up ↑ |
590 723
591 724 nvlist_free(nvroot);
592 725 zpool_close(zhp);
593 726
594 727 return (ret);
595 728 }
596 729
597 730 /*
598 731 * zpool remove <pool> <vdev> ...
599 732 *
600 - * Removes the given vdev from the pool.
733 + * Removes the given vdev from the pool. Currently, this supports removing
734 + * spares, cache, and log devices from the pool.
601 735 */
602 736 int
603 737 zpool_do_remove(int argc, char **argv)
604 738 {
605 739 char *poolname;
606 740 int i, ret = 0;
607 741 zpool_handle_t *zhp;
608 - boolean_t stop = B_FALSE;
609 - boolean_t noop = B_FALSE;
610 - boolean_t parsable = B_FALSE;
611 - char c;
612 742
613 - /* check options */
614 - while ((c = getopt(argc, argv, "nps")) != -1) {
615 - switch (c) {
616 - case 'n':
617 - noop = B_TRUE;
618 - break;
619 - case 'p':
620 - parsable = B_TRUE;
621 - break;
622 - case 's':
623 - stop = B_TRUE;
624 - break;
625 - case '?':
626 - (void) fprintf(stderr, gettext("invalid option '%c'\n"),
627 - optopt);
628 - usage(B_FALSE);
629 - }
630 - }
743 + argc--;
744 + argv++;
631 745
632 - argc -= optind;
633 - argv += optind;
634 -
635 746 /* get pool name and check number of arguments */
636 747 if (argc < 1) {
637 748 (void) fprintf(stderr, gettext("missing pool name argument\n"));
638 749 usage(B_FALSE);
639 750 }
751 + if (argc < 2) {
752 + (void) fprintf(stderr, gettext("missing device\n"));
753 + usage(B_FALSE);
754 + }
640 755
641 756 poolname = argv[0];
642 757
643 758 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
644 759 return (1);
645 760
646 - if (stop && noop) {
647 - (void) fprintf(stderr, gettext("stop request ignored\n"));
648 - return (0);
649 - }
650 -
651 - if (stop) {
652 - if (argc > 1) {
653 - (void) fprintf(stderr, gettext("too many arguments\n"));
654 - usage(B_FALSE);
655 - }
656 - if (zpool_vdev_remove_cancel(zhp) != 0)
761 + for (i = 1; i < argc; i++) {
762 + if (zpool_vdev_remove(zhp, argv[i]) != 0)
657 763 ret = 1;
658 - } else {
659 - if (argc < 2) {
660 - (void) fprintf(stderr, gettext("missing device\n"));
661 - usage(B_FALSE);
662 - }
663 -
664 - for (i = 1; i < argc; i++) {
665 - if (noop) {
666 - uint64_t size;
667 -
668 - if (zpool_vdev_indirect_size(zhp, argv[i],
669 - &size) != 0) {
670 - ret = 1;
671 - break;
672 - }
673 - if (parsable) {
674 - (void) printf("%s %llu\n",
675 - argv[i], size);
676 - } else {
677 - char valstr[32];
678 - zfs_nicenum(size, valstr,
679 - sizeof (valstr));
680 - (void) printf("Memory that will be "
681 - "used after removing %s: %s\n",
682 - argv[i], valstr);
683 - }
684 - } else {
685 - if (zpool_vdev_remove(zhp, argv[i]) != 0)
686 - ret = 1;
687 - }
688 - }
689 764 }
690 765
691 766 return (ret);
692 767 }
693 768
694 769 /*
695 770 * zpool labelclear [-f] <vdev>
696 771 *
697 772 * -f Force clearing the label for the vdevs which are members of
698 773 * the exported or foreign pools.
699 774 *
700 775 * Verifies that the vdev is not active and zeros out the label information
701 776 * on the device.
702 777 */
703 778 int
704 779 zpool_do_labelclear(int argc, char **argv)
705 780 {
706 781 char vdev[MAXPATHLEN];
707 782 char *name = NULL;
708 783 struct stat st;
709 784 int c, fd, ret = 0;
710 785 nvlist_t *config;
711 786 pool_state_t state;
712 787 boolean_t inuse = B_FALSE;
713 788 boolean_t force = B_FALSE;
714 789
715 790 /* check options */
716 791 while ((c = getopt(argc, argv, "f")) != -1) {
717 792 switch (c) {
718 793 case 'f':
719 794 force = B_TRUE;
720 795 break;
721 796 default:
722 797 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
723 798 optopt);
724 799 usage(B_FALSE);
725 800 }
726 801 }
727 802
728 803 argc -= optind;
729 804 argv += optind;
730 805
731 806 /* get vdev name */
732 807 if (argc < 1) {
733 808 (void) fprintf(stderr, gettext("missing vdev name\n"));
734 809 usage(B_FALSE);
735 810 }
736 811 if (argc > 1) {
737 812 (void) fprintf(stderr, gettext("too many arguments\n"));
738 813 usage(B_FALSE);
739 814 }
740 815
741 816 /*
742 817 * Check if we were given absolute path and use it as is.
743 818 * Otherwise if the provided vdev name doesn't point to a file,
744 819 * try prepending dsk path and appending s0.
745 820 */
746 821 (void) strlcpy(vdev, argv[0], sizeof (vdev));
747 822 if (vdev[0] != '/' && stat(vdev, &st) != 0) {
748 823 char *s;
749 824
750 825 (void) snprintf(vdev, sizeof (vdev), "%s/%s",
751 826 ZFS_DISK_ROOT, argv[0]);
752 827 if ((s = strrchr(argv[0], 's')) == NULL ||
753 828 !isdigit(*(s + 1)))
754 829 (void) strlcat(vdev, "s0", sizeof (vdev));
755 830 if (stat(vdev, &st) != 0) {
756 831 (void) fprintf(stderr, gettext(
757 832 "failed to find device %s, try specifying absolute "
758 833 "path instead\n"), argv[0]);
759 834 return (1);
760 835 }
761 836 }
762 837
763 838 if ((fd = open(vdev, O_RDWR)) < 0) {
764 839 (void) fprintf(stderr, gettext("failed to open %s: %s\n"),
765 840 vdev, strerror(errno));
766 841 return (1);
767 842 }
768 843
769 844 if (zpool_read_label(fd, &config) != 0) {
770 845 (void) fprintf(stderr,
771 846 gettext("failed to read label from %s\n"), vdev);
772 847 return (1);
773 848 }
774 849 nvlist_free(config);
775 850
776 851 ret = zpool_in_use(g_zfs, fd, &state, &name, &inuse);
777 852 if (ret != 0) {
778 853 (void) fprintf(stderr,
779 854 gettext("failed to check state for %s\n"), vdev);
780 855 return (1);
781 856 }
782 857
783 858 if (!inuse)
784 859 goto wipe_label;
785 860
786 861 switch (state) {
787 862 default:
788 863 case POOL_STATE_ACTIVE:
789 864 case POOL_STATE_SPARE:
790 865 case POOL_STATE_L2CACHE:
791 866 (void) fprintf(stderr, gettext(
792 867 "%s is a member (%s) of pool \"%s\"\n"),
793 868 vdev, zpool_pool_state_to_name(state), name);
794 869 ret = 1;
795 870 goto errout;
796 871
797 872 case POOL_STATE_EXPORTED:
798 873 if (force)
799 874 break;
800 875 (void) fprintf(stderr, gettext(
801 876 "use '-f' to override the following error:\n"
802 877 "%s is a member of exported pool \"%s\"\n"),
803 878 vdev, name);
804 879 ret = 1;
805 880 goto errout;
806 881
807 882 case POOL_STATE_POTENTIALLY_ACTIVE:
808 883 if (force)
809 884 break;
810 885 (void) fprintf(stderr, gettext(
811 886 "use '-f' to override the following error:\n"
812 887 "%s is a member of potentially active pool \"%s\"\n"),
813 888 vdev, name);
814 889 ret = 1;
815 890 goto errout;
816 891
817 892 case POOL_STATE_DESTROYED:
818 893 /* inuse should never be set for a destroyed pool */
819 894 assert(0);
820 895 break;
821 896 }
822 897
823 898 wipe_label:
824 899 ret = zpool_clear_label(fd);
825 900 if (ret != 0) {
826 901 (void) fprintf(stderr,
827 902 gettext("failed to clear label for %s\n"), vdev);
828 903 }
829 904
830 905 errout:
831 906 free(name);
832 907 (void) close(fd);
833 908
834 909 return (ret);
835 910 }
836 911
837 912 /*
838 913 * zpool create [-fnd] [-B] [-o property=value] ...
839 914 * [-O file-system-property=value] ...
840 915 * [-R root] [-m mountpoint] <pool> <dev> ...
841 916 *
842 917 * -B Create boot partition.
843 918 * -f Force creation, even if devices appear in use
844 919 * -n Do not create the pool, but display the resulting layout if it
845 920 * were to be created.
846 921 * -R Create a pool under an alternate root
847 922 * -m Set default mountpoint for the root dataset. By default it's
848 923 * '/<pool>'
849 924 * -o Set property=value.
850 925 * -d Don't automatically enable all supported pool features
851 926 * (individual features can be enabled with -o).
852 927 * -O Set fsproperty=value in the pool's root file system
853 928 *
854 929 * Creates the named pool according to the given vdev specification. The
855 930 * bulk of the vdev processing is done in get_vdev_spec() in zpool_vdev.c. Once
856 931 * we get the nvlist back from get_vdev_spec(), we either print out the contents
857 932 * (if '-n' was specified), or pass it to libzfs to do the creation.
858 933 */
859 934
860 935 #define SYSTEM256 (256 * 1024 * 1024)
861 936 int
862 937 zpool_do_create(int argc, char **argv)
863 938 {
864 939 boolean_t force = B_FALSE;
865 940 boolean_t dryrun = B_FALSE;
866 941 boolean_t enable_all_pool_feat = B_TRUE;
867 942 zpool_boot_label_t boot_type = ZPOOL_NO_BOOT_LABEL;
868 943 uint64_t boot_size = 0;
869 944 int c;
870 945 nvlist_t *nvroot = NULL;
871 946 char *poolname;
872 947 int ret = 1;
873 948 char *altroot = NULL;
874 949 char *mountpoint = NULL;
875 950 nvlist_t *fsprops = NULL;
876 951 nvlist_t *props = NULL;
877 952 char *propval;
878 953
879 954 /* check options */
880 955 while ((c = getopt(argc, argv, ":fndBR:m:o:O:")) != -1) {
881 956 switch (c) {
882 957 case 'f':
883 958 force = B_TRUE;
884 959 break;
885 960 case 'n':
886 961 dryrun = B_TRUE;
887 962 break;
888 963 case 'd':
889 964 enable_all_pool_feat = B_FALSE;
890 965 break;
891 966 case 'B':
892 967 /*
893 968 * We should create the system partition.
894 969 * Also make sure the size is set.
895 970 */
896 971 boot_type = ZPOOL_CREATE_BOOT_LABEL;
897 972 if (boot_size == 0)
898 973 boot_size = SYSTEM256;
899 974 break;
900 975 case 'R':
901 976 altroot = optarg;
902 977 if (add_prop_list(zpool_prop_to_name(
903 978 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
904 979 goto errout;
905 980 if (nvlist_lookup_string(props,
906 981 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
907 982 &propval) == 0)
908 983 break;
909 984 if (add_prop_list(zpool_prop_to_name(
910 985 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
911 986 goto errout;
912 987 break;
913 988 case 'm':
914 989 /* Equivalent to -O mountpoint=optarg */
915 990 mountpoint = optarg;
916 991 break;
917 992 case 'o':
918 993 if ((propval = strchr(optarg, '=')) == NULL) {
919 994 (void) fprintf(stderr, gettext("missing "
920 995 "'=' for -o option\n"));
921 996 goto errout;
922 997 }
923 998 *propval = '\0';
924 999 propval++;
925 1000
926 1001 if (add_prop_list(optarg, propval, &props, B_TRUE))
927 1002 goto errout;
928 1003
929 1004 /*
930 1005 * Get bootsize value for make_root_vdev().
931 1006 */
932 1007 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_BOOTSIZE) {
933 1008 if (zfs_nicestrtonum(g_zfs, propval,
934 1009 &boot_size) < 0 || boot_size == 0) {
935 1010 (void) fprintf(stderr,
936 1011 gettext("bad boot partition size "
937 1012 "'%s': %s\n"), propval,
938 1013 libzfs_error_description(g_zfs));
939 1014 goto errout;
940 1015 }
941 1016 }
942 1017
943 1018 /*
944 1019 * If the user is creating a pool that doesn't support
945 1020 * feature flags, don't enable any features.
946 1021 */
947 1022 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_VERSION) {
948 1023 char *end;
949 1024 u_longlong_t ver;
950 1025
951 1026 ver = strtoull(propval, &end, 10);
952 1027 if (*end == '\0' &&
953 1028 ver < SPA_VERSION_FEATURES) {
954 1029 enable_all_pool_feat = B_FALSE;
955 1030 }
956 1031 }
957 1032 if (zpool_name_to_prop(optarg) == ZPOOL_PROP_ALTROOT)
958 1033 altroot = propval;
959 1034 break;
960 1035 case 'O':
961 1036 if ((propval = strchr(optarg, '=')) == NULL) {
962 1037 (void) fprintf(stderr, gettext("missing "
963 1038 "'=' for -O option\n"));
964 1039 goto errout;
965 1040 }
966 1041 *propval = '\0';
967 1042 propval++;
968 1043
969 1044 /*
970 1045 * Mountpoints are checked and then added later.
971 1046 * Uniquely among properties, they can be specified
972 1047 * more than once, to avoid conflict with -m.
973 1048 */
974 1049 if (0 == strcmp(optarg,
975 1050 zfs_prop_to_name(ZFS_PROP_MOUNTPOINT))) {
976 1051 mountpoint = propval;
977 1052 } else if (add_prop_list(optarg, propval, &fsprops,
978 1053 B_FALSE)) {
979 1054 goto errout;
980 1055 }
981 1056 break;
982 1057 case ':':
983 1058 (void) fprintf(stderr, gettext("missing argument for "
984 1059 "'%c' option\n"), optopt);
985 1060 goto badusage;
986 1061 case '?':
987 1062 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
988 1063 optopt);
989 1064 goto badusage;
990 1065 }
991 1066 }
992 1067
993 1068 argc -= optind;
994 1069 argv += optind;
995 1070
996 1071 /* get pool name and check number of arguments */
997 1072 if (argc < 1) {
998 1073 (void) fprintf(stderr, gettext("missing pool name argument\n"));
999 1074 goto badusage;
1000 1075 }
1001 1076 if (argc < 2) {
1002 1077 (void) fprintf(stderr, gettext("missing vdev specification\n"));
1003 1078 goto badusage;
1004 1079 }
1005 1080
1006 1081 poolname = argv[0];
1007 1082
1008 1083 /*
1009 1084 * As a special case, check for use of '/' in the name, and direct the
1010 1085 * user to use 'zfs create' instead.
1011 1086 */
1012 1087 if (strchr(poolname, '/') != NULL) {
1013 1088 (void) fprintf(stderr, gettext("cannot create '%s': invalid "
1014 1089 "character '/' in pool name\n"), poolname);
1015 1090 (void) fprintf(stderr, gettext("use 'zfs create' to "
1016 1091 "create a dataset\n"));
1017 1092 goto errout;
1018 1093 }
1019 1094
1020 1095 /*
1021 1096 * Make sure the bootsize is set when ZPOOL_CREATE_BOOT_LABEL is used,
1022 1097 * and not set otherwise.
1023 1098 */
1024 1099 if (boot_type == ZPOOL_CREATE_BOOT_LABEL) {
1025 1100 const char *propname;
1026 1101 char *strptr, *buf = NULL;
1027 1102 int rv;
1028 1103
1029 1104 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1030 1105 if (nvlist_lookup_string(props, propname, &strptr) != 0) {
1031 1106 (void) asprintf(&buf, "%" PRIu64, boot_size);
1032 1107 if (buf == NULL) {
1033 1108 (void) fprintf(stderr,
1034 1109 gettext("internal error: out of memory\n"));
1035 1110 goto errout;
1036 1111 }
1037 1112 rv = add_prop_list(propname, buf, &props, B_TRUE);
1038 1113 free(buf);
1039 1114 if (rv != 0)
1040 1115 goto errout;
1041 1116 }
1042 1117 } else {
1043 1118 const char *propname;
1044 1119 char *strptr;
1045 1120
1046 1121 propname = zpool_prop_to_name(ZPOOL_PROP_BOOTSIZE);
1047 1122 if (nvlist_lookup_string(props, propname, &strptr) == 0) {
1048 1123 (void) fprintf(stderr, gettext("error: setting boot "
1049 1124 "partition size requires option '-B'\n"));
1050 1125 goto errout;
1051 1126 }
1052 1127 }
1053 1128
1054 1129 /* pass off to get_vdev_spec for bulk processing */
1055 1130 nvroot = make_root_vdev(NULL, force, !force, B_FALSE, dryrun,
1056 1131 boot_type, boot_size, argc - 1, argv + 1);
1057 1132 if (nvroot == NULL)
1058 1133 goto errout;
1059 1134
1060 1135 /* make_root_vdev() allows 0 toplevel children if there are spares */
1061 1136 if (!zfs_allocatable_devs(nvroot)) {
1062 1137 (void) fprintf(stderr, gettext("invalid vdev "
1063 1138 "specification: at least one toplevel vdev must be "
1064 1139 "specified\n"));
1065 1140 goto errout;
1066 1141 }
1067 1142
1068 1143 if (altroot != NULL && altroot[0] != '/') {
1069 1144 (void) fprintf(stderr, gettext("invalid alternate root '%s': "
1070 1145 "must be an absolute path\n"), altroot);
1071 1146 goto errout;
1072 1147 }
1073 1148
1074 1149 /*
1075 1150 * Check the validity of the mountpoint and direct the user to use the
1076 1151 * '-m' mountpoint option if it looks like its in use.
1077 1152 */
1078 1153 if (mountpoint == NULL ||
1079 1154 (strcmp(mountpoint, ZFS_MOUNTPOINT_LEGACY) != 0 &&
1080 1155 strcmp(mountpoint, ZFS_MOUNTPOINT_NONE) != 0)) {
1081 1156 char buf[MAXPATHLEN];
1082 1157 DIR *dirp;
1083 1158
1084 1159 if (mountpoint && mountpoint[0] != '/') {
1085 1160 (void) fprintf(stderr, gettext("invalid mountpoint "
1086 1161 "'%s': must be an absolute path, 'legacy', or "
1087 1162 "'none'\n"), mountpoint);
1088 1163 goto errout;
1089 1164 }
1090 1165
1091 1166 if (mountpoint == NULL) {
1092 1167 if (altroot != NULL)
1093 1168 (void) snprintf(buf, sizeof (buf), "%s/%s",
1094 1169 altroot, poolname);
1095 1170 else
1096 1171 (void) snprintf(buf, sizeof (buf), "/%s",
1097 1172 poolname);
1098 1173 } else {
1099 1174 if (altroot != NULL)
1100 1175 (void) snprintf(buf, sizeof (buf), "%s%s",
1101 1176 altroot, mountpoint);
1102 1177 else
1103 1178 (void) snprintf(buf, sizeof (buf), "%s",
1104 1179 mountpoint);
1105 1180 }
1106 1181
1107 1182 if ((dirp = opendir(buf)) == NULL && errno != ENOENT) {
1108 1183 (void) fprintf(stderr, gettext("mountpoint '%s' : "
1109 1184 "%s\n"), buf, strerror(errno));
1110 1185 (void) fprintf(stderr, gettext("use '-m' "
1111 1186 "option to provide a different default\n"));
1112 1187 goto errout;
1113 1188 } else if (dirp) {
1114 1189 int count = 0;
1115 1190
1116 1191 while (count < 3 && readdir(dirp) != NULL)
1117 1192 count++;
1118 1193 (void) closedir(dirp);
1119 1194
1120 1195 if (count > 2) {
1121 1196 (void) fprintf(stderr, gettext("mountpoint "
1122 1197 "'%s' exists and is not empty\n"), buf);
1123 1198 (void) fprintf(stderr, gettext("use '-m' "
1124 1199 "option to provide a "
1125 1200 "different default\n"));
1126 1201 goto errout;
1127 1202 }
1128 1203 }
1129 1204 }
1130 1205
1131 1206 /*
1132 1207 * Now that the mountpoint's validity has been checked, ensure that
1133 1208 * the property is set appropriately prior to creating the pool.
1134 1209 */
1135 1210 if (mountpoint != NULL) {
1136 1211 ret = add_prop_list(zfs_prop_to_name(ZFS_PROP_MOUNTPOINT),
1137 1212 mountpoint, &fsprops, B_FALSE);
1138 1213 if (ret != 0)
1139 1214 goto errout;
1140 1215 }
1141 1216
1142 1217 ret = 1;
1143 1218 if (dryrun) {
1144 1219 /*
1145 1220 * For a dry run invocation, print out a basic message and run
1146 1221 * through all the vdevs in the list and print out in an
1147 1222 * appropriate hierarchy.
1148 1223 */
1149 1224 (void) printf(gettext("would create '%s' with the "
1150 1225 "following layout:\n\n"), poolname);
1151 1226
1152 1227 print_vdev_tree(NULL, poolname, nvroot, 0, B_FALSE);
1153 1228 if (num_logs(nvroot) > 0)
1154 1229 print_vdev_tree(NULL, "logs", nvroot, 0, B_TRUE);
1155 1230
1156 1231 ret = 0;
1157 1232 } else {
1158 1233 /*
1159 1234 * Hand off to libzfs.
1160 1235 */
1161 1236 if (enable_all_pool_feat) {
1162 1237 spa_feature_t i;
1163 1238 for (i = 0; i < SPA_FEATURES; i++) {
1164 1239 char propname[MAXPATHLEN];
1165 1240 zfeature_info_t *feat = &spa_feature_table[i];
1166 1241
1167 1242 (void) snprintf(propname, sizeof (propname),
1168 1243 "feature@%s", feat->fi_uname);
1169 1244
1170 1245 /*
1171 1246 * Skip feature if user specified it manually
1172 1247 * on the command line.
1173 1248 */
1174 1249 if (nvlist_exists(props, propname))
1175 1250 continue;
1176 1251
1177 1252 ret = add_prop_list(propname,
1178 1253 ZFS_FEATURE_ENABLED, &props, B_TRUE);
1179 1254 if (ret != 0)
1180 1255 goto errout;
1181 1256 }
1182 1257 }
1183 1258
1184 1259 ret = 1;
1185 1260 if (zpool_create(g_zfs, poolname,
1186 1261 nvroot, props, fsprops) == 0) {
1187 1262 zfs_handle_t *pool = zfs_open(g_zfs, poolname,
1188 1263 ZFS_TYPE_FILESYSTEM);
1189 1264 if (pool != NULL) {
1190 1265 if (zfs_mount(pool, NULL, 0) == 0)
1191 1266 ret = zfs_shareall(pool);
1192 1267 zfs_close(pool);
1193 1268 }
1194 1269 } else if (libzfs_errno(g_zfs) == EZFS_INVALIDNAME) {
1195 1270 (void) fprintf(stderr, gettext("pool name may have "
1196 1271 "been omitted\n"));
1197 1272 }
1198 1273 }
1199 1274
1200 1275 errout:
1201 1276 nvlist_free(nvroot);
1202 1277 nvlist_free(fsprops);
1203 1278 nvlist_free(props);
1204 1279 return (ret);
1205 1280 badusage:
1206 1281 nvlist_free(fsprops);
1207 1282 nvlist_free(props);
1208 1283 usage(B_FALSE);
1209 1284 return (2);
1210 1285 }
1211 1286
1212 1287 /*
1213 1288 * zpool destroy <pool>
1214 1289 *
1215 1290 * -f Forcefully unmount any datasets
1216 1291 *
1217 1292 * Destroy the given pool. Automatically unmounts any datasets in the pool.
1218 1293 */
1219 1294 int
1220 1295 zpool_do_destroy(int argc, char **argv)
1221 1296 {
1222 1297 boolean_t force = B_FALSE;
1223 1298 int c;
1224 1299 char *pool;
1225 1300 zpool_handle_t *zhp;
1226 1301 int ret;
1227 1302
1228 1303 /* check options */
1229 1304 while ((c = getopt(argc, argv, "f")) != -1) {
1230 1305 switch (c) {
1231 1306 case 'f':
1232 1307 force = B_TRUE;
1233 1308 break;
1234 1309 case '?':
1235 1310 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1236 1311 optopt);
1237 1312 usage(B_FALSE);
1238 1313 }
1239 1314 }
1240 1315
1241 1316 argc -= optind;
1242 1317 argv += optind;
1243 1318
1244 1319 /* check arguments */
1245 1320 if (argc < 1) {
1246 1321 (void) fprintf(stderr, gettext("missing pool argument\n"));
1247 1322 usage(B_FALSE);
1248 1323 }
1249 1324 if (argc > 1) {
1250 1325 (void) fprintf(stderr, gettext("too many arguments\n"));
1251 1326 usage(B_FALSE);
1252 1327 }
1253 1328
1254 1329 pool = argv[0];
1255 1330
1256 1331 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
|
↓ open down ↓ |
558 lines elided |
↑ open up ↑ |
1257 1332 /*
1258 1333 * As a special case, check for use of '/' in the name, and
1259 1334 * direct the user to use 'zfs destroy' instead.
1260 1335 */
1261 1336 if (strchr(pool, '/') != NULL)
1262 1337 (void) fprintf(stderr, gettext("use 'zfs destroy' to "
1263 1338 "destroy a dataset\n"));
1264 1339 return (1);
1265 1340 }
1266 1341
1342 + ret = zfs_check_krrp(g_zfs, argv[0]);
1343 + /*
1344 + * ENOTSUP means that autosnaper doesn't handle this pool.
1345 + */
1346 + if (ret != ENOTSUP) {
1347 + if (ret == ECHILD || ret == EBUSY || ret == EUSERS)
1348 + ret = EBUSY;
1349 +
1350 + if (ret) {
1351 + (void) zpool_standard_error(g_zfs,
1352 + ret, gettext("cannnot destroy pool because "
1353 + "of krrp"));
1354 + zpool_close(zhp);
1355 + ret = 1;
1356 + return (ret);
1357 + }
1358 + } else {
1359 + ret = 0;
1360 + }
1361 +
1267 1362 if (zpool_disable_datasets(zhp, force) != 0) {
1268 1363 (void) fprintf(stderr, gettext("could not destroy '%s': "
1269 1364 "could not unmount datasets\n"), zpool_get_name(zhp));
1270 1365 return (1);
1271 1366 }
1272 1367
1273 1368 /* The history must be logged as part of the export */
1274 1369 log_history = B_FALSE;
1275 1370
1276 1371 ret = (zpool_destroy(zhp, history_str) != 0);
1277 1372
1278 1373 zpool_close(zhp);
1279 1374
1280 1375 return (ret);
1281 1376 }
1282 1377
1283 1378 /*
1284 1379 * zpool export [-f] <pool> ...
1285 1380 *
1286 1381 * -f Forcefully unmount datasets
|
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
1287 1382 *
1288 1383 * Export the given pools. By default, the command will attempt to cleanly
1289 1384 * unmount any active datasets within the pool. If the '-f' flag is specified,
1290 1385 * then the datasets will be forcefully unmounted.
1291 1386 */
1292 1387 int
1293 1388 zpool_do_export(int argc, char **argv)
1294 1389 {
1295 1390 boolean_t force = B_FALSE;
1296 1391 boolean_t hardforce = B_FALSE;
1392 + boolean_t saveconfig = B_FALSE;
1297 1393 int c;
1394 + int n_threads = sysconf(_SC_NPROCESSORS_ONLN) * 2;
1298 1395 zpool_handle_t *zhp;
1299 1396 int ret;
1300 1397 int i;
1301 1398
1302 1399 /* check options */
1303 - while ((c = getopt(argc, argv, "fF")) != -1) {
1400 + while ((c = getopt(argc, argv, ":fFct:")) != -1) {
1304 1401 switch (c) {
1305 1402 case 'f':
1306 1403 force = B_TRUE;
1307 1404 break;
1308 1405 case 'F':
1309 1406 hardforce = B_TRUE;
1310 1407 break;
1408 + case 'c':
1409 + saveconfig = B_TRUE;
1410 + break;
1411 + case 't':
1412 + n_threads = atoi(optarg);
1413 + break;
1311 1414 case '?':
1312 1415 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
1313 1416 optopt);
1314 1417 usage(B_FALSE);
1418 + break;
1419 + case ':':
1420 + (void) fprintf(stderr, gettext("missing argument "
1421 + "for option '%c'\n"), optopt);
1422 + usage(B_FALSE);
1423 + break;
1315 1424 }
1316 1425 }
1317 1426
1318 1427 argc -= optind;
1319 1428 argv += optind;
1320 1429
1321 1430 /* check arguments */
1322 1431 if (argc < 1) {
1323 1432 (void) fprintf(stderr, gettext("missing pool argument\n"));
1324 1433 usage(B_FALSE);
1325 1434 }
1326 1435
1327 1436 ret = 0;
1328 1437 for (i = 0; i < argc; i++) {
1329 1438 if ((zhp = zpool_open_canfail(g_zfs, argv[i])) == NULL) {
1330 1439 ret = 1;
1331 1440 continue;
1332 1441 }
1333 1442
1334 - if (zpool_disable_datasets(zhp, force) != 0) {
1443 + ret = zfs_check_krrp(g_zfs, argv[0]);
1444 + /*
1445 + * ENOTSUP means that autosnaper doesn't handle this pool.
1446 + */
1447 + if (ret != ENOTSUP) {
1448 + if (ret == ECHILD || ret == EBUSY || ret == EUSERS)
1449 + ret = EBUSY;
1450 +
1451 + if (ret) {
1452 + (void) zpool_standard_error(g_zfs,
1453 + ret, gettext("cannnot export pool because "
1454 + "of krrp"));
1455 + zpool_close(zhp);
1456 + ret = 1;
1457 + continue;
1458 + }
1459 + } else {
1460 + ret = 0;
1461 + }
1462 +
1463 + if (zpool_disable_datasets_ex(zhp, force, n_threads) != 0) {
1335 1464 ret = 1;
1336 1465 zpool_close(zhp);
1337 1466 continue;
1338 1467 }
1339 1468
1340 1469 /* The history must be logged as part of the export */
1341 1470 log_history = B_FALSE;
1342 1471
1343 1472 if (hardforce) {
1344 - if (zpool_export_force(zhp, history_str) != 0)
1473 + if (zpool_export_force(zhp, saveconfig, history_str)
1474 + != 0)
1345 1475 ret = 1;
1346 - } else if (zpool_export(zhp, force, history_str) != 0) {
1476 + } else if (zpool_export(zhp, force, saveconfig, history_str)
1477 + != 0) {
1347 1478 ret = 1;
1348 1479 }
1349 1480
1350 1481 zpool_close(zhp);
1351 1482 }
1352 1483
1353 1484 return (ret);
1354 1485 }
1355 1486
1356 1487 /*
1357 1488 * Given a vdev configuration, determine the maximum width needed for the device
1358 1489 * name column.
1359 1490 */
1360 1491 static int
1361 1492 max_width(zpool_handle_t *zhp, nvlist_t *nv, int depth, int max)
1362 1493 {
1363 1494 char *name = zpool_vdev_name(g_zfs, zhp, nv, B_TRUE);
1364 1495 nvlist_t **child;
1365 1496 uint_t c, children;
1366 1497 int ret;
1367 1498
1368 1499 if (strlen(name) + depth > max)
1369 1500 max = strlen(name) + depth;
1370 1501
1371 1502 free(name);
1372 1503
1373 1504 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1374 1505 &child, &children) == 0) {
1375 1506 for (c = 0; c < children; c++)
1376 1507 if ((ret = max_width(zhp, child[c], depth + 2,
1377 1508 max)) > max)
1378 1509 max = ret;
1379 1510 }
1380 1511
1381 1512 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1382 1513 &child, &children) == 0) {
1383 1514 for (c = 0; c < children; c++)
1384 1515 if ((ret = max_width(zhp, child[c], depth + 2,
1385 1516 max)) > max)
1386 1517 max = ret;
1387 1518 }
1388 1519
1389 1520 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1390 1521 &child, &children) == 0) {
1391 1522 for (c = 0; c < children; c++)
1392 1523 if ((ret = max_width(zhp, child[c], depth + 2,
1393 1524 max)) > max)
1394 1525 max = ret;
1395 1526 }
1396 1527
1397 1528
1398 1529 return (max);
1399 1530 }
1400 1531
1401 1532 typedef struct spare_cbdata {
1402 1533 uint64_t cb_guid;
1403 1534 zpool_handle_t *cb_zhp;
1404 1535 } spare_cbdata_t;
1405 1536
1406 1537 static boolean_t
1407 1538 find_vdev(nvlist_t *nv, uint64_t search)
1408 1539 {
1409 1540 uint64_t guid;
1410 1541 nvlist_t **child;
1411 1542 uint_t c, children;
1412 1543
1413 1544 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid) == 0 &&
1414 1545 search == guid)
1415 1546 return (B_TRUE);
1416 1547
1417 1548 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1418 1549 &child, &children) == 0) {
1419 1550 for (c = 0; c < children; c++)
1420 1551 if (find_vdev(child[c], search))
1421 1552 return (B_TRUE);
1422 1553 }
1423 1554
1424 1555 return (B_FALSE);
1425 1556 }
1426 1557
1427 1558 static int
1428 1559 find_spare(zpool_handle_t *zhp, void *data)
1429 1560 {
1430 1561 spare_cbdata_t *cbp = data;
1431 1562 nvlist_t *config, *nvroot;
1432 1563
1433 1564 config = zpool_get_config(zhp, NULL);
1434 1565 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1435 1566 &nvroot) == 0);
1436 1567
1437 1568 if (find_vdev(nvroot, cbp->cb_guid)) {
1438 1569 cbp->cb_zhp = zhp;
1439 1570 return (1);
1440 1571 }
1441 1572
1442 1573 zpool_close(zhp);
1443 1574 return (0);
1444 1575 }
1445 1576
1446 1577 /*
1447 1578 * Print out configuration state as requested by status_callback.
1448 1579 */
1449 1580 void
1450 1581 print_status_config(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
1451 1582 int namewidth, int depth, boolean_t isspare)
|
↓ open down ↓ |
95 lines elided |
↑ open up ↑ |
1452 1583 {
1453 1584 nvlist_t **child;
1454 1585 uint_t c, children;
1455 1586 pool_scan_stat_t *ps = NULL;
1456 1587 vdev_stat_t *vs;
1457 1588 char rbuf[6], wbuf[6], cbuf[6];
1458 1589 char *vname;
1459 1590 uint64_t notpresent;
1460 1591 spare_cbdata_t cb;
1461 1592 const char *state;
1462 - char *type;
1463 1593
1464 1594 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1465 1595 &child, &children) != 0)
1466 1596 children = 0;
1467 1597
1468 1598 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1469 1599 (uint64_t **)&vs, &c) == 0);
1470 1600
1471 - verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1472 -
1473 - if (strcmp(type, VDEV_TYPE_INDIRECT) == 0)
1474 - return;
1475 -
1476 1601 state = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1477 1602 if (isspare) {
1478 1603 /*
1479 1604 * For hot spares, we use the terms 'INUSE' and 'AVAILABLE' for
1480 1605 * online drives.
1481 1606 */
1482 1607 if (vs->vs_aux == VDEV_AUX_SPARED)
1483 1608 state = "INUSE";
1484 1609 else if (vs->vs_state == VDEV_STATE_HEALTHY)
1485 1610 state = "AVAIL";
1486 1611 }
1487 1612
1488 1613 (void) printf("\t%*s%-*s %-8s", depth, "", namewidth - depth,
1489 1614 name, state);
1490 1615
1491 1616 if (!isspare) {
1492 1617 zfs_nicenum(vs->vs_read_errors, rbuf, sizeof (rbuf));
1493 1618 zfs_nicenum(vs->vs_write_errors, wbuf, sizeof (wbuf));
1494 1619 zfs_nicenum(vs->vs_checksum_errors, cbuf, sizeof (cbuf));
1495 1620 (void) printf(" %5s %5s %5s", rbuf, wbuf, cbuf);
1496 1621 }
1497 1622
1498 1623 if (nvlist_lookup_uint64(nv, ZPOOL_CONFIG_NOT_PRESENT,
1499 1624 ¬present) == 0) {
1500 1625 char *path;
1501 1626 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0);
1502 1627 (void) printf(" was %s", path);
1503 1628 } else if (vs->vs_aux != 0) {
1504 1629 (void) printf(" ");
1505 1630
1506 1631 switch (vs->vs_aux) {
1507 1632 case VDEV_AUX_OPEN_FAILED:
1508 1633 (void) printf(gettext("cannot open"));
1509 1634 break;
1510 1635
1511 1636 case VDEV_AUX_BAD_GUID_SUM:
1512 1637 (void) printf(gettext("missing device"));
1513 1638 break;
1514 1639
1515 1640 case VDEV_AUX_NO_REPLICAS:
1516 1641 (void) printf(gettext("insufficient replicas"));
1517 1642 break;
1518 1643
1519 1644 case VDEV_AUX_VERSION_NEWER:
1520 1645 (void) printf(gettext("newer version"));
1521 1646 break;
1522 1647
1523 1648 case VDEV_AUX_UNSUP_FEAT:
1524 1649 (void) printf(gettext("unsupported feature(s)"));
1525 1650 break;
1526 1651
1527 1652 case VDEV_AUX_SPARED:
1528 1653 verify(nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID,
1529 1654 &cb.cb_guid) == 0);
1530 1655 if (zpool_iter(g_zfs, find_spare, &cb) == 1) {
1531 1656 if (strcmp(zpool_get_name(cb.cb_zhp),
1532 1657 zpool_get_name(zhp)) == 0)
1533 1658 (void) printf(gettext("currently in "
1534 1659 "use"));
1535 1660 else
1536 1661 (void) printf(gettext("in use by "
1537 1662 "pool '%s'"),
1538 1663 zpool_get_name(cb.cb_zhp));
1539 1664 zpool_close(cb.cb_zhp);
1540 1665 } else {
1541 1666 (void) printf(gettext("currently in use"));
1542 1667 }
1543 1668 break;
1544 1669
1545 1670 case VDEV_AUX_ERR_EXCEEDED:
1546 1671 (void) printf(gettext("too many errors"));
1547 1672 break;
1548 1673
1549 1674 case VDEV_AUX_IO_FAILURE:
1550 1675 (void) printf(gettext("experienced I/O failures"));
1551 1676 break;
1552 1677
1553 1678 case VDEV_AUX_BAD_LOG:
1554 1679 (void) printf(gettext("bad intent log"));
|
↓ open down ↓ |
69 lines elided |
↑ open up ↑ |
1555 1680 break;
1556 1681
1557 1682 case VDEV_AUX_EXTERNAL:
1558 1683 (void) printf(gettext("external device fault"));
1559 1684 break;
1560 1685
1561 1686 case VDEV_AUX_SPLIT_POOL:
1562 1687 (void) printf(gettext("split into new pool"));
1563 1688 break;
1564 1689
1565 - case VDEV_AUX_CHILDREN_OFFLINE:
1566 - (void) printf(gettext("all children offline"));
1567 - break;
1568 -
1569 1690 default:
1570 1691 (void) printf(gettext("corrupted data"));
1571 1692 break;
1572 1693 }
1573 1694 }
1574 1695
1575 1696 (void) nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_SCAN_STATS,
1576 1697 (uint64_t **)&ps, &c);
1577 1698
1578 - if (ps && ps->pss_state == DSS_SCANNING &&
1579 - vs->vs_scan_processed != 0 && children == 0) {
1699 + if (ps != NULL && (ps->pss_state == DSS_SCANNING ||
1700 + ps->pss_state == DSS_FINISHING) && vs->vs_scan_processed != 0 &&
1701 + children == 0) {
1580 1702 (void) printf(gettext(" (%s)"),
1581 1703 (ps->pss_func == POOL_SCAN_RESILVER) ?
1582 1704 "resilvering" : "repairing");
1583 1705 }
1584 1706
1585 1707 (void) printf("\n");
1586 1708
1587 1709 for (c = 0; c < children; c++) {
1588 - uint64_t islog = B_FALSE, ishole = B_FALSE;
1710 + uint64_t islog = B_FALSE, ishole = B_FALSE, isspecial = B_FALSE;
1589 1711
1590 1712 /* Don't print logs or holes here */
1591 1713 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1592 1714 &islog);
1593 1715 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_HOLE,
1594 1716 &ishole);
1595 - if (islog || ishole)
1717 + (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_SPECIAL,
1718 + &isspecial);
1719 + if (islog || ishole || isspecial)
1596 1720 continue;
1597 1721 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1598 1722 print_status_config(zhp, vname, child[c],
1599 1723 namewidth, depth + 2, isspare);
1600 1724 free(vname);
1601 1725 }
1602 1726 }
1603 1727
1604 1728
1605 1729 /*
1606 1730 * Print the configuration of an exported pool. Iterate over all vdevs in the
1607 1731 * pool, printing out the name and status for each one.
1608 1732 */
1609 1733 void
1610 1734 print_import_config(const char *name, nvlist_t *nv, int namewidth, int depth)
1611 1735 {
1612 1736 nvlist_t **child;
1613 1737 uint_t c, children;
1614 1738 vdev_stat_t *vs;
1615 1739 char *type, *vname;
1616 1740
1617 1741 verify(nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) == 0);
1618 1742 if (strcmp(type, VDEV_TYPE_MISSING) == 0 ||
1619 1743 strcmp(type, VDEV_TYPE_HOLE) == 0)
1620 1744 return;
1621 1745
1622 1746 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
1623 1747 (uint64_t **)&vs, &c) == 0);
1624 1748
1625 1749 (void) printf("\t%*s%-*s", depth, "", namewidth - depth, name);
1626 1750 (void) printf(" %s", zpool_state_to_name(vs->vs_state, vs->vs_aux));
1627 1751
1628 1752 if (vs->vs_aux != 0) {
1629 1753 (void) printf(" ");
1630 1754
1631 1755 switch (vs->vs_aux) {
1632 1756 case VDEV_AUX_OPEN_FAILED:
1633 1757 (void) printf(gettext("cannot open"));
1634 1758 break;
1635 1759
1636 1760 case VDEV_AUX_BAD_GUID_SUM:
1637 1761 (void) printf(gettext("missing device"));
1638 1762 break;
1639 1763
1640 1764 case VDEV_AUX_NO_REPLICAS:
1641 1765 (void) printf(gettext("insufficient replicas"));
1642 1766 break;
1643 1767
1644 1768 case VDEV_AUX_VERSION_NEWER:
1645 1769 (void) printf(gettext("newer version"));
|
↓ open down ↓ |
40 lines elided |
↑ open up ↑ |
1646 1770 break;
1647 1771
1648 1772 case VDEV_AUX_UNSUP_FEAT:
1649 1773 (void) printf(gettext("unsupported feature(s)"));
1650 1774 break;
1651 1775
1652 1776 case VDEV_AUX_ERR_EXCEEDED:
1653 1777 (void) printf(gettext("too many errors"));
1654 1778 break;
1655 1779
1656 - case VDEV_AUX_CHILDREN_OFFLINE:
1657 - (void) printf(gettext("all children offline"));
1658 - break;
1659 -
1660 1780 default:
1661 1781 (void) printf(gettext("corrupted data"));
1662 1782 break;
1663 1783 }
1664 1784 }
1665 1785 (void) printf("\n");
1666 1786
1667 1787 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
1668 1788 &child, &children) != 0)
1669 1789 return;
1670 1790
1671 1791 for (c = 0; c < children; c++) {
1672 - uint64_t is_log = B_FALSE;
1792 + uint64_t is_log = B_FALSE, is_special = B_FALSE;
1673 1793
1674 1794 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1675 1795 &is_log);
1676 - if (is_log)
1796 + (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_SPECIAL,
1797 + &is_special);
1798 + if (is_log || is_special)
1677 1799 continue;
1678 1800
1679 1801 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_TRUE);
1680 1802 print_import_config(vname, child[c], namewidth, depth + 2);
1681 1803 free(vname);
1682 1804 }
1683 1805
1684 1806 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
1685 1807 &child, &children) == 0) {
1686 1808 (void) printf(gettext("\tcache\n"));
1687 1809 for (c = 0; c < children; c++) {
1688 1810 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1689 1811 (void) printf("\t %s\n", vname);
1690 1812 free(vname);
1691 1813 }
1692 1814 }
1693 1815
1694 1816 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES,
1695 1817 &child, &children) == 0) {
1696 1818 (void) printf(gettext("\tspares\n"));
1697 1819 for (c = 0; c < children; c++) {
1698 1820 vname = zpool_vdev_name(g_zfs, NULL, child[c], B_FALSE);
1699 1821 (void) printf("\t %s\n", vname);
1700 1822 free(vname);
1701 1823 }
1702 1824 }
1703 1825 }
1704 1826
1705 1827 /*
1706 1828 * Print log vdevs.
1707 1829 * Logs are recorded as top level vdevs in the main pool child array
1708 1830 * but with "is_log" set to 1. We use either print_status_config() or
1709 1831 * print_import_config() to print the top level logs then any log
1710 1832 * children (eg mirrored slogs) are printed recursively - which
1711 1833 * works because only the top level vdev is marked "is_log"
1712 1834 */
1713 1835 static void
1714 1836 print_logs(zpool_handle_t *zhp, nvlist_t *nv, int namewidth, boolean_t verbose)
1715 1837 {
1716 1838 uint_t c, children;
1717 1839 nvlist_t **child;
1718 1840
1719 1841 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1720 1842 &children) != 0)
1721 1843 return;
1722 1844
1723 1845 (void) printf(gettext("\tlogs\n"));
1724 1846
1725 1847 for (c = 0; c < children; c++) {
1726 1848 uint64_t is_log = B_FALSE;
1727 1849 char *name;
1728 1850
1729 1851 (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
1730 1852 &is_log);
1731 1853 if (!is_log)
1732 1854 continue;
1733 1855 name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
|
↓ open down ↓ |
47 lines elided |
↑ open up ↑ |
1734 1856 if (verbose)
1735 1857 print_status_config(zhp, name, child[c], namewidth,
1736 1858 2, B_FALSE);
1737 1859 else
1738 1860 print_import_config(name, child[c], namewidth, 2);
1739 1861 free(name);
1740 1862 }
1741 1863 }
1742 1864
1743 1865 /*
1866 + * Print special vdevs.
1867 + * Special vdevs are recorded as top level vdevs in the main pool child array
1868 + * but with "is_special" set to 1. We use either print_status_config() or
1869 + * print_import_config() to print the top level logs then any log
1870 + * children (eg mirrored slogs) are printed recursively - which
1871 + * works because only the top level vdev is marked "is_special"
1872 + */
1873 +static void
1874 +print_special(zpool_handle_t *zhp, nvlist_t *nv, int namewidth,
1875 + boolean_t verbose)
1876 +{
1877 + uint_t c, children;
1878 + nvlist_t **child;
1879 +
1880 + if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child,
1881 + &children) != 0)
1882 + return;
1883 +
1884 + (void) printf(gettext("\tspecial\n"));
1885 +
1886 + for (c = 0; c < children; c++) {
1887 + uint64_t is_special = B_FALSE;
1888 + char *name;
1889 +
1890 + (void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_SPECIAL,
1891 + &is_special);
1892 + if (!is_special)
1893 + continue;
1894 + name = zpool_vdev_name(g_zfs, zhp, child[c], B_TRUE);
1895 + if (verbose)
1896 + print_status_config(zhp, name, child[c], namewidth,
1897 + 2, B_FALSE);
1898 + else
1899 + print_import_config(name, child[c], namewidth, 2);
1900 + free(name);
1901 + }
1902 +}
1903 +
1904 +/*
1744 1905 * Display the status for the given pool.
1745 1906 */
1746 1907 static void
1747 1908 show_import(nvlist_t *config)
1748 1909 {
1749 1910 uint64_t pool_state;
1750 1911 vdev_stat_t *vs;
1751 1912 char *name;
1752 1913 uint64_t guid;
1753 1914 char *msgid;
1754 1915 nvlist_t *nvroot;
1755 1916 int reason;
1756 1917 const char *health;
1757 1918 uint_t vsc;
1758 1919 int namewidth;
1759 1920 char *comment;
1760 1921
1761 1922 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1762 1923 &name) == 0);
1763 1924 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
1764 1925 &guid) == 0);
1765 1926 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
1766 1927 &pool_state) == 0);
1767 1928 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
1768 1929 &nvroot) == 0);
1769 1930
1770 1931 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
1771 1932 (uint64_t **)&vs, &vsc) == 0);
1772 1933 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
1773 1934
1774 1935 reason = zpool_import_status(config, &msgid);
1775 1936
1776 1937 (void) printf(gettext(" pool: %s\n"), name);
1777 1938 (void) printf(gettext(" id: %llu\n"), (u_longlong_t)guid);
1778 1939 (void) printf(gettext(" state: %s"), health);
1779 1940 if (pool_state == POOL_STATE_DESTROYED)
1780 1941 (void) printf(gettext(" (DESTROYED)"));
1781 1942 (void) printf("\n");
1782 1943
1783 1944 switch (reason) {
1784 1945 case ZPOOL_STATUS_MISSING_DEV_R:
1785 1946 case ZPOOL_STATUS_MISSING_DEV_NR:
1786 1947 case ZPOOL_STATUS_BAD_GUID_SUM:
1787 1948 (void) printf(gettext(" status: One or more devices are "
1788 1949 "missing from the system.\n"));
1789 1950 break;
1790 1951
1791 1952 case ZPOOL_STATUS_CORRUPT_LABEL_R:
1792 1953 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
1793 1954 (void) printf(gettext(" status: One or more devices contains "
1794 1955 "corrupted data.\n"));
1795 1956 break;
1796 1957
1797 1958 case ZPOOL_STATUS_CORRUPT_DATA:
1798 1959 (void) printf(
1799 1960 gettext(" status: The pool data is corrupted.\n"));
1800 1961 break;
1801 1962
1802 1963 case ZPOOL_STATUS_OFFLINE_DEV:
1803 1964 (void) printf(gettext(" status: One or more devices "
1804 1965 "are offlined.\n"));
1805 1966 break;
1806 1967
1807 1968 case ZPOOL_STATUS_CORRUPT_POOL:
1808 1969 (void) printf(gettext(" status: The pool metadata is "
1809 1970 "corrupted.\n"));
1810 1971 break;
1811 1972
1812 1973 case ZPOOL_STATUS_VERSION_OLDER:
1813 1974 (void) printf(gettext(" status: The pool is formatted using a "
1814 1975 "legacy on-disk version.\n"));
1815 1976 break;
1816 1977
1817 1978 case ZPOOL_STATUS_VERSION_NEWER:
1818 1979 (void) printf(gettext(" status: The pool is formatted using an "
1819 1980 "incompatible version.\n"));
1820 1981 break;
1821 1982
1822 1983 case ZPOOL_STATUS_FEAT_DISABLED:
1823 1984 (void) printf(gettext(" status: Some supported features are "
1824 1985 "not enabled on the pool.\n"));
1825 1986 break;
1826 1987
1827 1988 case ZPOOL_STATUS_UNSUP_FEAT_READ:
1828 1989 (void) printf(gettext("status: The pool uses the following "
1829 1990 "feature(s) not supported on this sytem:\n"));
1830 1991 zpool_print_unsup_feat(config);
1831 1992 break;
1832 1993
1833 1994 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1834 1995 (void) printf(gettext("status: The pool can only be accessed "
1835 1996 "in read-only mode on this system. It\n\tcannot be "
1836 1997 "accessed in read-write mode because it uses the "
1837 1998 "following\n\tfeature(s) not supported on this system:\n"));
1838 1999 zpool_print_unsup_feat(config);
1839 2000 break;
1840 2001
1841 2002 case ZPOOL_STATUS_HOSTID_MISMATCH:
1842 2003 (void) printf(gettext(" status: The pool was last accessed by "
1843 2004 "another system.\n"));
1844 2005 break;
1845 2006
1846 2007 case ZPOOL_STATUS_FAULTED_DEV_R:
1847 2008 case ZPOOL_STATUS_FAULTED_DEV_NR:
1848 2009 (void) printf(gettext(" status: One or more devices are "
1849 2010 "faulted.\n"));
1850 2011 break;
1851 2012
1852 2013 case ZPOOL_STATUS_BAD_LOG:
1853 2014 (void) printf(gettext(" status: An intent log record cannot be "
1854 2015 "read.\n"));
1855 2016 break;
1856 2017
1857 2018 case ZPOOL_STATUS_RESILVERING:
1858 2019 (void) printf(gettext(" status: One or more devices were being "
1859 2020 "resilvered.\n"));
1860 2021 break;
1861 2022
1862 2023 default:
1863 2024 /*
1864 2025 * No other status can be seen when importing pools.
1865 2026 */
1866 2027 assert(reason == ZPOOL_STATUS_OK);
1867 2028 }
1868 2029
1869 2030 /*
1870 2031 * Print out an action according to the overall state of the pool.
1871 2032 */
1872 2033 if (vs->vs_state == VDEV_STATE_HEALTHY) {
1873 2034 if (reason == ZPOOL_STATUS_VERSION_OLDER ||
1874 2035 reason == ZPOOL_STATUS_FEAT_DISABLED) {
1875 2036 (void) printf(gettext(" action: The pool can be "
1876 2037 "imported using its name or numeric identifier, "
1877 2038 "though\n\tsome features will not be available "
1878 2039 "without an explicit 'zpool upgrade'.\n"));
1879 2040 } else if (reason == ZPOOL_STATUS_HOSTID_MISMATCH) {
1880 2041 (void) printf(gettext(" action: The pool can be "
1881 2042 "imported using its name or numeric "
1882 2043 "identifier and\n\tthe '-f' flag.\n"));
1883 2044 } else {
1884 2045 (void) printf(gettext(" action: The pool can be "
1885 2046 "imported using its name or numeric "
1886 2047 "identifier.\n"));
1887 2048 }
1888 2049 } else if (vs->vs_state == VDEV_STATE_DEGRADED) {
1889 2050 (void) printf(gettext(" action: The pool can be imported "
1890 2051 "despite missing or damaged devices. The\n\tfault "
1891 2052 "tolerance of the pool may be compromised if imported.\n"));
1892 2053 } else {
1893 2054 switch (reason) {
1894 2055 case ZPOOL_STATUS_VERSION_NEWER:
1895 2056 (void) printf(gettext(" action: The pool cannot be "
1896 2057 "imported. Access the pool on a system running "
1897 2058 "newer\n\tsoftware, or recreate the pool from "
1898 2059 "backup.\n"));
1899 2060 break;
1900 2061 case ZPOOL_STATUS_UNSUP_FEAT_READ:
1901 2062 (void) printf(gettext("action: The pool cannot be "
1902 2063 "imported. Access the pool on a system that "
1903 2064 "supports\n\tthe required feature(s), or recreate "
1904 2065 "the pool from backup.\n"));
1905 2066 break;
1906 2067 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
1907 2068 (void) printf(gettext("action: The pool cannot be "
1908 2069 "imported in read-write mode. Import the pool "
1909 2070 "with\n"
1910 2071 "\t\"-o readonly=on\", access the pool on a system "
1911 2072 "that supports the\n\trequired feature(s), or "
1912 2073 "recreate the pool from backup.\n"));
1913 2074 break;
1914 2075 case ZPOOL_STATUS_MISSING_DEV_R:
1915 2076 case ZPOOL_STATUS_MISSING_DEV_NR:
1916 2077 case ZPOOL_STATUS_BAD_GUID_SUM:
1917 2078 (void) printf(gettext(" action: The pool cannot be "
1918 2079 "imported. Attach the missing\n\tdevices and try "
1919 2080 "again.\n"));
1920 2081 break;
1921 2082 default:
1922 2083 (void) printf(gettext(" action: The pool cannot be "
1923 2084 "imported due to damaged devices or data.\n"));
1924 2085 }
1925 2086 }
1926 2087
1927 2088 /* Print the comment attached to the pool. */
1928 2089 if (nvlist_lookup_string(config, ZPOOL_CONFIG_COMMENT, &comment) == 0)
1929 2090 (void) printf(gettext("comment: %s\n"), comment);
1930 2091
1931 2092 /*
1932 2093 * If the state is "closed" or "can't open", and the aux state
1933 2094 * is "corrupt data":
1934 2095 */
1935 2096 if (((vs->vs_state == VDEV_STATE_CLOSED) ||
1936 2097 (vs->vs_state == VDEV_STATE_CANT_OPEN)) &&
1937 2098 (vs->vs_aux == VDEV_AUX_CORRUPT_DATA)) {
1938 2099 if (pool_state == POOL_STATE_DESTROYED)
1939 2100 (void) printf(gettext("\tThe pool was destroyed, "
1940 2101 "but can be imported using the '-Df' flags.\n"));
1941 2102 else if (pool_state != POOL_STATE_EXPORTED)
1942 2103 (void) printf(gettext("\tThe pool may be active on "
1943 2104 "another system, but can be imported using\n\t"
1944 2105 "the '-f' flag.\n"));
1945 2106 }
1946 2107
1947 2108 if (msgid != NULL)
|
↓ open down ↓ |
194 lines elided |
↑ open up ↑ |
1948 2109 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
1949 2110 msgid);
1950 2111
1951 2112 (void) printf(gettext(" config:\n\n"));
1952 2113
1953 2114 namewidth = max_width(NULL, nvroot, 0, 0);
1954 2115 if (namewidth < 10)
1955 2116 namewidth = 10;
1956 2117
1957 2118 print_import_config(name, nvroot, namewidth, 0);
2119 + if (num_special(nvroot) > 0)
2120 + print_special(NULL, nvroot, namewidth, B_FALSE);
2121 +
1958 2122 if (num_logs(nvroot) > 0)
1959 2123 print_logs(NULL, nvroot, namewidth, B_FALSE);
1960 2124
1961 2125 if (reason == ZPOOL_STATUS_BAD_GUID_SUM) {
1962 2126 (void) printf(gettext("\n\tAdditional devices are known to "
1963 2127 "be part of this pool, though their\n\texact "
1964 2128 "configuration cannot be determined.\n"));
1965 2129 }
1966 2130 }
1967 2131
1968 2132 /*
1969 2133 * Perform the import for the given configuration. This passes the heavy
1970 2134 * lifting off to zpool_import_props(), and then mounts the datasets contained
1971 2135 * within the pool.
1972 2136 */
1973 2137 static int
1974 2138 do_import(nvlist_t *config, const char *newname, const char *mntopts,
1975 - nvlist_t *props, int flags)
2139 + nvlist_t *props, int flags, int n_threads)
1976 2140 {
1977 2141 zpool_handle_t *zhp;
1978 2142 char *name;
1979 2143 uint64_t state;
1980 2144 uint64_t version;
1981 2145
1982 2146 verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
1983 2147 &name) == 0);
1984 2148
1985 2149 verify(nvlist_lookup_uint64(config,
1986 2150 ZPOOL_CONFIG_POOL_STATE, &state) == 0);
1987 2151 verify(nvlist_lookup_uint64(config,
1988 2152 ZPOOL_CONFIG_VERSION, &version) == 0);
1989 2153 if (!SPA_VERSION_IS_SUPPORTED(version)) {
1990 2154 (void) fprintf(stderr, gettext("cannot import '%s': pool "
1991 2155 "is formatted using an unsupported ZFS version\n"), name);
1992 2156 return (1);
1993 2157 } else if (state != POOL_STATE_EXPORTED &&
1994 2158 !(flags & ZFS_IMPORT_ANY_HOST)) {
1995 2159 uint64_t hostid;
1996 2160
1997 2161 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID,
1998 2162 &hostid) == 0) {
1999 2163 if ((unsigned long)hostid != gethostid()) {
2000 2164 char *hostname;
2001 2165 uint64_t timestamp;
2002 2166 time_t t;
2003 2167
2004 2168 verify(nvlist_lookup_string(config,
2005 2169 ZPOOL_CONFIG_HOSTNAME, &hostname) == 0);
2006 2170 verify(nvlist_lookup_uint64(config,
2007 2171 ZPOOL_CONFIG_TIMESTAMP, ×tamp) == 0);
2008 2172 t = timestamp;
2009 2173 (void) fprintf(stderr, gettext("cannot import "
2010 2174 "'%s': pool may be in use from other "
2011 2175 "system, it was last accessed by %s "
2012 2176 "(hostid: 0x%lx) on %s"), name, hostname,
2013 2177 (unsigned long)hostid,
2014 2178 asctime(localtime(&t)));
2015 2179 (void) fprintf(stderr, gettext("use '-f' to "
2016 2180 "import anyway\n"));
2017 2181 return (1);
2018 2182 }
2019 2183 } else {
2020 2184 (void) fprintf(stderr, gettext("cannot import '%s': "
2021 2185 "pool may be in use from other system\n"), name);
2022 2186 (void) fprintf(stderr, gettext("use '-f' to import "
2023 2187 "anyway\n"));
2024 2188 return (1);
2025 2189 }
2026 2190 }
2027 2191
2028 2192 if (zpool_import_props(g_zfs, config, newname, props, flags) != 0)
|
↓ open down ↓ |
43 lines elided |
↑ open up ↑ |
2029 2193 return (1);
2030 2194
2031 2195 if (newname != NULL)
2032 2196 name = (char *)newname;
2033 2197
2034 2198 if ((zhp = zpool_open_canfail(g_zfs, name)) == NULL)
2035 2199 return (1);
2036 2200
2037 2201 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
2038 2202 !(flags & ZFS_IMPORT_ONLY) &&
2039 - zpool_enable_datasets(zhp, mntopts, 0) != 0) {
2203 + zpool_enable_datasets_ex(zhp, mntopts, 0, n_threads) != 0) {
2040 2204 zpool_close(zhp);
2041 2205 return (1);
2042 2206 }
2043 2207
2044 2208 zpool_close(zhp);
2045 2209 return (0);
2046 2210 }
2047 2211
2048 2212 /*
2049 2213 * zpool import [-d dir] [-D]
2050 - * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2214 + * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-t num]
2051 2215 * [-d dir | -c cachefile] [-f] -a
2052 - * import [-o mntopts] [-o prop=value] ... [-R root] [-D]
2216 + * import [-o mntopts] [-o prop=value] ... [-R root] [-D] [-t num]
2053 2217 * [-d dir | -c cachefile] [-f] [-n] [-F] <pool | id> [newpool]
2054 2218 *
2055 2219 * -c Read pool information from a cachefile instead of searching
2056 2220 * devices.
2057 2221 *
2058 2222 * -d Scan in a specific directory, other than /dev/dsk. More than
2059 2223 * one directory can be specified using multiple '-d' options.
2060 2224 *
2061 2225 * -D Scan for previously destroyed pools or import all or only
2062 2226 * specified destroyed pools.
2063 2227 *
2064 2228 * -R Temporarily import the pool, with all mountpoints relative to
2065 2229 * the given root. The pool will remain exported when the machine
2066 2230 * is rebooted.
2067 2231 *
2068 2232 * -V Import even in the presence of faulted vdevs. This is an
2069 - * intentionally undocumented option for testing purposes, and
2070 - * treats the pool configuration as complete, leaving any bad
2233 + * intentionally undocumented option for testing purposes, and
2234 + * treats the pool configuration as complete, leaving any bad
2071 2235 * vdevs in the FAULTED state. In other words, it does verbatim
2072 2236 * import.
2073 2237 *
2074 2238 * -f Force import, even if it appears that the pool is active.
2075 2239 *
2076 2240 * -F Attempt rewind if necessary.
2077 2241 *
2078 2242 * -n See if rewind would work, but don't actually rewind.
2079 2243 *
2080 2244 * -N Import the pool but don't mount datasets.
2081 2245 *
2246 + * -t Use up to num threads to mount datasets in parallel.
2247 + *
2082 2248 * -T Specify a starting txg to use for import. This option is
2083 - * intentionally undocumented option for testing purposes.
2249 + * intentionally undocumented option for testing purposes.
2084 2250 *
2085 2251 * -a Import all pools found.
2086 2252 *
2087 2253 * -o Set property=value and/or temporary mount options (without '=').
2088 2254 *
2089 2255 * The import command scans for pools to import, and import pools based on pool
2090 2256 * name and GUID. The pool can also be renamed as part of the import process.
2091 2257 */
2092 2258 int
2093 2259 zpool_do_import(int argc, char **argv)
2094 2260 {
2095 2261 char **searchdirs = NULL;
2096 2262 int nsearch = 0;
2097 2263 int c;
2098 2264 int err = 0;
2099 2265 nvlist_t *pools = NULL;
2100 2266 boolean_t do_all = B_FALSE;
2101 2267 boolean_t do_destroyed = B_FALSE;
2102 2268 char *mntopts = NULL;
2103 2269 nvpair_t *elem;
2104 2270 nvlist_t *config;
2105 2271 uint64_t searchguid = 0;
2106 2272 char *searchname = NULL;
2107 2273 char *propval;
2108 2274 nvlist_t *found_config;
2109 2275 nvlist_t *policy = NULL;
|
↓ open down ↓ |
16 lines elided |
↑ open up ↑ |
2110 2276 nvlist_t *props = NULL;
2111 2277 boolean_t first;
2112 2278 int flags = ZFS_IMPORT_NORMAL;
2113 2279 uint32_t rewind_policy = ZPOOL_NO_REWIND;
2114 2280 boolean_t dryrun = B_FALSE;
2115 2281 boolean_t do_rewind = B_FALSE;
2116 2282 boolean_t xtreme_rewind = B_FALSE;
2117 2283 uint64_t pool_state, txg = -1ULL;
2118 2284 char *cachefile = NULL;
2119 2285 importargs_t idata = { 0 };
2286 + unsigned long n_threads = sysconf(_SC_NPROCESSORS_ONLN) * 2;
2120 2287 char *endptr;
2121 2288
2122 2289 /* check options */
2123 - while ((c = getopt(argc, argv, ":aCc:d:DEfFmnNo:rR:T:VX")) != -1) {
2290 + while ((c = getopt(argc, argv, ":aCc:d:DEfFmnNo:rR:t:T:VX")) != -1) {
2124 2291 switch (c) {
2125 2292 case 'a':
2126 2293 do_all = B_TRUE;
2127 2294 break;
2128 2295 case 'c':
2129 2296 cachefile = optarg;
2130 2297 break;
2131 2298 case 'd':
2132 2299 if (searchdirs == NULL) {
2133 2300 searchdirs = safe_malloc(sizeof (char *));
2134 2301 } else {
2135 2302 char **tmp = safe_malloc((nsearch + 1) *
2136 2303 sizeof (char *));
2137 2304 bcopy(searchdirs, tmp, nsearch *
2138 2305 sizeof (char *));
2139 2306 free(searchdirs);
2140 2307 searchdirs = tmp;
2141 2308 }
2142 2309 searchdirs[nsearch++] = optarg;
2143 2310 break;
2144 2311 case 'D':
2145 2312 do_destroyed = B_TRUE;
2146 2313 break;
2147 2314 case 'f':
2148 2315 flags |= ZFS_IMPORT_ANY_HOST;
2149 2316 break;
2150 2317 case 'F':
2151 2318 do_rewind = B_TRUE;
2152 2319 break;
2153 2320 case 'm':
2154 2321 flags |= ZFS_IMPORT_MISSING_LOG;
2155 2322 break;
2156 2323 case 'n':
2157 2324 dryrun = B_TRUE;
2158 2325 break;
2159 2326 case 'N':
2160 2327 flags |= ZFS_IMPORT_ONLY;
2161 2328 break;
2162 2329 case 'o':
2163 2330 if ((propval = strchr(optarg, '=')) != NULL) {
2164 2331 *propval = '\0';
2165 2332 propval++;
2166 2333 if (add_prop_list(optarg, propval,
2167 2334 &props, B_TRUE))
2168 2335 goto error;
2169 2336 } else {
2170 2337 mntopts = optarg;
2171 2338 }
2172 2339 break;
2173 2340 case 'R':
2174 2341 if (add_prop_list(zpool_prop_to_name(
|
↓ open down ↓ |
41 lines elided |
↑ open up ↑ |
2175 2342 ZPOOL_PROP_ALTROOT), optarg, &props, B_TRUE))
2176 2343 goto error;
2177 2344 if (nvlist_lookup_string(props,
2178 2345 zpool_prop_to_name(ZPOOL_PROP_CACHEFILE),
2179 2346 &propval) == 0)
2180 2347 break;
2181 2348 if (add_prop_list(zpool_prop_to_name(
2182 2349 ZPOOL_PROP_CACHEFILE), "none", &props, B_TRUE))
2183 2350 goto error;
2184 2351 break;
2352 + case 't':
2353 + errno = 0;
2354 + n_threads = strtol(optarg, &endptr, 10);
2355 + if (errno != 0 || *endptr != '\0') {
2356 + (void) fprintf(stderr,
2357 + gettext("invalid num value\n"));
2358 + usage(B_FALSE);
2359 + }
2360 + break;
2185 2361 case 'T':
2186 2362 errno = 0;
2187 2363 txg = strtoull(optarg, &endptr, 0);
2188 2364 if (errno != 0 || *endptr != '\0') {
2189 2365 (void) fprintf(stderr,
2190 2366 gettext("invalid txg value\n"));
2191 2367 usage(B_FALSE);
2192 2368 }
2193 2369 rewind_policy = ZPOOL_DO_REWIND | ZPOOL_EXTREME_REWIND;
2194 2370 break;
2195 2371 case 'V':
2196 2372 flags |= ZFS_IMPORT_VERBATIM;
2197 2373 break;
2198 2374 case 'X':
2199 2375 xtreme_rewind = B_TRUE;
2200 2376 break;
2201 2377 case ':':
2202 2378 (void) fprintf(stderr, gettext("missing argument for "
2203 2379 "'%c' option\n"), optopt);
2204 2380 usage(B_FALSE);
2205 2381 break;
2206 2382 case '?':
2207 2383 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2208 2384 optopt);
2209 2385 usage(B_FALSE);
2210 2386 }
2211 2387 }
2212 2388
2213 2389 argc -= optind;
2214 2390 argv += optind;
2215 2391
2216 2392 if (cachefile && nsearch != 0) {
2217 2393 (void) fprintf(stderr, gettext("-c is incompatible with -d\n"));
2218 2394 usage(B_FALSE);
2219 2395 }
2220 2396
2221 2397 if ((dryrun || xtreme_rewind) && !do_rewind) {
2222 2398 (void) fprintf(stderr,
2223 2399 gettext("-n or -X only meaningful with -F\n"));
2224 2400 usage(B_FALSE);
2225 2401 }
2226 2402 if (dryrun)
2227 2403 rewind_policy = ZPOOL_TRY_REWIND;
2228 2404 else if (do_rewind)
2229 2405 rewind_policy = ZPOOL_DO_REWIND;
2230 2406 if (xtreme_rewind)
2231 2407 rewind_policy |= ZPOOL_EXTREME_REWIND;
2232 2408
2233 2409 /* In the future, we can capture further policy and include it here */
2234 2410 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
2235 2411 nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, txg) != 0 ||
2236 2412 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
2237 2413 goto error;
2238 2414
2239 2415 if (searchdirs == NULL) {
2240 2416 searchdirs = safe_malloc(sizeof (char *));
2241 2417 searchdirs[0] = ZFS_DISK_ROOT;
2242 2418 nsearch = 1;
2243 2419 }
2244 2420
2245 2421 /* check argument count */
2246 2422 if (do_all) {
2247 2423 if (argc != 0) {
2248 2424 (void) fprintf(stderr, gettext("too many arguments\n"));
2249 2425 usage(B_FALSE);
2250 2426 }
2251 2427 } else {
2252 2428 if (argc > 2) {
2253 2429 (void) fprintf(stderr, gettext("too many arguments\n"));
2254 2430 usage(B_FALSE);
2255 2431 }
2256 2432
2257 2433 /*
2258 2434 * Check for the SYS_CONFIG privilege. We do this explicitly
2259 2435 * here because otherwise any attempt to discover pools will
2260 2436 * silently fail.
2261 2437 */
2262 2438 if (argc == 0 && !priv_ineffect(PRIV_SYS_CONFIG)) {
2263 2439 (void) fprintf(stderr, gettext("cannot "
2264 2440 "discover pools: permission denied\n"));
2265 2441 free(searchdirs);
2266 2442 nvlist_free(policy);
2267 2443 return (1);
2268 2444 }
2269 2445 }
2270 2446
2271 2447 /*
2272 2448 * Depending on the arguments given, we do one of the following:
2273 2449 *
2274 2450 * <none> Iterate through all pools and display information about
2275 2451 * each one.
2276 2452 *
2277 2453 * -a Iterate through all pools and try to import each one.
2278 2454 *
2279 2455 * <id> Find the pool that corresponds to the given GUID/pool
2280 2456 * name and import that one.
2281 2457 *
2282 2458 * -D Above options applies only to destroyed pools.
2283 2459 */
2284 2460 if (argc != 0) {
2285 2461 char *endptr;
2286 2462
2287 2463 errno = 0;
2288 2464 searchguid = strtoull(argv[0], &endptr, 10);
2289 2465 if (errno != 0 || *endptr != '\0') {
2290 2466 searchname = argv[0];
2291 2467 searchguid = 0;
2292 2468 }
2293 2469 found_config = NULL;
2294 2470
2295 2471 /*
2296 2472 * User specified a name or guid. Ensure it's unique.
|
↓ open down ↓ |
102 lines elided |
↑ open up ↑ |
2297 2473 */
2298 2474 idata.unique = B_TRUE;
2299 2475 }
2300 2476
2301 2477
2302 2478 idata.path = searchdirs;
2303 2479 idata.paths = nsearch;
2304 2480 idata.poolname = searchname;
2305 2481 idata.guid = searchguid;
2306 2482 idata.cachefile = cachefile;
2307 - idata.policy = policy;
2308 2483
2309 2484 pools = zpool_search_import(g_zfs, &idata);
2310 2485
2311 2486 if (pools != NULL && idata.exists &&
2312 2487 (argc == 1 || strcmp(argv[0], argv[1]) == 0)) {
2313 2488 (void) fprintf(stderr, gettext("cannot import '%s': "
2314 2489 "a pool with that name already exists\n"),
2315 2490 argv[0]);
2316 2491 (void) fprintf(stderr, gettext("use the form '%s "
2317 2492 "<pool | id> <newpool>' to give it a new name\n"),
2318 2493 "zpool import");
2319 2494 err = 1;
2320 2495 } else if (pools == NULL && idata.exists) {
2321 2496 (void) fprintf(stderr, gettext("cannot import '%s': "
2322 2497 "a pool with that name is already created/imported,\n"),
2323 2498 argv[0]);
2324 2499 (void) fprintf(stderr, gettext("and no additional pools "
2325 2500 "with that name were found\n"));
2326 2501 err = 1;
2327 2502 } else if (pools == NULL) {
2328 2503 if (argc != 0) {
2329 2504 (void) fprintf(stderr, gettext("cannot import '%s': "
2330 2505 "no such pool available\n"), argv[0]);
2331 2506 }
2332 2507 err = 1;
2333 2508 }
2334 2509
2335 2510 if (err == 1) {
2336 2511 free(searchdirs);
2337 2512 nvlist_free(policy);
2338 2513 return (1);
2339 2514 }
2340 2515
2341 2516 /*
2342 2517 * At this point we have a list of import candidate configs. Even if
2343 2518 * we were searching by pool name or guid, we still need to
2344 2519 * post-process the list to deal with pool state and possible
2345 2520 * duplicate names.
2346 2521 */
2347 2522 err = 0;
2348 2523 elem = NULL;
2349 2524 first = B_TRUE;
2350 2525 while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) {
2351 2526
2352 2527 verify(nvpair_value_nvlist(elem, &config) == 0);
2353 2528
2354 2529 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
2355 2530 &pool_state) == 0);
2356 2531 if (!do_destroyed && pool_state == POOL_STATE_DESTROYED)
2357 2532 continue;
2358 2533 if (do_destroyed && pool_state != POOL_STATE_DESTROYED)
2359 2534 continue;
2360 2535
2361 2536 verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY,
|
↓ open down ↓ |
44 lines elided |
↑ open up ↑ |
2362 2537 policy) == 0);
2363 2538
2364 2539 if (argc == 0) {
2365 2540 if (first)
2366 2541 first = B_FALSE;
2367 2542 else if (!do_all)
2368 2543 (void) printf("\n");
2369 2544
2370 2545 if (do_all) {
2371 2546 err |= do_import(config, NULL, mntopts,
2372 - props, flags);
2547 + props, flags, n_threads);
2373 2548 } else {
2374 2549 show_import(config);
2375 2550 }
2376 2551 } else if (searchname != NULL) {
2377 2552 char *name;
2378 2553
2379 2554 /*
2380 2555 * We are searching for a pool based on name.
2381 2556 */
2382 2557 verify(nvlist_lookup_string(config,
2383 2558 ZPOOL_CONFIG_POOL_NAME, &name) == 0);
2384 2559
2385 2560 if (strcmp(name, searchname) == 0) {
2386 2561 if (found_config != NULL) {
2387 2562 (void) fprintf(stderr, gettext(
2388 2563 "cannot import '%s': more than "
2389 2564 "one matching pool\n"), searchname);
2390 2565 (void) fprintf(stderr, gettext(
2391 2566 "import by numeric ID instead\n"));
2392 2567 err = B_TRUE;
2393 2568 }
2394 2569 found_config = config;
2395 2570 }
2396 2571 } else {
2397 2572 uint64_t guid;
2398 2573
2399 2574 /*
2400 2575 * Search for a pool by guid.
2401 2576 */
2402 2577 verify(nvlist_lookup_uint64(config,
2403 2578 ZPOOL_CONFIG_POOL_GUID, &guid) == 0);
2404 2579
2405 2580 if (guid == searchguid)
2406 2581 found_config = config;
2407 2582 }
2408 2583 }
2409 2584
2410 2585 /*
|
↓ open down ↓ |
28 lines elided |
↑ open up ↑ |
2411 2586 * If we were searching for a specific pool, verify that we found a
2412 2587 * pool, and then do the import.
2413 2588 */
2414 2589 if (argc != 0 && err == 0) {
2415 2590 if (found_config == NULL) {
2416 2591 (void) fprintf(stderr, gettext("cannot import '%s': "
2417 2592 "no such pool available\n"), argv[0]);
2418 2593 err = B_TRUE;
2419 2594 } else {
2420 2595 err |= do_import(found_config, argc == 1 ? NULL :
2421 - argv[1], mntopts, props, flags);
2596 + argv[1], mntopts, props, flags, n_threads);
2422 2597 }
2423 2598 }
2424 2599
2425 2600 /*
2426 2601 * If we were just looking for pools, report an error if none were
2427 2602 * found.
2428 2603 */
2429 2604 if (argc == 0 && first)
2430 2605 (void) fprintf(stderr,
2431 2606 gettext("no pools available to import\n"));
2432 2607
2433 2608 error:
2434 2609 nvlist_free(props);
2435 2610 nvlist_free(pools);
2436 2611 nvlist_free(policy);
2437 2612 free(searchdirs);
2438 2613
2439 2614 return (err ? 1 : 0);
2440 2615 }
2441 2616
2442 2617 typedef struct iostat_cbdata {
2443 2618 boolean_t cb_verbose;
2444 2619 int cb_namewidth;
2445 2620 int cb_iteration;
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
2446 2621 zpool_list_t *cb_list;
2447 2622 } iostat_cbdata_t;
2448 2623
2449 2624 static void
2450 2625 print_iostat_separator(iostat_cbdata_t *cb)
2451 2626 {
2452 2627 int i = 0;
2453 2628
2454 2629 for (i = 0; i < cb->cb_namewidth; i++)
2455 2630 (void) printf("-");
2456 - (void) printf(" ----- ----- ----- ----- ----- -----\n");
2631 + (void) printf(" ----- ----- ----- ----- ----- ----- ----- "
2632 + "-----\n");
2457 2633 }
2458 2634
2459 2635 static void
2460 2636 print_iostat_header(iostat_cbdata_t *cb)
2461 2637 {
2462 - (void) printf("%*s capacity operations bandwidth\n",
2463 - cb->cb_namewidth, "");
2464 - (void) printf("%-*s alloc free read write read write\n",
2465 - cb->cb_namewidth, "pool");
2638 + (void) printf("%*s capacity operations bandwidth "
2639 + "latency\n", cb->cb_namewidth, "");
2640 + (void) printf("%-*s alloc free read write read write read "
2641 + "write\n", cb->cb_namewidth, "pool");
2466 2642 print_iostat_separator(cb);
2467 2643 }
2468 2644
2469 2645 /*
2470 2646 * Display a single statistic.
2471 2647 */
2472 2648 static void
2473 2649 print_one_stat(uint64_t value)
2474 2650 {
2475 2651 char buf[64];
2476 2652
2477 2653 zfs_nicenum(value, buf, sizeof (buf));
2478 2654 (void) printf(" %5s", buf);
2479 2655 }
2480 2656
2481 2657 /*
2658 + * Display latency statistic (extra care needed)
2659 + */
2660 +static void
2661 +print_one_latency_stat(uint64_t iotime, uint64_t ops)
2662 +{
2663 + char buf[64];
2664 + double value = 0.0; /* latency in milliseconds */
2665 +
2666 + if (ops != 0) {
2667 + value = (double)iotime;
2668 + value /= (double)ops;
2669 + value /= (double)(MICROSEC / MILLISEC);
2670 + }
2671 +
2672 + (void) sprintf(buf, "%.2f", value);
2673 + (void) printf(" %5s", buf);
2674 +}
2675 +
2676 +/*
2482 2677 * Print out all the statistics for the given vdev. This can either be the
2483 2678 * toplevel configuration, or called recursively. If 'name' is NULL, then this
2484 2679 * is a verbose output, and we don't want to display the toplevel pool stats.
2485 2680 */
2486 2681 void
2487 2682 print_vdev_stats(zpool_handle_t *zhp, const char *name, nvlist_t *oldnv,
2488 2683 nvlist_t *newnv, iostat_cbdata_t *cb, int depth)
2489 2684 {
2490 2685 nvlist_t **oldchild, **newchild;
2491 2686 uint_t c, children;
2492 2687 vdev_stat_t *oldvs, *newvs;
2493 2688 vdev_stat_t zerovs = { 0 };
2494 2689 uint64_t tdelta;
2495 2690 double scale;
2496 2691 char *vname;
2497 2692
2498 - if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
2499 - return;
2500 -
2501 2693 if (oldnv != NULL) {
2502 2694 verify(nvlist_lookup_uint64_array(oldnv,
2503 2695 ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&oldvs, &c) == 0);
2504 2696 } else {
2505 2697 oldvs = &zerovs;
2506 2698 }
2507 2699
2508 2700 verify(nvlist_lookup_uint64_array(newnv, ZPOOL_CONFIG_VDEV_STATS,
2509 2701 (uint64_t **)&newvs, &c) == 0);
2510 2702
2511 2703 if (strlen(name) + depth > cb->cb_namewidth)
2512 2704 (void) printf("%*s%s", depth, "", name);
2513 2705 else
2514 2706 (void) printf("%*s%s%*s", depth, "", name,
2515 2707 (int)(cb->cb_namewidth - strlen(name) - depth), "");
2516 2708
2517 2709 tdelta = newvs->vs_timestamp - oldvs->vs_timestamp;
2518 2710
2519 2711 if (tdelta == 0)
2520 2712 scale = 1.0;
2521 2713 else
2522 2714 scale = (double)NANOSEC / tdelta;
2523 2715
2524 2716 /* only toplevel vdevs have capacity stats */
2525 2717 if (newvs->vs_space == 0) {
2526 2718 (void) printf(" - -");
2527 2719 } else {
2528 2720 print_one_stat(newvs->vs_alloc);
2529 2721 print_one_stat(newvs->vs_space - newvs->vs_alloc);
2530 2722 }
2531 2723
2532 2724 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_READ] -
2533 2725 oldvs->vs_ops[ZIO_TYPE_READ])));
|
↓ open down ↓ |
23 lines elided |
↑ open up ↑ |
2534 2726
2535 2727 print_one_stat((uint64_t)(scale * (newvs->vs_ops[ZIO_TYPE_WRITE] -
2536 2728 oldvs->vs_ops[ZIO_TYPE_WRITE])));
2537 2729
2538 2730 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_READ] -
2539 2731 oldvs->vs_bytes[ZIO_TYPE_READ])));
2540 2732
2541 2733 print_one_stat((uint64_t)(scale * (newvs->vs_bytes[ZIO_TYPE_WRITE] -
2542 2734 oldvs->vs_bytes[ZIO_TYPE_WRITE])));
2543 2735
2736 + /*
2737 + * No scale needed here since we are dividing in
2738 + * print_one_latency_stat()
2739 + */
2740 +
2741 + print_one_latency_stat(
2742 + newvs->vs_iotime[ZIO_TYPE_READ] - oldvs->vs_iotime[ZIO_TYPE_READ],
2743 + newvs->vs_ops[ZIO_TYPE_READ] - oldvs->vs_ops[ZIO_TYPE_READ]);
2744 +
2745 + print_one_latency_stat(
2746 + newvs->vs_iotime[ZIO_TYPE_WRITE] - oldvs->vs_iotime[ZIO_TYPE_WRITE],
2747 + newvs->vs_ops[ZIO_TYPE_WRITE] - oldvs->vs_ops[ZIO_TYPE_WRITE]);
2748 +
2544 2749 (void) printf("\n");
2545 2750
2546 2751 if (!cb->cb_verbose)
2547 2752 return;
2548 2753
2549 2754 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_CHILDREN,
2550 2755 &newchild, &children) != 0)
2551 2756 return;
2552 2757
2553 2758 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_CHILDREN,
2554 2759 &oldchild, &c) != 0)
2555 2760 return;
2556 2761
2557 2762 for (c = 0; c < children; c++) {
2558 - uint64_t ishole = B_FALSE, islog = B_FALSE;
2763 + uint64_t ishole = B_FALSE, islog = B_FALSE, isspec = B_FALSE;
2559 2764
2560 2765 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_HOLE,
2561 2766 &ishole);
2562 2767
2563 2768 (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
2564 2769 &islog);
2565 2770
2566 - if (ishole || islog)
2771 + (void) nvlist_lookup_uint64(newchild[c],
2772 + ZPOOL_CONFIG_IS_SPECIAL, &isspec);
2773 +
2774 + if (ishole || islog || isspec)
2567 2775 continue;
2568 2776
2569 2777 vname = zpool_vdev_name(g_zfs, zhp, newchild[c], B_FALSE);
2570 2778 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2571 2779 newchild[c], cb, depth + 2);
2572 2780 free(vname);
2573 2781 }
2574 2782
2575 2783 /*
2576 2784 * Log device section
2577 2785 */
2578 2786
2579 2787 if (num_logs(newnv) > 0) {
2580 2788 (void) printf("%-*s - - - - - "
2581 2789 "-\n", cb->cb_namewidth, "logs");
2582 2790
2583 2791 for (c = 0; c < children; c++) {
2584 2792 uint64_t islog = B_FALSE;
2585 2793 (void) nvlist_lookup_uint64(newchild[c],
2586 2794 ZPOOL_CONFIG_IS_LOG, &islog);
|
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
2587 2795
2588 2796 if (islog) {
2589 2797 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2590 2798 B_FALSE);
2591 2799 print_vdev_stats(zhp, vname, oldnv ?
2592 2800 oldchild[c] : NULL, newchild[c],
2593 2801 cb, depth + 2);
2594 2802 free(vname);
2595 2803 }
2596 2804 }
2805 + }
2597 2806
2807 + /*
2808 + * Special device section
2809 + */
2810 +
2811 + if (num_special(newnv) > 0) {
2812 + (void) printf("%-*s - - - - - "
2813 + "-\n", cb->cb_namewidth, "special");
2814 +
2815 + for (c = 0; c < children; c++) {
2816 + uint64_t isspec = B_FALSE;
2817 + (void) nvlist_lookup_uint64(newchild[c],
2818 + ZPOOL_CONFIG_IS_SPECIAL, &isspec);
2819 +
2820 + if (isspec) {
2821 + vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2822 + B_FALSE);
2823 + print_vdev_stats(zhp, vname, oldnv ?
2824 + oldchild[c] : NULL, newchild[c],
2825 + cb, depth + 2);
2826 + free(vname);
2827 + }
2828 + }
2598 2829 }
2599 2830
2600 2831 /*
2601 2832 * Include level 2 ARC devices in iostat output
2602 2833 */
2603 2834 if (nvlist_lookup_nvlist_array(newnv, ZPOOL_CONFIG_L2CACHE,
2604 2835 &newchild, &children) != 0)
2605 2836 return;
2606 2837
2607 2838 if (oldnv && nvlist_lookup_nvlist_array(oldnv, ZPOOL_CONFIG_L2CACHE,
2608 2839 &oldchild, &c) != 0)
2609 2840 return;
2610 2841
2611 2842 if (children > 0) {
2612 2843 (void) printf("%-*s - - - - - "
2613 2844 "-\n", cb->cb_namewidth, "cache");
2614 2845 for (c = 0; c < children; c++) {
2615 2846 vname = zpool_vdev_name(g_zfs, zhp, newchild[c],
2616 2847 B_FALSE);
2617 2848 print_vdev_stats(zhp, vname, oldnv ? oldchild[c] : NULL,
2618 2849 newchild[c], cb, depth + 2);
2619 2850 free(vname);
2620 2851 }
2621 2852 }
2622 2853 }
2623 2854
2624 2855 static int
2625 2856 refresh_iostat(zpool_handle_t *zhp, void *data)
2626 2857 {
2627 2858 iostat_cbdata_t *cb = data;
2628 2859 boolean_t missing;
2629 2860
2630 2861 /*
2631 2862 * If the pool has disappeared, remove it from the list and continue.
2632 2863 */
2633 2864 if (zpool_refresh_stats(zhp, &missing) != 0)
2634 2865 return (-1);
2635 2866
2636 2867 if (missing)
2637 2868 pool_list_remove(cb->cb_list, zhp);
2638 2869
2639 2870 return (0);
2640 2871 }
2641 2872
2642 2873 /*
2643 2874 * Callback to print out the iostats for the given pool.
2644 2875 */
2645 2876 int
2646 2877 print_iostat(zpool_handle_t *zhp, void *data)
2647 2878 {
2648 2879 iostat_cbdata_t *cb = data;
2649 2880 nvlist_t *oldconfig, *newconfig;
2650 2881 nvlist_t *oldnvroot, *newnvroot;
2651 2882
2652 2883 newconfig = zpool_get_config(zhp, &oldconfig);
2653 2884
2654 2885 if (cb->cb_iteration == 1)
2655 2886 oldconfig = NULL;
2656 2887
2657 2888 verify(nvlist_lookup_nvlist(newconfig, ZPOOL_CONFIG_VDEV_TREE,
2658 2889 &newnvroot) == 0);
2659 2890
2660 2891 if (oldconfig == NULL)
2661 2892 oldnvroot = NULL;
2662 2893 else
2663 2894 verify(nvlist_lookup_nvlist(oldconfig, ZPOOL_CONFIG_VDEV_TREE,
2664 2895 &oldnvroot) == 0);
2665 2896
2666 2897 /*
2667 2898 * Print out the statistics for the pool.
2668 2899 */
2669 2900 print_vdev_stats(zhp, zpool_get_name(zhp), oldnvroot, newnvroot, cb, 0);
2670 2901
2671 2902 if (cb->cb_verbose)
2672 2903 print_iostat_separator(cb);
2673 2904
2674 2905 return (0);
2675 2906 }
2676 2907
2677 2908 int
2678 2909 get_namewidth(zpool_handle_t *zhp, void *data)
2679 2910 {
2680 2911 iostat_cbdata_t *cb = data;
2681 2912 nvlist_t *config, *nvroot;
2682 2913
2683 2914 if ((config = zpool_get_config(zhp, NULL)) != NULL) {
2684 2915 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
2685 2916 &nvroot) == 0);
2686 2917 if (!cb->cb_verbose)
2687 2918 cb->cb_namewidth = strlen(zpool_get_name(zhp));
2688 2919 else
2689 2920 cb->cb_namewidth = max_width(zhp, nvroot, 0,
2690 2921 cb->cb_namewidth);
2691 2922 }
2692 2923
2693 2924 /*
2694 2925 * The width must fall into the range [10,38]. The upper limit is the
2695 2926 * maximum we can have and still fit in 80 columns.
2696 2927 */
2697 2928 if (cb->cb_namewidth < 10)
2698 2929 cb->cb_namewidth = 10;
2699 2930 if (cb->cb_namewidth > 38)
2700 2931 cb->cb_namewidth = 38;
2701 2932
2702 2933 return (0);
2703 2934 }
2704 2935
2705 2936 /*
2706 2937 * Parse the input string, get the 'interval' and 'count' value if there is one.
2707 2938 */
2708 2939 static void
2709 2940 get_interval_count(int *argcp, char **argv, unsigned long *iv,
2710 2941 unsigned long *cnt)
2711 2942 {
2712 2943 unsigned long interval = 0, count = 0;
2713 2944 int argc = *argcp, errno;
2714 2945
2715 2946 /*
2716 2947 * Determine if the last argument is an integer or a pool name
2717 2948 */
2718 2949 if (argc > 0 && isdigit(argv[argc - 1][0])) {
2719 2950 char *end;
2720 2951
2721 2952 errno = 0;
2722 2953 interval = strtoul(argv[argc - 1], &end, 10);
2723 2954
2724 2955 if (*end == '\0' && errno == 0) {
2725 2956 if (interval == 0) {
2726 2957 (void) fprintf(stderr, gettext("interval "
2727 2958 "cannot be zero\n"));
2728 2959 usage(B_FALSE);
2729 2960 }
2730 2961 /*
2731 2962 * Ignore the last parameter
2732 2963 */
2733 2964 argc--;
2734 2965 } else {
2735 2966 /*
2736 2967 * If this is not a valid number, just plow on. The
2737 2968 * user will get a more informative error message later
2738 2969 * on.
2739 2970 */
2740 2971 interval = 0;
2741 2972 }
2742 2973 }
2743 2974
2744 2975 /*
2745 2976 * If the last argument is also an integer, then we have both a count
2746 2977 * and an interval.
2747 2978 */
2748 2979 if (argc > 0 && isdigit(argv[argc - 1][0])) {
2749 2980 char *end;
2750 2981
2751 2982 errno = 0;
2752 2983 count = interval;
2753 2984 interval = strtoul(argv[argc - 1], &end, 10);
2754 2985
2755 2986 if (*end == '\0' && errno == 0) {
2756 2987 if (interval == 0) {
2757 2988 (void) fprintf(stderr, gettext("interval "
2758 2989 "cannot be zero\n"));
2759 2990 usage(B_FALSE);
2760 2991 }
2761 2992
2762 2993 /*
2763 2994 * Ignore the last parameter
2764 2995 */
2765 2996 argc--;
2766 2997 } else {
2767 2998 interval = 0;
2768 2999 }
2769 3000 }
2770 3001
2771 3002 *iv = interval;
2772 3003 *cnt = count;
2773 3004 *argcp = argc;
2774 3005 }
2775 3006
2776 3007 static void
2777 3008 get_timestamp_arg(char c)
2778 3009 {
2779 3010 if (c == 'u')
2780 3011 timestamp_fmt = UDATE;
2781 3012 else if (c == 'd')
2782 3013 timestamp_fmt = DDATE;
2783 3014 else
2784 3015 usage(B_FALSE);
2785 3016 }
2786 3017
2787 3018 /*
2788 3019 * zpool iostat [-v] [-T d|u] [pool] ... [interval [count]]
2789 3020 *
2790 3021 * -v Display statistics for individual vdevs
2791 3022 * -T Display a timestamp in date(1) or Unix format
2792 3023 *
2793 3024 * This command can be tricky because we want to be able to deal with pool
2794 3025 * creation/destruction as well as vdev configuration changes. The bulk of this
2795 3026 * processing is handled by the pool_list_* routines in zpool_iter.c. We rely
2796 3027 * on pool_list_update() to detect the addition of new pools. Configuration
2797 3028 * changes are all handled within libzfs.
2798 3029 */
2799 3030 int
2800 3031 zpool_do_iostat(int argc, char **argv)
2801 3032 {
2802 3033 int c;
2803 3034 int ret;
2804 3035 int npools;
2805 3036 unsigned long interval = 0, count = 0;
2806 3037 zpool_list_t *list;
2807 3038 boolean_t verbose = B_FALSE;
2808 3039 iostat_cbdata_t cb;
2809 3040
2810 3041 /* check options */
2811 3042 while ((c = getopt(argc, argv, "T:v")) != -1) {
2812 3043 switch (c) {
2813 3044 case 'T':
2814 3045 get_timestamp_arg(*optarg);
2815 3046 break;
2816 3047 case 'v':
2817 3048 verbose = B_TRUE;
2818 3049 break;
2819 3050 case '?':
2820 3051 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
2821 3052 optopt);
2822 3053 usage(B_FALSE);
2823 3054 }
2824 3055 }
2825 3056
2826 3057 argc -= optind;
2827 3058 argv += optind;
2828 3059
2829 3060 get_interval_count(&argc, argv, &interval, &count);
2830 3061
2831 3062 /*
2832 3063 * Construct the list of all interesting pools.
2833 3064 */
2834 3065 ret = 0;
2835 3066 if ((list = pool_list_get(argc, argv, NULL, &ret)) == NULL)
2836 3067 return (1);
2837 3068
2838 3069 if (pool_list_count(list) == 0 && argc != 0) {
2839 3070 pool_list_free(list);
2840 3071 return (1);
2841 3072 }
2842 3073
2843 3074 if (pool_list_count(list) == 0 && interval == 0) {
2844 3075 pool_list_free(list);
2845 3076 (void) fprintf(stderr, gettext("no pools available\n"));
2846 3077 return (1);
2847 3078 }
2848 3079
2849 3080 /*
2850 3081 * Enter the main iostat loop.
2851 3082 */
2852 3083 cb.cb_list = list;
2853 3084 cb.cb_verbose = verbose;
2854 3085 cb.cb_iteration = 0;
2855 3086 cb.cb_namewidth = 0;
2856 3087
2857 3088 for (;;) {
2858 3089 pool_list_update(list);
2859 3090
2860 3091 if ((npools = pool_list_count(list)) == 0)
2861 3092 break;
2862 3093
2863 3094 /*
2864 3095 * Refresh all statistics. This is done as an explicit step
2865 3096 * before calculating the maximum name width, so that any
2866 3097 * configuration changes are properly accounted for.
2867 3098 */
2868 3099 (void) pool_list_iter(list, B_FALSE, refresh_iostat, &cb);
2869 3100
2870 3101 /*
2871 3102 * Iterate over all pools to determine the maximum width
2872 3103 * for the pool / device name column across all pools.
2873 3104 */
2874 3105 cb.cb_namewidth = 0;
2875 3106 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
2876 3107
2877 3108 if (timestamp_fmt != NODATE)
2878 3109 print_timestamp(timestamp_fmt);
2879 3110
2880 3111 /*
2881 3112 * If it's the first time, or verbose mode, print the header.
2882 3113 */
2883 3114 if (++cb.cb_iteration == 1 || verbose)
2884 3115 print_iostat_header(&cb);
2885 3116
2886 3117 (void) pool_list_iter(list, B_FALSE, print_iostat, &cb);
2887 3118
2888 3119 /*
2889 3120 * If there's more than one pool, and we're not in verbose mode
2890 3121 * (which prints a separator for us), then print a separator.
2891 3122 */
2892 3123 if (npools > 1 && !verbose)
2893 3124 print_iostat_separator(&cb);
2894 3125
2895 3126 if (verbose)
2896 3127 (void) printf("\n");
2897 3128
2898 3129 /*
2899 3130 * Flush the output so that redirection to a file isn't buffered
2900 3131 * indefinitely.
2901 3132 */
2902 3133 (void) fflush(stdout);
2903 3134
2904 3135 if (interval == 0)
2905 3136 break;
2906 3137
2907 3138 if (count != 0 && --count == 0)
2908 3139 break;
2909 3140
2910 3141 (void) sleep(interval);
2911 3142 }
2912 3143
2913 3144 pool_list_free(list);
2914 3145
2915 3146 return (ret);
2916 3147 }
2917 3148
2918 3149 typedef struct list_cbdata {
2919 3150 boolean_t cb_verbose;
2920 3151 int cb_namewidth;
2921 3152 boolean_t cb_scripted;
2922 3153 zprop_list_t *cb_proplist;
2923 3154 boolean_t cb_literal;
2924 3155 } list_cbdata_t;
2925 3156
2926 3157 /*
2927 3158 * Given a list of columns to display, output appropriate headers for each one.
2928 3159 */
2929 3160 static void
2930 3161 print_header(list_cbdata_t *cb)
2931 3162 {
2932 3163 zprop_list_t *pl = cb->cb_proplist;
2933 3164 char headerbuf[ZPOOL_MAXPROPLEN];
2934 3165 const char *header;
2935 3166 boolean_t first = B_TRUE;
2936 3167 boolean_t right_justify;
2937 3168 size_t width = 0;
2938 3169
2939 3170 for (; pl != NULL; pl = pl->pl_next) {
2940 3171 width = pl->pl_width;
2941 3172 if (first && cb->cb_verbose) {
2942 3173 /*
2943 3174 * Reset the width to accommodate the verbose listing
2944 3175 * of devices.
2945 3176 */
2946 3177 width = cb->cb_namewidth;
2947 3178 }
2948 3179
2949 3180 if (!first)
2950 3181 (void) printf(" ");
2951 3182 else
2952 3183 first = B_FALSE;
2953 3184
2954 3185 right_justify = B_FALSE;
2955 3186 if (pl->pl_prop != ZPROP_INVAL) {
2956 3187 header = zpool_prop_column_name(pl->pl_prop);
2957 3188 right_justify = zpool_prop_align_right(pl->pl_prop);
2958 3189 } else {
2959 3190 int i;
2960 3191
2961 3192 for (i = 0; pl->pl_user_prop[i] != '\0'; i++)
2962 3193 headerbuf[i] = toupper(pl->pl_user_prop[i]);
2963 3194 headerbuf[i] = '\0';
2964 3195 header = headerbuf;
2965 3196 }
2966 3197
2967 3198 if (pl->pl_next == NULL && !right_justify)
2968 3199 (void) printf("%s", header);
2969 3200 else if (right_justify)
2970 3201 (void) printf("%*s", width, header);
2971 3202 else
2972 3203 (void) printf("%-*s", width, header);
2973 3204
2974 3205 }
2975 3206
2976 3207 (void) printf("\n");
2977 3208 }
2978 3209
2979 3210 /*
2980 3211 * Given a pool and a list of properties, print out all the properties according
2981 3212 * to the described layout.
2982 3213 */
2983 3214 static void
2984 3215 print_pool(zpool_handle_t *zhp, list_cbdata_t *cb)
2985 3216 {
2986 3217 zprop_list_t *pl = cb->cb_proplist;
2987 3218 boolean_t first = B_TRUE;
2988 3219 char property[ZPOOL_MAXPROPLEN];
2989 3220 char *propstr;
2990 3221 boolean_t right_justify;
2991 3222 size_t width;
2992 3223
2993 3224 for (; pl != NULL; pl = pl->pl_next) {
2994 3225
2995 3226 width = pl->pl_width;
2996 3227 if (first && cb->cb_verbose) {
2997 3228 /*
2998 3229 * Reset the width to accommodate the verbose listing
2999 3230 * of devices.
3000 3231 */
3001 3232 width = cb->cb_namewidth;
3002 3233 }
3003 3234
3004 3235 if (!first) {
3005 3236 if (cb->cb_scripted)
3006 3237 (void) printf("\t");
3007 3238 else
3008 3239 (void) printf(" ");
3009 3240 } else {
3010 3241 first = B_FALSE;
3011 3242 }
3012 3243
3013 3244 right_justify = B_FALSE;
3014 3245 if (pl->pl_prop != ZPROP_INVAL) {
3015 3246 if (zpool_get_prop(zhp, pl->pl_prop, property,
3016 3247 sizeof (property), NULL, cb->cb_literal) != 0)
3017 3248 propstr = "-";
3018 3249 else
3019 3250 propstr = property;
3020 3251
3021 3252 right_justify = zpool_prop_align_right(pl->pl_prop);
3022 3253 } else if ((zpool_prop_feature(pl->pl_user_prop) ||
3023 3254 zpool_prop_unsupported(pl->pl_user_prop)) &&
3024 3255 zpool_prop_get_feature(zhp, pl->pl_user_prop, property,
3025 3256 sizeof (property)) == 0) {
3026 3257 propstr = property;
3027 3258 } else {
3028 3259 propstr = "-";
3029 3260 }
3030 3261
3031 3262
3032 3263 /*
3033 3264 * If this is being called in scripted mode, or if this is the
3034 3265 * last column and it is left-justified, don't include a width
3035 3266 * format specifier.
3036 3267 */
3037 3268 if (cb->cb_scripted || (pl->pl_next == NULL && !right_justify))
3038 3269 (void) printf("%s", propstr);
3039 3270 else if (right_justify)
3040 3271 (void) printf("%*s", width, propstr);
3041 3272 else
3042 3273 (void) printf("%-*s", width, propstr);
3043 3274 }
3044 3275
3045 3276 (void) printf("\n");
3046 3277 }
3047 3278
3048 3279 static void
3049 3280 print_one_column(zpool_prop_t prop, uint64_t value, boolean_t scripted,
3050 3281 boolean_t valid)
3051 3282 {
3052 3283 char propval[64];
3053 3284 boolean_t fixed;
3054 3285 size_t width = zprop_width(prop, &fixed, ZFS_TYPE_POOL);
3055 3286
3056 3287 switch (prop) {
3057 3288 case ZPOOL_PROP_EXPANDSZ:
3058 3289 if (value == 0)
3059 3290 (void) strlcpy(propval, "-", sizeof (propval));
3060 3291 else
3061 3292 zfs_nicenum(value, propval, sizeof (propval));
3062 3293 break;
3063 3294 case ZPOOL_PROP_FRAGMENTATION:
3064 3295 if (value == ZFS_FRAG_INVALID) {
3065 3296 (void) strlcpy(propval, "-", sizeof (propval));
3066 3297 } else {
3067 3298 (void) snprintf(propval, sizeof (propval), "%llu%%",
3068 3299 value);
3069 3300 }
3070 3301 break;
3071 3302 case ZPOOL_PROP_CAPACITY:
3072 3303 (void) snprintf(propval, sizeof (propval), "%llu%%", value);
3073 3304 break;
3074 3305 default:
3075 3306 zfs_nicenum(value, propval, sizeof (propval));
3076 3307 }
3077 3308
3078 3309 if (!valid)
3079 3310 (void) strlcpy(propval, "-", sizeof (propval));
3080 3311
3081 3312 if (scripted)
3082 3313 (void) printf("\t%s", propval);
3083 3314 else
3084 3315 (void) printf(" %*s", width, propval);
3085 3316 }
3086 3317
3087 3318 void
3088 3319 print_list_stats(zpool_handle_t *zhp, const char *name, nvlist_t *nv,
3089 3320 list_cbdata_t *cb, int depth)
3090 3321 {
3091 3322 nvlist_t **child;
3092 3323 vdev_stat_t *vs;
3093 3324 uint_t c, children;
3094 3325 char *vname;
3095 3326 boolean_t scripted = cb->cb_scripted;
3096 3327 uint64_t islog = B_FALSE;
|
↓ open down ↓ |
489 lines elided |
↑ open up ↑ |
3097 3328 boolean_t haslog = B_FALSE;
3098 3329 char *dashes = "%-*s - - - - - -\n";
3099 3330
3100 3331 verify(nvlist_lookup_uint64_array(nv, ZPOOL_CONFIG_VDEV_STATS,
3101 3332 (uint64_t **)&vs, &c) == 0);
3102 3333
3103 3334 if (name != NULL) {
3104 3335 boolean_t toplevel = (vs->vs_space != 0);
3105 3336 uint64_t cap;
3106 3337
3107 - if (strcmp(name, VDEV_TYPE_INDIRECT) == 0)
3108 - return;
3109 -
3110 3338 if (scripted)
3111 3339 (void) printf("\t%s", name);
3112 3340 else if (strlen(name) + depth > cb->cb_namewidth)
3113 3341 (void) printf("%*s%s", depth, "", name);
3114 3342 else
3115 3343 (void) printf("%*s%s%*s", depth, "", name,
3116 3344 (int)(cb->cb_namewidth - strlen(name) - depth), "");
3117 3345
3118 3346 /*
3119 3347 * Print the properties for the individual vdevs. Some
3120 3348 * properties are only applicable to toplevel vdevs. The
3121 3349 * 'toplevel' boolean value is passed to the print_one_column()
3122 3350 * to indicate that the value is valid.
3123 3351 */
3124 3352 print_one_column(ZPOOL_PROP_SIZE, vs->vs_space, scripted,
3125 3353 toplevel);
3126 3354 print_one_column(ZPOOL_PROP_ALLOCATED, vs->vs_alloc, scripted,
3127 3355 toplevel);
3128 3356 print_one_column(ZPOOL_PROP_FREE, vs->vs_space - vs->vs_alloc,
3129 3357 scripted, toplevel);
3130 3358 print_one_column(ZPOOL_PROP_EXPANDSZ, vs->vs_esize, scripted,
3131 3359 B_TRUE);
3132 3360 print_one_column(ZPOOL_PROP_FRAGMENTATION,
3133 3361 vs->vs_fragmentation, scripted,
3134 3362 (vs->vs_fragmentation != ZFS_FRAG_INVALID && toplevel));
3135 3363 cap = (vs->vs_space == 0) ? 0 :
3136 3364 (vs->vs_alloc * 100 / vs->vs_space);
3137 3365 print_one_column(ZPOOL_PROP_CAPACITY, cap, scripted, toplevel);
3138 3366 (void) printf("\n");
3139 3367 }
3140 3368
3141 3369 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
3142 3370 &child, &children) != 0)
3143 3371 return;
3144 3372
3145 3373 for (c = 0; c < children; c++) {
3146 3374 uint64_t ishole = B_FALSE;
3147 3375
3148 3376 if (nvlist_lookup_uint64(child[c],
3149 3377 ZPOOL_CONFIG_IS_HOLE, &ishole) == 0 && ishole)
3150 3378 continue;
3151 3379
3152 3380 if (nvlist_lookup_uint64(child[c],
3153 3381 ZPOOL_CONFIG_IS_LOG, &islog) == 0 && islog) {
3154 3382 haslog = B_TRUE;
3155 3383 continue;
3156 3384 }
3157 3385
3158 3386 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3159 3387 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3160 3388 free(vname);
3161 3389 }
3162 3390
3163 3391 if (haslog == B_TRUE) {
3164 3392 /* LINTED E_SEC_PRINTF_VAR_FMT */
3165 3393 (void) printf(dashes, cb->cb_namewidth, "log");
3166 3394 for (c = 0; c < children; c++) {
3167 3395 if (nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
3168 3396 &islog) != 0 || !islog)
3169 3397 continue;
3170 3398 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3171 3399 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3172 3400 free(vname);
3173 3401 }
3174 3402 }
3175 3403
3176 3404 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
3177 3405 &child, &children) == 0 && children > 0) {
3178 3406 /* LINTED E_SEC_PRINTF_VAR_FMT */
3179 3407 (void) printf(dashes, cb->cb_namewidth, "cache");
3180 3408 for (c = 0; c < children; c++) {
3181 3409 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3182 3410 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3183 3411 free(vname);
3184 3412 }
3185 3413 }
3186 3414
3187 3415 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child,
3188 3416 &children) == 0 && children > 0) {
3189 3417 /* LINTED E_SEC_PRINTF_VAR_FMT */
3190 3418 (void) printf(dashes, cb->cb_namewidth, "spare");
3191 3419 for (c = 0; c < children; c++) {
3192 3420 vname = zpool_vdev_name(g_zfs, zhp, child[c], B_FALSE);
3193 3421 print_list_stats(zhp, vname, child[c], cb, depth + 2);
3194 3422 free(vname);
3195 3423 }
3196 3424 }
3197 3425 }
3198 3426
3199 3427
3200 3428 /*
3201 3429 * Generic callback function to list a pool.
3202 3430 */
3203 3431 int
3204 3432 list_callback(zpool_handle_t *zhp, void *data)
3205 3433 {
3206 3434 list_cbdata_t *cbp = data;
3207 3435 nvlist_t *config;
3208 3436 nvlist_t *nvroot;
3209 3437
3210 3438 config = zpool_get_config(zhp, NULL);
3211 3439
3212 3440 print_pool(zhp, cbp);
3213 3441 if (!cbp->cb_verbose)
3214 3442 return (0);
3215 3443
3216 3444 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
3217 3445 &nvroot) == 0);
3218 3446 print_list_stats(zhp, NULL, nvroot, cbp, 0);
3219 3447
3220 3448 return (0);
3221 3449 }
3222 3450
3223 3451 /*
3224 3452 * zpool list [-Hp] [-o prop[,prop]*] [-T d|u] [pool] ... [interval [count]]
3225 3453 *
3226 3454 * -H Scripted mode. Don't display headers, and separate properties
3227 3455 * by a single tab.
3228 3456 * -o List of properties to display. Defaults to
3229 3457 * "name,size,allocated,free,expandsize,fragmentation,capacity,"
3230 3458 * "dedupratio,health,altroot"
|
↓ open down ↓ |
111 lines elided |
↑ open up ↑ |
3231 3459 * -p Diplay values in parsable (exact) format.
3232 3460 * -T Display a timestamp in date(1) or Unix format
3233 3461 *
3234 3462 * List all pools in the system, whether or not they're healthy. Output space
3235 3463 * statistics for each one, as well as health status summary.
3236 3464 */
3237 3465 int
3238 3466 zpool_do_list(int argc, char **argv)
3239 3467 {
3240 3468 int c;
3241 - int ret;
3469 + int ret = 0;
3242 3470 list_cbdata_t cb = { 0 };
3243 3471 static char default_props[] =
3244 3472 "name,size,allocated,free,expandsize,fragmentation,capacity,"
3245 3473 "dedupratio,health,altroot";
3246 3474 char *props = default_props;
3247 3475 unsigned long interval = 0, count = 0;
3248 3476 zpool_list_t *list;
3249 3477 boolean_t first = B_TRUE;
3250 3478
3251 3479 /* check options */
3252 3480 while ((c = getopt(argc, argv, ":Ho:pT:v")) != -1) {
3253 3481 switch (c) {
3254 3482 case 'H':
3255 3483 cb.cb_scripted = B_TRUE;
3256 3484 break;
3257 3485 case 'o':
3258 3486 props = optarg;
3259 3487 break;
3260 3488 case 'p':
3261 3489 cb.cb_literal = B_TRUE;
3262 3490 break;
3263 3491 case 'T':
3264 3492 get_timestamp_arg(*optarg);
3265 3493 break;
3266 3494 case 'v':
3267 3495 cb.cb_verbose = B_TRUE;
3268 3496 break;
3269 3497 case ':':
3270 3498 (void) fprintf(stderr, gettext("missing argument for "
3271 3499 "'%c' option\n"), optopt);
3272 3500 usage(B_FALSE);
3273 3501 break;
3274 3502 case '?':
3275 3503 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3276 3504 optopt);
3277 3505 usage(B_FALSE);
3278 3506 }
3279 3507 }
3280 3508
3281 3509 argc -= optind;
3282 3510 argv += optind;
3283 3511
3284 3512 get_interval_count(&argc, argv, &interval, &count);
3285 3513
3286 3514 if (zprop_get_list(g_zfs, props, &cb.cb_proplist, ZFS_TYPE_POOL) != 0)
3287 3515 usage(B_FALSE);
3288 3516
3289 3517 for (;;) {
3290 3518 if ((list = pool_list_get(argc, argv, &cb.cb_proplist,
3291 3519 &ret)) == NULL)
3292 3520 return (1);
3293 3521
3294 3522 if (pool_list_count(list) == 0)
3295 3523 break;
3296 3524
3297 3525 cb.cb_namewidth = 0;
3298 3526 (void) pool_list_iter(list, B_FALSE, get_namewidth, &cb);
3299 3527
3300 3528 if (timestamp_fmt != NODATE)
3301 3529 print_timestamp(timestamp_fmt);
3302 3530
3303 3531 if (!cb.cb_scripted && (first || cb.cb_verbose)) {
3304 3532 print_header(&cb);
3305 3533 first = B_FALSE;
3306 3534 }
3307 3535 ret = pool_list_iter(list, B_TRUE, list_callback, &cb);
3308 3536
3309 3537 if (interval == 0)
3310 3538 break;
3311 3539
3312 3540 if (count != 0 && --count == 0)
3313 3541 break;
3314 3542
3315 3543 pool_list_free(list);
3316 3544 (void) sleep(interval);
3317 3545 }
3318 3546
3319 3547 if (argc == 0 && !cb.cb_scripted && pool_list_count(list) == 0) {
3320 3548 (void) printf(gettext("no pools available\n"));
3321 3549 ret = 0;
3322 3550 }
3323 3551
3324 3552 pool_list_free(list);
3325 3553 zprop_free_list(cb.cb_proplist);
3326 3554 return (ret);
3327 3555 }
3328 3556
3329 3557 static int
3330 3558 zpool_do_attach_or_replace(int argc, char **argv, int replacing)
3331 3559 {
3332 3560 boolean_t force = B_FALSE;
3333 3561 int c;
3334 3562 nvlist_t *nvroot;
3335 3563 char *poolname, *old_disk, *new_disk;
3336 3564 zpool_handle_t *zhp;
3337 3565 zpool_boot_label_t boot_type;
3338 3566 uint64_t boot_size;
3339 3567 int ret;
3340 3568
3341 3569 /* check options */
3342 3570 while ((c = getopt(argc, argv, "f")) != -1) {
3343 3571 switch (c) {
3344 3572 case 'f':
3345 3573 force = B_TRUE;
3346 3574 break;
3347 3575 case '?':
3348 3576 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3349 3577 optopt);
3350 3578 usage(B_FALSE);
3351 3579 }
3352 3580 }
3353 3581
3354 3582 argc -= optind;
3355 3583 argv += optind;
3356 3584
3357 3585 /* get pool name and check number of arguments */
3358 3586 if (argc < 1) {
3359 3587 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3360 3588 usage(B_FALSE);
3361 3589 }
3362 3590
3363 3591 poolname = argv[0];
3364 3592
3365 3593 if (argc < 2) {
3366 3594 (void) fprintf(stderr,
3367 3595 gettext("missing <device> specification\n"));
3368 3596 usage(B_FALSE);
3369 3597 }
3370 3598
3371 3599 old_disk = argv[1];
3372 3600
3373 3601 if (argc < 3) {
3374 3602 if (!replacing) {
3375 3603 (void) fprintf(stderr,
3376 3604 gettext("missing <new_device> specification\n"));
3377 3605 usage(B_FALSE);
3378 3606 }
3379 3607 new_disk = old_disk;
3380 3608 argc -= 1;
3381 3609 argv += 1;
3382 3610 } else {
3383 3611 new_disk = argv[2];
3384 3612 argc -= 2;
3385 3613 argv += 2;
3386 3614 }
3387 3615
3388 3616 if (argc > 1) {
3389 3617 (void) fprintf(stderr, gettext("too many arguments\n"));
3390 3618 usage(B_FALSE);
3391 3619 }
3392 3620
3393 3621 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3394 3622 return (1);
3395 3623
3396 3624 if (zpool_get_config(zhp, NULL) == NULL) {
3397 3625 (void) fprintf(stderr, gettext("pool '%s' is unavailable\n"),
3398 3626 poolname);
3399 3627 zpool_close(zhp);
3400 3628 return (1);
3401 3629 }
3402 3630
3403 3631 if (zpool_is_bootable(zhp))
3404 3632 boot_type = ZPOOL_COPY_BOOT_LABEL;
3405 3633 else
3406 3634 boot_type = ZPOOL_NO_BOOT_LABEL;
3407 3635
3408 3636 boot_size = zpool_get_prop_int(zhp, ZPOOL_PROP_BOOTSIZE, NULL);
3409 3637 nvroot = make_root_vdev(zhp, force, B_FALSE, replacing, B_FALSE,
3410 3638 boot_type, boot_size, argc, argv);
3411 3639 if (nvroot == NULL) {
3412 3640 zpool_close(zhp);
3413 3641 return (1);
3414 3642 }
3415 3643
3416 3644 ret = zpool_vdev_attach(zhp, old_disk, new_disk, nvroot, replacing);
3417 3645
3418 3646 nvlist_free(nvroot);
3419 3647 zpool_close(zhp);
3420 3648
3421 3649 return (ret);
3422 3650 }
3423 3651
3424 3652 /*
3425 3653 * zpool replace [-f] <pool> <device> <new_device>
3426 3654 *
3427 3655 * -f Force attach, even if <new_device> appears to be in use.
3428 3656 *
3429 3657 * Replace <device> with <new_device>.
3430 3658 */
3431 3659 /* ARGSUSED */
3432 3660 int
3433 3661 zpool_do_replace(int argc, char **argv)
3434 3662 {
3435 3663 return (zpool_do_attach_or_replace(argc, argv, B_TRUE));
3436 3664 }
3437 3665
3438 3666 /*
3439 3667 * zpool attach [-f] <pool> <device> <new_device>
3440 3668 *
3441 3669 * -f Force attach, even if <new_device> appears to be in use.
3442 3670 *
3443 3671 * Attach <new_device> to the mirror containing <device>. If <device> is not
3444 3672 * part of a mirror, then <device> will be transformed into a mirror of
3445 3673 * <device> and <new_device>. In either case, <new_device> will begin life
3446 3674 * with a DTL of [0, now], and will immediately begin to resilver itself.
3447 3675 */
3448 3676 int
3449 3677 zpool_do_attach(int argc, char **argv)
3450 3678 {
3451 3679 return (zpool_do_attach_or_replace(argc, argv, B_FALSE));
3452 3680 }
3453 3681
3454 3682 /*
3455 3683 * zpool detach [-f] <pool> <device>
3456 3684 *
3457 3685 * -f Force detach of <device>, even if DTLs argue against it
3458 3686 * (not supported yet)
3459 3687 *
3460 3688 * Detach a device from a mirror. The operation will be refused if <device>
3461 3689 * is the last device in the mirror, or if the DTLs indicate that this device
3462 3690 * has the only valid copy of some data.
3463 3691 */
3464 3692 /* ARGSUSED */
3465 3693 int
3466 3694 zpool_do_detach(int argc, char **argv)
3467 3695 {
3468 3696 int c;
3469 3697 char *poolname, *path;
3470 3698 zpool_handle_t *zhp;
3471 3699 int ret;
3472 3700
3473 3701 /* check options */
3474 3702 while ((c = getopt(argc, argv, "f")) != -1) {
3475 3703 switch (c) {
3476 3704 case 'f':
3477 3705 case '?':
3478 3706 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3479 3707 optopt);
3480 3708 usage(B_FALSE);
3481 3709 }
3482 3710 }
3483 3711
3484 3712 argc -= optind;
3485 3713 argv += optind;
3486 3714
3487 3715 /* get pool name and check number of arguments */
3488 3716 if (argc < 1) {
3489 3717 (void) fprintf(stderr, gettext("missing pool name argument\n"));
3490 3718 usage(B_FALSE);
3491 3719 }
3492 3720
3493 3721 if (argc < 2) {
3494 3722 (void) fprintf(stderr,
3495 3723 gettext("missing <device> specification\n"));
3496 3724 usage(B_FALSE);
3497 3725 }
3498 3726
3499 3727 poolname = argv[0];
3500 3728 path = argv[1];
3501 3729
3502 3730 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3503 3731 return (1);
3504 3732
3505 3733 ret = zpool_vdev_detach(zhp, path);
3506 3734
3507 3735 zpool_close(zhp);
3508 3736
3509 3737 return (ret);
3510 3738 }
3511 3739
3512 3740 /*
3513 3741 * zpool split [-n] [-o prop=val] ...
3514 3742 * [-o mntopt] ...
3515 3743 * [-R altroot] <pool> <newpool> [<device> ...]
3516 3744 *
3517 3745 * -n Do not split the pool, but display the resulting layout if
3518 3746 * it were to be split.
3519 3747 * -o Set property=value, or set mount options.
3520 3748 * -R Mount the split-off pool under an alternate root.
3521 3749 *
3522 3750 * Splits the named pool and gives it the new pool name. Devices to be split
3523 3751 * off may be listed, provided that no more than one device is specified
3524 3752 * per top-level vdev mirror. The newly split pool is left in an exported
3525 3753 * state unless -R is specified.
3526 3754 *
3527 3755 * Restrictions: the top-level of the pool pool must only be made up of
3528 3756 * mirrors; all devices in the pool must be healthy; no device may be
3529 3757 * undergoing a resilvering operation.
3530 3758 */
3531 3759 int
3532 3760 zpool_do_split(int argc, char **argv)
3533 3761 {
3534 3762 char *srcpool, *newpool, *propval;
3535 3763 char *mntopts = NULL;
3536 3764 splitflags_t flags;
3537 3765 int c, ret = 0;
3538 3766 zpool_handle_t *zhp;
3539 3767 nvlist_t *config, *props = NULL;
3540 3768
3541 3769 flags.dryrun = B_FALSE;
3542 3770 flags.import = B_FALSE;
3543 3771
3544 3772 /* check options */
3545 3773 while ((c = getopt(argc, argv, ":R:no:")) != -1) {
3546 3774 switch (c) {
3547 3775 case 'R':
3548 3776 flags.import = B_TRUE;
3549 3777 if (add_prop_list(
3550 3778 zpool_prop_to_name(ZPOOL_PROP_ALTROOT), optarg,
3551 3779 &props, B_TRUE) != 0) {
3552 3780 nvlist_free(props);
3553 3781 usage(B_FALSE);
3554 3782 }
3555 3783 break;
3556 3784 case 'n':
3557 3785 flags.dryrun = B_TRUE;
3558 3786 break;
3559 3787 case 'o':
3560 3788 if ((propval = strchr(optarg, '=')) != NULL) {
3561 3789 *propval = '\0';
3562 3790 propval++;
3563 3791 if (add_prop_list(optarg, propval,
3564 3792 &props, B_TRUE) != 0) {
3565 3793 nvlist_free(props);
3566 3794 usage(B_FALSE);
3567 3795 }
3568 3796 } else {
3569 3797 mntopts = optarg;
3570 3798 }
3571 3799 break;
3572 3800 case ':':
3573 3801 (void) fprintf(stderr, gettext("missing argument for "
3574 3802 "'%c' option\n"), optopt);
3575 3803 usage(B_FALSE);
3576 3804 break;
3577 3805 case '?':
3578 3806 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3579 3807 optopt);
3580 3808 usage(B_FALSE);
3581 3809 break;
3582 3810 }
3583 3811 }
3584 3812
3585 3813 if (!flags.import && mntopts != NULL) {
3586 3814 (void) fprintf(stderr, gettext("setting mntopts is only "
3587 3815 "valid when importing the pool\n"));
3588 3816 usage(B_FALSE);
3589 3817 }
3590 3818
3591 3819 argc -= optind;
3592 3820 argv += optind;
3593 3821
3594 3822 if (argc < 1) {
3595 3823 (void) fprintf(stderr, gettext("Missing pool name\n"));
3596 3824 usage(B_FALSE);
3597 3825 }
3598 3826 if (argc < 2) {
3599 3827 (void) fprintf(stderr, gettext("Missing new pool name\n"));
3600 3828 usage(B_FALSE);
3601 3829 }
3602 3830
3603 3831 srcpool = argv[0];
3604 3832 newpool = argv[1];
3605 3833
3606 3834 argc -= 2;
3607 3835 argv += 2;
3608 3836
3609 3837 if ((zhp = zpool_open(g_zfs, srcpool)) == NULL)
3610 3838 return (1);
3611 3839
3612 3840 config = split_mirror_vdev(zhp, newpool, props, flags, argc, argv);
3613 3841 if (config == NULL) {
3614 3842 ret = 1;
3615 3843 } else {
3616 3844 if (flags.dryrun) {
3617 3845 (void) printf(gettext("would create '%s' with the "
3618 3846 "following layout:\n\n"), newpool);
3619 3847 print_vdev_tree(NULL, newpool, config, 0, B_FALSE);
3620 3848 }
3621 3849 nvlist_free(config);
3622 3850 }
3623 3851
3624 3852 zpool_close(zhp);
3625 3853
3626 3854 if (ret != 0 || flags.dryrun || !flags.import)
3627 3855 return (ret);
3628 3856
3629 3857 /*
3630 3858 * The split was successful. Now we need to open the new
3631 3859 * pool and import it.
3632 3860 */
3633 3861 if ((zhp = zpool_open_canfail(g_zfs, newpool)) == NULL)
3634 3862 return (1);
3635 3863 if (zpool_get_state(zhp) != POOL_STATE_UNAVAIL &&
3636 3864 zpool_enable_datasets(zhp, mntopts, 0) != 0) {
3637 3865 ret = 1;
3638 3866 (void) fprintf(stderr, gettext("Split was successful, but "
3639 3867 "the datasets could not all be mounted\n"));
3640 3868 (void) fprintf(stderr, gettext("Try doing '%s' with a "
3641 3869 "different altroot\n"), "zpool import");
3642 3870 }
3643 3871 zpool_close(zhp);
3644 3872
3645 3873 return (ret);
3646 3874 }
3647 3875
3648 3876
3649 3877
3650 3878 /*
3651 3879 * zpool online <pool> <device> ...
3652 3880 */
3653 3881 int
3654 3882 zpool_do_online(int argc, char **argv)
3655 3883 {
3656 3884 int c, i;
3657 3885 char *poolname;
3658 3886 zpool_handle_t *zhp;
3659 3887 int ret = 0;
3660 3888 vdev_state_t newstate;
3661 3889 int flags = 0;
3662 3890
3663 3891 /* check options */
3664 3892 while ((c = getopt(argc, argv, "et")) != -1) {
3665 3893 switch (c) {
3666 3894 case 'e':
3667 3895 flags |= ZFS_ONLINE_EXPAND;
3668 3896 break;
3669 3897 case 't':
3670 3898 case '?':
3671 3899 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3672 3900 optopt);
3673 3901 usage(B_FALSE);
3674 3902 }
3675 3903 }
3676 3904
3677 3905 argc -= optind;
3678 3906 argv += optind;
3679 3907
3680 3908 /* get pool name and check number of arguments */
3681 3909 if (argc < 1) {
3682 3910 (void) fprintf(stderr, gettext("missing pool name\n"));
3683 3911 usage(B_FALSE);
3684 3912 }
3685 3913 if (argc < 2) {
3686 3914 (void) fprintf(stderr, gettext("missing device name\n"));
3687 3915 usage(B_FALSE);
3688 3916 }
3689 3917
3690 3918 poolname = argv[0];
3691 3919
3692 3920 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3693 3921 return (1);
3694 3922
3695 3923 for (i = 1; i < argc; i++) {
3696 3924 if (zpool_vdev_online(zhp, argv[i], flags, &newstate) == 0) {
3697 3925 if (newstate != VDEV_STATE_HEALTHY) {
3698 3926 (void) printf(gettext("warning: device '%s' "
3699 3927 "onlined, but remains in faulted state\n"),
3700 3928 argv[i]);
3701 3929 if (newstate == VDEV_STATE_FAULTED)
3702 3930 (void) printf(gettext("use 'zpool "
3703 3931 "clear' to restore a faulted "
3704 3932 "device\n"));
3705 3933 else
3706 3934 (void) printf(gettext("use 'zpool "
3707 3935 "replace' to replace devices "
3708 3936 "that are no longer present\n"));
3709 3937 }
3710 3938 } else {
3711 3939 ret = 1;
3712 3940 }
3713 3941 }
3714 3942
3715 3943 zpool_close(zhp);
3716 3944
3717 3945 return (ret);
3718 3946 }
3719 3947
3720 3948 /*
3721 3949 * zpool offline [-ft] <pool> <device> ...
3722 3950 *
3723 3951 * -f Force the device into the offline state, even if doing
3724 3952 * so would appear to compromise pool availability.
3725 3953 * (not supported yet)
3726 3954 *
3727 3955 * -t Only take the device off-line temporarily. The offline
3728 3956 * state will not be persistent across reboots.
3729 3957 */
3730 3958 /* ARGSUSED */
3731 3959 int
3732 3960 zpool_do_offline(int argc, char **argv)
3733 3961 {
3734 3962 int c, i;
3735 3963 char *poolname;
3736 3964 zpool_handle_t *zhp;
3737 3965 int ret = 0;
3738 3966 boolean_t istmp = B_FALSE;
3739 3967
3740 3968 /* check options */
3741 3969 while ((c = getopt(argc, argv, "ft")) != -1) {
3742 3970 switch (c) {
3743 3971 case 't':
3744 3972 istmp = B_TRUE;
3745 3973 break;
3746 3974 case 'f':
3747 3975 case '?':
3748 3976 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3749 3977 optopt);
3750 3978 usage(B_FALSE);
3751 3979 }
3752 3980 }
3753 3981
3754 3982 argc -= optind;
3755 3983 argv += optind;
3756 3984
3757 3985 /* get pool name and check number of arguments */
3758 3986 if (argc < 1) {
3759 3987 (void) fprintf(stderr, gettext("missing pool name\n"));
3760 3988 usage(B_FALSE);
3761 3989 }
3762 3990 if (argc < 2) {
3763 3991 (void) fprintf(stderr, gettext("missing device name\n"));
3764 3992 usage(B_FALSE);
3765 3993 }
3766 3994
3767 3995 poolname = argv[0];
3768 3996
3769 3997 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3770 3998 return (1);
3771 3999
3772 4000 for (i = 1; i < argc; i++) {
3773 4001 if (zpool_vdev_offline(zhp, argv[i], istmp) != 0)
3774 4002 ret = 1;
3775 4003 }
3776 4004
3777 4005 zpool_close(zhp);
3778 4006
3779 4007 return (ret);
3780 4008 }
3781 4009
3782 4010 /*
3783 4011 * zpool clear <pool> [device]
3784 4012 *
3785 4013 * Clear all errors associated with a pool or a particular device.
3786 4014 */
3787 4015 int
3788 4016 zpool_do_clear(int argc, char **argv)
3789 4017 {
3790 4018 int c;
3791 4019 int ret = 0;
3792 4020 boolean_t dryrun = B_FALSE;
3793 4021 boolean_t do_rewind = B_FALSE;
3794 4022 boolean_t xtreme_rewind = B_FALSE;
3795 4023 uint32_t rewind_policy = ZPOOL_NO_REWIND;
3796 4024 nvlist_t *policy = NULL;
3797 4025 zpool_handle_t *zhp;
3798 4026 char *pool, *device;
3799 4027
3800 4028 /* check options */
3801 4029 while ((c = getopt(argc, argv, "FnX")) != -1) {
3802 4030 switch (c) {
3803 4031 case 'F':
3804 4032 do_rewind = B_TRUE;
3805 4033 break;
3806 4034 case 'n':
3807 4035 dryrun = B_TRUE;
3808 4036 break;
3809 4037 case 'X':
3810 4038 xtreme_rewind = B_TRUE;
3811 4039 break;
3812 4040 case '?':
3813 4041 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3814 4042 optopt);
3815 4043 usage(B_FALSE);
3816 4044 }
3817 4045 }
3818 4046
3819 4047 argc -= optind;
3820 4048 argv += optind;
3821 4049
3822 4050 if (argc < 1) {
3823 4051 (void) fprintf(stderr, gettext("missing pool name\n"));
3824 4052 usage(B_FALSE);
3825 4053 }
3826 4054
3827 4055 if (argc > 2) {
3828 4056 (void) fprintf(stderr, gettext("too many arguments\n"));
3829 4057 usage(B_FALSE);
3830 4058 }
3831 4059
3832 4060 if ((dryrun || xtreme_rewind) && !do_rewind) {
3833 4061 (void) fprintf(stderr,
3834 4062 gettext("-n or -X only meaningful with -F\n"));
3835 4063 usage(B_FALSE);
3836 4064 }
3837 4065 if (dryrun)
3838 4066 rewind_policy = ZPOOL_TRY_REWIND;
3839 4067 else if (do_rewind)
3840 4068 rewind_policy = ZPOOL_DO_REWIND;
3841 4069 if (xtreme_rewind)
3842 4070 rewind_policy |= ZPOOL_EXTREME_REWIND;
3843 4071
3844 4072 /* In future, further rewind policy choices can be passed along here */
3845 4073 if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
3846 4074 nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
3847 4075 return (1);
3848 4076
3849 4077 pool = argv[0];
3850 4078 device = argc == 2 ? argv[1] : NULL;
3851 4079
3852 4080 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL) {
3853 4081 nvlist_free(policy);
3854 4082 return (1);
3855 4083 }
3856 4084
3857 4085 if (zpool_clear(zhp, device, policy) != 0)
3858 4086 ret = 1;
3859 4087
3860 4088 zpool_close(zhp);
3861 4089
3862 4090 nvlist_free(policy);
3863 4091
3864 4092 return (ret);
3865 4093 }
3866 4094
3867 4095 /*
3868 4096 * zpool reguid <pool>
3869 4097 */
3870 4098 int
3871 4099 zpool_do_reguid(int argc, char **argv)
3872 4100 {
3873 4101 int c;
3874 4102 char *poolname;
3875 4103 zpool_handle_t *zhp;
3876 4104 int ret = 0;
3877 4105
3878 4106 /* check options */
3879 4107 while ((c = getopt(argc, argv, "")) != -1) {
3880 4108 switch (c) {
3881 4109 case '?':
3882 4110 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3883 4111 optopt);
3884 4112 usage(B_FALSE);
3885 4113 }
3886 4114 }
3887 4115
3888 4116 argc -= optind;
3889 4117 argv += optind;
3890 4118
3891 4119 /* get pool name and check number of arguments */
3892 4120 if (argc < 1) {
3893 4121 (void) fprintf(stderr, gettext("missing pool name\n"));
3894 4122 usage(B_FALSE);
3895 4123 }
3896 4124
3897 4125 if (argc > 1) {
3898 4126 (void) fprintf(stderr, gettext("too many arguments\n"));
3899 4127 usage(B_FALSE);
3900 4128 }
3901 4129
3902 4130 poolname = argv[0];
3903 4131 if ((zhp = zpool_open(g_zfs, poolname)) == NULL)
3904 4132 return (1);
3905 4133
3906 4134 ret = zpool_reguid(zhp);
3907 4135
3908 4136 zpool_close(zhp);
3909 4137 return (ret);
3910 4138 }
3911 4139
3912 4140
3913 4141 /*
3914 4142 * zpool reopen <pool>
3915 4143 *
3916 4144 * Reopen the pool so that the kernel can update the sizes of all vdevs.
3917 4145 */
3918 4146 int
3919 4147 zpool_do_reopen(int argc, char **argv)
3920 4148 {
3921 4149 int c;
3922 4150 int ret = 0;
3923 4151 zpool_handle_t *zhp;
3924 4152 char *pool;
3925 4153
3926 4154 /* check options */
3927 4155 while ((c = getopt(argc, argv, "")) != -1) {
3928 4156 switch (c) {
3929 4157 case '?':
3930 4158 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
3931 4159 optopt);
3932 4160 usage(B_FALSE);
3933 4161 }
3934 4162 }
3935 4163
3936 4164 argc--;
3937 4165 argv++;
3938 4166
3939 4167 if (argc < 1) {
3940 4168 (void) fprintf(stderr, gettext("missing pool name\n"));
3941 4169 usage(B_FALSE);
3942 4170 }
3943 4171
3944 4172 if (argc > 1) {
3945 4173 (void) fprintf(stderr, gettext("too many arguments\n"));
3946 4174 usage(B_FALSE);
3947 4175 }
3948 4176
3949 4177 pool = argv[0];
3950 4178 if ((zhp = zpool_open_canfail(g_zfs, pool)) == NULL)
3951 4179 return (1);
3952 4180
3953 4181 ret = zpool_reopen(zhp);
3954 4182 zpool_close(zhp);
3955 4183 return (ret);
3956 4184 }
3957 4185
3958 4186 typedef struct scrub_cbdata {
3959 4187 int cb_type;
3960 4188 int cb_argc;
3961 4189 char **cb_argv;
3962 4190 pool_scrub_cmd_t cb_scrub_cmd;
3963 4191 } scrub_cbdata_t;
3964 4192
3965 4193 int
3966 4194 scrub_callback(zpool_handle_t *zhp, void *data)
3967 4195 {
3968 4196 scrub_cbdata_t *cb = data;
3969 4197 int err;
3970 4198
3971 4199 /*
3972 4200 * Ignore faulted pools.
3973 4201 */
3974 4202 if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
|
↓ open down ↓ |
723 lines elided |
↑ open up ↑ |
3975 4203 (void) fprintf(stderr, gettext("cannot scrub '%s': pool is "
3976 4204 "currently unavailable\n"), zpool_get_name(zhp));
3977 4205 return (1);
3978 4206 }
3979 4207
3980 4208 err = zpool_scan(zhp, cb->cb_type, cb->cb_scrub_cmd);
3981 4209
3982 4210 return (err != 0);
3983 4211 }
3984 4212
4213 +typedef struct trim_cbdata {
4214 + boolean_t cb_start;
4215 + uint64_t cb_rate;
4216 +} trim_cbdata_t;
4217 +
4218 +int
4219 +trim_callback(zpool_handle_t *zhp, void *data)
4220 +{
4221 + trim_cbdata_t *cb = data;
4222 + int err;
4223 +
4224 + /*
4225 + * Ignore faulted pools.
4226 + */
4227 + if (zpool_get_state(zhp) == POOL_STATE_UNAVAIL) {
4228 + (void) fprintf(stderr, gettext("cannot trim '%s': pool is "
4229 + "currently unavailable\n"), zpool_get_name(zhp));
4230 + return (1);
4231 + }
4232 +
4233 + err = zpool_trim(zhp, cb->cb_start, cb->cb_rate);
4234 +
4235 + return (err != 0);
4236 +}
4237 +
3985 4238 /*
3986 4239 * zpool scrub [-s | -p] <pool> ...
3987 4240 *
3988 4241 * -s Stop. Stops any in-progress scrub.
3989 4242 * -p Pause. Pause in-progress scrub.
3990 4243 */
3991 4244 int
3992 4245 zpool_do_scrub(int argc, char **argv)
3993 4246 {
3994 4247 int c;
3995 4248 scrub_cbdata_t cb;
3996 4249
3997 4250 cb.cb_type = POOL_SCAN_SCRUB;
3998 4251 cb.cb_scrub_cmd = POOL_SCRUB_NORMAL;
3999 4252
4000 4253 /* check options */
4001 - while ((c = getopt(argc, argv, "sp")) != -1) {
4254 + while ((c = getopt(argc, argv, "mMps")) != -1) {
4002 4255 switch (c) {
4003 4256 case 's':
4004 - cb.cb_type = POOL_SCAN_NONE;
4257 + if (cb.cb_type != POOL_SCAN_SCRUB) {
4258 + (void) fprintf(stderr,
4259 + gettext("incompatible options\n"));
4260 + usage(B_FALSE);
4261 + } else
4262 + cb.cb_type = POOL_SCAN_NONE;
4005 4263 break;
4264 + case 'M':
4265 + if (cb.cb_type != POOL_SCAN_SCRUB) {
4266 + (void) fprintf(stderr,
4267 + gettext("incompatible options\n"));
4268 + usage(B_FALSE);
4269 + } else
4270 + cb.cb_type = POOL_SCAN_MOS;
4271 + break;
4272 + case 'm':
4273 + if (cb.cb_type != POOL_SCAN_SCRUB) {
4274 + (void) fprintf(stderr,
4275 + gettext("incompatible options\n"));
4276 + usage(B_FALSE);
4277 + } else
4278 + cb.cb_type = POOL_SCAN_META;
4279 + break;
4006 4280 case 'p':
4007 4281 cb.cb_scrub_cmd = POOL_SCRUB_PAUSE;
4008 4282 break;
4009 4283 case '?':
4010 4284 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4011 4285 optopt);
4012 4286 usage(B_FALSE);
4013 4287 }
4014 4288 }
4015 4289
4016 4290 if (cb.cb_type == POOL_SCAN_NONE &&
4017 4291 cb.cb_scrub_cmd == POOL_SCRUB_PAUSE) {
4018 4292 (void) fprintf(stderr, gettext("invalid option combination: "
4019 4293 "-s and -p are mutually exclusive\n"));
4020 4294 usage(B_FALSE);
4021 4295 }
4022 4296
4023 4297 cb.cb_argc = argc;
4024 4298 cb.cb_argv = argv;
4025 4299 argc -= optind;
|
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
4026 4300 argv += optind;
4027 4301
4028 4302 if (argc < 1) {
4029 4303 (void) fprintf(stderr, gettext("missing pool name argument\n"));
4030 4304 usage(B_FALSE);
4031 4305 }
4032 4306
4033 4307 return (for_each_pool(argc, argv, B_TRUE, NULL, scrub_callback, &cb));
4034 4308 }
4035 4309
4310 +/*
4311 + * zpool trim [-s|-r <rate>] <pool> ...
4312 + *
4313 + * -s Stop. Stops any in-progress trim.
4314 + * -r <rate> Sets the TRIM rate.
4315 + */
4316 +int
4317 +zpool_do_trim(int argc, char **argv)
4318 +{
4319 + int c;
4320 + trim_cbdata_t cb;
4321 +
4322 + cb.cb_start = B_TRUE;
4323 + cb.cb_rate = 0;
4324 +
4325 + /* check options */
4326 + while ((c = getopt(argc, argv, "sr:")) != -1) {
4327 + switch (c) {
4328 + case 's':
4329 + cb.cb_start = B_FALSE;
4330 + break;
4331 + case 'r':
4332 + if (zfs_nicestrtonum(NULL, optarg, &cb.cb_rate) == -1) {
4333 + (void) fprintf(stderr,
4334 + gettext("invalid value for rate\n"));
4335 + usage(B_FALSE);
4336 + }
4337 + break;
4338 + case '?':
4339 + (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4340 + optopt);
4341 + usage(B_FALSE);
4342 + }
4343 + }
4344 +
4345 + argc -= optind;
4346 + argv += optind;
4347 +
4348 + if (argc < 1) {
4349 + (void) fprintf(stderr, gettext("missing pool name argument\n"));
4350 + usage(B_FALSE);
4351 + }
4352 +
4353 + return (for_each_pool(argc, argv, B_TRUE, NULL, trim_callback, &cb));
4354 +}
4355 +
4036 4356 typedef struct status_cbdata {
4037 4357 int cb_count;
4038 4358 boolean_t cb_allpools;
4039 4359 boolean_t cb_verbose;
4040 4360 boolean_t cb_explain;
4041 4361 boolean_t cb_first;
4042 4362 boolean_t cb_dedup_stats;
4043 4363 } status_cbdata_t;
4044 4364
4045 4365 /*
4046 4366 * Print out detailed scrub status.
4047 4367 */
4048 -static void
4368 +void
4049 4369 print_scan_status(pool_scan_stat_t *ps)
4050 4370 {
4051 4371 time_t start, end, pause;
4052 4372 uint64_t elapsed, mins_left, hours_left;
4053 - uint64_t pass_exam, examined, total;
4054 - uint_t rate;
4373 + uint64_t examined, total;
4374 + uint64_t rate, proc_rate;
4055 4375 double fraction_done;
4056 - char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4376 + char processed_buf[7], examined_buf[7], total_buf[7], rate_buf[7],
4377 + issued_buf[7];
4057 4378
4058 4379 (void) printf(gettext(" scan: "));
4059 4380
4060 4381 /* If there's never been a scan, there's not much to say. */
4061 4382 if (ps == NULL || ps->pss_func == POOL_SCAN_NONE ||
4062 4383 ps->pss_func >= POOL_SCAN_FUNCS) {
4063 4384 (void) printf(gettext("none requested\n"));
4064 4385 return;
4065 4386 }
4066 4387
4067 4388 start = ps->pss_start_time;
4068 4389 end = ps->pss_end_time;
4069 4390 pause = ps->pss_pass_scrub_pause;
4070 4391 zfs_nicenum(ps->pss_processed, processed_buf, sizeof (processed_buf));
4071 4392
4072 4393 assert(ps->pss_func == POOL_SCAN_SCRUB ||
4073 - ps->pss_func == POOL_SCAN_RESILVER);
4394 + ps->pss_func == POOL_SCAN_RESILVER ||
4395 + ps->pss_func == POOL_SCAN_MOS ||
4396 + ps->pss_func == POOL_SCAN_META);
4074 4397 /*
4075 4398 * Scan is finished or canceled.
4076 4399 */
4077 4400 if (ps->pss_state == DSS_FINISHED) {
4078 4401 uint64_t minutes_taken = (end - start) / 60;
4079 4402 char *fmt = NULL;
4080 4403
4081 4404 if (ps->pss_func == POOL_SCAN_SCRUB) {
4082 4405 fmt = gettext("scrub repaired %s in %lluh%um with "
4083 4406 "%llu errors on %s");
4407 + } else if (ps->pss_func == POOL_SCAN_MOS) {
4408 + fmt = gettext("MOS scrub repaired %s in %lluh%um with "
4409 + "%llu errors on %s");
4410 + } else if (ps->pss_func == POOL_SCAN_META) {
4411 + fmt = gettext("meta scrub repaired %s in %lluh%um with "
4412 + "%llu errors on %s");
4084 4413 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4085 4414 fmt = gettext("resilvered %s in %lluh%um with "
4086 4415 "%llu errors on %s");
4087 4416 }
4088 4417 /* LINTED */
4089 4418 (void) printf(fmt, processed_buf,
4090 4419 (u_longlong_t)(minutes_taken / 60),
4091 4420 (uint_t)(minutes_taken % 60),
4092 4421 (u_longlong_t)ps->pss_errors,
4093 4422 ctime((time_t *)&end));
4094 4423 return;
4095 4424 } else if (ps->pss_state == DSS_CANCELED) {
4096 4425 if (ps->pss_func == POOL_SCAN_SCRUB) {
4097 4426 (void) printf(gettext("scrub canceled on %s"),
4098 4427 ctime(&end));
4428 + } else if (ps->pss_func == POOL_SCAN_MOS) {
4429 + (void) printf(gettext("MOS scrub canceled on %s"),
4430 + ctime(&end));
4431 + } else if (ps->pss_func == POOL_SCAN_META) {
4432 + (void) printf(gettext("meta scrub canceled on %s"),
4433 + ctime(&end));
4099 4434 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4100 4435 (void) printf(gettext("resilver canceled on %s"),
4101 4436 ctime(&end));
4102 4437 }
4103 4438 return;
4104 4439 }
4105 4440
4106 - assert(ps->pss_state == DSS_SCANNING);
4441 + assert(ps->pss_state == DSS_SCANNING || ps->pss_state == DSS_FINISHING);
4107 4442
4108 4443 /*
4109 4444 * Scan is in progress.
4110 4445 */
4111 4446 if (ps->pss_func == POOL_SCAN_SCRUB) {
4112 4447 if (pause == 0) {
4113 4448 (void) printf(gettext("scrub in progress since %s"),
4114 4449 ctime(&start));
4115 4450 } else {
4116 4451 char buf[32];
4117 4452 struct tm *p = localtime(&pause);
4118 4453 (void) strftime(buf, sizeof (buf), "%a %b %e %T %Y", p);
4119 4454 (void) printf(gettext("scrub paused since %s\n"), buf);
4120 4455 (void) printf(gettext("\tscrub started on %s"),
4121 4456 ctime(&start));
4122 4457 }
4458 + } else if (ps->pss_func == POOL_SCAN_MOS) {
4459 + (void) printf(gettext("MOS scrub in progress since %s"),
4460 + ctime(&start));
4461 + } else if (ps->pss_func == POOL_SCAN_META) {
4462 + (void) printf(gettext("meta scrub in progress since %s"),
4463 + ctime(&start));
4123 4464 } else if (ps->pss_func == POOL_SCAN_RESILVER) {
4124 4465 (void) printf(gettext("resilver in progress since %s"),
4125 4466 ctime(&start));
4126 4467 }
4127 4468
4128 - examined = ps->pss_examined ? ps->pss_examined : 1;
4469 + examined = ps->pss_examined;
4129 4470 total = ps->pss_to_examine;
4130 - fraction_done = (double)examined / total;
4471 + fraction_done = (double)ps->pss_issued / total;
4131 4472
4132 4473 /* elapsed time for this pass */
4133 - elapsed = time(NULL) - ps->pss_pass_start;
4134 - elapsed -= ps->pss_pass_scrub_spent_paused;
4135 - elapsed = elapsed ? elapsed : 1;
4136 - pass_exam = ps->pss_pass_exam ? ps->pss_pass_exam : 1;
4137 - rate = pass_exam / elapsed;
4138 - rate = rate ? rate : 1;
4139 - mins_left = ((total - examined) / rate) / 60;
4474 + elapsed = MAX(time(NULL) - ps->pss_start_time -
4475 + ps->pss_pass_scrub_spent_paused, 1);
4476 + if (ps->pss_func == POOL_SCAN_RESILVER) {
4477 + rate = MAX(((ps->pss_issued + ps->pss_processed) / 2) /
4478 + elapsed, 1);
4479 + } else {
4480 + rate = MAX(ps->pss_issued / elapsed, 1);
4481 + }
4482 + proc_rate = MAX(ps->pss_processed / elapsed, 1);
4483 + if (ps->pss_func == POOL_SCAN_RESILVER)
4484 + mins_left = ((total - ps->pss_issued) / proc_rate) / 60;
4485 + else
4486 + mins_left = ((total - ps->pss_issued) / rate) / 60;
4140 4487 hours_left = mins_left / 60;
4141 4488
4142 4489 zfs_nicenum(examined, examined_buf, sizeof (examined_buf));
4490 + zfs_nicenum(ps->pss_issued, issued_buf, sizeof (issued_buf));
4143 4491 zfs_nicenum(total, total_buf, sizeof (total_buf));
4492 + zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4144 4493
4494 + if (pause == 0) {
4495 + (void) printf(gettext(" %s scanned, %s verified "
4496 + "out of %s at %s/s, %.2f%% done\n"), examined_buf,
4497 + issued_buf, total_buf, rate_buf, 100 * fraction_done);
4498 + }
4499 +
4500 + if (ps->pss_func == POOL_SCAN_RESILVER) {
4501 + char proc_rate_buf[7];
4502 + zfs_nicenum(proc_rate, proc_rate_buf,
4503 + sizeof (proc_rate_buf));
4504 + (void) printf(gettext(" %s resilvered at %s/s"),
4505 + processed_buf, proc_rate_buf);
4506 + } else if (ps->pss_func == POOL_SCAN_SCRUB ||
4507 + ps->pss_func == POOL_SCAN_MOS ||
4508 + ps->pss_func == POOL_SCAN_META) {
4509 + (void) printf(gettext(" %s repaired"),
4510 + processed_buf);
4511 + }
4512 +
4145 4513 /*
4146 4514 * do not print estimated time if hours_left is more than 30 days
4147 4515 * or we have a paused scrub
4148 4516 */
4149 4517 if (pause == 0) {
4150 - zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4151 - (void) printf(gettext("\t%s scanned out of %s at %s/s"),
4152 - examined_buf, total_buf, rate_buf);
4153 4518 if (hours_left < (30 * 24)) {
4154 4519 (void) printf(gettext(", %lluh%um to go\n"),
4155 4520 (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4156 4521 } else {
4157 4522 (void) printf(gettext(
4158 4523 ", (scan is slow, no estimated time)\n"));
4159 4524 }
4160 4525 } else {
4161 - (void) printf(gettext("\t%s scanned out of %s\n"),
4162 - examined_buf, total_buf);
4526 + (void) printf(gettext("\t%s scanned, %s verified out of %s\n"),
4527 + examined_buf, issued_buf, total_buf);
4163 4528 }
4164 -
4165 - if (ps->pss_func == POOL_SCAN_RESILVER) {
4166 - (void) printf(gettext(" %s resilvered, %.2f%% done\n"),
4167 - processed_buf, 100 * fraction_done);
4168 - } else if (ps->pss_func == POOL_SCAN_SCRUB) {
4169 - (void) printf(gettext(" %s repaired, %.2f%% done\n"),
4170 - processed_buf, 100 * fraction_done);
4171 - }
4172 4529 }
4173 4530
4174 -/*
4175 - * Print out detailed removal status.
4176 - */
4177 4531 static void
4178 -print_removal_status(zpool_handle_t *zhp, pool_removal_stat_t *prs)
4532 +print_trim_status(uint64_t trim_prog, uint64_t total_size, uint64_t rate,
4533 + uint64_t start_time_u64, uint64_t end_time_u64)
4179 4534 {
4180 - char copied_buf[7], examined_buf[7], total_buf[7], rate_buf[7];
4181 - time_t start, end;
4182 - nvlist_t *config, *nvroot;
4183 - nvlist_t **child;
4184 - uint_t children;
4185 - char *vdev_name;
4535 + time_t start_time = start_time_u64, end_time = end_time_u64;
4536 + char *buf;
4186 4537
4187 - if (prs == NULL || prs->prs_state == DSS_NONE)
4188 - return;
4189 -
4190 - /*
4191 - * Determine name of vdev.
4192 - */
4193 - config = zpool_get_config(zhp, NULL);
4194 - nvroot = fnvlist_lookup_nvlist(config,
4195 - ZPOOL_CONFIG_VDEV_TREE);
4196 - verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4197 - &child, &children) == 0);
4198 - assert(prs->prs_removing_vdev < children);
4199 - vdev_name = zpool_vdev_name(g_zfs, zhp,
4200 - child[prs->prs_removing_vdev], B_TRUE);
4201 -
4202 - (void) printf(gettext("remove: "));
4203 -
4204 - start = prs->prs_start_time;
4205 - end = prs->prs_end_time;
4206 - zfs_nicenum(prs->prs_copied, copied_buf, sizeof (copied_buf));
4207 -
4208 - /*
4209 - * Removal is finished or canceled.
4210 - */
4211 - if (prs->prs_state == DSS_FINISHED) {
4212 - uint64_t minutes_taken = (end - start) / 60;
4213 -
4214 - (void) printf(gettext("Removal of vdev %llu copied %s "
4215 - "in %lluh%um, completed on %s"),
4216 - (longlong_t)prs->prs_removing_vdev,
4217 - copied_buf,
4218 - (u_longlong_t)(minutes_taken / 60),
4219 - (uint_t)(minutes_taken % 60),
4220 - ctime((time_t *)&end));
4221 - } else if (prs->prs_state == DSS_CANCELED) {
4222 - (void) printf(gettext("Removal of %s canceled on %s"),
4223 - vdev_name, ctime(&end));
4538 + assert(trim_prog <= total_size);
4539 + if (trim_prog != 0 && trim_prog != total_size) {
4540 + buf = ctime(&start_time);
4541 + buf[strlen(buf) - 1] = '\0'; /* strip trailing newline */
4542 + if (rate != 0) {
4543 + char rate_str[32];
4544 + zfs_nicenum(rate, rate_str, sizeof (rate_str));
4545 + (void) printf(" trim: %.02f%%\tstarted: %s\t"
4546 + "(rate: %s/s)\n", (((double)trim_prog) /
4547 + total_size) * 100, buf, rate_str);
4548 + } else {
4549 + (void) printf(" trim: %.02f%%\tstarted: %s\t"
4550 + "(rate: max)\n", (((double)trim_prog) /
4551 + total_size) * 100, buf);
4552 + }
4224 4553 } else {
4225 - uint64_t copied, total, elapsed, mins_left, hours_left;
4226 - double fraction_done;
4227 - uint_t rate;
4554 + if (start_time != 0) {
4555 + /*
4556 + * Non-zero start time means we were run at some point
4557 + * in the past.
4558 + */
4559 + if (end_time != 0) {
4560 + /* Non-zero end time means we completed */
4561 + time_t diff = end_time - start_time;
4562 + int hrs, mins;
4228 4563
4229 - assert(prs->prs_state == DSS_SCANNING);
4230 -
4231 - /*
4232 - * Removal is in progress.
4233 - */
4234 - (void) printf(gettext(
4235 - "Evacuation of %s in progress since %s"),
4236 - vdev_name, ctime(&start));
4237 -
4238 - copied = prs->prs_copied > 0 ? prs->prs_copied : 1;
4239 - total = prs->prs_to_copy;
4240 - fraction_done = (double)copied / total;
4241 -
4242 - /* elapsed time for this pass */
4243 - elapsed = time(NULL) - prs->prs_start_time;
4244 - elapsed = elapsed > 0 ? elapsed : 1;
4245 - rate = copied / elapsed;
4246 - rate = rate > 0 ? rate : 1;
4247 - mins_left = ((total - copied) / rate) / 60;
4248 - hours_left = mins_left / 60;
4249 -
4250 - zfs_nicenum(copied, examined_buf, sizeof (examined_buf));
4251 - zfs_nicenum(total, total_buf, sizeof (total_buf));
4252 - zfs_nicenum(rate, rate_buf, sizeof (rate_buf));
4253 -
4254 - /*
4255 - * do not print estimated time if hours_left is more than
4256 - * 30 days
4257 - */
4258 - (void) printf(gettext(" %s copied out of %s at %s/s, "
4259 - "%.2f%% done"),
4260 - examined_buf, total_buf, rate_buf, 100 * fraction_done);
4261 - if (hours_left < (30 * 24)) {
4262 - (void) printf(gettext(", %lluh%um to go\n"),
4263 - (u_longlong_t)hours_left, (uint_t)(mins_left % 60));
4564 + buf = ctime(&end_time);
4565 + buf[strlen(buf) - 1] = '\0';
4566 + hrs = diff / 3600;
4567 + mins = (diff % 3600) / 60;
4568 + (void) printf(gettext(" trim: completed on %s "
4569 + "(after %dh%dm)\n"), buf, hrs, mins);
4570 + } else {
4571 + buf = ctime(&start_time);
4572 + buf[strlen(buf) - 1] = '\0';
4573 + /* Zero end time means we were interrupted */
4574 + (void) printf(gettext(" trim: interrupted\t"
4575 + "(started %s)\n"), buf);
4576 + }
4264 4577 } else {
4265 - (void) printf(gettext(
4266 - ", (copy is slow, no estimated time)\n"));
4578 + /* trim was never run */
4579 + (void) printf(gettext(" trim: none requested\n"));
4267 4580 }
4268 4581 }
4269 -
4270 - if (prs->prs_mapping_memory > 0) {
4271 - char mem_buf[7];
4272 - zfs_nicenum(prs->prs_mapping_memory, mem_buf, sizeof (mem_buf));
4273 - (void) printf(gettext(" %s memory used for "
4274 - "removed device mappings\n"),
4275 - mem_buf);
4276 - }
4277 4582 }
4278 4583
4279 4584 static void
4280 4585 print_error_log(zpool_handle_t *zhp)
4281 4586 {
4282 4587 nvlist_t *nverrlist = NULL;
4283 4588 nvpair_t *elem;
4284 4589 char *pathname;
4285 4590 size_t len = MAXPATHLEN * 2;
4286 4591
4287 4592 if (zpool_get_errlog(zhp, &nverrlist) != 0) {
4288 4593 (void) printf("errors: List of errors unavailable "
4289 4594 "(insufficient privileges)\n");
4290 4595 return;
4291 4596 }
4292 4597
4293 4598 (void) printf("errors: Permanent errors have been "
4294 4599 "detected in the following files:\n\n");
4295 4600
4296 4601 pathname = safe_malloc(len);
4297 4602 elem = NULL;
4298 4603 while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) {
4299 4604 nvlist_t *nv;
4300 4605 uint64_t dsobj, obj;
4301 4606
4302 4607 verify(nvpair_value_nvlist(elem, &nv) == 0);
4303 4608 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET,
4304 4609 &dsobj) == 0);
4305 4610 verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT,
4306 4611 &obj) == 0);
4307 4612 zpool_obj_to_path(zhp, dsobj, obj, pathname, len);
4308 4613 (void) printf("%7s %s\n", "", pathname);
4309 4614 }
4310 4615 free(pathname);
4311 4616 nvlist_free(nverrlist);
4312 4617 }
4313 4618
4314 4619 static void
4315 4620 print_spares(zpool_handle_t *zhp, nvlist_t **spares, uint_t nspares,
4316 4621 int namewidth)
4317 4622 {
4318 4623 uint_t i;
4319 4624 char *name;
4320 4625
4321 4626 if (nspares == 0)
4322 4627 return;
4323 4628
4324 4629 (void) printf(gettext("\tspares\n"));
4325 4630
4326 4631 for (i = 0; i < nspares; i++) {
4327 4632 name = zpool_vdev_name(g_zfs, zhp, spares[i], B_FALSE);
4328 4633 print_status_config(zhp, name, spares[i],
4329 4634 namewidth, 2, B_TRUE);
4330 4635 free(name);
4331 4636 }
4332 4637 }
4333 4638
4334 4639 static void
4335 4640 print_l2cache(zpool_handle_t *zhp, nvlist_t **l2cache, uint_t nl2cache,
4336 4641 int namewidth)
4337 4642 {
4338 4643 uint_t i;
4339 4644 char *name;
4340 4645
4341 4646 if (nl2cache == 0)
4342 4647 return;
4343 4648
4344 4649 (void) printf(gettext("\tcache\n"));
4345 4650
4346 4651 for (i = 0; i < nl2cache; i++) {
4347 4652 name = zpool_vdev_name(g_zfs, zhp, l2cache[i], B_FALSE);
4348 4653 print_status_config(zhp, name, l2cache[i],
4349 4654 namewidth, 2, B_FALSE);
4350 4655 free(name);
4351 4656 }
4352 4657 }
4353 4658
4354 4659 static void
4355 4660 print_dedup_stats(nvlist_t *config)
4356 4661 {
4357 4662 ddt_histogram_t *ddh;
4358 4663 ddt_stat_t *dds;
4359 4664 ddt_object_t *ddo;
4360 4665 uint_t c;
4361 4666
4362 4667 /*
4363 4668 * If the pool was faulted then we may not have been able to
4364 4669 * obtain the config. Otherwise, if we have anything in the dedup
4365 4670 * table continue processing the stats.
4366 4671 */
4367 4672 if (nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_OBJ_STATS,
4368 4673 (uint64_t **)&ddo, &c) != 0)
4369 4674 return;
4370 4675
4371 4676 (void) printf("\n");
4372 4677 (void) printf(gettext(" dedup: "));
4373 4678 if (ddo->ddo_count == 0) {
4374 4679 (void) printf(gettext("no DDT entries\n"));
4375 4680 return;
4376 4681 }
4377 4682
4378 4683 (void) printf("DDT entries %llu, size %llu on disk, %llu in core\n",
4379 4684 (u_longlong_t)ddo->ddo_count,
4380 4685 (u_longlong_t)ddo->ddo_dspace,
|
↓ open down ↓ |
94 lines elided |
↑ open up ↑ |
4381 4686 (u_longlong_t)ddo->ddo_mspace);
4382 4687
4383 4688 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_STATS,
4384 4689 (uint64_t **)&dds, &c) == 0);
4385 4690 verify(nvlist_lookup_uint64_array(config, ZPOOL_CONFIG_DDT_HISTOGRAM,
4386 4691 (uint64_t **)&ddh, &c) == 0);
4387 4692 zpool_dump_ddt(dds, ddh);
4388 4693 }
4389 4694
4390 4695 /*
4696 + * Calculates the total space available on log devices on the pool.
4697 + * For whatever reason, this is not counted in the root vdev's space stats.
4698 + */
4699 +static uint64_t
4700 +zpool_slog_space(nvlist_t *nvroot)
4701 +{
4702 + nvlist_t **newchild;
4703 + uint_t c, children;
4704 + uint64_t space = 0;
4705 +
4706 + verify(nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
4707 + &newchild, &children) == 0);
4708 +
4709 + for (c = 0; c < children; c++) {
4710 + uint64_t islog = B_FALSE;
4711 + vdev_stat_t *vs;
4712 + uint_t n;
4713 + uint_t n_subchildren = 1;
4714 + nvlist_t **subchild;
4715 +
4716 + (void) nvlist_lookup_uint64(newchild[c], ZPOOL_CONFIG_IS_LOG,
4717 + &islog);
4718 + if (!islog)
4719 + continue;
4720 + verify(nvlist_lookup_uint64_array(newchild[c],
4721 + ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &n) == 0);
4722 +
4723 + /* vdev can be non-leaf, so multiply by number of children */
4724 + (void) nvlist_lookup_nvlist_array(newchild[c],
4725 + ZPOOL_CONFIG_CHILDREN, &subchild, &n_subchildren);
4726 + space += n_subchildren * vs->vs_space;
4727 + }
4728 +
4729 + return (space);
4730 +}
4731 +
4732 +/*
4391 4733 * Display a summary of pool status. Displays a summary such as:
4392 4734 *
4393 4735 * pool: tank
4394 4736 * status: DEGRADED
4395 4737 * reason: One or more devices ...
4396 4738 * see: http://illumos.org/msg/ZFS-xxxx-01
4397 4739 * config:
4398 4740 * mirror DEGRADED
4399 4741 * c1t0d0 OK
4400 4742 * c2t0d0 UNAVAIL
4401 4743 *
4402 4744 * When given the '-v' option, we print out the complete config. If the '-e'
4403 4745 * option is specified, then we print out error rate information as well.
4404 4746 */
4405 4747 int
4406 4748 status_callback(zpool_handle_t *zhp, void *data)
4407 4749 {
4408 4750 status_cbdata_t *cbp = data;
4409 4751 nvlist_t *config, *nvroot;
4410 4752 char *msgid;
4411 4753 int reason;
4412 4754 const char *health;
4413 4755 uint_t c;
4414 4756 vdev_stat_t *vs;
4415 4757
4416 4758 config = zpool_get_config(zhp, NULL);
4417 4759 reason = zpool_get_status(zhp, &msgid);
4418 4760
4419 4761 cbp->cb_count++;
4420 4762
4421 4763 /*
4422 4764 * If we were given 'zpool status -x', only report those pools with
4423 4765 * problems.
4424 4766 */
4425 4767 if (cbp->cb_explain &&
4426 4768 (reason == ZPOOL_STATUS_OK ||
4427 4769 reason == ZPOOL_STATUS_VERSION_OLDER ||
4428 4770 reason == ZPOOL_STATUS_FEAT_DISABLED)) {
4429 4771 if (!cbp->cb_allpools) {
4430 4772 (void) printf(gettext("pool '%s' is healthy\n"),
4431 4773 zpool_get_name(zhp));
4432 4774 if (cbp->cb_first)
|
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
4433 4775 cbp->cb_first = B_FALSE;
4434 4776 }
4435 4777 return (0);
4436 4778 }
4437 4779
4438 4780 if (cbp->cb_first)
4439 4781 cbp->cb_first = B_FALSE;
4440 4782 else
4441 4783 (void) printf("\n");
4442 4784
4443 - nvroot = fnvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE);
4785 + verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
4786 + &nvroot) == 0);
4444 4787 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
4445 4788 (uint64_t **)&vs, &c) == 0);
4446 4789 health = zpool_state_to_name(vs->vs_state, vs->vs_aux);
4447 4790
4448 4791 (void) printf(gettext(" pool: %s\n"), zpool_get_name(zhp));
4449 4792 (void) printf(gettext(" state: %s\n"), health);
4450 4793
4451 4794 switch (reason) {
4452 4795 case ZPOOL_STATUS_MISSING_DEV_R:
4453 4796 (void) printf(gettext("status: One or more devices could not "
4454 4797 "be opened. Sufficient replicas exist for\n\tthe pool to "
4455 4798 "continue functioning in a degraded state.\n"));
4456 4799 (void) printf(gettext("action: Attach the missing device and "
4457 4800 "online it using 'zpool online'.\n"));
4458 4801 break;
4459 4802
4460 4803 case ZPOOL_STATUS_MISSING_DEV_NR:
4461 4804 (void) printf(gettext("status: One or more devices could not "
4462 4805 "be opened. There are insufficient\n\treplicas for the "
4463 4806 "pool to continue functioning.\n"));
4464 4807 (void) printf(gettext("action: Attach the missing device and "
4465 4808 "online it using 'zpool online'.\n"));
4466 4809 break;
4467 4810
4468 4811 case ZPOOL_STATUS_CORRUPT_LABEL_R:
4469 4812 (void) printf(gettext("status: One or more devices could not "
4470 4813 "be used because the label is missing or\n\tinvalid. "
4471 4814 "Sufficient replicas exist for the pool to continue\n\t"
4472 4815 "functioning in a degraded state.\n"));
4473 4816 (void) printf(gettext("action: Replace the device using "
4474 4817 "'zpool replace'.\n"));
4475 4818 break;
4476 4819
4477 4820 case ZPOOL_STATUS_CORRUPT_LABEL_NR:
4478 4821 (void) printf(gettext("status: One or more devices could not "
4479 4822 "be used because the label is missing \n\tor invalid. "
4480 4823 "There are insufficient replicas for the pool to "
4481 4824 "continue\n\tfunctioning.\n"));
4482 4825 zpool_explain_recover(zpool_get_handle(zhp),
4483 4826 zpool_get_name(zhp), reason, config);
4484 4827 break;
4485 4828
4486 4829 case ZPOOL_STATUS_FAILING_DEV:
4487 4830 (void) printf(gettext("status: One or more devices has "
4488 4831 "experienced an unrecoverable error. An\n\tattempt was "
4489 4832 "made to correct the error. Applications are "
4490 4833 "unaffected.\n"));
4491 4834 (void) printf(gettext("action: Determine if the device needs "
4492 4835 "to be replaced, and clear the errors\n\tusing "
4493 4836 "'zpool clear' or replace the device with 'zpool "
4494 4837 "replace'.\n"));
4495 4838 break;
4496 4839
4497 4840 case ZPOOL_STATUS_OFFLINE_DEV:
4498 4841 (void) printf(gettext("status: One or more devices has "
4499 4842 "been taken offline by the administrator.\n\tSufficient "
4500 4843 "replicas exist for the pool to continue functioning in "
4501 4844 "a\n\tdegraded state.\n"));
4502 4845 (void) printf(gettext("action: Online the device using "
4503 4846 "'zpool online' or replace the device with\n\t'zpool "
4504 4847 "replace'.\n"));
4505 4848 break;
4506 4849
4507 4850 case ZPOOL_STATUS_REMOVED_DEV:
4508 4851 (void) printf(gettext("status: One or more devices has "
4509 4852 "been removed by the administrator.\n\tSufficient "
4510 4853 "replicas exist for the pool to continue functioning in "
4511 4854 "a\n\tdegraded state.\n"));
4512 4855 (void) printf(gettext("action: Online the device using "
4513 4856 "'zpool online' or replace the device with\n\t'zpool "
4514 4857 "replace'.\n"));
4515 4858 break;
4516 4859
4517 4860 case ZPOOL_STATUS_RESILVERING:
4518 4861 (void) printf(gettext("status: One or more devices is "
4519 4862 "currently being resilvered. The pool will\n\tcontinue "
4520 4863 "to function, possibly in a degraded state.\n"));
4521 4864 (void) printf(gettext("action: Wait for the resilver to "
4522 4865 "complete.\n"));
4523 4866 break;
4524 4867
4525 4868 case ZPOOL_STATUS_CORRUPT_DATA:
4526 4869 (void) printf(gettext("status: One or more devices has "
4527 4870 "experienced an error resulting in data\n\tcorruption. "
4528 4871 "Applications may be affected.\n"));
4529 4872 (void) printf(gettext("action: Restore the file in question "
4530 4873 "if possible. Otherwise restore the\n\tentire pool from "
4531 4874 "backup.\n"));
4532 4875 break;
4533 4876
4534 4877 case ZPOOL_STATUS_CORRUPT_POOL:
4535 4878 (void) printf(gettext("status: The pool metadata is corrupted "
4536 4879 "and the pool cannot be opened.\n"));
4537 4880 zpool_explain_recover(zpool_get_handle(zhp),
4538 4881 zpool_get_name(zhp), reason, config);
4539 4882 break;
4540 4883
4541 4884 case ZPOOL_STATUS_VERSION_OLDER:
4542 4885 (void) printf(gettext("status: The pool is formatted using a "
4543 4886 "legacy on-disk format. The pool can\n\tstill be used, "
4544 4887 "but some features are unavailable.\n"));
4545 4888 (void) printf(gettext("action: Upgrade the pool using 'zpool "
4546 4889 "upgrade'. Once this is done, the\n\tpool will no longer "
4547 4890 "be accessible on software that does not support feature\n"
4548 4891 "\tflags.\n"));
4549 4892 break;
4550 4893
4551 4894 case ZPOOL_STATUS_VERSION_NEWER:
4552 4895 (void) printf(gettext("status: The pool has been upgraded to a "
4553 4896 "newer, incompatible on-disk version.\n\tThe pool cannot "
4554 4897 "be accessed on this system.\n"));
4555 4898 (void) printf(gettext("action: Access the pool from a system "
4556 4899 "running more recent software, or\n\trestore the pool from "
4557 4900 "backup.\n"));
4558 4901 break;
4559 4902
4560 4903 case ZPOOL_STATUS_FEAT_DISABLED:
4561 4904 (void) printf(gettext("status: Some supported features are not "
4562 4905 "enabled on the pool. The pool can\n\tstill be used, but "
4563 4906 "some features are unavailable.\n"));
4564 4907 (void) printf(gettext("action: Enable all features using "
4565 4908 "'zpool upgrade'. Once this is done,\n\tthe pool may no "
4566 4909 "longer be accessible by software that does not support\n\t"
4567 4910 "the features. See zpool-features(5) for details.\n"));
4568 4911 break;
4569 4912
4570 4913 case ZPOOL_STATUS_UNSUP_FEAT_READ:
4571 4914 (void) printf(gettext("status: The pool cannot be accessed on "
4572 4915 "this system because it uses the\n\tfollowing feature(s) "
4573 4916 "not supported on this system:\n"));
4574 4917 zpool_print_unsup_feat(config);
4575 4918 (void) printf("\n");
4576 4919 (void) printf(gettext("action: Access the pool from a system "
4577 4920 "that supports the required feature(s),\n\tor restore the "
4578 4921 "pool from backup.\n"));
4579 4922 break;
4580 4923
4581 4924 case ZPOOL_STATUS_UNSUP_FEAT_WRITE:
4582 4925 (void) printf(gettext("status: The pool can only be accessed "
4583 4926 "in read-only mode on this system. It\n\tcannot be "
4584 4927 "accessed in read-write mode because it uses the "
4585 4928 "following\n\tfeature(s) not supported on this system:\n"));
4586 4929 zpool_print_unsup_feat(config);
4587 4930 (void) printf("\n");
4588 4931 (void) printf(gettext("action: The pool cannot be accessed in "
4589 4932 "read-write mode. Import the pool with\n"
4590 4933 "\t\"-o readonly=on\", access the pool from a system that "
4591 4934 "supports the\n\trequired feature(s), or restore the "
4592 4935 "pool from backup.\n"));
4593 4936 break;
4594 4937
4595 4938 case ZPOOL_STATUS_FAULTED_DEV_R:
4596 4939 (void) printf(gettext("status: One or more devices are "
4597 4940 "faulted in response to persistent errors.\n\tSufficient "
4598 4941 "replicas exist for the pool to continue functioning "
4599 4942 "in a\n\tdegraded state.\n"));
4600 4943 (void) printf(gettext("action: Replace the faulted device, "
4601 4944 "or use 'zpool clear' to mark the device\n\trepaired.\n"));
4602 4945 break;
4603 4946
4604 4947 case ZPOOL_STATUS_FAULTED_DEV_NR:
4605 4948 (void) printf(gettext("status: One or more devices are "
4606 4949 "faulted in response to persistent errors. There are "
4607 4950 "insufficient replicas for the pool to\n\tcontinue "
4608 4951 "functioning.\n"));
4609 4952 (void) printf(gettext("action: Destroy and re-create the pool "
4610 4953 "from a backup source. Manually marking the device\n"
4611 4954 "\trepaired using 'zpool clear' may allow some data "
4612 4955 "to be recovered.\n"));
4613 4956 break;
4614 4957
4615 4958 case ZPOOL_STATUS_IO_FAILURE_WAIT:
4616 4959 case ZPOOL_STATUS_IO_FAILURE_CONTINUE:
4617 4960 (void) printf(gettext("status: One or more devices are "
4618 4961 "faulted in response to IO failures.\n"));
4619 4962 (void) printf(gettext("action: Make sure the affected devices "
4620 4963 "are connected, then run 'zpool clear'.\n"));
4621 4964 break;
4622 4965
4623 4966 case ZPOOL_STATUS_BAD_LOG:
4624 4967 (void) printf(gettext("status: An intent log record "
4625 4968 "could not be read.\n"
4626 4969 "\tWaiting for adminstrator intervention to fix the "
4627 4970 "faulted pool.\n"));
4628 4971 (void) printf(gettext("action: Either restore the affected "
4629 4972 "device(s) and run 'zpool online',\n"
4630 4973 "\tor ignore the intent log records by running "
4631 4974 "'zpool clear'.\n"));
4632 4975 break;
4633 4976
4634 4977 default:
4635 4978 /*
4636 4979 * The remaining errors can't actually be generated, yet.
4637 4980 */
4638 4981 assert(reason == ZPOOL_STATUS_OK);
4639 4982 }
4640 4983
|
↓ open down ↓ |
187 lines elided |
↑ open up ↑ |
4641 4984 if (msgid != NULL)
4642 4985 (void) printf(gettext(" see: http://illumos.org/msg/%s\n"),
4643 4986 msgid);
4644 4987
4645 4988 if (config != NULL) {
4646 4989 int namewidth;
4647 4990 uint64_t nerr;
4648 4991 nvlist_t **spares, **l2cache;
4649 4992 uint_t nspares, nl2cache;
4650 4993 pool_scan_stat_t *ps = NULL;
4651 - pool_removal_stat_t *prs = NULL;
4994 + uint64_t trim_prog, trim_rate, trim_start_time, trim_stop_time;
4652 4995
4653 4996 (void) nvlist_lookup_uint64_array(nvroot,
4654 4997 ZPOOL_CONFIG_SCAN_STATS, (uint64_t **)&ps, &c);
4655 4998 print_scan_status(ps);
4656 4999
4657 - (void) nvlist_lookup_uint64_array(nvroot,
4658 - ZPOOL_CONFIG_REMOVAL_STATS, (uint64_t **)&prs, &c);
4659 - print_removal_status(zhp, prs);
5000 + /* Grab trim stats if the pool supports it */
5001 + if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_TRIM_PROG,
5002 + &trim_prog) == 0 &&
5003 + nvlist_lookup_uint64(config, ZPOOL_CONFIG_TRIM_RATE,
5004 + &trim_rate) == 0 &&
5005 + nvlist_lookup_uint64(config, ZPOOL_CONFIG_TRIM_START_TIME,
5006 + &trim_start_time) == 0 &&
5007 + nvlist_lookup_uint64(config, ZPOOL_CONFIG_TRIM_STOP_TIME,
5008 + &trim_stop_time) == 0) {
5009 + /*
5010 + * For whatever reason, root vdev_stats_t don't
5011 + * include log devices.
5012 + */
5013 + print_trim_status(trim_prog, vs->vs_space +
5014 + zpool_slog_space(nvroot), trim_rate,
5015 + trim_start_time, trim_stop_time);
5016 + }
4660 5017
4661 5018 namewidth = max_width(zhp, nvroot, 0, 0);
4662 5019 if (namewidth < 10)
4663 5020 namewidth = 10;
4664 5021
4665 5022 (void) printf(gettext("config:\n\n"));
4666 5023 (void) printf(gettext("\t%-*s %-8s %5s %5s %5s\n"), namewidth,
4667 5024 "NAME", "STATE", "READ", "WRITE", "CKSUM");
4668 5025 print_status_config(zhp, zpool_get_name(zhp), nvroot,
4669 5026 namewidth, 0, B_FALSE);
4670 5027
5028 + if (num_special(nvroot) > 0)
5029 + print_special(zhp, nvroot, namewidth, B_TRUE);
4671 5030 if (num_logs(nvroot) > 0)
4672 5031 print_logs(zhp, nvroot, namewidth, B_TRUE);
4673 5032 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_L2CACHE,
4674 5033 &l2cache, &nl2cache) == 0)
4675 5034 print_l2cache(zhp, l2cache, nl2cache, namewidth);
4676 5035
4677 5036 if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES,
4678 5037 &spares, &nspares) == 0)
4679 5038 print_spares(zhp, spares, nspares, namewidth);
4680 5039
4681 5040 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
4682 5041 &nerr) == 0) {
4683 5042 nvlist_t *nverrlist = NULL;
4684 5043
4685 5044 /*
4686 5045 * If the approximate error count is small, get a
4687 5046 * precise count by fetching the entire log and
4688 5047 * uniquifying the results.
4689 5048 */
4690 5049 if (nerr > 0 && nerr < 100 && !cbp->cb_verbose &&
4691 5050 zpool_get_errlog(zhp, &nverrlist) == 0) {
4692 5051 nvpair_t *elem;
4693 5052
4694 5053 elem = NULL;
4695 5054 nerr = 0;
4696 5055 while ((elem = nvlist_next_nvpair(nverrlist,
4697 5056 elem)) != NULL) {
4698 5057 nerr++;
4699 5058 }
4700 5059 }
4701 5060 nvlist_free(nverrlist);
4702 5061
4703 5062 (void) printf("\n");
4704 5063
4705 5064 if (nerr == 0)
4706 5065 (void) printf(gettext("errors: No known data "
4707 5066 "errors\n"));
4708 5067 else if (!cbp->cb_verbose)
4709 5068 (void) printf(gettext("errors: %llu data "
4710 5069 "errors, use '-v' for a list\n"),
4711 5070 (u_longlong_t)nerr);
4712 5071 else
4713 5072 print_error_log(zhp);
4714 5073 }
4715 5074
4716 5075 if (cbp->cb_dedup_stats)
4717 5076 print_dedup_stats(config);
4718 5077 } else {
4719 5078 (void) printf(gettext("config: The configuration cannot be "
4720 5079 "determined.\n"));
4721 5080 }
4722 5081
4723 5082 return (0);
4724 5083 }
4725 5084
4726 5085 /*
4727 5086 * zpool status [-vx] [-T d|u] [pool] ... [interval [count]]
4728 5087 *
4729 5088 * -v Display complete error logs
4730 5089 * -x Display only pools with potential problems
4731 5090 * -D Display dedup status (undocumented)
4732 5091 * -T Display a timestamp in date(1) or Unix format
4733 5092 *
4734 5093 * Describes the health status of all pools or some subset.
4735 5094 */
4736 5095 int
4737 5096 zpool_do_status(int argc, char **argv)
4738 5097 {
4739 5098 int c;
4740 5099 int ret;
4741 5100 unsigned long interval = 0, count = 0;
4742 5101 status_cbdata_t cb = { 0 };
4743 5102
4744 5103 /* check options */
4745 5104 while ((c = getopt(argc, argv, "vxDT:")) != -1) {
4746 5105 switch (c) {
4747 5106 case 'v':
4748 5107 cb.cb_verbose = B_TRUE;
4749 5108 break;
4750 5109 case 'x':
4751 5110 cb.cb_explain = B_TRUE;
4752 5111 break;
4753 5112 case 'D':
4754 5113 cb.cb_dedup_stats = B_TRUE;
4755 5114 break;
4756 5115 case 'T':
4757 5116 get_timestamp_arg(*optarg);
4758 5117 break;
4759 5118 case '?':
4760 5119 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
4761 5120 optopt);
4762 5121 usage(B_FALSE);
4763 5122 }
4764 5123 }
4765 5124
4766 5125 argc -= optind;
4767 5126 argv += optind;
4768 5127
4769 5128 get_interval_count(&argc, argv, &interval, &count);
4770 5129
4771 5130 if (argc == 0)
4772 5131 cb.cb_allpools = B_TRUE;
4773 5132
4774 5133 cb.cb_first = B_TRUE;
4775 5134
4776 5135 for (;;) {
4777 5136 if (timestamp_fmt != NODATE)
4778 5137 print_timestamp(timestamp_fmt);
4779 5138
4780 5139 ret = for_each_pool(argc, argv, B_TRUE, NULL,
4781 5140 status_callback, &cb);
4782 5141
4783 5142 if (argc == 0 && cb.cb_count == 0)
4784 5143 (void) printf(gettext("no pools available\n"));
4785 5144 else if (cb.cb_explain && cb.cb_first && cb.cb_allpools)
4786 5145 (void) printf(gettext("all pools are healthy\n"));
4787 5146
4788 5147 if (ret != 0)
4789 5148 return (ret);
4790 5149
4791 5150 if (interval == 0)
4792 5151 break;
4793 5152
4794 5153 if (count != 0 && --count == 0)
4795 5154 break;
4796 5155
4797 5156 (void) sleep(interval);
4798 5157 }
4799 5158
4800 5159 return (0);
4801 5160 }
4802 5161
4803 5162 typedef struct upgrade_cbdata {
4804 5163 int cb_first;
4805 5164 int cb_argc;
4806 5165 uint64_t cb_version;
4807 5166 char **cb_argv;
4808 5167 } upgrade_cbdata_t;
4809 5168
4810 5169 static int
4811 5170 upgrade_version(zpool_handle_t *zhp, uint64_t version)
4812 5171 {
4813 5172 int ret;
4814 5173 nvlist_t *config;
4815 5174 uint64_t oldversion;
4816 5175
4817 5176 config = zpool_get_config(zhp, NULL);
4818 5177 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4819 5178 &oldversion) == 0);
4820 5179
4821 5180 assert(SPA_VERSION_IS_SUPPORTED(oldversion));
4822 5181 assert(oldversion < version);
4823 5182
4824 5183 ret = zpool_upgrade(zhp, version);
4825 5184 if (ret != 0)
4826 5185 return (ret);
4827 5186
4828 5187 if (version >= SPA_VERSION_FEATURES) {
4829 5188 (void) printf(gettext("Successfully upgraded "
4830 5189 "'%s' from version %llu to feature flags.\n"),
4831 5190 zpool_get_name(zhp), oldversion);
4832 5191 } else {
4833 5192 (void) printf(gettext("Successfully upgraded "
4834 5193 "'%s' from version %llu to version %llu.\n"),
4835 5194 zpool_get_name(zhp), oldversion, version);
4836 5195 }
4837 5196
4838 5197 return (0);
4839 5198 }
|
↓ open down ↓ |
159 lines elided |
↑ open up ↑ |
4840 5199
4841 5200 static int
4842 5201 upgrade_enable_all(zpool_handle_t *zhp, int *countp)
4843 5202 {
4844 5203 int i, ret, count;
4845 5204 boolean_t firstff = B_TRUE;
4846 5205 nvlist_t *enabled = zpool_get_features(zhp);
4847 5206
4848 5207 count = 0;
4849 5208 for (i = 0; i < SPA_FEATURES; i++) {
4850 - const char *fname = spa_feature_table[i].fi_uname;
4851 - const char *fguid = spa_feature_table[i].fi_guid;
5209 + zfeature_info_t *finfo = &spa_feature_table[i];
5210 + const char *fname = finfo->fi_uname;
5211 + const char *fguid = finfo->fi_guid;
4852 5212 if (!nvlist_exists(enabled, fguid)) {
4853 5213 char *propname;
5214 +
5215 + /*
5216 + * SPA_FEATURE_WBC can be enabled only
5217 + * if 'special' vdev available
5218 + */
5219 + if (finfo->fi_feature == SPA_FEATURE_WBC)
5220 + continue;
5221 +
4854 5222 verify(-1 != asprintf(&propname, "feature@%s", fname));
4855 5223 ret = zpool_set_prop(zhp, propname,
4856 5224 ZFS_FEATURE_ENABLED);
4857 5225 if (ret != 0) {
4858 5226 free(propname);
4859 5227 return (ret);
4860 5228 }
4861 5229 count++;
4862 5230
4863 5231 if (firstff) {
4864 5232 (void) printf(gettext("Enabled the "
4865 5233 "following features on '%s':\n"),
4866 5234 zpool_get_name(zhp));
4867 5235 firstff = B_FALSE;
4868 5236 }
4869 5237 (void) printf(gettext(" %s\n"), fname);
4870 5238 free(propname);
4871 5239 }
4872 5240 }
4873 5241
4874 5242 if (countp != NULL)
4875 5243 *countp = count;
4876 5244 return (0);
4877 5245 }
4878 5246
4879 5247 static int
4880 5248 upgrade_cb(zpool_handle_t *zhp, void *arg)
4881 5249 {
4882 5250 upgrade_cbdata_t *cbp = arg;
4883 5251 nvlist_t *config;
4884 5252 uint64_t version;
4885 5253 boolean_t printnl = B_FALSE;
4886 5254 int ret;
4887 5255
4888 5256 config = zpool_get_config(zhp, NULL);
4889 5257 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4890 5258 &version) == 0);
4891 5259
4892 5260 assert(SPA_VERSION_IS_SUPPORTED(version));
4893 5261
4894 5262 if (version < cbp->cb_version) {
4895 5263 cbp->cb_first = B_FALSE;
4896 5264 ret = upgrade_version(zhp, cbp->cb_version);
4897 5265 if (ret != 0)
4898 5266 return (ret);
4899 5267 printnl = B_TRUE;
4900 5268
4901 5269 /*
4902 5270 * If they did "zpool upgrade -a", then we could
4903 5271 * be doing ioctls to different pools. We need
4904 5272 * to log this history once to each pool, and bypass
4905 5273 * the normal history logging that happens in main().
4906 5274 */
4907 5275 (void) zpool_log_history(g_zfs, history_str);
4908 5276 log_history = B_FALSE;
4909 5277 }
4910 5278
4911 5279 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
4912 5280 int count;
4913 5281 ret = upgrade_enable_all(zhp, &count);
4914 5282 if (ret != 0)
4915 5283 return (ret);
4916 5284
4917 5285 if (count > 0) {
4918 5286 cbp->cb_first = B_FALSE;
4919 5287 printnl = B_TRUE;
4920 5288 }
4921 5289 }
4922 5290
4923 5291 if (printnl) {
4924 5292 (void) printf(gettext("\n"));
4925 5293 }
4926 5294
4927 5295 return (0);
4928 5296 }
4929 5297
4930 5298 static int
4931 5299 upgrade_list_older_cb(zpool_handle_t *zhp, void *arg)
4932 5300 {
4933 5301 upgrade_cbdata_t *cbp = arg;
4934 5302 nvlist_t *config;
4935 5303 uint64_t version;
4936 5304
4937 5305 config = zpool_get_config(zhp, NULL);
4938 5306 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4939 5307 &version) == 0);
4940 5308
4941 5309 assert(SPA_VERSION_IS_SUPPORTED(version));
4942 5310
4943 5311 if (version < SPA_VERSION_FEATURES) {
4944 5312 if (cbp->cb_first) {
4945 5313 (void) printf(gettext("The following pools are "
4946 5314 "formatted with legacy version numbers and can\n"
4947 5315 "be upgraded to use feature flags. After "
4948 5316 "being upgraded, these pools\nwill no "
4949 5317 "longer be accessible by software that does not "
4950 5318 "support feature\nflags.\n\n"));
4951 5319 (void) printf(gettext("VER POOL\n"));
4952 5320 (void) printf(gettext("--- ------------\n"));
4953 5321 cbp->cb_first = B_FALSE;
4954 5322 }
4955 5323
4956 5324 (void) printf("%2llu %s\n", (u_longlong_t)version,
4957 5325 zpool_get_name(zhp));
4958 5326 }
4959 5327
4960 5328 return (0);
4961 5329 }
4962 5330
4963 5331 static int
4964 5332 upgrade_list_disabled_cb(zpool_handle_t *zhp, void *arg)
4965 5333 {
4966 5334 upgrade_cbdata_t *cbp = arg;
4967 5335 nvlist_t *config;
4968 5336 uint64_t version;
4969 5337
4970 5338 config = zpool_get_config(zhp, NULL);
4971 5339 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
4972 5340 &version) == 0);
4973 5341
4974 5342 if (version >= SPA_VERSION_FEATURES) {
4975 5343 int i;
4976 5344 boolean_t poolfirst = B_TRUE;
4977 5345 nvlist_t *enabled = zpool_get_features(zhp);
4978 5346
4979 5347 for (i = 0; i < SPA_FEATURES; i++) {
4980 5348 const char *fguid = spa_feature_table[i].fi_guid;
4981 5349 const char *fname = spa_feature_table[i].fi_uname;
4982 5350 if (!nvlist_exists(enabled, fguid)) {
4983 5351 if (cbp->cb_first) {
4984 5352 (void) printf(gettext("\nSome "
4985 5353 "supported features are not "
4986 5354 "enabled on the following pools. "
4987 5355 "Once a\nfeature is enabled the "
4988 5356 "pool may become incompatible with "
4989 5357 "software\nthat does not support "
4990 5358 "the feature. See "
4991 5359 "zpool-features(5) for "
4992 5360 "details.\n\n"));
4993 5361 (void) printf(gettext("POOL "
4994 5362 "FEATURE\n"));
4995 5363 (void) printf(gettext("------"
4996 5364 "---------\n"));
4997 5365 cbp->cb_first = B_FALSE;
4998 5366 }
4999 5367
5000 5368 if (poolfirst) {
5001 5369 (void) printf(gettext("%s\n"),
5002 5370 zpool_get_name(zhp));
5003 5371 poolfirst = B_FALSE;
5004 5372 }
5005 5373
5006 5374 (void) printf(gettext(" %s\n"), fname);
5007 5375 }
5008 5376 }
5009 5377 }
5010 5378
5011 5379 return (0);
5012 5380 }
5013 5381
5014 5382 /* ARGSUSED */
5015 5383 static int
5016 5384 upgrade_one(zpool_handle_t *zhp, void *data)
5017 5385 {
5018 5386 boolean_t printnl = B_FALSE;
5019 5387 upgrade_cbdata_t *cbp = data;
5020 5388 uint64_t cur_version;
5021 5389 int ret;
5022 5390
5023 5391 if (strcmp("log", zpool_get_name(zhp)) == 0) {
5024 5392 (void) printf(gettext("'log' is now a reserved word\n"
5025 5393 "Pool 'log' must be renamed using export and import"
5026 5394 " to upgrade.\n"));
5027 5395 return (1);
5028 5396 }
5029 5397
5030 5398 cur_version = zpool_get_prop_int(zhp, ZPOOL_PROP_VERSION, NULL);
5031 5399 if (cur_version > cbp->cb_version) {
5032 5400 (void) printf(gettext("Pool '%s' is already formatted "
5033 5401 "using more current version '%llu'.\n\n"),
5034 5402 zpool_get_name(zhp), cur_version);
5035 5403 return (0);
5036 5404 }
5037 5405
5038 5406 if (cbp->cb_version != SPA_VERSION && cur_version == cbp->cb_version) {
5039 5407 (void) printf(gettext("Pool '%s' is already formatted "
5040 5408 "using version %llu.\n\n"), zpool_get_name(zhp),
5041 5409 cbp->cb_version);
5042 5410 return (0);
5043 5411 }
5044 5412
5045 5413 if (cur_version != cbp->cb_version) {
5046 5414 printnl = B_TRUE;
5047 5415 ret = upgrade_version(zhp, cbp->cb_version);
5048 5416 if (ret != 0)
5049 5417 return (ret);
5050 5418 }
5051 5419
5052 5420 if (cbp->cb_version >= SPA_VERSION_FEATURES) {
5053 5421 int count = 0;
5054 5422 ret = upgrade_enable_all(zhp, &count);
5055 5423 if (ret != 0)
5056 5424 return (ret);
5057 5425
5058 5426 if (count != 0) {
5059 5427 printnl = B_TRUE;
5060 5428 } else if (cur_version == SPA_VERSION) {
5061 5429 (void) printf(gettext("Pool '%s' already has all "
5062 5430 "supported features enabled.\n"),
5063 5431 zpool_get_name(zhp));
5064 5432 }
5065 5433 }
5066 5434
5067 5435 if (printnl) {
5068 5436 (void) printf(gettext("\n"));
5069 5437 }
5070 5438
5071 5439 return (0);
5072 5440 }
5073 5441
5074 5442 /*
5075 5443 * zpool upgrade
5076 5444 * zpool upgrade -v
5077 5445 * zpool upgrade [-V version] <-a | pool ...>
5078 5446 *
5079 5447 * With no arguments, display downrev'd ZFS pool available for upgrade.
5080 5448 * Individual pools can be upgraded by specifying the pool, and '-a' will
5081 5449 * upgrade all pools.
5082 5450 */
5083 5451 int
5084 5452 zpool_do_upgrade(int argc, char **argv)
5085 5453 {
5086 5454 int c;
5087 5455 upgrade_cbdata_t cb = { 0 };
5088 5456 int ret = 0;
5089 5457 boolean_t showversions = B_FALSE;
5090 5458 boolean_t upgradeall = B_FALSE;
5091 5459 char *end;
5092 5460
5093 5461
5094 5462 /* check options */
5095 5463 while ((c = getopt(argc, argv, ":avV:")) != -1) {
5096 5464 switch (c) {
5097 5465 case 'a':
5098 5466 upgradeall = B_TRUE;
5099 5467 break;
5100 5468 case 'v':
5101 5469 showversions = B_TRUE;
5102 5470 break;
5103 5471 case 'V':
5104 5472 cb.cb_version = strtoll(optarg, &end, 10);
5105 5473 if (*end != '\0' ||
5106 5474 !SPA_VERSION_IS_SUPPORTED(cb.cb_version)) {
5107 5475 (void) fprintf(stderr,
5108 5476 gettext("invalid version '%s'\n"), optarg);
5109 5477 usage(B_FALSE);
5110 5478 }
5111 5479 break;
5112 5480 case ':':
5113 5481 (void) fprintf(stderr, gettext("missing argument for "
5114 5482 "'%c' option\n"), optopt);
5115 5483 usage(B_FALSE);
5116 5484 break;
5117 5485 case '?':
5118 5486 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5119 5487 optopt);
5120 5488 usage(B_FALSE);
5121 5489 }
5122 5490 }
5123 5491
5124 5492 cb.cb_argc = argc;
5125 5493 cb.cb_argv = argv;
5126 5494 argc -= optind;
5127 5495 argv += optind;
5128 5496
5129 5497 if (cb.cb_version == 0) {
5130 5498 cb.cb_version = SPA_VERSION;
5131 5499 } else if (!upgradeall && argc == 0) {
5132 5500 (void) fprintf(stderr, gettext("-V option is "
5133 5501 "incompatible with other arguments\n"));
5134 5502 usage(B_FALSE);
5135 5503 }
5136 5504
5137 5505 if (showversions) {
5138 5506 if (upgradeall || argc != 0) {
5139 5507 (void) fprintf(stderr, gettext("-v option is "
5140 5508 "incompatible with other arguments\n"));
5141 5509 usage(B_FALSE);
5142 5510 }
5143 5511 } else if (upgradeall) {
5144 5512 if (argc != 0) {
5145 5513 (void) fprintf(stderr, gettext("-a option should not "
5146 5514 "be used along with a pool name\n"));
5147 5515 usage(B_FALSE);
5148 5516 }
5149 5517 }
5150 5518
5151 5519 (void) printf(gettext("This system supports ZFS pool feature "
5152 5520 "flags.\n\n"));
5153 5521 if (showversions) {
5154 5522 int i;
5155 5523
5156 5524 (void) printf(gettext("The following features are "
5157 5525 "supported:\n\n"));
5158 5526 (void) printf(gettext("FEAT DESCRIPTION\n"));
5159 5527 (void) printf("----------------------------------------------"
5160 5528 "---------------\n");
5161 5529 for (i = 0; i < SPA_FEATURES; i++) {
5162 5530 zfeature_info_t *fi = &spa_feature_table[i];
5163 5531 const char *ro =
5164 5532 (fi->fi_flags & ZFEATURE_FLAG_READONLY_COMPAT) ?
5165 5533 " (read-only compatible)" : "";
5166 5534
5167 5535 (void) printf("%-37s%s\n", fi->fi_uname, ro);
5168 5536 (void) printf(" %s\n", fi->fi_desc);
5169 5537 }
5170 5538 (void) printf("\n");
5171 5539
5172 5540 (void) printf(gettext("The following legacy versions are also "
5173 5541 "supported:\n\n"));
5174 5542 (void) printf(gettext("VER DESCRIPTION\n"));
5175 5543 (void) printf("--- -----------------------------------------"
5176 5544 "---------------\n");
5177 5545 (void) printf(gettext(" 1 Initial ZFS version\n"));
5178 5546 (void) printf(gettext(" 2 Ditto blocks "
5179 5547 "(replicated metadata)\n"));
5180 5548 (void) printf(gettext(" 3 Hot spares and double parity "
5181 5549 "RAID-Z\n"));
5182 5550 (void) printf(gettext(" 4 zpool history\n"));
5183 5551 (void) printf(gettext(" 5 Compression using the gzip "
5184 5552 "algorithm\n"));
5185 5553 (void) printf(gettext(" 6 bootfs pool property\n"));
5186 5554 (void) printf(gettext(" 7 Separate intent log devices\n"));
5187 5555 (void) printf(gettext(" 8 Delegated administration\n"));
5188 5556 (void) printf(gettext(" 9 refquota and refreservation "
5189 5557 "properties\n"));
5190 5558 (void) printf(gettext(" 10 Cache devices\n"));
5191 5559 (void) printf(gettext(" 11 Improved scrub performance\n"));
5192 5560 (void) printf(gettext(" 12 Snapshot properties\n"));
5193 5561 (void) printf(gettext(" 13 snapused property\n"));
5194 5562 (void) printf(gettext(" 14 passthrough-x aclinherit\n"));
5195 5563 (void) printf(gettext(" 15 user/group space accounting\n"));
5196 5564 (void) printf(gettext(" 16 stmf property support\n"));
5197 5565 (void) printf(gettext(" 17 Triple-parity RAID-Z\n"));
5198 5566 (void) printf(gettext(" 18 Snapshot user holds\n"));
5199 5567 (void) printf(gettext(" 19 Log device removal\n"));
5200 5568 (void) printf(gettext(" 20 Compression using zle "
5201 5569 "(zero-length encoding)\n"));
5202 5570 (void) printf(gettext(" 21 Deduplication\n"));
5203 5571 (void) printf(gettext(" 22 Received properties\n"));
5204 5572 (void) printf(gettext(" 23 Slim ZIL\n"));
5205 5573 (void) printf(gettext(" 24 System attributes\n"));
5206 5574 (void) printf(gettext(" 25 Improved scrub stats\n"));
5207 5575 (void) printf(gettext(" 26 Improved snapshot deletion "
5208 5576 "performance\n"));
5209 5577 (void) printf(gettext(" 27 Improved snapshot creation "
5210 5578 "performance\n"));
5211 5579 (void) printf(gettext(" 28 Multiple vdev replacements\n"));
5212 5580 (void) printf(gettext("\nFor more information on a particular "
5213 5581 "version, including supported releases,\n"));
5214 5582 (void) printf(gettext("see the ZFS Administration Guide.\n\n"));
5215 5583 } else if (argc == 0 && upgradeall) {
5216 5584 cb.cb_first = B_TRUE;
5217 5585 ret = zpool_iter(g_zfs, upgrade_cb, &cb);
5218 5586 if (ret == 0 && cb.cb_first) {
5219 5587 if (cb.cb_version == SPA_VERSION) {
5220 5588 (void) printf(gettext("All pools are already "
5221 5589 "formatted using feature flags.\n\n"));
5222 5590 (void) printf(gettext("Every feature flags "
5223 5591 "pool already has all supported features "
5224 5592 "enabled.\n"));
5225 5593 } else {
5226 5594 (void) printf(gettext("All pools are already "
5227 5595 "formatted with version %llu or higher.\n"),
5228 5596 cb.cb_version);
5229 5597 }
5230 5598 }
5231 5599 } else if (argc == 0) {
5232 5600 cb.cb_first = B_TRUE;
5233 5601 ret = zpool_iter(g_zfs, upgrade_list_older_cb, &cb);
5234 5602 assert(ret == 0);
5235 5603
5236 5604 if (cb.cb_first) {
5237 5605 (void) printf(gettext("All pools are formatted "
5238 5606 "using feature flags.\n\n"));
5239 5607 } else {
5240 5608 (void) printf(gettext("\nUse 'zpool upgrade -v' "
5241 5609 "for a list of available legacy versions.\n"));
5242 5610 }
5243 5611
5244 5612 cb.cb_first = B_TRUE;
5245 5613 ret = zpool_iter(g_zfs, upgrade_list_disabled_cb, &cb);
5246 5614 assert(ret == 0);
5247 5615
5248 5616 if (cb.cb_first) {
5249 5617 (void) printf(gettext("Every feature flags pool has "
5250 5618 "all supported features enabled.\n"));
5251 5619 } else {
5252 5620 (void) printf(gettext("\n"));
5253 5621 }
5254 5622 } else {
5255 5623 ret = for_each_pool(argc, argv, B_FALSE, NULL,
5256 5624 upgrade_one, &cb);
5257 5625 }
5258 5626
5259 5627 return (ret);
5260 5628 }
5261 5629
5262 5630 typedef struct hist_cbdata {
5263 5631 boolean_t first;
5264 5632 boolean_t longfmt;
5265 5633 boolean_t internal;
5266 5634 } hist_cbdata_t;
5267 5635
5268 5636 /*
5269 5637 * Print out the command history for a specific pool.
5270 5638 */
5271 5639 static int
5272 5640 get_history_one(zpool_handle_t *zhp, void *data)
5273 5641 {
5274 5642 nvlist_t *nvhis;
5275 5643 nvlist_t **records;
5276 5644 uint_t numrecords;
5277 5645 int ret, i;
5278 5646 hist_cbdata_t *cb = (hist_cbdata_t *)data;
5279 5647
5280 5648 cb->first = B_FALSE;
5281 5649
5282 5650 (void) printf(gettext("History for '%s':\n"), zpool_get_name(zhp));
5283 5651
5284 5652 if ((ret = zpool_get_history(zhp, &nvhis)) != 0)
5285 5653 return (ret);
5286 5654
5287 5655 verify(nvlist_lookup_nvlist_array(nvhis, ZPOOL_HIST_RECORD,
5288 5656 &records, &numrecords) == 0);
5289 5657 for (i = 0; i < numrecords; i++) {
5290 5658 nvlist_t *rec = records[i];
5291 5659 char tbuf[30] = "";
5292 5660
5293 5661 if (nvlist_exists(rec, ZPOOL_HIST_TIME)) {
5294 5662 time_t tsec;
5295 5663 struct tm t;
5296 5664
5297 5665 tsec = fnvlist_lookup_uint64(records[i],
5298 5666 ZPOOL_HIST_TIME);
5299 5667 (void) localtime_r(&tsec, &t);
5300 5668 (void) strftime(tbuf, sizeof (tbuf), "%F.%T", &t);
5301 5669 }
5302 5670
5303 5671 if (nvlist_exists(rec, ZPOOL_HIST_CMD)) {
5304 5672 (void) printf("%s %s", tbuf,
5305 5673 fnvlist_lookup_string(rec, ZPOOL_HIST_CMD));
5306 5674 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_EVENT)) {
5307 5675 int ievent =
5308 5676 fnvlist_lookup_uint64(rec, ZPOOL_HIST_INT_EVENT);
5309 5677 if (!cb->internal)
5310 5678 continue;
5311 5679 if (ievent >= ZFS_NUM_LEGACY_HISTORY_EVENTS) {
5312 5680 (void) printf("%s unrecognized record:\n",
5313 5681 tbuf);
5314 5682 dump_nvlist(rec, 4);
5315 5683 continue;
5316 5684 }
5317 5685 (void) printf("%s [internal %s txg:%lld] %s", tbuf,
5318 5686 zfs_history_event_names[ievent],
5319 5687 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5320 5688 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_STR));
5321 5689 } else if (nvlist_exists(rec, ZPOOL_HIST_INT_NAME)) {
5322 5690 if (!cb->internal)
5323 5691 continue;
5324 5692 (void) printf("%s [txg:%lld] %s", tbuf,
5325 5693 fnvlist_lookup_uint64(rec, ZPOOL_HIST_TXG),
5326 5694 fnvlist_lookup_string(rec, ZPOOL_HIST_INT_NAME));
5327 5695 if (nvlist_exists(rec, ZPOOL_HIST_DSNAME)) {
5328 5696 (void) printf(" %s (%llu)",
5329 5697 fnvlist_lookup_string(rec,
5330 5698 ZPOOL_HIST_DSNAME),
5331 5699 fnvlist_lookup_uint64(rec,
5332 5700 ZPOOL_HIST_DSID));
5333 5701 }
5334 5702 (void) printf(" %s", fnvlist_lookup_string(rec,
5335 5703 ZPOOL_HIST_INT_STR));
5336 5704 } else if (nvlist_exists(rec, ZPOOL_HIST_IOCTL)) {
5337 5705 if (!cb->internal)
5338 5706 continue;
5339 5707 (void) printf("%s ioctl %s\n", tbuf,
5340 5708 fnvlist_lookup_string(rec, ZPOOL_HIST_IOCTL));
5341 5709 if (nvlist_exists(rec, ZPOOL_HIST_INPUT_NVL)) {
5342 5710 (void) printf(" input:\n");
5343 5711 dump_nvlist(fnvlist_lookup_nvlist(rec,
5344 5712 ZPOOL_HIST_INPUT_NVL), 8);
5345 5713 }
5346 5714 if (nvlist_exists(rec, ZPOOL_HIST_OUTPUT_NVL)) {
5347 5715 (void) printf(" output:\n");
5348 5716 dump_nvlist(fnvlist_lookup_nvlist(rec,
5349 5717 ZPOOL_HIST_OUTPUT_NVL), 8);
5350 5718 }
5351 5719 if (nvlist_exists(rec, ZPOOL_HIST_ERRNO)) {
5352 5720 (void) printf(" errno: %lld\n",
5353 5721 fnvlist_lookup_int64(rec,
5354 5722 ZPOOL_HIST_ERRNO));
5355 5723 }
5356 5724 } else {
5357 5725 if (!cb->internal)
5358 5726 continue;
5359 5727 (void) printf("%s unrecognized record:\n", tbuf);
5360 5728 dump_nvlist(rec, 4);
5361 5729 }
5362 5730
5363 5731 if (!cb->longfmt) {
5364 5732 (void) printf("\n");
5365 5733 continue;
5366 5734 }
5367 5735 (void) printf(" [");
5368 5736 if (nvlist_exists(rec, ZPOOL_HIST_WHO)) {
5369 5737 uid_t who = fnvlist_lookup_uint64(rec, ZPOOL_HIST_WHO);
5370 5738 struct passwd *pwd = getpwuid(who);
5371 5739 (void) printf("user %d ", (int)who);
5372 5740 if (pwd != NULL)
5373 5741 (void) printf("(%s) ", pwd->pw_name);
5374 5742 }
5375 5743 if (nvlist_exists(rec, ZPOOL_HIST_HOST)) {
5376 5744 (void) printf("on %s",
5377 5745 fnvlist_lookup_string(rec, ZPOOL_HIST_HOST));
5378 5746 }
5379 5747 if (nvlist_exists(rec, ZPOOL_HIST_ZONE)) {
5380 5748 (void) printf(":%s",
5381 5749 fnvlist_lookup_string(rec, ZPOOL_HIST_ZONE));
5382 5750 }
5383 5751 (void) printf("]");
5384 5752 (void) printf("\n");
5385 5753 }
5386 5754 (void) printf("\n");
5387 5755 nvlist_free(nvhis);
5388 5756
5389 5757 return (ret);
5390 5758 }
5391 5759
5392 5760 /*
5393 5761 * zpool history <pool>
5394 5762 *
5395 5763 * Displays the history of commands that modified pools.
5396 5764 */
5397 5765 int
5398 5766 zpool_do_history(int argc, char **argv)
5399 5767 {
5400 5768 hist_cbdata_t cbdata = { 0 };
5401 5769 int ret;
5402 5770 int c;
5403 5771
5404 5772 cbdata.first = B_TRUE;
5405 5773 /* check options */
5406 5774 while ((c = getopt(argc, argv, "li")) != -1) {
5407 5775 switch (c) {
5408 5776 case 'l':
5409 5777 cbdata.longfmt = B_TRUE;
5410 5778 break;
5411 5779 case 'i':
5412 5780 cbdata.internal = B_TRUE;
5413 5781 break;
5414 5782 case '?':
5415 5783 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5416 5784 optopt);
5417 5785 usage(B_FALSE);
5418 5786 }
5419 5787 }
5420 5788 argc -= optind;
5421 5789 argv += optind;
5422 5790
5423 5791 ret = for_each_pool(argc, argv, B_FALSE, NULL, get_history_one,
5424 5792 &cbdata);
5425 5793
5426 5794 if (argc == 0 && cbdata.first == B_TRUE) {
5427 5795 (void) printf(gettext("no pools available\n"));
5428 5796 return (0);
5429 5797 }
5430 5798
5431 5799 return (ret);
5432 5800 }
5433 5801
5434 5802 static int
5435 5803 get_callback(zpool_handle_t *zhp, void *data)
5436 5804 {
5437 5805 zprop_get_cbdata_t *cbp = (zprop_get_cbdata_t *)data;
5438 5806 char value[MAXNAMELEN];
5439 5807 zprop_source_t srctype;
5440 5808 zprop_list_t *pl;
5441 5809
5442 5810 for (pl = cbp->cb_proplist; pl != NULL; pl = pl->pl_next) {
5443 5811
5444 5812 /*
5445 5813 * Skip the special fake placeholder. This will also skip
5446 5814 * over the name property when 'all' is specified.
5447 5815 */
5448 5816 if (pl->pl_prop == ZPOOL_PROP_NAME &&
5449 5817 pl == cbp->cb_proplist)
5450 5818 continue;
5451 5819
5452 5820 if (pl->pl_prop == ZPROP_INVAL &&
5453 5821 (zpool_prop_feature(pl->pl_user_prop) ||
5454 5822 zpool_prop_unsupported(pl->pl_user_prop))) {
5455 5823 srctype = ZPROP_SRC_LOCAL;
5456 5824
5457 5825 if (zpool_prop_get_feature(zhp, pl->pl_user_prop,
5458 5826 value, sizeof (value)) == 0) {
5459 5827 zprop_print_one_property(zpool_get_name(zhp),
5460 5828 cbp, pl->pl_user_prop, value, srctype,
5461 5829 NULL, NULL);
5462 5830 }
5463 5831 } else {
5464 5832 if (zpool_get_prop(zhp, pl->pl_prop, value,
5465 5833 sizeof (value), &srctype, cbp->cb_literal) != 0)
5466 5834 continue;
5467 5835
5468 5836 zprop_print_one_property(zpool_get_name(zhp), cbp,
5469 5837 zpool_prop_to_name(pl->pl_prop), value, srctype,
5470 5838 NULL, NULL);
5471 5839 }
5472 5840 }
5473 5841 return (0);
5474 5842 }
5475 5843
5476 5844 /*
5477 5845 * zpool get [-Hp] [-o "all" | field[,...]] <"all" | property[,...]> <pool> ...
5478 5846 *
5479 5847 * -H Scripted mode. Don't display headers, and separate properties
5480 5848 * by a single tab.
5481 5849 * -o List of columns to display. Defaults to
5482 5850 * "name,property,value,source".
5483 5851 * -p Diplay values in parsable (exact) format.
5484 5852 *
5485 5853 * Get properties of pools in the system. Output space statistics
5486 5854 * for each one as well as other attributes.
5487 5855 */
5488 5856 int
5489 5857 zpool_do_get(int argc, char **argv)
5490 5858 {
5491 5859 zprop_get_cbdata_t cb = { 0 };
5492 5860 zprop_list_t fake_name = { 0 };
5493 5861 int ret;
5494 5862 int c, i;
5495 5863 char *value;
5496 5864
5497 5865 cb.cb_first = B_TRUE;
5498 5866
5499 5867 /*
5500 5868 * Set up default columns and sources.
5501 5869 */
5502 5870 cb.cb_sources = ZPROP_SRC_ALL;
5503 5871 cb.cb_columns[0] = GET_COL_NAME;
5504 5872 cb.cb_columns[1] = GET_COL_PROPERTY;
5505 5873 cb.cb_columns[2] = GET_COL_VALUE;
5506 5874 cb.cb_columns[3] = GET_COL_SOURCE;
5507 5875 cb.cb_type = ZFS_TYPE_POOL;
5508 5876
5509 5877 /* check options */
5510 5878 while ((c = getopt(argc, argv, ":Hpo:")) != -1) {
5511 5879 switch (c) {
5512 5880 case 'p':
5513 5881 cb.cb_literal = B_TRUE;
5514 5882 break;
5515 5883 case 'H':
5516 5884 cb.cb_scripted = B_TRUE;
5517 5885 break;
5518 5886 case 'o':
5519 5887 bzero(&cb.cb_columns, sizeof (cb.cb_columns));
5520 5888 i = 0;
5521 5889 while (*optarg != '\0') {
5522 5890 static char *col_subopts[] =
5523 5891 { "name", "property", "value", "source",
5524 5892 "all", NULL };
5525 5893
5526 5894 if (i == ZFS_GET_NCOLS) {
5527 5895 (void) fprintf(stderr, gettext("too "
5528 5896 "many fields given to -o "
5529 5897 "option\n"));
5530 5898 usage(B_FALSE);
5531 5899 }
5532 5900
5533 5901 switch (getsubopt(&optarg, col_subopts,
5534 5902 &value)) {
5535 5903 case 0:
5536 5904 cb.cb_columns[i++] = GET_COL_NAME;
5537 5905 break;
5538 5906 case 1:
5539 5907 cb.cb_columns[i++] = GET_COL_PROPERTY;
5540 5908 break;
5541 5909 case 2:
5542 5910 cb.cb_columns[i++] = GET_COL_VALUE;
5543 5911 break;
5544 5912 case 3:
5545 5913 cb.cb_columns[i++] = GET_COL_SOURCE;
5546 5914 break;
5547 5915 case 4:
5548 5916 if (i > 0) {
5549 5917 (void) fprintf(stderr,
5550 5918 gettext("\"all\" conflicts "
5551 5919 "with specific fields "
5552 5920 "given to -o option\n"));
5553 5921 usage(B_FALSE);
5554 5922 }
5555 5923 cb.cb_columns[0] = GET_COL_NAME;
5556 5924 cb.cb_columns[1] = GET_COL_PROPERTY;
5557 5925 cb.cb_columns[2] = GET_COL_VALUE;
5558 5926 cb.cb_columns[3] = GET_COL_SOURCE;
5559 5927 i = ZFS_GET_NCOLS;
5560 5928 break;
5561 5929 default:
5562 5930 (void) fprintf(stderr,
5563 5931 gettext("invalid column name "
5564 5932 "'%s'\n"), value);
5565 5933 usage(B_FALSE);
5566 5934 }
5567 5935 }
5568 5936 break;
5569 5937 case '?':
5570 5938 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5571 5939 optopt);
5572 5940 usage(B_FALSE);
5573 5941 }
5574 5942 }
5575 5943
5576 5944 argc -= optind;
5577 5945 argv += optind;
5578 5946
5579 5947 if (argc < 1) {
5580 5948 (void) fprintf(stderr, gettext("missing property "
5581 5949 "argument\n"));
5582 5950 usage(B_FALSE);
5583 5951 }
5584 5952
5585 5953 if (zprop_get_list(g_zfs, argv[0], &cb.cb_proplist,
5586 5954 ZFS_TYPE_POOL) != 0)
5587 5955 usage(B_FALSE);
5588 5956
5589 5957 argc--;
5590 5958 argv++;
5591 5959
5592 5960 if (cb.cb_proplist != NULL) {
5593 5961 fake_name.pl_prop = ZPOOL_PROP_NAME;
5594 5962 fake_name.pl_width = strlen(gettext("NAME"));
5595 5963 fake_name.pl_next = cb.cb_proplist;
5596 5964 cb.cb_proplist = &fake_name;
5597 5965 }
5598 5966
5599 5967 ret = for_each_pool(argc, argv, B_TRUE, &cb.cb_proplist,
5600 5968 get_callback, &cb);
|
↓ open down ↓ |
737 lines elided |
↑ open up ↑ |
5601 5969
5602 5970 if (cb.cb_proplist == &fake_name)
5603 5971 zprop_free_list(fake_name.pl_next);
5604 5972 else
5605 5973 zprop_free_list(cb.cb_proplist);
5606 5974
5607 5975 return (ret);
5608 5976 }
5609 5977
5610 5978 typedef struct set_cbdata {
5611 - char *cb_propname;
5612 - char *cb_value;
5979 + nvlist_t *cb_nvl;
5613 5980 boolean_t cb_any_successful;
5614 5981 } set_cbdata_t;
5615 5982
5616 5983 int
5617 5984 set_callback(zpool_handle_t *zhp, void *data)
5618 5985 {
5619 5986 int error;
5620 5987 set_cbdata_t *cb = (set_cbdata_t *)data;
5621 5988
5622 - error = zpool_set_prop(zhp, cb->cb_propname, cb->cb_value);
5623 -
5989 + error = zpool_set_proplist(zhp, cb->cb_nvl);
5624 5990 if (!error)
5625 5991 cb->cb_any_successful = B_TRUE;
5626 5992
5627 5993 return (error);
5628 5994 }
5629 5995
5996 +static void
5997 +parse_props(char *propname, nvlist_t **nvl, zfs_type_t prop_type)
5998 +{
5999 + char *propval;
6000 + char *delim;
6001 + int err;
6002 +
6003 + do {
6004 + delim = strchr(propname, ',');
6005 + if (delim != NULL)
6006 + *delim++ = '\0';
6007 +
6008 + propval = strchr(propname, '=');
6009 + if (propval == NULL) {
6010 + (void) fprintf(stderr, gettext("missing value "
6011 + "in property=value argument\n"));
6012 + if (*nvl != NULL)
6013 + nvlist_free(*nvl);
6014 + usage(B_FALSE);
6015 + }
6016 + *propval++ = '\0';
6017 + switch (prop_type) {
6018 + case ZFS_TYPE_VDEV:
6019 + err = add_vdev_prop_list(propname, propval, nvl);
6020 + break;
6021 + case ZFS_TYPE_COS:
6022 + err = add_cos_prop_list(propname, propval, nvl);
6023 + break;
6024 + default:
6025 + err = add_prop_list(propname, propval, nvl, B_TRUE);
6026 + }
6027 +
6028 + if (err) {
6029 + if (*nvl != NULL)
6030 + nvlist_free(*nvl);
6031 + usage(B_FALSE);
6032 + }
6033 +
6034 + propname = delim;
6035 + } while (delim != NULL);
6036 +}
6037 +
5630 6038 int
5631 6039 zpool_do_set(int argc, char **argv)
5632 6040 {
5633 6041 set_cbdata_t cb = { 0 };
5634 6042 int error;
5635 6043
5636 6044 if (argc > 1 && argv[1][0] == '-') {
5637 6045 (void) fprintf(stderr, gettext("invalid option '%c'\n"),
5638 6046 argv[1][1]);
5639 6047 usage(B_FALSE);
5640 6048 }
5641 6049
5642 6050 if (argc < 2) {
5643 6051 (void) fprintf(stderr, gettext("missing property=value "
5644 6052 "argument\n"));
5645 6053 usage(B_FALSE);
5646 6054 }
5647 6055
|
↓ open down ↓ |
8 lines elided |
↑ open up ↑ |
5648 6056 if (argc < 3) {
5649 6057 (void) fprintf(stderr, gettext("missing pool name\n"));
5650 6058 usage(B_FALSE);
5651 6059 }
5652 6060
5653 6061 if (argc > 3) {
5654 6062 (void) fprintf(stderr, gettext("too many pool names\n"));
5655 6063 usage(B_FALSE);
5656 6064 }
5657 6065
5658 - cb.cb_propname = argv[1];
5659 - cb.cb_value = strchr(cb.cb_propname, '=');
5660 - if (cb.cb_value == NULL) {
5661 - (void) fprintf(stderr, gettext("missing value in "
5662 - "property=value argument\n"));
6066 + parse_props(argv[1], &cb.cb_nvl, ZFS_TYPE_POOL);
6067 +
6068 + error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
6069 + set_callback, &cb);
6070 +
6071 + return (error);
6072 +}
6073 +
6074 +typedef struct vdev_cbdata {
6075 + char *vcb_vdev;
6076 + nvlist_t *vcb_nvl; /* values */
6077 + boolean_t vcb_any_successful;
6078 +} vdev_cbdata_t;
6079 +
6080 +typedef struct vdev_get_cbdata {
6081 + zprop_get_cbdata_t vcb_zprop_get_cbdata;
6082 + char *vcb_vdev;
6083 + nvlist_t *vcb_nvl; /* values */
6084 + boolean_t vcb_any_successful;
6085 +} vdev_get_cbdata_t;
6086 +
6087 +static int
6088 +vdev_get_callback(zpool_handle_t *zhp, void *data)
6089 +{
6090 + int err;
6091 + boolean_t l2cache, avail_space;
6092 + vdev_get_cbdata_t *vcb = (vdev_get_cbdata_t *)data;
6093 + zprop_get_cbdata_t *cb = &vcb->vcb_zprop_get_cbdata;
6094 + char value[MAXNAMELEN];
6095 + zprop_list_t *pl;
6096 +
6097 + (void) zpool_find_vdev(zhp, vcb->vcb_vdev, &avail_space,
6098 + &l2cache, NULL, NULL);
6099 + for (pl = cb->cb_proplist; pl != NULL; pl = pl->pl_next) {
6100 + if ((err = vdev_get_prop(zhp, vcb->vcb_vdev,
6101 + pl->pl_prop, value, sizeof (value))) != 0)
6102 + return (err);
6103 +
6104 + /* don't show L2ARC prop for non L2ARC dev, can't set anyway */
6105 + if (!l2cache && pl->pl_prop == VDEV_PROP_L2ADDDT)
6106 + continue;
6107 + vdev_print_one_property(zpool_get_name(zhp), vcb->vcb_vdev, cb,
6108 + vdev_prop_to_name(pl->pl_prop), value);
6109 + }
6110 +
6111 + return (0);
6112 +}
6113 +
6114 +
6115 +int
6116 +zpool_do_vdev_get(int argc, char **argv)
6117 +{
6118 + vdev_get_cbdata_t vcb = { 0 };
6119 + zprop_get_cbdata_t *cb = &vcb.vcb_zprop_get_cbdata;
6120 + int error;
6121 +
6122 + if (argc > 1 && argv[1][0] == '-') {
6123 + (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6124 + argv[1][1]);
5663 6125 usage(B_FALSE);
5664 6126 }
5665 6127
5666 - *(cb.cb_value) = '\0';
5667 - cb.cb_value++;
6128 + if (argc < 2) {
6129 + (void) fprintf(stderr, gettext("missing property name\n"));
6130 + usage(B_FALSE);
6131 + }
5668 6132
5669 - error = for_each_pool(argc - 2, argv + 2, B_TRUE, NULL,
5670 - set_callback, &cb);
6133 + if (argc < 3) {
6134 + (void) fprintf(stderr, gettext("missing pool name\n"));
6135 + usage(B_FALSE);
6136 + }
5671 6137
6138 + if (argc < 4) {
6139 + (void) fprintf(stderr,
6140 + gettext("at least one vdev name or guid is required\n"));
6141 + usage(B_FALSE);
6142 + }
6143 +
6144 + cb->cb_first = B_TRUE;
6145 + cb->cb_sources = ZPROP_SRC_ALL;
6146 + cb->cb_columns[0] = GET_COL_NAME;
6147 + cb->cb_columns[1] = GET_COL_SOURCE;
6148 + cb->cb_columns[2] = GET_COL_PROPERTY;
6149 + cb->cb_columns[3] = GET_COL_VALUE;
6150 + cb->cb_type = ZFS_TYPE_VDEV;
6151 +
6152 + if (vdev_get_proplist(g_zfs, argv[1], &cb->cb_proplist) != 0)
6153 + usage(B_FALSE);
6154 +
6155 + vcb.vcb_vdev = argv[3];
6156 + error = for_each_pool(1, argv + 2, B_TRUE, NULL,
6157 + vdev_get_callback, &vcb);
6158 +
6159 + zprop_free_list(cb->cb_proplist);
6160 +
5672 6161 return (error);
5673 6162 }
5674 6163
6164 +int
6165 +vdev_set_callback(zpool_handle_t *zhp, void *data)
6166 +{
6167 + int error;
6168 + vdev_cbdata_t *cb = (vdev_cbdata_t *)data;
6169 +
6170 + error = vdev_set_proplist(zhp, cb->vcb_vdev, cb->vcb_nvl);
6171 + if (!error)
6172 + cb->vcb_any_successful = B_TRUE;
6173 +
6174 + return (error);
6175 +}
6176 +
6177 +int
6178 +zpool_do_vdev_set(int argc, char **argv)
6179 +{
6180 + vdev_cbdata_t cb = { 0 };
6181 + int error;
6182 +
6183 + if (argc > 1 && argv[1][0] == '-') {
6184 + (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6185 + argv[1][1]);
6186 + usage(B_FALSE);
6187 + }
6188 +
6189 + if (argc < 2) {
6190 + (void) fprintf(stderr, gettext("missing property=value "
6191 + "argument\n"));
6192 + usage(B_FALSE);
6193 + }
6194 +
6195 + if (argc < 3) {
6196 + (void) fprintf(stderr, gettext("missing pool name\n"));
6197 + usage(B_FALSE);
6198 + }
6199 +
6200 + if (argc < 4) {
6201 + (void) fprintf(stderr,
6202 + gettext("at least one vdev name or guid is required\n"));
6203 + usage(B_FALSE);
6204 + }
6205 +
6206 + parse_props(argv[1], &cb.vcb_nvl, ZFS_TYPE_VDEV);
6207 +
6208 + cb.vcb_vdev = argv[3];
6209 + error = for_each_pool(1, argv + 2, B_TRUE, NULL,
6210 + vdev_set_callback, &cb);
6211 +
6212 + return (error);
6213 +}
6214 +
6215 +typedef struct cos_af_cbdata {
6216 + char *cb_cos;
6217 + uint64_t cb_guid;
6218 + boolean_t cb_alloc;
6219 + boolean_t cb_any_successful;
6220 + boolean_t cb_force;
6221 + nvlist_t *cb_nvl;
6222 +} cos_af_cbdata_t;
6223 +
6224 +int
6225 +cos_alloc_callback(zpool_handle_t *zhp, void *data)
6226 +{
6227 + int error;
6228 + cos_af_cbdata_t *cb = (cos_af_cbdata_t *)data;
6229 +
6230 + if (cb->cb_alloc)
6231 + error = cos_alloc(zhp, cb->cb_cos, cb->cb_nvl);
6232 + else
6233 + error = cos_free(zhp, cb->cb_cos, cb->cb_guid, cb->cb_force);
6234 + if (!error)
6235 + cb->cb_any_successful = B_TRUE;
6236 +
6237 + if (error == ENOTSUP) {
6238 + (void) fprintf(stderr, gettext("operation failed: "
6239 + "CoS feature is disabled.\n"));
6240 + }
6241 +
6242 + return (error);
6243 +}
6244 +
6245 +int
6246 +zpool_do_cos_alloc(int argc, char **argv)
6247 +{
6248 + nvlist_t *nvl;
6249 + cos_af_cbdata_t cb = { 0 };
6250 + int error;
6251 +
6252 + if (!nexenta_meta_enable())
6253 + return (-1);
6254 +
6255 + if (argc < 2) {
6256 + (void) fprintf(stderr, gettext("missing pool name\n"));
6257 + usage(B_FALSE);
6258 + }
6259 +
6260 + if (argc < 3) {
6261 + (void) fprintf(stderr,
6262 + gettext("at least one cos name or id is required\n"));
6263 + usage(B_FALSE);
6264 + }
6265 +
6266 + if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
6267 + (void) fprintf(stderr,
6268 + gettext("internal error: out of memory\n"));
6269 + return (1);
6270 + }
6271 +
6272 + cb.cb_cos = argv[2];
6273 + cb.cb_alloc = B_TRUE;
6274 + cb.cb_nvl = nvl;
6275 + error = for_each_pool(1, argv + 1, B_TRUE, NULL,
6276 + cos_alloc_callback, &cb);
6277 +
6278 + nvlist_free(nvl);
6279 +
6280 + return (error);
6281 +}
6282 +
6283 +int
6284 +zpool_do_cos_free(int argc, char **argv)
6285 +{
6286 + cos_af_cbdata_t cb = { 0 };
6287 + char *endp;
6288 + int error;
6289 +
6290 + if (!nexenta_meta_enable())
6291 + return (-1);
6292 +
6293 + if (argc > 1 && strncmp(argv[1], "-f", sizeof ("-f")) == 0) {
6294 + /* -f - force option */
6295 + cb.cb_force = B_TRUE;
6296 + argc--;
6297 + argv++;
6298 + }
6299 +
6300 + if (argc < 2) {
6301 + (void) fprintf(stderr, gettext("missing pool name\n"));
6302 + usage(B_FALSE);
6303 + }
6304 +
6305 + if (argc < 3) {
6306 + (void) fprintf(stderr,
6307 + gettext("at least one cos name or id is required\n"));
6308 + usage(B_FALSE);
6309 + }
6310 +
6311 + cb.cb_guid = strtoll(argv[2], &endp, 10);
6312 + if (endp < argv[2] + strlen(argv[2])) {
6313 + cb.cb_guid = 0;
6314 + }
6315 +
6316 + if (cb.cb_guid == 0)
6317 + cb.cb_cos = argv[2];
6318 + else
6319 + cb.cb_cos = "";
6320 +
6321 + error = for_each_pool(1, argv + 1, B_TRUE, NULL,
6322 + cos_alloc_callback, &cb);
6323 +
6324 + return (error);
6325 +}
6326 +
6327 +
5675 6328 static int
6329 +cos_list_callback(zpool_handle_t *zhp, void *data)
6330 +{
6331 + int err, i;
6332 + nvlist_t *nvl = (nvlist_t *)data;
6333 + nvpair_t *nvp;
6334 +
6335 + if ((err = cos_list(zhp, &nvl)) == 0) {
6336 + (void) printf("%-*s %s\n", MAXCOSNAMELEN, gettext("COSNAME"),
6337 + gettext("COSID"));
6338 + for (i = 0, nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
6339 + nvp = nvlist_next_nvpair(nvl, nvp), i++) {
6340 + uint64_t cosid;
6341 + char *cosname = nvpair_name(nvp);
6342 + if (nvpair_value_uint64(nvp, &cosid) == 0)
6343 + (void) printf("%-*s %llu\n", MAXCOSNAMELEN,
6344 + cosname, cosid);
6345 + }
6346 +
6347 + if (!i)
6348 + (void) printf("%s\n", gettext("<no classes found>"));
6349 + }
6350 + return (err);
6351 +}
6352 +
6353 +int
6354 +zpool_do_cos_list(int argc, char **argv)
6355 +{
6356 + nvlist_t *nvl;
6357 + int error;
6358 +
6359 + if (!nexenta_meta_enable())
6360 + return (-1);
6361 +
6362 + if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) {
6363 + (void) fprintf(stderr,
6364 + gettext("internal error: out of memory\n"));
6365 + return (1);
6366 + }
6367 +
6368 + if (argc < 2) {
6369 + (void) fprintf(stderr, gettext("missing pool name\n"));
6370 + usage(B_FALSE);
6371 + }
6372 +
6373 + error = for_each_pool(1, argv+1, B_TRUE, NULL,
6374 + cos_list_callback, nvl);
6375 +
6376 + nvlist_free(nvl);
6377 +
6378 + return (error);
6379 +
6380 +}
6381 +
6382 +typedef struct cos_cbdata {
6383 + char *vcb_cos;
6384 + nvlist_t *vcb_nvl; /* values */
6385 + boolean_t vcb_any_successful;
6386 +} cos_cbdata_t;
6387 +
6388 +typedef struct cos_get_cbdata {
6389 + zprop_get_cbdata_t vcb_zprop_get_cbdata;
6390 + char *vcb_cos;
6391 + nvlist_t *vcb_nvl; /* values */
6392 + boolean_t vcb_any_successful;
6393 +} cos_get_cbdata_t;
6394 +
6395 +static int
6396 +cos_get_callback(zpool_handle_t *zhp, void *data)
6397 +{
6398 + int err;
6399 + cos_get_cbdata_t *vcb = (cos_get_cbdata_t *)data;
6400 + zprop_get_cbdata_t *cb = &vcb->vcb_zprop_get_cbdata;
6401 + char value[MAXNAMELEN];
6402 + zprop_list_t *pl;
6403 + nvlist_t *nvl = NULL;
6404 +
6405 + for (pl = cb->cb_proplist; pl != NULL; pl = pl->pl_next) {
6406 + if ((err = cos_get_prop(zhp, vcb->vcb_cos,
6407 + pl->pl_prop, value, sizeof (value), &nvl)) != 0)
6408 + return (err);
6409 +
6410 + cos_print_one_property(zpool_get_name(zhp), vcb->vcb_cos, cb,
6411 + cos_prop_to_name(pl->pl_prop), value);
6412 + }
6413 +
6414 + return (0);
6415 +}
6416 +
6417 +
6418 +int
6419 +zpool_do_cos_get(int argc, char **argv)
6420 +{
6421 + cos_get_cbdata_t vcb = { 0 };
6422 + zprop_get_cbdata_t *cb = &vcb.vcb_zprop_get_cbdata;
6423 + int error;
6424 +
6425 + if (!nexenta_meta_enable())
6426 + return (-1);
6427 +
6428 + if (argc > 1 && argv[1][0] == '-') {
6429 + (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6430 + argv[1][1]);
6431 + usage(B_FALSE);
6432 + }
6433 +
6434 + if (argc < 2) {
6435 + (void) fprintf(stderr, gettext("missing property name\n"));
6436 + usage(B_FALSE);
6437 + }
6438 +
6439 + if (argc < 3) {
6440 + (void) fprintf(stderr, gettext("missing pool name\n"));
6441 + usage(B_FALSE);
6442 + }
6443 +
6444 + if (argc < 4) {
6445 + (void) fprintf(stderr,
6446 + gettext("at least one cos name or guid is required\n"));
6447 + usage(B_FALSE);
6448 + }
6449 +
6450 + cb->cb_first = B_TRUE;
6451 + cb->cb_sources = ZPROP_SRC_ALL;
6452 + cb->cb_columns[0] = GET_COL_NAME;
6453 + cb->cb_columns[1] = GET_COL_SOURCE;
6454 + cb->cb_columns[2] = GET_COL_PROPERTY;
6455 + cb->cb_columns[3] = GET_COL_VALUE;
6456 + cb->cb_type = ZFS_TYPE_COS;
6457 +
6458 + if (cos_get_proplist(g_zfs, argv[1], &cb->cb_proplist) != 0)
6459 + usage(B_FALSE);
6460 +
6461 + vcb.vcb_cos = argv[3];
6462 + error = for_each_pool(1, argv + 2, B_TRUE, NULL,
6463 + cos_get_callback, &vcb);
6464 +
6465 + zprop_free_list(cb->cb_proplist);
6466 +
6467 + return (error);
6468 +
6469 +}
6470 +
6471 +int
6472 +cos_set_callback(zpool_handle_t *zhp, void *data)
6473 +{
6474 + int error;
6475 + cos_cbdata_t *cb = (cos_cbdata_t *)data;
6476 +
6477 + error = cos_set_proplist(zhp, cb->vcb_cos, cb->vcb_nvl);
6478 + if (!error)
6479 + cb->vcb_any_successful = B_TRUE;
6480 +
6481 + return (error);
6482 +}
6483 +
6484 +int
6485 +zpool_do_cos_set(int argc, char **argv)
6486 +{
6487 + cos_cbdata_t cb = { 0 };
6488 + int error;
6489 +
6490 + if (!nexenta_meta_enable())
6491 + return (-1);
6492 +
6493 + if (argc > 1 && argv[1][0] == '-') {
6494 + (void) fprintf(stderr, gettext("invalid option '%c'\n"),
6495 + argv[1][1]);
6496 + usage(B_FALSE);
6497 + }
6498 +
6499 + if (argc < 2) {
6500 + (void) fprintf(stderr, gettext("missing property=value "
6501 + "argument\n"));
6502 + usage(B_FALSE);
6503 + }
6504 +
6505 + if (argc < 3) {
6506 + (void) fprintf(stderr, gettext("missing pool name\n"));
6507 + usage(B_FALSE);
6508 + }
6509 +
6510 + if (argc < 4) {
6511 + (void) fprintf(stderr,
6512 + gettext("at least one cos name or id is required\n"));
6513 + usage(B_FALSE);
6514 + }
6515 +
6516 + parse_props(argv[1], &cb.vcb_nvl, ZFS_TYPE_COS);
6517 +
6518 + cb.vcb_cos = argv[3];
6519 + error = for_each_pool(1, argv + 2, B_TRUE, NULL,
6520 + cos_set_callback, &cb);
6521 +
6522 + return (error);
6523 +}
6524 +
6525 +static int
5676 6526 find_command_idx(char *command, int *idx)
5677 6527 {
5678 6528 int i;
5679 6529
5680 6530 for (i = 0; i < NCOMMAND; i++) {
5681 6531 if (command_table[i].name == NULL)
5682 6532 continue;
5683 6533
5684 6534 if (strcmp(command, command_table[i].name) == 0) {
5685 6535 *idx = i;
5686 6536 return (0);
5687 6537 }
5688 6538 }
5689 6539 return (1);
5690 6540 }
5691 6541
5692 6542 int
5693 6543 main(int argc, char **argv)
5694 6544 {
5695 6545 int ret = 0;
5696 6546 int i;
5697 6547 char *cmdname;
5698 6548
5699 6549 (void) setlocale(LC_ALL, "");
5700 6550 (void) textdomain(TEXT_DOMAIN);
5701 6551
5702 6552 if ((g_zfs = libzfs_init()) == NULL) {
5703 6553 (void) fprintf(stderr, gettext("internal error: failed to "
5704 6554 "initialize ZFS library\n"));
5705 6555 return (1);
5706 6556 }
5707 6557
5708 6558 libzfs_print_on_error(g_zfs, B_TRUE);
5709 6559
5710 6560 opterr = 0;
5711 6561
5712 6562 /*
5713 6563 * Make sure the user has specified some command.
5714 6564 */
5715 6565 if (argc < 2) {
5716 6566 (void) fprintf(stderr, gettext("missing command\n"));
5717 6567 usage(B_FALSE);
5718 6568 }
|
↓ open down ↓ |
33 lines elided |
↑ open up ↑ |
5719 6569
5720 6570 cmdname = argv[1];
5721 6571
5722 6572 /*
5723 6573 * Special case '-?'
5724 6574 */
5725 6575 if (strcmp(cmdname, "-?") == 0)
5726 6576 usage(B_TRUE);
5727 6577
5728 6578 zfs_save_arguments(argc, argv, history_str, sizeof (history_str));
6579 + verify(zpool_stage_history(g_zfs, history_str) == 0);
5729 6580
5730 6581 /*
5731 6582 * Run the appropriate command.
5732 6583 */
5733 6584 if (find_command_idx(cmdname, &i) == 0) {
5734 6585 current_command = &command_table[i];
5735 6586 ret = command_table[i].func(argc - 1, argv + 1);
5736 6587 } else if (strchr(cmdname, '=')) {
5737 6588 verify(find_command_idx("set", &i) == 0);
5738 6589 current_command = &command_table[i];
5739 6590 ret = command_table[i].func(argc, argv);
5740 6591 } else if (strcmp(cmdname, "freeze") == 0 && argc == 3) {
5741 6592 /*
5742 6593 * 'freeze' is a vile debugging abomination, so we treat
5743 6594 * it as such.
5744 6595 */
5745 6596 char buf[16384];
5746 6597 int fd = open(ZFS_DEV, O_RDWR);
5747 6598 (void) strcpy((void *)buf, argv[2]);
5748 6599 return (!!ioctl(fd, ZFS_IOC_POOL_FREEZE, buf));
5749 6600 } else {
5750 6601 (void) fprintf(stderr, gettext("unrecognized "
5751 6602 "command '%s'\n"), cmdname);
5752 6603 usage(B_FALSE);
5753 6604 }
5754 6605
5755 6606 if (ret == 0 && log_history)
5756 6607 (void) zpool_log_history(g_zfs, history_str);
5757 6608
5758 6609 libzfs_fini(g_zfs);
5759 6610
5760 6611 /*
5761 6612 * The 'ZFS_ABORT' environment variable causes us to dump core on exit
5762 6613 * for the purposes of running ::findleaks.
5763 6614 */
5764 6615 if (getenv("ZFS_ABORT") != NULL) {
5765 6616 (void) printf("dumping core by request\n");
5766 6617 abort();
5767 6618 }
5768 6619
5769 6620 return (ret);
5770 6621 }
|
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX