Print this page
Placeholder
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libzfs_core/common/libzfs_core.c
+++ new/usr/src/lib/libzfs_core/common/libzfs_core.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2012, 2014 by Delphix. All rights reserved.
24 24 * Copyright (c) 2013 Steven Hartland. All rights reserved.
25 + * Copyright 2015 RackTop Systems.
25 26 */
26 27
27 28 /*
28 29 * LibZFS_Core (lzc) is intended to replace most functionality in libzfs.
29 30 * It has the following characteristics:
30 31 *
31 32 * - Thread Safe. libzfs_core is accessible concurrently from multiple
32 33 * threads. This is accomplished primarily by avoiding global data
33 34 * (e.g. caching). Since it's thread-safe, there is no reason for a
34 35 * process to have multiple libzfs "instances". Therefore, we store
35 36 * our few pieces of data (e.g. the file descriptor) in global
36 37 * variables. The fd is reference-counted so that the libzfs_core
37 38 * library can be "initialized" multiple times (e.g. by different
38 39 * consumers within the same process).
39 40 *
40 41 * - Committed Interface. The libzfs_core interface will be committed,
41 42 * therefore consumers can compile against it and be confident that
42 43 * their code will continue to work on future releases of this code.
43 44 * Currently, the interface is Evolving (not Committed), but we intend
44 45 * to commit to it once it is more complete and we determine that it
45 46 * meets the needs of all consumers.
46 47 *
47 48 * - Programatic Error Handling. libzfs_core communicates errors with
48 49 * defined error numbers, and doesn't print anything to stdout/stderr.
49 50 *
50 51 * - Thin Layer. libzfs_core is a thin layer, marshaling arguments
51 52 * to/from the kernel ioctls. There is generally a 1:1 correspondence
52 53 * between libzfs_core functions and ioctls to /dev/zfs.
53 54 *
54 55 * - Clear Atomicity. Because libzfs_core functions are generally 1:1
55 56 * with kernel ioctls, and kernel ioctls are general atomic, each
56 57 * libzfs_core function is atomic. For example, creating multiple
57 58 * snapshots with a single call to lzc_snapshot() is atomic -- it
58 59 * can't fail with only some of the requested snapshots created, even
59 60 * in the event of power loss or system crash.
60 61 *
61 62 * - Continued libzfs Support. Some higher-level operations (e.g.
62 63 * support for "zfs send -R") are too complicated to fit the scope of
63 64 * libzfs_core. This functionality will continue to live in libzfs.
64 65 * Where appropriate, libzfs will use the underlying atomic operations
65 66 * of libzfs_core. For example, libzfs may implement "zfs send -R |
66 67 * zfs receive" by using individual "send one snapshot", rename,
67 68 * destroy, and "receive one snapshot" operations in libzfs_core.
68 69 * /sbin/zfs and /zbin/zpool will link with both libzfs and
69 70 * libzfs_core. Other consumers should aim to use only libzfs_core,
70 71 * since that will be the supported, stable interface going forwards.
71 72 */
72 73
73 74 #include <libzfs_core.h>
74 75 #include <ctype.h>
75 76 #include <unistd.h>
76 77 #include <stdlib.h>
77 78 #include <string.h>
78 79 #include <errno.h>
79 80 #include <fcntl.h>
80 81 #include <pthread.h>
81 82 #include <sys/nvpair.h>
82 83 #include <sys/param.h>
83 84 #include <sys/types.h>
84 85 #include <sys/stat.h>
85 86 #include <sys/zfs_ioctl.h>
86 87
87 88 static int g_fd;
88 89 static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
89 90 static int g_refcount;
90 91
91 92 int
92 93 libzfs_core_init(void)
93 94 {
94 95 (void) pthread_mutex_lock(&g_lock);
95 96 if (g_refcount == 0) {
96 97 g_fd = open("/dev/zfs", O_RDWR);
97 98 if (g_fd < 0) {
98 99 (void) pthread_mutex_unlock(&g_lock);
99 100 return (errno);
100 101 }
101 102 }
102 103 g_refcount++;
103 104 (void) pthread_mutex_unlock(&g_lock);
104 105 return (0);
105 106 }
106 107
107 108 void
108 109 libzfs_core_fini(void)
109 110 {
110 111 (void) pthread_mutex_lock(&g_lock);
111 112 ASSERT3S(g_refcount, >, 0);
112 113 g_refcount--;
113 114 if (g_refcount == 0)
114 115 (void) close(g_fd);
115 116 (void) pthread_mutex_unlock(&g_lock);
116 117 }
117 118
118 119 static int
119 120 lzc_ioctl(zfs_ioc_t ioc, const char *name,
120 121 nvlist_t *source, nvlist_t **resultp)
121 122 {
122 123 zfs_cmd_t zc = { 0 };
123 124 int error = 0;
124 125 char *packed;
125 126 size_t size;
126 127
127 128 ASSERT3S(g_refcount, >, 0);
128 129
129 130 (void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
130 131
131 132 packed = fnvlist_pack(source, &size);
132 133 zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed;
133 134 zc.zc_nvlist_src_size = size;
134 135
135 136 if (resultp != NULL) {
136 137 *resultp = NULL;
137 138 zc.zc_nvlist_dst_size = MAX(size * 2, 128 * 1024);
138 139 zc.zc_nvlist_dst = (uint64_t)(uintptr_t)
139 140 malloc(zc.zc_nvlist_dst_size);
140 141 if (zc.zc_nvlist_dst == NULL) {
141 142 error = ENOMEM;
142 143 goto out;
143 144 }
144 145 }
145 146
146 147 while (ioctl(g_fd, ioc, &zc) != 0) {
147 148 if (errno == ENOMEM && resultp != NULL) {
148 149 free((void *)(uintptr_t)zc.zc_nvlist_dst);
149 150 zc.zc_nvlist_dst_size *= 2;
150 151 zc.zc_nvlist_dst = (uint64_t)(uintptr_t)
151 152 malloc(zc.zc_nvlist_dst_size);
152 153 if (zc.zc_nvlist_dst == NULL) {
153 154 error = ENOMEM;
154 155 goto out;
155 156 }
156 157 } else {
157 158 error = errno;
158 159 break;
159 160 }
160 161 }
161 162 if (zc.zc_nvlist_dst_filled) {
162 163 *resultp = fnvlist_unpack((void *)(uintptr_t)zc.zc_nvlist_dst,
163 164 zc.zc_nvlist_dst_size);
164 165 }
165 166
166 167 out:
167 168 fnvlist_pack_free(packed, size);
168 169 free((void *)(uintptr_t)zc.zc_nvlist_dst);
169 170 return (error);
170 171 }
171 172
172 173 int
173 174 lzc_create(const char *fsname, dmu_objset_type_t type, nvlist_t *props)
174 175 {
175 176 int error;
176 177 nvlist_t *args = fnvlist_alloc();
177 178 fnvlist_add_int32(args, "type", type);
178 179 if (props != NULL)
179 180 fnvlist_add_nvlist(args, "props", props);
180 181 error = lzc_ioctl(ZFS_IOC_CREATE, fsname, args, NULL);
181 182 nvlist_free(args);
182 183 return (error);
183 184 }
184 185
185 186 int
186 187 lzc_clone(const char *fsname, const char *origin,
187 188 nvlist_t *props)
188 189 {
189 190 int error;
190 191 nvlist_t *args = fnvlist_alloc();
191 192 fnvlist_add_string(args, "origin", origin);
192 193 if (props != NULL)
193 194 fnvlist_add_nvlist(args, "props", props);
194 195 error = lzc_ioctl(ZFS_IOC_CLONE, fsname, args, NULL);
195 196 nvlist_free(args);
196 197 return (error);
197 198 }
198 199
199 200 /*
200 201 * Creates snapshots.
201 202 *
202 203 * The keys in the snaps nvlist are the snapshots to be created.
203 204 * They must all be in the same pool.
204 205 *
205 206 * The props nvlist is properties to set. Currently only user properties
206 207 * are supported. { user:prop_name -> string value }
207 208 *
208 209 * The returned results nvlist will have an entry for each snapshot that failed.
209 210 * The value will be the (int32) error code.
210 211 *
211 212 * The return value will be 0 if all snapshots were created, otherwise it will
212 213 * be the errno of a (unspecified) snapshot that failed.
213 214 */
214 215 int
215 216 lzc_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t **errlist)
216 217 {
217 218 nvpair_t *elem;
218 219 nvlist_t *args;
219 220 int error;
220 221 char pool[MAXNAMELEN];
221 222
222 223 *errlist = NULL;
223 224
224 225 /* determine the pool name */
225 226 elem = nvlist_next_nvpair(snaps, NULL);
226 227 if (elem == NULL)
227 228 return (0);
228 229 (void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
229 230 pool[strcspn(pool, "/@")] = '\0';
230 231
231 232 args = fnvlist_alloc();
232 233 fnvlist_add_nvlist(args, "snaps", snaps);
233 234 if (props != NULL)
234 235 fnvlist_add_nvlist(args, "props", props);
235 236
236 237 error = lzc_ioctl(ZFS_IOC_SNAPSHOT, pool, args, errlist);
237 238 nvlist_free(args);
238 239
239 240 return (error);
240 241 }
241 242
242 243 /*
243 244 * Destroys snapshots.
244 245 *
245 246 * The keys in the snaps nvlist are the snapshots to be destroyed.
246 247 * They must all be in the same pool.
247 248 *
248 249 * Snapshots that do not exist will be silently ignored.
249 250 *
250 251 * If 'defer' is not set, and a snapshot has user holds or clones, the
251 252 * destroy operation will fail and none of the snapshots will be
252 253 * destroyed.
253 254 *
254 255 * If 'defer' is set, and a snapshot has user holds or clones, it will be
255 256 * marked for deferred destruction, and will be destroyed when the last hold
256 257 * or clone is removed/destroyed.
257 258 *
258 259 * The return value will be 0 if all snapshots were destroyed (or marked for
259 260 * later destruction if 'defer' is set) or didn't exist to begin with.
260 261 *
261 262 * Otherwise the return value will be the errno of a (unspecified) snapshot
262 263 * that failed, no snapshots will be destroyed, and the errlist will have an
263 264 * entry for each snapshot that failed. The value in the errlist will be
264 265 * the (int32) error code.
265 266 */
266 267 int
267 268 lzc_destroy_snaps(nvlist_t *snaps, boolean_t defer, nvlist_t **errlist)
268 269 {
269 270 nvpair_t *elem;
270 271 nvlist_t *args;
271 272 int error;
272 273 char pool[MAXNAMELEN];
273 274
274 275 /* determine the pool name */
275 276 elem = nvlist_next_nvpair(snaps, NULL);
276 277 if (elem == NULL)
277 278 return (0);
278 279 (void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
279 280 pool[strcspn(pool, "/@")] = '\0';
280 281
281 282 args = fnvlist_alloc();
282 283 fnvlist_add_nvlist(args, "snaps", snaps);
283 284 if (defer)
284 285 fnvlist_add_boolean(args, "defer");
285 286
286 287 error = lzc_ioctl(ZFS_IOC_DESTROY_SNAPS, pool, args, errlist);
287 288 nvlist_free(args);
288 289
289 290 return (error);
290 291 }
291 292
292 293 int
293 294 lzc_snaprange_space(const char *firstsnap, const char *lastsnap,
294 295 uint64_t *usedp)
295 296 {
296 297 nvlist_t *args;
297 298 nvlist_t *result;
298 299 int err;
299 300 char fs[MAXNAMELEN];
300 301 char *atp;
301 302
302 303 /* determine the fs name */
303 304 (void) strlcpy(fs, firstsnap, sizeof (fs));
304 305 atp = strchr(fs, '@');
305 306 if (atp == NULL)
306 307 return (EINVAL);
307 308 *atp = '\0';
308 309
309 310 args = fnvlist_alloc();
310 311 fnvlist_add_string(args, "firstsnap", firstsnap);
311 312
312 313 err = lzc_ioctl(ZFS_IOC_SPACE_SNAPS, lastsnap, args, &result);
313 314 nvlist_free(args);
314 315 if (err == 0)
315 316 *usedp = fnvlist_lookup_uint64(result, "used");
316 317 fnvlist_free(result);
317 318
318 319 return (err);
319 320 }
320 321
321 322 boolean_t
322 323 lzc_exists(const char *dataset)
323 324 {
324 325 /*
325 326 * The objset_stats ioctl is still legacy, so we need to construct our
326 327 * own zfs_cmd_t rather than using zfsc_ioctl().
327 328 */
328 329 zfs_cmd_t zc = { 0 };
329 330
330 331 (void) strlcpy(zc.zc_name, dataset, sizeof (zc.zc_name));
331 332 return (ioctl(g_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0);
332 333 }
333 334
334 335 /*
335 336 * Create "user holds" on snapshots. If there is a hold on a snapshot,
336 337 * the snapshot can not be destroyed. (However, it can be marked for deletion
337 338 * by lzc_destroy_snaps(defer=B_TRUE).)
338 339 *
339 340 * The keys in the nvlist are snapshot names.
340 341 * The snapshots must all be in the same pool.
341 342 * The value is the name of the hold (string type).
342 343 *
343 344 * If cleanup_fd is not -1, it must be the result of open("/dev/zfs", O_EXCL).
344 345 * In this case, when the cleanup_fd is closed (including on process
345 346 * termination), the holds will be released. If the system is shut down
346 347 * uncleanly, the holds will be released when the pool is next opened
347 348 * or imported.
348 349 *
349 350 * Holds for snapshots which don't exist will be skipped and have an entry
350 351 * added to errlist, but will not cause an overall failure.
351 352 *
352 353 * The return value will be 0 if all holds, for snapshots that existed,
353 354 * were succesfully created.
354 355 *
355 356 * Otherwise the return value will be the errno of a (unspecified) hold that
356 357 * failed and no holds will be created.
357 358 *
358 359 * In all cases the errlist will have an entry for each hold that failed
359 360 * (name = snapshot), with its value being the error code (int32).
360 361 */
361 362 int
362 363 lzc_hold(nvlist_t *holds, int cleanup_fd, nvlist_t **errlist)
363 364 {
364 365 char pool[MAXNAMELEN];
365 366 nvlist_t *args;
366 367 nvpair_t *elem;
367 368 int error;
368 369
369 370 /* determine the pool name */
370 371 elem = nvlist_next_nvpair(holds, NULL);
371 372 if (elem == NULL)
372 373 return (0);
373 374 (void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
374 375 pool[strcspn(pool, "/@")] = '\0';
375 376
376 377 args = fnvlist_alloc();
377 378 fnvlist_add_nvlist(args, "holds", holds);
378 379 if (cleanup_fd != -1)
379 380 fnvlist_add_int32(args, "cleanup_fd", cleanup_fd);
380 381
381 382 error = lzc_ioctl(ZFS_IOC_HOLD, pool, args, errlist);
382 383 nvlist_free(args);
383 384 return (error);
384 385 }
385 386
386 387 /*
387 388 * Release "user holds" on snapshots. If the snapshot has been marked for
388 389 * deferred destroy (by lzc_destroy_snaps(defer=B_TRUE)), it does not have
389 390 * any clones, and all the user holds are removed, then the snapshot will be
390 391 * destroyed.
391 392 *
392 393 * The keys in the nvlist are snapshot names.
393 394 * The snapshots must all be in the same pool.
394 395 * The value is a nvlist whose keys are the holds to remove.
395 396 *
396 397 * Holds which failed to release because they didn't exist will have an entry
397 398 * added to errlist, but will not cause an overall failure.
398 399 *
399 400 * The return value will be 0 if the nvl holds was empty or all holds that
400 401 * existed, were successfully removed.
401 402 *
402 403 * Otherwise the return value will be the errno of a (unspecified) hold that
403 404 * failed to release and no holds will be released.
404 405 *
405 406 * In all cases the errlist will have an entry for each hold that failed to
406 407 * to release.
407 408 */
408 409 int
409 410 lzc_release(nvlist_t *holds, nvlist_t **errlist)
410 411 {
411 412 char pool[MAXNAMELEN];
412 413 nvpair_t *elem;
413 414
414 415 /* determine the pool name */
415 416 elem = nvlist_next_nvpair(holds, NULL);
416 417 if (elem == NULL)
417 418 return (0);
418 419 (void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
419 420 pool[strcspn(pool, "/@")] = '\0';
420 421
421 422 return (lzc_ioctl(ZFS_IOC_RELEASE, pool, holds, errlist));
422 423 }
423 424
424 425 /*
425 426 * Retrieve list of user holds on the specified snapshot.
426 427 *
427 428 * On success, *holdsp will be set to a nvlist which the caller must free.
428 429 * The keys are the names of the holds, and the value is the creation time
429 430 * of the hold (uint64) in seconds since the epoch.
430 431 */
431 432 int
432 433 lzc_get_holds(const char *snapname, nvlist_t **holdsp)
433 434 {
434 435 int error;
435 436 nvlist_t *innvl = fnvlist_alloc();
436 437 error = lzc_ioctl(ZFS_IOC_GET_HOLDS, snapname, innvl, holdsp);
437 438 fnvlist_free(innvl);
438 439 return (error);
439 440 }
440 441
441 442 /*
442 443 * Generate a zfs send stream for the specified snapshot and write it to
443 444 * the specified file descriptor.
444 445 *
445 446 * "snapname" is the full name of the snapshot to send (e.g. "pool/fs@snap")
446 447 *
447 448 * If "from" is NULL, a full (non-incremental) stream will be sent.
448 449 * If "from" is non-NULL, it must be the full name of a snapshot or
449 450 * bookmark to send an incremental from (e.g. "pool/fs@earlier_snap" or
450 451 * "pool/fs#earlier_bmark"). If non-NULL, the specified snapshot or
451 452 * bookmark must represent an earlier point in the history of "snapname").
452 453 * It can be an earlier snapshot in the same filesystem or zvol as "snapname",
453 454 * or it can be the origin of "snapname"'s filesystem, or an earlier
454 455 * snapshot in the origin, etc.
455 456 *
456 457 * "fd" is the file descriptor to write the send stream to.
457 458 *
458 459 * If "flags" contains LZC_SEND_FLAG_LARGE_BLOCK, the stream is permitted
459 460 * to contain DRR_WRITE records with drr_length > 128K, and DRR_OBJECT
460 461 * records with drr_blksz > 128K.
461 462 *
462 463 * If "flags" contains LZC_SEND_FLAG_EMBED_DATA, the stream is permitted
463 464 * to contain DRR_WRITE_EMBEDDED records with drr_etype==BP_EMBEDDED_TYPE_DATA,
464 465 * which the receiving system must support (as indicated by support
465 466 * for the "embedded_data" feature).
466 467 */
467 468 int
468 469 lzc_send(const char *snapname, const char *from, int fd,
469 470 enum lzc_send_flags flags)
470 471 {
471 472 return (lzc_send_resume(snapname, from, fd, flags, 0, 0));
472 473 }
473 474
474 475 int
475 476 lzc_send_resume(const char *snapname, const char *from, int fd,
476 477 enum lzc_send_flags flags, uint64_t resumeobj, uint64_t resumeoff)
477 478 {
478 479 nvlist_t *args;
↓ open down ↓ |
444 lines elided |
↑ open up ↑ |
479 480 int err;
480 481
481 482 args = fnvlist_alloc();
482 483 fnvlist_add_int32(args, "fd", fd);
483 484 if (from != NULL)
484 485 fnvlist_add_string(args, "fromsnap", from);
485 486 if (flags & LZC_SEND_FLAG_LARGE_BLOCK)
486 487 fnvlist_add_boolean(args, "largeblockok");
487 488 if (flags & LZC_SEND_FLAG_EMBED_DATA)
488 489 fnvlist_add_boolean(args, "embedok");
490 + if (flags & LZC_SEND_FLAG_SKIP_FREE)
491 + fnvlist_add_boolean(args, "skip_free");
489 492 if (resumeobj != 0 || resumeoff != 0) {
490 493 fnvlist_add_uint64(args, "resume_object", resumeobj);
491 494 fnvlist_add_uint64(args, "resume_offset", resumeoff);
492 495 }
493 496 err = lzc_ioctl(ZFS_IOC_SEND_NEW, snapname, args, NULL);
494 497 nvlist_free(args);
495 498 return (err);
496 499 }
497 500
498 501 /*
499 502 * "from" can be NULL, a snapshot, or a bookmark.
500 503 *
501 504 * If from is NULL, a full (non-incremental) stream will be estimated. This
502 505 * is calculated very efficiently.
503 506 *
504 507 * If from is a snapshot, lzc_send_space uses the deadlists attached to
505 508 * each snapshot to efficiently estimate the stream size.
506 509 *
507 510 * If from is a bookmark, the indirect blocks in the destination snapshot
508 511 * are traversed, looking for blocks with a birth time since the creation TXG of
509 512 * the snapshot this bookmark was created from. This will result in
510 513 * significantly more I/O and be less efficient than a send space estimation on
511 514 * an equivalent snapshot.
512 515 */
513 516 int
514 517 lzc_send_space(const char *snapname, const char *from, uint64_t *spacep)
515 518 {
516 519 nvlist_t *args;
517 520 nvlist_t *result;
518 521 int err;
519 522
520 523 args = fnvlist_alloc();
521 524 if (from != NULL)
522 525 fnvlist_add_string(args, "from", from);
523 526 err = lzc_ioctl(ZFS_IOC_SEND_SPACE, snapname, args, &result);
524 527 nvlist_free(args);
525 528 if (err == 0)
526 529 *spacep = fnvlist_lookup_uint64(result, "space");
527 530 nvlist_free(result);
528 531 return (err);
529 532 }
530 533
531 534 static int
532 535 recv_read(int fd, void *buf, int ilen)
533 536 {
534 537 char *cp = buf;
535 538 int rv;
536 539 int len = ilen;
537 540
538 541 do {
539 542 rv = read(fd, cp, len);
540 543 cp += rv;
541 544 len -= rv;
542 545 } while (rv > 0);
543 546
544 547 if (rv < 0 || len != 0)
545 548 return (EIO);
546 549
547 550 return (0);
548 551 }
549 552
550 553 static int
551 554 recv_impl(const char *snapname, nvlist_t *props, const char *origin,
552 555 boolean_t force, boolean_t resumable, int fd,
553 556 const dmu_replay_record_t *begin_record)
554 557 {
555 558 /*
556 559 * The receive ioctl is still legacy, so we need to construct our own
557 560 * zfs_cmd_t rather than using zfsc_ioctl().
558 561 */
559 562 zfs_cmd_t zc = { 0 };
560 563 char *atp;
561 564 char *packed = NULL;
562 565 size_t size;
563 566 int error;
564 567
565 568 ASSERT3S(g_refcount, >, 0);
566 569
567 570 /* zc_name is name of containing filesystem */
568 571 (void) strlcpy(zc.zc_name, snapname, sizeof (zc.zc_name));
569 572 atp = strchr(zc.zc_name, '@');
570 573 if (atp == NULL)
571 574 return (EINVAL);
572 575 *atp = '\0';
573 576
574 577 /* if the fs does not exist, try its parent. */
575 578 if (!lzc_exists(zc.zc_name)) {
576 579 char *slashp = strrchr(zc.zc_name, '/');
577 580 if (slashp == NULL)
578 581 return (ENOENT);
579 582 *slashp = '\0';
580 583
581 584 }
582 585
583 586 /* zc_value is full name of the snapshot to create */
584 587 (void) strlcpy(zc.zc_value, snapname, sizeof (zc.zc_value));
585 588
586 589 if (props != NULL) {
587 590 /* zc_nvlist_src is props to set */
588 591 packed = fnvlist_pack(props, &size);
589 592 zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed;
590 593 zc.zc_nvlist_src_size = size;
591 594 }
592 595
593 596 /* zc_string is name of clone origin (if DRR_FLAG_CLONE) */
594 597 if (origin != NULL)
595 598 (void) strlcpy(zc.zc_string, origin, sizeof (zc.zc_string));
596 599
597 600 /* zc_begin_record is non-byteswapped BEGIN record */
598 601 if (begin_record == NULL) {
599 602 error = recv_read(fd, &zc.zc_begin_record,
600 603 sizeof (zc.zc_begin_record));
601 604 if (error != 0)
602 605 goto out;
603 606 } else {
604 607 zc.zc_begin_record = *begin_record;
605 608 }
606 609
607 610 /* zc_cookie is fd to read from */
608 611 zc.zc_cookie = fd;
609 612
610 613 /* zc guid is force flag */
611 614 zc.zc_guid = force;
612 615
613 616 zc.zc_resumable = resumable;
614 617
615 618 /* zc_cleanup_fd is unused */
616 619 zc.zc_cleanup_fd = -1;
617 620
618 621 error = ioctl(g_fd, ZFS_IOC_RECV, &zc);
619 622 if (error != 0)
620 623 error = errno;
621 624
622 625 out:
623 626 if (packed != NULL)
624 627 fnvlist_pack_free(packed, size);
625 628 free((void*)(uintptr_t)zc.zc_nvlist_dst);
626 629 return (error);
627 630 }
628 631
629 632 /*
630 633 * The simplest receive case: receive from the specified fd, creating the
631 634 * specified snapshot. Apply the specified properties as "received" properties
632 635 * (which can be overridden by locally-set properties). If the stream is a
633 636 * clone, its origin snapshot must be specified by 'origin'. The 'force'
634 637 * flag will cause the target filesystem to be rolled back or destroyed if
635 638 * necessary to receive.
636 639 *
637 640 * Return 0 on success or an errno on failure.
638 641 *
639 642 * Note: this interface does not work on dedup'd streams
640 643 * (those with DMU_BACKUP_FEATURE_DEDUP).
641 644 */
642 645 int
643 646 lzc_receive(const char *snapname, nvlist_t *props, const char *origin,
644 647 boolean_t force, int fd)
645 648 {
646 649 return (recv_impl(snapname, props, origin, force, B_FALSE, fd, NULL));
647 650 }
648 651
649 652 /*
650 653 * Like lzc_receive, but if the receive fails due to premature stream
651 654 * termination, the intermediate state will be preserved on disk. In this
652 655 * case, ECKSUM will be returned. The receive may subsequently be resumed
653 656 * with a resuming send stream generated by lzc_send_resume().
654 657 */
655 658 int
656 659 lzc_receive_resumable(const char *snapname, nvlist_t *props, const char *origin,
657 660 boolean_t force, int fd)
658 661 {
659 662 return (recv_impl(snapname, props, origin, force, B_TRUE, fd, NULL));
660 663 }
661 664
662 665 /*
663 666 * Like lzc_receive, but allows the caller to read the begin record and then to
664 667 * pass it in. That could be useful if the caller wants to derive, for example,
665 668 * the snapname or the origin parameters based on the information contained in
666 669 * the begin record.
667 670 * The begin record must be in its original form as read from the stream,
668 671 * in other words, it should not be byteswapped.
669 672 *
670 673 * The 'resumable' parameter allows to obtain the same behavior as with
671 674 * lzc_receive_resumable.
672 675 */
673 676 int
674 677 lzc_receive_with_header(const char *snapname, nvlist_t *props,
675 678 const char *origin, boolean_t force, boolean_t resumable, int fd,
676 679 const dmu_replay_record_t *begin_record)
677 680 {
678 681 if (begin_record == NULL)
679 682 return (EINVAL);
680 683 return (recv_impl(snapname, props, origin, force, resumable, fd,
681 684 begin_record));
682 685 }
683 686
684 687 /*
685 688 * Roll back this filesystem or volume to its most recent snapshot.
686 689 * If snapnamebuf is not NULL, it will be filled in with the name
687 690 * of the most recent snapshot.
688 691 *
689 692 * Return 0 on success or an errno on failure.
690 693 */
691 694 int
692 695 lzc_rollback(const char *fsname, char *snapnamebuf, int snapnamelen)
693 696 {
694 697 nvlist_t *args;
695 698 nvlist_t *result;
696 699 int err;
697 700
698 701 args = fnvlist_alloc();
699 702 err = lzc_ioctl(ZFS_IOC_ROLLBACK, fsname, args, &result);
700 703 nvlist_free(args);
701 704 if (err == 0 && snapnamebuf != NULL) {
702 705 const char *snapname = fnvlist_lookup_string(result, "target");
703 706 (void) strlcpy(snapnamebuf, snapname, snapnamelen);
704 707 }
705 708 return (err);
706 709 }
707 710
708 711 /*
709 712 * Creates bookmarks.
710 713 *
711 714 * The bookmarks nvlist maps from name of the bookmark (e.g. "pool/fs#bmark") to
712 715 * the name of the snapshot (e.g. "pool/fs@snap"). All the bookmarks and
713 716 * snapshots must be in the same pool.
714 717 *
715 718 * The returned results nvlist will have an entry for each bookmark that failed.
716 719 * The value will be the (int32) error code.
717 720 *
718 721 * The return value will be 0 if all bookmarks were created, otherwise it will
719 722 * be the errno of a (undetermined) bookmarks that failed.
720 723 */
721 724 int
722 725 lzc_bookmark(nvlist_t *bookmarks, nvlist_t **errlist)
723 726 {
724 727 nvpair_t *elem;
725 728 int error;
726 729 char pool[MAXNAMELEN];
727 730
728 731 /* determine the pool name */
729 732 elem = nvlist_next_nvpair(bookmarks, NULL);
730 733 if (elem == NULL)
731 734 return (0);
732 735 (void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
733 736 pool[strcspn(pool, "/#")] = '\0';
734 737
735 738 error = lzc_ioctl(ZFS_IOC_BOOKMARK, pool, bookmarks, errlist);
736 739
737 740 return (error);
738 741 }
739 742
740 743 /*
741 744 * Retrieve bookmarks.
742 745 *
743 746 * Retrieve the list of bookmarks for the given file system. The props
744 747 * parameter is an nvlist of property names (with no values) that will be
745 748 * returned for each bookmark.
746 749 *
747 750 * The following are valid properties on bookmarks, all of which are numbers
748 751 * (represented as uint64 in the nvlist)
749 752 *
750 753 * "guid" - globally unique identifier of the snapshot it refers to
751 754 * "createtxg" - txg when the snapshot it refers to was created
752 755 * "creation" - timestamp when the snapshot it refers to was created
753 756 *
754 757 * The format of the returned nvlist as follows:
755 758 * <short name of bookmark> -> {
756 759 * <name of property> -> {
757 760 * "value" -> uint64
758 761 * }
759 762 * }
760 763 */
761 764 int
762 765 lzc_get_bookmarks(const char *fsname, nvlist_t *props, nvlist_t **bmarks)
763 766 {
764 767 return (lzc_ioctl(ZFS_IOC_GET_BOOKMARKS, fsname, props, bmarks));
765 768 }
766 769
767 770 /*
768 771 * Destroys bookmarks.
769 772 *
770 773 * The keys in the bmarks nvlist are the bookmarks to be destroyed.
771 774 * They must all be in the same pool. Bookmarks are specified as
772 775 * <fs>#<bmark>.
773 776 *
774 777 * Bookmarks that do not exist will be silently ignored.
775 778 *
776 779 * The return value will be 0 if all bookmarks that existed were destroyed.
777 780 *
778 781 * Otherwise the return value will be the errno of a (undetermined) bookmark
779 782 * that failed, no bookmarks will be destroyed, and the errlist will have an
780 783 * entry for each bookmarks that failed. The value in the errlist will be
781 784 * the (int32) error code.
782 785 */
783 786 int
784 787 lzc_destroy_bookmarks(nvlist_t *bmarks, nvlist_t **errlist)
785 788 {
786 789 nvpair_t *elem;
787 790 int error;
788 791 char pool[MAXNAMELEN];
789 792
790 793 /* determine the pool name */
791 794 elem = nvlist_next_nvpair(bmarks, NULL);
792 795 if (elem == NULL)
793 796 return (0);
794 797 (void) strlcpy(pool, nvpair_name(elem), sizeof (pool));
795 798 pool[strcspn(pool, "/#")] = '\0';
796 799
797 800 error = lzc_ioctl(ZFS_IOC_DESTROY_BOOKMARKS, pool, bmarks, errlist);
798 801
799 802 return (error);
800 803 }
↓ open down ↓ |
302 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX