1*13013Sglenn.lagasse@oracle.com /* 2*13013Sglenn.lagasse@oracle.com * CDDL HEADER START 3*13013Sglenn.lagasse@oracle.com * 4*13013Sglenn.lagasse@oracle.com * The contents of this file are subject to the terms of the 5*13013Sglenn.lagasse@oracle.com * Common Development and Distribution License (the "License"). 6*13013Sglenn.lagasse@oracle.com * You may not use this file except in compliance with the License. 7*13013Sglenn.lagasse@oracle.com * 8*13013Sglenn.lagasse@oracle.com * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*13013Sglenn.lagasse@oracle.com * or http://www.opensolaris.org/os/licensing. 10*13013Sglenn.lagasse@oracle.com * See the License for the specific language governing permissions 11*13013Sglenn.lagasse@oracle.com * and limitations under the License. 12*13013Sglenn.lagasse@oracle.com * 13*13013Sglenn.lagasse@oracle.com * When distributing Covered Code, include this CDDL HEADER in each 14*13013Sglenn.lagasse@oracle.com * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*13013Sglenn.lagasse@oracle.com * If applicable, add the following below this CDDL HEADER, with the 16*13013Sglenn.lagasse@oracle.com * fields enclosed by brackets "[]" replaced with your own identifying 17*13013Sglenn.lagasse@oracle.com * information: Portions Copyright [yyyy] [name of copyright owner] 18*13013Sglenn.lagasse@oracle.com * 19*13013Sglenn.lagasse@oracle.com * CDDL HEADER END 20*13013Sglenn.lagasse@oracle.com */ 21*13013Sglenn.lagasse@oracle.com 22*13013Sglenn.lagasse@oracle.com /* 23*13013Sglenn.lagasse@oracle.com * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 24*13013Sglenn.lagasse@oracle.com */ 25*13013Sglenn.lagasse@oracle.com 26*13013Sglenn.lagasse@oracle.com #include <assert.h> 27*13013Sglenn.lagasse@oracle.com #include <libintl.h> 28*13013Sglenn.lagasse@oracle.com #include <libnvpair.h> 29*13013Sglenn.lagasse@oracle.com #include <libzfs.h> 30*13013Sglenn.lagasse@oracle.com #include <stdio.h> 31*13013Sglenn.lagasse@oracle.com #include <stdlib.h> 32*13013Sglenn.lagasse@oracle.com #include <string.h> 33*13013Sglenn.lagasse@oracle.com #include <sys/types.h> 34*13013Sglenn.lagasse@oracle.com #include <sys/stat.h> 35*13013Sglenn.lagasse@oracle.com #include <unistd.h> 36*13013Sglenn.lagasse@oracle.com 37*13013Sglenn.lagasse@oracle.com #include <libbe.h> 38*13013Sglenn.lagasse@oracle.com #include <libbe_priv.h> 39*13013Sglenn.lagasse@oracle.com 40*13013Sglenn.lagasse@oracle.com /* ******************************************************************** */ 41*13013Sglenn.lagasse@oracle.com /* Public Functions */ 42*13013Sglenn.lagasse@oracle.com /* ******************************************************************** */ 43*13013Sglenn.lagasse@oracle.com 44*13013Sglenn.lagasse@oracle.com /* 45*13013Sglenn.lagasse@oracle.com * Function: be_rename 46*13013Sglenn.lagasse@oracle.com * Description: Renames the BE from the original name to the new name 47*13013Sglenn.lagasse@oracle.com * passed in through be_attrs. Also the entries in vfstab and 48*13013Sglenn.lagasse@oracle.com * menu.lst are updated with the new name. 49*13013Sglenn.lagasse@oracle.com * Parameters: 50*13013Sglenn.lagasse@oracle.com * be_attrs - pointer to nvlist_t of attributes being passed in. 51*13013Sglenn.lagasse@oracle.com * The following attribute values are used by 52*13013Sglenn.lagasse@oracle.com * this function: 53*13013Sglenn.lagasse@oracle.com * 54*13013Sglenn.lagasse@oracle.com * BE_ATTR_ORIG_BE_NAME *required 55*13013Sglenn.lagasse@oracle.com * BE_ATTR_NEW_BE_NAME *required 56*13013Sglenn.lagasse@oracle.com * Return: 57*13013Sglenn.lagasse@oracle.com * BE_SUCCESS - Success 58*13013Sglenn.lagasse@oracle.com * be_errno_t - Failure 59*13013Sglenn.lagasse@oracle.com * Scope: 60*13013Sglenn.lagasse@oracle.com * Public 61*13013Sglenn.lagasse@oracle.com */ 62*13013Sglenn.lagasse@oracle.com 63*13013Sglenn.lagasse@oracle.com int 64*13013Sglenn.lagasse@oracle.com be_rename(nvlist_t *be_attrs) 65*13013Sglenn.lagasse@oracle.com { 66*13013Sglenn.lagasse@oracle.com be_transaction_data_t bt = { 0 }; 67*13013Sglenn.lagasse@oracle.com be_transaction_data_t cbt = { 0 }; 68*13013Sglenn.lagasse@oracle.com be_fs_list_data_t fld = { 0 }; 69*13013Sglenn.lagasse@oracle.com zfs_handle_t *zhp = NULL; 70*13013Sglenn.lagasse@oracle.com char root_ds[MAXPATHLEN]; 71*13013Sglenn.lagasse@oracle.com char *mp = NULL; 72*13013Sglenn.lagasse@oracle.com int zret = 0, ret = BE_SUCCESS; 73*13013Sglenn.lagasse@oracle.com 74*13013Sglenn.lagasse@oracle.com /* Initialize libzfs handle */ 75*13013Sglenn.lagasse@oracle.com if (!be_zfs_init()) 76*13013Sglenn.lagasse@oracle.com return (BE_ERR_INIT); 77*13013Sglenn.lagasse@oracle.com 78*13013Sglenn.lagasse@oracle.com /* Get original BE name to rename from */ 79*13013Sglenn.lagasse@oracle.com if (nvlist_lookup_string(be_attrs, BE_ATTR_ORIG_BE_NAME, &bt.obe_name) 80*13013Sglenn.lagasse@oracle.com != 0) { 81*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_rename: failed to " 82*13013Sglenn.lagasse@oracle.com "lookup BE_ATTR_ORIG_BE_NAME attribute\n")); 83*13013Sglenn.lagasse@oracle.com be_zfs_fini(); 84*13013Sglenn.lagasse@oracle.com return (BE_ERR_INVAL); 85*13013Sglenn.lagasse@oracle.com } 86*13013Sglenn.lagasse@oracle.com 87*13013Sglenn.lagasse@oracle.com /* Get new BE name to rename to */ 88*13013Sglenn.lagasse@oracle.com if (nvlist_lookup_string(be_attrs, BE_ATTR_NEW_BE_NAME, &bt.nbe_name) 89*13013Sglenn.lagasse@oracle.com != 0) { 90*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_rename: failed to " 91*13013Sglenn.lagasse@oracle.com "lookup BE_ATTR_NEW_BE_NAME attribute\n")); 92*13013Sglenn.lagasse@oracle.com be_zfs_fini(); 93*13013Sglenn.lagasse@oracle.com return (BE_ERR_INVAL); 94*13013Sglenn.lagasse@oracle.com } 95*13013Sglenn.lagasse@oracle.com 96*13013Sglenn.lagasse@oracle.com /* 97*13013Sglenn.lagasse@oracle.com * Get the currently active BE and check to see if this 98*13013Sglenn.lagasse@oracle.com * is an attempt to rename the currently active BE. 99*13013Sglenn.lagasse@oracle.com */ 100*13013Sglenn.lagasse@oracle.com if (be_find_current_be(&cbt) != BE_SUCCESS) { 101*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_rename: failed to find the currently " 102*13013Sglenn.lagasse@oracle.com "active BE\n")); 103*13013Sglenn.lagasse@oracle.com be_zfs_fini(); 104*13013Sglenn.lagasse@oracle.com return (BE_ERR_CURR_BE_NOT_FOUND); 105*13013Sglenn.lagasse@oracle.com } 106*13013Sglenn.lagasse@oracle.com 107*13013Sglenn.lagasse@oracle.com if (strncmp(bt.obe_name, cbt.obe_name, 108*13013Sglenn.lagasse@oracle.com MAX(strlen(bt.obe_name), strlen(cbt.obe_name))) == 0) { 109*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_rename: This is an attempt to rename " 110*13013Sglenn.lagasse@oracle.com "the currently active BE, which is not supported\n")); 111*13013Sglenn.lagasse@oracle.com be_zfs_fini(); 112*13013Sglenn.lagasse@oracle.com free(cbt.obe_name); 113*13013Sglenn.lagasse@oracle.com return (BE_ERR_RENAME_ACTIVE); 114*13013Sglenn.lagasse@oracle.com } 115*13013Sglenn.lagasse@oracle.com 116*13013Sglenn.lagasse@oracle.com /* Validate original BE name */ 117*13013Sglenn.lagasse@oracle.com if (!be_valid_be_name(bt.obe_name)) { 118*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_rename: " 119*13013Sglenn.lagasse@oracle.com "invalid BE name %s\n"), bt.obe_name); 120*13013Sglenn.lagasse@oracle.com be_zfs_fini(); 121*13013Sglenn.lagasse@oracle.com return (BE_ERR_INVAL); 122*13013Sglenn.lagasse@oracle.com } 123*13013Sglenn.lagasse@oracle.com 124*13013Sglenn.lagasse@oracle.com /* Validate new BE name */ 125*13013Sglenn.lagasse@oracle.com if (!be_valid_be_name(bt.nbe_name)) { 126*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_rename: invalid BE name %s\n"), 127*13013Sglenn.lagasse@oracle.com bt.nbe_name); 128*13013Sglenn.lagasse@oracle.com be_zfs_fini(); 129*13013Sglenn.lagasse@oracle.com return (BE_ERR_INVAL); 130*13013Sglenn.lagasse@oracle.com } 131*13013Sglenn.lagasse@oracle.com 132*13013Sglenn.lagasse@oracle.com /* Find which zpool the BE is in */ 133*13013Sglenn.lagasse@oracle.com if ((zret = zpool_iter(g_zfs, be_find_zpool_callback, &bt)) == 0) { 134*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_rename: failed to " 135*13013Sglenn.lagasse@oracle.com "find zpool for BE (%s)\n"), bt.obe_name); 136*13013Sglenn.lagasse@oracle.com be_zfs_fini(); 137*13013Sglenn.lagasse@oracle.com return (BE_ERR_BE_NOENT); 138*13013Sglenn.lagasse@oracle.com } else if (zret < 0) { 139*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_rename: zpool_iter failed: %s\n"), 140*13013Sglenn.lagasse@oracle.com libzfs_error_description(g_zfs)); 141*13013Sglenn.lagasse@oracle.com ret = zfs_err_to_be_err(g_zfs); 142*13013Sglenn.lagasse@oracle.com be_zfs_fini(); 143*13013Sglenn.lagasse@oracle.com return (ret); 144*13013Sglenn.lagasse@oracle.com } 145*13013Sglenn.lagasse@oracle.com 146*13013Sglenn.lagasse@oracle.com /* New BE will reside in the same zpool as orig BE */ 147*13013Sglenn.lagasse@oracle.com bt.nbe_zpool = bt.obe_zpool; 148*13013Sglenn.lagasse@oracle.com 149*13013Sglenn.lagasse@oracle.com be_make_root_ds(bt.obe_zpool, bt.obe_name, root_ds, sizeof (root_ds)); 150*13013Sglenn.lagasse@oracle.com bt.obe_root_ds = strdup(root_ds); 151*13013Sglenn.lagasse@oracle.com be_make_root_ds(bt.nbe_zpool, bt.nbe_name, root_ds, sizeof (root_ds)); 152*13013Sglenn.lagasse@oracle.com bt.nbe_root_ds = strdup(root_ds); 153*13013Sglenn.lagasse@oracle.com 154*13013Sglenn.lagasse@oracle.com /* 155*13013Sglenn.lagasse@oracle.com * Generate a list of file systems from the BE that are legacy 156*13013Sglenn.lagasse@oracle.com * mounted before renaming. We use this list to determine which 157*13013Sglenn.lagasse@oracle.com * entries in the vfstab we need to update after we've renamed the BE. 158*13013Sglenn.lagasse@oracle.com */ 159*13013Sglenn.lagasse@oracle.com if ((ret = be_get_legacy_fs(bt.obe_name, bt.obe_root_ds, NULL, NULL, 160*13013Sglenn.lagasse@oracle.com &fld)) != BE_SUCCESS) { 161*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_rename: failed to " 162*13013Sglenn.lagasse@oracle.com "get legacy mounted file system list for %s\n"), 163*13013Sglenn.lagasse@oracle.com bt.obe_name); 164*13013Sglenn.lagasse@oracle.com goto done; 165*13013Sglenn.lagasse@oracle.com } 166*13013Sglenn.lagasse@oracle.com 167*13013Sglenn.lagasse@oracle.com /* Get handle to BE's root dataset */ 168*13013Sglenn.lagasse@oracle.com if ((zhp = zfs_open(g_zfs, bt.obe_root_ds, ZFS_TYPE_FILESYSTEM)) 169*13013Sglenn.lagasse@oracle.com == NULL) { 170*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_rename: failed to " 171*13013Sglenn.lagasse@oracle.com "open BE root dataset (%s): %s\n"), 172*13013Sglenn.lagasse@oracle.com bt.obe_root_ds, libzfs_error_description(g_zfs)); 173*13013Sglenn.lagasse@oracle.com ret = zfs_err_to_be_err(g_zfs); 174*13013Sglenn.lagasse@oracle.com goto done; 175*13013Sglenn.lagasse@oracle.com } 176*13013Sglenn.lagasse@oracle.com 177*13013Sglenn.lagasse@oracle.com /* Rename of BE's root dataset. */ 178*13013Sglenn.lagasse@oracle.com if (zfs_rename(zhp, bt.nbe_root_ds, B_FALSE) != 0) { 179*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_rename: failed to " 180*13013Sglenn.lagasse@oracle.com "rename dataset (%s): %s\n"), bt.obe_root_ds, 181*13013Sglenn.lagasse@oracle.com libzfs_error_description(g_zfs)); 182*13013Sglenn.lagasse@oracle.com ret = zfs_err_to_be_err(g_zfs); 183*13013Sglenn.lagasse@oracle.com goto done; 184*13013Sglenn.lagasse@oracle.com } 185*13013Sglenn.lagasse@oracle.com 186*13013Sglenn.lagasse@oracle.com /* Refresh handle to BE's root dataset after the rename */ 187*13013Sglenn.lagasse@oracle.com ZFS_CLOSE(zhp); 188*13013Sglenn.lagasse@oracle.com if ((zhp = zfs_open(g_zfs, bt.nbe_root_ds, ZFS_TYPE_FILESYSTEM)) 189*13013Sglenn.lagasse@oracle.com == NULL) { 190*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_rename: failed to " 191*13013Sglenn.lagasse@oracle.com "open BE root dataset (%s): %s\n"), 192*13013Sglenn.lagasse@oracle.com bt.obe_root_ds, libzfs_error_description(g_zfs)); 193*13013Sglenn.lagasse@oracle.com ret = zfs_err_to_be_err(g_zfs); 194*13013Sglenn.lagasse@oracle.com goto done; 195*13013Sglenn.lagasse@oracle.com } 196*13013Sglenn.lagasse@oracle.com 197*13013Sglenn.lagasse@oracle.com /* If BE is already mounted, get its mountpoint */ 198*13013Sglenn.lagasse@oracle.com if (zfs_is_mounted(zhp, &mp) && mp == NULL) { 199*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_rename: failed to " 200*13013Sglenn.lagasse@oracle.com "get altroot of mounted BE %s: %s\n"), 201*13013Sglenn.lagasse@oracle.com bt.nbe_name, libzfs_error_description(g_zfs)); 202*13013Sglenn.lagasse@oracle.com ret = zfs_err_to_be_err(g_zfs); 203*13013Sglenn.lagasse@oracle.com goto done; 204*13013Sglenn.lagasse@oracle.com } 205*13013Sglenn.lagasse@oracle.com 206*13013Sglenn.lagasse@oracle.com /* Update BE's vfstab */ 207*13013Sglenn.lagasse@oracle.com if ((ret = be_update_vfstab(bt.nbe_name, bt.obe_zpool, bt.nbe_zpool, 208*13013Sglenn.lagasse@oracle.com &fld, mp)) != BE_SUCCESS) { 209*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_rename: " 210*13013Sglenn.lagasse@oracle.com "failed to update new BE's vfstab (%s)\n"), bt.nbe_name); 211*13013Sglenn.lagasse@oracle.com goto done; 212*13013Sglenn.lagasse@oracle.com } 213*13013Sglenn.lagasse@oracle.com 214*13013Sglenn.lagasse@oracle.com /* Update this BE's GRUB menu entry */ 215*13013Sglenn.lagasse@oracle.com if (getzoneid() == GLOBAL_ZONEID && (ret = be_update_menu(bt.obe_name, 216*13013Sglenn.lagasse@oracle.com bt.nbe_name, bt.obe_zpool, NULL)) != BE_SUCCESS) { 217*13013Sglenn.lagasse@oracle.com be_print_err(gettext("be_rename: " 218*13013Sglenn.lagasse@oracle.com "failed to update grub menu entry from %s to %s\n"), 219*13013Sglenn.lagasse@oracle.com bt.obe_name, bt.nbe_name); 220*13013Sglenn.lagasse@oracle.com } 221*13013Sglenn.lagasse@oracle.com 222*13013Sglenn.lagasse@oracle.com done: 223*13013Sglenn.lagasse@oracle.com be_free_fs_list(&fld); 224*13013Sglenn.lagasse@oracle.com 225*13013Sglenn.lagasse@oracle.com ZFS_CLOSE(zhp); 226*13013Sglenn.lagasse@oracle.com 227*13013Sglenn.lagasse@oracle.com be_zfs_fini(); 228*13013Sglenn.lagasse@oracle.com 229*13013Sglenn.lagasse@oracle.com free(bt.obe_root_ds); 230*13013Sglenn.lagasse@oracle.com free(bt.nbe_root_ds); 231*13013Sglenn.lagasse@oracle.com return (ret); 232*13013Sglenn.lagasse@oracle.com } 233