diff options
author | phk <phk@FreeBSD.org> | 1999-07-20 09:47:55 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 1999-07-20 09:47:55 +0000 |
commit | cacc73aa1890c8a258a383716e0c90da798acd4e (patch) | |
tree | 895deb1c3a5fdc3b63cee3173606b1811c3149f5 /sys/kern/vfs_subr.c | |
parent | cf4a7fab742bfd88596615a4e608783600af67b5 (diff) | |
download | FreeBSD-src-cacc73aa1890c8a258a383716e0c90da798acd4e.zip FreeBSD-src-cacc73aa1890c8a258a383716e0c90da798acd4e.tar.gz |
Now a dev_t is a pointer to struct specinfo which is shared by all specdev
vnodes referencing this device.
Details:
cdevsw->d_parms has been removed, the specinfo is available
now (== dev_t) and the driver should modify it directly
when applicable, and the only driver doing so, does so:
vn.c. I am not sure the logic in checking for "<" was right
before, and it looks even less so now.
An intial pool of 50 struct specinfo are depleted during
early boot, after that malloc had better work. It is
likely that fewer than 50 would do.
Hashing is done from udev_t to dev_t with a prime number
remainder hash, experiments show no better hash available
for decent cost (MD5 is only marginally better) The prime
number used should not be close to a power of two, we use
83 for now.
Add new checkalias2() to get around the loss of info from
dev2udev() in bdevvp();
The aliased vnodes are hung on a list straight of the dev_t,
and speclisth[SPECSZ] is unused. The sharing of struct
specinfo means that the v_specnext moves into the vnode
which grows by 4 bytes.
Don't use a VBLK dev_t which doesn't make sense in MFS, now
we hang a dummy cdevsw on B/Cmaj 253 so that things look sane.
Storage overhead from all of this is O(50k).
Bump __FreeBSD_version to 400009
The next step will add the stuff needed so device-drivers can start to
hang things from struct specinfo
Diffstat (limited to 'sys/kern/vfs_subr.c')
-rw-r--r-- | sys/kern/vfs_subr.c | 89 |
1 files changed, 38 insertions, 51 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 7dd2110..fddda87 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_subr.c 8.31 (Berkeley) 5/26/95 - * $Id: vfs_subr.c,v 1.211 1999/07/18 14:30:37 phk Exp $ + * $Id: vfs_subr.c,v 1.212 1999/07/19 09:37:59 phk Exp $ */ /* @@ -80,6 +80,7 @@ static MALLOC_DEFINE(M_NETADDR, "Export Host", "Export host address structure"); +static struct vnode *checkalias2 __P((struct vnode *nvp, dev_t dev, struct mount *mp)); static void insmntque __P((struct vnode *vp, struct mount *mp)); static void vclean __P((struct vnode *vp, int flags, struct proc *p)); static void vfree __P((struct vnode *)); @@ -1245,12 +1246,11 @@ bdevvp(dev, vpp) } vp = nvp; /* dev2udev() results in a CDEV, so we need to cheat here. */ - vp->v_type = VCHR; - if ((nvp = checkalias(vp, dev2udev(dev), (struct mount *)0)) != NULL) { + vp->v_type = VBLK; + if ((nvp = checkalias2(vp, dev, (struct mount *)0)) != NULL) { vput(vp); vp = nvp; } - vp->v_type = VBLK; *vpp = vp; return (0); } @@ -1269,21 +1269,33 @@ checkalias(nvp, nvp_rdev, mp) udev_t nvp_rdev; struct mount *mp; { - struct proc *p = curproc; /* XXX */ - struct vnode *vp; - struct vnode **vpp; dev_t dev; if (nvp->v_type != VBLK && nvp->v_type != VCHR) return (NULLVP); dev = udev2dev(nvp_rdev, nvp->v_type == VBLK ? 1 : 0); + return (checkalias2(nvp, dev, mp)); +} - vpp = &speclisth[SPECHASH(dev)]; +static struct vnode * +checkalias2(nvp, dev, mp) + register struct vnode *nvp; + dev_t dev; + struct mount *mp; +{ + struct proc *p = curproc; /* XXX */ + struct vnode *vp; + struct vnode **vpp; + + if (nvp->v_type != VBLK && nvp->v_type != VCHR) + return (NULLVP); + + vpp = &dev->si_hlist; loop: simple_lock(&spechash_slock); for (vp = *vpp; vp; vp = vp->v_specnext) { - if (dev != vp->v_rdev || nvp->v_type != vp->v_type) + if (nvp->v_type != vp->v_type) continue; /* * Alias, but not in use, so flush it out. @@ -1319,32 +1331,11 @@ loop: * Put the new vnode into the hash chain. * and if there was an alias, connect them. */ - MALLOC(sinfo, struct specinfo *, - sizeof(struct specinfo), M_VNODE, M_WAITOK); - bzero(sinfo, sizeof(struct specinfo)); - nvp->v_specinfo = sinfo; - sinfo->si_rdev = dev; - sinfo->si_hashchain = vpp; - sinfo->si_specnext = *vpp; - sinfo->si_bsize_phys = DEV_BSIZE; - sinfo->si_bsize_best = BLKDEV_IOSIZE; - sinfo->si_bsize_max = MAXBSIZE; - - /* - * Ask the device to fix up specinfo. Typically the - * si_bsize_* parameters may need fixing up. - */ - - if (nvp->v_type == VBLK) { - if (bdevsw(dev) && bdevsw(dev)->d_parms) - (*bdevsw(dev)->d_parms)(dev, sinfo, DPARM_GET); - } else if (nvp->v_type == VCHR) { - if (devsw(dev) && devsw(dev)->d_parms) - (*devsw(dev)->d_parms)(dev, sinfo, DPARM_GET); - } + nvp->v_specnext = *vpp; + *vpp = nvp; + nvp->v_specinfo = sinfo = dev; simple_unlock(&spechash_slock); - *vpp = nvp; if (vp != NULLVP) { nvp->v_flag |= VALIASED; vp->v_flag |= VALIASED; @@ -1355,7 +1346,7 @@ loop: /* * if ( vp && (vp->v_tag == VT_NULL)) * We have a vnode alias, but it is a trashed. - * Make it look like it's newley allocated. (by getnewvnode()) + * Make it look like it's newly allocated. (by getnewvnode()) * The caller should use this instead. */ simple_unlock(&spechash_slock); @@ -1797,9 +1788,8 @@ vop_revoke(ap) simple_unlock(&vp->v_interlock); while (vp->v_flag & VALIASED) { simple_lock(&spechash_slock); - for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { - if (vq->v_rdev != vp->v_rdev || - vq->v_type != vp->v_type || vp == vq) + for (vq = vp->v_hashchain; vq; vq = vq->v_specnext) { + if (vq->v_type != vp->v_type || vp == vq) continue; simple_unlock(&spechash_slock); vgone(vq); @@ -1902,10 +1892,10 @@ vgonel(vp, p) */ if ((vp->v_type == VBLK || vp->v_type == VCHR) && vp->v_specinfo != 0) { simple_lock(&spechash_slock); - if (*vp->v_hashchain == vp) { - *vp->v_hashchain = vp->v_specnext; + if (vp->v_hashchain == vp) { + vp->v_hashchain = vp->v_specnext; } else { - for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { + for (vq = vp->v_hashchain; vq; vq = vq->v_specnext) { if (vq->v_specnext != vp) continue; vq->v_specnext = vp->v_specnext; @@ -1916,9 +1906,8 @@ vgonel(vp, p) } if (vp->v_flag & VALIASED) { vx = NULL; - for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { - if (vq->v_rdev != vp->v_rdev || - vq->v_type != vp->v_type) + for (vq = vp->v_hashchain; vq; vq = vq->v_specnext) { + if (vq->v_type != vp->v_type) continue; if (vx) break; @@ -1931,7 +1920,6 @@ vgonel(vp, p) vp->v_flag &= ~VALIASED; } simple_unlock(&spechash_slock); - FREE(vp->v_specinfo, M_VNODE); vp->v_specinfo = NULL; } @@ -1979,8 +1967,8 @@ vfinddev(dev, type, vpp) int rc = 0; simple_lock(&spechash_slock); - for (vp = speclisth[SPECHASH(dev)]; vp; vp = vp->v_specnext) { - if (dev != vp->v_rdev || type != vp->v_type) + for (vp = dev->si_hlist; vp; vp = vp->v_specnext) { + if (type != vp->v_type) continue; *vpp = vp; rc = 1; @@ -2004,9 +1992,9 @@ loop: if ((vp->v_flag & VALIASED) == 0) return (vp->v_usecount); simple_lock(&spechash_slock); - for (count = 0, vq = *vp->v_hashchain; vq; vq = vnext) { + for (count = 0, vq = vp->v_hashchain; vq; vq = vnext) { vnext = vq->v_specnext; - if (vq->v_rdev != vp->v_rdev || vq->v_type != vp->v_type) + if (vq->v_type != vp->v_type) continue; /* * Alias, but not in use, so flush it out. @@ -2267,9 +2255,8 @@ vfs_mountedon(vp) return (EBUSY); if (vp->v_flag & VALIASED) { simple_lock(&spechash_slock); - for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { - if (vq->v_rdev != vp->v_rdev || - vq->v_type != vp->v_type) + for (vq = vp->v_hashchain; vq; vq = vq->v_specnext) { + if (vq->v_type != vp->v_type) continue; if (vq->v_specmountpoint != NULL) { error = EBUSY; |