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