Print this page
*** NO COMMENTS ***


   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