# HG changeset patch # User Alexander Eremin # Date 1302101122 25200 # Node ID 70ccb19abd772fd0dc8a6d677e3d1c89926456c9 # Parent ab46f88a2660f35ae5d429a920af508c914868c1 719 beadm should allow BEs outside of /ROOT Reviewed by: Dan McDonald Reviewed by: Rich Lowe Approved by: Garrett D'Amore diff -r ab46f88a2660 -r 70ccb19abd77 usr/src/lib/libbe/common/be_create.c --- a/usr/src/lib/libbe/common/be_create.c Tue Apr 05 09:31:14 2011 -0700 +++ b/usr/src/lib/libbe/common/be_create.c Wed Apr 06 07:45:22 2011 -0700 @@ -24,6 +24,10 @@ */ /* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + */ + +/* * System includes */ @@ -576,17 +580,20 @@ be_transaction_data_t bt = { 0 }; be_fs_list_data_t fld = { 0 }; zfs_handle_t *zhp = NULL; + zpool_handle_t *zphp = NULL; nvlist_t *zfs_props = NULL; uuid_t uu = { 0 }; char obe_root_ds[MAXPATHLEN]; char nbe_root_ds[MAXPATHLEN]; char ss[MAXPATHLEN]; char *new_mp = NULL; + char *obe_name = NULL; boolean_t autoname = B_FALSE; boolean_t be_created = B_FALSE; int i; int zret; int ret = BE_SUCCESS; + struct be_defaults be_defaults; /* Initialize libzfs handle */ if (!be_zfs_init()) @@ -594,18 +601,21 @@ /* Get original BE name */ if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, - BE_ATTR_ORIG_BE_NAME, DATA_TYPE_STRING, &bt.obe_name, NULL) != 0) { + BE_ATTR_ORIG_BE_NAME, DATA_TYPE_STRING, &obe_name, NULL) != 0) { be_print_err(gettext("be_copy: failed to lookup " "BE_ATTR_ORIG_BE_NAME attribute\n")); return (BE_ERR_INVAL); } + if ((ret = be_find_current_be(&bt)) != BE_SUCCESS) { + return (ret); + } + + be_get_defaults(&be_defaults); + /* If original BE name not provided, use current BE */ - if (bt.obe_name == NULL) { - if ((ret = be_find_current_be(&bt)) != BE_SUCCESS) { - return (ret); - } - } else { + if (obe_name != NULL) { + bt.obe_name = obe_name; /* Validate original BE name */ if (!be_valid_be_name(bt.obe_name)) { be_print_err(gettext("be_copy: " @@ -614,16 +624,29 @@ } } - /* Find which zpool obe_name lives in */ - if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) == 0) { - be_print_err(gettext("be_copy: failed to " - "find zpool for BE (%s)\n"), bt.obe_name); - return (BE_ERR_BE_NOENT); - } else if (zret < 0) { - be_print_err(gettext("be_copy: " - "zpool_iter failed: %s\n"), - libzfs_error_description(g_zfs)); - return (zfs_err_to_be_err(g_zfs)); + if (be_defaults.be_deflt_rpool_container) { + if ((zphp = zpool_open(g_zfs, bt.obe_zpool)) == NULL) { + be_print_err(gettext("be_get_node_data: failed to " + "open rpool (%s): %s\n"), bt.obe_zpool, + libzfs_error_description(g_zfs)); + return (zfs_err_to_be_err(g_zfs)); + } + if (be_find_zpool_callback(zphp, &bt) == 0) { + return (BE_ERR_BE_NOENT); + } + } else { + /* Find which zpool obe_name lives in */ + if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) == + 0) { + be_print_err(gettext("be_copy: failed to " + "find zpool for BE (%s)\n"), bt.obe_name); + return (BE_ERR_BE_NOENT); + } else if (zret < 0) { + be_print_err(gettext("be_copy: " + "zpool_iter failed: %s\n"), + libzfs_error_description(g_zfs)); + return (zfs_err_to_be_err(g_zfs)); + } } /* Get snapshot name of original BE if one was provided */ @@ -1414,7 +1437,8 @@ if (be_destroy_callback(zhp, dd) != 0) { be_print_err(gettext("be_destroy: failed to " "destroy BE %s\n"), root_ds); - return (BE_ERR_DESTROY); + ret = zfs_err_to_be_err(g_zfs); + return (ret); } /* If BE has an origin */ diff -r ab46f88a2660 -r 70ccb19abd77 usr/src/lib/libbe/common/be_list.c --- a/usr/src/lib/libbe/common/be_list.c Tue Apr 05 09:31:14 2011 -0700 +++ b/usr/src/lib/libbe/common/be_list.c Wed Apr 06 07:45:22 2011 -0700 @@ -23,6 +23,10 @@ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. */ +/* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + */ + #include #include #include @@ -153,10 +157,15 @@ list_callback_data_t cb = { 0 }; be_transaction_data_t bt = { 0 }; int ret = BE_SUCCESS; + zpool_handle_t *zphp; + char *rpool = NULL; + struct be_defaults be_defaults; if (be_nodes == NULL) return (BE_ERR_INVAL); + be_get_defaults(&be_defaults); + if (be_find_current_be(&bt) != BE_SUCCESS) { /* * We were unable to find a currently booted BE which @@ -167,6 +176,7 @@ } else { (void) strncpy(cb.current_be, bt.obe_name, sizeof (cb.current_be)); + rpool = bt.obe_zpool; } /* @@ -176,13 +186,25 @@ if (be_name != NULL) cb.be_name = strdup(be_name); - if ((zpool_iter(g_zfs, be_get_list_callback, &cb)) != 0) { - if (cb.be_nodes_head != NULL) { - be_free_list(cb.be_nodes_head); - cb.be_nodes_head = NULL; - cb.be_nodes = NULL; + if (be_defaults.be_deflt_rpool_container && rpool != NULL) { + if ((zphp = zpool_open(g_zfs, rpool)) == NULL) { + be_print_err(gettext("be_get_node_data: failed to " + "open rpool (%s): %s\n"), rpool, + libzfs_error_description(g_zfs)); + free(cb.be_name); + return (zfs_err_to_be_err(g_zfs)); } - ret = BE_ERR_BE_NOENT; + + ret = be_get_list_callback(zphp, &cb); + } else { + if ((zpool_iter(g_zfs, be_get_list_callback, &cb)) != 0) { + if (cb.be_nodes_head != NULL) { + be_free_list(cb.be_nodes_head); + cb.be_nodes_head = NULL; + cb.be_nodes = NULL; + } + ret = BE_ERR_BE_NOENT; + } } if (cb.be_nodes_head == NULL) { @@ -367,6 +389,8 @@ * the information for the specified BE. */ if (cb->be_name != NULL) { + if (!be_valid_be_name(cb->be_name)) + return (BE_ERR_INVAL); /* * Generate string for the BE root dataset */ @@ -398,16 +422,6 @@ return (ret); } - if (cb->be_nodes_head == NULL) { - if ((cb->be_nodes_head = be_list_alloc(&ret, - sizeof (be_node_list_t))) == NULL) { - ZFS_CLOSE(zhp); - zpool_close(zlp); - return (ret); - } - cb->be_nodes = cb->be_nodes_head; - } - /* * If a BE name was specified we iterate through the datasets * and snapshots for this BE only. Otherwise we will iterate @@ -415,6 +429,16 @@ * within the pool */ if (cb->be_name != NULL) { + if (cb->be_nodes_head == NULL) { + if ((cb->be_nodes_head = be_list_alloc(&ret, + sizeof (be_node_list_t))) == NULL) { + ZFS_CLOSE(zhp); + zpool_close(zlp); + return (ret); + } + cb->be_nodes = cb->be_nodes_head; + } + if ((ret = be_get_node_data(zhp, cb->be_nodes, cb->be_name, rpool, cb->current_be, be_ds)) != BE_SUCCESS) { ZFS_CLOSE(zhp); @@ -454,6 +478,9 @@ list_callback_data_t *cb = (list_callback_data_t *)data; char *str = NULL, *ds_path = NULL; int ret = 0; + struct be_defaults be_defaults; + + be_get_defaults(&be_defaults); ds_path = str = strdup(zfs_get_name(zhp)); @@ -461,6 +488,21 @@ * get past the end of the container dataset plus the trailing "/" */ str = str + (strlen(be_container_ds) + 1); + if (be_defaults.be_deflt_bename_starts_with != '\0') { + /* just skip if invalid */ + if (!be_valid_be_name(str)) + return (BE_SUCCESS); + } + + if (cb->be_nodes_head == NULL) { + if ((cb->be_nodes_head = be_list_alloc(&ret, + sizeof (be_node_list_t))) == NULL) { + ZFS_CLOSE(zhp); + return (ret); + } + cb->be_nodes = cb->be_nodes_head; + } + if (zfs_get_type(zhp) == ZFS_TYPE_SNAPSHOT && !zone_be) { be_snapshot_list_t *snapshots = NULL; if (cb->be_nodes->be_node_snapshots == NULL) { diff -r ab46f88a2660 -r 70ccb19abd77 usr/src/lib/libbe/common/be_snapshot.c --- a/usr/src/lib/libbe/common/be_snapshot.c Tue Apr 05 09:31:14 2011 -0700 +++ b/usr/src/lib/libbe/common/be_snapshot.c Wed Apr 06 07:45:22 2011 -0700 @@ -24,6 +24,10 @@ */ /* + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + */ + +/* * System includes */ #include @@ -248,27 +252,33 @@ { be_transaction_data_t bt = { 0 }; zfs_handle_t *zhp = NULL; + zpool_handle_t *zphp; char obe_root_ds[MAXPATHLEN]; + char *obe_name = NULL; int zret = 0, ret = BE_SUCCESS; + struct be_defaults be_defaults; /* Initialize libzfs handle */ if (!be_zfs_init()) return (BE_ERR_INIT); + if ((ret = be_find_current_be(&bt)) != BE_SUCCESS) { + return (ret); + } + /* Get original BE name if one was provided */ if (nvlist_lookup_pairs(be_attrs, NV_FLAG_NOENTOK, - BE_ATTR_ORIG_BE_NAME, DATA_TYPE_STRING, &bt.obe_name, NULL) != 0) { + BE_ATTR_ORIG_BE_NAME, DATA_TYPE_STRING, &obe_name, NULL) != 0) { be_print_err(gettext("be_rollback: " "failed to lookup BE_ATTR_ORIG_BE_NAME attribute\n")); return (BE_ERR_INVAL); } + be_get_defaults(&be_defaults); + /* If original BE name not provided, use current BE */ - if (bt.obe_name == NULL) { - if ((ret = be_find_current_be(&bt)) != BE_SUCCESS) { - return (ret); - } - } else { + if (obe_name != NULL) { + bt.obe_name = obe_name; /* Validate original BE name */ if (!be_valid_be_name(bt.obe_name)) { be_print_err(gettext("be_rollback: " @@ -285,16 +295,27 @@ return (BE_ERR_INVAL); } - /* Find which zpool obe_name lives in */ - if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) == 0) { - be_print_err(gettext("be_rollback: " - "failed to find zpool for BE (%s)\n"), bt.obe_name); - return (BE_ERR_BE_NOENT); - } else if (zret < 0) { - be_print_err(gettext("be_rollback: " - "zpool_iter failed: %s\n"), - libzfs_error_description(g_zfs)); - return (zfs_err_to_be_err(g_zfs)); + if (be_defaults.be_deflt_rpool_container) { + if ((zphp = zpool_open(g_zfs, bt.obe_zpool)) == NULL) { + be_print_err(gettext("be_rollback: failed to " + "open rpool (%s): %s\n"), bt.obe_zpool, + libzfs_error_description(g_zfs)); + return (zfs_err_to_be_err(g_zfs)); + } + zret = be_find_zpool_callback(zphp, &bt); + } else { + /* Find which zpool obe_name lives in */ + if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) == + 0) { + be_print_err(gettext("be_rollback: " + "failed to find zpool for BE (%s)\n"), bt.obe_name); + return (BE_ERR_BE_NOENT); + } else if (zret < 0) { + be_print_err(gettext("be_rollback: " + "zpool_iter failed: %s\n"), + libzfs_error_description(g_zfs)); + return (zfs_err_to_be_err(g_zfs)); + } } /* Generate string for BE's root dataset */ diff -r ab46f88a2660 -r 70ccb19abd77 usr/src/lib/libbe/common/be_utils.c --- a/usr/src/lib/libbe/common/be_utils.c Tue Apr 05 09:31:14 2011 -0700 +++ b/usr/src/lib/libbe/common/be_utils.c Wed Apr 06 07:45:22 2011 -0700 @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -59,8 +60,8 @@ /* Private function prototypes */ static int update_dataset(char *, int, char *, char *, char *); static int _update_vfstab(char *, char *, char *, char *, be_fs_list_data_t *); -static int be_open_menu(char *, char *, char *, FILE **, char *, boolean_t); -static int be_create_menu(char *, char *, char *, FILE **, char *); +static int be_open_menu(char *, char *, FILE **, char *, boolean_t); +static int be_create_menu(char *, char *, FILE **, char *); static char *be_get_auto_name(char *, char *, boolean_t); /* @@ -181,6 +182,35 @@ } /* + * Function: be_get_defaults + * Description: Open defaults and gets be default paramets + * Parameters: + * defaults - be defaults struct + * Returns: + * None + * Scope: + * Semi-private (library wide use only) + */ +void +be_get_defaults(struct be_defaults *defaults) +{ + void *defp; + + defaults->be_deflt_rpool_container = B_FALSE; + defaults->be_deflt_bename_starts_with[0] = '\0'; + + if ((defp = defopen_r(BE_DEFAULTS)) != NULL) { + const char *res = defread_r(BE_DFLT_BENAME_STARTS, defp); + if (res != NULL && res[0] != NULL) { + (void) strlcpy(defaults->be_deflt_bename_starts_with, + res, ZFS_MAXNAMELEN); + defaults->be_deflt_rpool_container = B_TRUE; + } + defclose_r(defp); + } +} + +/* * Function: be_make_root_ds * Description: Generate string for BE's root dataset given the pool * it lives in and the BE name. @@ -198,8 +228,15 @@ be_make_root_ds(const char *zpool, const char *be_name, char *be_root_ds, int be_root_ds_size) { - (void) snprintf(be_root_ds, be_root_ds_size, "%s/%s/%s", zpool, - BE_CONTAINER_DS_NAME, be_name); + struct be_defaults be_defaults; + be_get_defaults(&be_defaults); + + if (be_defaults.be_deflt_rpool_container) + (void) snprintf(be_root_ds, be_root_ds_size, "%s/%s", zpool, + be_name); + else + (void) snprintf(be_root_ds, be_root_ds_size, "%s/%s/%s", zpool, + BE_CONTAINER_DS_NAME, be_name); } /* @@ -219,8 +256,14 @@ be_make_container_ds(const char *zpool, char *container_ds, int container_ds_size) { - (void) snprintf(container_ds, container_ds_size, "%s/%s", zpool, - BE_CONTAINER_DS_NAME); + struct be_defaults be_defaults; + be_get_defaults(&be_defaults); + + if (be_defaults.be_deflt_rpool_container) + (void) snprintf(container_ds, container_ds_size, "%s", zpool); + else + (void) snprintf(container_ds, container_ds_size, "%s/%s", zpool, + BE_CONTAINER_DS_NAME); } /* @@ -244,31 +287,41 @@ char ds[ZFS_MAXNAMELEN]; char *tok = NULL; char *name = NULL; + struct be_defaults be_defaults; + int rlen = strlen(rc_loc); + + be_get_defaults(&be_defaults); /* * First token is the location of where the root container dataset * lives; it must match rc_loc. */ - if (strncmp(dataset, rc_loc, strlen(rc_loc)) == 0 && - dataset[strlen(rc_loc)] == '/') { - (void) strlcpy(ds, dataset + strlen(rc_loc) + 1, sizeof (ds)); - } else { + if (strncmp(dataset, rc_loc, rlen) == 0 && dataset[rlen] == '/') + (void) strlcpy(ds, dataset + rlen + 1, sizeof (ds)); + else return (NULL); - } - - /* Second token must be BE container dataset name */ - if ((tok = strtok(ds, "/")) == NULL || - strcmp(tok, BE_CONTAINER_DS_NAME) != 0) - return (NULL); - - /* Return the remaining token if one exists */ - if ((tok = strtok(NULL, "")) == NULL) - return (NULL); - - if ((name = strdup(tok)) == NULL) { - be_print_err(gettext("be_make_name_from_ds: " - "memory allocation failed\n")); - return (NULL); + + if (be_defaults.be_deflt_rpool_container) { + if ((name = strdup(ds)) == NULL) { + be_print_err(gettext("be_make_name_from_ds: " + "memory allocation failed\n")); + return (NULL); + } + } else { + /* Second token must be BE container dataset name */ + if ((tok = strtok(ds, "/")) == NULL || + strcmp(tok, BE_CONTAINER_DS_NAME) != 0) + return (NULL); + + /* Return the remaining token if one exists */ + if ((tok = strtok(NULL, "")) == NULL) + return (NULL); + + if ((name = strdup(tok)) == NULL) { + be_print_err(gettext("be_make_name_from_ds: " + "memory allocation failed\n")); + return (NULL); + } } return (name); @@ -393,7 +446,7 @@ * track of that BE's menu entry. We will then use the lines from * that entry to create the entry for the new BE. */ - if ((ret = be_open_menu(be_root_pool, pool_mntpnt, menu_file, + if ((ret = be_open_menu(be_root_pool, menu_file, &menu_fp, "r", B_TRUE)) != BE_SUCCESS) { goto cleanup; } else if (menu_fp == NULL) { @@ -682,7 +735,7 @@ (void) strlcat(menu, BE_SPARC_MENU, sizeof (menu)); /* Get handle to boot menu file */ - if ((ret = be_open_menu(be_root_pool, pool_mntpnt, menu, &menu_fp, "r", + if ((ret = be_open_menu(be_root_pool, menu, &menu_fp, "r", B_TRUE)) != BE_SUCCESS) { goto cleanup; } else if (menu_fp == NULL) { @@ -1122,7 +1175,7 @@ (void) snprintf(grub_file, MAXPATHLEN, "%s%s", pool_mntpnt, BE_GRUB_MENU); - if ((ret = be_open_menu((char *)be_root_pool, pool_mntpnt, grub_file, + if ((ret = be_open_menu((char *)be_root_pool, grub_file, &menu_fp, "r", B_FALSE)) != BE_SUCCESS) { goto cleanup; } else if (menu_fp == NULL) { @@ -1283,7 +1336,7 @@ (void) snprintf(grub_file, MAXPATHLEN, "%s%s", pool_mntpnt, BE_GRUB_MENU); - if ((ret = be_open_menu(be_root_pool, pool_mntpnt, grub_file, + if ((ret = be_open_menu(be_root_pool, grub_file, &grub_fp, "r+", B_TRUE)) != BE_SUCCESS) { goto cleanup; } else if (grub_fp == NULL) { @@ -1521,7 +1574,7 @@ be_make_root_ds(be_root_pool, be_new_name, be_new_root_ds, sizeof (be_new_root_ds)); - if ((ret = be_open_menu(be_root_pool, pool_mntpnt, menu_file, + if ((ret = be_open_menu(be_root_pool, menu_file, &menu_fp, "r", B_TRUE)) != BE_SUCCESS) { goto cleanup; } else if (menu_fp == NULL) { @@ -1787,7 +1840,7 @@ rpool_mntpnt, BE_SPARC_MENU); } - if (be_open_menu(be_root_pool, rpool_mntpnt, menu_file, &menu_fp, "r", + if (be_open_menu(be_root_pool, menu_file, &menu_fp, "r", B_FALSE) != 0) { ret = B_FALSE; goto cleanup; @@ -2098,10 +2151,13 @@ be_valid_be_name(const char *be_name) { const char *c = NULL; + struct be_defaults be_defaults; if (be_name == NULL) return (B_FALSE); + be_get_defaults(&be_defaults); + /* * A BE name must not be a multi-level dataset name. We also check * that it does not contain the ' ' and '%' characters. The ' ' is @@ -2124,6 +2180,11 @@ strlen(be_name) > BE_NAME_MAX_LEN) return (B_FALSE); + if (be_defaults.be_deflt_bename_starts_with[0] != '\0' && + strstr(be_name, be_defaults.be_deflt_bename_starts_with) == NULL) { + return (B_FALSE); + } + return (B_TRUE); } @@ -2469,6 +2530,7 @@ ZFS_CLOSE(zhp); return (0); } + if ((bt->obe_name = strdup(basename(bt->obe_root_ds))) == NULL) { be_print_err(gettext( @@ -3506,7 +3568,6 @@ * lines are added to the file. * Parameters: * pool - The name of the pool the menu.lst file is on - * pool_mntpt - The mountpoint for the pool we're using. * menu_file - The name of the file we're creating. * menu_fp - A pointer to the file pointer of the file we * created. This is also used to pass back the file @@ -3522,7 +3583,6 @@ static int be_create_menu( char *pool, - char *pool_mntpt, char *menu_file, FILE **menu_fp, char *mode) @@ -3653,9 +3713,6 @@ * exist it is simply opened using the mode passed in. * Parameters: * pool - The name of the pool the menu.lst file is on - * pool_mntpt - The mountpoint for the pool we're using. - * The mountpoint is used since the mountpoint - * name can differ from the pool name. * menu_file - The name of the file we're opening. * menu_fp - A pointer to the file pointer of the file we're * opening. This is also used to pass back the file @@ -3675,7 +3732,6 @@ static int be_open_menu( char *pool, - char *pool_mntpt, char *menu_file, FILE **menu_fp, char *mode, @@ -3700,7 +3756,7 @@ if (set_print) do_print = B_FALSE; err = 0; - if ((err = be_create_menu(pool, pool_mntpt, menu_file, + if ((err = be_create_menu(pool, menu_file, menu_fp, mode)) == ENOENT) return (BE_ERR_NO_MENU); else if (err != BE_SUCCESS) diff -r ab46f88a2660 -r 70ccb19abd77 usr/src/lib/libbe/common/libbe_priv.h --- a/usr/src/lib/libbe/common/libbe_priv.h Tue Apr 05 09:31:14 2011 -0700 +++ b/usr/src/lib/libbe/common/libbe_priv.h Wed Apr 06 07:45:22 2011 -0700 @@ -41,6 +41,8 @@ #define ARCH_LENGTH MAXNAMELEN #define BE_AUTO_NAME_MAX_TRY 3 #define BE_AUTO_NAME_DELIM '-' +#define BE_DEFAULTS "/etc/default/be" +#define BE_DFLT_BENAME_STARTS "BENAME_STARTS_WITH=" #define BE_CONTAINER_DS_NAME "ROOT" #define BE_DEFAULT_CONSOLE "text" #define BE_POLICY_PROPERTY "org.opensolaris.libbe:policy" @@ -129,6 +131,11 @@ struct be_plcy_list *be_next_plcy; }be_plcy_list_t; +struct be_defaults { + boolean_t be_deflt_rpool_container; + char be_deflt_bename_starts_with[ZFS_MAXNAMELEN]; +}; + /* Library globals */ extern libzfs_handle_t *g_zfs; extern boolean_t do_print; @@ -211,6 +218,9 @@ int be_zfs_find_current_be_callback(zfs_handle_t *, void *); int be_check_be_roots_callback(zpool_handle_t *, void *); +/* defaults */ +void be_get_defaults(struct be_defaults *defaults); + #ifdef __cplusplus } #endif diff -r ab46f88a2660 -r 70ccb19abd77 usr/src/man/man1m/beadm.1m --- a/usr/src/man/man1m/beadm.1m Tue Apr 05 09:31:14 2011 -0700 +++ b/usr/src/man/man1m/beadm.1m Wed Apr 06 07:45:22 2011 -0700 @@ -1,4 +1,5 @@ '\" te +.\" Copyright 2011 Nexenta Systems, Inc. All rights reserved. .TH beadm 1M "26 Feb 2011" "SunOS 5.11" "System Administration Commands" .SH NAME beadm \- utility for managing zfs boot environments @@ -406,6 +407,13 @@ Makes beName the active BE on next reboot. .RE +.SH ALTERNATE BE LOCATION +.LP +The alternate BE location outside rpool/ROOT can be configured +by modifying the BENAME_STARTS_WITH parameter in /etc/default/be. +For example: BENAME_STARTS_WITH=rootfs +.RE + .SH EXAMPLES .LP \fBExample 1\fR: Create a new BE named BE1, by cloning the current live BE. @@ -685,6 +693,20 @@ .sp .RE .RE +.sp +.LP +.sp +.ne 2 +.mk +.na +\fB/etc/default/be\fR +.ad +.sp .6 +.RS 4n +Contains default value for BENAME_STARTS_WITH parameter +.sp +.RE +.RE .SH ATTRIBUTES .sp