1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * Just in case we're not in a build environment, make sure that 31*0Sstevel@tonic-gate * TEXT_DOMAIN gets set to something. 32*0Sstevel@tonic-gate */ 33*0Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 34*0Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST" 35*0Sstevel@tonic-gate #endif 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate /* 38*0Sstevel@tonic-gate * trans operations 39*0Sstevel@tonic-gate */ 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate #include <meta.h> 42*0Sstevel@tonic-gate #include <meta_basic.h> 43*0Sstevel@tonic-gate #include <sys/lvm/md_trans.h> 44*0Sstevel@tonic-gate #include <sys/wait.h> 45*0Sstevel@tonic-gate #include <sys/mnttab.h> 46*0Sstevel@tonic-gate #include <stddef.h> 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate extern char *getfullblkname(); 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate /* 51*0Sstevel@tonic-gate * replace trans 52*0Sstevel@tonic-gate */ 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate int 55*0Sstevel@tonic-gate meta_trans_replace(mdsetname_t *sp, mdname_t *transnp, mdname_t *oldnp, 56*0Sstevel@tonic-gate mdname_t *newnp, mdcmdopts_t options, md_error_t *ep) 57*0Sstevel@tonic-gate { 58*0Sstevel@tonic-gate replace_params_t params; 59*0Sstevel@tonic-gate md_dev64_t old_dev, 60*0Sstevel@tonic-gate new_dev; 61*0Sstevel@tonic-gate daddr_t new_start_blk, 62*0Sstevel@tonic-gate new_end_blk; 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate /* should have same set */ 65*0Sstevel@tonic-gate assert(sp != NULL); 66*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(transnp->dev))); 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate new_dev = newnp->dev; 69*0Sstevel@tonic-gate new_start_blk = newnp->start_blk; 70*0Sstevel@tonic-gate new_end_blk = newnp->end_blk; 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate meta_invalidate_name(transnp); 73*0Sstevel@tonic-gate /* the old device binding is now established */ 74*0Sstevel@tonic-gate if ((old_dev = oldnp->dev) == NODEV64) 75*0Sstevel@tonic-gate return (mdsyserror(ep, ENODEV, oldnp->cname)); 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate if (((strcmp(oldnp->rname, newnp->rname) == 0) && 78*0Sstevel@tonic-gate (old_dev != new_dev))) { 79*0Sstevel@tonic-gate newnp->dev = new_dev; 80*0Sstevel@tonic-gate newnp->start_blk = new_start_blk; 81*0Sstevel@tonic-gate newnp->end_blk = new_end_blk; 82*0Sstevel@tonic-gate } 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate if (add_key_name(sp, newnp, NULL, ep) != 0) 85*0Sstevel@tonic-gate return (-1); 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate (void) memset(¶ms, 0, sizeof (params)); 88*0Sstevel@tonic-gate params.mnum = meta_getminor(transnp->dev); 89*0Sstevel@tonic-gate MD_SETDRIVERNAME(¶ms, MD_TRANS, sp->setno); 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate params.cmd = REPLACE_COMP; 92*0Sstevel@tonic-gate params.old_dev = old_dev; 93*0Sstevel@tonic-gate params.new_dev = new_dev; 94*0Sstevel@tonic-gate params.new_key = newnp->key; 95*0Sstevel@tonic-gate if (metaioctl(MD_IOCREPLACE, ¶ms, ¶ms.mde, NULL) != 0) { 96*0Sstevel@tonic-gate (void) del_key_name(sp, newnp, ep); 97*0Sstevel@tonic-gate return (mdstealerror(ep, ¶ms.mde)); 98*0Sstevel@tonic-gate } 99*0Sstevel@tonic-gate meta_invalidate_name(oldnp); 100*0Sstevel@tonic-gate meta_invalidate_name(newnp); 101*0Sstevel@tonic-gate meta_invalidate_name(transnp); 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate if (options & MDCMD_PRINT) { 104*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 105*0Sstevel@tonic-gate "%s: device %s is replaced with %s\n"), 106*0Sstevel@tonic-gate transnp->cname, oldnp->cname, newnp->cname); 107*0Sstevel@tonic-gate } 108*0Sstevel@tonic-gate return (0); 109*0Sstevel@tonic-gate } 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate 113*0Sstevel@tonic-gate /* 114*0Sstevel@tonic-gate * FUNCTION: meta_get_trans_names() 115*0Sstevel@tonic-gate * INPUT: sp - the set name to get trans from 116*0Sstevel@tonic-gate * options - options from the command line 117*0Sstevel@tonic-gate * OUTPUT: nlpp - list of all trans names 118*0Sstevel@tonic-gate * ep - return error pointer 119*0Sstevel@tonic-gate * RETURNS: int - -1 if error, 0 success 120*0Sstevel@tonic-gate * PURPOSE: returns a list of all trans in the metadb 121*0Sstevel@tonic-gate * for all devices in the specified set 122*0Sstevel@tonic-gate */ 123*0Sstevel@tonic-gate int 124*0Sstevel@tonic-gate meta_get_trans_names( 125*0Sstevel@tonic-gate mdsetname_t *sp, 126*0Sstevel@tonic-gate mdnamelist_t **nlpp, 127*0Sstevel@tonic-gate int options, 128*0Sstevel@tonic-gate md_error_t *ep 129*0Sstevel@tonic-gate ) 130*0Sstevel@tonic-gate { 131*0Sstevel@tonic-gate return (meta_get_names(MD_TRANS, sp, nlpp, options, ep)); 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate /* 135*0Sstevel@tonic-gate * free trans unit 136*0Sstevel@tonic-gate */ 137*0Sstevel@tonic-gate void 138*0Sstevel@tonic-gate meta_free_trans( 139*0Sstevel@tonic-gate md_trans_t *transp 140*0Sstevel@tonic-gate ) 141*0Sstevel@tonic-gate { 142*0Sstevel@tonic-gate Free(transp); 143*0Sstevel@tonic-gate } 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate /* 146*0Sstevel@tonic-gate * get trans (common) 147*0Sstevel@tonic-gate */ 148*0Sstevel@tonic-gate md_trans_t * 149*0Sstevel@tonic-gate meta_get_trans_common( 150*0Sstevel@tonic-gate mdsetname_t *sp, 151*0Sstevel@tonic-gate mdname_t *transnp, 152*0Sstevel@tonic-gate int fast, 153*0Sstevel@tonic-gate md_error_t *ep 154*0Sstevel@tonic-gate ) 155*0Sstevel@tonic-gate { 156*0Sstevel@tonic-gate mddrivename_t *dnp = transnp->drivenamep; 157*0Sstevel@tonic-gate char *miscname; 158*0Sstevel@tonic-gate mt_unit_t *mt; 159*0Sstevel@tonic-gate md_trans_t *transp; 160*0Sstevel@tonic-gate int gotlog; 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate /* must have set */ 163*0Sstevel@tonic-gate assert(sp != NULL); 164*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(transnp->dev))); 165*0Sstevel@tonic-gate 166*0Sstevel@tonic-gate /* short circuit */ 167*0Sstevel@tonic-gate if (dnp->unitp != NULL) { 168*0Sstevel@tonic-gate assert(dnp->unitp->type == MD_METATRANS); 169*0Sstevel@tonic-gate return ((md_trans_t *)dnp->unitp); 170*0Sstevel@tonic-gate } 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate /* get miscname and unit */ 173*0Sstevel@tonic-gate if ((miscname = metagetmiscname(transnp, ep)) == NULL) 174*0Sstevel@tonic-gate return (NULL); 175*0Sstevel@tonic-gate if (strcmp(miscname, MD_TRANS) != 0) { 176*0Sstevel@tonic-gate (void) mdmderror(ep, MDE_NOT_MT, 177*0Sstevel@tonic-gate meta_getminor(transnp->dev), transnp->cname); 178*0Sstevel@tonic-gate return (NULL); 179*0Sstevel@tonic-gate } 180*0Sstevel@tonic-gate if ((mt = (mt_unit_t *)meta_get_mdunit(sp, transnp, ep)) == NULL) 181*0Sstevel@tonic-gate return (NULL); 182*0Sstevel@tonic-gate assert(mt->c.un_type == MD_METATRANS); 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate /* allocate trans */ 185*0Sstevel@tonic-gate transp = Zalloc(sizeof (*transp)); 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate /* get common info */ 188*0Sstevel@tonic-gate transp->common.namep = transnp; 189*0Sstevel@tonic-gate transp->common.type = mt->c.un_type; 190*0Sstevel@tonic-gate transp->common.state = mt->c.un_status; 191*0Sstevel@tonic-gate transp->common.capabilities = mt->c.un_capabilities; 192*0Sstevel@tonic-gate transp->common.parent = mt->c.un_parent; 193*0Sstevel@tonic-gate transp->common.size = mt->c.un_total_blocks; 194*0Sstevel@tonic-gate transp->common.user_flags = mt->c.un_user_flags; 195*0Sstevel@tonic-gate transp->common.revision = mt->c.un_revision; 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate /* get master */ 198*0Sstevel@tonic-gate transp->masternamep = metakeyname(&sp, mt->un_m_key, fast, ep); 199*0Sstevel@tonic-gate if (transp->masternamep == NULL) 200*0Sstevel@tonic-gate goto out; 201*0Sstevel@tonic-gate 202*0Sstevel@tonic-gate /* get log */ 203*0Sstevel@tonic-gate gotlog = ((mt->un_flags & TRANS_DETACHED) == 0); 204*0Sstevel@tonic-gate if (gotlog) { 205*0Sstevel@tonic-gate daddr_t sblk; 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate transp->lognamep = metakeyname(&sp, mt->un_l_key, fast, ep); 208*0Sstevel@tonic-gate if (transp->lognamep == NULL) 209*0Sstevel@tonic-gate goto out; 210*0Sstevel@tonic-gate 211*0Sstevel@tonic-gate /* calculate the kernels start block */ 212*0Sstevel@tonic-gate sblk = mt->un_l_pwsblk + mt->un_l_maxtransfer; 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate if (getenv("META_DEBUG_START_BLK") != NULL) { 215*0Sstevel@tonic-gate if (metagetstart(sp, transp->lognamep, ep) == 216*0Sstevel@tonic-gate MD_DISKADDR_ERROR) 217*0Sstevel@tonic-gate mdclrerror(ep); 218*0Sstevel@tonic-gate 219*0Sstevel@tonic-gate if (transp->lognamep->start_blk > sblk) 220*0Sstevel@tonic-gate md_eprintf(dgettext(TEXT_DOMAIN, 221*0Sstevel@tonic-gate "%s: suspected bad start block [trans]\n"), 222*0Sstevel@tonic-gate transp->lognamep->cname); 223*0Sstevel@tonic-gate } 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate /* override any start_blk */ 226*0Sstevel@tonic-gate transp->lognamep->start_blk = sblk; 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate /* get flags, etc. */ 230*0Sstevel@tonic-gate transp->flags = mt->un_flags; 231*0Sstevel@tonic-gate transp->timestamp = mt->un_timestamp; 232*0Sstevel@tonic-gate transp->log_error = mt->un_l_error; 233*0Sstevel@tonic-gate transp->log_timestamp = mt->un_l_timestamp; 234*0Sstevel@tonic-gate transp->log_size = mt->un_l_nblks; 235*0Sstevel@tonic-gate transp->debug = mt->un_debug; 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate /* cleanup, return success */ 238*0Sstevel@tonic-gate Free(mt); 239*0Sstevel@tonic-gate dnp->unitp = (md_common_t *)transp; 240*0Sstevel@tonic-gate return (transp); 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate /* cleanup, return error */ 243*0Sstevel@tonic-gate out: 244*0Sstevel@tonic-gate Free(mt); 245*0Sstevel@tonic-gate meta_free_trans(transp); 246*0Sstevel@tonic-gate return (NULL); 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate /* 250*0Sstevel@tonic-gate * get trans 251*0Sstevel@tonic-gate */ 252*0Sstevel@tonic-gate md_trans_t * 253*0Sstevel@tonic-gate meta_get_trans( 254*0Sstevel@tonic-gate mdsetname_t *sp, 255*0Sstevel@tonic-gate mdname_t *transnp, 256*0Sstevel@tonic-gate md_error_t *ep 257*0Sstevel@tonic-gate ) 258*0Sstevel@tonic-gate { 259*0Sstevel@tonic-gate return (meta_get_trans_common(sp, transnp, 0, ep)); 260*0Sstevel@tonic-gate } 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate /* 263*0Sstevel@tonic-gate * check trans for dev 264*0Sstevel@tonic-gate */ 265*0Sstevel@tonic-gate static int 266*0Sstevel@tonic-gate in_trans( 267*0Sstevel@tonic-gate mdsetname_t *sp, 268*0Sstevel@tonic-gate mdname_t *transnp, 269*0Sstevel@tonic-gate mdname_t *np, 270*0Sstevel@tonic-gate mdchkopts_t options, 271*0Sstevel@tonic-gate diskaddr_t slblk, 272*0Sstevel@tonic-gate diskaddr_t nblks, 273*0Sstevel@tonic-gate md_error_t *ep 274*0Sstevel@tonic-gate ) 275*0Sstevel@tonic-gate { 276*0Sstevel@tonic-gate md_trans_t *transp; 277*0Sstevel@tonic-gate mdname_t *masternp; 278*0Sstevel@tonic-gate mdname_t *lognp; 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate /* should be in the same set */ 281*0Sstevel@tonic-gate assert(sp != NULL); 282*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(transnp->dev))); 283*0Sstevel@tonic-gate 284*0Sstevel@tonic-gate /* get unit */ 285*0Sstevel@tonic-gate if ((transp = meta_get_trans(sp, transnp, ep)) == NULL) 286*0Sstevel@tonic-gate return (-1); 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate /* check master */ 289*0Sstevel@tonic-gate masternp = transp->masternamep; 290*0Sstevel@tonic-gate if ((! metaismeta(masternp)) && 291*0Sstevel@tonic-gate (meta_check_overlap(transnp->cname, np, slblk, nblks, 292*0Sstevel@tonic-gate masternp, 0, -1, ep) != 0)) { 293*0Sstevel@tonic-gate return (-1); 294*0Sstevel@tonic-gate } 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate /* check log */ 297*0Sstevel@tonic-gate if (((lognp = transp->lognamep) != NULL) && 298*0Sstevel@tonic-gate (! (options & MDCHK_ALLOW_LOG)) && 299*0Sstevel@tonic-gate (! metaismeta(lognp))) { 300*0Sstevel@tonic-gate daddr_t log_start; 301*0Sstevel@tonic-gate int err; 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate /* check same drive since metagetstart() can fail */ 304*0Sstevel@tonic-gate if ((err = meta_check_samedrive(np, lognp, ep)) < 0) 305*0Sstevel@tonic-gate return (-1); 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate /* check overlap */ 308*0Sstevel@tonic-gate if (err != 0) { 309*0Sstevel@tonic-gate if ((log_start = metagetstart(sp, lognp, ep)) == 310*0Sstevel@tonic-gate MD_DISKADDR_ERROR) 311*0Sstevel@tonic-gate return (-1); 312*0Sstevel@tonic-gate if (meta_check_overlap(transnp->cname, np, slblk, 313*0Sstevel@tonic-gate nblks, lognp, log_start, -1, ep) != 0) { 314*0Sstevel@tonic-gate return (-1); 315*0Sstevel@tonic-gate } 316*0Sstevel@tonic-gate } 317*0Sstevel@tonic-gate } 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate /* return success */ 320*0Sstevel@tonic-gate return (0); 321*0Sstevel@tonic-gate } 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate /* 324*0Sstevel@tonic-gate * check to see if we're in a trans 325*0Sstevel@tonic-gate */ 326*0Sstevel@tonic-gate int 327*0Sstevel@tonic-gate meta_check_intrans( 328*0Sstevel@tonic-gate mdsetname_t *sp, 329*0Sstevel@tonic-gate mdname_t *np, 330*0Sstevel@tonic-gate mdchkopts_t options, 331*0Sstevel@tonic-gate diskaddr_t slblk, 332*0Sstevel@tonic-gate diskaddr_t nblks, 333*0Sstevel@tonic-gate md_error_t *ep 334*0Sstevel@tonic-gate ) 335*0Sstevel@tonic-gate { 336*0Sstevel@tonic-gate mdnamelist_t *transnlp = NULL; 337*0Sstevel@tonic-gate mdnamelist_t *p; 338*0Sstevel@tonic-gate int rval = 0; 339*0Sstevel@tonic-gate 340*0Sstevel@tonic-gate /* should have a set */ 341*0Sstevel@tonic-gate assert(sp != NULL); 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate /* for each trans */ 344*0Sstevel@tonic-gate if (meta_get_trans_names(sp, &transnlp, 0, ep) < 0) 345*0Sstevel@tonic-gate return (-1); 346*0Sstevel@tonic-gate for (p = transnlp; (p != NULL); p = p->next) { 347*0Sstevel@tonic-gate mdname_t *transnp = p->namep; 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate /* check trans */ 350*0Sstevel@tonic-gate if (in_trans(sp, transnp, np, options, slblk, nblks, ep) != 0) { 351*0Sstevel@tonic-gate rval = -1; 352*0Sstevel@tonic-gate break; 353*0Sstevel@tonic-gate } 354*0Sstevel@tonic-gate } 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate /* cleanup, return success */ 357*0Sstevel@tonic-gate metafreenamelist(transnlp); 358*0Sstevel@tonic-gate return (rval); 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate /* 362*0Sstevel@tonic-gate * check master 363*0Sstevel@tonic-gate */ 364*0Sstevel@tonic-gate int 365*0Sstevel@tonic-gate meta_check_master( 366*0Sstevel@tonic-gate mdsetname_t *sp, 367*0Sstevel@tonic-gate mdname_t *np, 368*0Sstevel@tonic-gate int force, 369*0Sstevel@tonic-gate md_error_t *ep 370*0Sstevel@tonic-gate ) 371*0Sstevel@tonic-gate { 372*0Sstevel@tonic-gate mdchkopts_t options = 0; 373*0Sstevel@tonic-gate md_common_t *mdp; 374*0Sstevel@tonic-gate 375*0Sstevel@tonic-gate /* make sure we have a disk */ 376*0Sstevel@tonic-gate if (metachkdisk(np, ep) != 0) 377*0Sstevel@tonic-gate return (-1); 378*0Sstevel@tonic-gate 379*0Sstevel@tonic-gate /* check to ensure that it is not already in use */ 380*0Sstevel@tonic-gate if ((!force) && meta_check_inuse(sp, np, MDCHK_INUSE, ep) != 0) { 381*0Sstevel@tonic-gate return (-1); 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate /* make sure it is in the set */ 385*0Sstevel@tonic-gate if (meta_check_inset(sp, np, ep) != 0) 386*0Sstevel@tonic-gate return (-1); 387*0Sstevel@tonic-gate 388*0Sstevel@tonic-gate /* make sure its not in a metadevice */ 389*0Sstevel@tonic-gate if (! metaismeta(np)) { /* Non-metadevices */ 390*0Sstevel@tonic-gate if (meta_check_inmeta(sp, np, options, 0, -1, ep) != 0) 391*0Sstevel@tonic-gate return (-1); 392*0Sstevel@tonic-gate } else { /* Metadevices only! */ 393*0Sstevel@tonic-gate if ((mdp = meta_get_unit(sp, np, ep)) == NULL) 394*0Sstevel@tonic-gate return (-1); 395*0Sstevel@tonic-gate 396*0Sstevel@tonic-gate /* 397*0Sstevel@tonic-gate * Since soft partitions may appear at the top or bottom 398*0Sstevel@tonic-gate * of the metadevice stack, we check them separately. 399*0Sstevel@tonic-gate * A trans may be built on top of a soft partition if 400*0Sstevel@tonic-gate * the soft partition has no parent (can't rely on the 401*0Sstevel@tonic-gate * MD_CAN_PARENT flag in this case since a soft partition 402*0Sstevel@tonic-gate * built on a metadevice clears this flag to prevent nested 403*0Sstevel@tonic-gate * configurations). 404*0Sstevel@tonic-gate */ 405*0Sstevel@tonic-gate if ((meta_sp_issp(sp, np, ep) == 0) && 406*0Sstevel@tonic-gate (mdp->parent == MD_NO_PARENT)) 407*0Sstevel@tonic-gate return (0); 408*0Sstevel@tonic-gate 409*0Sstevel@tonic-gate if ((! (mdp->capabilities & MD_CAN_PARENT)) || 410*0Sstevel@tonic-gate (mdp->parent != MD_NO_PARENT)) { 411*0Sstevel@tonic-gate return (mdmderror(ep, MDE_INVAL_UNIT, 412*0Sstevel@tonic-gate meta_getminor(np->dev), np->cname)); 413*0Sstevel@tonic-gate } 414*0Sstevel@tonic-gate } 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate /* return success */ 417*0Sstevel@tonic-gate return (0); 418*0Sstevel@tonic-gate } 419*0Sstevel@tonic-gate 420*0Sstevel@tonic-gate /* 421*0Sstevel@tonic-gate * check log 422*0Sstevel@tonic-gate */ 423*0Sstevel@tonic-gate int 424*0Sstevel@tonic-gate meta_check_log( 425*0Sstevel@tonic-gate mdsetname_t *sp, 426*0Sstevel@tonic-gate mdname_t *np, 427*0Sstevel@tonic-gate md_error_t *ep 428*0Sstevel@tonic-gate ) 429*0Sstevel@tonic-gate { 430*0Sstevel@tonic-gate mdchkopts_t options = (MDCHK_ALLOW_MDDB | MDCHK_ALLOW_LOG); 431*0Sstevel@tonic-gate md_common_t *mdp; 432*0Sstevel@tonic-gate 433*0Sstevel@tonic-gate /* make sure we have a disk */ 434*0Sstevel@tonic-gate if (metachkdisk(np, ep) != 0) 435*0Sstevel@tonic-gate return (-1); 436*0Sstevel@tonic-gate 437*0Sstevel@tonic-gate /* check to ensure that it is not already in use */ 438*0Sstevel@tonic-gate if (meta_check_inuse(sp, np, MDCHK_INUSE, ep) != 0) { 439*0Sstevel@tonic-gate return (-1); 440*0Sstevel@tonic-gate } 441*0Sstevel@tonic-gate 442*0Sstevel@tonic-gate /* make sure it is in the set */ 443*0Sstevel@tonic-gate if (meta_check_inset(sp, np, ep) != 0) 444*0Sstevel@tonic-gate return (-1); 445*0Sstevel@tonic-gate 446*0Sstevel@tonic-gate /* make sure its not in a metadevice */ 447*0Sstevel@tonic-gate if (! metaismeta(np)) { /* Non-metadevices */ 448*0Sstevel@tonic-gate if (meta_check_inmeta(sp, np, options, 0, -1, ep) != 0) 449*0Sstevel@tonic-gate return (-1); 450*0Sstevel@tonic-gate } else { /* Metadevices only! */ 451*0Sstevel@tonic-gate if ((mdp = meta_get_unit(sp, np, ep)) == NULL) 452*0Sstevel@tonic-gate return (-1); 453*0Sstevel@tonic-gate 454*0Sstevel@tonic-gate /* 455*0Sstevel@tonic-gate * Since soft partitions may appear at the top or bottom 456*0Sstevel@tonic-gate * of the metadevice stack, we check them separately. 457*0Sstevel@tonic-gate * A trans may be built on top of a soft partition if 458*0Sstevel@tonic-gate * the soft partition has no parent (can't rely on the 459*0Sstevel@tonic-gate * MD_CAN_PARENT flag in this case since a soft partition 460*0Sstevel@tonic-gate * built on a metadevice clears this flag to prevent nested 461*0Sstevel@tonic-gate * configurations). 462*0Sstevel@tonic-gate * 463*0Sstevel@tonic-gate */ 464*0Sstevel@tonic-gate if ((meta_sp_issp(sp, np, ep) == 0) && 465*0Sstevel@tonic-gate (mdp->parent == MD_NO_PARENT)) 466*0Sstevel@tonic-gate return (0); 467*0Sstevel@tonic-gate 468*0Sstevel@tonic-gate if ((! (mdp->capabilities & MD_CAN_PARENT)) || 469*0Sstevel@tonic-gate ((mdp->parent != MD_NO_PARENT) && 470*0Sstevel@tonic-gate (mdp->parent != MD_MULTI_PARENT))) { 471*0Sstevel@tonic-gate return (mdmderror(ep, MDE_INVAL_UNIT, 472*0Sstevel@tonic-gate meta_getminor(np->dev), np->cname)); 473*0Sstevel@tonic-gate } 474*0Sstevel@tonic-gate } 475*0Sstevel@tonic-gate 476*0Sstevel@tonic-gate /* return success */ 477*0Sstevel@tonic-gate return (0); 478*0Sstevel@tonic-gate } 479*0Sstevel@tonic-gate 480*0Sstevel@tonic-gate /* 481*0Sstevel@tonic-gate * print trans 482*0Sstevel@tonic-gate */ 483*0Sstevel@tonic-gate static int 484*0Sstevel@tonic-gate trans_print( 485*0Sstevel@tonic-gate md_trans_t *transp, 486*0Sstevel@tonic-gate char *fname, 487*0Sstevel@tonic-gate FILE *fp, 488*0Sstevel@tonic-gate md_error_t *ep 489*0Sstevel@tonic-gate ) 490*0Sstevel@tonic-gate { 491*0Sstevel@tonic-gate int rval = -1; 492*0Sstevel@tonic-gate 493*0Sstevel@tonic-gate /* print name and -t */ 494*0Sstevel@tonic-gate if (fprintf(fp, "%s -t", transp->common.namep->cname) == EOF) 495*0Sstevel@tonic-gate goto out; 496*0Sstevel@tonic-gate 497*0Sstevel@tonic-gate /* print master */ 498*0Sstevel@tonic-gate /* 499*0Sstevel@tonic-gate * If the path is our standard /dev/rdsk or /dev/md/rdsk 500*0Sstevel@tonic-gate * then just print out the cxtxdxsx or the dx, metainit 501*0Sstevel@tonic-gate * will assume the default, otherwise we need the full 502*0Sstevel@tonic-gate * pathname to make sure this works as we intend. 503*0Sstevel@tonic-gate */ 504*0Sstevel@tonic-gate if ((strstr(transp->masternamep->rname, "/dev/rdsk") == NULL) && 505*0Sstevel@tonic-gate (strstr(transp->masternamep->rname, "/dev/md/rdsk") == NULL) && 506*0Sstevel@tonic-gate (strstr(transp->masternamep->rname, "/dev/td/") == NULL)) { 507*0Sstevel@tonic-gate /* not standard path, print full pathname */ 508*0Sstevel@tonic-gate if (fprintf(fp, " %s", transp->masternamep->rname) == EOF) 509*0Sstevel@tonic-gate goto out; 510*0Sstevel@tonic-gate } else { 511*0Sstevel@tonic-gate /* standard path, print ctds or d number */ 512*0Sstevel@tonic-gate if (fprintf(fp, " %s", transp->masternamep->cname) == EOF) 513*0Sstevel@tonic-gate goto out; 514*0Sstevel@tonic-gate } 515*0Sstevel@tonic-gate 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate /* print log */ 518*0Sstevel@tonic-gate if (transp->lognamep != NULL) { 519*0Sstevel@tonic-gate /* 520*0Sstevel@tonic-gate * If the path is our standard /dev/rdsk or /dev/md/rdsk 521*0Sstevel@tonic-gate * then just print out the cxtxdxsx or the dx, metainit 522*0Sstevel@tonic-gate * will assume the default, otherwise we need the full 523*0Sstevel@tonic-gate * pathname to make sure this works as we intend. 524*0Sstevel@tonic-gate */ 525*0Sstevel@tonic-gate if ((strstr(transp->lognamep->rname, "/dev/rdsk") == NULL) && 526*0Sstevel@tonic-gate (strstr(transp->lognamep->rname, "/dev/md/rdsk") == NULL) && 527*0Sstevel@tonic-gate (strstr(transp->lognamep->rname, "/dev/td/") == NULL)) { 528*0Sstevel@tonic-gate /* not standard path, print full pathname */ 529*0Sstevel@tonic-gate if (fprintf(fp, " %s", transp->lognamep->rname) == EOF) 530*0Sstevel@tonic-gate goto out; 531*0Sstevel@tonic-gate } else { 532*0Sstevel@tonic-gate /* standard path */ 533*0Sstevel@tonic-gate if (fprintf(fp, " %s", transp->lognamep->cname) == EOF) 534*0Sstevel@tonic-gate goto out; 535*0Sstevel@tonic-gate } 536*0Sstevel@tonic-gate } 537*0Sstevel@tonic-gate 538*0Sstevel@tonic-gate /* print terminating newline */ 539*0Sstevel@tonic-gate if (fprintf(fp, "\n") == EOF) 540*0Sstevel@tonic-gate goto out; 541*0Sstevel@tonic-gate 542*0Sstevel@tonic-gate /* success */ 543*0Sstevel@tonic-gate rval = 0; 544*0Sstevel@tonic-gate 545*0Sstevel@tonic-gate /* cleanup, return error */ 546*0Sstevel@tonic-gate out: 547*0Sstevel@tonic-gate if (rval != 0) 548*0Sstevel@tonic-gate (void) mdsyserror(ep, errno, fname); 549*0Sstevel@tonic-gate return (rval); 550*0Sstevel@tonic-gate } 551*0Sstevel@tonic-gate 552*0Sstevel@tonic-gate /* 553*0Sstevel@tonic-gate * convert flags to repair action 554*0Sstevel@tonic-gate */ 555*0Sstevel@tonic-gate 556*0Sstevel@tonic-gate char * 557*0Sstevel@tonic-gate mt_flags_to_action( 558*0Sstevel@tonic-gate md_trans_t *transp 559*0Sstevel@tonic-gate ) 560*0Sstevel@tonic-gate { 561*0Sstevel@tonic-gate int len; 562*0Sstevel@tonic-gate char *actionp = NULL; 563*0Sstevel@tonic-gate int err = -1; 564*0Sstevel@tonic-gate 565*0Sstevel@tonic-gate if (!transp) { 566*0Sstevel@tonic-gate goto out; 567*0Sstevel@tonic-gate } 568*0Sstevel@tonic-gate 569*0Sstevel@tonic-gate /* 570*0Sstevel@tonic-gate * if in any of these states, the log_error word is not (yet) meaningful 571*0Sstevel@tonic-gate */ 572*0Sstevel@tonic-gate if (transp->flags & (TRANS_DETACHED|TRANS_DETACHING|TRANS_ATTACHING)) { 573*0Sstevel@tonic-gate goto out; 574*0Sstevel@tonic-gate } 575*0Sstevel@tonic-gate 576*0Sstevel@tonic-gate if (transp->log_error & LDL_ANYERROR) { 577*0Sstevel@tonic-gate char *fix_msg = dgettext(TEXT_DOMAIN, 578*0Sstevel@tonic-gate " To Fix: Please refer to the log device's status.\n"); 579*0Sstevel@tonic-gate 580*0Sstevel@tonic-gate if ((len = strlen(fix_msg)) <= 0) { 581*0Sstevel@tonic-gate goto out; 582*0Sstevel@tonic-gate } 583*0Sstevel@tonic-gate if (!(actionp = Zalloc(len+1))) { 584*0Sstevel@tonic-gate goto out; 585*0Sstevel@tonic-gate } 586*0Sstevel@tonic-gate if (strncpy(actionp, fix_msg, len + 1) != actionp) { 587*0Sstevel@tonic-gate goto out; 588*0Sstevel@tonic-gate } 589*0Sstevel@tonic-gate } 590*0Sstevel@tonic-gate err = 0; 591*0Sstevel@tonic-gate out: 592*0Sstevel@tonic-gate if (err != 0) { 593*0Sstevel@tonic-gate if (actionp) { 594*0Sstevel@tonic-gate Free(actionp); 595*0Sstevel@tonic-gate actionp = NULL; 596*0Sstevel@tonic-gate } 597*0Sstevel@tonic-gate } 598*0Sstevel@tonic-gate return (actionp); 599*0Sstevel@tonic-gate } 600*0Sstevel@tonic-gate 601*0Sstevel@tonic-gate /* 602*0Sstevel@tonic-gate * convert log state to repair action 603*0Sstevel@tonic-gate */ 604*0Sstevel@tonic-gate char * 605*0Sstevel@tonic-gate mt_l_error_to_action( 606*0Sstevel@tonic-gate mdsetname_t *sp, 607*0Sstevel@tonic-gate mdnamelist_t *transnlp, 608*0Sstevel@tonic-gate mdname_t *lognamep, 609*0Sstevel@tonic-gate md_error_t *ep 610*0Sstevel@tonic-gate ) 611*0Sstevel@tonic-gate { 612*0Sstevel@tonic-gate char umnt_msg[1024]; 613*0Sstevel@tonic-gate char fsck_msg[1024]; 614*0Sstevel@tonic-gate char mnt_msg[1024]; 615*0Sstevel@tonic-gate mdnamelist_t *p; 616*0Sstevel@tonic-gate md_trans_t *tp; 617*0Sstevel@tonic-gate int rc; 618*0Sstevel@tonic-gate int len = 0; 619*0Sstevel@tonic-gate char *rmsg = NULL; 620*0Sstevel@tonic-gate char *mp = NULL; 621*0Sstevel@tonic-gate bool_t is_mounted = FALSE; 622*0Sstevel@tonic-gate bool_t any_in_error = FALSE; 623*0Sstevel@tonic-gate int only_fsck = TRUE; 624*0Sstevel@tonic-gate 625*0Sstevel@tonic-gate (void) memset(umnt_msg, 0, sizeof (umnt_msg)); 626*0Sstevel@tonic-gate (void) memset(fsck_msg, 0, sizeof (fsck_msg)); 627*0Sstevel@tonic-gate (void) memset(mnt_msg, 0, sizeof (mnt_msg)); 628*0Sstevel@tonic-gate 629*0Sstevel@tonic-gate /* 630*0Sstevel@tonic-gate * If a the trans devices listed in transnlp contain 631*0Sstevel@tonic-gate * devices which are in error and are sub-mount points 632*0Sstevel@tonic-gate * of each other, than it would need to be reverse sorted. 633*0Sstevel@tonic-gate * When this actually occurs, and customers find the usage 634*0Sstevel@tonic-gate * message insufficiently clear, then we should take the 635*0Sstevel@tonic-gate * hit to sort it. 636*0Sstevel@tonic-gate */ 637*0Sstevel@tonic-gate 638*0Sstevel@tonic-gate /* 639*0Sstevel@tonic-gate * this preliminary loop is necessary to keep the 640*0Sstevel@tonic-gate * fsck message greppable, if possible 641*0Sstevel@tonic-gate */ 642*0Sstevel@tonic-gate for (p = transnlp; ((p != NULL) && (only_fsck == TRUE)); p = p->next) { 643*0Sstevel@tonic-gate 644*0Sstevel@tonic-gate if ((tp = meta_get_trans(sp, p->namep, ep)) == NULL) { 645*0Sstevel@tonic-gate goto out; 646*0Sstevel@tonic-gate } 647*0Sstevel@tonic-gate 648*0Sstevel@tonic-gate if (!(tp->log_error & LDL_ANYERROR)) { 649*0Sstevel@tonic-gate continue; 650*0Sstevel@tonic-gate } 651*0Sstevel@tonic-gate 652*0Sstevel@tonic-gate if ((tp->lognamep == NULL) || 653*0Sstevel@tonic-gate (strcmp(lognamep->bname, tp->lognamep->bname) != 0)) { 654*0Sstevel@tonic-gate continue; 655*0Sstevel@tonic-gate } 656*0Sstevel@tonic-gate 657*0Sstevel@tonic-gate mdclrerror(ep); 658*0Sstevel@tonic-gate is_mounted = (meta_check_inuse(sp, 659*0Sstevel@tonic-gate p->namep, MDCHK_MOUNTED, ep) != 0); 660*0Sstevel@tonic-gate 661*0Sstevel@tonic-gate if (!mdisok(ep) && mdiserror(ep, MDE_IS_MOUNTED)) { 662*0Sstevel@tonic-gate goto out; 663*0Sstevel@tonic-gate } 664*0Sstevel@tonic-gate 665*0Sstevel@tonic-gate mdclrerror(ep); 666*0Sstevel@tonic-gate mp = meta_get_mountp(sp, p->namep, ep); 667*0Sstevel@tonic-gate 668*0Sstevel@tonic-gate if (!mdisok(ep)) { 669*0Sstevel@tonic-gate goto out; 670*0Sstevel@tonic-gate } 671*0Sstevel@tonic-gate 672*0Sstevel@tonic-gate if (is_mounted) { 673*0Sstevel@tonic-gate if (!mp) { 674*0Sstevel@tonic-gate goto out; 675*0Sstevel@tonic-gate } 676*0Sstevel@tonic-gate only_fsck = FALSE; 677*0Sstevel@tonic-gate 678*0Sstevel@tonic-gate /* 679*0Sstevel@tonic-gate * not greppable; there must be multiple commands, so 680*0Sstevel@tonic-gate * add preliminary newline so the formatting is uniform 681*0Sstevel@tonic-gate */ 682*0Sstevel@tonic-gate if (sprintf(umnt_msg, "\n") == EOF) { 683*0Sstevel@tonic-gate goto out; 684*0Sstevel@tonic-gate } 685*0Sstevel@tonic-gate 686*0Sstevel@tonic-gate } 687*0Sstevel@tonic-gate 688*0Sstevel@tonic-gate if (mp) { 689*0Sstevel@tonic-gate Free(mp); 690*0Sstevel@tonic-gate mp = NULL; 691*0Sstevel@tonic-gate } 692*0Sstevel@tonic-gate } 693*0Sstevel@tonic-gate 694*0Sstevel@tonic-gate /* 695*0Sstevel@tonic-gate * although the log may either be in error or hard-error 696*0Sstevel@tonic-gate * states, the action is the same; unmount, fsck and remount 697*0Sstevel@tonic-gate * all fs associated with this log 698*0Sstevel@tonic-gate */ 699*0Sstevel@tonic-gate for (p = transnlp; (p != NULL); p = p->next) { 700*0Sstevel@tonic-gate 701*0Sstevel@tonic-gate if ((tp = meta_get_trans(sp, p->namep, ep)) == NULL) { 702*0Sstevel@tonic-gate goto out; 703*0Sstevel@tonic-gate } 704*0Sstevel@tonic-gate 705*0Sstevel@tonic-gate if (!(tp->log_error & LDL_ANYERROR)) { 706*0Sstevel@tonic-gate continue; 707*0Sstevel@tonic-gate } 708*0Sstevel@tonic-gate 709*0Sstevel@tonic-gate if ((tp->lognamep == NULL) || 710*0Sstevel@tonic-gate (strcmp(lognamep->bname, tp->lognamep->bname) != 0)) { 711*0Sstevel@tonic-gate continue; 712*0Sstevel@tonic-gate } 713*0Sstevel@tonic-gate 714*0Sstevel@tonic-gate mdclrerror(ep); 715*0Sstevel@tonic-gate is_mounted = (meta_check_inuse(sp, 716*0Sstevel@tonic-gate p->namep, MDCHK_MOUNTED, ep) != 0); 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate if (!mdisok(ep) && mdiserror(ep, MDE_IS_MOUNTED)) { 719*0Sstevel@tonic-gate goto out; 720*0Sstevel@tonic-gate } 721*0Sstevel@tonic-gate 722*0Sstevel@tonic-gate mdclrerror(ep); 723*0Sstevel@tonic-gate mp = meta_get_mountp(sp, p->namep, ep); 724*0Sstevel@tonic-gate 725*0Sstevel@tonic-gate if (!mdisok(ep)) { 726*0Sstevel@tonic-gate goto out; 727*0Sstevel@tonic-gate } 728*0Sstevel@tonic-gate 729*0Sstevel@tonic-gate if (is_mounted) { 730*0Sstevel@tonic-gate if (!mp) { 731*0Sstevel@tonic-gate goto out; 732*0Sstevel@tonic-gate } 733*0Sstevel@tonic-gate } 734*0Sstevel@tonic-gate 735*0Sstevel@tonic-gate if (is_mounted) { 736*0Sstevel@tonic-gate rc = snprintf(umnt_msg, sizeof (umnt_msg), 737*0Sstevel@tonic-gate "%s umount %s\n", umnt_msg, mp); 738*0Sstevel@tonic-gate 739*0Sstevel@tonic-gate if (rc < 0) { 740*0Sstevel@tonic-gate goto out; 741*0Sstevel@tonic-gate } 742*0Sstevel@tonic-gate } 743*0Sstevel@tonic-gate 744*0Sstevel@tonic-gate rc = snprintf(fsck_msg, sizeof (fsck_msg), "%s %s", 745*0Sstevel@tonic-gate (any_in_error) ? fsck_msg : 746*0Sstevel@tonic-gate ((only_fsck) ? "fsck" : " fsck"), 747*0Sstevel@tonic-gate p->namep->rname); 748*0Sstevel@tonic-gate if (rc < 0) { 749*0Sstevel@tonic-gate goto out; 750*0Sstevel@tonic-gate } 751*0Sstevel@tonic-gate 752*0Sstevel@tonic-gate if (is_mounted) { 753*0Sstevel@tonic-gate rc = snprintf(mnt_msg, sizeof (mnt_msg), 754*0Sstevel@tonic-gate "%s mount %s %s\n", 755*0Sstevel@tonic-gate mnt_msg, p->namep->bname, mp); 756*0Sstevel@tonic-gate 757*0Sstevel@tonic-gate if (rc < 0) { 758*0Sstevel@tonic-gate goto out; 759*0Sstevel@tonic-gate } 760*0Sstevel@tonic-gate } 761*0Sstevel@tonic-gate 762*0Sstevel@tonic-gate if (mp) { 763*0Sstevel@tonic-gate Free(mp); 764*0Sstevel@tonic-gate mp = NULL; 765*0Sstevel@tonic-gate } 766*0Sstevel@tonic-gate 767*0Sstevel@tonic-gate any_in_error |= TRUE; 768*0Sstevel@tonic-gate } 769*0Sstevel@tonic-gate 770*0Sstevel@tonic-gate if (!any_in_error) { 771*0Sstevel@tonic-gate goto out; 772*0Sstevel@tonic-gate } 773*0Sstevel@tonic-gate 774*0Sstevel@tonic-gate len = strlen(umnt_msg) + strlen(fsck_msg) + strlen(mnt_msg) + 775*0Sstevel@tonic-gate (only_fsck? 1: 0) + 1; 776*0Sstevel@tonic-gate if (!(rmsg = Zalloc(len))) { 777*0Sstevel@tonic-gate len = 0; 778*0Sstevel@tonic-gate goto out; 779*0Sstevel@tonic-gate } 780*0Sstevel@tonic-gate rc = snprintf(rmsg, len, "%s%s%s%s", umnt_msg, fsck_msg, 781*0Sstevel@tonic-gate !only_fsck? "\n": "", mnt_msg); 782*0Sstevel@tonic-gate if (rc == EOF) { 783*0Sstevel@tonic-gate goto out; 784*0Sstevel@tonic-gate } 785*0Sstevel@tonic-gate 786*0Sstevel@tonic-gate out: 787*0Sstevel@tonic-gate if (mp) { 788*0Sstevel@tonic-gate Free(mp); 789*0Sstevel@tonic-gate mp = NULL; 790*0Sstevel@tonic-gate } 791*0Sstevel@tonic-gate if (len == 0 && rmsg) { 792*0Sstevel@tonic-gate Free(rmsg); 793*0Sstevel@tonic-gate rmsg = NULL; 794*0Sstevel@tonic-gate } 795*0Sstevel@tonic-gate 796*0Sstevel@tonic-gate return (rmsg); 797*0Sstevel@tonic-gate } 798*0Sstevel@tonic-gate 799*0Sstevel@tonic-gate /* 800*0Sstevel@tonic-gate * printable log state 801*0Sstevel@tonic-gate */ 802*0Sstevel@tonic-gate char * 803*0Sstevel@tonic-gate mt_l_error_to_name( 804*0Sstevel@tonic-gate md_trans_t *transp, 805*0Sstevel@tonic-gate md_timeval32_t *tvp, 806*0Sstevel@tonic-gate uint_t tstate /* Errored tstate flags */ 807*0Sstevel@tonic-gate ) 808*0Sstevel@tonic-gate { 809*0Sstevel@tonic-gate mt_l_error_t log_error = transp->log_error; 810*0Sstevel@tonic-gate 811*0Sstevel@tonic-gate /* grab time */ 812*0Sstevel@tonic-gate if (tvp != NULL) 813*0Sstevel@tonic-gate *tvp = transp->log_timestamp; 814*0Sstevel@tonic-gate 815*0Sstevel@tonic-gate if (tstate != 0) { 816*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unavailable")); 817*0Sstevel@tonic-gate } 818*0Sstevel@tonic-gate 819*0Sstevel@tonic-gate /* return state */ 820*0Sstevel@tonic-gate if (log_error & LDL_ERROR) { 821*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Error")); 822*0Sstevel@tonic-gate } else if (log_error & LDL_HERROR) { 823*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Hard Error")); 824*0Sstevel@tonic-gate } else { 825*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Okay")); 826*0Sstevel@tonic-gate } 827*0Sstevel@tonic-gate } 828*0Sstevel@tonic-gate 829*0Sstevel@tonic-gate /* 830*0Sstevel@tonic-gate * printable trans state 831*0Sstevel@tonic-gate */ 832*0Sstevel@tonic-gate char * 833*0Sstevel@tonic-gate mt_flags_to_name( 834*0Sstevel@tonic-gate md_trans_t *transp, 835*0Sstevel@tonic-gate md_timeval32_t *tvp, 836*0Sstevel@tonic-gate uint_t tstate /* Errored tstate flags */ 837*0Sstevel@tonic-gate ) 838*0Sstevel@tonic-gate { 839*0Sstevel@tonic-gate /* grab time */ 840*0Sstevel@tonic-gate if (tvp != NULL) 841*0Sstevel@tonic-gate *tvp = transp->timestamp; 842*0Sstevel@tonic-gate 843*0Sstevel@tonic-gate if (tstate != 0) { 844*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Unavailable")); 845*0Sstevel@tonic-gate } 846*0Sstevel@tonic-gate 847*0Sstevel@tonic-gate /* return state */ 848*0Sstevel@tonic-gate if (transp->flags & TRANS_DETACHED) 849*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Detached")); 850*0Sstevel@tonic-gate else if (transp->flags & TRANS_DETACHING) 851*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Detaching")); 852*0Sstevel@tonic-gate else if (transp->flags & TRANS_ATTACHING) 853*0Sstevel@tonic-gate return (dgettext(TEXT_DOMAIN, "Attaching")); 854*0Sstevel@tonic-gate return (mt_l_error_to_name(transp, tvp, tstate)); 855*0Sstevel@tonic-gate } 856*0Sstevel@tonic-gate 857*0Sstevel@tonic-gate /* 858*0Sstevel@tonic-gate * report trans 859*0Sstevel@tonic-gate */ 860*0Sstevel@tonic-gate static int 861*0Sstevel@tonic-gate trans_report( 862*0Sstevel@tonic-gate mdsetname_t *sp, 863*0Sstevel@tonic-gate md_trans_t *transp, 864*0Sstevel@tonic-gate char *fname, 865*0Sstevel@tonic-gate FILE *fp, 866*0Sstevel@tonic-gate mdprtopts_t options, 867*0Sstevel@tonic-gate md_error_t *ep 868*0Sstevel@tonic-gate ) 869*0Sstevel@tonic-gate { 870*0Sstevel@tonic-gate char *mt_state; 871*0Sstevel@tonic-gate md_timeval32_t tv; 872*0Sstevel@tonic-gate char *timep; 873*0Sstevel@tonic-gate int rval = -1; 874*0Sstevel@tonic-gate char *actionp = NULL; 875*0Sstevel@tonic-gate char *devid = ""; 876*0Sstevel@tonic-gate mdname_t *didnp = NULL; 877*0Sstevel@tonic-gate ddi_devid_t dtp; 878*0Sstevel@tonic-gate uint_t tstate = 0; 879*0Sstevel@tonic-gate 880*0Sstevel@tonic-gate /* print header */ 881*0Sstevel@tonic-gate if (options & PRINT_HEADER) { 882*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, "%s: Trans" 883*0Sstevel@tonic-gate " (Feature replaced see message below)\n"), 884*0Sstevel@tonic-gate transp->common.namep->cname) == EOF) { 885*0Sstevel@tonic-gate goto out; 886*0Sstevel@tonic-gate } 887*0Sstevel@tonic-gate } 888*0Sstevel@tonic-gate 889*0Sstevel@tonic-gate /* print state */ 890*0Sstevel@tonic-gate if (metaismeta(transp->common.namep)) { 891*0Sstevel@tonic-gate if (meta_get_tstate(transp->common.namep->dev, &tstate, ep) 892*0Sstevel@tonic-gate != 0) 893*0Sstevel@tonic-gate goto out; 894*0Sstevel@tonic-gate } 895*0Sstevel@tonic-gate mt_state = mt_flags_to_name(transp, &tv, tstate & MD_DEV_ERRORED); 896*0Sstevel@tonic-gate if (options & PRINT_TIMES) { 897*0Sstevel@tonic-gate timep = meta_print_time(&tv); 898*0Sstevel@tonic-gate } else { 899*0Sstevel@tonic-gate timep = ""; 900*0Sstevel@tonic-gate } 901*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, " State: %-12s %s\n"), 902*0Sstevel@tonic-gate mt_state, timep) == EOF) { 903*0Sstevel@tonic-gate goto out; 904*0Sstevel@tonic-gate } 905*0Sstevel@tonic-gate 906*0Sstevel@tonic-gate if ((tstate & MD_DEV_ERRORED) == 0) { 907*0Sstevel@tonic-gate actionp = mt_flags_to_action(transp); 908*0Sstevel@tonic-gate if (actionp) { 909*0Sstevel@tonic-gate if (fprintf(fp, "%s", actionp) == EOF) { 910*0Sstevel@tonic-gate goto out; 911*0Sstevel@tonic-gate } 912*0Sstevel@tonic-gate Free(actionp); 913*0Sstevel@tonic-gate actionp = NULL; 914*0Sstevel@tonic-gate } 915*0Sstevel@tonic-gate } 916*0Sstevel@tonic-gate 917*0Sstevel@tonic-gate /* debug stuff */ 918*0Sstevel@tonic-gate if (transp->debug) { 919*0Sstevel@tonic-gate if (fprintf(fp, 920*0Sstevel@tonic-gate " Debug Modes:%s%s%s%s%s%s%s%s%s%s%s\n", 921*0Sstevel@tonic-gate (transp->debug & MT_TRANSACT) ? " TRANSACT" : "", 922*0Sstevel@tonic-gate (transp->debug & MT_MATAMAP) ? " METADATA" : "", 923*0Sstevel@tonic-gate (transp->debug & MT_WRITE_CHECK) ? " WRITES" : "", 924*0Sstevel@tonic-gate (transp->debug & MT_LOG_WRITE_CHECK) ? " LOGWRITES" : "", 925*0Sstevel@tonic-gate (transp->debug & MT_CHECK_MAP) ? " MAP" : "", 926*0Sstevel@tonic-gate (transp->debug & MT_TRACE) ? " TRACE" : "", 927*0Sstevel@tonic-gate (transp->debug & MT_SIZE) ? " SIZE" : "", 928*0Sstevel@tonic-gate (transp->debug & MT_NOASYNC) ? " NOASYNC" : "", 929*0Sstevel@tonic-gate (transp->debug & MT_FORCEROLL) ? " FORCEROLL" : "", 930*0Sstevel@tonic-gate (transp->debug & MT_SCAN) ? " SCAN" : "", 931*0Sstevel@tonic-gate (transp->debug & MT_PREWRITE) ? " PREWRITE" : "") 932*0Sstevel@tonic-gate == EOF) { 933*0Sstevel@tonic-gate goto out; 934*0Sstevel@tonic-gate } 935*0Sstevel@tonic-gate } 936*0Sstevel@tonic-gate 937*0Sstevel@tonic-gate /* print size */ 938*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, " Size: %lld blocks (%s)\n"), 939*0Sstevel@tonic-gate transp->common.size, 940*0Sstevel@tonic-gate meta_number_to_string(transp->common.size, DEV_BSIZE)) == EOF) { 941*0Sstevel@tonic-gate goto out; 942*0Sstevel@tonic-gate } 943*0Sstevel@tonic-gate 944*0Sstevel@tonic-gate 945*0Sstevel@tonic-gate /* print master */ 946*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, " Master Device: %s\n"), 947*0Sstevel@tonic-gate transp->masternamep->cname) == EOF) { 948*0Sstevel@tonic-gate goto out; 949*0Sstevel@tonic-gate } 950*0Sstevel@tonic-gate 951*0Sstevel@tonic-gate /* print log */ 952*0Sstevel@tonic-gate if (transp->lognamep != NULL) { 953*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 954*0Sstevel@tonic-gate " Logging Device: %s\n"), 955*0Sstevel@tonic-gate transp->lognamep->cname) == EOF) { 956*0Sstevel@tonic-gate goto out; 957*0Sstevel@tonic-gate } 958*0Sstevel@tonic-gate } 959*0Sstevel@tonic-gate 960*0Sstevel@tonic-gate /* add extra line */ 961*0Sstevel@tonic-gate if (fprintf(fp, "\n") == EOF) 962*0Sstevel@tonic-gate goto out; 963*0Sstevel@tonic-gate 964*0Sstevel@tonic-gate /* print master details if regular device */ 965*0Sstevel@tonic-gate if (! metaismeta(transp->masternamep)) { 966*0Sstevel@tonic-gate daddr_t start_blk = 0; 967*0Sstevel@tonic-gate char *has_mddb_str = dgettext(TEXT_DOMAIN, "No"); 968*0Sstevel@tonic-gate int len; 969*0Sstevel@tonic-gate 970*0Sstevel@tonic-gate /* 971*0Sstevel@tonic-gate * Building a format string on the fly that will 972*0Sstevel@tonic-gate * be used in (f)printf. This allows the length 973*0Sstevel@tonic-gate * of the ctd to vary from small to large without 974*0Sstevel@tonic-gate * looking horrible. 975*0Sstevel@tonic-gate */ 976*0Sstevel@tonic-gate len = strlen(transp->masternamep->cname) + 2; 977*0Sstevel@tonic-gate len = max(len, strlen(dgettext(TEXT_DOMAIN, "Master Device"))); 978*0Sstevel@tonic-gate 979*0Sstevel@tonic-gate /* print header */ 980*0Sstevel@tonic-gate if (fprintf(fp, 981*0Sstevel@tonic-gate "\t%-*.*s %-12.12s %-5.5s %s\n", 982*0Sstevel@tonic-gate len, len, 983*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Master Device"), 984*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Start Block"), 985*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Dbase"), 986*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Reloc")) == EOF) { 987*0Sstevel@tonic-gate goto out; 988*0Sstevel@tonic-gate } 989*0Sstevel@tonic-gate 990*0Sstevel@tonic-gate /* populate the key in the name_p structure */ 991*0Sstevel@tonic-gate if ((didnp = metadevname(&sp, 992*0Sstevel@tonic-gate transp->masternamep->dev, ep)) == NULL) { 993*0Sstevel@tonic-gate return (-1); 994*0Sstevel@tonic-gate } 995*0Sstevel@tonic-gate 996*0Sstevel@tonic-gate /* determine if devid does NOT exist */ 997*0Sstevel@tonic-gate if (options & PRINT_DEVID) 998*0Sstevel@tonic-gate if ((dtp = meta_getdidbykey(sp->setno, getmyside(sp, ep), 999*0Sstevel@tonic-gate didnp->key, ep)) == NULL) 1000*0Sstevel@tonic-gate devid = dgettext(TEXT_DOMAIN, "No "); 1001*0Sstevel@tonic-gate else { 1002*0Sstevel@tonic-gate devid = dgettext(TEXT_DOMAIN, "Yes"); 1003*0Sstevel@tonic-gate free(dtp); 1004*0Sstevel@tonic-gate } 1005*0Sstevel@tonic-gate 1006*0Sstevel@tonic-gate /* print info */ 1007*0Sstevel@tonic-gate /* 1008*0Sstevel@tonic-gate * This allows the length 1009*0Sstevel@tonic-gate * of the ctd to vary from small to large without 1010*0Sstevel@tonic-gate * looking horrible. 1011*0Sstevel@tonic-gate */ 1012*0Sstevel@tonic-gate if (fprintf(fp, "\t%-*s %8ld %-5.5s %s\n", len, 1013*0Sstevel@tonic-gate transp->masternamep->cname, 1014*0Sstevel@tonic-gate start_blk, has_mddb_str, devid) == EOF) { 1015*0Sstevel@tonic-gate goto out; 1016*0Sstevel@tonic-gate } 1017*0Sstevel@tonic-gate /* add extra line */ 1018*0Sstevel@tonic-gate if (fprintf(fp, "\n") == EOF) 1019*0Sstevel@tonic-gate goto out; 1020*0Sstevel@tonic-gate } 1021*0Sstevel@tonic-gate 1022*0Sstevel@tonic-gate /* success */ 1023*0Sstevel@tonic-gate rval = 0; 1024*0Sstevel@tonic-gate 1025*0Sstevel@tonic-gate /* cleanup, return error */ 1026*0Sstevel@tonic-gate out: 1027*0Sstevel@tonic-gate if (rval != 0) 1028*0Sstevel@tonic-gate (void) mdsyserror(ep, errno, fname); 1029*0Sstevel@tonic-gate return (rval); 1030*0Sstevel@tonic-gate } 1031*0Sstevel@tonic-gate 1032*0Sstevel@tonic-gate /* 1033*0Sstevel@tonic-gate * print/report trans 1034*0Sstevel@tonic-gate */ 1035*0Sstevel@tonic-gate int 1036*0Sstevel@tonic-gate meta_trans_print( 1037*0Sstevel@tonic-gate mdsetname_t *sp, 1038*0Sstevel@tonic-gate mdname_t *transnp, 1039*0Sstevel@tonic-gate mdnamelist_t **nlistpp, 1040*0Sstevel@tonic-gate char *fname, 1041*0Sstevel@tonic-gate FILE *fp, 1042*0Sstevel@tonic-gate mdprtopts_t options, 1043*0Sstevel@tonic-gate int *meta_print_trans_msgp, /* NULL if transnp != NULL */ 1044*0Sstevel@tonic-gate mdnamelist_t **lognlpp, 1045*0Sstevel@tonic-gate md_error_t *ep 1046*0Sstevel@tonic-gate ) 1047*0Sstevel@tonic-gate { 1048*0Sstevel@tonic-gate md_trans_t *transp; 1049*0Sstevel@tonic-gate mdname_t *lognamep; 1050*0Sstevel@tonic-gate 1051*0Sstevel@tonic-gate /* should have same set */ 1052*0Sstevel@tonic-gate assert(sp != NULL); 1053*0Sstevel@tonic-gate 1054*0Sstevel@tonic-gate /* print all transs */ 1055*0Sstevel@tonic-gate if (transnp == NULL) { 1056*0Sstevel@tonic-gate mdnamelist_t *nlp = NULL; 1057*0Sstevel@tonic-gate mdnamelist_t *p; 1058*0Sstevel@tonic-gate int cnt; 1059*0Sstevel@tonic-gate int rval = 0; 1060*0Sstevel@tonic-gate 1061*0Sstevel@tonic-gate /* get list */ 1062*0Sstevel@tonic-gate if ((cnt = meta_get_trans_names(sp, &nlp, options, ep)) < 0) 1063*0Sstevel@tonic-gate return (-1); 1064*0Sstevel@tonic-gate else if (cnt == 0) 1065*0Sstevel@tonic-gate return (0); 1066*0Sstevel@tonic-gate 1067*0Sstevel@tonic-gate /* recurse */ 1068*0Sstevel@tonic-gate for (p = nlp; (p != NULL); p = p->next) { 1069*0Sstevel@tonic-gate mdname_t *np = p->namep; 1070*0Sstevel@tonic-gate 1071*0Sstevel@tonic-gate if (meta_trans_print(sp, np, nlistpp, fname, fp, 1072*0Sstevel@tonic-gate options, meta_print_trans_msgp, lognlpp, ep) != 0) 1073*0Sstevel@tonic-gate rval = -1; 1074*0Sstevel@tonic-gate } 1075*0Sstevel@tonic-gate 1076*0Sstevel@tonic-gate if (meta_print_trans_msgp) 1077*0Sstevel@tonic-gate *meta_print_trans_msgp = 1; 1078*0Sstevel@tonic-gate 1079*0Sstevel@tonic-gate /* cleanup, return success */ 1080*0Sstevel@tonic-gate metafreenamelist(nlp); 1081*0Sstevel@tonic-gate return (rval); 1082*0Sstevel@tonic-gate } 1083*0Sstevel@tonic-gate 1084*0Sstevel@tonic-gate 1085*0Sstevel@tonic-gate /* get unit structure */ 1086*0Sstevel@tonic-gate if ((transp = meta_get_trans_common(sp, transnp, 1087*0Sstevel@tonic-gate ((options & PRINT_FAST) ? 1 : 0), ep)) == NULL) 1088*0Sstevel@tonic-gate return (-1); 1089*0Sstevel@tonic-gate 1090*0Sstevel@tonic-gate /* save unique log */ 1091*0Sstevel@tonic-gate if ((lognlpp != NULL) && 1092*0Sstevel@tonic-gate ((lognamep = transp->lognamep) != NULL)) { 1093*0Sstevel@tonic-gate mdnamelist_t *p; 1094*0Sstevel@tonic-gate 1095*0Sstevel@tonic-gate for (p = *lognlpp; (p != NULL); p = p->next) { 1096*0Sstevel@tonic-gate if (strcmp(lognamep->bname, p->namep->bname) == 0) 1097*0Sstevel@tonic-gate break; 1098*0Sstevel@tonic-gate } 1099*0Sstevel@tonic-gate if (p == NULL) 1100*0Sstevel@tonic-gate (void) metanamelist_append(lognlpp, lognamep); 1101*0Sstevel@tonic-gate } 1102*0Sstevel@tonic-gate 1103*0Sstevel@tonic-gate /* check for parented */ 1104*0Sstevel@tonic-gate if ((! (options & PRINT_SUBDEVS)) && 1105*0Sstevel@tonic-gate (MD_HAS_PARENT(transp->common.parent))) { 1106*0Sstevel@tonic-gate return (0); 1107*0Sstevel@tonic-gate } 1108*0Sstevel@tonic-gate 1109*0Sstevel@tonic-gate /* can't have a large trans */ 1110*0Sstevel@tonic-gate if (!(options & PRINT_LARGEDEVICES)) { 1111*0Sstevel@tonic-gate /* print appropriate detail */ 1112*0Sstevel@tonic-gate if (options & PRINT_SHORT) { 1113*0Sstevel@tonic-gate if (trans_print(transp, fname, fp, ep) != 0) 1114*0Sstevel@tonic-gate return (-1); 1115*0Sstevel@tonic-gate } else { 1116*0Sstevel@tonic-gate if (trans_report(sp, transp, fname, fp, options, ep) 1117*0Sstevel@tonic-gate != 0) 1118*0Sstevel@tonic-gate return (-1); 1119*0Sstevel@tonic-gate } 1120*0Sstevel@tonic-gate } 1121*0Sstevel@tonic-gate 1122*0Sstevel@tonic-gate /* print underlying metadevices, log is later */ 1123*0Sstevel@tonic-gate if (metaismeta(transp->masternamep)) { 1124*0Sstevel@tonic-gate if (meta_print_name(sp, transp->masternamep, nlistpp, fname, 1125*0Sstevel@tonic-gate fp, (options | PRINT_HEADER | PRINT_SUBDEVS), NULL, ep) 1126*0Sstevel@tonic-gate != 0) { 1127*0Sstevel@tonic-gate return (-1); 1128*0Sstevel@tonic-gate } 1129*0Sstevel@tonic-gate } 1130*0Sstevel@tonic-gate 1131*0Sstevel@tonic-gate /* return success */ 1132*0Sstevel@tonic-gate return (0); 1133*0Sstevel@tonic-gate } 1134*0Sstevel@tonic-gate 1135*0Sstevel@tonic-gate /* 1136*0Sstevel@tonic-gate * print log 1137*0Sstevel@tonic-gate */ 1138*0Sstevel@tonic-gate static int 1139*0Sstevel@tonic-gate log_print( 1140*0Sstevel@tonic-gate mdsetname_t *sp, 1141*0Sstevel@tonic-gate mdname_t *lognamep, 1142*0Sstevel@tonic-gate char *fname, 1143*0Sstevel@tonic-gate FILE *fp, 1144*0Sstevel@tonic-gate mdprtopts_t options, 1145*0Sstevel@tonic-gate md_error_t *ep 1146*0Sstevel@tonic-gate ) 1147*0Sstevel@tonic-gate { 1148*0Sstevel@tonic-gate mdnamelist_t *nlp = NULL; 1149*0Sstevel@tonic-gate 1150*0Sstevel@tonic-gate /* metadevice info */ 1151*0Sstevel@tonic-gate if (metaismeta(lognamep)) { 1152*0Sstevel@tonic-gate return (meta_print_name(sp, lognamep, &nlp, fname, fp, 1153*0Sstevel@tonic-gate options, NULL, ep)); 1154*0Sstevel@tonic-gate } 1155*0Sstevel@tonic-gate 1156*0Sstevel@tonic-gate /* regular device info */ 1157*0Sstevel@tonic-gate return (0); 1158*0Sstevel@tonic-gate } 1159*0Sstevel@tonic-gate 1160*0Sstevel@tonic-gate /* 1161*0Sstevel@tonic-gate * report log 1162*0Sstevel@tonic-gate */ 1163*0Sstevel@tonic-gate static int 1164*0Sstevel@tonic-gate log_report( 1165*0Sstevel@tonic-gate mdsetname_t *sp, 1166*0Sstevel@tonic-gate mdname_t *lognamep, 1167*0Sstevel@tonic-gate mdnamelist_t **nlistpp, 1168*0Sstevel@tonic-gate char *fname, 1169*0Sstevel@tonic-gate FILE *fp, 1170*0Sstevel@tonic-gate mdprtopts_t options, 1171*0Sstevel@tonic-gate mdnamelist_t *transnlp, 1172*0Sstevel@tonic-gate md_error_t *ep 1173*0Sstevel@tonic-gate ) 1174*0Sstevel@tonic-gate { 1175*0Sstevel@tonic-gate md_trans_t *transp = NULL; 1176*0Sstevel@tonic-gate mdnamelist_t *p; 1177*0Sstevel@tonic-gate char *ml_state; 1178*0Sstevel@tonic-gate md_timeval32_t tv; 1179*0Sstevel@tonic-gate char *timep; 1180*0Sstevel@tonic-gate char *actionp = NULL; 1181*0Sstevel@tonic-gate int rval = -1; 1182*0Sstevel@tonic-gate char *devid = " "; 1183*0Sstevel@tonic-gate mdname_t *didnp = NULL; 1184*0Sstevel@tonic-gate ddi_devid_t dtp; 1185*0Sstevel@tonic-gate uint_t tstate = 0; 1186*0Sstevel@tonic-gate 1187*0Sstevel@tonic-gate for (p = transnlp; (p != NULL); p = p->next) { 1188*0Sstevel@tonic-gate md_trans_t *tp; 1189*0Sstevel@tonic-gate 1190*0Sstevel@tonic-gate if ((tp = meta_get_trans(sp, p->namep, ep)) == NULL) 1191*0Sstevel@tonic-gate return (-1); 1192*0Sstevel@tonic-gate if ((tp->lognamep != NULL) && 1193*0Sstevel@tonic-gate (strcmp(lognamep->bname, tp->lognamep->bname) == 0)) { 1194*0Sstevel@tonic-gate transp = tp; /* save any parent trans */ 1195*0Sstevel@tonic-gate } 1196*0Sstevel@tonic-gate } 1197*0Sstevel@tonic-gate 1198*0Sstevel@tonic-gate /* we must have at least one trans */ 1199*0Sstevel@tonic-gate assert(transp != NULL); 1200*0Sstevel@tonic-gate if (transp == NULL) { 1201*0Sstevel@tonic-gate rval = 0; 1202*0Sstevel@tonic-gate goto out; 1203*0Sstevel@tonic-gate } 1204*0Sstevel@tonic-gate 1205*0Sstevel@tonic-gate if ((options & PRINT_LARGEDEVICES) && 1206*0Sstevel@tonic-gate (transp->log_size <= MD_MAX_BLKS_FOR_SMALL_DEVS)) { 1207*0Sstevel@tonic-gate rval = 0; 1208*0Sstevel@tonic-gate goto out; 1209*0Sstevel@tonic-gate } 1210*0Sstevel@tonic-gate 1211*0Sstevel@tonic-gate /* print header and trans devices, collect log_error and size */ 1212*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, "%s: Logging device for"), 1213*0Sstevel@tonic-gate lognamep->cname) == EOF) { 1214*0Sstevel@tonic-gate goto out; 1215*0Sstevel@tonic-gate } 1216*0Sstevel@tonic-gate 1217*0Sstevel@tonic-gate if ((transp->lognamep != NULL) && 1218*0Sstevel@tonic-gate (strcmp(lognamep->bname, transp->lognamep->bname) == 0)) { 1219*0Sstevel@tonic-gate if (fprintf(fp, " %s", transp->common.namep->cname) 1220*0Sstevel@tonic-gate == EOF) { 1221*0Sstevel@tonic-gate goto out; 1222*0Sstevel@tonic-gate } 1223*0Sstevel@tonic-gate } 1224*0Sstevel@tonic-gate if (fprintf(fp, "\n") == EOF) 1225*0Sstevel@tonic-gate goto out; 1226*0Sstevel@tonic-gate 1227*0Sstevel@tonic-gate /* print state */ 1228*0Sstevel@tonic-gate if (metaismeta(transp->lognamep)) { 1229*0Sstevel@tonic-gate if (meta_get_tstate(transp->lognamep->dev, &tstate, ep) != 0) 1230*0Sstevel@tonic-gate return (-1); 1231*0Sstevel@tonic-gate } 1232*0Sstevel@tonic-gate ml_state = mt_l_error_to_name(transp, &tv, tstate & MD_DEV_ERRORED); 1233*0Sstevel@tonic-gate if (options & PRINT_TIMES) { 1234*0Sstevel@tonic-gate timep = meta_print_time(&tv); 1235*0Sstevel@tonic-gate } else { 1236*0Sstevel@tonic-gate timep = ""; 1237*0Sstevel@tonic-gate } 1238*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, " State: %-12s %s\n"), 1239*0Sstevel@tonic-gate ml_state, timep) == EOF) { 1240*0Sstevel@tonic-gate goto out; 1241*0Sstevel@tonic-gate } 1242*0Sstevel@tonic-gate 1243*0Sstevel@tonic-gate if ((tstate & MD_DEV_ERRORED) == 0) { 1244*0Sstevel@tonic-gate actionp = mt_l_error_to_action(sp, transnlp, lognamep, ep); 1245*0Sstevel@tonic-gate if (actionp) { 1246*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 1247*0Sstevel@tonic-gate " Invoke: %s\n"), actionp) == EOF) { 1248*0Sstevel@tonic-gate goto out; 1249*0Sstevel@tonic-gate } 1250*0Sstevel@tonic-gate Free(actionp); 1251*0Sstevel@tonic-gate actionp = NULL; 1252*0Sstevel@tonic-gate } 1253*0Sstevel@tonic-gate } 1254*0Sstevel@tonic-gate 1255*0Sstevel@tonic-gate /* print size */ 1256*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, " Size: %ld blocks (%s)\n"), 1257*0Sstevel@tonic-gate transp->log_size, 1258*0Sstevel@tonic-gate meta_number_to_string(transp->log_size, DEV_BSIZE)) == EOF) { 1259*0Sstevel@tonic-gate goto out; 1260*0Sstevel@tonic-gate } 1261*0Sstevel@tonic-gate 1262*0Sstevel@tonic-gate /* MD_DEBUG stuff */ 1263*0Sstevel@tonic-gate if (options & PRINT_DEBUG) { 1264*0Sstevel@tonic-gate mdname_t *transnp = transp->common.namep; 1265*0Sstevel@tonic-gate mt_unit_t *mt; 1266*0Sstevel@tonic-gate daddr_t blksinuse, head, tail, nblks, eblk, sblk; 1267*0Sstevel@tonic-gate int percent; 1268*0Sstevel@tonic-gate 1269*0Sstevel@tonic-gate if ((mt = (mt_unit_t *)meta_get_mdunit(sp, transnp, ep)) 1270*0Sstevel@tonic-gate == NULL) { 1271*0Sstevel@tonic-gate return (-1); 1272*0Sstevel@tonic-gate } 1273*0Sstevel@tonic-gate assert(mt->c.un_type == MD_METATRANS); 1274*0Sstevel@tonic-gate 1275*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 1276*0Sstevel@tonic-gate " Transfer Size: %d blocks\n"), 1277*0Sstevel@tonic-gate mt->un_l_maxtransfer) == EOF) { 1278*0Sstevel@tonic-gate Free(mt); 1279*0Sstevel@tonic-gate goto out; 1280*0Sstevel@tonic-gate } 1281*0Sstevel@tonic-gate 1282*0Sstevel@tonic-gate head = mt->un_l_head; 1283*0Sstevel@tonic-gate tail = mt->un_l_tail; 1284*0Sstevel@tonic-gate sblk = mt->un_l_sblk; 1285*0Sstevel@tonic-gate nblks = mt->un_l_nblks; 1286*0Sstevel@tonic-gate eblk = sblk + nblks; 1287*0Sstevel@tonic-gate if (head <= tail) 1288*0Sstevel@tonic-gate blksinuse = tail - head; 1289*0Sstevel@tonic-gate else 1290*0Sstevel@tonic-gate blksinuse = (eblk - head) + (tail - sblk); 1291*0Sstevel@tonic-gate 1292*0Sstevel@tonic-gate percent = ((u_longlong_t)blksinuse * 100) / nblks; 1293*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 1294*0Sstevel@tonic-gate " Full: %d%% (%ld of %ld blocks)\n"), 1295*0Sstevel@tonic-gate percent, blksinuse, nblks) == EOF) { 1296*0Sstevel@tonic-gate Free(mt); 1297*0Sstevel@tonic-gate goto out; 1298*0Sstevel@tonic-gate } 1299*0Sstevel@tonic-gate 1300*0Sstevel@tonic-gate percent = ((u_longlong_t)mt->un_l_resv * 100) / 1301*0Sstevel@tonic-gate mt->un_l_maxresv; 1302*0Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, 1303*0Sstevel@tonic-gate " Reserved: %d%% (%ud of %ud bytes)\n"), 1304*0Sstevel@tonic-gate percent, mt->un_l_resv, mt->un_l_maxresv) == EOF) { 1305*0Sstevel@tonic-gate Free(mt); 1306*0Sstevel@tonic-gate goto out; 1307*0Sstevel@tonic-gate } 1308*0Sstevel@tonic-gate Free(mt); 1309*0Sstevel@tonic-gate } 1310*0Sstevel@tonic-gate 1311*0Sstevel@tonic-gate /* add extra line */ 1312*0Sstevel@tonic-gate if (fprintf(fp, "\n") == EOF) 1313*0Sstevel@tonic-gate goto out; 1314*0Sstevel@tonic-gate 1315*0Sstevel@tonic-gate /* print log details */ 1316*0Sstevel@tonic-gate if (metaismeta(lognamep)) { 1317*0Sstevel@tonic-gate if (meta_print_name(sp, lognamep, nlistpp, fname, fp, 1318*0Sstevel@tonic-gate options, NULL, ep) != 0) { 1319*0Sstevel@tonic-gate return (-1); 1320*0Sstevel@tonic-gate } 1321*0Sstevel@tonic-gate } else { 1322*0Sstevel@tonic-gate daddr_t start_blk; 1323*0Sstevel@tonic-gate int has_mddb; 1324*0Sstevel@tonic-gate char *has_mddb_str; 1325*0Sstevel@tonic-gate int len; 1326*0Sstevel@tonic-gate 1327*0Sstevel@tonic-gate /* 1328*0Sstevel@tonic-gate * Building a format string on the fly that will 1329*0Sstevel@tonic-gate * be used in (f)printf. This allows the length 1330*0Sstevel@tonic-gate * of the ctd to vary from small to large without 1331*0Sstevel@tonic-gate * looking horrible. 1332*0Sstevel@tonic-gate */ 1333*0Sstevel@tonic-gate len = strlen(lognamep->cname) + 2; 1334*0Sstevel@tonic-gate len = max(len, strlen(dgettext(TEXT_DOMAIN, "Logging Device"))); 1335*0Sstevel@tonic-gate /* print header */ 1336*0Sstevel@tonic-gate if (fprintf(fp, 1337*0Sstevel@tonic-gate "\t%-*.*s %-12.12s %-5.5s %s\n", 1338*0Sstevel@tonic-gate len, len, 1339*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Logging Device"), 1340*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Start Block"), 1341*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Dbase"), 1342*0Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Reloc")) == EOF) { 1343*0Sstevel@tonic-gate goto out; 1344*0Sstevel@tonic-gate } 1345*0Sstevel@tonic-gate /* get info */ 1346*0Sstevel@tonic-gate if ((start_blk = metagetstart(sp, lognamep, ep)) == 1347*0Sstevel@tonic-gate MD_DISKADDR_ERROR) { 1348*0Sstevel@tonic-gate return (-1); 1349*0Sstevel@tonic-gate } 1350*0Sstevel@tonic-gate if ((has_mddb = metahasmddb(sp, lognamep, ep)) < 0) { 1351*0Sstevel@tonic-gate return (-1); 1352*0Sstevel@tonic-gate } 1353*0Sstevel@tonic-gate if (has_mddb) 1354*0Sstevel@tonic-gate has_mddb_str = dgettext(TEXT_DOMAIN, "Yes"); 1355*0Sstevel@tonic-gate else 1356*0Sstevel@tonic-gate has_mddb_str = dgettext(TEXT_DOMAIN, "No"); 1357*0Sstevel@tonic-gate 1358*0Sstevel@tonic-gate /* populate the key in the name_p structure */ 1359*0Sstevel@tonic-gate if ((didnp = metadevname(&sp, lognamep->dev, ep)) == NULL) { 1360*0Sstevel@tonic-gate return (-1); 1361*0Sstevel@tonic-gate } 1362*0Sstevel@tonic-gate 1363*0Sstevel@tonic-gate /* determine if devid does NOT exist */ 1364*0Sstevel@tonic-gate if (options & PRINT_DEVID) 1365*0Sstevel@tonic-gate if ((dtp = meta_getdidbykey(sp->setno, getmyside(sp, ep), 1366*0Sstevel@tonic-gate didnp->key, ep)) == NULL) 1367*0Sstevel@tonic-gate devid = dgettext(TEXT_DOMAIN, "No "); 1368*0Sstevel@tonic-gate else { 1369*0Sstevel@tonic-gate devid = dgettext(TEXT_DOMAIN, "Yes"); 1370*0Sstevel@tonic-gate free(dtp); 1371*0Sstevel@tonic-gate } 1372*0Sstevel@tonic-gate 1373*0Sstevel@tonic-gate /* print info */ 1374*0Sstevel@tonic-gate /* 1375*0Sstevel@tonic-gate * This allows the length 1376*0Sstevel@tonic-gate * of the ctd to vary from small to large without 1377*0Sstevel@tonic-gate * looking horrible. 1378*0Sstevel@tonic-gate */ 1379*0Sstevel@tonic-gate if (fprintf(fp, "\t%-*s %8ld %-5.5s %s\n", 1380*0Sstevel@tonic-gate len, lognamep->cname, start_blk, 1381*0Sstevel@tonic-gate has_mddb_str, devid) == EOF) { 1382*0Sstevel@tonic-gate goto out; 1383*0Sstevel@tonic-gate } 1384*0Sstevel@tonic-gate } 1385*0Sstevel@tonic-gate 1386*0Sstevel@tonic-gate /* add extra line */ 1387*0Sstevel@tonic-gate if (fprintf(fp, "\n") == EOF) 1388*0Sstevel@tonic-gate goto out; 1389*0Sstevel@tonic-gate 1390*0Sstevel@tonic-gate /* success */ 1391*0Sstevel@tonic-gate rval = 0; 1392*0Sstevel@tonic-gate 1393*0Sstevel@tonic-gate /* cleanup, return error */ 1394*0Sstevel@tonic-gate out: 1395*0Sstevel@tonic-gate if (rval != 0) 1396*0Sstevel@tonic-gate (void) mdsyserror(ep, errno, fname); 1397*0Sstevel@tonic-gate return (rval); 1398*0Sstevel@tonic-gate } 1399*0Sstevel@tonic-gate 1400*0Sstevel@tonic-gate /* 1401*0Sstevel@tonic-gate * print/report logs 1402*0Sstevel@tonic-gate */ 1403*0Sstevel@tonic-gate int 1404*0Sstevel@tonic-gate meta_logs_print( 1405*0Sstevel@tonic-gate mdsetname_t *sp, 1406*0Sstevel@tonic-gate mdnamelist_t *lognlp, 1407*0Sstevel@tonic-gate mdnamelist_t **nlistpp, 1408*0Sstevel@tonic-gate char *fname, 1409*0Sstevel@tonic-gate FILE *fp, 1410*0Sstevel@tonic-gate mdprtopts_t options, 1411*0Sstevel@tonic-gate md_error_t *ep 1412*0Sstevel@tonic-gate ) 1413*0Sstevel@tonic-gate { 1414*0Sstevel@tonic-gate mdnamelist_t *transnlp = NULL; 1415*0Sstevel@tonic-gate mdnamelist_t *p; 1416*0Sstevel@tonic-gate int rval = 0; 1417*0Sstevel@tonic-gate 1418*0Sstevel@tonic-gate /* must have a set */ 1419*0Sstevel@tonic-gate assert(sp != NULL); 1420*0Sstevel@tonic-gate 1421*0Sstevel@tonic-gate /* get trans devices */ 1422*0Sstevel@tonic-gate if (lognlp == NULL) 1423*0Sstevel@tonic-gate return (0); 1424*0Sstevel@tonic-gate 1425*0Sstevel@tonic-gate if (! (options & PRINT_SHORT)) 1426*0Sstevel@tonic-gate if (meta_get_trans_names(sp, &transnlp, options, ep) < 0) 1427*0Sstevel@tonic-gate return (-1); 1428*0Sstevel@tonic-gate 1429*0Sstevel@tonic-gate /* print all logs */ 1430*0Sstevel@tonic-gate options |= PRINT_SUBDEVS; 1431*0Sstevel@tonic-gate for (p = lognlp; (p != NULL); p = p->next) { 1432*0Sstevel@tonic-gate mdname_t *lognamep = p->namep; 1433*0Sstevel@tonic-gate 1434*0Sstevel@tonic-gate /* print appropriate detail */ 1435*0Sstevel@tonic-gate if (options & PRINT_SHORT) { 1436*0Sstevel@tonic-gate if (log_print(sp, lognamep, fname, fp, options, 1437*0Sstevel@tonic-gate ep) != 0) { 1438*0Sstevel@tonic-gate rval = -1; 1439*0Sstevel@tonic-gate } 1440*0Sstevel@tonic-gate } else { 1441*0Sstevel@tonic-gate if (log_report(sp, lognamep, nlistpp, fname, fp, 1442*0Sstevel@tonic-gate options, transnlp, ep) != 0) { 1443*0Sstevel@tonic-gate rval = -1; 1444*0Sstevel@tonic-gate } 1445*0Sstevel@tonic-gate } 1446*0Sstevel@tonic-gate } 1447*0Sstevel@tonic-gate 1448*0Sstevel@tonic-gate /* cleanup, return success */ 1449*0Sstevel@tonic-gate out: 1450*0Sstevel@tonic-gate metafreenamelist(transnlp); 1451*0Sstevel@tonic-gate return (rval); 1452*0Sstevel@tonic-gate } 1453*0Sstevel@tonic-gate 1454*0Sstevel@tonic-gate /* 1455*0Sstevel@tonic-gate * meta_lockfs_common -- common lock and unlock code 1456*0Sstevel@tonic-gate * 1457*0Sstevel@tonic-gate * Normally this routine will return a 0 for success. Even if 1458*0Sstevel@tonic-gate * lockfs wasn't able to lock down the filesystem. The reason 1459*0Sstevel@tonic-gate * for this is that the master device can be in an errored state 1460*0Sstevel@tonic-gate * and the lock can't be obtained. We don't want to prevent 1461*0Sstevel@tonic-gate * possible recovery in this case and it's not likely any activity 1462*0Sstevel@tonic-gate * will be occurring. If the filesystem is healthy with activity 1463*0Sstevel@tonic-gate * lockfs will successfully lock the filesystem and return an 1464*0Sstevel@tonic-gate * error code of 0. 1465*0Sstevel@tonic-gate * 1466*0Sstevel@tonic-gate * The one case where this routine returns a non-zero value would 1467*0Sstevel@tonic-gate * be if we can't determine the outcome of the lockfs. This should 1468*0Sstevel@tonic-gate * never occur because we don't catch signals that could cause 1469*0Sstevel@tonic-gate * waitpid() to prematurely return. 1470*0Sstevel@tonic-gate */ 1471*0Sstevel@tonic-gate static int 1472*0Sstevel@tonic-gate meta_lockfs_common(mdname_t *fs, void **cookie, int lockit) 1473*0Sstevel@tonic-gate { 1474*0Sstevel@tonic-gate char *blkname; 1475*0Sstevel@tonic-gate FILE *m; 1476*0Sstevel@tonic-gate struct mnttab tab_wildcard, tab_match; 1477*0Sstevel@tonic-gate pid_t pid; 1478*0Sstevel@tonic-gate int lock_exit; 1479*0Sstevel@tonic-gate 1480*0Sstevel@tonic-gate (void) memset(&tab_wildcard, 0, sizeof (tab_wildcard)); 1481*0Sstevel@tonic-gate (void) memset(&tab_match, 0, sizeof (tab_match)); 1482*0Sstevel@tonic-gate 1483*0Sstevel@tonic-gate if ((blkname = fs->bname) == NULL) 1484*0Sstevel@tonic-gate blkname = getfullblkname(fs->cname); 1485*0Sstevel@tonic-gate 1486*0Sstevel@tonic-gate tab_wildcard.mnt_special = blkname; 1487*0Sstevel@tonic-gate 1488*0Sstevel@tonic-gate if ((m = fopen(MNTTAB, "r")) == NULL) { 1489*0Sstevel@tonic-gate /* 1490*0Sstevel@tonic-gate * No mnttab means nothing is mounted 1491*0Sstevel@tonic-gate */ 1492*0Sstevel@tonic-gate *cookie = 0; 1493*0Sstevel@tonic-gate return (0); 1494*0Sstevel@tonic-gate } 1495*0Sstevel@tonic-gate 1496*0Sstevel@tonic-gate if (getmntany(m, &tab_match, &tab_wildcard)) { 1497*0Sstevel@tonic-gate /* 1498*0Sstevel@tonic-gate * No match in mnttab so we're not mounted ... at least 1499*0Sstevel@tonic-gate * nothing better be mounted. 1500*0Sstevel@tonic-gate */ 1501*0Sstevel@tonic-gate *cookie = 0; 1502*0Sstevel@tonic-gate return (0); 1503*0Sstevel@tonic-gate } 1504*0Sstevel@tonic-gate 1505*0Sstevel@tonic-gate (void) fclose(m); 1506*0Sstevel@tonic-gate 1507*0Sstevel@tonic-gate switch (pid = fork()) { 1508*0Sstevel@tonic-gate case -1: 1509*0Sstevel@tonic-gate /* 1510*0Sstevel@tonic-gate * We've got some major trouble here and shouldn't 1511*0Sstevel@tonic-gate * continue. The user needs to clear up the problems 1512*0Sstevel@tonic-gate * that the system currently has before proceeding 1513*0Sstevel@tonic-gate * to detach the log. 1514*0Sstevel@tonic-gate */ 1515*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, "failed to fork lockfs\n")); 1516*0Sstevel@tonic-gate *cookie = 0; 1517*0Sstevel@tonic-gate return (1); 1518*0Sstevel@tonic-gate 1519*0Sstevel@tonic-gate case 0: 1520*0Sstevel@tonic-gate (void) execl("/usr/sbin/lockfs", "lockfs", lockit ? "-w" : "-u", 1521*0Sstevel@tonic-gate "-c", "Solaris Volume Manager detach lock", 1522*0Sstevel@tonic-gate tab_match.mnt_mountp, 0); 1523*0Sstevel@tonic-gate /* 1524*0Sstevel@tonic-gate * Shouldn't reach here, but if this code is run on 1525*0Sstevel@tonic-gate * a release that doesn't have lockfs return an error 1526*0Sstevel@tonic-gate * code so that the -f (force) option could be used 1527*0Sstevel@tonic-gate * by metadetach. 1528*0Sstevel@tonic-gate */ 1529*0Sstevel@tonic-gate exit(1); 1530*0Sstevel@tonic-gate 1531*0Sstevel@tonic-gate default: 1532*0Sstevel@tonic-gate if (waitpid(pid, &lock_exit, 0) != pid) { 1533*0Sstevel@tonic-gate /* 1534*0Sstevel@tonic-gate * We couldn't get status regarding the 1535*0Sstevel@tonic-gate * outcome of the lockfs command. We should 1536*0Sstevel@tonic-gate * attempt to unlock the filesystem though. 1537*0Sstevel@tonic-gate * Return an error code so that if the user 1538*0Sstevel@tonic-gate * is trying to force the detach make them 1539*0Sstevel@tonic-gate * clear up this problem first. 1540*0Sstevel@tonic-gate */ 1541*0Sstevel@tonic-gate *cookie = (void *)1; 1542*0Sstevel@tonic-gate return (1); 1543*0Sstevel@tonic-gate } 1544*0Sstevel@tonic-gate 1545*0Sstevel@tonic-gate *cookie = (void *)1; 1546*0Sstevel@tonic-gate return (0); 1547*0Sstevel@tonic-gate } 1548*0Sstevel@tonic-gate } 1549*0Sstevel@tonic-gate 1550*0Sstevel@tonic-gate /* 1551*0Sstevel@tonic-gate * meta_lockfs - if mounted, lock a given device against writes 1552*0Sstevel@tonic-gate * 1553*0Sstevel@tonic-gate * See comment section for meta_lockfs_common 1554*0Sstevel@tonic-gate */ 1555*0Sstevel@tonic-gate static int 1556*0Sstevel@tonic-gate meta_lockfs(mdname_t *fs, void **cookie) 1557*0Sstevel@tonic-gate { 1558*0Sstevel@tonic-gate return (meta_lockfs_common(fs, cookie, 1)); 1559*0Sstevel@tonic-gate } 1560*0Sstevel@tonic-gate 1561*0Sstevel@tonic-gate /* 1562*0Sstevel@tonic-gate * meta_unlockfs - if mounted, unlock the filesystem if previously locked 1563*0Sstevel@tonic-gate * 1564*0Sstevel@tonic-gate * See comment section for meta_lockfs_common 1565*0Sstevel@tonic-gate */ 1566*0Sstevel@tonic-gate static void 1567*0Sstevel@tonic-gate meta_unlockfs(mdname_t *fs, void **cookie) 1568*0Sstevel@tonic-gate { 1569*0Sstevel@tonic-gate /* 1570*0Sstevel@tonic-gate * Simple time saver. We could always try to unlock 1571*0Sstevel@tonic-gate * the filesystem, that takes time a resources. 1572*0Sstevel@tonic-gate */ 1573*0Sstevel@tonic-gate if (*cookie == (void *)1) 1574*0Sstevel@tonic-gate (void) meta_lockfs_common(fs, cookie, 0); 1575*0Sstevel@tonic-gate } 1576*0Sstevel@tonic-gate 1577*0Sstevel@tonic-gate /* 1578*0Sstevel@tonic-gate * meta_trans_detach -- detach log from trans device 1579*0Sstevel@tonic-gate */ 1580*0Sstevel@tonic-gate int 1581*0Sstevel@tonic-gate meta_trans_detach( 1582*0Sstevel@tonic-gate mdsetname_t *sp, 1583*0Sstevel@tonic-gate mdname_t *transnp, 1584*0Sstevel@tonic-gate mdcmdopts_t options, 1585*0Sstevel@tonic-gate int *delayed, 1586*0Sstevel@tonic-gate md_error_t *ep 1587*0Sstevel@tonic-gate ) 1588*0Sstevel@tonic-gate { 1589*0Sstevel@tonic-gate int force = ((options & MDCMD_FORCE) ? 1 : 0); 1590*0Sstevel@tonic-gate md_i_get_t detach; 1591*0Sstevel@tonic-gate md_trans_t *transp; 1592*0Sstevel@tonic-gate mdname_t *lognp; 1593*0Sstevel@tonic-gate void *lock_cookie; 1594*0Sstevel@tonic-gate 1595*0Sstevel@tonic-gate /* should have a set */ 1596*0Sstevel@tonic-gate assert(sp != NULL); 1597*0Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(transnp->dev))); 1598*0Sstevel@tonic-gate 1599*0Sstevel@tonic-gate /* check name */ 1600*0Sstevel@tonic-gate if (metachkmeta(transnp, ep) != 0) 1601*0Sstevel@tonic-gate return (-1); 1602*0Sstevel@tonic-gate 1603*0Sstevel@tonic-gate /* save log name */ 1604*0Sstevel@tonic-gate if ((transp = meta_get_trans(sp, transnp, ep)) == NULL) 1605*0Sstevel@tonic-gate return (-1); 1606*0Sstevel@tonic-gate if ((lognp = transp->lognamep) == NULL) 1607*0Sstevel@tonic-gate return (mdmderror(ep, MDE_NO_LOG, meta_getminor(transnp->dev), 1608*0Sstevel@tonic-gate transnp->cname)); 1609*0Sstevel@tonic-gate 1610*0Sstevel@tonic-gate /* 1611*0Sstevel@tonic-gate * If trans device is mounted lock the filesystem 1612*0Sstevel@tonic-gate * against writes and mod time updates. 1613*0Sstevel@tonic-gate */ 1614*0Sstevel@tonic-gate if (force && meta_lockfs(transnp, &lock_cookie)) { 1615*0Sstevel@tonic-gate /* 1616*0Sstevel@tonic-gate * This device is mounted and we were unable 1617*0Sstevel@tonic-gate * lock the device. Data corruption can occur 1618*0Sstevel@tonic-gate * if we don't lock the device before removing 1619*0Sstevel@tonic-gate * the log so bail out here. 1620*0Sstevel@tonic-gate * NOTE: There's one case were the exist status 1621*0Sstevel@tonic-gate * of lockfs could have been lost yet the command 1622*0Sstevel@tonic-gate * could have run. We should try to unlock the filesystem 1623*0Sstevel@tonic-gate * before returning. 1624*0Sstevel@tonic-gate */ 1625*0Sstevel@tonic-gate meta_unlockfs(transnp, &lock_cookie); 1626*0Sstevel@tonic-gate return (mdmderror(ep, MDE_UNKNOWN_TYPE, 1627*0Sstevel@tonic-gate meta_getminor(transnp->dev), transnp->cname)); 1628*0Sstevel@tonic-gate } 1629*0Sstevel@tonic-gate 1630*0Sstevel@tonic-gate /* detach log */ 1631*0Sstevel@tonic-gate *delayed = 0; 1632*0Sstevel@tonic-gate (void) memset(&detach, 0, sizeof (detach)); 1633*0Sstevel@tonic-gate detach.id = meta_getminor(transnp->dev); 1634*0Sstevel@tonic-gate MD_SETDRIVERNAME(&detach, MD_TRANS, sp->setno); 1635*0Sstevel@tonic-gate detach.size = force; 1636*0Sstevel@tonic-gate if (metaioctl(MD_IOC_TRANS_DETACH, &detach, &detach.mde, NULL) != 0) { 1637*0Sstevel@tonic-gate /* delayed detach */ 1638*0Sstevel@tonic-gate if ((force) && (mdissyserror(&detach.mde, EBUSY))) { 1639*0Sstevel@tonic-gate *delayed = 1; 1640*0Sstevel@tonic-gate mdclrerror(&detach.mde); 1641*0Sstevel@tonic-gate } else { 1642*0Sstevel@tonic-gate meta_unlockfs(transnp, &lock_cookie); 1643*0Sstevel@tonic-gate return (mdstealerror(ep, &detach.mde)); 1644*0Sstevel@tonic-gate } 1645*0Sstevel@tonic-gate } 1646*0Sstevel@tonic-gate 1647*0Sstevel@tonic-gate /* 1648*0Sstevel@tonic-gate * Unlock the filesystem 1649*0Sstevel@tonic-gate */ 1650*0Sstevel@tonic-gate meta_unlockfs(transnp, &lock_cookie); 1651*0Sstevel@tonic-gate 1652*0Sstevel@tonic-gate /* clear cache */ 1653*0Sstevel@tonic-gate meta_invalidate_name(lognp); 1654*0Sstevel@tonic-gate meta_invalidate_name(transnp); 1655*0Sstevel@tonic-gate 1656*0Sstevel@tonic-gate /* let em know */ 1657*0Sstevel@tonic-gate if (options & MDCMD_PRINT) { 1658*0Sstevel@tonic-gate if (*delayed) { 1659*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 1660*0Sstevel@tonic-gate "%s: logging device %s will be detached at unmount or reboot\n"), 1661*0Sstevel@tonic-gate transnp->cname, lognp->cname); 1662*0Sstevel@tonic-gate } else { 1663*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, 1664*0Sstevel@tonic-gate "%s: logging device %s is detached\n"), 1665*0Sstevel@tonic-gate transnp->cname, lognp->cname); 1666*0Sstevel@tonic-gate } 1667*0Sstevel@tonic-gate (void) fflush(stdout); 1668*0Sstevel@tonic-gate } 1669*0Sstevel@tonic-gate 1670*0Sstevel@tonic-gate /* return success */ 1671*0Sstevel@tonic-gate return (0); 1672*0Sstevel@tonic-gate } 1673*0Sstevel@tonic-gate 1674*0Sstevel@tonic-gate /* 1675*0Sstevel@tonic-gate * reset trans 1676*0Sstevel@tonic-gate */ 1677*0Sstevel@tonic-gate int 1678*0Sstevel@tonic-gate meta_trans_reset( 1679*0Sstevel@tonic-gate mdsetname_t *sp, 1680*0Sstevel@tonic-gate mdname_t *transnp, 1681*0Sstevel@tonic-gate mdcmdopts_t options, 1682*0Sstevel@tonic-gate md_error_t *ep 1683*0Sstevel@tonic-gate ) 1684*0Sstevel@tonic-gate { 1685*0Sstevel@tonic-gate md_trans_t *transp; 1686*0Sstevel@tonic-gate int rval = -1; 1687*0Sstevel@tonic-gate 1688*0Sstevel@tonic-gate /* should have a set */ 1689*0Sstevel@tonic-gate assert(sp != NULL); 1690*0Sstevel@tonic-gate assert((transnp == NULL) || 1691*0Sstevel@tonic-gate (sp->setno == MD_MIN2SET(meta_getminor(transnp->dev)))); 1692*0Sstevel@tonic-gate 1693*0Sstevel@tonic-gate /* reset all trans */ 1694*0Sstevel@tonic-gate if (transnp == NULL) { 1695*0Sstevel@tonic-gate mdnamelist_t *transnlp = NULL; 1696*0Sstevel@tonic-gate mdnamelist_t *p; 1697*0Sstevel@tonic-gate 1698*0Sstevel@tonic-gate /* for each trans */ 1699*0Sstevel@tonic-gate rval = 0; 1700*0Sstevel@tonic-gate if (meta_get_trans_names(sp, &transnlp, 0, ep) < 0) 1701*0Sstevel@tonic-gate return (-1); 1702*0Sstevel@tonic-gate for (p = transnlp; (p != NULL); p = p->next) { 1703*0Sstevel@tonic-gate /* reset trans */ 1704*0Sstevel@tonic-gate transnp = p->namep; 1705*0Sstevel@tonic-gate if (meta_trans_reset(sp, transnp, options, ep) != 0) { 1706*0Sstevel@tonic-gate rval = -1; 1707*0Sstevel@tonic-gate break; 1708*0Sstevel@tonic-gate } 1709*0Sstevel@tonic-gate } 1710*0Sstevel@tonic-gate 1711*0Sstevel@tonic-gate /* cleanup, return success */ 1712*0Sstevel@tonic-gate metafreenamelist(transnlp); 1713*0Sstevel@tonic-gate return (rval); 1714*0Sstevel@tonic-gate } 1715*0Sstevel@tonic-gate 1716*0Sstevel@tonic-gate /* check name */ 1717*0Sstevel@tonic-gate if (metachkmeta(transnp, ep) != 0) 1718*0Sstevel@tonic-gate return (-1); 1719*0Sstevel@tonic-gate /* get unit structure */ 1720*0Sstevel@tonic-gate if ((transp = meta_get_trans(sp, transnp, ep)) == NULL) 1721*0Sstevel@tonic-gate return (-1); 1722*0Sstevel@tonic-gate 1723*0Sstevel@tonic-gate /* make sure nobody owns us */ 1724*0Sstevel@tonic-gate if (MD_HAS_PARENT(transp->common.parent)) { 1725*0Sstevel@tonic-gate return (mdmderror(ep, MDE_IN_USE, meta_getminor(transnp->dev), 1726*0Sstevel@tonic-gate transnp->cname)); 1727*0Sstevel@tonic-gate } 1728*0Sstevel@tonic-gate 1729*0Sstevel@tonic-gate /* clear subdevices cache */ 1730*0Sstevel@tonic-gate meta_invalidate_name(transp->masternamep); 1731*0Sstevel@tonic-gate if (transp->lognamep) 1732*0Sstevel@tonic-gate meta_invalidate_name(transp->lognamep); 1733*0Sstevel@tonic-gate 1734*0Sstevel@tonic-gate /* clear metadevice */ 1735*0Sstevel@tonic-gate if (meta_reset(sp, transnp, options, ep) != 0) 1736*0Sstevel@tonic-gate goto out; 1737*0Sstevel@tonic-gate rval = 0; /* success */ 1738*0Sstevel@tonic-gate 1739*0Sstevel@tonic-gate /* let em know */ 1740*0Sstevel@tonic-gate if (options & MDCMD_PRINT) { 1741*0Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, "%s: Trans is cleared\n"), 1742*0Sstevel@tonic-gate transnp->cname); 1743*0Sstevel@tonic-gate (void) fflush(stdout); 1744*0Sstevel@tonic-gate } 1745*0Sstevel@tonic-gate 1746*0Sstevel@tonic-gate /* clear subdevices */ 1747*0Sstevel@tonic-gate if (! (options & MDCMD_RECURSE)) 1748*0Sstevel@tonic-gate goto out; 1749*0Sstevel@tonic-gate if (metaismeta(transp->masternamep)) { 1750*0Sstevel@tonic-gate mdname_t *masternp = transp->masternamep; 1751*0Sstevel@tonic-gate 1752*0Sstevel@tonic-gate if (meta_reset_by_name(sp, masternp, options, ep) != 0) 1753*0Sstevel@tonic-gate rval = -1; 1754*0Sstevel@tonic-gate } 1755*0Sstevel@tonic-gate /* (multi-parented) log will be cleared later */ 1756*0Sstevel@tonic-gate 1757*0Sstevel@tonic-gate /* cleanup, return success */ 1758*0Sstevel@tonic-gate out: 1759*0Sstevel@tonic-gate meta_invalidate_name(transnp); 1760*0Sstevel@tonic-gate return (rval); 1761*0Sstevel@tonic-gate } 1762