4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * initialize metadevices
34 #include <sys/lvm/mdio.h>
35 #include <libdevinfo.h>
40 char *uname
, /* Meta Device name (eg d0) */
41 char *str
, /* String to Parse */
42 diskaddr_t
*interlacep
,
51 if ((cnt
= sscanf(str
, "%llu%c", &num
, &c
)) < 1) {
52 return (meta_cook_syntax(ep
, MDE_BAD_INTERLACE
,
54 } else if (cnt
== 1) {
55 if (num
& (DEV_BSIZE
- 1)) {
56 return (meta_cook_syntax(ep
, MDE_BAD_INTERLACE
,
63 num
*= DEV_BSIZE
/ DEV_BSIZE
;
67 num
*= 1024 / DEV_BSIZE
;
71 num
*= 1024 * 1024 / DEV_BSIZE
;
74 return (meta_cook_syntax(ep
, MDE_BAD_INTERLACE
,
84 * cook up syntax error
89 md_void_errno_t errcode
,
97 /* if we have a token, concat it to uname */
98 if ((argc
> 0) && (argv
[0] != NULL
) && (argv
[0][0] != '\0')) {
101 if ((uname
!= NULL
) && (uname
[0] != '\0')) {
102 p
= Malloc(strlen(uname
) + 2
103 + 1 + strlen(argv
[0]) + 1 + 1);
104 (void) strcpy(p
, uname
);
105 (void) strcat(p
, ": ");
107 p
= Malloc(1 + strlen(argv
[0]) + 1 + 1);
110 (void) strcat(p
, "\"");
111 (void) strcat(p
, argv
[0]);
112 (void) strcat(p
, "\"");
113 rval
= mderror(ep
, errcode
, p
);
116 rval
= mderror(ep
, errcode
, uname
);
123 meta_check_devicesize(
124 diskaddr_t total_blocks
127 int rval
= MD_CRO_32BIT
;
130 if (total_blocks
> MD_MAX_BLKS_FOR_SMALL_DEVS
) {
138 * setup metadevice geometry
146 uint_t write_reinstruct
,
147 uint_t read_reinstruct
,
152 diskaddr_t cylsize
= geomp
->nhead
* geomp
->nsect
;
153 diskaddr_t total_blocks
;
156 total_blocks
= rounddown(md
->c
.un_actual_tb
, cylsize
);
158 total_blocks
= md
->c
.un_actual_tb
;
161 md
->c
.un_total_blocks
= total_blocks
;
162 md
->c
.un_nhead
= geomp
->nhead
;
163 md
->c
.un_nsect
= geomp
->nsect
;
164 md
->c
.un_rpm
= geomp
->rpm
;
165 md
->c
.un_wr_reinstruct
= write_reinstruct
;
166 md
->c
.un_rd_reinstruct
= read_reinstruct
;
171 * adjust metadevice geometry
178 uint_t write_reinstruct
,
179 uint_t read_reinstruct
,
184 diskaddr_t cylsize
= md
->c
.un_nhead
* md
->c
.un_nsect
;
185 diskaddr_t total_blocks
;
188 total_blocks
= rounddown(md
->c
.un_actual_tb
, cylsize
);
190 total_blocks
= md
->c
.un_actual_tb
;
193 md
->c
.un_total_blocks
= total_blocks
;
194 if (write_reinstruct
> md
->c
.un_wr_reinstruct
)
195 md
->c
.un_wr_reinstruct
= write_reinstruct
;
196 if (read_reinstruct
> md
->c
.un_rd_reinstruct
)
197 md
->c
.un_rd_reinstruct
= read_reinstruct
;
202 * Function: meta_init_make_device
204 * Create the device node <uname> by constructing the necessary
205 * md_mkdev_params_t structure. We have to handle relative names
206 * (e.g. "d80") and fully-qualified names (e.g. "/dev/md/red/dsk/d80").
207 * The field that we need is the unit number of the metadevice (80 in
208 * the above examples).
209 * Input: spp set structure
210 * uname unit-name (fully qualified or relative)
211 * Output: ep error return structure
212 * Returns: > 0 success and return 'key'
213 * -1 Error. <ep> contains error reason
216 meta_init_make_device(
222 md_mkdev_params_t params
;
225 int len
= strlen(uname
);
227 (void) memset(¶ms
, 0, sizeof (params
));
228 MD_SETDRIVERNAME(¶ms
, "md", (*spp
)->setno
);
231 * This ioctl call causes kernel to allocate a unit number
232 * and populate /devices for the named metadevice
234 if (metaioctl(MD_IOCMAKE_DEV
, ¶ms
, ¶ms
.mde
, NULL
) != 0) {
235 return (mdstealerror(ep
, ¶ms
.mde
));
239 * Now we have minor number so add it to the namespace
242 if ((rval
= add_self_name(*spp
, uname
, ¶ms
, ep
)) <= 0) {
244 (void) mderror(ep
, MDE_UNIT_NOT_FOUND
, NULL
);
249 /* Make sure the /dev link is created */
250 if (meta_update_devtree(MD_MKMIN((*spp
)->setno
, params
.un
)) != 0) {
252 * Delete name entry we just created
254 (void) del_self_name(*spp
, rval
, ep
);
256 (void) snprintf(p
, len
+ 3, "\"%s\"", uname
);
257 rval
= mderror(ep
, MDE_UNIT_NOT_FOUND
, p
);
264 * FUNCTION: is_metadb_cmd()
265 * INPUT: argc - number of command line arguments
266 * argv - pointer to array of command line arguments
268 * RETURNS: TRUE if a metadb is to be created, FALSE otherwise
269 * PURPOSE: parses enough of the command line to determine if a metadb
270 * create is being attempted
282 if (argc
> 0 && (sscanf(argv
[0], "mddb%lu%n", &num
, &len
) == 1) &&
283 (strlen(argv
[0]) == len
) && ((long)num
>= 0)) {
291 * FUNCTION: is_stripe_cmd()
292 * INPUT: argc - number of command line arguments
293 * argv - pointer to array of command line arguments
295 * RETURNS: TRUE if a stripe is to be created, FALSE otherwise
296 * PURPOSE: parses enough of the command line to determine if a stripe
297 * create is being attempted
307 if (argc
> 1 && (sscanf(argv
[1], "%u", &nrow
) != 1) || ((int)nrow
< 0))
314 * FUNCTION: meta_get_init_type()
315 * INPUT: argc - number of command line arguments
316 * argv - pointer to array of command line arguments
318 * RETURNS: type of metadevice or hot spare pools being initialized
319 * PURPOSE: parses enough of the command line to determine what type
320 * of metainit is being attempted
329 mdinittypes_t init_type
;
331 if (argc
== 1) /* must be a hot spare pool w/o devices */
334 init_type
= TAB_UNKNOWN
;
336 if (strcmp(arg
, "-m") == 0) {
337 init_type
= TAB_MIRROR
;
338 } else if (strcmp(arg
, "-r") == 0) {
339 init_type
= TAB_RAID
;
340 } else if (strcmp(arg
, "-p") == 0) {
342 } else if (strcmp(arg
, "-t") == 0) {
343 init_type
= TAB_TRANS
;
344 } else if (is_metadb_cmd(argc
, argv
)) {
345 init_type
= TAB_MDDB
;
346 } else if (is_stripe_cmd(argc
, argv
)) {
347 init_type
= TAB_STRIPE
;
348 } else { /* assume that it is a hsp */
356 * initialize named device or hotspare pool
363 char *cname
, /* canonical name */
368 mdinittypes_t init_type
;
371 char *uname
= argv
[0];
372 mdkey_t key
= MD_KEYWILD
;
374 md_error_t t_e
= mdnullerror
;
377 assert(*spp
!= NULL
);
379 /* determine type of metadevice or hot spare pool being created */
380 init_type
= meta_get_init_type(argc
, argv
);
385 if (init_type
== TAB_TRANS
)
386 return (mderror(ep
, MDE_EOF_TRANS
, NULL
));
389 if (init_type
== TAB_HSP
)
390 return (meta_init_hsp(spp
, argc
, argv
, options
, ep
));
393 * We are creating metadevice so make sure the name
396 if (is_existing_meta_hsp(*spp
, cname
)) {
398 * The name has been used by hsp
400 if (is_existing_hsp(*spp
, cname
)) {
401 return (mderror(ep
, MDE_NAME_IN_USE
, cname
));
405 * If path exists but unit is not created
406 * then meta_init_make_device will correct
407 * that. If unit also exists then it
408 * will return a conflict error
410 if (init_type
!= TAB_UNKNOWN
) {
411 /* Create device node */
412 if ((key
= meta_init_make_device(spp
, uname
,
414 return (mdstealerror(ep
, &t_e
));
420 if (argc
>= 2 && init_type
!= TAB_UNKNOWN
) {
422 * We need to create the device node if the specified metadevice
423 * does not already exist in the database. The actual creation
424 * is undertaken by the md driver and the links propagated by
427 if (key
== MD_KEYWILD
) {
428 if ((key
= meta_init_make_device(spp
, uname
,
430 return (mdstealerror(ep
, &t_e
));
435 rval
= meta_init_mirror(spp
, argc
, argv
, options
, ep
);
438 rval
= meta_init_raid(spp
, argc
, argv
, options
, ep
);
441 rval
= meta_init_sp(spp
, argc
, argv
, options
, ep
);
444 rval
= meta_init_stripe(spp
, argc
, argv
, options
, ep
);
448 if (rval
== -1 || !(options
& MDCMD_DOIT
)) {
450 * Remove the device node created before
452 if ((meta_getnmentbykey((*spp
)->setno
, MD_SIDEWILD
,
453 key
, NULL
, &mnum
, NULL
, ep
) != NULL
) &&
454 MD_MIN2UNIT(mnum
) < MD_MAXUNITS
) {
455 (void) metaioctl(MD_IOCREM_DEV
, &mnum
, &t_e
, NULL
);
459 * Del what we added before
461 (void) del_self_name(*spp
, key
, &t_e
);
467 p
= Malloc(1 + strlen(uname
) + 1 + 1);
468 (void) strcpy(p
, "\"");
469 (void) strcat(p
, uname
);
470 (void) strcat(p
, "\"");
471 rval
= mderror(ep
, MDE_SYNTAX
, p
);