Mon Apr 20 13:30:34 2020 UTC ()
Add missing include of <sys/atomic.h> to fix the build


(martin)
diff -r1.81 -r1.82 src/sys/miscfs/procfs/procfs_linux.c

cvs diff -r1.81 -r1.82 src/sys/miscfs/procfs/procfs_linux.c (switch to unified diff)

--- src/sys/miscfs/procfs/procfs_linux.c 2020/04/19 20:31:59 1.81
+++ src/sys/miscfs/procfs/procfs_linux.c 2020/04/20 13:30:34 1.82
@@ -1,741 +1,742 @@ @@ -1,741 +1,742 @@
1/* $NetBSD: procfs_linux.c,v 1.81 2020/04/19 20:31:59 thorpej Exp $ */ 1/* $NetBSD: procfs_linux.c,v 1.82 2020/04/20 13:30:34 martin Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001 Wasabi Systems, Inc. 4 * Copyright (c) 2001 Wasabi Systems, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Written by Frank van der Linden for Wasabi Systems, Inc. 7 * Written by Frank van der Linden for Wasabi Systems, Inc.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the 15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution. 16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software 17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement: 18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by 19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc. 20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior 22 * or promote products derived from this software without specific prior
23 * written permission. 23 * written permission.
24 * 24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE. 35 * POSSIBILITY OF SUCH DAMAGE.
36 */ 36 */
37 37
38#include <sys/cdefs.h> 38#include <sys/cdefs.h>
39__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.81 2020/04/19 20:31:59 thorpej Exp $"); 39__KERNEL_RCSID(0, "$NetBSD: procfs_linux.c,v 1.82 2020/04/20 13:30:34 martin Exp $");
40 40
41#include <sys/param.h> 41#include <sys/param.h>
42#include <sys/systm.h> 42#include <sys/systm.h>
 43#include <sys/atomic.h>
43#include <sys/time.h> 44#include <sys/time.h>
44#include <sys/cpu.h> 45#include <sys/cpu.h>
45#include <sys/kernel.h> 46#include <sys/kernel.h>
46#include <sys/proc.h> 47#include <sys/proc.h>
47#include <sys/vnode.h> 48#include <sys/vnode.h>
48#include <sys/exec.h> 49#include <sys/exec.h>
49#include <sys/resource.h> 50#include <sys/resource.h>
50#include <sys/resourcevar.h> 51#include <sys/resourcevar.h>
51#include <sys/signal.h> 52#include <sys/signal.h>
52#include <sys/signalvar.h> 53#include <sys/signalvar.h>
53#include <sys/tty.h> 54#include <sys/tty.h>
54#include <sys/malloc.h> 55#include <sys/malloc.h>
55#include <sys/mount.h> 56#include <sys/mount.h>
56#include <sys/conf.h> 57#include <sys/conf.h>
57#include <sys/sysctl.h> 58#include <sys/sysctl.h>
58#include <sys/kauth.h> 59#include <sys/kauth.h>
59#include <sys/filedesc.h> 60#include <sys/filedesc.h>
60 61
61#include <miscfs/procfs/procfs.h> 62#include <miscfs/procfs/procfs.h>
62 63
63#include <compat/linux/common/linux_exec.h> 64#include <compat/linux/common/linux_exec.h>
64#include <compat/linux32/common/linux32_sysctl.h> 65#include <compat/linux32/common/linux32_sysctl.h>
65 66
66#include <uvm/uvm_extern.h> 67#include <uvm/uvm_extern.h>
67#include <uvm/uvm.h> 68#include <uvm/uvm.h>
68 69
69extern struct devsw_conv *devsw_conv; 70extern struct devsw_conv *devsw_conv;
70extern int max_devsw_convs; 71extern int max_devsw_convs;
71 72
72#define PGTOB(p) ((unsigned long)(p) << PAGE_SHIFT) 73#define PGTOB(p) ((unsigned long)(p) << PAGE_SHIFT)
73#define PGTOKB(p) ((unsigned long)(p) << (PAGE_SHIFT - 10)) 74#define PGTOKB(p) ((unsigned long)(p) << (PAGE_SHIFT - 10))
74 75
75#define LBFSZ (8 * 1024) 76#define LBFSZ (8 * 1024)
76 77
77static void 78static void
78get_proc_size_info(struct proc *p, struct vm_map *map, unsigned long *stext, 79get_proc_size_info(struct proc *p, struct vm_map *map, unsigned long *stext,
79 unsigned long *etext, unsigned long *sstack) 80 unsigned long *etext, unsigned long *sstack)
80{ 81{
81 struct vm_map_entry *entry; 82 struct vm_map_entry *entry;
82 83
83 *stext = 0; 84 *stext = 0;
84 *etext = 0; 85 *etext = 0;
85 *sstack = 0; 86 *sstack = 0;
86 87
87 vm_map_lock_read(map); 88 vm_map_lock_read(map);
88 89
89 for (entry = map->header.next; entry != &map->header; 90 for (entry = map->header.next; entry != &map->header;
90 entry = entry->next) { 91 entry = entry->next) {
91 if (UVM_ET_ISSUBMAP(entry)) 92 if (UVM_ET_ISSUBMAP(entry))
92 continue; 93 continue;
93 /* assume text is the first entry */ 94 /* assume text is the first entry */
94 if (*stext == *etext) { 95 if (*stext == *etext) {
95 *stext = entry->start; 96 *stext = entry->start;
96 *etext = entry->end; 97 *etext = entry->end;
97 break; 98 break;
98 } 99 }
99 } 100 }
100#if defined(LINUX_USRSTACK32) && defined(USRSTACK32) 101#if defined(LINUX_USRSTACK32) && defined(USRSTACK32)
101 if (strcmp(p->p_emul->e_name, "linux32") == 0 && 102 if (strcmp(p->p_emul->e_name, "linux32") == 0 &&
102 LINUX_USRSTACK32 < USRSTACK32) 103 LINUX_USRSTACK32 < USRSTACK32)
103 *sstack = (unsigned long)LINUX_USRSTACK32; 104 *sstack = (unsigned long)LINUX_USRSTACK32;
104 else 105 else
105#endif 106#endif
106#ifdef LINUX_USRSTACK 107#ifdef LINUX_USRSTACK
107 if (strcmp(p->p_emul->e_name, "linux") == 0 && 108 if (strcmp(p->p_emul->e_name, "linux") == 0 &&
108 LINUX_USRSTACK < USRSTACK) 109 LINUX_USRSTACK < USRSTACK)
109 *sstack = (unsigned long)LINUX_USRSTACK; 110 *sstack = (unsigned long)LINUX_USRSTACK;
110 else 111 else
111#endif 112#endif
112#ifdef USRSTACK32 113#ifdef USRSTACK32
113 if (strstr(p->p_emul->e_name, "32") != NULL) 114 if (strstr(p->p_emul->e_name, "32") != NULL)
114 *sstack = (unsigned long)USRSTACK32; 115 *sstack = (unsigned long)USRSTACK32;
115 else 116 else
116#endif 117#endif
117 *sstack = (unsigned long)USRSTACK; 118 *sstack = (unsigned long)USRSTACK;
118 119
119 /* 120 /*
120 * jdk 1.6 compares low <= addr && addr < high 121 * jdk 1.6 compares low <= addr && addr < high
121 * if we put addr == high, then the test fails 122 * if we put addr == high, then the test fails
122 * so eat one page. 123 * so eat one page.
123 */ 124 */
124 *sstack -= PAGE_SIZE; 125 *sstack -= PAGE_SIZE;
125 126
126 vm_map_unlock_read(map); 127 vm_map_unlock_read(map);
127} 128}
128 129
129/* 130/*
130 * Linux compatible /proc/meminfo. Only active when the -o linux 131 * Linux compatible /proc/meminfo. Only active when the -o linux
131 * mountflag is used. 132 * mountflag is used.
132 */ 133 */
133int 134int
134procfs_domeminfo(struct lwp *curl, struct proc *p, 135procfs_domeminfo(struct lwp *curl, struct proc *p,
135 struct pfsnode *pfs, struct uio *uio) 136 struct pfsnode *pfs, struct uio *uio)
136{ 137{
137 char *bf; 138 char *bf;
138 int len; 139 int len;
139 int error = 0; 140 int error = 0;
140 long filepg, anonpg, execpg, freepg; 141 long filepg, anonpg, execpg, freepg;
141 142
142 bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 143 bf = malloc(LBFSZ, M_TEMP, M_WAITOK);
143 144
144 cpu_count_sync_all(); 145 cpu_count_sync_all();
145 freepg = (long)uvm_availmem(); 146 freepg = (long)uvm_availmem();
146 filepg = (long)cpu_count_get(CPU_COUNT_FILEPAGES); 147 filepg = (long)cpu_count_get(CPU_COUNT_FILEPAGES);
147 anonpg = (long)cpu_count_get(CPU_COUNT_ANONPAGES); 148 anonpg = (long)cpu_count_get(CPU_COUNT_ANONPAGES);
148 execpg = (long)cpu_count_get(CPU_COUNT_EXECPAGES); 149 execpg = (long)cpu_count_get(CPU_COUNT_EXECPAGES);
149 150
150 len = snprintf(bf, LBFSZ, 151 len = snprintf(bf, LBFSZ,
151 " total: used: free: shared: buffers: cached:\n" 152 " total: used: free: shared: buffers: cached:\n"
152 "Mem: %8lu %8lu %8lu %8lu %8lu %8lu\n" 153 "Mem: %8lu %8lu %8lu %8lu %8lu %8lu\n"
153 "Swap: %8lu %8lu %8lu\n" 154 "Swap: %8lu %8lu %8lu\n"
154 "MemTotal: %8lu kB\n" 155 "MemTotal: %8lu kB\n"
155 "MemFree: %8lu kB\n" 156 "MemFree: %8lu kB\n"
156 "MemShared: %8lu kB\n" 157 "MemShared: %8lu kB\n"
157 "Buffers: %8lu kB\n" 158 "Buffers: %8lu kB\n"
158 "Cached: %8lu kB\n" 159 "Cached: %8lu kB\n"
159 "SwapTotal: %8lu kB\n" 160 "SwapTotal: %8lu kB\n"
160 "SwapFree: %8lu kB\n", 161 "SwapFree: %8lu kB\n",
161 PGTOB(uvmexp.npages), 162 PGTOB(uvmexp.npages),
162 PGTOB(uvmexp.npages - freepg), 163 PGTOB(uvmexp.npages - freepg),
163 PGTOB(freepg), 164 PGTOB(freepg),
164 0L, 165 0L,
165 PGTOB(filepg), 166 PGTOB(filepg),
166 PGTOB(anonpg + filepg + execpg), 167 PGTOB(anonpg + filepg + execpg),
167 PGTOB(uvmexp.swpages), 168 PGTOB(uvmexp.swpages),
168 PGTOB(uvmexp.swpginuse), 169 PGTOB(uvmexp.swpginuse),
169 PGTOB(uvmexp.swpages - uvmexp.swpginuse), 170 PGTOB(uvmexp.swpages - uvmexp.swpginuse),
170 PGTOKB(uvmexp.npages), 171 PGTOKB(uvmexp.npages),
171 PGTOKB(freepg), 172 PGTOKB(freepg),
172 0L, 173 0L,
173 PGTOKB(freepg), 174 PGTOKB(freepg),
174 PGTOKB(anonpg + filepg + execpg), 175 PGTOKB(anonpg + filepg + execpg),
175 PGTOKB(uvmexp.swpages), 176 PGTOKB(uvmexp.swpages),
176 PGTOKB(uvmexp.swpages - uvmexp.swpginuse)); 177 PGTOKB(uvmexp.swpages - uvmexp.swpginuse));
177 178
178 if (len == 0) 179 if (len == 0)
179 goto out; 180 goto out;
180 181
181 error = uiomove_frombuf(bf, len, uio); 182 error = uiomove_frombuf(bf, len, uio);
182out: 183out:
183 free(bf, M_TEMP); 184 free(bf, M_TEMP);
184 return error; 185 return error;
185} 186}
186 187
187/* 188/*
188 * Linux compatible /proc/devices. Only active when the -o linux 189 * Linux compatible /proc/devices. Only active when the -o linux
189 * mountflag is used. 190 * mountflag is used.
190 */ 191 */
191int 192int
192procfs_dodevices(struct lwp *curl, struct proc *p, 193procfs_dodevices(struct lwp *curl, struct proc *p,
193 struct pfsnode *pfs, struct uio *uio) 194 struct pfsnode *pfs, struct uio *uio)
194{ 195{
195 char *bf; 196 char *bf;
196 int offset = 0; 197 int offset = 0;
197 int i, error = ENAMETOOLONG; 198 int i, error = ENAMETOOLONG;
198 199
199 /* XXX elad - may need filtering. */ 200 /* XXX elad - may need filtering. */
200 201
201 bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 202 bf = malloc(LBFSZ, M_TEMP, M_WAITOK);
202 203
203 offset += snprintf(&bf[offset], LBFSZ - offset, "Character devices:\n"); 204 offset += snprintf(&bf[offset], LBFSZ - offset, "Character devices:\n");
204 if (offset >= LBFSZ) 205 if (offset >= LBFSZ)
205 goto out; 206 goto out;
206 207
207 mutex_enter(&device_lock); 208 mutex_enter(&device_lock);
208 for (i = 0; i < max_devsw_convs; i++) { 209 for (i = 0; i < max_devsw_convs; i++) {
209 if ((devsw_conv[i].d_name == NULL) ||  210 if ((devsw_conv[i].d_name == NULL) ||
210 (devsw_conv[i].d_cmajor == -1)) 211 (devsw_conv[i].d_cmajor == -1))
211 continue; 212 continue;
212 213
213 offset += snprintf(&bf[offset], LBFSZ - offset,  214 offset += snprintf(&bf[offset], LBFSZ - offset,
214 "%3d %s\n", devsw_conv[i].d_cmajor, devsw_conv[i].d_name); 215 "%3d %s\n", devsw_conv[i].d_cmajor, devsw_conv[i].d_name);
215 if (offset >= LBFSZ) { 216 if (offset >= LBFSZ) {
216 mutex_exit(&device_lock); 217 mutex_exit(&device_lock);
217 goto out; 218 goto out;
218 } 219 }
219 } 220 }
220 221
221 offset += snprintf(&bf[offset], LBFSZ - offset, "\nBlock devices:\n"); 222 offset += snprintf(&bf[offset], LBFSZ - offset, "\nBlock devices:\n");
222 if (offset >= LBFSZ) { 223 if (offset >= LBFSZ) {
223 mutex_exit(&device_lock); 224 mutex_exit(&device_lock);
224 goto out; 225 goto out;
225 } 226 }
226 227
227 for (i = 0; i < max_devsw_convs; i++) { 228 for (i = 0; i < max_devsw_convs; i++) {
228 if ((devsw_conv[i].d_name == NULL) ||  229 if ((devsw_conv[i].d_name == NULL) ||
229 (devsw_conv[i].d_bmajor == -1)) 230 (devsw_conv[i].d_bmajor == -1))
230 continue; 231 continue;
231 232
232 offset += snprintf(&bf[offset], LBFSZ - offset,  233 offset += snprintf(&bf[offset], LBFSZ - offset,
233 "%3d %s\n", devsw_conv[i].d_bmajor, devsw_conv[i].d_name); 234 "%3d %s\n", devsw_conv[i].d_bmajor, devsw_conv[i].d_name);
234 if (offset >= LBFSZ) { 235 if (offset >= LBFSZ) {
235 mutex_exit(&device_lock); 236 mutex_exit(&device_lock);
236 goto out; 237 goto out;
237 } 238 }
238 } 239 }
239 mutex_exit(&device_lock); 240 mutex_exit(&device_lock);
240 241
241 error = uiomove_frombuf(bf, offset, uio); 242 error = uiomove_frombuf(bf, offset, uio);
242out: 243out:
243 free(bf, M_TEMP); 244 free(bf, M_TEMP);
244 return error; 245 return error;
245} 246}
246 247
247/* 248/*
248 * Linux compatible /proc/stat. Only active when the -o linux 249 * Linux compatible /proc/stat. Only active when the -o linux
249 * mountflag is used. 250 * mountflag is used.
250 */ 251 */
251int 252int
252procfs_docpustat(struct lwp *curl, struct proc *p, 253procfs_docpustat(struct lwp *curl, struct proc *p,
253 struct pfsnode *pfs, struct uio *uio) 254 struct pfsnode *pfs, struct uio *uio)
254{ 255{
255 char *bf; 256 char *bf;
256 int error; 257 int error;
257 int len; 258 int len;
258#if defined(MULTIPROCESSOR) 259#if defined(MULTIPROCESSOR)
259 struct cpu_info *ci; 260 struct cpu_info *ci;
260 CPU_INFO_ITERATOR cii; 261 CPU_INFO_ITERATOR cii;
261#endif 262#endif
262 int i; 263 int i;
263 264
264 error = ENAMETOOLONG; 265 error = ENAMETOOLONG;
265 bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 266 bf = malloc(LBFSZ, M_TEMP, M_WAITOK);
266 267
267 len = snprintf(bf, LBFSZ, 268 len = snprintf(bf, LBFSZ,
268 "cpu %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", 269 "cpu %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
269 curcpu()->ci_schedstate.spc_cp_time[CP_USER], 270 curcpu()->ci_schedstate.spc_cp_time[CP_USER],
270 curcpu()->ci_schedstate.spc_cp_time[CP_NICE], 271 curcpu()->ci_schedstate.spc_cp_time[CP_NICE],
271 curcpu()->ci_schedstate.spc_cp_time[CP_SYS] /*+ [CP_INTR]*/, 272 curcpu()->ci_schedstate.spc_cp_time[CP_SYS] /*+ [CP_INTR]*/,
272 curcpu()->ci_schedstate.spc_cp_time[CP_IDLE]); 273 curcpu()->ci_schedstate.spc_cp_time[CP_IDLE]);
273 if (len == 0) 274 if (len == 0)
274 goto out; 275 goto out;
275 276
276#if defined(MULTIPROCESSOR) 277#if defined(MULTIPROCESSOR)
277#define ALLCPUS CPU_INFO_FOREACH(cii, ci) 278#define ALLCPUS CPU_INFO_FOREACH(cii, ci)
278#define CPUNAME ci 279#define CPUNAME ci
279#else 280#else
280#define ALLCPUS ; i < 1 ; 281#define ALLCPUS ; i < 1 ;
281#define CPUNAME curcpu() 282#define CPUNAME curcpu()
282#endif 283#endif
283 284
284 i = 0; 285 i = 0;
285 for (ALLCPUS) { 286 for (ALLCPUS) {
286 len += snprintf(&bf[len], LBFSZ - len,  287 len += snprintf(&bf[len], LBFSZ - len,
287 "cpu%d %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 288 "cpu%d %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64
288 "\n", i, 289 "\n", i,
289 CPUNAME->ci_schedstate.spc_cp_time[CP_USER], 290 CPUNAME->ci_schedstate.spc_cp_time[CP_USER],
290 CPUNAME->ci_schedstate.spc_cp_time[CP_NICE], 291 CPUNAME->ci_schedstate.spc_cp_time[CP_NICE],
291 CPUNAME->ci_schedstate.spc_cp_time[CP_SYS], 292 CPUNAME->ci_schedstate.spc_cp_time[CP_SYS],
292 CPUNAME->ci_schedstate.spc_cp_time[CP_IDLE]); 293 CPUNAME->ci_schedstate.spc_cp_time[CP_IDLE]);
293 if (len >= LBFSZ) 294 if (len >= LBFSZ)
294 goto out; 295 goto out;
295 i += 1; 296 i += 1;
296 } 297 }
297 298
298 cpu_count_sync_all(); 299 cpu_count_sync_all();
299 300
300 struct timeval btv; 301 struct timeval btv;
301 getmicroboottime(&btv); 302 getmicroboottime(&btv);
302 303
303 len += snprintf(&bf[len], LBFSZ - len, 304 len += snprintf(&bf[len], LBFSZ - len,
304 "disk 0 0 0 0\n" 305 "disk 0 0 0 0\n"
305 "page %u %u\n" 306 "page %u %u\n"
306 "swap %u %u\n" 307 "swap %u %u\n"
307 "intr %"PRId64"\n" 308 "intr %"PRId64"\n"
308 "ctxt %"PRId64"\n" 309 "ctxt %"PRId64"\n"
309 "btime %"PRId64"\n", 310 "btime %"PRId64"\n",
310 uvmexp.pageins, uvmexp.pdpageouts, 311 uvmexp.pageins, uvmexp.pdpageouts,
311 uvmexp.pgswapin, uvmexp.pgswapout, 312 uvmexp.pgswapin, uvmexp.pgswapout,
312 cpu_count_get(CPU_COUNT_NINTR), 313 cpu_count_get(CPU_COUNT_NINTR),
313 cpu_count_get(CPU_COUNT_NSWTCH), 314 cpu_count_get(CPU_COUNT_NSWTCH),
314 btv.tv_sec); 315 btv.tv_sec);
315 if (len >= LBFSZ) 316 if (len >= LBFSZ)
316 goto out; 317 goto out;
317 318
318 error = uiomove_frombuf(bf, len, uio); 319 error = uiomove_frombuf(bf, len, uio);
319out: 320out:
320 free(bf, M_TEMP); 321 free(bf, M_TEMP);
321 return error; 322 return error;
322} 323}
323 324
324/* 325/*
325 * Linux compatible /proc/loadavg. Only active when the -o linux 326 * Linux compatible /proc/loadavg. Only active when the -o linux
326 * mountflag is used. 327 * mountflag is used.
327 */ 328 */
328int 329int
329procfs_doloadavg(struct lwp *curl, struct proc *p, 330procfs_doloadavg(struct lwp *curl, struct proc *p,
330 struct pfsnode *pfs, struct uio *uio) 331 struct pfsnode *pfs, struct uio *uio)
331{ 332{
332 char *bf; 333 char *bf;
333 int error; 334 int error;
334 int len; 335 int len;
335 336
336 error = ENAMETOOLONG; 337 error = ENAMETOOLONG;
337 bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 338 bf = malloc(LBFSZ, M_TEMP, M_WAITOK);
338 339
339 averunnable.fscale = FSCALE; 340 averunnable.fscale = FSCALE;
340 len = snprintf(bf, LBFSZ, 341 len = snprintf(bf, LBFSZ,
341 "%d.%02d %d.%02d %d.%02d %d/%d %d\n", 342 "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
342 (int)(averunnable.ldavg[0] / averunnable.fscale), 343 (int)(averunnable.ldavg[0] / averunnable.fscale),
343 (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100), 344 (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
344 (int)(averunnable.ldavg[1] / averunnable.fscale), 345 (int)(averunnable.ldavg[1] / averunnable.fscale),
345 (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100), 346 (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
346 (int)(averunnable.ldavg[2] / averunnable.fscale), 347 (int)(averunnable.ldavg[2] / averunnable.fscale),
347 (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100), 348 (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
348 1, /* number of ONPROC processes */ 349 1, /* number of ONPROC processes */
349 atomic_load_relaxed(&nprocs), 350 atomic_load_relaxed(&nprocs),
350 30000); /* last pid */ 351 30000); /* last pid */
351 if (len == 0) 352 if (len == 0)
352 goto out; 353 goto out;
353 354
354 error = uiomove_frombuf(bf, len, uio); 355 error = uiomove_frombuf(bf, len, uio);
355out: 356out:
356 free(bf, M_TEMP); 357 free(bf, M_TEMP);
357 return error; 358 return error;
358} 359}
359 360
360/* 361/*
361 * Linux compatible /proc/<pid>/statm. Only active when the -o linux 362 * Linux compatible /proc/<pid>/statm. Only active when the -o linux
362 * mountflag is used. 363 * mountflag is used.
363 */ 364 */
364int 365int
365procfs_do_pid_statm(struct lwp *curl, struct lwp *l, 366procfs_do_pid_statm(struct lwp *curl, struct lwp *l,
366 struct pfsnode *pfs, struct uio *uio) 367 struct pfsnode *pfs, struct uio *uio)
367{ 368{
368 struct vmspace *vm; 369 struct vmspace *vm;
369 struct proc *p = l->l_proc; 370 struct proc *p = l->l_proc;
370 char *bf; 371 char *bf;
371 int error; 372 int error;
372 int len; 373 int len;
373 struct kinfo_proc2 ki; 374 struct kinfo_proc2 ki;
374 375
375 bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 376 bf = malloc(LBFSZ, M_TEMP, M_WAITOK);
376 377
377 /* XXX - we use values from vmspace, since dsl says that ru figures 378 /* XXX - we use values from vmspace, since dsl says that ru figures
378 are always 0 except for zombies. See kvm_proc.c::kvm_getproc2() */ 379 are always 0 except for zombies. See kvm_proc.c::kvm_getproc2() */
379 if ((error = proc_vmspace_getref(p, &vm)) != 0) { 380 if ((error = proc_vmspace_getref(p, &vm)) != 0) {
380 goto out; 381 goto out;
381 } 382 }
382 383
383 mutex_enter(proc_lock); 384 mutex_enter(proc_lock);
384 mutex_enter(p->p_lock); 385 mutex_enter(p->p_lock);
385 386
386 /* retrieve RSS size */ 387 /* retrieve RSS size */
387 memset(&ki, 0, sizeof(ki)); 388 memset(&ki, 0, sizeof(ki));
388 fill_kproc2(p, &ki, false, false); 389 fill_kproc2(p, &ki, false, false);
389 390
390 mutex_exit(p->p_lock); 391 mutex_exit(p->p_lock);
391 mutex_exit(proc_lock); 392 mutex_exit(proc_lock);
392 393
393 uvmspace_free(vm); 394 uvmspace_free(vm);
394 395
395 len = snprintf(bf, LBFSZ, 396 len = snprintf(bf, LBFSZ,
396 "%lu %lu %lu %lu %lu %lu %lu\n", 397 "%lu %lu %lu %lu %lu %lu %lu\n",
397 (unsigned long)(ki.p_vm_msize), /* size */ 398 (unsigned long)(ki.p_vm_msize), /* size */
398 (unsigned long)(ki.p_vm_rssize),/* resident */ 399 (unsigned long)(ki.p_vm_rssize),/* resident */
399 (unsigned long)(ki.p_uru_ixrss),/* shared */ 400 (unsigned long)(ki.p_uru_ixrss),/* shared */
400 (unsigned long)(ki.p_vm_tsize), /* text */ 401 (unsigned long)(ki.p_vm_tsize), /* text */
401 (unsigned long) 0, /* library (unused) */ 402 (unsigned long) 0, /* library (unused) */
402 (unsigned long)(ki.p_vm_dsize + ki.p_vm_ssize), /* data+stack */ 403 (unsigned long)(ki.p_vm_dsize + ki.p_vm_ssize), /* data+stack */
403 (unsigned long) 0); /* dirty */ 404 (unsigned long) 0); /* dirty */
404 405
405 if (len == 0) 406 if (len == 0)
406 goto out; 407 goto out;
407 408
408 error = uiomove_frombuf(bf, len, uio); 409 error = uiomove_frombuf(bf, len, uio);
409out: 410out:
410 free(bf, M_TEMP); 411 free(bf, M_TEMP);
411 return error; 412 return error;
412} 413}
413 414
414#define UTIME2TICKS(s,u) (((uint64_t)(s) * 1000000 + (u)) / 10000) 415#define UTIME2TICKS(s,u) (((uint64_t)(s) * 1000000 + (u)) / 10000)
415 416
416/* 417/*
417 * Linux compatible /proc/<pid>/stat. Only active when the -o linux 418 * Linux compatible /proc/<pid>/stat. Only active when the -o linux
418 * mountflag is used. 419 * mountflag is used.
419 */ 420 */
420int 421int
421procfs_do_pid_stat(struct lwp *curl, struct lwp *l, 422procfs_do_pid_stat(struct lwp *curl, struct lwp *l,
422 struct pfsnode *pfs, struct uio *uio) 423 struct pfsnode *pfs, struct uio *uio)
423{ 424{
424 char *bf; 425 char *bf;
425 struct proc *p = l->l_proc; 426 struct proc *p = l->l_proc;
426 int len; 427 int len;
427 struct rusage *cru = &p->p_stats->p_cru; 428 struct rusage *cru = &p->p_stats->p_cru;
428 unsigned long stext = 0, etext = 0, sstack = 0; 429 unsigned long stext = 0, etext = 0, sstack = 0;
429 struct timeval rt; 430 struct timeval rt;
430 struct vmspace *vm; 431 struct vmspace *vm;
431 struct kinfo_proc2 ki; 432 struct kinfo_proc2 ki;
432 int error; 433 int error;
433 434
434 bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 435 bf = malloc(LBFSZ, M_TEMP, M_WAITOK);
435 436
436 if ((error = proc_vmspace_getref(p, &vm)) != 0) { 437 if ((error = proc_vmspace_getref(p, &vm)) != 0) {
437 goto out; 438 goto out;
438 } 439 }
439 440
440 get_proc_size_info(p, &vm->vm_map, &stext, &etext, &sstack); 441 get_proc_size_info(p, &vm->vm_map, &stext, &etext, &sstack);
441 442
442 mutex_enter(proc_lock); 443 mutex_enter(proc_lock);
443 mutex_enter(p->p_lock); 444 mutex_enter(p->p_lock);
444 445
445 memset(&ki, 0, sizeof(ki)); 446 memset(&ki, 0, sizeof(ki));
446 fill_kproc2(p, &ki, false, false); 447 fill_kproc2(p, &ki, false, false);
447 calcru(p, NULL, NULL, NULL, &rt); 448 calcru(p, NULL, NULL, NULL, &rt);
448 449
449 len = snprintf(bf, LBFSZ, 450 len = snprintf(bf, LBFSZ,
450 "%d (%s) %c %d %d %d %u %d " 451 "%d (%s) %c %d %d %d %u %d "
451 "%u " 452 "%u "
452 "%"PRIu64" %lu %"PRIu64" %lu %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" " 453 "%"PRIu64" %lu %"PRIu64" %lu %"PRIu64" %"PRIu64" %"PRIu64" %"PRIu64" "
453 "%d %d %"PRIu64" " 454 "%d %d %"PRIu64" "
454 "%lld %"PRIu64" %"PRId64" %lu %"PRIu64" " 455 "%lld %"PRIu64" %"PRId64" %lu %"PRIu64" "
455 "%lu %lu %lu " 456 "%lu %lu %lu "
456 "%u %u " 457 "%u %u "
457 "%u %u %u %u " 458 "%u %u %u %u "
458 "%"PRIu64" %"PRIu64" %"PRIu64" %d %"PRIu64"\n", 459 "%"PRIu64" %"PRIu64" %"PRIu64" %d %"PRIu64"\n",
459 460
460 ki.p_pid, /* 1 pid */ 461 ki.p_pid, /* 1 pid */
461 ki.p_comm, /* 2 tcomm */ 462 ki.p_comm, /* 2 tcomm */
462 "0RRSTZXR8"[(ki.p_stat > 8) ? 0 : (int)ki.p_stat], /* 3 state */ 463 "0RRSTZXR8"[(ki.p_stat > 8) ? 0 : (int)ki.p_stat], /* 3 state */
463 ki.p_ppid, /* 4 ppid */ 464 ki.p_ppid, /* 4 ppid */
464 ki.p__pgid, /* 5 pgrp */ 465 ki.p__pgid, /* 5 pgrp */
465 ki.p_sid, /* 6 sid */ 466 ki.p_sid, /* 6 sid */
466 (ki.p_tdev != (uint32_t)NODEV) ? ki.p_tdev : 0, /* 7 tty_nr */ 467 (ki.p_tdev != (uint32_t)NODEV) ? ki.p_tdev : 0, /* 7 tty_nr */
467 ki.p_tpgid, /* 8 tty_pgrp */ 468 ki.p_tpgid, /* 8 tty_pgrp */
468 469
469 ki.p_flag, /* 9 flags */ 470 ki.p_flag, /* 9 flags */
470 471
471 ki.p_uru_minflt, /* 10 min_flt */ 472 ki.p_uru_minflt, /* 10 min_flt */
472 cru->ru_minflt, 473 cru->ru_minflt,
473 ki.p_uru_majflt, /* 12 maj_flt */ 474 ki.p_uru_majflt, /* 12 maj_flt */
474 cru->ru_majflt, 475 cru->ru_majflt,
475 UTIME2TICKS(ki.p_uutime_sec, ki.p_uutime_usec), /* 14 utime */ 476 UTIME2TICKS(ki.p_uutime_sec, ki.p_uutime_usec), /* 14 utime */
476 UTIME2TICKS(ki.p_ustime_sec, ki.p_ustime_usec), /* 15 stime */ 477 UTIME2TICKS(ki.p_ustime_sec, ki.p_ustime_usec), /* 15 stime */
477 UTIME2TICKS(cru->ru_utime.tv_sec, cru->ru_utime.tv_usec), /* 16 cutime */ 478 UTIME2TICKS(cru->ru_utime.tv_sec, cru->ru_utime.tv_usec), /* 16 cutime */
478 UTIME2TICKS(cru->ru_stime.tv_sec, cru->ru_stime.tv_usec), /* 17 cstime */ 479 UTIME2TICKS(cru->ru_stime.tv_sec, cru->ru_stime.tv_usec), /* 17 cstime */
479 480
480 ki.p_priority, /* XXX: 18 priority */ 481 ki.p_priority, /* XXX: 18 priority */
481 ki.p_nice - NZERO, /* 19 nice */ 482 ki.p_nice - NZERO, /* 19 nice */
482 ki.p_nlwps, /* 20 num_threads */ 483 ki.p_nlwps, /* 20 num_threads */
483 484
484 (long long)rt.tv_sec, 485 (long long)rt.tv_sec,
485 UTIME2TICKS(ki.p_ustart_sec, ki.p_ustart_usec), /* 22 start_time */ 486 UTIME2TICKS(ki.p_ustart_sec, ki.p_ustart_usec), /* 22 start_time */
486 ki.p_vm_msize, /* 23 vsize */ 487 ki.p_vm_msize, /* 23 vsize */
487 PGTOKB(ki.p_vm_rssize), /* 24 rss */ 488 PGTOKB(ki.p_vm_rssize), /* 24 rss */
488 p->p_rlimit[RLIMIT_RSS].rlim_cur, /* 25 rsslim */ 489 p->p_rlimit[RLIMIT_RSS].rlim_cur, /* 25 rsslim */
489 490
490 stext, /* 26 start_code */ 491 stext, /* 26 start_code */
491 etext, /* 27 end_code */ 492 etext, /* 27 end_code */
492 sstack, /* 28 start_stack */ 493 sstack, /* 28 start_stack */
493 494
494 0, /* XXX: 29 esp */ 495 0, /* XXX: 29 esp */
495 0, /* XXX: 30 eip */ 496 0, /* XXX: 30 eip */
496 497
497 ki.p_siglist.__bits[0], /* XXX: 31 pending */ 498 ki.p_siglist.__bits[0], /* XXX: 31 pending */
498 0, /* XXX: 32 blocked */ 499 0, /* XXX: 32 blocked */
499 ki.p_sigignore.__bits[0], /* 33 sigign */ 500 ki.p_sigignore.__bits[0], /* 33 sigign */
500 ki.p_sigcatch.__bits[0], /* 34 sigcatch */ 501 ki.p_sigcatch.__bits[0], /* 34 sigcatch */
501 502
502 ki.p_wchan, /* 35 wchan */ 503 ki.p_wchan, /* 35 wchan */
503 ki.p_uru_nvcsw, 504 ki.p_uru_nvcsw,
504 ki.p_uru_nivcsw, 505 ki.p_uru_nivcsw,
505 ki.p_exitsig, /* 38 exit_signal */ 506 ki.p_exitsig, /* 38 exit_signal */
506 ki.p_cpuid); /* 39 task_cpu */ 507 ki.p_cpuid); /* 39 task_cpu */
507 508
508 mutex_exit(p->p_lock); 509 mutex_exit(p->p_lock);
509 mutex_exit(proc_lock); 510 mutex_exit(proc_lock);
510 511
511 uvmspace_free(vm); 512 uvmspace_free(vm);
512 513
513 if (len == 0) 514 if (len == 0)
514 goto out; 515 goto out;
515 516
516 error = uiomove_frombuf(bf, len, uio); 517 error = uiomove_frombuf(bf, len, uio);
517out: 518out:
518 free(bf, M_TEMP); 519 free(bf, M_TEMP);
519 return error; 520 return error;
520} 521}
521 522
522int 523int
523procfs_docpuinfo(struct lwp *curl, struct proc *p, 524procfs_docpuinfo(struct lwp *curl, struct proc *p,
524 struct pfsnode *pfs, struct uio *uio) 525 struct pfsnode *pfs, struct uio *uio)
525{ 526{
526 size_t len = LBFSZ; 527 size_t len = LBFSZ;
527 char *bf = NULL; 528 char *bf = NULL;
528 int error; 529 int error;
529 530
530 do { 531 do {
531 if (bf) 532 if (bf)
532 free(bf, M_TEMP); 533 free(bf, M_TEMP);
533 bf = malloc(len, M_TEMP, M_WAITOK); 534 bf = malloc(len, M_TEMP, M_WAITOK);
534 } while (procfs_getcpuinfstr(bf, &len) < 0); 535 } while (procfs_getcpuinfstr(bf, &len) < 0);
535 536
536 if (len == 0) { 537 if (len == 0) {
537 error = 0; 538 error = 0;
538 goto done; 539 goto done;
539 } 540 }
540 541
541 error = uiomove_frombuf(bf, len, uio); 542 error = uiomove_frombuf(bf, len, uio);
542done: 543done:
543 free(bf, M_TEMP); 544 free(bf, M_TEMP);
544 return error; 545 return error;
545} 546}
546 547
547int 548int
548procfs_douptime(struct lwp *curl, struct proc *p, 549procfs_douptime(struct lwp *curl, struct proc *p,
549 struct pfsnode *pfs, struct uio *uio) 550 struct pfsnode *pfs, struct uio *uio)
550{ 551{
551 char *bf; 552 char *bf;
552 int len; 553 int len;
553 struct timeval runtime; 554 struct timeval runtime;
554 u_int64_t idle; 555 u_int64_t idle;
555 int error = 0; 556 int error = 0;
556 557
557 bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 558 bf = malloc(LBFSZ, M_TEMP, M_WAITOK);
558 559
559 microuptime(&runtime); 560 microuptime(&runtime);
560 idle = curcpu()->ci_schedstate.spc_cp_time[CP_IDLE]; 561 idle = curcpu()->ci_schedstate.spc_cp_time[CP_IDLE];
561 len = snprintf(bf, LBFSZ, 562 len = snprintf(bf, LBFSZ,
562 "%lld.%02lu %" PRIu64 ".%02" PRIu64 "\n", 563 "%lld.%02lu %" PRIu64 ".%02" PRIu64 "\n",
563 (long long)runtime.tv_sec, (long)runtime.tv_usec / 10000, 564 (long long)runtime.tv_sec, (long)runtime.tv_usec / 10000,
564 idle / hz, (((idle % hz) * 100) / hz) % 100); 565 idle / hz, (((idle % hz) * 100) / hz) % 100);
565 566
566 if (len == 0) 567 if (len == 0)
567 goto out; 568 goto out;
568 569
569 error = uiomove_frombuf(bf, len, uio); 570 error = uiomove_frombuf(bf, len, uio);
570out: 571out:
571 free(bf, M_TEMP); 572 free(bf, M_TEMP);
572 return error; 573 return error;
573} 574}
574 575
575static int 576static int
576procfs_format_sfs(char **mtab, size_t *mlen, char *buf, size_t blen, 577procfs_format_sfs(char **mtab, size_t *mlen, char *buf, size_t blen,
577 const struct statvfs *sfs, struct lwp *curl, int suser) 578 const struct statvfs *sfs, struct lwp *curl, int suser)
578{ 579{
579 const char *fsname; 580 const char *fsname;
580 581
581 /* Linux uses different names for some filesystems */ 582 /* Linux uses different names for some filesystems */
582 fsname = sfs->f_fstypename; 583 fsname = sfs->f_fstypename;
583 if (strcmp(fsname, "procfs") == 0) 584 if (strcmp(fsname, "procfs") == 0)
584 fsname = "proc"; 585 fsname = "proc";
585 else if (strcmp(fsname, "ext2fs") == 0) 586 else if (strcmp(fsname, "ext2fs") == 0)
586 fsname = "ext2"; 587 fsname = "ext2";
587 588
588 blen = snprintf(buf, blen, "%s %s %s %s%s%s%s%s%s 0 0\n", 589 blen = snprintf(buf, blen, "%s %s %s %s%s%s%s%s%s 0 0\n",
589 sfs->f_mntfromname, sfs->f_mntonname, fsname, 590 sfs->f_mntfromname, sfs->f_mntonname, fsname,
590 (sfs->f_flag & ST_RDONLY) ? "ro" : "rw", 591 (sfs->f_flag & ST_RDONLY) ? "ro" : "rw",
591 (sfs->f_flag & ST_NOSUID) ? ",nosuid" : "", 592 (sfs->f_flag & ST_NOSUID) ? ",nosuid" : "",
592 (sfs->f_flag & ST_NOEXEC) ? ",noexec" : "", 593 (sfs->f_flag & ST_NOEXEC) ? ",noexec" : "",
593 (sfs->f_flag & ST_NODEV) ? ",nodev" : "", 594 (sfs->f_flag & ST_NODEV) ? ",nodev" : "",
594 (sfs->f_flag & ST_SYNCHRONOUS) ? ",sync" : "", 595 (sfs->f_flag & ST_SYNCHRONOUS) ? ",sync" : "",
595 (sfs->f_flag & ST_NOATIME) ? ",noatime" : ""); 596 (sfs->f_flag & ST_NOATIME) ? ",noatime" : "");
596 597
597 *mtab = realloc(*mtab, *mlen + blen, M_TEMP, M_WAITOK); 598 *mtab = realloc(*mtab, *mlen + blen, M_TEMP, M_WAITOK);
598 memcpy(*mtab + *mlen, buf, blen); 599 memcpy(*mtab + *mlen, buf, blen);
599 *mlen += blen; 600 *mlen += blen;
600 return sfs->f_mntonname[0] == '/' && sfs->f_mntonname[1] == '\0'; 601 return sfs->f_mntonname[0] == '/' && sfs->f_mntonname[1] == '\0';
601} 602}
602 603
603int 604int
604procfs_domounts(struct lwp *curl, struct proc *p, 605procfs_domounts(struct lwp *curl, struct proc *p,
605 struct pfsnode *pfs, struct uio *uio) 606 struct pfsnode *pfs, struct uio *uio)
606{ 607{
607 char *bf, *mtab = NULL; 608 char *bf, *mtab = NULL;
608 size_t mtabsz = 0; 609 size_t mtabsz = 0;
609 mount_iterator_t *iter; 610 mount_iterator_t *iter;
610 struct mount *mp; 611 struct mount *mp;
611 int error = 0, root = 0; 612 int error = 0, root = 0;
612 struct cwdinfo *cwdi = curl->l_proc->p_cwdi; 613 struct cwdinfo *cwdi = curl->l_proc->p_cwdi;
613 614
614 bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 615 bf = malloc(LBFSZ, M_TEMP, M_WAITOK);
615 616
616 mountlist_iterator_init(&iter); 617 mountlist_iterator_init(&iter);
617 while ((mp = mountlist_iterator_next(iter)) != NULL) { 618 while ((mp = mountlist_iterator_next(iter)) != NULL) {
618 struct statvfs sfs; 619 struct statvfs sfs;
619 620
620 if ((error = dostatvfs(mp, &sfs, curl, MNT_WAIT, 0)) == 0) 621 if ((error = dostatvfs(mp, &sfs, curl, MNT_WAIT, 0)) == 0)
621 root |= procfs_format_sfs(&mtab, &mtabsz, bf, LBFSZ, 622 root |= procfs_format_sfs(&mtab, &mtabsz, bf, LBFSZ,
622 &sfs, curl, 0); 623 &sfs, curl, 0);
623 } 624 }
624 mountlist_iterator_destroy(iter); 625 mountlist_iterator_destroy(iter);
625 626
626 /* 627 /*
627 * If we are inside a chroot that is not itself a mount point, 628 * If we are inside a chroot that is not itself a mount point,
628 * fake a root entry. 629 * fake a root entry.
629 */ 630 */
630 if (!root && cwdi->cwdi_rdir) 631 if (!root && cwdi->cwdi_rdir)
631 (void)procfs_format_sfs(&mtab, &mtabsz, bf, LBFSZ, 632 (void)procfs_format_sfs(&mtab, &mtabsz, bf, LBFSZ,
632 &cwdi->cwdi_rdir->v_mount->mnt_stat, curl, 1); 633 &cwdi->cwdi_rdir->v_mount->mnt_stat, curl, 1);
633 634
634 free(bf, M_TEMP); 635 free(bf, M_TEMP);
635 636
636 if (mtabsz > 0) { 637 if (mtabsz > 0) {
637 error = uiomove_frombuf(mtab, mtabsz, uio); 638 error = uiomove_frombuf(mtab, mtabsz, uio);
638 free(mtab, M_TEMP); 639 free(mtab, M_TEMP);
639 } 640 }
640 641
641 return error; 642 return error;
642} 643}
643 644
644/* 645/*
645 * Linux compatible /proc/version. Only active when the -o linux 646 * Linux compatible /proc/version. Only active when the -o linux
646 * mountflag is used. 647 * mountflag is used.
647 */ 648 */
648int 649int
649procfs_doversion(struct lwp *curl, struct proc *p, 650procfs_doversion(struct lwp *curl, struct proc *p,
650 struct pfsnode *pfs, struct uio *uio) 651 struct pfsnode *pfs, struct uio *uio)
651{ 652{
652 char *bf; 653 char *bf;
653 char lostype[20], losrelease[20], lversion[80]; 654 char lostype[20], losrelease[20], lversion[80];
654 const char *postype, *posrelease, *pversion; 655 const char *postype, *posrelease, *pversion;
655 const char *emulname = curlwp->l_proc->p_emul->e_name; 656 const char *emulname = curlwp->l_proc->p_emul->e_name;
656 int len; 657 int len;
657 int error = 0; 658 int error = 0;
658 int nm[4]; 659 int nm[4];
659 size_t buflen; 660 size_t buflen;
660 661
661 CTASSERT(EMUL_LINUX_KERN_OSTYPE == EMUL_LINUX32_KERN_OSTYPE); 662 CTASSERT(EMUL_LINUX_KERN_OSTYPE == EMUL_LINUX32_KERN_OSTYPE);
662 CTASSERT(EMUL_LINUX_KERN_OSRELEASE == EMUL_LINUX32_KERN_OSRELEASE); 663 CTASSERT(EMUL_LINUX_KERN_OSRELEASE == EMUL_LINUX32_KERN_OSRELEASE);
663 CTASSERT(EMUL_LINUX_KERN_VERSION == EMUL_LINUX32_KERN_VERSION); 664 CTASSERT(EMUL_LINUX_KERN_VERSION == EMUL_LINUX32_KERN_VERSION);
664 665
665 bf = malloc(LBFSZ, M_TEMP, M_WAITOK); 666 bf = malloc(LBFSZ, M_TEMP, M_WAITOK);
666 667
667 sysctl_lock(false); 668 sysctl_lock(false);
668 669
669 if (strncmp(emulname, "linux", 5) == 0) { 670 if (strncmp(emulname, "linux", 5) == 0) {
670 /* 671 /*
671 * Lookup the emulation ostype, osrelease, and version. 672 * Lookup the emulation ostype, osrelease, and version.
672 * Since compat_linux and compat_linux32 can be built as 673 * Since compat_linux and compat_linux32 can be built as
673 * modules, we use sysctl to obtain the values instead of 674 * modules, we use sysctl to obtain the values instead of
674 * using the symbols directly. 675 * using the symbols directly.
675 */ 676 */
676 677
677 if (strcmp(emulname, "linux32") == 0) { 678 if (strcmp(emulname, "linux32") == 0) {
678 nm[0] = CTL_EMUL; 679 nm[0] = CTL_EMUL;
679 nm[1] = EMUL_LINUX32; 680 nm[1] = EMUL_LINUX32;
680 nm[2] = EMUL_LINUX32_KERN; 681 nm[2] = EMUL_LINUX32_KERN;
681 } else { 682 } else {
682 nm[0] = CTL_EMUL; 683 nm[0] = CTL_EMUL;
683 nm[1] = EMUL_LINUX; 684 nm[1] = EMUL_LINUX;
684 nm[2] = EMUL_LINUX_KERN; 685 nm[2] = EMUL_LINUX_KERN;
685 } 686 }
686 687
687 nm[3] = EMUL_LINUX_KERN_OSTYPE; 688 nm[3] = EMUL_LINUX_KERN_OSTYPE;
688 buflen = sizeof(lostype); 689 buflen = sizeof(lostype);
689 error = sysctl_dispatch(nm, __arraycount(nm), 690 error = sysctl_dispatch(nm, __arraycount(nm),
690 lostype, &buflen, 691 lostype, &buflen,
691 NULL, 0, NULL, NULL, NULL); 692 NULL, 0, NULL, NULL, NULL);
692 if (error) 693 if (error)
693 goto out; 694 goto out;
694 695
695 nm[3] = EMUL_LINUX_KERN_OSRELEASE; 696 nm[3] = EMUL_LINUX_KERN_OSRELEASE;
696 buflen = sizeof(losrelease); 697 buflen = sizeof(losrelease);
697 error = sysctl_dispatch(nm, __arraycount(nm), 698 error = sysctl_dispatch(nm, __arraycount(nm),
698 losrelease, &buflen, 699 losrelease, &buflen,
699 NULL, 0, NULL, NULL, NULL); 700 NULL, 0, NULL, NULL, NULL);
700 if (error) 701 if (error)
701 goto out; 702 goto out;
702 703
703 nm[3] = EMUL_LINUX_KERN_VERSION; 704 nm[3] = EMUL_LINUX_KERN_VERSION;
704 buflen = sizeof(lversion); 705 buflen = sizeof(lversion);
705 error = sysctl_dispatch(nm, __arraycount(nm), 706 error = sysctl_dispatch(nm, __arraycount(nm),
706 lversion, &buflen, 707 lversion, &buflen,
707 NULL, 0, NULL, NULL, NULL); 708 NULL, 0, NULL, NULL, NULL);
708 if (error) 709 if (error)
709 goto out; 710 goto out;
710 711
711 postype = lostype; 712 postype = lostype;
712 posrelease = losrelease; 713 posrelease = losrelease;
713 pversion = lversion; 714 pversion = lversion;
714 } else { 715 } else {
715 postype = ostype; 716 postype = ostype;
716 posrelease = osrelease; 717 posrelease = osrelease;
717 strlcpy(lversion, version, sizeof(lversion)); 718 strlcpy(lversion, version, sizeof(lversion));
718 if (strchr(lversion, '\n')) 719 if (strchr(lversion, '\n'))
719 *strchr(lversion, '\n') = '\0'; 720 *strchr(lversion, '\n') = '\0';
720 pversion = lversion; 721 pversion = lversion;
721 } 722 }
722 723
723 len = snprintf(bf, LBFSZ, 724 len = snprintf(bf, LBFSZ,
724 "%s version %s (%s@localhost) (gcc version %s) %s\n", 725 "%s version %s (%s@localhost) (gcc version %s) %s\n",
725 postype, posrelease, emulname, 726 postype, posrelease, emulname,
726#ifdef __VERSION__ 727#ifdef __VERSION__
727 __VERSION__, 728 __VERSION__,
728#else 729#else
729 "unknown", 730 "unknown",
730#endif 731#endif
731 pversion); 732 pversion);
732 733
733 if (len == 0) 734 if (len == 0)
734 goto out; 735 goto out;
735 736
736 error = uiomove_frombuf(bf, len, uio); 737 error = uiomove_frombuf(bf, len, uio);
737out: 738out:
738 free(bf, M_TEMP); 739 free(bf, M_TEMP);
739 sysctl_unlock(); 740 sysctl_unlock();
740 return error; 741 return error;
741} 742}