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