7712 mandoc -Tlint does always exit with error code 0
[unleashed.git] / usr / src / lib / lvm / libmeta / common / meta_init.c
blob5dd653103e5e41b22df3271525fdb38b3d798ef8
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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
33 #include <meta.h>
34 #include <sys/lvm/mdio.h>
35 #include <libdevinfo.h>
38 int
39 parse_interlace(
40 char *uname, /* Meta Device name (eg d0) */
41 char *str, /* String to Parse */
42 diskaddr_t *interlacep,
43 md_error_t *ep
46 diskaddr_t num;
47 char c;
48 int cnt;
50 /* parse interlace */
51 if ((cnt = sscanf(str, "%llu%c", &num, &c)) < 1) {
52 return (meta_cook_syntax(ep, MDE_BAD_INTERLACE,
53 uname, 1, &str));
54 } else if (cnt == 1) {
55 if (num & (DEV_BSIZE - 1)) {
56 return (meta_cook_syntax(ep, MDE_BAD_INTERLACE,
57 uname, 1, &str));
59 num = lbtodb(num);
60 } else switch (c) {
61 case 'b':
62 case 'B':
63 num *= DEV_BSIZE / DEV_BSIZE;
64 break;
65 case 'k':
66 case 'K':
67 num *= 1024 / DEV_BSIZE;
68 break;
69 case 'm':
70 case 'M':
71 num *= 1024 * 1024 / DEV_BSIZE;
72 break;
73 default:
74 return (meta_cook_syntax(ep, MDE_BAD_INTERLACE,
75 NULL, 1, &str));
78 /* return success */
79 *interlacep = num;
80 return (0);
84 * cook up syntax error
86 int
87 meta_cook_syntax(
88 md_error_t *ep,
89 md_void_errno_t errcode,
90 char *uname,
91 int argc,
92 char *argv[]
95 int rval;
97 /* if we have a token, concat it to uname */
98 if ((argc > 0) && (argv[0] != NULL) && (argv[0][0] != '\0')) {
99 char *p;
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, ": ");
106 } else {
107 p = Malloc(1 + strlen(argv[0]) + 1 + 1);
108 p[0] = '\0';
110 (void) strcat(p, "\"");
111 (void) strcat(p, argv[0]);
112 (void) strcat(p, "\"");
113 rval = mderror(ep, errcode, p);
114 Free(p);
115 } else {
116 rval = mderror(ep, errcode, uname);
119 return (rval);
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) {
131 rval = MD_CRO_64BIT;
133 return (rval);
138 * setup metadevice geometry
140 /*ARGSUSED*/
142 meta_setup_geom(
143 md_unit_t *md,
144 mdname_t *np,
145 mdgeom_t *geomp,
146 uint_t write_reinstruct,
147 uint_t read_reinstruct,
148 uint_t round_cyl,
149 md_error_t *ep
152 diskaddr_t cylsize = geomp->nhead * geomp->nsect;
153 diskaddr_t total_blocks;
155 if (round_cyl) {
156 total_blocks = rounddown(md->c.un_actual_tb, cylsize);
157 } else {
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;
167 return (0);
171 * adjust metadevice geometry
173 /*ARGSUSED*/
175 meta_adjust_geom(
176 md_unit_t *md,
177 mdname_t *np,
178 uint_t write_reinstruct,
179 uint_t read_reinstruct,
180 uint_t round_cyl,
181 md_error_t *ep
184 diskaddr_t cylsize = md->c.un_nhead * md->c.un_nsect;
185 diskaddr_t total_blocks;
187 if (round_cyl) {
188 total_blocks = rounddown(md->c.un_actual_tb, cylsize);
189 } else {
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;
198 return (0);
202 * Function: meta_init_make_device
203 * Purpose:
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
215 mdkey_t
216 meta_init_make_device(
217 mdsetname_t **spp,
218 char *uname,
219 md_error_t *ep
222 md_mkdev_params_t params;
223 mdkey_t rval = 0;
224 char *p;
225 int len = strlen(uname);
227 (void) memset(&params, 0, sizeof (params));
228 MD_SETDRIVERNAME(&params, "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, &params, &params.mde, NULL) != 0) {
235 return (mdstealerror(ep, &params.mde));
239 * Now we have minor number so add it to the namespace
240 * and return the key
242 if ((rval = add_self_name(*spp, uname, &params, ep)) <= 0) {
243 if (mdisok(ep))
244 (void) mderror(ep, MDE_UNIT_NOT_FOUND, NULL);
246 return (-1);
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);
255 p = Malloc(len + 3);
256 (void) snprintf(p, len + 3, "\"%s\"", uname);
257 rval = mderror(ep, MDE_UNIT_NOT_FOUND, p);
258 Free(p);
260 return (rval);
264 * FUNCTION: is_metadb_cmd()
265 * INPUT: argc - number of command line arguments
266 * argv - pointer to array of command line arguments
267 * OUTPUT: none
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
272 static boolean_t
273 is_metadb_cmd(
274 int argc,
275 char *argv[]
278 ulong_t num;
279 int len;
281 /* look for match */
282 if (argc > 0 && (sscanf(argv[0], "mddb%lu%n", &num, &len) == 1) &&
283 (strlen(argv[0]) == len) && ((long)num >= 0)) {
284 return (B_TRUE);
287 return (B_FALSE);
291 * FUNCTION: is_stripe_cmd()
292 * INPUT: argc - number of command line arguments
293 * argv - pointer to array of command line arguments
294 * OUTPUT: none
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
299 static boolean_t
300 is_stripe_cmd(
301 int argc,
302 char *argv[]
305 uint_t nrow;
307 if (argc > 1 && (sscanf(argv[1], "%u", &nrow) != 1) || ((int)nrow < 0))
308 return (B_FALSE);
310 return (B_TRUE);
314 * FUNCTION: meta_get_init_type()
315 * INPUT: argc - number of command line arguments
316 * argv - pointer to array of command line arguments
317 * OUTPUT: none
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
322 mdinittypes_t
323 meta_get_init_type(
324 int argc,
325 char *argv[]
328 char *arg = argv[1];
329 mdinittypes_t init_type;
331 if (argc == 1) /* must be a hot spare pool w/o devices */
332 return (TAB_HSP);
334 init_type = TAB_UNKNOWN;
335 if (arg != NULL) {
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) {
341 init_type = TAB_SP;
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 */
349 init_type = TAB_HSP;
352 return (init_type);
356 * initialize named device or hotspare pool
359 meta_init_name(
360 mdsetname_t **spp,
361 int argc,
362 char *argv[],
363 char *cname, /* canonical name */
364 mdcmdopts_t options,
365 md_error_t *ep
368 mdinittypes_t init_type;
369 char *p;
370 int rval;
371 char *uname = argv[0];
372 mdkey_t key = MD_KEYWILD;
373 minor_t mnum;
374 md_error_t t_e = mdnullerror;
376 assert(argc > 0);
377 assert(*spp != NULL);
379 /* determine type of metadevice or hot spare pool being created */
380 init_type = meta_get_init_type(argc, argv);
383 * Metatrans is eof
385 if (init_type == TAB_TRANS)
386 return (mderror(ep, MDE_EOF_TRANS, NULL));
388 /* hotspare pool */
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
394 * has not been used
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,
413 &t_e)) <= 0) {
414 return (mdstealerror(ep, &t_e));
419 /* metadevice */
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
425 * devfsadm.
427 if (key == MD_KEYWILD) {
428 if ((key = meta_init_make_device(spp, uname,
429 &t_e)) <= 0)
430 return (mdstealerror(ep, &t_e));
433 switch (init_type) {
434 case TAB_MIRROR:
435 rval = meta_init_mirror(spp, argc, argv, options, ep);
436 break;
437 case TAB_RAID:
438 rval = meta_init_raid(spp, argc, argv, options, ep);
439 break;
440 case TAB_SP:
441 rval = meta_init_sp(spp, argc, argv, options, ep);
442 break;
443 case TAB_STRIPE:
444 rval = meta_init_stripe(spp, argc, argv, options, ep);
445 break;
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);
463 return (rval);
466 /* unknown type */
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);
472 Free(p);
473 return (rval);