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 51623Stw21770 * Common Development and Distribution License (the "License"). 61623Stw21770 * 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 /* 231623Stw21770 * 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> 341623Stw21770 #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 2121623Stw21770 * Returns: > 0 success and return 'key' 2130Sstevel@tonic-gate * -1 Error. <ep> contains error reason 2140Sstevel@tonic-gate */ 2151623Stw21770 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 md_mkdev_params_t params; 2231623Stw21770 mdkey_t rval = 0; 2241623Stw21770 char *p; 2251623Stw21770 int len = strlen(uname); 2260Sstevel@tonic-gate 2270Sstevel@tonic-gate (void) memset(¶ms, 0, sizeof (params)); 2280Sstevel@tonic-gate MD_SETDRIVERNAME(¶ms, "md", (*spp)->setno); 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate /* 2311623Stw21770 * This ioctl call causes kernel to allocate a unit number 2321623Stw21770 * and populate /devices for the named metadevice 2330Sstevel@tonic-gate */ 2340Sstevel@tonic-gate if (metaioctl(MD_IOCMAKE_DEV, ¶ms, ¶ms.mde, NULL) != 0) { 2350Sstevel@tonic-gate return (mdstealerror(ep, ¶ms.mde)); 2360Sstevel@tonic-gate } 2371623Stw21770 2381623Stw21770 /* 2391623Stw21770 * Now we have minor number so add it to the namespace 2401623Stw21770 * and return the key 2411623Stw21770 */ 2421623Stw21770 if ((rval = add_self_name(*spp, uname, ¶ms, ep)) <= 0) { 2432099Stn143363 if (mdisok(ep)) 2442099Stn143363 (void) mderror(ep, MDE_UNIT_NOT_FOUND, NULL); 2452099Stn143363 2462099Stn143363 return (-1); 2471623Stw21770 } 2481623Stw21770 249*2291Stn143363 /* Make sure the /dev link is created */ 250*2291Stn143363 if (meta_update_devtree(MD_MKMIN((*spp)->setno, params.un)) != 0) { 2511623Stw21770 /* 2521623Stw21770 * Delete name entry we just created 2531623Stw21770 */ 2541623Stw21770 (void) del_self_name(*spp, rval, ep); 2550Sstevel@tonic-gate p = Malloc(len + 3); 2560Sstevel@tonic-gate (void) snprintf(p, len + 3, "\"%s\"", uname); 2570Sstevel@tonic-gate rval = mderror(ep, MDE_UNIT_NOT_FOUND, p); 2580Sstevel@tonic-gate Free(p); 2590Sstevel@tonic-gate } 2600Sstevel@tonic-gate return (rval); 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate /* 2640Sstevel@tonic-gate * FUNCTION: is_metadb_cmd() 2650Sstevel@tonic-gate * INPUT: argc - number of command line arguments 2660Sstevel@tonic-gate * argv - pointer to array of command line arguments 2670Sstevel@tonic-gate * OUTPUT: none 2680Sstevel@tonic-gate * RETURNS: TRUE if a metadb is to be created, FALSE otherwise 2690Sstevel@tonic-gate * PURPOSE: parses enough of the command line to determine if a metadb 2700Sstevel@tonic-gate * create is being attempted 2710Sstevel@tonic-gate */ 2720Sstevel@tonic-gate static boolean_t 2730Sstevel@tonic-gate is_metadb_cmd( 2740Sstevel@tonic-gate int argc, 2750Sstevel@tonic-gate char *argv[] 2760Sstevel@tonic-gate ) 2770Sstevel@tonic-gate { 2780Sstevel@tonic-gate ulong_t num; 2790Sstevel@tonic-gate int len; 2800Sstevel@tonic-gate 2810Sstevel@tonic-gate /* look for match */ 2820Sstevel@tonic-gate if (argc > 0 && (sscanf(argv[0], "mddb%lu%n", &num, &len) == 1) && 2830Sstevel@tonic-gate (strlen(argv[0]) == len) && ((long)num >= 0)) { 2840Sstevel@tonic-gate return (B_TRUE); 2850Sstevel@tonic-gate } 2860Sstevel@tonic-gate 2870Sstevel@tonic-gate return (B_FALSE); 2880Sstevel@tonic-gate } 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate /* 2910Sstevel@tonic-gate * FUNCTION: is_stripe_cmd() 2920Sstevel@tonic-gate * INPUT: argc - number of command line arguments 2930Sstevel@tonic-gate * argv - pointer to array of command line arguments 2940Sstevel@tonic-gate * OUTPUT: none 2950Sstevel@tonic-gate * RETURNS: TRUE if a stripe is to be created, FALSE otherwise 2960Sstevel@tonic-gate * PURPOSE: parses enough of the command line to determine if a stripe 2970Sstevel@tonic-gate * create is being attempted 2980Sstevel@tonic-gate */ 2990Sstevel@tonic-gate static boolean_t 3000Sstevel@tonic-gate is_stripe_cmd( 3010Sstevel@tonic-gate int argc, 3020Sstevel@tonic-gate char *argv[] 3030Sstevel@tonic-gate ) 3040Sstevel@tonic-gate { 3050Sstevel@tonic-gate uint_t nrow; 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate if (argc > 1 && (sscanf(argv[1], "%u", &nrow) != 1) || ((int)nrow < 0)) 3080Sstevel@tonic-gate return (B_FALSE); 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate return (B_TRUE); 3110Sstevel@tonic-gate } 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate /* 3140Sstevel@tonic-gate * FUNCTION: meta_get_init_type() 3150Sstevel@tonic-gate * INPUT: argc - number of command line arguments 3160Sstevel@tonic-gate * argv - pointer to array of command line arguments 3170Sstevel@tonic-gate * OUTPUT: none 3180Sstevel@tonic-gate * RETURNS: type of metadevice or hot spare pools being initialized 3190Sstevel@tonic-gate * PURPOSE: parses enough of the command line to determine what type 3200Sstevel@tonic-gate * of metainit is being attempted 3210Sstevel@tonic-gate */ 3220Sstevel@tonic-gate mdinittypes_t 3230Sstevel@tonic-gate meta_get_init_type( 3240Sstevel@tonic-gate int argc, 3250Sstevel@tonic-gate char *argv[] 3260Sstevel@tonic-gate ) 3270Sstevel@tonic-gate { 3280Sstevel@tonic-gate char *arg = argv[1]; 3290Sstevel@tonic-gate mdinittypes_t init_type; 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate if (argc == 1) /* must be a hot spare pool w/o devices */ 3320Sstevel@tonic-gate return (TAB_HSP); 3330Sstevel@tonic-gate 3340Sstevel@tonic-gate init_type = TAB_UNKNOWN; 3350Sstevel@tonic-gate if (arg != NULL) { 3360Sstevel@tonic-gate if (strcmp(arg, "-m") == 0) { 3370Sstevel@tonic-gate init_type = TAB_MIRROR; 3380Sstevel@tonic-gate } else if (strcmp(arg, "-r") == 0) { 3390Sstevel@tonic-gate init_type = TAB_RAID; 3400Sstevel@tonic-gate } else if (strcmp(arg, "-p") == 0) { 3410Sstevel@tonic-gate init_type = TAB_SP; 3420Sstevel@tonic-gate } else if (strcmp(arg, "-t") == 0) { 3430Sstevel@tonic-gate init_type = TAB_TRANS; 3440Sstevel@tonic-gate } else if (is_metadb_cmd(argc, argv)) { 3450Sstevel@tonic-gate init_type = TAB_MDDB; 3460Sstevel@tonic-gate } else if (is_stripe_cmd(argc, argv)) { 3470Sstevel@tonic-gate init_type = TAB_STRIPE; 3480Sstevel@tonic-gate } else { /* assume that it is a hsp */ 3490Sstevel@tonic-gate init_type = TAB_HSP; 3500Sstevel@tonic-gate } 3510Sstevel@tonic-gate } 3520Sstevel@tonic-gate return (init_type); 3530Sstevel@tonic-gate } 3540Sstevel@tonic-gate 3550Sstevel@tonic-gate /* 3560Sstevel@tonic-gate * initialize named device or hotspare pool 3570Sstevel@tonic-gate */ 3580Sstevel@tonic-gate int 3590Sstevel@tonic-gate meta_init_name( 3600Sstevel@tonic-gate mdsetname_t **spp, 3610Sstevel@tonic-gate int argc, 3620Sstevel@tonic-gate char *argv[], 3631623Stw21770 char *cname, /* canonical name */ 3640Sstevel@tonic-gate mdcmdopts_t options, 3650Sstevel@tonic-gate md_error_t *ep 3660Sstevel@tonic-gate ) 3670Sstevel@tonic-gate { 3680Sstevel@tonic-gate mdinittypes_t init_type; 3690Sstevel@tonic-gate char *p; 3700Sstevel@tonic-gate int rval; 3710Sstevel@tonic-gate char *uname = argv[0]; 3721623Stw21770 mdkey_t key = MD_KEYWILD; 3731623Stw21770 minor_t mnum; 3741623Stw21770 md_error_t t_e = mdnullerror; 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate assert(argc > 0); 3771623Stw21770 assert(*spp != NULL); 3780Sstevel@tonic-gate 3790Sstevel@tonic-gate /* determine type of metadevice or hot spare pool being created */ 3800Sstevel@tonic-gate init_type = meta_get_init_type(argc, argv); 3810Sstevel@tonic-gate 3821623Stw21770 /* 3831623Stw21770 * Metatrans is eof 3841623Stw21770 */ 3851623Stw21770 if (init_type == TAB_TRANS) 3861623Stw21770 return (mderror(ep, MDE_EOF_TRANS, NULL)); 3871623Stw21770 3880Sstevel@tonic-gate /* hotspare pool */ 3890Sstevel@tonic-gate if (init_type == TAB_HSP) 3900Sstevel@tonic-gate return (meta_init_hsp(spp, argc, argv, options, ep)); 3910Sstevel@tonic-gate 3921623Stw21770 /* 3931623Stw21770 * We are creating metadevice so make sure the name 3941623Stw21770 * has not been used 3951623Stw21770 */ 3961623Stw21770 if (is_existing_meta_hsp(*spp, cname)) { 3971623Stw21770 /* 3981623Stw21770 * The name has been used by hsp 3991623Stw21770 */ 4001623Stw21770 if (is_existing_hsp(*spp, cname)) { 4011623Stw21770 return (mderror(ep, MDE_NAME_IN_USE, cname)); 4021623Stw21770 } 4031623Stw21770 4041623Stw21770 /* 4051623Stw21770 * If path exists but unit is not created 4061623Stw21770 * then meta_init_make_device will correct 4071623Stw21770 * that. If unit also exists then it 4081623Stw21770 * will return a conflict error 4091623Stw21770 */ 4101623Stw21770 if (init_type != TAB_UNKNOWN) { 4111623Stw21770 /* Create device node */ 4121623Stw21770 if ((key = meta_init_make_device(spp, uname, 4131623Stw21770 &t_e)) <= 0) { 4141623Stw21770 return (mdstealerror(ep, &t_e)); 4151623Stw21770 } 4161623Stw21770 } 4171623Stw21770 } 4181623Stw21770 4190Sstevel@tonic-gate /* metadevice */ 4200Sstevel@tonic-gate if (argc >= 2 && init_type != TAB_UNKNOWN) { 4210Sstevel@tonic-gate /* 4220Sstevel@tonic-gate * We need to create the device node if the specified metadevice 4230Sstevel@tonic-gate * does not already exist in the database. The actual creation 4240Sstevel@tonic-gate * is undertaken by the md driver and the links propagated by 4250Sstevel@tonic-gate * devfsadm. 4260Sstevel@tonic-gate */ 4271623Stw21770 if (key == MD_KEYWILD) { 4281623Stw21770 if ((key = meta_init_make_device(spp, uname, 4291623Stw21770 &t_e)) <= 0) 4301623Stw21770 return (mdstealerror(ep, &t_e)); 4310Sstevel@tonic-gate } 4320Sstevel@tonic-gate 4330Sstevel@tonic-gate switch (init_type) { 4340Sstevel@tonic-gate case TAB_MIRROR: 4351623Stw21770 rval = meta_init_mirror(spp, argc, argv, options, ep); 4360Sstevel@tonic-gate break; 4370Sstevel@tonic-gate case TAB_RAID: 4381623Stw21770 rval = meta_init_raid(spp, argc, argv, options, ep); 4390Sstevel@tonic-gate break; 4400Sstevel@tonic-gate case TAB_SP: 4411623Stw21770 rval = meta_init_sp(spp, argc, argv, options, ep); 4420Sstevel@tonic-gate break; 4430Sstevel@tonic-gate case TAB_STRIPE: 4441623Stw21770 rval = meta_init_stripe(spp, argc, argv, options, ep); 4450Sstevel@tonic-gate break; 4460Sstevel@tonic-gate } 4471623Stw21770 4481623Stw21770 if (rval == -1 || !(options & MDCMD_DOIT)) { 4491623Stw21770 /* 4501623Stw21770 * Remove the device node created before 4511623Stw21770 */ 4521623Stw21770 if ((meta_getnmentbykey((*spp)->setno, MD_SIDEWILD, 4531623Stw21770 key, NULL, &mnum, NULL, ep) != NULL) && 4541623Stw21770 MD_MIN2UNIT(mnum) < MD_MAXUNITS) { 4551623Stw21770 (void) metaioctl(MD_IOCREM_DEV, &mnum, &t_e, NULL); 4561623Stw21770 } 4571623Stw21770 4581623Stw21770 /* 4591623Stw21770 * Del what we added before 4601623Stw21770 */ 4611623Stw21770 (void) del_self_name(*spp, key, &t_e); 4621623Stw21770 } 4631623Stw21770 return (rval); 4640Sstevel@tonic-gate } 4650Sstevel@tonic-gate 4660Sstevel@tonic-gate /* unknown type */ 4670Sstevel@tonic-gate p = Malloc(1 + strlen(uname) + 1 + 1); 4680Sstevel@tonic-gate (void) strcpy(p, "\""); 4690Sstevel@tonic-gate (void) strcat(p, uname); 4700Sstevel@tonic-gate (void) strcat(p, "\""); 4710Sstevel@tonic-gate rval = mderror(ep, MDE_SYNTAX, p); 4720Sstevel@tonic-gate Free(p); 4730Sstevel@tonic-gate return (rval); 4740Sstevel@tonic-gate } 475