1 /* $NetBSD: genfs_vnops.c,v 1.164 2008/02/05 14:19:53 ad 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.164 2008/02/05 14:19:53 ad 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 #include <sys/fstrans.h> 83 84 #include <miscfs/genfs/genfs.h> 85 #include <miscfs/genfs/genfs_node.h> 86 #include <miscfs/specfs/specdev.h> 87 88 #include <uvm/uvm.h> 89 #include <uvm/uvm_pager.h> 90 91 static void filt_genfsdetach(struct knote *); 92 static int filt_genfsread(struct knote *, long); 93 static int filt_genfsvnode(struct knote *, long); 94 95 int 96 genfs_poll(void *v) 97 { 98 struct vop_poll_args /* { 99 struct vnode *a_vp; 100 int a_events; 101 struct lwp *a_l; 102 } */ *ap = v; 103 104 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); 105 } 106 107 int 108 genfs_seek(void *v) 109 { 110 struct vop_seek_args /* { 111 struct vnode *a_vp; 112 off_t a_oldoff; 113 off_t a_newoff; 114 kauth_cred_t cred; 115 } */ *ap = v; 116 117 if (ap->a_newoff < 0) 118 return (EINVAL); 119 120 return (0); 121 } 122 123 int 124 genfs_abortop(void *v) 125 { 126 struct vop_abortop_args /* { 127 struct vnode *a_dvp; 128 struct componentname *a_cnp; 129 } */ *ap = v; 130 131 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 132 PNBUF_PUT(ap->a_cnp->cn_pnbuf); 133 return (0); 134 } 135 136 int 137 genfs_fcntl(void *v) 138 { 139 struct vop_fcntl_args /* { 140 struct vnode *a_vp; 141 u_int a_command; 142 void *a_data; 143 int a_fflag; 144 kauth_cred_t a_cred; 145 struct lwp *a_l; 146 } */ *ap = v; 147 148 if (ap->a_command == F_SETFL) 149 return (0); 150 else 151 return (EOPNOTSUPP); 152 } 153 154 /*ARGSUSED*/ 155 int 156 genfs_badop(void *v) 157 { 158 159 panic("genfs: bad op"); 160 } 161 162 /*ARGSUSED*/ 163 int 164 genfs_nullop(void *v) 165 { 166 167 return (0); 168 } 169 170 /*ARGSUSED*/ 171 int 172 genfs_einval(void *v) 173 { 174 175 return (EINVAL); 176 } 177 178 /* 179 * Called when an fs doesn't support a particular vop. 180 * This takes care to vrele, vput, or vunlock passed in vnodes. 181 */ 182 int 183 genfs_eopnotsupp(void *v) 184 { 185 struct vop_generic_args /* 186 struct vnodeop_desc *a_desc; 187 / * other random data follows, presumably * / 188 } */ *ap = v; 189 struct vnodeop_desc *desc = ap->a_desc; 190 struct vnode *vp, *vp_last = NULL; 191 int flags, i, j, offset; 192 193 flags = desc->vdesc_flags; 194 for (i = 0; i < VDESC_MAX_VPS; flags >>=1, i++) { 195 if ((offset = desc->vdesc_vp_offsets[i]) == VDESC_NO_OFFSET) 196 break; /* stop at end of list */ 197 if ((j = flags & VDESC_VP0_WILLPUT)) { 198 vp = *VOPARG_OFFSETTO(struct vnode **, offset, ap); 199 200 /* Skip if NULL */ 201 if (!vp) 202 continue; 203 204 switch (j) { 205 case VDESC_VP0_WILLPUT: 206 /* Check for dvp == vp cases */ 207 if (vp == vp_last) 208 vrele(vp); 209 else { 210 vput(vp); 211 vp_last = vp; 212 } 213 break; 214 case VDESC_VP0_WILLUNLOCK: 215 VOP_UNLOCK(vp, 0); 216 break; 217 case VDESC_VP0_WILLRELE: 218 vrele(vp); 219 break; 220 } 221 } 222 } 223 224 return (EOPNOTSUPP); 225 } 226 227 /*ARGSUSED*/ 228 int 229 genfs_ebadf(void *v) 230 { 231 232 return (EBADF); 233 } 234 235 /* ARGSUSED */ 236 int 237 genfs_enoioctl(void *v) 238 { 239 240 return (EPASSTHROUGH); 241 } 242 243 244 /* 245 * Eliminate all activity associated with the requested vnode 246 * and with all vnodes aliased to the requested vnode. 247 */ 248 int 249 genfs_revoke(void *v) 250 { 251 struct vop_revoke_args /* { 252 struct vnode *a_vp; 253 int a_flags; 254 } */ *ap = v; 255 256 #ifdef DIAGNOSTIC 257 if ((ap->a_flags & REVOKEALL) == 0) 258 panic("genfs_revoke: not revokeall"); 259 #endif 260 vrevoke(ap->a_vp); 261 return (0); 262 } 263 264 /* 265 * Lock the node. 266 */ 267 int 268 genfs_lock(void *v) 269 { 270 struct vop_lock_args /* { 271 struct vnode *a_vp; 272 int a_flags; 273 } */ *ap = v; 274 struct vnode *vp = ap->a_vp; 275 int flags = ap->a_flags; 276 277 if ((flags & LK_INTERLOCK) != 0) { 278 flags &= ~LK_INTERLOCK; 279 mutex_exit(&vp->v_interlock); 280 } 281 282 return (vlockmgr(vp->v_vnlock, flags)); 283 } 284 285 /* 286 * Unlock the node. 287 */ 288 int 289 genfs_unlock(void *v) 290 { 291 struct vop_unlock_args /* { 292 struct vnode *a_vp; 293 int a_flags; 294 } */ *ap = v; 295 struct vnode *vp = ap->a_vp; 296 297 KASSERT(ap->a_flags == 0); 298 299 return (vlockmgr(vp->v_vnlock, LK_RELEASE)); 300 } 301 302 /* 303 * Return whether or not the node is locked. 304 */ 305 int 306 genfs_islocked(void *v) 307 { 308 struct vop_islocked_args /* { 309 struct vnode *a_vp; 310 } */ *ap = v; 311 struct vnode *vp = ap->a_vp; 312 313 return (vlockstatus(vp->v_vnlock)); 314 } 315 316 /* 317 * Stubs to use when there is no locking to be done on the underlying object. 318 */ 319 int 320 genfs_nolock(void *v) 321 { 322 struct vop_lock_args /* { 323 struct vnode *a_vp; 324 int a_flags; 325 struct lwp *a_l; 326 } */ *ap = v; 327 328 /* 329 * Since we are not using the lock manager, we must clear 330 * the interlock here. 331 */ 332 if (ap->a_flags & LK_INTERLOCK) 333 mutex_exit(&ap->a_vp->v_interlock); 334 return (0); 335 } 336 337 int 338 genfs_nounlock(void *v) 339 { 340 341 return (0); 342 } 343 344 int 345 genfs_noislocked(void *v) 346 { 347 348 return (0); 349 } 350 351 int 352 genfs_mmap(void *v) 353 { 354 355 return (0); 356 } 357 358 void 359 genfs_node_init(struct vnode *vp, const struct genfs_ops *ops) 360 { 361 struct genfs_node *gp = VTOG(vp); 362 363 rw_init(&gp->g_glock); 364 gp->g_op = ops; 365 } 366 367 void 368 genfs_node_destroy(struct vnode *vp) 369 { 370 struct genfs_node *gp = VTOG(vp); 371 372 rw_destroy(&gp->g_glock); 373 } 374 375 void 376 genfs_size(struct vnode *vp, off_t size, off_t *eobp, int flags) 377 { 378 int bsize; 379 380 bsize = 1 << vp->v_mount->mnt_fs_bshift; 381 *eobp = (size + bsize - 1) & ~(bsize - 1); 382 } 383 384 static void 385 filt_genfsdetach(struct knote *kn) 386 { 387 struct vnode *vp = (struct vnode *)kn->kn_hook; 388 389 mutex_enter(&vp->v_interlock); 390 SLIST_REMOVE(&vp->v_klist, kn, knote, kn_selnext); 391 mutex_exit(&vp->v_interlock); 392 } 393 394 static int 395 filt_genfsread(struct knote *kn, long hint) 396 { 397 struct vnode *vp = (struct vnode *)kn->kn_hook; 398 int rv; 399 400 /* 401 * filesystem is gone, so set the EOF flag and schedule 402 * the knote for deletion. 403 */ 404 switch (hint) { 405 case NOTE_REVOKE: 406 KASSERT(mutex_owned(&vp->v_interlock)); 407 kn->kn_flags |= (EV_EOF | EV_ONESHOT); 408 return (1); 409 case 0: 410 mutex_enter(&vp->v_interlock); 411 kn->kn_data = vp->v_size - kn->kn_fp->f_offset; 412 rv = (kn->kn_data != 0); 413 mutex_exit(&vp->v_interlock); 414 return rv; 415 default: 416 KASSERT(mutex_owned(&vp->v_interlock)); 417 kn->kn_data = vp->v_size - kn->kn_fp->f_offset; 418 return (kn->kn_data != 0); 419 } 420 } 421 422 static int 423 filt_genfsvnode(struct knote *kn, long hint) 424 { 425 struct vnode *vp = (struct vnode *)kn->kn_hook; 426 int fflags; 427 428 switch (hint) { 429 case NOTE_REVOKE: 430 KASSERT(mutex_owned(&vp->v_interlock)); 431 kn->kn_flags |= EV_EOF; 432 if ((kn->kn_sfflags & hint) != 0) 433 kn->kn_fflags |= hint; 434 return (1); 435 case 0: 436 mutex_enter(&vp->v_interlock); 437 fflags = kn->kn_fflags; 438 mutex_exit(&vp->v_interlock); 439 break; 440 default: 441 KASSERT(mutex_owned(&vp->v_interlock)); 442 if ((kn->kn_sfflags & hint) != 0) 443 kn->kn_fflags |= hint; 444 fflags = kn->kn_fflags; 445 break; 446 } 447 448 return (kn->kn_fflags != 0); 449 } 450 451 static const struct filterops genfsread_filtops = 452 { 1, NULL, filt_genfsdetach, filt_genfsread }; 453 static const struct filterops genfsvnode_filtops = 454 { 1, NULL, filt_genfsdetach, filt_genfsvnode }; 455 456 int 457 genfs_kqfilter(void *v) 458 { 459 struct vop_kqfilter_args /* { 460 struct vnode *a_vp; 461 struct knote *a_kn; 462 } */ *ap = v; 463 struct vnode *vp; 464 struct knote *kn; 465 466 vp = ap->a_vp; 467 kn = ap->a_kn; 468 switch (kn->kn_filter) { 469 case EVFILT_READ: 470 kn->kn_fop = &genfsread_filtops; 471 break; 472 case EVFILT_VNODE: 473 kn->kn_fop = &genfsvnode_filtops; 474 break; 475 default: 476 return (EINVAL); 477 } 478 479 kn->kn_hook = vp; 480 481 mutex_enter(&vp->v_interlock); 482 SLIST_INSERT_HEAD(&vp->v_klist, kn, kn_selnext); 483 mutex_exit(&vp->v_interlock); 484 485 return (0); 486 } 487 488 void 489 genfs_node_wrlock(struct vnode *vp) 490 { 491 struct genfs_node *gp = VTOG(vp); 492 493 rw_enter(&gp->g_glock, RW_WRITER); 494 } 495 496 void 497 genfs_node_rdlock(struct vnode *vp) 498 { 499 struct genfs_node *gp = VTOG(vp); 500 501 rw_enter(&gp->g_glock, RW_READER); 502 } 503 504 void 505 genfs_node_unlock(struct vnode *vp) 506 { 507 struct genfs_node *gp = VTOG(vp); 508 509 rw_exit(&gp->g_glock); 510 } 511