1 /* $NetBSD: genfs_vnops.c,v 1.159 2007/12/05 17:19:59 pooka 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. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 */ 32 33 #include <sys/cdefs.h> 34 __KERNEL_RCSID(0, "$NetBSD: genfs_vnops.c,v 1.159 2007/12/05 17:19:59 pooka Exp $"); 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/proc.h> 39 #include <sys/kernel.h> 40 #include <sys/mount.h> 41 #include <sys/namei.h> 42 #include <sys/vnode.h> 43 #include <sys/fcntl.h> 44 #include <sys/kmem.h> 45 #include <sys/poll.h> 46 #include <sys/mman.h> 47 #include <sys/file.h> 48 #include <sys/kauth.h> 49 #include <sys/fstrans.h> 50 51 #include <miscfs/genfs/genfs.h> 52 #include <miscfs/genfs/genfs_node.h> 53 #include <miscfs/specfs/specdev.h> 54 55 #include <uvm/uvm.h> 56 #include <uvm/uvm_pager.h> 57 58 static void filt_genfsdetach(struct knote *); 59 static int filt_genfsread(struct knote *, long); 60 static int filt_genfsvnode(struct knote *, long); 61 62 int 63 genfs_poll(void *v) 64 { 65 struct vop_poll_args /* { 66 struct vnode *a_vp; 67 int a_events; 68 struct lwp *a_l; 69 } */ *ap = v; 70 71 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); 72 } 73 74 int 75 genfs_seek(void *v) 76 { 77 struct vop_seek_args /* { 78 struct vnode *a_vp; 79 off_t a_oldoff; 80 off_t a_newoff; 81 kauth_cred_t cred; 82 } */ *ap = v; 83 84 if (ap->a_newoff < 0) 85 return (EINVAL); 86 87 return (0); 88 } 89 90 int 91 genfs_abortop(void *v) 92 { 93 struct vop_abortop_args /* { 94 struct vnode *a_dvp; 95 struct componentname *a_cnp; 96 } */ *ap = v; 97 98 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 99 PNBUF_PUT(ap->a_cnp->cn_pnbuf); 100 return (0); 101 } 102 103 int 104 genfs_fcntl(void *v) 105 { 106 struct vop_fcntl_args /* { 107 struct vnode *a_vp; 108 u_int a_command; 109 void *a_data; 110 int a_fflag; 111 kauth_cred_t a_cred; 112 struct lwp *a_l; 113 } */ *ap = v; 114 115 if (ap->a_command == F_SETFL) 116 return (0); 117 else 118 return (EOPNOTSUPP); 119 } 120 121 /*ARGSUSED*/ 122 int 123 genfs_badop(void *v) 124 { 125 126 panic("genfs: bad op"); 127 } 128 129 /*ARGSUSED*/ 130 int 131 genfs_nullop(void *v) 132 { 133 134 return (0); 135 } 136 137 /*ARGSUSED*/ 138 int 139 genfs_einval(void *v) 140 { 141 142 return (EINVAL); 143 } 144 145 /* 146 * Called when an fs doesn't support a particular vop. 147 * This takes care to vrele, vput, or vunlock passed in vnodes. 148 */ 149 int 150 genfs_eopnotsupp(void *v) 151 { 152 struct vop_generic_args /* 153 struct vnodeop_desc *a_desc; 154 / * other random data follows, presumably * / 155 } */ *ap = v; 156 struct vnodeop_desc *desc = ap->a_desc; 157 struct vnode *vp, *vp_last = NULL; 158 int flags, i, j, offset; 159 160 flags = desc->vdesc_flags; 161 for (i = 0; i < VDESC_MAX_VPS; flags >>=1, i++) { 162 if ((offset = desc->vdesc_vp_offsets[i]) == VDESC_NO_OFFSET) 163 break; /* stop at end of list */ 164 if ((j = flags & VDESC_VP0_WILLPUT)) { 165 vp = *VOPARG_OFFSETTO(struct vnode **, offset, ap); 166 167 /* Skip if NULL */ 168 if (!vp) 169 continue; 170 171 switch (j) { 172 case VDESC_VP0_WILLPUT: 173 /* Check for dvp == vp cases */ 174 if (vp == vp_last) 175 vrele(vp); 176 else { 177 vput(vp); 178 vp_last = vp; 179 } 180 break; 181 case VDESC_VP0_WILLUNLOCK: 182 VOP_UNLOCK(vp, 0); 183 break; 184 case VDESC_VP0_WILLRELE: 185 vrele(vp); 186 break; 187 } 188 } 189 } 190 191 return (EOPNOTSUPP); 192 } 193 194 /*ARGSUSED*/ 195 int 196 genfs_ebadf(void *v) 197 { 198 199 return (EBADF); 200 } 201 202 /* ARGSUSED */ 203 int 204 genfs_enoioctl(void *v) 205 { 206 207 return (EPASSTHROUGH); 208 } 209 210 211 /* 212 * Eliminate all activity associated with the requested vnode 213 * and with all vnodes aliased to the requested vnode. 214 */ 215 int 216 genfs_revoke(void *v) 217 { 218 struct vop_revoke_args /* { 219 struct vnode *a_vp; 220 int a_flags; 221 } */ *ap = v; 222 struct vnode *vp, *vq; 223 struct lwp *l = curlwp; /* XXX */ 224 225 #ifdef DIAGNOSTIC 226 if ((ap->a_flags & REVOKEALL) == 0) 227 panic("genfs_revoke: not revokeall"); 228 #endif 229 230 vp = ap->a_vp; 231 simple_lock(&vp->v_interlock); 232 233 if (vp->v_iflag & VI_ALIASED) { 234 /* 235 * If a vgone (or vclean) is already in progress, 236 * wait until it is done and return. 237 */ 238 if (vp->v_iflag & VI_XLOCK) { 239 vp->v_iflag |= VI_XWANT; 240 ltsleep(vp, PINOD|PNORELOCK, "vop_revokeall", 0, 241 &vp->v_interlock); 242 return (0); 243 } 244 /* 245 * Ensure that vp will not be vgone'd while we 246 * are eliminating its aliases. 247 */ 248 vp->v_iflag |= VI_XLOCK; 249 simple_unlock(&vp->v_interlock); 250 while (vp->v_iflag & VI_ALIASED) { 251 simple_lock(&spechash_slock); 252 for (vq = *vp->v_hashchain; vq; vq = vq->v_specnext) { 253 if (vq->v_rdev != vp->v_rdev || 254 vq->v_type != vp->v_type || vp == vq) 255 continue; 256 simple_unlock(&spechash_slock); 257 vgone(vq); 258 break; 259 } 260 if (vq == NULLVP) 261 simple_unlock(&spechash_slock); 262 } 263 /* 264 * Remove the lock so that vgone below will 265 * really eliminate the vnode after which time 266 * vgone will awaken any sleepers. 267 */ 268 simple_lock(&vp->v_interlock); 269 vp->v_iflag &= ~VI_XLOCK; 270 } 271 vgonel(vp, l); 272 return (0); 273 } 274 275 /* 276 * Lock the node. 277 */ 278 int 279 genfs_lock(void *v) 280 { 281 struct vop_lock_args /* { 282 struct vnode *a_vp; 283 int a_flags; 284 } */ *ap = v; 285 struct vnode *vp = ap->a_vp; 286 287 return (lockmgr(vp->v_vnlock, ap->a_flags, &vp->v_interlock)); 288 } 289 290 /* 291 * Unlock the node. 292 */ 293 int 294 genfs_unlock(void *v) 295 { 296 struct vop_unlock_args /* { 297 struct vnode *a_vp; 298 int a_flags; 299 } */ *ap = v; 300 struct vnode *vp = ap->a_vp; 301 302 return (lockmgr(vp->v_vnlock, ap->a_flags | LK_RELEASE, 303 &vp->v_interlock)); 304 } 305 306 /* 307 * Return whether or not the node is locked. 308 */ 309 int 310 genfs_islocked(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 return (lockstatus(vp->v_vnlock)); 318 } 319 320 /* 321 * Stubs to use when there is no locking to be done on the underlying object. 322 */ 323 int 324 genfs_nolock(void *v) 325 { 326 struct vop_lock_args /* { 327 struct vnode *a_vp; 328 int a_flags; 329 struct lwp *a_l; 330 } */ *ap = v; 331 332 /* 333 * Since we are not using the lock manager, we must clear 334 * the interlock here. 335 */ 336 if (ap->a_flags & LK_INTERLOCK) 337 simple_unlock(&ap->a_vp->v_interlock); 338 return (0); 339 } 340 341 int 342 genfs_nounlock(void *v) 343 { 344 345 return (0); 346 } 347 348 int 349 genfs_noislocked(void *v) 350 { 351 352 return (0); 353 } 354 355 /* 356 * Local lease check. 357 */ 358 int 359 genfs_lease_check(void *v) 360 { 361 362 return (0); 363 } 364 365 int 366 genfs_mmap(void *v) 367 { 368 369 return (0); 370 } 371 372 void 373 genfs_node_init(struct vnode *vp, const struct genfs_ops *ops) 374 { 375 struct genfs_node *gp = VTOG(vp); 376 377 rw_init(&gp->g_glock); 378 gp->g_op = ops; 379 } 380 381 void 382 genfs_node_destroy(struct vnode *vp) 383 { 384 struct genfs_node *gp = VTOG(vp); 385 386 rw_destroy(&gp->g_glock); 387 } 388 389 void 390 genfs_size(struct vnode *vp, off_t size, off_t *eobp, int flags) 391 { 392 int bsize; 393 394 bsize = 1 << vp->v_mount->mnt_fs_bshift; 395 *eobp = (size + bsize - 1) & ~(bsize - 1); 396 } 397 398 static void 399 filt_genfsdetach(struct knote *kn) 400 { 401 struct vnode *vp = (struct vnode *)kn->kn_hook; 402 403 /* XXXLUKEM lock the struct? */ 404 SLIST_REMOVE(&vp->v_klist, kn, knote, kn_selnext); 405 } 406 407 static int 408 filt_genfsread(struct knote *kn, long hint) 409 { 410 struct vnode *vp = (struct vnode *)kn->kn_hook; 411 412 /* 413 * filesystem is gone, so set the EOF flag and schedule 414 * the knote for deletion. 415 */ 416 if (hint == NOTE_REVOKE) { 417 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 418 return (1); 419 } 420 421 /* XXXLUKEM lock the struct? */ 422 kn->kn_data = vp->v_size - kn->kn_fp->f_offset; 423 return (kn->kn_data != 0); 424 } 425 426 static int 427 filt_genfsvnode(struct knote *kn, long hint) 428 { 429 430 if (kn->kn_sfflags & hint) 431 kn->kn_fflags |= hint; 432 if (hint == NOTE_REVOKE) { 433 kn->kn_flags |= EV_EOF; 434 return (1); 435 } 436 return (kn->kn_fflags != 0); 437 } 438 439 static const struct filterops genfsread_filtops = 440 { 1, NULL, filt_genfsdetach, filt_genfsread }; 441 static const struct filterops genfsvnode_filtops = 442 { 1, NULL, filt_genfsdetach, filt_genfsvnode }; 443 444 int 445 genfs_kqfilter(void *v) 446 { 447 struct vop_kqfilter_args /* { 448 struct vnode *a_vp; 449 struct knote *a_kn; 450 } */ *ap = v; 451 struct vnode *vp; 452 struct knote *kn; 453 454 vp = ap->a_vp; 455 kn = ap->a_kn; 456 switch (kn->kn_filter) { 457 case EVFILT_READ: 458 kn->kn_fop = &genfsread_filtops; 459 break; 460 case EVFILT_VNODE: 461 kn->kn_fop = &genfsvnode_filtops; 462 break; 463 default: 464 return (EINVAL); 465 } 466 467 kn->kn_hook = vp; 468 469 /* XXXLUKEM lock the struct? */ 470 SLIST_INSERT_HEAD(&vp->v_klist, kn, kn_selnext); 471 472 return (0); 473 } 474 475 void 476 genfs_node_wrlock(struct vnode *vp) 477 { 478 struct genfs_node *gp = VTOG(vp); 479 480 rw_enter(&gp->g_glock, RW_WRITER); 481 } 482 483 void 484 genfs_node_rdlock(struct vnode *vp) 485 { 486 struct genfs_node *gp = VTOG(vp); 487 488 rw_enter(&gp->g_glock, RW_READER); 489 } 490 491 void 492 genfs_node_unlock(struct vnode *vp) 493 { 494 struct genfs_node *gp = VTOG(vp); 495 496 rw_exit(&gp->g_glock); 497 } 498