diff options
author | 2002-02-17 04:29:52 +0000 | |
---|---|---|
committer | 2002-02-17 04:29:52 +0000 | |
commit | 5dceb04625698df0cbfc9f80292dbf0fda5f3e01 (patch) | |
tree | 770a0b59b0deee3ca59dfcc24fcbf6eab4ee2f35 | |
parent | oops, add -U to usage (diff) | |
download | wireguard-openbsd-5dceb04625698df0cbfc9f80292dbf0fda5f3e01.tar.xz wireguard-openbsd-5dceb04625698df0cbfc9f80292dbf0fda5f3e01.zip |
Cache vnodes, don't hold on to the root vnode, some cleanups, handle
physmem and usermem correctly.
kernel/2404 from peterw@ifost.org.au with some small fixups from me.
-rw-r--r-- | sys/miscfs/kernfs/kernfs.h | 21 | ||||
-rw-r--r-- | sys/miscfs/kernfs/kernfs_vfsops.c | 76 | ||||
-rw-r--r-- | sys/miscfs/kernfs/kernfs_vnops.c | 246 |
3 files changed, 204 insertions, 139 deletions
diff --git a/sys/miscfs/kernfs/kernfs.h b/sys/miscfs/kernfs/kernfs.h index 9b720db8aee..a4647ca8f3c 100644 --- a/sys/miscfs/kernfs/kernfs.h +++ b/sys/miscfs/kernfs/kernfs.h @@ -1,4 +1,4 @@ -/* $OpenBSD: kernfs.h,v 1.8 2000/02/07 04:57:16 assar Exp $ */ +/* $OpenBSD: kernfs.h,v 1.9 2002/02/17 04:29:52 art Exp $ */ /* $NetBSD: kernfs.h,v 1.10 1996/02/09 22:40:21 christos Exp $ */ /* @@ -58,6 +58,7 @@ struct kern_target { #define KTT_MSGBUF 89 #define KTT_USERMEM 91 #define KTT_DOMAIN 95 +#define KTT_PHYSMEM 99 #ifdef IPSEC #define KTT_IPSECSPI 107 #endif @@ -66,15 +67,20 @@ struct kern_target { mode_t kt_mode; }; -struct kernfs_mount { - struct vnode *kf_root; /* Root node */ -}; - struct kernfs_node { + TAILQ_ENTRY(kernfs_node) list; struct kern_target *kf_kt; + struct vnode *kf_vnode; +#define kf_type kf_kt->kt_type +#define kf_namlen kf_kt->kt_namlen +#define kf_name kf_kt->kt_name +#define kf_data kf_kt->kt_data +#define kf_vtype kf_kt->kt_vtype +#define kf_mode kf_kt->kt_mode +#define kf_tag kf_kt->kt_tag }; -#define VFSTOKERNFS(mp) ((struct kernfs_mount *)((mp)->mnt_data)) +#define KERNTOV(kn) ((struct vnode *)(kn)->kf_vnode) #define VTOKERN(vp) ((struct kernfs_node *)(vp)->v_data) #define kernfs_fhtovp ((int (*) __P((struct mount *, struct fid *, \ @@ -91,6 +97,9 @@ struct kernfs_node { #define kernfs_checkexp ((int (*) __P((struct mount *, struct mbuf *, \ int *, struct ucred **)))eopnotsupp) +int kernfs_init __P((struct vfsconf *)); +int kernfs_allocvp __P((struct kern_target *, struct mount *, struct vnode **)); +struct kern_target *kernfs_findtarget __P((char *, int)); extern int (**kernfs_vnodeop_p) __P((void *)); extern struct vfsops kernfs_vfsops; extern dev_t rrootdev; diff --git a/sys/miscfs/kernfs/kernfs_vfsops.c b/sys/miscfs/kernfs/kernfs_vfsops.c index c78f89f896e..9ac13e1427e 100644 --- a/sys/miscfs/kernfs/kernfs_vfsops.c +++ b/sys/miscfs/kernfs/kernfs_vfsops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kernfs_vfsops.c,v 1.16 2001/11/06 19:53:20 miod Exp $ */ +/* $OpenBSD: kernfs_vfsops.c,v 1.17 2002/02/17 04:29:52 art Exp $ */ /* $NetBSD: kernfs_vfsops.c,v 1.26 1996/04/22 01:42:27 christos Exp $ */ /* @@ -60,7 +60,6 @@ dev_t rrootdev = NODEV; -int kernfs_init __P((struct vfsconf *)); void kernfs_get_rrootdev __P((void)); int kernfs_mount __P((struct mount *, const char *, void *, struct nameidata *, struct proc *)); @@ -69,14 +68,6 @@ int kernfs_unmount __P((struct mount *, int, struct proc *)); int kernfs_root __P((struct mount *, struct vnode **)); int kernfs_statfs __P((struct mount *, struct statfs *, struct proc *)); -/*ARGSUSED*/ -int -kernfs_init(vfsp) - struct vfsconf *vfsp; -{ - return (0); -} - void kernfs_get_rrootdev() { @@ -111,10 +102,7 @@ kernfs_mount(mp, path, data, ndp, p) struct nameidata *ndp; struct proc *p; { - int error = 0; size_t size; - struct kernfs_mount *fmp; - struct vnode *rvp; #ifdef KERNFS_DIAGNOSTIC printf("kernfs_mount(mp = %p)\n", mp); @@ -126,20 +114,7 @@ kernfs_mount(mp, path, data, ndp, p) if (mp->mnt_flag & MNT_UPDATE) return (EOPNOTSUPP); - error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, &rvp); - if (error) - return (error); - - MALLOC(fmp, struct kernfs_mount *, sizeof(struct kernfs_mount), - M_MISCFSMNT, M_WAITOK); - rvp->v_type = VDIR; - rvp->v_flag |= VROOT; -#ifdef KERNFS_DIAGNOSTIC - printf("kernfs_mount: root vp = %p\n", rvp); -#endif - fmp->kf_root = rvp; mp->mnt_flag |= MNT_LOCAL; - mp->mnt_data = (qaddr_t)fmp; vfs_getnewfsid(mp); (void) copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size); @@ -160,7 +135,6 @@ kernfs_start(mp, flags, p) int flags; struct proc *p; { - return (0); } @@ -172,7 +146,6 @@ kernfs_unmount(mp, mntflags, p) { int error; int flags = 0; - struct vnode *rootvp = VFSTOKERNFS(mp)->kf_root; #ifdef KERNFS_DIAGNOSTIC printf("kernfs_unmount(mp = %p)\n", mp); @@ -182,32 +155,12 @@ kernfs_unmount(mp, mntflags, p) flags |= FORCECLOSE; } - /* - * Clear out buffer cache. I don't think we - * ever get anything cached at this level at the - * moment, but who knows... - */ - if (rootvp->v_usecount > 1) - return (EBUSY); #ifdef KERNFS_DIAGNOSTIC printf("kernfs_unmount: calling vflush\n"); #endif - if ((error = vflush(mp, rootvp, flags)) != 0) + if ((error = vflush(mp, 0, flags)) != 0) return (error); -#ifdef KERNFS_DIAGNOSTIC - vprint("kernfs root", rootvp); -#endif - /* - * Clean out the old root vnode for reuse. - */ - vrele(rootvp); - vgone(rootvp); - /* - * Finally, throw away the kernfs_mount structure - */ - free(mp->mnt_data, M_MISCFSMNT); - mp->mnt_data = 0; return (0); } @@ -216,21 +169,24 @@ kernfs_root(mp, vpp) struct mount *mp; struct vnode **vpp; { - struct vnode *vp; - struct proc *p = curproc; + struct kern_target *kt; + int error; #ifdef KERNFS_DIAGNOSTIC printf("kernfs_root(mp = %p)\n", mp); #endif - - /* - * Return locked reference to root. - */ - vp = VFSTOKERNFS(mp)->kf_root; - VREF(vp); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); - *vpp = vp; - return (0); + kt = kernfs_findtarget(".", 1); + /* this should never happen */ + if (kt == NULL) + panic("kernfs_root: findtarget returned NULL\n"); + + error = kernfs_allocvp(kt, mp, vpp); + /* this should never happen */ + if (error) + panic("kernfs_root: couldn't find root\n"); + + return(0); + } int diff --git a/sys/miscfs/kernfs/kernfs_vnops.c b/sys/miscfs/kernfs/kernfs_vnops.c index e60b69fc3f6..f5b754fc892 100644 --- a/sys/miscfs/kernfs/kernfs_vnops.c +++ b/sys/miscfs/kernfs/kernfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kernfs_vnops.c,v 1.24 2001/12/11 16:48:12 millert Exp $ */ +/* $OpenBSD: kernfs_vnops.c,v 1.25 2002/02/17 04:29:52 art Exp $ */ /* $NetBSD: kernfs_vnops.c,v 1.43 1996/03/16 23:52:47 christos Exp $ */ /* @@ -101,7 +101,7 @@ struct kern_target kern_targets[] = { { DT_REG, N("osrelease"), &osrelease, KTT_STRING, VREG, READ_MODE }, { DT_REG, N("osrev"), &osrev, KTT_INT, VREG, READ_MODE }, { DT_REG, N("pagesize"), &uvmexp.pagesize, KTT_INT, VREG, READ_MODE }, - { DT_REG, N("physmem"), &physmem, KTT_INT, VREG, READ_MODE }, + { DT_REG, N("physmem"), &physmem, KTT_PHYSMEM, VREG, READ_MODE }, { DT_REG, N("posix"), &posix, KTT_INT, VREG, READ_MODE }, #if 0 { DT_DIR, N("root"), 0, KTT_NULL, VDIR, DIR_MODE }, @@ -163,6 +163,7 @@ int kernfs_vfree __P((void *)); int kernfs_xread __P((struct kern_target *, int, char **, int)); int kernfs_xwrite __P((struct kern_target *, char *, int)); +int kernfs_freevp __P((struct vnode *, struct proc *)); int (**kernfs_vnodeop_p) __P((void *)); struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = { @@ -206,6 +207,117 @@ struct vnodeopv_entry_desc kernfs_vnodeop_entries[] = { struct vnodeopv_desc kernfs_vnodeop_opv_desc = { &kernfs_vnodeop_p, kernfs_vnodeop_entries }; +TAILQ_HEAD(, kernfs_node) kfshead; +static struct lock kfscache_lock; + +int +kernfs_init(vfsp) + struct vfsconf *vfsp; +{ + lockinit(&kfscache_lock, PVFS, "kfs", 0, 0); + TAILQ_INIT(&kfshead); + return(0); +} + +int +kernfs_allocvp(kt, mp, vpp) + struct kern_target *kt; + struct mount *mp; + struct vnode **vpp; +{ + struct proc *p = curproc; + struct kernfs_node *kf; + struct vnode *vp; + int error = 0; + +#ifdef KERNFS_DIAGNOSTIC + /* this should never happen */ + if (kt == NULL) + panic("kernfs_allocvp passed NULL kt, mp %p, vpp %p!\n", mp, vpp); + + printf("kernfs_allocvp: looking for %s\n", kt->kt_name); +#endif + if ((error = lockmgr(&kfscache_lock, LK_EXCLUSIVE, NULL, p)) != 0) + return(error); + +loop: + for (kf = TAILQ_FIRST(&kfshead); kf != NULL; kf = TAILQ_NEXT(kf, list)) { + vp = KERNTOV(kf); + if (vp->v_mount == mp && kt->kt_namlen == kf->kf_namlen && + bcmp(kf->kf_name, kt->kt_name, kt->kt_namlen) == 0) { +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_allocvp: hit %s\n", kt->kt_name); +#endif + if (vget(vp, 0, p)) + goto loop; + *vpp = vp; + goto out; + } + } + + MALLOC(kf, void *, sizeof(struct kernfs_node), M_TEMP, M_WAITOK); + error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, vpp); + if (error) { + FREE(kf, M_TEMP); + goto out; + } + vp = *vpp; + kf->kf_kt = kt; + kf->kf_vnode = vp; + vp->v_type = kf->kf_vtype; + vp->v_data = kf; + if (kf->kf_namlen == 1 && bcmp(kf->kf_name, ".", 1) == 0) + vp->v_flag |= VROOT; + + TAILQ_INSERT_TAIL(&kfshead, kf, list); +out: + lockmgr(&kfscache_lock, LK_RELEASE, NULL, p); + +#ifdef KERNFS_DIAGNOSTIC + if (error) + printf("kernfs_allocvp: error %d\n", error); +#endif + return(error); +} + +int +kernfs_freevp(vp, p) + struct vnode *vp; + struct proc *p; +{ + struct kernfs_node *kf = VTOKERN(vp); + + TAILQ_REMOVE(&kfshead, kf, list); + VOP_UNLOCK(vp, 0, p); + FREE(vp->v_data, M_TEMP); + vp->v_data = 0; + return(0); +} + +struct kern_target * +kernfs_findtarget(name, namlen) + char *name; + int namlen; +{ + struct kern_target *kt = NULL; + int i; + + for (i = 0; i < nkern_targets; i++) { + if (kern_targets[i].kt_namlen == namlen && + bcmp(kern_targets[i].kt_name, name, namlen) == 0) { + kt = &kern_targets[i]; + break; + } + } + +#ifdef KERNFS_DIAGNOSTIC + if (i == nkern_targets || kt == NULL) + printf("kernfs_findtarget: no match for %s\n"); +#endif + return(kt); +} + + int kernfs_xread(kt, off, bufp, len) struct kern_target *kt; @@ -304,8 +416,13 @@ kernfs_xread(kt, off, bufp, len) break; case KTT_USERMEM: - sprintf(*bufp, "%u\n", physmem - uvmexp.wired); + sprintf(*bufp, "%u\n", ctob(physmem - uvmexp.wired)); + break; + + case KTT_PHYSMEM: + sprintf(*bufp, "%u\n", ctob(physmem)); break; + #ifdef IPSEC case KTT_IPSECSPI: return(ipsp_kern(off, bufp, len)); @@ -370,83 +487,57 @@ kernfs_lookup(v) char *pname = cnp->cn_nameptr; struct proc *p = cnp->cn_proc; struct kern_target *kt; - struct vnode *fvp; - int error, i; + struct vnode *vp; + int error; #ifdef KERNFS_DIAGNOSTIC printf("kernfs_lookup(%p)\n", ap); printf("kernfs_lookup(dp = %p, vpp = %p, cnp = %p)\n", dvp, vpp, ap->a_cnp); printf("kernfs_lookup(%s)\n", pname); #endif - + VOP_UNLOCK(dvp, 0, p); *vpp = NULLVP; if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME) return (EROFS); - if (cnp->cn_namelen == 1 && *pname == '.') { + if (cnp->cn_namelen == 1 && *pname == '.') { *vpp = dvp; VREF(dvp); vn_lock(dvp, LK_SHARED | LK_RETRY, p); return (0); } -#if 0 - if (cnp->cn_namelen == 4 && bcmp(pname, "root", 4) == 0) { - *vpp = rootdir; - VREF(rootdir); - vn_lock(rootdir, LK_SHARED | LK_RETRY, p); - return (0); - } -#endif - - for (kt = kern_targets, i = 0; i < nkern_targets; kt++, i++) { - if (cnp->cn_namelen == kt->kt_namlen && - bcmp(kt->kt_name, pname, cnp->cn_namelen) == 0) - goto found; + kt = kernfs_findtarget(pname, cnp->cn_namelen); + if (kt == NULL) { + /* not found */ + vn_lock(dvp, LK_SHARED | LK_RETRY, p); + return(cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); } -#ifdef KERNFS_DIAGNOSTIC - printf("kernfs_lookup: i = %d, failed", i); -#endif - - vn_lock(dvp, LK_SHARED | LK_RETRY, p); - return (cnp->cn_nameiop == LOOKUP ? ENOENT : EROFS); - -found: if (kt->kt_tag == KTT_DEVICE) { dev_t *dp = kt->kt_data; + loop: - if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &fvp)) - return (ENOENT); - *vpp = fvp; - if (vget(fvp, LK_EXCLUSIVE, p)) + if (*dp == NODEV || !vfinddev(*dp, kt->kt_vtype, &vp)) + return(ENOENT); + + *vpp = vp; + if (vget(vp, LK_EXCLUSIVE, p)) goto loop; - return (0); + return(0); } -#ifdef KERNFS_DIAGNOSTIC - printf("kernfs_lookup: allocate new vnode\n"); -#endif - error = getnewvnode(VT_KERNFS, dvp->v_mount, kernfs_vnodeop_p, &fvp); - if (error) { + + if ((error = kernfs_allocvp(kt, dvp->v_mount, vpp)) != 0) { vn_lock(dvp, LK_SHARED | LK_RETRY, p); - return (error); + return(error); } - MALLOC(fvp->v_data, void *, sizeof(struct kernfs_node), M_TEMP, - M_WAITOK); - VTOKERN(fvp)->kf_kt = kt; - fvp->v_type = kt->kt_vtype; - vn_lock(fvp, LK_SHARED | LK_RETRY, p); - *vpp = fvp; - -#ifdef KERNFS_DIAGNOSTIC - printf("kernfs_lookup: newvp = %p\n", fvp); -#endif - return (0); + vn_lock(*vpp, LK_SHARED | LK_RETRY, p); + return(error); } - + /*ARGSUSED*/ int kernfs_open(v) @@ -467,8 +558,8 @@ kernfs_access(v) struct proc *a_p; } */ *ap = v; struct vnode *vp = ap->a_vp; - mode_t fmode = - (vp->v_flag & VROOT) ? DIR_MODE : VTOKERN(vp)->kf_kt->kt_mode; + + mode_t fmode = (vp->v_flag & VROOT) ? DIR_MODE : VTOKERN(vp)->kf_mode; return (vaccess(fmode, (uid_t)0, (gid_t)0, ap->a_mode, ap->a_cred)); } @@ -489,6 +580,7 @@ kernfs_getattr(v) int error = 0; char strbuf[KSTRING], *buf; + bzero((caddr_t) vap, sizeof(*vap)); vattr_null(vap); vap->va_uid = 0; @@ -507,7 +599,8 @@ kernfs_getattr(v) if (vp->v_flag & VROOT) { #ifdef KERNFS_DIAGNOSTIC - printf("kernfs_getattr: stat rootdir\n"); + struct kern_target *kt = VTOKERN(vp)->kf_kt; + printf("kernfs_getattr: stat rootdir (%s)\n", kt->kt_name); #endif vap->va_type = VDIR; vap->va_mode = DIR_MODE; @@ -622,6 +715,10 @@ kernfs_write(v) kt = VTOKERN(vp)->kf_kt; +#ifdef KERNFS_DIAGNOSTIC + printf("kernfs_write %s\n", kt->kt_name); +#endif + if (uio->uio_offset != 0) return (EINVAL); @@ -703,16 +800,14 @@ kernfs_inactive(v) struct proc *a_p; } */ *ap = v; struct vnode *vp = ap->a_vp; - #ifdef KERNFS_DIAGNOSTIC - printf("kernfs_inactive(%p)\n", vp); + struct kernfs_node *kf; + + kf = VTOKERN(vp); + + printf("kernfs_inactive(%p) %s\n", vp, kf->kf_name); #endif - /* - * Clear out the v_type field to avoid - * nasty things happening in vgone(). - */ VOP_UNLOCK(vp, 0, ap->a_p); - vp->v_type = VNON; return (0); } @@ -724,15 +819,15 @@ kernfs_reclaim(v) struct vnode *a_vp; } */ *ap = v; struct vnode *vp = ap->a_vp; - + struct proc *p = curproc; #ifdef KERNFS_DIAGNOSTIC - printf("kernfs_reclaim(%p)\n", vp); + struct kernfs_node *kf; + + kf = VTOKERN(vp); + + printf("kernfs_reclaim(%p) %s\n", vp, kf->kf_name); #endif - if (vp->v_data) { - FREE(vp->v_data, M_TEMP); - vp->v_data = 0; - } - return (0); + return(kernfs_freevp(vp, p)); } /* @@ -774,15 +869,21 @@ kernfs_pathconf(v) } /* - * Print out the contents of a /dev/fd vnode. + * Print out some details of a kernfs vnode. */ /* ARGSUSED */ int kernfs_print(v) void *v; { + struct vop_print_args /* + struct vnode *a_vp; + } */ *ap = v; + struct kernfs_node *kf = VTOKERN(ap->a_vp); - printf("tag VT_KERNFS, kernfs vnode\n"); + printf("tag VT_KERNFS, kernfs vnode: name %s, vp %p, tag %d\n", + kf->kf_name, kf->kf_vnode, kf->kf_tag); + return (0); } @@ -791,7 +892,6 @@ int kernfs_vfree(v) void *v; { - return (0); } @@ -821,14 +921,14 @@ kernfs_symlink(v) struct vattr *a_vap; char *a_target; } */ *ap = v; - + VOP_ABORTOP(ap->a_dvp, ap->a_cnp); vput(ap->a_dvp); return (EROFS); } /* - * /dev/fd "should never get here" operation + * kernfs "should never get here" operation */ /*ARGSUSED*/ int |