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