summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Sing <jsing@cvs.openbsd.org>2008-08-14 17:10:30 +0000
committerJoel Sing <jsing@cvs.openbsd.org>2008-08-14 17:10:30 +0000
commit3ae163dbd6453b43a968daba4c367b8cb1e70100 (patch)
tree9e8c6e3cd03ea998fa6bed516003ae0063e92236
parent93820f4b0b65e48a8c5fe415afa684e8fcdb1feb (diff)
Allow the sector size to be specified by the user when configuring a
vnd(4) device, via a new -s option to vnconfig/mount_vnd. This allows us to create disklabels and file systems that are suitable for use on devices that have a non-512 byte sector size (eg. CDROMs). With help from krw@ and feedback from pedro@. ok krw@, pedro@
-rw-r--r--sbin/mount_vnd/mount_vnd.812
-rw-r--r--sbin/mount_vnd/mount_vnd.c23
-rw-r--r--sys/dev/vnd.c53
-rw-r--r--sys/dev/vndioctl.h3
4 files changed, 65 insertions, 26 deletions
diff --git a/sbin/mount_vnd/mount_vnd.8 b/sbin/mount_vnd/mount_vnd.8
index fe3a8636085..a44c76af947 100644
--- a/sbin/mount_vnd/mount_vnd.8
+++ b/sbin/mount_vnd/mount_vnd.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: mount_vnd.8,v 1.13 2008/05/26 21:14:46 jmc Exp $
+.\" $OpenBSD: mount_vnd.8,v 1.14 2008/08/14 17:10:29 jsing Exp $
.\"
.\" Copyright (c) 1993 University of Utah.
.\" Copyright (c) 1980, 1989, 1991, 1993
@@ -49,7 +49,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: May 26 2008 $
+.Dd $Mdocdate: August 14 2008 $
.Dt MOUNT_VND 8
.Os
.Sh NAME
@@ -63,6 +63,7 @@
.Op Fl K Ar rounds
.Op Fl o Ar options
.Op Fl S Ar saltfile
+.Op Fl s Ar secsize
.Ar image
.Ar vnd_dev
.Ek
@@ -71,6 +72,7 @@
.Op Fl ckluv
.Op Fl K Ar rounds
.Op Fl S Ar saltfile
+.Op Fl s Ar secsize
.Ar vnd_dev
.Ar image
.Ek
@@ -208,6 +210,12 @@ If the salt filename is not specified using
.Fl S ,
it defaults to
.Ar image Ns .slt .
+.It Fl s Ar secsize
+Specify the sector size, in bytes, to be used by the device.
+The default sector size is 512 bytes.
+If specified
+.Ar secsize
+must be a multiple of 512 bytes and cannot exceed 65536 bytes.
.It Fl u
.Nm vnconfig
only.
diff --git a/sbin/mount_vnd/mount_vnd.c b/sbin/mount_vnd/mount_vnd.c
index 50fe6555525..70441e42b51 100644
--- a/sbin/mount_vnd/mount_vnd.c
+++ b/sbin/mount_vnd/mount_vnd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mount_vnd.c,v 1.5 2008/06/14 01:47:27 grunk Exp $ */
+/* $OpenBSD: mount_vnd.c,v 1.6 2008/08/14 17:10:29 jsing Exp $ */
/*
* Copyright (c) 1993 University of Utah.
* Copyright (c) 1990, 1993
@@ -67,7 +67,7 @@ int verbose = 0;
int run_mount_vnd = 0;
__dead void usage(void);
-int config(char *, char *, int, char *, size_t);
+int config(char *, char *, int, size_t, char *, size_t);
int getinfo(const char *);
char *get_pkcs_key(char *, char *);
@@ -76,7 +76,8 @@ main(int argc, char **argv)
{
int ch, rv, action, opt_c, opt_k, opt_K, opt_l, opt_u;
char *key, *mntopts, *rounds, *saltopt;
- size_t keylen = 0;
+ size_t keylen = 0, secsize = 0;
+ const char *errstr;
extern char *__progname;
if (strcasecmp(__progname, "mount_vnd") == 0)
@@ -86,7 +87,7 @@ main(int argc, char **argv)
key = mntopts = rounds = saltopt = NULL;
action = VND_CONFIG;
- while ((ch = getopt(argc, argv, "ckK:lo:S:uv")) != -1) {
+ while ((ch = getopt(argc, argv, "ckK:lo:s:S:uv")) != -1) {
switch (ch) {
case 'c':
opt_c = 1;
@@ -107,6 +108,11 @@ main(int argc, char **argv)
case 'S':
saltopt = optarg;
break;
+ case 's':
+ secsize = strtonum(optarg, 512, 65536, &errstr);
+ if (errstr || (secsize & 0x1ff) != 0)
+ errx(1, "invalid sector size: %s", optarg);
+ break;
case 'u':
opt_u = 1;
break;
@@ -156,9 +162,10 @@ main(int argc, char **argv)
ind_raw = 0;
ind_reg = 1;
}
- rv = config(argv[ind_raw], argv[ind_reg], action, key, keylen);
+ rv = config(argv[ind_raw], argv[ind_reg], action, secsize, key,
+ keylen);
} else if (action == VND_UNCONFIG && argc == 1)
- rv = config(argv[0], NULL, action, NULL, 0);
+ rv = config(argv[0], NULL, action, 0, NULL, 0);
else if (action == VND_GET)
rv = getinfo(argc ? argv[0] : NULL);
else
@@ -274,7 +281,8 @@ query:
}
int
-config(char *dev, char *file, int action, char *key, size_t keylen)
+config(char *dev, char *file, int action, size_t secsize, char *key,
+ size_t keylen)
{
struct vnd_ioctl vndio;
FILE *f;
@@ -289,6 +297,7 @@ config(char *dev, char *file, int action, char *key, size_t keylen)
goto out;
}
vndio.vnd_file = file;
+ vndio.vnd_secsize = secsize;
vndio.vnd_key = (u_char *)key;
vndio.vnd_keylen = keylen;
diff --git a/sys/dev/vnd.c b/sys/dev/vnd.c
index 602f56f2006..fe4c9d3115b 100644
--- a/sys/dev/vnd.c
+++ b/sys/dev/vnd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vnd.c,v 1.88 2008/07/23 16:24:43 beck Exp $ */
+/* $OpenBSD: vnd.c,v 1.89 2008/08/14 17:10:29 jsing Exp $ */
/* $NetBSD: vnd.c,v 1.26 1996/03/30 23:06:11 christos Exp $ */
/*
@@ -128,7 +128,8 @@ struct vnd_softc {
char sc_file[VNDNLEN]; /* file we're covering */
int sc_flags; /* flags */
- size_t sc_size; /* size of vnd in blocks */
+ size_t sc_size; /* size of vnd in sectors */
+ size_t sc_secsize; /* sector size in bytes */
struct vnode *sc_vp; /* vnode */
struct ucred *sc_cred; /* credentials */
struct buf sc_tab; /* transfer queue */
@@ -305,7 +306,7 @@ vndgetdisklabel(dev_t dev, struct vnd_softc *sc, struct disklabel *lp,
bzero(lp, sizeof(struct disklabel));
- lp->d_secsize = DEV_BSIZE;
+ lp->d_secsize = sc->sc_secsize;
lp->d_ntracks = 1;
lp->d_nsectors = 100;
lp->d_ncylinders = sc->sc_size / 100;
@@ -407,6 +408,16 @@ vndstrategy(struct buf *bp)
return;
}
+ /* Ensure that the requested block is sector aligned. */
+ if (bp->b_blkno % DL_BLKSPERSEC(vnd->sc_dk.dk_label) != 0) {
+ bp->b_error = EINVAL;
+ bp->b_flags |= B_ERROR;
+ s = splbio();
+ biodone(bp);
+ splx(s);
+ return;
+ }
+
bn = bp->b_blkno;
bp->b_resid = bp->b_bcount;
@@ -434,15 +445,18 @@ vndstrategy(struct buf *bp)
bp->b_resid = bp->b_bcount;
}
- sz = howmany(bp->b_bcount, DEV_BSIZE);
+ if (vnd->sc_flags & VNF_HAVELABEL)
+ sz = howmany(bp->b_bcount, vnd->sc_dk.dk_label->d_secsize);
+ else
+ sz = howmany(bp->b_bcount, DEV_BSIZE);
/* No bypassing of buffer cache? */
if (vndsimple(bp->b_dev)) {
/* Loop until all queued requests are handled. */
for (;;) {
int part = DISKPART(bp->b_dev);
- daddr64_t off = DL_GETPOFFSET(&vnd->sc_dk.dk_label->d_partitions[part]);
-
+ daddr64_t off = DL_SECTOBLK(vnd->sc_dk.dk_label,
+ DL_GETPOFFSET(&vnd->sc_dk.dk_label->d_partitions[part]));
aiov.iov_base = bp->b_data;
auio.uio_resid = aiov.iov_len = bp->b_bcount;
auio.uio_iov = &aiov;
@@ -509,7 +523,8 @@ vndstrategy(struct buf *bp)
}
/* The old-style buffercache bypassing method. */
- bn += DL_GETPOFFSET(&vnd->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)]);
+ bn += DL_SECTOBLK(vnd->sc_dk.dk_label,
+ DL_GETPOFFSET(&vnd->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)]));
bn = dbtob(bn);
bsize = vnd->sc_vp->v_mount->mnt_stat.f_iosize;
addr = bp->b_data;
@@ -714,7 +729,6 @@ vndbdevsize(struct vnode *vp, struct proc *p)
{
struct partinfo pi;
struct bdevsw *bsw;
- long sscale;
dev_t dev;
dev = vp->v_rdev;
@@ -723,10 +737,9 @@ vndbdevsize(struct vnode *vp, struct proc *p)
return (0);
if (bsw->d_ioctl(dev, DIOCGPART, (caddr_t)&pi, FREAD, p))
return (0);
- sscale = pi.disklab->d_secsize / DEV_BSIZE;
- DNPRINTF(VDB_INIT, "vndbdevsize: size %li secsize %li sscale %li\n",
- (long)pi.part->p_size,(long)pi.disklab->d_secsize,sscale);
- return (pi.part->p_size * sscale);
+ DNPRINTF(VDB_INIT, "vndbdevsize: size %li secsize %li\n",
+ (long)pi.part->p_size,(long)pi.disklab->d_secsize);
+ return (pi.part->p_size);
}
/* ARGSUSED */
@@ -777,6 +790,14 @@ vndioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
return(ENXIO);
}
+ /* Set sector size for device, if specified. */
+ if (vio->vnd_secsize == 0)
+ vnd->sc_secsize = DEV_BSIZE;
+ else if (vio->vnd_secsize % DEV_BSIZE == 0)
+ vnd->sc_secsize = vio->vnd_secsize;
+ else
+ return (EINVAL);
+
/*
* Open for read and write first. This lets vn_open() weed out
* directories, sockets, etc. so we don't have to worry about
@@ -811,7 +832,7 @@ vndioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
vndunlock(vnd);
return (error);
}
- vnd->sc_size = btodb(vattr.va_size); /* note truncation */
+ vnd->sc_size = vattr.va_size / vnd->sc_secsize;
}
VOP_UNLOCK(nd.ni_vp, 0, p);
vnd->sc_vp = nd.ni_vp;
@@ -842,7 +863,7 @@ vndioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
} else
vnd->sc_keyctx = NULL;
- vio->vnd_size = dbtob((off_t)vnd->sc_size);
+ vio->vnd_size = vnd->sc_size * vnd->sc_secsize;
vnd->sc_flags |= VNF_INITED;
DNPRINTF(VDB_INIT, "vndioctl: SET vp %p size %llx\n",
@@ -1004,7 +1025,7 @@ vndsetcred(struct vnd_softc *vnd, struct ucred *cred)
/* XXX: Horrible kludge to establish credentials for NFS */
aiov.iov_base = tmpbuf;
- aiov.iov_len = MIN(DEV_BSIZE, dbtob((off_t)vnd->sc_size));
+ aiov.iov_len = MIN(DEV_BSIZE, vnd->sc_size * vnd->sc_secsize);
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_offset = 0;
@@ -1055,7 +1076,7 @@ vndsize(dev_t dev)
if (unit >= numvnd || (vnd->sc_flags & VNF_INITED) == 0)
return (-1);
- return (vnd->sc_size);
+ return (vnd->sc_size * (vnd->sc_secsize / DEV_BSIZE));
}
int
diff --git a/sys/dev/vndioctl.h b/sys/dev/vndioctl.h
index 2227952677f..6995d80ba21 100644
--- a/sys/dev/vndioctl.h
+++ b/sys/dev/vndioctl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vndioctl.h,v 1.6 2004/06/20 18:03:03 pedro Exp $ */
+/* $OpenBSD: vndioctl.h,v 1.7 2008/08/14 17:10:29 jsing Exp $ */
/* $NetBSD: vndioctl.h,v 1.5 1995/01/25 04:46:30 cgd Exp $ */
/*
@@ -49,6 +49,7 @@
*/
struct vnd_ioctl {
char *vnd_file; /* pathname of file to mount */
+ size_t vnd_secsize; /* sector size in bytes */
off_t vnd_size; /* (returned) size of disk */
u_char *vnd_key;
int vnd_keylen;