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