0
|
1 /*
|
|
2 * CDDL HEADER START
|
|
3 *
|
|
4 * The contents of this file are subject to the terms of the
|
|
5 * Common Development and Distribution License (the "License").
|
|
6 * You may not use this file except in compliance with the License.
|
|
7 *
|
|
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
9 * or http://www.opensolaris.org/os/licensing.
|
|
10 * See the License for the specific language governing permissions
|
|
11 * and limitations under the License.
|
|
12 *
|
|
13 * When distributing Covered Code, include this CDDL HEADER in each
|
|
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
15 * If applicable, add the following below this CDDL HEADER, with the
|
|
16 * fields enclosed by brackets "[]" replaced with your own identifying
|
|
17 * information: Portions Copyright [yyyy] [name of copyright owner]
|
|
18 *
|
|
19 * CDDL HEADER END
|
|
20 */
|
|
21 /*
|
|
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
|
|
23 * Use is subject to license terms.
|
|
24 */
|
|
25
|
|
26 #pragma ident "@(#)scheme.c 1.3 07/09/18 SMI"
|
|
27
|
|
28 #include <fm/fmd_fmri.h>
|
|
29 #include <strings.h>
|
|
30 #include <libzfs.h>
|
|
31
|
|
32 typedef struct cbdata {
|
|
33 uint64_t cb_guid;
|
|
34 zpool_handle_t *cb_pool;
|
|
35 } cbdata_t;
|
|
36
|
|
37 libzfs_handle_t *g_zfs;
|
|
38
|
|
39 static int
|
|
40 find_pool(zpool_handle_t *zhp, void *data)
|
|
41 {
|
|
42 cbdata_t *cbp = data;
|
|
43
|
|
44 if (zpool_get_prop_int(zhp, ZPOOL_PROP_GUID, NULL) == cbp->cb_guid) {
|
|
45 cbp->cb_pool = zhp;
|
|
46 return (1);
|
|
47 }
|
|
48
|
|
49 zpool_close(zhp);
|
|
50
|
|
51 return (0);
|
|
52 }
|
|
53
|
|
54 ssize_t
|
|
55 fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen)
|
|
56 {
|
|
57 uint64_t pool_guid, vdev_guid;
|
|
58 cbdata_t cb;
|
|
59 ssize_t len;
|
|
60 const char *name;
|
|
61 char guidbuf[64];
|
|
62
|
|
63 (void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid);
|
|
64
|
|
65 /*
|
|
66 * Attempt to convert the pool guid to a name.
|
|
67 */
|
|
68 cb.cb_guid = pool_guid;
|
|
69 cb.cb_pool = NULL;
|
|
70
|
|
71 if (zpool_iter(g_zfs, find_pool, &cb) == 1) {
|
|
72 name = zpool_get_name(cb.cb_pool);
|
|
73 } else {
|
|
74 (void) snprintf(guidbuf, sizeof (guidbuf), "%llx", pool_guid);
|
|
75 name = guidbuf;
|
|
76 }
|
|
77
|
|
78 if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) == 0)
|
|
79 len = snprintf(buf, buflen, "%s://pool=%s/vdev=%llx",
|
|
80 FM_FMRI_SCHEME_ZFS, name, vdev_guid);
|
|
81 else
|
|
82 len = snprintf(buf, buflen, "%s://pool=%s",
|
|
83 FM_FMRI_SCHEME_ZFS, name);
|
|
84
|
|
85 if (cb.cb_pool)
|
|
86 zpool_close(cb.cb_pool);
|
|
87
|
|
88 return (len);
|
|
89 }
|
|
90
|
|
91 static nvlist_t *
|
|
92 find_vdev_iter(nvlist_t *nv, uint64_t search)
|
|
93 {
|
|
94 uint_t c, children;
|
|
95 nvlist_t **child;
|
|
96 uint64_t guid;
|
|
97 nvlist_t *ret;
|
|
98
|
|
99 (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid);
|
|
100
|
|
101 if (search == guid)
|
|
102 return (nv);
|
|
103
|
|
104 if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
|
|
105 &child, &children) != 0)
|
|
106 return (0);
|
|
107
|
|
108 for (c = 0; c < children; c++)
|
|
109 if ((ret = find_vdev_iter(child[c], search)) != 0)
|
|
110 return (ret);
|
|
111
|
|
112 return (NULL);
|
|
113 }
|
|
114
|
|
115 static nvlist_t *
|
|
116 find_vdev(zpool_handle_t *zhp, uint64_t guid)
|
|
117 {
|
|
118 nvlist_t *config;
|
|
119 nvlist_t *nvroot;
|
|
120
|
|
121 config = zpool_get_config(zhp, NULL);
|
|
122
|
|
123 (void) nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvroot);
|
|
124
|
|
125 return (find_vdev_iter(nvroot, guid));
|
|
126 }
|
|
127
|
|
128 int
|
|
129 fmd_fmri_present(nvlist_t *nvl)
|
|
130 {
|
|
131 uint64_t pool_guid, vdev_guid;
|
|
132 cbdata_t cb;
|
|
133 int ret;
|
|
134
|
|
135 (void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid);
|
|
136
|
|
137 cb.cb_guid = pool_guid;
|
|
138 cb.cb_pool = NULL;
|
|
139
|
|
140 if (zpool_iter(g_zfs, find_pool, &cb) != 1)
|
|
141 return (0);
|
|
142
|
|
143 if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) {
|
|
144 zpool_close(cb.cb_pool);
|
|
145 return (1);
|
|
146 }
|
|
147
|
|
148 ret = (find_vdev(cb.cb_pool, vdev_guid) != NULL);
|
|
149
|
|
150 zpool_close(cb.cb_pool);
|
|
151
|
|
152 return (ret);
|
|
153 }
|
|
154
|
|
155 int
|
|
156 fmd_fmri_unusable(nvlist_t *nvl)
|
|
157 {
|
|
158 uint64_t pool_guid, vdev_guid;
|
|
159 cbdata_t cb;
|
|
160 nvlist_t *vd;
|
|
161 int ret;
|
|
162
|
|
163 (void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid);
|
|
164
|
|
165 cb.cb_guid = pool_guid;
|
|
166 cb.cb_pool = NULL;
|
|
167
|
|
168 if (zpool_iter(g_zfs, find_pool, &cb) != 1)
|
|
169 return (1);
|
|
170
|
|
171 if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) {
|
|
172 ret = (zpool_get_state(cb.cb_pool) == POOL_STATE_UNAVAIL);
|
|
173 zpool_close(cb.cb_pool);
|
|
174 return (ret);
|
|
175 }
|
|
176
|
|
177 vd = find_vdev(cb.cb_pool, vdev_guid);
|
|
178 if (vd == NULL) {
|
|
179 ret = 1;
|
|
180 } else {
|
|
181 vdev_stat_t *vs;
|
|
182 uint_t c;
|
|
183
|
|
184 (void) nvlist_lookup_uint64_array(vd, ZPOOL_CONFIG_STATS,
|
|
185 (uint64_t **)&vs, &c);
|
|
186
|
|
187 ret = (vs->vs_state < VDEV_STATE_DEGRADED);
|
|
188 }
|
|
189
|
|
190 zpool_close(cb.cb_pool);
|
|
191
|
|
192 return (ret);
|
|
193 }
|
|
194
|
|
195 int
|
|
196 fmd_fmri_init(void)
|
|
197 {
|
|
198 g_zfs = libzfs_init();
|
|
199
|
|
200 if (g_zfs == NULL)
|
|
201 return (-1);
|
|
202 else
|
|
203 return (0);
|
|
204 }
|
|
205
|
|
206 void
|
|
207 fmd_fmri_fini(void)
|
|
208 {
|
|
209 if (g_zfs)
|
|
210 libzfs_fini(g_zfs);
|
|
211 }
|