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
|