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