xref: /illumos-gate/usr/src/lib/libzpool/common/kernel.c (revision dd50e0cc4cbe1474096300fe52e9855769c0d478)
1fa9e4066Sahrens /*
2fa9e4066Sahrens  * CDDL HEADER START
3fa9e4066Sahrens  *
4fa9e4066Sahrens  * The contents of this file are subject to the terms of the
5ea8dc4b6Seschrock  * Common Development and Distribution License (the "License").
6ea8dc4b6Seschrock  * You may not use this file except in compliance with the License.
7fa9e4066Sahrens  *
8fa9e4066Sahrens  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fa9e4066Sahrens  * or http://www.opensolaris.org/os/licensing.
10fa9e4066Sahrens  * See the License for the specific language governing permissions
11fa9e4066Sahrens  * and limitations under the License.
12fa9e4066Sahrens  *
13fa9e4066Sahrens  * When distributing Covered Code, include this CDDL HEADER in each
14fa9e4066Sahrens  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fa9e4066Sahrens  * If applicable, add the following below this CDDL HEADER, with the
16fa9e4066Sahrens  * fields enclosed by brackets "[]" replaced with your own identifying
17fa9e4066Sahrens  * information: Portions Copyright [yyyy] [name of copyright owner]
18fa9e4066Sahrens  *
19fa9e4066Sahrens  * CDDL HEADER END
20fa9e4066Sahrens  */
21fa9e4066Sahrens /*
22c99e4bdcSChris Kirby  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
239a686fbcSPaul Dagnelie  * Copyright (c) 2012, 2015 by Delphix. All rights reserved.
24d8ab6e12SDon Brady  * Copyright 2020 Joyent, Inc.
25f06dce2cSAndrew Stormont  * Copyright 2017 RackTop Systems.
26fa9e4066Sahrens  */
27fa9e4066Sahrens 
28fa9e4066Sahrens #include <assert.h>
29c9431fa1Sahl #include <fcntl.h>
30fa9e4066Sahrens #include <poll.h>
31fa9e4066Sahrens #include <stdio.h>
32fa9e4066Sahrens #include <stdlib.h>
33c9431fa1Sahl #include <string.h>
34c9431fa1Sahl #include <zlib.h>
35df15e419SMatthew Ahrens #include <libgen.h>
36fa9e4066Sahrens #include <sys/spa.h>
37c9431fa1Sahl #include <sys/stat.h>
38fa9e4066Sahrens #include <sys/processor.h>
39c9431fa1Sahl #include <sys/zfs_context.h>
403b2aab18SMatthew Ahrens #include <sys/rrwlock.h>
41c9431fa1Sahl #include <sys/zmod.h>
4295173954Sek #include <sys/utsname.h>
435679c89fSjv #include <sys/systeminfo.h>
44d8ab6e12SDon Brady #include <libzutil.h>
45eb633035STom Caputi #include <sys/crypto/common.h>
46eb633035STom Caputi #include <sys/crypto/impl.h>
47eb633035STom Caputi #include <sys/crypto/api.h>
48eb633035STom Caputi #include <sys/sha2.h>
49eb633035STom Caputi #include <crypto/aes/aes_impl.h>
505ad82045Snd 
51f06dce2cSAndrew Stormont extern void system_taskq_init(void);
52f06dce2cSAndrew Stormont extern void system_taskq_fini(void);
53f06dce2cSAndrew Stormont 
54fa9e4066Sahrens /*
55fa9e4066Sahrens  * Emulation of kernel services in userland.
56fa9e4066Sahrens  */
57fa9e4066Sahrens 
58f06dce2cSAndrew Stormont pgcnt_t physmem;
59fa9e4066Sahrens vnode_t *rootdir = (vnode_t *)0xabcd1234;
605679c89fSjv char hw_serial[HW_HOSTID_LEN];
61283b8460SGeorge.Wilson kmutex_t cpu_lock;
6294dd93aeSGeorge Wilson vmem_t *zio_arena = NULL;
6395173954Sek 
64df15e419SMatthew Ahrens /* If set, all blocks read will be copied to the specified directory. */
65df15e419SMatthew Ahrens char *vn_dumpdir = NULL;
66df15e419SMatthew Ahrens 
6795173954Sek struct utsname utsname = {
6895173954Sek 	"userland", "libzpool", "1", "1", "na"
6995173954Sek };
70fa9e4066Sahrens 
71fa9e4066Sahrens /*
72fa9e4066Sahrens  * =========================================================================
73fa9e4066Sahrens  * vnode operations
74fa9e4066Sahrens  * =========================================================================
75fa9e4066Sahrens  */
76fa9e4066Sahrens /*
77fa9e4066Sahrens  * Note: for the xxxat() versions of these functions, we assume that the
78fa9e4066Sahrens  * starting vp is always rootdir (which is true for spa_directory.c, the only
79fa9e4066Sahrens  * ZFS consumer of these interfaces).  We assert this is true, and then emulate
80fa9e4066Sahrens  * them by adding '/' in front of the path.
81fa9e4066Sahrens  */
82fa9e4066Sahrens 
83fa9e4066Sahrens /*ARGSUSED*/
84fa9e4066Sahrens int
85fa9e4066Sahrens vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
86fa9e4066Sahrens {
87fa9e4066Sahrens 	int fd;
88df15e419SMatthew Ahrens 	int dump_fd;
89fa9e4066Sahrens 	vnode_t *vp;
90fa9e4066Sahrens 	int old_umask;
91fa9e4066Sahrens 	char realpath[MAXPATHLEN];
92fa9e4066Sahrens 	struct stat64 st;
93fa9e4066Sahrens 
94fa9e4066Sahrens 	/*
95fa9e4066Sahrens 	 * If we're accessing a real disk from userland, we need to use
96fa9e4066Sahrens 	 * the character interface to avoid caching.  This is particularly
97fa9e4066Sahrens 	 * important if we're trying to look at a real in-kernel storage
98fa9e4066Sahrens 	 * pool from userland, e.g. via zdb, because otherwise we won't
99fa9e4066Sahrens 	 * see the changes occurring under the segmap cache.
100fa9e4066Sahrens 	 * On the other hand, the stupid character device returns zero
101fa9e4066Sahrens 	 * for its size.  So -- gag -- we open the block device to get
102fa9e4066Sahrens 	 * its size, and remember it for subsequent VOP_GETATTR().
103fa9e4066Sahrens 	 */
104fa9e4066Sahrens 	if (strncmp(path, "/dev/", 5) == 0) {
105fa9e4066Sahrens 		char *dsk;
106fa9e4066Sahrens 		fd = open64(path, O_RDONLY);
107fa9e4066Sahrens 		if (fd == -1)
108fa9e4066Sahrens 			return (errno);
109fa9e4066Sahrens 		if (fstat64(fd, &st) == -1) {
110fa9e4066Sahrens 			close(fd);
111fa9e4066Sahrens 			return (errno);
112fa9e4066Sahrens 		}
113fa9e4066Sahrens 		close(fd);
114fa9e4066Sahrens 		(void) sprintf(realpath, "%s", path);
115fa9e4066Sahrens 		dsk = strstr(path, "/dsk/");
116fa9e4066Sahrens 		if (dsk != NULL)
117fa9e4066Sahrens 			(void) sprintf(realpath + (dsk - path) + 1, "r%s",
118fa9e4066Sahrens 			    dsk + 1);
119fa9e4066Sahrens 	} else {
120fa9e4066Sahrens 		(void) sprintf(realpath, "%s", path);
121fa9e4066Sahrens 		if (!(flags & FCREAT) && stat64(realpath, &st) == -1)
122fa9e4066Sahrens 			return (errno);
123fa9e4066Sahrens 	}
124fa9e4066Sahrens 
125fa9e4066Sahrens 	if (flags & FCREAT)
126fa9e4066Sahrens 		old_umask = umask(0);
127fa9e4066Sahrens 
128fa9e4066Sahrens 	/*
129fa9e4066Sahrens 	 * The construct 'flags - FREAD' conveniently maps combinations of
130fa9e4066Sahrens 	 * FREAD and FWRITE to the corresponding O_RDONLY, O_WRONLY, and O_RDWR.
131fa9e4066Sahrens 	 */
132fa9e4066Sahrens 	fd = open64(realpath, flags - FREAD, mode);
133fa9e4066Sahrens 
134fa9e4066Sahrens 	if (flags & FCREAT)
135fa9e4066Sahrens 		(void) umask(old_umask);
136fa9e4066Sahrens 
137df15e419SMatthew Ahrens 	if (vn_dumpdir != NULL) {
138df15e419SMatthew Ahrens 		char dumppath[MAXPATHLEN];
139df15e419SMatthew Ahrens 		(void) snprintf(dumppath, sizeof (dumppath),
140df15e419SMatthew Ahrens 		    "%s/%s", vn_dumpdir, basename(realpath));
141df15e419SMatthew Ahrens 		dump_fd = open64(dumppath, O_CREAT | O_WRONLY, 0666);
142df15e419SMatthew Ahrens 		if (dump_fd == -1)
143df15e419SMatthew Ahrens 			return (errno);
144df15e419SMatthew Ahrens 	} else {
145df15e419SMatthew Ahrens 		dump_fd = -1;
146df15e419SMatthew Ahrens 	}
147df15e419SMatthew Ahrens 
148fa9e4066Sahrens 	if (fd == -1)
149fa9e4066Sahrens 		return (errno);
150fa9e4066Sahrens 
151fa9e4066Sahrens 	if (fstat64(fd, &st) == -1) {
152fa9e4066Sahrens 		close(fd);
153fa9e4066Sahrens 		return (errno);
154fa9e4066Sahrens 	}
155fa9e4066Sahrens 
156fa9e4066Sahrens 	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
157fa9e4066Sahrens 
158fa9e4066Sahrens 	*vpp = vp = umem_zalloc(sizeof (vnode_t), UMEM_NOFAIL);
159fa9e4066Sahrens 
160fa9e4066Sahrens 	vp->v_fd = fd;
161fa9e4066Sahrens 	vp->v_size = st.st_size;
162fa9e4066Sahrens 	vp->v_path = spa_strdup(path);
163df15e419SMatthew Ahrens 	vp->v_dump_fd = dump_fd;
164fa9e4066Sahrens 
165fa9e4066Sahrens 	return (0);
166fa9e4066Sahrens }
167fa9e4066Sahrens 
168da6c28aaSamw /*ARGSUSED*/
169fa9e4066Sahrens int
170fa9e4066Sahrens vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
171da6c28aaSamw     int x3, vnode_t *startvp, int fd)
172fa9e4066Sahrens {
173fa9e4066Sahrens 	char *realpath = umem_alloc(strlen(path) + 2, UMEM_NOFAIL);
174fa9e4066Sahrens 	int ret;
175fa9e4066Sahrens 
176fa9e4066Sahrens 	ASSERT(startvp == rootdir);
177fa9e4066Sahrens 	(void) sprintf(realpath, "/%s", path);
178fa9e4066Sahrens 
179da6c28aaSamw 	/* fd ignored for now, need if want to simulate nbmand support */
180fa9e4066Sahrens 	ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
181fa9e4066Sahrens 
182fa9e4066Sahrens 	umem_free(realpath, strlen(path) + 2);
183fa9e4066Sahrens 
184fa9e4066Sahrens 	return (ret);
185fa9e4066Sahrens }
186fa9e4066Sahrens 
187fa9e4066Sahrens /*ARGSUSED*/
188fa9e4066Sahrens int
189fa9e4066Sahrens vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
1909a686fbcSPaul Dagnelie     int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp)
191fa9e4066Sahrens {
192fa9e4066Sahrens 	ssize_t iolen, split;
193fa9e4066Sahrens 
194fa9e4066Sahrens 	if (uio == UIO_READ) {
195fa9e4066Sahrens 		iolen = pread64(vp->v_fd, addr, len, offset);
196df15e419SMatthew Ahrens 		if (vp->v_dump_fd != -1) {
197df15e419SMatthew Ahrens 			int status =
198df15e419SMatthew Ahrens 			    pwrite64(vp->v_dump_fd, addr, iolen, offset);
199df15e419SMatthew Ahrens 			ASSERT(status != -1);
200df15e419SMatthew Ahrens 		}
201fa9e4066Sahrens 	} else {
202fa9e4066Sahrens 		/*
203fa9e4066Sahrens 		 * To simulate partial disk writes, we split writes into two
204fa9e4066Sahrens 		 * system calls so that the process can be killed in between.
205fa9e4066Sahrens 		 */
206ad135b5dSChristopher Siden 		int sectors = len >> SPA_MINBLOCKSHIFT;
207ad135b5dSChristopher Siden 		split = (sectors > 0 ? rand() % sectors : 0) <<
208ad135b5dSChristopher Siden 		    SPA_MINBLOCKSHIFT;
209fa9e4066Sahrens 		iolen = pwrite64(vp->v_fd, addr, split, offset);
210fa9e4066Sahrens 		iolen += pwrite64(vp->v_fd, (char *)addr + split,
211fa9e4066Sahrens 		    len - split, offset + split);
212fa9e4066Sahrens 	}
213fa9e4066Sahrens 
214fa9e4066Sahrens 	if (iolen == -1)
215fa9e4066Sahrens 		return (errno);
216fa9e4066Sahrens 	if (residp)
217fa9e4066Sahrens 		*residp = len - iolen;
218fa9e4066Sahrens 	else if (iolen != len)
219fa9e4066Sahrens 		return (EIO);
220fa9e4066Sahrens 	return (0);
221fa9e4066Sahrens }
222fa9e4066Sahrens 
223fa9e4066Sahrens void
224fa9e4066Sahrens vn_close(vnode_t *vp)
225fa9e4066Sahrens {
226fa9e4066Sahrens 	close(vp->v_fd);
227df15e419SMatthew Ahrens 	if (vp->v_dump_fd != -1)
228df15e419SMatthew Ahrens 		close(vp->v_dump_fd);
229fa9e4066Sahrens 	spa_strfree(vp->v_path);
230fa9e4066Sahrens 	umem_free(vp, sizeof (vnode_t));
231fa9e4066Sahrens }
232fa9e4066Sahrens 
233095bcd66SGeorge Wilson /*
234095bcd66SGeorge Wilson  * At a minimum we need to update the size since vdev_reopen()
235095bcd66SGeorge Wilson  * will no longer call vn_openat().
236095bcd66SGeorge Wilson  */
237095bcd66SGeorge Wilson int
238095bcd66SGeorge Wilson fop_getattr(vnode_t *vp, vattr_t *vap)
239095bcd66SGeorge Wilson {
240095bcd66SGeorge Wilson 	struct stat64 st;
241095bcd66SGeorge Wilson 
242095bcd66SGeorge Wilson 	if (fstat64(vp->v_fd, &st) == -1) {
243095bcd66SGeorge Wilson 		close(vp->v_fd);
244095bcd66SGeorge Wilson 		return (errno);
245095bcd66SGeorge Wilson 	}
246095bcd66SGeorge Wilson 
247095bcd66SGeorge Wilson 	vap->va_size = st.st_size;
248095bcd66SGeorge Wilson 	return (0);
249095bcd66SGeorge Wilson }
250095bcd66SGeorge Wilson 
251fa9e4066Sahrens #ifdef ZFS_DEBUG
252fa9e4066Sahrens 
253fa9e4066Sahrens /*
254fa9e4066Sahrens  * =========================================================================
255fa9e4066Sahrens  * Figure out which debugging statements to print
256fa9e4066Sahrens  * =========================================================================
257fa9e4066Sahrens  */
258fa9e4066Sahrens 
259fa9e4066Sahrens static char *dprintf_string;
260fa9e4066Sahrens static int dprintf_print_all;
261fa9e4066Sahrens 
262fa9e4066Sahrens int
263fa9e4066Sahrens dprintf_find_string(const char *string)
264fa9e4066Sahrens {
265fa9e4066Sahrens 	char *tmp_str = dprintf_string;
266fa9e4066Sahrens 	int len = strlen(string);
267fa9e4066Sahrens 
268fa9e4066Sahrens 	/*
269fa9e4066Sahrens 	 * Find out if this is a string we want to print.
270fa9e4066Sahrens 	 * String format: file1.c,function_name1,file2.c,file3.c
271fa9e4066Sahrens 	 */
272fa9e4066Sahrens 
273fa9e4066Sahrens 	while (tmp_str != NULL) {
274fa9e4066Sahrens 		if (strncmp(tmp_str, string, len) == 0 &&
275fa9e4066Sahrens 		    (tmp_str[len] == ',' || tmp_str[len] == '\0'))
276fa9e4066Sahrens 			return (1);
277fa9e4066Sahrens 		tmp_str = strchr(tmp_str, ',');
278fa9e4066Sahrens 		if (tmp_str != NULL)
279fa9e4066Sahrens 			tmp_str++; /* Get rid of , */
280fa9e4066Sahrens 	}
281fa9e4066Sahrens 	return (0);
282fa9e4066Sahrens }
283fa9e4066Sahrens 
284fa9e4066Sahrens void
285fa9e4066Sahrens dprintf_setup(int *argc, char **argv)
286fa9e4066Sahrens {
287fa9e4066Sahrens 	int i, j;
288fa9e4066Sahrens 
289fa9e4066Sahrens 	/*
290fa9e4066Sahrens 	 * Debugging can be specified two ways: by setting the
291fa9e4066Sahrens 	 * environment variable ZFS_DEBUG, or by including a
292fa9e4066Sahrens 	 * "debug=..."  argument on the command line.  The command
293fa9e4066Sahrens 	 * line setting overrides the environment variable.
294fa9e4066Sahrens 	 */
295fa9e4066Sahrens 
296fa9e4066Sahrens 	for (i = 1; i < *argc; i++) {
297fa9e4066Sahrens 		int len = strlen("debug=");
298fa9e4066Sahrens 		/* First look for a command line argument */
299fa9e4066Sahrens 		if (strncmp("debug=", argv[i], len) == 0) {
300fa9e4066Sahrens 			dprintf_string = argv[i] + len;
301fa9e4066Sahrens 			/* Remove from args */
302fa9e4066Sahrens 			for (j = i; j < *argc; j++)
303fa9e4066Sahrens 				argv[j] = argv[j+1];
304fa9e4066Sahrens 			argv[j] = NULL;
305fa9e4066Sahrens 			(*argc)--;
306fa9e4066Sahrens 		}
307fa9e4066Sahrens 	}
308fa9e4066Sahrens 
309fa9e4066Sahrens 	if (dprintf_string == NULL) {
310fa9e4066Sahrens 		/* Look for ZFS_DEBUG environment variable */
311fa9e4066Sahrens 		dprintf_string = getenv("ZFS_DEBUG");
312fa9e4066Sahrens 	}
313fa9e4066Sahrens 
314fa9e4066Sahrens 	/*
315fa9e4066Sahrens 	 * Are we just turning on all debugging?
316fa9e4066Sahrens 	 */
317fa9e4066Sahrens 	if (dprintf_find_string("on"))
318fa9e4066Sahrens 		dprintf_print_all = 1;
3197fa49ea5SMatthew Ahrens 
3207fa49ea5SMatthew Ahrens 	if (dprintf_string != NULL)
3217fa49ea5SMatthew Ahrens 		zfs_flags |= ZFS_DEBUG_DPRINTF;
322fa9e4066Sahrens }
323fa9e4066Sahrens 
324fa9e4066Sahrens /*
325fa9e4066Sahrens  * =========================================================================
326fa9e4066Sahrens  * debug printfs
327fa9e4066Sahrens  * =========================================================================
328fa9e4066Sahrens  */
329fa9e4066Sahrens void
330fa9e4066Sahrens __dprintf(const char *file, const char *func, int line, const char *fmt, ...)
331fa9e4066Sahrens {
332fa9e4066Sahrens 	const char *newfile;
333fa9e4066Sahrens 	va_list adx;
334fa9e4066Sahrens 
335fa9e4066Sahrens 	/*
336fa9e4066Sahrens 	 * Get rid of annoying "../common/" prefix to filename.
337fa9e4066Sahrens 	 */
338fa9e4066Sahrens 	newfile = strrchr(file, '/');
339fa9e4066Sahrens 	if (newfile != NULL) {
340fa9e4066Sahrens 		newfile = newfile + 1; /* Get rid of leading / */
341fa9e4066Sahrens 	} else {
342fa9e4066Sahrens 		newfile = file;
343fa9e4066Sahrens 	}
344fa9e4066Sahrens 
345fa9e4066Sahrens 	if (dprintf_print_all ||
346fa9e4066Sahrens 	    dprintf_find_string(newfile) ||
347fa9e4066Sahrens 	    dprintf_find_string(func)) {
348fa9e4066Sahrens 		/* Print out just the function name if requested */
349fa9e4066Sahrens 		flockfile(stdout);
350fa9e4066Sahrens 		if (dprintf_find_string("pid"))
351fa9e4066Sahrens 			(void) printf("%d ", getpid());
352fa9e4066Sahrens 		if (dprintf_find_string("tid"))
353fa9e4066Sahrens 			(void) printf("%u ", thr_self());
354fa9e4066Sahrens 		if (dprintf_find_string("cpu"))
355fa9e4066Sahrens 			(void) printf("%u ", getcpuid());
356fa9e4066Sahrens 		if (dprintf_find_string("time"))
357fa9e4066Sahrens 			(void) printf("%llu ", gethrtime());
358fa9e4066Sahrens 		if (dprintf_find_string("long"))
359fa9e4066Sahrens 			(void) printf("%s, line %d: ", newfile, line);
360fa9e4066Sahrens 		(void) printf("%s: ", func);
361fa9e4066Sahrens 		va_start(adx, fmt);
362fa9e4066Sahrens 		(void) vprintf(fmt, adx);
363fa9e4066Sahrens 		va_end(adx);
364fa9e4066Sahrens 		funlockfile(stdout);
365fa9e4066Sahrens 	}
366fa9e4066Sahrens }
367fa9e4066Sahrens 
368fa9e4066Sahrens #endif /* ZFS_DEBUG */
369fa9e4066Sahrens 
370ea8dc4b6Seschrock /*
371ea8dc4b6Seschrock  * =========================================================================
372ea8dc4b6Seschrock  * kobj interfaces
373ea8dc4b6Seschrock  * =========================================================================
374ea8dc4b6Seschrock  */
375ea8dc4b6Seschrock struct _buf *
376ea8dc4b6Seschrock kobj_open_file(char *name)
377ea8dc4b6Seschrock {
378ea8dc4b6Seschrock 	struct _buf *file;
379ea8dc4b6Seschrock 	vnode_t *vp;
380ea8dc4b6Seschrock 
381ea8dc4b6Seschrock 	/* set vp as the _fd field of the file */
382da6c28aaSamw 	if (vn_openat(name, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0, rootdir,
383da6c28aaSamw 	    -1) != 0)
384ea8dc4b6Seschrock 		return ((void *)-1UL);
385ea8dc4b6Seschrock 
386ea8dc4b6Seschrock 	file = umem_zalloc(sizeof (struct _buf), UMEM_NOFAIL);
387ea8dc4b6Seschrock 	file->_fd = (intptr_t)vp;
388ea8dc4b6Seschrock 	return (file);
389ea8dc4b6Seschrock }
390ea8dc4b6Seschrock 
391ea8dc4b6Seschrock int
392ea8dc4b6Seschrock kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
393ea8dc4b6Seschrock {
394ea8dc4b6Seschrock 	ssize_t resid;
395ea8dc4b6Seschrock 
396ea8dc4b6Seschrock 	vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off,
397ea8dc4b6Seschrock 	    UIO_SYSSPACE, 0, 0, 0, &resid);
398ea8dc4b6Seschrock 
399b1b8ab34Slling 	return (size - resid);
400ea8dc4b6Seschrock }
401ea8dc4b6Seschrock 
402ea8dc4b6Seschrock void
403ea8dc4b6Seschrock kobj_close_file(struct _buf *file)
404ea8dc4b6Seschrock {
405ea8dc4b6Seschrock 	vn_close((vnode_t *)file->_fd);
406ea8dc4b6Seschrock 	umem_free(file, sizeof (struct _buf));
407ea8dc4b6Seschrock }
408ea8dc4b6Seschrock 
409ea8dc4b6Seschrock int
410b1b8ab34Slling kobj_get_filesize(struct _buf *file, uint64_t *size)
411ea8dc4b6Seschrock {
412ea8dc4b6Seschrock 	struct stat64 st;
413b1b8ab34Slling 	vnode_t *vp = (vnode_t *)file->_fd;
414b1b8ab34Slling 
415ea8dc4b6Seschrock 	if (fstat64(vp->v_fd, &st) == -1) {
416ea8dc4b6Seschrock 		vn_close(vp);
417ea8dc4b6Seschrock 		return (errno);
418ea8dc4b6Seschrock 	}
419b1b8ab34Slling 	*size = st.st_size;
420ea8dc4b6Seschrock 	return (0);
421ea8dc4b6Seschrock }
422ea8dc4b6Seschrock 
423*dd50e0ccSTony Hutter /*
424*dd50e0ccSTony Hutter  * =========================================================================
425*dd50e0ccSTony Hutter  * misc routines
426*dd50e0ccSTony Hutter  * =========================================================================
427*dd50e0ccSTony Hutter  */
428*dd50e0ccSTony Hutter 
429*dd50e0ccSTony Hutter /*
430*dd50e0ccSTony Hutter  * Find lowest one bit set.
431*dd50e0ccSTony Hutter  * Returns bit number + 1 of lowest bit that is set, otherwise returns 0.
432*dd50e0ccSTony Hutter  * This is basically a reimplementation of ffsll(), which is GNU specific.
433*dd50e0ccSTony Hutter  */
434*dd50e0ccSTony Hutter int
435*dd50e0ccSTony Hutter lowbit64(uint64_t i)
436*dd50e0ccSTony Hutter {
437*dd50e0ccSTony Hutter 	register int h = 64;
438*dd50e0ccSTony Hutter 	if (i == 0)
439*dd50e0ccSTony Hutter 		return (0);
440*dd50e0ccSTony Hutter 
441*dd50e0ccSTony Hutter 	if (i & 0x00000000ffffffffULL)
442*dd50e0ccSTony Hutter 		h -= 32;
443*dd50e0ccSTony Hutter 	else
444*dd50e0ccSTony Hutter 		i >>= 32;
445*dd50e0ccSTony Hutter 
446*dd50e0ccSTony Hutter 	if (i & 0x0000ffff)
447*dd50e0ccSTony Hutter 		h -= 16;
448*dd50e0ccSTony Hutter 	else
449*dd50e0ccSTony Hutter 		i >>= 16;
450*dd50e0ccSTony Hutter 
451*dd50e0ccSTony Hutter 	if (i & 0x00ff)
452*dd50e0ccSTony Hutter 		h -= 8;
453*dd50e0ccSTony Hutter 	else
454*dd50e0ccSTony Hutter 		i >>= 8;
455*dd50e0ccSTony Hutter 
456*dd50e0ccSTony Hutter 	if (i & 0x0f)
457*dd50e0ccSTony Hutter 		h -= 4;
458*dd50e0ccSTony Hutter 	else
459*dd50e0ccSTony Hutter 		i >>= 4;
460*dd50e0ccSTony Hutter 
461*dd50e0ccSTony Hutter 	if (i & 0x3)
462*dd50e0ccSTony Hutter 		h -= 2;
463*dd50e0ccSTony Hutter 	else
464*dd50e0ccSTony Hutter 		i >>= 2;
465*dd50e0ccSTony Hutter 
466*dd50e0ccSTony Hutter 	if (i & 0x1)
467*dd50e0ccSTony Hutter 		h -= 1;
468*dd50e0ccSTony Hutter 
469*dd50e0ccSTony Hutter 	return (h);
470*dd50e0ccSTony Hutter }
471*dd50e0ccSTony Hutter 
472*dd50e0ccSTony Hutter int
473*dd50e0ccSTony Hutter highbit64(uint64_t i)
474*dd50e0ccSTony Hutter {
475*dd50e0ccSTony Hutter 	int h = 1;
476*dd50e0ccSTony Hutter 
477*dd50e0ccSTony Hutter 	if (i == 0)
478*dd50e0ccSTony Hutter 		return (0);
479*dd50e0ccSTony Hutter 	if (i & 0xffffffff00000000ULL) {
480*dd50e0ccSTony Hutter 		h += 32; i >>= 32;
481*dd50e0ccSTony Hutter 	}
482*dd50e0ccSTony Hutter 	if (i & 0xffff0000) {
483*dd50e0ccSTony Hutter 		h += 16; i >>= 16;
484*dd50e0ccSTony Hutter 	}
485*dd50e0ccSTony Hutter 	if (i & 0xff00) {
486*dd50e0ccSTony Hutter 		h += 8; i >>= 8;
487*dd50e0ccSTony Hutter 	}
488*dd50e0ccSTony Hutter 	if (i & 0xf0) {
489*dd50e0ccSTony Hutter 		h += 4; i >>= 4;
490*dd50e0ccSTony Hutter 	}
491*dd50e0ccSTony Hutter 	if (i & 0xc) {
492*dd50e0ccSTony Hutter 		h += 2; i >>= 2;
493*dd50e0ccSTony Hutter 	}
494*dd50e0ccSTony Hutter 	if (i & 0x2) {
495*dd50e0ccSTony Hutter 		h += 1;
496*dd50e0ccSTony Hutter 	}
497*dd50e0ccSTony Hutter 	return (h);
498*dd50e0ccSTony Hutter }
499*dd50e0ccSTony Hutter 
500fa9e4066Sahrens /*
501fa9e4066Sahrens  * =========================================================================
502fa9e4066Sahrens  * kernel emulation setup & teardown
503fa9e4066Sahrens  * =========================================================================
504fa9e4066Sahrens  */
505fa9e4066Sahrens static int
506fa9e4066Sahrens umem_out_of_memory(void)
507fa9e4066Sahrens {
508fa9e4066Sahrens 	char errmsg[] = "out of memory -- generating core dump\n";
509fa9e4066Sahrens 
510fa9e4066Sahrens 	write(fileno(stderr), errmsg, sizeof (errmsg));
511fa9e4066Sahrens 	abort();
512fa9e4066Sahrens 	return (0);
513fa9e4066Sahrens }
514fa9e4066Sahrens 
515fa9e4066Sahrens void
516fa9e4066Sahrens kernel_init(int mode)
517fa9e4066Sahrens {
5183b2aab18SMatthew Ahrens 	extern uint_t rrw_tsd_key;
5193b2aab18SMatthew Ahrens 
520fa9e4066Sahrens 	umem_nofail_callback(umem_out_of_memory);
521fa9e4066Sahrens 
522fa9e4066Sahrens 	physmem = sysconf(_SC_PHYS_PAGES);
523fa9e4066Sahrens 
524fa9e4066Sahrens 	dprintf("physmem = %llu pages (%.2f GB)\n", physmem,
525fa9e4066Sahrens 	    (double)physmem * sysconf(_SC_PAGE_SIZE) / (1ULL << 30));
526fa9e4066Sahrens 
5273ad6c7f9SVictor Latushkin 	(void) snprintf(hw_serial, sizeof (hw_serial), "%ld",
528e0f1c0afSOlaf Faaland 	    (mode & FWRITE) ? get_system_hostid() : 0);
52995173954Sek 
53088b7b0f2SMatthew Ahrens 	system_taskq_init();
53188b7b0f2SMatthew Ahrens 
532283b8460SGeorge.Wilson 	mutex_init(&cpu_lock, NULL, MUTEX_DEFAULT, NULL);
533283b8460SGeorge.Wilson 
534fa9e4066Sahrens 	spa_init(mode);
5353b2aab18SMatthew Ahrens 
5363b2aab18SMatthew Ahrens 	tsd_create(&rrw_tsd_key, rrw_tsd_destroy);
537fa9e4066Sahrens }
538fa9e4066Sahrens 
539fa9e4066Sahrens void
540fa9e4066Sahrens kernel_fini(void)
541fa9e4066Sahrens {
542fa9e4066Sahrens 	spa_fini();
54317f17c2dSbonwick 
544d20e665cSRicardo M. Correia 	system_taskq_fini();
545fa9e4066Sahrens }
546c9431fa1Sahl 
5476f793812SPavel Zakharov /* ARGSUSED */
5486f793812SPavel Zakharov uint32_t
5496f793812SPavel Zakharov zone_get_hostid(void *zonep)
5506f793812SPavel Zakharov {
5516f793812SPavel Zakharov 	/*
5526f793812SPavel Zakharov 	 * We're emulating the system's hostid in userland.
5536f793812SPavel Zakharov 	 */
5546f793812SPavel Zakharov 	return (strtoul(hw_serial, NULL, 10));
5556f793812SPavel Zakharov }
5566f793812SPavel Zakharov 
557c9431fa1Sahl int
558c9431fa1Sahl z_uncompress(void *dst, size_t *dstlen, const void *src, size_t srclen)
559c9431fa1Sahl {
560c9431fa1Sahl 	int ret;
561c9431fa1Sahl 	uLongf len = *dstlen;
562c9431fa1Sahl 
563c9431fa1Sahl 	if ((ret = uncompress(dst, &len, src, srclen)) == Z_OK)
564c9431fa1Sahl 		*dstlen = (size_t)len;
565c9431fa1Sahl 
566c9431fa1Sahl 	return (ret);
567c9431fa1Sahl }
568c9431fa1Sahl 
569c9431fa1Sahl int
570c9431fa1Sahl z_compress_level(void *dst, size_t *dstlen, const void *src, size_t srclen,
571c9431fa1Sahl     int level)
572c9431fa1Sahl {
573c9431fa1Sahl 	int ret;
574c9431fa1Sahl 	uLongf len = *dstlen;
575c9431fa1Sahl 
576c9431fa1Sahl 	if ((ret = compress2(dst, &len, src, srclen, level)) == Z_OK)
577c9431fa1Sahl 		*dstlen = (size_t)len;
578c9431fa1Sahl 
579c9431fa1Sahl 	return (ret);
580c9431fa1Sahl }
581ecd6cf80Smarks 
582ecd6cf80Smarks int
583ecd6cf80Smarks zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr)
584ecd6cf80Smarks {
585ecd6cf80Smarks 	return (0);
586ecd6cf80Smarks }
587ecd6cf80Smarks 
588ecd6cf80Smarks int
589ecd6cf80Smarks zfs_secpolicy_rename_perms(const char *from, const char *to, cred_t *cr)
590ecd6cf80Smarks {
591ecd6cf80Smarks 	return (0);
592ecd6cf80Smarks }
593ecd6cf80Smarks 
594ecd6cf80Smarks int
595ecd6cf80Smarks zfs_secpolicy_destroy_perms(const char *name, cred_t *cr)
596ecd6cf80Smarks {
597ecd6cf80Smarks 	return (0);
598ecd6cf80Smarks }
599e0d35c44Smarks 
600c99e4bdcSChris Kirby /* ARGSUSED */
601c99e4bdcSChris Kirby int
602a7f53a56SChris Kirby zfs_onexit_fd_hold(int fd, minor_t *minorp)
603a7f53a56SChris Kirby {
604a7f53a56SChris Kirby 	*minorp = 0;
605a7f53a56SChris Kirby 	return (0);
606a7f53a56SChris Kirby }
607a7f53a56SChris Kirby 
608a7f53a56SChris Kirby /* ARGSUSED */
609a7f53a56SChris Kirby void
610a7f53a56SChris Kirby zfs_onexit_fd_rele(int fd)
611a7f53a56SChris Kirby {
612a7f53a56SChris Kirby }
613a7f53a56SChris Kirby 
614a7f53a56SChris Kirby /* ARGSUSED */
615a7f53a56SChris Kirby int
616a7f53a56SChris Kirby zfs_onexit_add_cb(minor_t minor, void (*func)(void *), void *data,
617c99e4bdcSChris Kirby     uint64_t *action_handle)
618c99e4bdcSChris Kirby {
619c99e4bdcSChris Kirby 	return (0);
620c99e4bdcSChris Kirby }
621c99e4bdcSChris Kirby 
622c99e4bdcSChris Kirby /* ARGSUSED */
623c99e4bdcSChris Kirby int
624a7f53a56SChris Kirby zfs_onexit_del_cb(minor_t minor, uint64_t action_handle, boolean_t fire)
625c99e4bdcSChris Kirby {
626c99e4bdcSChris Kirby 	return (0);
627c99e4bdcSChris Kirby }
628c99e4bdcSChris Kirby 
629c99e4bdcSChris Kirby /* ARGSUSED */
630c99e4bdcSChris Kirby int
631a7f53a56SChris Kirby zfs_onexit_cb_data(minor_t minor, uint64_t action_handle, void **data)
632c99e4bdcSChris Kirby {
633c99e4bdcSChris Kirby 	return (0);
634c99e4bdcSChris Kirby }
63531d7e8faSGeorge Wilson 
63631d7e8faSGeorge Wilson void
63731d7e8faSGeorge Wilson bioinit(buf_t *bp)
63831d7e8faSGeorge Wilson {
63931d7e8faSGeorge Wilson 	bzero(bp, sizeof (buf_t));
64031d7e8faSGeorge Wilson }
64131d7e8faSGeorge Wilson 
64231d7e8faSGeorge Wilson void
64331d7e8faSGeorge Wilson biodone(buf_t *bp)
64431d7e8faSGeorge Wilson {
64531d7e8faSGeorge Wilson 	if (bp->b_iodone != NULL) {
64631d7e8faSGeorge Wilson 		(*(bp->b_iodone))(bp);
64731d7e8faSGeorge Wilson 		return;
64831d7e8faSGeorge Wilson 	}
64931d7e8faSGeorge Wilson 	ASSERT((bp->b_flags & B_DONE) == 0);
65031d7e8faSGeorge Wilson 	bp->b_flags |= B_DONE;
65131d7e8faSGeorge Wilson }
65231d7e8faSGeorge Wilson 
65331d7e8faSGeorge Wilson void
65431d7e8faSGeorge Wilson bioerror(buf_t *bp, int error)
65531d7e8faSGeorge Wilson {
65631d7e8faSGeorge Wilson 	ASSERT(bp != NULL);
65731d7e8faSGeorge Wilson 	ASSERT(error >= 0);
65831d7e8faSGeorge Wilson 
65931d7e8faSGeorge Wilson 	if (error != 0) {
66031d7e8faSGeorge Wilson 		bp->b_flags |= B_ERROR;
66131d7e8faSGeorge Wilson 	} else {
66231d7e8faSGeorge Wilson 		bp->b_flags &= ~B_ERROR;
66331d7e8faSGeorge Wilson 	}
66431d7e8faSGeorge Wilson 	bp->b_error = error;
66531d7e8faSGeorge Wilson }
66631d7e8faSGeorge Wilson 
66731d7e8faSGeorge Wilson 
66831d7e8faSGeorge Wilson int
66931d7e8faSGeorge Wilson geterror(struct buf *bp)
67031d7e8faSGeorge Wilson {
67131d7e8faSGeorge Wilson 	int error = 0;
67231d7e8faSGeorge Wilson 
67331d7e8faSGeorge Wilson 	if (bp->b_flags & B_ERROR) {
67431d7e8faSGeorge Wilson 		error = bp->b_error;
67531d7e8faSGeorge Wilson 		if (!error)
67631d7e8faSGeorge Wilson 			error = EIO;
67731d7e8faSGeorge Wilson 	}
67831d7e8faSGeorge Wilson 	return (error);
67931d7e8faSGeorge Wilson }
680eb633035STom Caputi 
681eb633035STom Caputi int
682eb633035STom Caputi crypto_create_ctx_template(crypto_mechanism_t *mech,
683eb633035STom Caputi     crypto_key_t *key, crypto_ctx_template_t *tmpl, int kmflag)
684eb633035STom Caputi {
685eb633035STom Caputi 	return (0);
686eb633035STom Caputi }
687eb633035STom Caputi 
688eb633035STom Caputi crypto_mech_type_t
689eb633035STom Caputi crypto_mech2id(crypto_mech_name_t name)
690eb633035STom Caputi {
691eb633035STom Caputi 	return (CRYPTO_MECH_INVALID);
692eb633035STom Caputi }
693eb633035STom Caputi 
694eb633035STom Caputi int
695eb633035STom Caputi crypto_mac(crypto_mechanism_t *mech, crypto_data_t *data,
696eb633035STom Caputi     crypto_key_t *key, crypto_ctx_template_t impl,
697eb633035STom Caputi     crypto_data_t *mac, crypto_call_req_t *cr)
698eb633035STom Caputi {
699eb633035STom Caputi 	return (0);
700eb633035STom Caputi }
701eb633035STom Caputi 
702eb633035STom Caputi int
703eb633035STom Caputi crypto_encrypt(crypto_mechanism_t *mech, crypto_data_t *plaintext,
704eb633035STom Caputi     crypto_key_t *key, crypto_ctx_template_t tmpl,
705eb633035STom Caputi     crypto_data_t *ciphertext, crypto_call_req_t *cr)
706eb633035STom Caputi {
707eb633035STom Caputi 	return (0);
708eb633035STom Caputi }
709eb633035STom Caputi 
710eb633035STom Caputi /* This could probably be a weak reference */
711eb633035STom Caputi int
712eb633035STom Caputi crypto_decrypt(crypto_mechanism_t *mech, crypto_data_t *plaintext,
713eb633035STom Caputi     crypto_key_t *key, crypto_ctx_template_t tmpl,
714eb633035STom Caputi     crypto_data_t *ciphertext, crypto_call_req_t *cr)
715eb633035STom Caputi {
716eb633035STom Caputi 	return (0);
717eb633035STom Caputi }
718eb633035STom Caputi 
719eb633035STom Caputi 
720eb633035STom Caputi int
721eb633035STom Caputi crypto_digest_final(crypto_context_t context, crypto_data_t *digest,
722eb633035STom Caputi     crypto_call_req_t *cr)
723eb633035STom Caputi {
724eb633035STom Caputi 	return (0);
725eb633035STom Caputi }
726eb633035STom Caputi 
727eb633035STom Caputi int
728eb633035STom Caputi crypto_digest_update(crypto_context_t context, crypto_data_t *data,
729eb633035STom Caputi     crypto_call_req_t *cr)
730eb633035STom Caputi {
731eb633035STom Caputi 	return (0);
732eb633035STom Caputi }
733eb633035STom Caputi 
734eb633035STom Caputi int
735eb633035STom Caputi crypto_digest_init(crypto_mechanism_t *mech, crypto_context_t *ctxp,
736eb633035STom Caputi     crypto_call_req_t  *crq)
737eb633035STom Caputi {
738eb633035STom Caputi 	return (0);
739eb633035STom Caputi }
740eb633035STom Caputi 
741eb633035STom Caputi void
742eb633035STom Caputi crypto_destroy_ctx_template(crypto_ctx_template_t tmpl)
743eb633035STom Caputi {
744eb633035STom Caputi }
745eb633035STom Caputi 
746eb633035STom Caputi extern int crypto_mac_init(crypto_mechanism_t *mech, crypto_key_t *key,
747eb633035STom Caputi 	crypto_ctx_template_t tmpl, crypto_context_t *ctxp,
748eb633035STom Caputi     crypto_call_req_t *cr)
749eb633035STom Caputi {
750eb633035STom Caputi 	return (0);
751eb633035STom Caputi }
752eb633035STom Caputi 
753eb633035STom Caputi extern int crypto_mac_update(crypto_context_t ctx, crypto_data_t *data,
754eb633035STom Caputi 	crypto_call_req_t *cr)
755eb633035STom Caputi {
756eb633035STom Caputi 	return (0);
757eb633035STom Caputi }
758eb633035STom Caputi 
759eb633035STom Caputi extern int crypto_mac_final(crypto_context_t ctx, crypto_data_t *data,
760eb633035STom Caputi 	crypto_call_req_t *cr)
761eb633035STom Caputi {
762eb633035STom Caputi 	return (0);
763eb633035STom Caputi }
764