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