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