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:
phk 2003-01-17 14:53:53 +00:00
parent 58da5356d7
commit 867cdc9da1
4 changed files with 265 additions and 32 deletions

View File

@ -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;
}

View File

@ -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"

View File

@ -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);

View File

@ -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);