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