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