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