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