1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed 6 * to Berkeley by John Heidemann of the UCLA Ficus project. 7 * 8 * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * 39 * $FreeBSD: src/sys/kern/vfs_default.c,v 1.28.2.7 2003/01/10 18:23:26 bde Exp $ 40 * $DragonFly: src/sys/kern/vfs_default.c,v 1.40 2006/05/06 18:48:52 dillon Exp $ 41 */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/buf.h> 46 #include <sys/conf.h> 47 #include <sys/fcntl.h> 48 #include <sys/file.h> 49 #include <sys/kernel.h> 50 #include <sys/lock.h> 51 #include <sys/malloc.h> 52 #include <sys/mount.h> 53 #include <sys/unistd.h> 54 #include <sys/vnode.h> 55 #include <sys/namei.h> 56 #include <sys/nlookup.h> 57 #include <sys/poll.h> 58 #include <sys/mountctl.h> 59 60 #include <machine/limits.h> 61 62 #include <vm/vm.h> 63 #include <vm/vm_object.h> 64 #include <vm/vm_page.h> 65 #include <vm/vm_pager.h> 66 #include <vm/vnode_pager.h> 67 68 static int vop_nolookup (struct vop_old_lookup_args *); 69 static int vop_nostrategy (struct vop_strategy_args *); 70 71 /* 72 * This vnode table stores what we want to do if the filesystem doesn't 73 * implement a particular VOP. 74 * 75 * If there is no specific entry here, we will return EOPNOTSUPP. 76 */ 77 struct vop_ops *default_vnode_vops; 78 static struct vnodeopv_entry_desc default_vnodeop_entries[] = { 79 { &vop_default_desc, vop_eopnotsupp }, 80 { &vop_advlock_desc, vop_einval }, 81 { &vop_fsync_desc, vop_null }, 82 { &vop_ioctl_desc, vop_enotty }, 83 { &vop_islocked_desc, (void *) vop_stdislocked }, 84 { &vop_lock_desc, (void *) vop_stdlock }, 85 { &vop_mmap_desc, vop_einval }, 86 { &vop_old_lookup_desc, (void *) vop_nolookup }, 87 { &vop_open_desc, (void *) vop_stdopen }, 88 { &vop_close_desc, (void *) vop_stdclose }, 89 { &vop_pathconf_desc, vop_einval }, 90 { &vop_poll_desc, (void *) vop_nopoll }, 91 { &vop_readlink_desc, vop_einval }, 92 { &vop_reallocblks_desc, vop_eopnotsupp }, 93 { &vop_revoke_desc, (void *) vop_stdrevoke }, 94 { &vop_strategy_desc, (void *) vop_nostrategy }, 95 { &vop_unlock_desc, (void *) vop_stdunlock }, 96 { &vop_getacl_desc, vop_eopnotsupp }, 97 { &vop_setacl_desc, vop_eopnotsupp }, 98 { &vop_aclcheck_desc, vop_eopnotsupp }, 99 { &vop_getextattr_desc, vop_eopnotsupp }, 100 { &vop_setextattr_desc, vop_eopnotsupp }, 101 { &vop_nresolve_desc, (void *) vop_compat_nresolve }, 102 { &vop_nlookupdotdot_desc, (void *) vop_compat_nlookupdotdot }, 103 { &vop_ncreate_desc, (void *) vop_compat_ncreate }, 104 { &vop_nmkdir_desc, (void *) vop_compat_nmkdir }, 105 { &vop_nmknod_desc, (void *) vop_compat_nmknod }, 106 { &vop_nlink_desc, (void *) vop_compat_nlink }, 107 { &vop_nsymlink_desc, (void *) vop_compat_nsymlink }, 108 { &vop_nwhiteout_desc, (void *) vop_compat_nwhiteout }, 109 { &vop_nremove_desc, (void *) vop_compat_nremove }, 110 { &vop_nrmdir_desc, (void *) vop_compat_nrmdir }, 111 { &vop_nrename_desc, (void *) vop_compat_nrename }, 112 { &vop_mountctl_desc, (void *) journal_mountctl }, 113 { NULL, NULL } 114 }; 115 116 static struct vnodeopv_desc default_vnodeop_opv_desc = 117 { &default_vnode_vops, default_vnodeop_entries, 0 }; 118 119 VNODEOP_SET(default_vnodeop_opv_desc); 120 121 int 122 vop_eopnotsupp(struct vop_generic_args *ap) 123 { 124 return (EOPNOTSUPP); 125 } 126 127 int 128 vop_ebadf(struct vop_generic_args *ap) 129 { 130 return (EBADF); 131 } 132 133 int 134 vop_enotty(struct vop_generic_args *ap) 135 { 136 return (ENOTTY); 137 } 138 139 int 140 vop_einval(struct vop_generic_args *ap) 141 { 142 return (EINVAL); 143 } 144 145 int 146 vop_null(struct vop_generic_args *ap) 147 { 148 return (0); 149 } 150 151 int 152 vop_defaultop(struct vop_generic_args *ap) 153 { 154 return (VOCALL(default_vnode_vops, ap)); 155 } 156 157 int 158 vop_panic(struct vop_generic_args *ap) 159 { 160 161 panic("filesystem goof: vop_panic[%s]", ap->a_desc->vdesc_name); 162 } 163 164 /* 165 * vop_compat_resolve { struct namecache *a_ncp } XXX STOPGAP FUNCTION 166 * 167 * XXX OLD API ROUTINE! WHEN ALL VFSs HAVE BEEN CLEANED UP THIS PROCEDURE 168 * WILL BE REMOVED. This procedure exists for all VFSs which have not 169 * yet implemented VOP_NRESOLVE(). It converts VOP_NRESOLVE() into a 170 * vop_old_lookup() and does appropriate translations. 171 * 172 * Resolve a ncp for VFSs which do not support the VOP. Eventually all 173 * VFSs will support this VOP and this routine can be removed, since 174 * VOP_NRESOLVE() is far less complex then the older LOOKUP/CACHEDLOOKUP 175 * API. 176 * 177 * A locked ncp is passed in to be resolved. The NCP is resolved by 178 * figuring out the vnode (if any) and calling cache_setvp() to attach the 179 * vnode to the entry. If the entry represents a non-existant node then 180 * cache_setvp() is called with a NULL vnode to resolve the entry into a 181 * negative cache entry. No vnode locks are retained and the 182 * ncp is left locked on return. 183 * 184 * The ncp will NEVER represent "", "." or "..", or contain any slashes. 185 * 186 * There is a potential directory and vnode interlock. The lock order 187 * requirement is: namecache, governing directory, resolved vnode. 188 */ 189 int 190 vop_compat_nresolve(struct vop_nresolve_args *ap) 191 { 192 int error; 193 struct vnode *dvp; 194 struct vnode *vp; 195 struct namecache *ncp; 196 struct componentname cnp; 197 198 ncp = ap->a_ncp; /* locked namecache node */ 199 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */ 200 return(EPERM); 201 if (ncp->nc_parent == NULL) 202 return(EPERM); 203 if ((dvp = ncp->nc_parent->nc_vp) == NULL) 204 return(EPERM); 205 206 /* 207 * UFS currently stores all sorts of side effects, including a loop 208 * variable, in the directory inode. That needs to be fixed and the 209 * other VFS's audited before we can switch to LK_SHARED. 210 */ 211 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 212 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 213 ncp, ncp->nc_name); 214 return(EAGAIN); 215 } 216 217 bzero(&cnp, sizeof(cnp)); 218 cnp.cn_nameiop = NAMEI_LOOKUP; 219 cnp.cn_flags = 0; 220 cnp.cn_nameptr = ncp->nc_name; 221 cnp.cn_namelen = ncp->nc_nlen; 222 cnp.cn_cred = ap->a_cred; 223 cnp.cn_td = curthread; /* XXX */ 224 225 /* 226 * vop_old_lookup() always returns vp locked. dvp may or may not be 227 * left locked depending on CNP_PDIRUNLOCK. 228 */ 229 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp); 230 if (error == 0) 231 VOP_UNLOCK(vp, 0); 232 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 233 VOP_UNLOCK(dvp, 0); 234 if ((ncp->nc_flag & NCF_UNRESOLVED) == 0) { 235 /* was resolved by another process while we were unlocked */ 236 if (error == 0) 237 vrele(vp); 238 } else if (error == 0) { 239 KKASSERT(vp != NULL); 240 cache_setvp(ncp, vp); 241 vrele(vp); 242 } else if (error == ENOENT) { 243 KKASSERT(vp == NULL); 244 if (cnp.cn_flags & CNP_ISWHITEOUT) 245 ncp->nc_flag |= NCF_WHITEOUT; 246 cache_setvp(ncp, NULL); 247 } 248 vrele(dvp); 249 return (error); 250 } 251 252 /* 253 * vop_compat_nlookupdotdot { struct vnode *a_dvp, 254 * struct vnode **a_vpp, 255 * struct ucred *a_cred } 256 * 257 * Lookup the vnode representing the parent directory of the specified 258 * directory vnode. a_dvp should not be locked. If no error occurs *a_vpp 259 * will contained the parent vnode, locked and refd, else *a_vpp will be NULL. 260 * 261 * This function is designed to aid NFS server-side operations and is 262 * used by cache_fromdvp() to create a consistent, connected namecache 263 * topology. 264 * 265 * As part of the NEW API work, VFSs will first split their CNP_ISDOTDOT 266 * code out from their *_lookup() and create *_nlookupdotdot(). Then as time 267 * permits VFSs will implement the remaining *_n*() calls and finally get 268 * rid of their *_lookup() call. 269 */ 270 int 271 vop_compat_nlookupdotdot(struct vop_nlookupdotdot_args *ap) 272 { 273 struct componentname cnp; 274 int error; 275 276 /* 277 * UFS currently stores all sorts of side effects, including a loop 278 * variable, in the directory inode. That needs to be fixed and the 279 * other VFS's audited before we can switch to LK_SHARED. 280 */ 281 *ap->a_vpp = NULL; 282 if ((error = vget(ap->a_dvp, LK_EXCLUSIVE)) != 0) 283 return (error); 284 if (ap->a_dvp->v_type != VDIR) { 285 vput(ap->a_dvp); 286 return (ENOTDIR); 287 } 288 289 bzero(&cnp, sizeof(cnp)); 290 cnp.cn_nameiop = NAMEI_LOOKUP; 291 cnp.cn_flags = CNP_ISDOTDOT; 292 cnp.cn_nameptr = ".."; 293 cnp.cn_namelen = 2; 294 cnp.cn_cred = ap->a_cred; 295 cnp.cn_td = curthread; /* XXX */ 296 297 /* 298 * vop_old_lookup() always returns vp locked. dvp may or may not be 299 * left locked depending on CNP_PDIRUNLOCK. 300 */ 301 error = vop_old_lookup(ap->a_head.a_ops, ap->a_dvp, ap->a_vpp, &cnp); 302 if (error == 0) 303 VOP_UNLOCK(*ap->a_vpp, 0); 304 if (cnp.cn_flags & CNP_PDIRUNLOCK) 305 vrele(ap->a_dvp); 306 else 307 vput(ap->a_dvp); 308 return (error); 309 } 310 311 /* 312 * vop_compat_ncreate { struct namecache *a_ncp, XXX STOPGAP FUNCTION 313 * struct vnode *a_vpp, 314 * struct ucred *a_cred, 315 * struct vattr *a_vap } 316 * 317 * Create a file as specified by a_vap. Compatibility requires us to issue 318 * the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_CREATE in order 319 * to setup the directory inode's i_offset and i_count (e.g. in UFS). 320 */ 321 int 322 vop_compat_ncreate(struct vop_ncreate_args *ap) 323 { 324 struct thread *td = curthread; 325 struct componentname cnp; 326 struct namecache *ncp; 327 struct vnode *dvp; 328 int error; 329 330 /* 331 * Sanity checks, get a locked directory vnode. 332 */ 333 ncp = ap->a_ncp; /* locked namecache node */ 334 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */ 335 return(EPERM); 336 if (ncp->nc_parent == NULL) 337 return(EPERM); 338 if ((dvp = ncp->nc_parent->nc_vp) == NULL) 339 return(EPERM); 340 341 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 342 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 343 ncp, ncp->nc_name); 344 return(EAGAIN); 345 } 346 347 /* 348 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 349 * caches all information required to create the entry in the 350 * directory inode. We expect a return code of EJUSTRETURN for 351 * the CREATE case. The cnp must simulated a saved-name situation. 352 */ 353 bzero(&cnp, sizeof(cnp)); 354 cnp.cn_nameiop = NAMEI_CREATE; 355 cnp.cn_flags = CNP_LOCKPARENT; 356 cnp.cn_nameptr = ncp->nc_name; 357 cnp.cn_namelen = ncp->nc_nlen; 358 cnp.cn_cred = ap->a_cred; 359 cnp.cn_td = td; 360 *ap->a_vpp = NULL; 361 362 error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp); 363 364 /* 365 * EJUSTRETURN should be returned for this case, which means that 366 * the VFS has setup the directory inode for the create. The dvp we 367 * passed in is expected to remain in a locked state. 368 * 369 * If the VOP_OLD_CREATE is successful we are responsible for updating 370 * the cache state of the locked ncp that was passed to us. 371 */ 372 if (error == EJUSTRETURN) { 373 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0); 374 error = VOP_OLD_CREATE(dvp, ap->a_vpp, &cnp, ap->a_vap); 375 if (error == 0) { 376 cache_setunresolved(ncp); 377 cache_setvp(ncp, *ap->a_vpp); 378 } 379 } else { 380 if (error == 0) { 381 vput(*ap->a_vpp); 382 *ap->a_vpp = NULL; 383 error = EEXIST; 384 } 385 KKASSERT(*ap->a_vpp == NULL); 386 } 387 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 388 VOP_UNLOCK(dvp, 0); 389 vrele(dvp); 390 return (error); 391 } 392 393 /* 394 * vop_compat_nmkdir { struct namecache *a_ncp, XXX STOPGAP FUNCTION 395 * struct vnode *a_vpp, 396 * struct ucred *a_cred, 397 * struct vattr *a_vap } 398 * 399 * Create a directory as specified by a_vap. Compatibility requires us to 400 * issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKDIR in 401 * order to setup the directory inode's i_offset and i_count (e.g. in UFS). 402 */ 403 int 404 vop_compat_nmkdir(struct vop_nmkdir_args *ap) 405 { 406 struct thread *td = curthread; 407 struct componentname cnp; 408 struct namecache *ncp; 409 struct vnode *dvp; 410 int error; 411 412 /* 413 * Sanity checks, get a locked directory vnode. 414 */ 415 ncp = ap->a_ncp; /* locked namecache node */ 416 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */ 417 return(EPERM); 418 if (ncp->nc_parent == NULL) 419 return(EPERM); 420 if ((dvp = ncp->nc_parent->nc_vp) == NULL) 421 return(EPERM); 422 423 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 424 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 425 ncp, ncp->nc_name); 426 return(EAGAIN); 427 } 428 429 /* 430 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 431 * caches all information required to create the entry in the 432 * directory inode. We expect a return code of EJUSTRETURN for 433 * the CREATE case. The cnp must simulated a saved-name situation. 434 */ 435 bzero(&cnp, sizeof(cnp)); 436 cnp.cn_nameiop = NAMEI_CREATE; 437 cnp.cn_flags = CNP_LOCKPARENT; 438 cnp.cn_nameptr = ncp->nc_name; 439 cnp.cn_namelen = ncp->nc_nlen; 440 cnp.cn_cred = ap->a_cred; 441 cnp.cn_td = td; 442 *ap->a_vpp = NULL; 443 444 error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp); 445 446 /* 447 * EJUSTRETURN should be returned for this case, which means that 448 * the VFS has setup the directory inode for the create. The dvp we 449 * passed in is expected to remain in a locked state. 450 * 451 * If the VOP_OLD_MKDIR is successful we are responsible for updating 452 * the cache state of the locked ncp that was passed to us. 453 */ 454 if (error == EJUSTRETURN) { 455 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0); 456 error = VOP_OLD_MKDIR(dvp, ap->a_vpp, &cnp, ap->a_vap); 457 if (error == 0) { 458 cache_setunresolved(ncp); 459 cache_setvp(ncp, *ap->a_vpp); 460 } 461 } else { 462 if (error == 0) { 463 vput(*ap->a_vpp); 464 *ap->a_vpp = NULL; 465 error = EEXIST; 466 } 467 KKASSERT(*ap->a_vpp == NULL); 468 } 469 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 470 VOP_UNLOCK(dvp, 0); 471 vrele(dvp); 472 return (error); 473 } 474 475 /* 476 * vop_compat_nmknod { struct namecache *a_ncp, XXX STOPGAP FUNCTION 477 * struct vnode *a_vpp, 478 * struct ucred *a_cred, 479 * struct vattr *a_vap } 480 * 481 * Create a device or fifo node as specified by a_vap. Compatibility requires 482 * us to issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKNOD 483 * in order to setup the directory inode's i_offset and i_count (e.g. in UFS). 484 */ 485 int 486 vop_compat_nmknod(struct vop_nmknod_args *ap) 487 { 488 struct thread *td = curthread; 489 struct componentname cnp; 490 struct namecache *ncp; 491 struct vnode *dvp; 492 int error; 493 494 /* 495 * Sanity checks, get a locked directory vnode. 496 */ 497 ncp = ap->a_ncp; /* locked namecache node */ 498 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */ 499 return(EPERM); 500 if (ncp->nc_parent == NULL) 501 return(EPERM); 502 if ((dvp = ncp->nc_parent->nc_vp) == NULL) 503 return(EPERM); 504 505 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 506 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 507 ncp, ncp->nc_name); 508 return(EAGAIN); 509 } 510 511 /* 512 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 513 * caches all information required to create the entry in the 514 * directory inode. We expect a return code of EJUSTRETURN for 515 * the CREATE case. The cnp must simulated a saved-name situation. 516 */ 517 bzero(&cnp, sizeof(cnp)); 518 cnp.cn_nameiop = NAMEI_CREATE; 519 cnp.cn_flags = CNP_LOCKPARENT; 520 cnp.cn_nameptr = ncp->nc_name; 521 cnp.cn_namelen = ncp->nc_nlen; 522 cnp.cn_cred = ap->a_cred; 523 cnp.cn_td = td; 524 *ap->a_vpp = NULL; 525 526 error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp); 527 528 /* 529 * EJUSTRETURN should be returned for this case, which means that 530 * the VFS has setup the directory inode for the create. The dvp we 531 * passed in is expected to remain in a locked state. 532 * 533 * If the VOP_OLD_MKNOD is successful we are responsible for updating 534 * the cache state of the locked ncp that was passed to us. 535 */ 536 if (error == EJUSTRETURN) { 537 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0); 538 error = VOP_OLD_MKNOD(dvp, ap->a_vpp, &cnp, ap->a_vap); 539 if (error == 0) { 540 cache_setunresolved(ncp); 541 cache_setvp(ncp, *ap->a_vpp); 542 } 543 } else { 544 if (error == 0) { 545 vput(*ap->a_vpp); 546 *ap->a_vpp = NULL; 547 error = EEXIST; 548 } 549 KKASSERT(*ap->a_vpp == NULL); 550 } 551 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 552 VOP_UNLOCK(dvp, 0); 553 vrele(dvp); 554 return (error); 555 } 556 557 /* 558 * vop_compat_nlink { struct namecache *a_ncp, XXX STOPGAP FUNCTION 559 * struct vnode *a_vp, 560 * struct ucred *a_cred } 561 * 562 * The passed vp is locked and represents the source. The passed ncp is 563 * locked and represents the target to create. 564 */ 565 int 566 vop_compat_nlink(struct vop_nlink_args *ap) 567 { 568 struct thread *td = curthread; 569 struct componentname cnp; 570 struct namecache *ncp; 571 struct vnode *dvp; 572 struct vnode *tvp; 573 int error; 574 575 /* 576 * Sanity checks, get a locked directory vnode. 577 */ 578 ncp = ap->a_ncp; /* locked namecache node */ 579 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */ 580 return(EPERM); 581 if (ncp->nc_parent == NULL) 582 return(EPERM); 583 if ((dvp = ncp->nc_parent->nc_vp) == NULL) 584 return(EPERM); 585 586 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 587 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 588 ncp, ncp->nc_name); 589 return(EAGAIN); 590 } 591 592 /* 593 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 594 * caches all information required to create the entry in the 595 * directory inode. We expect a return code of EJUSTRETURN for 596 * the CREATE case. The cnp must simulated a saved-name situation. 597 */ 598 bzero(&cnp, sizeof(cnp)); 599 cnp.cn_nameiop = NAMEI_CREATE; 600 cnp.cn_flags = CNP_LOCKPARENT; 601 cnp.cn_nameptr = ncp->nc_name; 602 cnp.cn_namelen = ncp->nc_nlen; 603 cnp.cn_cred = ap->a_cred; 604 cnp.cn_td = td; 605 606 tvp = NULL; 607 error = vop_old_lookup(ap->a_head.a_ops, dvp, &tvp, &cnp); 608 609 /* 610 * EJUSTRETURN should be returned for this case, which means that 611 * the VFS has setup the directory inode for the create. The dvp we 612 * passed in is expected to remain in a locked state. 613 * 614 * If the VOP_OLD_LINK is successful we are responsible for updating 615 * the cache state of the locked ncp that was passed to us. 616 */ 617 if (error == EJUSTRETURN) { 618 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0); 619 error = VOP_OLD_LINK(dvp, ap->a_vp, &cnp); 620 if (error == 0) { 621 cache_setunresolved(ncp); 622 cache_setvp(ncp, ap->a_vp); 623 } 624 } else { 625 if (error == 0) { 626 vput(tvp); 627 error = EEXIST; 628 } 629 } 630 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 631 VOP_UNLOCK(dvp, 0); 632 vrele(dvp); 633 return (error); 634 } 635 636 int 637 vop_compat_nsymlink(struct vop_nsymlink_args *ap) 638 { 639 struct thread *td = curthread; 640 struct componentname cnp; 641 struct namecache *ncp; 642 struct vnode *dvp; 643 struct vnode *vp; 644 int error; 645 646 /* 647 * Sanity checks, get a locked directory vnode. 648 */ 649 *ap->a_vpp = NULL; 650 ncp = ap->a_ncp; /* locked namecache node */ 651 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */ 652 return(EPERM); 653 if (ncp->nc_parent == NULL) 654 return(EPERM); 655 if ((dvp = ncp->nc_parent->nc_vp) == NULL) 656 return(EPERM); 657 658 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 659 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 660 ncp, ncp->nc_name); 661 return(EAGAIN); 662 } 663 664 /* 665 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 666 * caches all information required to create the entry in the 667 * directory inode. We expect a return code of EJUSTRETURN for 668 * the CREATE case. The cnp must simulated a saved-name situation. 669 */ 670 bzero(&cnp, sizeof(cnp)); 671 cnp.cn_nameiop = NAMEI_CREATE; 672 cnp.cn_flags = CNP_LOCKPARENT; 673 cnp.cn_nameptr = ncp->nc_name; 674 cnp.cn_namelen = ncp->nc_nlen; 675 cnp.cn_cred = ap->a_cred; 676 cnp.cn_td = td; 677 678 vp = NULL; 679 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp); 680 681 /* 682 * EJUSTRETURN should be returned for this case, which means that 683 * the VFS has setup the directory inode for the create. The dvp we 684 * passed in is expected to remain in a locked state. 685 * 686 * If the VOP_OLD_SYMLINK is successful we are responsible for updating 687 * the cache state of the locked ncp that was passed to us. 688 */ 689 if (error == EJUSTRETURN) { 690 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0); 691 error = VOP_OLD_SYMLINK(dvp, &vp, &cnp, ap->a_vap, ap->a_target); 692 if (error == 0) { 693 cache_setunresolved(ncp); 694 cache_setvp(ncp, vp); 695 *ap->a_vpp = vp; 696 } 697 } else { 698 if (error == 0) { 699 vput(vp); 700 vp = NULL; 701 error = EEXIST; 702 } 703 KKASSERT(vp == NULL); 704 } 705 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 706 VOP_UNLOCK(dvp, 0); 707 vrele(dvp); 708 return (error); 709 } 710 711 /* 712 * vop_compat_nwhiteout { struct namecache *a_ncp, XXX STOPGAP FUNCTION 713 * struct ucred *a_cred, 714 * int a_flags } 715 * 716 * Issie a whiteout operation (create, lookup, or delete). Compatibility 717 * requires us to issue the appropriate VOP_OLD_LOOKUP before we issue 718 * VOP_OLD_WHITEOUT in order to setup the directory inode's i_offset and i_count 719 * (e.g. in UFS) for the NAMEI_CREATE and NAMEI_DELETE ops. For NAMEI_LOOKUP 720 * no lookup is necessary. 721 */ 722 int 723 vop_compat_nwhiteout(struct vop_nwhiteout_args *ap) 724 { 725 struct thread *td = curthread; 726 struct componentname cnp; 727 struct namecache *ncp; 728 struct vnode *dvp; 729 struct vnode *vp; 730 int error; 731 732 /* 733 * Sanity checks, get a locked directory vnode. 734 */ 735 ncp = ap->a_ncp; /* locked namecache node */ 736 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */ 737 return(EPERM); 738 if (ncp->nc_parent == NULL) 739 return(EPERM); 740 if ((dvp = ncp->nc_parent->nc_vp) == NULL) 741 return(EPERM); 742 743 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 744 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 745 ncp, ncp->nc_name); 746 return(EAGAIN); 747 } 748 749 /* 750 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 751 * caches all information required to create the entry in the 752 * directory inode. We expect a return code of EJUSTRETURN for 753 * the CREATE case. The cnp must simulated a saved-name situation. 754 */ 755 bzero(&cnp, sizeof(cnp)); 756 cnp.cn_nameiop = ap->a_flags; 757 cnp.cn_flags = CNP_LOCKPARENT; 758 cnp.cn_nameptr = ncp->nc_name; 759 cnp.cn_namelen = ncp->nc_nlen; 760 cnp.cn_cred = ap->a_cred; 761 cnp.cn_td = td; 762 763 vp = NULL; 764 765 /* 766 * EJUSTRETURN should be returned for the CREATE or DELETE cases. 767 * The VFS has setup the directory inode for the create. The dvp we 768 * passed in is expected to remain in a locked state. 769 * 770 * If the VOP_OLD_WHITEOUT is successful we are responsible for updating 771 * the cache state of the locked ncp that was passed to us. 772 */ 773 switch(ap->a_flags) { 774 case NAMEI_DELETE: 775 cnp.cn_flags |= CNP_DOWHITEOUT; 776 /* fall through */ 777 case NAMEI_CREATE: 778 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp); 779 if (error == EJUSTRETURN) { 780 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0); 781 error = VOP_OLD_WHITEOUT(dvp, &cnp, ap->a_flags); 782 if (error == 0) 783 cache_setunresolved(ncp); 784 } else { 785 if (error == 0) { 786 vput(vp); 787 vp = NULL; 788 error = EEXIST; 789 } 790 KKASSERT(vp == NULL); 791 } 792 break; 793 case NAMEI_LOOKUP: 794 error = VOP_OLD_WHITEOUT(dvp, NULL, ap->a_flags); 795 break; 796 default: 797 error = EINVAL; 798 break; 799 } 800 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 801 VOP_UNLOCK(dvp, 0); 802 vrele(dvp); 803 return (error); 804 } 805 806 807 /* 808 * vop_compat_nremove { struct namecache *a_ncp, XXX STOPGAP FUNCTION 809 * struct ucred *a_cred } 810 */ 811 int 812 vop_compat_nremove(struct vop_nremove_args *ap) 813 { 814 struct thread *td = curthread; 815 struct componentname cnp; 816 struct namecache *ncp; 817 struct vnode *dvp; 818 struct vnode *vp; 819 int error; 820 821 /* 822 * Sanity checks, get a locked directory vnode. 823 */ 824 ncp = ap->a_ncp; /* locked namecache node */ 825 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */ 826 return(EPERM); 827 if (ncp->nc_parent == NULL) 828 return(EPERM); 829 if ((dvp = ncp->nc_parent->nc_vp) == NULL) 830 return(EPERM); 831 832 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 833 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 834 ncp, ncp->nc_name); 835 return(EAGAIN); 836 } 837 838 /* 839 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 840 * caches all information required to delete the entry in the 841 * directory inode. We expect a return code of 0 for the DELETE 842 * case (meaning that a vp has been found). The cnp must simulated 843 * a saved-name situation. 844 */ 845 bzero(&cnp, sizeof(cnp)); 846 cnp.cn_nameiop = NAMEI_DELETE; 847 cnp.cn_flags = CNP_LOCKPARENT; 848 cnp.cn_nameptr = ncp->nc_name; 849 cnp.cn_namelen = ncp->nc_nlen; 850 cnp.cn_cred = ap->a_cred; 851 cnp.cn_td = td; 852 853 /* 854 * The vnode must be a directory and must not represent the 855 * current directory. 856 */ 857 vp = NULL; 858 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp); 859 if (error == 0 && vp->v_type == VDIR) 860 error = EPERM; 861 if (error == 0) { 862 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0); 863 error = VOP_OLD_REMOVE(dvp, vp, &cnp); 864 if (error == 0) { 865 cache_setunresolved(ncp); 866 cache_setvp(ncp, NULL); 867 } 868 } 869 if (vp) { 870 if (dvp == vp) 871 vrele(vp); 872 else 873 vput(vp); 874 } 875 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 876 VOP_UNLOCK(dvp, 0); 877 vrele(dvp); 878 return (error); 879 } 880 881 /* 882 * vop_compat_nrmdir { struct namecache *a_ncp, XXX STOPGAP FUNCTION 883 * struct ucred *a_cred } 884 */ 885 int 886 vop_compat_nrmdir(struct vop_nrmdir_args *ap) 887 { 888 struct thread *td = curthread; 889 struct componentname cnp; 890 struct namecache *ncp; 891 struct vnode *dvp; 892 struct vnode *vp; 893 int error; 894 895 /* 896 * Sanity checks, get a locked directory vnode. 897 */ 898 ncp = ap->a_ncp; /* locked namecache node */ 899 if (ncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */ 900 return(EPERM); 901 if (ncp->nc_parent == NULL) 902 return(EPERM); 903 if ((dvp = ncp->nc_parent->nc_vp) == NULL) 904 return(EPERM); 905 906 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 907 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 908 ncp, ncp->nc_name); 909 return(EAGAIN); 910 } 911 912 /* 913 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 914 * caches all information required to delete the entry in the 915 * directory inode. We expect a return code of 0 for the DELETE 916 * case (meaning that a vp has been found). The cnp must simulated 917 * a saved-name situation. 918 */ 919 bzero(&cnp, sizeof(cnp)); 920 cnp.cn_nameiop = NAMEI_DELETE; 921 cnp.cn_flags = CNP_LOCKPARENT; 922 cnp.cn_nameptr = ncp->nc_name; 923 cnp.cn_namelen = ncp->nc_nlen; 924 cnp.cn_cred = ap->a_cred; 925 cnp.cn_td = td; 926 927 /* 928 * The vnode must be a directory and must not represent the 929 * current directory. 930 */ 931 vp = NULL; 932 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp); 933 if (error == 0 && vp->v_type != VDIR) 934 error = ENOTDIR; 935 if (error == 0 && vp == dvp) 936 error = EINVAL; 937 if (error == 0 && (vp->v_flag & VROOT)) 938 error = EBUSY; 939 if (error == 0) { 940 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0); 941 error = VOP_OLD_RMDIR(dvp, vp, &cnp); 942 943 /* 944 * Note that this invalidation will cause any process 945 * currently CD'd into the directory being removed to be 946 * disconnected from the topology and not be able to ".." 947 * back out. 948 */ 949 if (error == 0) 950 cache_inval(ncp, CINV_DESTROY); 951 } 952 if (vp) { 953 if (dvp == vp) 954 vrele(vp); 955 else 956 vput(vp); 957 } 958 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 959 VOP_UNLOCK(dvp, 0); 960 vrele(dvp); 961 return (error); 962 } 963 964 /* 965 * vop_compat_nrename { struct namecache *a_fncp, XXX STOPGAP FUNCTION 966 * struct namecache *a_tncp, 967 * struct ucred *a_cred } 968 * 969 * This is a fairly difficult procedure. The old VOP_OLD_RENAME requires that 970 * the source directory and vnode be unlocked and the target directory and 971 * vnode (if it exists) be locked. All arguments will be vrele'd and 972 * the targets will also be unlocked regardless of the return code. 973 */ 974 int 975 vop_compat_nrename(struct vop_nrename_args *ap) 976 { 977 struct thread *td = curthread; 978 struct componentname fcnp; 979 struct componentname tcnp; 980 struct namecache *fncp; 981 struct namecache *tncp; 982 struct vnode *fdvp, *fvp; 983 struct vnode *tdvp, *tvp; 984 int error; 985 986 /* 987 * Sanity checks, get referenced vnodes representing the source. 988 */ 989 fncp = ap->a_fncp; /* locked namecache node */ 990 if (fncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */ 991 return(EPERM); 992 if (fncp->nc_parent == NULL) 993 return(EPERM); 994 if ((fdvp = fncp->nc_parent->nc_vp) == NULL) 995 return(EPERM); 996 997 /* 998 * Temporarily lock the source directory and lookup in DELETE mode to 999 * check permissions. XXX delete permissions should have been 1000 * checked by nlookup(), we need to add NLC_DELETE for delete 1001 * checking. It is unclear whether VFS's require the directory setup 1002 * info NAMEI_DELETE causes to be stored in the fdvp's inode, but 1003 * since it isn't locked and since UFS always does a relookup of 1004 * the source, it is believed that the only side effect that matters 1005 * is the permissions check. 1006 */ 1007 if ((error = vget(fdvp, LK_EXCLUSIVE)) != 0) { 1008 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 1009 fncp, fncp->nc_name); 1010 return(EAGAIN); 1011 } 1012 1013 bzero(&fcnp, sizeof(fcnp)); 1014 fcnp.cn_nameiop = NAMEI_DELETE; 1015 fcnp.cn_flags = CNP_LOCKPARENT; 1016 fcnp.cn_nameptr = fncp->nc_name; 1017 fcnp.cn_namelen = fncp->nc_nlen; 1018 fcnp.cn_cred = ap->a_cred; 1019 fcnp.cn_td = td; 1020 1021 /* 1022 * note: vop_old_lookup (i.e. VOP_OLD_LOOKUP) always returns a locked 1023 * fvp. 1024 */ 1025 fvp = NULL; 1026 error = vop_old_lookup(ap->a_head.a_ops, fdvp, &fvp, &fcnp); 1027 if (error == 0 && (fvp->v_flag & VROOT)) { 1028 vput(fvp); /* as if vop_old_lookup had failed */ 1029 error = EBUSY; 1030 } 1031 if ((fcnp.cn_flags & CNP_PDIRUNLOCK) == 0) { 1032 fcnp.cn_flags |= CNP_PDIRUNLOCK; 1033 VOP_UNLOCK(fdvp, 0); 1034 } 1035 if (error) { 1036 vrele(fdvp); 1037 return (error); 1038 } 1039 VOP_UNLOCK(fvp, 0); 1040 1041 /* 1042 * fdvp and fvp are now referenced and unlocked. 1043 * 1044 * Get a locked directory vnode for the target and lookup the target 1045 * in CREATE mode so it places the required information in the 1046 * directory inode. 1047 */ 1048 tncp = ap->a_tncp; /* locked namecache node */ 1049 if (tncp->nc_flag & NCF_MOUNTPT) /* can't cross a mount point! */ 1050 error = EPERM; 1051 if (tncp->nc_parent == NULL) 1052 error = EPERM; 1053 if ((tdvp = tncp->nc_parent->nc_vp) == NULL) 1054 error = EPERM; 1055 if (error) { 1056 vrele(fdvp); 1057 vrele(fvp); 1058 return (error); 1059 } 1060 if ((error = vget(tdvp, LK_EXCLUSIVE)) != 0) { 1061 printf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 1062 tncp, tncp->nc_name); 1063 vrele(fdvp); 1064 vrele(fvp); 1065 return(EAGAIN); 1066 } 1067 1068 /* 1069 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 1070 * caches all information required to create the entry in the 1071 * target directory inode. 1072 */ 1073 bzero(&tcnp, sizeof(tcnp)); 1074 tcnp.cn_nameiop = NAMEI_RENAME; 1075 tcnp.cn_flags = CNP_LOCKPARENT; 1076 tcnp.cn_nameptr = tncp->nc_name; 1077 tcnp.cn_namelen = tncp->nc_nlen; 1078 tcnp.cn_cred = ap->a_cred; 1079 tcnp.cn_td = td; 1080 1081 tvp = NULL; 1082 error = vop_old_lookup(ap->a_head.a_ops, tdvp, &tvp, &tcnp); 1083 1084 if (error == EJUSTRETURN) { 1085 /* 1086 * Target does not exist. tvp should be NULL. 1087 */ 1088 KKASSERT(tvp == NULL); 1089 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0); 1090 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp); 1091 if (error == 0) { 1092 cache_rename(fncp, tncp); 1093 cache_setvp(tncp, fvp); 1094 } 1095 } else if (error == 0) { 1096 /* 1097 * Target exists. VOP_OLD_RENAME should correctly delete the 1098 * target. 1099 */ 1100 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0); 1101 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp); 1102 if (error == 0) { 1103 cache_rename(fncp, tncp); 1104 cache_setvp(tncp, fvp); 1105 } 1106 } else { 1107 vrele(fdvp); 1108 vrele(fvp); 1109 if (tcnp.cn_flags & CNP_PDIRUNLOCK) 1110 vrele(tdvp); 1111 else 1112 vput(tdvp); 1113 } 1114 return (error); 1115 } 1116 1117 static int 1118 vop_nolookup(ap) 1119 struct vop_old_lookup_args /* { 1120 struct vnode *a_dvp; 1121 struct vnode **a_vpp; 1122 struct componentname *a_cnp; 1123 } */ *ap; 1124 { 1125 1126 *ap->a_vpp = NULL; 1127 return (ENOTDIR); 1128 } 1129 1130 /* 1131 * vop_nostrategy: 1132 * 1133 * Strategy routine for VFS devices that have none. 1134 * 1135 * B_ERROR and B_INVAL must be cleared prior to calling any strategy 1136 * routine. Typically this is done for a BUF_CMD_READ strategy call. 1137 * Typically B_INVAL is assumed to already be clear prior to a write 1138 * and should not be cleared manually unless you just made the buffer 1139 * invalid. B_ERROR should be cleared either way. 1140 */ 1141 1142 static int 1143 vop_nostrategy (struct vop_strategy_args *ap) 1144 { 1145 printf("No strategy for buffer at %p\n", ap->a_bio->bio_buf); 1146 vprint("", ap->a_vp); 1147 ap->a_bio->bio_buf->b_flags |= B_ERROR; 1148 ap->a_bio->bio_buf->b_error = EOPNOTSUPP; 1149 biodone(ap->a_bio); 1150 return (EOPNOTSUPP); 1151 } 1152 1153 int 1154 vop_stdpathconf(ap) 1155 struct vop_pathconf_args /* { 1156 struct vnode *a_vp; 1157 int a_name; 1158 int *a_retval; 1159 } */ *ap; 1160 { 1161 1162 switch (ap->a_name) { 1163 case _PC_LINK_MAX: 1164 *ap->a_retval = LINK_MAX; 1165 return (0); 1166 case _PC_MAX_CANON: 1167 *ap->a_retval = MAX_CANON; 1168 return (0); 1169 case _PC_MAX_INPUT: 1170 *ap->a_retval = MAX_INPUT; 1171 return (0); 1172 case _PC_PIPE_BUF: 1173 *ap->a_retval = PIPE_BUF; 1174 return (0); 1175 case _PC_CHOWN_RESTRICTED: 1176 *ap->a_retval = 1; 1177 return (0); 1178 case _PC_VDISABLE: 1179 *ap->a_retval = _POSIX_VDISABLE; 1180 return (0); 1181 default: 1182 return (EINVAL); 1183 } 1184 /* NOTREACHED */ 1185 } 1186 1187 /* 1188 * Standard open. 1189 * 1190 * (struct vnode *a_vp, int a_mode, struct ucred *a_ucred, struct file *a_fp, 1191 * struct thread *a_td) 1192 * 1193 * a_mode: note, 'F' modes, e.g. FREAD, FWRITE 1194 */ 1195 int 1196 vop_stdopen(struct vop_open_args *ap) 1197 { 1198 struct vnode *vp = ap->a_vp; 1199 struct file *fp; 1200 1201 if ((fp = ap->a_fp) != NULL) { 1202 switch(vp->v_type) { 1203 case VFIFO: 1204 fp->f_type = DTYPE_FIFO; 1205 break; 1206 default: 1207 fp->f_type = DTYPE_VNODE; 1208 break; 1209 } 1210 fp->f_flag = ap->a_mode & FMASK; 1211 fp->f_ops = &vnode_fileops; 1212 fp->f_data = vp; 1213 vref(vp); 1214 } 1215 if (ap->a_mode & FWRITE) 1216 ++vp->v_writecount; 1217 KKASSERT(vp->v_opencount >= 0 && vp->v_opencount != INT_MAX); 1218 ++vp->v_opencount; 1219 return (0); 1220 } 1221 1222 /* 1223 * Standard close. 1224 * 1225 * (struct vnode *a_vp, int a_fflag, struct thread *a_td) 1226 * 1227 * a_fflag: note, 'F' modes, e.g. FREAD, FWRITE. same as a_mode in stdopen? 1228 */ 1229 int 1230 vop_stdclose(struct vop_close_args *ap) 1231 { 1232 struct vnode *vp = ap->a_vp; 1233 1234 KASSERT(vp->v_opencount > 0, 1235 ("VOP_STDCLOSE: BAD OPENCOUNT %p %d\n", vp, vp->v_opencount)); 1236 if (ap->a_fflag & FWRITE) { 1237 KASSERT(vp->v_writecount > 0, 1238 ("VOP_STDCLOSE: BAD WRITECOUNT %p %d\n", 1239 vp, vp->v_writecount)); 1240 --vp->v_writecount; 1241 } 1242 --vp->v_opencount; 1243 return (0); 1244 } 1245 1246 /* 1247 * Standard lock. The lock is recursive-capable only if the lock was 1248 * initialized with LK_CANRECURSE or that flag is passed in a_flags. 1249 */ 1250 int 1251 vop_stdlock(ap) 1252 struct vop_lock_args /* { 1253 struct vnode *a_vp; 1254 int a_flags; 1255 } */ *ap; 1256 { 1257 int error; 1258 1259 #ifndef DEBUG_LOCKS 1260 error = lockmgr(&ap->a_vp->v_lock, ap->a_flags); 1261 #else 1262 error = debuglockmgr(&ap->a_vp->v_lock, ap->a_flags, 1263 "vop_stdlock", ap->a_vp->filename, ap->a_vp->line); 1264 #endif 1265 return(error); 1266 } 1267 1268 int 1269 vop_stdunlock(ap) 1270 struct vop_unlock_args /* { 1271 struct vnode *a_vp; 1272 int a_flags; 1273 } */ *ap; 1274 { 1275 int error; 1276 1277 error = lockmgr(&ap->a_vp->v_lock, ap->a_flags | LK_RELEASE); 1278 return(error); 1279 } 1280 1281 int 1282 vop_stdislocked(ap) 1283 struct vop_islocked_args /* { 1284 struct vnode *a_vp; 1285 struct thread *a_td; 1286 } */ *ap; 1287 { 1288 return (lockstatus(&ap->a_vp->v_lock, ap->a_td)); 1289 } 1290 1291 /* 1292 * Return true for select/poll. 1293 */ 1294 int 1295 vop_nopoll(ap) 1296 struct vop_poll_args /* { 1297 struct vnode *a_vp; 1298 int a_events; 1299 struct ucred *a_cred; 1300 struct proc *a_p; 1301 } */ *ap; 1302 { 1303 /* 1304 * Return true for read/write. If the user asked for something 1305 * special, return POLLNVAL, so that clients have a way of 1306 * determining reliably whether or not the extended 1307 * functionality is present without hard-coding knowledge 1308 * of specific filesystem implementations. 1309 */ 1310 if (ap->a_events & ~POLLSTANDARD) 1311 return (POLLNVAL); 1312 1313 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); 1314 } 1315 1316 /* 1317 * Implement poll for local filesystems that support it. 1318 */ 1319 int 1320 vop_stdpoll(ap) 1321 struct vop_poll_args /* { 1322 struct vnode *a_vp; 1323 int a_events; 1324 struct ucred *a_cred; 1325 } */ *ap; 1326 { 1327 if (ap->a_events & ~POLLSTANDARD) 1328 return (vn_pollrecord(ap->a_vp, ap->a_events)); 1329 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); 1330 } 1331 1332 /* 1333 * vfs default ops 1334 * used to fill the vfs fucntion table to get reasonable default return values. 1335 */ 1336 int 1337 vfs_stdmount(struct mount *mp, char *path, caddr_t data, struct ucred *cred) 1338 { 1339 return (0); 1340 } 1341 1342 int 1343 vfs_stdunmount(struct mount *mp, int mntflags) 1344 { 1345 return (0); 1346 } 1347 1348 int 1349 vfs_stdroot(struct mount *mp, struct vnode **vpp) 1350 { 1351 return (EOPNOTSUPP); 1352 } 1353 1354 int 1355 vfs_stdstatfs(struct mount *mp, struct statfs *sbp, struct ucred *cred) 1356 { 1357 return (EOPNOTSUPP); 1358 } 1359 1360 int 1361 vfs_stdvptofh(struct vnode *vp, struct fid *fhp) 1362 { 1363 return (EOPNOTSUPP); 1364 } 1365 1366 int 1367 vfs_stdstart(struct mount *mp, int flags) 1368 { 1369 return (0); 1370 } 1371 1372 int 1373 vfs_stdquotactl(struct mount *mp, int cmds, uid_t uid, 1374 caddr_t arg, struct ucred *cred) 1375 { 1376 return (EOPNOTSUPP); 1377 } 1378 1379 int 1380 vfs_stdsync(struct mount *mp, int waitfor) 1381 { 1382 return (0); 1383 } 1384 1385 int 1386 vfs_stdnosync(struct mount *mp, int waitfor) 1387 { 1388 return (EOPNOTSUPP); 1389 } 1390 1391 int 1392 vfs_stdvget(struct mount *mp, ino_t ino, struct vnode **vpp) 1393 { 1394 return (EOPNOTSUPP); 1395 } 1396 1397 int 1398 vfs_stdfhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) 1399 { 1400 return (EOPNOTSUPP); 1401 } 1402 1403 int 1404 vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp, 1405 struct ucred **credanonp) 1406 { 1407 return (EOPNOTSUPP); 1408 } 1409 1410 int 1411 vfs_stdinit(struct vfsconf *vfsp) 1412 { 1413 return (0); 1414 } 1415 1416 int 1417 vfs_stduninit(struct vfsconf *vfsp) 1418 { 1419 return(0); 1420 } 1421 1422 int 1423 vfs_stdextattrctl(struct mount *mp, int cmd, const char *attrname, 1424 caddr_t arg, struct ucred *cred) 1425 { 1426 return(EOPNOTSUPP); 1427 } 1428 1429 /* end of vfs default ops */ 1430