xref: /netbsd-src/sys/kern/vfs_cwd.c (revision ccd9df534e375a4366c5b55f23782053c7a98d82)
1 /*	$NetBSD: vfs_cwd.c,v 1.11 2023/09/23 18:21:11 ad 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.11 2023/09/23 18:21:11 ad Exp $");
35 
36 #include <sys/param.h>
37 #include <sys/atomic.h>
38 #include <sys/filedesc.h>
39 #include <sys/proc.h>
40 #include <sys/vnode.h>
41 #include <sys/kmem.h>
42 
43 /*
44  * Create an initial cwdinfo structure, using the same current and root
45  * directories as curproc.
46  */
47 struct cwdinfo *
48 cwdinit(void)
49 {
50 	struct cwdinfo *cwdi;
51 	struct cwdinfo *copy;
52 
53 	cwdi = kmem_alloc(sizeof(*cwdi), KM_SLEEP);
54 	KASSERT(ALIGNED_POINTER(cwdi, COHERENCY_UNIT));
55 	rw_init(&cwdi->cwdi_lock);
56 	copy = curproc->p_cwdi;
57 
58 	rw_enter(&copy->cwdi_lock, RW_READER);
59 	cwdi->cwdi_cdir = copy->cwdi_cdir;
60 	if (cwdi->cwdi_cdir)
61 		vref(cwdi->cwdi_cdir);
62 	cwdi->cwdi_rdir = copy->cwdi_rdir;
63 	if (cwdi->cwdi_rdir)
64 		vref(cwdi->cwdi_rdir);
65 	cwdi->cwdi_edir = copy->cwdi_edir;
66 	if (cwdi->cwdi_edir)
67 		vref(cwdi->cwdi_edir);
68 	rw_exit(&copy->cwdi_lock);
69 
70 	cwdi->cwdi_cmask = copy->cwdi_cmask;
71 	cwdi->cwdi_refcnt = 1;
72 
73 	return (cwdi);
74 }
75 
76 /*
77  * Make p2 share p1's cwdinfo.
78  */
79 void
80 cwdshare(struct proc *p2)
81 {
82 	struct cwdinfo *cwdi;
83 
84 	cwdi = curproc->p_cwdi;
85 
86 	atomic_inc_uint(&cwdi->cwdi_refcnt);
87 	p2->p_cwdi = cwdi;
88 }
89 
90 /*
91  * Make sure proc has only one reference to its cwdi, creating
92  * a new one if necessary.
93  */
94 void
95 cwdunshare(struct proc *p)
96 {
97 	struct cwdinfo *cwdi = p->p_cwdi;
98 
99 	if (cwdi->cwdi_refcnt > 1) {
100 		cwdi = cwdinit();
101 		cwdfree(p->p_cwdi);
102 		p->p_cwdi = cwdi;
103 	}
104 }
105 
106 /*
107  * Release a cwdinfo structure.
108  */
109 void
110 cwdfree(struct cwdinfo *cwdi)
111 {
112 
113 	membar_release();
114 	if (atomic_dec_uint_nv(&cwdi->cwdi_refcnt) > 0)
115 		return;
116 	membar_acquire();
117 
118 	vrele(cwdi->cwdi_cdir);
119 	rw_destroy(&cwdi->cwdi_lock);
120 	if (cwdi->cwdi_rdir)
121 		vrele(cwdi->cwdi_rdir);
122 	if (cwdi->cwdi_edir)
123 		vrele(cwdi->cwdi_edir);
124 	kmem_free(cwdi, sizeof(*cwdi));
125 }
126 
127 void
128 cwdexec(struct proc *p)
129 {
130 
131 	cwdunshare(p);
132 
133 	if (p->p_cwdi->cwdi_edir) {
134 		vrele(p->p_cwdi->cwdi_edir);
135 	}
136 }
137