1 /* $NetBSD: genfs_vnops.c,v 1.18 2000/05/29 18:59:51 mycroft 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 "opt_nfsserver.h" 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/proc.h> 42 #include <sys/kernel.h> 43 #include <sys/mount.h> 44 #include <sys/namei.h> 45 #include <sys/vnode.h> 46 #include <sys/fcntl.h> 47 #include <sys/malloc.h> 48 #include <sys/poll.h> 49 50 #include <miscfs/genfs/genfs.h> 51 #include <miscfs/specfs/specdev.h> 52 53 #ifdef NFSSERVER 54 #include <nfs/rpcv2.h> 55 #include <nfs/nfsproto.h> 56 #include <nfs/nfs.h> 57 #include <nfs/nqnfs.h> 58 #include <nfs/nfs_var.h> 59 #endif 60 61 int 62 genfs_poll(v) 63 void *v; 64 { 65 struct vop_poll_args /* { 66 struct vnode *a_vp; 67 int a_events; 68 struct proc *a_p; 69 } */ *ap = v; 70 71 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); 72 } 73 74 int 75 genfs_fsync(v) 76 void *v; 77 { 78 struct vop_fsync_args /* { 79 struct vnode *a_vp; 80 struct ucred *a_cred; 81 int a_flags; 82 struct proc *a_p; 83 } */ *ap = v; 84 struct vnode *vp = ap->a_vp; 85 int wait; 86 87 wait = (ap->a_flags & FSYNC_WAIT) != 0; 88 vflushbuf(vp, wait); 89 if ((ap->a_flags & FSYNC_DATAONLY) != 0) 90 return (0); 91 else 92 return (VOP_UPDATE(vp, NULL, NULL, wait ? UPDATE_WAIT : 0)); 93 } 94 95 int 96 genfs_seek(v) 97 void *v; 98 { 99 struct vop_seek_args /* { 100 struct vnode *a_vp; 101 off_t a_oldoff; 102 off_t a_newoff; 103 struct ucred *a_ucred; 104 } */ *ap = v; 105 106 if (ap->a_newoff < 0) 107 return (EINVAL); 108 109 return (0); 110 } 111 112 int 113 genfs_abortop(v) 114 void *v; 115 { 116 struct vop_abortop_args /* { 117 struct vnode *a_dvp; 118 struct componentname *a_cnp; 119 } */ *ap = v; 120 121 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 122 FREE(ap->a_cnp->cn_pnbuf, M_NAMEI); 123 return (0); 124 } 125 126 int 127 genfs_fcntl(v) 128 void *v; 129 { 130 struct vop_fcntl_args /* { 131 struct vnode *a_vp; 132 u_int a_command; 133 caddr_t a_data; 134 int a_fflag; 135 struct ucred *a_cred; 136 struct proc *a_p; 137 } */ *ap = v; 138 139 if (ap->a_command == F_SETFL) 140 return (0); 141 else 142 return (EOPNOTSUPP); 143 } 144 145 /*ARGSUSED*/ 146 int 147 genfs_badop(v) 148 void *v; 149 { 150 151 panic("genfs: bad op"); 152 } 153 154 /*ARGSUSED*/ 155 int 156 genfs_nullop(v) 157 void *v; 158 { 159 160 return (0); 161 } 162 163 /*ARGSUSED*/ 164 int 165 genfs_einval(v) 166 void *v; 167 { 168 169 return (EINVAL); 170 } 171 172 /*ARGSUSED*/ 173 int 174 genfs_eopnotsupp(v) 175 void *v; 176 { 177 178 return (EOPNOTSUPP); 179 } 180 181 /* 182 * Called when an fs doesn't support a particular vop but the vop needs to 183 * vrele, vput, or vunlock passed in vnodes. 184 */ 185 int 186 genfs_eopnotsupp_rele(v) 187 void *v; 188 { 189 struct vop_generic_args /* 190 struct vnodeop_desc *a_desc; 191 / * other random data follows, presumably * / 192 } */ *ap = v; 193 struct vnodeop_desc *desc = ap->a_desc; 194 struct vnode *vp; 195 int flags, i, j, offset; 196 197 flags = desc->vdesc_flags; 198 for (i = 0; i < VDESC_MAX_VPS; flags >>=1, i++) { 199 if ((offset = desc->vdesc_vp_offsets[i]) == VDESC_NO_OFFSET) 200 break; /* stop at end of list */ 201 if ((j = flags & VDESC_VP0_WILLPUT)) { 202 vp = *VOPARG_OFFSETTO(struct vnode**,offset,ap); 203 switch (j) { 204 case VDESC_VP0_WILLPUT: 205 vput(vp); 206 break; 207 case VDESC_VP0_WILLUNLOCK: 208 VOP_UNLOCK(vp, 0); 209 break; 210 case VDESC_VP0_WILLRELE: 211 vrele(vp); 212 break; 213 } 214 } 215 } 216 217 return (EOPNOTSUPP); 218 } 219 220 /*ARGSUSED*/ 221 int 222 genfs_ebadf(v) 223 void *v; 224 { 225 226 return (EBADF); 227 } 228 229 /* ARGSUSED */ 230 int 231 genfs_enoioctl(v) 232 void *v; 233 { 234 235 return (ENOTTY); 236 } 237 238 239 /* 240 * Eliminate all activity associated with the requested vnode 241 * and with all vnodes aliased to the requested vnode. 242 */ 243 int 244 genfs_revoke(v) 245 void *v; 246 { 247 struct vop_revoke_args /* { 248 struct vnode *a_vp; 249 int a_flags; 250 } */ *ap = v; 251 struct vnode *vp, *vq; 252 struct proc *p = curproc; /* XXX */ 253 254 #ifdef DIAGNOSTIC 255 if ((ap->a_flags & REVOKEALL) == 0) 256 panic("genfs_revoke: not revokeall"); 257 #endif 258 259 vp = ap->a_vp; 260 simple_lock(&vp->v_interlock); 261 262 if (vp->v_flag & VALIASED) { 263 /* 264 * If a vgone (or vclean) is already in progress, 265 * wait until it is done and return. 266 */ 267 if (vp->v_flag & VXLOCK) { 268 vp->v_flag |= VXWANT; 269 simple_unlock(&vp->v_interlock); 270 tsleep((caddr_t)vp, PINOD, "vop_revokeall", 0); 271 return (0); 272 } 273 /* 274 * Ensure that vp will not be vgone'd while we 275 * are eliminating its aliases. 276 */ 277 vp->v_flag |= VXLOCK; 278 simple_unlock(&vp->v_interlock); 279 while (vp->v_flag & VALIASED) { 280 simple_lock(&spechash_slock); 281 for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { 282 if (vq->v_rdev != vp->v_rdev || 283 vq->v_type != vp->v_type || vp == vq) 284 continue; 285 simple_unlock(&spechash_slock); 286 vgone(vq); 287 break; 288 } 289 if (vq == NULLVP) 290 simple_unlock(&spechash_slock); 291 } 292 /* 293 * Remove the lock so that vgone below will 294 * really eliminate the vnode after which time 295 * vgone will awaken any sleepers. 296 */ 297 simple_lock(&vp->v_interlock); 298 vp->v_flag &= ~VXLOCK; 299 } 300 vgonel(vp, p); 301 return (0); 302 } 303 304 /* 305 * Lock the node. 306 */ 307 int 308 genfs_lock(v) 309 void *v; 310 { 311 struct vop_lock_args /* { 312 struct vnode *a_vp; 313 int a_flags; 314 } */ *ap = v; 315 struct vnode *vp = ap->a_vp; 316 317 return (lockmgr(&vp->v_lock, ap->a_flags, &vp->v_interlock)); 318 } 319 320 /* 321 * Unlock the node. 322 */ 323 int 324 genfs_unlock(v) 325 void *v; 326 { 327 struct vop_unlock_args /* { 328 struct vnode *a_vp; 329 int a_flags; 330 } */ *ap = v; 331 struct vnode *vp = ap->a_vp; 332 333 return (lockmgr(&vp->v_lock, ap->a_flags | LK_RELEASE, 334 &vp->v_interlock)); 335 } 336 337 /* 338 * Return whether or not the node is locked. 339 */ 340 int 341 genfs_islocked(v) 342 void *v; 343 { 344 struct vop_islocked_args /* { 345 struct vnode *a_vp; 346 } */ *ap = v; 347 struct vnode *vp = ap->a_vp; 348 349 return (lockstatus(&vp->v_lock)); 350 } 351 352 /* 353 * Stubs to use when there is no locking to be done on the underlying object. 354 */ 355 int 356 genfs_nolock(v) 357 void *v; 358 { 359 struct vop_lock_args /* { 360 struct vnode *a_vp; 361 int a_flags; 362 struct proc *a_p; 363 } */ *ap = v; 364 365 /* 366 * Since we are not using the lock manager, we must clear 367 * the interlock here. 368 */ 369 if (ap->a_flags & LK_INTERLOCK) 370 simple_unlock(&ap->a_vp->v_interlock); 371 return (0); 372 } 373 374 int 375 genfs_nounlock(v) 376 void *v; 377 { 378 return (0); 379 } 380 381 int 382 genfs_noislocked(v) 383 void *v; 384 { 385 return (0); 386 } 387 388 /* 389 * Local lease check for NFS servers. Just set up args and let 390 * nqsrv_getlease() do the rest. If NFSSERVER is not in the kernel, 391 * this is a null operation. 392 */ 393 int 394 genfs_lease_check(v) 395 void *v; 396 { 397 #ifdef NFSSERVER 398 struct vop_lease_args /* { 399 struct vnode *a_vp; 400 struct proc *a_p; 401 struct ucred *a_cred; 402 int a_flag; 403 } */ *ap = v; 404 u_int32_t duration = 0; 405 int cache; 406 u_quad_t frev; 407 408 (void) nqsrv_getlease(ap->a_vp, &duration, ND_CHECK | ap->a_flag, 409 NQLOCALSLP, ap->a_p, (struct mbuf *)0, &cache, &frev, ap->a_cred); 410 return (0); 411 #else 412 return (0); 413 #endif /* NFSSERVER */ 414 } 415