Home | History | Annotate | Line # | Download | only in genfs
genfs_vnops.c revision 1.7
      1 /*	$NetBSD: genfs_vnops.c,v 1.7 1998/06/05 19:53:00 kleink 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_flags;
     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_flags & FSYNC_WAIT) != 0);
     77 	if ((ap->a_flags & FSYNC_DATAONLY) != 0) {
     78 		return (0);
     79 	} else {
     80 		TIMEVAL_TO_TIMESPEC(&time, &ts);
     81 		return (VOP_UPDATE(ap->a_vp, &ts, &ts,
     82 		    (ap->a_flags & FSYNC_WAIT) != 0));
     83 	}
     84 }
     85 
     86 int
     87 genfs_seek(v)
     88 	void *v;
     89 {
     90 	struct vop_seek_args /* {
     91 		struct vnode *a_vp;
     92 		off_t a_oldoff;
     93 		off_t a_newoff;
     94 		struct ucred *a_ucred;
     95 	} */ *ap = v;
     96 
     97 	if (ap->a_newoff < 0)
     98 		return (EINVAL);
     99 
    100 	return (0);
    101 }
    102 
    103 int
    104 genfs_abortop(v)
    105 	void *v;
    106 {
    107 	struct vop_abortop_args /* {
    108 		struct vnode *a_dvp;
    109 		struct componentname *a_cnp;
    110 	} */ *ap = v;
    111 
    112 	if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
    113 		FREE(ap->a_cnp->cn_pnbuf, M_NAMEI);
    114 	return (0);
    115 }
    116 
    117 /*ARGSUSED*/
    118 int
    119 genfs_badop(v)
    120 	void *v;
    121 {
    122 
    123 	panic("genfs: bad op");
    124 }
    125 
    126 /*ARGSUSED*/
    127 int
    128 genfs_nullop(v)
    129 	void *v;
    130 {
    131 
    132 	return (0);
    133 }
    134 
    135 /*ARGSUSED*/
    136 int
    137 genfs_eopnotsupp(v)
    138 	void *v;
    139 {
    140 
    141 	return (EOPNOTSUPP);
    142 }
    143 
    144 /*ARGSUSED*/
    145 int
    146 genfs_ebadf(v)
    147 	void *v;
    148 {
    149 
    150 	return (EBADF);
    151 }
    152 
    153 
    154 /*
    155  * Eliminate all activity associated with  the requested vnode
    156  * and with all vnodes aliased to the requested vnode.
    157  */
    158 int
    159 genfs_revoke(v)
    160 	void *v;
    161 {
    162 	struct vop_revoke_args /* {
    163 		struct vnode *a_vp;
    164 		int a_flags;
    165 	} */ *ap = v;
    166 	struct vnode *vp, *vq;
    167 	struct proc *p = curproc;	/* XXX */
    168 
    169 #ifdef DIAGNOSTIC
    170 	if ((ap->a_flags & REVOKEALL) == 0)
    171 		panic("genfs_revoke: not revokeall");
    172 #endif
    173 
    174 	vp = ap->a_vp;
    175 	simple_lock(&vp->v_interlock);
    176 
    177 	if (vp->v_flag & VALIASED) {
    178 		/*
    179 		 * If a vgone (or vclean) is already in progress,
    180 		 * wait until it is done and return.
    181 		 */
    182 		if (vp->v_flag & VXLOCK) {
    183 			vp->v_flag |= VXWANT;
    184 			simple_unlock(&vp->v_interlock);
    185 			tsleep((caddr_t)vp, PINOD, "vop_revokeall", 0);
    186 			return (0);
    187 		}
    188 		/*
    189 		 * Ensure that vp will not be vgone'd while we
    190 		 * are eliminating its aliases.
    191 		 */
    192 		vp->v_flag |= VXLOCK;
    193 		simple_unlock(&vp->v_interlock);
    194 		while (vp->v_flag & VALIASED) {
    195 			simple_lock(&spechash_slock);
    196 			for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) {
    197 				if (vq->v_rdev != vp->v_rdev ||
    198 				    vq->v_type != vp->v_type || vp == vq)
    199 					continue;
    200 				simple_unlock(&spechash_slock);
    201 				vgone(vq);
    202 				break;
    203 			}
    204 			if (vq == NULLVP)
    205 				simple_unlock(&spechash_slock);
    206 		}
    207 		/*
    208 		 * Remove the lock so that vgone below will
    209 		 * really eliminate the vnode after which time
    210 		 * vgone will awaken any sleepers.
    211 		 */
    212 		simple_lock(&vp->v_interlock);
    213 		vp->v_flag &= ~VXLOCK;
    214 	}
    215 	vgonel(vp, p);
    216 	return (0);
    217 }
    218 
    219 
    220 /*
    221  * Stubs to use when there is no locking to be done on the underlying object.
    222  * A minimal shared lock is necessary to ensure that the underlying object
    223  * is not revoked while an operation is in progress. So, an active shared
    224  * count is maintained in an auxillary vnode lock structure.
    225  */
    226 int
    227 genfs_nolock(v)
    228 	void *v;
    229 {
    230 	struct vop_lock_args /* {
    231 		struct vnode *a_vp;
    232 		int a_flags;
    233 		struct proc *a_p;
    234 	} */ *ap = v;
    235 
    236 #ifdef notyet
    237 	/*
    238 	 * This code cannot be used until all the non-locking filesystems
    239 	 * (notably NFS) are converted to properly lock and release nodes.
    240 	 * Also, certain vnode operations change the locking state within
    241 	 * the operation (create, mknod, remove, link, rename, mkdir, rmdir,
    242 	 * and symlink). Ideally these operations should not change the
    243 	 * lock state, but should be changed to let the caller of the
    244 	 * function unlock them. Otherwise all intermediate vnode layers
    245 	 * (such as union, umapfs, etc) must catch these functions to do
    246 	 * the necessary locking at their layer. Note that the inactive
    247 	 * and lookup operations also change their lock state, but this
    248 	 * cannot be avoided, so these two operations will always need
    249 	 * to be handled in intermediate layers.
    250 	 */
    251 	struct vnode *vp = ap->a_vp;
    252 	int vnflags, flags = ap->a_flags;
    253 
    254 	if (vp->v_vnlock == NULL) {
    255 		if ((flags & LK_TYPE_MASK) == LK_DRAIN)
    256 			return (0);
    257 		MALLOC(vp->v_vnlock, struct lock *, sizeof(struct lock),
    258 		    M_VNODE, M_WAITOK);
    259 		lockinit(vp->v_vnlock, PVFS, "vnlock", 0, 0);
    260 	}
    261 	switch (flags & LK_TYPE_MASK) {
    262 	case LK_DRAIN:
    263 		vnflags = LK_DRAIN;
    264 		break;
    265 	case LK_EXCLUSIVE:
    266 	case LK_SHARED:
    267 		vnflags = LK_SHARED;
    268 		break;
    269 	case LK_UPGRADE:
    270 	case LK_EXCLUPGRADE:
    271 	case LK_DOWNGRADE:
    272 		return (0);
    273 	case LK_RELEASE:
    274 	default:
    275 		panic("vop_nolock: bad operation %d", flags & LK_TYPE_MASK);
    276 	}
    277 	if (flags & LK_INTERLOCK)
    278 		vnflags |= LK_INTERLOCK;
    279 	return(lockmgr(vp->v_vnlock, vnflags, &vp->v_interlock));
    280 #else /* for now */
    281 	/*
    282 	 * Since we are not using the lock manager, we must clear
    283 	 * the interlock here.
    284 	 */
    285 	if (ap->a_flags & LK_INTERLOCK)
    286 		simple_unlock(&ap->a_vp->v_interlock);
    287 	return (0);
    288 #endif
    289 }
    290 
    291 /*
    292  * Decrement the active use count.
    293  */
    294 int
    295 genfs_nounlock(v)
    296 	void *v;
    297 {
    298 	struct vop_unlock_args /* {
    299 		struct vnode *a_vp;
    300 		int a_flags;
    301 		struct proc *a_p;
    302 	} */ *ap = v;
    303 	struct vnode *vp = ap->a_vp;
    304 
    305 	if (vp->v_vnlock == NULL)
    306 		return (0);
    307 	return (lockmgr(vp->v_vnlock, LK_RELEASE, NULL));
    308 }
    309 
    310 /*
    311  * Return whether or not the node is in use.
    312  */
    313 int
    314 genfs_noislocked(v)
    315 	void *v;
    316 {
    317 	struct vop_islocked_args /* {
    318 		struct vnode *a_vp;
    319 	} */ *ap = v;
    320 	struct vnode *vp = ap->a_vp;
    321 
    322 	if (vp->v_vnlock == NULL)
    323 		return (0);
    324 	return (lockstatus(vp->v_vnlock));
    325 }
    326