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 2020 Joyent, Inc.
  25  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  26  * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
  27  * Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
  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 #include <sys/types.h>
  44 #include <sys/param.h>
 
 
 825 done:
 826         if (in_crit)
 827                 nbl_end_crit(vp);
 828         return (error);
 829 }
 830 
 831 /*
 832  * Release a vnode.  Call VOP_INACTIVE on last reference or
 833  * decrement reference count.
 834  *
 835  * To avoid race conditions, the v_count is left at 1 for
 836  * the call to VOP_INACTIVE. This prevents another thread
 837  * from reclaiming and releasing the vnode *before* the
 838  * VOP_INACTIVE routine has a chance to destroy the vnode.
 839  * We can't have more than 1 thread calling VOP_INACTIVE
 840  * on a vnode.
 841  */
 842 void
 843 vn_rele(vnode_t *vp)
 844 {
 845         VERIFY(vp->v_count > 0);
 846         mutex_enter(&vp->v_lock);
 847         if (vp->v_count == 1) {
 848                 mutex_exit(&vp->v_lock);
 849                 VOP_INACTIVE(vp, CRED(), NULL);
 850                 return;
 851         }
 852         VN_RELE_LOCKED(vp);
 853         mutex_exit(&vp->v_lock);
 854 }
 855 
 856 void
 857 vn_phantom_rele(vnode_t *vp)
 858 {
 859         VERIFY(vp->v_count > 0);
 860 
 861         mutex_enter(&vp->v_lock);
 862         VERIFY3U(vp->v_count, >=, vp->v_phantom_count);
 863         vp->v_phantom_count--;
 864         DTRACE_PROBE1(vn__phantom_rele, vnode_t *, vp);
 865         if (vp->v_count == 1) {
 866                 ASSERT0(vp->v_phantom_count);
 867                 mutex_exit(&vp->v_lock);
 868                 VOP_INACTIVE(vp, CRED(), NULL);
 869                 return;
 870         }
 871         VN_RELE_LOCKED(vp);
 872         mutex_exit(&vp->v_lock);
 873 }
 874 
 875 /*
 876  * Return the number of non-phantom holds. Things such as portfs will use
 877  * phantom holds to prevent it from blocking filesystems from mounting over
 878  * watched directories.
 879  */
 880 uint_t
 881 vn_count(vnode_t *vp)
 882 {
 883         ASSERT(MUTEX_HELD(&vp->v_lock));
 884         return (vp->v_count - vp->v_phantom_count);
 885 }
 886 
 887 /*
 888  * Release a vnode referenced by the DNLC. Multiple DNLC references are treated
 889  * as a single reference, so v_count is not decremented until the last DNLC hold
 890  * is released. This makes it possible to distinguish vnodes that are referenced
 891  * only by the DNLC.
 892  */
 893 void
 894 vn_rele_dnlc(vnode_t *vp)
 895 {
 896         VERIFY((vp->v_count > 0) && (vp->v_count_dnlc > 0));
 897         mutex_enter(&vp->v_lock);
 898         if (--vp->v_count_dnlc == 0) {
 899                 if (vp->v_count == 1) {
 900                         mutex_exit(&vp->v_lock);
 901                         VOP_INACTIVE(vp, CRED(), NULL);
 902                         return;
 903                 }
 904                 VN_RELE_LOCKED(vp);
 905         }
 906         mutex_exit(&vp->v_lock);
 907 }
 908 
 909 /*
 910  * Like vn_rele() except that it clears v_stream under v_lock.
 911  * This is used by sockfs when it dismantles the association between
 912  * the sockfs node and the vnode in the underlying file system.
 913  * v_lock has to be held to prevent a thread coming through the lookupname
 914  * path from accessing a stream head that is going away.
 915  */
 916 void
 917 vn_rele_stream(vnode_t *vp)
 918 {
 919         VERIFY(vp->v_count > 0);
 920         mutex_enter(&vp->v_lock);
 921         vp->v_stream = NULL;
 922         if (vp->v_count == 1) {
 923                 mutex_exit(&vp->v_lock);
 924                 VOP_INACTIVE(vp, CRED(), NULL);
 925                 return;
 926         }
 927         VN_RELE_LOCKED(vp);
 928         mutex_exit(&vp->v_lock);
 929 }
 930 
 931 static void
 932 vn_rele_inactive(vnode_t *vp)
 933 {
 934         VOP_INACTIVE(vp, CRED(), NULL);
 935 }
 936 
 937 /*
 938  * Like vn_rele() except if we are going to call VOP_INACTIVE() then do it
 939  * asynchronously using a taskq. This can avoid deadlocks caused by re-entering
 940  * the file system as a result of releasing the vnode. Note, file systems
 941  * already have to handle the race where the vnode is incremented before the
 942  * inactive routine is called and does its locking.
 943  *
 944  * Warning: Excessive use of this routine can lead to performance problems.
 945  * This is because taskqs throttle back allocation if too many are created.
 946  */
 947 void
 948 vn_rele_async(vnode_t *vp, taskq_t *taskq)
 949 {
 950         VERIFY(vp->v_count > 0);
 951         mutex_enter(&vp->v_lock);
 952         if (vp->v_count == 1) {
 953                 mutex_exit(&vp->v_lock);
 954                 VERIFY(taskq_dispatch(taskq, (task_func_t *)vn_rele_inactive,
 955                     vp, TQ_SLEEP) != TASKQID_INVALID);
 956                 return;
 957         }
 958         VN_RELE_LOCKED(vp);
 959         mutex_exit(&vp->v_lock);
 960 }
 961 
 962 int
 963 vn_open(
 964         char *pnamep,
 965         enum uio_seg seg,
 966         int filemode,
 967         int createmode,
 968         struct vnode **vpp,
 969         enum create crwhy,
 970         mode_t umask)
 971 {
 972         return (vn_openat(pnamep, seg, filemode, createmode, vpp, crwhy,
 973             umask, NULL, -1));
 974 }
 975 
 976 
 
 | 
 
 
   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 2020 Joyent, Inc.
  25  * Copyright 2022 Spencer Evans-Cole.
  26  * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  27  * Copyright (c) 2011, 2017 by Delphix. All rights reserved.
  28  * Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
  29  */
  30 
  31 /*      Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
  32 /*        All Rights Reserved   */
  33 
  34 /*
  35  * University Copyright- Copyright (c) 1982, 1986, 1988
  36  * The Regents of the University of California
  37  * All Rights Reserved
  38  *
  39  * University Acknowledgment- Portions of this document are derived from
  40  * software developed by the University of California, Berkeley, and its
  41  * contributors.
  42  */
  43 
  44 #include <sys/types.h>
  45 #include <sys/param.h>
 
 
 826 done:
 827         if (in_crit)
 828                 nbl_end_crit(vp);
 829         return (error);
 830 }
 831 
 832 /*
 833  * Release a vnode.  Call VOP_INACTIVE on last reference or
 834  * decrement reference count.
 835  *
 836  * To avoid race conditions, the v_count is left at 1 for
 837  * the call to VOP_INACTIVE. This prevents another thread
 838  * from reclaiming and releasing the vnode *before* the
 839  * VOP_INACTIVE routine has a chance to destroy the vnode.
 840  * We can't have more than 1 thread calling VOP_INACTIVE
 841  * on a vnode.
 842  */
 843 void
 844 vn_rele(vnode_t *vp)
 845 {
 846         mutex_enter(&vp->v_lock);
 847         if (vp->v_count == 1) {
 848                 mutex_exit(&vp->v_lock);
 849                 VOP_INACTIVE(vp, CRED(), NULL);
 850                 return;
 851         } else {
 852                 VERIFY(vp->v_count > 0);
 853         }
 854         VN_RELE_LOCKED(vp);
 855         mutex_exit(&vp->v_lock);
 856 }
 857 
 858 void
 859 vn_phantom_rele(vnode_t *vp)
 860 {
 861         mutex_enter(&vp->v_lock);
 862         VERIFY3U(vp->v_count, >=, vp->v_phantom_count);
 863         vp->v_phantom_count--;
 864         DTRACE_PROBE1(vn__phantom_rele, vnode_t *, vp);
 865         if (vp->v_count == 1) {
 866                 ASSERT0(vp->v_phantom_count);
 867                 mutex_exit(&vp->v_lock);
 868                 VOP_INACTIVE(vp, CRED(), NULL);
 869                 return;
 870         } else {
 871                 VERIFY(vp->v_count > 0);
 872         }
 873         VN_RELE_LOCKED(vp);
 874         mutex_exit(&vp->v_lock);
 875 }
 876 
 877 /*
 878  * Return the number of non-phantom holds. Things such as portfs will use
 879  * phantom holds to prevent it from blocking filesystems from mounting over
 880  * watched directories.
 881  */
 882 uint_t
 883 vn_count(vnode_t *vp)
 884 {
 885         ASSERT(MUTEX_HELD(&vp->v_lock));
 886         return (vp->v_count - vp->v_phantom_count);
 887 }
 888 
 889 /*
 890  * Release a vnode referenced by the DNLC. Multiple DNLC references are treated
 891  * as a single reference, so v_count is not decremented until the last DNLC hold
 892  * is released. This makes it possible to distinguish vnodes that are referenced
 893  * only by the DNLC.
 894  */
 895 void
 896 vn_rele_dnlc(vnode_t *vp)
 897 {
 898         mutex_enter(&vp->v_lock);
 899         VERIFY((vp->v_count > 0) && (vp->v_count_dnlc > 0));
 900         if (--vp->v_count_dnlc == 0) {
 901                 if (vp->v_count == 1) {
 902                         mutex_exit(&vp->v_lock);
 903                         VOP_INACTIVE(vp, CRED(), NULL);
 904                         return;
 905                 }
 906                 VN_RELE_LOCKED(vp);
 907         }
 908         mutex_exit(&vp->v_lock);
 909 }
 910 
 911 /*
 912  * Like vn_rele() except that it clears v_stream under v_lock.
 913  * This is used by sockfs when it dismantles the association between
 914  * the sockfs node and the vnode in the underlying file system.
 915  * v_lock has to be held to prevent a thread coming through the lookupname
 916  * path from accessing a stream head that is going away.
 917  */
 918 void
 919 vn_rele_stream(vnode_t *vp)
 920 {
 921         mutex_enter(&vp->v_lock);
 922         vp->v_stream = NULL;
 923         if (vp->v_count == 1) {
 924                 mutex_exit(&vp->v_lock);
 925                 VOP_INACTIVE(vp, CRED(), NULL);
 926                 return;
 927         } else {
 928                 VERIFY(vp->v_count > 0);
 929         }
 930         VN_RELE_LOCKED(vp);
 931         mutex_exit(&vp->v_lock);
 932 }
 933 
 934 static void
 935 vn_rele_inactive(vnode_t *vp)
 936 {
 937         VOP_INACTIVE(vp, CRED(), NULL);
 938 }
 939 
 940 /*
 941  * Like vn_rele() except if we are going to call VOP_INACTIVE() then do it
 942  * asynchronously using a taskq. This can avoid deadlocks caused by re-entering
 943  * the file system as a result of releasing the vnode. Note, file systems
 944  * already have to handle the race where the vnode is incremented before the
 945  * inactive routine is called and does its locking.
 946  *
 947  * Warning: Excessive use of this routine can lead to performance problems.
 948  * This is because taskqs throttle back allocation if too many are created.
 949  */
 950 void
 951 vn_rele_async(vnode_t *vp, taskq_t *taskq)
 952 {
 953         mutex_enter(&vp->v_lock);
 954         if (vp->v_count == 1) {
 955                 mutex_exit(&vp->v_lock);
 956                 VERIFY(taskq_dispatch(taskq, (task_func_t *)vn_rele_inactive,
 957                     vp, TQ_SLEEP) != TASKQID_INVALID);
 958                 return;
 959         } else {
 960                 VERIFY(vp->v_count > 0);
 961         }
 962         VN_RELE_LOCKED(vp);
 963         mutex_exit(&vp->v_lock);
 964 }
 965 
 966 int
 967 vn_open(
 968         char *pnamep,
 969         enum uio_seg seg,
 970         int filemode,
 971         int createmode,
 972         struct vnode **vpp,
 973         enum create crwhy,
 974         mode_t umask)
 975 {
 976         return (vn_openat(pnamep, seg, filemode, createmode, vpp, crwhy,
 977             umask, NULL, -1));
 978 }
 979 
 980 
 
 |