summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorart <art@openbsd.org>2002-02-17 04:29:52 +0000
committerart <art@openbsd.org>2002-02-17 04:29:52 +0000
commit5dceb04625698df0cbfc9f80292dbf0fda5f3e01 (patch)
tree770a0b59b0deee3ca59dfcc24fcbf6eab4ee2f35
parentoops, add -U to usage (diff)
downloadwireguard-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.h21
-rw-r--r--sys/miscfs/kernfs/kernfs_vfsops.c76
-rw-r--r--sys/miscfs/kernfs/kernfs_vnops.c246
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