1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 14 */ 15 16 #include <sys/types.h> 17 #include <sys/param.h> 18 #include <sys/t_lock.h> 19 #include <sys/errno.h> 20 #include <sys/cred.h> 21 #include <sys/user.h> 22 #include <sys/uio.h> 23 #include <sys/file.h> 24 #include <sys/pathname.h> 25 #include <sys/vfs.h> 26 #include <sys/vnode.h> 27 #include <sys/stat.h> 28 #include <sys/mode.h> 29 #include <sys/kmem.h> 30 #include <sys/debug.h> 31 #include <sys/atomic.h> 32 #include <sys/acl.h> 33 #include <sys/flock.h> 34 #include <sys/nbmlock.h> 35 #include <sys/fcntl.h> 36 #include <sys/poll.h> 37 #include <sys/time.h> 38 39 #include <errno.h> 40 #include <fcntl.h> 41 #include <unistd.h> 42 43 #include "vncache.h" 44 45 #define O_RWMASK (O_WRONLY | O_RDWR) /* == 3 */ 46 47 int fop_shrlock_enable = 0; 48 49 int stat_to_vattr(const struct stat *, vattr_t *); 50 int fop__getxvattr(vnode_t *, xvattr_t *); 51 int fop__setxvattr(vnode_t *, xvattr_t *); 52 53 54 /* ARGSUSED */ 55 int 56 fop_open( 57 vnode_t **vpp, 58 int mode, 59 cred_t *cr, 60 caller_context_t *ct) 61 { 62 63 if ((*vpp)->v_type == VREG) { 64 if (mode & FREAD) 65 atomic_add_32(&((*vpp)->v_rdcnt), 1); 66 if (mode & FWRITE) 67 atomic_add_32(&((*vpp)->v_wrcnt), 1); 68 } 69 70 /* call to ->vop_open was here */ 71 72 return (0); 73 } 74 75 /* ARGSUSED */ 76 int 77 fop_close( 78 vnode_t *vp, 79 int flag, 80 int count, 81 offset_t offset, 82 cred_t *cr, 83 caller_context_t *ct) 84 { 85 86 /* call to ->vop_close was here */ 87 88 /* 89 * Check passed in count to handle possible dups. Vnode counts are only 90 * kept on regular files 91 */ 92 if ((vp->v_type == VREG) && (count == 1)) { 93 if (flag & FREAD) { 94 ASSERT(vp->v_rdcnt > 0); 95 atomic_add_32(&(vp->v_rdcnt), -1); 96 } 97 if (flag & FWRITE) { 98 ASSERT(vp->v_wrcnt > 0); 99 atomic_add_32(&(vp->v_wrcnt), -1); 100 } 101 } 102 return (0); 103 } 104 105 /* ARGSUSED */ 106 int 107 fop_read( 108 vnode_t *vp, 109 uio_t *uio, 110 int ioflag, 111 cred_t *cr, 112 caller_context_t *ct) 113 { 114 struct stat st; 115 struct iovec *iov; 116 ssize_t resid; 117 size_t cnt; 118 int n; 119 120 /* 121 * If that caller asks for read beyond end of file, 122 * that causes the pread call to block. (Ugh!) 123 * Get the file size and return what we can. 124 */ 125 (void) fstat(vp->v_fd, &st); 126 resid = uio->uio_resid; 127 if ((uio->uio_loffset + resid) > st.st_size) 128 resid = st.st_size - uio->uio_loffset; 129 130 while (resid > 0) { 131 132 ASSERT(uio->uio_iovcnt > 0); 133 iov = uio->uio_iov; 134 135 if (iov->iov_len == 0) { 136 uio->uio_iov++; 137 uio->uio_iovcnt--; 138 continue; 139 } 140 cnt = iov->iov_len; 141 if (cnt > resid) 142 cnt = resid; 143 144 n = pread(vp->v_fd, iov->iov_base, cnt, uio->uio_loffset); 145 if (n < 0) 146 return (errno); 147 148 iov->iov_base += n; 149 iov->iov_len -= n; 150 151 uio->uio_resid -= n; 152 uio->uio_loffset += n; 153 154 resid -= n; 155 } 156 157 return (0); 158 } 159 160 /* ARGSUSED */ 161 int 162 fop_write( 163 vnode_t *vp, 164 uio_t *uio, 165 int ioflag, 166 cred_t *cr, 167 caller_context_t *ct) 168 { 169 struct iovec *iov; 170 size_t cnt; 171 int n; 172 173 while (uio->uio_resid > 0) { 174 175 ASSERT(uio->uio_iovcnt > 0); 176 iov = uio->uio_iov; 177 178 if (iov->iov_len == 0) { 179 uio->uio_iov++; 180 uio->uio_iovcnt--; 181 continue; 182 } 183 cnt = iov->iov_len; 184 if (cnt > uio->uio_resid) 185 cnt = uio->uio_resid; 186 187 n = pwrite(vp->v_fd, iov->iov_base, iov->iov_len, 188 uio->uio_loffset); 189 if (n < 0) 190 return (errno); 191 192 iov->iov_base += n; 193 iov->iov_len -= n; 194 195 uio->uio_resid -= n; 196 uio->uio_loffset += n; 197 } 198 199 if (ioflag == FSYNC) { 200 (void) fsync(vp->v_fd); 201 } 202 203 return (0); 204 } 205 206 /* ARGSUSED */ 207 int 208 fop_ioctl( 209 vnode_t *vp, 210 int cmd, 211 intptr_t arg, 212 int flag, 213 cred_t *cr, 214 int *rvalp, 215 caller_context_t *ct) 216 { 217 return (ENOSYS); 218 } 219 220 /* ARGSUSED */ 221 int 222 fop_setfl( 223 vnode_t *vp, 224 int oflags, 225 int nflags, 226 cred_t *cr, 227 caller_context_t *ct) 228 { 229 /* allow any flags? See fs_setfl */ 230 return (0); 231 } 232 233 /* ARGSUSED */ 234 int 235 fop_getattr( 236 vnode_t *vp, 237 vattr_t *vap, 238 int flags, 239 cred_t *cr, 240 caller_context_t *ct) 241 { 242 int error; 243 struct stat st; 244 245 if (fstat(vp->v_fd, &st) == -1) 246 return (errno); 247 error = stat_to_vattr(&st, vap); 248 249 if (vap->va_mask & AT_XVATTR) 250 (void) fop__getxvattr(vp, (xvattr_t *)vap); 251 252 return (error); 253 } 254 255 /* ARGSUSED */ 256 int 257 fop_setattr( 258 vnode_t *vp, 259 vattr_t *vap, 260 int flags, 261 cred_t *cr, 262 caller_context_t *ct) 263 { 264 struct timeval times[2]; 265 266 if (vap->va_mask & AT_SIZE) { 267 if (ftruncate(vp->v_fd, vap->va_size) == -1) 268 return (errno); 269 } 270 271 /* AT_MODE or anything else? */ 272 273 if (vap->va_mask & AT_XVATTR) 274 (void) fop__setxvattr(vp, (xvattr_t *)vap); 275 276 if (vap->va_mask & (AT_ATIME | AT_MTIME)) { 277 times[0].tv_sec = 0; 278 times[0].tv_usec = UTIME_OMIT; 279 times[1].tv_sec = 0; 280 times[1].tv_usec = UTIME_OMIT; 281 if (vap->va_mask & AT_ATIME) { 282 times[0].tv_sec = vap->va_atime.tv_sec; 283 times[0].tv_usec = vap->va_atime.tv_nsec / 1000; 284 } 285 if (vap->va_mask & AT_MTIME) { 286 times[1].tv_sec = vap->va_mtime.tv_sec; 287 times[1].tv_usec = vap->va_mtime.tv_nsec / 1000; 288 } 289 290 (void) futimesat(vp->v_fd, NULL, times); 291 } 292 293 return (0); 294 } 295 296 /* ARGSUSED */ 297 int 298 fop_access( 299 vnode_t *vp, 300 int mode, 301 int flags, 302 cred_t *cr, 303 caller_context_t *ct) 304 { 305 return (0); 306 } 307 308 /* ARGSUSED */ 309 int 310 fop_lookup( 311 vnode_t *dvp, 312 char *name, 313 vnode_t **vpp, 314 pathname_t *pnp, 315 int flags, 316 vnode_t *rdir, 317 cred_t *cr, 318 caller_context_t *ct, 319 int *deflags, /* Returned per-dirent flags */ 320 pathname_t *ppnp) /* Returned case-preserved name in directory */ 321 { 322 int fd; 323 int omode = O_RDWR | O_NOFOLLOW; 324 vnode_t *vp; 325 struct stat st; 326 327 if (flags & LOOKUP_XATTR) 328 return (ENOENT); 329 330 /* 331 * If lookup is for "", just return dvp. 332 */ 333 if (name[0] == '\0') { 334 vn_hold(dvp); 335 *vpp = dvp; 336 return (0); 337 } 338 339 if (fstatat(dvp->v_fd, name, &st, AT_SYMLINK_NOFOLLOW) == -1) 340 return (errno); 341 342 vp = vncache_lookup(&st); 343 if (vp != NULL) { 344 /* lookup gave us a hold */ 345 *vpp = vp; 346 return (0); 347 } 348 349 if (S_ISDIR(st.st_mode)) 350 omode = O_RDONLY | O_NOFOLLOW; 351 352 again: 353 fd = openat(dvp->v_fd, name, omode, 0); 354 if (fd < 0) { 355 if ((omode & O_RWMASK) == O_RDWR) { 356 omode &= ~O_RWMASK; 357 omode |= O_RDONLY; 358 goto again; 359 } 360 return (errno); 361 } 362 363 if (fstat(fd, &st) == -1) { 364 (void) close(fd); 365 return (errno); 366 } 367 368 vp = vncache_enter(&st, dvp, name, fd); 369 370 *vpp = vp; 371 return (0); 372 } 373 374 /* ARGSUSED */ 375 int 376 fop_create( 377 vnode_t *dvp, 378 char *name, 379 vattr_t *vap, 380 vcexcl_t excl, 381 int mode, 382 vnode_t **vpp, 383 cred_t *cr, 384 int flags, 385 caller_context_t *ct, 386 vsecattr_t *vsecp) /* ACL to set during create */ 387 { 388 struct stat st; 389 vnode_t *vp; 390 int err, fd, omode; 391 392 /* 393 * If creating "", just return dvp. 394 */ 395 if (name[0] == '\0') { 396 vn_hold(dvp); 397 *vpp = dvp; 398 return (0); 399 } 400 401 err = fstatat(dvp->v_fd, name, &st, AT_SYMLINK_NOFOLLOW); 402 if (err != 0) 403 err = errno; 404 405 vp = NULL; 406 if (err == 0) { 407 /* The file already exists. */ 408 if (excl == EXCL) 409 return (EEXIST); 410 411 vp = vncache_lookup(&st); 412 /* vp gained a hold */ 413 } 414 415 if (vp == NULL) { 416 /* 417 * Open it. (may or may not exist) 418 */ 419 omode = O_RDWR | O_CREAT | O_NOFOLLOW; 420 if (excl == EXCL) 421 omode |= O_EXCL; 422 open_again: 423 fd = openat(dvp->v_fd, name, omode, mode); 424 if (fd < 0) { 425 if ((omode & O_RWMASK) == O_RDWR) { 426 omode &= ~O_RWMASK; 427 omode |= O_RDONLY; 428 goto open_again; 429 } 430 return (errno); 431 } 432 (void) fstat(fd, &st); 433 434 vp = vncache_enter(&st, dvp, name, fd); 435 /* vp has its initial hold */ 436 } 437 438 /* Should have the vp now. */ 439 if (vp == NULL) 440 return (EFAULT); 441 442 if (vp->v_type == VDIR && vap->va_type != VDIR) { 443 vn_rele(vp); 444 return (EISDIR); 445 } 446 if (vp->v_type != VDIR && vap->va_type == VDIR) { 447 vn_rele(vp); 448 return (ENOTDIR); 449 } 450 451 /* 452 * Truncate (if requested). 453 */ 454 if ((vap->va_mask & AT_SIZE) && vap->va_size == 0) { 455 (void) ftruncate(vp->v_fd, 0); 456 } 457 458 *vpp = vp; 459 return (0); 460 } 461 462 /* ARGSUSED */ 463 int 464 fop_remove( 465 vnode_t *dvp, 466 char *name, 467 cred_t *cr, 468 caller_context_t *ct, 469 int flags) 470 { 471 472 if (unlinkat(dvp->v_fd, name, 0)) 473 return (errno); 474 475 return (0); 476 } 477 478 /* ARGSUSED */ 479 int 480 fop_link( 481 vnode_t *to_dvp, 482 vnode_t *fr_vp, 483 char *to_name, 484 cred_t *cr, 485 caller_context_t *ct, 486 int flags) 487 { 488 int err; 489 490 /* 491 * Would prefer to specify "from" as the combination: 492 * (fr_vp->v_fd, NULL) but linkat does not permit it. 493 */ 494 err = linkat(AT_FDCWD, fr_vp->v_path, to_dvp->v_fd, to_name, 495 AT_SYMLINK_FOLLOW); 496 if (err == -1) 497 err = errno; 498 499 return (err); 500 } 501 502 /* ARGSUSED */ 503 int 504 fop_rename( 505 vnode_t *from_dvp, 506 char *from_name, 507 vnode_t *to_dvp, 508 char *to_name, 509 cred_t *cr, 510 caller_context_t *ct, 511 int flags) 512 { 513 struct stat st; 514 vnode_t *vp; 515 int err; 516 517 if (fstatat(from_dvp->v_fd, from_name, &st, 518 AT_SYMLINK_NOFOLLOW) == -1) 519 return (errno); 520 521 vp = vncache_lookup(&st); 522 if (vp == NULL) 523 return (ENOENT); 524 525 err = renameat(from_dvp->v_fd, from_name, to_dvp->v_fd, to_name); 526 if (err == -1) 527 err = errno; 528 else 529 vncache_renamed(vp, to_dvp, to_name); 530 531 vn_rele(vp); 532 533 return (err); 534 } 535 536 /* ARGSUSED */ 537 int 538 fop_mkdir( 539 vnode_t *dvp, 540 char *name, 541 vattr_t *vap, 542 vnode_t **vpp, 543 cred_t *cr, 544 caller_context_t *ct, 545 int flags, 546 vsecattr_t *vsecp) /* ACL to set during create */ 547 { 548 struct stat st; 549 int err, fd; 550 551 mode_t mode = vap->va_mode & 0777; 552 553 if (mkdirat(dvp->v_fd, name, mode) == -1) 554 return (errno); 555 556 if ((fd = openat(dvp->v_fd, name, O_RDONLY)) == -1) 557 return (errno); 558 if (fstat(fd, &st) == -1) { 559 err = errno; 560 (void) close(fd); 561 return (err); 562 } 563 564 *vpp = vncache_enter(&st, dvp, name, fd); 565 566 return (0); 567 } 568 569 /* ARGSUSED */ 570 int 571 fop_rmdir( 572 vnode_t *dvp, 573 char *name, 574 vnode_t *cdir, 575 cred_t *cr, 576 caller_context_t *ct, 577 int flags) 578 { 579 580 if (unlinkat(dvp->v_fd, name, AT_REMOVEDIR) == -1) 581 return (errno); 582 583 return (0); 584 } 585 586 /* ARGSUSED */ 587 int 588 fop_readdir( 589 vnode_t *vp, 590 uio_t *uiop, 591 cred_t *cr, 592 int *eofp, 593 caller_context_t *ct, 594 int flags) 595 { 596 struct iovec *iov; 597 int cnt; 598 int error = 0; 599 int fd = vp->v_fd; 600 601 if (eofp) { 602 *eofp = 0; 603 } 604 605 error = lseek(fd, uiop->uio_loffset, SEEK_SET); 606 if (error == -1) 607 return (errno); 608 609 ASSERT(uiop->uio_iovcnt > 0); 610 iov = uiop->uio_iov; 611 if (iov->iov_len < sizeof (struct dirent)) 612 return (EINVAL); 613 614 /* LINTED E_BAD_PTR_CAST_ALIGN */ 615 cnt = getdents(fd, (struct dirent *)(uiop->uio_iov->iov_base), 616 uiop->uio_resid); 617 if (cnt == -1) 618 return (errno); 619 if (cnt == 0) { 620 if (eofp) { 621 *eofp = 1; 622 } 623 return (ENOENT); 624 } 625 626 iov->iov_base += cnt; 627 iov->iov_len -= cnt; 628 uiop->uio_resid -= cnt; 629 uiop->uio_loffset = lseek(fd, 0LL, SEEK_CUR); 630 631 return (0); 632 } 633 634 /* ARGSUSED */ 635 int 636 fop_symlink( 637 vnode_t *dvp, 638 char *linkname, 639 vattr_t *vap, 640 char *target, 641 cred_t *cr, 642 caller_context_t *ct, 643 int flags) 644 { 645 return (ENOSYS); 646 } 647 648 /* ARGSUSED */ 649 int 650 fop_readlink( 651 vnode_t *vp, 652 uio_t *uiop, 653 cred_t *cr, 654 caller_context_t *ct) 655 { 656 return (ENOSYS); 657 } 658 659 /* ARGSUSED */ 660 int 661 fop_fsync( 662 vnode_t *vp, 663 int syncflag, 664 cred_t *cr, 665 caller_context_t *ct) 666 { 667 668 if (fsync(vp->v_fd) == -1) 669 return (errno); 670 671 return (0); 672 } 673 674 /* ARGSUSED */ 675 void 676 fop_inactive( 677 vnode_t *vp, 678 cred_t *cr, 679 caller_context_t *ct) 680 { 681 vncache_inactive(vp); 682 } 683 684 /* ARGSUSED */ 685 int 686 fop_fid( 687 vnode_t *vp, 688 fid_t *fidp, 689 caller_context_t *ct) 690 { 691 return (ENOSYS); 692 } 693 694 /* ARGSUSED */ 695 int 696 fop_rwlock( 697 vnode_t *vp, 698 int write_lock, 699 caller_context_t *ct) 700 { 701 /* See: fs_rwlock */ 702 return (-1); 703 } 704 705 /* ARGSUSED */ 706 void 707 fop_rwunlock( 708 vnode_t *vp, 709 int write_lock, 710 caller_context_t *ct) 711 { 712 /* See: fs_rwunlock */ 713 } 714 715 /* ARGSUSED */ 716 int 717 fop_seek( 718 vnode_t *vp, 719 offset_t ooff, 720 offset_t *noffp, 721 caller_context_t *ct) 722 { 723 return (ENOSYS); 724 } 725 726 /* ARGSUSED */ 727 int 728 fop_cmp( 729 vnode_t *vp1, 730 vnode_t *vp2, 731 caller_context_t *ct) 732 { 733 /* See fs_cmp */ 734 return (vncache_cmp(vp1, vp2)); 735 } 736 737 /* ARGSUSED */ 738 int 739 fop_frlock( 740 vnode_t *vp, 741 int cmd, 742 flock64_t *bfp, 743 int flag, 744 offset_t offset, 745 struct flk_callback *flk_cbp, 746 cred_t *cr, 747 caller_context_t *ct) 748 { 749 /* See fs_frlock */ 750 751 switch (cmd) { 752 case F_GETLK: 753 case F_SETLK_NBMAND: 754 case F_SETLK: 755 case F_SETLKW: 756 break; 757 default: 758 return (EINVAL); 759 } 760 761 if (fcntl(vp->v_fd, cmd, bfp) == -1) 762 return (errno); 763 764 return (0); 765 } 766 767 /* ARGSUSED */ 768 int 769 fop_space( 770 vnode_t *vp, 771 int cmd, 772 flock64_t *bfp, 773 int flag, 774 offset_t offset, 775 cred_t *cr, 776 caller_context_t *ct) 777 { 778 /* See fs_frlock */ 779 780 switch (cmd) { 781 case F_ALLOCSP: 782 case F_FREESP: 783 break; 784 default: 785 return (EINVAL); 786 } 787 788 if (fcntl(vp->v_fd, cmd, bfp) == -1) 789 return (errno); 790 791 return (0); 792 } 793 794 /* ARGSUSED */ 795 int 796 fop_realvp( 797 vnode_t *vp, 798 vnode_t **vpp, 799 caller_context_t *ct) 800 { 801 return (ENOSYS); 802 } 803 804 /* ARGSUSED */ 805 int 806 fop_getpage( 807 vnode_t *vp, 808 offset_t off, 809 size_t len, 810 uint_t *protp, 811 struct page **plarr, 812 size_t plsz, 813 struct seg *seg, 814 caddr_t addr, 815 enum seg_rw rw, 816 cred_t *cr, 817 caller_context_t *ct) 818 { 819 return (ENOSYS); 820 } 821 822 /* ARGSUSED */ 823 int 824 fop_putpage( 825 vnode_t *vp, 826 offset_t off, 827 size_t len, 828 int flags, 829 cred_t *cr, 830 caller_context_t *ct) 831 { 832 return (ENOSYS); 833 } 834 835 /* ARGSUSED */ 836 int 837 fop_map( 838 vnode_t *vp, 839 offset_t off, 840 struct as *as, 841 caddr_t *addrp, 842 size_t len, 843 uchar_t prot, 844 uchar_t maxprot, 845 uint_t flags, 846 cred_t *cr, 847 caller_context_t *ct) 848 { 849 return (ENOSYS); 850 } 851 852 /* ARGSUSED */ 853 int 854 fop_addmap( 855 vnode_t *vp, 856 offset_t off, 857 struct as *as, 858 caddr_t addr, 859 size_t len, 860 uchar_t prot, 861 uchar_t maxprot, 862 uint_t flags, 863 cred_t *cr, 864 caller_context_t *ct) 865 { 866 return (ENOSYS); 867 } 868 869 /* ARGSUSED */ 870 int 871 fop_delmap( 872 vnode_t *vp, 873 offset_t off, 874 struct as *as, 875 caddr_t addr, 876 size_t len, 877 uint_t prot, 878 uint_t maxprot, 879 uint_t flags, 880 cred_t *cr, 881 caller_context_t *ct) 882 { 883 return (ENOSYS); 884 } 885 886 /* ARGSUSED */ 887 int 888 fop_poll( 889 vnode_t *vp, 890 short events, 891 int anyyet, 892 short *reventsp, 893 struct pollhead **phpp, 894 caller_context_t *ct) 895 { 896 *reventsp = 0; 897 if (events & POLLIN) 898 *reventsp |= POLLIN; 899 if (events & POLLRDNORM) 900 *reventsp |= POLLRDNORM; 901 if (events & POLLRDBAND) 902 *reventsp |= POLLRDBAND; 903 if (events & POLLOUT) 904 *reventsp |= POLLOUT; 905 if (events & POLLWRBAND) 906 *reventsp |= POLLWRBAND; 907 *phpp = NULL; /* or fake_pollhead? */ 908 909 return (0); 910 } 911 912 /* ARGSUSED */ 913 int 914 fop_dump( 915 vnode_t *vp, 916 caddr_t addr, 917 offset_t lbdn, 918 offset_t dblks, 919 caller_context_t *ct) 920 { 921 return (ENOSYS); 922 } 923 924 /* 925 * See fs_pathconf 926 */ 927 /* ARGSUSED */ 928 int 929 fop_pathconf( 930 vnode_t *vp, 931 int cmd, 932 ulong_t *valp, 933 cred_t *cr, 934 caller_context_t *ct) 935 { 936 register ulong_t val; 937 register int error = 0; 938 939 switch (cmd) { 940 941 case _PC_LINK_MAX: 942 val = MAXLINK; 943 break; 944 945 case _PC_MAX_CANON: 946 val = MAX_CANON; 947 break; 948 949 case _PC_MAX_INPUT: 950 val = MAX_INPUT; 951 break; 952 953 case _PC_NAME_MAX: 954 val = MAXNAMELEN; 955 break; 956 957 case _PC_PATH_MAX: 958 case _PC_SYMLINK_MAX: 959 val = MAXPATHLEN; 960 break; 961 962 case _PC_PIPE_BUF: 963 val = PIPE_BUF; 964 break; 965 966 case _PC_NO_TRUNC: 967 val = (ulong_t)-1; 968 break; 969 970 case _PC_VDISABLE: 971 val = _POSIX_VDISABLE; 972 break; 973 974 case _PC_CHOWN_RESTRICTED: 975 val = 1; /* chown restricted enabled */ 976 break; 977 978 case _PC_FILESIZEBITS: 979 val = (ulong_t)-1; /* large file support */ 980 break; 981 982 case _PC_ACL_ENABLED: 983 val = 0; 984 break; 985 986 case _PC_CASE_BEHAVIOR: 987 val = _CASE_SENSITIVE; 988 break; 989 990 case _PC_SATTR_ENABLED: 991 case _PC_SATTR_EXISTS: 992 val = 0; 993 break; 994 995 case _PC_ACCESS_FILTERING: 996 val = 0; 997 break; 998 999 default: 1000 error = EINVAL; 1001 break; 1002 } 1003 1004 if (error == 0) 1005 *valp = val; 1006 return (error); 1007 } 1008 1009 /* ARGSUSED */ 1010 int 1011 fop_pageio( 1012 vnode_t *vp, 1013 struct page *pp, 1014 u_offset_t io_off, 1015 size_t io_len, 1016 int flags, 1017 cred_t *cr, 1018 caller_context_t *ct) 1019 { 1020 return (ENOSYS); 1021 } 1022 1023 /* ARGSUSED */ 1024 int 1025 fop_dumpctl( 1026 vnode_t *vp, 1027 int action, 1028 offset_t *blkp, 1029 caller_context_t *ct) 1030 { 1031 return (ENOSYS); 1032 } 1033 1034 /* ARGSUSED */ 1035 void 1036 fop_dispose( 1037 vnode_t *vp, 1038 struct page *pp, 1039 int flag, 1040 int dn, 1041 cred_t *cr, 1042 caller_context_t *ct) 1043 { 1044 } 1045 1046 /* ARGSUSED */ 1047 int 1048 fop_setsecattr( 1049 vnode_t *vp, 1050 vsecattr_t *vsap, 1051 int flag, 1052 cred_t *cr, 1053 caller_context_t *ct) 1054 { 1055 return (0); 1056 } 1057 1058 /* 1059 * Fake up just enough of this so we can test get/set SDs. 1060 */ 1061 /* ARGSUSED */ 1062 int 1063 fop_getsecattr( 1064 vnode_t *vp, 1065 vsecattr_t *vsecattr, 1066 int flag, 1067 cred_t *cr, 1068 caller_context_t *ct) 1069 { 1070 1071 vsecattr->vsa_aclcnt = 0; 1072 vsecattr->vsa_aclentsz = 0; 1073 vsecattr->vsa_aclentp = NULL; 1074 vsecattr->vsa_dfaclcnt = 0; /* Default ACLs are not fabricated */ 1075 vsecattr->vsa_dfaclentp = NULL; 1076 1077 if (vsecattr->vsa_mask & (VSA_ACLCNT | VSA_ACL)) { 1078 aclent_t *aclentp; 1079 size_t aclsize; 1080 1081 aclsize = sizeof (aclent_t); 1082 vsecattr->vsa_aclcnt = 1; 1083 vsecattr->vsa_aclentp = kmem_zalloc(aclsize, KM_SLEEP); 1084 aclentp = vsecattr->vsa_aclentp; 1085 1086 aclentp->a_type = OTHER_OBJ; 1087 aclentp->a_perm = 0777; 1088 aclentp->a_id = (gid_t)-1; 1089 aclentp++; 1090 } else if (vsecattr->vsa_mask & (VSA_ACECNT | VSA_ACE)) { 1091 ace_t *acl; 1092 1093 acl = kmem_alloc(sizeof (ace_t), KM_SLEEP); 1094 acl->a_who = (uint32_t)-1; 1095 acl->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 1096 acl->a_flags = ACE_EVERYONE; 1097 acl->a_access_mask = ACE_MODIFY_PERMS; 1098 1099 vsecattr->vsa_aclentp = (void *)acl; 1100 vsecattr->vsa_aclcnt = 1; 1101 vsecattr->vsa_aclentsz = sizeof (ace_t); 1102 } 1103 1104 return (0); 1105 } 1106 1107 /* ARGSUSED */ 1108 int 1109 fop_shrlock( 1110 vnode_t *vp, 1111 int cmd, 1112 struct shrlock *shr, 1113 int flag, 1114 cred_t *cr, 1115 caller_context_t *ct) 1116 { 1117 1118 switch (cmd) { 1119 case F_SHARE: 1120 case F_SHARE_NBMAND: 1121 case F_UNSHARE: 1122 break; 1123 default: 1124 return (EINVAL); 1125 } 1126 1127 if (!fop_shrlock_enable) 1128 return (0); 1129 1130 if (fcntl(vp->v_fd, cmd, shr) == -1) 1131 return (errno); 1132 1133 return (0); 1134 } 1135 1136 /* ARGSUSED */ 1137 int 1138 fop_vnevent(vnode_t *vp, vnevent_t vnevent, vnode_t *dvp, char *fnm, 1139 caller_context_t *ct) 1140 { 1141 return (ENOSYS); 1142 } 1143 1144 /* ARGSUSED */ 1145 int 1146 fop_reqzcbuf(vnode_t *vp, enum uio_rw ioflag, xuio_t *uiop, cred_t *cr, 1147 caller_context_t *ct) 1148 { 1149 return (ENOSYS); 1150 } 1151 1152 /* ARGSUSED */ 1153 int 1154 fop_retzcbuf(vnode_t *vp, xuio_t *uiop, cred_t *cr, caller_context_t *ct) 1155 { 1156 return (ENOSYS); 1157 } 1158 1159 1160 /* 1161 * *************************************************************** 1162 * other VOP support 1163 */ 1164 1165 /* 1166 * Convert stat(2) formats to vnode types and vice versa. (Knows about 1167 * numerical order of S_IFMT and vnode types.) 1168 */ 1169 enum vtype iftovt_tab[] = { 1170 VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, 1171 VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VNON 1172 }; 1173 1174 ushort_t vttoif_tab[] = { 1175 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFIFO, 1176 S_IFDOOR, 0, S_IFSOCK, S_IFPORT, 0 1177 }; 1178 1179 /* 1180 * stat_to_vattr() 1181 * 1182 * Convert from a stat structure to an vattr structure 1183 * Note: only set fields according to va_mask 1184 */ 1185 1186 int 1187 stat_to_vattr(const struct stat *st, vattr_t *vap) 1188 { 1189 1190 if (vap->va_mask & AT_TYPE) 1191 vap->va_type = IFTOVT(st->st_mode); 1192 1193 if (vap->va_mask & AT_MODE) 1194 vap->va_mode = st->st_mode; 1195 1196 if (vap->va_mask & AT_UID) 1197 vap->va_uid = st->st_uid; 1198 1199 if (vap->va_mask & AT_GID) 1200 vap->va_gid = st->st_gid; 1201 1202 if (vap->va_mask & AT_FSID) 1203 vap->va_fsid = st->st_dev; 1204 1205 if (vap->va_mask & AT_NODEID) 1206 vap->va_nodeid = st->st_ino; 1207 1208 if (vap->va_mask & AT_NLINK) 1209 vap->va_nlink = st->st_nlink; 1210 1211 if (vap->va_mask & AT_SIZE) 1212 vap->va_size = (u_offset_t)st->st_size; 1213 1214 if (vap->va_mask & AT_ATIME) { 1215 vap->va_atime.tv_sec = st->st_atim.tv_sec; 1216 vap->va_atime.tv_nsec = st->st_atim.tv_nsec; 1217 } 1218 1219 if (vap->va_mask & AT_MTIME) { 1220 vap->va_mtime.tv_sec = st->st_mtim.tv_sec; 1221 vap->va_mtime.tv_nsec = st->st_mtim.tv_nsec; 1222 } 1223 1224 if (vap->va_mask & AT_CTIME) { 1225 vap->va_ctime.tv_sec = st->st_ctim.tv_sec; 1226 vap->va_ctime.tv_nsec = st->st_ctim.tv_nsec; 1227 } 1228 1229 if (vap->va_mask & AT_RDEV) 1230 vap->va_rdev = st->st_rdev; 1231 1232 if (vap->va_mask & AT_BLKSIZE) 1233 vap->va_blksize = (uint_t)st->st_blksize; 1234 1235 1236 if (vap->va_mask & AT_NBLOCKS) 1237 vap->va_nblocks = (u_longlong_t)st->st_blocks; 1238 1239 if (vap->va_mask & AT_SEQ) 1240 vap->va_seq = 0; 1241 1242 return (0); 1243 } 1244 1245 /* ARGSUSED */ 1246 void 1247 flk_init_callback(flk_callback_t *flk_cb, 1248 callb_cpr_t *(*cb_fcn)(flk_cb_when_t, void *), void *cbdata) 1249 { 1250 } 1251 1252 void 1253 vn_hold(vnode_t *vp) 1254 { 1255 mutex_enter(&vp->v_lock); 1256 vp->v_count++; 1257 mutex_exit(&vp->v_lock); 1258 } 1259 1260 void 1261 vn_rele(vnode_t *vp) 1262 { 1263 VERIFY3U(vp->v_count, !=, 0); 1264 mutex_enter(&vp->v_lock); 1265 if (vp->v_count == 1) { 1266 mutex_exit(&vp->v_lock); 1267 vncache_inactive(vp); 1268 } else { 1269 vp->v_count--; 1270 mutex_exit(&vp->v_lock); 1271 } 1272 } 1273 1274 int 1275 vn_has_other_opens( 1276 vnode_t *vp, 1277 v_mode_t mode) 1278 { 1279 1280 switch (mode) { 1281 case V_WRITE: 1282 if (vp->v_wrcnt > 1) 1283 return (V_TRUE); 1284 break; 1285 case V_RDORWR: 1286 if ((vp->v_rdcnt > 1) || (vp->v_wrcnt > 1)) 1287 return (V_TRUE); 1288 break; 1289 case V_RDANDWR: 1290 if ((vp->v_rdcnt > 1) && (vp->v_wrcnt > 1)) 1291 return (V_TRUE); 1292 break; 1293 case V_READ: 1294 if (vp->v_rdcnt > 1) 1295 return (V_TRUE); 1296 break; 1297 } 1298 1299 return (V_FALSE); 1300 } 1301 1302 /* 1303 * vn_is_opened() checks whether a particular file is opened and 1304 * whether the open is for read and/or write. 1305 * 1306 * Vnode counts are only kept on regular files (v_type=VREG). 1307 */ 1308 int 1309 vn_is_opened( 1310 vnode_t *vp, 1311 v_mode_t mode) 1312 { 1313 1314 ASSERT(vp != NULL); 1315 1316 switch (mode) { 1317 case V_WRITE: 1318 if (vp->v_wrcnt) 1319 return (V_TRUE); 1320 break; 1321 case V_RDANDWR: 1322 if (vp->v_rdcnt && vp->v_wrcnt) 1323 return (V_TRUE); 1324 break; 1325 case V_RDORWR: 1326 if (vp->v_rdcnt || vp->v_wrcnt) 1327 return (V_TRUE); 1328 break; 1329 case V_READ: 1330 if (vp->v_rdcnt) 1331 return (V_TRUE); 1332 break; 1333 } 1334 1335 return (V_FALSE); 1336 } 1337 1338 /* 1339 * vn_is_mapped() checks whether a particular file is mapped and whether 1340 * the file is mapped read and/or write. 1341 */ 1342 /* ARGSUSED */ 1343 int 1344 vn_is_mapped( 1345 vnode_t *vp, 1346 v_mode_t mode) 1347 { 1348 return (V_FALSE); 1349 } 1350