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