15913Sperrin /*
25913Sperrin  * CDDL HEADER START
35913Sperrin  *
45913Sperrin  * The contents of this file are subject to the terms of the
55913Sperrin  * Common Development and Distribution License (the "License").
65913Sperrin  * You may not use this file except in compliance with the License.
75913Sperrin  *
85913Sperrin  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95913Sperrin  * or http://www.opensolaris.org/os/licensing.
105913Sperrin  * See the License for the specific language governing permissions
115913Sperrin  * and limitations under the License.
125913Sperrin  *
135913Sperrin  * When distributing Covered Code, include this CDDL HEADER in each
145913Sperrin  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155913Sperrin  * If applicable, add the following below this CDDL HEADER, with the
165913Sperrin  * fields enclosed by brackets "[]" replaced with your own identifying
175913Sperrin  * information: Portions Copyright [yyyy] [name of copyright owner]
185913Sperrin  *
195913Sperrin  * CDDL HEADER END
205913Sperrin  */
215913Sperrin /*
2211727SVictor.Latushkin@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
235913Sperrin  * Use is subject to license terms.
245913Sperrin  */
255913Sperrin 
265913Sperrin /*
275913Sperrin  * This file is intended for functions that ought to be common between user
285913Sperrin  * land (libzfs) and the kernel. When many common routines need to be shared
295913Sperrin  * then a separate file should to be created.
305913Sperrin  */
315913Sperrin 
325913Sperrin #if defined(_KERNEL)
335913Sperrin #include <sys/systm.h>
3410921STim.Haley@Sun.COM #else
3510921STim.Haley@Sun.COM #include <string.h>
365913Sperrin #endif
375913Sperrin 
385913Sperrin #include <sys/types.h>
395913Sperrin #include <sys/fs/zfs.h>
4010921STim.Haley@Sun.COM #include <sys/int_limits.h>
415913Sperrin #include <sys/nvpair.h>
42*11935SMark.Shellenbaum@Sun.COM #include "zfs_comutil.h"
435913Sperrin 
445913Sperrin /*
455913Sperrin  * Are there allocatable vdevs?
465913Sperrin  */
475913Sperrin boolean_t
485913Sperrin zfs_allocatable_devs(nvlist_t *nv)
495913Sperrin {
505913Sperrin 	uint64_t is_log;
515913Sperrin 	uint_t c;
525913Sperrin 	nvlist_t **child;
535913Sperrin 	uint_t children;
545913Sperrin 
555913Sperrin 	if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN,
565913Sperrin 	    &child, &children) != 0) {
575913Sperrin 		return (B_FALSE);
585913Sperrin 	}
595913Sperrin 	for (c = 0; c < children; c++) {
605913Sperrin 		is_log = 0;
615913Sperrin 		(void) nvlist_lookup_uint64(child[c], ZPOOL_CONFIG_IS_LOG,
625913Sperrin 		    &is_log);
635913Sperrin 		if (!is_log)
645913Sperrin 			return (B_TRUE);
655913Sperrin 	}
665913Sperrin 	return (B_FALSE);
675913Sperrin }
6810921STim.Haley@Sun.COM 
6910921STim.Haley@Sun.COM void
7010921STim.Haley@Sun.COM zpool_get_rewind_policy(nvlist_t *nvl, zpool_rewind_policy_t *zrpp)
7110921STim.Haley@Sun.COM {
7210921STim.Haley@Sun.COM 	nvlist_t *policy;
7310921STim.Haley@Sun.COM 	nvpair_t *elem;
7410921STim.Haley@Sun.COM 	char *nm;
7510921STim.Haley@Sun.COM 
7610921STim.Haley@Sun.COM 	/* Defaults */
7710921STim.Haley@Sun.COM 	zrpp->zrp_request = ZPOOL_NO_REWIND;
7810921STim.Haley@Sun.COM 	zrpp->zrp_maxmeta = 0;
7911727SVictor.Latushkin@Sun.COM 	zrpp->zrp_maxdata = UINT64_MAX;
8010921STim.Haley@Sun.COM 	zrpp->zrp_txg = UINT64_MAX;
8110921STim.Haley@Sun.COM 
8210921STim.Haley@Sun.COM 	if (nvl == NULL)
8310921STim.Haley@Sun.COM 		return;
8410921STim.Haley@Sun.COM 
8510921STim.Haley@Sun.COM 	elem = NULL;
8610921STim.Haley@Sun.COM 	while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
8710921STim.Haley@Sun.COM 		nm = nvpair_name(elem);
8810921STim.Haley@Sun.COM 		if (strcmp(nm, ZPOOL_REWIND_POLICY) == 0) {
8910921STim.Haley@Sun.COM 			if (nvpair_value_nvlist(elem, &policy) == 0)
9010921STim.Haley@Sun.COM 				zpool_get_rewind_policy(policy, zrpp);
9110921STim.Haley@Sun.COM 			return;
9210921STim.Haley@Sun.COM 		} else if (strcmp(nm, ZPOOL_REWIND_REQUEST) == 0) {
9311727SVictor.Latushkin@Sun.COM 			if (nvpair_value_uint32(elem, &zrpp->zrp_request) == 0)
9411727SVictor.Latushkin@Sun.COM 				if (zrpp->zrp_request & ~ZPOOL_REWIND_POLICIES)
9510921STim.Haley@Sun.COM 					zrpp->zrp_request = ZPOOL_NO_REWIND;
9610921STim.Haley@Sun.COM 		} else if (strcmp(nm, ZPOOL_REWIND_REQUEST_TXG) == 0) {
9710921STim.Haley@Sun.COM 			(void) nvpair_value_uint64(elem, &zrpp->zrp_txg);
9810921STim.Haley@Sun.COM 		} else if (strcmp(nm, ZPOOL_REWIND_META_THRESH) == 0) {
9911727SVictor.Latushkin@Sun.COM 			(void) nvpair_value_uint64(elem, &zrpp->zrp_maxmeta);
10010921STim.Haley@Sun.COM 		} else if (strcmp(nm, ZPOOL_REWIND_DATA_THRESH) == 0) {
10111727SVictor.Latushkin@Sun.COM 			(void) nvpair_value_uint64(elem, &zrpp->zrp_maxdata);
10210921STim.Haley@Sun.COM 		}
10310921STim.Haley@Sun.COM 	}
10411727SVictor.Latushkin@Sun.COM 	if (zrpp->zrp_request == 0)
10511727SVictor.Latushkin@Sun.COM 		zrpp->zrp_request = ZPOOL_NO_REWIND;
10610921STim.Haley@Sun.COM }
107*11935SMark.Shellenbaum@Sun.COM 
108*11935SMark.Shellenbaum@Sun.COM typedef struct zfs_version_spa_map {
109*11935SMark.Shellenbaum@Sun.COM 	int	version_zpl;
110*11935SMark.Shellenbaum@Sun.COM 	int	version_spa;
111*11935SMark.Shellenbaum@Sun.COM } zfs_version_spa_map_t;
112*11935SMark.Shellenbaum@Sun.COM 
113*11935SMark.Shellenbaum@Sun.COM /*
114*11935SMark.Shellenbaum@Sun.COM  * Keep this table in monotonically increasing version number order.
115*11935SMark.Shellenbaum@Sun.COM  */
116*11935SMark.Shellenbaum@Sun.COM static zfs_version_spa_map_t zfs_version_table[] = {
117*11935SMark.Shellenbaum@Sun.COM 	{ZPL_VERSION_INITIAL, SPA_VERSION_INITIAL},
118*11935SMark.Shellenbaum@Sun.COM 	{ZPL_VERSION_DIRENT_TYPE, SPA_VERSION_INITIAL},
119*11935SMark.Shellenbaum@Sun.COM 	{ZPL_VERSION_FUID, SPA_VERSION_FUID},
120*11935SMark.Shellenbaum@Sun.COM 	{ZPL_VERSION_USERSPACE, SPA_VERSION_USERSPACE},
121*11935SMark.Shellenbaum@Sun.COM 	{ZPL_VERSION_SA, SPA_VERSION_SA},
122*11935SMark.Shellenbaum@Sun.COM 	{0, 0}
123*11935SMark.Shellenbaum@Sun.COM };
124*11935SMark.Shellenbaum@Sun.COM 
125*11935SMark.Shellenbaum@Sun.COM /*
126*11935SMark.Shellenbaum@Sun.COM  * Return the max zpl version for a corresponding spa version
127*11935SMark.Shellenbaum@Sun.COM  * -1 is returned if no mapping exists.
128*11935SMark.Shellenbaum@Sun.COM  */
129*11935SMark.Shellenbaum@Sun.COM int
130*11935SMark.Shellenbaum@Sun.COM zfs_zpl_version_map(int spa_version)
131*11935SMark.Shellenbaum@Sun.COM {
132*11935SMark.Shellenbaum@Sun.COM 	int i;
133*11935SMark.Shellenbaum@Sun.COM 	int version = -1;
134*11935SMark.Shellenbaum@Sun.COM 
135*11935SMark.Shellenbaum@Sun.COM 	for (i = 0; zfs_version_table[i].version_spa; i++) {
136*11935SMark.Shellenbaum@Sun.COM 		if (spa_version >= zfs_version_table[i].version_spa)
137*11935SMark.Shellenbaum@Sun.COM 			version = zfs_version_table[i].version_zpl;
138*11935SMark.Shellenbaum@Sun.COM 	}
139*11935SMark.Shellenbaum@Sun.COM 
140*11935SMark.Shellenbaum@Sun.COM 	return (version);
141*11935SMark.Shellenbaum@Sun.COM }
142*11935SMark.Shellenbaum@Sun.COM 
143*11935SMark.Shellenbaum@Sun.COM /*
144*11935SMark.Shellenbaum@Sun.COM  * Return the min spa version for a corresponding spa version
145*11935SMark.Shellenbaum@Sun.COM  * -1 is returned if no mapping exists.
146*11935SMark.Shellenbaum@Sun.COM  */
147*11935SMark.Shellenbaum@Sun.COM int
148*11935SMark.Shellenbaum@Sun.COM zfs_spa_version_map(int zpl_version)
149*11935SMark.Shellenbaum@Sun.COM {
150*11935SMark.Shellenbaum@Sun.COM 	int i;
151*11935SMark.Shellenbaum@Sun.COM 	int version = -1;
152*11935SMark.Shellenbaum@Sun.COM 
153*11935SMark.Shellenbaum@Sun.COM 	for (i = 0; zfs_version_table[i].version_zpl; i++) {
154*11935SMark.Shellenbaum@Sun.COM 		if (zfs_version_table[i].version_zpl >= zpl_version)
155*11935SMark.Shellenbaum@Sun.COM 			return (zfs_version_table[i].version_spa);
156*11935SMark.Shellenbaum@Sun.COM 	}
157*11935SMark.Shellenbaum@Sun.COM 
158*11935SMark.Shellenbaum@Sun.COM 	return (version);
159*11935SMark.Shellenbaum@Sun.COM }
160