Home | History | Annotate | Line # | Download | only in genfs
genfs_vnops.c revision 1.6
      1 /*	$NetBSD: genfs_vnops.c,v 1.6 1998/03/01 02:22:04 fvdl Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1982, 1986, 1989, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  *
     35  */
     36 
     37 #include <sys/param.h>
     38 #include <sys/systm.h>
     39 #include <sys/proc.h>
     40 #include <sys/kernel.h>
     41 #include <sys/mount.h>
     42 #include <sys/namei.h>
     43 #include <sys/vnode.h>
     44 #include <sys/malloc.h>
     45 #include <sys/poll.h>
     46 
     47 #include <miscfs/genfs/genfs.h>
     48 #include <miscfs/specfs/specdev.h>
     49 
     50 int
     51 genfs_poll(v)
     52 	void *v;
     53 {
     54 	struct vop_poll_args /* {
     55 		struct vnode *a_vp;
     56 		int a_events;
     57 		struct proc *a_p;
     58 	} */ *ap = v;
     59 
     60 	return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
     61 }
     62 
     63 int
     64 genfs_fsync(v)
     65 	void *v;
     66 {
     67 	struct vop_fsync_args /* {
     68 		struct vnode *a_vp;
     69 		struct ucred *a_cred;
     70 		int a_waitfor;
     71 		struct proc *a_p;
     72 	} */ *ap = v;
     73 	register struct vnode *vp = ap->a_vp;
     74 	struct timespec ts;
     75 
     76 	vflushbuf(vp, ap->a_waitfor == MNT_WAIT);
     77 	TIMEVAL_TO_TIMESPEC(&time, &ts);
     78 	return (VOP_UPDATE(ap->a_vp, &ts, &ts, ap->a_waitfor == MNT_WAIT));
     79 }
     80 
     81 int
     82 genfs_seek(v)
     83 	void *v;
     84 {
     85 	struct vop_seek_args /* {
     86 		struct vnode *a_vp;
     87 		off_t a_oldoff;
     88 		off_t a_newoff;
     89 		struct ucred *a_ucred;
     90 	} */ *ap = v;
     91 
     92 	if (ap->a_newoff < 0)
     93 		return (EINVAL);
     94 
     95 	return (0);
     96 }
     97 
     98 int
     99 genfs_abortop(v)
    100 	void *v;
    101 {
    102 	struct vop_abortop_args /* {
    103 		struct vnode *a_dvp;
    104 		struct componentname *a_cnp;
    105 	} */ *ap = v;
    106 
    107 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
    108 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
    109 	return (0);
    110 }
    111 
    112 /*ARGSUSED*/
    113 int
    114 genfs_badop(v)
    115 	void *v;
    116 {
    117 
    118 	panic("genfs: bad op");
    119 }
    120 
    121 /*ARGSUSED*/
    122 int
    123 genfs_nullop(v)
    124 	void *v;
    125 {
    126 
    127 	return (0);
    128 }
    129 
    130 /*ARGSUSED*/
    131 int
    132 genfs_eopnotsupp(v)
    133 	void *v;
    134 {
    135 
    136 	return (EOPNOTSUPP);
    137 }
    138 
    139 /*ARGSUSED*/
    140 int
    141 genfs_ebadf(v)
    142 	void *v;
    143 {
    144 
    145 	return (EBADF);
    146 }
    147 
    148 
    149 /*
    150  * Eliminate all activity associated with  the requested vnode
    151  * and with all vnodes aliased to the requested vnode.
    152  */
    153 int
    154 genfs_revoke(v)
    155 	void *v;
    156 {
    157 	struct vop_revoke_args /* {
    158 		struct vnode *a_vp;
    159 		int a_flags;
    160 	} */ *ap = v;
    161 	struct vnode *vp, *vq;
    162 	struct proc *p = curproc;	/* XXX */
    163 
    164 #ifdef DIAGNOSTIC
    165 	if ((ap->a_flags & REVOKEALL) == 0)
    166 		panic("genfs_revoke: not revokeall");
    167 #endif
    168 
    169 	vp = ap->a_vp;
    170 	simple_lock(&vp->v_interlock);
    171 
    172 	if (vp->v_flag & VALIASED) {
    173 		/*
    174 		 * If a vgone (or vclean) is already in progress,
    175 		 * wait until it is done and return.
    176 		 */
    177 		if (vp->v_flag & VXLOCK) {
    178 			vp->v_flag |= VXWANT;
    179 			simple_unlock(&vp->v_interlock);
    180 			tsleep((caddr_t)vp, PINOD, "vop_revokeall", 0);
    181 			return (0);
    182 		}
    183 		/*
    184 		 * Ensure that vp will not be vgone'd while we
    185 		 * are eliminating its aliases.
    186 		 */
    187 		vp->v_flag |= VXLOCK;
    188 		simple_unlock(&vp->v_interlock);
    189 		while (vp->v_flag & VALIASED) {
    190 			simple_lock(&spechash_slock);
    191 			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
    192 				if (vq->v_rdev != vp->v_rdev ||
    193 				    vq->v_type != vp->v_type || vp == vq)
    194 					continue;
    195 				simple_unlock(&spechash_slock);
    196 				vgone(vq);
    197 				break;
    198 			}
    199 			if (vq == NULLVP)
    200 				simple_unlock(&spechash_slock);
    201 		}
    202 		/*
    203 		 * Remove the lock so that vgone below will
    204 		 * really eliminate the vnode after which time
    205 		 * vgone will awaken any sleepers.
    206 		 */
    207 		simple_lock(&vp->v_interlock);
    208 		vp->v_flag &= ~VXLOCK;
    209 	}
    210 	vgonel(vp, p);
    211 	return (0);
    212 }
    213 
    214 
    215 /*
    216  * Stubs to use when there is no locking to be done on the underlying object.
    217  * A minimal shared lock is necessary to ensure that the underlying object
    218  * is not revoked while an operation is in progress. So, an active shared
    219  * count is maintained in an auxillary vnode lock structure.
    220  */
    221 int
    222 genfs_nolock(v)
    223 	void *v;
    224 {
    225 	struct vop_lock_args /* {
    226 		struct vnode *a_vp;
    227 		int a_flags;
    228 		struct proc *a_p;
    229 	} */ *ap = v;
    230 
    231 #ifdef notyet
    232 	/*
    233 	 * This code cannot be used until all the non-locking filesystems
    234 	 * (notably NFS) are converted to properly lock and release nodes.
    235 	 * Also, certain vnode operations change the locking state within
    236 	 * the operation (create, mknod, remove, link, rename, mkdir, rmdir,
    237 	 * and symlink). Ideally these operations should not change the
    238 	 * lock state, but should be changed to let the caller of the
    239 	 * function unlock them. Otherwise all intermediate vnode layers
    240 	 * (such as union, umapfs, etc) must catch these functions to do
    241 	 * the necessary locking at their layer. Note that the inactive
    242 	 * and lookup operations also change their lock state, but this
    243 	 * cannot be avoided, so these two operations will always need
    244 	 * to be handled in intermediate layers.
    245 	 */
    246 	struct vnode *vp = ap->a_vp;
    247 	int vnflags, flags = ap->a_flags;
    248 
    249 	if (vp->v_vnlock == NULL) {
    250 		if ((flags & LK_TYPE_MASK) == LK_DRAIN)
    251 			return (0);
    252 		MALLOC(vp->v_vnlock, struct lock *, sizeof(struct lock),
    253 		    M_VNODE, M_WAITOK);
    254 		lockinit(vp->v_vnlock, PVFS, "vnlock", 0, 0);
    255 	}
    256 	switch (flags & LK_TYPE_MASK) {
    257 	case LK_DRAIN:
    258 		vnflags = LK_DRAIN;
    259 		break;
    260 	case LK_EXCLUSIVE:
    261 	case LK_SHARED:
    262 		vnflags = LK_SHARED;
    263 		break;
    264 	case LK_UPGRADE:
    265 	case LK_EXCLUPGRADE:
    266 	case LK_DOWNGRADE:
    267 		return (0);
    268 	case LK_RELEASE:
    269 	default:
    270 		panic("vop_nolock: bad operation %d", flags & LK_TYPE_MASK);
    271 	}
    272 	if (flags & LK_INTERLOCK)
    273 		vnflags |= LK_INTERLOCK;
    274 	return(lockmgr(vp->v_vnlock, vnflags, &vp->v_interlock));
    275 #else /* for now */
    276 	/*
    277 	 * Since we are not using the lock manager, we must clear
    278 	 * the interlock here.
    279 	 */
    280 	if (ap->a_flags & LK_INTERLOCK)
    281 		simple_unlock(&ap->a_vp->v_interlock);
    282 	return (0);
    283 #endif
    284 }
    285 
    286 /*
    287  * Decrement the active use count.
    288  */
    289 int
    290 genfs_nounlock(v)
    291 	void *v;
    292 {
    293 	struct vop_unlock_args /* {
    294 		struct vnode *a_vp;
    295 		int a_flags;
    296 		struct proc *a_p;
    297 	} */ *ap = v;
    298 	struct vnode *vp = ap->a_vp;
    299 
    300 	if (vp->v_vnlock == NULL)
    301 		return (0);
    302 	return (lockmgr(vp->v_vnlock, LK_RELEASE, NULL));
    303 }
    304 
    305 /*
    306  * Return whether or not the node is in use.
    307  */
    308 int
    309 genfs_noislocked(v)
    310 	void *v;
    311 {
    312 	struct vop_islocked_args /* {
    313 		struct vnode *a_vp;
    314 	} */ *ap = v;
    315 	struct vnode *vp = ap->a_vp;
    316 
    317 	if (vp->v_vnlock == NULL)
    318 		return (0);
    319 	return (lockstatus(vp->v_vnlock));
    320 }
    321