Print this page
2619 asynchronous destruction of ZFS file systems
2747 SPA versioning with zfs feature flags
Reviewed by: Matt Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <gwilson@delphix.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>
Approved by: Dan McDonald <danmcd@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/libzfs/common/libzfs_status.c
+++ new/usr/src/lib/libzfs/common/libzfs_status.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
|
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
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 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 + * Copyright (c) 2012 by Delphix. All rights reserved.
23 25 */
24 26
25 27 /*
26 28 * This file contains the functions which analyze the status of a pool. This
27 29 * include both the status of an active pool, as well as the status exported
28 30 * pools. Returns one of the ZPOOL_STATUS_* defines describing the status of
29 31 * the pool. This status is independent (to a certain degree) from the state of
30 32 * the pool. A pool's state describes only whether or not it is capable of
31 33 * providing the necessary fault tolerance for data. The status describes the
32 34 * overall status of devices. A pool that is online can still have a device
33 35 * that is experiencing errors.
34 36 *
35 37 * Only a subset of the possible faults can be detected using 'zpool status',
36 38 * and not all possible errors correspond to a FMA message ID. The explanation
37 39 * is left up to the caller, depending on whether it is a live pool or an
38 40 * import.
39 41 */
40 42
41 43 #include <libzfs.h>
42 44 #include <string.h>
43 45 #include <unistd.h>
44 46 #include "libzfs_impl.h"
45 47
46 48 /*
47 49 * Message ID table. This must be kept in sync with the ZPOOL_STATUS_* defines
48 50 * in libzfs.h. Note that there are some status results which go past the end
49 51 * of this table, and hence have no associated message ID.
50 52 */
51 53 static char *zfs_msgid_table[] = {
52 54 "ZFS-8000-14",
53 55 "ZFS-8000-2Q",
54 56 "ZFS-8000-3C",
55 57 "ZFS-8000-4J",
56 58 "ZFS-8000-5E",
57 59 "ZFS-8000-6X",
58 60 "ZFS-8000-72",
59 61 "ZFS-8000-8A",
60 62 "ZFS-8000-9P",
61 63 "ZFS-8000-A5",
62 64 "ZFS-8000-EY",
63 65 "ZFS-8000-HC",
64 66 "ZFS-8000-JQ",
65 67 "ZFS-8000-K4",
66 68 };
67 69
68 70 #define NMSGID (sizeof (zfs_msgid_table) / sizeof (zfs_msgid_table[0]))
69 71
70 72 /* ARGSUSED */
71 73 static int
72 74 vdev_missing(uint64_t state, uint64_t aux, uint64_t errs)
73 75 {
74 76 return (state == VDEV_STATE_CANT_OPEN &&
75 77 aux == VDEV_AUX_OPEN_FAILED);
76 78 }
77 79
78 80 /* ARGSUSED */
79 81 static int
80 82 vdev_faulted(uint64_t state, uint64_t aux, uint64_t errs)
81 83 {
82 84 return (state == VDEV_STATE_FAULTED);
83 85 }
84 86
85 87 /* ARGSUSED */
86 88 static int
87 89 vdev_errors(uint64_t state, uint64_t aux, uint64_t errs)
88 90 {
89 91 return (state == VDEV_STATE_DEGRADED || errs != 0);
90 92 }
91 93
92 94 /* ARGSUSED */
93 95 static int
94 96 vdev_broken(uint64_t state, uint64_t aux, uint64_t errs)
95 97 {
96 98 return (state == VDEV_STATE_CANT_OPEN);
97 99 }
98 100
99 101 /* ARGSUSED */
100 102 static int
101 103 vdev_offlined(uint64_t state, uint64_t aux, uint64_t errs)
102 104 {
103 105 return (state == VDEV_STATE_OFFLINE);
104 106 }
105 107
106 108 /* ARGSUSED */
107 109 static int
108 110 vdev_removed(uint64_t state, uint64_t aux, uint64_t errs)
109 111 {
110 112 return (state == VDEV_STATE_REMOVED);
111 113 }
112 114
113 115 /*
114 116 * Detect if any leaf devices that have seen errors or could not be opened.
115 117 */
116 118 static boolean_t
117 119 find_vdev_problem(nvlist_t *vdev, int (*func)(uint64_t, uint64_t, uint64_t))
118 120 {
119 121 nvlist_t **child;
120 122 vdev_stat_t *vs;
121 123 uint_t c, children;
122 124 char *type;
123 125
124 126 /*
125 127 * Ignore problems within a 'replacing' vdev, since we're presumably in
126 128 * the process of repairing any such errors, and don't want to call them
127 129 * out again. We'll pick up the fact that a resilver is happening
128 130 * later.
129 131 */
130 132 verify(nvlist_lookup_string(vdev, ZPOOL_CONFIG_TYPE, &type) == 0);
131 133 if (strcmp(type, VDEV_TYPE_REPLACING) == 0)
132 134 return (B_FALSE);
133 135
134 136 if (nvlist_lookup_nvlist_array(vdev, ZPOOL_CONFIG_CHILDREN, &child,
135 137 &children) == 0) {
136 138 for (c = 0; c < children; c++)
137 139 if (find_vdev_problem(child[c], func))
138 140 return (B_TRUE);
139 141 } else {
140 142 verify(nvlist_lookup_uint64_array(vdev, ZPOOL_CONFIG_VDEV_STATS,
141 143 (uint64_t **)&vs, &c) == 0);
142 144
143 145 if (func(vs->vs_state, vs->vs_aux,
144 146 vs->vs_read_errors +
145 147 vs->vs_write_errors +
146 148 vs->vs_checksum_errors))
147 149 return (B_TRUE);
148 150 }
149 151
150 152 return (B_FALSE);
151 153 }
152 154
153 155 /*
154 156 * Active pool health status.
155 157 *
156 158 * To determine the status for a pool, we make several passes over the config,
157 159 * picking the most egregious error we find. In order of importance, we do the
158 160 * following:
159 161 *
160 162 * - Check for a complete and valid configuration
161 163 * - Look for any faulted or missing devices in a non-replicated config
162 164 * - Check for any data errors
163 165 * - Check for any faulted or missing devices in a replicated config
164 166 * - Look for any devices showing errors
165 167 * - Check for any resilvering devices
166 168 *
167 169 * There can obviously be multiple errors within a single pool, so this routine
168 170 * only picks the most damaging of all the current errors to report.
169 171 */
170 172 static zpool_status_t
171 173 check_status(nvlist_t *config, boolean_t isimport)
172 174 {
173 175 nvlist_t *nvroot;
174 176 vdev_stat_t *vs;
175 177 pool_scan_stat_t *ps = NULL;
176 178 uint_t vsc, psc;
177 179 uint64_t nerr;
178 180 uint64_t version;
179 181 uint64_t stateval;
180 182 uint64_t suspended;
181 183 uint64_t hostid = 0;
182 184
183 185 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_VERSION,
184 186 &version) == 0);
185 187 verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
186 188 &nvroot) == 0);
187 189 verify(nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS,
188 190 (uint64_t **)&vs, &vsc) == 0);
189 191 verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
190 192 &stateval) == 0);
191 193
192 194 /*
193 195 * Currently resilvering a vdev
194 196 */
195 197 (void) nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_SCAN_STATS,
196 198 (uint64_t **)&ps, &psc);
197 199 if (ps && ps->pss_func == POOL_SCAN_RESILVER &&
198 200 ps->pss_state == DSS_SCANNING)
199 201 return (ZPOOL_STATUS_RESILVERING);
200 202
201 203 /*
202 204 * Pool last accessed by another system.
203 205 */
204 206 (void) nvlist_lookup_uint64(config, ZPOOL_CONFIG_HOSTID, &hostid);
205 207 if (hostid != 0 && (unsigned long)hostid != gethostid() &&
206 208 stateval == POOL_STATE_ACTIVE)
|
↓ open down ↓ |
174 lines elided |
↑ open up ↑ |
207 209 return (ZPOOL_STATUS_HOSTID_MISMATCH);
208 210
209 211 /*
210 212 * Newer on-disk version.
211 213 */
212 214 if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
213 215 vs->vs_aux == VDEV_AUX_VERSION_NEWER)
214 216 return (ZPOOL_STATUS_VERSION_NEWER);
215 217
216 218 /*
219 + * Unsupported feature(s).
220 + */
221 + if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
222 + vs->vs_aux == VDEV_AUX_UNSUP_FEAT) {
223 + nvlist_t *nvinfo;
224 +
225 + verify(nvlist_lookup_nvlist(config, ZPOOL_CONFIG_LOAD_INFO,
226 + &nvinfo) == 0);
227 + if (nvlist_exists(nvinfo, ZPOOL_CONFIG_CAN_RDONLY))
228 + return (ZPOOL_STATUS_UNSUP_FEAT_WRITE);
229 + return (ZPOOL_STATUS_UNSUP_FEAT_READ);
230 + }
231 +
232 + /*
217 233 * Check that the config is complete.
218 234 */
219 235 if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
220 236 vs->vs_aux == VDEV_AUX_BAD_GUID_SUM)
221 237 return (ZPOOL_STATUS_BAD_GUID_SUM);
222 238
223 239 /*
224 240 * Check whether the pool has suspended due to failed I/O.
225 241 */
226 242 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_SUSPENDED,
227 243 &suspended) == 0) {
228 244 if (suspended == ZIO_FAILURE_MODE_CONTINUE)
229 245 return (ZPOOL_STATUS_IO_FAILURE_CONTINUE);
230 246 return (ZPOOL_STATUS_IO_FAILURE_WAIT);
231 247 }
232 248
233 249 /*
234 250 * Could not read a log.
235 251 */
236 252 if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
237 253 vs->vs_aux == VDEV_AUX_BAD_LOG) {
238 254 return (ZPOOL_STATUS_BAD_LOG);
239 255 }
240 256
241 257 /*
242 258 * Bad devices in non-replicated config.
243 259 */
244 260 if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
245 261 find_vdev_problem(nvroot, vdev_faulted))
246 262 return (ZPOOL_STATUS_FAULTED_DEV_NR);
247 263
248 264 if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
249 265 find_vdev_problem(nvroot, vdev_missing))
250 266 return (ZPOOL_STATUS_MISSING_DEV_NR);
251 267
252 268 if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
253 269 find_vdev_problem(nvroot, vdev_broken))
254 270 return (ZPOOL_STATUS_CORRUPT_LABEL_NR);
255 271
256 272 /*
257 273 * Corrupted pool metadata
258 274 */
259 275 if (vs->vs_state == VDEV_STATE_CANT_OPEN &&
260 276 vs->vs_aux == VDEV_AUX_CORRUPT_DATA)
261 277 return (ZPOOL_STATUS_CORRUPT_POOL);
262 278
263 279 /*
264 280 * Persistent data errors.
265 281 */
266 282 if (!isimport) {
267 283 if (nvlist_lookup_uint64(config, ZPOOL_CONFIG_ERRCOUNT,
268 284 &nerr) == 0 && nerr != 0)
269 285 return (ZPOOL_STATUS_CORRUPT_DATA);
270 286 }
271 287
272 288 /*
273 289 * Missing devices in a replicated config.
274 290 */
275 291 if (find_vdev_problem(nvroot, vdev_faulted))
276 292 return (ZPOOL_STATUS_FAULTED_DEV_R);
277 293 if (find_vdev_problem(nvroot, vdev_missing))
278 294 return (ZPOOL_STATUS_MISSING_DEV_R);
279 295 if (find_vdev_problem(nvroot, vdev_broken))
280 296 return (ZPOOL_STATUS_CORRUPT_LABEL_R);
281 297
282 298 /*
283 299 * Devices with errors
284 300 */
285 301 if (!isimport && find_vdev_problem(nvroot, vdev_errors))
286 302 return (ZPOOL_STATUS_FAILING_DEV);
287 303
288 304 /*
289 305 * Offlined devices
290 306 */
291 307 if (find_vdev_problem(nvroot, vdev_offlined))
292 308 return (ZPOOL_STATUS_OFFLINE_DEV);
|
↓ open down ↓ |
66 lines elided |
↑ open up ↑ |
293 309
294 310 /*
295 311 * Removed device
296 312 */
297 313 if (find_vdev_problem(nvroot, vdev_removed))
298 314 return (ZPOOL_STATUS_REMOVED_DEV);
299 315
300 316 /*
301 317 * Outdated, but usable, version
302 318 */
303 - if (version < SPA_VERSION)
319 + if (SPA_VERSION_IS_SUPPORTED(version) && version != SPA_VERSION)
304 320 return (ZPOOL_STATUS_VERSION_OLDER);
305 321
306 322 return (ZPOOL_STATUS_OK);
307 323 }
308 324
309 325 zpool_status_t
310 326 zpool_get_status(zpool_handle_t *zhp, char **msgid)
311 327 {
312 328 zpool_status_t ret = check_status(zhp->zpool_config, B_FALSE);
313 329
314 330 if (ret >= NMSGID)
315 331 *msgid = NULL;
316 332 else
317 333 *msgid = zfs_msgid_table[ret];
318 334
319 335 return (ret);
320 336 }
321 337
322 338 zpool_status_t
323 339 zpool_import_status(nvlist_t *config, char **msgid)
324 340 {
325 341 zpool_status_t ret = check_status(config, B_TRUE);
326 342
327 343 if (ret >= NMSGID)
328 344 *msgid = NULL;
329 345 else
330 346 *msgid = zfs_msgid_table[ret];
331 347
332 348 return (ret);
333 349 }
334 350
335 351 static void
336 352 dump_ddt_stat(const ddt_stat_t *dds, int h)
337 353 {
338 354 char refcnt[6];
339 355 char blocks[6], lsize[6], psize[6], dsize[6];
340 356 char ref_blocks[6], ref_lsize[6], ref_psize[6], ref_dsize[6];
341 357
342 358 if (dds == NULL || dds->dds_blocks == 0)
343 359 return;
344 360
345 361 if (h == -1)
346 362 (void) strcpy(refcnt, "Total");
347 363 else
348 364 zfs_nicenum(1ULL << h, refcnt, sizeof (refcnt));
349 365
350 366 zfs_nicenum(dds->dds_blocks, blocks, sizeof (blocks));
351 367 zfs_nicenum(dds->dds_lsize, lsize, sizeof (lsize));
352 368 zfs_nicenum(dds->dds_psize, psize, sizeof (psize));
353 369 zfs_nicenum(dds->dds_dsize, dsize, sizeof (dsize));
354 370 zfs_nicenum(dds->dds_ref_blocks, ref_blocks, sizeof (ref_blocks));
355 371 zfs_nicenum(dds->dds_ref_lsize, ref_lsize, sizeof (ref_lsize));
356 372 zfs_nicenum(dds->dds_ref_psize, ref_psize, sizeof (ref_psize));
357 373 zfs_nicenum(dds->dds_ref_dsize, ref_dsize, sizeof (ref_dsize));
358 374
359 375 (void) printf("%6s %6s %5s %5s %5s %6s %5s %5s %5s\n",
360 376 refcnt,
361 377 blocks, lsize, psize, dsize,
362 378 ref_blocks, ref_lsize, ref_psize, ref_dsize);
363 379 }
364 380
365 381 /*
366 382 * Print the DDT histogram and the column totals.
367 383 */
368 384 void
369 385 zpool_dump_ddt(const ddt_stat_t *dds_total, const ddt_histogram_t *ddh)
370 386 {
371 387 int h;
372 388
373 389 (void) printf("\n");
374 390
375 391 (void) printf("bucket "
376 392 " allocated "
377 393 " referenced \n");
378 394 (void) printf("______ "
379 395 "______________________________ "
380 396 "______________________________\n");
381 397
382 398 (void) printf("%6s %6s %5s %5s %5s %6s %5s %5s %5s\n",
383 399 "refcnt",
384 400 "blocks", "LSIZE", "PSIZE", "DSIZE",
385 401 "blocks", "LSIZE", "PSIZE", "DSIZE");
386 402
387 403 (void) printf("%6s %6s %5s %5s %5s %6s %5s %5s %5s\n",
388 404 "------",
389 405 "------", "-----", "-----", "-----",
390 406 "------", "-----", "-----", "-----");
391 407
392 408 for (h = 0; h < 64; h++)
393 409 dump_ddt_stat(&ddh->ddh_stat[h], h);
394 410
395 411 dump_ddt_stat(dds_total, -1);
396 412
397 413 (void) printf("\n");
398 414 }
|
↓ open down ↓ |
85 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX