Find places to store the previously implicityly passed unit number in
the three configuration ioctls which need a unit number. Add a "ccd.ctl" device for config operations. Implement ioctls on ccd.ctl which rely on the explicityly passed unit numbers. Update ccdconfig to use the new ccd.ctl interface. Add code to the kernel to detect old ccdconfig binaries, and whine about it. Add code to ccdconfig to detect old kernels, and whine about it. These two compatibility measures will be retained only for a limited period since they are in the way of GEOM'ification of ccd.
This commit is contained in:
parent
58da5356d7
commit
867cdc9da1
@ -182,6 +182,7 @@ do_single(int argc, char **argv, int action)
|
||||
i = 1;
|
||||
continue;
|
||||
}
|
||||
ccio.ccio_size = ccd;
|
||||
if (do_io(ccd, CCDIOCCLR, &ccio))
|
||||
i = 1;
|
||||
else
|
||||
@ -251,6 +252,7 @@ do_single(int argc, char **argv, int action)
|
||||
ccio.ccio_ndisks = i;
|
||||
ccio.ccio_ileave = ileave;
|
||||
ccio.ccio_flags = flags;
|
||||
ccio.ccio_size = ccd;
|
||||
|
||||
if (do_io(ccd, CCDIOCSET, &ccio)) {
|
||||
free(disks);
|
||||
@ -379,11 +381,19 @@ do_io(int unit, u_long cmd, struct ccd_ioctl *cciop)
|
||||
char *cp;
|
||||
char *path;
|
||||
|
||||
asprintf(&path, "%sccd%dc", _PATH_DEV, unit);
|
||||
asprintf(&path, "%s%s", _PATH_DEV, _PATH_CCDCTL);
|
||||
|
||||
if ((fd = open(path, O_RDWR, 0640)) < 0) {
|
||||
warn("open: %s", path);
|
||||
return (1);
|
||||
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) {
|
||||
@ -510,19 +520,9 @@ print_ccd_info(struct ccd_s *cs)
|
||||
warnx("can't read component info: invalid ccd name: %s", cp);
|
||||
return;
|
||||
}
|
||||
cpps.size = 0;
|
||||
if (do_io(ccd, CCDCPPINFO, (struct ccd_ioctl *) &cpps)) {
|
||||
printf("\n");
|
||||
warnx("can't read component info");
|
||||
return;
|
||||
}
|
||||
cpps.size = 1024;
|
||||
cpps.buffer = alloca(cpps.size);
|
||||
if (cpps.buffer == NULL) {
|
||||
printf("\n");
|
||||
warn("ccd%d: can't allocate memory for component info",
|
||||
cs->sc_unit);
|
||||
return;
|
||||
}
|
||||
memcpy(cpps.buffer, &ccd, sizeof ccd);
|
||||
if (do_io(ccd, CCDCPPINFO, (struct ccd_ioctl *) &cpps)) {
|
||||
printf("\n");
|
||||
warnx("can't read component info");
|
||||
@ -530,11 +530,11 @@ print_ccd_info(struct ccd_s *cs)
|
||||
}
|
||||
|
||||
/* Display component info. */
|
||||
for (cp = cpps.buffer; cp - cpps.buffer < cpps.size; cp += strlen(cp) + 1) {
|
||||
for (cp = cpps.buffer; *cp && cp - cpps.buffer < cpps.size; cp += strlen(cp) + 1) {
|
||||
printf((cp + strlen(cp) + 1) < (cpps.buffer + cpps.size) ?
|
||||
"%s " : "%s\n", cp);
|
||||
fflush(stdout);
|
||||
"%s " : "%s", cp);
|
||||
}
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,9 @@
|
||||
* 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#define _PATH_CCDCONF "/etc/ccd.conf"
|
||||
#define _PATH_CCDCTL "ccd.ctl"
|
||||
|
@ -124,8 +124,13 @@ static int ccddebug = CCDB_FOLLOW | CCDB_INIT | CCDB_IO | CCDB_LABEL |
|
||||
SYSCTL_INT(_debug, OID_AUTO, ccddebug, CTLFLAG_RW, &ccddebug, 0, "");
|
||||
#endif
|
||||
|
||||
#define ccdunit(x) dkunit(x)
|
||||
#define ccdpart(x) dkpart(x)
|
||||
static u_int
|
||||
ccdunit(dev_t dev)
|
||||
{
|
||||
return (((minor(dev) >> 16) & 0x1e0) | ((minor(dev) >> 3) & 0x1f));
|
||||
}
|
||||
|
||||
#define ccdpart(x) (minor(x) & 7)
|
||||
|
||||
/*
|
||||
This is how mirroring works (only writes are special):
|
||||
@ -161,10 +166,15 @@ struct ccdbuf {
|
||||
#define IS_ALLOCATED(unit) (ccdfind(unit) != NULL)
|
||||
#define IS_INITED(cs) (((cs)->sc_flags & CCDF_INITED) != 0)
|
||||
|
||||
|
||||
static dev_t ccdctldev;
|
||||
|
||||
|
||||
static d_open_t ccdopen;
|
||||
static d_close_t ccdclose;
|
||||
static d_strategy_t ccdstrategy;
|
||||
static d_ioctl_t ccdioctl;
|
||||
static d_ioctl_t ccdioctltoo;
|
||||
static d_psize_t ccdsize;
|
||||
|
||||
#define NCCDFREEHIWAT 16
|
||||
@ -354,6 +364,9 @@ static void
|
||||
ccdattach()
|
||||
{
|
||||
|
||||
ccdctldev = make_dev(&ccd_cdevsw, 0xffff00ff,
|
||||
UID_ROOT, GID_OPERATOR, 0640, "ccd.ctl");
|
||||
ccdctldev->si_drv1 = ccdctldev;
|
||||
EVENTHANDLER_REGISTER(dev_clone, ccd_clone, 0, 1000);
|
||||
}
|
||||
|
||||
@ -517,7 +530,7 @@ ccdinit(struct ccd_s *cs, char **cpaths, struct thread *td)
|
||||
*
|
||||
* Lost space must be taken into account when calculating the
|
||||
* overall size. Half the space is lost when CCDF_MIRROR is
|
||||
* specified. One disk is lost when CCDF_PARITY is specified.
|
||||
* specified.
|
||||
*/
|
||||
if (cs->sc_flags & CCDF_UNIFORM) {
|
||||
for (ci = cs->sc_cinfo;
|
||||
@ -617,7 +630,7 @@ ccdinterleave(struct ccd_s *cs, int unit)
|
||||
* Trivial case: no interleave (actually interleave of disk size).
|
||||
* Each table entry represents a single component in its entirety.
|
||||
*
|
||||
* An interleave of 0 may not be used with a mirror or parity setup.
|
||||
* An interleave of 0 may not be used with a mirror setup.
|
||||
*/
|
||||
if (cs->sc_ileave == 0) {
|
||||
bn = 0;
|
||||
@ -718,6 +731,8 @@ ccdopen(dev_t dev, int flags, int fmt, struct thread *td)
|
||||
struct disklabel *lp;
|
||||
int error = 0, part, pmask;
|
||||
|
||||
if (dev->si_drv1 == dev)
|
||||
return (0);
|
||||
#ifdef DEBUG
|
||||
if (ccddebug & CCDB_FOLLOW)
|
||||
printf("ccdopen(%p, %x)\n", dev, flags);
|
||||
@ -762,6 +777,8 @@ ccdclose(dev_t dev, int flags, int fmt, struct thread *td)
|
||||
struct ccd_s *cs;
|
||||
int error = 0, part;
|
||||
|
||||
if (dev->si_drv1 == dev)
|
||||
return (0);
|
||||
#ifdef DEBUG
|
||||
if (ccddebug & CCDB_FOLLOW)
|
||||
printf("ccdclose(%p, %x)\n", dev, flags);
|
||||
@ -795,6 +812,10 @@ ccdstrategy(struct bio *bp)
|
||||
int wlabel;
|
||||
struct disklabel *lp;
|
||||
|
||||
if (bp->bio_dev->si_drv1 == bp->bio_dev) {
|
||||
biofinish(bp, NULL, ENXIO);
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (ccddebug & CCDB_FOLLOW)
|
||||
printf("ccdstrategy(%p): unit %d\n", bp, unit);
|
||||
@ -1243,7 +1264,96 @@ ccdiodone(struct bio *ibp)
|
||||
static int
|
||||
ccdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
{
|
||||
int unit = ccdunit(dev);
|
||||
struct ccd_ioctl *ccio;
|
||||
u_int unit;
|
||||
dev_t dev2;
|
||||
int error;
|
||||
|
||||
if (dev->si_drv1 != dev) {
|
||||
switch (cmd) {
|
||||
case CCDIOCSET:
|
||||
case CCDIOCCLR:
|
||||
case CCDCONFINFO:
|
||||
case CCDCPPINFO:
|
||||
printf("*** WARNING: upgrade your ccdconfig(8) binary\n");
|
||||
printf("*** WARNING: continuing in 30 seconds\n");
|
||||
tsleep(dev, PRIBIO, "ccdbug", hz * 30);
|
||||
break;
|
||||
}
|
||||
return ccdioctltoo(dev, cmd, data, flag, td);
|
||||
}
|
||||
switch (cmd) {
|
||||
case CCDIOCSET:
|
||||
case CCDIOCCLR:
|
||||
ccio = (struct ccd_ioctl *)data;
|
||||
unit = ccio->ccio_size;
|
||||
dev2 = makedev(CDEV_MAJOR, unit * 8 + 2);
|
||||
if (!(dev2->si_flags & SI_NAMED)) {
|
||||
dev2 = make_dev(&ccd_cdevsw, unit * 8 + 2,
|
||||
UID_ROOT, GID_OPERATOR, 0640, "ccd%dc", unit);
|
||||
ccdnew(unit);
|
||||
}
|
||||
return (ccdioctltoo(dev2, cmd, data, flag, td));
|
||||
case CCDCONFINFO:
|
||||
{
|
||||
int ninit = 0;
|
||||
struct ccdconf *conf = (struct ccdconf *)data;
|
||||
struct ccd_s *tmpcs;
|
||||
struct ccd_s *ubuf = conf->buffer;
|
||||
|
||||
/* XXX: LOCK(unique unit numbers) */
|
||||
LIST_FOREACH(tmpcs, &ccd_softc_list, list)
|
||||
if (IS_INITED(tmpcs))
|
||||
ninit++;
|
||||
|
||||
if (conf->size == 0) {
|
||||
conf->size = sizeof(struct ccd_s) * ninit;
|
||||
return (0);
|
||||
} else if ((conf->size / sizeof(struct ccd_s) != ninit) ||
|
||||
(conf->size % sizeof(struct ccd_s) != 0)) {
|
||||
/* XXX: UNLOCK(unique unit numbers) */
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
ubuf += ninit;
|
||||
LIST_FOREACH(tmpcs, &ccd_softc_list, list) {
|
||||
if (!IS_INITED(tmpcs))
|
||||
continue;
|
||||
error = copyout(tmpcs, --ubuf,
|
||||
sizeof(struct ccd_s));
|
||||
if (error != 0)
|
||||
/* XXX: UNLOCK(unique unit numbers) */
|
||||
return (error);
|
||||
}
|
||||
/* XXX: UNLOCK(unique unit numbers) */
|
||||
return (0);
|
||||
}
|
||||
|
||||
case CCDCPPINFO:
|
||||
{
|
||||
struct ccdcpps *cpps = (struct ccdcpps *)data;
|
||||
char *ubuf = cpps->buffer;
|
||||
|
||||
|
||||
error = copyin(ubuf, &unit, sizeof (unit));
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
if (!IS_ALLOCATED(unit))
|
||||
return (ENXIO);
|
||||
dev2 = makedev(CDEV_MAJOR, unit * 8 + 2);
|
||||
return (ccdioctltoo(dev2, cmd, data, flag, td));
|
||||
}
|
||||
|
||||
default:
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ccdioctltoo(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
{
|
||||
int unit;
|
||||
int i, j, lookedup = 0, error = 0;
|
||||
int part, pmask, s;
|
||||
struct ccd_s *cs;
|
||||
@ -1251,6 +1361,7 @@ ccdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
char **cpp;
|
||||
struct vnode **vpp;
|
||||
|
||||
unit = ccdunit(dev);
|
||||
if (!IS_ALLOCATED(unit))
|
||||
return (ENXIO);
|
||||
cs = ccdfind(unit);
|
||||
@ -1469,8 +1580,8 @@ ccdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
if (cpps->size == 0) {
|
||||
cpps->size = len;
|
||||
break;
|
||||
} else if (cpps->size != len) {
|
||||
return (EINVAL);
|
||||
} else if (cpps->size < len) {
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
for (i = 0; i < cs->sc_nccdisks; ++i) {
|
||||
@ -1481,6 +1592,7 @@ ccdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
return (error);
|
||||
ubuf += len;
|
||||
}
|
||||
return(copyout("", ubuf, 1));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1545,6 +1657,9 @@ ccdsize(dev_t dev)
|
||||
struct ccd_s *cs;
|
||||
int part, size;
|
||||
|
||||
if (dev->si_drv1 == dev)
|
||||
return (-1);
|
||||
|
||||
if (ccdopen(dev, 0, S_IFCHR, curthread))
|
||||
return (-1);
|
||||
|
||||
|
@ -124,8 +124,13 @@ static int ccddebug = CCDB_FOLLOW | CCDB_INIT | CCDB_IO | CCDB_LABEL |
|
||||
SYSCTL_INT(_debug, OID_AUTO, ccddebug, CTLFLAG_RW, &ccddebug, 0, "");
|
||||
#endif
|
||||
|
||||
#define ccdunit(x) dkunit(x)
|
||||
#define ccdpart(x) dkpart(x)
|
||||
static u_int
|
||||
ccdunit(dev_t dev)
|
||||
{
|
||||
return (((minor(dev) >> 16) & 0x1e0) | ((minor(dev) >> 3) & 0x1f));
|
||||
}
|
||||
|
||||
#define ccdpart(x) (minor(x) & 7)
|
||||
|
||||
/*
|
||||
This is how mirroring works (only writes are special):
|
||||
@ -161,10 +166,15 @@ struct ccdbuf {
|
||||
#define IS_ALLOCATED(unit) (ccdfind(unit) != NULL)
|
||||
#define IS_INITED(cs) (((cs)->sc_flags & CCDF_INITED) != 0)
|
||||
|
||||
|
||||
static dev_t ccdctldev;
|
||||
|
||||
|
||||
static d_open_t ccdopen;
|
||||
static d_close_t ccdclose;
|
||||
static d_strategy_t ccdstrategy;
|
||||
static d_ioctl_t ccdioctl;
|
||||
static d_ioctl_t ccdioctltoo;
|
||||
static d_psize_t ccdsize;
|
||||
|
||||
#define NCCDFREEHIWAT 16
|
||||
@ -354,6 +364,9 @@ static void
|
||||
ccdattach()
|
||||
{
|
||||
|
||||
ccdctldev = make_dev(&ccd_cdevsw, 0xffff00ff,
|
||||
UID_ROOT, GID_OPERATOR, 0640, "ccd.ctl");
|
||||
ccdctldev->si_drv1 = ccdctldev;
|
||||
EVENTHANDLER_REGISTER(dev_clone, ccd_clone, 0, 1000);
|
||||
}
|
||||
|
||||
@ -517,7 +530,7 @@ ccdinit(struct ccd_s *cs, char **cpaths, struct thread *td)
|
||||
*
|
||||
* Lost space must be taken into account when calculating the
|
||||
* overall size. Half the space is lost when CCDF_MIRROR is
|
||||
* specified. One disk is lost when CCDF_PARITY is specified.
|
||||
* specified.
|
||||
*/
|
||||
if (cs->sc_flags & CCDF_UNIFORM) {
|
||||
for (ci = cs->sc_cinfo;
|
||||
@ -617,7 +630,7 @@ ccdinterleave(struct ccd_s *cs, int unit)
|
||||
* Trivial case: no interleave (actually interleave of disk size).
|
||||
* Each table entry represents a single component in its entirety.
|
||||
*
|
||||
* An interleave of 0 may not be used with a mirror or parity setup.
|
||||
* An interleave of 0 may not be used with a mirror setup.
|
||||
*/
|
||||
if (cs->sc_ileave == 0) {
|
||||
bn = 0;
|
||||
@ -718,6 +731,8 @@ ccdopen(dev_t dev, int flags, int fmt, struct thread *td)
|
||||
struct disklabel *lp;
|
||||
int error = 0, part, pmask;
|
||||
|
||||
if (dev->si_drv1 == dev)
|
||||
return (0);
|
||||
#ifdef DEBUG
|
||||
if (ccddebug & CCDB_FOLLOW)
|
||||
printf("ccdopen(%p, %x)\n", dev, flags);
|
||||
@ -762,6 +777,8 @@ ccdclose(dev_t dev, int flags, int fmt, struct thread *td)
|
||||
struct ccd_s *cs;
|
||||
int error = 0, part;
|
||||
|
||||
if (dev->si_drv1 == dev)
|
||||
return (0);
|
||||
#ifdef DEBUG
|
||||
if (ccddebug & CCDB_FOLLOW)
|
||||
printf("ccdclose(%p, %x)\n", dev, flags);
|
||||
@ -795,6 +812,10 @@ ccdstrategy(struct bio *bp)
|
||||
int wlabel;
|
||||
struct disklabel *lp;
|
||||
|
||||
if (bp->bio_dev->si_drv1 == bp->bio_dev) {
|
||||
biofinish(bp, NULL, ENXIO);
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (ccddebug & CCDB_FOLLOW)
|
||||
printf("ccdstrategy(%p): unit %d\n", bp, unit);
|
||||
@ -1243,7 +1264,96 @@ ccdiodone(struct bio *ibp)
|
||||
static int
|
||||
ccdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
{
|
||||
int unit = ccdunit(dev);
|
||||
struct ccd_ioctl *ccio;
|
||||
u_int unit;
|
||||
dev_t dev2;
|
||||
int error;
|
||||
|
||||
if (dev->si_drv1 != dev) {
|
||||
switch (cmd) {
|
||||
case CCDIOCSET:
|
||||
case CCDIOCCLR:
|
||||
case CCDCONFINFO:
|
||||
case CCDCPPINFO:
|
||||
printf("*** WARNING: upgrade your ccdconfig(8) binary\n");
|
||||
printf("*** WARNING: continuing in 30 seconds\n");
|
||||
tsleep(dev, PRIBIO, "ccdbug", hz * 30);
|
||||
break;
|
||||
}
|
||||
return ccdioctltoo(dev, cmd, data, flag, td);
|
||||
}
|
||||
switch (cmd) {
|
||||
case CCDIOCSET:
|
||||
case CCDIOCCLR:
|
||||
ccio = (struct ccd_ioctl *)data;
|
||||
unit = ccio->ccio_size;
|
||||
dev2 = makedev(CDEV_MAJOR, unit * 8 + 2);
|
||||
if (!(dev2->si_flags & SI_NAMED)) {
|
||||
dev2 = make_dev(&ccd_cdevsw, unit * 8 + 2,
|
||||
UID_ROOT, GID_OPERATOR, 0640, "ccd%dc", unit);
|
||||
ccdnew(unit);
|
||||
}
|
||||
return (ccdioctltoo(dev2, cmd, data, flag, td));
|
||||
case CCDCONFINFO:
|
||||
{
|
||||
int ninit = 0;
|
||||
struct ccdconf *conf = (struct ccdconf *)data;
|
||||
struct ccd_s *tmpcs;
|
||||
struct ccd_s *ubuf = conf->buffer;
|
||||
|
||||
/* XXX: LOCK(unique unit numbers) */
|
||||
LIST_FOREACH(tmpcs, &ccd_softc_list, list)
|
||||
if (IS_INITED(tmpcs))
|
||||
ninit++;
|
||||
|
||||
if (conf->size == 0) {
|
||||
conf->size = sizeof(struct ccd_s) * ninit;
|
||||
return (0);
|
||||
} else if ((conf->size / sizeof(struct ccd_s) != ninit) ||
|
||||
(conf->size % sizeof(struct ccd_s) != 0)) {
|
||||
/* XXX: UNLOCK(unique unit numbers) */
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
ubuf += ninit;
|
||||
LIST_FOREACH(tmpcs, &ccd_softc_list, list) {
|
||||
if (!IS_INITED(tmpcs))
|
||||
continue;
|
||||
error = copyout(tmpcs, --ubuf,
|
||||
sizeof(struct ccd_s));
|
||||
if (error != 0)
|
||||
/* XXX: UNLOCK(unique unit numbers) */
|
||||
return (error);
|
||||
}
|
||||
/* XXX: UNLOCK(unique unit numbers) */
|
||||
return (0);
|
||||
}
|
||||
|
||||
case CCDCPPINFO:
|
||||
{
|
||||
struct ccdcpps *cpps = (struct ccdcpps *)data;
|
||||
char *ubuf = cpps->buffer;
|
||||
|
||||
|
||||
error = copyin(ubuf, &unit, sizeof (unit));
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
if (!IS_ALLOCATED(unit))
|
||||
return (ENXIO);
|
||||
dev2 = makedev(CDEV_MAJOR, unit * 8 + 2);
|
||||
return (ccdioctltoo(dev2, cmd, data, flag, td));
|
||||
}
|
||||
|
||||
default:
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
ccdioctltoo(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
{
|
||||
int unit;
|
||||
int i, j, lookedup = 0, error = 0;
|
||||
int part, pmask, s;
|
||||
struct ccd_s *cs;
|
||||
@ -1251,6 +1361,7 @@ ccdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
char **cpp;
|
||||
struct vnode **vpp;
|
||||
|
||||
unit = ccdunit(dev);
|
||||
if (!IS_ALLOCATED(unit))
|
||||
return (ENXIO);
|
||||
cs = ccdfind(unit);
|
||||
@ -1469,8 +1580,8 @@ ccdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
if (cpps->size == 0) {
|
||||
cpps->size = len;
|
||||
break;
|
||||
} else if (cpps->size != len) {
|
||||
return (EINVAL);
|
||||
} else if (cpps->size < len) {
|
||||
return (ENOMEM);
|
||||
}
|
||||
|
||||
for (i = 0; i < cs->sc_nccdisks; ++i) {
|
||||
@ -1481,6 +1592,7 @@ ccdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct thread *td)
|
||||
return (error);
|
||||
ubuf += len;
|
||||
}
|
||||
return(copyout("", ubuf, 1));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -1545,6 +1657,9 @@ ccdsize(dev_t dev)
|
||||
struct ccd_s *cs;
|
||||
int part, size;
|
||||
|
||||
if (dev->si_drv1 == dev)
|
||||
return (-1);
|
||||
|
||||
if (ccdopen(dev, 0, S_IFCHR, curthread))
|
||||
return (-1);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user