summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sbin/ccdconfig/ccdconfig.c36
-rw-r--r--sbin/ccdconfig/pathnames.h3
-rw-r--r--sys/dev/ccd/ccd.c129
-rw-r--r--sys/geom/geom_ccd.c129
4 files changed, 265 insertions, 32 deletions
diff --git a/sbin/ccdconfig/ccdconfig.c b/sbin/ccdconfig/ccdconfig.c
index 2908399..c1c7ad5 100644
--- a/sbin/ccdconfig/ccdconfig.c
+++ b/sbin/ccdconfig/ccdconfig.c
@@ -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;
}
diff --git a/sbin/ccdconfig/pathnames.h b/sbin/ccdconfig/pathnames.h
index f8da9e0..538cfed 100644
--- a/sbin/ccdconfig/pathnames.h
+++ b/sbin/ccdconfig/pathnames.h
@@ -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"
diff --git a/sys/dev/ccd/ccd.c b/sys/dev/ccd/ccd.c
index 7b2ea9a..c012ceb 100644
--- a/sys/dev/ccd/ccd.c
+++ b/sys/dev/ccd/ccd.c
@@ -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);
diff --git a/sys/geom/geom_ccd.c b/sys/geom/geom_ccd.c
index 7b2ea9a..c012ceb 100644
--- a/sys/geom/geom_ccd.c
+++ b/sys/geom/geom_ccd.c
@@ -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);
OpenPOWER on IntegriCloud