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 */
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 #include <sys/types.h>
43 #include <sys/param.h>
44 #include <sys/t_lock.h>
820 done:
821 if (in_crit)
822 nbl_end_crit(vp);
823 return (error);
824 }
825
826 /*
827 * Release a vnode. Call VOP_INACTIVE on last reference or
828 * decrement reference count.
829 *
830 * To avoid race conditions, the v_count is left at 1 for
831 * the call to VOP_INACTIVE. This prevents another thread
832 * from reclaiming and releasing the vnode *before* the
833 * VOP_INACTIVE routine has a chance to destroy the vnode.
834 * We can't have more than 1 thread calling VOP_INACTIVE
835 * on a vnode.
836 */
837 void
838 vn_rele(vnode_t *vp)
839 {
840 VERIFY(vp->v_count > 0);
841 mutex_enter(&vp->v_lock);
842 if (vp->v_count == 1) {
843 mutex_exit(&vp->v_lock);
844 VOP_INACTIVE(vp, CRED(), NULL);
845 return;
846 }
847 VN_RELE_LOCKED(vp);
848 mutex_exit(&vp->v_lock);
849 }
850
851 /*
852 * Release a vnode referenced by the DNLC. Multiple DNLC references are treated
853 * as a single reference, so v_count is not decremented until the last DNLC hold
854 * is released. This makes it possible to distinguish vnodes that are referenced
855 * only by the DNLC.
856 */
857 void
858 vn_rele_dnlc(vnode_t *vp)
859 {
860 VERIFY((vp->v_count > 0) && (vp->v_count_dnlc > 0));
861 mutex_enter(&vp->v_lock);
862 if (--vp->v_count_dnlc == 0) {
863 if (vp->v_count == 1) {
864 mutex_exit(&vp->v_lock);
865 VOP_INACTIVE(vp, CRED(), NULL);
866 return;
867 }
868 VN_RELE_LOCKED(vp);
869 }
870 mutex_exit(&vp->v_lock);
871 }
872
873 /*
874 * Like vn_rele() except that it clears v_stream under v_lock.
875 * This is used by sockfs when it dismantles the association between
876 * the sockfs node and the vnode in the underlying file system.
877 * v_lock has to be held to prevent a thread coming through the lookupname
878 * path from accessing a stream head that is going away.
879 */
880 void
881 vn_rele_stream(vnode_t *vp)
882 {
883 VERIFY(vp->v_count > 0);
884 mutex_enter(&vp->v_lock);
885 vp->v_stream = NULL;
886 if (vp->v_count == 1) {
887 mutex_exit(&vp->v_lock);
888 VOP_INACTIVE(vp, CRED(), NULL);
889 return;
890 }
891 VN_RELE_LOCKED(vp);
892 mutex_exit(&vp->v_lock);
893 }
894
895 static void
896 vn_rele_inactive(vnode_t *vp)
897 {
898 VOP_INACTIVE(vp, CRED(), NULL);
899 }
900
901 /*
902 * Like vn_rele() except if we are going to call VOP_INACTIVE() then do it
903 * asynchronously using a taskq. This can avoid deadlocks caused by re-entering
904 * the file system as a result of releasing the vnode. Note, file systems
905 * already have to handle the race where the vnode is incremented before the
906 * inactive routine is called and does its locking.
907 *
908 * Warning: Excessive use of this routine can lead to performance problems.
909 * This is because taskqs throttle back allocation if too many are created.
910 */
911 void
912 vn_rele_async(vnode_t *vp, taskq_t *taskq)
913 {
914 VERIFY(vp->v_count > 0);
915 mutex_enter(&vp->v_lock);
916 if (vp->v_count == 1) {
917 mutex_exit(&vp->v_lock);
918 VERIFY(taskq_dispatch(taskq, (task_func_t *)vn_rele_inactive,
919 vp, TQ_SLEEP) != TASKQID_INVALID);
920 return;
921 }
922 VN_RELE_LOCKED(vp);
923 mutex_exit(&vp->v_lock);
924 }
925
926 int
927 vn_open(
928 char *pnamep,
929 enum uio_seg seg,
930 int filemode,
931 int createmode,
932 struct vnode **vpp,
933 enum create crwhy,
934 mode_t umask)
935 {
936 return (vn_openat(pnamep, seg, filemode, createmode, vpp, crwhy,
937 umask, NULL, -1));
938 }
939
940
|
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 */
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>
45 #include <sys/t_lock.h>
821 done:
822 if (in_crit)
823 nbl_end_crit(vp);
824 return (error);
825 }
826
827 /*
828 * Release a vnode. Call VOP_INACTIVE on last reference or
829 * decrement reference count.
830 *
831 * To avoid race conditions, the v_count is left at 1 for
832 * the call to VOP_INACTIVE. This prevents another thread
833 * from reclaiming and releasing the vnode *before* the
834 * VOP_INACTIVE routine has a chance to destroy the vnode.
835 * We can't have more than 1 thread calling VOP_INACTIVE
836 * on a vnode.
837 */
838 void
839 vn_rele(vnode_t *vp)
840 {
841 mutex_enter(&vp->v_lock);
842 if (vp->v_count == 1) {
843 mutex_exit(&vp->v_lock);
844 VOP_INACTIVE(vp, CRED(), NULL);
845 return;
846 } else {
847 VERIFY(vp->v_count > 0);
848 }
849 VN_RELE_LOCKED(vp);
850 mutex_exit(&vp->v_lock);
851 }
852
853 /*
854 * Release a vnode referenced by the DNLC. Multiple DNLC references are treated
855 * as a single reference, so v_count is not decremented until the last DNLC hold
856 * is released. This makes it possible to distinguish vnodes that are referenced
857 * only by the DNLC.
858 */
859 void
860 vn_rele_dnlc(vnode_t *vp)
861 {
862 mutex_enter(&vp->v_lock);
863 VERIFY((vp->v_count > 0) && (vp->v_count_dnlc > 0));
864 if (--vp->v_count_dnlc == 0) {
865 if (vp->v_count == 1) {
866 mutex_exit(&vp->v_lock);
867 VOP_INACTIVE(vp, CRED(), NULL);
868 return;
869 }
870 VN_RELE_LOCKED(vp);
871 }
872 mutex_exit(&vp->v_lock);
873 }
874
875 /*
876 * Like vn_rele() except that it clears v_stream under v_lock.
877 * This is used by sockfs when it dismantles the association between
878 * the sockfs node and the vnode in the underlying file system.
879 * v_lock has to be held to prevent a thread coming through the lookupname
880 * path from accessing a stream head that is going away.
881 */
882 void
883 vn_rele_stream(vnode_t *vp)
884 {
885 mutex_enter(&vp->v_lock);
886 vp->v_stream = NULL;
887 if (vp->v_count == 1) {
888 mutex_exit(&vp->v_lock);
889 VOP_INACTIVE(vp, CRED(), NULL);
890 return;
891 } else {
892 VERIFY(vp->v_count > 0);
893 }
894 VN_RELE_LOCKED(vp);
895 mutex_exit(&vp->v_lock);
896 }
897
898 static void
899 vn_rele_inactive(vnode_t *vp)
900 {
901 VOP_INACTIVE(vp, CRED(), NULL);
902 }
903
904 /*
905 * Like vn_rele() except if we are going to call VOP_INACTIVE() then do it
906 * asynchronously using a taskq. This can avoid deadlocks caused by re-entering
907 * the file system as a result of releasing the vnode. Note, file systems
908 * already have to handle the race where the vnode is incremented before the
909 * inactive routine is called and does its locking.
910 *
911 * Warning: Excessive use of this routine can lead to performance problems.
912 * This is because taskqs throttle back allocation if too many are created.
913 */
914 void
915 vn_rele_async(vnode_t *vp, taskq_t *taskq)
916 {
917 mutex_enter(&vp->v_lock);
918 if (vp->v_count == 1) {
919 mutex_exit(&vp->v_lock);
920 VERIFY(taskq_dispatch(taskq, (task_func_t *)vn_rele_inactive,
921 vp, TQ_SLEEP) != TASKQID_INVALID);
922 return;
923 } else {
924 VERIFY(vp->v_count > 0);
925 }
926 VN_RELE_LOCKED(vp);
927 mutex_exit(&vp->v_lock);
928 }
929
930 int
931 vn_open(
932 char *pnamep,
933 enum uio_seg seg,
934 int filemode,
935 int createmode,
936 struct vnode **vpp,
937 enum create crwhy,
938 mode_t umask)
939 {
940 return (vn_openat(pnamep, seg, filemode, createmode, vpp, crwhy,
941 umask, NULL, -1));
942 }
943
944
|