7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
28 */
29
30 /*
31 * System includes
32 */
33 #include <assert.h>
34 #include <libintl.h>
35 #include <libnvpair.h>
36 #include <libzfs.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <unistd.h>
43
44 #include <libbe.h>
45 #include <libbe_priv.h>
46
47 /* Private function prototypes */
306 } else {
307 /* Find which zpool obe_name lives in */
308 if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) ==
309 0) {
310 be_print_err(gettext("be_rollback: "
311 "failed to find zpool for BE (%s)\n"), bt.obe_name);
312 return (BE_ERR_BE_NOENT);
313 } else if (zret < 0) {
314 be_print_err(gettext("be_rollback: "
315 "zpool_iter failed: %s\n"),
316 libzfs_error_description(g_zfs));
317 return (zfs_err_to_be_err(g_zfs));
318 }
319 }
320
321 /* Generate string for BE's root dataset */
322 be_make_root_ds(bt.obe_zpool, bt.obe_name, obe_root_ds,
323 sizeof (obe_root_ds));
324 bt.obe_root_ds = obe_root_ds;
325
326 /* Get handle to BE's root dataset */
327 if ((zhp = zfs_open(g_zfs, bt.obe_root_ds, ZFS_TYPE_DATASET)) == NULL) {
328 be_print_err(gettext("be_rollback: "
329 "failed to open BE root dataset (%s): %s\n"),
330 bt.obe_root_ds, libzfs_error_description(g_zfs));
331 return (zfs_err_to_be_err(g_zfs));
332 }
333
334 /*
335 * Check that snapshot name exists for this BE and all of its
336 * children file systems. This call will end up closing the
337 * zfs handle passed in whether it succeeds or fails.
338 */
339 if ((ret = be_rollback_check_callback(zhp, bt.obe_snap_name)) != 0) {
340 zhp = NULL;
341 return (ret);
342 }
343
344 /* Get handle to BE's root dataset */
345 if ((zhp = zfs_open(g_zfs, bt.obe_root_ds, ZFS_TYPE_DATASET)) == NULL) {
412 return (ret);
413 }
414 }
415
416 /* Find which zpool obe_name lives in */
417 if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) == 0) {
418 be_print_err(gettext("be_create_snapshot: failed to "
419 "find zpool for BE (%s)\n"), bt.obe_name);
420 return (BE_ERR_BE_NOENT);
421 } else if (zret < 0) {
422 be_print_err(gettext("be_create_snapshot: "
423 "zpool_iter failed: %s\n"),
424 libzfs_error_description(g_zfs));
425 return (zfs_err_to_be_err(g_zfs));
426 }
427
428 be_make_root_ds(bt.obe_zpool, bt.obe_name, root_ds,
429 sizeof (root_ds));
430 bt.obe_root_ds = root_ds;
431
432 /* If BE policy not specified, use the default policy */
433 if (bt.policy == NULL) {
434 bt.policy = be_default_policy();
435 } else {
436 /* Validate policy type */
437 if (!valid_be_policy(bt.policy)) {
438 be_print_err(gettext("be_create_snapshot: "
439 "invalid BE policy type (%s)\n"), bt.policy);
440 return (BE_ERR_INVAL);
441 }
442 }
443
444 /*
445 * If snapshot name not specified, set auto name flag and
446 * generate auto snapshot name.
447 */
448 if (bt.obe_snap_name == NULL) {
449 autoname = B_TRUE;
450 if ((bt.obe_snap_name = be_auto_snap_name())
451 == NULL) {
465 == NULL) {
466 be_print_err(gettext("be_create_snapshot: "
467 "failed to open BE root dataset (%s): %s\n"),
468 bt.obe_root_ds, libzfs_error_description(g_zfs));
469 ret = zfs_err_to_be_err(g_zfs);
470 goto done;
471 }
472
473 /* Get the ZFS pool version of the pool where this dataset resides */
474 if (zfs_spa_version(zhp, &pool_version) != 0) {
475 be_print_err(gettext("be_create_snapshot: failed to "
476 "get ZFS pool version for %s: %s\n"), zfs_get_name(zhp),
477 libzfs_error_description(g_zfs));
478 }
479
480 /*
481 * If ZFS pool version supports snapshot user properties, store
482 * cleanup policy there. Otherwise don't set one - this snapshot
483 * will always inherit the cleanup policy from its parent.
484 */
485 if (pool_version >= SPA_VERSION_SNAP_PROPS) {
486 if (nvlist_alloc(&ss_props, NV_UNIQUE_NAME, 0) != 0) {
487 be_print_err(gettext("be_create_snapshot: internal "
488 "error: out of memory\n"));
489 return (BE_ERR_NOMEM);
490 }
491 if (nvlist_add_string(ss_props, BE_POLICY_PROPERTY, bt.policy)
492 != 0) {
493 be_print_err(gettext("be_create_snapshot: internal "
494 "error: out of memory\n"));
495 nvlist_free(ss_props);
496 return (BE_ERR_NOMEM);
497 }
498 } else if (policy != NULL) {
499 /*
500 * If an explicit cleanup policy was requested
501 * by the caller and we don't support it, error out.
502 */
503 be_print_err(gettext("be_create_snapshot: cannot set "
504 "cleanup policy: ZFS pool version is %d\n"), pool_version);
505 return (BE_ERR_NOTSUP);
506 }
507
508 /* Create the snapshots recursively */
509 if (zfs_snapshot(g_zfs, ss, B_TRUE, ss_props) != 0) {
510 if (!autoname || libzfs_errno(g_zfs) != EZFS_EXISTS) {
511 be_print_err(gettext("be_create_snapshot: "
512 "recursive snapshot of %s failed: %s\n"),
513 ss, libzfs_error_description(g_zfs));
514
515 if (libzfs_errno(g_zfs) == EZFS_EXISTS)
516 ret = BE_ERR_SS_EXISTS;
517 else
518 ret = zfs_err_to_be_err(g_zfs);
519
520 goto done;
521 } else {
522 for (i = 1; i < BE_AUTO_NAME_MAX_TRY; i++) {
523
524 /* Sleep 1 before retrying */
525 (void) sleep(1);
526
|
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
28 */
29
30 /*
31 * System includes
32 */
33 #include <assert.h>
34 #include <libintl.h>
35 #include <libnvpair.h>
36 #include <libzfs.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <unistd.h>
43
44 #include <libbe.h>
45 #include <libbe_priv.h>
46
47 /* Private function prototypes */
306 } else {
307 /* Find which zpool obe_name lives in */
308 if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) ==
309 0) {
310 be_print_err(gettext("be_rollback: "
311 "failed to find zpool for BE (%s)\n"), bt.obe_name);
312 return (BE_ERR_BE_NOENT);
313 } else if (zret < 0) {
314 be_print_err(gettext("be_rollback: "
315 "zpool_iter failed: %s\n"),
316 libzfs_error_description(g_zfs));
317 return (zfs_err_to_be_err(g_zfs));
318 }
319 }
320
321 /* Generate string for BE's root dataset */
322 be_make_root_ds(bt.obe_zpool, bt.obe_name, obe_root_ds,
323 sizeof (obe_root_ds));
324 bt.obe_root_ds = obe_root_ds;
325
326 if (getzoneid() != GLOBAL_ZONEID) {
327 if (!be_zone_compare_uuids(bt.obe_root_ds)) {
328 be_print_err(gettext("be_rollback: rolling back zone "
329 "root dataset from non-active global BE is not "
330 "supported\n"));
331 return (BE_ERR_NOTSUP);
332 }
333 }
334
335 /* Get handle to BE's root dataset */
336 if ((zhp = zfs_open(g_zfs, bt.obe_root_ds, ZFS_TYPE_DATASET)) == NULL) {
337 be_print_err(gettext("be_rollback: "
338 "failed to open BE root dataset (%s): %s\n"),
339 bt.obe_root_ds, libzfs_error_description(g_zfs));
340 return (zfs_err_to_be_err(g_zfs));
341 }
342
343 /*
344 * Check that snapshot name exists for this BE and all of its
345 * children file systems. This call will end up closing the
346 * zfs handle passed in whether it succeeds or fails.
347 */
348 if ((ret = be_rollback_check_callback(zhp, bt.obe_snap_name)) != 0) {
349 zhp = NULL;
350 return (ret);
351 }
352
353 /* Get handle to BE's root dataset */
354 if ((zhp = zfs_open(g_zfs, bt.obe_root_ds, ZFS_TYPE_DATASET)) == NULL) {
421 return (ret);
422 }
423 }
424
425 /* Find which zpool obe_name lives in */
426 if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) == 0) {
427 be_print_err(gettext("be_create_snapshot: failed to "
428 "find zpool for BE (%s)\n"), bt.obe_name);
429 return (BE_ERR_BE_NOENT);
430 } else if (zret < 0) {
431 be_print_err(gettext("be_create_snapshot: "
432 "zpool_iter failed: %s\n"),
433 libzfs_error_description(g_zfs));
434 return (zfs_err_to_be_err(g_zfs));
435 }
436
437 be_make_root_ds(bt.obe_zpool, bt.obe_name, root_ds,
438 sizeof (root_ds));
439 bt.obe_root_ds = root_ds;
440
441 if (getzoneid() != GLOBAL_ZONEID) {
442 if (!be_zone_compare_uuids(bt.obe_root_ds)) {
443 be_print_err(gettext("be_create_snapshot: creating "
444 "snapshot for the zone root dataset from "
445 "non-active global BE is not "
446 "supported\n"));
447 return (BE_ERR_NOTSUP);
448 }
449 }
450
451 /* If BE policy not specified, use the default policy */
452 if (bt.policy == NULL) {
453 bt.policy = be_default_policy();
454 } else {
455 /* Validate policy type */
456 if (!valid_be_policy(bt.policy)) {
457 be_print_err(gettext("be_create_snapshot: "
458 "invalid BE policy type (%s)\n"), bt.policy);
459 return (BE_ERR_INVAL);
460 }
461 }
462
463 /*
464 * If snapshot name not specified, set auto name flag and
465 * generate auto snapshot name.
466 */
467 if (bt.obe_snap_name == NULL) {
468 autoname = B_TRUE;
469 if ((bt.obe_snap_name = be_auto_snap_name())
470 == NULL) {
484 == NULL) {
485 be_print_err(gettext("be_create_snapshot: "
486 "failed to open BE root dataset (%s): %s\n"),
487 bt.obe_root_ds, libzfs_error_description(g_zfs));
488 ret = zfs_err_to_be_err(g_zfs);
489 goto done;
490 }
491
492 /* Get the ZFS pool version of the pool where this dataset resides */
493 if (zfs_spa_version(zhp, &pool_version) != 0) {
494 be_print_err(gettext("be_create_snapshot: failed to "
495 "get ZFS pool version for %s: %s\n"), zfs_get_name(zhp),
496 libzfs_error_description(g_zfs));
497 }
498
499 /*
500 * If ZFS pool version supports snapshot user properties, store
501 * cleanup policy there. Otherwise don't set one - this snapshot
502 * will always inherit the cleanup policy from its parent.
503 */
504 if (getzoneid() == GLOBAL_ZONEID) {
505 if (pool_version >= SPA_VERSION_SNAP_PROPS) {
506 if (nvlist_alloc(&ss_props, NV_UNIQUE_NAME, 0) != 0) {
507 be_print_err(gettext("be_create_snapshot: "
508 "internal error: out of memory\n"));
509 return (BE_ERR_NOMEM);
510 }
511 if (nvlist_add_string(ss_props, BE_POLICY_PROPERTY,
512 bt.policy) != 0) {
513 be_print_err(gettext("be_create_snapshot: "
514 "internal error: out of memory\n"));
515 nvlist_free(ss_props);
516 return (BE_ERR_NOMEM);
517 }
518 } else if (policy != NULL) {
519 /*
520 * If an explicit cleanup policy was requested
521 * by the caller and we don't support it, error out.
522 */
523 be_print_err(gettext("be_create_snapshot: cannot set "
524 "cleanup policy: ZFS pool version is %d\n"),
525 pool_version);
526 return (BE_ERR_NOTSUP);
527 }
528 }
529
530 /* Create the snapshots recursively */
531 if (zfs_snapshot(g_zfs, ss, B_TRUE, ss_props) != 0) {
532 if (!autoname || libzfs_errno(g_zfs) != EZFS_EXISTS) {
533 be_print_err(gettext("be_create_snapshot: "
534 "recursive snapshot of %s failed: %s\n"),
535 ss, libzfs_error_description(g_zfs));
536
537 if (libzfs_errno(g_zfs) == EZFS_EXISTS)
538 ret = BE_ERR_SS_EXISTS;
539 else
540 ret = zfs_err_to_be_err(g_zfs);
541
542 goto done;
543 } else {
544 for (i = 1; i < BE_AUTO_NAME_MAX_TRY; i++) {
545
546 /* Sleep 1 before retrying */
547 (void) sleep(1);
548
|