libzfs_core.c revision 329484
1238592Smm/*
2238592Smm * CDDL HEADER START
3238592Smm *
4238592Smm * The contents of this file are subject to the terms of the
5238592Smm * Common Development and Distribution License (the "License").
6238592Smm * You may not use this file except in compliance with the License.
7238592Smm *
8238592Smm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9238592Smm * or http://www.opensolaris.org/os/licensing.
10238592Smm * See the License for the specific language governing permissions
11238592Smm * and limitations under the License.
12238592Smm *
13238592Smm * When distributing Covered Code, include this CDDL HEADER in each
14238592Smm * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15238592Smm * If applicable, add the following below this CDDL HEADER, with the
16238592Smm * fields enclosed by brackets "[]" replaced with your own identifying
17238592Smm * information: Portions Copyright [yyyy] [name of copyright owner]
18238592Smm *
19238592Smm * CDDL HEADER END
20238592Smm */
21238592Smm
22238592Smm/*
23325538Savg * Copyright (c) 2012, 2017 by Delphix. All rights reserved.
24251646Sdelphij * Copyright (c) 2013 Steven Hartland. All rights reserved.
25296519Smav * Copyright (c) 2014 Integros [integros.com]
26321577Smav * Copyright 2017 RackTop Systems.
27238592Smm */
28238592Smm
29238592Smm/*
30238592Smm * LibZFS_Core (lzc) is intended to replace most functionality in libzfs.
31238592Smm * It has the following characteristics:
32238592Smm *
33238592Smm *  - Thread Safe.  libzfs_core is accessible concurrently from multiple
34238592Smm *  threads.  This is accomplished primarily by avoiding global data
35238592Smm *  (e.g. caching).  Since it's thread-safe, there is no reason for a
36238592Smm *  process to have multiple libzfs "instances".  Therefore, we store
37238592Smm *  our few pieces of data (e.g. the file descriptor) in global
38238592Smm *  variables.  The fd is reference-counted so that the libzfs_core
39238592Smm *  library can be "initialized" multiple times (e.g. by different
40238592Smm *  consumers within the same process).
41238592Smm *
42238592Smm *  - Committed Interface.  The libzfs_core interface will be committed,
43238592Smm *  therefore consumers can compile against it and be confident that
44238592Smm *  their code will continue to work on future releases of this code.
45238592Smm *  Currently, the interface is Evolving (not Committed), but we intend
46238592Smm *  to commit to it once it is more complete and we determine that it
47238592Smm *  meets the needs of all consumers.
48238592Smm *
49238592Smm *  - Programatic Error Handling.  libzfs_core communicates errors with
50238592Smm *  defined error numbers, and doesn't print anything to stdout/stderr.
51238592Smm *
52238592Smm *  - Thin Layer.  libzfs_core is a thin layer, marshaling arguments
53238592Smm *  to/from the kernel ioctls.  There is generally a 1:1 correspondence
54238592Smm *  between libzfs_core functions and ioctls to /dev/zfs.
55238592Smm *
56238592Smm *  - Clear Atomicity.  Because libzfs_core functions are generally 1:1
57238592Smm *  with kernel ioctls, and kernel ioctls are general atomic, each
58238592Smm *  libzfs_core function is atomic.  For example, creating multiple
59238592Smm *  snapshots with a single call to lzc_snapshot() is atomic -- it
60238592Smm *  can't fail with only some of the requested snapshots created, even
61238592Smm *  in the event of power loss or system crash.
62238592Smm *
63238592Smm *  - Continued libzfs Support.  Some higher-level operations (e.g.
64238592Smm *  support for "zfs send -R") are too complicated to fit the scope of
65238592Smm *  libzfs_core.  This functionality will continue to live in libzfs.
66238592Smm *  Where appropriate, libzfs will use the underlying atomic operations
67238592Smm *  of libzfs_core.  For example, libzfs may implement "zfs send -R |
68238592Smm *  zfs receive" by using individual "send one snapshot", rename,
69238592Smm *  destroy, and "receive one snapshot" operations in libzfs_core.
70238592Smm *  /sbin/zfs and /zbin/zpool will link with both libzfs and
71238592Smm *  libzfs_core.  Other consumers should aim to use only libzfs_core,
72238592Smm *  since that will be the supported, stable interface going forwards.
73238592Smm */
74238592Smm
75247831Smm#define _IN_LIBZFS_CORE_
76247831Smm
77238592Smm#include <libzfs_core.h>
78238592Smm#include <ctype.h>
79238592Smm#include <unistd.h>
80238592Smm#include <stdlib.h>
81238592Smm#include <string.h>
82238592Smm#include <errno.h>
83238592Smm#include <fcntl.h>
84238592Smm#include <pthread.h>
85238592Smm#include <sys/nvpair.h>
86238592Smm#include <sys/param.h>
87238592Smm#include <sys/types.h>
88238592Smm#include <sys/stat.h>
89238592Smm#include <sys/zfs_ioctl.h>
90248445Smm#include "libzfs_core_compat.h"
91248445Smm#include "libzfs_compat.h"
92238592Smm
93248435Smm#ifdef __FreeBSD__
94248461Smmextern int zfs_ioctl_version;
95248435Smm#endif
96248435Smm
97238592Smmstatic int g_fd;
98238592Smmstatic pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
99238592Smmstatic int g_refcount;
100238592Smm
101238592Smmint
102238592Smmlibzfs_core_init(void)
103238592Smm{
104238592Smm	(void) pthread_mutex_lock(&g_lock);
105238592Smm	if (g_refcount == 0) {
106238592Smm		g_fd = open("/dev/zfs", O_RDWR);
107238592Smm		if (g_fd < 0) {
108238592Smm			(void) pthread_mutex_unlock(&g_lock);
109238592Smm			return (errno);
110238592Smm		}
111238592Smm	}
112238592Smm	g_refcount++;
113238592Smm	(void) pthread_mutex_unlock(&g_lock);
114248445Smm
115238592Smm	return (0);
116238592Smm}
117238592Smm
118238592Smmvoid
119238592Smmlibzfs_core_fini(void)
120238592Smm{
121238592Smm	(void) pthread_mutex_lock(&g_lock);
122238592Smm	ASSERT3S(g_refcount, >, 0);
123238592Smm	g_refcount--;
124238592Smm	if (g_refcount == 0)
125238592Smm		(void) close(g_fd);
126238592Smm	(void) pthread_mutex_unlock(&g_lock);
127238592Smm}
128238592Smm
129238592Smmstatic int
130238592Smmlzc_ioctl(zfs_ioc_t ioc, const char *name,
131238592Smm    nvlist_t *source, nvlist_t **resultp)
132238592Smm{
133238592Smm	zfs_cmd_t zc = { 0 };
134238592Smm	int error = 0;
135238592Smm	char *packed;
136248435Smm#ifdef __FreeBSD__
137248435Smm	nvlist_t *oldsource;
138248435Smm#endif
139238592Smm	size_t size;
140238592Smm
141238592Smm	ASSERT3S(g_refcount, >, 0);
142238592Smm
143238592Smm	(void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
144238592Smm
145248435Smm#ifdef __FreeBSD__
146248461Smm	if (zfs_ioctl_version == ZFS_IOCVER_UNDEF)
147248461Smm		zfs_ioctl_version = get_zfs_ioctl_version();
148248445Smm
149248461Smm	if (zfs_ioctl_version < ZFS_IOCVER_LZC) {
150248435Smm		oldsource = source;
151248435Smm		error = lzc_compat_pre(&zc, &ioc, &source);
152248435Smm		if (error)
153248435Smm			return (error);
154248435Smm	}
155248435Smm#endif
156248435Smm
157238592Smm	packed = fnvlist_pack(source, &size);
158238592Smm	zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed;
159238592Smm	zc.zc_nvlist_src_size = size;
160238592Smm
161238592Smm	if (resultp != NULL) {
162248498Smm		*resultp = NULL;
163325538Savg		if (ioc == ZFS_IOC_CHANNEL_PROGRAM) {
164325538Savg			zc.zc_nvlist_dst_size = fnvlist_lookup_uint64(source,
165325538Savg			    ZCP_ARG_MEMLIMIT);
166325538Savg		} else {
167325538Savg			zc.zc_nvlist_dst_size = MAX(size * 2, 128 * 1024);
168325538Savg		}
169238592Smm		zc.zc_nvlist_dst = (uint64_t)(uintptr_t)
170238592Smm		    malloc(zc.zc_nvlist_dst_size);
171247831Smm#ifdef illumos
172238592Smm		if (zc.zc_nvlist_dst == NULL) {
173247831Smm#else
174247831Smm		if (zc.zc_nvlist_dst == 0) {
175247831Smm#endif
176238592Smm			error = ENOMEM;
177238592Smm			goto out;
178238592Smm		}
179238592Smm	}
180238592Smm
181238592Smm	while (ioctl(g_fd, ioc, &zc) != 0) {
182325534Savg		/*
183325534Savg		 * If ioctl exited with ENOMEM, we retry the ioctl after
184325534Savg		 * increasing the size of the destination nvlist.
185325534Savg		 *
186325538Savg		 * Channel programs that exit with ENOMEM ran over the
187325534Savg		 * lua memory sandbox; they should not be retried.
188325534Savg		 */
189325534Savg		if (errno == ENOMEM && resultp != NULL &&
190325534Savg		    ioc != ZFS_IOC_CHANNEL_PROGRAM) {
191238592Smm			free((void *)(uintptr_t)zc.zc_nvlist_dst);
192238592Smm			zc.zc_nvlist_dst_size *= 2;
193238592Smm			zc.zc_nvlist_dst = (uint64_t)(uintptr_t)
194238592Smm			    malloc(zc.zc_nvlist_dst_size);
195247831Smm#ifdef illumos
196238592Smm			if (zc.zc_nvlist_dst == NULL) {
197247831Smm#else
198247831Smm			if (zc.zc_nvlist_dst == 0) {
199247831Smm#endif
200238592Smm				error = ENOMEM;
201238592Smm				goto out;
202238592Smm			}
203238592Smm		} else {
204238592Smm			error = errno;
205238592Smm			break;
206238592Smm		}
207238592Smm	}
208248435Smm
209248435Smm#ifdef __FreeBSD__
210248461Smm	if (zfs_ioctl_version < ZFS_IOCVER_LZC)
211248435Smm		lzc_compat_post(&zc, ioc);
212248435Smm#endif
213238592Smm	if (zc.zc_nvlist_dst_filled) {
214238592Smm		*resultp = fnvlist_unpack((void *)(uintptr_t)zc.zc_nvlist_dst,
215238592Smm		    zc.zc_nvlist_dst_size);
216238592Smm	}
217248435Smm#ifdef __FreeBSD__
218248461Smm	if (zfs_ioctl_version < ZFS_IOCVER_LZC)
219248435Smm		lzc_compat_outnvl(&zc, ioc, resultp);
220248435Smm#endif
221238592Smmout:
222248435Smm#ifdef __FreeBSD__
223248461Smm	if (zfs_ioctl_version < ZFS_IOCVER_LZC) {
224248435Smm		if (source != oldsource)
225248435Smm			nvlist_free(source);
226248435Smm		source = oldsource;
227248435Smm	}
228248435Smm#endif
229238592Smm	fnvlist_pack_free(packed, size);
230238592Smm	free((void *)(uintptr_t)zc.zc_nvlist_dst);
231238592Smm	return (error);
232238592Smm}
233238592Smm
234238592Smmint
235298472Savglzc_create(const char *fsname, enum lzc_dataset_type type, nvlist_t *props)
236238592Smm{
237238592Smm	int error;
238238592Smm	nvlist_t *args = fnvlist_alloc();
239298472Savg	fnvlist_add_int32(args, "type", (dmu_objset_type_t)type);
240238592Smm	if (props != NULL)
241238592Smm		fnvlist_add_nvlist(args, "props", props);
242238592Smm	error = lzc_ioctl(ZFS_IOC_CREATE, fsname, args, NULL);
243238592Smm	nvlist_free(args);
244238592Smm	return (error);
245238592Smm}
246238592Smm
247238592Smmint
248238592Smmlzc_clone(const char *fsname, const char *origin,
249238592Smm    nvlist_t *props)
250238592Smm{
251238592Smm	int error;
252238592Smm	nvlist_t *args = fnvlist_alloc();
253238592Smm	fnvlist_add_string(args, "origin", origin);
254238592Smm	if (props != NULL)
255238592Smm		fnvlist_add_nvlist(args, "props", props);
256238592Smm	error = lzc_ioctl(ZFS_IOC_CLONE, fsname, args, NULL);
257238592Smm	nvlist_free(args);
258238592Smm	return (error);
259238592Smm}
260238592Smm
261321577Smavint
262321577Smavlzc_promote(const char *fsname, char *snapnamebuf, int snapnamelen)
263321577Smav{
264321577Smav	/*
265321577Smav	 * The promote ioctl is still legacy, so we need to construct our
266321577Smav	 * own zfs_cmd_t rather than using lzc_ioctl().
267321577Smav	 */
268321577Smav	zfs_cmd_t zc = { 0 };
269321577Smav
270321577Smav	ASSERT3S(g_refcount, >, 0);
271321577Smav	VERIFY3S(g_fd, !=, -1);
272321577Smav
273321577Smav	(void) strlcpy(zc.zc_name, fsname, sizeof (zc.zc_name));
274321577Smav	if (ioctl(g_fd, ZFS_IOC_PROMOTE, &zc) != 0) {
275321577Smav		int error = errno;
276321577Smav		if (error == EEXIST && snapnamebuf != NULL)
277321577Smav			(void) strlcpy(snapnamebuf, zc.zc_string, snapnamelen);
278321577Smav		return (error);
279321577Smav	}
280321577Smav	return (0);
281321577Smav}
282321577Smav
283238592Smm/*
284238592Smm * Creates snapshots.
285238592Smm *
286238592Smm * The keys in the snaps nvlist are the snapshots to be created.
287238592Smm * They must all be in the same pool.
288238592Smm *
289238592Smm * The props nvlist is properties to set.  Currently only user properties
290238592Smm * are supported.  { user:prop_name -> string value }
291238592Smm *
292238592Smm * The returned results nvlist will have an entry for each snapshot that failed.
293238592Smm * The value will be the (int32) error code.
294238592Smm *
295238592Smm * The return value will be 0 if all snapshots were created, otherwise it will
296248498Smm * be the errno of a (unspecified) snapshot that failed.
297238592Smm */
298238592Smmint
299238592Smmlzc_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t **errlist)
300238592Smm{
301238592Smm	nvpair_t *elem;
302238592Smm	nvlist_t *args;
303238592Smm	int error;
304307108Smav	char pool[ZFS_MAX_DATASET_NAME_LEN];
305238592Smm
306238592Smm	*errlist = NULL;
307238592Smm
308238592Smm	/* determine the pool name */
309238592Smm	elem = nvlist_next_nvpair(snaps, NULL);
310238592Smm	if (elem == NULL)
311238592Smm		return (0);
312238592Smm	(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
313238592Smm	pool[strcspn(pool, "/@")] = '\0';
314238592Smm
315238592Smm	args = fnvlist_alloc();
316238592Smm	fnvlist_add_nvlist(args, "snaps", snaps);
317238592Smm	if (props != NULL)
318238592Smm		fnvlist_add_nvlist(args, "props", props);
319238592Smm
320238592Smm	error = lzc_ioctl(ZFS_IOC_SNAPSHOT, pool, args, errlist);
321238592Smm	nvlist_free(args);
322238592Smm
323238592Smm	return (error);
324238592Smm}
325238592Smm
326238592Smm/*
327238592Smm * Destroys snapshots.
328238592Smm *
329238592Smm * The keys in the snaps nvlist are the snapshots to be destroyed.
330238592Smm * They must all be in the same pool.
331238592Smm *
332238592Smm * Snapshots that do not exist will be silently ignored.
333238592Smm *
334238592Smm * If 'defer' is not set, and a snapshot has user holds or clones, the
335238592Smm * destroy operation will fail and none of the snapshots will be
336238592Smm * destroyed.
337238592Smm *
338238592Smm * If 'defer' is set, and a snapshot has user holds or clones, it will be
339238592Smm * marked for deferred destruction, and will be destroyed when the last hold
340238592Smm * or clone is removed/destroyed.
341238592Smm *
342238592Smm * The return value will be 0 if all snapshots were destroyed (or marked for
343252219Sdelphij * later destruction if 'defer' is set) or didn't exist to begin with.
344238592Smm *
345248498Smm * Otherwise the return value will be the errno of a (unspecified) snapshot
346238592Smm * that failed, no snapshots will be destroyed, and the errlist will have an
347238592Smm * entry for each snapshot that failed.  The value in the errlist will be
348238592Smm * the (int32) error code.
349238592Smm */
350238592Smmint
351238592Smmlzc_destroy_snaps(nvlist_t *snaps, boolean_t defer, nvlist_t **errlist)
352238592Smm{
353238592Smm	nvpair_t *elem;
354238592Smm	nvlist_t *args;
355238592Smm	int error;
356307108Smav	char pool[ZFS_MAX_DATASET_NAME_LEN];
357238592Smm
358238592Smm	/* determine the pool name */
359238592Smm	elem = nvlist_next_nvpair(snaps, NULL);
360238592Smm	if (elem == NULL)
361238592Smm		return (0);
362238592Smm	(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
363238592Smm	pool[strcspn(pool, "/@")] = '\0';
364238592Smm
365238592Smm	args = fnvlist_alloc();
366238592Smm	fnvlist_add_nvlist(args, "snaps", snaps);
367238592Smm	if (defer)
368238592Smm		fnvlist_add_boolean(args, "defer");
369238592Smm
370238592Smm	error = lzc_ioctl(ZFS_IOC_DESTROY_SNAPS, pool, args, errlist);
371238592Smm	nvlist_free(args);
372238592Smm
373238592Smm	return (error);
374238592Smm}
375238592Smm
376238592Smmint
377238592Smmlzc_snaprange_space(const char *firstsnap, const char *lastsnap,
378238592Smm    uint64_t *usedp)
379238592Smm{
380238592Smm	nvlist_t *args;
381238592Smm	nvlist_t *result;
382238592Smm	int err;
383307108Smav	char fs[ZFS_MAX_DATASET_NAME_LEN];
384238592Smm	char *atp;
385238592Smm
386238592Smm	/* determine the fs name */
387238592Smm	(void) strlcpy(fs, firstsnap, sizeof (fs));
388238592Smm	atp = strchr(fs, '@');
389238592Smm	if (atp == NULL)
390238592Smm		return (EINVAL);
391238592Smm	*atp = '\0';
392238592Smm
393238592Smm	args = fnvlist_alloc();
394238592Smm	fnvlist_add_string(args, "firstsnap", firstsnap);
395238592Smm
396238592Smm	err = lzc_ioctl(ZFS_IOC_SPACE_SNAPS, lastsnap, args, &result);
397238592Smm	nvlist_free(args);
398238592Smm	if (err == 0)
399238592Smm		*usedp = fnvlist_lookup_uint64(result, "used");
400238592Smm	fnvlist_free(result);
401238592Smm
402238592Smm	return (err);
403238592Smm}
404238592Smm
405238592Smmboolean_t
406238592Smmlzc_exists(const char *dataset)
407238592Smm{
408238592Smm	/*
409238592Smm	 * The objset_stats ioctl is still legacy, so we need to construct our
410321577Smav	 * own zfs_cmd_t rather than using lzc_ioctl().
411238592Smm	 */
412238592Smm	zfs_cmd_t zc = { 0 };
413238592Smm
414238592Smm	(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
415238592Smm	return (ioctl(g_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0);
416238592Smm}
417238592Smm
418238592Smm/*
419248498Smm * Create "user holds" on snapshots.  If there is a hold on a snapshot,
420248498Smm * the snapshot can not be destroyed.  (However, it can be marked for deletion
421248498Smm * by lzc_destroy_snaps(defer=B_TRUE).)
422248498Smm *
423248498Smm * The keys in the nvlist are snapshot names.
424248498Smm * The snapshots must all be in the same pool.
425248498Smm * The value is the name of the hold (string type).
426248498Smm *
427248498Smm * If cleanup_fd is not -1, it must be the result of open("/dev/zfs", O_EXCL).
428248498Smm * In this case, when the cleanup_fd is closed (including on process
429248498Smm * termination), the holds will be released.  If the system is shut down
430248498Smm * uncleanly, the holds will be released when the pool is next opened
431248498Smm * or imported.
432248498Smm *
433251646Sdelphij * Holds for snapshots which don't exist will be skipped and have an entry
434252219Sdelphij * added to errlist, but will not cause an overall failure.
435251646Sdelphij *
436252219Sdelphij * The return value will be 0 if all holds, for snapshots that existed,
437252219Sdelphij * were succesfully created.
438251646Sdelphij *
439251646Sdelphij * Otherwise the return value will be the errno of a (unspecified) hold that
440251646Sdelphij * failed and no holds will be created.
441251646Sdelphij *
442251646Sdelphij * In all cases the errlist will have an entry for each hold that failed
443251646Sdelphij * (name = snapshot), with its value being the error code (int32).
444248498Smm */
445248498Smmint
446248498Smmlzc_hold(nvlist_t *holds, int cleanup_fd, nvlist_t **errlist)
447248498Smm{
448307108Smav	char pool[ZFS_MAX_DATASET_NAME_LEN];
449248498Smm	nvlist_t *args;
450248498Smm	nvpair_t *elem;
451248498Smm	int error;
452248498Smm
453248498Smm	/* determine the pool name */
454248498Smm	elem = nvlist_next_nvpair(holds, NULL);
455248498Smm	if (elem == NULL)
456248498Smm		return (0);
457248498Smm	(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
458248498Smm	pool[strcspn(pool, "/@")] = '\0';
459248498Smm
460248498Smm	args = fnvlist_alloc();
461248498Smm	fnvlist_add_nvlist(args, "holds", holds);
462248498Smm	if (cleanup_fd != -1)
463248498Smm		fnvlist_add_int32(args, "cleanup_fd", cleanup_fd);
464248498Smm
465248498Smm	error = lzc_ioctl(ZFS_IOC_HOLD, pool, args, errlist);
466248498Smm	nvlist_free(args);
467248498Smm	return (error);
468248498Smm}
469248498Smm
470248498Smm/*
471248498Smm * Release "user holds" on snapshots.  If the snapshot has been marked for
472248498Smm * deferred destroy (by lzc_destroy_snaps(defer=B_TRUE)), it does not have
473248498Smm * any clones, and all the user holds are removed, then the snapshot will be
474248498Smm * destroyed.
475248498Smm *
476248498Smm * The keys in the nvlist are snapshot names.
477248498Smm * The snapshots must all be in the same pool.
478248498Smm * The value is a nvlist whose keys are the holds to remove.
479248498Smm *
480251646Sdelphij * Holds which failed to release because they didn't exist will have an entry
481252219Sdelphij * added to errlist, but will not cause an overall failure.
482251646Sdelphij *
483251646Sdelphij * The return value will be 0 if the nvl holds was empty or all holds that
484252219Sdelphij * existed, were successfully removed.
485251646Sdelphij *
486251646Sdelphij * Otherwise the return value will be the errno of a (unspecified) hold that
487251646Sdelphij * failed to release and no holds will be released.
488251646Sdelphij *
489251646Sdelphij * In all cases the errlist will have an entry for each hold that failed to
490251646Sdelphij * to release.
491248498Smm */
492248498Smmint
493248498Smmlzc_release(nvlist_t *holds, nvlist_t **errlist)
494248498Smm{
495307108Smav	char pool[ZFS_MAX_DATASET_NAME_LEN];
496248498Smm	nvpair_t *elem;
497248498Smm
498248498Smm	/* determine the pool name */
499248498Smm	elem = nvlist_next_nvpair(holds, NULL);
500248498Smm	if (elem == NULL)
501248498Smm		return (0);
502248498Smm	(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
503248498Smm	pool[strcspn(pool, "/@")] = '\0';
504248498Smm
505248498Smm	return (lzc_ioctl(ZFS_IOC_RELEASE, pool, holds, errlist));
506248498Smm}
507248498Smm
508248498Smm/*
509248498Smm * Retrieve list of user holds on the specified snapshot.
510248498Smm *
511248498Smm * On success, *holdsp will be set to a nvlist which the caller must free.
512248498Smm * The keys are the names of the holds, and the value is the creation time
513248498Smm * of the hold (uint64) in seconds since the epoch.
514248498Smm */
515248498Smmint
516248498Smmlzc_get_holds(const char *snapname, nvlist_t **holdsp)
517248498Smm{
518248498Smm	int error;
519248498Smm	nvlist_t *innvl = fnvlist_alloc();
520248498Smm	error = lzc_ioctl(ZFS_IOC_GET_HOLDS, snapname, innvl, holdsp);
521248498Smm	fnvlist_free(innvl);
522248498Smm	return (error);
523248498Smm}
524248498Smm
525248498Smm/*
526268075Sdelphij * Generate a zfs send stream for the specified snapshot and write it to
527268075Sdelphij * the specified file descriptor.
528260183Sdelphij *
529260183Sdelphij * "snapname" is the full name of the snapshot to send (e.g. "pool/fs@snap")
530260183Sdelphij *
531260183Sdelphij * If "from" is NULL, a full (non-incremental) stream will be sent.
532260183Sdelphij * If "from" is non-NULL, it must be the full name of a snapshot or
533260183Sdelphij * bookmark to send an incremental from (e.g. "pool/fs@earlier_snap" or
534260183Sdelphij * "pool/fs#earlier_bmark").  If non-NULL, the specified snapshot or
535260183Sdelphij * bookmark must represent an earlier point in the history of "snapname").
536260183Sdelphij * It can be an earlier snapshot in the same filesystem or zvol as "snapname",
537260183Sdelphij * or it can be the origin of "snapname"'s filesystem, or an earlier
538260183Sdelphij * snapshot in the origin, etc.
539260183Sdelphij *
540260183Sdelphij * "fd" is the file descriptor to write the send stream to.
541268075Sdelphij *
542274337Sdelphij * If "flags" contains LZC_SEND_FLAG_LARGE_BLOCK, the stream is permitted
543274337Sdelphij * to contain DRR_WRITE records with drr_length > 128K, and DRR_OBJECT
544274337Sdelphij * records with drr_blksz > 128K.
545274337Sdelphij *
546268075Sdelphij * If "flags" contains LZC_SEND_FLAG_EMBED_DATA, the stream is permitted
547268075Sdelphij * to contain DRR_WRITE_EMBEDDED records with drr_etype==BP_EMBEDDED_TYPE_DATA,
548268075Sdelphij * which the receiving system must support (as indicated by support
549268075Sdelphij * for the "embedded_data" feature).
550238592Smm */
551238592Smmint
552268075Sdelphijlzc_send(const char *snapname, const char *from, int fd,
553268075Sdelphij    enum lzc_send_flags flags)
554238592Smm{
555289362Smav	return (lzc_send_resume(snapname, from, fd, flags, 0, 0));
556289362Smav}
557289362Smav
558289362Smavint
559289362Smavlzc_send_resume(const char *snapname, const char *from, int fd,
560289362Smav    enum lzc_send_flags flags, uint64_t resumeobj, uint64_t resumeoff)
561289362Smav{
562238592Smm	nvlist_t *args;
563238592Smm	int err;
564238592Smm
565238592Smm	args = fnvlist_alloc();
566238592Smm	fnvlist_add_int32(args, "fd", fd);
567260183Sdelphij	if (from != NULL)
568260183Sdelphij		fnvlist_add_string(args, "fromsnap", from);
569274337Sdelphij	if (flags & LZC_SEND_FLAG_LARGE_BLOCK)
570274337Sdelphij		fnvlist_add_boolean(args, "largeblockok");
571268075Sdelphij	if (flags & LZC_SEND_FLAG_EMBED_DATA)
572268075Sdelphij		fnvlist_add_boolean(args, "embedok");
573321535Smav	if (flags & LZC_SEND_FLAG_COMPRESS)
574321535Smav		fnvlist_add_boolean(args, "compressok");
575289362Smav	if (resumeobj != 0 || resumeoff != 0) {
576289362Smav		fnvlist_add_uint64(args, "resume_object", resumeobj);
577289362Smav		fnvlist_add_uint64(args, "resume_offset", resumeoff);
578289362Smav	}
579238592Smm	err = lzc_ioctl(ZFS_IOC_SEND_NEW, snapname, args, NULL);
580238592Smm	nvlist_free(args);
581238592Smm	return (err);
582238592Smm}
583238592Smm
584238592Smm/*
585286683Smav * "from" can be NULL, a snapshot, or a bookmark.
586286683Smav *
587286683Smav * If from is NULL, a full (non-incremental) stream will be estimated.  This
588286683Smav * is calculated very efficiently.
589286683Smav *
590286683Smav * If from is a snapshot, lzc_send_space uses the deadlists attached to
591286683Smav * each snapshot to efficiently estimate the stream size.
592286683Smav *
593286683Smav * If from is a bookmark, the indirect blocks in the destination snapshot
594286683Smav * are traversed, looking for blocks with a birth time since the creation TXG of
595286683Smav * the snapshot this bookmark was created from.  This will result in
596286683Smav * significantly more I/O and be less efficient than a send space estimation on
597286683Smav * an equivalent snapshot.
598238592Smm */
599238592Smmint
600321535Smavlzc_send_space(const char *snapname, const char *from,
601321535Smav    enum lzc_send_flags flags, uint64_t *spacep)
602238592Smm{
603238592Smm	nvlist_t *args;
604238592Smm	nvlist_t *result;
605238592Smm	int err;
606238592Smm
607238592Smm	args = fnvlist_alloc();
608286683Smav	if (from != NULL)
609286683Smav		fnvlist_add_string(args, "from", from);
610321535Smav	if (flags & LZC_SEND_FLAG_LARGE_BLOCK)
611321535Smav		fnvlist_add_boolean(args, "largeblockok");
612321535Smav	if (flags & LZC_SEND_FLAG_EMBED_DATA)
613321535Smav		fnvlist_add_boolean(args, "embedok");
614321535Smav	if (flags & LZC_SEND_FLAG_COMPRESS)
615321535Smav		fnvlist_add_boolean(args, "compressok");
616238592Smm	err = lzc_ioctl(ZFS_IOC_SEND_SPACE, snapname, args, &result);
617238592Smm	nvlist_free(args);
618238592Smm	if (err == 0)
619238592Smm		*spacep = fnvlist_lookup_uint64(result, "space");
620238592Smm	nvlist_free(result);
621238592Smm	return (err);
622238592Smm}
623238592Smm
624238592Smmstatic int
625238592Smmrecv_read(int fd, void *buf, int ilen)
626238592Smm{
627238592Smm	char *cp = buf;
628238592Smm	int rv;
629238592Smm	int len = ilen;
630238592Smm
631238592Smm	do {
632238592Smm		rv = read(fd, cp, len);
633238592Smm		cp += rv;
634238592Smm		len -= rv;
635238592Smm	} while (rv > 0);
636238592Smm
637238592Smm	if (rv < 0 || len != 0)
638238592Smm		return (EIO);
639238592Smm
640238592Smm	return (0);
641238592Smm}
642238592Smm
643289362Smavstatic int
644308763Savgrecv_impl(const char *snapname, nvlist_t *props, const char *origin,
645308763Savg    boolean_t force, boolean_t resumable, int fd,
646308763Savg    const dmu_replay_record_t *begin_record)
647238592Smm{
648238592Smm	/*
649238592Smm	 * The receive ioctl is still legacy, so we need to construct our own
650238592Smm	 * zfs_cmd_t rather than using zfsc_ioctl().
651238592Smm	 */
652238592Smm	zfs_cmd_t zc = { 0 };
653238592Smm	char *atp;
654238592Smm	char *packed = NULL;
655238592Smm	size_t size;
656238592Smm	int error;
657238592Smm
658238592Smm	ASSERT3S(g_refcount, >, 0);
659238592Smm
660238592Smm	/* zc_name is name of containing filesystem */
661238592Smm	(void) strlcpy(zc.zc_name, snapname, sizeof (zc.zc_name));
662238592Smm	atp = strchr(zc.zc_name, '@');
663238592Smm	if (atp == NULL)
664238592Smm		return (EINVAL);
665238592Smm	*atp = '\0';
666238592Smm
667238592Smm	/* if the fs does not exist, try its parent. */
668238592Smm	if (!lzc_exists(zc.zc_name)) {
669238592Smm		char *slashp = strrchr(zc.zc_name, '/');
670238592Smm		if (slashp == NULL)
671238592Smm			return (ENOENT);
672238592Smm		*slashp = '\0';
673238592Smm
674238592Smm	}
675238592Smm
676238592Smm	/* zc_value is full name of the snapshot to create */
677238592Smm	(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
678238592Smm
679238592Smm	if (props != NULL) {
680238592Smm		/* zc_nvlist_src is props to set */
681238592Smm		packed = fnvlist_pack(props, &size);
682238592Smm		zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed;
683238592Smm		zc.zc_nvlist_src_size = size;
684238592Smm	}
685238592Smm
686238592Smm	/* zc_string is name of clone origin (if DRR_FLAG_CLONE) */
687238592Smm	if (origin != NULL)
688238592Smm		(void) strlcpy(zc.zc_string, origin, sizeof (zc.zc_string));
689238592Smm
690238592Smm	/* zc_begin_record is non-byteswapped BEGIN record */
691308763Savg	if (begin_record == NULL) {
692308763Savg		error = recv_read(fd, &zc.zc_begin_record,
693308763Savg		    sizeof (zc.zc_begin_record));
694308763Savg		if (error != 0)
695308763Savg			goto out;
696308763Savg	} else {
697308763Savg		zc.zc_begin_record = *begin_record;
698308763Savg	}
699238592Smm
700238592Smm	/* zc_cookie is fd to read from */
701238592Smm	zc.zc_cookie = fd;
702238592Smm
703238592Smm	/* zc guid is force flag */
704238592Smm	zc.zc_guid = force;
705238592Smm
706289362Smav	zc.zc_resumable = resumable;
707289362Smav
708238592Smm	/* zc_cleanup_fd is unused */
709238592Smm	zc.zc_cleanup_fd = -1;
710238592Smm
711238592Smm	error = ioctl(g_fd, ZFS_IOC_RECV, &zc);
712238592Smm	if (error != 0)
713238592Smm		error = errno;
714238592Smm
715238592Smmout:
716238592Smm	if (packed != NULL)
717238592Smm		fnvlist_pack_free(packed, size);
718238592Smm	free((void*)(uintptr_t)zc.zc_nvlist_dst);
719238592Smm	return (error);
720238592Smm}
721254587Sdelphij
722254587Sdelphij/*
723289362Smav * The simplest receive case: receive from the specified fd, creating the
724289362Smav * specified snapshot.  Apply the specified properties as "received" properties
725289362Smav * (which can be overridden by locally-set properties).  If the stream is a
726289362Smav * clone, its origin snapshot must be specified by 'origin'.  The 'force'
727289362Smav * flag will cause the target filesystem to be rolled back or destroyed if
728289362Smav * necessary to receive.
729289362Smav *
730289362Smav * Return 0 on success or an errno on failure.
731289362Smav *
732289362Smav * Note: this interface does not work on dedup'd streams
733289362Smav * (those with DMU_BACKUP_FEATURE_DEDUP).
734289362Smav */
735289362Smavint
736289362Smavlzc_receive(const char *snapname, nvlist_t *props, const char *origin,
737289362Smav    boolean_t force, int fd)
738289362Smav{
739308763Savg	return (recv_impl(snapname, props, origin, force, B_FALSE, fd, NULL));
740289362Smav}
741289362Smav
742289362Smav/*
743289362Smav * Like lzc_receive, but if the receive fails due to premature stream
744289362Smav * termination, the intermediate state will be preserved on disk.  In this
745289362Smav * case, ECKSUM will be returned.  The receive may subsequently be resumed
746289362Smav * with a resuming send stream generated by lzc_send_resume().
747289362Smav */
748289362Smavint
749289362Smavlzc_receive_resumable(const char *snapname, nvlist_t *props, const char *origin,
750289362Smav    boolean_t force, int fd)
751289362Smav{
752308763Savg	return (recv_impl(snapname, props, origin, force, B_TRUE, fd, NULL));
753289362Smav}
754289362Smav
755289362Smav/*
756308763Savg * Like lzc_receive, but allows the caller to read the begin record and then to
757308763Savg * pass it in.  That could be useful if the caller wants to derive, for example,
758308763Savg * the snapname or the origin parameters based on the information contained in
759308763Savg * the begin record.
760308763Savg * The begin record must be in its original form as read from the stream,
761308763Savg * in other words, it should not be byteswapped.
762308763Savg *
763308763Savg * The 'resumable' parameter allows to obtain the same behavior as with
764308763Savg * lzc_receive_resumable.
765308763Savg */
766308763Savgint
767308763Savglzc_receive_with_header(const char *snapname, nvlist_t *props,
768308763Savg    const char *origin, boolean_t force, boolean_t resumable, int fd,
769308763Savg    const dmu_replay_record_t *begin_record)
770308763Savg{
771308763Savg	if (begin_record == NULL)
772308763Savg		return (EINVAL);
773308763Savg	return (recv_impl(snapname, props, origin, force, resumable, fd,
774308763Savg	    begin_record));
775308763Savg}
776308763Savg
777308763Savg/*
778254587Sdelphij * Roll back this filesystem or volume to its most recent snapshot.
779254587Sdelphij * If snapnamebuf is not NULL, it will be filled in with the name
780254587Sdelphij * of the most recent snapshot.
781323757Savg * Note that the latest snapshot may change if a new one is concurrently
782323757Savg * created or the current one is destroyed.  lzc_rollback_to can be used
783323757Savg * to roll back to a specific latest snapshot.
784254587Sdelphij *
785254587Sdelphij * Return 0 on success or an errno on failure.
786254587Sdelphij */
787254587Sdelphijint
788254587Sdelphijlzc_rollback(const char *fsname, char *snapnamebuf, int snapnamelen)
789254587Sdelphij{
790254587Sdelphij	nvlist_t *args;
791254587Sdelphij	nvlist_t *result;
792254587Sdelphij	int err;
793254587Sdelphij
794254587Sdelphij	args = fnvlist_alloc();
795254587Sdelphij	err = lzc_ioctl(ZFS_IOC_ROLLBACK, fsname, args, &result);
796254587Sdelphij	nvlist_free(args);
797254587Sdelphij	if (err == 0 && snapnamebuf != NULL) {
798254587Sdelphij		const char *snapname = fnvlist_lookup_string(result, "target");
799254587Sdelphij		(void) strlcpy(snapnamebuf, snapname, snapnamelen);
800254587Sdelphij	}
801321544Smav	nvlist_free(result);
802321544Smav
803254587Sdelphij	return (err);
804254587Sdelphij}
805260183Sdelphij
806260183Sdelphij/*
807323757Savg * Roll back this filesystem or volume to the specified snapshot,
808323757Savg * if possible.
809323757Savg *
810323757Savg * Return 0 on success or an errno on failure.
811323757Savg */
812323757Savgint
813323757Savglzc_rollback_to(const char *fsname, const char *snapname)
814323757Savg{
815323757Savg	nvlist_t *args;
816323757Savg	nvlist_t *result;
817323757Savg	int err;
818323757Savg
819323757Savg	args = fnvlist_alloc();
820323757Savg	fnvlist_add_string(args, "target", snapname);
821323757Savg	err = lzc_ioctl(ZFS_IOC_ROLLBACK, fsname, args, &result);
822323757Savg	nvlist_free(args);
823323757Savg	nvlist_free(result);
824323757Savg	return (err);
825323757Savg}
826323757Savg
827323757Savg/*
828260183Sdelphij * Creates bookmarks.
829260183Sdelphij *
830260183Sdelphij * The bookmarks nvlist maps from name of the bookmark (e.g. "pool/fs#bmark") to
831260183Sdelphij * the name of the snapshot (e.g. "pool/fs@snap").  All the bookmarks and
832260183Sdelphij * snapshots must be in the same pool.
833260183Sdelphij *
834260183Sdelphij * The returned results nvlist will have an entry for each bookmark that failed.
835260183Sdelphij * The value will be the (int32) error code.
836260183Sdelphij *
837260183Sdelphij * The return value will be 0 if all bookmarks were created, otherwise it will
838260183Sdelphij * be the errno of a (undetermined) bookmarks that failed.
839260183Sdelphij */
840260183Sdelphijint
841260183Sdelphijlzc_bookmark(nvlist_t *bookmarks, nvlist_t **errlist)
842260183Sdelphij{
843260183Sdelphij	nvpair_t *elem;
844260183Sdelphij	int error;
845307108Smav	char pool[ZFS_MAX_DATASET_NAME_LEN];
846260183Sdelphij
847260183Sdelphij	/* determine the pool name */
848260183Sdelphij	elem = nvlist_next_nvpair(bookmarks, NULL);
849260183Sdelphij	if (elem == NULL)
850260183Sdelphij		return (0);
851260183Sdelphij	(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
852260183Sdelphij	pool[strcspn(pool, "/#")] = '\0';
853260183Sdelphij
854260183Sdelphij	error = lzc_ioctl(ZFS_IOC_BOOKMARK, pool, bookmarks, errlist);
855260183Sdelphij
856260183Sdelphij	return (error);
857260183Sdelphij}
858260183Sdelphij
859260183Sdelphij/*
860260183Sdelphij * Retrieve bookmarks.
861260183Sdelphij *
862260183Sdelphij * Retrieve the list of bookmarks for the given file system. The props
863260183Sdelphij * parameter is an nvlist of property names (with no values) that will be
864260183Sdelphij * returned for each bookmark.
865260183Sdelphij *
866260183Sdelphij * The following are valid properties on bookmarks, all of which are numbers
867260183Sdelphij * (represented as uint64 in the nvlist)
868260183Sdelphij *
869260183Sdelphij * "guid" - globally unique identifier of the snapshot it refers to
870260183Sdelphij * "createtxg" - txg when the snapshot it refers to was created
871260183Sdelphij * "creation" - timestamp when the snapshot it refers to was created
872260183Sdelphij *
873260183Sdelphij * The format of the returned nvlist as follows:
874260183Sdelphij * <short name of bookmark> -> {
875260183Sdelphij *     <name of property> -> {
876260183Sdelphij *         "value" -> uint64
877260183Sdelphij *     }
878260183Sdelphij *  }
879260183Sdelphij */
880260183Sdelphijint
881260183Sdelphijlzc_get_bookmarks(const char *fsname, nvlist_t *props, nvlist_t **bmarks)
882260183Sdelphij{
883260183Sdelphij	return (lzc_ioctl(ZFS_IOC_GET_BOOKMARKS, fsname, props, bmarks));
884260183Sdelphij}
885260183Sdelphij
886260183Sdelphij/*
887260183Sdelphij * Destroys bookmarks.
888260183Sdelphij *
889260183Sdelphij * The keys in the bmarks nvlist are the bookmarks to be destroyed.
890260183Sdelphij * They must all be in the same pool.  Bookmarks are specified as
891260183Sdelphij * <fs>#<bmark>.
892260183Sdelphij *
893260183Sdelphij * Bookmarks that do not exist will be silently ignored.
894260183Sdelphij *
895260183Sdelphij * The return value will be 0 if all bookmarks that existed were destroyed.
896260183Sdelphij *
897260183Sdelphij * Otherwise the return value will be the errno of a (undetermined) bookmark
898260183Sdelphij * that failed, no bookmarks will be destroyed, and the errlist will have an
899260183Sdelphij * entry for each bookmarks that failed.  The value in the errlist will be
900260183Sdelphij * the (int32) error code.
901260183Sdelphij */
902260183Sdelphijint
903260183Sdelphijlzc_destroy_bookmarks(nvlist_t *bmarks, nvlist_t **errlist)
904260183Sdelphij{
905260183Sdelphij	nvpair_t *elem;
906260183Sdelphij	int error;
907307108Smav	char pool[ZFS_MAX_DATASET_NAME_LEN];
908260183Sdelphij
909260183Sdelphij	/* determine the pool name */
910260183Sdelphij	elem = nvlist_next_nvpair(bmarks, NULL);
911260183Sdelphij	if (elem == NULL)
912260183Sdelphij		return (0);
913260183Sdelphij	(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
914260183Sdelphij	pool[strcspn(pool, "/#")] = '\0';
915260183Sdelphij
916260183Sdelphij	error = lzc_ioctl(ZFS_IOC_DESTROY_BOOKMARKS, pool, bmarks, errlist);
917260183Sdelphij
918260183Sdelphij	return (error);
919260183Sdelphij}
920325534Savg
921329484Smavstatic int
922329484Smavlzc_channel_program_impl(const char *pool, const char *program, boolean_t sync,
923329484Smav    uint64_t instrlimit, uint64_t memlimit, nvlist_t *argnvl, nvlist_t **outnvl)
924329484Smav{
925329484Smav	int error;
926329484Smav	nvlist_t *args;
927329484Smav
928329484Smav	args = fnvlist_alloc();
929329484Smav	fnvlist_add_string(args, ZCP_ARG_PROGRAM, program);
930329484Smav	fnvlist_add_nvlist(args, ZCP_ARG_ARGLIST, argnvl);
931329484Smav	fnvlist_add_boolean_value(args, ZCP_ARG_SYNC, sync);
932329484Smav	fnvlist_add_uint64(args, ZCP_ARG_INSTRLIMIT, instrlimit);
933329484Smav	fnvlist_add_uint64(args, ZCP_ARG_MEMLIMIT, memlimit);
934329484Smav	error = lzc_ioctl(ZFS_IOC_CHANNEL_PROGRAM, pool, args, outnvl);
935329484Smav	fnvlist_free(args);
936329484Smav
937329484Smav	return (error);
938329484Smav}
939329484Smav
940325534Savg/*
941325534Savg * Executes a channel program.
942325534Savg *
943325534Savg * If this function returns 0 the channel program was successfully loaded and
944325534Savg * ran without failing. Note that individual commands the channel program ran
945325534Savg * may have failed and the channel program is responsible for reporting such
946325534Savg * errors through outnvl if they are important.
947325534Savg *
948325534Savg * This method may also return:
949325534Savg *
950325534Savg * EINVAL   The program contains syntax errors, or an invalid memory or time
951325534Savg *          limit was given. No part of the channel program was executed.
952325534Savg *          If caused by syntax errors, 'outnvl' contains information about the
953325534Savg *          errors.
954325534Savg *
955325534Savg * EDOM     The program was executed, but encountered a runtime error, such as
956325534Savg *          calling a function with incorrect arguments, invoking the error()
957325534Savg *          function directly, failing an assert() command, etc. Some portion
958325534Savg *          of the channel program may have executed and committed changes.
959325534Savg *          Information about the failure can be found in 'outnvl'.
960325534Savg *
961325534Savg * ENOMEM   The program fully executed, but the output buffer was not large
962325534Savg *          enough to store the returned value. No output is returned through
963325534Savg *          'outnvl'.
964325534Savg *
965325534Savg * ENOSPC   The program was terminated because it exceeded its memory usage
966325534Savg *          limit. Some portion of the channel program may have executed and
967325534Savg *          committed changes to disk. No output is returned through 'outnvl'.
968325534Savg *
969325534Savg * ETIMEDOUT The program was terminated because it exceeded its Lua instruction
970325534Savg *           limit. Some portion of the channel program may have executed and
971325534Savg *           committed changes to disk. No output is returned through 'outnvl'.
972325534Savg */
973325534Savgint
974325534Savglzc_channel_program(const char *pool, const char *program, uint64_t instrlimit,
975325534Savg    uint64_t memlimit, nvlist_t *argnvl, nvlist_t **outnvl)
976325534Savg{
977329484Smav	return (lzc_channel_program_impl(pool, program, B_TRUE, instrlimit,
978329484Smav	    memlimit, argnvl, outnvl));
979329484Smav}
980325534Savg
981329484Smav/*
982329484Smav * Executes a read-only channel program.
983329484Smav *
984329484Smav * A read-only channel program works programmatically the same way as a
985329484Smav * normal channel program executed with lzc_channel_program(). The only
986329484Smav * difference is it runs exclusively in open-context and therefore can
987329484Smav * return faster. The downside to that, is that the program cannot change
988329484Smav * on-disk state by calling functions from the zfs.sync submodule.
989329484Smav *
990329484Smav * The return values of this function (and their meaning) are exactly the
991329484Smav * same as the ones described in lzc_channel_program().
992329484Smav */
993329484Smavint
994329484Smavlzc_channel_program_nosync(const char *pool, const char *program,
995329484Smav    uint64_t timeout, uint64_t memlimit, nvlist_t *argnvl, nvlist_t **outnvl)
996329484Smav{
997329484Smav	return (lzc_channel_program_impl(pool, program, B_FALSE, timeout,
998329484Smav	    memlimit, argnvl, outnvl));
999325534Savg}
1000