From b8477cda8783596a7c765667658de9a94dd368fd Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Thu, 2 Apr 2009 23:38:31 -0700 Subject: [PATCH] Revoke reimplementation - primary commit part 1/2. Rip out and replace the old revoke code. The old code basically ripped vnodes out from under the related VFSs, faked close operations, hacked up ref counts, and generally wreaked havoc on the system. The new code is not as efficient, but plays a lot nicer with the kernel. It locates and closes matching file descriptors (replacing the descriptor with a dummy that just returns an error). No ref count hacks are needed and vnodes are no longer unceremoniously canned. The new revoke code is also capable of revoking any vnode in the system, device or file. root, jail root, and chrooted directories cannot be revoked. This also fixes an issue with HAMMER getting confused when one of its vnodes got ripped out from under it by the old revoke. --- sys/kern/kern_descrip.c | 120 +++++++++++++++++++++++++++++------- sys/kern/tty.c | 4 +- sys/kern/uipc_usrreq.c | 13 ++-- sys/kern/vfs_default.c | 1 - sys/kern/vfs_subr.c | 36 ++++------- sys/kern/vfs_syscalls.c | 12 ++-- sys/kern/vfs_vopops.c | 25 -------- sys/sys/file.h | 2 +- sys/sys/filedesc.h | 3 +- sys/sys/vfsops.h | 14 +---- sys/sys/vnode.h | 3 +- sys/vfs/specfs/spec_vnops.c | 28 ++++----- sys/vfs/union/union_vnops.c | 25 -------- 13 files changed, 141 insertions(+), 145 deletions(-) diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index cebd09b074..f5a970301f 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -596,7 +596,7 @@ retry: * close() were performed on it). */ if (delfp) { - (void)closef(delfp, td); + closef(delfp, p); if (holdleaders) { spin_lock_wr(&fdp->fd_spin); fdp->fd_holdleaderscount--; @@ -830,7 +830,7 @@ kern_close(int fd) knote_fdclose(p, fd); rel_mplock(); } - error = closef(fp, td); + error = closef(fp, p); if (holdleaders) { spin_lock_wr(&fdp->fd_spin); fdp->fd_holdleaderscount--; @@ -1179,6 +1179,98 @@ fdavail(struct proc *p, int n) return (0); } +/* + * Revoke open descriptors referencing (f_data, f_type) + * + * Any revoke executed within a prison is only able to + * revoke descriptors for processes within that prison. + * + * Returns 0 on success or an error code. + */ +struct fdrevoke_info { + void *data; + short type; + short unused; + int count; + int again; + struct ucred *cred; + struct file *nfp; +}; + +static int fdrevoke_callback(struct proc *p, void *vinfo); + +int +fdrevoke(void *f_data, short f_type, struct ucred *cred) +{ + struct fdrevoke_info info; + int error; + + bzero(&info, sizeof(info)); + info.data = f_data; + info.type = f_type; + info.cred = cred; + error = falloc(NULL, &info.nfp, NULL); + if (error) + return (error); + do { + info.again = 0; + allproc_scan(fdrevoke_callback, &info); + } while (info.again != 0); + fdrop(info.nfp); + return(info.count); +} + +static int +fdrevoke_callback(struct proc *p, void *vinfo) +{ + struct fdrevoke_info *info = vinfo; + struct filedesc *fdp; + struct file *fp; + int n; + + if (p->p_stat == SIDL || p->p_stat == SZOMB) + return(0); + if (info->cred->cr_prison && + info->cred->cr_prison != p->p_ucred->cr_prison) { + return(0); + } + + /* + * If the controlling terminal of the process matches the + * vnode being revoked we clear the controlling terminal. + * + * The normal spec_close() may not catch this because it + * uses curproc instead of p. + */ + if (p->p_session && info->type == DTYPE_VNODE && + info->data == p->p_session->s_ttyvp) { + p->p_session->s_ttyvp = NULL; + vrele(info->data); + } + + /* + * Locate and close any matching file descriptors. + */ + if ((fdp = p->p_fd) == NULL) + return(0); + spin_lock_wr(&fdp->fd_spin); + for (n = 0; n < fdp->fd_nfiles; ++n) { + if ((fp = fdp->fd_files[n].fp) == NULL) + continue; + if (info->data == fp->f_data && info->type == fp->f_type) { + fhold(info->nfp); + fdp->fd_files[n].fp = info->nfp; + spin_unlock_wr(&fdp->fd_spin); + closef(fp, p); + spin_lock_wr(&fdp->fd_spin); + ++info->count; + info->again = 1; + } + } + spin_unlock_wr(&fdp->fd_spin); + return(0); +} + /* * falloc: * Create a new open file structure and reserve a file decriptor @@ -1630,8 +1722,6 @@ again: void fdfree(struct proc *p) { - /* Take any thread of p */ - struct thread *td = FIRST_LWP_IN_PROC(p)->lwp_thread; struct filedesc *fdp = p->p_fd; struct fdnode *fdnode; int i; @@ -1731,7 +1821,7 @@ fdfree(struct proc *p) */ for (i = 0; i <= fdp->fd_lastfile; ++i) { if (fdp->fd_files[i].fp) - closef(fdp->fd_files[i].fp, td); + closef(fdp->fd_files[i].fp, p); } if (fdp->fd_files != fdp->fd_builtin_files) kfree(fdp->fd_files, M_FILEDESC); @@ -1879,8 +1969,6 @@ is_unsafe(struct file *fp) void setugidsafety(struct proc *p) { - /* Take any thread of p */ - struct thread *td = FIRST_LWP_IN_PROC(p)->lwp_thread; struct filedesc *fdp = p->p_fd; int i; @@ -1905,7 +1993,7 @@ setugidsafety(struct proc *p) * a race while close blocks. */ if ((fp = funsetfd_locked(fdp, i)) != NULL) - closef(fp, td); + closef(fp, p); } } } @@ -1918,8 +2006,6 @@ setugidsafety(struct proc *p) void fdcloseexec(struct proc *p) { - /* Take any thread of p */ - struct thread *td = FIRST_LWP_IN_PROC(p)->lwp_thread; struct filedesc *fdp = p->p_fd; int i; @@ -1943,7 +2029,7 @@ fdcloseexec(struct proc *p) * a race while close blocks. */ if ((fp = funsetfd_locked(fdp, i)) != NULL) - closef(fp, td); + closef(fp, p); } } } @@ -2010,21 +2096,15 @@ fdcheckstd(struct proc *p) * MPALMOSTSAFE - acquires mplock for VOP operations */ int -closef(struct file *fp, struct thread *td) +closef(struct file *fp, struct proc *p) { struct vnode *vp; struct flock lf; struct filedesc_to_leader *fdtol; - struct proc *p; if (fp == NULL) return (0); - if (td == NULL) { - td = curthread; - p = NULL; /* allow no proc association */ - } else { - p = td->td_proc; /* can also be NULL */ - } + /* * POSIX record locking dictates that any close releases ALL * locks owned by this process. This is handled by setting @@ -2323,9 +2403,7 @@ allfiles_scan_exclusive(int (*callback)(struct file *, void *), void *data) spin_lock_wr(&filehead_spin); LIST_FOREACH(fp, &filehead, f_list) { - spin_lock_wr(&fp->f_spin); res = callback(fp, data); - spin_unlock_wr(&fp->f_spin); if (res < 0) break; } diff --git a/sys/kern/tty.c b/sys/kern/tty.c index c252227c11..bcf94b616a 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -341,9 +341,9 @@ retry: vclrflags(vp, VCTTYISOPEN); VOP_CLOSE(vp, FREAD|FWRITE); } - if (dorevoke) - VOP_REVOKE(vp, REVOKEALL); vn_unlock(vp); + if (dorevoke) + vrevoke(vp, proc0.p_ucred); vdrop(vp); } else { sp->s_ttyvp = NULL; diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index c12e78a49a..f30f340d39 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1265,7 +1265,7 @@ unp_gc_checkrefs(struct file *fp, void *data) static int unp_gc_clearmarks(struct file *fp, void *data __unused) { - fp->f_flag &= ~(FMARK|FDEFER); + atomic_clear_int(&fp->f_flag, FMARK | FDEFER); return(0); } @@ -1289,7 +1289,7 @@ unp_gc_checkmarks(struct file *fp, void *data) * and un-mark it */ if (fp->f_flag & FDEFER) { - fp->f_flag &= ~FDEFER; + atomic_clear_int(&fp->f_flag, FDEFER); --info->defer; } else { /* @@ -1309,7 +1309,7 @@ unp_gc_checkmarks(struct file *fp, void *data) * If it got this far then it must be * externally accessible. */ - fp->f_flag |= FMARK; + atomic_set_int(&fp->f_flag, FMARK); } /* * either it was defered, or it is externally @@ -1323,7 +1323,6 @@ unp_gc_checkmarks(struct file *fp, void *data) !(so->so_proto->pr_flags & PR_RIGHTS)) return(0); #ifdef notdef - XXX note: exclusive fp->f_spin lock held if (so->so_rcv.sb_flags & SB_LOCK) { /* * This is problematical; it's not clear @@ -1406,14 +1405,10 @@ unp_mark(struct file *fp, void *data) { struct unp_gc_info *info = data; - if (info->locked_fp != fp) - spin_lock_wr(&fp->f_spin); if ((fp->f_flag & FMARK) == 0) { ++info->defer; - fp->f_flag |= (FMARK|FDEFER); + atomic_set_int(&fp->f_flag, FMARK | FDEFER); } - if (info->locked_fp != fp) - spin_unlock_wr(&fp->f_spin); } static void diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c index fe3c03325f..70ccdb54ce 100644 --- a/sys/kern/vfs_default.c +++ b/sys/kern/vfs_default.c @@ -88,7 +88,6 @@ struct vop_ops default_vnode_vops = { .vop_poll = vop_nopoll, .vop_readlink = (void *)vop_einval, .vop_reallocblks = (void *)vop_eopnotsupp, - .vop_revoke = vop_stdrevoke, .vop_strategy = vop_nostrategy, .vop_getacl = (void *)vop_eopnotsupp, .vop_setacl = (void *)vop_eopnotsupp, diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 9a4c0398e6..5c31d014a2 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -1200,26 +1201,15 @@ vclean_vxlocked(struct vnode *vp, int flags) * Eliminate all activity associated with the requested vnode * and with all vnodes aliased to the requested vnode. * - * The vnode must be referenced and vx_lock()'d - * - * revoke { struct vnode *a_vp, int a_flags } + * The vnode must be referenced but should not be locked. */ int -vop_stdrevoke(struct vop_revoke_args *ap) +vrevoke(struct vnode *vp, struct ucred *cred) { - struct vnode *vp, *vq; + struct vnode *vq; lwkt_tokref ilock; cdev_t dev; - - KASSERT((ap->a_flags & REVOKEALL) != 0, ("vop_revoke")); - - vp = ap->a_vp; - - /* - * If the vnode is already dead don't try to revoke it - */ - if (vp->v_flag & VRECLAIMED) - return (0); + int error; /* * If the vnode has a device association, scrap all vnodes associated @@ -1229,8 +1219,10 @@ vop_stdrevoke(struct vop_revoke_args *ap) * The passed vp will probably show up in the list, do not VX lock * it twice! */ - if (vp->v_type != VCHR) - return(0); + if (vp->v_type != VCHR) { + error = fdrevoke(vp, DTYPE_VNODE, cred); + return (error); + } if ((dev = vp->v_rdev) == NULL) { if ((dev = get_dev(vp->v_umajor, vp->v_uminor)) == NULL) return(0); @@ -1238,12 +1230,10 @@ vop_stdrevoke(struct vop_revoke_args *ap) reference_dev(dev); lwkt_gettoken(&ilock, &spechash_token); while ((vq = SLIST_FIRST(&dev->si_hlist)) != NULL) { - if (vp != vq) - vx_get(vq); - if (vq == SLIST_FIRST(&dev->si_hlist)) - vgone_vxlocked(vq); - if (vp != vq) - vx_put(vq); + vref(vq); + fdrevoke(vq, DTYPE_VNODE, cred); + v_release_rdev(vq); + vrele(vq); } lwkt_reltoken(&ilock); release_dev(dev); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index b5888cf428..461e20e9b3 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -3565,17 +3565,15 @@ sys_revoke(struct revoke_args *uap) cred = crhold(nd.nl_cred); nlookup_done(&nd); if (error == 0) { - if (vp->v_type != VCHR && vp->v_type != VBLK) - error = EINVAL; if (error == 0) error = VOP_GETATTR(vp, &vattr); if (error == 0 && cred->cr_uid != vattr.va_uid) error = priv_check_cred(cred, PRIV_ROOT, PRISON_ROOT); - if (error == 0 && count_udev(vp->v_umajor, vp->v_uminor) > 0) { - error = 0; - vx_lock(vp); - VOP_REVOKE(vp, REVOKEALL); - vx_unlock(vp); + if (error == 0 && (vp->v_type == VCHR || vp->v_type == VBLK)) { + if (count_udev(vp->v_umajor, vp->v_uminor) > 0) + error = vrevoke(vp, cred); + } else if (error == 0) { + error = vrevoke(vp, cred); } vrele(vp); } diff --git a/sys/kern/vfs_vopops.c b/sys/kern/vfs_vopops.c index 89ce089418..ec92b3e4a5 100644 --- a/sys/kern/vfs_vopops.c +++ b/sys/kern/vfs_vopops.c @@ -97,7 +97,6 @@ VNODEOP_DESC_INIT(write); VNODEOP_DESC_INIT(ioctl); VNODEOP_DESC_INIT(poll); VNODEOP_DESC_INIT(kqfilter); -VNODEOP_DESC_INIT(revoke); VNODEOP_DESC_INIT(mmap); VNODEOP_DESC_INIT(fsync); VNODEOP_DESC_INIT(old_remove); @@ -405,21 +404,6 @@ vop_kqfilter(struct vop_ops *ops, struct vnode *vp, struct knote *kn) return(error); } -int -vop_revoke(struct vop_ops *ops, struct vnode *vp, int flags) -{ - struct vop_revoke_args ap; - int error; - - ap.a_head.a_desc = &vop_revoke_desc; - ap.a_head.a_ops = ops; - ap.a_vp = vp; - ap.a_flags = flags; - - DO_OPS(ops, error, &ap, vop_revoke); - return(error); -} - int vop_mmap(struct vop_ops *ops, struct vnode *vp, int fflags, struct ucred *cred) { @@ -1414,15 +1398,6 @@ vop_kqfilter_ap(struct vop_kqfilter_args *ap) return(error); } -int -vop_revoke_ap(struct vop_revoke_args *ap) -{ - int error; - - DO_OPS(ap->a_head.a_ops, error, ap, vop_revoke); - return(error); -} - int vop_mmap_ap(struct vop_mmap_args *ap) { diff --git a/sys/sys/file.h b/sys/sys/file.h index 646fcc232a..cd5e7dd96d 100644 --- a/sys/sys/file.h +++ b/sys/sys/file.h @@ -118,7 +118,7 @@ struct file { int f_count; /* reference count */ int f_msgcount; /* (U) reference count from message queue */ struct nchandle f_nchandle; /* namecache reference */ - struct spinlock f_spin; + struct spinlock f_spin; /* NOT USED */ }; #define DTYPE_VNODE 1 /* file */ diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h index d57e9d8791..c3deef5f3d 100644 --- a/sys/sys/filedesc.h +++ b/sys/sys/filedesc.h @@ -170,7 +170,8 @@ struct filedesc *fdinit (struct proc *p); struct filedesc *fdshare (struct proc *p); struct filedesc *fdcopy (struct proc *p); void fdfree (struct proc *p); -int closef (struct file *fp, struct thread *td); +int fdrevoke(void *f_data, short f_type, struct ucred *cred); +int closef (struct file *fp, struct proc *p); void fdcloseexec (struct proc *p); int fdcheckstd (struct proc *p); struct file *holdfp (struct filedesc *fdp, int fd, int flag); diff --git a/sys/sys/vfsops.h b/sys/sys/vfsops.h index b2ae193213..6d80f34c42 100644 --- a/sys/sys/vfsops.h +++ b/sys/sys/vfsops.h @@ -193,12 +193,6 @@ struct vop_kqfilter_args { struct knote *a_kn; }; -struct vop_revoke_args { - struct vop_generic_args a_head; - struct vnode *a_vp; - int a_flags; -}; - struct vop_mmap_args { struct vop_generic_args a_head; struct vnode *a_vp; @@ -593,7 +587,7 @@ struct vop_ops { int (*vop_ioctl)(struct vop_ioctl_args *); int (*vop_poll)(struct vop_poll_args *); int (*vop_kqfilter)(struct vop_kqfilter_args *); - int (*vop_revoke)(struct vop_revoke_args *); + int (*vop_unused01)(void *); /* was vop_revoke */ int (*vop_mmap)(struct vop_mmap_args *); int (*vop_fsync)(struct vop_fsync_args *); int (*vop_old_remove)(struct vop_old_remove_args *); @@ -672,7 +666,6 @@ union vop_args_union { struct vop_ioctl_args vu_ioctl; struct vop_poll_args vu_poll; struct vop_kqfilter_args vu_kqfilter; - struct vop_revoke_args vu_revoke; struct vop_mmap_args vu_mmap; struct vop_fsync_args vu_fsync; struct vop_old_remove_args vu_remove; @@ -753,7 +746,6 @@ int vop_ioctl(struct vop_ops *ops, struct vnode *vp, u_long command, int vop_poll(struct vop_ops *ops, struct vnode *vp, int events, struct ucred *cred); int vop_kqfilter(struct vop_ops *ops, struct vnode *vp, struct knote *kn); -int vop_revoke(struct vop_ops *ops, struct vnode *vp, int flags); int vop_mmap(struct vop_ops *ops, struct vnode *vp, int fflags, struct ucred *cred); int vop_fsync(struct vop_ops *ops, struct vnode *vp, int waitfor); @@ -864,7 +856,6 @@ int vop_write_ap(struct vop_write_args *ap); int vop_ioctl_ap(struct vop_ioctl_args *ap); int vop_poll_ap(struct vop_poll_args *ap); int vop_kqfilter_ap(struct vop_kqfilter_args *ap); -int vop_revoke_ap(struct vop_revoke_args *ap); int vop_mmap_ap(struct vop_mmap_args *ap); int vop_fsync_ap(struct vop_fsync_args *ap); int vop_old_remove_ap(struct vop_old_remove_args *ap); @@ -927,7 +918,6 @@ extern struct syslink_desc vop_write_desc; extern struct syslink_desc vop_ioctl_desc; extern struct syslink_desc vop_poll_desc; extern struct syslink_desc vop_kqfilter_desc; -extern struct syslink_desc vop_revoke_desc; extern struct syslink_desc vop_mmap_desc; extern struct syslink_desc vop_fsync_desc; extern struct syslink_desc vop_old_remove_desc; @@ -996,8 +986,6 @@ extern struct syslink_desc vop_nrename_desc; vop_poll(*(vp)->v_ops, vp, events, cred) #define VOP_KQFILTER(vp, kn) \ vop_kqfilter(*(vp)->v_ops, vp, kn) -#define VOP_REVOKE(vp, flags) \ - vop_revoke(*(vp)->v_ops, vp, flags) #define VOP_MMAP(vp, fflags, cred) \ vop_mmap(*(vp)->v_ops, vp, fflags, cred) #define VOP_FSYNC(vp, waitfor) \ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index d12a0429a8..dab955e96f 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -359,7 +359,6 @@ extern int vttoif_tab[]; #define WRITECLOSE 0x0004 /* vflush: only close writable files */ #define DOCLOSE 0x0008 /* vclean: close active files */ #define V_SAVE 0x0001 /* vinvalbuf: sync file first */ -#define REVOKEALL 0x0001 /* vop_revoke: revoke all aliases */ #ifdef DIAGNOSTIC #define VATTR_NULL(vap) vattr_null(vap) @@ -480,6 +479,7 @@ void vclean_vxlocked (struct vnode *vp, int flags); void vclean_unlocked (struct vnode *vp); void vgone_vxlocked (struct vnode *vp); void vupdatefsmid (struct vnode *vp); +int vrevoke (struct vnode *vp, struct ucred *cred); int vinvalbuf (struct vnode *vp, int save, int slpflag, int slptimeo); int vtruncbuf (struct vnode *vp, off_t length, int blksize); int vfsync(struct vnode *vp, int waitfor, int passes, @@ -529,7 +529,6 @@ int vop_stdmarkatime(struct vop_markatime_args *ap); int vop_nopoll (struct vop_poll_args *ap); int vop_stdpathconf (struct vop_pathconf_args *ap); int vop_stdpoll (struct vop_poll_args *ap); -int vop_stdrevoke (struct vop_revoke_args *ap); int vop_eopnotsupp (struct vop_generic_args *ap); int vop_ebadf (struct vop_generic_args *ap); int vop_einval (struct vop_generic_args *ap); diff --git a/sys/vfs/specfs/spec_vnops.c b/sys/vfs/specfs/spec_vnops.c index 97b5cf96a8..91fbbfdd28 100644 --- a/sys/vfs/specfs/spec_vnops.c +++ b/sys/vfs/specfs/spec_vnops.c @@ -688,7 +688,7 @@ spec_bmap(struct vop_bmap_args *ap) * * spec_close(struct vnode *a_vp, int a_fflag) * - * NOTE: the vnode may or may not be locked on call. + * NOTE: The vnode may or may not be locked on call. */ /* ARGSUSED */ static int @@ -701,37 +701,35 @@ spec_close(struct vop_close_args *ap) int needrelock; /* - * Hack: a tty device that is a controlling terminal - * has a reference from the session structure. - * We cannot easily tell that a character device is - * a controlling terminal, unless it is the closing - * process' controlling terminal. In that case, - * if the reference count is 2 (this last descriptor - * plus the session), release the reference from the session. + * A couple of hacks for devices and tty devices. The + * vnode ref count cannot be used to figure out the + * last close, but we can use v_opencount now that + * revoke works properly. * - * It is possible for v_opencount to be 0 or 1 in this case, 0 - * because the tty might have been revoked. + * Detect the last close on a controlling terminal and clear + * the session (half-close). */ if (dev) reference_dev(dev); - if (vcount(vp) == 2 && vp->v_opencount <= 1 && - p && vp == p->p_session->s_ttyvp) { + + if (p && vp->v_opencount <= 1 && vp == p->p_session->s_ttyvp) { p->p_session->s_ttyvp = NULL; vrele(vp); } /* - * Vnodes can be opened and close multiple times. Do not really + * Vnodes can be opened and closed multiple times. Do not really * close the device unless (1) it is being closed forcibly, * (2) the device wants to track closes, or (3) this is the last * vnode doing its last close on the device. * * XXX the VXLOCK (force close) case can leave vnodes referencing - * a closed device. + * a closed device. This might not occur now that our revoke is + * fixed. */ if (dev && ((vp->v_flag & VRECLAIMED) || (dev_dflags(dev) & D_TRACKCLOSE) || - (vcount(vp) <= 1 && vp->v_opencount == 1))) { + (vp->v_opencount == 1))) { needrelock = 0; if (vn_islocked(vp)) { needrelock = 1; diff --git a/sys/vfs/union/union_vnops.c b/sys/vfs/union/union_vnops.c index 60c7962b9f..ae6378cbda 100644 --- a/sys/vfs/union/union_vnops.c +++ b/sys/vfs/union/union_vnops.c @@ -94,7 +94,6 @@ static int union_readlink (struct vop_readlink_args *ap); static int union_reclaim (struct vop_reclaim_args *ap); static int union_remove (struct vop_old_remove_args *ap); static int union_rename (struct vop_old_rename_args *ap); -static int union_revoke (struct vop_revoke_args *ap); static int union_rmdir (struct vop_old_rmdir_args *ap); static int union_poll (struct vop_poll_args *ap); static int union_setattr (struct vop_setattr_args *ap); @@ -1142,29 +1141,6 @@ union_poll(struct vop_poll_args *ap) return(vop_poll_ap(ap)); } -/* - * union_revoke(struct vnode *a_vp, int a_flags, struct thread *a_td) - */ -static int -union_revoke(struct vop_revoke_args *ap) -{ - struct vnode *vp = ap->a_vp; - struct vnode *vx; - - if ((vx = UPPERVP(vp)) != NULL) { - vx_get(vx); - VOP_REVOKE(vx, ap->a_flags); - vx_put(vx); - } - if ((vx = LOWERVP(vp)) != NULL) { - vx_get(vx); - VOP_REVOKE(vx, ap->a_flags); - vx_put(vx); - } - vgone_vxlocked(vp); - return (0); -} - /* * union_mmap(struct vnode *a_vp, int a_fflags, struct ucred *a_cred, * struct thread *a_td) @@ -1804,7 +1780,6 @@ struct vop_ops union_vnode_vops = { .vop_reclaim = union_reclaim, .vop_old_remove = union_remove, .vop_old_rename = union_rename, - .vop_revoke = union_revoke, .vop_old_rmdir = union_rmdir, .vop_setattr = union_setattr, .vop_strategy = union_strategy, -- 2.41.0