xref: /illumos-gate/usr/src/cmd/fm/schemes/zfs/scheme.c (revision 990b4856d0eaada6f8140335733a1b1771ed2746)
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	"%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 (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 }
212