]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - cddl/contrib/opensolaris/lib/libzfs/common/libzfs_config.c
MFC r296528: MFV r296527: 6659 nvlist_free(NULL) is a no-op
[FreeBSD/stable/10.git] / cddl / contrib / opensolaris / lib / libzfs / common / libzfs_config.c
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 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26
27 /*
28  * Copyright (c) 2012 by Delphix. All rights reserved.
29  * Copyright (c) 2015 by Syneto S.R.L. All rights reserved.
30  */
31
32 /*
33  * The pool configuration repository is stored in /etc/zfs/zpool.cache as a
34  * single packed nvlist.  While it would be nice to just read in this
35  * file from userland, this wouldn't work from a local zone.  So we have to have
36  * a zpool ioctl to return the complete configuration for all pools.  In the
37  * global zone, this will be identical to reading the file and unpacking it in
38  * userland.
39  */
40
41 #include <errno.h>
42 #include <sys/stat.h>
43 #include <fcntl.h>
44 #include <stddef.h>
45 #include <string.h>
46 #include <unistd.h>
47 #include <libintl.h>
48 #include <libuutil.h>
49
50 #include "libzfs_impl.h"
51
52 typedef struct config_node {
53         char            *cn_name;
54         nvlist_t        *cn_config;
55         uu_avl_node_t   cn_avl;
56 } config_node_t;
57
58 /* ARGSUSED */
59 static int
60 config_node_compare(const void *a, const void *b, void *unused)
61 {
62         int ret;
63
64         const config_node_t *ca = (config_node_t *)a;
65         const config_node_t *cb = (config_node_t *)b;
66
67         ret = strcmp(ca->cn_name, cb->cn_name);
68
69         if (ret < 0)
70                 return (-1);
71         else if (ret > 0)
72                 return (1);
73         else
74                 return (0);
75 }
76
77 void
78 namespace_clear(libzfs_handle_t *hdl)
79 {
80         if (hdl->libzfs_ns_avl) {
81                 config_node_t *cn;
82                 void *cookie = NULL;
83
84                 while ((cn = uu_avl_teardown(hdl->libzfs_ns_avl,
85                     &cookie)) != NULL) {
86                         nvlist_free(cn->cn_config);
87                         free(cn->cn_name);
88                         free(cn);
89                 }
90
91                 uu_avl_destroy(hdl->libzfs_ns_avl);
92                 hdl->libzfs_ns_avl = NULL;
93         }
94
95         if (hdl->libzfs_ns_avlpool) {
96                 uu_avl_pool_destroy(hdl->libzfs_ns_avlpool);
97                 hdl->libzfs_ns_avlpool = NULL;
98         }
99 }
100
101 /*
102  * Loads the pool namespace, or re-loads it if the cache has changed.
103  */
104 static int
105 namespace_reload(libzfs_handle_t *hdl)
106 {
107         nvlist_t *config;
108         config_node_t *cn;
109         nvpair_t *elem;
110         zfs_cmd_t zc = { 0 };
111         void *cookie;
112
113         if (hdl->libzfs_ns_gen == 0) {
114                 /*
115                  * This is the first time we've accessed the configuration
116                  * cache.  Initialize the AVL tree and then fall through to the
117                  * common code.
118                  */
119                 if ((hdl->libzfs_ns_avlpool = uu_avl_pool_create("config_pool",
120                     sizeof (config_node_t),
121                     offsetof(config_node_t, cn_avl),
122                     config_node_compare, UU_DEFAULT)) == NULL)
123                         return (no_memory(hdl));
124
125                 if ((hdl->libzfs_ns_avl = uu_avl_create(hdl->libzfs_ns_avlpool,
126                     NULL, UU_DEFAULT)) == NULL)
127                         return (no_memory(hdl));
128         }
129
130         if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0)
131                 return (-1);
132
133         for (;;) {
134                 zc.zc_cookie = hdl->libzfs_ns_gen;
135                 if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CONFIGS, &zc) != 0) {
136                         switch (errno) {
137                         case EEXIST:
138                                 /*
139                                  * The namespace hasn't changed.
140                                  */
141                                 zcmd_free_nvlists(&zc);
142                                 return (0);
143
144                         case ENOMEM:
145                                 if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
146                                         zcmd_free_nvlists(&zc);
147                                         return (-1);
148                                 }
149                                 break;
150
151                         default:
152                                 zcmd_free_nvlists(&zc);
153                                 return (zfs_standard_error(hdl, errno,
154                                     dgettext(TEXT_DOMAIN, "failed to read "
155                                     "pool configuration")));
156                         }
157                 } else {
158                         hdl->libzfs_ns_gen = zc.zc_cookie;
159                         break;
160                 }
161         }
162
163         if (zcmd_read_dst_nvlist(hdl, &zc, &config) != 0) {
164                 zcmd_free_nvlists(&zc);
165                 return (-1);
166         }
167
168         zcmd_free_nvlists(&zc);
169
170         /*
171          * Clear out any existing configuration information.
172          */
173         cookie = NULL;
174         while ((cn = uu_avl_teardown(hdl->libzfs_ns_avl, &cookie)) != NULL) {
175                 nvlist_free(cn->cn_config);
176                 free(cn->cn_name);
177                 free(cn);
178         }
179
180         elem = NULL;
181         while ((elem = nvlist_next_nvpair(config, elem)) != NULL) {
182                 nvlist_t *child;
183                 uu_avl_index_t where;
184
185                 if ((cn = zfs_alloc(hdl, sizeof (config_node_t))) == NULL) {
186                         nvlist_free(config);
187                         return (-1);
188                 }
189
190                 if ((cn->cn_name = zfs_strdup(hdl,
191                     nvpair_name(elem))) == NULL) {
192                         free(cn);
193                         nvlist_free(config);
194                         return (-1);
195                 }
196
197                 verify(nvpair_value_nvlist(elem, &child) == 0);
198                 if (nvlist_dup(child, &cn->cn_config, 0) != 0) {
199                         free(cn->cn_name);
200                         free(cn);
201                         nvlist_free(config);
202                         return (no_memory(hdl));
203                 }
204                 verify(uu_avl_find(hdl->libzfs_ns_avl, cn, NULL, &where)
205                     == NULL);
206
207                 uu_avl_insert(hdl->libzfs_ns_avl, cn, where);
208         }
209
210         nvlist_free(config);
211         return (0);
212 }
213
214 /*
215  * Retrieve the configuration for the given pool.  The configuration is a nvlist
216  * describing the vdevs, as well as the statistics associated with each one.
217  */
218 nvlist_t *
219 zpool_get_config(zpool_handle_t *zhp, nvlist_t **oldconfig)
220 {
221         if (oldconfig)
222                 *oldconfig = zhp->zpool_old_config;
223         return (zhp->zpool_config);
224 }
225
226 /*
227  * Retrieves a list of enabled features and their refcounts and caches it in
228  * the pool handle.
229  */
230 nvlist_t *
231 zpool_get_features(zpool_handle_t *zhp)
232 {
233         nvlist_t *config, *features;
234
235         config = zpool_get_config(zhp, NULL);
236
237         if (config == NULL || !nvlist_exists(config,
238             ZPOOL_CONFIG_FEATURE_STATS)) {
239                 int error;
240                 boolean_t missing = B_FALSE;
241
242                 error = zpool_refresh_stats(zhp, &missing);
243
244                 if (error != 0 || missing)
245                         return (NULL);
246
247                 config = zpool_get_config(zhp, NULL);
248         }
249
250         if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_FEATURE_STATS,
251             &features) != 0)
252                 return (NULL);
253
254         return (features);
255 }
256
257 /*
258  * Refresh the vdev statistics associated with the given pool.  This is used in
259  * iostat to show configuration changes and determine the delta from the last
260  * time the function was called.  This function can fail, in case the pool has
261  * been destroyed.
262  */
263 int
264 zpool_refresh_stats(zpool_handle_t *zhp, boolean_t *missing)
265 {
266         zfs_cmd_t zc = { 0 };
267         int error;
268         nvlist_t *config;
269         libzfs_handle_t *hdl = zhp->zpool_hdl;
270
271         *missing = B_FALSE;
272         (void) strcpy(zc.zc_name, zhp->zpool_name);
273
274         if (zhp->zpool_config_size == 0)
275                 zhp->zpool_config_size = 1 << 16;
276
277         if (zcmd_alloc_dst_nvlist(hdl, &zc, zhp->zpool_config_size) != 0)
278                 return (-1);
279
280         for (;;) {
281                 if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_STATS,
282                     &zc) == 0) {
283                         /*
284                          * The real error is returned in the zc_cookie field.
285                          */
286                         error = zc.zc_cookie;
287                         break;
288                 }
289
290                 if (errno == ENOMEM) {
291                         if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) {
292                                 zcmd_free_nvlists(&zc);
293                                 return (-1);
294                         }
295                 } else {
296                         zcmd_free_nvlists(&zc);
297                         if (errno == ENOENT || errno == EINVAL)
298                                 *missing = B_TRUE;
299                         zhp->zpool_state = POOL_STATE_UNAVAIL;
300                         return (0);
301                 }
302         }
303
304         if (zcmd_read_dst_nvlist(hdl, &zc, &config) != 0) {
305                 zcmd_free_nvlists(&zc);
306                 return (-1);
307         }
308
309         zcmd_free_nvlists(&zc);
310
311         zhp->zpool_config_size = zc.zc_nvlist_dst_size;
312
313         if (zhp->zpool_config != NULL) {
314                 uint64_t oldtxg, newtxg;
315
316                 verify(nvlist_lookup_uint64(zhp->zpool_config,
317                     ZPOOL_CONFIG_POOL_TXG, &oldtxg) == 0);
318                 verify(nvlist_lookup_uint64(config,
319                     ZPOOL_CONFIG_POOL_TXG, &newtxg) == 0);
320
321                 nvlist_free(zhp->zpool_old_config);
322
323                 if (oldtxg != newtxg) {
324                         nvlist_free(zhp->zpool_config);
325                         zhp->zpool_old_config = NULL;
326                 } else {
327                         zhp->zpool_old_config = zhp->zpool_config;
328                 }
329         }
330
331         zhp->zpool_config = config;
332         if (error)
333                 zhp->zpool_state = POOL_STATE_UNAVAIL;
334         else
335                 zhp->zpool_state = POOL_STATE_ACTIVE;
336
337         return (0);
338 }
339
340 /*
341  * If the __ZFS_POOL_RESTRICT environment variable is set we only iterate over
342  * pools it lists.
343  *
344  * This is an undocumented feature for use during testing only.
345  *
346  * This function returns B_TRUE if the pool should be skipped
347  * during iteration.
348  */
349 static boolean_t
350 check_restricted(const char *poolname)
351 {
352         static boolean_t initialized = B_FALSE;
353         static char *restricted = NULL;
354
355         const char *cur, *end;
356         int len, namelen;
357
358         if (!initialized) {
359                 initialized = B_TRUE;
360                 restricted = getenv("__ZFS_POOL_RESTRICT");
361         }
362
363         if (NULL == restricted)
364                 return (B_FALSE);
365
366         cur = restricted;
367         namelen = strlen(poolname);
368         do {
369                 end = strchr(cur, ' ');
370                 len = (NULL == end) ? strlen(cur) : (end - cur);
371
372                 if (len == namelen && 0 == strncmp(cur, poolname, len)) {
373                         return (B_FALSE);
374                 }
375
376                 cur += (len + 1);
377         } while (NULL != end);
378
379         return (B_TRUE);
380 }
381
382 /*
383  * Iterate over all pools in the system.
384  */
385 int
386 zpool_iter(libzfs_handle_t *hdl, zpool_iter_f func, void *data)
387 {
388         config_node_t *cn;
389         zpool_handle_t *zhp;
390         int ret;
391
392         /*
393          * If someone makes a recursive call to zpool_iter(), we want to avoid
394          * refreshing the namespace because that will invalidate the parent
395          * context.  We allow recursive calls, but simply re-use the same
396          * namespace AVL tree.
397          */
398         if (!hdl->libzfs_pool_iter && namespace_reload(hdl) != 0)
399                 return (-1);
400
401         hdl->libzfs_pool_iter++;
402         for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL;
403             cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) {
404
405                 if (check_restricted(cn->cn_name))
406                         continue;
407
408                 if (zpool_open_silent(hdl, cn->cn_name, &zhp) != 0) {
409                         hdl->libzfs_pool_iter--;
410                         return (-1);
411                 }
412
413                 if (zhp == NULL)
414                         continue;
415
416                 if ((ret = func(zhp, data)) != 0) {
417                         hdl->libzfs_pool_iter--;
418                         return (ret);
419                 }
420         }
421         hdl->libzfs_pool_iter--;
422
423         return (0);
424 }
425
426 /*
427  * Iterate over root datasets, calling the given function for each.  The zfs
428  * handle passed each time must be explicitly closed by the callback.
429  */
430 int
431 zfs_iter_root(libzfs_handle_t *hdl, zfs_iter_f func, void *data)
432 {
433         config_node_t *cn;
434         zfs_handle_t *zhp;
435         int ret;
436
437         if (namespace_reload(hdl) != 0)
438                 return (-1);
439
440         for (cn = uu_avl_first(hdl->libzfs_ns_avl); cn != NULL;
441             cn = uu_avl_next(hdl->libzfs_ns_avl, cn)) {
442
443                 if (check_restricted(cn->cn_name))
444                         continue;
445
446                 if ((zhp = make_dataset_handle(hdl, cn->cn_name)) == NULL)
447                         continue;
448
449                 if ((ret = func(zhp, data)) != 0)
450                         return (ret);
451         }
452
453         return (0);
454 }