10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1623Stw21770 * Common Development and Distribution License (the "License"). 6*1623Stw21770 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate 220Sstevel@tonic-gate /* 23*1623Stw21770 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate /* 300Sstevel@tonic-gate * initialize metadevices 310Sstevel@tonic-gate */ 320Sstevel@tonic-gate 330Sstevel@tonic-gate #include <meta.h> 34*1623Stw21770 #include <sys/lvm/mdio.h> 350Sstevel@tonic-gate #include <libdevinfo.h> 360Sstevel@tonic-gate 370Sstevel@tonic-gate 380Sstevel@tonic-gate int 390Sstevel@tonic-gate parse_interlace( 400Sstevel@tonic-gate char *uname, /* Meta Device name (eg d0) */ 410Sstevel@tonic-gate char *str, /* String to Parse */ 420Sstevel@tonic-gate diskaddr_t *interlacep, 430Sstevel@tonic-gate md_error_t *ep 440Sstevel@tonic-gate ) 450Sstevel@tonic-gate { 460Sstevel@tonic-gate diskaddr_t num; 470Sstevel@tonic-gate char c; 480Sstevel@tonic-gate int cnt; 490Sstevel@tonic-gate 500Sstevel@tonic-gate /* parse interlace */ 510Sstevel@tonic-gate if ((cnt = sscanf(str, "%llu%c", &num, &c)) < 1) { 520Sstevel@tonic-gate return (meta_cook_syntax(ep, MDE_BAD_INTERLACE, 530Sstevel@tonic-gate uname, 1, &str)); 540Sstevel@tonic-gate } else if (cnt == 1) { 550Sstevel@tonic-gate if (num & (DEV_BSIZE - 1)) { 560Sstevel@tonic-gate return (meta_cook_syntax(ep, MDE_BAD_INTERLACE, 570Sstevel@tonic-gate uname, 1, &str)); 580Sstevel@tonic-gate } 590Sstevel@tonic-gate num = lbtodb(num); 600Sstevel@tonic-gate } else switch (c) { 610Sstevel@tonic-gate case 'b': 620Sstevel@tonic-gate case 'B': 630Sstevel@tonic-gate num *= DEV_BSIZE / DEV_BSIZE; 640Sstevel@tonic-gate break; 650Sstevel@tonic-gate case 'k': 660Sstevel@tonic-gate case 'K': 670Sstevel@tonic-gate num *= 1024 / DEV_BSIZE; 680Sstevel@tonic-gate break; 690Sstevel@tonic-gate case 'm': 700Sstevel@tonic-gate case 'M': 710Sstevel@tonic-gate num *= 1024 * 1024 / DEV_BSIZE; 720Sstevel@tonic-gate break; 730Sstevel@tonic-gate default: 740Sstevel@tonic-gate return (meta_cook_syntax(ep, MDE_BAD_INTERLACE, 750Sstevel@tonic-gate NULL, 1, &str)); 760Sstevel@tonic-gate } 770Sstevel@tonic-gate 780Sstevel@tonic-gate /* return success */ 790Sstevel@tonic-gate *interlacep = num; 800Sstevel@tonic-gate return (0); 810Sstevel@tonic-gate } 820Sstevel@tonic-gate 830Sstevel@tonic-gate /* 840Sstevel@tonic-gate * cook up syntax error 850Sstevel@tonic-gate */ 860Sstevel@tonic-gate int 870Sstevel@tonic-gate meta_cook_syntax( 880Sstevel@tonic-gate md_error_t *ep, 890Sstevel@tonic-gate md_void_errno_t errcode, 900Sstevel@tonic-gate char *uname, 910Sstevel@tonic-gate int argc, 920Sstevel@tonic-gate char *argv[] 930Sstevel@tonic-gate ) 940Sstevel@tonic-gate { 950Sstevel@tonic-gate int rval; 960Sstevel@tonic-gate 970Sstevel@tonic-gate /* if we have a token, concat it to uname */ 980Sstevel@tonic-gate if ((argc > 0) && (argv[0] != NULL) && (argv[0][0] != '\0')) { 990Sstevel@tonic-gate char *p; 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate if ((uname != NULL) && (uname[0] != '\0')) { 1020Sstevel@tonic-gate p = Malloc(strlen(uname) + 2 1030Sstevel@tonic-gate + 1 + strlen(argv[0]) + 1 + 1); 1040Sstevel@tonic-gate (void) strcpy(p, uname); 1050Sstevel@tonic-gate (void) strcat(p, ": "); 1060Sstevel@tonic-gate } else { 1070Sstevel@tonic-gate p = Malloc(1 + strlen(argv[0]) + 1 + 1); 1080Sstevel@tonic-gate p[0] = '\0'; 1090Sstevel@tonic-gate } 1100Sstevel@tonic-gate (void) strcat(p, "\""); 1110Sstevel@tonic-gate (void) strcat(p, argv[0]); 1120Sstevel@tonic-gate (void) strcat(p, "\""); 1130Sstevel@tonic-gate rval = mderror(ep, errcode, p); 1140Sstevel@tonic-gate Free(p); 1150Sstevel@tonic-gate } else { 1160Sstevel@tonic-gate rval = mderror(ep, errcode, uname); 1170Sstevel@tonic-gate } 1180Sstevel@tonic-gate 1190Sstevel@tonic-gate return (rval); 1200Sstevel@tonic-gate } 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate int 1230Sstevel@tonic-gate meta_check_devicesize( 1240Sstevel@tonic-gate diskaddr_t total_blocks 1250Sstevel@tonic-gate ) 1260Sstevel@tonic-gate { 1270Sstevel@tonic-gate int rval = MD_CRO_32BIT; 1280Sstevel@tonic-gate 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate if (total_blocks > MD_MAX_BLKS_FOR_SMALL_DEVS) { 1310Sstevel@tonic-gate rval = MD_CRO_64BIT; 1320Sstevel@tonic-gate } 1330Sstevel@tonic-gate return (rval); 1340Sstevel@tonic-gate } 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate /* 1380Sstevel@tonic-gate * setup metadevice geometry 1390Sstevel@tonic-gate */ 1400Sstevel@tonic-gate /*ARGSUSED*/ 1410Sstevel@tonic-gate int 1420Sstevel@tonic-gate meta_setup_geom( 1430Sstevel@tonic-gate md_unit_t *md, 1440Sstevel@tonic-gate mdname_t *np, 1450Sstevel@tonic-gate mdgeom_t *geomp, 1460Sstevel@tonic-gate uint_t write_reinstruct, 1470Sstevel@tonic-gate uint_t read_reinstruct, 1480Sstevel@tonic-gate uint_t round_cyl, 1490Sstevel@tonic-gate md_error_t *ep 1500Sstevel@tonic-gate ) 1510Sstevel@tonic-gate { 1520Sstevel@tonic-gate diskaddr_t cylsize = geomp->nhead * geomp->nsect; 1530Sstevel@tonic-gate diskaddr_t total_blocks; 1540Sstevel@tonic-gate 1550Sstevel@tonic-gate if (round_cyl) { 1560Sstevel@tonic-gate total_blocks = rounddown(md->c.un_actual_tb, cylsize); 1570Sstevel@tonic-gate } else { 1580Sstevel@tonic-gate total_blocks = md->c.un_actual_tb; 1590Sstevel@tonic-gate } 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate md->c.un_total_blocks = total_blocks; 1620Sstevel@tonic-gate md->c.un_nhead = geomp->nhead; 1630Sstevel@tonic-gate md->c.un_nsect = geomp->nsect; 1640Sstevel@tonic-gate md->c.un_rpm = geomp->rpm; 1650Sstevel@tonic-gate md->c.un_wr_reinstruct = write_reinstruct; 1660Sstevel@tonic-gate md->c.un_rd_reinstruct = read_reinstruct; 1670Sstevel@tonic-gate return (0); 1680Sstevel@tonic-gate } 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate /* 1710Sstevel@tonic-gate * adjust metadevice geometry 1720Sstevel@tonic-gate */ 1730Sstevel@tonic-gate /*ARGSUSED*/ 1740Sstevel@tonic-gate int 1750Sstevel@tonic-gate meta_adjust_geom( 1760Sstevel@tonic-gate md_unit_t *md, 1770Sstevel@tonic-gate mdname_t *np, 1780Sstevel@tonic-gate uint_t write_reinstruct, 1790Sstevel@tonic-gate uint_t read_reinstruct, 1800Sstevel@tonic-gate uint_t round_cyl, 1810Sstevel@tonic-gate md_error_t *ep 1820Sstevel@tonic-gate ) 1830Sstevel@tonic-gate { 1840Sstevel@tonic-gate diskaddr_t cylsize = md->c.un_nhead * md->c.un_nsect; 1850Sstevel@tonic-gate diskaddr_t total_blocks; 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate if (round_cyl) { 1880Sstevel@tonic-gate total_blocks = rounddown(md->c.un_actual_tb, cylsize); 1890Sstevel@tonic-gate } else { 1900Sstevel@tonic-gate total_blocks = md->c.un_actual_tb; 1910Sstevel@tonic-gate } 1920Sstevel@tonic-gate 1930Sstevel@tonic-gate md->c.un_total_blocks = total_blocks; 1940Sstevel@tonic-gate if (write_reinstruct > md->c.un_wr_reinstruct) 1950Sstevel@tonic-gate md->c.un_wr_reinstruct = write_reinstruct; 1960Sstevel@tonic-gate if (read_reinstruct > md->c.un_rd_reinstruct) 1970Sstevel@tonic-gate md->c.un_rd_reinstruct = read_reinstruct; 1980Sstevel@tonic-gate return (0); 1990Sstevel@tonic-gate } 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate /* 2020Sstevel@tonic-gate * Function: meta_init_make_device 2030Sstevel@tonic-gate * Purpose: 2040Sstevel@tonic-gate * Create the device node <uname> by constructing the necessary 2050Sstevel@tonic-gate * md_mkdev_params_t structure. We have to handle relative names 2060Sstevel@tonic-gate * (e.g. "d80") and fully-qualified names (e.g. "/dev/md/red/dsk/d80"). 2070Sstevel@tonic-gate * The field that we need is the unit number of the metadevice (80 in 2080Sstevel@tonic-gate * the above examples). 2090Sstevel@tonic-gate * Input: spp set structure 2100Sstevel@tonic-gate * uname unit-name (fully qualified or relative) 2110Sstevel@tonic-gate * Output: ep error return structure 212*1623Stw21770 * Returns: > 0 success and return 'key' 2130Sstevel@tonic-gate * -1 Error. <ep> contains error reason 2140Sstevel@tonic-gate */ 215*1623Stw21770 mdkey_t 2160Sstevel@tonic-gate meta_init_make_device( 2170Sstevel@tonic-gate mdsetname_t **spp, 2180Sstevel@tonic-gate char *uname, 2190Sstevel@tonic-gate md_error_t *ep 2200Sstevel@tonic-gate ) 2210Sstevel@tonic-gate { 2220Sstevel@tonic-gate di_devlink_handle_t hdl; 2230Sstevel@tonic-gate md_mkdev_params_t params; 224*1623Stw21770 mdkey_t rval = 0; 225*1623Stw21770 char *p; 226*1623Stw21770 int len = strlen(uname); 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate (void) memset(¶ms, 0, sizeof (params)); 2290Sstevel@tonic-gate MD_SETDRIVERNAME(¶ms, "md", (*spp)->setno); 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate /* 232*1623Stw21770 * This ioctl call causes kernel to allocate a unit number 233*1623Stw21770 * and populate /devices for the named metadevice 2340Sstevel@tonic-gate */ 2350Sstevel@tonic-gate if (metaioctl(MD_IOCMAKE_DEV, ¶ms, ¶ms.mde, NULL) != 0) { 2360Sstevel@tonic-gate return (mdstealerror(ep, ¶ms.mde)); 2370Sstevel@tonic-gate } 238*1623Stw21770 239*1623Stw21770 /* 240*1623Stw21770 * Now we have minor number so add it to the namespace 241*1623Stw21770 * and return the key 242*1623Stw21770 */ 243*1623Stw21770 if ((rval = add_self_name(*spp, uname, ¶ms, ep)) <= 0) { 244*1623Stw21770 return (mderror(ep, MDE_UNIT_NOT_FOUND, NULL)); 245*1623Stw21770 } 246*1623Stw21770 2470Sstevel@tonic-gate /* 2480Sstevel@tonic-gate * Wait until device appears in namespace. di_devlink_init() returns 2490Sstevel@tonic-gate * once the /dev links have been created. If NULL is returned the 2500Sstevel@tonic-gate * link operation failed and we haven't got a device to use. 2510Sstevel@tonic-gate * NOTE: This will take a _long_ time for large numbers of metadevices. 2520Sstevel@tonic-gate * Change to use the enhanced di_devlink_init() interface when 2530Sstevel@tonic-gate * available. 2540Sstevel@tonic-gate */ 2550Sstevel@tonic-gate hdl = di_devlink_init("md", DI_MAKE_LINK); 2560Sstevel@tonic-gate if (hdl != NULL) { 2570Sstevel@tonic-gate (void) di_devlink_fini(&hdl); 2580Sstevel@tonic-gate } else { 259*1623Stw21770 /* 260*1623Stw21770 * Delete name entry we just created 261*1623Stw21770 */ 262*1623Stw21770 (void) del_self_name(*spp, rval, ep); 2630Sstevel@tonic-gate p = Malloc(len + 3); 2640Sstevel@tonic-gate (void) snprintf(p, len + 3, "\"%s\"", uname); 2650Sstevel@tonic-gate rval = mderror(ep, MDE_UNIT_NOT_FOUND, p); 2660Sstevel@tonic-gate Free(p); 2670Sstevel@tonic-gate } 2680Sstevel@tonic-gate return (rval); 2690Sstevel@tonic-gate } 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate /* 2720Sstevel@tonic-gate * FUNCTION: is_metadb_cmd() 2730Sstevel@tonic-gate * INPUT: argc - number of command line arguments 2740Sstevel@tonic-gate * argv - pointer to array of command line arguments 2750Sstevel@tonic-gate * OUTPUT: none 2760Sstevel@tonic-gate * RETURNS: TRUE if a metadb is to be created, FALSE otherwise 2770Sstevel@tonic-gate * PURPOSE: parses enough of the command line to determine if a metadb 2780Sstevel@tonic-gate * create is being attempted 2790Sstevel@tonic-gate */ 2800Sstevel@tonic-gate static boolean_t 2810Sstevel@tonic-gate is_metadb_cmd( 2820Sstevel@tonic-gate int argc, 2830Sstevel@tonic-gate char *argv[] 2840Sstevel@tonic-gate ) 2850Sstevel@tonic-gate { 2860Sstevel@tonic-gate ulong_t num; 2870Sstevel@tonic-gate int len; 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate /* look for match */ 2900Sstevel@tonic-gate if (argc > 0 && (sscanf(argv[0], "mddb%lu%n", &num, &len) == 1) && 2910Sstevel@tonic-gate (strlen(argv[0]) == len) && ((long)num >= 0)) { 2920Sstevel@tonic-gate return (B_TRUE); 2930Sstevel@tonic-gate } 2940Sstevel@tonic-gate 2950Sstevel@tonic-gate return (B_FALSE); 2960Sstevel@tonic-gate } 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate /* 2990Sstevel@tonic-gate * FUNCTION: is_stripe_cmd() 3000Sstevel@tonic-gate * INPUT: argc - number of command line arguments 3010Sstevel@tonic-gate * argv - pointer to array of command line arguments 3020Sstevel@tonic-gate * OUTPUT: none 3030Sstevel@tonic-gate * RETURNS: TRUE if a stripe is to be created, FALSE otherwise 3040Sstevel@tonic-gate * PURPOSE: parses enough of the command line to determine if a stripe 3050Sstevel@tonic-gate * create is being attempted 3060Sstevel@tonic-gate */ 3070Sstevel@tonic-gate static boolean_t 3080Sstevel@tonic-gate is_stripe_cmd( 3090Sstevel@tonic-gate int argc, 3100Sstevel@tonic-gate char *argv[] 3110Sstevel@tonic-gate ) 3120Sstevel@tonic-gate { 3130Sstevel@tonic-gate uint_t nrow; 3140Sstevel@tonic-gate 3150Sstevel@tonic-gate if (argc > 1 && (sscanf(argv[1], "%u", &nrow) != 1) || ((int)nrow < 0)) 3160Sstevel@tonic-gate return (B_FALSE); 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate return (B_TRUE); 3190Sstevel@tonic-gate } 3200Sstevel@tonic-gate 3210Sstevel@tonic-gate /* 3220Sstevel@tonic-gate * FUNCTION: meta_get_init_type() 3230Sstevel@tonic-gate * INPUT: argc - number of command line arguments 3240Sstevel@tonic-gate * argv - pointer to array of command line arguments 3250Sstevel@tonic-gate * OUTPUT: none 3260Sstevel@tonic-gate * RETURNS: type of metadevice or hot spare pools being initialized 3270Sstevel@tonic-gate * PURPOSE: parses enough of the command line to determine what type 3280Sstevel@tonic-gate * of metainit is being attempted 3290Sstevel@tonic-gate */ 3300Sstevel@tonic-gate mdinittypes_t 3310Sstevel@tonic-gate meta_get_init_type( 3320Sstevel@tonic-gate int argc, 3330Sstevel@tonic-gate char *argv[] 3340Sstevel@tonic-gate ) 3350Sstevel@tonic-gate { 3360Sstevel@tonic-gate char *arg = argv[1]; 3370Sstevel@tonic-gate mdinittypes_t init_type; 3380Sstevel@tonic-gate 3390Sstevel@tonic-gate if (argc == 1) /* must be a hot spare pool w/o devices */ 3400Sstevel@tonic-gate return (TAB_HSP); 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate init_type = TAB_UNKNOWN; 3430Sstevel@tonic-gate if (arg != NULL) { 3440Sstevel@tonic-gate if (strcmp(arg, "-m") == 0) { 3450Sstevel@tonic-gate init_type = TAB_MIRROR; 3460Sstevel@tonic-gate } else if (strcmp(arg, "-r") == 0) { 3470Sstevel@tonic-gate init_type = TAB_RAID; 3480Sstevel@tonic-gate } else if (strcmp(arg, "-p") == 0) { 3490Sstevel@tonic-gate init_type = TAB_SP; 3500Sstevel@tonic-gate } else if (strcmp(arg, "-t") == 0) { 3510Sstevel@tonic-gate init_type = TAB_TRANS; 3520Sstevel@tonic-gate } else if (is_metadb_cmd(argc, argv)) { 3530Sstevel@tonic-gate init_type = TAB_MDDB; 3540Sstevel@tonic-gate } else if (is_stripe_cmd(argc, argv)) { 3550Sstevel@tonic-gate init_type = TAB_STRIPE; 3560Sstevel@tonic-gate } else { /* assume that it is a hsp */ 3570Sstevel@tonic-gate init_type = TAB_HSP; 3580Sstevel@tonic-gate } 3590Sstevel@tonic-gate } 3600Sstevel@tonic-gate return (init_type); 3610Sstevel@tonic-gate } 3620Sstevel@tonic-gate 3630Sstevel@tonic-gate /* 3640Sstevel@tonic-gate * initialize named device or hotspare pool 3650Sstevel@tonic-gate */ 3660Sstevel@tonic-gate int 3670Sstevel@tonic-gate meta_init_name( 3680Sstevel@tonic-gate mdsetname_t **spp, 3690Sstevel@tonic-gate int argc, 3700Sstevel@tonic-gate char *argv[], 371*1623Stw21770 char *cname, /* canonical name */ 3720Sstevel@tonic-gate mdcmdopts_t options, 3730Sstevel@tonic-gate md_error_t *ep 3740Sstevel@tonic-gate ) 3750Sstevel@tonic-gate { 3760Sstevel@tonic-gate mdinittypes_t init_type; 3770Sstevel@tonic-gate char *p; 3780Sstevel@tonic-gate int rval; 3790Sstevel@tonic-gate char *uname = argv[0]; 380*1623Stw21770 mdkey_t key = MD_KEYWILD; 381*1623Stw21770 minor_t mnum; 382*1623Stw21770 md_error_t t_e = mdnullerror; 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate assert(argc > 0); 385*1623Stw21770 assert(*spp != NULL); 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate /* determine type of metadevice or hot spare pool being created */ 3880Sstevel@tonic-gate init_type = meta_get_init_type(argc, argv); 3890Sstevel@tonic-gate 390*1623Stw21770 /* 391*1623Stw21770 * Metatrans is eof 392*1623Stw21770 */ 393*1623Stw21770 if (init_type == TAB_TRANS) 394*1623Stw21770 return (mderror(ep, MDE_EOF_TRANS, NULL)); 395*1623Stw21770 3960Sstevel@tonic-gate /* hotspare pool */ 3970Sstevel@tonic-gate if (init_type == TAB_HSP) 3980Sstevel@tonic-gate return (meta_init_hsp(spp, argc, argv, options, ep)); 3990Sstevel@tonic-gate 400*1623Stw21770 /* 401*1623Stw21770 * We are creating metadevice so make sure the name 402*1623Stw21770 * has not been used 403*1623Stw21770 */ 404*1623Stw21770 if (is_existing_meta_hsp(*spp, cname)) { 405*1623Stw21770 /* 406*1623Stw21770 * The name has been used by hsp 407*1623Stw21770 */ 408*1623Stw21770 if (is_existing_hsp(*spp, cname)) { 409*1623Stw21770 return (mderror(ep, MDE_NAME_IN_USE, cname)); 410*1623Stw21770 } 411*1623Stw21770 412*1623Stw21770 /* 413*1623Stw21770 * If path exists but unit is not created 414*1623Stw21770 * then meta_init_make_device will correct 415*1623Stw21770 * that. If unit also exists then it 416*1623Stw21770 * will return a conflict error 417*1623Stw21770 */ 418*1623Stw21770 if (init_type != TAB_UNKNOWN) { 419*1623Stw21770 /* Create device node */ 420*1623Stw21770 if ((key = meta_init_make_device(spp, uname, 421*1623Stw21770 &t_e)) <= 0) { 422*1623Stw21770 return (mdstealerror(ep, &t_e)); 423*1623Stw21770 } 424*1623Stw21770 } 425*1623Stw21770 } 426*1623Stw21770 4270Sstevel@tonic-gate /* metadevice */ 4280Sstevel@tonic-gate if (argc >= 2 && init_type != TAB_UNKNOWN) { 4290Sstevel@tonic-gate /* 4300Sstevel@tonic-gate * We need to create the device node if the specified metadevice 4310Sstevel@tonic-gate * does not already exist in the database. The actual creation 4320Sstevel@tonic-gate * is undertaken by the md driver and the links propagated by 4330Sstevel@tonic-gate * devfsadm. 4340Sstevel@tonic-gate */ 435*1623Stw21770 if (key == MD_KEYWILD) { 436*1623Stw21770 if ((key = meta_init_make_device(spp, uname, 437*1623Stw21770 &t_e)) <= 0) 438*1623Stw21770 return (mdstealerror(ep, &t_e)); 4390Sstevel@tonic-gate } 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate switch (init_type) { 4420Sstevel@tonic-gate case TAB_MIRROR: 443*1623Stw21770 rval = meta_init_mirror(spp, argc, argv, options, ep); 4440Sstevel@tonic-gate break; 4450Sstevel@tonic-gate case TAB_RAID: 446*1623Stw21770 rval = meta_init_raid(spp, argc, argv, options, ep); 4470Sstevel@tonic-gate break; 4480Sstevel@tonic-gate case TAB_SP: 449*1623Stw21770 rval = meta_init_sp(spp, argc, argv, options, ep); 4500Sstevel@tonic-gate break; 4510Sstevel@tonic-gate case TAB_STRIPE: 452*1623Stw21770 rval = meta_init_stripe(spp, argc, argv, options, ep); 4530Sstevel@tonic-gate break; 4540Sstevel@tonic-gate } 455*1623Stw21770 456*1623Stw21770 if (rval == -1 || !(options & MDCMD_DOIT)) { 457*1623Stw21770 /* 458*1623Stw21770 * Remove the device node created before 459*1623Stw21770 */ 460*1623Stw21770 if ((meta_getnmentbykey((*spp)->setno, MD_SIDEWILD, 461*1623Stw21770 key, NULL, &mnum, NULL, ep) != NULL) && 462*1623Stw21770 MD_MIN2UNIT(mnum) < MD_MAXUNITS) { 463*1623Stw21770 (void) metaioctl(MD_IOCREM_DEV, &mnum, &t_e, NULL); 464*1623Stw21770 } 465*1623Stw21770 466*1623Stw21770 /* 467*1623Stw21770 * Del what we added before 468*1623Stw21770 */ 469*1623Stw21770 (void) del_self_name(*spp, key, &t_e); 470*1623Stw21770 } 471*1623Stw21770 return (rval); 4720Sstevel@tonic-gate } 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate /* unknown type */ 4750Sstevel@tonic-gate p = Malloc(1 + strlen(uname) + 1 + 1); 4760Sstevel@tonic-gate (void) strcpy(p, "\""); 4770Sstevel@tonic-gate (void) strcat(p, uname); 4780Sstevel@tonic-gate (void) strcat(p, "\""); 4790Sstevel@tonic-gate rval = mderror(ep, MDE_SYNTAX, p); 4800Sstevel@tonic-gate Free(p); 4810Sstevel@tonic-gate return (rval); 4820Sstevel@tonic-gate } 483