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