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