1 /* $OpenBSD: vfs_default.c,v 1.21 2003/07/21 22:44:50 tedu Exp $ */ 2 3 /* 4 * Portions of this code are: 5 * 6 * Copyright (c) 1989, 1993 7 * The Regents of the University of California. All rights reserved. 8 * (c) UNIX System Laboratories, Inc. 9 * All or some portions of this file are derived from material licensed 10 * to the University of California by American Telephone and Telegraph 11 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 12 * the permission of UNIX System Laboratories, Inc. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions and the following disclaimer. 19 * 2. Redistributions in binary form must reproduce the above copyright 20 * notice, this list of conditions and the following disclaimer in the 21 * documentation and/or other materials provided with the distribution. 22 * 3. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/proc.h> 43 #include <sys/mount.h> 44 #include <sys/vnode.h> 45 #include <sys/namei.h> 46 #include <sys/malloc.h> 47 #include <sys/event.h> 48 #include <miscfs/specfs/specdev.h> 49 50 51 extern struct simplelock spechash_slock; 52 53 int filt_generic_readwrite(struct knote *kn, long hint); 54 void filt_generic_detach(struct knote *kn); 55 56 /* 57 * Eliminate all activity associated with the requested vnode 58 * and with all vnodes aliased to the requested vnode. 59 */ 60 int 61 vop_generic_revoke(v) 62 void *v; 63 { 64 struct vop_revoke_args /* { 65 struct vnode *a_vp; 66 int a_flags; 67 } */ *ap = v; 68 struct vnode *vp, *vq; 69 struct proc *p = curproc; 70 71 #ifdef DIAGNOSTIC 72 if ((ap->a_flags & REVOKEALL) == 0) 73 panic("vop_generic_revoke"); 74 #endif 75 76 vp = ap->a_vp; 77 simple_lock(&vp->v_interlock); 78 79 if (vp->v_flag & VALIASED) { 80 /* 81 * If a vgone (or vclean) is already in progress, 82 * wait until it is done and return. 83 */ 84 if (vp->v_flag & VXLOCK) { 85 vp->v_flag |= VXWANT; 86 simple_unlock(&vp->v_interlock); 87 tsleep(vp, PINOD, "vop_generic_revokeall", 0); 88 return(0); 89 } 90 /* 91 * Ensure that vp will not be vgone'd while we 92 * are eliminating its aliases. 93 */ 94 vp->v_flag |= VXLOCK; 95 simple_unlock(&vp->v_interlock); 96 while (vp->v_flag & VALIASED) { 97 simple_lock(&spechash_slock); 98 for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { 99 if (vq->v_rdev != vp->v_rdev || 100 vq->v_type != vp->v_type || vp == vq) 101 continue; 102 simple_unlock(&spechash_slock); 103 vgone(vq); 104 break; 105 } 106 simple_unlock(&spechash_slock); 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 255 struct filterops generic_filtops = 256 { 1, NULL, filt_generic_detach, filt_generic_readwrite }; 257 258 int 259 vop_generic_kqfilter(v) 260 void *v; 261 { 262 struct vop_kqfilter_args /* { 263 struct vnode *a_vp; 264 struct knote *a_kn; 265 } */ *ap = v; 266 struct knote *kn = ap->a_kn; 267 268 switch (kn->kn_filter) { 269 case EVFILT_READ: 270 case EVFILT_WRITE: 271 kn->kn_fop = &generic_filtops; 272 break; 273 default: 274 return (1); 275 } 276 277 return (0); 278 } 279 280 void 281 filt_generic_detach(struct knote *kn) 282 { 283 } 284 285 int 286 filt_generic_readwrite(struct knote *kn, long hint) 287 { 288 /* 289 * filesystem is gone, so set the EOF flag and schedule 290 * the knote for deletion. 291 */ 292 if (hint == NOTE_REVOKE) { 293 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 294 return (1); 295 } 296 297 kn->kn_data = 0; 298 return (1); 299 } 300 301 int lease_check(void *); 302 303 int 304 lease_check(void *v) 305 { 306 return (0); 307 } 308 309 /* 310 * vfs default ops 311 * used to fill the vfs function table to get reasonable default return values. 312 */ 313 int 314 vfs_stdextattrctl(mp, cmd, filename_vp, attrnamespace, attrname, td) 315 struct mount *mp; 316 int cmd; 317 struct vnode *filename_vp; 318 int attrnamespace; 319 const char *attrname; 320 struct proc *td; 321 { 322 return(EOPNOTSUPP); 323 } 324