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 2015 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 timespec_t 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 if (vap->va_mask & AT_ATIME) { 278 times[0] = vap->va_atime; 279 } else { 280 times[0].tv_sec = 0; 281 times[0].tv_nsec = UTIME_OMIT; 282 } 283 if (vap->va_mask & AT_MTIME) { 284 times[1] = vap->va_mtime; 285 } else { 286 times[1].tv_sec = 0; 287 times[1].tv_nsec = UTIME_OMIT; 288 } 289 290 (void) futimens(vp->v_fd, 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 * Might need to set attributes. 453 */ 454 (void) fop_setattr(vp, vap, 0, cr, ct); 455 456 *vpp = vp; 457 return (0); 458 } 459 460 /* ARGSUSED */ 461 int 462 fop_remove( 463 vnode_t *dvp, 464 char *name, 465 cred_t *cr, 466 caller_context_t *ct, 467 int flags) 468 { 469 470 if (unlinkat(dvp->v_fd, name, 0)) 471 return (errno); 472 473 return (0); 474 } 475 476 /* ARGSUSED */ 477 int 478 fop_link( 479 vnode_t *to_dvp, 480 vnode_t *fr_vp, 481 char *to_name, 482 cred_t *cr, 483 caller_context_t *ct, 484 int flags) 485 { 486 int err; 487 488 /* 489 * Would prefer to specify "from" as the combination: 490 * (fr_vp->v_fd, NULL) but linkat does not permit it. 491 */ 492 err = linkat(AT_FDCWD, fr_vp->v_path, to_dvp->v_fd, to_name, 493 AT_SYMLINK_FOLLOW); 494 if (err == -1) 495 err = errno; 496 497 return (err); 498 } 499 500 /* ARGSUSED */ 501 int 502 fop_rename( 503 vnode_t *from_dvp, 504 char *from_name, 505 vnode_t *to_dvp, 506 char *to_name, 507 cred_t *cr, 508 caller_context_t *ct, 509 int flags) 510 { 511 struct stat st; 512 vnode_t *vp; 513 int err; 514 515 if (fstatat(from_dvp->v_fd, from_name, &st, 516 AT_SYMLINK_NOFOLLOW) == -1) 517 return (errno); 518 519 vp = vncache_lookup(&st); 520 if (vp == NULL) 521 return (ENOENT); 522 523 err = renameat(from_dvp->v_fd, from_name, to_dvp->v_fd, to_name); 524 if (err == -1) 525 err = errno; 526 else 527 vncache_renamed(vp, to_dvp, to_name); 528 529 vn_rele(vp); 530 531 return (err); 532 } 533 534 /* ARGSUSED */ 535 int 536 fop_mkdir( 537 vnode_t *dvp, 538 char *name, 539 vattr_t *vap, 540 vnode_t **vpp, 541 cred_t *cr, 542 caller_context_t *ct, 543 int flags, 544 vsecattr_t *vsecp) /* ACL to set during create */ 545 { 546 struct stat st; 547 int err, fd; 548 549 mode_t mode = vap->va_mode & 0777; 550 551 if (mkdirat(dvp->v_fd, name, mode) == -1) 552 return (errno); 553 554 if ((fd = openat(dvp->v_fd, name, O_RDONLY)) == -1) 555 return (errno); 556 if (fstat(fd, &st) == -1) { 557 err = errno; 558 (void) close(fd); 559 return (err); 560 } 561 562 *vpp = vncache_enter(&st, dvp, name, fd); 563 564 /* 565 * Might need to set attributes. 566 */ 567 (void) fop_setattr(*vpp, vap, 0, cr, ct); 568 569 return (0); 570 } 571 572 /* ARGSUSED */ 573 int 574 fop_rmdir( 575 vnode_t *dvp, 576 char *name, 577 vnode_t *cdir, 578 cred_t *cr, 579 caller_context_t *ct, 580 int flags) 581 { 582 583 if (unlinkat(dvp->v_fd, name, AT_REMOVEDIR) == -1) 584 return (errno); 585 586 return (0); 587 } 588 589 /* ARGSUSED */ 590 int 591 fop_readdir( 592 vnode_t *vp, 593 uio_t *uiop, 594 cred_t *cr, 595 int *eofp, 596 caller_context_t *ct, 597 int flags) 598 { 599 struct iovec *iov; 600 int cnt; 601 int error = 0; 602 int fd = vp->v_fd; 603 604 if (eofp) { 605 *eofp = 0; 606 } 607 608 error = lseek(fd, uiop->uio_loffset, SEEK_SET); 609 if (error == -1) 610 return (errno); 611 612 ASSERT(uiop->uio_iovcnt > 0); 613 iov = uiop->uio_iov; 614 if (iov->iov_len < sizeof (struct dirent)) 615 return (EINVAL); 616 617 /* LINTED E_BAD_PTR_CAST_ALIGN */ 618 cnt = getdents(fd, (struct dirent *)(uiop->uio_iov->iov_base), 619 uiop->uio_resid); 620 if (cnt == -1) 621 return (errno); 622 if (cnt == 0) { 623 if (eofp) { 624 *eofp = 1; 625 } 626 return (ENOENT); 627 } 628 629 iov->iov_base += cnt; 630 iov->iov_len -= cnt; 631 uiop->uio_resid -= cnt; 632 uiop->uio_loffset = lseek(fd, 0LL, SEEK_CUR); 633 634 return (0); 635 } 636 637 /* ARGSUSED */ 638 int 639 fop_symlink( 640 vnode_t *dvp, 641 char *linkname, 642 vattr_t *vap, 643 char *target, 644 cred_t *cr, 645 caller_context_t *ct, 646 int flags) 647 { 648 return (ENOSYS); 649 } 650 651 /* ARGSUSED */ 652 int 653 fop_readlink( 654 vnode_t *vp, 655 uio_t *uiop, 656 cred_t *cr, 657 caller_context_t *ct) 658 { 659 return (ENOSYS); 660 } 661 662 /* ARGSUSED */ 663 int 664 fop_fsync( 665 vnode_t *vp, 666 int syncflag, 667 cred_t *cr, 668 caller_context_t *ct) 669 { 670 671 if (fsync(vp->v_fd) == -1) 672 return (errno); 673 674 return (0); 675 } 676 677 /* ARGSUSED */ 678 void 679 fop_inactive( 680 vnode_t *vp, 681 cred_t *cr, 682 caller_context_t *ct) 683 { 684 vncache_inactive(vp); 685 } 686 687 /* ARGSUSED */ 688 int 689 fop_fid( 690 vnode_t *vp, 691 fid_t *fidp, 692 caller_context_t *ct) 693 { 694 return (ENOSYS); 695 } 696 697 /* ARGSUSED */ 698 int 699 fop_rwlock( 700 vnode_t *vp, 701 int write_lock, 702 caller_context_t *ct) 703 { 704 /* See: fs_rwlock */ 705 return (-1); 706 } 707 708 /* ARGSUSED */ 709 void 710 fop_rwunlock( 711 vnode_t *vp, 712 int write_lock, 713 caller_context_t *ct) 714 { 715 /* See: fs_rwunlock */ 716 } 717 718 /* ARGSUSED */ 719 int 720 fop_seek( 721 vnode_t *vp, 722 offset_t ooff, 723 offset_t *noffp, 724 caller_context_t *ct) 725 { 726 return (ENOSYS); 727 } 728 729 /* ARGSUSED */ 730 int 731 fop_cmp( 732 vnode_t *vp1, 733 vnode_t *vp2, 734 caller_context_t *ct) 735 { 736 /* See fs_cmp */ 737 return (vncache_cmp(vp1, vp2)); 738 } 739 740 /* ARGSUSED */ 741 int 742 fop_frlock( 743 vnode_t *vp, 744 int cmd, 745 flock64_t *bfp, 746 int flag, 747 offset_t offset, 748 struct flk_callback *flk_cbp, 749 cred_t *cr, 750 caller_context_t *ct) 751 { 752 /* See fs_frlock */ 753 754 switch (cmd) { 755 case F_GETLK: 756 case F_SETLK_NBMAND: 757 case F_SETLK: 758 case F_SETLKW: 759 break; 760 default: 761 return (EINVAL); 762 } 763 764 if (fcntl(vp->v_fd, cmd, bfp) == -1) 765 return (errno); 766 767 return (0); 768 } 769 770 /* ARGSUSED */ 771 int 772 fop_space( 773 vnode_t *vp, 774 int cmd, 775 flock64_t *bfp, 776 int flag, 777 offset_t offset, 778 cred_t *cr, 779 caller_context_t *ct) 780 { 781 /* See fs_frlock */ 782 783 switch (cmd) { 784 case F_ALLOCSP: 785 case F_FREESP: 786 break; 787 default: 788 return (EINVAL); 789 } 790 791 if (fcntl(vp->v_fd, cmd, bfp) == -1) 792 return (errno); 793 794 return (0); 795 } 796 797 /* ARGSUSED */ 798 int 799 fop_realvp( 800 vnode_t *vp, 801 vnode_t **vpp, 802 caller_context_t *ct) 803 { 804 return (ENOSYS); 805 } 806 807 /* ARGSUSED */ 808 int 809 fop_getpage( 810 vnode_t *vp, 811 offset_t off, 812 size_t len, 813 uint_t *protp, 814 struct page **plarr, 815 size_t plsz, 816 struct seg *seg, 817 caddr_t addr, 818 enum seg_rw rw, 819 cred_t *cr, 820 caller_context_t *ct) 821 { 822 return (ENOSYS); 823 } 824 825 /* ARGSUSED */ 826 int 827 fop_putpage( 828 vnode_t *vp, 829 offset_t off, 830 size_t len, 831 int flags, 832 cred_t *cr, 833 caller_context_t *ct) 834 { 835 return (ENOSYS); 836 } 837 838 /* ARGSUSED */ 839 int 840 fop_map( 841 vnode_t *vp, 842 offset_t off, 843 struct as *as, 844 caddr_t *addrp, 845 size_t len, 846 uchar_t prot, 847 uchar_t maxprot, 848 uint_t flags, 849 cred_t *cr, 850 caller_context_t *ct) 851 { 852 return (ENOSYS); 853 } 854 855 /* ARGSUSED */ 856 int 857 fop_addmap( 858 vnode_t *vp, 859 offset_t off, 860 struct as *as, 861 caddr_t addr, 862 size_t len, 863 uchar_t prot, 864 uchar_t maxprot, 865 uint_t flags, 866 cred_t *cr, 867 caller_context_t *ct) 868 { 869 return (ENOSYS); 870 } 871 872 /* ARGSUSED */ 873 int 874 fop_delmap( 875 vnode_t *vp, 876 offset_t off, 877 struct as *as, 878 caddr_t addr, 879 size_t len, 880 uint_t prot, 881 uint_t maxprot, 882 uint_t flags, 883 cred_t *cr, 884 caller_context_t *ct) 885 { 886 return (ENOSYS); 887 } 888 889 /* ARGSUSED */ 890 int 891 fop_poll( 892 vnode_t *vp, 893 short events, 894 int anyyet, 895 short *reventsp, 896 struct pollhead **phpp, 897 caller_context_t *ct) 898 { 899 *reventsp = 0; 900 if (events & POLLIN) 901 *reventsp |= POLLIN; 902 if (events & POLLRDNORM) 903 *reventsp |= POLLRDNORM; 904 if (events & POLLRDBAND) 905 *reventsp |= POLLRDBAND; 906 if (events & POLLOUT) 907 *reventsp |= POLLOUT; 908 if (events & POLLWRBAND) 909 *reventsp |= POLLWRBAND; 910 *phpp = NULL; /* or fake_pollhead? */ 911 912 return (0); 913 } 914 915 /* ARGSUSED */ 916 int 917 fop_dump( 918 vnode_t *vp, 919 caddr_t addr, 920 offset_t lbdn, 921 offset_t dblks, 922 caller_context_t *ct) 923 { 924 return (ENOSYS); 925 } 926 927 /* 928 * See fs_pathconf 929 */ 930 /* ARGSUSED */ 931 int 932 fop_pathconf( 933 vnode_t *vp, 934 int cmd, 935 ulong_t *valp, 936 cred_t *cr, 937 caller_context_t *ct) 938 { 939 register ulong_t val; 940 register int error = 0; 941 942 switch (cmd) { 943 944 case _PC_LINK_MAX: 945 val = MAXLINK; 946 break; 947 948 case _PC_MAX_CANON: 949 val = MAX_CANON; 950 break; 951 952 case _PC_MAX_INPUT: 953 val = MAX_INPUT; 954 break; 955 956 case _PC_NAME_MAX: 957 val = MAXNAMELEN; 958 break; 959 960 case _PC_PATH_MAX: 961 case _PC_SYMLINK_MAX: 962 val = MAXPATHLEN; 963 break; 964 965 case _PC_PIPE_BUF: 966 val = PIPE_BUF; 967 break; 968 969 case _PC_NO_TRUNC: 970 val = (ulong_t)-1; 971 break; 972 973 case _PC_VDISABLE: 974 val = _POSIX_VDISABLE; 975 break; 976 977 case _PC_CHOWN_RESTRICTED: 978 val = 1; /* chown restricted enabled */ 979 break; 980 981 case _PC_FILESIZEBITS: 982 val = (ulong_t)-1; /* large file support */ 983 break; 984 985 case _PC_ACL_ENABLED: 986 val = 0; 987 break; 988 989 case _PC_CASE_BEHAVIOR: 990 val = _CASE_SENSITIVE; 991 break; 992 993 case _PC_SATTR_ENABLED: 994 case _PC_SATTR_EXISTS: 995 val = 0; 996 break; 997 998 case _PC_ACCESS_FILTERING: 999 val = 0; 1000 break; 1001 1002 default: 1003 error = EINVAL; 1004 break; 1005 } 1006 1007 if (error == 0) 1008 *valp = val; 1009 return (error); 1010 } 1011 1012 /* ARGSUSED */ 1013 int 1014 fop_pageio( 1015 vnode_t *vp, 1016 struct page *pp, 1017 u_offset_t io_off, 1018 size_t io_len, 1019 int flags, 1020 cred_t *cr, 1021 caller_context_t *ct) 1022 { 1023 return (ENOSYS); 1024 } 1025 1026 /* ARGSUSED */ 1027 int 1028 fop_dumpctl( 1029 vnode_t *vp, 1030 int action, 1031 offset_t *blkp, 1032 caller_context_t *ct) 1033 { 1034 return (ENOSYS); 1035 } 1036 1037 /* ARGSUSED */ 1038 void 1039 fop_dispose( 1040 vnode_t *vp, 1041 struct page *pp, 1042 int flag, 1043 int dn, 1044 cred_t *cr, 1045 caller_context_t *ct) 1046 { 1047 } 1048 1049 /* ARGSUSED */ 1050 int 1051 fop_setsecattr( 1052 vnode_t *vp, 1053 vsecattr_t *vsap, 1054 int flag, 1055 cred_t *cr, 1056 caller_context_t *ct) 1057 { 1058 return (0); 1059 } 1060 1061 /* 1062 * Fake up just enough of this so we can test get/set SDs. 1063 */ 1064 /* ARGSUSED */ 1065 int 1066 fop_getsecattr( 1067 vnode_t *vp, 1068 vsecattr_t *vsecattr, 1069 int flag, 1070 cred_t *cr, 1071 caller_context_t *ct) 1072 { 1073 1074 vsecattr->vsa_aclcnt = 0; 1075 vsecattr->vsa_aclentsz = 0; 1076 vsecattr->vsa_aclentp = NULL; 1077 vsecattr->vsa_dfaclcnt = 0; /* Default ACLs are not fabricated */ 1078 vsecattr->vsa_dfaclentp = NULL; 1079 1080 if (vsecattr->vsa_mask & (VSA_ACLCNT | VSA_ACL)) { 1081 aclent_t *aclentp; 1082 size_t aclsize; 1083 1084 aclsize = sizeof (aclent_t); 1085 vsecattr->vsa_aclcnt = 1; 1086 vsecattr->vsa_aclentp = kmem_zalloc(aclsize, KM_SLEEP); 1087 aclentp = vsecattr->vsa_aclentp; 1088 1089 aclentp->a_type = OTHER_OBJ; 1090 aclentp->a_perm = 0777; 1091 aclentp->a_id = (gid_t)-1; 1092 aclentp++; 1093 } else if (vsecattr->vsa_mask & (VSA_ACECNT | VSA_ACE)) { 1094 ace_t *acl; 1095 1096 acl = kmem_alloc(sizeof (ace_t), KM_SLEEP); 1097 acl->a_who = (uint32_t)-1; 1098 acl->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 1099 acl->a_flags = ACE_EVERYONE; 1100 acl->a_access_mask = ACE_MODIFY_PERMS; 1101 1102 vsecattr->vsa_aclentp = (void *)acl; 1103 vsecattr->vsa_aclcnt = 1; 1104 vsecattr->vsa_aclentsz = sizeof (ace_t); 1105 } 1106 1107 return (0); 1108 } 1109 1110 /* ARGSUSED */ 1111 int 1112 fop_shrlock( 1113 vnode_t *vp, 1114 int cmd, 1115 struct shrlock *shr, 1116 int flag, 1117 cred_t *cr, 1118 caller_context_t *ct) 1119 { 1120 1121 switch (cmd) { 1122 case F_SHARE: 1123 case F_SHARE_NBMAND: 1124 case F_UNSHARE: 1125 break; 1126 default: 1127 return (EINVAL); 1128 } 1129 1130 if (!fop_shrlock_enable) 1131 return (0); 1132 1133 if (fcntl(vp->v_fd, cmd, shr) == -1) 1134 return (errno); 1135 1136 return (0); 1137 } 1138 1139 /* ARGSUSED */ 1140 int 1141 fop_vnevent(vnode_t *vp, vnevent_t vnevent, vnode_t *dvp, char *fnm, 1142 caller_context_t *ct) 1143 { 1144 return (ENOSYS); 1145 } 1146 1147 /* ARGSUSED */ 1148 int 1149 fop_reqzcbuf(vnode_t *vp, enum uio_rw ioflag, xuio_t *uiop, cred_t *cr, 1150 caller_context_t *ct) 1151 { 1152 return (ENOSYS); 1153 } 1154 1155 /* ARGSUSED */ 1156 int 1157 fop_retzcbuf(vnode_t *vp, xuio_t *uiop, cred_t *cr, caller_context_t *ct) 1158 { 1159 return (ENOSYS); 1160 } 1161 1162 1163 /* 1164 * *************************************************************** 1165 * other VOP support 1166 */ 1167 1168 /* 1169 * Convert stat(2) formats to vnode types and vice versa. (Knows about 1170 * numerical order of S_IFMT and vnode types.) 1171 */ 1172 enum vtype iftovt_tab[] = { 1173 VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, 1174 VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VNON 1175 }; 1176 1177 ushort_t vttoif_tab[] = { 1178 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFIFO, 1179 S_IFDOOR, 0, S_IFSOCK, S_IFPORT, 0 1180 }; 1181 1182 /* 1183 * stat_to_vattr() 1184 * 1185 * Convert from a stat structure to an vattr structure 1186 * Note: only set fields according to va_mask 1187 */ 1188 1189 int 1190 stat_to_vattr(const struct stat *st, vattr_t *vap) 1191 { 1192 1193 if (vap->va_mask & AT_TYPE) 1194 vap->va_type = IFTOVT(st->st_mode); 1195 1196 if (vap->va_mask & AT_MODE) 1197 vap->va_mode = st->st_mode; 1198 1199 if (vap->va_mask & AT_UID) 1200 vap->va_uid = st->st_uid; 1201 1202 if (vap->va_mask & AT_GID) 1203 vap->va_gid = st->st_gid; 1204 1205 if (vap->va_mask & AT_FSID) 1206 vap->va_fsid = st->st_dev; 1207 1208 if (vap->va_mask & AT_NODEID) 1209 vap->va_nodeid = st->st_ino; 1210 1211 if (vap->va_mask & AT_NLINK) 1212 vap->va_nlink = st->st_nlink; 1213 1214 if (vap->va_mask & AT_SIZE) 1215 vap->va_size = (u_offset_t)st->st_size; 1216 1217 if (vap->va_mask & AT_ATIME) { 1218 vap->va_atime.tv_sec = st->st_atim.tv_sec; 1219 vap->va_atime.tv_nsec = st->st_atim.tv_nsec; 1220 } 1221 1222 if (vap->va_mask & AT_MTIME) { 1223 vap->va_mtime.tv_sec = st->st_mtim.tv_sec; 1224 vap->va_mtime.tv_nsec = st->st_mtim.tv_nsec; 1225 } 1226 1227 if (vap->va_mask & AT_CTIME) { 1228 vap->va_ctime.tv_sec = st->st_ctim.tv_sec; 1229 vap->va_ctime.tv_nsec = st->st_ctim.tv_nsec; 1230 } 1231 1232 if (vap->va_mask & AT_RDEV) 1233 vap->va_rdev = st->st_rdev; 1234 1235 if (vap->va_mask & AT_BLKSIZE) 1236 vap->va_blksize = (uint_t)st->st_blksize; 1237 1238 1239 if (vap->va_mask & AT_NBLOCKS) 1240 vap->va_nblocks = (u_longlong_t)st->st_blocks; 1241 1242 if (vap->va_mask & AT_SEQ) 1243 vap->va_seq = 0; 1244 1245 return (0); 1246 } 1247 1248 /* ARGSUSED */ 1249 void 1250 flk_init_callback(flk_callback_t *flk_cb, 1251 callb_cpr_t *(*cb_fcn)(flk_cb_when_t, void *), void *cbdata) 1252 { 1253 } 1254 1255 void 1256 vn_hold(vnode_t *vp) 1257 { 1258 mutex_enter(&vp->v_lock); 1259 vp->v_count++; 1260 mutex_exit(&vp->v_lock); 1261 } 1262 1263 void 1264 vn_rele(vnode_t *vp) 1265 { 1266 VERIFY3U(vp->v_count, !=, 0); 1267 mutex_enter(&vp->v_lock); 1268 if (vp->v_count == 1) { 1269 mutex_exit(&vp->v_lock); 1270 vncache_inactive(vp); 1271 } else { 1272 vp->v_count--; 1273 mutex_exit(&vp->v_lock); 1274 } 1275 } 1276 1277 int 1278 vn_has_other_opens( 1279 vnode_t *vp, 1280 v_mode_t mode) 1281 { 1282 1283 switch (mode) { 1284 case V_WRITE: 1285 if (vp->v_wrcnt > 1) 1286 return (V_TRUE); 1287 break; 1288 case V_RDORWR: 1289 if ((vp->v_rdcnt > 1) || (vp->v_wrcnt > 1)) 1290 return (V_TRUE); 1291 break; 1292 case V_RDANDWR: 1293 if ((vp->v_rdcnt > 1) && (vp->v_wrcnt > 1)) 1294 return (V_TRUE); 1295 break; 1296 case V_READ: 1297 if (vp->v_rdcnt > 1) 1298 return (V_TRUE); 1299 break; 1300 } 1301 1302 return (V_FALSE); 1303 } 1304 1305 /* 1306 * vn_is_opened() checks whether a particular file is opened and 1307 * whether the open is for read and/or write. 1308 * 1309 * Vnode counts are only kept on regular files (v_type=VREG). 1310 */ 1311 int 1312 vn_is_opened( 1313 vnode_t *vp, 1314 v_mode_t mode) 1315 { 1316 1317 ASSERT(vp != NULL); 1318 1319 switch (mode) { 1320 case V_WRITE: 1321 if (vp->v_wrcnt) 1322 return (V_TRUE); 1323 break; 1324 case V_RDANDWR: 1325 if (vp->v_rdcnt && vp->v_wrcnt) 1326 return (V_TRUE); 1327 break; 1328 case V_RDORWR: 1329 if (vp->v_rdcnt || vp->v_wrcnt) 1330 return (V_TRUE); 1331 break; 1332 case V_READ: 1333 if (vp->v_rdcnt) 1334 return (V_TRUE); 1335 break; 1336 } 1337 1338 return (V_FALSE); 1339 } 1340 1341 /* 1342 * vn_is_mapped() checks whether a particular file is mapped and whether 1343 * the file is mapped read and/or write. 1344 */ 1345 /* ARGSUSED */ 1346 int 1347 vn_is_mapped( 1348 vnode_t *vp, 1349 v_mode_t mode) 1350 { 1351 return (V_FALSE); 1352 } 1353