xref: /dragonfly/sys/dev/raid/vinum/vinumutil.c (revision 86d7f5d3)
1*86d7f5d3SJohn Marino /*-
2*86d7f5d3SJohn Marino  * Copyright (c) 1997, 1998, 1999
3*86d7f5d3SJohn Marino  *	Nan Yang Computer Services Limited.  All rights reserved.
4*86d7f5d3SJohn Marino  *
5*86d7f5d3SJohn Marino  *  Written by Greg Lehey
6*86d7f5d3SJohn Marino  *
7*86d7f5d3SJohn Marino  *  This software is distributed under the so-called ``Berkeley
8*86d7f5d3SJohn Marino  *  License'':
9*86d7f5d3SJohn Marino  *
10*86d7f5d3SJohn Marino  * Redistribution and use in source and binary forms, with or without
11*86d7f5d3SJohn Marino  * modification, are permitted provided that the following conditions
12*86d7f5d3SJohn Marino  * are met:
13*86d7f5d3SJohn Marino  * 1. Redistributions of source code must retain the above copyright
14*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer.
15*86d7f5d3SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
16*86d7f5d3SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
17*86d7f5d3SJohn Marino  *    documentation and/or other materials provided with the distribution.
18*86d7f5d3SJohn Marino  * 3. All advertising materials mentioning features or use of this software
19*86d7f5d3SJohn Marino  *    must display the following acknowledgement:
20*86d7f5d3SJohn Marino  *	This product includes software developed by Nan Yang Computer
21*86d7f5d3SJohn Marino  *      Services Limited.
22*86d7f5d3SJohn Marino  * 4. Neither the name of the Company nor the names of its contributors
23*86d7f5d3SJohn Marino  *    may be used to endorse or promote products derived from this software
24*86d7f5d3SJohn Marino  *    without specific prior written permission.
25*86d7f5d3SJohn Marino  *
26*86d7f5d3SJohn Marino  * This software is provided ``as is'', and any express or implied
27*86d7f5d3SJohn Marino  * warranties, including, but not limited to, the implied warranties of
28*86d7f5d3SJohn Marino  * merchantability and fitness for a particular purpose are disclaimed.
29*86d7f5d3SJohn Marino  * In no event shall the company or contributors be liable for any
30*86d7f5d3SJohn Marino  * direct, indirect, incidental, special, exemplary, or consequential
31*86d7f5d3SJohn Marino  * damages (including, but not limited to, procurement of substitute
32*86d7f5d3SJohn Marino  * goods or services; loss of use, data, or profits; or business
33*86d7f5d3SJohn Marino  * interruption) however caused and on any theory of liability, whether
34*86d7f5d3SJohn Marino  * in contract, strict liability, or tort (including negligence or
35*86d7f5d3SJohn Marino  * otherwise) arising in any way out of the use of this software, even if
36*86d7f5d3SJohn Marino  * advised of the possibility of such damage.
37*86d7f5d3SJohn Marino  *
38*86d7f5d3SJohn Marino  * $Id: vinumutil.c,v 1.14 1999/12/30 07:04:02 grog Exp grog $
39*86d7f5d3SJohn Marino  * $FreeBSD: src/sys/dev/vinum/vinumutil.c,v 1.15 2000/02/29 06:16:44 grog Exp $
40*86d7f5d3SJohn Marino  * $DragonFly: src/sys/dev/raid/vinum/vinumutil.c,v 1.6 2006/12/20 18:14:40 dillon Exp $
41*86d7f5d3SJohn Marino  */
42*86d7f5d3SJohn Marino 
43*86d7f5d3SJohn Marino /* This file contains utility routines used both in kernel and user context */
44*86d7f5d3SJohn Marino 
45*86d7f5d3SJohn Marino #include "vinumhdr.h"
46*86d7f5d3SJohn Marino #include "statetexts.h"
47*86d7f5d3SJohn Marino 
48*86d7f5d3SJohn Marino #ifdef _KERNEL
49*86d7f5d3SJohn Marino #define sprintf	ksprintf
50*86d7f5d3SJohn Marino #endif
51*86d7f5d3SJohn Marino 
52*86d7f5d3SJohn Marino static char numeric_state[32];				    /* temporary buffer for ASCII conversions */
53*86d7f5d3SJohn Marino #define STATECOUNT(x) (sizeof (x##statetext) / sizeof (char *))
54*86d7f5d3SJohn Marino /* Return drive state as a string */
55*86d7f5d3SJohn Marino char *
drive_state(enum drivestate state)56*86d7f5d3SJohn Marino drive_state(enum drivestate state)
57*86d7f5d3SJohn Marino {
58*86d7f5d3SJohn Marino     if (((unsigned) state) >= STATECOUNT(drive)) {
59*86d7f5d3SJohn Marino 	sprintf(numeric_state, "Invalid state %d", (int) state);
60*86d7f5d3SJohn Marino 	return numeric_state;
61*86d7f5d3SJohn Marino     } else
62*86d7f5d3SJohn Marino 	return drivestatetext[state];
63*86d7f5d3SJohn Marino }
64*86d7f5d3SJohn Marino 
65*86d7f5d3SJohn Marino /* Return volume state as a string */
66*86d7f5d3SJohn Marino char *
volume_state(enum volumestate state)67*86d7f5d3SJohn Marino volume_state(enum volumestate state)
68*86d7f5d3SJohn Marino {
69*86d7f5d3SJohn Marino     if (((unsigned) state) >= STATECOUNT(vol)) {
70*86d7f5d3SJohn Marino 	sprintf(numeric_state, "Invalid state %d", (int) state);
71*86d7f5d3SJohn Marino 	return numeric_state;
72*86d7f5d3SJohn Marino     } else
73*86d7f5d3SJohn Marino 	return volstatetext[state];
74*86d7f5d3SJohn Marino }
75*86d7f5d3SJohn Marino 
76*86d7f5d3SJohn Marino /* Return plex state as a string */
77*86d7f5d3SJohn Marino char *
plex_state(enum plexstate state)78*86d7f5d3SJohn Marino plex_state(enum plexstate state)
79*86d7f5d3SJohn Marino {
80*86d7f5d3SJohn Marino     if (((unsigned) state) >= STATECOUNT(plex)) {
81*86d7f5d3SJohn Marino 	sprintf(numeric_state, "Invalid state %d", (int) state);
82*86d7f5d3SJohn Marino 	return numeric_state;
83*86d7f5d3SJohn Marino     } else
84*86d7f5d3SJohn Marino 	return plexstatetext[state];
85*86d7f5d3SJohn Marino }
86*86d7f5d3SJohn Marino 
87*86d7f5d3SJohn Marino /* Return plex organization as a string */
88*86d7f5d3SJohn Marino char *
plex_org(enum plexorg org)89*86d7f5d3SJohn Marino plex_org(enum plexorg org)
90*86d7f5d3SJohn Marino {
91*86d7f5d3SJohn Marino     switch (org) {
92*86d7f5d3SJohn Marino     case plex_disorg:					    /* disorganized */
93*86d7f5d3SJohn Marino 	return "disorg";
94*86d7f5d3SJohn Marino 	break;
95*86d7f5d3SJohn Marino 
96*86d7f5d3SJohn Marino     case plex_concat:					    /* concatenated plex */
97*86d7f5d3SJohn Marino 	return "concat";
98*86d7f5d3SJohn Marino 	break;
99*86d7f5d3SJohn Marino 
100*86d7f5d3SJohn Marino     case plex_striped:					    /* striped plex */
101*86d7f5d3SJohn Marino 	return "striped";
102*86d7f5d3SJohn Marino 	break;
103*86d7f5d3SJohn Marino 
104*86d7f5d3SJohn Marino     case plex_raid4:					    /* RAID-4 plex */
105*86d7f5d3SJohn Marino 	return "raid4";
106*86d7f5d3SJohn Marino 
107*86d7f5d3SJohn Marino     case plex_raid5:					    /* RAID-5 plex */
108*86d7f5d3SJohn Marino 	return "raid5";
109*86d7f5d3SJohn Marino 	break;
110*86d7f5d3SJohn Marino 
111*86d7f5d3SJohn Marino     default:
112*86d7f5d3SJohn Marino 	sprintf(numeric_state, "Invalid org %d", (int) org);
113*86d7f5d3SJohn Marino 	return numeric_state;
114*86d7f5d3SJohn Marino     }
115*86d7f5d3SJohn Marino }
116*86d7f5d3SJohn Marino 
117*86d7f5d3SJohn Marino /* Return sd state as a string */
118*86d7f5d3SJohn Marino char *
sd_state(enum sdstate state)119*86d7f5d3SJohn Marino sd_state(enum sdstate state)
120*86d7f5d3SJohn Marino {
121*86d7f5d3SJohn Marino     if (((unsigned) state) >= STATECOUNT(sd)) {
122*86d7f5d3SJohn Marino 	sprintf(numeric_state, "Invalid state %d", (int) state);
123*86d7f5d3SJohn Marino 	return numeric_state;
124*86d7f5d3SJohn Marino     } else
125*86d7f5d3SJohn Marino 	return sdstatetext[state];
126*86d7f5d3SJohn Marino }
127*86d7f5d3SJohn Marino 
128*86d7f5d3SJohn Marino /* Now convert in the other direction */
129*86d7f5d3SJohn Marino /*
130*86d7f5d3SJohn Marino  * These are currently used only internally,
131*86d7f5d3SJohn Marino  * so we don't do too much error checking
132*86d7f5d3SJohn Marino  */
133*86d7f5d3SJohn Marino enum drivestate
DriveState(char * text)134*86d7f5d3SJohn Marino DriveState(char *text)
135*86d7f5d3SJohn Marino {
136*86d7f5d3SJohn Marino     int i;
137*86d7f5d3SJohn Marino     for (i = 0; i < STATECOUNT(drive); i++)
138*86d7f5d3SJohn Marino 	if (strcmp(text, drivestatetext[i]) == 0)	    /* found it */
139*86d7f5d3SJohn Marino 	    return (enum drivestate) i;
140*86d7f5d3SJohn Marino     return -1;
141*86d7f5d3SJohn Marino }
142*86d7f5d3SJohn Marino 
143*86d7f5d3SJohn Marino enum sdstate
SdState(char * text)144*86d7f5d3SJohn Marino SdState(char *text)
145*86d7f5d3SJohn Marino {
146*86d7f5d3SJohn Marino     int i;
147*86d7f5d3SJohn Marino     for (i = 0; i < STATECOUNT(sd); i++)
148*86d7f5d3SJohn Marino 	if (strcmp(text, sdstatetext[i]) == 0)		    /* found it */
149*86d7f5d3SJohn Marino 	    return (enum sdstate) i;
150*86d7f5d3SJohn Marino     return -1;
151*86d7f5d3SJohn Marino }
152*86d7f5d3SJohn Marino 
153*86d7f5d3SJohn Marino enum plexstate
PlexState(char * text)154*86d7f5d3SJohn Marino PlexState(char *text)
155*86d7f5d3SJohn Marino {
156*86d7f5d3SJohn Marino     int i;
157*86d7f5d3SJohn Marino     for (i = 0; i < STATECOUNT(plex); i++)
158*86d7f5d3SJohn Marino 	if (strcmp(text, plexstatetext[i]) == 0)	    /* found it */
159*86d7f5d3SJohn Marino 	    return (enum plexstate) i;
160*86d7f5d3SJohn Marino     return -1;
161*86d7f5d3SJohn Marino }
162*86d7f5d3SJohn Marino 
163*86d7f5d3SJohn Marino enum volumestate
VolState(char * text)164*86d7f5d3SJohn Marino VolState(char *text)
165*86d7f5d3SJohn Marino {
166*86d7f5d3SJohn Marino     int i;
167*86d7f5d3SJohn Marino     for (i = 0; i < STATECOUNT(vol); i++)
168*86d7f5d3SJohn Marino 	if (strcmp(text, volstatetext[i]) == 0)		    /* found it */
169*86d7f5d3SJohn Marino 	    return (enum volumestate) i;
170*86d7f5d3SJohn Marino     return -1;
171*86d7f5d3SJohn Marino }
172*86d7f5d3SJohn Marino 
173*86d7f5d3SJohn Marino /*
174*86d7f5d3SJohn Marino  * Take a number with an optional scale factor and convert
175*86d7f5d3SJohn Marino  * it to a number of bytes.
176*86d7f5d3SJohn Marino  *
177*86d7f5d3SJohn Marino  * The scale factors are:
178*86d7f5d3SJohn Marino  *
179*86d7f5d3SJohn Marino  * s    sectors (of 512 bytes)
180*86d7f5d3SJohn Marino  * b    blocks (of 512 bytes).  This unit is deprecated,
181*86d7f5d3SJohn Marino  *      because it's confusing, but maintained to avoid
182*86d7f5d3SJohn Marino  *      confusing Veritas users.
183*86d7f5d3SJohn Marino  * k    kilobytes (1024 bytes)
184*86d7f5d3SJohn Marino  * m    megabytes (of 1024 * 1024 bytes)
185*86d7f5d3SJohn Marino  * g    gigabytes (of 1024 * 1024 * 1024 bytes)
186*86d7f5d3SJohn Marino  */
187*86d7f5d3SJohn Marino u_int64_t
sizespec(char * spec)188*86d7f5d3SJohn Marino sizespec(char *spec)
189*86d7f5d3SJohn Marino {
190*86d7f5d3SJohn Marino     u_int64_t size;
191*86d7f5d3SJohn Marino     char *s;
192*86d7f5d3SJohn Marino     int sign = 1;					    /* -1 if negative */
193*86d7f5d3SJohn Marino 
194*86d7f5d3SJohn Marino     size = 0;
195*86d7f5d3SJohn Marino     if (spec != NULL) {					    /* we have a parameter */
196*86d7f5d3SJohn Marino 	s = spec;
197*86d7f5d3SJohn Marino 	if (*s == '-') {				    /* negative, */
198*86d7f5d3SJohn Marino 	    sign = -1;
199*86d7f5d3SJohn Marino 	    s++;					    /* skip */
200*86d7f5d3SJohn Marino 	}
201*86d7f5d3SJohn Marino 	if ((*s >= '0') && (*s <= '9')) {		    /* it's numeric */
202*86d7f5d3SJohn Marino 	    while ((*s >= '0') && (*s <= '9'))		    /* it's numeric */
203*86d7f5d3SJohn Marino 		size = size * 10 + *s++ - '0';		    /* convert it */
204*86d7f5d3SJohn Marino 	    switch (*s) {
205*86d7f5d3SJohn Marino 	    case '\0':
206*86d7f5d3SJohn Marino 		return size * sign;
207*86d7f5d3SJohn Marino 
208*86d7f5d3SJohn Marino 	    case 'B':
209*86d7f5d3SJohn Marino 	    case 'b':
210*86d7f5d3SJohn Marino 	    case 'S':
211*86d7f5d3SJohn Marino 	    case 's':
212*86d7f5d3SJohn Marino 		return size * sign * 512;
213*86d7f5d3SJohn Marino 
214*86d7f5d3SJohn Marino 	    case 'K':
215*86d7f5d3SJohn Marino 	    case 'k':
216*86d7f5d3SJohn Marino 		return size * sign * 1024;
217*86d7f5d3SJohn Marino 
218*86d7f5d3SJohn Marino 	    case 'M':
219*86d7f5d3SJohn Marino 	    case 'm':
220*86d7f5d3SJohn Marino 		return size * sign * 1024 * 1024;
221*86d7f5d3SJohn Marino 
222*86d7f5d3SJohn Marino 	    case 'G':
223*86d7f5d3SJohn Marino 	    case 'g':
224*86d7f5d3SJohn Marino 		return size * sign * 1024 * 1024 * 1024;
225*86d7f5d3SJohn Marino 	    }
226*86d7f5d3SJohn Marino 	}
227*86d7f5d3SJohn Marino 	throw_rude_remark(EINVAL, "Invalid length specification: %s", spec);
228*86d7f5d3SJohn Marino     }
229*86d7f5d3SJohn Marino     throw_rude_remark(EINVAL, "Missing length specification");
230*86d7f5d3SJohn Marino     /* NOTREACHED */
231*86d7f5d3SJohn Marino     return -1;
232*86d7f5d3SJohn Marino }
233*86d7f5d3SJohn Marino 
234*86d7f5d3SJohn Marino /*
235*86d7f5d3SJohn Marino  * Extract the volume number from a device number.
236*86d7f5d3SJohn Marino  * Perform no checking.
237*86d7f5d3SJohn Marino  */
238*86d7f5d3SJohn Marino int
Volno(cdev_t dev)239*86d7f5d3SJohn Marino Volno(cdev_t dev)
240*86d7f5d3SJohn Marino {
241*86d7f5d3SJohn Marino     return (minor(dev) & MASK(VINUM_VOL_WIDTH)) >> VINUM_VOL_SHIFT;
242*86d7f5d3SJohn Marino }
243*86d7f5d3SJohn Marino 
244*86d7f5d3SJohn Marino /*
245*86d7f5d3SJohn Marino  * Extract a plex number from a device number.
246*86d7f5d3SJohn Marino  * Don't check the major number, but check the
247*86d7f5d3SJohn Marino  * type.  Return -1 for invalid types.
248*86d7f5d3SJohn Marino  */
249*86d7f5d3SJohn Marino int
Plexno(cdev_t dev)250*86d7f5d3SJohn Marino Plexno(cdev_t dev)
251*86d7f5d3SJohn Marino {
252*86d7f5d3SJohn Marino     switch (DEVTYPE(dev)) {
253*86d7f5d3SJohn Marino     case VINUM_VOLUME_TYPE:
254*86d7f5d3SJohn Marino     case VINUM_DRIVE_TYPE:
255*86d7f5d3SJohn Marino     case VINUM_SUPERDEV_TYPE:				    /* ordinary super device */
256*86d7f5d3SJohn Marino     case VINUM_RAWSD_TYPE:
257*86d7f5d3SJohn Marino 	return -1;
258*86d7f5d3SJohn Marino 
259*86d7f5d3SJohn Marino     case VINUM_PLEX_TYPE:
260*86d7f5d3SJohn Marino     case VINUM_SD_TYPE:
261*86d7f5d3SJohn Marino 	return VOL[Volno(dev)].plex[(minor(dev) >> VINUM_PLEX_SHIFT) & (MASK(VINUM_PLEX_WIDTH))];
262*86d7f5d3SJohn Marino 
263*86d7f5d3SJohn Marino     case VINUM_RAWPLEX_TYPE:
264*86d7f5d3SJohn Marino 	return ((minor(dev) & MASK(VINUM_VOL_WIDTH)) >> VINUM_VOL_SHIFT) /* low order 8 bits */
265*86d7f5d3SJohn Marino 	|((minor(dev) >> VINUM_RAWPLEX_SHIFT)
266*86d7f5d3SJohn Marino 	    & (MASK(VINUM_RAWPLEX_WIDTH)
267*86d7f5d3SJohn Marino 		<< (VINUM_VOL_SHIFT + VINUM_VOL_WIDTH)));   /* upper 12 bits */
268*86d7f5d3SJohn Marino     }
269*86d7f5d3SJohn Marino     return 0;						    /* compiler paranoia */
270*86d7f5d3SJohn Marino }
271*86d7f5d3SJohn Marino 
272*86d7f5d3SJohn Marino /*
273*86d7f5d3SJohn Marino  * Extract a subdisk number from a device number.
274*86d7f5d3SJohn Marino  * Don't check the major number, but check the
275*86d7f5d3SJohn Marino  * type.  Return -1 for invalid types.
276*86d7f5d3SJohn Marino  */
277*86d7f5d3SJohn Marino int
Sdno(cdev_t dev)278*86d7f5d3SJohn Marino Sdno(cdev_t dev)
279*86d7f5d3SJohn Marino {
280*86d7f5d3SJohn Marino     switch (DEVTYPE(dev)) {
281*86d7f5d3SJohn Marino     case VINUM_VOLUME_TYPE:
282*86d7f5d3SJohn Marino     case VINUM_DRIVE_TYPE:
283*86d7f5d3SJohn Marino     case VINUM_SUPERDEV_TYPE:				    /* ordinary super device */
284*86d7f5d3SJohn Marino     case VINUM_PLEX_TYPE:
285*86d7f5d3SJohn Marino     case VINUM_RAWPLEX_TYPE:
286*86d7f5d3SJohn Marino 	return -1;
287*86d7f5d3SJohn Marino 
288*86d7f5d3SJohn Marino     case VINUM_SD_TYPE:
289*86d7f5d3SJohn Marino 	return PLEX[Plexno(dev)].sdnos[(minor(dev) >> VINUM_SD_SHIFT) & (MASK(VINUM_SD_WIDTH))];
290*86d7f5d3SJohn Marino 
291*86d7f5d3SJohn Marino     case VINUM_RAWSD_TYPE:
292*86d7f5d3SJohn Marino 	return ((minor(dev) & MASK(VINUM_VOL_WIDTH)) >> VINUM_VOL_SHIFT) /* low order 8 bits */
293*86d7f5d3SJohn Marino 	|((minor(dev) >> VINUM_RAWPLEX_SHIFT) & (MASK(VINUM_RAWPLEX_WIDTH)
294*86d7f5d3SJohn Marino 		<< (VINUM_VOL_SHIFT + VINUM_VOL_WIDTH)));   /* upper 12 bits */
295*86d7f5d3SJohn Marino     }
296*86d7f5d3SJohn Marino     return -1;						    /* compiler paranoia */
297*86d7f5d3SJohn Marino }
298