ccdconfig.c (3f4f4a1465e1b9e6174d6bac813020768efd18b3) | ccdconfig.c (89a7b2b7140aff11a0c927c44f4c573dcc969434) |
---|---|
1/* $NetBSD: ccdconfig.c,v 1.2.2.1 1995/11/11 02:43:35 thorpej Exp $ */ 2 |
|
1/* | 3/* |
2 * Copyright (c) 2003 Poul-Henning Kamp | |
3 * Copyright (c) 1995 Jason R. Thorpe. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. --- 15 unchanged lines hidden (view full) --- 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 | 4 * Copyright (c) 1995 Jason R. Thorpe. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. --- 15 unchanged lines hidden (view full) --- 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 |
34#include <sys/cdefs.h> 35__FBSDID("$FreeBSD$"); 36 | |
37#include <sys/param.h> | 35#include <sys/param.h> |
38#include <sys/linker.h> 39#include <sys/module.h> | 36#include <sys/ioctl.h> 37#include <sys/disklabel.h> 38#include <sys/device.h> 39#include <sys/disk.h> 40#include <sys/stat.h> 41#include <sys/sysctl.h> |
40#include <ctype.h> 41#include <err.h> 42#include <errno.h> | 42#include <ctype.h> 43#include <err.h> 44#include <errno.h> |
45#include <fcntl.h> 46#include <kvm.h> |
|
43#include <limits.h> | 47#include <limits.h> |
44#include <paths.h> | 48#include <nlist.h> |
45#include <stdio.h> 46#include <stdlib.h> 47#include <string.h> 48#include <unistd.h> | 49#include <stdio.h> 50#include <stdlib.h> 51#include <string.h> 52#include <unistd.h> |
49#include <libgeom.h> | |
50 | 53 |
51#define CCDF_UNIFORM 0x02 /* use LCCD of sizes for uniform interleave */ 52#define CCDF_MIRROR 0x04 /* use mirroring */ 53#define CCDF_NO_OFFSET 0x08 /* do not leave space in front */ 54#define CCDF_LINUX 0x10 /* use Linux compatibility mode */ | 54#include <dev/ccdvar.h> |
55 56#include "pathnames.h" 57 | 55 56#include "pathnames.h" 57 |
58extern char *__progname; 59 |
|
58static int lineno = 0; 59static int verbose = 0; | 60static int lineno = 0; 61static int verbose = 0; |
60static const char *ccdconf = _PATH_CCDCONF; | 62static char *ccdconf = _PATH_CCDCONF; |
61 | 63 |
64static char *core = NULL; 65static char *kernel = NULL; 66 |
|
62struct flagval { | 67struct flagval { |
63 const char *fv_flag; 64 int fv_val; | 68 char *fv_flag; 69 int fv_val; |
65} flagvaltab[] = { | 70} flagvaltab[] = { |
71 { "CCDF_SWAP", CCDF_SWAP }, |
|
66 { "CCDF_UNIFORM", CCDF_UNIFORM }, | 72 { "CCDF_UNIFORM", CCDF_UNIFORM }, |
67 { "uniform", CCDF_UNIFORM }, 68 { "CCDF_MIRROR", CCDF_MIRROR }, 69 { "mirror", CCDF_MIRROR }, 70 { "CCDF_NO_OFFSET", CCDF_NO_OFFSET }, 71 { "no_offset", CCDF_NO_OFFSET }, 72 { "CCDF_LINUX", CCDF_LINUX }, 73 { "linux", CCDF_LINUX }, 74 { "none", 0 }, | |
75 { NULL, 0 }, 76}; 77 | 73 { NULL, 0 }, 74}; 75 |
76static struct nlist nl[] = { 77 { "_ccd_softc" }, 78#define SYM_CCDSOFTC 0 79 { "_numccd" }, 80#define SYM_NUMCCD 1 81 { NULL }, 82}; 83 |
|
78#define CCD_CONFIG 0 /* configure a device */ 79#define CCD_CONFIGALL 1 /* configure all devices */ 80#define CCD_UNCONFIG 2 /* unconfigure a device */ 81#define CCD_UNCONFIGALL 3 /* unconfigure all devices */ 82#define CCD_DUMP 4 /* dump a ccd's configuration */ 83 | 84#define CCD_CONFIG 0 /* configure a device */ 85#define CCD_CONFIGALL 1 /* configure all devices */ 86#define CCD_UNCONFIG 2 /* unconfigure a device */ 87#define CCD_UNCONFIGALL 3 /* unconfigure all devices */ 88#define CCD_DUMP 4 /* dump a ccd's configuration */ 89 |
84static int do_single(int, char **, int); 85static int do_all(int); 86static int dump_ccd(int, char **); 87static int flags_to_val(char *); 88static int resolve_ccdname(char *); 89static void usage(void); | 90static int checkdev __P((char *)); 91static int do_io __P((char *, u_long, struct ccd_ioctl *)); 92static int do_single __P((int, char **, int)); 93static int do_all __P((int)); 94static int dump_ccd __P((int, char **)); 95static int getmaxpartitions __P((void)); 96static int getrawpartition __P((void)); 97static int flags_to_val __P((char *)); 98static int pathtodevt __P((char *, dev_t *)); 99static void print_ccd_info __P((struct ccd_softc *, kvm_t *)); 100static char *resolve_ccdname __P((char *)); 101static void usage __P((void)); |
90 91int | 102 103int |
92main(int argc, char *argv[]) | 104main(argc, argv) 105 int argc; 106 char **argv; |
93{ 94 int ch, options = 0, action = CCD_CONFIG; 95 | 107{ 108 int ch, options = 0, action = CCD_CONFIG; 109 |
96 while ((ch = getopt(argc, argv, "cCf:guUv")) != -1) { | 110 while ((ch = getopt(argc, argv, "cCf:gM:N:uUv")) != -1) { |
97 switch (ch) { 98 case 'c': 99 action = CCD_CONFIG; 100 ++options; 101 break; 102 103 case 'C': 104 action = CCD_CONFIGALL; 105 ++options; 106 break; 107 108 case 'f': 109 ccdconf = optarg; 110 break; 111 112 case 'g': 113 action = CCD_DUMP; 114 break; 115 | 111 switch (ch) { 112 case 'c': 113 action = CCD_CONFIG; 114 ++options; 115 break; 116 117 case 'C': 118 action = CCD_CONFIGALL; 119 ++options; 120 break; 121 122 case 'f': 123 ccdconf = optarg; 124 break; 125 126 case 'g': 127 action = CCD_DUMP; 128 break; 129 |
130 case 'M': 131 core = optarg; 132 break; 133 134 case 'N': 135 kernel = optarg; 136 break; 137 |
|
116 case 'u': 117 action = CCD_UNCONFIG; 118 ++options; 119 break; 120 121 case 'U': 122 action = CCD_UNCONFIGALL; 123 ++options; --- 8 unchanged lines hidden (view full) --- 132 } 133 } 134 argc -= optind; 135 argv += optind; 136 137 if (options > 1) 138 usage(); 139 | 138 case 'u': 139 action = CCD_UNCONFIG; 140 ++options; 141 break; 142 143 case 'U': 144 action = CCD_UNCONFIGALL; 145 ++options; --- 8 unchanged lines hidden (view full) --- 154 } 155 } 156 argc -= optind; 157 argv += optind; 158 159 if (options > 1) 160 usage(); 161 |
140 if (modfind("g_ccd") < 0) { 141 /* Not present in kernel, try loading it */ 142 if (kldload("geom_ccd") < 0 || modfind("g_ccd") < 0) 143 warn("geom_ccd module not available!"); 144 } 145 | |
146 switch (action) { 147 case CCD_CONFIG: 148 case CCD_UNCONFIG: 149 exit(do_single(argc, argv, action)); 150 /* NOTREACHED */ 151 152 case CCD_CONFIGALL: 153 case CCD_UNCONFIGALL: 154 exit(do_all(action)); 155 /* NOTREACHED */ 156 157 case CCD_DUMP: 158 exit(dump_ccd(argc, argv)); 159 /* NOTREACHED */ 160 } 161 /* NOTREACHED */ | 162 switch (action) { 163 case CCD_CONFIG: 164 case CCD_UNCONFIG: 165 exit(do_single(argc, argv, action)); 166 /* NOTREACHED */ 167 168 case CCD_CONFIGALL: 169 case CCD_UNCONFIGALL: 170 exit(do_all(action)); 171 /* NOTREACHED */ 172 173 case CCD_DUMP: 174 exit(dump_ccd(argc, argv)); 175 /* NOTREACHED */ 176 } 177 /* NOTREACHED */ |
162 return (0); | |
163} 164 165static int | 178} 179 180static int |
166do_single(int argc, char **argv, int action) | 181do_single(argc, argv, action) 182 int argc; 183 char **argv; 184 int action; |
167{ | 185{ |
168 char *cp, *cp2; 169 int ccd, noflags = 0, i, ileave, flags = 0; 170 struct gctl_req *grq; 171 char const *errstr; 172 char buf1[BUFSIZ]; 173 int ex; | 186 struct ccd_ioctl ccio; 187 char *ccd, *cp, *cp2, **disks; 188 int noflags = 0, i, ileave, flags, j, error; |
174 | 189 |
190 bzero(&ccio, sizeof(ccio)); 191 |
|
175 /* 176 * If unconfiguring, all arguments are treated as ccds. 177 */ 178 if (action == CCD_UNCONFIG || action == CCD_UNCONFIGALL) { | 192 /* 193 * If unconfiguring, all arguments are treated as ccds. 194 */ 195 if (action == CCD_UNCONFIG || action == CCD_UNCONFIGALL) { |
179 ex = 0; | |
180 for (i = 0; argc != 0; ) { 181 cp = *argv++; --argc; | 196 for (i = 0; argc != 0; ) { 197 cp = *argv++; --argc; |
182 if ((ccd = resolve_ccdname(cp)) < 0) { | 198 if ((ccd = resolve_ccdname(cp)) == NULL) { |
183 warnx("invalid ccd name: %s", cp); 184 i = 1; 185 continue; 186 } | 199 warnx("invalid ccd name: %s", cp); 200 i = 1; 201 continue; 202 } |
187 grq = gctl_get_handle(); 188 gctl_ro_param(grq, "verb", -1, "destroy geom"); 189 gctl_ro_param(grq, "class", -1, "CCD"); 190 sprintf(buf1, "ccd%d", ccd); 191 gctl_ro_param(grq, "geom", -1, buf1); 192 errstr = gctl_issue(grq); 193 if (errstr == NULL) { | 203 if (do_io(ccd, CCDIOCCLR, &ccio)) 204 i = 1; 205 else |
194 if (verbose) 195 printf("%s unconfigured\n", cp); | 206 if (verbose) 207 printf("%s unconfigured\n", cp); |
196 gctl_free(grq); 197 continue; 198 } 199 warnx( 200 "%s\nor possibly kernel and ccdconfig out of sync", 201 errstr); 202 ex = 1; | |
203 } | 208 } |
204 return (ex); | 209 return (i); |
205 } 206 207 /* Make sure there are enough arguments. */ | 210 } 211 212 /* Make sure there are enough arguments. */ |
208 if (argc < 4) { | 213 if (argc < 4) |
209 if (argc == 3) { 210 /* Assume that no flags are specified. */ 211 noflags = 1; 212 } else { 213 if (action == CCD_CONFIGALL) { 214 warnx("%s: bad line: %d", ccdconf, lineno); 215 return (1); 216 } else 217 usage(); 218 } | 214 if (argc == 3) { 215 /* Assume that no flags are specified. */ 216 noflags = 1; 217 } else { 218 if (action == CCD_CONFIGALL) { 219 warnx("%s: bad line: %d", ccdconf, lineno); 220 return (1); 221 } else 222 usage(); 223 } |
219 } | |
220 221 /* First argument is the ccd to configure. */ 222 cp = *argv++; --argc; | 224 225 /* First argument is the ccd to configure. */ 226 cp = *argv++; --argc; |
223 if ((ccd = resolve_ccdname(cp)) < 0) { | 227 if ((ccd = resolve_ccdname(cp)) == NULL) { |
224 warnx("invalid ccd name: %s", cp); 225 return (1); 226 } 227 228 /* Next argument is the interleave factor. */ 229 cp = *argv++; --argc; 230 errno = 0; /* to check for ERANGE */ 231 ileave = (int)strtol(cp, &cp2, 10); --- 5 unchanged lines hidden (view full) --- 237 if (noflags == 0) { 238 /* Next argument is the ccd configuration flags. */ 239 cp = *argv++; --argc; 240 if ((flags = flags_to_val(cp)) < 0) { 241 warnx("invalid flags argument: %s", cp); 242 return (1); 243 } 244 } | 228 warnx("invalid ccd name: %s", cp); 229 return (1); 230 } 231 232 /* Next argument is the interleave factor. */ 233 cp = *argv++; --argc; 234 errno = 0; /* to check for ERANGE */ 235 ileave = (int)strtol(cp, &cp2, 10); --- 5 unchanged lines hidden (view full) --- 241 if (noflags == 0) { 242 /* Next argument is the ccd configuration flags. */ 243 cp = *argv++; --argc; 244 if ((flags = flags_to_val(cp)) < 0) { 245 warnx("invalid flags argument: %s", cp); 246 return (1); 247 } 248 } |
245 grq = gctl_get_handle(); 246 gctl_ro_param(grq, "verb", -1, "create geom"); 247 gctl_ro_param(grq, "class", -1, "CCD"); 248 gctl_ro_param(grq, "unit", sizeof(ccd), &ccd); 249 gctl_ro_param(grq, "ileave", sizeof(ileave), &ileave); 250 if (flags & CCDF_UNIFORM) 251 gctl_ro_param(grq, "uniform", -1, ""); 252 if (flags & CCDF_MIRROR) 253 gctl_ro_param(grq, "mirror", -1, ""); 254 if (flags & CCDF_NO_OFFSET) 255 gctl_ro_param(grq, "no_offset", -1, ""); 256 if (flags & CCDF_LINUX) 257 gctl_ro_param(grq, "linux", -1, ""); 258 gctl_ro_param(grq, "nprovider", sizeof(argc), &argc); 259 for (i = 0; i < argc; i++) { 260 sprintf(buf1, "provider%d", i); 261 cp = argv[i]; 262 if (!strncmp(cp, _PATH_DEV, strlen(_PATH_DEV))) 263 cp += strlen(_PATH_DEV); 264 gctl_ro_param(grq, buf1, -1, cp); | 249 250 /* Next is the list of disks to make the ccd from. */ 251 disks = malloc(argc * sizeof(char *)); 252 if (disks == NULL) { 253 warnx("no memory to configure ccd"); 254 return (1); |
265 } | 255 } |
266 gctl_rw_param(grq, "output", sizeof(buf1), buf1); 267 errstr = gctl_issue(grq); 268 if (errstr == NULL) { 269 if (verbose) { 270 printf("%s", buf1); | 256 for (i = 0; argc != 0; ) { 257 cp = *argv++; --argc; 258 if ((j = checkdev(cp)) == 0) 259 disks[i++] = cp; 260 else { 261 warnx("%s: %s", cp, strerror(j)); 262 return (1); |
271 } | 263 } |
272 gctl_free(grq); 273 return (0); | |
274 } | 264 } |
275 warnx( 276 "%s\nor possibly kernel and ccdconfig out of sync", 277 errstr); 278 return (1); | 265 266 /* Fill in the ccio. */ 267 ccio.ccio_disks = disks; 268 ccio.ccio_ndisks = i; 269 ccio.ccio_ileave = ileave; 270 ccio.ccio_flags = flags; 271 272 if (do_io(ccd, CCDIOCSET, &ccio)) { 273 free(disks); 274 return (1); 275 } 276 277 if (verbose) { 278 printf("ccd%d: %d components ", ccio.ccio_unit, 279 ccio.ccio_ndisks); 280 for (i = 0; i < ccio.ccio_ndisks; ++i) { 281 if ((cp2 = strrchr(disks[i], '/')) != NULL) 282 ++cp2; 283 else 284 cp2 = disks[i]; 285 printf("%c%s%c", 286 i == 0 ? '(' : ' ', cp2, 287 i == ccio.ccio_ndisks - 1 ? ')' : ','); 288 } 289 printf(", %d blocks ", ccio.ccio_size); 290 if (ccio.ccio_ileave != 0) 291 printf("interleaved at %d blocks\n", ccio.ccio_ileave); 292 else 293 printf("concatenated\n"); 294 } 295 296 free(disks); 297 return (0); |
279} 280 281static int | 298} 299 300static int |
282do_all(int action) | 301do_all(action) 302 int action; |
283{ 284 FILE *f; 285 char line[_POSIX2_LINE_MAX]; 286 char *cp, **argv; 287 int argc, rval; | 303{ 304 FILE *f; 305 char line[_POSIX2_LINE_MAX]; 306 char *cp, **argv; 307 int argc, rval; |
288 gid_t egid; | |
289 | 308 |
290 rval = 0; 291 egid = getegid(); 292 setegid(getgid()); | |
293 if ((f = fopen(ccdconf, "r")) == NULL) { | 309 if ((f = fopen(ccdconf, "r")) == NULL) { |
294 setegid(egid); | |
295 warn("fopen: %s", ccdconf); 296 return (1); 297 } | 310 warn("fopen: %s", ccdconf); 311 return (1); 312 } |
298 setegid(egid); | |
299 300 while (fgets(line, sizeof(line), f) != NULL) { 301 argc = 0; 302 argv = NULL; 303 ++lineno; 304 if ((cp = strrchr(line, '\n')) != NULL) 305 *cp = '\0'; 306 --- 31 unchanged lines hidden (view full) --- 338 free(argv); 339 } 340 341 (void)fclose(f); 342 return (rval); 343} 344 345static int | 313 314 while (fgets(line, sizeof(line), f) != NULL) { 315 argc = 0; 316 argv = NULL; 317 ++lineno; 318 if ((cp = strrchr(line, '\n')) != NULL) 319 *cp = '\0'; 320 --- 31 unchanged lines hidden (view full) --- 352 free(argv); 353 } 354 355 (void)fclose(f); 356 return (rval); 357} 358 359static int |
346resolve_ccdname(char *name) | 360checkdev(path) 361 char *path; |
347{ | 362{ |
363 struct stat st; |
|
348 | 364 |
349 if (!strncmp(name, _PATH_DEV, strlen(_PATH_DEV))) 350 name += strlen(_PATH_DEV); 351 if (strncmp(name, "ccd", 3)) 352 return -1; 353 name += 3; 354 if (!isdigit(*name)) 355 return -1; 356 return (strtoul(name, NULL, 10)); | 365 if (stat(path, &st) != 0) 366 return (errno); 367 368 if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) 369 return (EINVAL); 370 371 return (0); |
357} 358 359static int | 372} 373 374static int |
360dumpout(int unit) | 375pathtounit(path, unitp) 376 char *path; 377 int *unitp; |
361{ | 378{ |
362 static int v; 363 struct gctl_req *grq; 364 int ncp; | 379 struct stat st; 380 dev_t dev; 381 int maxpartitions; 382 383 if (stat(path, &st) != 0) 384 return (errno); 385 386 if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) 387 return (EINVAL); 388 389 if ((maxpartitions = getmaxpartitions()) < 0) 390 return (errno); 391 392 *unitp = minor(st.st_rdev) / maxpartitions; 393 394 return (0); 395} 396 397static char * 398resolve_ccdname(name) 399 char *name; 400{ 401 char c, *cp, *path; 402 size_t len, newlen; 403 int rawpart; 404 405 if (name[0] == '/' || name[0] == '.') { 406 /* Assume they gave the correct pathname. */ 407 return (strdup(name)); 408 } 409 410 len = strlen(name); 411 c = name[len - 1]; 412 413 newlen = len + 8; 414 if ((path = malloc(newlen)) == NULL) 415 return (NULL); 416 bzero(path, newlen); 417 418 if (isdigit(c)) { 419 if ((rawpart = getrawpartition()) < 0) { 420 free(path); 421 return (NULL); 422 } 423 (void)sprintf(path, "/dev/%s%c", name, 'a' + rawpart); 424 } else 425 (void)sprintf(path, "/dev/%s", name); 426 427 return (path); 428} 429 430static int 431do_io(path, cmd, cciop) 432 char *path; 433 u_long cmd; 434 struct ccd_ioctl *cciop; 435{ 436 int fd; |
365 char *cp; | 437 char *cp; |
366 char const *errstr; | |
367 | 438 |
368 grq = gctl_get_handle(); 369 ncp = 65536; 370 cp = malloc(ncp); 371 gctl_ro_param(grq, "verb", -1, "list"); 372 gctl_ro_param(grq, "class", -1, "CCD"); 373 gctl_ro_param(grq, "unit", sizeof(unit), &unit); 374 gctl_rw_param(grq, "output", ncp, cp); 375 errstr = gctl_issue(grq); 376 if (errstr != NULL) 377 errx(1, "%s\nor possibly kernel and ccdconfig out of sync", 378 errstr); 379 if (strlen(cp) == 0) 380 errx(1, "ccd%d not configured", unit); 381 if (verbose && !v) { 382 printf("# ccd\t\tileave\tflags\tcomponent devices\n"); 383 v = 1; | 439 if ((fd = open(path, O_RDWR, 0640)) < 0) { 440 warn("open: %s", path); 441 return (1); |
384 } | 442 } |
385 printf("%s", cp); 386 free(cp); | 443 444 if (ioctl(fd, cmd, cciop) < 0) { 445 switch (cmd) { 446 case CCDIOCSET: 447 cp = "CCDIOCSET"; 448 break; 449 450 case CCDIOCCLR: 451 cp = "CCDIOCCLR"; 452 break; 453 454 default: 455 cp = "unknown"; 456 } 457 warn("ioctl (%s): %s", cp, path); 458 return (1); 459 } 460 |
387 return (0); 388} 389 | 461 return (0); 462} 463 |
464#define KVM_ABORT(kd, str) { \ 465 (void)kvm_close((kd)); \ 466 warnx((str)); \ 467 warnx(kvm_geterr((kd))); \ 468 return (1); \ 469} 470 |
|
390static int | 471static int |
391dump_ccd(int argc, char **argv) | 472dump_ccd(argc, argv) 473 int argc; 474 char **argv; |
392{ | 475{ |
393 int i, error; | 476 char errbuf[_POSIX2_LINE_MAX], *ccd, *cp; 477 struct ccd_softc *cs, *kcs; 478 size_t readsize; 479 int i, error, numccd, numconfiged = 0; 480 kvm_t *kd; |
394 | 481 |
482 bzero(errbuf, sizeof(errbuf)); 483 484 if ((kd = kvm_openfiles(kernel, core, NULL, O_RDONLY, 485 errbuf)) == NULL) { 486 warnx("can't open kvm: %s", errbuf); 487 return (1); 488 } 489 490 if (kvm_nlist(kd, nl)) 491 KVM_ABORT(kd, "ccd-related symbols not available"); 492 493 /* Check to see how many ccds are currently configured. */ 494 if (kvm_read(kd, nl[SYM_NUMCCD].n_value, (char *)&numccd, 495 sizeof(numccd)) != sizeof(numccd)) 496 KVM_ABORT(kd, "can't determine number of configured ccds"); 497 498 if (numccd == 0) { 499 printf("ccd driver in kernel, but is uninitialized\n"); 500 goto done; 501 } 502 503 /* Allocate space for the configuration data. */ 504 readsize = numccd * sizeof(struct ccd_softc); 505 if ((cs = malloc(readsize)) == NULL) { 506 warnx("no memory for configuration data"); 507 goto bad; 508 } 509 bzero(cs, readsize); 510 511 /* 512 * Read the ccd configuration data from the kernel and dump 513 * it to stdout. 514 */ 515 if (kvm_read(kd, nl[SYM_CCDSOFTC].n_value, (char *)&kcs, 516 sizeof(kcs)) != sizeof(kcs)) { 517 free(cs); 518 KVM_ABORT(kd, "can't find pointer to configuration data"); 519 } 520 if (kvm_read(kd, (u_long)kcs, (char *)cs, readsize) != readsize) { 521 free(cs); 522 KVM_ABORT(kd, "can't read configuration data"); 523 } 524 |
|
395 if (argc == 0) { | 525 if (argc == 0) { |
396 error = dumpout(-1); | 526 for (i = 0; i < numccd; ++i) 527 if (cs[i].sc_flags & CCDF_INITED) { 528 ++numconfiged; 529 print_ccd_info(&cs[i], kd); 530 } 531 532 if (numconfiged == 0) 533 printf("no concatenated disks configured\n"); |
397 } else { | 534 } else { |
398 error = 0; 399 for (i = 0; error == 0 && i < argc; i++) 400 error = dumpout(resolve_ccdname(argv[i])); | 535 while (argc) { 536 cp = *argv++; --argc; 537 if ((ccd = resolve_ccdname(cp)) == NULL) { 538 warnx("invalid ccd name: %s", cp); 539 continue; 540 } 541 if ((error = pathtounit(ccd, &i)) != 0) { 542 warnx("%s: %s", ccd, strerror(error)); 543 continue; 544 } 545 if (i >= numccd) { 546 warnx("ccd%d not configured", i); 547 continue; 548 } 549 if (cs[i].sc_flags & CCDF_INITED) 550 print_ccd_info(&cs[i], kd); 551 else 552 printf("ccd%d not configured\n", i); 553 } |
401 } | 554 } |
402 return (error); | 555 556 free(cs); 557 558 done: 559 (void)kvm_close(kd); 560 return (0); 561 562 bad: 563 (void)kvm_close(kd); 564 return (1); |
403} 404 | 565} 566 |
567static void 568print_ccd_info(cs, kd) 569 struct ccd_softc *cs; 570 kvm_t *kd; 571{ 572 static int header_printed = 0; 573 struct ccdcinfo *cip; 574 size_t readsize; 575 char path[MAXPATHLEN]; 576 int i; 577 578 if (header_printed == 0 && verbose) { 579 printf("# ccd\t\tileave\tflags\tcompnent devices\n"); 580 header_printed = 1; 581 } 582 583 readsize = cs->sc_nccdisks * sizeof(struct ccdcinfo); 584 if ((cip = malloc(readsize)) == NULL) { 585 warn("ccd%d: can't allocate memory for component info", 586 cs->sc_unit); 587 return; 588 } 589 bzero(cip, readsize); 590 591 /* Dump out softc information. */ 592 printf("ccd%d\t\t%d\t%d\t", cs->sc_unit, cs->sc_ileave, 593 cs->sc_cflags & CCDF_USERMASK); 594 fflush(stdout); 595 596 /* Read in the component info. */ 597 if (kvm_read(kd, (u_long)cs->sc_cinfo, (char *)cip, 598 readsize) != readsize) { 599 printf("\n"); 600 warnx("can't read component info"); 601 warnx(kvm_geterr(kd)); 602 goto done; 603 } 604 605 /* Read component pathname and display component info. */ 606 for (i = 0; i < cs->sc_nccdisks; ++i) { 607 if (kvm_read(kd, (u_long)cip[i].ci_path, (char *)path, 608 cip[i].ci_pathlen) != cip[i].ci_pathlen) { 609 printf("\n"); 610 warnx("can't read component pathname"); 611 warnx(kvm_geterr(kd)); 612 goto done; 613 } 614 printf((i + 1 < cs->sc_nccdisks) ? "%s " : "%s\n", path); 615 fflush(stdout); 616 } 617 618 done: 619 free(cip); 620} 621 |
|
405static int | 622static int |
406flags_to_val(char *flags) | 623getmaxpartitions() |
407{ | 624{ |
625 int maxpart, mib[2]; 626 size_t varlen; 627 628 mib[0] = CTL_KERN; 629 mib[1] = KERN_MAXPARTITIONS; 630 varlen = sizeof(maxpart); 631 if (sysctl(mib, 2, &maxpart, &varlen, NULL, 0) < 0) 632 return (-1); 633 634 return (maxpart); 635} 636 637static int 638getrawpartition() 639{ 640 int rawpart, mib[2]; 641 size_t varlen; 642 643 mib[0] = CTL_KERN; 644 mib[1] = KERN_RAWPARTITION; 645 varlen = sizeof(rawpart); 646 if (sysctl(mib, 2, &rawpart, &varlen, NULL, 0) < 0) 647 return (-1); 648 649 return (rawpart); 650} 651 652static int 653flags_to_val(flags) 654 char *flags; 655{ |
|
408 char *cp, *tok; | 656 char *cp, *tok; |
409 int i, tmp, val; | 657 int i, tmp, val = ~CCDF_USERMASK; 658 size_t flagslen; |
410 | 659 |
411 errno = 0; /* to check for ERANGE */ 412 val = (int)strtol(flags, &cp, 0); 413 if ((errno != ERANGE) && (*cp == '\0')) { 414 if (val & ~(CCDF_UNIFORM|CCDF_MIRROR)) 415 return (-1); 416 return (val); 417 } | 660 /* 661 * The most common case is that of NIL flags, so check for 662 * those first. 663 */ 664 if (strcmp("none", flags) == 0 || strcmp("0x0", flags) == 0 || 665 strcmp("0", flags) == 0) 666 return (0); |
418 | 667 |
668 flagslen = strlen(flags); 669 |
|
419 /* Check for values represented by strings. */ 420 if ((cp = strdup(flags)) == NULL) 421 err(1, "no memory to parse flags"); 422 tmp = 0; 423 for (tok = cp; (tok = strtok(tok, ",")) != NULL; tok = NULL) { 424 for (i = 0; flagvaltab[i].fv_flag != NULL; ++i) 425 if (strcmp(tok, flagvaltab[i].fv_flag) == 0) 426 break; 427 if (flagvaltab[i].fv_flag == NULL) { 428 free(cp); | 670 /* Check for values represented by strings. */ 671 if ((cp = strdup(flags)) == NULL) 672 err(1, "no memory to parse flags"); 673 tmp = 0; 674 for (tok = cp; (tok = strtok(tok, ",")) != NULL; tok = NULL) { 675 for (i = 0; flagvaltab[i].fv_flag != NULL; ++i) 676 if (strcmp(tok, flagvaltab[i].fv_flag) == 0) 677 break; 678 if (flagvaltab[i].fv_flag == NULL) { 679 free(cp); |
429 return (-1); | 680 goto bad_string; |
430 } 431 tmp |= flagvaltab[i].fv_val; 432 } 433 434 /* If we get here, the string was ok. */ 435 free(cp); | 681 } 682 tmp |= flagvaltab[i].fv_val; 683 } 684 685 /* If we get here, the string was ok. */ 686 free(cp); |
436 return (tmp); | 687 val = tmp; 688 goto out; 689 690 bad_string: 691 692 /* Check for values represented in hex. */ 693 if (flagslen > 2 && flags[0] == '0' && flags[1] == 'x') { 694 errno = 0; /* to check for ERANGE */ 695 val = (int)strtol(&flags[2], &cp, 16); 696 if ((errno == ERANGE) || (*cp != '\0')) 697 return (-1); 698 goto out; 699 } 700 701 /* Check for values represented in decimal. */ 702 errno = 0; /* to check for ERANGE */ 703 val = (int)strtol(flags, &cp, 10); 704 if ((errno == ERANGE) || (*cp != '\0')) 705 return (-1); 706 707 out: 708 return (((val & ~CCDF_USERMASK) == 0) ? val : -1); |
437} 438 439static void | 709} 710 711static void |
440usage(void) | 712usage() |
441{ | 713{ |
442 fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 443 "usage: ccdconfig [-cv] ccd ileave [flags] dev ...", 444 " ccdconfig -C [-v] [-f config_file]", 445 " ccdconfig -u [-v] ccd ...", 446 " ccdconfig -U [-v] [-f config_file]", 447 " ccdconfig -g [ccd ...]"); | 714 715 fprintf(stderr, "usage: %s [-cv] ccd ileave [flags] %s\n", __progname, 716 "dev [...]"); 717 fprintf(stderr, " %s -C [-v] [-f config_file]\n", __progname); 718 fprintf(stderr, " %s -u [-v] ccd [...]\n", __progname); 719 fprintf(stderr, " %s -U [-v] [-f config_file]\n", __progname); 720 fprintf(stderr, " %s -g [-M core] [-N system] %s\n", __progname, 721 "[ccd [...]]"); |
448 exit(1); 449} | 722 exit(1); 723} |