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 * The statvfs->statfs conversion code was contributed to the DragonFly 9 * Project by Joerg Sonnenberger <joerg@bec.de>. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * Source: * @(#)i405_init.c 2.10 92/04/27 UCLA Ficus project 40 * $FreeBSD: src/sys/kern/vfs_default.c,v 1.28.2.7 2003/01/10 18:23:26 bde Exp $ 41 * $DragonFly: src/sys/kern/vfs_default.c,v 1.55 2008/09/28 04:31:50 dillon Exp $ 42 */ 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/buf.h> 47 #include <sys/conf.h> 48 #include <sys/fcntl.h> 49 #include <sys/file.h> 50 #include <sys/kernel.h> 51 #include <sys/lock.h> 52 #include <sys/malloc.h> 53 #include <sys/mount.h> 54 #include <sys/unistd.h> 55 #include <sys/vnode.h> 56 #include <sys/namei.h> 57 #include <sys/nlookup.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_mmap = (void *)vop_einval, 83 .vop_old_lookup = vop_nolookup, 84 .vop_open = vop_stdopen, 85 .vop_close = vop_stdclose, 86 .vop_pathconf = vop_stdpathconf, 87 .vop_readlink = (void *)vop_einval, 88 .vop_reallocblks = (void *)vop_eopnotsupp, 89 .vop_strategy = vop_nostrategy, 90 .vop_getacl = (void *)vop_eopnotsupp, 91 .vop_setacl = (void *)vop_eopnotsupp, 92 .vop_aclcheck = (void *)vop_eopnotsupp, 93 .vop_getextattr = (void *)vop_eopnotsupp, 94 .vop_setextattr = (void *)vop_eopnotsupp, 95 .vop_markatime = vop_stdmarkatime, 96 .vop_nresolve = vop_compat_nresolve, 97 .vop_nlookupdotdot = vop_compat_nlookupdotdot, 98 .vop_ncreate = vop_compat_ncreate, 99 .vop_nmkdir = vop_compat_nmkdir, 100 .vop_nmknod = vop_compat_nmknod, 101 .vop_nlink = vop_compat_nlink, 102 .vop_nsymlink = vop_compat_nsymlink, 103 .vop_nwhiteout = vop_compat_nwhiteout, 104 .vop_nremove = vop_compat_nremove, 105 .vop_nrmdir = vop_compat_nrmdir, 106 .vop_nrename = vop_compat_nrename, 107 .vop_mountctl = vop_stdmountctl 108 }; 109 110 VNODEOP_SET(default_vnode_vops); 111 112 int 113 vop_eopnotsupp(struct vop_generic_args *ap) 114 { 115 return (EOPNOTSUPP); 116 } 117 118 int 119 vop_ebadf(struct vop_generic_args *ap) 120 { 121 return (EBADF); 122 } 123 124 int 125 vop_enotty(struct vop_generic_args *ap) 126 { 127 return (ENOTTY); 128 } 129 130 int 131 vop_einval(struct vop_generic_args *ap) 132 { 133 return (EINVAL); 134 } 135 136 int 137 vop_stdmarkatime(struct vop_markatime_args *ap) 138 { 139 return (EOPNOTSUPP); 140 } 141 142 int 143 vop_null(struct vop_generic_args *ap) 144 { 145 return (0); 146 } 147 148 int 149 vop_defaultop(struct vop_generic_args *ap) 150 { 151 return (VOCALL(&default_vnode_vops, ap)); 152 } 153 154 int 155 vop_panic(struct vop_generic_args *ap) 156 { 157 panic("filesystem goof: vop_panic[%s]", ap->a_desc->sd_name); 158 } 159 160 /* 161 * vop_compat_resolve { struct nchandle *a_nch, struct vnode *dvp } 162 * XXX STOPGAP FUNCTION 163 * 164 * XXX OLD API ROUTINE! WHEN ALL VFSs HAVE BEEN CLEANED UP THIS PROCEDURE 165 * WILL BE REMOVED. This procedure exists for all VFSs which have not 166 * yet implemented VOP_NRESOLVE(). It converts VOP_NRESOLVE() into a 167 * vop_old_lookup() and does appropriate translations. 168 * 169 * Resolve a ncp for VFSs which do not support the VOP. Eventually all 170 * VFSs will support this VOP and this routine can be removed, since 171 * VOP_NRESOLVE() is far less complex then the older LOOKUP/CACHEDLOOKUP 172 * API. 173 * 174 * A locked ncp is passed in to be resolved. The NCP is resolved by 175 * figuring out the vnode (if any) and calling cache_setvp() to attach the 176 * vnode to the entry. If the entry represents a non-existant node then 177 * cache_setvp() is called with a NULL vnode to resolve the entry into a 178 * negative cache entry. No vnode locks are retained and the 179 * ncp is left locked on return. 180 * 181 * The ncp will NEVER represent "", "." or "..", or contain any slashes. 182 * 183 * There is a potential directory and vnode interlock. The lock order 184 * requirement is: namecache, governing directory, resolved vnode. 185 */ 186 int 187 vop_compat_nresolve(struct vop_nresolve_args *ap) 188 { 189 int error; 190 struct vnode *dvp; 191 struct vnode *vp; 192 struct nchandle *nch; 193 struct namecache *ncp; 194 struct componentname cnp; 195 196 nch = ap->a_nch; /* locked namecache node */ 197 ncp = nch->ncp; 198 dvp = ap->a_dvp; 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 kprintf("[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 vn_unlock(vp); 226 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 227 vn_unlock(dvp); 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(nch, 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(nch, 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 vn_unlock(*ap->a_vpp); 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 nchandle *a_nch, XXX STOPGAP FUNCTION 307 * struct vnode *a_dvp, 308 * struct vnode **a_vpp, 309 * struct ucred *a_cred, 310 * struct vattr *a_vap } 311 * 312 * Create a file as specified by a_vap. Compatibility requires us to issue 313 * the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_CREATE in order 314 * to setup the directory inode's i_offset and i_count (e.g. in UFS). 315 */ 316 int 317 vop_compat_ncreate(struct vop_ncreate_args *ap) 318 { 319 struct thread *td = curthread; 320 struct componentname cnp; 321 struct nchandle *nch; 322 struct namecache *ncp; 323 struct vnode *dvp; 324 int error; 325 326 /* 327 * Sanity checks, get a locked directory vnode. 328 */ 329 nch = ap->a_nch; /* locked namecache node */ 330 dvp = ap->a_dvp; 331 ncp = nch->ncp; 332 333 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 334 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 335 ncp, ncp->nc_name); 336 return(EAGAIN); 337 } 338 339 /* 340 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 341 * caches all information required to create the entry in the 342 * directory inode. We expect a return code of EJUSTRETURN for 343 * the CREATE case. The cnp must simulated a saved-name situation. 344 */ 345 bzero(&cnp, sizeof(cnp)); 346 cnp.cn_nameiop = NAMEI_CREATE; 347 cnp.cn_flags = CNP_LOCKPARENT; 348 cnp.cn_nameptr = ncp->nc_name; 349 cnp.cn_namelen = ncp->nc_nlen; 350 cnp.cn_cred = ap->a_cred; 351 cnp.cn_td = td; 352 *ap->a_vpp = NULL; 353 354 error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp); 355 356 /* 357 * EJUSTRETURN should be returned for this case, which means that 358 * the VFS has setup the directory inode for the create. The dvp we 359 * passed in is expected to remain in a locked state. 360 * 361 * If the VOP_OLD_CREATE is successful we are responsible for updating 362 * the cache state of the locked ncp that was passed to us. 363 */ 364 if (error == EJUSTRETURN) { 365 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0); 366 error = VOP_OLD_CREATE(dvp, ap->a_vpp, &cnp, ap->a_vap); 367 if (error == 0) { 368 cache_setunresolved(nch); 369 cache_setvp(nch, *ap->a_vpp); 370 } 371 } else { 372 if (error == 0) { 373 vput(*ap->a_vpp); 374 *ap->a_vpp = NULL; 375 error = EEXIST; 376 } 377 KKASSERT(*ap->a_vpp == NULL); 378 } 379 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 380 vn_unlock(dvp); 381 vrele(dvp); 382 return (error); 383 } 384 385 /* 386 * vop_compat_nmkdir { struct nchandle *a_nch, XXX STOPGAP FUNCTION 387 * struct vnode *a_dvp, 388 * struct vnode **a_vpp, 389 * struct ucred *a_cred, 390 * struct vattr *a_vap } 391 * 392 * Create a directory as specified by a_vap. Compatibility requires us to 393 * issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKDIR in 394 * order to setup the directory inode's i_offset and i_count (e.g. in UFS). 395 */ 396 int 397 vop_compat_nmkdir(struct vop_nmkdir_args *ap) 398 { 399 struct thread *td = curthread; 400 struct componentname cnp; 401 struct nchandle *nch; 402 struct namecache *ncp; 403 struct vnode *dvp; 404 int error; 405 406 /* 407 * Sanity checks, get a locked directory vnode. 408 */ 409 nch = ap->a_nch; /* locked namecache node */ 410 ncp = nch->ncp; 411 dvp = ap->a_dvp; 412 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 413 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 414 ncp, ncp->nc_name); 415 return(EAGAIN); 416 } 417 418 /* 419 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 420 * caches all information required to create the entry in the 421 * directory inode. We expect a return code of EJUSTRETURN for 422 * the CREATE case. The cnp must simulated a saved-name situation. 423 */ 424 bzero(&cnp, sizeof(cnp)); 425 cnp.cn_nameiop = NAMEI_CREATE; 426 cnp.cn_flags = CNP_LOCKPARENT; 427 cnp.cn_nameptr = ncp->nc_name; 428 cnp.cn_namelen = ncp->nc_nlen; 429 cnp.cn_cred = ap->a_cred; 430 cnp.cn_td = td; 431 *ap->a_vpp = NULL; 432 433 error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp); 434 435 /* 436 * EJUSTRETURN should be returned for this case, which means that 437 * the VFS has setup the directory inode for the create. The dvp we 438 * passed in is expected to remain in a locked state. 439 * 440 * If the VOP_OLD_MKDIR is successful we are responsible for updating 441 * the cache state of the locked ncp that was passed to us. 442 */ 443 if (error == EJUSTRETURN) { 444 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0); 445 error = VOP_OLD_MKDIR(dvp, ap->a_vpp, &cnp, ap->a_vap); 446 if (error == 0) { 447 cache_setunresolved(nch); 448 cache_setvp(nch, *ap->a_vpp); 449 } 450 } else { 451 if (error == 0) { 452 vput(*ap->a_vpp); 453 *ap->a_vpp = NULL; 454 error = EEXIST; 455 } 456 KKASSERT(*ap->a_vpp == NULL); 457 } 458 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 459 vn_unlock(dvp); 460 vrele(dvp); 461 return (error); 462 } 463 464 /* 465 * vop_compat_nmknod { struct nchandle *a_nch, XXX STOPGAP FUNCTION 466 * struct vnode *a_dvp, 467 * struct vnode **a_vpp, 468 * struct ucred *a_cred, 469 * struct vattr *a_vap } 470 * 471 * Create a device or fifo node as specified by a_vap. Compatibility requires 472 * us to issue the appropriate VOP_OLD_LOOKUP before we issue VOP_OLD_MKNOD 473 * in order to setup the directory inode's i_offset and i_count (e.g. in UFS). 474 */ 475 int 476 vop_compat_nmknod(struct vop_nmknod_args *ap) 477 { 478 struct thread *td = curthread; 479 struct componentname cnp; 480 struct nchandle *nch; 481 struct namecache *ncp; 482 struct vnode *dvp; 483 int error; 484 485 /* 486 * Sanity checks, get a locked directory vnode. 487 */ 488 nch = ap->a_nch; /* locked namecache node */ 489 ncp = nch->ncp; 490 dvp = ap->a_dvp; 491 492 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 493 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 494 ncp, ncp->nc_name); 495 return(EAGAIN); 496 } 497 498 /* 499 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 500 * caches all information required to create the entry in the 501 * directory inode. We expect a return code of EJUSTRETURN for 502 * the CREATE case. The cnp must simulated a saved-name situation. 503 */ 504 bzero(&cnp, sizeof(cnp)); 505 cnp.cn_nameiop = NAMEI_CREATE; 506 cnp.cn_flags = CNP_LOCKPARENT; 507 cnp.cn_nameptr = ncp->nc_name; 508 cnp.cn_namelen = ncp->nc_nlen; 509 cnp.cn_cred = ap->a_cred; 510 cnp.cn_td = td; 511 *ap->a_vpp = NULL; 512 513 error = vop_old_lookup(ap->a_head.a_ops, dvp, ap->a_vpp, &cnp); 514 515 /* 516 * EJUSTRETURN should be returned for this case, which means that 517 * the VFS has setup the directory inode for the create. The dvp we 518 * passed in is expected to remain in a locked state. 519 * 520 * If the VOP_OLD_MKNOD is successful we are responsible for updating 521 * the cache state of the locked ncp that was passed to us. 522 */ 523 if (error == EJUSTRETURN) { 524 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0); 525 error = VOP_OLD_MKNOD(dvp, ap->a_vpp, &cnp, ap->a_vap); 526 if (error == 0) { 527 cache_setunresolved(nch); 528 cache_setvp(nch, *ap->a_vpp); 529 } 530 } else { 531 if (error == 0) { 532 vput(*ap->a_vpp); 533 *ap->a_vpp = NULL; 534 error = EEXIST; 535 } 536 KKASSERT(*ap->a_vpp == NULL); 537 } 538 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 539 vn_unlock(dvp); 540 vrele(dvp); 541 return (error); 542 } 543 544 /* 545 * vop_compat_nlink { struct nchandle *a_nch, XXX STOPGAP FUNCTION 546 * struct vnode *a_dvp, 547 * struct vnode *a_vp, 548 * struct ucred *a_cred } 549 * 550 * The passed vp is locked and represents the source. The passed ncp is 551 * locked and represents the target to create. 552 */ 553 int 554 vop_compat_nlink(struct vop_nlink_args *ap) 555 { 556 struct thread *td = curthread; 557 struct componentname cnp; 558 struct nchandle *nch; 559 struct namecache *ncp; 560 struct vnode *dvp; 561 struct vnode *tvp; 562 int error; 563 564 /* 565 * Sanity checks, get a locked directory vnode. 566 */ 567 nch = ap->a_nch; /* locked namecache node */ 568 ncp = nch->ncp; 569 dvp = ap->a_dvp; 570 571 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 572 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 573 ncp, ncp->nc_name); 574 return(EAGAIN); 575 } 576 577 /* 578 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 579 * caches all information required to create the entry in the 580 * directory inode. We expect a return code of EJUSTRETURN for 581 * the CREATE case. The cnp must simulated a saved-name situation. 582 */ 583 bzero(&cnp, sizeof(cnp)); 584 cnp.cn_nameiop = NAMEI_CREATE; 585 cnp.cn_flags = CNP_LOCKPARENT; 586 cnp.cn_nameptr = ncp->nc_name; 587 cnp.cn_namelen = ncp->nc_nlen; 588 cnp.cn_cred = ap->a_cred; 589 cnp.cn_td = td; 590 591 tvp = NULL; 592 error = vop_old_lookup(ap->a_head.a_ops, dvp, &tvp, &cnp); 593 594 /* 595 * EJUSTRETURN should be returned for this case, which means that 596 * the VFS has setup the directory inode for the create. The dvp we 597 * passed in is expected to remain in a locked state. 598 * 599 * If the VOP_OLD_LINK is successful we are responsible for updating 600 * the cache state of the locked ncp that was passed to us. 601 */ 602 if (error == EJUSTRETURN) { 603 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0); 604 error = VOP_OLD_LINK(dvp, ap->a_vp, &cnp); 605 if (error == 0) { 606 cache_setunresolved(nch); 607 cache_setvp(nch, ap->a_vp); 608 } 609 } else { 610 if (error == 0) { 611 vput(tvp); 612 error = EEXIST; 613 } 614 } 615 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 616 vn_unlock(dvp); 617 vrele(dvp); 618 return (error); 619 } 620 621 int 622 vop_compat_nsymlink(struct vop_nsymlink_args *ap) 623 { 624 struct thread *td = curthread; 625 struct componentname cnp; 626 struct nchandle *nch; 627 struct namecache *ncp; 628 struct vnode *dvp; 629 struct vnode *vp; 630 int error; 631 632 /* 633 * Sanity checks, get a locked directory vnode. 634 */ 635 *ap->a_vpp = NULL; 636 nch = ap->a_nch; /* locked namecache node */ 637 ncp = nch->ncp; 638 dvp = ap->a_dvp; 639 640 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 641 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 642 ncp, ncp->nc_name); 643 return(EAGAIN); 644 } 645 646 /* 647 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 648 * caches all information required to create the entry in the 649 * directory inode. We expect a return code of EJUSTRETURN for 650 * the CREATE case. The cnp must simulated a saved-name situation. 651 */ 652 bzero(&cnp, sizeof(cnp)); 653 cnp.cn_nameiop = NAMEI_CREATE; 654 cnp.cn_flags = CNP_LOCKPARENT; 655 cnp.cn_nameptr = ncp->nc_name; 656 cnp.cn_namelen = ncp->nc_nlen; 657 cnp.cn_cred = ap->a_cred; 658 cnp.cn_td = td; 659 660 vp = NULL; 661 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp); 662 663 /* 664 * EJUSTRETURN should be returned for this case, which means that 665 * the VFS has setup the directory inode for the create. The dvp we 666 * passed in is expected to remain in a locked state. 667 * 668 * If the VOP_OLD_SYMLINK is successful we are responsible for updating 669 * the cache state of the locked ncp that was passed to us. 670 */ 671 if (error == EJUSTRETURN) { 672 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0); 673 error = VOP_OLD_SYMLINK(dvp, &vp, &cnp, ap->a_vap, ap->a_target); 674 if (error == 0) { 675 cache_setunresolved(nch); 676 cache_setvp(nch, vp); 677 *ap->a_vpp = vp; 678 } 679 } else { 680 if (error == 0) { 681 vput(vp); 682 vp = NULL; 683 error = EEXIST; 684 } 685 KKASSERT(vp == NULL); 686 } 687 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 688 vn_unlock(dvp); 689 vrele(dvp); 690 return (error); 691 } 692 693 /* 694 * vop_compat_nwhiteout { struct nchandle *a_nch, XXX STOPGAP FUNCTION 695 * struct vnode *a_dvp, 696 * struct ucred *a_cred, 697 * int a_flags } 698 * 699 * Issie a whiteout operation (create, lookup, or delete). Compatibility 700 * requires us to issue the appropriate VOP_OLD_LOOKUP before we issue 701 * VOP_OLD_WHITEOUT in order to setup the directory inode's i_offset and i_count 702 * (e.g. in UFS) for the NAMEI_CREATE and NAMEI_DELETE ops. For NAMEI_LOOKUP 703 * no lookup is necessary. 704 */ 705 int 706 vop_compat_nwhiteout(struct vop_nwhiteout_args *ap) 707 { 708 struct thread *td = curthread; 709 struct componentname cnp; 710 struct nchandle *nch; 711 struct namecache *ncp; 712 struct vnode *dvp; 713 struct vnode *vp; 714 int error; 715 716 /* 717 * Sanity checks, get a locked directory vnode. 718 */ 719 nch = ap->a_nch; /* locked namecache node */ 720 ncp = nch->ncp; 721 dvp = ap->a_dvp; 722 723 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 724 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 725 ncp, ncp->nc_name); 726 return(EAGAIN); 727 } 728 729 /* 730 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 731 * caches all information required to create the entry in the 732 * directory inode. We expect a return code of EJUSTRETURN for 733 * the CREATE case. The cnp must simulated a saved-name situation. 734 */ 735 bzero(&cnp, sizeof(cnp)); 736 cnp.cn_nameiop = ap->a_flags; 737 cnp.cn_flags = CNP_LOCKPARENT; 738 cnp.cn_nameptr = ncp->nc_name; 739 cnp.cn_namelen = ncp->nc_nlen; 740 cnp.cn_cred = ap->a_cred; 741 cnp.cn_td = td; 742 743 vp = NULL; 744 745 /* 746 * EJUSTRETURN should be returned for the CREATE or DELETE cases. 747 * The VFS has setup the directory inode for the create. The dvp we 748 * passed in is expected to remain in a locked state. 749 * 750 * If the VOP_OLD_WHITEOUT is successful we are responsible for updating 751 * the cache state of the locked ncp that was passed to us. 752 */ 753 switch(ap->a_flags) { 754 case NAMEI_DELETE: 755 cnp.cn_flags |= CNP_DOWHITEOUT; 756 /* fall through */ 757 case NAMEI_CREATE: 758 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp); 759 if (error == EJUSTRETURN) { 760 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0); 761 error = VOP_OLD_WHITEOUT(dvp, &cnp, ap->a_flags); 762 if (error == 0) 763 cache_setunresolved(nch); 764 } else { 765 if (error == 0) { 766 vput(vp); 767 vp = NULL; 768 error = EEXIST; 769 } 770 KKASSERT(vp == NULL); 771 } 772 break; 773 case NAMEI_LOOKUP: 774 error = VOP_OLD_WHITEOUT(dvp, NULL, ap->a_flags); 775 break; 776 default: 777 error = EINVAL; 778 break; 779 } 780 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 781 vn_unlock(dvp); 782 vrele(dvp); 783 return (error); 784 } 785 786 787 /* 788 * vop_compat_nremove { struct nchandle *a_nch, XXX STOPGAP FUNCTION 789 * struct vnode *a_dvp, 790 * struct ucred *a_cred } 791 */ 792 int 793 vop_compat_nremove(struct vop_nremove_args *ap) 794 { 795 struct thread *td = curthread; 796 struct componentname cnp; 797 struct nchandle *nch; 798 struct namecache *ncp; 799 struct vnode *dvp; 800 struct vnode *vp; 801 int error; 802 803 /* 804 * Sanity checks, get a locked directory vnode. 805 */ 806 nch = ap->a_nch; /* locked namecache node */ 807 ncp = nch->ncp; 808 dvp = ap->a_dvp; 809 810 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 811 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 812 ncp, ncp->nc_name); 813 return(EAGAIN); 814 } 815 816 /* 817 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 818 * caches all information required to delete the entry in the 819 * directory inode. We expect a return code of 0 for the DELETE 820 * case (meaning that a vp has been found). The cnp must simulated 821 * a saved-name situation. 822 */ 823 bzero(&cnp, sizeof(cnp)); 824 cnp.cn_nameiop = NAMEI_DELETE; 825 cnp.cn_flags = CNP_LOCKPARENT; 826 cnp.cn_nameptr = ncp->nc_name; 827 cnp.cn_namelen = ncp->nc_nlen; 828 cnp.cn_cred = ap->a_cred; 829 cnp.cn_td = td; 830 831 /* 832 * The vnode must be a directory and must not represent the 833 * current directory. 834 */ 835 vp = NULL; 836 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp); 837 if (error == 0 && vp->v_type == VDIR) 838 error = EPERM; 839 if (error == 0) { 840 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0); 841 error = VOP_OLD_REMOVE(dvp, vp, &cnp); 842 if (error == 0) { 843 cache_setunresolved(nch); 844 cache_setvp(nch, NULL); 845 cache_inval_vp(vp, CINV_DESTROY); 846 } 847 } 848 if (vp) { 849 if (dvp == vp) 850 vrele(vp); 851 else 852 vput(vp); 853 } 854 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 855 vn_unlock(dvp); 856 vrele(dvp); 857 return (error); 858 } 859 860 /* 861 * vop_compat_nrmdir { struct nchandle *a_nch, XXX STOPGAP FUNCTION 862 * struct vnode *dvp, 863 * struct ucred *a_cred } 864 */ 865 int 866 vop_compat_nrmdir(struct vop_nrmdir_args *ap) 867 { 868 struct thread *td = curthread; 869 struct componentname cnp; 870 struct nchandle *nch; 871 struct namecache *ncp; 872 struct vnode *dvp; 873 struct vnode *vp; 874 int error; 875 876 /* 877 * Sanity checks, get a locked directory vnode. 878 */ 879 nch = ap->a_nch; /* locked namecache node */ 880 ncp = nch->ncp; 881 dvp = ap->a_dvp; 882 883 if ((error = vget(dvp, LK_EXCLUSIVE)) != 0) { 884 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 885 ncp, ncp->nc_name); 886 return(EAGAIN); 887 } 888 889 /* 890 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 891 * caches all information required to delete the entry in the 892 * directory inode. We expect a return code of 0 for the DELETE 893 * case (meaning that a vp has been found). The cnp must simulated 894 * a saved-name situation. 895 */ 896 bzero(&cnp, sizeof(cnp)); 897 cnp.cn_nameiop = NAMEI_DELETE; 898 cnp.cn_flags = CNP_LOCKPARENT; 899 cnp.cn_nameptr = ncp->nc_name; 900 cnp.cn_namelen = ncp->nc_nlen; 901 cnp.cn_cred = ap->a_cred; 902 cnp.cn_td = td; 903 904 /* 905 * The vnode must be a directory and must not represent the 906 * current directory. 907 */ 908 vp = NULL; 909 error = vop_old_lookup(ap->a_head.a_ops, dvp, &vp, &cnp); 910 if (error == 0 && vp->v_type != VDIR) 911 error = ENOTDIR; 912 if (error == 0 && vp == dvp) 913 error = EINVAL; 914 if (error == 0 && (vp->v_flag & VROOT)) 915 error = EBUSY; 916 if (error == 0) { 917 KKASSERT((cnp.cn_flags & CNP_PDIRUNLOCK) == 0); 918 error = VOP_OLD_RMDIR(dvp, vp, &cnp); 919 920 /* 921 * Note that this invalidation will cause any process 922 * currently CD'd into the directory being removed to be 923 * disconnected from the topology and not be able to ".." 924 * back out. 925 */ 926 if (error == 0) { 927 cache_inval(nch, CINV_DESTROY); 928 cache_inval_vp(vp, CINV_DESTROY); 929 } 930 } 931 if (vp) { 932 if (dvp == vp) 933 vrele(vp); 934 else 935 vput(vp); 936 } 937 if ((cnp.cn_flags & CNP_PDIRUNLOCK) == 0) 938 vn_unlock(dvp); 939 vrele(dvp); 940 return (error); 941 } 942 943 /* 944 * vop_compat_nrename { struct nchandle *a_fnch, XXX STOPGAP FUNCTION 945 * struct nchandle *a_tnch, 946 * struct ucred *a_cred } 947 * 948 * This is a fairly difficult procedure. The old VOP_OLD_RENAME requires that 949 * the source directory and vnode be unlocked and the target directory and 950 * vnode (if it exists) be locked. All arguments will be vrele'd and 951 * the targets will also be unlocked regardless of the return code. 952 */ 953 int 954 vop_compat_nrename(struct vop_nrename_args *ap) 955 { 956 struct thread *td = curthread; 957 struct componentname fcnp; 958 struct componentname tcnp; 959 struct nchandle *fnch; 960 struct nchandle *tnch; 961 struct namecache *fncp; 962 struct namecache *tncp; 963 struct vnode *fdvp, *fvp; 964 struct vnode *tdvp, *tvp; 965 int error; 966 967 /* 968 * Sanity checks, get referenced vnodes representing the source. 969 */ 970 fnch = ap->a_fnch; /* locked namecache node */ 971 fncp = fnch->ncp; 972 fdvp = ap->a_fdvp; 973 974 /* 975 * Temporarily lock the source directory and lookup in DELETE mode to 976 * check permissions. XXX delete permissions should have been 977 * checked by nlookup(), we need to add NLC_DELETE for delete 978 * checking. It is unclear whether VFS's require the directory setup 979 * info NAMEI_DELETE causes to be stored in the fdvp's inode, but 980 * since it isn't locked and since UFS always does a relookup of 981 * the source, it is believed that the only side effect that matters 982 * is the permissions check. 983 */ 984 if ((error = vget(fdvp, LK_EXCLUSIVE)) != 0) { 985 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 986 fncp, fncp->nc_name); 987 return(EAGAIN); 988 } 989 990 bzero(&fcnp, sizeof(fcnp)); 991 fcnp.cn_nameiop = NAMEI_DELETE; 992 fcnp.cn_flags = CNP_LOCKPARENT; 993 fcnp.cn_nameptr = fncp->nc_name; 994 fcnp.cn_namelen = fncp->nc_nlen; 995 fcnp.cn_cred = ap->a_cred; 996 fcnp.cn_td = td; 997 998 /* 999 * note: vop_old_lookup (i.e. VOP_OLD_LOOKUP) always returns a locked 1000 * fvp. 1001 */ 1002 fvp = NULL; 1003 error = vop_old_lookup(ap->a_head.a_ops, fdvp, &fvp, &fcnp); 1004 if (error == 0 && (fvp->v_flag & VROOT)) { 1005 vput(fvp); /* as if vop_old_lookup had failed */ 1006 error = EBUSY; 1007 } 1008 if ((fcnp.cn_flags & CNP_PDIRUNLOCK) == 0) { 1009 fcnp.cn_flags |= CNP_PDIRUNLOCK; 1010 vn_unlock(fdvp); 1011 } 1012 if (error) { 1013 vrele(fdvp); 1014 return (error); 1015 } 1016 vn_unlock(fvp); 1017 1018 /* 1019 * fdvp and fvp are now referenced and unlocked. 1020 * 1021 * Get a locked directory vnode for the target and lookup the target 1022 * in CREATE mode so it places the required information in the 1023 * directory inode. 1024 */ 1025 tnch = ap->a_tnch; /* locked namecache node */ 1026 tncp = tnch->ncp; 1027 tdvp = ap->a_tdvp; 1028 if (error) { 1029 vrele(fdvp); 1030 vrele(fvp); 1031 return (error); 1032 } 1033 if ((error = vget(tdvp, LK_EXCLUSIVE)) != 0) { 1034 kprintf("[diagnostic] vop_compat_resolve: EAGAIN on ncp %p %s\n", 1035 tncp, tncp->nc_name); 1036 vrele(fdvp); 1037 vrele(fvp); 1038 return(EAGAIN); 1039 } 1040 1041 /* 1042 * Setup the cnp for a traditional vop_old_lookup() call. The lookup 1043 * caches all information required to create the entry in the 1044 * target directory inode. 1045 */ 1046 bzero(&tcnp, sizeof(tcnp)); 1047 tcnp.cn_nameiop = NAMEI_RENAME; 1048 tcnp.cn_flags = CNP_LOCKPARENT; 1049 tcnp.cn_nameptr = tncp->nc_name; 1050 tcnp.cn_namelen = tncp->nc_nlen; 1051 tcnp.cn_cred = ap->a_cred; 1052 tcnp.cn_td = td; 1053 1054 tvp = NULL; 1055 error = vop_old_lookup(ap->a_head.a_ops, tdvp, &tvp, &tcnp); 1056 1057 if (error == EJUSTRETURN) { 1058 /* 1059 * Target does not exist. tvp should be NULL. 1060 */ 1061 KKASSERT(tvp == NULL); 1062 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0); 1063 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp); 1064 if (error == 0) 1065 cache_rename(fnch, tnch); 1066 } else if (error == 0) { 1067 /* 1068 * Target exists. VOP_OLD_RENAME should correctly delete the 1069 * target. 1070 */ 1071 KKASSERT((tcnp.cn_flags & CNP_PDIRUNLOCK) == 0); 1072 error = VOP_OLD_RENAME(fdvp, fvp, &fcnp, tdvp, tvp, &tcnp); 1073 if (error == 0) 1074 cache_rename(fnch, tnch); 1075 } else { 1076 vrele(fdvp); 1077 vrele(fvp); 1078 if (tcnp.cn_flags & CNP_PDIRUNLOCK) 1079 vrele(tdvp); 1080 else 1081 vput(tdvp); 1082 } 1083 return (error); 1084 } 1085 1086 static int 1087 vop_nolookup(struct vop_old_lookup_args *ap) 1088 { 1089 1090 *ap->a_vpp = NULL; 1091 return (ENOTDIR); 1092 } 1093 1094 /* 1095 * vop_nostrategy: 1096 * 1097 * Strategy routine for VFS devices that have none. 1098 * 1099 * B_ERROR and B_INVAL must be cleared prior to calling any strategy 1100 * routine. Typically this is done for a BUF_CMD_READ strategy call. 1101 * Typically B_INVAL is assumed to already be clear prior to a write 1102 * and should not be cleared manually unless you just made the buffer 1103 * invalid. B_ERROR should be cleared either way. 1104 */ 1105 1106 static int 1107 vop_nostrategy (struct vop_strategy_args *ap) 1108 { 1109 kprintf("No strategy for buffer at %p\n", ap->a_bio->bio_buf); 1110 vprint("", ap->a_vp); 1111 ap->a_bio->bio_buf->b_flags |= B_ERROR; 1112 ap->a_bio->bio_buf->b_error = EOPNOTSUPP; 1113 biodone(ap->a_bio); 1114 return (EOPNOTSUPP); 1115 } 1116 1117 int 1118 vop_stdpathconf(struct vop_pathconf_args *ap) 1119 { 1120 int error = 0; 1121 1122 switch (ap->a_name) { 1123 case _PC_LINK_MAX: 1124 *ap->a_retval = LINK_MAX; 1125 break; 1126 case _PC_NAME_MAX: 1127 *ap->a_retval = NAME_MAX; 1128 break; 1129 case _PC_PATH_MAX: 1130 *ap->a_retval = PATH_MAX; 1131 break; 1132 case _PC_MAX_CANON: 1133 *ap->a_retval = MAX_CANON; 1134 break; 1135 case _PC_MAX_INPUT: 1136 *ap->a_retval = MAX_INPUT; 1137 break; 1138 case _PC_PIPE_BUF: 1139 *ap->a_retval = PIPE_BUF; 1140 break; 1141 case _PC_CHOWN_RESTRICTED: 1142 *ap->a_retval = 1; 1143 break; 1144 case _PC_NO_TRUNC: 1145 *ap->a_retval = 1; 1146 break; 1147 case _PC_VDISABLE: 1148 *ap->a_retval = _POSIX_VDISABLE; 1149 break; 1150 default: 1151 error = EINVAL; 1152 break; 1153 } 1154 return (error); 1155 } 1156 1157 /* 1158 * Standard open. 1159 * 1160 * (struct vnode *a_vp, int a_mode, struct ucred *a_ucred, struct file *a_fp) 1161 * 1162 * a_mode: note, 'F' modes, e.g. FREAD, FWRITE 1163 */ 1164 int 1165 vop_stdopen(struct vop_open_args *ap) 1166 { 1167 struct vnode *vp = ap->a_vp; 1168 struct file *fp; 1169 1170 if ((fp = ap->a_fp) != NULL) { 1171 switch(vp->v_type) { 1172 case VFIFO: 1173 fp->f_type = DTYPE_FIFO; 1174 break; 1175 default: 1176 fp->f_type = DTYPE_VNODE; 1177 break; 1178 } 1179 fp->f_flag = ap->a_mode & FMASK; 1180 fp->f_ops = &vnode_fileops; 1181 fp->f_data = vp; 1182 vref(vp); 1183 } 1184 if (ap->a_mode & FWRITE) 1185 ++vp->v_writecount; 1186 KKASSERT(vp->v_opencount >= 0 && vp->v_opencount != INT_MAX); 1187 ++vp->v_opencount; 1188 return (0); 1189 } 1190 1191 /* 1192 * Standard close. 1193 * 1194 * (struct vnode *a_vp, int a_fflag) 1195 * 1196 * a_fflag: note, 'F' modes, e.g. FREAD, FWRITE. same as a_mode in stdopen? 1197 */ 1198 int 1199 vop_stdclose(struct vop_close_args *ap) 1200 { 1201 struct vnode *vp = ap->a_vp; 1202 1203 KASSERT(vp->v_opencount > 0, 1204 ("VOP_STDCLOSE: BAD OPENCOUNT %p %d type=%d ops=%p flgs=%08x\n", 1205 vp, vp->v_opencount, vp->v_type, *vp->v_ops, vp->v_flag)); 1206 if (ap->a_fflag & FWRITE) { 1207 KASSERT(vp->v_writecount > 0, 1208 ("VOP_STDCLOSE: BAD WRITECOUNT %p %d\n", 1209 vp, vp->v_writecount)); 1210 --vp->v_writecount; 1211 } 1212 --vp->v_opencount; 1213 return (0); 1214 } 1215 1216 /* 1217 * Implement standard getpages and putpages. All filesystems must use 1218 * the buffer cache to back regular files. 1219 */ 1220 int 1221 vop_stdgetpages(struct vop_getpages_args *ap) 1222 { 1223 struct mount *mp; 1224 int error; 1225 1226 if ((mp = ap->a_vp->v_mount) != NULL) { 1227 error = vnode_pager_generic_getpages( 1228 ap->a_vp, ap->a_m, ap->a_count, 1229 ap->a_reqpage, ap->a_seqaccess); 1230 } else { 1231 error = VM_PAGER_BAD; 1232 } 1233 return (error); 1234 } 1235 1236 int 1237 vop_stdputpages(struct vop_putpages_args *ap) 1238 { 1239 struct mount *mp; 1240 int error; 1241 1242 if ((mp = ap->a_vp->v_mount) != NULL) { 1243 error = vnode_pager_generic_putpages( 1244 ap->a_vp, ap->a_m, ap->a_count, 1245 ap->a_sync, ap->a_rtvals); 1246 } else { 1247 error = VM_PAGER_BAD; 1248 } 1249 return (error); 1250 } 1251 1252 int 1253 vop_stdnoread(struct vop_read_args *ap) 1254 { 1255 return (EINVAL); 1256 } 1257 1258 int 1259 vop_stdnowrite(struct vop_write_args *ap) 1260 { 1261 return (EINVAL); 1262 } 1263 1264 /* 1265 * vfs default ops 1266 * used to fill the vfs fucntion table to get reasonable default return values. 1267 */ 1268 int 1269 vfs_stdmount(struct mount *mp, char *path, caddr_t data, struct ucred *cred) 1270 { 1271 return (0); 1272 } 1273 1274 int 1275 vfs_stdunmount(struct mount *mp, int mntflags) 1276 { 1277 return (0); 1278 } 1279 1280 int 1281 vop_stdmountctl(struct vop_mountctl_args *ap) 1282 { 1283 1284 struct mount *mp; 1285 int error = 0; 1286 1287 mp = ap->a_head.a_ops->head.vv_mount; 1288 1289 switch(ap->a_op) { 1290 case MOUNTCTL_MOUNTFLAGS: 1291 /* 1292 * Get a string buffer with all the mount flags 1293 * names comman separated. 1294 * mount(2) will use this information. 1295 */ 1296 *ap->a_res = vfs_flagstostr(mp->mnt_flag & MNT_VISFLAGMASK, NULL, 1297 ap->a_buf, ap->a_buflen, &error); 1298 break; 1299 case MOUNTCTL_INSTALL_VFS_JOURNAL: 1300 case MOUNTCTL_RESTART_VFS_JOURNAL: 1301 case MOUNTCTL_REMOVE_VFS_JOURNAL: 1302 case MOUNTCTL_RESYNC_VFS_JOURNAL: 1303 case MOUNTCTL_STATUS_VFS_JOURNAL: 1304 error = journal_mountctl(ap); 1305 break; 1306 default: 1307 error = EOPNOTSUPP; 1308 break; 1309 } 1310 return (error); 1311 } 1312 1313 int 1314 vfs_stdroot(struct mount *mp, struct vnode **vpp) 1315 { 1316 return (EOPNOTSUPP); 1317 } 1318 1319 int 1320 vfs_stdstatfs(struct mount *mp, struct statfs *sbp, struct ucred *cred) 1321 { 1322 return (EOPNOTSUPP); 1323 } 1324 1325 /* 1326 * If the VFS does not implement statvfs, then call statfs and convert 1327 * the values. This code was taken from libc's __cvtstatvfs() function, 1328 * contributed by Joerg Sonnenberger. 1329 */ 1330 int 1331 vfs_stdstatvfs(struct mount *mp, struct statvfs *sbp, struct ucred *cred) 1332 { 1333 struct statfs *in; 1334 int error; 1335 1336 in = &mp->mnt_stat; 1337 error = VFS_STATFS(mp, in, cred); 1338 if (error == 0) { 1339 bzero(sbp, sizeof(*sbp)); 1340 1341 sbp->f_bsize = in->f_bsize; 1342 sbp->f_frsize = in->f_bsize; 1343 sbp->f_blocks = in->f_blocks; 1344 sbp->f_bfree = in->f_bfree; 1345 sbp->f_bavail = in->f_bavail; 1346 sbp->f_files = in->f_files; 1347 sbp->f_ffree = in->f_ffree; 1348 1349 /* 1350 * XXX 1351 * This field counts the number of available inodes to non-root 1352 * users, but this information is not available via statfs. 1353 * Just ignore this issue by returning the total number 1354 * instead. 1355 */ 1356 sbp->f_favail = in->f_ffree; 1357 1358 /* 1359 * XXX 1360 * This field has a different meaning for statfs and statvfs. 1361 * For the former it is the cookie exported for NFS and not 1362 * intended for normal userland use. 1363 */ 1364 sbp->f_fsid = 0; 1365 1366 sbp->f_flag = 0; 1367 if (in->f_flags & MNT_RDONLY) 1368 sbp->f_flag |= ST_RDONLY; 1369 if (in->f_flags & MNT_NOSUID) 1370 sbp->f_flag |= ST_NOSUID; 1371 sbp->f_namemax = 0; 1372 sbp->f_owner = in->f_owner; 1373 /* 1374 * XXX 1375 * statfs contains the type as string, statvfs expects it as 1376 * enumeration. 1377 */ 1378 sbp->f_type = 0; 1379 1380 sbp->f_syncreads = in->f_syncreads; 1381 sbp->f_syncwrites = in->f_syncwrites; 1382 sbp->f_asyncreads = in->f_asyncreads; 1383 sbp->f_asyncwrites = in->f_asyncwrites; 1384 } 1385 return (error); 1386 } 1387 1388 int 1389 vfs_stdvptofh(struct vnode *vp, struct fid *fhp) 1390 { 1391 return (EOPNOTSUPP); 1392 } 1393 1394 int 1395 vfs_stdstart(struct mount *mp, int flags) 1396 { 1397 return (0); 1398 } 1399 1400 int 1401 vfs_stdquotactl(struct mount *mp, int cmds, uid_t uid, 1402 caddr_t arg, struct ucred *cred) 1403 { 1404 return (EOPNOTSUPP); 1405 } 1406 1407 int 1408 vfs_stdsync(struct mount *mp, int waitfor) 1409 { 1410 return (0); 1411 } 1412 1413 int 1414 vfs_stdnosync(struct mount *mp, int waitfor) 1415 { 1416 return (EOPNOTSUPP); 1417 } 1418 1419 int 1420 vfs_stdvget(struct mount *mp, struct vnode *dvp, ino_t ino, struct vnode **vpp) 1421 { 1422 return (EOPNOTSUPP); 1423 } 1424 1425 int 1426 vfs_stdfhtovp(struct mount *mp, struct vnode *rootvp, 1427 struct fid *fhp, struct vnode **vpp) 1428 { 1429 return (EOPNOTSUPP); 1430 } 1431 1432 int 1433 vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp, 1434 struct ucred **credanonp) 1435 { 1436 return (EOPNOTSUPP); 1437 } 1438 1439 int 1440 vfs_stdinit(struct vfsconf *vfsp) 1441 { 1442 return (0); 1443 } 1444 1445 int 1446 vfs_stduninit(struct vfsconf *vfsp) 1447 { 1448 return(0); 1449 } 1450 1451 int 1452 vfs_stdextattrctl(struct mount *mp, int cmd, struct vnode *vp, 1453 int attrnamespace, const char *attrname, 1454 struct ucred *cred) 1455 { 1456 return(EOPNOTSUPP); 1457 } 1458 1459 /* end of vfs default ops */ 1460