From c902fadbae12e0dfdef3c9349c9d410471c99ac9 Mon Sep 17 00:00:00 2001 From: jsing Date: Thu, 14 Aug 2008 17:10:29 +0000 Subject: [PATCH] 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@ --- sbin/mount_vnd/mount_vnd.8 | 12 +++++++-- sbin/mount_vnd/mount_vnd.c | 23 ++++++++++++----- sys/dev/vnd.c | 53 ++++++++++++++++++++++++++------------ sys/dev/vndioctl.h | 3 ++- 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; -- 2.20.1