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.
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.
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]
22 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2012 by Delphix. All rights reserved.
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.
33 #include <sys/systm.h>
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 #include <sys/zfs_ratelimit.h>
46 * Are there allocatable vdevs?
49 zfs_allocatable_devs(nvlist_t
*nv
)
56 if (nvlist_lookup_nvlist_array(nv
, ZPOOL_CONFIG_CHILDREN
,
57 &child
, &children
) != 0) {
60 for (c
= 0; c
< children
; c
++) {
62 (void) nvlist_lookup_uint64(child
[c
], ZPOOL_CONFIG_IS_LOG
,
71 zpool_get_rewind_policy(nvlist_t
*nvl
, zpool_rewind_policy_t
*zrpp
)
78 zrpp
->zrp_request
= ZPOOL_NO_REWIND
;
79 zrpp
->zrp_maxmeta
= 0;
80 zrpp
->zrp_maxdata
= UINT64_MAX
;
81 zrpp
->zrp_txg
= UINT64_MAX
;
87 while ((elem
= nvlist_next_nvpair(nvl
, elem
)) != NULL
) {
88 nm
= nvpair_name(elem
);
89 if (strcmp(nm
, ZPOOL_REWIND_POLICY
) == 0) {
90 if (nvpair_value_nvlist(elem
, &policy
) == 0)
91 zpool_get_rewind_policy(policy
, zrpp
);
93 } else if (strcmp(nm
, ZPOOL_REWIND_REQUEST
) == 0) {
94 if (nvpair_value_uint32(elem
, &zrpp
->zrp_request
) == 0)
95 if (zrpp
->zrp_request
& ~ZPOOL_REWIND_POLICIES
)
96 zrpp
->zrp_request
= ZPOOL_NO_REWIND
;
97 } else if (strcmp(nm
, ZPOOL_REWIND_REQUEST_TXG
) == 0) {
98 (void) nvpair_value_uint64(elem
, &zrpp
->zrp_txg
);
99 } else if (strcmp(nm
, ZPOOL_REWIND_META_THRESH
) == 0) {
100 (void) nvpair_value_uint64(elem
, &zrpp
->zrp_maxmeta
);
101 } else if (strcmp(nm
, ZPOOL_REWIND_DATA_THRESH
) == 0) {
102 (void) nvpair_value_uint64(elem
, &zrpp
->zrp_maxdata
);
105 if (zrpp
->zrp_request
== 0)
106 zrpp
->zrp_request
= ZPOOL_NO_REWIND
;
109 typedef struct zfs_version_spa_map
{
112 } zfs_version_spa_map_t
;
115 * Keep this table in monotonically increasing version number order.
117 static zfs_version_spa_map_t zfs_version_table
[] = {
118 {ZPL_VERSION_INITIAL
, SPA_VERSION_INITIAL
},
119 {ZPL_VERSION_DIRENT_TYPE
, SPA_VERSION_INITIAL
},
120 {ZPL_VERSION_FUID
, SPA_VERSION_FUID
},
121 {ZPL_VERSION_USERSPACE
, SPA_VERSION_USERSPACE
},
122 {ZPL_VERSION_SA
, SPA_VERSION_SA
},
127 * Return the max zpl version for a corresponding spa version
128 * -1 is returned if no mapping exists.
131 zfs_zpl_version_map(int spa_version
)
136 for (i
= 0; zfs_version_table
[i
].version_spa
; i
++) {
137 if (spa_version
>= zfs_version_table
[i
].version_spa
)
138 version
= zfs_version_table
[i
].version_zpl
;
145 * Return the min spa version for a corresponding spa version
146 * -1 is returned if no mapping exists.
149 zfs_spa_version_map(int zpl_version
)
154 for (i
= 0; zfs_version_table
[i
].version_zpl
; i
++) {
155 if (zfs_version_table
[i
].version_zpl
>= zpl_version
)
156 return (zfs_version_table
[i
].version_spa
);
163 * This is the table of legacy internal event names; it should not be modified.
164 * The internal events are now stored in the history log as strings.
166 const char *zfs_history_event_names
[ZFS_NUM_LEGACY_HISTORY_EVENTS
] = {
186 "destroy_begin_sync",
192 "permission who remove",
201 "filesystem version upgrade",
203 "refreservation set",
211 * Initialize rate limit struct
213 * rl: zfs_ratelimit_t struct
214 * burst: Number to allow in an interval before rate limiting
215 * interval: Interval time in seconds
218 zfs_ratelimit_init(zfs_ratelimit_t
*rl
, unsigned int *burst
,
219 unsigned int interval
)
223 rl
->interval
= interval
;
225 mutex_init(&rl
->lock
, NULL
, MUTEX_DEFAULT
, NULL
);
229 * Finalize rate limit struct
231 * rl: zfs_ratelimit_t struct
234 zfs_ratelimit_fini(zfs_ratelimit_t
*rl
)
236 mutex_destroy(&rl
->lock
);
240 * Re-implementation of the kernel's __ratelimit() function
242 * We had to write our own rate limiter because the kernel's __ratelimit()
243 * function annoyingly prints out how many times it rate limited to the kernel
244 * logs (and there's no way to turn it off):
246 * __ratelimit: 59 callbacks suppressed
248 * If the kernel ever allows us to disable these prints, we should go back to
249 * using __ratelimit() instead.
251 * Return values are the same as __ratelimit():
253 * 0: If we're rate limiting
254 * 1: If we're not rate limiting.
257 zfs_ratelimit(zfs_ratelimit_t
*rl
)
263 mutex_enter(&rl
->lock
);
266 elapsed
= now
- rl
->start
;
269 if (NSEC2SEC(elapsed
) >= rl
->interval
) {
273 if (rl
->count
>= *rl
->burst
) {
274 rc
= 0; /* We're ratelimiting */
277 mutex_exit(&rl
->lock
);
282 #if defined(_KERNEL) && defined(HAVE_SPL)
283 EXPORT_SYMBOL(zfs_allocatable_devs
);
284 EXPORT_SYMBOL(zpool_get_rewind_policy
);
285 EXPORT_SYMBOL(zfs_zpl_version_map
);
286 EXPORT_SYMBOL(zfs_spa_version_map
);
287 EXPORT_SYMBOL(zfs_history_event_names
);
288 EXPORT_SYMBOL(zfs_ratelimit_init
);
289 EXPORT_SYMBOL(zfs_ratelimit_fini
);
290 EXPORT_SYMBOL(zfs_ratelimit
);