summaryrefslogtreecommitdiff
path: root/sys
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 /sys
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@
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/vnd.c53
-rw-r--r--sys/dev/vndioctl.h3
2 files changed, 39 insertions, 17 deletions
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;