summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthib <thib@openbsd.org>2008-04-08 14:46:45 +0000
committerthib <thib@openbsd.org>2008-04-08 14:46:45 +0000
commit43ba3c33f7056a6498869018ae580cca628c2ac2 (patch)
treea4d79c440b0ada362c82da1f9d5200d593270d90
parentSplit the cdev makro for bpftun into two seperate definitions. tun(4) and (diff)
downloadwireguard-openbsd-43ba3c33f7056a6498869018ae580cca628c2ac2.tar.xz
wireguard-openbsd-43ba3c33f7056a6498869018ae580cca628c2ac2.zip
bring cloning up too date; Munge it so it will work with atleast
oga@'s upcoming DRM changes and too some degree ratchov@'s audio work. It still works for bpf's though. Parts from ratchov@; fstat(1) parts from Pedro Martelletto; tested by many, ok'ed by a few; "get going with cloning" deraadt@
-rw-r--r--sys/kern/spec_vnops.c47
-rw-r--r--sys/kern/vfs_vnops.c14
-rw-r--r--sys/miscfs/specfs/spec_subr.c22
-rw-r--r--sys/miscfs/specfs/spec_vnops.c47
-rw-r--r--sys/miscfs/specfs/specdev.h9
-rw-r--r--sys/sys/specdev.h9
-rw-r--r--sys/sys/vnode.h5
-rw-r--r--usr.bin/fstat/fstat.c51
8 files changed, 167 insertions, 37 deletions
diff --git a/sys/kern/spec_vnops.c b/sys/kern/spec_vnops.c
index 97bfdf61f85..e5d3f2c86f0 100644
--- a/sys/kern/spec_vnops.c
+++ b/sys/kern/spec_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: spec_vnops.c,v 1.44 2007/12/27 13:59:12 thib Exp $ */
+/* $OpenBSD: spec_vnops.c,v 1.45 2008/04/08 14:46:45 thib Exp $ */
/* $NetBSD: spec_vnops.c,v 1.29 1996/04/22 01:42:38 christos Exp $ */
/*
@@ -529,6 +529,8 @@ spec_close(void *v)
vrele(vp);
ap->a_p->p_session->s_ttyvp = NULL;
}
+ if (cdevsw[major(dev)].d_flags & D_CLONE)
+ return (spec_close_clone(ap));
/*
* If the vnode is locked, then we are in the midst
* of forcably closing the device, otherwise we only
@@ -536,8 +538,6 @@ spec_close(void *v)
*/
if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
return (0);
- if (cdevsw[major(dev)].d_flags & D_CLONE)
- return (spec_close_clone(ap));
devclose = cdevsw[major(dev)].d_close;
mode = S_IFCHR;
break;
@@ -579,6 +579,47 @@ spec_close(void *v)
return ((*devclose)(dev, ap->a_fflag, mode, ap->a_p));
}
+int
+spec_getattr(void *v)
+{
+ struct vop_getattr_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+
+ if (!(vp->v_flag & VCLONE))
+ return (EBADF);
+
+ return (VOP_GETATTR(vp->v_specparent, ap->a_vap, ap->a_cred, ap->a_p));
+}
+
+int
+spec_setattr(void *v)
+{
+ struct vop_getattr_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ int error;
+
+ if (!(vp->v_flag & VCLONE))
+ return (EBADF);
+
+ vn_lock(vp->v_specparent, LK_EXCLUSIVE|LK_RETRY, ap->a_p);
+ error = VOP_SETATTR(vp->v_specparent, ap->a_vap, ap->a_cred, ap->a_p);
+ VOP_UNLOCK(vp, 0, ap->a_p);
+
+ return (error);
+}
+
+int
+spec_access(void *v)
+{
+ struct vop_access_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+
+ if (!(vp->v_flag & VCLONE))
+ return (EBADF);
+
+ return (VOP_ACCESS(vp->v_specparent, ap->a_mode, ap->a_cred, ap->a_p));
+}
+
/*
* Print out the contents of a special device vnode.
*/
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index ab92846c193..f7782056ea7 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_vnops.c,v 1.58 2007/06/14 20:36:34 otto Exp $ */
+/* $OpenBSD: vfs_vnops.c,v 1.59 2008/04/08 14:46:45 thib Exp $ */
/* $NetBSD: vfs_vnops.c,v 1.20 1996/02/04 02:18:41 christos Exp $ */
/*
@@ -77,6 +77,7 @@ vn_open(struct nameidata *ndp, int fmode, int cmode)
struct proc *p = ndp->ni_cnd.cn_proc;
struct ucred *cred = p->p_ucred;
struct vattr va;
+ struct cloneinfo *cip;
int error;
if ((fmode & (FREAD|FWRITE)) == 0)
@@ -156,13 +157,14 @@ vn_open(struct nameidata *ndp, int fmode, int cmode)
goto bad;
if (vp->v_flag & VCLONED) {
- struct cloneinfo *cip = (struct cloneinfo *) vp->v_data;
+ cip = (struct cloneinfo *)vp->v_data;
vp->v_flag &= ~VCLONED;
- ndp->ni_vp = cip->ci_vp; /* return cloned vnode */
- vp->v_data = cip->ci_data; /* restore v_data */
- VOP_UNLOCK(vp, 0, p); /* keep a reference */
- vp = ndp->ni_vp; /* for the increment below */
+
+ ndp->ni_vp = cip->ci_vp; /* return cloned vnode */
+ vp->v_data = cip->ci_data; /* restore v_data */
+ VOP_UNLOCK(vp, 0, p); /* keep a reference */
+ vp = ndp->ni_vp; /* for the increment below */
free(cip, M_TEMP);
}
diff --git a/sys/miscfs/specfs/spec_subr.c b/sys/miscfs/specfs/spec_subr.c
index 399aa02c7b1..2077afe0b35 100644
--- a/sys/miscfs/specfs/spec_subr.c
+++ b/sys/miscfs/specfs/spec_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: spec_subr.c,v 1.3 2007/12/09 20:54:01 jmc Exp $ */
+/* $OpenBSD: spec_subr.c,v 1.4 2008/04/08 14:46:45 thib Exp $ */
/*
* Copyright (c) 2006 Pedro Martelletto <pedro@ambientworks.net>
@@ -25,6 +25,12 @@
#include <miscfs/specfs/specdev.h>
+#ifdef CLONE_DEBUG
+#define DNPRINTF(m...) do { printf(m); } while (0)
+#else
+#define DNPRINTF(m...) /* nothing */
+#endif
+
int
spec_open_clone(struct vop_open_args *ap)
{
@@ -32,6 +38,8 @@ spec_open_clone(struct vop_open_args *ap)
struct cloneinfo *cip;
int error, i;
+ DNPRINTF("cloning vnode\n");
+
for (i = 1; i < sizeof(vp->v_specbitmap) * NBBY; i++)
if (isclr(vp->v_specbitmap, i)) {
setbit(vp->v_specbitmap, i);
@@ -41,9 +49,6 @@ spec_open_clone(struct vop_open_args *ap)
if (i == sizeof(vp->v_specbitmap) * NBBY)
return (EBUSY); /* too many open instances */
- printf("spec_open_clone(): cloning device (%d, %d) for pid %u\n",
- major(vp->v_rdev), minor(vp->v_rdev), curproc->p_pid);
-
error = cdevvp(makedev(major(vp->v_rdev), i), &cvp);
if (error)
return (error); /* out of vnodes */
@@ -60,6 +65,8 @@ spec_open_clone(struct vop_open_args *ap)
return (error); /* device open failed */
}
+ cvp->v_flag |= VCLONE;
+
cip = malloc(sizeof(struct cloneinfo), M_TEMP, M_WAITOK);
cip->ci_data = vp->v_data;
cip->ci_vp = cvp;
@@ -68,8 +75,7 @@ spec_open_clone(struct vop_open_args *ap)
vp->v_flag |= VCLONED;
vp->v_data = cip;
- printf("spec_open_clone(): new minor for cloned device is %d\n",
- minor(cvp->v_rdev));
+ DNPRINTF("clone of vnode %p is vnode %p\n", vp, cvp);
return (0); /* device cloned */
}
@@ -87,9 +93,7 @@ spec_close_clone(struct vop_close_args *ap)
pvp = vp->v_specparent; /* get parent device */
clrbit(pvp->v_specbitmap, minor(vp->v_rdev));
-
- printf("spec_close_clone(): freeing minor %d of dev %d for"
- " pid %u\n", minor(vp->v_rdev), major(vp->v_rdev), curproc->p_pid);
+ vrele(pvp);
return (0); /* clone closed */
}
diff --git a/sys/miscfs/specfs/spec_vnops.c b/sys/miscfs/specfs/spec_vnops.c
index 97bfdf61f85..e5d3f2c86f0 100644
--- a/sys/miscfs/specfs/spec_vnops.c
+++ b/sys/miscfs/specfs/spec_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: spec_vnops.c,v 1.44 2007/12/27 13:59:12 thib Exp $ */
+/* $OpenBSD: spec_vnops.c,v 1.45 2008/04/08 14:46:45 thib Exp $ */
/* $NetBSD: spec_vnops.c,v 1.29 1996/04/22 01:42:38 christos Exp $ */
/*
@@ -529,6 +529,8 @@ spec_close(void *v)
vrele(vp);
ap->a_p->p_session->s_ttyvp = NULL;
}
+ if (cdevsw[major(dev)].d_flags & D_CLONE)
+ return (spec_close_clone(ap));
/*
* If the vnode is locked, then we are in the midst
* of forcably closing the device, otherwise we only
@@ -536,8 +538,6 @@ spec_close(void *v)
*/
if (vcount(vp) > 1 && (vp->v_flag & VXLOCK) == 0)
return (0);
- if (cdevsw[major(dev)].d_flags & D_CLONE)
- return (spec_close_clone(ap));
devclose = cdevsw[major(dev)].d_close;
mode = S_IFCHR;
break;
@@ -579,6 +579,47 @@ spec_close(void *v)
return ((*devclose)(dev, ap->a_fflag, mode, ap->a_p));
}
+int
+spec_getattr(void *v)
+{
+ struct vop_getattr_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+
+ if (!(vp->v_flag & VCLONE))
+ return (EBADF);
+
+ return (VOP_GETATTR(vp->v_specparent, ap->a_vap, ap->a_cred, ap->a_p));
+}
+
+int
+spec_setattr(void *v)
+{
+ struct vop_getattr_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+ int error;
+
+ if (!(vp->v_flag & VCLONE))
+ return (EBADF);
+
+ vn_lock(vp->v_specparent, LK_EXCLUSIVE|LK_RETRY, ap->a_p);
+ error = VOP_SETATTR(vp->v_specparent, ap->a_vap, ap->a_cred, ap->a_p);
+ VOP_UNLOCK(vp, 0, ap->a_p);
+
+ return (error);
+}
+
+int
+spec_access(void *v)
+{
+ struct vop_access_args *ap = v;
+ struct vnode *vp = ap->a_vp;
+
+ if (!(vp->v_flag & VCLONE))
+ return (EBADF);
+
+ return (VOP_ACCESS(vp->v_specparent, ap->a_mode, ap->a_cred, ap->a_p));
+}
+
/*
* Print out the contents of a special device vnode.
*/
diff --git a/sys/miscfs/specfs/specdev.h b/sys/miscfs/specfs/specdev.h
index fc40a7e2805..98eb73cfe8d 100644
--- a/sys/miscfs/specfs/specdev.h
+++ b/sys/miscfs/specfs/specdev.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: specdev.h,v 1.21 2007/12/27 13:59:12 thib Exp $ */
+/* $OpenBSD: specdev.h,v 1.22 2008/04/08 14:46:45 thib Exp $ */
/* $NetBSD: specdev.h,v 1.12 1996/02/13 13:13:01 mycroft Exp $ */
/*
@@ -91,14 +91,13 @@ struct uio;
int spec_badop(void *);
int spec_ebadf(void *);
-
+int spec_getattr(void *);
+int spec_setattr(void *);
+int spec_access(void *);
#define spec_create spec_badop
#define spec_mknod spec_badop
int spec_open(void *);
int spec_close(void *);
-#define spec_access spec_ebadf
-#define spec_getattr spec_ebadf
-#define spec_setattr spec_ebadf
int spec_read(void *);
int spec_write(void *);
int spec_ioctl(void *);
diff --git a/sys/sys/specdev.h b/sys/sys/specdev.h
index fc40a7e2805..98eb73cfe8d 100644
--- a/sys/sys/specdev.h
+++ b/sys/sys/specdev.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: specdev.h,v 1.21 2007/12/27 13:59:12 thib Exp $ */
+/* $OpenBSD: specdev.h,v 1.22 2008/04/08 14:46:45 thib Exp $ */
/* $NetBSD: specdev.h,v 1.12 1996/02/13 13:13:01 mycroft Exp $ */
/*
@@ -91,14 +91,13 @@ struct uio;
int spec_badop(void *);
int spec_ebadf(void *);
-
+int spec_getattr(void *);
+int spec_setattr(void *);
+int spec_access(void *);
#define spec_create spec_badop
#define spec_mknod spec_badop
int spec_open(void *);
int spec_close(void *);
-#define spec_access spec_ebadf
-#define spec_getattr spec_ebadf
-#define spec_setattr spec_ebadf
int spec_read(void *);
int spec_write(void *);
int spec_ioctl(void *);
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 85855330a33..ba8404b1c6d 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: vnode.h,v 1.91 2008/03/16 19:42:57 otto Exp $ */
+/* $OpenBSD: vnode.h,v 1.92 2008/04/08 14:46:45 thib Exp $ */
/* $NetBSD: vnode.h,v 1.38 1996/02/29 20:59:05 cgd Exp $ */
/*
@@ -126,8 +126,9 @@ struct vnode {
#define VCLONED 0x0400 /* vnode was cloned */
#define VALIASED 0x0800 /* vnode has an alias */
#define VLOCKSWORK 0x4000 /* FS supports locking discipline */
+#define VCLONE 0x8000 /* vnode is a clone */
#define VBITS "\010\001ROOT\002TEXT\003SYSTEM\004ISTTY\010XLOCK" \
- "\011XWANT\013ALIASED\016LOCKSWORK"
+ "\011XWANT\013ALIASED\016LOCKSWORK\017CLONE"
/*
* (v_bioflag) Flags that may be manipulated by interrupt handlers
diff --git a/usr.bin/fstat/fstat.c b/usr.bin/fstat/fstat.c
index a7800f39853..c5b1f7c881c 100644
--- a/usr.bin/fstat/fstat.c
+++ b/usr.bin/fstat/fstat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fstat.c,v 1.60 2007/10/01 22:06:02 sobrado Exp $ */
+/* $OpenBSD: fstat.c,v 1.61 2008/04/08 14:46:45 thib Exp $ */
/*-
* Copyright (c) 1988, 1993
@@ -37,7 +37,7 @@ static char copyright[] =
#ifndef lint
/*static char sccsid[] = "from: @(#)fstat.c 8.1 (Berkeley) 6/6/93";*/
-static char *rcsid = "$OpenBSD: fstat.c,v 1.60 2007/10/01 22:06:02 sobrado Exp $";
+static char *rcsid = "$OpenBSD: fstat.c,v 1.61 2008/04/08 14:46:45 thib Exp $";
#endif /* not lint */
#include <sys/param.h>
@@ -73,6 +73,8 @@ static char *rcsid = "$OpenBSD: fstat.c,v 1.60 2007/10/01 22:06:02 sobrado Exp $
#include <xfs/xfs_config.h>
#include <xfs/xfs_node.h>
+#include <miscfs/specfs/specdev.h>
+
#include <net/route.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
@@ -151,6 +153,7 @@ int isofs_filestat(struct vnode *, struct filestat *);
int msdos_filestat(struct vnode *, struct filestat *);
int nfs_filestat(struct vnode *, struct filestat *);
int xfs_filestat(struct vnode *, struct filestat *);
+int spec_filestat(struct vnode *, struct filestat *);
void dofiles(struct kinfo_proc2 *);
void getinetproto(int);
void usage(void);
@@ -416,7 +419,7 @@ vtrans(struct vnode *vp, int i, int flag, struct file *fp)
dprintf("can't read vnode at %p for pid %ld", vp, (long)Pid);
return;
}
- if (vn.v_type == VNON || vn.v_tag == VT_NON)
+ if (vn.v_type == VNON)
badtype = "none";
else if (vn.v_type == VBAD)
badtype = "bad";
@@ -447,6 +450,14 @@ vtrans(struct vnode *vp, int i, int flag, struct file *fp)
if (!xfs_filestat(&vn, &fst))
badtype = "error";
break;
+ case VT_NON:
+ if (vn.v_flag & VCLONE) {
+ if (!spec_filestat(&vn, &fst))
+ badtype = "error";
+ } else {
+ badtype = "none"; /* not a clone */
+ }
+ break;
default: {
static char unknown[30];
snprintf(badtype = unknown, sizeof unknown,
@@ -476,11 +487,14 @@ vtrans(struct vnode *vp, int i, int flag, struct file *fp)
(void)printf(" - - %10s -\n", badtype);
return;
}
+
if (nflg)
(void)printf(" %2ld,%-2ld", (long)major(fst.fsid),
(long)minor(fst.fsid));
- else
+ else if (!(vn.v_flag & VCLONE))
(void)printf(" %-8s", getmnton(vn.v_mount));
+ else
+ (void)printf(" clone");
if (nflg)
(void)snprintf(mode, sizeof mode, "%o", fst.mode);
else
@@ -664,6 +678,35 @@ xfs_filestat(struct vnode *vp, struct filestat *fsp)
return 1;
}
+int
+spec_filestat(struct vnode *vp, struct filestat *fsp)
+{
+ struct specinfo specinfo;
+ struct vnode parent;
+
+ if (!KVM_READ(vp->v_specinfo, &specinfo, sizeof(struct specinfo))) {
+ dprintf("can't read specinfo at %p for pid %ld",
+ vp->v_specinfo, (long) Pid);
+ return (0);
+ }
+
+ vp->v_specinfo = &specinfo;
+
+ if (!KVM_READ(vp->v_specparent, &parent, sizeof(struct vnode))) {
+ dprintf("can't read parent vnode at %p for pid %ld",
+ vp->v_specparent, (long) Pid);
+ return (0);
+ }
+
+ if (!ufs_filestat(&parent, fsp))
+ return (0);
+
+ if (nflg)
+ fsp->rdev = vp->v_rdev;
+
+ return (1);
+}
+
char *
getmnton(struct mount *m)
{