diff options
author | dillon <dillon@FreeBSD.org> | 1999-02-25 05:22:30 +0000 |
---|---|---|
committer | dillon <dillon@FreeBSD.org> | 1999-02-25 05:22:30 +0000 |
commit | 9b8aaaa7375f258fd7dc7faf201875d578599b02 (patch) | |
tree | fbbc77b0ff3baa9b7cd6260e12c22dbbc9dd5ca7 /sys/miscfs | |
parent | 2cb5b6d7d54b14e1086055e6a5d05f9f96e0fc40 (diff) | |
download | FreeBSD-src-9b8aaaa7375f258fd7dc7faf201875d578599b02.zip FreeBSD-src-9b8aaaa7375f258fd7dc7faf201875d578599b02.tar.gz |
Reviewed by: Julian Elischer <julian@whistle.com>
Add d_parms() to {c,b}devsw[]. If non-NULL this function points to
a device routine that will properly fill in the specinfo structure.
vfs_subr.c's checkalias() supplies appropriate defaults. This change
should be fully backwards compatible with existing devices.
Diffstat (limited to 'sys/miscfs')
-rw-r--r-- | sys/miscfs/specfs/spec_vnops.c | 65 | ||||
-rw-r--r-- | sys/miscfs/specfs/specdev.h | 7 |
2 files changed, 46 insertions, 26 deletions
diff --git a/sys/miscfs/specfs/spec_vnops.c b/sys/miscfs/specfs/spec_vnops.c index 88290e4..3f29d9362 100644 --- a/sys/miscfs/specfs/spec_vnops.c +++ b/sys/miscfs/specfs/spec_vnops.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)spec_vnops.c 8.14 (Berkeley) 5/21/95 - * $Id: spec_vnops.c,v 1.79 1999/01/21 08:29:07 dillon Exp $ + * $Id: spec_vnops.c,v 1.80 1999/01/27 22:42:07 dillon Exp $ */ #include <sys/param.h> @@ -286,8 +286,15 @@ spec_read(ap) case VBLK: if (uio->uio_offset < 0) return (EINVAL); - bsize = BLKDEV_IOSIZE; dev = vp->v_rdev; + + /* + * Calculate block size for block device. The block size must + * be larger then the physical minimum. + */ + + bsize = vp->v_specinfo->si_bsize_best; + if ((ioctl = bdevsw[major(dev)]->d_ioctl) != NULL && (*ioctl)(dev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0 && dpart.part->p_fstype == FS_BSDFFS && @@ -365,7 +372,13 @@ spec_write(ap) return (0); if (uio->uio_offset < 0) return (EINVAL); - bsize = BLKDEV_IOSIZE; + + /* + * Calculate block size for block device. The block size must + * be larger then the physical minimum. + */ + bsize = vp->v_specinfo->si_bsize_best; + if ((*bdevsw[major(vp->v_rdev)]->d_ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&dpart, FREAD, p) == 0) { if (dpart.part->p_fstype == FS_BSDFFS && @@ -749,14 +762,16 @@ spec_getpages(ap) pcount = round_page(ap->a_count) / PAGE_SIZE; /* - * Calculate the offset of the transfer. + * Calculate the offset of the transfer and do sanity check. + * FreeBSD currently only supports an 8 TB range due to b_blkno + * being in DEV_BSIZE ( usually 512 ) byte chunks on call to + * VOP_STRATEGY. XXX */ offset = IDX_TO_OFF(ap->a_m[0]->pindex) + ap->a_offset; - /* XXX sanity check before we go into details. */ - /* XXX limits should be defined elsewhere. */ -#define DADDR_T_BIT 32 +#define DADDR_T_BIT (sizeof(daddr_t)*8) #define OFFSET_MAX ((1LL << (DADDR_T_BIT + DEV_BSHIFT)) - 1) + if (offset < 0 || offset > OFFSET_MAX) { /* XXX still no %q in kernel. */ printf("spec_getpages: preposterous offset 0x%x%08x\n", @@ -768,20 +783,20 @@ spec_getpages(ap) blkno = btodb(offset); /* - * Round up physical size for real devices, use the - * fundamental blocksize of the fs if possible. + * Round up physical size for real devices. We cannot round using + * v_mount's block size data because v_mount has nothing to do with + * the device. i.e. it's usually '/dev'. We need the physical block + * size for the device itself. + * + * We can't use v_specmountpoint because it only exists when the + * block device is mounted. However, we can use v_specinfo. */ - if (vp && vp->v_mount) { - if (vp->v_type != VBLK) { - vprint("Non VBLK", vp); - } - blksiz = vp->v_mount->mnt_stat.f_bsize; - if (blksiz < DEV_BSIZE) { - blksiz = DEV_BSIZE; - } - } + + if (vp->v_type == VBLK) + blksiz = vp->v_specinfo->si_bsize_phys; else blksiz = DEV_BSIZE; + size = (ap->a_count + blksiz - 1) & ~(blksiz - 1); bp = getpbuf(NULL); @@ -885,8 +900,8 @@ spec_getpages(ap) m = ap->a_m[ap->a_reqpage]; #ifndef MAX_PERF printf( - "spec_getpages: I/O read failure: (error code=%d)\n", - error); + "spec_getpages: I/O read failure: (error code=%d) bp %p vp %p\n", + error, bp, bp->b_vp); printf( " size: %d, resid: %ld, a_count: %d, valid: 0x%x\n", size, bp->b_resid, ap->a_count, m->valid); @@ -923,10 +938,14 @@ spec_getattr(ap) bzero(vap, sizeof (*vap)); - if (vp->v_type == VBLK) - vap->va_blocksize = BLKDEV_IOSIZE; - else if (vp->v_type == VCHR) + if (vp->v_type == VBLK) { + if (vp->v_specinfo) + vap->va_blocksize = vp->v_specmountpoint->mnt_stat.f_iosize; + else + vap->va_blocksize = BLKDEV_IOSIZE; + } else if (vp->v_type == VCHR) { vap->va_blocksize = MAXBSIZE; + } if ((*bdevsw[major(vp->v_rdev)]->d_ioctl)(vp->v_rdev, DIOCGPART, (caddr_t)&dpart, FREAD, ap->a_p) == 0) { diff --git a/sys/miscfs/specfs/specdev.h b/sys/miscfs/specfs/specdev.h index 9c225a3..a7e2bab 100644 --- a/sys/miscfs/specfs/specdev.h +++ b/sys/miscfs/specfs/specdev.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)specdev.h 8.6 (Berkeley) 5/21/95 - * $Id: specdev.h,v 1.14 1998/03/08 09:57:40 julian Exp $ + * $Id: specdev.h,v 1.15 1998/04/19 23:32:29 julian Exp $ */ /* @@ -44,7 +44,9 @@ struct specinfo { struct vnode *si_specnext; struct mount *si_mountpoint; dev_t si_rdev; - unsigned long si_blksize; /* smallest IO unit */ + int si_bsize_phys; /* minimum physical block size */ + int si_bsize_best; /* optimal block size / VBLK */ + int si_bsize_max; /* maximum block size */ }; /* * Exported shorthand @@ -53,7 +55,6 @@ struct specinfo { #define v_hashchain v_specinfo->si_hashchain #define v_specnext v_specinfo->si_specnext #define v_specmountpoint v_specinfo->si_mountpoint -#define v_blksize v_specinfo->si_blksize /* * Special device management |