1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2017, Joyent, Inc. 25 * Copyright (c) 2011, 2017 by Delphix. All rights reserved. 26 * Copyright 2018 Nexenta Systems, Inc. All rights reserved. 27 */ 28 29 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 30 /* All Rights Reserved */ 31 32 /* 33 * University Copyright- Copyright (c) 1982, 1986, 1988 34 * The Regents of the University of California 35 * All Rights Reserved 36 * 37 * University Acknowledgment- Portions of this document are derived from 38 * software developed by the University of California, Berkeley, and its 39 * contributors. 40 */ 41 42 /* 43 * This file contains those functions from fs/vnode.c that can be 44 * used with relatively little change. Functions that differ 45 * significantly from that are in other files. 46 */ 47 48 #include <sys/types.h> 49 #include <sys/param.h> 50 #include <sys/t_lock.h> 51 #include <sys/errno.h> 52 #include <sys/cred.h> 53 #include <sys/user.h> 54 #include <sys/uio.h> 55 #include <sys/file.h> 56 #include <sys/pathname.h> 57 #include <sys/vfs.h> 58 #include <sys/vfs_opreg.h> 59 #include <sys/vnode.h> 60 #include <sys/rwstlock.h> 61 #include <sys/fem.h> 62 #include <sys/stat.h> 63 #include <sys/mode.h> 64 #include <sys/conf.h> 65 #include <sys/sysmacros.h> 66 #include <sys/cmn_err.h> 67 #include <sys/systm.h> 68 #include <sys/kmem.h> 69 #include <sys/atomic.h> 70 #include <sys/debug.h> 71 #include <sys/acl.h> 72 #include <sys/nbmlock.h> 73 #include <sys/fcntl.h> 74 #include <sys/time.h> 75 #include <fs/fs_subr.h> 76 #include <fs/fs_reparse.h> 77 78 #include <libfksmbfs.h> 79 80 /* Determine if this vnode is a file that is read-only */ 81 #define ISROFILE(vp) \ 82 ((vp)->v_type != VCHR && (vp)->v_type != VBLK && \ 83 (vp)->v_type != VFIFO && vn_is_readonly(vp)) 84 85 #define VOPSTATS_UPDATE(vp, counter) ((void)vp) 86 #define VOPSTATS_UPDATE_IO(vp, counter, bytecounter, bytesval) \ 87 ((void)vp, (void)bytesval) 88 #define VOPXID_MAP_CR(vp, cr) ((void)vp) 89 90 /* 91 * Excerpts from fs/vnode.c 92 */ 93 94 /* Global used for empty/invalid v_path */ 95 char *vn_vpath_empty = ""; 96 97 static int fs_reparse_mark(char *target, vattr_t *vap, xvattr_t *xvattr); 98 99 /* 100 * Convert stat(2) formats to vnode types and vice versa. (Knows about 101 * numerical order of S_IFMT and vnode types.) 102 */ 103 enum vtype iftovt_tab[] = { 104 VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON, 105 VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VNON 106 }; 107 108 ushort_t vttoif_tab[] = { 109 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFIFO, 110 S_IFDOOR, 0, S_IFSOCK, S_IFPORT, 0 111 }; 112 113 /* 114 * The system vnode cache. 115 */ 116 117 kmem_cache_t *vn_cache; 118 119 120 /* 121 * Vnode operations vector. 122 */ 123 124 static const fs_operation_trans_def_t vn_ops_table[] = { 125 VOPNAME_OPEN, offsetof(struct vnodeops, vop_open), 126 fs_nosys, fs_nosys, 127 128 VOPNAME_CLOSE, offsetof(struct vnodeops, vop_close), 129 fs_nosys, fs_nosys, 130 131 VOPNAME_READ, offsetof(struct vnodeops, vop_read), 132 fs_nosys, fs_nosys, 133 134 VOPNAME_WRITE, offsetof(struct vnodeops, vop_write), 135 fs_nosys, fs_nosys, 136 137 VOPNAME_IOCTL, offsetof(struct vnodeops, vop_ioctl), 138 fs_nosys, fs_nosys, 139 140 VOPNAME_SETFL, offsetof(struct vnodeops, vop_setfl), 141 fs_setfl, fs_nosys, 142 143 VOPNAME_GETATTR, offsetof(struct vnodeops, vop_getattr), 144 fs_nosys, fs_nosys, 145 146 VOPNAME_SETATTR, offsetof(struct vnodeops, vop_setattr), 147 fs_nosys, fs_nosys, 148 149 VOPNAME_ACCESS, offsetof(struct vnodeops, vop_access), 150 fs_nosys, fs_nosys, 151 152 VOPNAME_LOOKUP, offsetof(struct vnodeops, vop_lookup), 153 fs_nosys, fs_nosys, 154 155 VOPNAME_CREATE, offsetof(struct vnodeops, vop_create), 156 fs_nosys, fs_nosys, 157 158 VOPNAME_REMOVE, offsetof(struct vnodeops, vop_remove), 159 fs_nosys, fs_nosys, 160 161 VOPNAME_LINK, offsetof(struct vnodeops, vop_link), 162 fs_nosys, fs_nosys, 163 164 VOPNAME_RENAME, offsetof(struct vnodeops, vop_rename), 165 fs_nosys, fs_nosys, 166 167 VOPNAME_MKDIR, offsetof(struct vnodeops, vop_mkdir), 168 fs_nosys, fs_nosys, 169 170 VOPNAME_RMDIR, offsetof(struct vnodeops, vop_rmdir), 171 fs_nosys, fs_nosys, 172 173 VOPNAME_READDIR, offsetof(struct vnodeops, vop_readdir), 174 fs_nosys, fs_nosys, 175 176 VOPNAME_SYMLINK, offsetof(struct vnodeops, vop_symlink), 177 fs_nosys, fs_nosys, 178 179 VOPNAME_READLINK, offsetof(struct vnodeops, vop_readlink), 180 fs_nosys, fs_nosys, 181 182 VOPNAME_FSYNC, offsetof(struct vnodeops, vop_fsync), 183 fs_nosys, fs_nosys, 184 185 VOPNAME_INACTIVE, offsetof(struct vnodeops, vop_inactive), 186 fs_nosys, fs_nosys, 187 188 VOPNAME_FID, offsetof(struct vnodeops, vop_fid), 189 fs_nosys, fs_nosys, 190 191 VOPNAME_RWLOCK, offsetof(struct vnodeops, vop_rwlock), 192 fs_rwlock, fs_rwlock, 193 194 VOPNAME_RWUNLOCK, offsetof(struct vnodeops, vop_rwunlock), 195 (fs_generic_func_p)(uintptr_t)fs_rwunlock, 196 (fs_generic_func_p)(intptr_t)fs_rwunlock, /* no errors allowed */ 197 198 VOPNAME_SEEK, offsetof(struct vnodeops, vop_seek), 199 fs_nosys, fs_nosys, 200 201 VOPNAME_CMP, offsetof(struct vnodeops, vop_cmp), 202 fs_cmp, fs_cmp, /* no errors allowed */ 203 204 VOPNAME_FRLOCK, offsetof(struct vnodeops, vop_frlock), 205 fs_frlock, fs_nosys, 206 207 VOPNAME_SPACE, offsetof(struct vnodeops, vop_space), 208 fs_nosys, fs_nosys, 209 210 VOPNAME_REALVP, offsetof(struct vnodeops, vop_realvp), 211 fs_nosys, fs_nosys, 212 213 VOPNAME_GETPAGE, offsetof(struct vnodeops, vop_getpage), 214 fs_nosys, fs_nosys, 215 216 VOPNAME_PUTPAGE, offsetof(struct vnodeops, vop_putpage), 217 fs_nosys, fs_nosys, 218 219 VOPNAME_MAP, offsetof(struct vnodeops, vop_map), 220 (fs_generic_func_p) fs_nosys_map, 221 (fs_generic_func_p) fs_nosys_map, 222 223 VOPNAME_ADDMAP, offsetof(struct vnodeops, vop_addmap), 224 (fs_generic_func_p) fs_nosys_addmap, 225 (fs_generic_func_p) fs_nosys_addmap, 226 227 VOPNAME_DELMAP, offsetof(struct vnodeops, vop_delmap), 228 fs_nosys, fs_nosys, 229 230 VOPNAME_POLL, offsetof(struct vnodeops, vop_poll), 231 (fs_generic_func_p) fs_poll, (fs_generic_func_p) fs_nosys_poll, 232 233 VOPNAME_DUMP, offsetof(struct vnodeops, vop_dump), 234 fs_nosys, fs_nosys, 235 236 VOPNAME_PATHCONF, offsetof(struct vnodeops, vop_pathconf), 237 fs_pathconf, fs_nosys, 238 239 VOPNAME_PAGEIO, offsetof(struct vnodeops, vop_pageio), 240 fs_nosys, fs_nosys, 241 242 VOPNAME_DUMPCTL, offsetof(struct vnodeops, vop_dumpctl), 243 fs_nosys, fs_nosys, 244 245 VOPNAME_DISPOSE, offsetof(struct vnodeops, vop_dispose), 246 (fs_generic_func_p)(intptr_t)fs_dispose, 247 (fs_generic_func_p)(intptr_t)fs_nodispose, 248 249 VOPNAME_SETSECATTR, offsetof(struct vnodeops, vop_setsecattr), 250 fs_nosys, fs_nosys, 251 252 VOPNAME_GETSECATTR, offsetof(struct vnodeops, vop_getsecattr), 253 fs_fab_acl, fs_nosys, 254 255 VOPNAME_SHRLOCK, offsetof(struct vnodeops, vop_shrlock), 256 fs_shrlock, fs_nosys, 257 258 VOPNAME_VNEVENT, offsetof(struct vnodeops, vop_vnevent), 259 (fs_generic_func_p) fs_vnevent_nosupport, 260 (fs_generic_func_p) fs_vnevent_nosupport, 261 262 VOPNAME_REQZCBUF, offsetof(struct vnodeops, vop_reqzcbuf), 263 fs_nosys, fs_nosys, 264 265 VOPNAME_RETZCBUF, offsetof(struct vnodeops, vop_retzcbuf), 266 fs_nosys, fs_nosys, 267 268 NULL, 0, NULL, NULL 269 }; 270 271 /* Extensible attribute (xva) routines. */ 272 273 /* 274 * Zero out the structure, set the size of the requested/returned bitmaps, 275 * set AT_XVATTR in the embedded vattr_t's va_mask, and set up the pointer 276 * to the returned attributes array. 277 */ 278 void 279 xva_init(xvattr_t *xvap) 280 { 281 bzero(xvap, sizeof (xvattr_t)); 282 xvap->xva_mapsize = XVA_MAPSIZE; 283 xvap->xva_magic = XVA_MAGIC; 284 xvap->xva_vattr.va_mask = AT_XVATTR; 285 xvap->xva_rtnattrmapp = &(xvap->xva_rtnattrmap)[0]; 286 } 287 288 /* 289 * If AT_XVATTR is set, returns a pointer to the embedded xoptattr_t 290 * structure. Otherwise, returns NULL. 291 */ 292 xoptattr_t * 293 xva_getxoptattr(xvattr_t *xvap) 294 { 295 xoptattr_t *xoap = NULL; 296 if (xvap->xva_vattr.va_mask & AT_XVATTR) 297 xoap = &xvap->xva_xoptattrs; 298 return (xoap); 299 } 300 301 // vska_compar 302 // create_vopstats_template 303 // new_vskstat 304 // vopstats_startup 305 // initialize_vopstats 306 // get_fstype_vopstats 307 // get_vskstat_anchor 308 // teardown_vopstats 309 310 /* 311 * Read or write a vnode. Called from kernel code. 312 */ 313 int 314 vn_rdwr( 315 enum uio_rw rw, 316 struct vnode *vp, 317 caddr_t base, 318 ssize_t len, 319 offset_t offset, 320 enum uio_seg seg, 321 int ioflag, 322 rlim64_t ulimit, /* meaningful only if rw is UIO_WRITE */ 323 cred_t *cr, 324 ssize_t *residp) 325 { 326 struct uio uio; 327 struct iovec iov; 328 int error; 329 int in_crit = 0; 330 331 if (rw == UIO_WRITE && ISROFILE(vp)) 332 return (EROFS); 333 334 if (len < 0) 335 return (EIO); 336 337 VOPXID_MAP_CR(vp, cr); 338 339 iov.iov_base = base; 340 iov.iov_len = len; 341 uio.uio_iov = &iov; 342 uio.uio_iovcnt = 1; 343 uio.uio_loffset = offset; 344 uio.uio_segflg = (short)seg; 345 uio.uio_resid = len; 346 uio.uio_llimit = ulimit; 347 348 /* 349 * We have to enter the critical region before calling VOP_RWLOCK 350 * to avoid a deadlock with ufs. 351 */ 352 if (nbl_need_check(vp)) { 353 int svmand; 354 355 nbl_start_crit(vp, RW_READER); 356 in_crit = 1; 357 error = nbl_svmand(vp, cr, &svmand); 358 if (error != 0) 359 goto done; 360 if (nbl_conflict(vp, rw == UIO_WRITE ? NBL_WRITE : NBL_READ, 361 uio.uio_offset, uio.uio_resid, svmand, NULL)) { 362 error = EACCES; 363 goto done; 364 } 365 } 366 367 (void) VOP_RWLOCK(vp, 368 rw == UIO_WRITE ? V_WRITELOCK_TRUE : V_WRITELOCK_FALSE, NULL); 369 if (rw == UIO_WRITE) { 370 uio.uio_fmode = FWRITE; 371 uio.uio_extflg = UIO_COPY_DEFAULT; 372 error = VOP_WRITE(vp, &uio, ioflag, cr, NULL); 373 } else { 374 uio.uio_fmode = FREAD; 375 uio.uio_extflg = UIO_COPY_CACHED; 376 error = VOP_READ(vp, &uio, ioflag, cr, NULL); 377 } 378 VOP_RWUNLOCK(vp, 379 rw == UIO_WRITE ? V_WRITELOCK_TRUE : V_WRITELOCK_FALSE, NULL); 380 if (residp) 381 *residp = uio.uio_resid; 382 else if (uio.uio_resid) 383 error = EIO; 384 385 done: 386 if (in_crit) 387 nbl_end_crit(vp); 388 return (error); 389 } 390 391 /* 392 * Incremend the hold on a vnode 393 * (Real kernel uses a macro) 394 */ 395 void 396 vn_hold(struct vnode *vp) 397 { 398 mutex_enter(&vp->v_lock); 399 (vp)->v_count++; 400 mutex_exit(&vp->v_lock); 401 } 402 403 /* 404 * Release a vnode. Call VOP_INACTIVE on last reference or 405 * decrement reference count... 406 */ 407 void 408 vn_rele(vnode_t *vp) 409 { 410 VERIFY(vp->v_count > 0); 411 mutex_enter(&vp->v_lock); 412 if (vp->v_count == 1) { 413 mutex_exit(&vp->v_lock); 414 VOP_INACTIVE(vp, CRED(), NULL); 415 return; 416 } 417 VN_RELE_LOCKED(vp); 418 mutex_exit(&vp->v_lock); 419 } 420 421 // vn_rele_dnlc 422 // vn_rele_stream 423 // vn_rele_inactive 424 // vn_rele_async 425 // vn_open, vn_openat 426 // vn_open_upgrade 427 // vn_open_downgrade 428 // vn_create, vn_createat 429 // vn_link, vn_linkat 430 // vn_rename, vn_renameat 431 // vn_remove, vn_removeat 432 433 434 /* 435 * Utility function to compare equality of vnodes. 436 * Compare the underlying real vnodes, if there are underlying vnodes. 437 * This is a more thorough comparison than the VN_CMP() macro provides. 438 */ 439 int 440 vn_compare(vnode_t *vp1, vnode_t *vp2) 441 { 442 vnode_t *realvp; 443 444 if (vp1 != NULL && VOP_REALVP(vp1, &realvp, NULL) == 0) 445 vp1 = realvp; 446 if (vp2 != NULL && VOP_REALVP(vp2, &realvp, NULL) == 0) 447 vp2 = realvp; 448 return (VN_CMP(vp1, vp2)); 449 } 450 451 // vn_vfslocks_buckets 452 // vn_vfslocks_getlock 453 // vn_vfslocks_rele 454 455 static krwlock_t vfsentry_ve_lock; 456 457 /* 458 * vn_vfswlock_wait is used to implement a lock which is logically a 459 * writers lock protecting the v_vfsmountedhere field. 460 * vn_vfswlock_wait has been modified to be similar to vn_vfswlock, 461 * except that it blocks to acquire the lock VVFSLOCK. 462 * 463 * traverse() and routines re-implementing part of traverse (e.g. autofs) 464 * need to hold this lock. mount(), vn_rename(), vn_remove() and so on 465 * need the non-blocking version of the writers lock i.e. vn_vfswlock 466 */ 467 int 468 vn_vfswlock_wait(vnode_t *vp) 469 { 470 471 ASSERT(vp != NULL); 472 473 rw_enter(&vfsentry_ve_lock, RW_WRITER); 474 475 return (0); 476 } 477 478 int 479 vn_vfsrlock_wait(vnode_t *vp) 480 { 481 482 ASSERT(vp != NULL); 483 484 rw_enter(&vfsentry_ve_lock, RW_READER); 485 486 return (0); 487 } 488 489 /* 490 * vn_vfswlock is used to implement a lock which is logically a writers lock 491 * protecting the v_vfsmountedhere field. 492 */ 493 int 494 vn_vfswlock(vnode_t *vp) 495 { 496 497 if (vp == NULL) 498 return (EBUSY); 499 500 if (rw_tryenter(&vfsentry_ve_lock, RW_WRITER)) 501 return (0); 502 503 return (EBUSY); 504 } 505 506 int 507 vn_vfsrlock(vnode_t *vp) 508 { 509 510 if (vp == NULL) 511 return (EBUSY); 512 513 if (rw_tryenter(&vfsentry_ve_lock, RW_READER)) 514 return (0); 515 516 return (EBUSY); 517 } 518 519 void 520 vn_vfsunlock(vnode_t *vp) 521 { 522 523 rw_exit(&vfsentry_ve_lock); 524 } 525 526 int 527 vn_vfswlock_held(vnode_t *vp) 528 { 529 int held; 530 531 ASSERT(vp != NULL); 532 533 held = rw_write_held(&vfsentry_ve_lock); 534 535 return (held); 536 } 537 538 539 int 540 vn_make_ops( 541 const char *name, /* Name of file system */ 542 const fs_operation_def_t *templ, /* Operation specification */ 543 vnodeops_t **actual) /* Return the vnodeops */ 544 { 545 int unused_ops; 546 int error; 547 548 *actual = (vnodeops_t *)kmem_alloc(sizeof (vnodeops_t), KM_SLEEP); 549 550 (*actual)->vnop_name = name; 551 552 error = fs_build_vector(*actual, &unused_ops, vn_ops_table, templ); 553 if (error) { 554 kmem_free(*actual, sizeof (vnodeops_t)); 555 } 556 557 #if DEBUG 558 if (unused_ops != 0) 559 cmn_err(CE_WARN, "vn_make_ops: %s: %d operations supplied " 560 "but not used", name, unused_ops); 561 #endif 562 563 return (error); 564 } 565 566 /* 567 * Free the vnodeops created as a result of vn_make_ops() 568 */ 569 void 570 vn_freevnodeops(vnodeops_t *vnops) 571 { 572 kmem_free(vnops, sizeof (vnodeops_t)); 573 } 574 575 /* 576 * Vnode cache. 577 */ 578 579 /* ARGSUSED */ 580 static int 581 vn_cache_constructor(void *buf, void *cdrarg, int kmflags) 582 { 583 struct vnode *vp = buf; 584 585 bzero(vp, sizeof (*vp)); 586 mutex_init(&vp->v_lock, NULL, MUTEX_DEFAULT, NULL); 587 rw_init(&vp->v_nbllock, NULL, RW_DEFAULT, NULL); 588 vp->v_path = vn_vpath_empty; 589 vp->v_fd = -1; 590 vp->v_st_dev = NODEV; 591 592 return (0); 593 } 594 595 /* ARGSUSED */ 596 static void 597 vn_cache_destructor(void *buf, void *cdrarg) 598 { 599 struct vnode *vp; 600 601 vp = buf; 602 603 rw_destroy(&vp->v_nbllock); 604 mutex_destroy(&vp->v_lock); 605 } 606 607 void 608 vn_create_cache(void) 609 { 610 vn_cache = kmem_cache_create("vn_cache", sizeof (struct vnode), 611 VNODE_ALIGN, vn_cache_constructor, vn_cache_destructor, NULL, NULL, 612 NULL, 0); 613 } 614 615 void 616 vn_destroy_cache(void) 617 { 618 kmem_cache_destroy(vn_cache); 619 } 620 621 /* 622 * Used by file systems when fs-specific nodes (e.g., ufs inodes) are 623 * cached by the file system and vnodes remain associated. 624 */ 625 void 626 vn_recycle(vnode_t *vp) 627 { 628 VERIFY(vp->v_path != NULL); 629 630 /* 631 * XXX - This really belongs in vn_reinit(), but we have some issues 632 * with the counts. Best to have it here for clean initialization. 633 */ 634 vp->v_rdcnt = 0; 635 vp->v_wrcnt = 0; 636 637 /* 638 * If FEM was in use... 639 */ 640 641 if (vp->v_path != vn_vpath_empty) { 642 kmem_free(vp->v_path, strlen(vp->v_path) + 1); 643 vp->v_path = vn_vpath_empty; 644 } 645 // vsd_free(vp); 646 } 647 648 /* 649 * Used to reset the vnode fields including those that are directly accessible 650 * as well as those which require an accessor function. 651 */ 652 void 653 vn_reinit(vnode_t *vp) 654 { 655 vp->v_count = 1; 656 // vp->v_count_dnlc = 0; 657 vp->v_vfsp = NULL; 658 vp->v_stream = NULL; 659 vp->v_vfsmountedhere = NULL; 660 vp->v_flag = 0; 661 vp->v_type = VNON; 662 vp->v_rdev = NODEV; 663 664 vp->v_xattrdir = NULL; 665 666 /* 667 * In a few specific instances, vn_reinit() is used to initialize 668 * locally defined vnode_t instances. Lacking the construction offered 669 * by vn_alloc(), these vnodes require v_path initialization. 670 */ 671 if (vp->v_path == NULL) { 672 vp->v_path = vn_vpath_empty; 673 } 674 675 /* Handles v_femhead, v_path, and the r/w/map counts */ 676 vn_recycle(vp); 677 } 678 679 vnode_t * 680 vn_alloc(int kmflag) 681 { 682 vnode_t *vp; 683 684 vp = kmem_cache_alloc(vn_cache, kmflag); 685 686 if (vp != NULL) { 687 // vp->v_femhead = NULL; /* Must be done before vn_reinit() */ 688 // vp->v_fopdata = NULL; 689 vn_reinit(vp); 690 } 691 692 return (vp); 693 } 694 695 void 696 vn_free(vnode_t *vp) 697 { 698 extern vnode_t *rootdir; 699 ASSERT(vp != rootdir); 700 701 /* 702 * Some file systems call vn_free() with v_count of zero, 703 * some with v_count of 1. In any case, the value should 704 * never be anything else. 705 */ 706 ASSERT((vp->v_count == 0) || (vp->v_count == 1)); 707 VERIFY(vp->v_path != NULL); 708 if (vp->v_path != vn_vpath_empty) { 709 kmem_free(vp->v_path, strlen(vp->v_path) + 1); 710 vp->v_path = vn_vpath_empty; 711 } 712 713 /* If FEM was in use... */ 714 715 // vsd_free(vp); 716 kmem_cache_free(vn_cache, vp); 717 } 718 719 /* 720 * vnode status changes, should define better states than 1, 0. 721 */ 722 void 723 vn_reclaim(vnode_t *vp) 724 { 725 vfs_t *vfsp = vp->v_vfsp; 726 727 if (vfsp == NULL || 728 vfsp->vfs_implp == NULL || vfsp->vfs_femhead == NULL) { 729 return; 730 } 731 (void) VFS_VNSTATE(vfsp, vp, VNTRANS_RECLAIMED); 732 } 733 734 void 735 vn_idle(vnode_t *vp) 736 { 737 vfs_t *vfsp = vp->v_vfsp; 738 739 if (vfsp == NULL || 740 vfsp->vfs_implp == NULL || vfsp->vfs_femhead == NULL) { 741 return; 742 } 743 (void) VFS_VNSTATE(vfsp, vp, VNTRANS_IDLED); 744 } 745 void 746 vn_exists(vnode_t *vp) 747 { 748 vfs_t *vfsp = vp->v_vfsp; 749 750 if (vfsp == NULL || 751 vfsp->vfs_implp == NULL || vfsp->vfs_femhead == NULL) { 752 return; 753 } 754 (void) VFS_VNSTATE(vfsp, vp, VNTRANS_EXISTS); 755 } 756 757 void 758 vn_invalid(vnode_t *vp) 759 { 760 } 761 762 /* Vnode event notification */ 763 // vnevent_support() 764 // vnevent_... 765 766 /* 767 * Vnode accessors. 768 */ 769 770 int 771 vn_is_readonly(vnode_t *vp) 772 { 773 return (vp->v_vfsp->vfs_flag & VFS_RDONLY); 774 } 775 776 int 777 vn_has_flocks(vnode_t *vp) 778 { 779 return (0); 780 } 781 782 int 783 vn_has_mandatory_locks(vnode_t *vp, int mode) 784 { 785 return (0); 786 } 787 788 int 789 vn_has_cached_data(vnode_t *vp) 790 { 791 return (0); 792 } 793 794 // vn_can_change_zones 795 796 /* 797 * Return nonzero if the vnode is a mount point, zero if not. 798 */ 799 int 800 vn_ismntpt(vnode_t *vp) 801 { 802 return (vp->v_vfsmountedhere != NULL); 803 } 804 805 /* Retrieve the vfs (if any) mounted on this vnode */ 806 vfs_t * 807 vn_mountedvfs(vnode_t *vp) 808 { 809 return (vp->v_vfsmountedhere); 810 } 811 812 /* 813 * Return nonzero if the vnode is referenced by the dnlc, zero if not. 814 * (no DNLC here) 815 */ 816 int 817 vn_in_dnlc(vnode_t *vp) 818 { 819 return (0); 820 } 821 822 823 /* 824 * vn_has_other_opens() checks whether a particular file is opened by more than 825 * just the caller and whether the open is for read and/or write. 826 * This routine is for calling after the caller has already called VOP_OPEN() 827 * and the caller wishes to know if they are the only one with it open for 828 * the mode(s) specified. 829 * 830 * Vnode counts are only kept on regular files (v_type=VREG). 831 */ 832 int 833 vn_has_other_opens( 834 vnode_t *vp, 835 v_mode_t mode) 836 { 837 838 ASSERT(vp != NULL); 839 840 switch (mode) { 841 case V_WRITE: 842 if (vp->v_wrcnt > 1) 843 return (V_TRUE); 844 break; 845 case V_RDORWR: 846 if ((vp->v_rdcnt > 1) || (vp->v_wrcnt > 1)) 847 return (V_TRUE); 848 break; 849 case V_RDANDWR: 850 if ((vp->v_rdcnt > 1) && (vp->v_wrcnt > 1)) 851 return (V_TRUE); 852 break; 853 case V_READ: 854 if (vp->v_rdcnt > 1) 855 return (V_TRUE); 856 break; 857 } 858 859 return (V_FALSE); 860 } 861 862 /* 863 * vn_is_opened() checks whether a particular file is opened and 864 * whether the open is for read and/or write. 865 * 866 * Vnode counts are only kept on regular files (v_type=VREG). 867 */ 868 int 869 vn_is_opened( 870 vnode_t *vp, 871 v_mode_t mode) 872 { 873 874 ASSERT(vp != NULL); 875 876 switch (mode) { 877 case V_WRITE: 878 if (vp->v_wrcnt) 879 return (V_TRUE); 880 break; 881 case V_RDANDWR: 882 if (vp->v_rdcnt && vp->v_wrcnt) 883 return (V_TRUE); 884 break; 885 case V_RDORWR: 886 if (vp->v_rdcnt || vp->v_wrcnt) 887 return (V_TRUE); 888 break; 889 case V_READ: 890 if (vp->v_rdcnt) 891 return (V_TRUE); 892 break; 893 } 894 895 return (V_FALSE); 896 } 897 898 /* 899 * vn_is_mapped() checks whether a particular file is mapped and whether 900 * the file is mapped read and/or write. (no mmap here) 901 */ 902 int 903 vn_is_mapped( 904 vnode_t *vp, 905 v_mode_t mode) 906 { 907 return (V_FALSE); 908 } 909 910 /* 911 * Set the operations vector for a vnode. 912 */ 913 void 914 vn_setops(vnode_t *vp, vnodeops_t *vnodeops) 915 { 916 917 ASSERT(vp != NULL); 918 ASSERT(vnodeops != NULL); 919 920 vp->v_op = vnodeops; 921 } 922 923 /* 924 * Retrieve the operations vector for a vnode 925 */ 926 vnodeops_t * 927 vn_getops(vnode_t *vp) 928 { 929 930 ASSERT(vp != NULL); 931 932 return (vp->v_op); 933 } 934 935 /* 936 * Returns non-zero (1) if the vnodeops matches that of the vnode. 937 * Returns zero (0) if not. 938 */ 939 int 940 vn_matchops(vnode_t *vp, vnodeops_t *vnodeops) 941 { 942 return (vn_getops(vp) == vnodeops); 943 } 944 945 // vn_matchopval 946 // fs_new_caller_id 947 948 // vn_clearpath 949 // vn_setpath_common 950 951 /* ARGSUSED */ 952 void 953 vn_updatepath(vnode_t *pvp, vnode_t *vp, const char *name) 954 { 955 } 956 957 // vn_setpath... 958 // vn_renamepath 959 // vn_copypath 960 961 // vn_vmpss_usepageio 962 963 /* VOP_XXX() macros call the corresponding fop_xxx() function */ 964 965 int 966 fop_open( 967 vnode_t **vpp, 968 int mode, 969 cred_t *cr, 970 caller_context_t *ct) 971 { 972 int ret; 973 vnode_t *vp = *vpp; 974 975 VN_HOLD(vp); 976 /* 977 * Adding to the vnode counts before calling open 978 * avoids the need for a mutex... 979 */ 980 if ((*vpp)->v_type == VREG) { 981 if (mode & FREAD) 982 atomic_inc_32(&(*vpp)->v_rdcnt); 983 if (mode & FWRITE) 984 atomic_inc_32(&(*vpp)->v_wrcnt); 985 } 986 987 VOPXID_MAP_CR(vp, cr); 988 989 ret = (*(*(vpp))->v_op->vop_open)(vpp, mode, cr, ct); 990 991 if (ret) { 992 /* 993 * Use the saved vp just in case the vnode ptr got trashed 994 * by the error. 995 */ 996 VOPSTATS_UPDATE(vp, open); 997 if ((vp->v_type == VREG) && (mode & FREAD)) 998 atomic_dec_32(&vp->v_rdcnt); 999 if ((vp->v_type == VREG) && (mode & FWRITE)) 1000 atomic_dec_32(&vp->v_wrcnt); 1001 } else { 1002 /* 1003 * Some filesystems will return a different vnode, 1004 * but the same path was still used to open it. 1005 * So if we do change the vnode and need to 1006 * copy over the path, do so here, rather than special 1007 * casing each filesystem. Adjust the vnode counts to 1008 * reflect the vnode switch. 1009 */ 1010 VOPSTATS_UPDATE(*vpp, open); 1011 if (*vpp != vp && *vpp != NULL) { 1012 // vn_copypath(vp, *vpp); 1013 if (((*vpp)->v_type == VREG) && (mode & FREAD)) 1014 atomic_inc_32(&(*vpp)->v_rdcnt); 1015 if ((vp->v_type == VREG) && (mode & FREAD)) 1016 atomic_dec_32(&vp->v_rdcnt); 1017 if (((*vpp)->v_type == VREG) && (mode & FWRITE)) 1018 atomic_inc_32(&(*vpp)->v_wrcnt); 1019 if ((vp->v_type == VREG) && (mode & FWRITE)) 1020 atomic_dec_32(&vp->v_wrcnt); 1021 } 1022 } 1023 VN_RELE(vp); 1024 return (ret); 1025 } 1026 1027 int 1028 fop_close( 1029 vnode_t *vp, 1030 int flag, 1031 int count, 1032 offset_t offset, 1033 cred_t *cr, 1034 caller_context_t *ct) 1035 { 1036 int err; 1037 1038 VOPXID_MAP_CR(vp, cr); 1039 1040 err = (*(vp)->v_op->vop_close)(vp, flag, count, offset, cr, ct); 1041 VOPSTATS_UPDATE(vp, close); 1042 /* 1043 * Check passed in count to handle possible dups. Vnode counts are only 1044 * kept on regular files 1045 */ 1046 if ((vp->v_type == VREG) && (count == 1)) { 1047 if (flag & FREAD) { 1048 ASSERT(vp->v_rdcnt > 0); 1049 atomic_dec_32(&vp->v_rdcnt); 1050 } 1051 if (flag & FWRITE) { 1052 ASSERT(vp->v_wrcnt > 0); 1053 atomic_dec_32(&vp->v_wrcnt); 1054 } 1055 } 1056 return (err); 1057 } 1058 1059 int 1060 fop_read( 1061 vnode_t *vp, 1062 uio_t *uiop, 1063 int ioflag, 1064 cred_t *cr, 1065 caller_context_t *ct) 1066 { 1067 int err; 1068 ssize_t resid_start = uiop->uio_resid; 1069 1070 VOPXID_MAP_CR(vp, cr); 1071 1072 err = (*(vp)->v_op->vop_read)(vp, uiop, ioflag, cr, ct); 1073 VOPSTATS_UPDATE_IO(vp, read, 1074 read_bytes, (resid_start - uiop->uio_resid)); 1075 return (err); 1076 } 1077 1078 int 1079 fop_write( 1080 vnode_t *vp, 1081 uio_t *uiop, 1082 int ioflag, 1083 cred_t *cr, 1084 caller_context_t *ct) 1085 { 1086 int err; 1087 ssize_t resid_start = uiop->uio_resid; 1088 1089 VOPXID_MAP_CR(vp, cr); 1090 1091 err = (*(vp)->v_op->vop_write)(vp, uiop, ioflag, cr, ct); 1092 VOPSTATS_UPDATE_IO(vp, write, 1093 write_bytes, (resid_start - uiop->uio_resid)); 1094 return (err); 1095 } 1096 1097 int 1098 fop_ioctl( 1099 vnode_t *vp, 1100 int cmd, 1101 intptr_t arg, 1102 int flag, 1103 cred_t *cr, 1104 int *rvalp, 1105 caller_context_t *ct) 1106 { 1107 int err; 1108 1109 VOPXID_MAP_CR(vp, cr); 1110 1111 err = (*(vp)->v_op->vop_ioctl)(vp, cmd, arg, flag, cr, rvalp, ct); 1112 VOPSTATS_UPDATE(vp, ioctl); 1113 return (err); 1114 } 1115 1116 int 1117 fop_setfl( 1118 vnode_t *vp, 1119 int oflags, 1120 int nflags, 1121 cred_t *cr, 1122 caller_context_t *ct) 1123 { 1124 int err; 1125 1126 VOPXID_MAP_CR(vp, cr); 1127 1128 err = (*(vp)->v_op->vop_setfl)(vp, oflags, nflags, cr, ct); 1129 VOPSTATS_UPDATE(vp, setfl); 1130 return (err); 1131 } 1132 1133 int 1134 fop_getattr( 1135 vnode_t *vp, 1136 vattr_t *vap, 1137 int flags, 1138 cred_t *cr, 1139 caller_context_t *ct) 1140 { 1141 int err; 1142 1143 VOPXID_MAP_CR(vp, cr); 1144 1145 /* 1146 * If this file system doesn't understand the xvattr extensions 1147 * then turn off the xvattr bit. 1148 */ 1149 if (vfs_has_feature(vp->v_vfsp, VFSFT_XVATTR) == 0) { 1150 vap->va_mask &= ~AT_XVATTR; 1151 } 1152 1153 /* 1154 * We're only allowed to skip the ACL check iff we used a 32 bit 1155 * ACE mask with VOP_ACCESS() to determine permissions. 1156 */ 1157 if ((flags & ATTR_NOACLCHECK) && 1158 vfs_has_feature(vp->v_vfsp, VFSFT_ACEMASKONACCESS) == 0) { 1159 return (EINVAL); 1160 } 1161 err = (*(vp)->v_op->vop_getattr)(vp, vap, flags, cr, ct); 1162 VOPSTATS_UPDATE(vp, getattr); 1163 return (err); 1164 } 1165 1166 int 1167 fop_setattr( 1168 vnode_t *vp, 1169 vattr_t *vap, 1170 int flags, 1171 cred_t *cr, 1172 caller_context_t *ct) 1173 { 1174 int err; 1175 1176 VOPXID_MAP_CR(vp, cr); 1177 1178 /* 1179 * If this file system doesn't understand the xvattr extensions 1180 * then turn off the xvattr bit. 1181 */ 1182 if (vfs_has_feature(vp->v_vfsp, VFSFT_XVATTR) == 0) { 1183 vap->va_mask &= ~AT_XVATTR; 1184 } 1185 1186 /* 1187 * We're only allowed to skip the ACL check iff we used a 32 bit 1188 * ACE mask with VOP_ACCESS() to determine permissions. 1189 */ 1190 if ((flags & ATTR_NOACLCHECK) && 1191 vfs_has_feature(vp->v_vfsp, VFSFT_ACEMASKONACCESS) == 0) { 1192 return (EINVAL); 1193 } 1194 err = (*(vp)->v_op->vop_setattr)(vp, vap, flags, cr, ct); 1195 VOPSTATS_UPDATE(vp, setattr); 1196 return (err); 1197 } 1198 1199 int 1200 fop_access( 1201 vnode_t *vp, 1202 int mode, 1203 int flags, 1204 cred_t *cr, 1205 caller_context_t *ct) 1206 { 1207 int err; 1208 1209 if ((flags & V_ACE_MASK) && 1210 vfs_has_feature(vp->v_vfsp, VFSFT_ACEMASKONACCESS) == 0) { 1211 return (EINVAL); 1212 } 1213 1214 VOPXID_MAP_CR(vp, cr); 1215 1216 err = (*(vp)->v_op->vop_access)(vp, mode, flags, cr, ct); 1217 VOPSTATS_UPDATE(vp, access); 1218 return (err); 1219 } 1220 1221 int 1222 fop_lookup( 1223 vnode_t *dvp, 1224 char *nm, 1225 vnode_t **vpp, 1226 pathname_t *pnp, 1227 int flags, 1228 vnode_t *rdir, 1229 cred_t *cr, 1230 caller_context_t *ct, 1231 int *deflags, /* Returned per-dirent flags */ 1232 pathname_t *ppnp) /* Returned case-preserved name in directory */ 1233 { 1234 int ret; 1235 1236 /* 1237 * If this file system doesn't support case-insensitive access 1238 * and said access is requested, fail quickly. It is required 1239 * that if the vfs supports case-insensitive lookup, it also 1240 * supports extended dirent flags. 1241 */ 1242 if (flags & FIGNORECASE && 1243 (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 && 1244 vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0)) 1245 return (EINVAL); 1246 1247 VOPXID_MAP_CR(dvp, cr); 1248 1249 /* 1250 * The real vnode.c would call xattr_dir_lookup here, 1251 * which inserts the special "System Attribute" files: 1252 * (SUNWattr_rw, SUNWattr_ro) into the xattr list. 1253 * Here the main focus is on testing xattr support, 1254 * so the system attribute stuff is ommitted. 1255 */ 1256 #if 0 1257 if ((flags & LOOKUP_XATTR) && (flags & LOOKUP_HAVE_SYSATTR_DIR) == 0) { 1258 // Don't need xattr support in libfksmbfs. 1259 // ret = xattr_dir_lookup(dvp, vpp, flags, cr); 1260 ret = EINVAL; 1261 } else 1262 #endif 1263 { 1264 ret = (*(dvp)->v_op->vop_lookup) 1265 (dvp, nm, vpp, pnp, flags, rdir, cr, ct, deflags, ppnp); 1266 } 1267 if (ret == 0 && *vpp) { 1268 VOPSTATS_UPDATE(*vpp, lookup); 1269 vn_updatepath(dvp, *vpp, nm); 1270 } 1271 1272 return (ret); 1273 } 1274 1275 int 1276 fop_create( 1277 vnode_t *dvp, 1278 char *name, 1279 vattr_t *vap, 1280 vcexcl_t excl, 1281 int mode, 1282 vnode_t **vpp, 1283 cred_t *cr, 1284 int flags, 1285 caller_context_t *ct, 1286 vsecattr_t *vsecp) /* ACL to set during create */ 1287 { 1288 int ret; 1289 1290 if (vsecp != NULL && 1291 vfs_has_feature(dvp->v_vfsp, VFSFT_ACLONCREATE) == 0) { 1292 return (EINVAL); 1293 } 1294 /* 1295 * If this file system doesn't support case-insensitive access 1296 * and said access is requested, fail quickly. 1297 */ 1298 if (flags & FIGNORECASE && 1299 (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 && 1300 vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0)) 1301 return (EINVAL); 1302 1303 VOPXID_MAP_CR(dvp, cr); 1304 1305 ret = (*(dvp)->v_op->vop_create) 1306 (dvp, name, vap, excl, mode, vpp, cr, flags, ct, vsecp); 1307 if (ret == 0 && *vpp) { 1308 VOPSTATS_UPDATE(*vpp, create); 1309 vn_updatepath(dvp, *vpp, name); 1310 } 1311 1312 return (ret); 1313 } 1314 1315 int 1316 fop_remove( 1317 vnode_t *dvp, 1318 char *nm, 1319 cred_t *cr, 1320 caller_context_t *ct, 1321 int flags) 1322 { 1323 int err; 1324 1325 /* 1326 * If this file system doesn't support case-insensitive access 1327 * and said access is requested, fail quickly. 1328 */ 1329 if (flags & FIGNORECASE && 1330 (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 && 1331 vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0)) 1332 return (EINVAL); 1333 1334 VOPXID_MAP_CR(dvp, cr); 1335 1336 err = (*(dvp)->v_op->vop_remove)(dvp, nm, cr, ct, flags); 1337 VOPSTATS_UPDATE(dvp, remove); 1338 return (err); 1339 } 1340 1341 int 1342 fop_link( 1343 vnode_t *tdvp, 1344 vnode_t *svp, 1345 char *tnm, 1346 cred_t *cr, 1347 caller_context_t *ct, 1348 int flags) 1349 { 1350 int err; 1351 1352 /* 1353 * If the target file system doesn't support case-insensitive access 1354 * and said access is requested, fail quickly. 1355 */ 1356 if (flags & FIGNORECASE && 1357 (vfs_has_feature(tdvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 && 1358 vfs_has_feature(tdvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0)) 1359 return (EINVAL); 1360 1361 VOPXID_MAP_CR(tdvp, cr); 1362 1363 err = (*(tdvp)->v_op->vop_link)(tdvp, svp, tnm, cr, ct, flags); 1364 VOPSTATS_UPDATE(tdvp, link); 1365 return (err); 1366 } 1367 1368 int 1369 fop_rename( 1370 vnode_t *sdvp, 1371 char *snm, 1372 vnode_t *tdvp, 1373 char *tnm, 1374 cred_t *cr, 1375 caller_context_t *ct, 1376 int flags) 1377 { 1378 int err; 1379 1380 /* 1381 * If the file system involved does not support 1382 * case-insensitive access and said access is requested, fail 1383 * quickly. 1384 */ 1385 if (flags & FIGNORECASE && 1386 ((vfs_has_feature(sdvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 && 1387 vfs_has_feature(sdvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0))) 1388 return (EINVAL); 1389 1390 VOPXID_MAP_CR(tdvp, cr); 1391 1392 err = (*(sdvp)->v_op->vop_rename)(sdvp, snm, tdvp, tnm, cr, ct, flags); 1393 VOPSTATS_UPDATE(sdvp, rename); 1394 return (err); 1395 } 1396 1397 int 1398 fop_mkdir( 1399 vnode_t *dvp, 1400 char *dirname, 1401 vattr_t *vap, 1402 vnode_t **vpp, 1403 cred_t *cr, 1404 caller_context_t *ct, 1405 int flags, 1406 vsecattr_t *vsecp) /* ACL to set during create */ 1407 { 1408 int ret; 1409 1410 if (vsecp != NULL && 1411 vfs_has_feature(dvp->v_vfsp, VFSFT_ACLONCREATE) == 0) { 1412 return (EINVAL); 1413 } 1414 /* 1415 * If this file system doesn't support case-insensitive access 1416 * and said access is requested, fail quickly. 1417 */ 1418 if (flags & FIGNORECASE && 1419 (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 && 1420 vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0)) 1421 return (EINVAL); 1422 1423 VOPXID_MAP_CR(dvp, cr); 1424 1425 ret = (*(dvp)->v_op->vop_mkdir) 1426 (dvp, dirname, vap, vpp, cr, ct, flags, vsecp); 1427 if (ret == 0 && *vpp) { 1428 VOPSTATS_UPDATE(*vpp, mkdir); 1429 vn_updatepath(dvp, *vpp, dirname); 1430 } 1431 1432 return (ret); 1433 } 1434 1435 int 1436 fop_rmdir( 1437 vnode_t *dvp, 1438 char *nm, 1439 vnode_t *cdir, 1440 cred_t *cr, 1441 caller_context_t *ct, 1442 int flags) 1443 { 1444 int err; 1445 1446 /* 1447 * If this file system doesn't support case-insensitive access 1448 * and said access is requested, fail quickly. 1449 */ 1450 if (flags & FIGNORECASE && 1451 (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 && 1452 vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0)) 1453 return (EINVAL); 1454 1455 VOPXID_MAP_CR(dvp, cr); 1456 1457 err = (*(dvp)->v_op->vop_rmdir)(dvp, nm, cdir, cr, ct, flags); 1458 VOPSTATS_UPDATE(dvp, rmdir); 1459 return (err); 1460 } 1461 1462 int 1463 fop_readdir( 1464 vnode_t *vp, 1465 uio_t *uiop, 1466 cred_t *cr, 1467 int *eofp, 1468 caller_context_t *ct, 1469 int flags) 1470 { 1471 int err; 1472 ssize_t resid_start = uiop->uio_resid; 1473 1474 /* 1475 * If this file system doesn't support retrieving directory 1476 * entry flags and said access is requested, fail quickly. 1477 */ 1478 if (flags & V_RDDIR_ENTFLAGS && 1479 vfs_has_feature(vp->v_vfsp, VFSFT_DIRENTFLAGS) == 0) 1480 return (EINVAL); 1481 1482 VOPXID_MAP_CR(vp, cr); 1483 1484 err = (*(vp)->v_op->vop_readdir)(vp, uiop, cr, eofp, ct, flags); 1485 VOPSTATS_UPDATE_IO(vp, readdir, 1486 readdir_bytes, (resid_start - uiop->uio_resid)); 1487 return (err); 1488 } 1489 1490 int 1491 fop_symlink( 1492 vnode_t *dvp, 1493 char *linkname, 1494 vattr_t *vap, 1495 char *target, 1496 cred_t *cr, 1497 caller_context_t *ct, 1498 int flags) 1499 { 1500 int err; 1501 xvattr_t xvattr; 1502 1503 /* 1504 * If this file system doesn't support case-insensitive access 1505 * and said access is requested, fail quickly. 1506 */ 1507 if (flags & FIGNORECASE && 1508 (vfs_has_feature(dvp->v_vfsp, VFSFT_CASEINSENSITIVE) == 0 && 1509 vfs_has_feature(dvp->v_vfsp, VFSFT_NOCASESENSITIVE) == 0)) 1510 return (EINVAL); 1511 1512 VOPXID_MAP_CR(dvp, cr); 1513 1514 /* check for reparse point */ 1515 if ((vfs_has_feature(dvp->v_vfsp, VFSFT_REPARSE)) && 1516 (strncmp(target, FS_REPARSE_TAG_STR, 1517 strlen(FS_REPARSE_TAG_STR)) == 0)) { 1518 if (!fs_reparse_mark(target, vap, &xvattr)) 1519 vap = (vattr_t *)&xvattr; 1520 } 1521 1522 err = (*(dvp)->v_op->vop_symlink) 1523 (dvp, linkname, vap, target, cr, ct, flags); 1524 VOPSTATS_UPDATE(dvp, symlink); 1525 return (err); 1526 } 1527 1528 int 1529 fop_readlink( 1530 vnode_t *vp, 1531 uio_t *uiop, 1532 cred_t *cr, 1533 caller_context_t *ct) 1534 { 1535 int err; 1536 1537 VOPXID_MAP_CR(vp, cr); 1538 1539 err = (*(vp)->v_op->vop_readlink)(vp, uiop, cr, ct); 1540 VOPSTATS_UPDATE(vp, readlink); 1541 return (err); 1542 } 1543 1544 int 1545 fop_fsync( 1546 vnode_t *vp, 1547 int syncflag, 1548 cred_t *cr, 1549 caller_context_t *ct) 1550 { 1551 int err; 1552 1553 VOPXID_MAP_CR(vp, cr); 1554 1555 err = (*(vp)->v_op->vop_fsync)(vp, syncflag, cr, ct); 1556 VOPSTATS_UPDATE(vp, fsync); 1557 return (err); 1558 } 1559 1560 void 1561 fop_inactive( 1562 vnode_t *vp, 1563 cred_t *cr, 1564 caller_context_t *ct) 1565 { 1566 /* Need to update stats before vop call since we may lose the vnode */ 1567 VOPSTATS_UPDATE(vp, inactive); 1568 1569 VOPXID_MAP_CR(vp, cr); 1570 1571 (*(vp)->v_op->vop_inactive)(vp, cr, ct); 1572 } 1573 1574 int 1575 fop_fid( 1576 vnode_t *vp, 1577 fid_t *fidp, 1578 caller_context_t *ct) 1579 { 1580 int err; 1581 1582 err = (*(vp)->v_op->vop_fid)(vp, fidp, ct); 1583 VOPSTATS_UPDATE(vp, fid); 1584 return (err); 1585 } 1586 1587 int 1588 fop_rwlock( 1589 vnode_t *vp, 1590 int write_lock, 1591 caller_context_t *ct) 1592 { 1593 int ret; 1594 1595 ret = ((*(vp)->v_op->vop_rwlock)(vp, write_lock, ct)); 1596 VOPSTATS_UPDATE(vp, rwlock); 1597 return (ret); 1598 } 1599 1600 void 1601 fop_rwunlock( 1602 vnode_t *vp, 1603 int write_lock, 1604 caller_context_t *ct) 1605 { 1606 (*(vp)->v_op->vop_rwunlock)(vp, write_lock, ct); 1607 VOPSTATS_UPDATE(vp, rwunlock); 1608 } 1609 1610 int 1611 fop_seek( 1612 vnode_t *vp, 1613 offset_t ooff, 1614 offset_t *noffp, 1615 caller_context_t *ct) 1616 { 1617 int err; 1618 1619 err = (*(vp)->v_op->vop_seek)(vp, ooff, noffp, ct); 1620 VOPSTATS_UPDATE(vp, seek); 1621 return (err); 1622 } 1623 1624 int 1625 fop_cmp( 1626 vnode_t *vp1, 1627 vnode_t *vp2, 1628 caller_context_t *ct) 1629 { 1630 int err; 1631 1632 err = (*(vp1)->v_op->vop_cmp)(vp1, vp2, ct); 1633 VOPSTATS_UPDATE(vp1, cmp); 1634 return (err); 1635 } 1636 1637 int 1638 fop_frlock( 1639 vnode_t *vp, 1640 int cmd, 1641 flock64_t *bfp, 1642 int flag, 1643 offset_t offset, 1644 struct flk_callback *flk_cbp, 1645 cred_t *cr, 1646 caller_context_t *ct) 1647 { 1648 int err; 1649 1650 VOPXID_MAP_CR(vp, cr); 1651 1652 err = (*(vp)->v_op->vop_frlock) 1653 (vp, cmd, bfp, flag, offset, flk_cbp, cr, ct); 1654 VOPSTATS_UPDATE(vp, frlock); 1655 return (err); 1656 } 1657 1658 int 1659 fop_space( 1660 vnode_t *vp, 1661 int cmd, 1662 flock64_t *bfp, 1663 int flag, 1664 offset_t offset, 1665 cred_t *cr, 1666 caller_context_t *ct) 1667 { 1668 int err; 1669 1670 VOPXID_MAP_CR(vp, cr); 1671 1672 err = (*(vp)->v_op->vop_space)(vp, cmd, bfp, flag, offset, cr, ct); 1673 VOPSTATS_UPDATE(vp, space); 1674 return (err); 1675 } 1676 1677 int 1678 fop_realvp( 1679 vnode_t *vp, 1680 vnode_t **vpp, 1681 caller_context_t *ct) 1682 { 1683 int err; 1684 1685 err = (*(vp)->v_op->vop_realvp)(vp, vpp, ct); 1686 VOPSTATS_UPDATE(vp, realvp); 1687 return (err); 1688 } 1689 1690 int 1691 fop_getpage( 1692 vnode_t *vp, 1693 offset_t off, 1694 size_t len, 1695 uint_t *protp, 1696 page_t **plarr, 1697 size_t plsz, 1698 struct seg *seg, 1699 caddr_t addr, 1700 enum seg_rw rw, 1701 cred_t *cr, 1702 caller_context_t *ct) 1703 { 1704 int err; 1705 1706 VOPXID_MAP_CR(vp, cr); 1707 1708 err = (*(vp)->v_op->vop_getpage) 1709 (vp, off, len, protp, plarr, plsz, seg, addr, rw, cr, ct); 1710 VOPSTATS_UPDATE(vp, getpage); 1711 return (err); 1712 } 1713 1714 int 1715 fop_putpage( 1716 vnode_t *vp, 1717 offset_t off, 1718 size_t len, 1719 int flags, 1720 cred_t *cr, 1721 caller_context_t *ct) 1722 { 1723 int err; 1724 1725 VOPXID_MAP_CR(vp, cr); 1726 1727 err = (*(vp)->v_op->vop_putpage)(vp, off, len, flags, cr, ct); 1728 VOPSTATS_UPDATE(vp, putpage); 1729 return (err); 1730 } 1731 1732 int 1733 fop_map( 1734 vnode_t *vp, 1735 offset_t off, 1736 struct as *as, 1737 caddr_t *addrp, 1738 size_t len, 1739 uchar_t prot, 1740 uchar_t maxprot, 1741 uint_t flags, 1742 cred_t *cr, 1743 caller_context_t *ct) 1744 { 1745 int err; 1746 1747 VOPXID_MAP_CR(vp, cr); 1748 1749 err = (*(vp)->v_op->vop_map) 1750 (vp, off, as, addrp, len, prot, maxprot, flags, cr, ct); 1751 VOPSTATS_UPDATE(vp, map); 1752 return (err); 1753 } 1754 1755 int 1756 fop_addmap( 1757 vnode_t *vp, 1758 offset_t off, 1759 struct as *as, 1760 caddr_t addr, 1761 size_t len, 1762 uchar_t prot, 1763 uchar_t maxprot, 1764 uint_t flags, 1765 cred_t *cr, 1766 caller_context_t *ct) 1767 { 1768 int error; 1769 1770 VOPXID_MAP_CR(vp, cr); 1771 1772 error = (*(vp)->v_op->vop_addmap) 1773 (vp, off, as, addr, len, prot, maxprot, flags, cr, ct); 1774 1775 VOPSTATS_UPDATE(vp, addmap); 1776 return (error); 1777 } 1778 1779 int 1780 fop_delmap( 1781 vnode_t *vp, 1782 offset_t off, 1783 struct as *as, 1784 caddr_t addr, 1785 size_t len, 1786 uint_t prot, 1787 uint_t maxprot, 1788 uint_t flags, 1789 cred_t *cr, 1790 caller_context_t *ct) 1791 { 1792 int error; 1793 1794 VOPXID_MAP_CR(vp, cr); 1795 1796 error = (*(vp)->v_op->vop_delmap) 1797 (vp, off, as, addr, len, prot, maxprot, flags, cr, ct); 1798 1799 VOPSTATS_UPDATE(vp, delmap); 1800 return (error); 1801 } 1802 1803 1804 int 1805 fop_poll( 1806 vnode_t *vp, 1807 short events, 1808 int anyyet, 1809 short *reventsp, 1810 struct pollhead **phpp, 1811 caller_context_t *ct) 1812 { 1813 int err; 1814 1815 err = (*(vp)->v_op->vop_poll)(vp, events, anyyet, reventsp, phpp, ct); 1816 VOPSTATS_UPDATE(vp, poll); 1817 return (err); 1818 } 1819 1820 int 1821 fop_dump( 1822 vnode_t *vp, 1823 caddr_t addr, 1824 offset_t lbdn, 1825 offset_t dblks, 1826 caller_context_t *ct) 1827 { 1828 int err; 1829 1830 /* ensure lbdn and dblks can be passed safely to bdev_dump */ 1831 if ((lbdn != (daddr_t)lbdn) || (dblks != (int)dblks)) 1832 return (EIO); 1833 1834 err = (*(vp)->v_op->vop_dump)(vp, addr, lbdn, dblks, ct); 1835 VOPSTATS_UPDATE(vp, dump); 1836 return (err); 1837 } 1838 1839 int 1840 fop_pathconf( 1841 vnode_t *vp, 1842 int cmd, 1843 ulong_t *valp, 1844 cred_t *cr, 1845 caller_context_t *ct) 1846 { 1847 int err; 1848 1849 VOPXID_MAP_CR(vp, cr); 1850 1851 err = (*(vp)->v_op->vop_pathconf)(vp, cmd, valp, cr, ct); 1852 VOPSTATS_UPDATE(vp, pathconf); 1853 return (err); 1854 } 1855 1856 int 1857 fop_pageio( 1858 vnode_t *vp, 1859 struct page *pp, 1860 u_offset_t io_off, 1861 size_t io_len, 1862 int flags, 1863 cred_t *cr, 1864 caller_context_t *ct) 1865 { 1866 int err; 1867 1868 VOPXID_MAP_CR(vp, cr); 1869 1870 err = (*(vp)->v_op->vop_pageio)(vp, pp, io_off, io_len, flags, cr, ct); 1871 VOPSTATS_UPDATE(vp, pageio); 1872 return (err); 1873 } 1874 1875 int 1876 fop_dumpctl( 1877 vnode_t *vp, 1878 int action, 1879 offset_t *blkp, 1880 caller_context_t *ct) 1881 { 1882 int err; 1883 err = (*(vp)->v_op->vop_dumpctl)(vp, action, blkp, ct); 1884 VOPSTATS_UPDATE(vp, dumpctl); 1885 return (err); 1886 } 1887 1888 void 1889 fop_dispose( 1890 vnode_t *vp, 1891 page_t *pp, 1892 int flag, 1893 int dn, 1894 cred_t *cr, 1895 caller_context_t *ct) 1896 { 1897 /* Must do stats first since it's possible to lose the vnode */ 1898 VOPSTATS_UPDATE(vp, dispose); 1899 1900 VOPXID_MAP_CR(vp, cr); 1901 1902 (*(vp)->v_op->vop_dispose)(vp, pp, flag, dn, cr, ct); 1903 } 1904 1905 int 1906 fop_setsecattr( 1907 vnode_t *vp, 1908 vsecattr_t *vsap, 1909 int flag, 1910 cred_t *cr, 1911 caller_context_t *ct) 1912 { 1913 int err; 1914 1915 VOPXID_MAP_CR(vp, cr); 1916 1917 /* 1918 * We're only allowed to skip the ACL check iff we used a 32 bit 1919 * ACE mask with VOP_ACCESS() to determine permissions. 1920 */ 1921 if ((flag & ATTR_NOACLCHECK) && 1922 vfs_has_feature(vp->v_vfsp, VFSFT_ACEMASKONACCESS) == 0) { 1923 return (EINVAL); 1924 } 1925 err = (*(vp)->v_op->vop_setsecattr) (vp, vsap, flag, cr, ct); 1926 VOPSTATS_UPDATE(vp, setsecattr); 1927 return (err); 1928 } 1929 1930 int 1931 fop_getsecattr( 1932 vnode_t *vp, 1933 vsecattr_t *vsap, 1934 int flag, 1935 cred_t *cr, 1936 caller_context_t *ct) 1937 { 1938 int err; 1939 1940 /* 1941 * We're only allowed to skip the ACL check iff we used a 32 bit 1942 * ACE mask with VOP_ACCESS() to determine permissions. 1943 */ 1944 if ((flag & ATTR_NOACLCHECK) && 1945 vfs_has_feature(vp->v_vfsp, VFSFT_ACEMASKONACCESS) == 0) { 1946 return (EINVAL); 1947 } 1948 1949 VOPXID_MAP_CR(vp, cr); 1950 1951 err = (*(vp)->v_op->vop_getsecattr) (vp, vsap, flag, cr, ct); 1952 VOPSTATS_UPDATE(vp, getsecattr); 1953 return (err); 1954 } 1955 1956 int 1957 fop_shrlock( 1958 vnode_t *vp, 1959 int cmd, 1960 struct shrlock *shr, 1961 int flag, 1962 cred_t *cr, 1963 caller_context_t *ct) 1964 { 1965 int err; 1966 1967 VOPXID_MAP_CR(vp, cr); 1968 1969 err = (*(vp)->v_op->vop_shrlock)(vp, cmd, shr, flag, cr, ct); 1970 VOPSTATS_UPDATE(vp, shrlock); 1971 return (err); 1972 } 1973 1974 int 1975 fop_vnevent(vnode_t *vp, vnevent_t vnevent, vnode_t *dvp, char *fnm, 1976 caller_context_t *ct) 1977 { 1978 int err; 1979 1980 err = (*(vp)->v_op->vop_vnevent)(vp, vnevent, dvp, fnm, ct); 1981 VOPSTATS_UPDATE(vp, vnevent); 1982 return (err); 1983 } 1984 1985 // fop_reqzcbuf 1986 // fop_retzcbuf 1987 1988 // vsd_defaultdestructor 1989 // vsd_create, vsd_destroy 1990 // vsd_get, vsd_set 1991 // vsd_free, vsd_realloc 1992 1993 static int 1994 fs_reparse_mark(char *target, vattr_t *vap, xvattr_t *xvattr) 1995 { 1996 return (-1); 1997 } 1998 1999 /* 2000 * Function to check whether a symlink is a reparse point. 2001 * Return B_TRUE if it is a reparse point, else return B_FALSE 2002 */ 2003 boolean_t 2004 vn_is_reparse(vnode_t *vp, cred_t *cr, caller_context_t *ct) 2005 { 2006 xvattr_t xvattr; 2007 xoptattr_t *xoap; 2008 2009 if ((vp->v_type != VLNK) || 2010 !(vfs_has_feature(vp->v_vfsp, VFSFT_XVATTR))) 2011 return (B_FALSE); 2012 2013 xva_init(&xvattr); 2014 xoap = xva_getxoptattr(&xvattr); 2015 ASSERT(xoap); 2016 XVA_SET_REQ(&xvattr, XAT_REPARSE); 2017 2018 if (VOP_GETATTR(vp, &xvattr.xva_vattr, 0, cr, ct)) 2019 return (B_FALSE); 2020 2021 if ((!(xvattr.xva_vattr.va_mask & AT_XVATTR)) || 2022 (!(XVA_ISSET_RTN(&xvattr, XAT_REPARSE)))) 2023 return (B_FALSE); 2024 2025 return (xoap->xoa_reparse ? B_TRUE : B_FALSE); 2026 } 2027