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 2005 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 #include <sys/param.h> 30*0Sstevel@tonic-gate #include <sys/systm.h> 31*0Sstevel@tonic-gate #include <sys/conf.h> 32*0Sstevel@tonic-gate #include <sys/debug.h> 33*0Sstevel@tonic-gate #include <sys/file.h> 34*0Sstevel@tonic-gate #include <sys/user.h> 35*0Sstevel@tonic-gate #include <sys/uio.h> 36*0Sstevel@tonic-gate #include <sys/dkio.h> 37*0Sstevel@tonic-gate #include <sys/vtoc.h> 38*0Sstevel@tonic-gate #include <sys/kmem.h> 39*0Sstevel@tonic-gate #include <vm/page.h> 40*0Sstevel@tonic-gate #include <sys/cmn_err.h> 41*0Sstevel@tonic-gate #include <sys/sysmacros.h> 42*0Sstevel@tonic-gate #include <sys/types.h> 43*0Sstevel@tonic-gate #include <sys/mkdev.h> 44*0Sstevel@tonic-gate #include <sys/stat.h> 45*0Sstevel@tonic-gate #include <sys/open.h> 46*0Sstevel@tonic-gate #include <sys/modctl.h> 47*0Sstevel@tonic-gate #include <sys/ddi.h> 48*0Sstevel@tonic-gate #include <sys/sunddi.h> 49*0Sstevel@tonic-gate #include <sys/disp.h> 50*0Sstevel@tonic-gate #include <sys/buf.h> 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate #include <sys/lvm/mdvar.h> 53*0Sstevel@tonic-gate #include <sys/lvm/md_trans.h> 54*0Sstevel@tonic-gate #include <sys/lvm/md_notify.h> 55*0Sstevel@tonic-gate #include <sys/lvm/md_convert.h> 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate #include <sys/sysevent/eventdefs.h> 58*0Sstevel@tonic-gate #include <sys/sysevent/svm.h> 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate md_ops_t trans_md_ops; 61*0Sstevel@tonic-gate #ifndef lint 62*0Sstevel@tonic-gate static char _depends_on[] = "drv/md fs/ufs"; 63*0Sstevel@tonic-gate md_ops_t *md_interface_ops = &trans_md_ops; 64*0Sstevel@tonic-gate #endif /* lint */ 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate extern unit_t md_nunits; 67*0Sstevel@tonic-gate extern set_t md_nsets; 68*0Sstevel@tonic-gate extern md_set_t md_set[]; 69*0Sstevel@tonic-gate extern int md_status; 70*0Sstevel@tonic-gate extern major_t md_major; 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate extern int md_trans_ioctl(); 73*0Sstevel@tonic-gate extern md_krwlock_t md_unit_array_rw; 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gate extern mdq_anchor_t md_done_daemon; 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate extern int md_in_upgrade; 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gate static kmem_cache_t *trans_parent_cache = NULL; 80*0Sstevel@tonic-gate kmem_cache_t *trans_child_cache = NULL; 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate #ifdef DEBUG 83*0Sstevel@tonic-gate /* 84*0Sstevel@tonic-gate * ROUTINES FOR TESTING: 85*0Sstevel@tonic-gate */ 86*0Sstevel@tonic-gate static int 87*0Sstevel@tonic-gate _init_debug() 88*0Sstevel@tonic-gate { 89*0Sstevel@tonic-gate extern int _init_ioctl(); 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate return (_init_ioctl()); 92*0Sstevel@tonic-gate } 93*0Sstevel@tonic-gate static int 94*0Sstevel@tonic-gate _fini_debug() 95*0Sstevel@tonic-gate { 96*0Sstevel@tonic-gate extern int _fini_ioctl(); 97*0Sstevel@tonic-gate int err = 0; 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate err = _fini_ioctl(); 100*0Sstevel@tonic-gate return (err); 101*0Sstevel@tonic-gate } 102*0Sstevel@tonic-gate 103*0Sstevel@tonic-gate #endif /* DEBUG */ 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate /* 106*0Sstevel@tonic-gate * BEGIN RELEASE DEBUG 107*0Sstevel@tonic-gate * The following routines remain in the released product for testability 108*0Sstevel@tonic-gate */ 109*0Sstevel@tonic-gate int 110*0Sstevel@tonic-gate trans_done_shadow(buf_t *bp) 111*0Sstevel@tonic-gate { 112*0Sstevel@tonic-gate buf_t *pb; 113*0Sstevel@tonic-gate md_tps_t *ps = (md_tps_t *)bp->b_chain; 114*0Sstevel@tonic-gate int rv = 0; 115*0Sstevel@tonic-gate 116*0Sstevel@tonic-gate pb = ps->ps_bp; 117*0Sstevel@tonic-gate mutex_enter(&ps->ps_mx); 118*0Sstevel@tonic-gate ps->ps_count--; 119*0Sstevel@tonic-gate if (ps->ps_count > 0) { 120*0Sstevel@tonic-gate if ((bp->b_flags & B_ERROR) != 0) { 121*0Sstevel@tonic-gate pb->b_flags |= B_ERROR; 122*0Sstevel@tonic-gate pb->b_error = bp->b_error; 123*0Sstevel@tonic-gate } 124*0Sstevel@tonic-gate mutex_exit(&ps->ps_mx); 125*0Sstevel@tonic-gate kmem_cache_free(trans_child_cache, bp); 126*0Sstevel@tonic-gate } else { 127*0Sstevel@tonic-gate mutex_exit(&ps->ps_mx); 128*0Sstevel@tonic-gate mutex_destroy(&ps->ps_mx); 129*0Sstevel@tonic-gate rv = trans_done(bp); 130*0Sstevel@tonic-gate } 131*0Sstevel@tonic-gate return (rv); 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate static void 135*0Sstevel@tonic-gate shadow_debug(mt_unit_t *un, /* trans unit info */ 136*0Sstevel@tonic-gate buf_t *pb, /* primary buffer */ 137*0Sstevel@tonic-gate md_tps_t *ps, /* trans parent save */ 138*0Sstevel@tonic-gate buf_t *cb, /* buffer for writing to master */ 139*0Sstevel@tonic-gate int flag, 140*0Sstevel@tonic-gate void *private) 141*0Sstevel@tonic-gate { 142*0Sstevel@tonic-gate buf_t *sb; /* Shadow buffer */ 143*0Sstevel@tonic-gate 144*0Sstevel@tonic-gate mutex_init(&ps->ps_mx, NULL, MUTEX_DEFAULT, NULL); 145*0Sstevel@tonic-gate ps->ps_count = 2; /* Write child buffer & shadow */ 146*0Sstevel@tonic-gate cb->b_iodone = trans_done_shadow; 147*0Sstevel@tonic-gate sb = kmem_cache_alloc(trans_child_cache, MD_ALLOCFLAGS); 148*0Sstevel@tonic-gate trans_child_init(sb); 149*0Sstevel@tonic-gate sb = bioclone(pb, 0, pb->b_bcount, md_dev64_to_dev(un->un_s_dev), 150*0Sstevel@tonic-gate pb->b_blkno, trans_done_shadow, sb, KM_NOSLEEP); 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate sb->b_flags |= B_ASYNC; 153*0Sstevel@tonic-gate sb->b_chain = (void *)ps; 154*0Sstevel@tonic-gate md_call_strategy(sb, flag | MD_STR_MAPPED, private); 155*0Sstevel@tonic-gate } 156*0Sstevel@tonic-gate /* 157*0Sstevel@tonic-gate * END RELEASE DEBUG 158*0Sstevel@tonic-gate */ 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate /* 161*0Sstevel@tonic-gate * COMMON MEMORY ALLOCATION ROUTINES (so that we can discover leaks) 162*0Sstevel@tonic-gate */ 163*0Sstevel@tonic-gate void * 164*0Sstevel@tonic-gate md_trans_zalloc(size_t nb) 165*0Sstevel@tonic-gate { 166*0Sstevel@tonic-gate TRANSSTATS(ts_trans_zalloc); 167*0Sstevel@tonic-gate TRANSSTATSADD(ts_trans_alloced, nb); 168*0Sstevel@tonic-gate return (kmem_zalloc(nb, KM_SLEEP)); 169*0Sstevel@tonic-gate } 170*0Sstevel@tonic-gate void * 171*0Sstevel@tonic-gate md_trans_alloc(size_t nb) 172*0Sstevel@tonic-gate { 173*0Sstevel@tonic-gate TRANSSTATS(ts_trans_alloc); 174*0Sstevel@tonic-gate TRANSSTATSADD(ts_trans_alloced, nb); 175*0Sstevel@tonic-gate return (kmem_alloc(nb, KM_SLEEP)); 176*0Sstevel@tonic-gate } 177*0Sstevel@tonic-gate void 178*0Sstevel@tonic-gate md_trans_free(void *va, size_t nb) 179*0Sstevel@tonic-gate { 180*0Sstevel@tonic-gate TRANSSTATS(ts_trans_free); 181*0Sstevel@tonic-gate TRANSSTATSADD(ts_trans_freed, nb); 182*0Sstevel@tonic-gate if (nb) 183*0Sstevel@tonic-gate kmem_free(va, nb); 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate 186*0Sstevel@tonic-gate static void 187*0Sstevel@tonic-gate trans_parent_init(md_tps_t *ps) 188*0Sstevel@tonic-gate { 189*0Sstevel@tonic-gate bzero(ps, sizeof (md_tps_t)); 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate /*ARGSUSED1*/ 193*0Sstevel@tonic-gate int 194*0Sstevel@tonic-gate trans_child_constructor(void *p, void *d1, int d2) 195*0Sstevel@tonic-gate { 196*0Sstevel@tonic-gate bioinit(p); 197*0Sstevel@tonic-gate return (0); 198*0Sstevel@tonic-gate } 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate void 201*0Sstevel@tonic-gate trans_child_init(struct buf *bp) 202*0Sstevel@tonic-gate { 203*0Sstevel@tonic-gate md_bioreset(bp); 204*0Sstevel@tonic-gate } 205*0Sstevel@tonic-gate 206*0Sstevel@tonic-gate /*ARGSUSED1*/ 207*0Sstevel@tonic-gate void 208*0Sstevel@tonic-gate trans_child_destructor(void *p, void *d) 209*0Sstevel@tonic-gate { 210*0Sstevel@tonic-gate biofini(p); 211*0Sstevel@tonic-gate } 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate void 214*0Sstevel@tonic-gate trans_commit(mt_unit_t *un, int domstr) 215*0Sstevel@tonic-gate { 216*0Sstevel@tonic-gate mddb_recid_t recids[4]; 217*0Sstevel@tonic-gate md_unit_t *su; 218*0Sstevel@tonic-gate int ri = 0; 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate if (md_get_setstatus(MD_UN2SET(un)) & MD_SET_STALE) 221*0Sstevel@tonic-gate return; 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate recids[ri++] = un->c.un_record_id; 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate if (domstr) 226*0Sstevel@tonic-gate if (md_getmajor(un->un_m_dev) == md_major) { 227*0Sstevel@tonic-gate su = MD_UNIT(md_getminor(un->un_m_dev)); 228*0Sstevel@tonic-gate recids[ri++] = su->c.un_record_id; 229*0Sstevel@tonic-gate } 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate if (ri == 0) 232*0Sstevel@tonic-gate return; 233*0Sstevel@tonic-gate recids[ri] = 0; 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate uniqtime32(&un->un_timestamp); 236*0Sstevel@tonic-gate mddb_commitrecs_wrapper(recids); 237*0Sstevel@tonic-gate } 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate void 240*0Sstevel@tonic-gate trans_close_all_devs(mt_unit_t *un) 241*0Sstevel@tonic-gate { 242*0Sstevel@tonic-gate if ((un->un_flags & TRANS_NEED_OPEN) == 0) { 243*0Sstevel@tonic-gate md_layered_close(un->un_m_dev, MD_OFLG_NULL); 244*0Sstevel@tonic-gate if (un->un_l_unit) 245*0Sstevel@tonic-gate ldl_close_dev(un->un_l_unit); 246*0Sstevel@tonic-gate un->un_flags |= TRANS_NEED_OPEN; 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate } 249*0Sstevel@tonic-gate 250*0Sstevel@tonic-gate int 251*0Sstevel@tonic-gate trans_open_all_devs(mt_unit_t *un) 252*0Sstevel@tonic-gate { 253*0Sstevel@tonic-gate int err; 254*0Sstevel@tonic-gate minor_t mnum = MD_SID(un); 255*0Sstevel@tonic-gate md_dev64_t tmpdev = un->un_m_dev; 256*0Sstevel@tonic-gate set_t setno = MD_MIN2SET(MD_SID(un)); 257*0Sstevel@tonic-gate side_t side = mddb_getsidenum(setno); 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate /* 260*0Sstevel@tonic-gate * Do the open by device id if it is regular device 261*0Sstevel@tonic-gate */ 262*0Sstevel@tonic-gate if ((md_getmajor(tmpdev) != md_major) && 263*0Sstevel@tonic-gate md_devid_found(setno, side, un->un_m_key) == 1) { 264*0Sstevel@tonic-gate tmpdev = md_resolve_bydevid(mnum, tmpdev, un->un_m_key); 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate err = md_layered_open(mnum, &tmpdev, MD_OFLG_NULL); 267*0Sstevel@tonic-gate un->un_m_dev = tmpdev; 268*0Sstevel@tonic-gate 269*0Sstevel@tonic-gate if (err) 270*0Sstevel@tonic-gate return (ENXIO); 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate if (un->un_l_unit) { 273*0Sstevel@tonic-gate err = ldl_open_dev(un, un->un_l_unit); 274*0Sstevel@tonic-gate if (err) { 275*0Sstevel@tonic-gate md_layered_close(tmpdev, MD_OFLG_NULL); 276*0Sstevel@tonic-gate return (ENXIO); 277*0Sstevel@tonic-gate } 278*0Sstevel@tonic-gate } 279*0Sstevel@tonic-gate return (0); 280*0Sstevel@tonic-gate } 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate uint_t mt_debug = 0; 283*0Sstevel@tonic-gate 284*0Sstevel@tonic-gate int 285*0Sstevel@tonic-gate trans_build_incore(void *p, int snarfing) 286*0Sstevel@tonic-gate { 287*0Sstevel@tonic-gate mt_unit_t *un = (mt_unit_t *)p; 288*0Sstevel@tonic-gate minor_t mnum; 289*0Sstevel@tonic-gate set_t setno; 290*0Sstevel@tonic-gate 291*0Sstevel@tonic-gate /* 292*0Sstevel@tonic-gate * initialize debug mode and always start with no shadowing. 293*0Sstevel@tonic-gate */ 294*0Sstevel@tonic-gate if (!snarfing) 295*0Sstevel@tonic-gate un->un_debug = mt_debug; 296*0Sstevel@tonic-gate un->un_s_dev = NODEV64; 297*0Sstevel@tonic-gate 298*0Sstevel@tonic-gate mnum = MD_SID(un); 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate if (MD_UNIT(mnum) != NULL) 301*0Sstevel@tonic-gate return (0); 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate setno = MD_MIN2SET(mnum); 304*0Sstevel@tonic-gate 305*0Sstevel@tonic-gate /* 306*0Sstevel@tonic-gate * If snarfing the metatrans device, 307*0Sstevel@tonic-gate * then remake the device number 308*0Sstevel@tonic-gate */ 309*0Sstevel@tonic-gate if (snarfing) { 310*0Sstevel@tonic-gate un->un_m_dev = md_getdevnum(setno, mddb_getsidenum(setno), 311*0Sstevel@tonic-gate un->un_m_key, MD_NOTRUST_DEVT); 312*0Sstevel@tonic-gate } 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate /* 315*0Sstevel@tonic-gate * db rec is partially deleted; finish the db delete later 316*0Sstevel@tonic-gate */ 317*0Sstevel@tonic-gate if (MD_STATUS(un) & MD_UN_BEING_RESET) { 318*0Sstevel@tonic-gate mddb_setrecprivate(un->c.un_record_id, MD_PRV_PENDCLEAN); 319*0Sstevel@tonic-gate return (1); 320*0Sstevel@tonic-gate } 321*0Sstevel@tonic-gate 322*0Sstevel@tonic-gate /* 323*0Sstevel@tonic-gate * With the current device id implementation there is possibility 324*0Sstevel@tonic-gate * that we may have NODEV if the underlying can't be resolved at 325*0Sstevel@tonic-gate * snarf time. If this is the case we want to be consistent with 326*0Sstevel@tonic-gate * the normal behavior and continue to allow the snarf of unit 327*0Sstevel@tonic-gate * and resolve the devt at the open time 328*0Sstevel@tonic-gate */ 329*0Sstevel@tonic-gate if ((md_getmajor(un->un_m_dev) == md_major) && 330*0Sstevel@tonic-gate (md_dev_exists(un->un_m_dev) == 0)) { 331*0Sstevel@tonic-gate return (1); 332*0Sstevel@tonic-gate } 333*0Sstevel@tonic-gate 334*0Sstevel@tonic-gate /* 335*0Sstevel@tonic-gate * retain the detach status; reset open status 336*0Sstevel@tonic-gate */ 337*0Sstevel@tonic-gate un->un_flags &= (TRANS_DETACHING | TRANS_DETACHED); 338*0Sstevel@tonic-gate un->un_flags |= TRANS_NEED_OPEN; 339*0Sstevel@tonic-gate if ((un->un_flags & TRANS_DETACHED) == 0) 340*0Sstevel@tonic-gate un->un_flags |= TRANS_ATTACHING; 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate /* 343*0Sstevel@tonic-gate * log device not set up yet; try again later 344*0Sstevel@tonic-gate */ 345*0Sstevel@tonic-gate if ((un->un_flags & TRANS_DETACHED) == 0) 346*0Sstevel@tonic-gate if (ldl_findlog(un->un_l_recid) == NULL) 347*0Sstevel@tonic-gate return (1); 348*0Sstevel@tonic-gate 349*0Sstevel@tonic-gate /* 350*0Sstevel@tonic-gate * initialize incore fields 351*0Sstevel@tonic-gate */ 352*0Sstevel@tonic-gate un->un_next = NULL; 353*0Sstevel@tonic-gate un->un_l_unit = NULL; 354*0Sstevel@tonic-gate un->un_deltamap = NULL; 355*0Sstevel@tonic-gate un->un_udmap = NULL; 356*0Sstevel@tonic-gate un->un_logmap = NULL; 357*0Sstevel@tonic-gate un->un_matamap = NULL; 358*0Sstevel@tonic-gate un->un_shadowmap = NULL; 359*0Sstevel@tonic-gate un->un_ut = NULL; 360*0Sstevel@tonic-gate un->un_logreset = 0; 361*0Sstevel@tonic-gate un->un_dev = md_makedevice(md_major, mnum); 362*0Sstevel@tonic-gate MD_STATUS(un) = 0; 363*0Sstevel@tonic-gate 364*0Sstevel@tonic-gate /* necessary because capability didn't exist pre-4.1 */ 365*0Sstevel@tonic-gate MD_CAPAB(un) = (MD_CAN_META_CHILD & ~MD_CAN_PARENT); 366*0Sstevel@tonic-gate 367*0Sstevel@tonic-gate /* 368*0Sstevel@tonic-gate * attach the log 369*0Sstevel@tonic-gate */ 370*0Sstevel@tonic-gate trans_attach(un, 0); 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate /* 373*0Sstevel@tonic-gate * check for master dev dynconcat 374*0Sstevel@tonic-gate */ 375*0Sstevel@tonic-gate if (md_getmajor(un->un_m_dev) == md_major) { 376*0Sstevel@tonic-gate struct mdc_unit *c; 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate c = MD_UNIT(md_getminor(un->un_m_dev)); 379*0Sstevel@tonic-gate un->c.un_total_blocks = c->un_total_blocks; 380*0Sstevel@tonic-gate } 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate MD_UNIT(mnum) = un; 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate return (0); 385*0Sstevel@tonic-gate } 386*0Sstevel@tonic-gate 387*0Sstevel@tonic-gate int 388*0Sstevel@tonic-gate trans_detach(mt_unit_t *un, int force) 389*0Sstevel@tonic-gate { 390*0Sstevel@tonic-gate mdi_unit_t *ui = MDI_UNIT(MD_SID(un)); 391*0Sstevel@tonic-gate int error = 0; 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate /* 394*0Sstevel@tonic-gate * The caller is responsible for single-threading this routine. 395*0Sstevel@tonic-gate */ 396*0Sstevel@tonic-gate 397*0Sstevel@tonic-gate if (ui == NULL) 398*0Sstevel@tonic-gate return (0); 399*0Sstevel@tonic-gate 400*0Sstevel@tonic-gate /* 401*0Sstevel@tonic-gate * already detached or the log isn't attached yet; do nothing 402*0Sstevel@tonic-gate */ 403*0Sstevel@tonic-gate if (un->un_flags & (TRANS_DETACHED | TRANS_ATTACHING)) 404*0Sstevel@tonic-gate return (0); 405*0Sstevel@tonic-gate 406*0Sstevel@tonic-gate /* 407*0Sstevel@tonic-gate * set state to detaching 408*0Sstevel@tonic-gate */ 409*0Sstevel@tonic-gate if (force || !md_unit_isopen(ui)) { 410*0Sstevel@tonic-gate un->un_flags |= TRANS_DETACHING; 411*0Sstevel@tonic-gate if (!MD_UPGRADE) { 412*0Sstevel@tonic-gate trans_commit(un, 0); 413*0Sstevel@tonic-gate } 414*0Sstevel@tonic-gate SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_DETACHING, TAG_METADEVICE, 415*0Sstevel@tonic-gate MD_UN2SET(un), MD_SID(un)); 416*0Sstevel@tonic-gate } 417*0Sstevel@tonic-gate 418*0Sstevel@tonic-gate /* 419*0Sstevel@tonic-gate * device is busy 420*0Sstevel@tonic-gate */ 421*0Sstevel@tonic-gate if (md_unit_isopen(ui)) 422*0Sstevel@tonic-gate return (EBUSY); 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gate /* 425*0Sstevel@tonic-gate * detach the log 426*0Sstevel@tonic-gate * if successful 427*0Sstevel@tonic-gate * flags committed to TRANS_DETACHED in database 428*0Sstevel@tonic-gate * un->un_l_unit set to NULL 429*0Sstevel@tonic-gate * no error returned 430*0Sstevel@tonic-gate */ 431*0Sstevel@tonic-gate error = ldl_reset(un, 1, force); 432*0Sstevel@tonic-gate if (error) 433*0Sstevel@tonic-gate return (error); 434*0Sstevel@tonic-gate 435*0Sstevel@tonic-gate /* 436*0Sstevel@tonic-gate * commit to database 437*0Sstevel@tonic-gate */ 438*0Sstevel@tonic-gate if (!MD_UPGRADE) { 439*0Sstevel@tonic-gate trans_commit(un, 0); 440*0Sstevel@tonic-gate } 441*0Sstevel@tonic-gate SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_DETACH, TAG_METADEVICE, MD_UN2SET(un), 442*0Sstevel@tonic-gate MD_SID(un)); 443*0Sstevel@tonic-gate 444*0Sstevel@tonic-gate return (0); 445*0Sstevel@tonic-gate } 446*0Sstevel@tonic-gate 447*0Sstevel@tonic-gate void 448*0Sstevel@tonic-gate trans_attach(mt_unit_t *un, int attaching) 449*0Sstevel@tonic-gate { 450*0Sstevel@tonic-gate mdi_unit_t *ui = MDI_UNIT(MD_SID(un)); 451*0Sstevel@tonic-gate ml_unit_t *ul; 452*0Sstevel@tonic-gate 453*0Sstevel@tonic-gate /* 454*0Sstevel@tonic-gate * called from snarf, set, and attach. Hence, the attaching param 455*0Sstevel@tonic-gate * The caller is responsible for single-threading this routine. 456*0Sstevel@tonic-gate */ 457*0Sstevel@tonic-gate 458*0Sstevel@tonic-gate /* 459*0Sstevel@tonic-gate * not attaching; do nothing 460*0Sstevel@tonic-gate */ 461*0Sstevel@tonic-gate if ((un->un_flags & TRANS_ATTACHING) == 0) 462*0Sstevel@tonic-gate return; 463*0Sstevel@tonic-gate 464*0Sstevel@tonic-gate /* 465*0Sstevel@tonic-gate * find log unit struct 466*0Sstevel@tonic-gate */ 467*0Sstevel@tonic-gate ul = ldl_findlog(un->un_l_recid); 468*0Sstevel@tonic-gate if (ul == NULL) 469*0Sstevel@tonic-gate return; 470*0Sstevel@tonic-gate un->un_l_dev = ul->un_dev; 471*0Sstevel@tonic-gate 472*0Sstevel@tonic-gate /* 473*0Sstevel@tonic-gate * device is busy; do nothing 474*0Sstevel@tonic-gate */ 475*0Sstevel@tonic-gate if (attaching && md_unit_isopen(ui)) 476*0Sstevel@tonic-gate return; 477*0Sstevel@tonic-gate /* 478*0Sstevel@tonic-gate * other functions use non-NULL un_l_unit as detach/attach flag 479*0Sstevel@tonic-gate */ 480*0Sstevel@tonic-gate un->un_l_unit = ul; 481*0Sstevel@tonic-gate 482*0Sstevel@tonic-gate /* 483*0Sstevel@tonic-gate * add metatrans device to the log's list of mt devices 484*0Sstevel@tonic-gate */ 485*0Sstevel@tonic-gate ldl_utadd(un); 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate /* 488*0Sstevel@tonic-gate * attached 489*0Sstevel@tonic-gate */ 490*0Sstevel@tonic-gate un->un_flags &= ~TRANS_ATTACHING; 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate } 493*0Sstevel@tonic-gate 494*0Sstevel@tonic-gate int 495*0Sstevel@tonic-gate trans_reset(mt_unit_t *un, minor_t mnum, int removing, int force) 496*0Sstevel@tonic-gate { 497*0Sstevel@tonic-gate sv_dev_t sv; 498*0Sstevel@tonic-gate mddb_recid_t vtoc_id; 499*0Sstevel@tonic-gate int error = 0; 500*0Sstevel@tonic-gate 501*0Sstevel@tonic-gate /* 502*0Sstevel@tonic-gate * reset log, maps, and ufs interface 503*0Sstevel@tonic-gate */ 504*0Sstevel@tonic-gate error = ldl_reset(un, removing, force); 505*0Sstevel@tonic-gate if (error) 506*0Sstevel@tonic-gate return (error); 507*0Sstevel@tonic-gate 508*0Sstevel@tonic-gate /* 509*0Sstevel@tonic-gate * done with underyling devices 510*0Sstevel@tonic-gate */ 511*0Sstevel@tonic-gate trans_close_all_devs(un); 512*0Sstevel@tonic-gate 513*0Sstevel@tonic-gate md_destroy_unit_incore(mnum, &trans_md_ops); 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate MD_UNIT(mnum) = NULL; 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate if (!removing) 518*0Sstevel@tonic-gate return (0); 519*0Sstevel@tonic-gate 520*0Sstevel@tonic-gate md_reset_parent(un->un_m_dev); 521*0Sstevel@tonic-gate MD_STATUS(un) |= MD_UN_BEING_RESET; 522*0Sstevel@tonic-gate trans_commit(un, 1); 523*0Sstevel@tonic-gate SE_NOTIFY(EC_SVM_CONFIG, ESC_SVM_DELETE, TAG_METADEVICE, MD_UN2SET(un), 524*0Sstevel@tonic-gate MD_SID(un)); 525*0Sstevel@tonic-gate 526*0Sstevel@tonic-gate /* Save the mstr key */ 527*0Sstevel@tonic-gate sv.setno = MD_MIN2SET(mnum); 528*0Sstevel@tonic-gate sv.key = un->un_m_key; 529*0Sstevel@tonic-gate 530*0Sstevel@tonic-gate vtoc_id = un->c.un_vtoc_id; 531*0Sstevel@tonic-gate 532*0Sstevel@tonic-gate mddb_deleterec_wrapper(un->c.un_record_id); 533*0Sstevel@tonic-gate 534*0Sstevel@tonic-gate /* Remove the vtoc, if present */ 535*0Sstevel@tonic-gate if (vtoc_id) 536*0Sstevel@tonic-gate mddb_deleterec_wrapper(vtoc_id); 537*0Sstevel@tonic-gate md_rem_names(&sv, 1); 538*0Sstevel@tonic-gate return (0); 539*0Sstevel@tonic-gate } 540*0Sstevel@tonic-gate 541*0Sstevel@tonic-gate static void 542*0Sstevel@tonic-gate trans_wait_panic(struct buf *cb) 543*0Sstevel@tonic-gate { 544*0Sstevel@tonic-gate while ((cb->b_flags & B_DONE) == 0) { 545*0Sstevel@tonic-gate md_daemon(1, &md_done_daemon); 546*0Sstevel@tonic-gate drv_usecwait(10); 547*0Sstevel@tonic-gate } 548*0Sstevel@tonic-gate } 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate static void 551*0Sstevel@tonic-gate trans_error(md_tps_t *ps) 552*0Sstevel@tonic-gate { 553*0Sstevel@tonic-gate md_dev64_t md_dev; 554*0Sstevel@tonic-gate md_dev64_t m_dev; 555*0Sstevel@tonic-gate char *str; 556*0Sstevel@tonic-gate struct buf *pb; 557*0Sstevel@tonic-gate mdi_unit_t *ui; 558*0Sstevel@tonic-gate 559*0Sstevel@tonic-gate pb = ps->ps_bp; 560*0Sstevel@tonic-gate ui = ps->ps_ui; 561*0Sstevel@tonic-gate 562*0Sstevel@tonic-gate /* 563*0Sstevel@tonic-gate * gather up params for cmn_err 564*0Sstevel@tonic-gate */ 565*0Sstevel@tonic-gate if (pb->b_flags & B_READ) 566*0Sstevel@tonic-gate str = "read"; 567*0Sstevel@tonic-gate else 568*0Sstevel@tonic-gate str = "write"; 569*0Sstevel@tonic-gate md_dev = md_expldev(pb->b_edev); 570*0Sstevel@tonic-gate m_dev = ps->ps_un->un_m_dev; 571*0Sstevel@tonic-gate 572*0Sstevel@tonic-gate /* 573*0Sstevel@tonic-gate * free up the resources for this request and done the errored buf 574*0Sstevel@tonic-gate */ 575*0Sstevel@tonic-gate md_kstat_done(ui, pb, 0); 576*0Sstevel@tonic-gate kmem_cache_free(trans_parent_cache, ps); 577*0Sstevel@tonic-gate md_unit_readerexit(ui); 578*0Sstevel@tonic-gate md_biodone(pb); 579*0Sstevel@tonic-gate 580*0Sstevel@tonic-gate /* 581*0Sstevel@tonic-gate * print pretty error message 582*0Sstevel@tonic-gate */ 583*0Sstevel@tonic-gate cmn_err(CE_WARN, "md: %s: %s error on %s", 584*0Sstevel@tonic-gate md_shortname(md_getminor(md_dev)), str, 585*0Sstevel@tonic-gate md_devname(MD_DEV2SET(md_dev), m_dev, NULL, 0)); 586*0Sstevel@tonic-gate } 587*0Sstevel@tonic-gate 588*0Sstevel@tonic-gate int 589*0Sstevel@tonic-gate trans_done(struct buf *cb) 590*0Sstevel@tonic-gate { 591*0Sstevel@tonic-gate struct buf *pb; 592*0Sstevel@tonic-gate mdi_unit_t *ui; 593*0Sstevel@tonic-gate md_tps_t *ps; 594*0Sstevel@tonic-gate 595*0Sstevel@tonic-gate ps = (md_tps_t *)cb->b_chain; 596*0Sstevel@tonic-gate pb = ps->ps_bp; 597*0Sstevel@tonic-gate ui = ps->ps_ui; 598*0Sstevel@tonic-gate 599*0Sstevel@tonic-gate if (cb->b_flags & B_ERROR) { 600*0Sstevel@tonic-gate pb->b_flags |= B_ERROR; 601*0Sstevel@tonic-gate pb->b_error = cb->b_error; 602*0Sstevel@tonic-gate /* 603*0Sstevel@tonic-gate * device not in hard error state; report error 604*0Sstevel@tonic-gate */ 605*0Sstevel@tonic-gate if (!ldl_isherror(ps->ps_un->un_l_unit)) { 606*0Sstevel@tonic-gate daemon_request(&md_done_daemon, trans_error, 607*0Sstevel@tonic-gate (daemon_queue_t *)ps, REQ_OLD); 608*0Sstevel@tonic-gate 609*0Sstevel@tonic-gate if (cb->b_flags & B_REMAPPED) 610*0Sstevel@tonic-gate bp_mapout(cb); 611*0Sstevel@tonic-gate if (panicstr) 612*0Sstevel@tonic-gate cb->b_flags |= B_DONE; 613*0Sstevel@tonic-gate else 614*0Sstevel@tonic-gate kmem_cache_free(trans_child_cache, cb); 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate return (1); 617*0Sstevel@tonic-gate } 618*0Sstevel@tonic-gate } 619*0Sstevel@tonic-gate 620*0Sstevel@tonic-gate if (cb->b_flags & B_REMAPPED) 621*0Sstevel@tonic-gate bp_mapout(cb); 622*0Sstevel@tonic-gate 623*0Sstevel@tonic-gate if (panicstr) 624*0Sstevel@tonic-gate cb->b_flags |= B_DONE; 625*0Sstevel@tonic-gate else 626*0Sstevel@tonic-gate kmem_cache_free(trans_child_cache, cb); 627*0Sstevel@tonic-gate kmem_cache_free(trans_parent_cache, ps); 628*0Sstevel@tonic-gate md_kstat_done(ui, pb, 0); 629*0Sstevel@tonic-gate md_unit_readerexit(ui); 630*0Sstevel@tonic-gate md_biodone(pb); 631*0Sstevel@tonic-gate 632*0Sstevel@tonic-gate return (0); 633*0Sstevel@tonic-gate } 634*0Sstevel@tonic-gate 635*0Sstevel@tonic-gate static void 636*0Sstevel@tonic-gate md_trans_strategy(buf_t *pb, int flag, void *private) 637*0Sstevel@tonic-gate { 638*0Sstevel@tonic-gate md_tps_t *ps; 639*0Sstevel@tonic-gate buf_t *cb; /* child buf pointer */ 640*0Sstevel@tonic-gate mt_unit_t *un; 641*0Sstevel@tonic-gate mdi_unit_t *ui; 642*0Sstevel@tonic-gate 643*0Sstevel@tonic-gate ui = MDI_UNIT(getminor(pb->b_edev)); 644*0Sstevel@tonic-gate 645*0Sstevel@tonic-gate md_kstat_waitq_enter(ui); 646*0Sstevel@tonic-gate 647*0Sstevel@tonic-gate un = (mt_unit_t *)md_unit_readerlock(ui); 648*0Sstevel@tonic-gate 649*0Sstevel@tonic-gate if (md_inc_iocount(MD_MIN2SET(getminor(pb->b_edev))) != 0) { 650*0Sstevel@tonic-gate pb->b_flags |= B_ERROR; 651*0Sstevel@tonic-gate pb->b_error = ENXIO; 652*0Sstevel@tonic-gate pb->b_resid = pb->b_bcount; 653*0Sstevel@tonic-gate md_unit_readerexit(ui); 654*0Sstevel@tonic-gate biodone(pb); 655*0Sstevel@tonic-gate return; 656*0Sstevel@tonic-gate } 657*0Sstevel@tonic-gate 658*0Sstevel@tonic-gate ASSERT(!(flag & MD_STR_NOTTOP)); 659*0Sstevel@tonic-gate 660*0Sstevel@tonic-gate /* check and map */ 661*0Sstevel@tonic-gate if (md_checkbuf(ui, (md_unit_t *)un, pb) != 0) { 662*0Sstevel@tonic-gate md_kstat_waitq_exit(ui); 663*0Sstevel@tonic-gate return; 664*0Sstevel@tonic-gate } 665*0Sstevel@tonic-gate 666*0Sstevel@tonic-gate bp_mapin(pb); 667*0Sstevel@tonic-gate 668*0Sstevel@tonic-gate ps = kmem_cache_alloc(trans_parent_cache, MD_ALLOCFLAGS); 669*0Sstevel@tonic-gate trans_parent_init(ps); 670*0Sstevel@tonic-gate 671*0Sstevel@tonic-gate /* 672*0Sstevel@tonic-gate * Save essential information from the original buffhdr 673*0Sstevel@tonic-gate * in the md_save structure. 674*0Sstevel@tonic-gate */ 675*0Sstevel@tonic-gate ps->ps_un = un; 676*0Sstevel@tonic-gate ps->ps_ui = ui; 677*0Sstevel@tonic-gate ps->ps_bp = pb; 678*0Sstevel@tonic-gate 679*0Sstevel@tonic-gate cb = kmem_cache_alloc(trans_child_cache, MD_ALLOCFLAGS); 680*0Sstevel@tonic-gate trans_child_init(cb); 681*0Sstevel@tonic-gate 682*0Sstevel@tonic-gate cb = bioclone(pb, 0, pb->b_bcount, md_dev64_to_dev(un->un_m_dev), 683*0Sstevel@tonic-gate pb->b_blkno, trans_done, cb, KM_NOSLEEP); 684*0Sstevel@tonic-gate 685*0Sstevel@tonic-gate cb->b_chain = (void *)ps; 686*0Sstevel@tonic-gate 687*0Sstevel@tonic-gate /* 688*0Sstevel@tonic-gate * RELEASE DEBUG 689*0Sstevel@tonic-gate * The following calls shadow debug for testing purposes if we are 690*0Sstevel@tonic-gate * writing and if shadowing is turned on. 691*0Sstevel@tonic-gate */ 692*0Sstevel@tonic-gate if ((un->un_s_dev != NODEV64) && 693*0Sstevel@tonic-gate ((pb->b_flags & B_READ) == 0)) 694*0Sstevel@tonic-gate shadow_debug(un, pb, ps, cb, flag, private); 695*0Sstevel@tonic-gate 696*0Sstevel@tonic-gate md_kstat_waitq_to_runq(ui); 697*0Sstevel@tonic-gate 698*0Sstevel@tonic-gate (void) md_call_strategy(cb, flag | MD_STR_MAPPED | MD_NOBLOCK, private); 699*0Sstevel@tonic-gate 700*0Sstevel@tonic-gate /* 701*0Sstevel@tonic-gate * panic in progress; process daemon queues 702*0Sstevel@tonic-gate */ 703*0Sstevel@tonic-gate if (panicstr) { 704*0Sstevel@tonic-gate trans_wait_panic(cb); 705*0Sstevel@tonic-gate kmem_cache_free(trans_child_cache, cb); 706*0Sstevel@tonic-gate } 707*0Sstevel@tonic-gate } 708*0Sstevel@tonic-gate 709*0Sstevel@tonic-gate /* ARGSUSED */ 710*0Sstevel@tonic-gate static int 711*0Sstevel@tonic-gate md_trans_read(dev_t dev, struct uio *uio, cred_t *credp) 712*0Sstevel@tonic-gate { 713*0Sstevel@tonic-gate int error; 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gate if ((error = md_chk_uio(uio)) != 0) 716*0Sstevel@tonic-gate return (error); 717*0Sstevel@tonic-gate 718*0Sstevel@tonic-gate return (physio(mdstrategy, NULL, dev, B_READ, minphys, uio)); 719*0Sstevel@tonic-gate } 720*0Sstevel@tonic-gate 721*0Sstevel@tonic-gate /* ARGSUSED */ 722*0Sstevel@tonic-gate static int 723*0Sstevel@tonic-gate md_trans_aread(dev_t dev, struct aio_req *aio, cred_t *credp) 724*0Sstevel@tonic-gate { 725*0Sstevel@tonic-gate int error; 726*0Sstevel@tonic-gate 727*0Sstevel@tonic-gate if ((error = md_chk_uio(aio->aio_uio)) != 0) 728*0Sstevel@tonic-gate return (error); 729*0Sstevel@tonic-gate 730*0Sstevel@tonic-gate return (aphysio(mdstrategy, anocancel, dev, B_READ, minphys, aio)); 731*0Sstevel@tonic-gate } 732*0Sstevel@tonic-gate 733*0Sstevel@tonic-gate /* ARGSUSED */ 734*0Sstevel@tonic-gate static int 735*0Sstevel@tonic-gate md_trans_write(dev_t dev, struct uio *uio, cred_t *credp) 736*0Sstevel@tonic-gate { 737*0Sstevel@tonic-gate int error; 738*0Sstevel@tonic-gate 739*0Sstevel@tonic-gate if ((error = md_chk_uio(uio)) != 0) 740*0Sstevel@tonic-gate return (error); 741*0Sstevel@tonic-gate 742*0Sstevel@tonic-gate return (physio(mdstrategy, NULL, dev, B_WRITE, minphys, uio)); 743*0Sstevel@tonic-gate } 744*0Sstevel@tonic-gate 745*0Sstevel@tonic-gate /* ARGSUSED */ 746*0Sstevel@tonic-gate static int 747*0Sstevel@tonic-gate md_trans_awrite(dev_t dev, struct aio_req *aio, cred_t *credp) 748*0Sstevel@tonic-gate { 749*0Sstevel@tonic-gate int error; 750*0Sstevel@tonic-gate 751*0Sstevel@tonic-gate if ((error = md_chk_uio(aio->aio_uio)) != 0) 752*0Sstevel@tonic-gate return (error); 753*0Sstevel@tonic-gate 754*0Sstevel@tonic-gate return (aphysio(mdstrategy, anocancel, dev, B_WRITE, minphys, aio)); 755*0Sstevel@tonic-gate } 756*0Sstevel@tonic-gate 757*0Sstevel@tonic-gate static void 758*0Sstevel@tonic-gate trans_cleanup(mt_unit_t *un) 759*0Sstevel@tonic-gate { 760*0Sstevel@tonic-gate sv_dev_t sv; 761*0Sstevel@tonic-gate 762*0Sstevel@tonic-gate MD_STATUS(un) |= MD_UN_LOG_DELETED; 763*0Sstevel@tonic-gate trans_commit(un, 0); 764*0Sstevel@tonic-gate 765*0Sstevel@tonic-gate /* Save the mstr key */ 766*0Sstevel@tonic-gate sv.setno = MD_UN2SET(un); 767*0Sstevel@tonic-gate sv.key = un->un_m_key; 768*0Sstevel@tonic-gate 769*0Sstevel@tonic-gate mddb_deleterec_wrapper(un->c.un_record_id); 770*0Sstevel@tonic-gate 771*0Sstevel@tonic-gate md_rem_names(&sv, 1); 772*0Sstevel@tonic-gate } 773*0Sstevel@tonic-gate 774*0Sstevel@tonic-gate static int 775*0Sstevel@tonic-gate trans_snarf(md_snarfcmd_t cmd, set_t setno) 776*0Sstevel@tonic-gate { 777*0Sstevel@tonic-gate mt_unit_t *un; 778*0Sstevel@tonic-gate ml_unit_t *ul; 779*0Sstevel@tonic-gate mddb_recid_t recid; 780*0Sstevel@tonic-gate int gotsomething; 781*0Sstevel@tonic-gate mddb_type_t typ1; 782*0Sstevel@tonic-gate int all_trans_gotten; 783*0Sstevel@tonic-gate mddb_de_ic_t *dep; 784*0Sstevel@tonic-gate mddb_rb32_t *rbp; 785*0Sstevel@tonic-gate size_t newreqsize; 786*0Sstevel@tonic-gate static int trans_found = 0; 787*0Sstevel@tonic-gate 788*0Sstevel@tonic-gate 789*0Sstevel@tonic-gate 790*0Sstevel@tonic-gate if (cmd == MD_SNARF_CLEANUP) { 791*0Sstevel@tonic-gate 792*0Sstevel@tonic-gate if (md_get_setstatus(setno) & MD_SET_STALE) 793*0Sstevel@tonic-gate return (0); 794*0Sstevel@tonic-gate 795*0Sstevel@tonic-gate /* 796*0Sstevel@tonic-gate * clean up partially cleared trans devices 797*0Sstevel@tonic-gate */ 798*0Sstevel@tonic-gate typ1 = (mddb_type_t)md_getshared_key(setno, 799*0Sstevel@tonic-gate trans_md_ops.md_driver.md_drivername); 800*0Sstevel@tonic-gate recid = mddb_makerecid(setno, 0); 801*0Sstevel@tonic-gate while ((recid = mddb_getnextrec(recid, typ1, TRANS_REC)) > 0) { 802*0Sstevel@tonic-gate un = (mt_unit_t *)mddb_getrecaddr(recid); 803*0Sstevel@tonic-gate (void) trans_detach(un, 1); 804*0Sstevel@tonic-gate if (mddb_getrecprivate(recid) & MD_PRV_CLEANUP) { 805*0Sstevel@tonic-gate trans_cleanup(un); 806*0Sstevel@tonic-gate recid = mddb_makerecid(setno, 0); 807*0Sstevel@tonic-gate } 808*0Sstevel@tonic-gate } 809*0Sstevel@tonic-gate /* 810*0Sstevel@tonic-gate * clean up partially cleared log devices 811*0Sstevel@tonic-gate */ 812*0Sstevel@tonic-gate recid = mddb_makerecid(setno, 0); 813*0Sstevel@tonic-gate while ((recid = mddb_getnextrec(recid, typ1, LOG_REC)) > 0) { 814*0Sstevel@tonic-gate if (mddb_getrecprivate(recid) & MD_PRV_CLEANUP) { 815*0Sstevel@tonic-gate ul = (ml_unit_t *)mddb_getrecaddr(recid); 816*0Sstevel@tonic-gate ldl_cleanup(ul); 817*0Sstevel@tonic-gate recid = mddb_makerecid(setno, 0); 818*0Sstevel@tonic-gate } 819*0Sstevel@tonic-gate } 820*0Sstevel@tonic-gate 821*0Sstevel@tonic-gate return (0); 822*0Sstevel@tonic-gate } 823*0Sstevel@tonic-gate 824*0Sstevel@tonic-gate /* 825*0Sstevel@tonic-gate * must snarf up the log devices first 826*0Sstevel@tonic-gate */ 827*0Sstevel@tonic-gate gotsomething = 0; 828*0Sstevel@tonic-gate all_trans_gotten = 1; 829*0Sstevel@tonic-gate typ1 = (mddb_type_t)md_getshared_key(setno, 830*0Sstevel@tonic-gate trans_md_ops.md_driver.md_drivername); 831*0Sstevel@tonic-gate recid = mddb_makerecid(setno, 0); 832*0Sstevel@tonic-gate while ((recid = mddb_getnextrec(recid, typ1, LOG_REC)) > 0) { 833*0Sstevel@tonic-gate ml_unit_t *big_ul; 834*0Sstevel@tonic-gate ml_unit32_od_t *small_ul; 835*0Sstevel@tonic-gate 836*0Sstevel@tonic-gate if (mddb_getrecprivate(recid) & MD_PRV_GOTIT) 837*0Sstevel@tonic-gate continue; 838*0Sstevel@tonic-gate 839*0Sstevel@tonic-gate small_ul = (ml_unit32_od_t *)mddb_getrecaddr(recid); 840*0Sstevel@tonic-gate dep = mddb_getrecdep(recid); 841*0Sstevel@tonic-gate dep->de_flags = MDDB_F_TRANS_LOG; 842*0Sstevel@tonic-gate rbp = dep->de_rb; 843*0Sstevel@tonic-gate /* 844*0Sstevel@tonic-gate * As trans records are always old records, 845*0Sstevel@tonic-gate * we have to check if this record already has been converted. 846*0Sstevel@tonic-gate * We don't want to do that work twice. 847*0Sstevel@tonic-gate */ 848*0Sstevel@tonic-gate if ((rbp->rb_private & MD_PRV_CONVD) == 0) { 849*0Sstevel@tonic-gate newreqsize = sizeof (ml_unit_t); 850*0Sstevel@tonic-gate big_ul = (ml_unit_t *)kmem_zalloc(newreqsize, KM_SLEEP); 851*0Sstevel@tonic-gate trans_log_convert((caddr_t)small_ul, (caddr_t)big_ul, 852*0Sstevel@tonic-gate SMALL_2_BIG); 853*0Sstevel@tonic-gate kmem_free(small_ul, dep->de_reqsize); 854*0Sstevel@tonic-gate /* 855*0Sstevel@tonic-gate * Update userdata and incore userdata 856*0Sstevel@tonic-gate * incores are at the end of ul 857*0Sstevel@tonic-gate */ 858*0Sstevel@tonic-gate dep->de_rb_userdata_ic = big_ul; 859*0Sstevel@tonic-gate dep->de_rb_userdata = big_ul; 860*0Sstevel@tonic-gate dep->de_icreqsize = newreqsize; 861*0Sstevel@tonic-gate rbp->rb_private |= MD_PRV_CONVD; 862*0Sstevel@tonic-gate ul = big_ul; 863*0Sstevel@tonic-gate } else { 864*0Sstevel@tonic-gate /* already converted, just set the pointer */ 865*0Sstevel@tonic-gate ul = dep->de_rb_userdata; 866*0Sstevel@tonic-gate } 867*0Sstevel@tonic-gate all_trans_gotten = 0; 868*0Sstevel@tonic-gate if (ldl_build_incore(ul, 1) == 0) { 869*0Sstevel@tonic-gate mddb_setrecprivate(recid, MD_PRV_GOTIT); 870*0Sstevel@tonic-gate gotsomething = 1; 871*0Sstevel@tonic-gate } 872*0Sstevel@tonic-gate } 873*0Sstevel@tonic-gate 874*0Sstevel@tonic-gate /* 875*0Sstevel@tonic-gate * now snarf up metatrans devices 876*0Sstevel@tonic-gate */ 877*0Sstevel@tonic-gate gotsomething = 0; 878*0Sstevel@tonic-gate recid = mddb_makerecid(setno, 0); 879*0Sstevel@tonic-gate while ((recid = mddb_getnextrec(recid, typ1, TRANS_REC)) > 0) { 880*0Sstevel@tonic-gate mt_unit_t *big_un; 881*0Sstevel@tonic-gate mt_unit32_od_t *small_un; 882*0Sstevel@tonic-gate 883*0Sstevel@tonic-gate if (mddb_getrecprivate(recid) & MD_PRV_GOTIT) 884*0Sstevel@tonic-gate continue; 885*0Sstevel@tonic-gate 886*0Sstevel@tonic-gate if ((trans_found == 0) && (!MD_UPGRADE)) { 887*0Sstevel@tonic-gate cmn_err(CE_WARN, MD_EOF_TRANS_MSG MD_EOF_TRANS_WARNING); 888*0Sstevel@tonic-gate trans_found = 1; 889*0Sstevel@tonic-gate } 890*0Sstevel@tonic-gate 891*0Sstevel@tonic-gate small_un = (mt_unit32_od_t *)mddb_getrecaddr(recid); 892*0Sstevel@tonic-gate 893*0Sstevel@tonic-gate dep = mddb_getrecdep(recid); 894*0Sstevel@tonic-gate dep->de_flags = MDDB_F_TRANS_MASTER; 895*0Sstevel@tonic-gate rbp = dep->de_rb; 896*0Sstevel@tonic-gate /* 897*0Sstevel@tonic-gate * As trans records are always old records, 898*0Sstevel@tonic-gate * we have to check if this record already has been converted. 899*0Sstevel@tonic-gate * We don't want to do that work twice. 900*0Sstevel@tonic-gate */ 901*0Sstevel@tonic-gate if ((rbp->rb_private & MD_PRV_CONVD) == 0) { 902*0Sstevel@tonic-gate newreqsize = sizeof (mt_unit_t); 903*0Sstevel@tonic-gate big_un = (mt_unit_t *)kmem_zalloc(newreqsize, KM_SLEEP); 904*0Sstevel@tonic-gate trans_master_convert((caddr_t)small_un, (caddr_t)big_un, 905*0Sstevel@tonic-gate SMALL_2_BIG); 906*0Sstevel@tonic-gate kmem_free(small_un, dep->de_reqsize); 907*0Sstevel@tonic-gate /* 908*0Sstevel@tonic-gate * Update userdata and incore userdata 909*0Sstevel@tonic-gate * incores are at the end of ul 910*0Sstevel@tonic-gate */ 911*0Sstevel@tonic-gate dep->de_rb_userdata_ic = big_un; 912*0Sstevel@tonic-gate dep->de_rb_userdata = big_un; 913*0Sstevel@tonic-gate dep->de_icreqsize = newreqsize; 914*0Sstevel@tonic-gate rbp->rb_private |= MD_PRV_CONVD; 915*0Sstevel@tonic-gate un = big_un; 916*0Sstevel@tonic-gate un->c.un_revision = MD_32BIT_META_DEV; 917*0Sstevel@tonic-gate } else { 918*0Sstevel@tonic-gate /* already converted, just set the pointer */ 919*0Sstevel@tonic-gate un = dep->de_rb_userdata; 920*0Sstevel@tonic-gate } 921*0Sstevel@tonic-gate 922*0Sstevel@tonic-gate /* 923*0Sstevel@tonic-gate * Create minor node for snarfed entry. 924*0Sstevel@tonic-gate */ 925*0Sstevel@tonic-gate (void) md_create_minor_node(MD_MIN2SET(MD_SID(un)), MD_SID(un)); 926*0Sstevel@tonic-gate 927*0Sstevel@tonic-gate if (MD_UNIT(MD_SID(un)) != NULL) { 928*0Sstevel@tonic-gate mddb_setrecprivate(recid, MD_PRV_PENDDEL); 929*0Sstevel@tonic-gate continue; 930*0Sstevel@tonic-gate } 931*0Sstevel@tonic-gate 932*0Sstevel@tonic-gate all_trans_gotten = 0; 933*0Sstevel@tonic-gate if (trans_build_incore(un, 1) == 0) { 934*0Sstevel@tonic-gate mddb_setrecprivate(recid, MD_PRV_GOTIT); 935*0Sstevel@tonic-gate md_create_unit_incore(MD_SID(un), &trans_md_ops, 0); 936*0Sstevel@tonic-gate gotsomething = 1; 937*0Sstevel@tonic-gate } 938*0Sstevel@tonic-gate } 939*0Sstevel@tonic-gate 940*0Sstevel@tonic-gate if (!all_trans_gotten) 941*0Sstevel@tonic-gate return (gotsomething); 942*0Sstevel@tonic-gate 943*0Sstevel@tonic-gate recid = mddb_makerecid(setno, 0); 944*0Sstevel@tonic-gate while ((recid = mddb_getnextrec(recid, typ1, 0)) > 0) 945*0Sstevel@tonic-gate if (!(mddb_getrecprivate(recid) & MD_PRV_GOTIT)) 946*0Sstevel@tonic-gate mddb_setrecprivate(recid, MD_PRV_PENDDEL); 947*0Sstevel@tonic-gate return (0); 948*0Sstevel@tonic-gate } 949*0Sstevel@tonic-gate 950*0Sstevel@tonic-gate static int 951*0Sstevel@tonic-gate trans_halt(md_haltcmd_t cmd, set_t setno) 952*0Sstevel@tonic-gate { 953*0Sstevel@tonic-gate unit_t i; 954*0Sstevel@tonic-gate mdi_unit_t *ui; 955*0Sstevel@tonic-gate minor_t mnum; 956*0Sstevel@tonic-gate mt_unit_t *un; 957*0Sstevel@tonic-gate 958*0Sstevel@tonic-gate if (cmd == MD_HALT_CLOSE) { 959*0Sstevel@tonic-gate for (i = 0; i < md_nunits; i++) { 960*0Sstevel@tonic-gate mnum = MD_MKMIN(setno, i); 961*0Sstevel@tonic-gate if ((ui = MDI_UNIT(mnum)) == NULL) 962*0Sstevel@tonic-gate continue; 963*0Sstevel@tonic-gate if (ui->ui_opsindex != trans_md_ops.md_selfindex) 964*0Sstevel@tonic-gate continue; 965*0Sstevel@tonic-gate if (md_unit_isopen(ui)) { 966*0Sstevel@tonic-gate return (1); 967*0Sstevel@tonic-gate } 968*0Sstevel@tonic-gate } 969*0Sstevel@tonic-gate for (i = 0; i < md_nunits; i++) { 970*0Sstevel@tonic-gate mnum = MD_MKMIN(setno, i); 971*0Sstevel@tonic-gate if ((ui = MDI_UNIT(mnum)) == NULL) 972*0Sstevel@tonic-gate continue; 973*0Sstevel@tonic-gate if (ui->ui_opsindex != trans_md_ops.md_selfindex) 974*0Sstevel@tonic-gate continue; 975*0Sstevel@tonic-gate un = (mt_unit_t *)MD_UNIT(mnum); 976*0Sstevel@tonic-gate if ((un->un_flags & TRANS_NEED_OPEN) == 0) { 977*0Sstevel@tonic-gate trans_close_all_devs(un); 978*0Sstevel@tonic-gate } 979*0Sstevel@tonic-gate } 980*0Sstevel@tonic-gate return (0); 981*0Sstevel@tonic-gate } 982*0Sstevel@tonic-gate 983*0Sstevel@tonic-gate if (cmd == MD_HALT_OPEN) { 984*0Sstevel@tonic-gate for (i = 0; i < md_nunits; i++) { 985*0Sstevel@tonic-gate mnum = MD_MKMIN(setno, i); 986*0Sstevel@tonic-gate if ((ui = MDI_UNIT(mnum)) == NULL) 987*0Sstevel@tonic-gate continue; 988*0Sstevel@tonic-gate if (ui->ui_opsindex != trans_md_ops.md_selfindex) 989*0Sstevel@tonic-gate continue; 990*0Sstevel@tonic-gate ldl_open_underlying((mt_unit_t *)MD_UNIT(mnum)); 991*0Sstevel@tonic-gate } 992*0Sstevel@tonic-gate return (0); 993*0Sstevel@tonic-gate } 994*0Sstevel@tonic-gate 995*0Sstevel@tonic-gate if (cmd == MD_HALT_CHECK) { 996*0Sstevel@tonic-gate for (i = 0; i < md_nunits; i++) { 997*0Sstevel@tonic-gate mnum = MD_MKMIN(setno, i); 998*0Sstevel@tonic-gate if ((ui = MDI_UNIT(mnum)) == NULL) 999*0Sstevel@tonic-gate continue; 1000*0Sstevel@tonic-gate if (ui->ui_opsindex != trans_md_ops.md_selfindex) 1001*0Sstevel@tonic-gate continue; 1002*0Sstevel@tonic-gate if (md_unit_isopen(ui)) { 1003*0Sstevel@tonic-gate return (1); 1004*0Sstevel@tonic-gate } 1005*0Sstevel@tonic-gate } 1006*0Sstevel@tonic-gate return (0); 1007*0Sstevel@tonic-gate } 1008*0Sstevel@tonic-gate if (cmd == MD_HALT_DOIT) { 1009*0Sstevel@tonic-gate for (i = 0; i < md_nunits; i++) { 1010*0Sstevel@tonic-gate mnum = MD_MKMIN(setno, i); 1011*0Sstevel@tonic-gate if ((ui = MDI_UNIT(mnum)) == NULL) 1012*0Sstevel@tonic-gate continue; 1013*0Sstevel@tonic-gate if (ui->ui_opsindex != trans_md_ops.md_selfindex) 1014*0Sstevel@tonic-gate continue; 1015*0Sstevel@tonic-gate (void) trans_reset((mt_unit_t *)MD_UNIT(mnum), mnum, 1016*0Sstevel@tonic-gate 0, 1); 1017*0Sstevel@tonic-gate } 1018*0Sstevel@tonic-gate return (0); 1019*0Sstevel@tonic-gate } 1020*0Sstevel@tonic-gate if (cmd == MD_HALT_UNLOAD) 1021*0Sstevel@tonic-gate return (0); 1022*0Sstevel@tonic-gate 1023*0Sstevel@tonic-gate return (1); 1024*0Sstevel@tonic-gate } 1025*0Sstevel@tonic-gate 1026*0Sstevel@tonic-gate /*ARGSUSED3*/ 1027*0Sstevel@tonic-gate static int 1028*0Sstevel@tonic-gate trans_open( 1029*0Sstevel@tonic-gate dev_t *dev, 1030*0Sstevel@tonic-gate int flag, 1031*0Sstevel@tonic-gate int otyp, 1032*0Sstevel@tonic-gate cred_t *cred_p, 1033*0Sstevel@tonic-gate int md_oflags 1034*0Sstevel@tonic-gate ) 1035*0Sstevel@tonic-gate { 1036*0Sstevel@tonic-gate minor_t mnum = getminor(*dev); 1037*0Sstevel@tonic-gate mdi_unit_t *ui = MDI_UNIT(mnum); 1038*0Sstevel@tonic-gate mt_unit_t *un; 1039*0Sstevel@tonic-gate int err; 1040*0Sstevel@tonic-gate 1041*0Sstevel@tonic-gate /* disallow layered opens (e.g., PrestoServe) */ 1042*0Sstevel@tonic-gate if (otyp == OTYP_LYR) 1043*0Sstevel@tonic-gate return (EINVAL); 1044*0Sstevel@tonic-gate 1045*0Sstevel@tonic-gate /* single thread */ 1046*0Sstevel@tonic-gate un = (mt_unit_t *)md_unit_openclose_enter(ui); 1047*0Sstevel@tonic-gate 1048*0Sstevel@tonic-gate /* if already open, count open, return success */ 1049*0Sstevel@tonic-gate if (md_unit_isopen(ui)) { 1050*0Sstevel@tonic-gate err = md_unit_incopen(mnum, flag, otyp); 1051*0Sstevel@tonic-gate md_unit_openclose_exit(ui); 1052*0Sstevel@tonic-gate if (err != 0) 1053*0Sstevel@tonic-gate return (err); 1054*0Sstevel@tonic-gate return (0); 1055*0Sstevel@tonic-gate } 1056*0Sstevel@tonic-gate 1057*0Sstevel@tonic-gate /* 1058*0Sstevel@tonic-gate * For some reason, not all of the metatrans devices attached to 1059*0Sstevel@tonic-gate * this log were openable at snarf; try again now. All of the 1060*0Sstevel@tonic-gate * underlying devices have to be openable for the roll thread to work. 1061*0Sstevel@tonic-gate */ 1062*0Sstevel@tonic-gate if (un->un_flags & TRANS_NEED_OPEN) { 1063*0Sstevel@tonic-gate md_unit_openclose_exit(ui); 1064*0Sstevel@tonic-gate ldl_open_underlying(un); 1065*0Sstevel@tonic-gate if (un->un_flags & TRANS_NEED_OPEN) 1066*0Sstevel@tonic-gate return (EINVAL); 1067*0Sstevel@tonic-gate un = (mt_unit_t *)md_unit_openclose_enter(ui); 1068*0Sstevel@tonic-gate } 1069*0Sstevel@tonic-gate 1070*0Sstevel@tonic-gate /* count open */ 1071*0Sstevel@tonic-gate err = md_unit_incopen(mnum, flag, otyp); 1072*0Sstevel@tonic-gate md_unit_openclose_exit(ui); 1073*0Sstevel@tonic-gate if (err != 0) 1074*0Sstevel@tonic-gate return (err); 1075*0Sstevel@tonic-gate 1076*0Sstevel@tonic-gate /* return success */ 1077*0Sstevel@tonic-gate return (0); 1078*0Sstevel@tonic-gate } 1079*0Sstevel@tonic-gate 1080*0Sstevel@tonic-gate /*ARGSUSED1*/ 1081*0Sstevel@tonic-gate static int 1082*0Sstevel@tonic-gate trans_close( 1083*0Sstevel@tonic-gate dev_t dev, 1084*0Sstevel@tonic-gate int flag, 1085*0Sstevel@tonic-gate int otyp, 1086*0Sstevel@tonic-gate cred_t *cred_p, 1087*0Sstevel@tonic-gate int md_oflags 1088*0Sstevel@tonic-gate ) 1089*0Sstevel@tonic-gate { 1090*0Sstevel@tonic-gate minor_t mnum = getminor(dev); 1091*0Sstevel@tonic-gate mdi_unit_t *ui = MDI_UNIT(mnum); 1092*0Sstevel@tonic-gate mt_unit_t *un; 1093*0Sstevel@tonic-gate int err = 0; 1094*0Sstevel@tonic-gate 1095*0Sstevel@tonic-gate /* single thread */ 1096*0Sstevel@tonic-gate un = (mt_unit_t *)md_unit_openclose_enter(ui); 1097*0Sstevel@tonic-gate 1098*0Sstevel@tonic-gate /* count closed */ 1099*0Sstevel@tonic-gate if ((err = md_unit_decopen(mnum, otyp)) != 0) { 1100*0Sstevel@tonic-gate md_unit_openclose_exit(ui); 1101*0Sstevel@tonic-gate return (err); 1102*0Sstevel@tonic-gate } 1103*0Sstevel@tonic-gate 1104*0Sstevel@tonic-gate /* if still open */ 1105*0Sstevel@tonic-gate if (md_unit_isopen(ui)) { 1106*0Sstevel@tonic-gate md_unit_openclose_exit(ui); 1107*0Sstevel@tonic-gate return (0); 1108*0Sstevel@tonic-gate } 1109*0Sstevel@tonic-gate md_unit_openclose_exit(ui); 1110*0Sstevel@tonic-gate 1111*0Sstevel@tonic-gate if (un->un_flags & TRANS_DETACHING) { 1112*0Sstevel@tonic-gate /* 1113*0Sstevel@tonic-gate * prevent new opens and try to detach the log 1114*0Sstevel@tonic-gate */ 1115*0Sstevel@tonic-gate rw_enter(&md_unit_array_rw.lock, RW_WRITER); 1116*0Sstevel@tonic-gate (void) trans_detach(un, 0); 1117*0Sstevel@tonic-gate rw_exit(&md_unit_array_rw.lock); 1118*0Sstevel@tonic-gate } 1119*0Sstevel@tonic-gate if (un->un_flags & TRANS_ATTACHING) { 1120*0Sstevel@tonic-gate /* 1121*0Sstevel@tonic-gate * prevent new opens and try to attach the log 1122*0Sstevel@tonic-gate */ 1123*0Sstevel@tonic-gate rw_enter(&md_unit_array_rw.lock, RW_WRITER); 1124*0Sstevel@tonic-gate trans_attach(un, 1); 1125*0Sstevel@tonic-gate rw_exit(&md_unit_array_rw.lock); 1126*0Sstevel@tonic-gate } 1127*0Sstevel@tonic-gate 1128*0Sstevel@tonic-gate return (0); 1129*0Sstevel@tonic-gate } 1130*0Sstevel@tonic-gate 1131*0Sstevel@tonic-gate static int 1132*0Sstevel@tonic-gate trans_imp_set( 1133*0Sstevel@tonic-gate set_t setno 1134*0Sstevel@tonic-gate ) 1135*0Sstevel@tonic-gate { 1136*0Sstevel@tonic-gate mt_unit32_od_t *un32; 1137*0Sstevel@tonic-gate ml_unit32_od_t *ul32; 1138*0Sstevel@tonic-gate mddb_recid_t recid; 1139*0Sstevel@tonic-gate int gotsomething = 0; 1140*0Sstevel@tonic-gate mddb_type_t typ1; 1141*0Sstevel@tonic-gate minor_t *self_id; /* minor needs to be updated */ 1142*0Sstevel@tonic-gate mddb_recid_t *record_id; /* record id needs to be updated */ 1143*0Sstevel@tonic-gate 1144*0Sstevel@tonic-gate /* 1145*0Sstevel@tonic-gate * Do log first if there is any 1146*0Sstevel@tonic-gate * Note that trans record is always 32 bit 1147*0Sstevel@tonic-gate */ 1148*0Sstevel@tonic-gate typ1 = (mddb_type_t)md_getshared_key(setno, 1149*0Sstevel@tonic-gate trans_md_ops.md_driver.md_drivername); 1150*0Sstevel@tonic-gate recid = mddb_makerecid(setno, 0); 1151*0Sstevel@tonic-gate 1152*0Sstevel@tonic-gate while ((recid = mddb_getnextrec(recid, typ1, LOG_REC)) > 0) { 1153*0Sstevel@tonic-gate if (mddb_getrecprivate(recid) & MD_PRV_GOTIT) 1154*0Sstevel@tonic-gate continue; 1155*0Sstevel@tonic-gate 1156*0Sstevel@tonic-gate ul32 = (ml_unit32_od_t *)mddb_getrecaddr(recid); 1157*0Sstevel@tonic-gate 1158*0Sstevel@tonic-gate /* 1159*0Sstevel@tonic-gate * Trans log record always is old format 1160*0Sstevel@tonic-gate * Go ahead update the record with the new set info 1161*0Sstevel@tonic-gate */ 1162*0Sstevel@tonic-gate record_id = &(ul32->un_recid); 1163*0Sstevel@tonic-gate 1164*0Sstevel@tonic-gate /* 1165*0Sstevel@tonic-gate * Mark the record and update it 1166*0Sstevel@tonic-gate */ 1167*0Sstevel@tonic-gate *record_id = MAKERECID(setno, DBID(*record_id)); 1168*0Sstevel@tonic-gate if (!md_update_minor(setno, mddb_getsidenum 1169*0Sstevel@tonic-gate (setno), ul32->un_key)) 1170*0Sstevel@tonic-gate goto out; 1171*0Sstevel@tonic-gate mddb_setrecprivate(recid, MD_PRV_GOTIT); 1172*0Sstevel@tonic-gate } 1173*0Sstevel@tonic-gate 1174*0Sstevel@tonic-gate 1175*0Sstevel@tonic-gate /* 1176*0Sstevel@tonic-gate * Now do the master 1177*0Sstevel@tonic-gate */ 1178*0Sstevel@tonic-gate recid = mddb_makerecid(setno, 0); 1179*0Sstevel@tonic-gate while ((recid = mddb_getnextrec(recid, typ1, TRANS_REC)) > 0) { 1180*0Sstevel@tonic-gate if (mddb_getrecprivate(recid) & MD_PRV_GOTIT) 1181*0Sstevel@tonic-gate continue; 1182*0Sstevel@tonic-gate 1183*0Sstevel@tonic-gate un32 = (mt_unit32_od_t *)mddb_getrecaddr(recid); 1184*0Sstevel@tonic-gate 1185*0Sstevel@tonic-gate /* 1186*0Sstevel@tonic-gate * Trans master record always is old format 1187*0Sstevel@tonic-gate */ 1188*0Sstevel@tonic-gate self_id = &(un32->c.un_self_id); 1189*0Sstevel@tonic-gate record_id = &(un32->c.un_record_id); 1190*0Sstevel@tonic-gate 1191*0Sstevel@tonic-gate /* 1192*0Sstevel@tonic-gate * Mark the record and update it 1193*0Sstevel@tonic-gate */ 1194*0Sstevel@tonic-gate *record_id = MAKERECID(setno, DBID(*record_id)); 1195*0Sstevel@tonic-gate *self_id = MD_MKMIN(setno, MD_MIN2UNIT(*self_id)); 1196*0Sstevel@tonic-gate if (!md_update_minor(setno, mddb_getsidenum 1197*0Sstevel@tonic-gate (setno), un32->un_m_key)) 1198*0Sstevel@tonic-gate goto out; 1199*0Sstevel@tonic-gate mddb_setrecprivate(recid, MD_PRV_GOTIT); 1200*0Sstevel@tonic-gate 1201*0Sstevel@tonic-gate gotsomething = 1; 1202*0Sstevel@tonic-gate } 1203*0Sstevel@tonic-gate 1204*0Sstevel@tonic-gate out: 1205*0Sstevel@tonic-gate return (gotsomething); 1206*0Sstevel@tonic-gate } 1207*0Sstevel@tonic-gate 1208*0Sstevel@tonic-gate static md_named_services_t trans_named_services[] = { 1209*0Sstevel@tonic-gate {(intptr_t (*)()) trans_rename_listkids, MDRNM_LIST_URKIDS }, 1210*0Sstevel@tonic-gate {(intptr_t (*)()) trans_rename_check, MDRNM_CHECK }, 1211*0Sstevel@tonic-gate {(intptr_t (*)()) trans_renexch_update_kids, MDRNM_UPDATE_KIDS }, 1212*0Sstevel@tonic-gate {(intptr_t (*)()) trans_rename_update_self, MDRNM_UPDATE_SELF }, 1213*0Sstevel@tonic-gate {(intptr_t (*)()) trans_exchange_self_update_from_down, 1214*0Sstevel@tonic-gate MDRNM_SELF_UPDATE_FROM_DOWN }, 1215*0Sstevel@tonic-gate {(intptr_t (*)()) trans_exchange_parent_update_to, 1216*0Sstevel@tonic-gate MDRNM_PARENT_UPDATE_TO }, 1217*0Sstevel@tonic-gate {NULL, 0 } 1218*0Sstevel@tonic-gate }; 1219*0Sstevel@tonic-gate 1220*0Sstevel@tonic-gate md_ops_t trans_md_ops = { 1221*0Sstevel@tonic-gate trans_open, /* open */ 1222*0Sstevel@tonic-gate trans_close, /* close */ 1223*0Sstevel@tonic-gate md_trans_strategy, /* strategy */ 1224*0Sstevel@tonic-gate NULL, /* print */ 1225*0Sstevel@tonic-gate NULL, /* dump */ 1226*0Sstevel@tonic-gate md_trans_read, /* read */ 1227*0Sstevel@tonic-gate md_trans_write, /* write */ 1228*0Sstevel@tonic-gate md_trans_ioctl, /* trans ioctl */ 1229*0Sstevel@tonic-gate trans_snarf, /* trans_snarf */ 1230*0Sstevel@tonic-gate trans_halt, /* halt */ 1231*0Sstevel@tonic-gate md_trans_aread, /* aread */ 1232*0Sstevel@tonic-gate md_trans_awrite, /* awrite */ 1233*0Sstevel@tonic-gate trans_imp_set, /* import set */ 1234*0Sstevel@tonic-gate trans_named_services 1235*0Sstevel@tonic-gate }; 1236*0Sstevel@tonic-gate 1237*0Sstevel@tonic-gate static void 1238*0Sstevel@tonic-gate init_init(void) 1239*0Sstevel@tonic-gate { 1240*0Sstevel@tonic-gate _init_ldl(); 1241*0Sstevel@tonic-gate ASSERT(_init_debug()); 1242*0Sstevel@tonic-gate trans_parent_cache = kmem_cache_create("md_trans_parent", 1243*0Sstevel@tonic-gate sizeof (md_tps_t), 0, NULL, NULL, NULL, NULL, NULL, 0); 1244*0Sstevel@tonic-gate trans_child_cache = kmem_cache_create("md_trans_child", biosize(), 0, 1245*0Sstevel@tonic-gate trans_child_constructor, trans_child_destructor, 1246*0Sstevel@tonic-gate NULL, NULL, NULL, 0); 1247*0Sstevel@tonic-gate } 1248*0Sstevel@tonic-gate 1249*0Sstevel@tonic-gate static void 1250*0Sstevel@tonic-gate fini_uninit(void) 1251*0Sstevel@tonic-gate { 1252*0Sstevel@tonic-gate ASSERT(_fini_debug()); 1253*0Sstevel@tonic-gate _fini_ldl(); 1254*0Sstevel@tonic-gate kmem_cache_destroy(trans_parent_cache); 1255*0Sstevel@tonic-gate kmem_cache_destroy(trans_child_cache); 1256*0Sstevel@tonic-gate trans_parent_cache = trans_child_cache = NULL; 1257*0Sstevel@tonic-gate } 1258*0Sstevel@tonic-gate 1259*0Sstevel@tonic-gate /* define the module linkage */ 1260*0Sstevel@tonic-gate MD_PLUGIN_MISC_MODULE("trans module %I%", init_init(), fini_uninit()) 1261