xref: /illumos-gate/usr/src/common/zfs/zfs_comutil.c (revision 134a1f4e)
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 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * This file is intended for functions that ought to be common between user
28  * land (libzfs) and the kernel. When many common routines need to be shared
29  * then a separate file should to be created.
30  */
31 
32 #if defined(_KERNEL)
33 #include <sys/systm.h>
34 #else
35 #include <string.h>
36 #endif
37 
38 #include <sys/types.h>
39 #include <sys/fs/zfs.h>
40 #include <sys/int_limits.h>
41 #include <sys/nvpair.h>
42 #include "zfs_comutil.h"
43 
44 /*
45  * Are there allocatable vdevs?
46  */
47 boolean_t
48 zfs_allocatable_devs(nvlist_t *nv)
49 {
50 	uint64_t is_log;
51 	uint_t c;
52 	nvlist_t **child;
53 	uint_t children;
54 
55 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
56 	    &child, &children) != 0) {
57 		return (B_FALSE);
58 	}
59 	for (c = 0; c < children; c++) {
60 		is_log = 0;
61 		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
62 		    &is_log);
63 		if (!is_log)
64 			return (B_TRUE);
65 	}
66 	return (B_FALSE);
67 }
68 
69 void
70 zpool_get_rewind_policy(nvlist_t *nvl, zpool_rewind_policy_t *zrpp)
71 {
72 	nvlist_t *policy;
73 	nvpair_t *elem;
74 	char *nm;
75 
76 	/* Defaults */
77 	zrpp->zrp_request = ZPOOL_NO_REWIND;
78 	zrpp->zrp_maxmeta = 0;
79 	zrpp->zrp_maxdata = UINT64_MAX;
80 	zrpp->zrp_txg = UINT64_MAX;
81 
82 	if (nvl == NULL)
83 		return;
84 
85 	elem = NULL;
86 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
87 		nm = nvpair_name(elem);
88 		if (strcmp(nm, ZPOOL_REWIND_POLICY) == 0) {
89 			if (nvpair_value_nvlist(elem, &policy) == 0)
90 				zpool_get_rewind_policy(policy, zrpp);
91 			return;
92 		} else if (strcmp(nm, ZPOOL_REWIND_REQUEST) == 0) {
93 			if (nvpair_value_uint32(elem, &zrpp->zrp_request) == 0)
94 				if (zrpp->zrp_request & ~ZPOOL_REWIND_POLICIES)
95 					zrpp->zrp_request = ZPOOL_NO_REWIND;
96 		} else if (strcmp(nm, ZPOOL_REWIND_REQUEST_TXG) == 0) {
97 			(void) nvpair_value_uint64(elem, &zrpp->zrp_txg);
98 		} else if (strcmp(nm, ZPOOL_REWIND_META_THRESH) == 0) {
99 			(void) nvpair_value_uint64(elem, &zrpp->zrp_maxmeta);
100 		} else if (strcmp(nm, ZPOOL_REWIND_DATA_THRESH) == 0) {
101 			(void) nvpair_value_uint64(elem, &zrpp->zrp_maxdata);
102 		}
103 	}
104 	if (zrpp->zrp_request == 0)
105 		zrpp->zrp_request = ZPOOL_NO_REWIND;
106 }
107 
108 typedef struct zfs_version_spa_map {
109 	int	version_zpl;
110 	int	version_spa;
111 } zfs_version_spa_map_t;
112 
113 /*
114  * Keep this table in monotonically increasing version number order.
115  */
116 static zfs_version_spa_map_t zfs_version_table[] = {
117 	{ZPL_VERSION_INITIAL, SPA_VERSION_INITIAL},
118 	{ZPL_VERSION_DIRENT_TYPE, SPA_VERSION_INITIAL},
119 	{ZPL_VERSION_FUID, SPA_VERSION_FUID},
120 	{ZPL_VERSION_USERSPACE, SPA_VERSION_USERSPACE},
121 	{ZPL_VERSION_SA, SPA_VERSION_SA},
122 	{0, 0}
123 };
124 
125 /*
126  * Return the max zpl version for a corresponding spa version
127  * -1 is returned if no mapping exists.
128  */
129 int
130 zfs_zpl_version_map(int spa_version)
131 {
132 	int i;
133 	int version = -1;
134 
135 	for (i = 0; zfs_version_table[i].version_spa; i++) {
136 		if (spa_version >= zfs_version_table[i].version_spa)
137 			version = zfs_version_table[i].version_zpl;
138 	}
139 
140 	return (version);
141 }
142 
143 /*
144  * Return the min spa version for a corresponding spa version
145  * -1 is returned if no mapping exists.
146  */
147 int
148 zfs_spa_version_map(int zpl_version)
149 {
150 	int i;
151 	int version = -1;
152 
153 	for (i = 0; zfs_version_table[i].version_zpl; i++) {
154 		if (zfs_version_table[i].version_zpl >= zpl_version)
155 			return (zfs_version_table[i].version_spa);
156 	}
157 
158 	return (version);
159 }
160