1 /* $OpenBSD: vfs_default.c,v 1.3 1998/08/06 19:34:24 csapuntz Exp $ */ 2 3 4 /* 5 * Portions of this code are: 6 * 7 * Copyright (c) 1989, 1993 8 * The Regents of the University of California. All rights reserved. 9 * (c) UNIX System Laboratories, Inc. 10 * All or some portions of this file are derived from material licensed 11 * to the University of California by American Telephone and Telegraph 12 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 13 * the permission of UNIX System Laboratories, Inc. 14 * 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in the 22 * documentation and/or other materials provided with the distribution. 23 * 3. All advertising materials mentioning features or use of this software 24 * must display the following acknowledgement: 25 * This product includes software developed by the University of 26 * California, Berkeley and its contributors. 27 * 4. Neither the name of the University nor the names of its contributors 28 * may be used to endorse or promote products derived from this software 29 * without specific prior written permission. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 32 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 35 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 39 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 40 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 41 * SUCH DAMAGE. 42 */ 43 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/proc.h> 48 #include <sys/mount.h> 49 #include <sys/vnode.h> 50 #include <sys/namei.h> 51 #include <sys/malloc.h> 52 #include <miscfs/specfs/specdev.h> 53 54 55 extern struct simplelock spechash_slock; 56 57 /* 58 * Eliminate all activity associated with the requested vnode 59 * and with all vnodes aliased to the requested vnode. 60 */ 61 int 62 vop_generic_revoke(v) 63 void *v; 64 { 65 struct vop_revoke_args /* { 66 struct vnode *a_vp; 67 int a_flags; 68 } */ *ap = v; 69 struct vnode *vp, *vq; 70 struct proc *p = curproc; 71 72 #ifdef DIAGNOSTIC 73 if ((ap->a_flags & REVOKEALL) == 0) 74 panic("vop_generic_revoke"); 75 #endif 76 77 vp = ap->a_vp; 78 simple_lock(&vp->v_interlock); 79 80 if (vp->v_flag & VALIASED) { 81 /* 82 * If a vgone (or vclean) is already in progress, 83 * wait until it is done and return. 84 */ 85 if (vp->v_flag & VXLOCK) { 86 vp->v_flag |= VXWANT; 87 simple_unlock(&vp->v_interlock); 88 tsleep((caddr_t)vp, PINOD, "vop_generic_revokeall", 0); 89 return(0); 90 } 91 /* 92 * Ensure that vp will not be vgone'd while we 93 * are eliminating its aliases. 94 */ 95 vp->v_flag |= VXLOCK; 96 simple_unlock(&vp->v_interlock); 97 while (vp->v_flag & VALIASED) { 98 simple_lock(&spechash_slock); 99 for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { 100 if (vq->v_rdev != vp->v_rdev || 101 vq->v_type != vp->v_type || vp == vq) 102 continue; 103 simple_unlock(&spechash_slock); 104 vgone(vq); 105 break; 106 } 107 } 108 /* 109 * Remove the lock so that vgone below will 110 * really eliminate the vnode after which time 111 * vgone will awaken any sleepers. 112 */ 113 simple_lock(&vp->v_interlock); 114 vp->v_flag &= ~VXLOCK; 115 } 116 vgonel(vp, p); 117 return (0); 118 } 119 120 121 int 122 vop_generic_bwrite(v) 123 void *v; 124 { 125 struct vop_bwrite_args *ap = v; 126 127 return (bwrite(ap->a_bp)); 128 } 129 130 131 int 132 vop_generic_abortop(v) 133 void *v; 134 { 135 struct vop_abortop_args /* { 136 struct vnode *a_dvp; 137 struct componentname *a_cnp; 138 } */ *ap = v; 139 140 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 141 FREE(ap->a_cnp->cn_pnbuf, M_NAMEI); 142 return (0); 143 } 144 145 /* 146 * Stubs to use when there is no locking to be done on the underlying object. 147 * A minimal shared lock is necessary to ensure that the underlying object 148 * is not revoked while an operation is in progress. So, an active shared 149 * count is maintained in an auxillary vnode lock structure. 150 */ 151 int 152 vop_generic_lock(v) 153 void *v; 154 { 155 struct vop_lock_args /* { 156 struct vnode *a_vp; 157 int a_flags; 158 struct proc *a_p; 159 } */ *ap = v; 160 161 #ifdef notyet 162 /* 163 * This code cannot be used until all the non-locking filesystems 164 * (notably NFS) are converted to properly lock and release nodes. 165 * Also, certain vnode operations change the locking state within 166 * the operation (create, mknod, remove, link, rename, mkdir, rmdir, 167 * and symlink). Ideally these operations should not change the 168 * lock state, but should be changed to let the caller of the 169 * function unlock them. Otherwise all intermediate vnode layers 170 * (such as union, umapfs, etc) must catch these functions to do 171 * the necessary locking at their layer. Note that the inactive 172 * and lookup operations also change their lock state, but this 173 * cannot be avoided, so these two operations will always need 174 * to be handled in intermediate layers. 175 */ 176 struct vnode *vp = ap->a_vp; 177 int vnflags, flags = ap->a_flags; 178 179 if (vp->v_vnlock == NULL) { 180 if ((flags & LK_TYPE_MASK) == LK_DRAIN) 181 return (0); 182 MALLOC(vp->v_vnlock, struct lock *, sizeof(struct lock), 183 M_VNODE, M_WAITOK); 184 lockinit(vp->v_vnlock, PVFS, "vnlock", 0, 0); 185 } 186 switch (flags & LK_TYPE_MASK) { 187 case LK_DRAIN: 188 vnflags = LK_DRAIN; 189 break; 190 case LK_EXCLUSIVE: 191 case LK_SHARED: 192 vnflags = LK_SHARED; 193 break; 194 case LK_UPGRADE: 195 case LK_EXCLUPGRADE: 196 case LK_DOWNGRADE: 197 return (0); 198 case LK_RELEASE: 199 default: 200 panic("vop_generic_lock: bad operation %d", flags & LK_TYPE_MASK); 201 } 202 if (flags & LK_INTERLOCK) 203 vnflags |= LK_INTERLOCK; 204 return(lockmgr(vp->v_vnlock, vnflags, &vp->v_interlock, ap->a_p)); 205 #else /* for now */ 206 /* 207 * Since we are not using the lock manager, we must clear 208 * the interlock here. 209 */ 210 if (ap->a_flags & LK_INTERLOCK) 211 simple_unlock(&ap->a_vp->v_interlock); 212 return (0); 213 #endif 214 } 215 216 /* 217 * Decrement the active use count. 218 */ 219 220 int 221 vop_generic_unlock(v) 222 void *v; 223 { 224 struct vop_unlock_args /* { 225 struct vnode *a_vp; 226 int a_flags; 227 struct proc *a_p; 228 } */ *ap = v; 229 230 struct vnode *vp = ap->a_vp; 231 232 if (vp->v_vnlock == NULL) 233 return (0); 234 return (lockmgr(vp->v_vnlock, LK_RELEASE, NULL, ap->a_p)); 235 } 236 237 /* 238 * Return whether or not the node is in use. 239 */ 240 int 241 vop_generic_islocked(v) 242 void *v; 243 { 244 struct vop_islocked_args /* { 245 struct vnode *a_vp; 246 } */ *ap = v; 247 248 struct vnode *vp = ap->a_vp; 249 250 if (vp->v_vnlock == NULL) 251 return (0); 252 return (lockstatus(vp->v_vnlock)); 253 } 254