diff options
| author | 2008-04-08 14:46:45 +0000 | |
|---|---|---|
| committer | 2008-04-08 14:46:45 +0000 | |
| commit | 43ba3c33f7056a6498869018ae580cca628c2ac2 (patch) | |
| tree | a4d79c440b0ada362c82da1f9d5200d593270d90 | |
| parent | Split the cdev makro for bpftun into two seperate definitions. tun(4) and (diff) | |
| download | wireguard-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.c | 47 | ||||
| -rw-r--r-- | sys/kern/vfs_vnops.c | 14 | ||||
| -rw-r--r-- | sys/miscfs/specfs/spec_subr.c | 22 | ||||
| -rw-r--r-- | sys/miscfs/specfs/spec_vnops.c | 47 | ||||
| -rw-r--r-- | sys/miscfs/specfs/specdev.h | 9 | ||||
| -rw-r--r-- | sys/sys/specdev.h | 9 | ||||
| -rw-r--r-- | sys/sys/vnode.h | 5 | ||||
| -rw-r--r-- | usr.bin/fstat/fstat.c | 51 |
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) { |
