2N/A/*
2N/A * CDDL HEADER START
2N/A *
2N/A * The contents of this file are subject to the terms of the
2N/A * Common Development and Distribution License (the "License").
2N/A * You may not use this file except in compliance with the License.
2N/A *
2N/A * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
2N/A * or http://www.opensolaris.org/os/licensing.
2N/A * See the License for the specific language governing permissions
2N/A * and limitations under the License.
2N/A *
2N/A * When distributing Covered Code, include this CDDL HEADER in each
2N/A * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
2N/A * If applicable, add the following below this CDDL HEADER, with the
2N/A * fields enclosed by brackets "[]" replaced with your own identifying
2N/A * information: Portions Copyright [yyyy] [name of copyright owner]
2N/A *
2N/A * CDDL HEADER END
2N/A */
2N/A
2N/A/*
2N/A * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
2N/A */
2N/A
2N/A/*
2N/A * System includes
2N/A */
2N/A
2N/A#include <stdio.h>
2N/A#include <strings.h>
2N/A#include <libzfs.h>
2N/A
2N/A#include "libbe.h"
2N/A
2N/Astatic int be_do_create(int argc, char **argv);
2N/Astatic int be_do_destroy(int argc, char **argv);
2N/Astatic int be_do_list(int argc, char **argv);
2N/Astatic int be_do_mount(int argc, char **argv);
2N/Astatic int be_do_unmount(int argc, char **argv);
2N/Astatic int be_do_rename(int argc, char **argv);
2N/Astatic int be_do_activate(int argc, char **argv);
2N/Astatic int be_do_create_snapshot(int argc, char **argv);
2N/Astatic int be_do_destroy_snapshot(int argc, char **argv);
2N/Astatic int be_do_rollback(int argc, char **argv);
2N/Astatic void usage(void);
2N/A
2N/Atypedef struct be_command {
2N/A const char *name;
2N/A int (*func)(int argc, char **argv);
2N/A} be_command_t;
2N/A
2N/Astatic be_command_t command_table[] = {
2N/A { "create", be_do_create },
2N/A { "destroy", be_do_destroy },
2N/A { "list", be_do_list },
2N/A { "mount", be_do_mount },
2N/A { "unmount", be_do_unmount },
2N/A { "rename", be_do_rename },
2N/A { "activate", be_do_activate },
2N/A { "create_snap", be_do_create_snapshot },
2N/A { "destroy_snap", be_do_destroy_snapshot },
2N/A};
2N/A
2N/Astatic int fs_num = 3;
2N/Astatic int fs_num_props = 2;
2N/Astatic char *fs_names[3] = {"/var", "foo", "/foo/bar"};
2N/Astatic char *fs_zfs_prop_names[3][2] =
2N/A {{"libbe:prop1", "libbe:prop2"},
2N/A {"libbe:prop3", "mountpoint"},
2N/A {"libbe:prop5", "libbe:prop6"}};
2N/Astatic char *fs_zfs_prop_values[3][2] =
2N/A {{"val1", "val2"},
2N/A {"val3", "/foodir"},
2N/A {"val5", "val6"}};
2N/Astatic nvlist_t **fs_zfs_props_nvlist_array;
2N/A
2N/Astatic int shared_fs_num = 4;
2N/Astatic int shared_fs_num_props = 2;
2N/Astatic char *shared_fs_names[4] = {"foo", "/foo/bar", "/bar", "bar/foo"};
2N/Astatic char *shared_fs_zfs_prop_names[4][2] =
2N/A {{"libbe:prop1", "libbe:prop2"},
2N/A {"libbe:prop3", "libbe:prop4"},
2N/A {"libbe:prop5", "libbe:prop6"},
2N/A {"libbe:prop7", "mountpoint"}};
2N/Astatic char *shared_fs_zfs_prop_values[4][2] =
2N/A {{"val1", "val2"},
2N/A {"val3", "val4"},
2N/A {"val5", "val6"},
2N/A {"val7", "/mydir"}};
2N/Astatic nvlist_t **shared_fs_zfs_props_nvlist_array;
2N/A
2N/Astatic void
2N/Ausage(void)
2N/A{
2N/A (void) printf("usage:\n"
2N/A "\ttbeadm\n"
2N/A "\ttbeadm create [-d BE_desc] [-e nonActiveBe | -i [-n]] \n"
2N/A "\t\t[-o property=value] ... [-p zpool] [beName]\n"
2N/A "\ttbeadm destroy [-fs] beName\n"
2N/A "\ttbeadm create_snap [-p policy] beName [snapshot]\n"
2N/A "\ttbeadm destroy_snap beName snapshot\n"
2N/A "\ttbeadm list [-s] [beName]\n"
2N/A "\ttbeadm mount [-s ro|rw] beName mountpoint\n"
2N/A "\ttbeadm unmount [-f] beName\n"
2N/A "\ttbeadm rename origBeName newBeName\n"
2N/A "\ttbeadm activate beName\n"
2N/A "\ttbeadm rollback beName snapshot\n");
2N/A}
2N/A
2N/Aint
2N/Amain(int argc, char **argv) {
2N/A
2N/A if (argc < 2) {
2N/A usage();
2N/A return (1);
2N/A }
2N/A
2N/A /* Turn error printing on */
2N/A libbe_print_errors(B_TRUE);
2N/A
2N/A if (strcmp(argv[1], "create") == 0) {
2N/A return (be_do_create(argc - 1, argv + 1));
2N/A } else if (strcmp(argv[1], "destroy") == 0) {
2N/A return (be_do_destroy(argc - 1, argv + 1));
2N/A } else if (strcmp(argv[1], "list") == 0) {
2N/A return (be_do_list(argc - 1, argv + 1));
2N/A } else if (strcmp(argv[1], "mount") == 0) {
2N/A return (be_do_mount(argc - 1, argv + 1));
2N/A } else if (strcmp(argv[1], "unmount") == 0) {
2N/A return (be_do_unmount(argc - 1, argv + 1));
2N/A } else if (strcmp(argv[1], "rename") == 0) {
2N/A return (be_do_rename(argc - 2, argv + 2));
2N/A } else if (strcmp(argv[1], "activate") == 0) {
2N/A return (be_do_activate(argc - 2, argv + 2));
2N/A } else if (strcmp(argv[1], "create_snap") == 0) {
2N/A return (be_do_create_snapshot(argc - 1, argv + 1));
2N/A } else if (strcmp(argv[1], "destroy_snap") == 0) {
2N/A return (be_do_destroy_snapshot(argc - 2, argv + 2));
2N/A } else if (strcmp(argv[1], "rollback") == 0) {
2N/A return (be_do_rollback(argc - 2, argv + 2));
2N/A } else {
2N/A usage();
2N/A return (1);
2N/A }
2N/A
2N/A /* NOTREACHED */
2N/A}
2N/A
2N/Astatic int
2N/Abe_do_create(int argc, char **argv)
2N/A{
2N/A nvlist_t *be_attrs;
2N/A char *obe_name = NULL;
2N/A char *snap_name = NULL;
2N/A char *nbe_zpool = NULL;
2N/A char *nbe_name = NULL;
2N/A char *nbe_desc = NULL;
2N/A nvlist_t *zfs_props = NULL;
2N/A char *propname = NULL;
2N/A char *propval = NULL;
2N/A char *strval = NULL;
2N/A boolean_t init = B_FALSE;
2N/A boolean_t nested_be = B_FALSE;
2N/A boolean_t allow_auto_naming = B_FALSE;
2N/A int c;
2N/A int ret = BE_SUCCESS;
2N/A
2N/A if (nvlist_alloc(&zfs_props, NV_UNIQUE_NAME, 0) != 0) {
2N/A printf("nvlist_alloc failed.\n");
2N/A return (1);
2N/A }
2N/A
2N/A while ((c = getopt(argc, argv, "ad:e:ino:p:")) != -1) {
2N/A switch (c) {
2N/A case 'd':
2N/A nbe_desc = optarg;
2N/A break;
2N/A case 'e':
2N/A obe_name = optarg;
2N/A break;
2N/A case 'i':
2N/A /* Special option to test be_init() function */
2N/A init = B_TRUE;
2N/A break;
2N/A case 'n':
2N/A /* Initialize a nested BE. */
2N/A nested_be = B_TRUE;
2N/A break;
2N/A case 'a':
2N/A /* Allow auto-naming when initializing a BE */
2N/A allow_auto_naming = B_TRUE;
2N/A break;
2N/A case 'o':
2N/A if (zfs_props == NULL) {
2N/A if (nvlist_alloc(&zfs_props, NV_UNIQUE_NAME,
2N/A 0) != 0) {
2N/A printf("nvlist_alloc failed.\n");
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A propname = optarg;
2N/A if ((propval = strchr(propname, '=')) == NULL) {
2N/A (void) fprintf(stderr, "missing "
2N/A "'=' for -o option\n");
2N/A return (1);
2N/A }
2N/A *propval = '\0';
2N/A propval++;
2N/A if (nvlist_lookup_string(zfs_props, propname,
2N/A &strval) == 0) {
2N/A (void) fprintf(stderr, "property '%s' "
2N/A "specified multiple times\n", propname);
2N/A return (1);
2N/A }
2N/A if (nvlist_add_string(zfs_props, propname, propval)
2N/A != 0) {
2N/A (void) fprintf(stderr, "internal "
2N/A "error: out of memory\n");
2N/A return (1);
2N/A }
2N/A break;
2N/A case 'p':
2N/A nbe_zpool = optarg;
2N/A break;
2N/A default:
2N/A usage();
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A if (init && obe_name) {
2N/A printf("ERROR: -e and -i are exclusive options\n");
2N/A usage();
2N/A return (1);
2N/A }
2N/A
2N/A argc -= optind;
2N/A argv += optind;
2N/A
2N/A if (argc == 1) {
2N/A nbe_name = argv[0];
2N/A } else if (argc > 1) {
2N/A usage();
2N/A return (1);
2N/A }
2N/A
2N/A if (obe_name) {
2N/A /*
2N/A * Check if obe_name is really a snapshot name.
2N/A * If so, split it out.
2N/A */
2N/A char *cp = NULL;
2N/A
2N/A cp = strrchr(obe_name, '@');
2N/A if (cp != NULL) {
2N/A cp[0] = '\0';
2N/A if (cp[1] != NULL && cp[1] != '\0') {
2N/A snap_name = cp+1;
2N/A }
2N/A }
2N/A }
2N/A
2N/A if (nvlist_alloc(&be_attrs, NV_UNIQUE_NAME, 0) != 0) {
2N/A printf("nvlist_alloc failed.\n");
2N/A return (1);
2N/A }
2N/A
2N/A if (zfs_props) {
2N/A if (nvlist_add_nvlist(be_attrs, BE_ATTR_ZFS_PROPERTIES,
2N/A zfs_props) != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_ZFS_PROPERTES (%s).\n", zfs_props);
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A if (obe_name != NULL) {
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_ORIG_BE_NAME (%s).\n", obe_name);
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A if (snap_name != NULL) {
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_SNAP_NAME, snap_name)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_SNAP_NANE (%s).\n", snap_name);
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A if (nbe_zpool != NULL) {
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_NEW_BE_POOL, nbe_zpool)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_NEW_BE_POOL (%s).\n", nbe_zpool);
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A if (nbe_name) {
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_NEW_BE_NAME, nbe_name)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_NEW_BE_NAME (%s).\n", nbe_name);
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A if (nbe_desc) {
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_NEW_BE_DESC, nbe_desc)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_NEW_BE_DESC (%s)\n", nbe_desc);
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A if (init) {
2N/A int i, j;
2N/A
2N/A /*
2N/A * Add boolean value to determine if we're initializing
2N/A * a nested BE.
2N/A */
2N/A if (nvlist_add_boolean_value(be_attrs, BE_ATTR_NEW_BE_NESTED_BE,
2N/A nested_be) != 0) {
2N/A return (1);
2N/A }
2N/A
2N/A /*
2N/A * Add boolean value to determine if we're allowing
2N/A * auto-naming in case there is a BE name conflict.
2N/A */
2N/A if (nvlist_add_boolean_value(be_attrs,
2N/A BE_ATTR_NEW_BE_ALLOW_AUTO_NAMING, allow_auto_naming) != 0) {
2N/A return (1);
2N/A }
2N/A
2N/A /*
2N/A * Add the default file system test values to test
2N/A * creating an initial BE.
2N/A */
2N/A if (nvlist_add_uint16(be_attrs, BE_ATTR_FS_NUM, fs_num) != 0) {
2N/A printf("nvlist_add_uint16 failed for BE_ATTR_FS_NUM "
2N/A "(%d).\n", fs_num);
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_string_array(be_attrs, BE_ATTR_FS_NAMES,
2N/A fs_names, fs_num) != 0) {
2N/A printf("nvlist_add_string_array failed for "
2N/A "BE_ATTR_FS_NAMES\n");
2N/A return (1);
2N/A }
2N/A
2N/A /* Add properties for the non-shared filesystems. */
2N/A if ((fs_zfs_props_nvlist_array =
2N/A calloc(sizeof (nvlist_t *), fs_num)) == NULL) {
2N/A printf("memory allocation failed\n");
2N/A return (1);
2N/A }
2N/A
2N/A for (i = 0; i < fs_num; i++) {
2N/A if (nvlist_alloc(&fs_zfs_props_nvlist_array[i],
2N/A NV_UNIQUE_NAME, 0) != 0) {
2N/A printf("nvlist_alloc_failed\n");
2N/A return (1);
2N/A }
2N/A for (j = 0; j < fs_num_props; j++) {
2N/A if (nvlist_add_string(
2N/A fs_zfs_props_nvlist_array[i],
2N/A fs_zfs_prop_names[i][j],
2N/A fs_zfs_prop_values[i][j]) != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_FS_ZFS_PROPERTIES\n");
2N/A return (1);
2N/A }
2N/A }
2N/A }
2N/A
2N/A if (nvlist_add_nvlist_array(be_attrs, BE_ATTR_FS_ZFS_PROPERTIES,
2N/A fs_zfs_props_nvlist_array, fs_num) != 0) {
2N/A printf("nvlist_add_nvlist_array failed for "
2N/A "BE_ATTR_FS_ZFS_PROPERTIES\n");
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_uint16(be_attrs, BE_ATTR_SHARED_FS_NUM,
2N/A shared_fs_num) != 0) {
2N/A printf("nvlist_add_uint16 failed for "
2N/A "BE_ATTR_SHARED_FS_NUM (%d).\n", shared_fs_num);
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_string_array(be_attrs, BE_ATTR_SHARED_FS_NAMES,
2N/A shared_fs_names, shared_fs_num) != 0) {
2N/A printf("nvlist_add_string_array failed for "
2N/A "BE_ATTR_SHARED_FS_NAMES\n");
2N/A return (1);
2N/A }
2N/A
2N/A /* Add properties for the shared filesystems. */
2N/A if ((shared_fs_zfs_props_nvlist_array =
2N/A calloc(sizeof (nvlist_t *), shared_fs_num)) == NULL) {
2N/A printf("memory allocation failed\n");
2N/A return (1);
2N/A }
2N/A
2N/A for (i = 0; i < shared_fs_num; i++) {
2N/A if (nvlist_alloc(&shared_fs_zfs_props_nvlist_array[i],
2N/A NV_UNIQUE_NAME, 0) != 0) {
2N/A printf("nvlist_alloc_failed\n");
2N/A return (1);
2N/A }
2N/A for (j = 0; j < shared_fs_num_props; j++) {
2N/A if (nvlist_add_string(
2N/A shared_fs_zfs_props_nvlist_array[i],
2N/A shared_fs_zfs_prop_names[i][j],
2N/A shared_fs_zfs_prop_values[i][j]) != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_SHARED_FS_ZFS_PROPERTIES\n");
2N/A return (1);
2N/A }
2N/A }
2N/A }
2N/A
2N/A if (nvlist_add_nvlist_array(be_attrs,
2N/A BE_ATTR_SHARED_FS_ZFS_PROPERTIES,
2N/A shared_fs_zfs_props_nvlist_array, shared_fs_num) != 0) {
2N/A printf("nvlist_add_nvlist_array failed for "
2N/A "BE_ATTR_SHARED_FS_ZFS_PROPERTIES\n");
2N/A return (1);
2N/A }
2N/A
2N/A ret = be_init(be_attrs);
2N/A
2N/A if (ret == BE_SUCCESS && allow_auto_naming) {
2N/A /*
2N/A * We requested to allow auto named BE; find out the
2N/A * name of the BE that was initialized for us.
2N/A */
2N/A if (nvlist_lookup_string(be_attrs, BE_ATTR_NEW_BE_NAME,
2N/A &nbe_name) != 0) {
2N/A printf("failed to get BE_ATTR_NEW_BE_NAME "
2N/A "attribute\n");
2N/A ret = 1;
2N/A } else {
2N/A printf("Initialized BE name: %s\n", nbe_name);
2N/A }
2N/A }
2N/A
2N/A return (ret);
2N/A }
2N/A
2N/A ret = be_copy(be_attrs);
2N/A
2N/A if (!nbe_name & ret == BE_SUCCESS) {
2N/A /*
2N/A * We requested an auto named BE; find out the
2N/A * name of the BE that was created for us and
2N/A * the auto snapshot created from the original BE.
2N/A */
2N/A if (nvlist_lookup_string(be_attrs, BE_ATTR_NEW_BE_NAME,
2N/A &nbe_name) != 0) {
2N/A printf("failed to get BE_ATTR_NEW_BE_NAME attribute\n");
2N/A ret = 1;
2N/A } else {
2N/A printf("Auto named BE: %s\n", nbe_name);
2N/A }
2N/A
2N/A if (nvlist_lookup_string(be_attrs, BE_ATTR_SNAP_NAME,
2N/A &snap_name) != 0) {
2N/A printf("failed to get BE_ATTR_SNAP_NAME attribute\n");
2N/A ret = 1;
2N/A } else {
2N/A printf("Auto named snapshot: %s\n", snap_name);
2N/A }
2N/A }
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/Astatic int
2N/Abe_do_destroy(int argc, char **argv)
2N/A{
2N/A nvlist_t *be_attrs;
2N/A int c;
2N/A int destroy_flags = 0;
2N/A char *be_name;
2N/A
2N/A while ((c = getopt(argc, argv, "fs")) != -1) {
2N/A switch (c) {
2N/A case 'f':
2N/A destroy_flags |= BE_DESTROY_FLAG_FORCE_UNMOUNT;
2N/A break;
2N/A case 's':
2N/A destroy_flags |= BE_DESTROY_FLAG_SNAPSHOTS;
2N/A break;
2N/A default:
2N/A usage();
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A argc -= optind;
2N/A argv += optind;
2N/A
2N/A if (argc != 1) {
2N/A usage();
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_alloc(&be_attrs, NV_UNIQUE_NAME, 0) != 0) {
2N/A printf("nvlist_alloc failed.\n");
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, argv[0]) != 0) {
2N/A printf("nvlist_add_string failed for BE_ATTR_NEW_BE_NAME "
2N/A "(%s).\n", argv[0]);
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_uint16(be_attrs, BE_ATTR_DESTROY_FLAGS, destroy_flags)
2N/A != 0) {
2N/A printf("nvlist_add_uint16 failed for "
2N/A "BE_ATTR_DESTROY_FLAGS.\n");
2N/A return (1);
2N/A }
2N/A
2N/A return (be_destroy(be_attrs));
2N/A}
2N/A
2N/Astatic int
2N/Abe_do_list(int argc, char **argv)
2N/A{
2N/A int err = BE_SUCCESS;
2N/A be_node_list_t *be_nodes;
2N/A be_node_list_t *cur_be;
2N/A boolean_t snaps = B_FALSE;
2N/A int c = 0;
2N/A
2N/A while ((c = getopt(argc, argv, "s")) != -1) {
2N/A switch (c) {
2N/A case 's':
2N/A snaps = B_TRUE;
2N/A break;
2N/A default:
2N/A usage();
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A argc -= optind;
2N/A argv += optind;
2N/A
2N/A
2N/A if (argc == 1) {
2N/A err = be_list(argv[0], &be_nodes);
2N/A } else {
2N/A err = be_list(NULL, &be_nodes);
2N/A }
2N/A
2N/A if (err == BE_SUCCESS) {
2N/A
2N/A printf(
2N/A "BE name\t\tActive\tActive \tBootable Dataset\t\t\t"
2N/A "Policy\tUUID\n");
2N/A printf(
2N/A " \t\t \ton boot\t\t \t\t \t \n");
2N/A printf(
2N/A "-------\t\t------\t-------\t-------- -------\t\t\t"
2N/A "------\t----\n");
2N/A
2N/A for (cur_be = be_nodes; cur_be != NULL;
2N/A cur_be = cur_be->be_next_node) {
2N/A
2N/A int name_len = strlen(cur_be->be_node_name);
2N/A int ds_len = strlen(cur_be->be_root_ds);
2N/A
2N/A printf("%s%s%s\t%s\t%s\t %s\t%s%s\t%s\n",
2N/A cur_be->be_node_name,
2N/A name_len < 8 ? "\t\t" : "\t",
2N/A cur_be->be_active ? "yes" : "no",
2N/A cur_be->be_active_on_boot ? "yes" : "no",
2N/A cur_be->be_active_unbootable ? "no" : "yes",
2N/A cur_be->be_root_ds,
2N/A ds_len < 8 ? "\t\t\t" :
2N/A (ds_len < 16 ? "\t\t" : "\t"),
2N/A cur_be->be_policy_type,
2N/A cur_be->be_uuid_str ? cur_be->be_uuid_str : "-");
2N/A if (snaps) {
2N/A be_snapshot_list_t *snapshots = NULL;
2N/A printf("Snapshot Name\n");
2N/A printf("--------------\n");
2N/A for (snapshots = cur_be->be_node_snapshots;
2N/A snapshots != NULL; snapshots =
2N/A snapshots->be_next_snapshot) {
2N/A printf("%s\n",
2N/A snapshots->be_snapshot_name);
2N/A }
2N/A }
2N/A }
2N/A }
2N/A
2N/A be_free_list(be_nodes);
2N/A return (err);
2N/A}
2N/A
2N/Astatic int
2N/Abe_do_rename(int argc, char **argv)
2N/A{
2N/A nvlist_t *be_attrs;
2N/A char *obe_name;
2N/A char *nbe_name;
2N/A
2N/A if (argc < 1 || argc > 2) {
2N/A usage();
2N/A return (1);
2N/A }
2N/A
2N/A obe_name = argv[0];
2N/A nbe_name = argv[1];
2N/A
2N/A if (nvlist_alloc(&be_attrs, NV_UNIQUE_NAME, 0) != 0) {
2N/A printf("nvlist_alloc failed.\n");
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_ORIG_BE_NAME (%s).\n", obe_name);
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_NEW_BE_NAME, nbe_name)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_NEW_BE_NAME (%s).\n", nbe_name);
2N/A return (1);
2N/A }
2N/A
2N/A return (be_rename(be_attrs));
2N/A
2N/A}
2N/A
2N/Astatic int
2N/Abe_do_create_snapshot(int argc, char **argv)
2N/A{
2N/A nvlist_t *be_attrs;
2N/A char *obe_name = NULL;
2N/A char *snap_name = NULL;
2N/A char *policy = NULL;
2N/A int c;
2N/A int ret = BE_SUCCESS;
2N/A
2N/A while ((c = getopt(argc, argv, "p:")) != -1) {
2N/A switch (c) {
2N/A case 'p':
2N/A policy = optarg;
2N/A break;
2N/A default:
2N/A usage();
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A argc -= optind;
2N/A argv += optind;
2N/A
2N/A if (argc < 1 || argc > 2) {
2N/A usage();
2N/A return (1);
2N/A }
2N/A
2N/A obe_name = argv[0];
2N/A
2N/A if (argc > 1) {
2N/A /* Snapshot name provided */
2N/A snap_name = argv[1];
2N/A }
2N/A
2N/A if (nvlist_alloc(&be_attrs, NV_UNIQUE_NAME, 0) != 0) {
2N/A printf("nvlist_alloc failed.\n");
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_ORIG_BE_NAME (%s).\n", obe_name);
2N/A return (1);
2N/A }
2N/A
2N/A if (policy) {
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_POLICY, policy) != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_POLICY (%s).\n", policy);
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A if (snap_name) {
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_SNAP_NAME, snap_name)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_SNAP_NAME (%s).\n", snap_name);
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A ret = be_create_snapshot(be_attrs);
2N/A
2N/A if (!snap_name && ret == BE_SUCCESS) {
2N/A /*
2N/A * We requested an auto named snapshot; find out
2N/A * the snapshot name that was created for us.
2N/A */
2N/A if (nvlist_lookup_string(be_attrs, BE_ATTR_SNAP_NAME,
2N/A &snap_name) != 0) {
2N/A printf("failed to get BE_ATTR_SNAP_NAME attribute\n");
2N/A ret = 1;
2N/A } else {
2N/A printf("Auto named snapshot: %s\n", snap_name);
2N/A }
2N/A }
2N/A
2N/A return (ret);
2N/A}
2N/A
2N/Astatic int
2N/Abe_do_destroy_snapshot(int argc, char **argv)
2N/A{
2N/A nvlist_t *be_attrs;
2N/A char *obe_name;
2N/A char *snap_name;
2N/A
2N/A if (argc != 2) {
2N/A usage();
2N/A return (1);
2N/A }
2N/A
2N/A obe_name = argv[0];
2N/A snap_name = argv[1];
2N/A
2N/A if (nvlist_alloc(&be_attrs, NV_UNIQUE_NAME, 0) != 0) {
2N/A printf("nvlist_alloc failed.\n");
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_ORIG_BE_NAME (%s).\n", obe_name);
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_SNAP_NAME, snap_name)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_SNAP_NAME (%s).\n", snap_name);
2N/A return (1);
2N/A }
2N/A
2N/A return (be_destroy_snapshot(be_attrs));
2N/A}
2N/A
2N/Astatic int
2N/Abe_do_rollback(int argc, char **argv)
2N/A{
2N/A nvlist_t *be_attrs;
2N/A char *obe_name;
2N/A char *snap_name;
2N/A
2N/A if (argc < 1 || argc > 2) {
2N/A usage();
2N/A return (1);
2N/A }
2N/A
2N/A obe_name = argv[0];
2N/A snap_name = argv[1];
2N/A
2N/A if (nvlist_alloc(&be_attrs, NV_UNIQUE_NAME, 0) != 0) {
2N/A printf("nvlist_alloc failed.\n");
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_ORIG_BE_NAME (%s).\n", obe_name);
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_SNAP_NAME, snap_name)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_SNAP_NAME (%s).\n", snap_name);
2N/A return (1);
2N/A }
2N/A
2N/A return (be_rollback(be_attrs));
2N/A}
2N/A
2N/Astatic int
2N/Abe_do_activate(int argc, char **argv)
2N/A{
2N/A nvlist_t *be_attrs;
2N/A char *obe_name;
2N/A
2N/A if (argc < 1 || argc > 2) {
2N/A usage();
2N/A return (1);
2N/A }
2N/A
2N/A obe_name = argv[0];
2N/A
2N/A if (nvlist_alloc(&be_attrs, NV_UNIQUE_NAME, 0) != 0) {
2N/A printf("nvlist_alloc failed.\n");
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_ORIG_BE_NAME (%s).\n", obe_name);
2N/A return (1);
2N/A }
2N/A
2N/A return (be_activate(be_attrs));
2N/A}
2N/A
2N/Astatic int
2N/Abe_do_mount(int argc, char **argv)
2N/A{
2N/A nvlist_t *be_attrs;
2N/A int c;
2N/A boolean_t shared_fs = B_FALSE;
2N/A int mount_flags = 0;
2N/A char *obe_name;
2N/A char *mountpoint;
2N/A
2N/A while ((c = getopt(argc, argv, "s:")) != -1) {
2N/A switch (c) {
2N/A case 's':
2N/A shared_fs = B_TRUE;
2N/A
2N/A mount_flags |= BE_MOUNT_FLAG_SHARED_FS;
2N/A
2N/A if (strcmp(optarg, "rw") == 0) {
2N/A mount_flags |= BE_MOUNT_FLAG_SHARED_RW;
2N/A } else if (strcmp(optarg, "ro") != 0) {
2N/A printf("The -s flag requires an argument "
2N/A "[ rw | ro ]\n");
2N/A usage();
2N/A return (1);
2N/A }
2N/A
2N/A break;
2N/A default:
2N/A usage();
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A argc -= optind;
2N/A argv += optind;
2N/A
2N/A if (argc < 1 || argc > 2) {
2N/A usage();
2N/A return (1);
2N/A }
2N/A
2N/A obe_name = argv[0];
2N/A
2N/A if (argc == 2) {
2N/A mountpoint = argv[1];
2N/A } else {
2N/A /*
2N/A * XXX - Need to generate a random mountpoint here;
2N/A * right now we're just exitting if one isn't supplied.
2N/A */
2N/A usage();
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_alloc(&be_attrs, NV_UNIQUE_NAME, 0) != 0) {
2N/A printf("nvlist_alloc failed.\n");
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_ORIG_BE_NAME (%s).\n", obe_name);
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_MOUNTPOINT, mountpoint)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_MOUNTPOINT (%s).\n", mountpoint);
2N/A return (1);
2N/A }
2N/A
2N/A if (shared_fs) {
2N/A if (nvlist_add_uint16(be_attrs, BE_ATTR_MOUNT_FLAGS,
2N/A mount_flags) != 0) {
2N/A printf("nvlist_add_uint16 failed for "
2N/A "BE_ATTR_MOUNT_FLAGS (%d).\n", mount_flags);
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A return (be_mount(be_attrs));
2N/A}
2N/A
2N/A
2N/Astatic int
2N/Abe_do_unmount(int argc, char **argv)
2N/A{
2N/A nvlist_t *be_attrs;
2N/A int c;
2N/A int unmount_flags = 0;
2N/A char *obe_name;
2N/A
2N/A while ((c = getopt(argc, argv, "f")) != -1) {
2N/A switch (c) {
2N/A case 'f':
2N/A unmount_flags |= BE_UNMOUNT_FLAG_FORCE;
2N/A break;
2N/A default:
2N/A usage();
2N/A return (1);
2N/A }
2N/A }
2N/A
2N/A argc -= optind;
2N/A argv += optind;
2N/A
2N/A if (argc != 1) {
2N/A usage();
2N/A return (1);
2N/A }
2N/A
2N/A obe_name = argv[0];
2N/A
2N/A if (nvlist_alloc(&be_attrs, NV_UNIQUE_NAME, 0) != 0) {
2N/A printf("nvlist_alloc failed.\n");
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_string(be_attrs, BE_ATTR_ORIG_BE_NAME, obe_name)
2N/A != 0) {
2N/A printf("nvlist_add_string failed for "
2N/A "BE_ATTR_ORIG_BE_NAME (%s).\n", obe_name);
2N/A return (1);
2N/A }
2N/A
2N/A if (nvlist_add_uint16(be_attrs, BE_ATTR_UNMOUNT_FLAGS, unmount_flags)
2N/A != 0) {
2N/A printf("nvlist_add_uint16 failed for "
2N/A "BE_ATTR_UNMOUNT_FLAGS\n");
2N/A return (1);
2N/A }
2N/A
2N/A return (be_unmount(be_attrs));
2N/A}