xref: /illumos-gate/usr/src/cmd/fm/schemes/zfs/scheme.c (revision 19397407)
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 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% 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 (NULL);
107 
108 	for (c = 0; c < children; c++)
109 		if ((ret = find_vdev_iter(child[c], search)) != 0)
110 			return (ret);
111 
112 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE,
113 	    &child, &children) != 0)
114 		return (NULL);
115 
116 	for (c = 0; c < children; c++)
117 		if ((ret = find_vdev_iter(child[c], search)) != 0)
118 			return (ret);
119 
120 	return (NULL);
121 }
122 
123 static nvlist_t *
124 find_vdev(zpool_handle_t *zhp, uint64_t guid)
125 {
126 	nvlist_t *config, *nvroot;
127 
128 	config = zpool_get_config(zhp, NULL);
129 
130 	(void) nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvroot);
131 
132 	return (find_vdev_iter(nvroot, guid));
133 }
134 
135 int
136 fmd_fmri_present(nvlist_t *nvl)
137 {
138 	uint64_t pool_guid, vdev_guid;
139 	cbdata_t cb;
140 	int ret;
141 
142 	(void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid);
143 
144 	cb.cb_guid = pool_guid;
145 	cb.cb_pool = NULL;
146 
147 	if (zpool_iter(g_zfs, find_pool, &cb) != 1)
148 		return (0);
149 
150 	if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) {
151 		zpool_close(cb.cb_pool);
152 		return (1);
153 	}
154 
155 	ret = (find_vdev(cb.cb_pool, vdev_guid) != NULL);
156 
157 	zpool_close(cb.cb_pool);
158 
159 	return (ret);
160 }
161 
162 int
163 fmd_fmri_unusable(nvlist_t *nvl)
164 {
165 	uint64_t pool_guid, vdev_guid;
166 	cbdata_t cb;
167 	nvlist_t *vd;
168 	int ret;
169 
170 	(void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid);
171 
172 	cb.cb_guid = pool_guid;
173 	cb.cb_pool = NULL;
174 
175 	if (zpool_iter(g_zfs, find_pool, &cb) != 1)
176 		return (1);
177 
178 	if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) {
179 		ret = (zpool_get_state(cb.cb_pool) == POOL_STATE_UNAVAIL);
180 		zpool_close(cb.cb_pool);
181 		return (ret);
182 	}
183 
184 	vd = find_vdev(cb.cb_pool, vdev_guid);
185 	if (vd == NULL) {
186 		ret = 1;
187 	} else {
188 		vdev_stat_t *vs;
189 		uint_t c;
190 
191 		(void) nvlist_lookup_uint64_array(vd, ZPOOL_CONFIG_STATS,
192 		    (uint64_t **)&vs, &c);
193 
194 		ret = (vs->vs_state < VDEV_STATE_DEGRADED);
195 	}
196 
197 	zpool_close(cb.cb_pool);
198 
199 	return (ret);
200 }
201 
202 int
203 fmd_fmri_init(void)
204 {
205 	g_zfs = libzfs_init();
206 
207 	if (g_zfs == NULL)
208 		return (-1);
209 	else
210 		return (0);
211 }
212 
213 void
214 fmd_fmri_fini(void)
215 {
216 	if (g_zfs)
217 		libzfs_fini(g_zfs);
218 }
219