1 // SPDX-License-Identifier: CDDL-1.0
2 /*
3 * This file and its contents are supplied under the terms of the
4 * Common Development and Distribution License ("CDDL"), version 1.0.
5 * You may only use this file in accordance with the terms of version
6 * 1.0 of the CDDL.
7 *
8 * A full copy of the text of the CDDL should have accompanied this
9 * source. A copy of the CDDL is also available via the Internet at
10 * https://opensource.org/license/CDDL-1.0.
11 */
12 /*
13 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
14 * Use is subject to license terms.
15 */
16
17 /*
18 * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
19 */
20
21 #include <sys/zfs_context.h>
22 #include <sys/spa.h>
23 #include <sys/vdev_impl.h>
24 #include <sys/zio.h>
25 #include <sys/fs/zfs.h>
26
27 /*
28 * Virtual device vector for the pool's root vdev.
29 */
30
31 static uint64_t
vdev_root_core_tvds(vdev_t * vd)32 vdev_root_core_tvds(vdev_t *vd)
33 {
34 uint64_t tvds = 0;
35
36 for (uint64_t c = 0; c < vd->vdev_children; c++) {
37 vdev_t *cvd = vd->vdev_child[c];
38
39 if (!cvd->vdev_ishole && !cvd->vdev_islog &&
40 cvd->vdev_ops != &vdev_indirect_ops) {
41 tvds++;
42 }
43 }
44
45 return (tvds);
46 }
47
48 /*
49 * We should be able to tolerate one failure with absolutely no damage
50 * to our metadata. Two failures will take out space maps, a bunch of
51 * indirect block trees, meta dnodes, dnodes, etc. Probably not a happy
52 * place to live. When we get smarter, we can liberalize this policy.
53 * e.g. If we haven't lost two consecutive top-level vdevs, then we are
54 * probably fine. Adding bean counters during alloc/free can make this
55 * future guesswork more accurate.
56 */
57 static boolean_t
too_many_errors(vdev_t * vd,uint64_t numerrors)58 too_many_errors(vdev_t *vd, uint64_t numerrors)
59 {
60 uint64_t tvds;
61
62 if (numerrors == 0)
63 return (B_FALSE);
64
65 tvds = vdev_root_core_tvds(vd);
66 ASSERT3U(numerrors, <=, tvds);
67
68 if (numerrors == tvds)
69 return (B_TRUE);
70
71 return (numerrors > spa_missing_tvds_allowed(vd->vdev_spa));
72 }
73
74 static int
vdev_root_open(vdev_t * vd,uint64_t * asize,uint64_t * max_asize,uint64_t * ashift,uint64_t * pshift,cred_t * cr)75 vdev_root_open(vdev_t *vd, uint64_t *asize, uint64_t *max_asize,
76 uint64_t *ashift, uint64_t *pshift, cred_t *cr)
77 {
78 spa_t *spa = vd->vdev_spa;
79 int lasterror = 0;
80 int numerrors = 0;
81
82 if (vd->vdev_children == 0) {
83 vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
84 return (SET_ERROR(EINVAL));
85 }
86
87 vdev_open_children(vd, cr);
88
89 for (int c = 0; c < vd->vdev_children; c++) {
90 vdev_t *cvd = vd->vdev_child[c];
91
92 if (cvd->vdev_open_error && !cvd->vdev_islog &&
93 cvd->vdev_ops != &vdev_indirect_ops) {
94 lasterror = cvd->vdev_open_error;
95 numerrors++;
96 }
97 }
98
99 if (spa_load_state(spa) != SPA_LOAD_NONE)
100 spa_set_missing_tvds(spa, numerrors);
101
102 if (too_many_errors(vd, numerrors)) {
103 vd->vdev_stat.vs_aux = VDEV_AUX_NO_REPLICAS;
104 return (lasterror);
105 }
106
107 *asize = 0;
108 *max_asize = 0;
109 *ashift = 0;
110 *pshift = 0;
111
112 return (0);
113 }
114
115 static void
vdev_root_close(vdev_t * vd)116 vdev_root_close(vdev_t *vd)
117 {
118 for (int c = 0; c < vd->vdev_children; c++)
119 vdev_close(vd->vdev_child[c]);
120 }
121
122 static void
vdev_root_state_change(vdev_t * vd,int faulted,int degraded)123 vdev_root_state_change(vdev_t *vd, int faulted, int degraded)
124 {
125 if (too_many_errors(vd, faulted)) {
126 vdev_set_state(vd, B_FALSE, VDEV_STATE_CANT_OPEN,
127 VDEV_AUX_NO_REPLICAS);
128 } else if (degraded || faulted) {
129 vdev_set_state(vd, B_FALSE, VDEV_STATE_DEGRADED, VDEV_AUX_NONE);
130 } else {
131 vdev_set_state(vd, B_FALSE, VDEV_STATE_HEALTHY, VDEV_AUX_NONE);
132 }
133 }
134
135 vdev_ops_t vdev_root_ops = {
136 .vdev_op_init = NULL,
137 .vdev_op_fini = NULL,
138 .vdev_op_open = vdev_root_open,
139 .vdev_op_close = vdev_root_close,
140 .vdev_op_psize_to_asize = vdev_default_asize,
141 .vdev_op_asize_to_psize = vdev_default_psize,
142 .vdev_op_min_asize = vdev_default_min_asize,
143 .vdev_op_min_alloc = NULL,
144 .vdev_op_io_start = NULL, /* not applicable to the root */
145 .vdev_op_io_done = NULL, /* not applicable to the root */
146 .vdev_op_state_change = vdev_root_state_change,
147 .vdev_op_need_resilver = NULL,
148 .vdev_op_hold = NULL,
149 .vdev_op_rele = NULL,
150 .vdev_op_remap = NULL,
151 .vdev_op_xlate = NULL,
152 .vdev_op_rebuild_asize = NULL,
153 .vdev_op_metaslab_init = NULL,
154 .vdev_op_config_generate = NULL,
155 .vdev_op_nparity = NULL,
156 .vdev_op_ndisks = NULL,
157 .vdev_op_type = VDEV_TYPE_ROOT, /* name of this vdev type */
158 .vdev_op_leaf = B_FALSE /* not a leaf vdev */
159 };
160