10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1623Stw21770 * Common Development and Distribution License (the "License"). 6*1623Stw21770 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*1623Stw21770 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 270Sstevel@tonic-gate 280Sstevel@tonic-gate /* 290Sstevel@tonic-gate * Just in case we're not in a build environment, make sure that 300Sstevel@tonic-gate * TEXT_DOMAIN gets set to something. 310Sstevel@tonic-gate */ 320Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 330Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 340Sstevel@tonic-gate #endif 350Sstevel@tonic-gate 360Sstevel@tonic-gate /* 370Sstevel@tonic-gate * change the identity of a metadevice 380Sstevel@tonic-gate * These are the "do it" functions for the metarename command. 390Sstevel@tonic-gate */ 400Sstevel@tonic-gate 410Sstevel@tonic-gate #include <string.h> 420Sstevel@tonic-gate #include <meta.h> 430Sstevel@tonic-gate #include <sys/lvm/md_rename.h> 440Sstevel@tonic-gate 450Sstevel@tonic-gate /* private */ 460Sstevel@tonic-gate #define FORCE (0x00000001) 470Sstevel@tonic-gate #define NOISY (0x00000010) 480Sstevel@tonic-gate #define NOFLIP (0x00000020) 490Sstevel@tonic-gate #define DRYRUN (0x00000040) 500Sstevel@tonic-gate 510Sstevel@tonic-gate #define OP_STR(op) \ 520Sstevel@tonic-gate ((op) == MDRNOP_EXCHANGE? "exchange": \ 530Sstevel@tonic-gate (op) == MDRNOP_RENAME? "rename": \ 540Sstevel@tonic-gate (op) == MDRNOP_UNK? "<unknown>": "garbage") 550Sstevel@tonic-gate 560Sstevel@tonic-gate 570Sstevel@tonic-gate /* 580Sstevel@tonic-gate * Check if from_np is open 590Sstevel@tonic-gate * Return 0 if not open, -1 if open 600Sstevel@tonic-gate */ 610Sstevel@tonic-gate static int 620Sstevel@tonic-gate check_open( 630Sstevel@tonic-gate mdsetname_t *sp, 640Sstevel@tonic-gate mdname_t *from_np, 650Sstevel@tonic-gate md_error_t *ep) 660Sstevel@tonic-gate { 670Sstevel@tonic-gate int rc; 680Sstevel@tonic-gate 690Sstevel@tonic-gate if ((rc = meta_isopen(sp, from_np, ep, (mdcmdopts_t)0)) < 0) { 700Sstevel@tonic-gate assert(!mdisok(ep)); 710Sstevel@tonic-gate return (-1); 720Sstevel@tonic-gate 730Sstevel@tonic-gate } else if (rc > 0) { 740Sstevel@tonic-gate if (mdisok(ep)) { 750Sstevel@tonic-gate (void) mdmderror(ep, MDE_RENAME_BUSY, 760Sstevel@tonic-gate meta_getminor(from_np->dev), 770Sstevel@tonic-gate from_np->cname); 780Sstevel@tonic-gate } 790Sstevel@tonic-gate return (-1); 800Sstevel@tonic-gate } 810Sstevel@tonic-gate return (0); 820Sstevel@tonic-gate } 830Sstevel@tonic-gate 840Sstevel@tonic-gate /* 850Sstevel@tonic-gate * meta_swap is the common code used by the 860Sstevel@tonic-gate * meta_rename() and meta_exchange() entry points 870Sstevel@tonic-gate */ 880Sstevel@tonic-gate 890Sstevel@tonic-gate static int 900Sstevel@tonic-gate meta_swap( 910Sstevel@tonic-gate mdsetname_t *sp, 920Sstevel@tonic-gate mdname_t *from_np, 93253Sstevep md_common_t *from_mdp, 940Sstevel@tonic-gate mdname_t *to_np, 95253Sstevep md_common_t *to_mdp, 960Sstevel@tonic-gate md_renop_t op, 970Sstevel@tonic-gate int flags, 980Sstevel@tonic-gate md_error_t *ep) 990Sstevel@tonic-gate { 1000Sstevel@tonic-gate md_rename_t txn; 101253Sstevep int from_add_flag = 0; 102253Sstevep int to_add_flag = 0; 103*1623Stw21770 int from_is_fn, to_is_fn; 104*1623Stw21770 bool_t from_has_parent, to_has_parent; 105*1623Stw21770 106*1623Stw21770 /* 107*1623Stw21770 * What types of devices we have here? 108*1623Stw21770 * For MDRNOP_RENAME to_mdp is NULL 109*1623Stw21770 */ 110*1623Stw21770 from_is_fn = (from_mdp->revision & MD_FN_META_DEV); 111*1623Stw21770 from_has_parent = MD_HAS_PARENT(from_mdp->parent); 112*1623Stw21770 if (to_mdp) { 113*1623Stw21770 to_is_fn = (to_mdp->revision & MD_FN_META_DEV); 114*1623Stw21770 to_has_parent = MD_HAS_PARENT(to_mdp->parent); 115*1623Stw21770 } 1160Sstevel@tonic-gate 1170Sstevel@tonic-gate /* 1180Sstevel@tonic-gate * If the device exists a key may already exist so need to find it 1190Sstevel@tonic-gate * otherwise we'll end up adding the key in again which will lead 1200Sstevel@tonic-gate * to an inconsistent n_count for the namespace record. 1210Sstevel@tonic-gate */ 1220Sstevel@tonic-gate if (from_np->dev != NODEV) { 1230Sstevel@tonic-gate (void) meta_getnmentbydev(sp->setno, MD_SIDEWILD, from_np->dev, 1240Sstevel@tonic-gate NULL, NULL, &from_np->key, ep); 1250Sstevel@tonic-gate } 1260Sstevel@tonic-gate 127253Sstevep if (to_np->dev != NODEV) { 128253Sstevep (void) meta_getnmentbydev(sp->setno, MD_SIDEWILD, to_np->dev, 129253Sstevep NULL, NULL, &to_np->key, ep); 130253Sstevep } 131253Sstevep 1320Sstevel@tonic-gate if ((from_np->key == MD_KEYWILD) || (from_np->key == MD_KEYBAD)) { 133253Sstevep /* 134*1623Stw21770 * If we are top and revision indicates that we 135*1623Stw21770 * should have key but we don't then something 136*1623Stw21770 * really goes wrong 137253Sstevep */ 138*1623Stw21770 assert(!from_has_parent && !from_is_fn); 139*1623Stw21770 140*1623Stw21770 if (from_has_parent || from_is_fn) { 141*1623Stw21770 return (-1); 142*1623Stw21770 } 143253Sstevep 144253Sstevep /* 145*1623Stw21770 * So only add the entry if necessary 146253Sstevep */ 1470Sstevel@tonic-gate if (add_key_name(sp, from_np, NULL, ep) != 0) { 1480Sstevel@tonic-gate assert(!mdisok(ep)); 1490Sstevel@tonic-gate return (-1); 150253Sstevep } else { 151253Sstevep from_add_flag = 1; 1520Sstevel@tonic-gate } 1530Sstevel@tonic-gate } 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate (void) memset(&txn, 0, sizeof (txn)); 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate txn.op = op; 1580Sstevel@tonic-gate txn.revision = MD_RENAME_VERSION; 1590Sstevel@tonic-gate txn.flags = 0; 1600Sstevel@tonic-gate txn.from.mnum = meta_getminor(from_np->dev); 1610Sstevel@tonic-gate txn.from.key = from_np->key; 1620Sstevel@tonic-gate 163253Sstevep if ((to_np->key == MD_KEYWILD) || (to_np->key == MD_KEYBAD)) { 164253Sstevep /* 165*1623Stw21770 * If we are top and revision indicates that we 166*1623Stw21770 * should have key but we don't then something 167*1623Stw21770 * really goes wrong 168253Sstevep */ 169*1623Stw21770 assert(!to_has_parent && !to_is_fn); 170*1623Stw21770 171*1623Stw21770 if (to_has_parent || to_is_fn) { 172*1623Stw21770 return (-1); 173*1623Stw21770 } 1740Sstevel@tonic-gate 175253Sstevep /* 176*1623Stw21770 * So only add the entry if necessary 177253Sstevep */ 1780Sstevel@tonic-gate if (add_key_name(sp, to_np, NULL, ep) != 0) { 1790Sstevel@tonic-gate assert(!mdisok(ep)); 180253Sstevep if (from_add_flag) 181253Sstevep (void) del_key_name(sp, from_np, ep); 1820Sstevel@tonic-gate return (-1); 183253Sstevep } else { 184253Sstevep to_add_flag = 1; 1850Sstevel@tonic-gate } 1860Sstevel@tonic-gate } 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate txn.to.mnum = meta_getminor(to_np->dev); 1890Sstevel@tonic-gate txn.to.key = to_np->key; 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate if (flags & NOISY) { 1920Sstevel@tonic-gate (void) fprintf(stderr, "\top: %s\n", OP_STR(txn.op)); 1930Sstevel@tonic-gate (void) fprintf(stderr, "\trevision: %d, flags: %d\n", 1940Sstevel@tonic-gate txn.revision, txn.flags); 1950Sstevel@tonic-gate (void) fprintf(stderr, 1960Sstevel@tonic-gate "\tfrom(mnum,key): %ld, %d\tto: %ld, %d\n", 1970Sstevel@tonic-gate txn.from.mnum, txn.from.key, 1980Sstevel@tonic-gate txn.to.mnum, txn.to.key); 1990Sstevel@tonic-gate } 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate mdclrerror(ep); 2020Sstevel@tonic-gate if (metaioctl(MD_IOCRENAME, &txn, &txn.mde, from_np->cname) != 0) { 203253Sstevep if (from_add_flag) { 204253Sstevep (void) del_key_name(sp, from_np, ep); 205*1623Stw21770 /* 206*1623Stw21770 * Attempt removal of device node 207*1623Stw21770 */ 208*1623Stw21770 (void) metaioctl(MD_IOCREM_DEV, &txn.from.mnum, 209*1623Stw21770 ep, NULL); 210253Sstevep } 211253Sstevep 212253Sstevep if (op == MDRNOP_RENAME || to_add_flag) { 213253Sstevep (void) del_key_name(sp, to_np, ep); 214*1623Stw21770 /* 215*1623Stw21770 * Attempt removal of device node 216*1623Stw21770 */ 217*1623Stw21770 (void) metaioctl(MD_IOCREM_DEV, &txn.to.mnum, 218*1623Stw21770 ep, NULL); 219253Sstevep } 220*1623Stw21770 221253Sstevep return (mdstealerror(ep, &txn.mde)); 222253Sstevep } 223253Sstevep 224253Sstevep /* 225*1623Stw21770 * Since now the metadevice can be ref'd in the namespace 226*1623Stw21770 * by self and by the top device so upon the successful 227*1623Stw21770 * rename/xchange, we need to check the type and make 228*1623Stw21770 * necessary adjustment for the device's n_cnt in the namespace 229*1623Stw21770 * by calling add_key_name/del_key_name to do the tricks 230253Sstevep */ 231*1623Stw21770 if (op == MDRNOP_RENAME && from_has_parent) { 232*1623Stw21770 (void) add_key_name(sp, to_np, NULL, ep); 233*1623Stw21770 if (from_is_fn) 234*1623Stw21770 (void) del_key_name(sp, from_np, ep); 235*1623Stw21770 (void) del_self_name(sp, from_np->key, ep); 236*1623Stw21770 } 237*1623Stw21770 238*1623Stw21770 if (op == MDRNOP_EXCHANGE && from_is_fn) { 239*1623Stw21770 (void) add_key_name(sp, from_np, NULL, ep); 2400Sstevel@tonic-gate } 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate /* force the name cache to re-read device state */ 2430Sstevel@tonic-gate meta_invalidate_name(from_np); 2440Sstevel@tonic-gate meta_invalidate_name(to_np); 2450Sstevel@tonic-gate 2460Sstevel@tonic-gate return (0); 2470Sstevel@tonic-gate } 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate /* 2500Sstevel@tonic-gate * rename a metadevice 2510Sstevel@tonic-gate */ 2520Sstevel@tonic-gate int 2530Sstevel@tonic-gate meta_rename( 2540Sstevel@tonic-gate mdsetname_t *sp, 2550Sstevel@tonic-gate mdname_t *from_np, 2560Sstevel@tonic-gate mdname_t *to_np, 2570Sstevel@tonic-gate mdcmdopts_t options, 2580Sstevel@tonic-gate md_error_t *ep 2590Sstevel@tonic-gate ) 2600Sstevel@tonic-gate { 2610Sstevel@tonic-gate int flags = (options & MDCMD_FORCE)? FORCE: 0; 2620Sstevel@tonic-gate int rc = 0; 2630Sstevel@tonic-gate char *p; 264253Sstevep md_common_t *from_mdp; 265*1623Stw21770 minor_t to_minor = meta_getminor(to_np->dev); 266*1623Stw21770 md_error_t status = mdnullerror; 267*1623Stw21770 md_error_t *t_ep = &status; 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate /* must have a set */ 2700Sstevel@tonic-gate assert(sp != NULL); 2710Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(from_np->dev))); 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate mdclrerror(ep); 2740Sstevel@tonic-gate 2750Sstevel@tonic-gate if (((p = getenv("MD_DEBUG")) != NULL) && 2760Sstevel@tonic-gate (strstr(p, "RENAME") != NULL)) { 2770Sstevel@tonic-gate flags |= NOISY; 2780Sstevel@tonic-gate } 2790Sstevel@tonic-gate /* if DOIT is not set, we are in dryrun mode */ 2800Sstevel@tonic-gate if ((options & MDCMD_DOIT) == 0) { 2810Sstevel@tonic-gate flags |= DRYRUN; 2820Sstevel@tonic-gate } 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate if (metachkmeta(from_np, ep) != 0) { 2860Sstevel@tonic-gate assert(!mdisok(ep)); 2870Sstevel@tonic-gate return (-1); 2880Sstevel@tonic-gate } 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate mdclrerror(ep); 2910Sstevel@tonic-gate 292253Sstevep if ((from_mdp = meta_get_unit(sp, from_np, ep)) == NULL) { 2930Sstevel@tonic-gate assert(!mdisok(ep)); 2940Sstevel@tonic-gate return (-1); 2950Sstevel@tonic-gate } 2960Sstevel@tonic-gate 297253Sstevep if (meta_get_unit(sp, to_np, ep) != NULL) { 2980Sstevel@tonic-gate if (mdisok(ep)) { 2990Sstevel@tonic-gate (void) mdmderror(ep, MDE_UNIT_ALREADY_SETUP, 3000Sstevel@tonic-gate meta_getminor(to_np->dev), 3010Sstevel@tonic-gate to_np->cname); 3020Sstevel@tonic-gate } 3030Sstevel@tonic-gate return (-1); 3040Sstevel@tonic-gate } 3050Sstevel@tonic-gate mdclrerror(ep); 3060Sstevel@tonic-gate 307*1623Stw21770 /* 308*1623Stw21770 * The dest device name has been added early on 309*1623Stw21770 * by meta_init_make_device call so get the entry from 310*1623Stw21770 * the namespace 311*1623Stw21770 */ 312*1623Stw21770 if (meta_getnmentbydev(sp->setno, MD_SIDEWILD, to_np->dev, 313*1623Stw21770 NULL, NULL, &to_np->key, ep) == NULL) { 314*1623Stw21770 return (-1); 315*1623Stw21770 } 316*1623Stw21770 3170Sstevel@tonic-gate /* If FORCE is not set, check if metadevice is open */ 3180Sstevel@tonic-gate if (!(flags & FORCE)) { 319*1623Stw21770 if (check_open(sp, from_np, ep) != 0) { 320*1623Stw21770 (void) del_key_name(sp, to_np, t_ep); 321*1623Stw21770 (void) metaioctl(MD_IOCREM_DEV, &to_minor, t_ep, NULL); 322*1623Stw21770 return (-1); 323*1623Stw21770 } 3240Sstevel@tonic-gate } 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate /* 3270Sstevel@tonic-gate * All checks are done, now we do the real work. 328*1623Stw21770 * If we are in dryrun mode, clear the deivce node 329*1623Stw21770 * and we are done. 3300Sstevel@tonic-gate */ 3310Sstevel@tonic-gate if (flags & DRYRUN) { 332*1623Stw21770 (void) del_key_name(sp, to_np, t_ep); 333*1623Stw21770 (void) metaioctl(MD_IOCREM_DEV, &to_minor, t_ep, NULL); 3340Sstevel@tonic-gate return (0); /* success */ 3350Sstevel@tonic-gate } 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate if (to_np->key == MD_KEYBAD || to_np->key == MD_KEYWILD) { 3380Sstevel@tonic-gate assert(!mdisok(ep)); 3390Sstevel@tonic-gate return (-1); 3400Sstevel@tonic-gate } 3410Sstevel@tonic-gate 342253Sstevep rc = meta_swap(sp, from_np, from_mdp, to_np, NULL, MDRNOP_RENAME, 343253Sstevep flags, ep); 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate if (rc == 0) { 3460Sstevel@tonic-gate if (options & MDCMD_PRINT) { 3470Sstevel@tonic-gate (void) fprintf(stdout, dgettext(TEXT_DOMAIN, 3480Sstevel@tonic-gate "%s: has been renamed to %s\n"), 3490Sstevel@tonic-gate from_np->cname, to_np->cname); 3500Sstevel@tonic-gate } 3510Sstevel@tonic-gate } 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate return (rc); 3540Sstevel@tonic-gate } 3550Sstevel@tonic-gate 3560Sstevel@tonic-gate /* 3570Sstevel@tonic-gate * return TRUE if current <from>, <to> ordering would 3580Sstevel@tonic-gate * prevent <from> from being in the role of <self> 3590Sstevel@tonic-gate */ 3600Sstevel@tonic-gate static bool_t 3610Sstevel@tonic-gate meta_exchange_need_to_flip( 3620Sstevel@tonic-gate md_common_t *from_mdp, 3630Sstevel@tonic-gate md_common_t *to_mdp 3640Sstevel@tonic-gate ) 3650Sstevel@tonic-gate { 3660Sstevel@tonic-gate assert(from_mdp); 3670Sstevel@tonic-gate assert(to_mdp); 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate /* 3700Sstevel@tonic-gate * ? 3710Sstevel@tonic-gate * \ 3720Sstevel@tonic-gate * <to> 3730Sstevel@tonic-gate * \ 3740Sstevel@tonic-gate * <from> 3750Sstevel@tonic-gate */ 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate if (MD_HAS_PARENT(from_mdp->parent)) { 3780Sstevel@tonic-gate if (MD_HAS_PARENT(to_mdp->parent)) { 3790Sstevel@tonic-gate if (from_mdp->parent == 3800Sstevel@tonic-gate meta_getminor(to_mdp->namep->dev)) { 3810Sstevel@tonic-gate return (TRUE); 3820Sstevel@tonic-gate } 3830Sstevel@tonic-gate } 3840Sstevel@tonic-gate } 3850Sstevel@tonic-gate 3860Sstevel@tonic-gate /* 3870Sstevel@tonic-gate * <from> 3880Sstevel@tonic-gate * \ 3890Sstevel@tonic-gate * <to> 3900Sstevel@tonic-gate * \ 3910Sstevel@tonic-gate * ? 3920Sstevel@tonic-gate */ 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate if (MD_HAS_PARENT(to_mdp->parent)) { 3950Sstevel@tonic-gate if (to_mdp->capabilities & MD_CAN_META_CHILD) { 3960Sstevel@tonic-gate return (TRUE); 3970Sstevel@tonic-gate } 3980Sstevel@tonic-gate } 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate /* 4010Sstevel@tonic-gate * <to> 4020Sstevel@tonic-gate * \ 4030Sstevel@tonic-gate * <from> 4040Sstevel@tonic-gate */ 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate if (MD_HAS_PARENT(from_mdp->parent)) { 4070Sstevel@tonic-gate if (from_mdp->parent == meta_getminor(to_mdp->namep->dev)) { 4080Sstevel@tonic-gate if (!(from_mdp->capabilities & MD_CAN_META_CHILD)) { 4090Sstevel@tonic-gate return (TRUE); 4100Sstevel@tonic-gate } 4110Sstevel@tonic-gate } 4120Sstevel@tonic-gate } 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate /* 4150Sstevel@tonic-gate * <from> or <to> 4160Sstevel@tonic-gate * \ \ 4170Sstevel@tonic-gate * <to> <from> 4180Sstevel@tonic-gate * \ 4190Sstevel@tonic-gate * ? 4200Sstevel@tonic-gate */ 4210Sstevel@tonic-gate 4220Sstevel@tonic-gate return (FALSE); 4230Sstevel@tonic-gate } 4240Sstevel@tonic-gate 4250Sstevel@tonic-gate /* 4260Sstevel@tonic-gate * exchange the names of two metadevices 4270Sstevel@tonic-gate */ 4280Sstevel@tonic-gate int 4290Sstevel@tonic-gate meta_exchange( 4300Sstevel@tonic-gate mdsetname_t *sp, 4310Sstevel@tonic-gate mdname_t *from_np, 4320Sstevel@tonic-gate mdname_t *to_np, 4330Sstevel@tonic-gate mdcmdopts_t options, 4340Sstevel@tonic-gate md_error_t *ep 4350Sstevel@tonic-gate ) 4360Sstevel@tonic-gate { 4370Sstevel@tonic-gate int flags = (options & MDCMD_FORCE)? FORCE: 0; 4380Sstevel@tonic-gate md_common_t *from_mdp, *to_mdp; 4390Sstevel@tonic-gate int rc; 4400Sstevel@tonic-gate char *p, *p2; 4410Sstevel@tonic-gate 4420Sstevel@tonic-gate /* must have a set */ 4430Sstevel@tonic-gate assert(sp != NULL); 4440Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(from_np->dev))); 4450Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(to_np->dev))); 4460Sstevel@tonic-gate 4470Sstevel@tonic-gate if (metachkmeta(from_np, ep) != 0) { 4480Sstevel@tonic-gate assert(!mdisok(ep)); 4490Sstevel@tonic-gate return (-1); 4500Sstevel@tonic-gate } 4510Sstevel@tonic-gate 4520Sstevel@tonic-gate if (metachkmeta(to_np, ep) != 0) { 4530Sstevel@tonic-gate assert(!mdisok(ep)); 4540Sstevel@tonic-gate return (-1); 4550Sstevel@tonic-gate } 4560Sstevel@tonic-gate 4570Sstevel@tonic-gate if ((options & MDCMD_DOIT) == 0) { 4580Sstevel@tonic-gate flags |= DRYRUN; 4590Sstevel@tonic-gate } 4600Sstevel@tonic-gate 4610Sstevel@tonic-gate if ((p = getenv("MD_DEBUG")) != NULL) { 4620Sstevel@tonic-gate if ((p2 = strstr(p, "EXCHANGE=")) != NULL) { 4630Sstevel@tonic-gate flags |= NOISY; 4640Sstevel@tonic-gate if ((p2 = strchr(p2, '=')) != NULL) { 4650Sstevel@tonic-gate if (strcmp((p2+1), "NOFLIP") == 0) { 4660Sstevel@tonic-gate flags |= NOFLIP; 4670Sstevel@tonic-gate } 4680Sstevel@tonic-gate } 4690Sstevel@tonic-gate } else if (strstr(p, "EXCHANGE") != NULL) { 4700Sstevel@tonic-gate flags |= NOISY; 4710Sstevel@tonic-gate } 4720Sstevel@tonic-gate } 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate if ((from_mdp = meta_get_unit(sp, from_np, ep)) == NULL) { 4750Sstevel@tonic-gate assert(!mdisok(ep)); 4760Sstevel@tonic-gate return (-1); 4770Sstevel@tonic-gate } 4780Sstevel@tonic-gate 4790Sstevel@tonic-gate if ((to_mdp = meta_get_unit(sp, to_np, ep)) == NULL) { 4800Sstevel@tonic-gate assert(!mdisok(ep)); 4810Sstevel@tonic-gate return (-1); 4820Sstevel@tonic-gate } 4830Sstevel@tonic-gate assert(mdisok(ep)); 4840Sstevel@tonic-gate 485253Sstevep 4860Sstevel@tonic-gate /* If FORCE is not set, check if metadevice is open */ 4870Sstevel@tonic-gate if (!(flags & FORCE)) { 4880Sstevel@tonic-gate if (check_open(sp, from_np, ep) != 0) { 4890Sstevel@tonic-gate return (-1); 4900Sstevel@tonic-gate } 4910Sstevel@tonic-gate } 4920Sstevel@tonic-gate 4930Sstevel@tonic-gate /* 4940Sstevel@tonic-gate * All checks are done, now we do the real work. 4950Sstevel@tonic-gate * If we are in dryrun mode, we're done. 4960Sstevel@tonic-gate */ 4970Sstevel@tonic-gate if (flags & DRYRUN) { 4980Sstevel@tonic-gate return (0); /* success */ 4990Sstevel@tonic-gate } 5000Sstevel@tonic-gate 5010Sstevel@tonic-gate /* 5020Sstevel@tonic-gate * NOFLIP is used only for debugging; the driver 5030Sstevel@tonic-gate * will catch this and return MDE_RENAME_ORDER, if necessary 5040Sstevel@tonic-gate */ 5050Sstevel@tonic-gate if (((flags & NOFLIP) == 0) && 5060Sstevel@tonic-gate meta_exchange_need_to_flip(from_mdp, to_mdp)) { 507253Sstevep rc = meta_swap(sp, to_np, to_mdp, from_np, from_mdp, 508253Sstevep MDRNOP_EXCHANGE, flags, ep); 5090Sstevel@tonic-gate 5100Sstevel@tonic-gate } else { 511253Sstevep rc = meta_swap(sp, from_np, from_mdp, to_np, to_mdp, 512253Sstevep MDRNOP_EXCHANGE, flags, ep); 5130Sstevel@tonic-gate } 5140Sstevel@tonic-gate 5150Sstevel@tonic-gate if (rc == 0) { 5160Sstevel@tonic-gate if (options & MDCMD_PRINT) { 5170Sstevel@tonic-gate (void) fprintf(stdout, dgettext(TEXT_DOMAIN, 5180Sstevel@tonic-gate "%s and %s have exchanged identities\n"), 5190Sstevel@tonic-gate from_np->cname, to_np->cname); 5200Sstevel@tonic-gate } 5210Sstevel@tonic-gate } 5220Sstevel@tonic-gate 5230Sstevel@tonic-gate return (rc); 5240Sstevel@tonic-gate } 525