libzfs_core.c revision 251646
1107572Sgrehan/*
2107572Sgrehan * CDDL HEADER START
3107572Sgrehan *
4107572Sgrehan * The contents of this file are subject to the terms of the
5107572Sgrehan * Common Development and Distribution License (the "License").
6107572Sgrehan * You may not use this file except in compliance with the License.
7107572Sgrehan *
8107572Sgrehan * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9107572Sgrehan * or http://www.opensolaris.org/os/licensing.
10107572Sgrehan * See the License for the specific language governing permissions
11107572Sgrehan * and limitations under the License.
12107572Sgrehan *
13107572Sgrehan * When distributing Covered Code, include this CDDL HEADER in each
14107572Sgrehan * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15107572Sgrehan * If applicable, add the following below this CDDL HEADER, with the
16107572Sgrehan * fields enclosed by brackets "[]" replaced with your own identifying
17107572Sgrehan * information: Portions Copyright [yyyy] [name of copyright owner]
18107572Sgrehan *
19107572Sgrehan * CDDL HEADER END
20107572Sgrehan */
21107572Sgrehan
22107572Sgrehan/*
23107572Sgrehan * Copyright (c) 2012 by Delphix. All rights reserved.
24107572Sgrehan * Copyright (c) 2013 Steven Hartland. All rights reserved.
25107572Sgrehan */
26107572Sgrehan
27107572Sgrehan/*
28107572Sgrehan * LibZFS_Core (lzc) is intended to replace most functionality in libzfs.
29107572Sgrehan * It has the following characteristics:
30107572Sgrehan *
31107572Sgrehan *  - Thread Safe.  libzfs_core is accessible concurrently from multiple
32107572Sgrehan *  threads.  This is accomplished primarily by avoiding global data
33107572Sgrehan *  (e.g. caching).  Since it's thread-safe, there is no reason for a
34107572Sgrehan *  process to have multiple libzfs "instances".  Therefore, we store
35107572Sgrehan *  our few pieces of data (e.g. the file descriptor) in global
36107572Sgrehan *  variables.  The fd is reference-counted so that the libzfs_core
37107572Sgrehan *  library can be "initialized" multiple times (e.g. by different
38107572Sgrehan *  consumers within the same process).
39107572Sgrehan *
40107572Sgrehan *  - Committed Interface.  The libzfs_core interface will be committed,
41173745Sjb *  therefore consumers can compile against it and be confident that
42107572Sgrehan *  their code will continue to work on future releases of this code.
43107572Sgrehan *  Currently, the interface is Evolving (not Committed), but we intend
44107572Sgrehan *  to commit to it once it is more complete and we determine that it
45107572Sgrehan *  meets the needs of all consumers.
46209885Snwhitehorn *
47209885Snwhitehorn *  - Programatic Error Handling.  libzfs_core communicates errors with
48209885Snwhitehorn *  defined error numbers, and doesn't print anything to stdout/stderr.
49209885Snwhitehorn *
50209885Snwhitehorn *  - Thin Layer.  libzfs_core is a thin layer, marshaling arguments
51107572Sgrehan *  to/from the kernel ioctls.  There is generally a 1:1 correspondence
52107572Sgrehan *  between libzfs_core functions and ioctls to /dev/zfs.
53107572Sgrehan *
54107572Sgrehan *  - Clear Atomicity.  Because libzfs_core functions are generally 1:1
55107572Sgrehan *  with kernel ioctls, and kernel ioctls are general atomic, each
56107572Sgrehan *  libzfs_core function is atomic.  For example, creating multiple
57107572Sgrehan *  snapshots with a single call to lzc_snapshot() is atomic -- it
58107572Sgrehan *  can't fail with only some of the requested snapshots created, even
59107572Sgrehan *  in the event of power loss or system crash.
60107572Sgrehan *
61115396Skan *  - Continued libzfs Support.  Some higher-level operations (e.g.
62107572Sgrehan *  support for "zfs send -R") are too complicated to fit the scope of
63107572Sgrehan *  libzfs_core.  This functionality will continue to live in libzfs.
64115396Skan *  Where appropriate, libzfs will use the underlying atomic operations
65107572Sgrehan *  of libzfs_core.  For example, libzfs may implement "zfs send -R |
66115396Skan *  zfs receive" by using individual "send one snapshot", rename,
67107572Sgrehan *  destroy, and "receive one snapshot" operations in libzfs_core.
68107572Sgrehan *  /sbin/zfs and /zbin/zpool will link with both libzfs and
69107572Sgrehan *  libzfs_core.  Other consumers should aim to use only libzfs_core,
70107572Sgrehan *  since that will be the supported, stable interface going forwards.
71107572Sgrehan */
72107572Sgrehan
73107572Sgrehan#define _IN_LIBZFS_CORE_
74107572Sgrehan
75216695Skib#include <libzfs_core.h>
76216695Skib#include <ctype.h>
77216695Skib#include <unistd.h>
78107572Sgrehan#include <stdlib.h>
79107572Sgrehan#include <string.h>
80107572Sgrehan#include <errno.h>
81107572Sgrehan#include <fcntl.h>
82107572Sgrehan#include <pthread.h>
83107572Sgrehan#include <sys/nvpair.h>
84107572Sgrehan#include <sys/param.h>
85107572Sgrehan#include <sys/types.h>
86107572Sgrehan#include <sys/stat.h>
87216695Skib#include <sys/zfs_ioctl.h>
88216695Skib#include "libzfs_core_compat.h"
89115396Skan#include "libzfs_compat.h"
90115396Skan
91107572Sgrehan#ifdef __FreeBSD__
92216695Skibextern int zfs_ioctl_version;
93216695Skib#endif
94216695Skib
95216695Skibstatic int g_fd;
96107572Sgrehanstatic pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
97107572Sgrehanstatic int g_refcount;
98107572Sgrehan
99107572Sgrehanint
100107572Sgrehanlibzfs_core_init(void)
101107572Sgrehan{
102107572Sgrehan	(void) pthread_mutex_lock(&g_lock);
103107572Sgrehan	if (g_refcount == 0) {
104107572Sgrehan		g_fd = open("/dev/zfs", O_RDWR);
105107572Sgrehan		if (g_fd < 0) {
106115396Skan			(void) pthread_mutex_unlock(&g_lock);
107216695Skib			return (errno);
108115396Skan		}
109209885Snwhitehorn	}
110107572Sgrehan	g_refcount++;
111115396Skan	(void) pthread_mutex_unlock(&g_lock);
112107572Sgrehan
113107572Sgrehan	return (0);
114107572Sgrehan}
115107572Sgrehan
116107572Sgrehanvoid
117107572Sgrehanlibzfs_core_fini(void)
118107572Sgrehan{
119107572Sgrehan	(void) pthread_mutex_lock(&g_lock);
120107572Sgrehan	ASSERT3S(g_refcount, >, 0);
121107572Sgrehan	g_refcount--;
122107572Sgrehan	if (g_refcount == 0)
123107572Sgrehan		(void) close(g_fd);
124107572Sgrehan	(void) pthread_mutex_unlock(&g_lock);
125107572Sgrehan}
126107572Sgrehan
127107572Sgrehanstatic int
128107572Sgrehanlzc_ioctl(zfs_ioc_t ioc, const char *name,
129107572Sgrehan    nvlist_t *source, nvlist_t **resultp)
130107572Sgrehan{
131107572Sgrehan	zfs_cmd_t zc = { 0 };
132107572Sgrehan	int error = 0;
133107572Sgrehan	char *packed;
134107572Sgrehan#ifdef __FreeBSD__
135107572Sgrehan	nvlist_t *oldsource;
136107572Sgrehan#endif
137107572Sgrehan	size_t size;
138107572Sgrehan
139107572Sgrehan	ASSERT3S(g_refcount, >, 0);
140107572Sgrehan
141115396Skan	(void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
142107572Sgrehan
143107572Sgrehan#ifdef __FreeBSD__
144107572Sgrehan	if (zfs_ioctl_version == ZFS_IOCVER_UNDEF)
145107572Sgrehan		zfs_ioctl_version = get_zfs_ioctl_version();
146107572Sgrehan
147107572Sgrehan	if (zfs_ioctl_version < ZFS_IOCVER_LZC) {
148107572Sgrehan		oldsource = source;
149107572Sgrehan		error = lzc_compat_pre(&zc, &ioc, &source);
150107572Sgrehan		if (error)
151107572Sgrehan			return (error);
152115396Skan	}
153107572Sgrehan#endif
154107572Sgrehan
155107572Sgrehan	packed = fnvlist_pack(source, &size);
156216695Skib	zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed;
157107572Sgrehan	zc.zc_nvlist_src_size = size;
158107572Sgrehan
159107572Sgrehan	if (resultp != NULL) {
160107572Sgrehan		*resultp = NULL;
161107572Sgrehan		zc.zc_nvlist_dst_size = MAX(size * 2, 128 * 1024);
162107572Sgrehan		zc.zc_nvlist_dst = (uint64_t)(uintptr_t)
163107572Sgrehan		    malloc(zc.zc_nvlist_dst_size);
164115396Skan#ifdef illumos
165107572Sgrehan		if (zc.zc_nvlist_dst == NULL) {
166107572Sgrehan#else
167107572Sgrehan		if (zc.zc_nvlist_dst == 0) {
168216939Snwhitehorn#endif
169216939Snwhitehorn			error = ENOMEM;
170209885Snwhitehorn			goto out;
171107572Sgrehan		}
172216695Skib	}
173107572Sgrehan
174107572Sgrehan	while (ioctl(g_fd, ioc, &zc) != 0) {
175107572Sgrehan		if (errno == ENOMEM && resultp != NULL) {
176107572Sgrehan			free((void *)(uintptr_t)zc.zc_nvlist_dst);
177107572Sgrehan			zc.zc_nvlist_dst_size *= 2;
178107572Sgrehan			zc.zc_nvlist_dst = (uint64_t)(uintptr_t)
179107572Sgrehan			    malloc(zc.zc_nvlist_dst_size);
180107572Sgrehan#ifdef illumos
181107572Sgrehan			if (zc.zc_nvlist_dst == NULL) {
182107572Sgrehan#else
183107572Sgrehan			if (zc.zc_nvlist_dst == 0) {
184107572Sgrehan#endif
185107572Sgrehan				error = ENOMEM;
186209885Snwhitehorn				goto out;
187107572Sgrehan			}
188115396Skan		} else {
189107572Sgrehan			error = errno;
190107572Sgrehan			break;
191107572Sgrehan		}
192107572Sgrehan	}
193107572Sgrehan
194107572Sgrehan#ifdef __FreeBSD__
195107572Sgrehan	if (zfs_ioctl_version < ZFS_IOCVER_LZC)
196107572Sgrehan		lzc_compat_post(&zc, ioc);
197107572Sgrehan#endif
198107572Sgrehan	if (zc.zc_nvlist_dst_filled) {
199107572Sgrehan		*resultp = fnvlist_unpack((void *)(uintptr_t)zc.zc_nvlist_dst,
200107572Sgrehan		    zc.zc_nvlist_dst_size);
201107572Sgrehan	}
202107572Sgrehan#ifdef __FreeBSD__
203107572Sgrehan	if (zfs_ioctl_version < ZFS_IOCVER_LZC)
204107572Sgrehan		lzc_compat_outnvl(&zc, ioc, resultp);
205107572Sgrehan#endif
206107572Sgrehanout:
207107572Sgrehan#ifdef __FreeBSD__
208115396Skan	if (zfs_ioctl_version < ZFS_IOCVER_LZC) {
209107572Sgrehan		if (source != oldsource)
210107572Sgrehan			nvlist_free(source);
211107572Sgrehan		source = oldsource;
212107572Sgrehan	}
213107572Sgrehan#endif
214107572Sgrehan	fnvlist_pack_free(packed, size);
215107572Sgrehan	free((void *)(uintptr_t)zc.zc_nvlist_dst);
216107572Sgrehan	return (error);
217209885Snwhitehorn}
218137122Sssouhlal
219216695Skibint
220137122Sssouhlallzc_create(const char *fsname, dmu_objset_type_t type, nvlist_t *props)
221137122Sssouhlal{
222137122Sssouhlal	int error;
223137122Sssouhlal	nvlist_t *args = fnvlist_alloc();
224137122Sssouhlal	fnvlist_add_int32(args, "type", type);
225137122Sssouhlal	if (props != NULL)
226137122Sssouhlal		fnvlist_add_nvlist(args, "props", props);
227137122Sssouhlal	error = lzc_ioctl(ZFS_IOC_CREATE, fsname, args, NULL);
228209885Snwhitehorn	nvlist_free(args);
229137122Sssouhlal	return (error);
230216695Skib}
231137122Sssouhlal
232137122Sssouhlalint
233137122Sssouhlallzc_clone(const char *fsname, const char *origin,
234137122Sssouhlal    nvlist_t *props)
235137122Sssouhlal{
236137122Sssouhlal	int error;
237137122Sssouhlal	nvlist_t *args = fnvlist_alloc();
238137122Sssouhlal	fnvlist_add_string(args, "origin", origin);
239137122Sssouhlal	if (props != NULL)
240137122Sssouhlal		fnvlist_add_nvlist(args, "props", props);
241137122Sssouhlal	error = lzc_ioctl(ZFS_IOC_CLONE, fsname, args, NULL);
242137122Sssouhlal	nvlist_free(args);
243137122Sssouhlal	return (error);
244137122Sssouhlal}
245137122Sssouhlal
246137122Sssouhlal/*
247137122Sssouhlal * Creates snapshots.
248137122Sssouhlal *
249137122Sssouhlal * The keys in the snaps nvlist are the snapshots to be created.
250137122Sssouhlal * They must all be in the same pool.
251137122Sssouhlal *
252137122Sssouhlal * The props nvlist is properties to set.  Currently only user properties
253161799Smarcel * are supported.  { user:prop_name -> string value }
254137122Sssouhlal *
255137122Sssouhlal * The returned results nvlist will have an entry for each snapshot that failed.
256137122Sssouhlal * The value will be the (int32) error code.
257209885Snwhitehorn *
258137122Sssouhlal * The return value will be 0 if all snapshots were created, otherwise it will
259216695Skib * be the errno of a (unspecified) snapshot that failed.
260137122Sssouhlal */
261137122Sssouhlalint
262137122Sssouhlallzc_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t **errlist)
263137122Sssouhlal{
264137122Sssouhlal	nvpair_t *elem;
265137122Sssouhlal	nvlist_t *args;
266137122Sssouhlal	int error;
267137122Sssouhlal	char pool[MAXNAMELEN];
268137122Sssouhlal
269107572Sgrehan	*errlist = NULL;
270209885Snwhitehorn
271107572Sgrehan	/* determine the pool name */
272115396Skan	elem = nvlist_next_nvpair(snaps, NULL);
273107572Sgrehan	if (elem == NULL)
274107572Sgrehan		return (0);
275115396Skan	(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
276107572Sgrehan	pool[strcspn(pool, "/@")] = '\0';
277107572Sgrehan
278107572Sgrehan	args = fnvlist_alloc();
279107572Sgrehan	fnvlist_add_nvlist(args, "snaps", snaps);
280107572Sgrehan	if (props != NULL)
281107572Sgrehan		fnvlist_add_nvlist(args, "props", props);
282107572Sgrehan
283216695Skib	error = lzc_ioctl(ZFS_IOC_SNAPSHOT, pool, args, errlist);
284107572Sgrehan	nvlist_free(args);
285107572Sgrehan
286107572Sgrehan	return (error);
287107572Sgrehan}
288209885Snwhitehorn
289107572Sgrehan/*
290107572Sgrehan * Destroys snapshots.
291107572Sgrehan *
292107572Sgrehan * The keys in the snaps nvlist are the snapshots to be destroyed.
293107572Sgrehan * They must all be in the same pool.
294107572Sgrehan *
295171462Smarcel * Snapshots that do not exist will be silently ignored.
296209885Snwhitehorn *
297209885Snwhitehorn * If 'defer' is not set, and a snapshot has user holds or clones, the
298209885Snwhitehorn * destroy operation will fail and none of the snapshots will be
299209885Snwhitehorn * destroyed.
300171462Smarcel *
301107572Sgrehan * If 'defer' is set, and a snapshot has user holds or clones, it will be
302107572Sgrehan * marked for deferred destruction, and will be destroyed when the last hold
303107572Sgrehan * or clone is removed/destroyed.
304107572Sgrehan *
305115396Skan * The return value will be ENOENT if none of the snapshots existed.
306107572Sgrehan *
307107572Sgrehan * The return value will be 0 if all snapshots were destroyed (or marked for
308107572Sgrehan * later destruction if 'defer' is set) or didn't exist to begin with and
309107572Sgrehan * at least one snapshot was destroyed.
310216695Skib *
311216695Skib * Otherwise the return value will be the errno of a (unspecified) snapshot
312107572Sgrehan * that failed, no snapshots will be destroyed, and the errlist will have an
313107572Sgrehan * entry for each snapshot that failed.  The value in the errlist will be
314107572Sgrehan * the (int32) error code.
315107572Sgrehan */
316228646Snwhitehornint
317209885Snwhitehornlzc_destroy_snaps(nvlist_t *snaps, boolean_t defer, nvlist_t **errlist)
318228646Snwhitehorn{
319228646Snwhitehorn	nvpair_t *elem;
320228646Snwhitehorn	nvlist_t *args;
321228646Snwhitehorn	int error;
322107572Sgrehan	char pool[MAXNAMELEN];
323107572Sgrehan
324107572Sgrehan	/* determine the pool name */
325209885Snwhitehorn	elem = nvlist_next_nvpair(snaps, NULL);
326107572Sgrehan	if (elem == NULL)
327107572Sgrehan		return (0);
328107572Sgrehan	(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
329107572Sgrehan	pool[strcspn(pool, "/@")] = '\0';
330107572Sgrehan
331107572Sgrehan	args = fnvlist_alloc();
332209885Snwhitehorn	fnvlist_add_nvlist(args, "snaps", snaps);
333209885Snwhitehorn	if (defer)
334209885Snwhitehorn		fnvlist_add_boolean(args, "defer");
335107572Sgrehan
336107572Sgrehan	error = lzc_ioctl(ZFS_IOC_DESTROY_SNAPS, pool, args, errlist);
337107572Sgrehan	nvlist_free(args);
338209885Snwhitehorn
339209885Snwhitehorn	return (error);
340209885Snwhitehorn}
341209885Snwhitehorn
342209885Snwhitehornint
343107572Sgrehanlzc_snaprange_space(const char *firstsnap, const char *lastsnap,
344209885Snwhitehorn    uint64_t *usedp)
345209885Snwhitehorn{
346209885Snwhitehorn	nvlist_t *args;
347209885Snwhitehorn	nvlist_t *result;
348107572Sgrehan	int err;
349107572Sgrehan	char fs[MAXNAMELEN];
350107572Sgrehan	char *atp;
351107572Sgrehan
352107572Sgrehan	/* determine the fs name */
353107572Sgrehan	(void) strlcpy(fs, firstsnap, sizeof (fs));
354107572Sgrehan	atp = strchr(fs, '@');
355107572Sgrehan	if (atp == NULL)
356107572Sgrehan		return (EINVAL);
357107572Sgrehan	*atp = '\0';
358107572Sgrehan
359107572Sgrehan	args = fnvlist_alloc();
360107572Sgrehan	fnvlist_add_string(args, "firstsnap", firstsnap);
361107572Sgrehan
362107572Sgrehan	err = lzc_ioctl(ZFS_IOC_SPACE_SNAPS, lastsnap, args, &result);
363115396Skan	nvlist_free(args);
364107572Sgrehan	if (err == 0)
365107572Sgrehan		*usedp = fnvlist_lookup_uint64(result, "used");
366107572Sgrehan	fnvlist_free(result);
367107572Sgrehan
368107572Sgrehan	return (err);
369107572Sgrehan}
370107572Sgrehan
371107572Sgrehanboolean_t
372107572Sgrehanlzc_exists(const char *dataset)
373107572Sgrehan{
374107572Sgrehan	/*
375107572Sgrehan	 * The objset_stats ioctl is still legacy, so we need to construct our
376107572Sgrehan	 * own zfs_cmd_t rather than using zfsc_ioctl().
377107572Sgrehan	 */
378107572Sgrehan	zfs_cmd_t zc = { 0 };
379107572Sgrehan
380107572Sgrehan	(void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
381107572Sgrehan	return (ioctl(g_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0);
382216695Skib}
383107572Sgrehan
384107572Sgrehan/*
385107572Sgrehan * Create "user holds" on snapshots.  If there is a hold on a snapshot,
386107572Sgrehan * the snapshot can not be destroyed.  (However, it can be marked for deletion
387107572Sgrehan * by lzc_destroy_snaps(defer=B_TRUE).)
388107572Sgrehan *
389107572Sgrehan * The keys in the nvlist are snapshot names.
390107572Sgrehan * The snapshots must all be in the same pool.
391107572Sgrehan * The value is the name of the hold (string type).
392107572Sgrehan *
393107572Sgrehan * If cleanup_fd is not -1, it must be the result of open("/dev/zfs", O_EXCL).
394107572Sgrehan * In this case, when the cleanup_fd is closed (including on process
395107572Sgrehan * termination), the holds will be released.  If the system is shut down
396216695Skib * uncleanly, the holds will be released when the pool is next opened
397107572Sgrehan * or imported.
398107572Sgrehan *
399107572Sgrehan * Holds for snapshots which don't exist will be skipped and have an entry
400107572Sgrehan * added to errlist, but will not cause an overall failure, except in the
401107572Sgrehan * case that all holds where skipped.
402107572Sgrehan *
403107572Sgrehan * The return value will be ENOENT if none of the snapshots for the requested
404107572Sgrehan * holds existed.
405107572Sgrehan *
406107572Sgrehan * The return value will be 0 if the nvl holds was empty or all holds, for
407107572Sgrehan * snapshots that existed, were succesfully created and at least one hold
408107572Sgrehan * was created.
409107572Sgrehan *
410107572Sgrehan * Otherwise the return value will be the errno of a (unspecified) hold that
411212497Snwhitehorn * failed and no holds will be created.
412212497Snwhitehorn *
413212497Snwhitehorn * In all cases the errlist will have an entry for each hold that failed
414212497Snwhitehorn * (name = snapshot), with its value being the error code (int32).
415212497Snwhitehorn */
416212497Snwhitehornint
417212497Snwhitehornlzc_hold(nvlist_t *holds, int cleanup_fd, nvlist_t **errlist)
418107572Sgrehan{
419107572Sgrehan	char pool[MAXNAMELEN];
420107572Sgrehan	nvlist_t *args;
421107572Sgrehan	nvpair_t *elem;
422107572Sgrehan	int error;
423107572Sgrehan
424107572Sgrehan	/* determine the pool name */
425107572Sgrehan	elem = nvlist_next_nvpair(holds, NULL);
426107572Sgrehan	if (elem == NULL)
427209885Snwhitehorn		return (0);
428107572Sgrehan	(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
429107572Sgrehan	pool[strcspn(pool, "/@")] = '\0';
430107572Sgrehan
431107572Sgrehan	args = fnvlist_alloc();
432107572Sgrehan	fnvlist_add_nvlist(args, "holds", holds);
433209885Snwhitehorn	if (cleanup_fd != -1)
434209885Snwhitehorn		fnvlist_add_int32(args, "cleanup_fd", cleanup_fd);
435209885Snwhitehorn
436107572Sgrehan	error = lzc_ioctl(ZFS_IOC_HOLD, pool, args, errlist);
437107572Sgrehan	nvlist_free(args);
438107572Sgrehan	return (error);
439107572Sgrehan}
440107572Sgrehan
441107572Sgrehan/*
442107572Sgrehan * Release "user holds" on snapshots.  If the snapshot has been marked for
443209885Snwhitehorn * deferred destroy (by lzc_destroy_snaps(defer=B_TRUE)), it does not have
444209885Snwhitehorn * any clones, and all the user holds are removed, then the snapshot will be
445209885Snwhitehorn * destroyed.
446209885Snwhitehorn *
447209885Snwhitehorn * The keys in the nvlist are snapshot names.
448209885Snwhitehorn * The snapshots must all be in the same pool.
449209885Snwhitehorn * The value is a nvlist whose keys are the holds to remove.
450107572Sgrehan *
451209885Snwhitehorn * Holds which failed to release because they didn't exist will have an entry
452209885Snwhitehorn * added to errlist, but will not cause an overall failure, except in the
453209885Snwhitehorn * case that all releases where skipped.
454209885Snwhitehorn *
455209885Snwhitehorn * The return value will be ENOENT if none of the specified holds existed.
456107572Sgrehan *
457209885Snwhitehorn * The return value will be 0 if the nvl holds was empty or all holds that
458107572Sgrehan * existed, were successfully removed and at least one hold was removed.
459107572Sgrehan *
460107572Sgrehan * Otherwise the return value will be the errno of a (unspecified) hold that
461107572Sgrehan * failed to release and no holds will be released.
462228435Skib *
463228435Skib * In all cases the errlist will have an entry for each hold that failed to
464228435Skib * to release.
465228435Skib */
466228435Skibint
467228435Skiblzc_release(nvlist_t *holds, nvlist_t **errlist)
468228435Skib{
469228435Skib	char pool[MAXNAMELEN];
470228435Skib	nvpair_t *elem;
471228435Skib
472228435Skib	/* determine the pool name */
473228435Skib	elem = nvlist_next_nvpair(holds, NULL);
474228435Skib	if (elem == NULL)
475228435Skib		return (0);
476228435Skib	(void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
477228435Skib	pool[strcspn(pool, "/@")] = '\0';
478107572Sgrehan
479107572Sgrehan	return (lzc_ioctl(ZFS_IOC_RELEASE, pool, holds, errlist));
480107572Sgrehan}
481107572Sgrehan
482133133Sdfr/*
483133133Sdfr * Retrieve list of user holds on the specified snapshot.
484133133Sdfr *
485133133Sdfr * On success, *holdsp will be set to a nvlist which the caller must free.
486209885Snwhitehorn * The keys are the names of the holds, and the value is the creation time
487137122Sssouhlal * of the hold (uint64) in seconds since the epoch.
488133133Sdfr */
489133133Sdfrint
490133133Sdfrlzc_get_holds(const char *snapname, nvlist_t **holdsp)
491133133Sdfr{
492133133Sdfr	int error;
493133133Sdfr	nvlist_t *innvl = fnvlist_alloc();
494133133Sdfr	error = lzc_ioctl(ZFS_IOC_GET_HOLDS, snapname, innvl, holdsp);
495133133Sdfr	fnvlist_free(innvl);
496133133Sdfr	return (error);
497209885Snwhitehorn}
498137122Sssouhlal
499137122Sssouhlal/*
500137122Sssouhlal * If fromsnap is NULL, a full (non-incremental) stream will be sent.
501137122Sssouhlal */
502137122Sssouhlalint
503137122Sssouhlallzc_send(const char *snapname, const char *fromsnap, int fd)
504137122Sssouhlal{
505133133Sdfr	nvlist_t *args;
506133133Sdfr	int err;
507133133Sdfr
508133133Sdfr	args = fnvlist_alloc();
509133133Sdfr	fnvlist_add_int32(args, "fd", fd);
510209885Snwhitehorn	if (fromsnap != NULL)
511133133Sdfr		fnvlist_add_string(args, "fromsnap", fromsnap);
512133133Sdfr	err = lzc_ioctl(ZFS_IOC_SEND_NEW, snapname, args, NULL);
513137122Sssouhlal	nvlist_free(args);
514137122Sssouhlal	return (err);
515137122Sssouhlal}
516137122Sssouhlal
517133133Sdfr/*
518 * If fromsnap is NULL, a full (non-incremental) stream will be estimated.
519 */
520int
521lzc_send_space(const char *snapname, const char *fromsnap, uint64_t *spacep)
522{
523	nvlist_t *args;
524	nvlist_t *result;
525	int err;
526
527	args = fnvlist_alloc();
528	if (fromsnap != NULL)
529		fnvlist_add_string(args, "fromsnap", fromsnap);
530	err = lzc_ioctl(ZFS_IOC_SEND_SPACE, snapname, args, &result);
531	nvlist_free(args);
532	if (err == 0)
533		*spacep = fnvlist_lookup_uint64(result, "space");
534	nvlist_free(result);
535	return (err);
536}
537
538static int
539recv_read(int fd, void *buf, int ilen)
540{
541	char *cp = buf;
542	int rv;
543	int len = ilen;
544
545	do {
546		rv = read(fd, cp, len);
547		cp += rv;
548		len -= rv;
549	} while (rv > 0);
550
551	if (rv < 0 || len != 0)
552		return (EIO);
553
554	return (0);
555}
556
557/*
558 * The simplest receive case: receive from the specified fd, creating the
559 * specified snapshot.  Apply the specified properties a "received" properties
560 * (which can be overridden by locally-set properties).  If the stream is a
561 * clone, its origin snapshot must be specified by 'origin'.  The 'force'
562 * flag will cause the target filesystem to be rolled back or destroyed if
563 * necessary to receive.
564 *
565 * Return 0 on success or an errno on failure.
566 *
567 * Note: this interface does not work on dedup'd streams
568 * (those with DMU_BACKUP_FEATURE_DEDUP).
569 */
570int
571lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
572    boolean_t force, int fd)
573{
574	/*
575	 * The receive ioctl is still legacy, so we need to construct our own
576	 * zfs_cmd_t rather than using zfsc_ioctl().
577	 */
578	zfs_cmd_t zc = { 0 };
579	char *atp;
580	char *packed = NULL;
581	size_t size;
582	dmu_replay_record_t drr;
583	int error;
584
585	ASSERT3S(g_refcount, >, 0);
586
587	/* zc_name is name of containing filesystem */
588	(void) strlcpy(zc.zc_name, snapname, sizeof (zc.zc_name));
589	atp = strchr(zc.zc_name, '@');
590	if (atp == NULL)
591		return (EINVAL);
592	*atp = '\0';
593
594	/* if the fs does not exist, try its parent. */
595	if (!lzc_exists(zc.zc_name)) {
596		char *slashp = strrchr(zc.zc_name, '/');
597		if (slashp == NULL)
598			return (ENOENT);
599		*slashp = '\0';
600
601	}
602
603	/* zc_value is full name of the snapshot to create */
604	(void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
605
606	if (props != NULL) {
607		/* zc_nvlist_src is props to set */
608		packed = fnvlist_pack(props, &size);
609		zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed;
610		zc.zc_nvlist_src_size = size;
611	}
612
613	/* zc_string is name of clone origin (if DRR_FLAG_CLONE) */
614	if (origin != NULL)
615		(void) strlcpy(zc.zc_string, origin, sizeof (zc.zc_string));
616
617	/* zc_begin_record is non-byteswapped BEGIN record */
618	error = recv_read(fd, &drr, sizeof (drr));
619	if (error != 0)
620		goto out;
621	zc.zc_begin_record = drr.drr_u.drr_begin;
622
623	/* zc_cookie is fd to read from */
624	zc.zc_cookie = fd;
625
626	/* zc guid is force flag */
627	zc.zc_guid = force;
628
629	/* zc_cleanup_fd is unused */
630	zc.zc_cleanup_fd = -1;
631
632	error = ioctl(g_fd, ZFS_IOC_RECV, &zc);
633	if (error != 0)
634		error = errno;
635
636out:
637	if (packed != NULL)
638		fnvlist_pack_free(packed, size);
639	free((void*)(uintptr_t)zc.zc_nvlist_dst);
640	return (error);
641}
642