GEOMification of CCD.
You need your kernel and ccdconfig(8) to be in sync, particularly if your source tree is on a ccd device.
This commit is contained in:
parent
00063a54b2
commit
3bba46e45a
8
UPDATING
8
UPDATING
@ -17,6 +17,14 @@ NOTE TO PEOPLE WHO THINK THAT 5.0-CURRENT IS SLOW:
|
||||
developers choose to disable these features on build machines
|
||||
to maximize performance.
|
||||
|
||||
20030509:
|
||||
CCD has been changed to be a fully GEOMified class. Kernel
|
||||
and ccdconfig(8) needs to be in sync, this is particularly
|
||||
important to remember beforehand if your source tree is on
|
||||
a ccd device. Consider making a copy of the old ccdconfig
|
||||
into /boot/kernel.good or wherever you keep your backup
|
||||
kernel.
|
||||
|
||||
20030505:
|
||||
Kerberos 5 (Heimdal) is now built by default. Setting
|
||||
MAKE_KERBEROS5 no longer has any effect. If you do NOT
|
||||
|
@ -1,6 +1,5 @@
|
||||
/* $NetBSD: ccdconfig.c,v 1.2.2.1 1995/11/11 02:43:35 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Poul-Henning Kamp
|
||||
* Copyright (c) 1995 Jason R. Thorpe.
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -37,13 +36,10 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/linker.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/module.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <paths.h>
|
||||
#include <stdio.h>
|
||||
@ -52,8 +48,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <unistd.h>
|
||||
#include <libgeom.h>
|
||||
|
||||
#include <sys/devicestat.h>
|
||||
#include <sys/ccdvar.h>
|
||||
#define CCDF_UNIFORM 0x02 /* use LCCD of sizes for uniform interleave */
|
||||
#define CCDF_MIRROR 0x04 /* use mirroring */
|
||||
|
||||
#include "pathnames.h"
|
||||
|
||||
@ -63,10 +59,13 @@ static const char *ccdconf = _PATH_CCDCONF;
|
||||
|
||||
struct flagval {
|
||||
const char *fv_flag;
|
||||
int fv_val;
|
||||
int fv_val;
|
||||
} flagvaltab[] = {
|
||||
{ "CCDF_UNIFORM", CCDF_UNIFORM },
|
||||
{ "uniform", CCDF_UNIFORM },
|
||||
{ "CCDF_MIRROR", CCDF_MIRROR },
|
||||
{ "mirror", CCDF_MIRROR },
|
||||
{ "none", 0 },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
@ -76,8 +75,6 @@ struct flagval {
|
||||
#define CCD_UNCONFIGALL 3 /* unconfigure all devices */
|
||||
#define CCD_DUMP 4 /* dump a ccd's configuration */
|
||||
|
||||
static int checkdev(char *);
|
||||
static int do_io(int, u_long, struct ccd_ioctl *);
|
||||
static int do_single(int, char **, int);
|
||||
static int do_all(int);
|
||||
static int dump_ccd(int, char **);
|
||||
@ -134,10 +131,10 @@ main(int argc, char *argv[])
|
||||
if (options > 1)
|
||||
usage();
|
||||
|
||||
if (modfind("ccd") < 0) {
|
||||
if (modfind("g_ccd") < 0) {
|
||||
/* Not present in kernel, try loading it */
|
||||
if (kldload("ccd") < 0 || modfind("ccd") < 0)
|
||||
warn("ccd module not available!");
|
||||
if (kldload("g_ccd") < 0 || modfind("g_ccd") < 0)
|
||||
warn("g_ccd module not available!");
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
@ -162,17 +159,18 @@ main(int argc, char *argv[])
|
||||
static int
|
||||
do_single(int argc, char **argv, int action)
|
||||
{
|
||||
struct ccd_ioctl ccio;
|
||||
char *cp, *cp2, **disks;
|
||||
int ccd, noflags = 0, i, ileave, flags = 0, j;
|
||||
u_int u;
|
||||
|
||||
bzero(&ccio, sizeof(ccio));
|
||||
char *cp, *cp2;
|
||||
int ccd, noflags = 0, i, ileave, flags = 0;
|
||||
struct gctl_req *grq;
|
||||
char const *errstr;
|
||||
char buf1[BUFSIZ];
|
||||
int ex;
|
||||
|
||||
/*
|
||||
* If unconfiguring, all arguments are treated as ccds.
|
||||
*/
|
||||
if (action == CCD_UNCONFIG || action == CCD_UNCONFIGALL) {
|
||||
ex = 0;
|
||||
for (i = 0; argc != 0; ) {
|
||||
cp = *argv++; --argc;
|
||||
if ((ccd = resolve_ccdname(cp)) < 0) {
|
||||
@ -180,14 +178,24 @@ do_single(int argc, char **argv, int action)
|
||||
i = 1;
|
||||
continue;
|
||||
}
|
||||
ccio.ccio_size = ccd;
|
||||
if (do_io(ccd, CCDIOCCLR, &ccio))
|
||||
i = 1;
|
||||
else
|
||||
grq = gctl_get_handle();
|
||||
gctl_ro_param(grq, "verb", -1, "destroy geom");
|
||||
gctl_ro_param(grq, "class", -1, "CCD");
|
||||
sprintf(buf1, "ccd%d", ccd);
|
||||
gctl_ro_param(grq, "geom", -1, buf1);
|
||||
errstr = gctl_issue(grq);
|
||||
if (errstr == NULL) {
|
||||
if (verbose)
|
||||
printf("%s unconfigured\n", cp);
|
||||
gctl_free(grq);
|
||||
continue;
|
||||
}
|
||||
warnx(
|
||||
"%s\nor possibly kernel and ccdconfig out of sync",
|
||||
errstr);
|
||||
ex = 1;
|
||||
}
|
||||
return (i);
|
||||
return (ex);
|
||||
}
|
||||
|
||||
/* Make sure there are enough arguments. */
|
||||
@ -228,56 +236,36 @@ do_single(int argc, char **argv, int action)
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Next is the list of disks to make the ccd from. */
|
||||
disks = malloc(argc * sizeof(char *));
|
||||
if (disks == NULL) {
|
||||
warnx("no memory to configure ccd");
|
||||
return (1);
|
||||
grq = gctl_get_handle();
|
||||
gctl_ro_param(grq, "verb", -1, "create geom");
|
||||
gctl_ro_param(grq, "class", -1, "CCD");
|
||||
gctl_ro_param(grq, "unit", sizeof(ccd), &ccd);
|
||||
gctl_ro_param(grq, "ileave", sizeof(ileave), &ileave);
|
||||
if (flags & CCDF_UNIFORM)
|
||||
gctl_ro_param(grq, "uniform", -1, "");
|
||||
if (flags & CCDF_MIRROR)
|
||||
gctl_ro_param(grq, "mirror", -1, "");
|
||||
gctl_ro_param(grq, "nprovider", sizeof(argc), &argc);
|
||||
for (i = 0; i < argc; i++) {
|
||||
sprintf(buf1, "provider%d", i);
|
||||
cp = argv[i];
|
||||
if (!strncmp(cp, _PATH_DEV, strlen(_PATH_DEV)))
|
||||
cp += strlen(_PATH_DEV);
|
||||
gctl_ro_param(grq, buf1, -1, cp);
|
||||
}
|
||||
for (i = 0; argc != 0; ) {
|
||||
cp = *argv++; --argc;
|
||||
if ((j = checkdev(cp)) == 0)
|
||||
disks[i++] = cp;
|
||||
else {
|
||||
warnx("%s: %s", cp, strerror(j));
|
||||
return (1);
|
||||
gctl_rw_param(grq, "output", sizeof(buf1), buf1);
|
||||
errstr = gctl_issue(grq);
|
||||
if (errstr == NULL) {
|
||||
if (verbose) {
|
||||
printf("%s", buf1);
|
||||
}
|
||||
gctl_free(grq);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Fill in the ccio. */
|
||||
ccio.ccio_disks = disks;
|
||||
ccio.ccio_ndisks = i;
|
||||
ccio.ccio_ileave = ileave;
|
||||
ccio.ccio_flags = flags;
|
||||
ccio.ccio_size = ccd;
|
||||
|
||||
if (do_io(ccd, CCDIOCSET, &ccio)) {
|
||||
free(disks);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
printf("ccd%d: %d components ", ccio.ccio_unit,
|
||||
ccio.ccio_ndisks);
|
||||
for (u = 0; u < ccio.ccio_ndisks; ++u) {
|
||||
if ((cp2 = strrchr(disks[u], '/')) != NULL)
|
||||
++cp2;
|
||||
else
|
||||
cp2 = disks[u];
|
||||
printf("%c%s%c",
|
||||
u == 0 ? '(' : ' ', cp2,
|
||||
u == ccio.ccio_ndisks - 1 ? ')' : ',');
|
||||
}
|
||||
printf(", %lu blocks ", (u_long)ccio.ccio_size);
|
||||
if (ccio.ccio_ileave != 0)
|
||||
printf("interleaved at %d blocks\n", ccio.ccio_ileave);
|
||||
else
|
||||
printf("concatenated\n");
|
||||
}
|
||||
|
||||
free(disks);
|
||||
return (0);
|
||||
warnx(
|
||||
"%s\nor possibly kernel and ccdconfig out of sync",
|
||||
errstr);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -344,20 +332,6 @@ do_all(int action)
|
||||
return (rval);
|
||||
}
|
||||
|
||||
static int
|
||||
checkdev(char *path)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (stat(path, &st) != 0)
|
||||
return (errno);
|
||||
|
||||
if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
|
||||
return (EINVAL);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
resolve_ccdname(char *name)
|
||||
{
|
||||
@ -372,48 +346,6 @@ resolve_ccdname(char *name)
|
||||
return (strtoul(name, NULL, 10));
|
||||
}
|
||||
|
||||
static int
|
||||
do_io(int unit, u_long cmd, struct ccd_ioctl *cciop)
|
||||
{
|
||||
int fd;
|
||||
char *cp;
|
||||
char *path;
|
||||
|
||||
asprintf(&path, "%s%s", _PATH_DEV, _PATH_CCDCTL);
|
||||
|
||||
if ((fd = open(path, O_RDWR, 0640)) < 0) {
|
||||
asprintf(&path, "%sccd%dc", _PATH_DEV, unit);
|
||||
if ((fd = open(path, O_RDWR, 0640)) < 0) {
|
||||
warn("open: %s", path);
|
||||
return (1);
|
||||
}
|
||||
fprintf(stderr,
|
||||
"***WARNING***: Kernel older than ccdconfig(8), please upgrade it.\n");
|
||||
fprintf(stderr,
|
||||
"***WARNING***: Continuing in 30 seconds\n");
|
||||
sleep(30);
|
||||
}
|
||||
|
||||
if (ioctl(fd, cmd, cciop) < 0) {
|
||||
switch (cmd) {
|
||||
case CCDIOCSET:
|
||||
cp = "CCDIOCSET";
|
||||
break;
|
||||
|
||||
case CCDIOCCLR:
|
||||
cp = "CCDIOCCLR";
|
||||
break;
|
||||
|
||||
default:
|
||||
cp = "unknown";
|
||||
}
|
||||
warn("ioctl (%s): %s", cp, path);
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
dumpout(int unit)
|
||||
{
|
||||
@ -422,7 +354,6 @@ dumpout(int unit)
|
||||
int ncp;
|
||||
char *cp;
|
||||
char const *errstr;
|
||||
|
||||
|
||||
grq = gctl_get_handle();
|
||||
ncp = 65536;
|
||||
@ -465,19 +396,18 @@ static int
|
||||
flags_to_val(char *flags)
|
||||
{
|
||||
char *cp, *tok;
|
||||
int i, tmp, val = ~CCDF_USERMASK;
|
||||
int i, tmp, val;
|
||||
size_t flagslen;
|
||||
|
||||
/*
|
||||
* The most common case is that of NIL flags, so check for
|
||||
* those first.
|
||||
*/
|
||||
if (strcmp("none", flags) == 0 || strcmp("0x0", flags) == 0 ||
|
||||
strcmp("0", flags) == 0)
|
||||
return (0);
|
||||
errno = 0; /* to check for ERANGE */
|
||||
val = (int)strtol(flags, &cp, 0);
|
||||
if ((errno != ERANGE) && (*cp == '\0')) {
|
||||
if (val & ~(CCDF_UNIFORM|CCDF_MIRROR))
|
||||
return (-1);
|
||||
return (val);
|
||||
}
|
||||
|
||||
flagslen = strlen(flags);
|
||||
|
||||
/* Check for values represented by strings. */
|
||||
if ((cp = strdup(flags)) == NULL)
|
||||
err(1, "no memory to parse flags");
|
||||
@ -488,35 +418,14 @@ flags_to_val(char *flags)
|
||||
break;
|
||||
if (flagvaltab[i].fv_flag == NULL) {
|
||||
free(cp);
|
||||
goto bad_string;
|
||||
return (-1);
|
||||
}
|
||||
tmp |= flagvaltab[i].fv_val;
|
||||
}
|
||||
|
||||
/* If we get here, the string was ok. */
|
||||
free(cp);
|
||||
val = tmp;
|
||||
goto out;
|
||||
|
||||
bad_string:
|
||||
|
||||
/* Check for values represented in hex. */
|
||||
if (flagslen > 2 && flags[0] == '0' && flags[1] == 'x') {
|
||||
errno = 0; /* to check for ERANGE */
|
||||
val = (int)strtol(&flags[2], &cp, 16);
|
||||
if ((errno == ERANGE) || (*cp != '\0'))
|
||||
return (-1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check for values represented in decimal. */
|
||||
errno = 0; /* to check for ERANGE */
|
||||
val = (int)strtol(flags, &cp, 10);
|
||||
if ((errno == ERANGE) || (*cp != '\0'))
|
||||
return (-1);
|
||||
|
||||
out:
|
||||
return (((val & ~CCDF_USERMASK) == 0) ? val : -1);
|
||||
return (tmp);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -530,8 +439,3 @@ usage(void)
|
||||
" ccdconfig -g [ccd [...]]");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Local Variables: */
|
||||
/* c-argdecl-indent: 8 */
|
||||
/* c-indent-level: 8 */
|
||||
/* End: */
|
||||
|
@ -336,7 +336,6 @@ dev/buslogic/bt_mca.c optional bt mca
|
||||
dev/buslogic/bt_pci.c optional bt pci
|
||||
dev/cardbus/cardbus.c optional cardbus
|
||||
dev/cardbus/cardbus_cis.c optional cardbus
|
||||
dev/ccd/ccd.c optional ccd
|
||||
dev/ciss/ciss.c optional ciss
|
||||
dev/cm/smc90cx6.c optional cm
|
||||
dev/cnw/if_cnw.c optional cnw card
|
||||
@ -904,6 +903,8 @@ geom/geom_aes.c optional geom_aes
|
||||
geom/geom_apple.c optional geom_apple
|
||||
geom/geom_bsd.c optional geom_bsd
|
||||
geom/geom_bsd_enc.c optional geom_bsd
|
||||
geom/geom_ccd.c optional ccd
|
||||
geom/geom_ccd.c optional geom_ccd
|
||||
geom/geom_ctl.c standard
|
||||
geom/geom_dev.c standard
|
||||
geom/geom_disk.c standard
|
||||
|
1322
sys/dev/ccd/ccd.c
1322
sys/dev/ccd/ccd.c
File diff suppressed because it is too large
Load Diff
120
sys/sys/ccdvar.h
120
sys/sys/ccdvar.h
@ -1,120 +0,0 @@
|
||||
/* $FreeBSD$ */
|
||||
|
||||
/* $NetBSD: ccdvar.h,v 1.7.2.1 1995/10/12 21:30:18 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Jason R. Thorpe.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed for the NetBSD Project
|
||||
* by Jason R. Thorpe.
|
||||
* 4. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988 University of Utah.
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* the Systems Programming Group of the University of Utah Computer
|
||||
* Science Department.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* from: Utah $Hdr: cdvar.h 1.1 90/07/09$
|
||||
*
|
||||
* @(#)cdvar.h 8.1 (Berkeley) 6/10/93
|
||||
*/
|
||||
|
||||
/*
|
||||
* Dynamic configuration and disklabel support by:
|
||||
* Jason R. Thorpe <thorpej@nas.nasa.gov>
|
||||
* Numerical Aerodynamic Simulation Facility
|
||||
* Mail Stop 258-6
|
||||
* NASA Ames Research Center
|
||||
* Moffett Field, CA 94035
|
||||
*/
|
||||
|
||||
/*
|
||||
* This structure is used to configure a ccd via ioctl(2).
|
||||
*/
|
||||
struct ccd_ioctl {
|
||||
char **ccio_disks; /* pointer to component paths */
|
||||
u_int ccio_ndisks; /* number of disks to concatenate */
|
||||
int ccio_ileave; /* interleave (DEV_BSIZE blocks) */
|
||||
int ccio_flags; /* misc. information */
|
||||
int ccio_unit; /* unit number: use varies */
|
||||
size_t ccio_size; /* (returned) size of ccd */
|
||||
};
|
||||
|
||||
/* sc_flags */
|
||||
#define CCDF_UNIFORM 0x02 /* use LCCD of sizes for uniform interleave */
|
||||
#define CCDF_MIRROR 0x04 /* use mirroring */
|
||||
#define CCDF_INITED 0x10 /* unit has been initialized */
|
||||
#define CCDF_WLABEL 0x20 /* label area is writable */
|
||||
#define CCDF_LABELLING 0x40 /* unit is currently being labelled */
|
||||
#define CCDF_WANTED 0x60 /* someone is waiting to obtain a lock */
|
||||
#define CCDF_LOCKED 0x80 /* unit is locked */
|
||||
|
||||
/* Mask of user-settable ccd flags. */
|
||||
#define CCDF_USERMASK (CCDF_UNIFORM|CCDF_MIRROR)
|
||||
|
||||
/*
|
||||
* Before you can use a unit, it must be configured with CCDIOCSET.
|
||||
* The configuration persists across opens and closes of the device;
|
||||
* a CCDIOCCLR must be used to reset a configuration. An attempt to
|
||||
* CCDIOCSET an already active unit will return EBUSY. Attempts to
|
||||
* CCDIOCCLR an inactive unit will return ENXIO.
|
||||
*/
|
||||
#define CCDIOCSET _IOWR('F', 16, struct ccd_ioctl) /* enable ccd */
|
||||
#define CCDIOCCLR _IOW('F', 17, struct ccd_ioctl) /* disable ccd */
|
Loading…
x
Reference in New Issue
Block a user