Home | History | Annotate | Line # | Download | only in genfs
genfs_vnops.c revision 1.201
      1  1.201        ad /*	$NetBSD: genfs_vnops.c,v 1.201 2020/02/23 15:46:41 ad Exp $	*/
      2  1.164        ad 
      3  1.164        ad /*-
      4  1.164        ad  * Copyright (c) 2008 The NetBSD Foundation, Inc.
      5  1.164        ad  * All rights reserved.
      6  1.164        ad  *
      7  1.164        ad  * Redistribution and use in source and binary forms, with or without
      8  1.164        ad  * modification, are permitted provided that the following conditions
      9  1.164        ad  * are met:
     10  1.164        ad  * 1. Redistributions of source code must retain the above copyright
     11  1.164        ad  *    notice, this list of conditions and the following disclaimer.
     12  1.164        ad  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.164        ad  *    notice, this list of conditions and the following disclaimer in the
     14  1.164        ad  *    documentation and/or other materials provided with the distribution.
     15  1.164        ad  *
     16  1.164        ad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  1.164        ad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  1.164        ad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  1.164        ad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  1.164        ad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  1.164        ad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  1.164        ad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  1.164        ad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  1.164        ad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  1.164        ad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  1.164        ad  * POSSIBILITY OF SUCH DAMAGE.
     27  1.164        ad  */
     28    1.6      fvdl 
     29    1.6      fvdl /*
     30    1.6      fvdl  * Copyright (c) 1982, 1986, 1989, 1993
     31    1.6      fvdl  *	The Regents of the University of California.  All rights reserved.
     32    1.6      fvdl  *
     33    1.6      fvdl  * Redistribution and use in source and binary forms, with or without
     34    1.6      fvdl  * modification, are permitted provided that the following conditions
     35    1.6      fvdl  * are met:
     36    1.6      fvdl  * 1. Redistributions of source code must retain the above copyright
     37    1.6      fvdl  *    notice, this list of conditions and the following disclaimer.
     38    1.6      fvdl  * 2. Redistributions in binary form must reproduce the above copyright
     39    1.6      fvdl  *    notice, this list of conditions and the following disclaimer in the
     40    1.6      fvdl  *    documentation and/or other materials provided with the distribution.
     41   1.81       agc  * 3. Neither the name of the University nor the names of its contributors
     42    1.6      fvdl  *    may be used to endorse or promote products derived from this software
     43    1.6      fvdl  *    without specific prior written permission.
     44    1.6      fvdl  *
     45    1.6      fvdl  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     46    1.6      fvdl  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     47    1.6      fvdl  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     48    1.6      fvdl  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     49    1.6      fvdl  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     50    1.6      fvdl  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     51    1.6      fvdl  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     52    1.6      fvdl  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     53    1.6      fvdl  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     54    1.6      fvdl  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     55    1.6      fvdl  * SUCH DAMAGE.
     56    1.6      fvdl  *
     57    1.6      fvdl  */
     58   1.40     lukem 
     59   1.40     lukem #include <sys/cdefs.h>
     60  1.201        ad __KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.201 2020/02/23 15:46:41 ad Exp $");
     61    1.8   thorpej 
     62    1.1   mycroft #include <sys/param.h>
     63    1.1   mycroft #include <sys/systm.h>
     64    1.6      fvdl #include <sys/proc.h>
     65    1.1   mycroft #include <sys/kernel.h>
     66    1.1   mycroft #include <sys/mount.h>
     67  1.186   hannken #include <sys/fstrans.h>
     68    1.1   mycroft #include <sys/namei.h>
     69  1.193   hannken #include <sys/vnode_impl.h>
     70   1.13  wrstuden #include <sys/fcntl.h>
     71  1.135      yamt #include <sys/kmem.h>
     72    1.3   mycroft #include <sys/poll.h>
     73   1.37       chs #include <sys/mman.h>
     74   1.66  jdolecek #include <sys/file.h>
     75  1.125      elad #include <sys/kauth.h>
     76  1.169      elad #include <sys/stat.h>
     77    1.1   mycroft 
     78    1.1   mycroft #include <miscfs/genfs/genfs.h>
     79   1.37       chs #include <miscfs/genfs/genfs_node.h>
     80    1.6      fvdl #include <miscfs/specfs/specdev.h>
     81    1.1   mycroft 
     82   1.21       chs #include <uvm/uvm.h>
     83   1.21       chs #include <uvm/uvm_pager.h>
     84   1.21       chs 
     85   1.70  christos static void filt_genfsdetach(struct knote *);
     86   1.70  christos static int filt_genfsread(struct knote *, long);
     87   1.70  christos static int filt_genfsvnode(struct knote *, long);
     88   1.70  christos 
     89    1.1   mycroft int
     90   1.53     enami genfs_poll(void *v)
     91    1.1   mycroft {
     92    1.3   mycroft 	struct vop_poll_args /* {
     93    1.1   mycroft 		struct vnode *a_vp;
     94    1.3   mycroft 		int a_events;
     95  1.116  christos 		struct lwp *a_l;
     96    1.1   mycroft 	} */ *ap = v;
     97    1.1   mycroft 
     98    1.3   mycroft 	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
     99    1.1   mycroft }
    100    1.1   mycroft 
    101    1.1   mycroft int
    102   1.53     enami genfs_seek(void *v)
    103    1.4    kleink {
    104    1.4    kleink 	struct vop_seek_args /* {
    105    1.4    kleink 		struct vnode *a_vp;
    106    1.4    kleink 		off_t a_oldoff;
    107    1.4    kleink 		off_t a_newoff;
    108  1.125      elad 		kauth_cred_t cred;
    109    1.4    kleink 	} */ *ap = v;
    110    1.4    kleink 
    111    1.4    kleink 	if (ap->a_newoff < 0)
    112    1.4    kleink 		return (EINVAL);
    113    1.4    kleink 
    114    1.4    kleink 	return (0);
    115    1.4    kleink }
    116    1.4    kleink 
    117    1.4    kleink int
    118   1.53     enami genfs_abortop(void *v)
    119    1.1   mycroft {
    120    1.1   mycroft 	struct vop_abortop_args /* {
    121    1.1   mycroft 		struct vnode *a_dvp;
    122    1.1   mycroft 		struct componentname *a_cnp;
    123    1.1   mycroft 	} */ *ap = v;
    124   1.53     enami 
    125  1.184  dholland 	(void)ap;
    126  1.184  dholland 
    127    1.1   mycroft 	return (0);
    128   1.13  wrstuden }
    129   1.13  wrstuden 
    130   1.13  wrstuden int
    131   1.53     enami genfs_fcntl(void *v)
    132   1.13  wrstuden {
    133   1.13  wrstuden 	struct vop_fcntl_args /* {
    134   1.13  wrstuden 		struct vnode *a_vp;
    135   1.13  wrstuden 		u_int a_command;
    136  1.150  christos 		void *a_data;
    137   1.13  wrstuden 		int a_fflag;
    138  1.125      elad 		kauth_cred_t a_cred;
    139  1.116  christos 		struct lwp *a_l;
    140   1.13  wrstuden 	} */ *ap = v;
    141   1.13  wrstuden 
    142   1.13  wrstuden 	if (ap->a_command == F_SETFL)
    143   1.13  wrstuden 		return (0);
    144   1.13  wrstuden 	else
    145   1.13  wrstuden 		return (EOPNOTSUPP);
    146    1.1   mycroft }
    147    1.1   mycroft 
    148    1.1   mycroft /*ARGSUSED*/
    149    1.1   mycroft int
    150  1.138  christos genfs_badop(void *v)
    151    1.1   mycroft {
    152    1.1   mycroft 
    153    1.1   mycroft 	panic("genfs: bad op");
    154    1.1   mycroft }
    155    1.1   mycroft 
    156    1.1   mycroft /*ARGSUSED*/
    157    1.1   mycroft int
    158  1.138  christos genfs_nullop(void *v)
    159    1.1   mycroft {
    160    1.1   mycroft 
    161    1.1   mycroft 	return (0);
    162   1.10    kleink }
    163   1.10    kleink 
    164   1.10    kleink /*ARGSUSED*/
    165   1.10    kleink int
    166  1.138  christos genfs_einval(void *v)
    167   1.10    kleink {
    168   1.10    kleink 
    169   1.10    kleink 	return (EINVAL);
    170    1.1   mycroft }
    171    1.1   mycroft 
    172   1.12  wrstuden /*
    173   1.74  jdolecek  * Called when an fs doesn't support a particular vop.
    174  1.177     pooka  * This takes care to vrele, vput, or vunlock passed in vnodes
    175  1.177     pooka  * and calls VOP_ABORTOP for a componentname (in non-rename VOP).
    176   1.12  wrstuden  */
    177   1.12  wrstuden int
    178   1.75  jdolecek genfs_eopnotsupp(void *v)
    179   1.12  wrstuden {
    180   1.12  wrstuden 	struct vop_generic_args /*
    181   1.12  wrstuden 		struct vnodeop_desc *a_desc;
    182   1.53     enami 		/ * other random data follows, presumably * /
    183   1.12  wrstuden 	} */ *ap = v;
    184   1.12  wrstuden 	struct vnodeop_desc *desc = ap->a_desc;
    185   1.74  jdolecek 	struct vnode *vp, *vp_last = NULL;
    186  1.177     pooka 	int flags, i, j, offset_cnp, offset_vp;
    187  1.177     pooka 
    188  1.177     pooka 	KASSERT(desc->vdesc_offset != VOP_LOOKUP_DESCOFFSET);
    189  1.177     pooka 	KASSERT(desc->vdesc_offset != VOP_ABORTOP_DESCOFFSET);
    190  1.177     pooka 
    191  1.177     pooka 	/*
    192  1.185  dholland 	 * Abort any componentname that lookup potentially left state in.
    193  1.177     pooka 	 *
    194  1.177     pooka 	 * As is logical, componentnames for VOP_RENAME are handled by
    195  1.177     pooka 	 * the caller of VOP_RENAME.  Yay, rename!
    196  1.177     pooka 	 */
    197  1.177     pooka 	if (desc->vdesc_offset != VOP_RENAME_DESCOFFSET &&
    198  1.177     pooka 	    (offset_vp = desc->vdesc_vp_offsets[0]) != VDESC_NO_OFFSET &&
    199  1.177     pooka 	    (offset_cnp = desc->vdesc_componentname_offset) != VDESC_NO_OFFSET){
    200  1.177     pooka 		struct componentname *cnp;
    201  1.177     pooka 		struct vnode *dvp;
    202  1.177     pooka 
    203  1.177     pooka 		dvp = *VOPARG_OFFSETTO(struct vnode **, offset_vp, ap);
    204  1.177     pooka 		cnp = *VOPARG_OFFSETTO(struct componentname **, offset_cnp, ap);
    205  1.177     pooka 
    206  1.177     pooka 		VOP_ABORTOP(dvp, cnp);
    207  1.177     pooka 	}
    208   1.12  wrstuden 
    209   1.12  wrstuden 	flags = desc->vdesc_flags;
    210   1.12  wrstuden 	for (i = 0; i < VDESC_MAX_VPS; flags >>=1, i++) {
    211  1.177     pooka 		if ((offset_vp = desc->vdesc_vp_offsets[i]) == VDESC_NO_OFFSET)
    212   1.12  wrstuden 			break;	/* stop at end of list */
    213   1.12  wrstuden 		if ((j = flags & VDESC_VP0_WILLPUT)) {
    214  1.177     pooka 			vp = *VOPARG_OFFSETTO(struct vnode **, offset_vp, ap);
    215   1.74  jdolecek 
    216   1.74  jdolecek 			/* Skip if NULL */
    217   1.74  jdolecek 			if (!vp)
    218   1.74  jdolecek 				continue;
    219   1.74  jdolecek 
    220   1.12  wrstuden 			switch (j) {
    221   1.12  wrstuden 			case VDESC_VP0_WILLPUT:
    222   1.74  jdolecek 				/* Check for dvp == vp cases */
    223   1.74  jdolecek 				if (vp == vp_last)
    224   1.74  jdolecek 					vrele(vp);
    225   1.74  jdolecek 				else {
    226   1.74  jdolecek 					vput(vp);
    227   1.74  jdolecek 					vp_last = vp;
    228   1.74  jdolecek 				}
    229   1.12  wrstuden 				break;
    230   1.12  wrstuden 			case VDESC_VP0_WILLRELE:
    231   1.12  wrstuden 				vrele(vp);
    232   1.12  wrstuden 				break;
    233   1.12  wrstuden 			}
    234   1.12  wrstuden 		}
    235   1.12  wrstuden 	}
    236   1.12  wrstuden 
    237   1.12  wrstuden 	return (EOPNOTSUPP);
    238   1.12  wrstuden }
    239   1.12  wrstuden 
    240    1.1   mycroft /*ARGSUSED*/
    241    1.1   mycroft int
    242  1.138  christos genfs_ebadf(void *v)
    243    1.1   mycroft {
    244    1.1   mycroft 
    245    1.1   mycroft 	return (EBADF);
    246    1.9  matthias }
    247    1.9  matthias 
    248    1.9  matthias /* ARGSUSED */
    249    1.9  matthias int
    250  1.138  christos genfs_enoioctl(void *v)
    251    1.9  matthias {
    252    1.9  matthias 
    253   1.51    atatat 	return (EPASSTHROUGH);
    254    1.6      fvdl }
    255    1.6      fvdl 
    256    1.6      fvdl 
    257    1.6      fvdl /*
    258   1.15      fvdl  * Eliminate all activity associated with the requested vnode
    259    1.6      fvdl  * and with all vnodes aliased to the requested vnode.
    260    1.6      fvdl  */
    261    1.6      fvdl int
    262   1.53     enami genfs_revoke(void *v)
    263    1.6      fvdl {
    264    1.6      fvdl 	struct vop_revoke_args /* {
    265    1.6      fvdl 		struct vnode *a_vp;
    266    1.6      fvdl 		int a_flags;
    267    1.6      fvdl 	} */ *ap = v;
    268    1.6      fvdl 
    269    1.6      fvdl #ifdef DIAGNOSTIC
    270    1.6      fvdl 	if ((ap->a_flags & REVOKEALL) == 0)
    271    1.6      fvdl 		panic("genfs_revoke: not revokeall");
    272    1.6      fvdl #endif
    273  1.161        ad 	vrevoke(ap->a_vp);
    274    1.6      fvdl 	return (0);
    275    1.6      fvdl }
    276    1.6      fvdl 
    277    1.6      fvdl /*
    278  1.190   hannken  * Lock the node (for deadfs).
    279  1.190   hannken  */
    280  1.190   hannken int
    281  1.190   hannken genfs_deadlock(void *v)
    282  1.190   hannken {
    283  1.190   hannken 	struct vop_lock_args /* {
    284  1.190   hannken 		struct vnode *a_vp;
    285  1.190   hannken 		int a_flags;
    286  1.190   hannken 	} */ *ap = v;
    287  1.193   hannken 	vnode_t *vp = ap->a_vp;
    288  1.193   hannken 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
    289  1.190   hannken 	int flags = ap->a_flags;
    290  1.190   hannken 	krw_t op;
    291  1.196   hannken 
    292  1.196   hannken 	if (! ISSET(flags, LK_RETRY))
    293  1.196   hannken 		return ENOENT;
    294  1.190   hannken 
    295  1.200        ad 	if (ISSET(flags, LK_DOWNGRADE)) {
    296  1.200        ad 		rw_downgrade(vip->vi_lock);
    297  1.200        ad 	} else if (ISSET(flags, LK_UPGRADE)) {
    298  1.200        ad 		if (!rw_tryupgrade(vip->vi_lock)) {
    299  1.200        ad 			if (ISSET(flags, LK_NOWAIT))
    300  1.200        ad 				return EBUSY;
    301  1.200        ad 			rw_exit(vip->vi_lock);
    302  1.200        ad 			rw_enter(vip->vi_lock, RW_WRITER);
    303  1.200        ad 		}
    304  1.196   hannken 	} else {
    305  1.200        ad 		op = (ISSET(flags, LK_EXCLUSIVE) ? RW_WRITER : RW_READER);
    306  1.200        ad 		if (ISSET(flags, LK_NOWAIT)) {
    307  1.200        ad 			if (!rw_tryenter(vip->vi_lock, op))
    308  1.200        ad 				return EBUSY;
    309  1.200        ad 		} else {
    310  1.200        ad 			rw_enter(vip->vi_lock, op);
    311  1.200        ad 		}
    312  1.190   hannken 	}
    313  1.196   hannken 	VSTATE_ASSERT_UNLOCKED(vp, VS_RECLAIMED);
    314  1.190   hannken 	return 0;
    315  1.190   hannken }
    316  1.190   hannken 
    317  1.190   hannken /*
    318  1.190   hannken  * Unlock the node (for deadfs).
    319  1.190   hannken  */
    320  1.190   hannken int
    321  1.190   hannken genfs_deadunlock(void *v)
    322  1.190   hannken {
    323  1.190   hannken 	struct vop_unlock_args /* {
    324  1.190   hannken 		struct vnode *a_vp;
    325  1.190   hannken 	} */ *ap = v;
    326  1.193   hannken 	vnode_t *vp = ap->a_vp;
    327  1.193   hannken 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
    328  1.190   hannken 
    329  1.200        ad 	rw_exit(vip->vi_lock);
    330  1.190   hannken 
    331  1.190   hannken 	return 0;
    332  1.190   hannken }
    333  1.190   hannken 
    334  1.190   hannken /*
    335   1.12  wrstuden  * Lock the node.
    336    1.6      fvdl  */
    337    1.6      fvdl int
    338   1.53     enami genfs_lock(void *v)
    339    1.6      fvdl {
    340    1.6      fvdl 	struct vop_lock_args /* {
    341    1.6      fvdl 		struct vnode *a_vp;
    342    1.6      fvdl 		int a_flags;
    343    1.6      fvdl 	} */ *ap = v;
    344  1.193   hannken 	vnode_t *vp = ap->a_vp;
    345  1.193   hannken 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
    346  1.163        ad 	int flags = ap->a_flags;
    347  1.182   hannken 	krw_t op;
    348    1.6      fvdl 
    349  1.200        ad 	if (ISSET(flags, LK_DOWNGRADE)) {
    350  1.200        ad 		rw_downgrade(vip->vi_lock);
    351  1.200        ad 	} else if (ISSET(flags, LK_UPGRADE)) {
    352  1.200        ad 		if (!rw_tryupgrade(vip->vi_lock)) {
    353  1.200        ad 			if (ISSET(flags, LK_NOWAIT))
    354  1.200        ad 				return EBUSY;
    355  1.200        ad 			rw_exit(vip->vi_lock);
    356  1.200        ad 			rw_enter(vip->vi_lock, RW_WRITER);
    357  1.200        ad 		}
    358  1.196   hannken 	} else {
    359  1.200        ad 		op = (ISSET(flags, LK_EXCLUSIVE) ? RW_WRITER : RW_READER);
    360  1.200        ad 		if (ISSET(flags, LK_NOWAIT)) {
    361  1.200        ad 			if (!rw_tryenter(vip->vi_lock, op))
    362  1.200        ad 				return EBUSY;
    363  1.200        ad 		} else {
    364  1.200        ad 			rw_enter(vip->vi_lock, op);
    365  1.200        ad 		}
    366  1.186   hannken 	}
    367  1.196   hannken 	VSTATE_ASSERT_UNLOCKED(vp, VS_ACTIVE);
    368  1.196   hannken 	return 0;
    369    1.6      fvdl }
    370    1.6      fvdl 
    371    1.6      fvdl /*
    372   1.12  wrstuden  * Unlock the node.
    373    1.6      fvdl  */
    374    1.6      fvdl int
    375   1.53     enami genfs_unlock(void *v)
    376    1.6      fvdl {
    377    1.6      fvdl 	struct vop_unlock_args /* {
    378    1.6      fvdl 		struct vnode *a_vp;
    379    1.6      fvdl 	} */ *ap = v;
    380  1.193   hannken 	vnode_t *vp = ap->a_vp;
    381  1.193   hannken 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
    382    1.6      fvdl 
    383  1.200        ad 	rw_exit(vip->vi_lock);
    384  1.182   hannken 
    385  1.182   hannken 	return 0;
    386    1.6      fvdl }
    387    1.6      fvdl 
    388    1.6      fvdl /*
    389   1.12  wrstuden  * Return whether or not the node is locked.
    390    1.6      fvdl  */
    391    1.6      fvdl int
    392   1.53     enami genfs_islocked(void *v)
    393    1.6      fvdl {
    394    1.6      fvdl 	struct vop_islocked_args /* {
    395    1.6      fvdl 		struct vnode *a_vp;
    396    1.6      fvdl 	} */ *ap = v;
    397  1.193   hannken 	vnode_t *vp = ap->a_vp;
    398  1.193   hannken 	vnode_impl_t *vip = VNODE_TO_VIMPL(vp);
    399    1.6      fvdl 
    400  1.200        ad 	if (rw_write_held(vip->vi_lock))
    401  1.182   hannken 		return LK_EXCLUSIVE;
    402  1.182   hannken 
    403  1.200        ad 	if (rw_read_held(vip->vi_lock))
    404  1.182   hannken 		return LK_SHARED;
    405  1.182   hannken 
    406  1.182   hannken 	return 0;
    407   1.12  wrstuden }
    408   1.12  wrstuden 
    409   1.12  wrstuden /*
    410   1.12  wrstuden  * Stubs to use when there is no locking to be done on the underlying object.
    411   1.12  wrstuden  */
    412   1.12  wrstuden int
    413   1.53     enami genfs_nolock(void *v)
    414   1.12  wrstuden {
    415   1.12  wrstuden 
    416   1.12  wrstuden 	return (0);
    417   1.12  wrstuden }
    418   1.12  wrstuden 
    419   1.12  wrstuden int
    420  1.138  christos genfs_nounlock(void *v)
    421   1.12  wrstuden {
    422   1.53     enami 
    423   1.12  wrstuden 	return (0);
    424   1.12  wrstuden }
    425   1.12  wrstuden 
    426   1.12  wrstuden int
    427  1.138  christos genfs_noislocked(void *v)
    428   1.12  wrstuden {
    429   1.53     enami 
    430   1.12  wrstuden 	return (0);
    431    1.8   thorpej }
    432    1.8   thorpej 
    433   1.34       chs int
    434  1.138  christos genfs_mmap(void *v)
    435   1.34       chs {
    436   1.53     enami 
    437   1.53     enami 	return (0);
    438   1.21       chs }
    439   1.21       chs 
    440  1.168     pooka /*
    441  1.168     pooka  * VOP_PUTPAGES() for vnodes which never have pages.
    442  1.168     pooka  */
    443  1.168     pooka 
    444  1.168     pooka int
    445  1.168     pooka genfs_null_putpages(void *v)
    446  1.168     pooka {
    447  1.168     pooka 	struct vop_putpages_args /* {
    448  1.168     pooka 		struct vnode *a_vp;
    449  1.168     pooka 		voff_t a_offlo;
    450  1.168     pooka 		voff_t a_offhi;
    451  1.168     pooka 		int a_flags;
    452  1.168     pooka 	} */ *ap = v;
    453  1.168     pooka 	struct vnode *vp = ap->a_vp;
    454  1.168     pooka 
    455  1.168     pooka 	KASSERT(vp->v_uobj.uo_npages == 0);
    456  1.201        ad 	rw_exit(vp->v_uobj.vmobjlock);
    457  1.168     pooka 	return (0);
    458  1.168     pooka }
    459  1.168     pooka 
    460   1.37       chs void
    461   1.98      yamt genfs_node_init(struct vnode *vp, const struct genfs_ops *ops)
    462   1.37       chs {
    463   1.37       chs 	struct genfs_node *gp = VTOG(vp);
    464   1.37       chs 
    465  1.146        ad 	rw_init(&gp->g_glock);
    466   1.37       chs 	gp->g_op = ops;
    467   1.37       chs }
    468   1.37       chs 
    469   1.37       chs void
    470  1.147        ad genfs_node_destroy(struct vnode *vp)
    471  1.147        ad {
    472  1.147        ad 	struct genfs_node *gp = VTOG(vp);
    473  1.147        ad 
    474  1.147        ad 	rw_destroy(&gp->g_glock);
    475  1.147        ad }
    476  1.147        ad 
    477  1.147        ad void
    478  1.138  christos genfs_size(struct vnode *vp, off_t size, off_t *eobp, int flags)
    479   1.21       chs {
    480   1.21       chs 	int bsize;
    481   1.21       chs 
    482   1.37       chs 	bsize = 1 << vp->v_mount->mnt_fs_bshift;
    483   1.37       chs 	*eobp = (size + bsize - 1) & ~(bsize - 1);
    484   1.43       chs }
    485   1.43       chs 
    486   1.66  jdolecek static void
    487   1.66  jdolecek filt_genfsdetach(struct knote *kn)
    488   1.66  jdolecek {
    489   1.66  jdolecek 	struct vnode *vp = (struct vnode *)kn->kn_hook;
    490   1.66  jdolecek 
    491  1.187     rmind 	mutex_enter(vp->v_interlock);
    492   1.66  jdolecek 	SLIST_REMOVE(&vp->v_klist, kn, knote, kn_selnext);
    493  1.187     rmind 	mutex_exit(vp->v_interlock);
    494   1.66  jdolecek }
    495   1.66  jdolecek 
    496   1.66  jdolecek static int
    497   1.66  jdolecek filt_genfsread(struct knote *kn, long hint)
    498   1.66  jdolecek {
    499   1.66  jdolecek 	struct vnode *vp = (struct vnode *)kn->kn_hook;
    500  1.164        ad 	int rv;
    501   1.66  jdolecek 
    502   1.66  jdolecek 	/*
    503   1.66  jdolecek 	 * filesystem is gone, so set the EOF flag and schedule
    504   1.66  jdolecek 	 * the knote for deletion.
    505   1.66  jdolecek 	 */
    506  1.164        ad 	switch (hint) {
    507  1.164        ad 	case NOTE_REVOKE:
    508  1.187     rmind 		KASSERT(mutex_owned(vp->v_interlock));
    509   1.66  jdolecek 		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
    510   1.66  jdolecek 		return (1);
    511  1.164        ad 	case 0:
    512  1.187     rmind 		mutex_enter(vp->v_interlock);
    513  1.165        ad 		kn->kn_data = vp->v_size - ((file_t *)kn->kn_obj)->f_offset;
    514  1.164        ad 		rv = (kn->kn_data != 0);
    515  1.187     rmind 		mutex_exit(vp->v_interlock);
    516  1.164        ad 		return rv;
    517  1.164        ad 	default:
    518  1.187     rmind 		KASSERT(mutex_owned(vp->v_interlock));
    519  1.165        ad 		kn->kn_data = vp->v_size - ((file_t *)kn->kn_obj)->f_offset;
    520  1.164        ad 		return (kn->kn_data != 0);
    521   1.66  jdolecek 	}
    522   1.66  jdolecek }
    523   1.66  jdolecek 
    524   1.66  jdolecek static int
    525  1.198  christos filt_genfswrite(struct knote *kn, long hint)
    526  1.198  christos {
    527  1.198  christos 	struct vnode *vp = (struct vnode *)kn->kn_hook;
    528  1.198  christos 
    529  1.198  christos 	/*
    530  1.198  christos 	 * filesystem is gone, so set the EOF flag and schedule
    531  1.198  christos 	 * the knote for deletion.
    532  1.198  christos 	 */
    533  1.198  christos 	switch (hint) {
    534  1.198  christos 	case NOTE_REVOKE:
    535  1.198  christos 		KASSERT(mutex_owned(vp->v_interlock));
    536  1.198  christos 		kn->kn_flags |= (EV_EOF | EV_ONESHOT);
    537  1.198  christos 		return (1);
    538  1.198  christos 	case 0:
    539  1.198  christos 		mutex_enter(vp->v_interlock);
    540  1.198  christos 		kn->kn_data = 0;
    541  1.198  christos 		mutex_exit(vp->v_interlock);
    542  1.198  christos 		return 1;
    543  1.198  christos 	default:
    544  1.198  christos 		KASSERT(mutex_owned(vp->v_interlock));
    545  1.198  christos 		kn->kn_data = 0;
    546  1.198  christos 		return 1;
    547  1.198  christos 	}
    548  1.198  christos }
    549  1.198  christos 
    550  1.198  christos static int
    551   1.66  jdolecek filt_genfsvnode(struct knote *kn, long hint)
    552   1.66  jdolecek {
    553  1.164        ad 	struct vnode *vp = (struct vnode *)kn->kn_hook;
    554  1.164        ad 	int fflags;
    555   1.66  jdolecek 
    556  1.164        ad 	switch (hint) {
    557  1.164        ad 	case NOTE_REVOKE:
    558  1.187     rmind 		KASSERT(mutex_owned(vp->v_interlock));
    559   1.66  jdolecek 		kn->kn_flags |= EV_EOF;
    560  1.164        ad 		if ((kn->kn_sfflags & hint) != 0)
    561  1.164        ad 			kn->kn_fflags |= hint;
    562   1.66  jdolecek 		return (1);
    563  1.164        ad 	case 0:
    564  1.187     rmind 		mutex_enter(vp->v_interlock);
    565  1.164        ad 		fflags = kn->kn_fflags;
    566  1.187     rmind 		mutex_exit(vp->v_interlock);
    567  1.164        ad 		break;
    568  1.164        ad 	default:
    569  1.187     rmind 		KASSERT(mutex_owned(vp->v_interlock));
    570  1.164        ad 		if ((kn->kn_sfflags & hint) != 0)
    571  1.164        ad 			kn->kn_fflags |= hint;
    572  1.164        ad 		fflags = kn->kn_fflags;
    573  1.164        ad 		break;
    574   1.66  jdolecek 	}
    575  1.164        ad 
    576  1.165        ad 	return (fflags != 0);
    577   1.66  jdolecek }
    578   1.66  jdolecek 
    579  1.199      maya static const struct filterops genfsread_filtops = {
    580  1.199      maya 	.f_isfd = 1,
    581  1.199      maya 	.f_attach = NULL,
    582  1.199      maya 	.f_detach = filt_genfsdetach,
    583  1.199      maya 	.f_event = filt_genfsread,
    584  1.199      maya };
    585  1.199      maya 
    586  1.199      maya static const struct filterops genfswrite_filtops = {
    587  1.199      maya 	.f_isfd = 1,
    588  1.199      maya 	.f_attach = NULL,
    589  1.199      maya 	.f_detach = filt_genfsdetach,
    590  1.199      maya 	.f_event = filt_genfswrite,
    591  1.199      maya };
    592  1.199      maya 
    593  1.199      maya static const struct filterops genfsvnode_filtops = {
    594  1.199      maya 	.f_isfd = 1,
    595  1.199      maya 	.f_attach = NULL,
    596  1.199      maya 	.f_detach = filt_genfsdetach,
    597  1.199      maya 	.f_event = filt_genfsvnode,
    598  1.199      maya };
    599   1.66  jdolecek 
    600   1.66  jdolecek int
    601   1.66  jdolecek genfs_kqfilter(void *v)
    602   1.66  jdolecek {
    603   1.66  jdolecek 	struct vop_kqfilter_args /* {
    604   1.66  jdolecek 		struct vnode	*a_vp;
    605   1.66  jdolecek 		struct knote	*a_kn;
    606   1.66  jdolecek 	} */ *ap = v;
    607   1.66  jdolecek 	struct vnode *vp;
    608   1.66  jdolecek 	struct knote *kn;
    609   1.66  jdolecek 
    610   1.66  jdolecek 	vp = ap->a_vp;
    611   1.66  jdolecek 	kn = ap->a_kn;
    612   1.66  jdolecek 	switch (kn->kn_filter) {
    613   1.66  jdolecek 	case EVFILT_READ:
    614   1.66  jdolecek 		kn->kn_fop = &genfsread_filtops;
    615   1.66  jdolecek 		break;
    616  1.198  christos 	case EVFILT_WRITE:
    617  1.198  christos 		kn->kn_fop = &genfswrite_filtops;
    618  1.198  christos 		break;
    619   1.66  jdolecek 	case EVFILT_VNODE:
    620   1.66  jdolecek 		kn->kn_fop = &genfsvnode_filtops;
    621   1.66  jdolecek 		break;
    622   1.66  jdolecek 	default:
    623  1.159     pooka 		return (EINVAL);
    624   1.66  jdolecek 	}
    625   1.66  jdolecek 
    626   1.66  jdolecek 	kn->kn_hook = vp;
    627   1.66  jdolecek 
    628  1.187     rmind 	mutex_enter(vp->v_interlock);
    629   1.66  jdolecek 	SLIST_INSERT_HEAD(&vp->v_klist, kn, kn_selnext);
    630  1.187     rmind 	mutex_exit(vp->v_interlock);
    631   1.66  jdolecek 
    632   1.66  jdolecek 	return (0);
    633    1.1   mycroft }
    634  1.136      yamt 
    635  1.136      yamt void
    636  1.136      yamt genfs_node_wrlock(struct vnode *vp)
    637  1.136      yamt {
    638  1.136      yamt 	struct genfs_node *gp = VTOG(vp);
    639  1.136      yamt 
    640  1.146        ad 	rw_enter(&gp->g_glock, RW_WRITER);
    641  1.136      yamt }
    642  1.136      yamt 
    643  1.136      yamt void
    644  1.136      yamt genfs_node_rdlock(struct vnode *vp)
    645  1.136      yamt {
    646  1.136      yamt 	struct genfs_node *gp = VTOG(vp);
    647  1.136      yamt 
    648  1.146        ad 	rw_enter(&gp->g_glock, RW_READER);
    649  1.136      yamt }
    650  1.136      yamt 
    651  1.176  uebayasi int
    652  1.175  uebayasi genfs_node_rdtrylock(struct vnode *vp)
    653  1.175  uebayasi {
    654  1.175  uebayasi 	struct genfs_node *gp = VTOG(vp);
    655  1.175  uebayasi 
    656  1.176  uebayasi 	return rw_tryenter(&gp->g_glock, RW_READER);
    657  1.175  uebayasi }
    658  1.175  uebayasi 
    659  1.175  uebayasi void
    660  1.136      yamt genfs_node_unlock(struct vnode *vp)
    661  1.136      yamt {
    662  1.136      yamt 	struct genfs_node *gp = VTOG(vp);
    663  1.136      yamt 
    664  1.146        ad 	rw_exit(&gp->g_glock);
    665  1.136      yamt }
    666  1.169      elad 
    667  1.183       chs int
    668  1.183       chs genfs_node_wrlocked(struct vnode *vp)
    669  1.183       chs {
    670  1.183       chs 	struct genfs_node *gp = VTOG(vp);
    671  1.183       chs 
    672  1.183       chs 	return rw_write_held(&gp->g_glock);
    673  1.183       chs }
    674  1.183       chs 
    675  1.169      elad /*
    676  1.172      elad  * Do the usual access checking.
    677  1.172      elad  * file_mode, uid and gid are from the vnode in question,
    678  1.172      elad  * while acc_mode and cred are from the VOP_ACCESS parameter list
    679  1.172      elad  */
    680  1.172      elad int
    681  1.172      elad genfs_can_access(enum vtype type, mode_t file_mode, uid_t uid, gid_t gid,
    682  1.172      elad     mode_t acc_mode, kauth_cred_t cred)
    683  1.172      elad {
    684  1.172      elad 	mode_t mask;
    685  1.172      elad 	int error, ismember;
    686  1.172      elad 
    687  1.172      elad 	mask = 0;
    688  1.172      elad 
    689  1.172      elad 	/* Otherwise, check the owner. */
    690  1.172      elad 	if (kauth_cred_geteuid(cred) == uid) {
    691  1.172      elad 		if (acc_mode & VEXEC)
    692  1.172      elad 			mask |= S_IXUSR;
    693  1.172      elad 		if (acc_mode & VREAD)
    694  1.172      elad 			mask |= S_IRUSR;
    695  1.172      elad 		if (acc_mode & VWRITE)
    696  1.172      elad 			mask |= S_IWUSR;
    697  1.172      elad 		return ((file_mode & mask) == mask ? 0 : EACCES);
    698  1.172      elad 	}
    699  1.172      elad 
    700  1.172      elad 	/* Otherwise, check the groups. */
    701  1.172      elad 	error = kauth_cred_ismember_gid(cred, gid, &ismember);
    702  1.172      elad 	if (error)
    703  1.172      elad 		return (error);
    704  1.172      elad 	if (kauth_cred_getegid(cred) == gid || ismember) {
    705  1.172      elad 		if (acc_mode & VEXEC)
    706  1.172      elad 			mask |= S_IXGRP;
    707  1.172      elad 		if (acc_mode & VREAD)
    708  1.172      elad 			mask |= S_IRGRP;
    709  1.172      elad 		if (acc_mode & VWRITE)
    710  1.172      elad 			mask |= S_IWGRP;
    711  1.172      elad 		return ((file_mode & mask) == mask ? 0 : EACCES);
    712  1.172      elad 	}
    713  1.172      elad 
    714  1.172      elad 	/* Otherwise, check everyone else. */
    715  1.172      elad 	if (acc_mode & VEXEC)
    716  1.172      elad 		mask |= S_IXOTH;
    717  1.172      elad 	if (acc_mode & VREAD)
    718  1.172      elad 		mask |= S_IROTH;
    719  1.172      elad 	if (acc_mode & VWRITE)
    720  1.172      elad 		mask |= S_IWOTH;
    721  1.172      elad 	return ((file_mode & mask) == mask ? 0 : EACCES);
    722  1.172      elad }
    723  1.172      elad 
    724  1.172      elad /*
    725  1.169      elad  * Common routine to check if chmod() is allowed.
    726  1.169      elad  *
    727  1.169      elad  * Policy:
    728  1.169      elad  *   - You must own the file, and
    729  1.169      elad  *     - You must not set the "sticky" bit (meaningless, see chmod(2))
    730  1.169      elad  *     - You must be a member of the group if you're trying to set the
    731  1.169      elad  *       SGIDf bit
    732  1.169      elad  *
    733  1.169      elad  * cred - credentials of the invoker
    734  1.169      elad  * vp - vnode of the file-system object
    735  1.169      elad  * cur_uid, cur_gid - current uid/gid of the file-system object
    736  1.169      elad  * new_mode - new mode for the file-system object
    737  1.169      elad  *
    738  1.169      elad  * Returns 0 if the change is allowed, or an error value otherwise.
    739  1.169      elad  */
    740  1.169      elad int
    741  1.188      elad genfs_can_chmod(enum vtype type, kauth_cred_t cred, uid_t cur_uid,
    742  1.169      elad     gid_t cur_gid, mode_t new_mode)
    743  1.169      elad {
    744  1.169      elad 	int error;
    745  1.169      elad 
    746  1.188      elad 	/* The user must own the file. */
    747  1.169      elad 	if (kauth_cred_geteuid(cred) != cur_uid)
    748  1.169      elad 		return (EPERM);
    749  1.169      elad 
    750  1.169      elad 	/*
    751  1.188      elad 	 * Unprivileged users can't set the sticky bit on files.
    752  1.169      elad 	 */
    753  1.188      elad 	if ((type != VDIR) && (new_mode & S_ISTXT))
    754  1.169      elad 		return (EFTYPE);
    755  1.169      elad 
    756  1.169      elad 	/*
    757  1.169      elad 	 * If the invoker is trying to set the SGID bit on the file,
    758  1.169      elad 	 * check group membership.
    759  1.169      elad 	 */
    760  1.169      elad 	if (new_mode & S_ISGID) {
    761  1.169      elad 		int ismember;
    762  1.169      elad 
    763  1.169      elad 		error = kauth_cred_ismember_gid(cred, cur_gid,
    764  1.169      elad 		    &ismember);
    765  1.169      elad 		if (error || !ismember)
    766  1.169      elad 			return (EPERM);
    767  1.169      elad 	}
    768  1.169      elad 
    769  1.169      elad 	return (0);
    770  1.169      elad }
    771  1.169      elad 
    772  1.169      elad /*
    773  1.169      elad  * Common routine to check if chown() is allowed.
    774  1.169      elad  *
    775  1.169      elad  * Policy:
    776  1.169      elad  *   - You must own the file, and
    777  1.169      elad  *     - You must not try to change ownership, and
    778  1.169      elad  *     - You must be member of the new group
    779  1.169      elad  *
    780  1.169      elad  * cred - credentials of the invoker
    781  1.169      elad  * cur_uid, cur_gid - current uid/gid of the file-system object
    782  1.169      elad  * new_uid, new_gid - target uid/gid of the file-system object
    783  1.169      elad  *
    784  1.169      elad  * Returns 0 if the change is allowed, or an error value otherwise.
    785  1.169      elad  */
    786  1.169      elad int
    787  1.188      elad genfs_can_chown(kauth_cred_t cred, uid_t cur_uid,
    788  1.169      elad     gid_t cur_gid, uid_t new_uid, gid_t new_gid)
    789  1.169      elad {
    790  1.169      elad 	int error, ismember;
    791  1.169      elad 
    792  1.169      elad 	/*
    793  1.169      elad 	 * You can only change ownership of a file if:
    794  1.169      elad 	 * You own the file and...
    795  1.169      elad 	 */
    796  1.169      elad 	if (kauth_cred_geteuid(cred) == cur_uid) {
    797  1.169      elad 		/*
    798  1.169      elad 		 * You don't try to change ownership, and...
    799  1.169      elad 		 */
    800  1.169      elad 		if (new_uid != cur_uid)
    801  1.169      elad 			return (EPERM);
    802  1.169      elad 
    803  1.169      elad 		/*
    804  1.169      elad 		 * You don't try to change group (no-op), or...
    805  1.169      elad 		 */
    806  1.169      elad 		if (new_gid == cur_gid)
    807  1.169      elad 			return (0);
    808  1.169      elad 
    809  1.169      elad 		/*
    810  1.169      elad 		 * Your effective gid is the new gid, or...
    811  1.169      elad 		 */
    812  1.169      elad 		if (kauth_cred_getegid(cred) == new_gid)
    813  1.169      elad 			return (0);
    814  1.169      elad 
    815  1.169      elad 		/*
    816  1.169      elad 		 * The new gid is one you're a member of.
    817  1.169      elad 		 */
    818  1.169      elad 		ismember = 0;
    819  1.169      elad 		error = kauth_cred_ismember_gid(cred, new_gid,
    820  1.169      elad 		    &ismember);
    821  1.174       roy 		if (!error && ismember)
    822  1.174       roy 			return (0);
    823  1.169      elad 	}
    824  1.169      elad 
    825  1.173     pooka 	return (EPERM);
    826  1.169      elad }
    827  1.169      elad 
    828  1.171      elad int
    829  1.171      elad genfs_can_chtimes(vnode_t *vp, u_int vaflags, uid_t owner_uid,
    830  1.171      elad     kauth_cred_t cred)
    831  1.171      elad {
    832  1.171      elad 	int error;
    833  1.171      elad 
    834  1.188      elad 	/* Must be owner, or... */
    835  1.171      elad 	if (kauth_cred_geteuid(cred) == owner_uid)
    836  1.171      elad 		return (0);
    837  1.171      elad 
    838  1.171      elad 	/* set the times to the current time, and... */
    839  1.171      elad 	if ((vaflags & VA_UTIMES_NULL) == 0)
    840  1.171      elad 		return (EPERM);
    841  1.171      elad 
    842  1.171      elad 	/* have write access. */
    843  1.171      elad 	error = VOP_ACCESS(vp, VWRITE, cred);
    844  1.171      elad 	if (error)
    845  1.171      elad 		return (error);
    846  1.171      elad 
    847  1.171      elad 	return (0);
    848  1.171      elad }
    849  1.171      elad 
    850  1.188      elad /*
    851  1.188      elad  * Common routine to check if chflags() is allowed.
    852  1.188      elad  *
    853  1.188      elad  * Policy:
    854  1.188      elad  *   - You must own the file, and
    855  1.188      elad  *   - You must not change system flags, and
    856  1.188      elad  *   - You must not change flags on character/block devices.
    857  1.188      elad  *
    858  1.188      elad  * cred - credentials of the invoker
    859  1.188      elad  * owner_uid - uid of the file-system object
    860  1.188      elad  * changing_sysflags - true if the invoker wants to change system flags
    861  1.188      elad  */
    862  1.188      elad int
    863  1.188      elad genfs_can_chflags(kauth_cred_t cred, enum vtype type, uid_t owner_uid,
    864  1.188      elad     bool changing_sysflags)
    865  1.188      elad {
    866  1.188      elad 
    867  1.188      elad 	/* The user must own the file. */
    868  1.188      elad 	if (kauth_cred_geteuid(cred) != owner_uid) {
    869  1.189     njoly 		return EPERM;
    870  1.188      elad 	}
    871  1.188      elad 
    872  1.188      elad 	if (changing_sysflags) {
    873  1.188      elad 		return EPERM;
    874  1.188      elad 	}
    875  1.188      elad 
    876  1.188      elad 	/*
    877  1.188      elad 	 * Unprivileged users cannot change the flags on devices, even if they
    878  1.188      elad 	 * own them.
    879  1.188      elad 	 */
    880  1.188      elad 	if (type == VCHR || type == VBLK) {
    881  1.188      elad 		return EPERM;
    882  1.188      elad 	}
    883  1.188      elad 
    884  1.188      elad 	return 0;
    885  1.188      elad }
    886  1.188      elad 
    887  1.188      elad /*
    888  1.188      elad  * Common "sticky" policy.
    889  1.188      elad  *
    890  1.188      elad  * When a directory is "sticky" (as determined by the caller), this
    891  1.188      elad  * function may help implementing the following policy:
    892  1.188      elad  * - Renaming a file in it is only possible if the user owns the directory
    893  1.188      elad  *   or the file being renamed.
    894  1.188      elad  * - Deleting a file from it is only possible if the user owns the
    895  1.188      elad  *   directory or the file being deleted.
    896  1.188      elad  */
    897  1.188      elad int
    898  1.188      elad genfs_can_sticky(kauth_cred_t cred, uid_t dir_uid, uid_t file_uid)
    899  1.188      elad {
    900  1.188      elad 	if (kauth_cred_geteuid(cred) != dir_uid &&
    901  1.188      elad 	    kauth_cred_geteuid(cred) != file_uid)
    902  1.188      elad 		return EPERM;
    903  1.188      elad 
    904  1.188      elad 	return 0;
    905  1.188      elad }
    906  1.188      elad 
    907  1.188      elad int
    908  1.188      elad genfs_can_extattr(kauth_cred_t cred, int access_mode, vnode_t *vp,
    909  1.188      elad     const char *attr)
    910  1.188      elad {
    911  1.188      elad 	/* We can't allow privileged namespaces. */
    912  1.188      elad 	if (strncasecmp(attr, "system", 6) == 0)
    913  1.188      elad 		return EPERM;
    914  1.188      elad 
    915  1.188      elad 	return VOP_ACCESS(vp, access_mode, cred);
    916  1.188      elad }
    917