xref: /netbsd-src/sys/kern/vfs_cwd.c (revision 1cf06cb48d037e93ef7b2f28b43ae0873f3a90ba)
1 /*	$NetBSD: vfs_cwd.c,v 1.12 2024/12/07 02:11:42 riastradh Exp $	*/
2 
3 /*-
4  * Copyright (c) 2008, 2020, 2023 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /*
30  * Current working directory.
31  */
32 
33 #include <sys/cdefs.h>
34 __KERNEL_RCSID(0, "$NetBSD: vfs_cwd.c,v 1.12 2024/12/07 02:11:42 riastradh Exp $");
35 
36 #include <sys/param.h>
37 
38 #include <sys/atomic.h>
39 #include <sys/filedesc.h>
40 #include <sys/kmem.h>
41 #include <sys/proc.h>
42 #include <sys/vnode.h>
43 
44 /*
45  * Create an initial cwdinfo structure, using the same current and root
46  * directories as curproc.
47  */
48 struct cwdinfo *
49 cwdinit(void)
50 {
51 	struct cwdinfo *cwdi;
52 	struct cwdinfo *copy;
53 
54 	cwdi = kmem_alloc(sizeof(*cwdi), KM_SLEEP);
55 	KASSERT(ALIGNED_POINTER(cwdi, COHERENCY_UNIT));
56 	rw_init(&cwdi->cwdi_lock);
57 	copy = curproc->p_cwdi;
58 
59 	rw_enter(&copy->cwdi_lock, RW_READER);
60 	cwdi->cwdi_cdir = copy->cwdi_cdir;
61 	if (cwdi->cwdi_cdir)
62 		vref(cwdi->cwdi_cdir);
63 	cwdi->cwdi_rdir = copy->cwdi_rdir;
64 	if (cwdi->cwdi_rdir)
65 		vref(cwdi->cwdi_rdir);
66 	cwdi->cwdi_edir = copy->cwdi_edir;
67 	if (cwdi->cwdi_edir)
68 		vref(cwdi->cwdi_edir);
69 	rw_exit(&copy->cwdi_lock);
70 
71 	cwdi->cwdi_cmask = copy->cwdi_cmask;
72 	cwdi->cwdi_refcnt = 1;
73 
74 	return cwdi;
75 }
76 
77 /*
78  * Make p2 share p1's cwdinfo.
79  */
80 void
81 cwdshare(struct proc *p2)
82 {
83 	struct cwdinfo *cwdi;
84 
85 	cwdi = curproc->p_cwdi;
86 
87 	atomic_inc_uint(&cwdi->cwdi_refcnt);
88 	p2->p_cwdi = cwdi;
89 }
90 
91 /*
92  * Make sure proc has only one reference to its cwdi, creating
93  * a new one if necessary.
94  */
95 void
96 cwdunshare(struct proc *p)
97 {
98 	struct cwdinfo *cwdi = p->p_cwdi;
99 
100 	if (cwdi->cwdi_refcnt > 1) {
101 		cwdi = cwdinit();
102 		cwdfree(p->p_cwdi);
103 		p->p_cwdi = cwdi;
104 	}
105 }
106 
107 /*
108  * Release a cwdinfo structure.
109  */
110 void
111 cwdfree(struct cwdinfo *cwdi)
112 {
113 
114 	membar_release();
115 	if (atomic_dec_uint_nv(&cwdi->cwdi_refcnt) > 0)
116 		return;
117 	membar_acquire();
118 
119 	vrele(cwdi->cwdi_cdir);
120 	rw_destroy(&cwdi->cwdi_lock);
121 	if (cwdi->cwdi_rdir)
122 		vrele(cwdi->cwdi_rdir);
123 	if (cwdi->cwdi_edir)
124 		vrele(cwdi->cwdi_edir);
125 	kmem_free(cwdi, sizeof(*cwdi));
126 }
127 
128 void
129 cwdexec(struct proc *p)
130 {
131 
132 	cwdunshare(p);
133 
134 	if (p->p_cwdi->cwdi_edir) {
135 		vrele(p->p_cwdi->cwdi_edir);
136 	}
137 }
138