xref: /dflybsd-src/sys/dev/raid/vinum/vinumutil.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /*-
286d7f5d3SJohn Marino  * Copyright (c) 1997, 1998, 1999
386d7f5d3SJohn Marino  *	Nan Yang Computer Services Limited.  All rights reserved.
486d7f5d3SJohn Marino  *
586d7f5d3SJohn Marino  *  Written by Greg Lehey
686d7f5d3SJohn Marino  *
786d7f5d3SJohn Marino  *  This software is distributed under the so-called ``Berkeley
886d7f5d3SJohn Marino  *  License'':
986d7f5d3SJohn Marino  *
1086d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
1186d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
1286d7f5d3SJohn Marino  * are met:
1386d7f5d3SJohn Marino  * 1. Redistributions of source code must retain the above copyright
1486d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer.
1586d7f5d3SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
1686d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
1786d7f5d3SJohn Marino  *    documentation and/or other materials provided with the distribution.
1886d7f5d3SJohn Marino  * 3. All advertising materials mentioning features or use of this software
1986d7f5d3SJohn Marino  *    must display the following acknowledgement:
2086d7f5d3SJohn Marino  *	This product includes software developed by Nan Yang Computer
2186d7f5d3SJohn Marino  *      Services Limited.
2286d7f5d3SJohn Marino  * 4. Neither the name of the Company nor the names of its contributors
2386d7f5d3SJohn Marino  *    may be used to endorse or promote products derived from this software
2486d7f5d3SJohn Marino  *    without specific prior written permission.
2586d7f5d3SJohn Marino  *
2686d7f5d3SJohn Marino  * This software is provided ``as is'', and any express or implied
2786d7f5d3SJohn Marino  * warranties, including, but not limited to, the implied warranties of
2886d7f5d3SJohn Marino  * merchantability and fitness for a particular purpose are disclaimed.
2986d7f5d3SJohn Marino  * In no event shall the company or contributors be liable for any
3086d7f5d3SJohn Marino  * direct, indirect, incidental, special, exemplary, or consequential
3186d7f5d3SJohn Marino  * damages (including, but not limited to, procurement of substitute
3286d7f5d3SJohn Marino  * goods or services; loss of use, data, or profits; or business
3386d7f5d3SJohn Marino  * interruption) however caused and on any theory of liability, whether
3486d7f5d3SJohn Marino  * in contract, strict liability, or tort (including negligence or
3586d7f5d3SJohn Marino  * otherwise) arising in any way out of the use of this software, even if
3686d7f5d3SJohn Marino  * advised of the possibility of such damage.
3786d7f5d3SJohn Marino  *
3886d7f5d3SJohn Marino  * $Id: vinumutil.c,v 1.14 1999/12/30 07:04:02 grog Exp grog $
3986d7f5d3SJohn Marino  * $FreeBSD: src/sys/dev/vinum/vinumutil.c,v 1.15 2000/02/29 06:16:44 grog Exp $
4086d7f5d3SJohn Marino  * $DragonFly: src/sys/dev/raid/vinum/vinumutil.c,v 1.6 2006/12/20 18:14:40 dillon Exp $
4186d7f5d3SJohn Marino  */
4286d7f5d3SJohn Marino 
4386d7f5d3SJohn Marino /* This file contains utility routines used both in kernel and user context */
4486d7f5d3SJohn Marino 
4586d7f5d3SJohn Marino #include "vinumhdr.h"
4686d7f5d3SJohn Marino #include "statetexts.h"
4786d7f5d3SJohn Marino 
4886d7f5d3SJohn Marino #ifdef _KERNEL
4986d7f5d3SJohn Marino #define sprintf	ksprintf
5086d7f5d3SJohn Marino #endif
5186d7f5d3SJohn Marino 
5286d7f5d3SJohn Marino static char numeric_state[32];				    /* temporary buffer for ASCII conversions */
5386d7f5d3SJohn Marino #define STATECOUNT(x) (sizeof (x##statetext) / sizeof (char *))
5486d7f5d3SJohn Marino /* Return drive state as a string */
5586d7f5d3SJohn Marino char *
drive_state(enum drivestate state)5686d7f5d3SJohn Marino drive_state(enum drivestate state)
5786d7f5d3SJohn Marino {
5886d7f5d3SJohn Marino     if (((unsigned) state) >= STATECOUNT(drive)) {
5986d7f5d3SJohn Marino 	sprintf(numeric_state, "Invalid state %d", (int) state);
6086d7f5d3SJohn Marino 	return numeric_state;
6186d7f5d3SJohn Marino     } else
6286d7f5d3SJohn Marino 	return drivestatetext[state];
6386d7f5d3SJohn Marino }
6486d7f5d3SJohn Marino 
6586d7f5d3SJohn Marino /* Return volume state as a string */
6686d7f5d3SJohn Marino char *
volume_state(enum volumestate state)6786d7f5d3SJohn Marino volume_state(enum volumestate state)
6886d7f5d3SJohn Marino {
6986d7f5d3SJohn Marino     if (((unsigned) state) >= STATECOUNT(vol)) {
7086d7f5d3SJohn Marino 	sprintf(numeric_state, "Invalid state %d", (int) state);
7186d7f5d3SJohn Marino 	return numeric_state;
7286d7f5d3SJohn Marino     } else
7386d7f5d3SJohn Marino 	return volstatetext[state];
7486d7f5d3SJohn Marino }
7586d7f5d3SJohn Marino 
7686d7f5d3SJohn Marino /* Return plex state as a string */
7786d7f5d3SJohn Marino char *
plex_state(enum plexstate state)7886d7f5d3SJohn Marino plex_state(enum plexstate state)
7986d7f5d3SJohn Marino {
8086d7f5d3SJohn Marino     if (((unsigned) state) >= STATECOUNT(plex)) {
8186d7f5d3SJohn Marino 	sprintf(numeric_state, "Invalid state %d", (int) state);
8286d7f5d3SJohn Marino 	return numeric_state;
8386d7f5d3SJohn Marino     } else
8486d7f5d3SJohn Marino 	return plexstatetext[state];
8586d7f5d3SJohn Marino }
8686d7f5d3SJohn Marino 
8786d7f5d3SJohn Marino /* Return plex organization as a string */
8886d7f5d3SJohn Marino char *
plex_org(enum plexorg org)8986d7f5d3SJohn Marino plex_org(enum plexorg org)
9086d7f5d3SJohn Marino {
9186d7f5d3SJohn Marino     switch (org) {
9286d7f5d3SJohn Marino     case plex_disorg:					    /* disorganized */
9386d7f5d3SJohn Marino 	return "disorg";
9486d7f5d3SJohn Marino 	break;
9586d7f5d3SJohn Marino 
9686d7f5d3SJohn Marino     case plex_concat:					    /* concatenated plex */
9786d7f5d3SJohn Marino 	return "concat";
9886d7f5d3SJohn Marino 	break;
9986d7f5d3SJohn Marino 
10086d7f5d3SJohn Marino     case plex_striped:					    /* striped plex */
10186d7f5d3SJohn Marino 	return "striped";
10286d7f5d3SJohn Marino 	break;
10386d7f5d3SJohn Marino 
10486d7f5d3SJohn Marino     case plex_raid4:					    /* RAID-4 plex */
10586d7f5d3SJohn Marino 	return "raid4";
10686d7f5d3SJohn Marino 
10786d7f5d3SJohn Marino     case plex_raid5:					    /* RAID-5 plex */
10886d7f5d3SJohn Marino 	return "raid5";
10986d7f5d3SJohn Marino 	break;
11086d7f5d3SJohn Marino 
11186d7f5d3SJohn Marino     default:
11286d7f5d3SJohn Marino 	sprintf(numeric_state, "Invalid org %d", (int) org);
11386d7f5d3SJohn Marino 	return numeric_state;
11486d7f5d3SJohn Marino     }
11586d7f5d3SJohn Marino }
11686d7f5d3SJohn Marino 
11786d7f5d3SJohn Marino /* Return sd state as a string */
11886d7f5d3SJohn Marino char *
sd_state(enum sdstate state)11986d7f5d3SJohn Marino sd_state(enum sdstate state)
12086d7f5d3SJohn Marino {
12186d7f5d3SJohn Marino     if (((unsigned) state) >= STATECOUNT(sd)) {
12286d7f5d3SJohn Marino 	sprintf(numeric_state, "Invalid state %d", (int) state);
12386d7f5d3SJohn Marino 	return numeric_state;
12486d7f5d3SJohn Marino     } else
12586d7f5d3SJohn Marino 	return sdstatetext[state];
12686d7f5d3SJohn Marino }
12786d7f5d3SJohn Marino 
12886d7f5d3SJohn Marino /* Now convert in the other direction */
12986d7f5d3SJohn Marino /*
13086d7f5d3SJohn Marino  * These are currently used only internally,
13186d7f5d3SJohn Marino  * so we don't do too much error checking
13286d7f5d3SJohn Marino  */
13386d7f5d3SJohn Marino enum drivestate
DriveState(char * text)13486d7f5d3SJohn Marino DriveState(char *text)
13586d7f5d3SJohn Marino {
13686d7f5d3SJohn Marino     int i;
13786d7f5d3SJohn Marino     for (i = 0; i < STATECOUNT(drive); i++)
13886d7f5d3SJohn Marino 	if (strcmp(text, drivestatetext[i]) == 0)	    /* found it */
13986d7f5d3SJohn Marino 	    return (enum drivestate) i;
14086d7f5d3SJohn Marino     return -1;
14186d7f5d3SJohn Marino }
14286d7f5d3SJohn Marino 
14386d7f5d3SJohn Marino enum sdstate
SdState(char * text)14486d7f5d3SJohn Marino SdState(char *text)
14586d7f5d3SJohn Marino {
14686d7f5d3SJohn Marino     int i;
14786d7f5d3SJohn Marino     for (i = 0; i < STATECOUNT(sd); i++)
14886d7f5d3SJohn Marino 	if (strcmp(text, sdstatetext[i]) == 0)		    /* found it */
14986d7f5d3SJohn Marino 	    return (enum sdstate) i;
15086d7f5d3SJohn Marino     return -1;
15186d7f5d3SJohn Marino }
15286d7f5d3SJohn Marino 
15386d7f5d3SJohn Marino enum plexstate
PlexState(char * text)15486d7f5d3SJohn Marino PlexState(char *text)
15586d7f5d3SJohn Marino {
15686d7f5d3SJohn Marino     int i;
15786d7f5d3SJohn Marino     for (i = 0; i < STATECOUNT(plex); i++)
15886d7f5d3SJohn Marino 	if (strcmp(text, plexstatetext[i]) == 0)	    /* found it */
15986d7f5d3SJohn Marino 	    return (enum plexstate) i;
16086d7f5d3SJohn Marino     return -1;
16186d7f5d3SJohn Marino }
16286d7f5d3SJohn Marino 
16386d7f5d3SJohn Marino enum volumestate
VolState(char * text)16486d7f5d3SJohn Marino VolState(char *text)
16586d7f5d3SJohn Marino {
16686d7f5d3SJohn Marino     int i;
16786d7f5d3SJohn Marino     for (i = 0; i < STATECOUNT(vol); i++)
16886d7f5d3SJohn Marino 	if (strcmp(text, volstatetext[i]) == 0)		    /* found it */
16986d7f5d3SJohn Marino 	    return (enum volumestate) i;
17086d7f5d3SJohn Marino     return -1;
17186d7f5d3SJohn Marino }
17286d7f5d3SJohn Marino 
17386d7f5d3SJohn Marino /*
17486d7f5d3SJohn Marino  * Take a number with an optional scale factor and convert
17586d7f5d3SJohn Marino  * it to a number of bytes.
17686d7f5d3SJohn Marino  *
17786d7f5d3SJohn Marino  * The scale factors are:
17886d7f5d3SJohn Marino  *
17986d7f5d3SJohn Marino  * s    sectors (of 512 bytes)
18086d7f5d3SJohn Marino  * b    blocks (of 512 bytes).  This unit is deprecated,
18186d7f5d3SJohn Marino  *      because it's confusing, but maintained to avoid
18286d7f5d3SJohn Marino  *      confusing Veritas users.
18386d7f5d3SJohn Marino  * k    kilobytes (1024 bytes)
18486d7f5d3SJohn Marino  * m    megabytes (of 1024 * 1024 bytes)
18586d7f5d3SJohn Marino  * g    gigabytes (of 1024 * 1024 * 1024 bytes)
18686d7f5d3SJohn Marino  */
18786d7f5d3SJohn Marino u_int64_t
sizespec(char * spec)18886d7f5d3SJohn Marino sizespec(char *spec)
18986d7f5d3SJohn Marino {
19086d7f5d3SJohn Marino     u_int64_t size;
19186d7f5d3SJohn Marino     char *s;
19286d7f5d3SJohn Marino     int sign = 1;					    /* -1 if negative */
19386d7f5d3SJohn Marino 
19486d7f5d3SJohn Marino     size = 0;
19586d7f5d3SJohn Marino     if (spec != NULL) {					    /* we have a parameter */
19686d7f5d3SJohn Marino 	s = spec;
19786d7f5d3SJohn Marino 	if (*s == '-') {				    /* negative, */
19886d7f5d3SJohn Marino 	    sign = -1;
19986d7f5d3SJohn Marino 	    s++;					    /* skip */
20086d7f5d3SJohn Marino 	}
20186d7f5d3SJohn Marino 	if ((*s >= '0') && (*s <= '9')) {		    /* it's numeric */
20286d7f5d3SJohn Marino 	    while ((*s >= '0') && (*s <= '9'))		    /* it's numeric */
20386d7f5d3SJohn Marino 		size = size * 10 + *s++ - '0';		    /* convert it */
20486d7f5d3SJohn Marino 	    switch (*s) {
20586d7f5d3SJohn Marino 	    case '\0':
20686d7f5d3SJohn Marino 		return size * sign;
20786d7f5d3SJohn Marino 
20886d7f5d3SJohn Marino 	    case 'B':
20986d7f5d3SJohn Marino 	    case 'b':
21086d7f5d3SJohn Marino 	    case 'S':
21186d7f5d3SJohn Marino 	    case 's':
21286d7f5d3SJohn Marino 		return size * sign * 512;
21386d7f5d3SJohn Marino 
21486d7f5d3SJohn Marino 	    case 'K':
21586d7f5d3SJohn Marino 	    case 'k':
21686d7f5d3SJohn Marino 		return size * sign * 1024;
21786d7f5d3SJohn Marino 
21886d7f5d3SJohn Marino 	    case 'M':
21986d7f5d3SJohn Marino 	    case 'm':
22086d7f5d3SJohn Marino 		return size * sign * 1024 * 1024;
22186d7f5d3SJohn Marino 
22286d7f5d3SJohn Marino 	    case 'G':
22386d7f5d3SJohn Marino 	    case 'g':
22486d7f5d3SJohn Marino 		return size * sign * 1024 * 1024 * 1024;
22586d7f5d3SJohn Marino 	    }
22686d7f5d3SJohn Marino 	}
22786d7f5d3SJohn Marino 	throw_rude_remark(EINVAL, "Invalid length specification: %s", spec);
22886d7f5d3SJohn Marino     }
22986d7f5d3SJohn Marino     throw_rude_remark(EINVAL, "Missing length specification");
23086d7f5d3SJohn Marino     /* NOTREACHED */
23186d7f5d3SJohn Marino     return -1;
23286d7f5d3SJohn Marino }
23386d7f5d3SJohn Marino 
23486d7f5d3SJohn Marino /*
23586d7f5d3SJohn Marino  * Extract the volume number from a device number.
23686d7f5d3SJohn Marino  * Perform no checking.
23786d7f5d3SJohn Marino  */
23886d7f5d3SJohn Marino int
Volno(cdev_t dev)23986d7f5d3SJohn Marino Volno(cdev_t dev)
24086d7f5d3SJohn Marino {
24186d7f5d3SJohn Marino     return (minor(dev) & MASK(VINUM_VOL_WIDTH)) >> VINUM_VOL_SHIFT;
24286d7f5d3SJohn Marino }
24386d7f5d3SJohn Marino 
24486d7f5d3SJohn Marino /*
24586d7f5d3SJohn Marino  * Extract a plex number from a device number.
24686d7f5d3SJohn Marino  * Don't check the major number, but check the
24786d7f5d3SJohn Marino  * type.  Return -1 for invalid types.
24886d7f5d3SJohn Marino  */
24986d7f5d3SJohn Marino int
Plexno(cdev_t dev)25086d7f5d3SJohn Marino Plexno(cdev_t dev)
25186d7f5d3SJohn Marino {
25286d7f5d3SJohn Marino     switch (DEVTYPE(dev)) {
25386d7f5d3SJohn Marino     case VINUM_VOLUME_TYPE:
25486d7f5d3SJohn Marino     case VINUM_DRIVE_TYPE:
25586d7f5d3SJohn Marino     case VINUM_SUPERDEV_TYPE:				    /* ordinary super device */
25686d7f5d3SJohn Marino     case VINUM_RAWSD_TYPE:
25786d7f5d3SJohn Marino 	return -1;
25886d7f5d3SJohn Marino 
25986d7f5d3SJohn Marino     case VINUM_PLEX_TYPE:
26086d7f5d3SJohn Marino     case VINUM_SD_TYPE:
26186d7f5d3SJohn Marino 	return VOL[Volno(dev)].plex[(minor(dev) >> VINUM_PLEX_SHIFT) & (MASK(VINUM_PLEX_WIDTH))];
26286d7f5d3SJohn Marino 
26386d7f5d3SJohn Marino     case VINUM_RAWPLEX_TYPE:
26486d7f5d3SJohn Marino 	return ((minor(dev) & MASK(VINUM_VOL_WIDTH)) >> VINUM_VOL_SHIFT) /* low order 8 bits */
26586d7f5d3SJohn Marino 	|((minor(dev) >> VINUM_RAWPLEX_SHIFT)
26686d7f5d3SJohn Marino 	    & (MASK(VINUM_RAWPLEX_WIDTH)
26786d7f5d3SJohn Marino 		<< (VINUM_VOL_SHIFT + VINUM_VOL_WIDTH)));   /* upper 12 bits */
26886d7f5d3SJohn Marino     }
26986d7f5d3SJohn Marino     return 0;						    /* compiler paranoia */
27086d7f5d3SJohn Marino }
27186d7f5d3SJohn Marino 
27286d7f5d3SJohn Marino /*
27386d7f5d3SJohn Marino  * Extract a subdisk number from a device number.
27486d7f5d3SJohn Marino  * Don't check the major number, but check the
27586d7f5d3SJohn Marino  * type.  Return -1 for invalid types.
27686d7f5d3SJohn Marino  */
27786d7f5d3SJohn Marino int
Sdno(cdev_t dev)27886d7f5d3SJohn Marino Sdno(cdev_t dev)
27986d7f5d3SJohn Marino {
28086d7f5d3SJohn Marino     switch (DEVTYPE(dev)) {
28186d7f5d3SJohn Marino     case VINUM_VOLUME_TYPE:
28286d7f5d3SJohn Marino     case VINUM_DRIVE_TYPE:
28386d7f5d3SJohn Marino     case VINUM_SUPERDEV_TYPE:				    /* ordinary super device */
28486d7f5d3SJohn Marino     case VINUM_PLEX_TYPE:
28586d7f5d3SJohn Marino     case VINUM_RAWPLEX_TYPE:
28686d7f5d3SJohn Marino 	return -1;
28786d7f5d3SJohn Marino 
28886d7f5d3SJohn Marino     case VINUM_SD_TYPE:
28986d7f5d3SJohn Marino 	return PLEX[Plexno(dev)].sdnos[(minor(dev) >> VINUM_SD_SHIFT) & (MASK(VINUM_SD_WIDTH))];
29086d7f5d3SJohn Marino 
29186d7f5d3SJohn Marino     case VINUM_RAWSD_TYPE:
29286d7f5d3SJohn Marino 	return ((minor(dev) & MASK(VINUM_VOL_WIDTH)) >> VINUM_VOL_SHIFT) /* low order 8 bits */
29386d7f5d3SJohn Marino 	|((minor(dev) >> VINUM_RAWPLEX_SHIFT) & (MASK(VINUM_RAWPLEX_WIDTH)
29486d7f5d3SJohn Marino 		<< (VINUM_VOL_SHIFT + VINUM_VOL_WIDTH)));   /* upper 12 bits */
29586d7f5d3SJohn Marino     }
29686d7f5d3SJohn Marino     return -1;						    /* compiler paranoia */
29786d7f5d3SJohn Marino }
298