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