Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/cddl/usr.sbin/zfsd/vdev_iterator.cc
104148 views
1
/*-
2
* Copyright (c) 2011, 2012, 2013 Spectra Logic Corporation
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions, and the following disclaimer,
10
* without modification.
11
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
12
* substantially similar to the "NO WARRANTY" disclaimer below
13
* ("Disclaimer") and any redistribution must be conditioned upon
14
* including a substantially similar Disclaimer requirement for further
15
* binary redistribution.
16
*
17
* NO WARRANTY
18
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
21
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
* POSSIBILITY OF SUCH DAMAGES.
29
*
30
* Authors: Justin T. Gibbs (Spectra Logic Corporation)
31
*/
32
33
/**
34
* \file vdev_iterator.cc
35
*
36
* Implementation of the VdevIterator class.
37
*/
38
#include <sys/cdefs.h>
39
#include <sys/byteorder.h>
40
#include <sys/fs/zfs.h>
41
42
#include <stdint.h>
43
#include <syslog.h>
44
45
#include <libzfs.h>
46
47
#include <list>
48
#include <string>
49
50
#include <devdctl/exception.h>
51
#include <devdctl/guid.h>
52
53
#include "vdev.h"
54
#include "vdev_iterator.h"
55
#include "zfsd_exception.h"
56
57
/*============================ Namespace Control =============================*/
58
using DevdCtl::Guid;
59
60
/*=========================== Class Implementations ==========================*/
61
/*------------------------------- VdevIterator -------------------------------*/
62
VdevIterator::VdevIterator(zpool_handle_t *pool)
63
: m_poolConfig(zpool_get_config(pool, NULL))
64
{
65
Reset();
66
}
67
68
VdevIterator::VdevIterator(nvlist_t *poolConfig)
69
: m_poolConfig(poolConfig)
70
{
71
Reset();
72
}
73
74
void
75
VdevIterator::Reset()
76
{
77
nvlist_t *rootVdev;
78
nvlist **cache_child;
79
nvlist **spare_child;
80
int result;
81
uint_t cache_children;
82
uint_t spare_children;
83
84
result = nvlist_lookup_nvlist(m_poolConfig,
85
ZPOOL_CONFIG_VDEV_TREE,
86
&rootVdev);
87
if (result != 0)
88
throw ZfsdException(m_poolConfig, "Unable to extract "
89
"ZPOOL_CONFIG_VDEV_TREE from pool.");
90
m_vdevQueue.assign(1, rootVdev);
91
result = nvlist_lookup_nvlist_array(rootVdev,
92
ZPOOL_CONFIG_L2CACHE,
93
&cache_child,
94
&cache_children);
95
if (result == 0)
96
for (uint_t c = 0; c < cache_children; c++)
97
m_vdevQueue.push_back(cache_child[c]);
98
result = nvlist_lookup_nvlist_array(rootVdev,
99
ZPOOL_CONFIG_SPARES,
100
&spare_child,
101
&spare_children);
102
if (result == 0)
103
for (uint_t c = 0; c < spare_children; c++)
104
m_vdevQueue.push_back(spare_child[c]);
105
}
106
107
nvlist_t *
108
VdevIterator::Next()
109
{
110
nvlist_t *vdevConfig;
111
112
for (vdevConfig = NULL; !m_vdevQueue.empty();) {
113
nvlist_t **vdevChildren;
114
int result;
115
u_int numChildren;
116
117
vdevConfig = m_vdevQueue.front();
118
m_vdevQueue.pop_front();
119
120
/* Expand non-leaf vdevs. */
121
result = nvlist_lookup_nvlist_array(vdevConfig,
122
ZPOOL_CONFIG_CHILDREN,
123
&vdevChildren, &numChildren);
124
if (result != 0) {
125
/* leaf vdev */
126
break;
127
}
128
129
/*
130
* Insert children at the head of the queue to effect a
131
* depth first traversal of the tree.
132
*/
133
m_vdevQueue.insert(m_vdevQueue.begin(), vdevChildren,
134
vdevChildren + numChildren);
135
}
136
137
return (vdevConfig);
138
}
139
140
void
141
VdevIterator::Each(VdevCallback_t *callBack, void *callBackArg)
142
{
143
nvlist_t *vdevConfig;
144
145
Reset();
146
while ((vdevConfig = Next()) != NULL) {
147
Vdev vdev(m_poolConfig, vdevConfig);
148
149
if (callBack(vdev, callBackArg))
150
break;
151
}
152
}
153
154
nvlist_t *
155
VdevIterator::Find(Guid vdevGUID)
156
{
157
nvlist_t *vdevConfig;
158
159
Reset();
160
while ((vdevConfig = Next()) != NULL) {
161
Vdev vdev(m_poolConfig, vdevConfig);
162
163
if (vdev.GUID() == vdevGUID)
164
return (vdevConfig);
165
}
166
return (NULL);
167
}
168
169