xref: /freebsd/sys/compat/linprocfs/linprocfs.c (revision 199b5a28d6eece71405bdc46de1a6081103dfcc4)
1 /*-
2  * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav
3  * Copyright (c) 1999 Pierre Beyssac
4  * Copyright (c) 1993 Jan-Simon Pendry
5  * Copyright (c) 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Jan-Simon Pendry.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the University of
22  *	California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  *	@(#)procfs_status.c	8.4 (Berkeley) 6/15/94
40  */
41 
42 #include "opt_compat.h"
43 
44 #include <sys/cdefs.h>
45 __FBSDID("$FreeBSD$");
46 
47 #include <sys/param.h>
48 #include <sys/queue.h>
49 #include <sys/blist.h>
50 #include <sys/conf.h>
51 #include <sys/exec.h>
52 #include <sys/fcntl.h>
53 #include <sys/filedesc.h>
54 #include <sys/jail.h>
55 #include <sys/kernel.h>
56 #include <sys/linker.h>
57 #include <sys/lock.h>
58 #include <sys/malloc.h>
59 #include <sys/mount.h>
60 #include <sys/msg.h>
61 #include <sys/mutex.h>
62 #include <sys/namei.h>
63 #include <sys/proc.h>
64 #include <sys/ptrace.h>
65 #include <sys/resourcevar.h>
66 #include <sys/sbuf.h>
67 #include <sys/sem.h>
68 #include <sys/smp.h>
69 #include <sys/socket.h>
70 #include <sys/sysctl.h>
71 #include <sys/systm.h>
72 #include <sys/time.h>
73 #include <sys/tty.h>
74 #include <sys/user.h>
75 #include <sys/vmmeter.h>
76 #include <sys/vnode.h>
77 #include <sys/bus.h>
78 
79 #include <net/if.h>
80 #include <net/vnet.h>
81 
82 #include <vm/vm.h>
83 #include <vm/vm_extern.h>
84 #include <vm/pmap.h>
85 #include <vm/vm_map.h>
86 #include <vm/vm_param.h>
87 #include <vm/vm_object.h>
88 #include <vm/swap_pager.h>
89 
90 #include <machine/clock.h>
91 
92 #include <geom/geom.h>
93 #include <geom/geom_int.h>
94 
95 #if defined(__i386__) || defined(__amd64__)
96 #include <machine/cputypes.h>
97 #include <machine/md_var.h>
98 #endif /* __i386__ || __amd64__ */
99 
100 #ifdef COMPAT_FREEBSD32
101 #include <compat/freebsd32/freebsd32_util.h>
102 #endif
103 
104 #ifdef COMPAT_LINUX32				/* XXX */
105 #include <machine/../linux32/linux.h>
106 #else
107 #include <machine/../linux/linux.h>
108 #endif
109 #include <compat/linux/linux_ioctl.h>
110 #include <compat/linux/linux_mib.h>
111 #include <compat/linux/linux_util.h>
112 #include <fs/pseudofs/pseudofs.h>
113 #include <fs/procfs/procfs.h>
114 
115 /*
116  * Various conversion macros
117  */
118 #define T2J(x) ((long)(((x) * 100ULL) / (stathz ? stathz : hz)))	/* ticks to jiffies */
119 #define T2CS(x) ((unsigned long)(((x) * 100ULL) / (stathz ? stathz : hz)))	/* ticks to centiseconds */
120 #define T2S(x) ((x) / (stathz ? stathz : hz))		/* ticks to seconds */
121 #define B2K(x) ((x) >> 10)				/* bytes to kbytes */
122 #define B2P(x) ((x) >> PAGE_SHIFT)			/* bytes to pages */
123 #define P2B(x) ((x) << PAGE_SHIFT)			/* pages to bytes */
124 #define P2K(x) ((x) << (PAGE_SHIFT - 10))		/* pages to kbytes */
125 #define TV2J(x)	((x)->tv_sec * 100UL + (x)->tv_usec / 10000)
126 
127 /**
128  * @brief Mapping of ki_stat in struct kinfo_proc to the linux state
129  *
130  * The linux procfs state field displays one of the characters RSDZTW to
131  * denote running, sleeping in an interruptible wait, waiting in an
132  * uninterruptible disk sleep, a zombie process, process is being traced
133  * or stopped, or process is paging respectively.
134  *
135  * Our struct kinfo_proc contains the variable ki_stat which contains a
136  * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK.
137  *
138  * This character array is used with ki_stati-1 as an index and tries to
139  * map our states to suitable linux states.
140  */
141 static char linux_state[] = "RRSTZDD";
142 
143 /*
144  * Filler function for proc/meminfo
145  */
146 static int
147 linprocfs_domeminfo(PFS_FILL_ARGS)
148 {
149 	unsigned long memtotal;		/* total memory in bytes */
150 	unsigned long memused;		/* used memory in bytes */
151 	unsigned long memfree;		/* free memory in bytes */
152 	unsigned long memshared;	/* shared memory ??? */
153 	unsigned long buffers, cached;	/* buffer / cache memory ??? */
154 	unsigned long long swaptotal;	/* total swap space in bytes */
155 	unsigned long long swapused;	/* used swap space in bytes */
156 	unsigned long long swapfree;	/* free swap space in bytes */
157 	vm_object_t object;
158 	int i, j;
159 
160 	memtotal = physmem * PAGE_SIZE;
161 	/*
162 	 * The correct thing here would be:
163 	 *
164 	memfree = cnt.v_free_count * PAGE_SIZE;
165 	memused = memtotal - memfree;
166 	 *
167 	 * but it might mislead linux binaries into thinking there
168 	 * is very little memory left, so we cheat and tell them that
169 	 * all memory that isn't wired down is free.
170 	 */
171 	memused = cnt.v_wire_count * PAGE_SIZE;
172 	memfree = memtotal - memused;
173 	swap_pager_status(&i, &j);
174 	swaptotal = (unsigned long long)i * PAGE_SIZE;
175 	swapused = (unsigned long long)j * PAGE_SIZE;
176 	swapfree = swaptotal - swapused;
177 	memshared = 0;
178 	mtx_lock(&vm_object_list_mtx);
179 	TAILQ_FOREACH(object, &vm_object_list, object_list)
180 		if (object->shadow_count > 1)
181 			memshared += object->resident_page_count;
182 	mtx_unlock(&vm_object_list_mtx);
183 	memshared *= PAGE_SIZE;
184 	/*
185 	 * We'd love to be able to write:
186 	 *
187 	buffers = bufspace;
188 	 *
189 	 * but bufspace is internal to vfs_bio.c and we don't feel
190 	 * like unstaticizing it just for linprocfs's sake.
191 	 */
192 	buffers = 0;
193 	cached = cnt.v_cache_count * PAGE_SIZE;
194 
195 	sbuf_printf(sb,
196 	    "	     total:    used:	free:  shared: buffers:	 cached:\n"
197 	    "Mem:  %lu %lu %lu %lu %lu %lu\n"
198 	    "Swap: %llu %llu %llu\n"
199 	    "MemTotal: %9lu kB\n"
200 	    "MemFree:  %9lu kB\n"
201 	    "MemShared:%9lu kB\n"
202 	    "Buffers:  %9lu kB\n"
203 	    "Cached:   %9lu kB\n"
204 	    "SwapTotal:%9llu kB\n"
205 	    "SwapFree: %9llu kB\n",
206 	    memtotal, memused, memfree, memshared, buffers, cached,
207 	    swaptotal, swapused, swapfree,
208 	    B2K(memtotal), B2K(memfree),
209 	    B2K(memshared), B2K(buffers), B2K(cached),
210 	    B2K(swaptotal), B2K(swapfree));
211 
212 	return (0);
213 }
214 
215 #if defined(__i386__) || defined(__amd64__)
216 /*
217  * Filler function for proc/cpuinfo (i386 & amd64 version)
218  */
219 static int
220 linprocfs_docpuinfo(PFS_FILL_ARGS)
221 {
222 	int hw_model[2];
223 	char model[128];
224 	size_t size;
225 	int class, fqmhz, fqkhz;
226 	int i;
227 
228 	/*
229 	 * We default the flags to include all non-conflicting flags,
230 	 * and the Intel versions of conflicting flags.
231 	 */
232 	static char *flags[] = {
233 		"fpu",	    "vme",     "de",	   "pse",      "tsc",
234 		"msr",	    "pae",     "mce",	   "cx8",      "apic",
235 		"sep",	    "sep",     "mtrr",	   "pge",      "mca",
236 		"cmov",	    "pat",     "pse36",	   "pn",       "b19",
237 		"b20",	    "b21",     "mmxext",   "mmx",      "fxsr",
238 		"xmm",	    "sse2",    "b27",	   "b28",      "b29",
239 		"3dnowext", "3dnow"
240 	};
241 
242 	switch (cpu_class) {
243 #ifdef __i386__
244 	case CPUCLASS_286:
245 		class = 2;
246 		break;
247 	case CPUCLASS_386:
248 		class = 3;
249 		break;
250 	case CPUCLASS_486:
251 		class = 4;
252 		break;
253 	case CPUCLASS_586:
254 		class = 5;
255 		break;
256 	case CPUCLASS_686:
257 		class = 6;
258 		break;
259 	default:
260 		class = 0;
261 		break;
262 #else /* __amd64__ */
263 	default:
264 		class = 15;
265 		break;
266 #endif
267 	}
268 
269 	hw_model[0] = CTL_HW;
270 	hw_model[1] = HW_MODEL;
271 	model[0] = '\0';
272 	size = sizeof(model);
273 	if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0)
274 		strcpy(model, "unknown");
275 	for (i = 0; i < mp_ncpus; ++i) {
276 		sbuf_printf(sb,
277 		    "processor\t: %d\n"
278 		    "vendor_id\t: %.20s\n"
279 		    "cpu family\t: %u\n"
280 		    "model\t\t: %u\n"
281 		    "model name\t: %s\n"
282 		    "stepping\t: %u\n\n",
283 		    i, cpu_vendor, CPUID_TO_FAMILY(cpu_id), CPUID_TO_MODEL(cpu_id), model, cpu_id & CPUID_STEPPING);
284 		/* XXX per-cpu vendor / class / model / id? */
285 	}
286 
287 	sbuf_cat(sb, "flags\t\t:");
288 
289 #ifdef __i386__
290 	switch (cpu_vendor_id) {
291 	case CPU_VENDOR_AMD:
292 		if (class < 6)
293 			flags[16] = "fcmov";
294 		break;
295 	case CPU_VENDOR_CYRIX:
296 		flags[24] = "cxmmx";
297 		break;
298 	}
299 #endif
300 
301 	for (i = 0; i < 32; i++)
302 		if (cpu_feature & (1 << i))
303 			sbuf_printf(sb, " %s", flags[i]);
304 	sbuf_cat(sb, "\n");
305 	if (class >= 5) {
306 		fqmhz = (tsc_freq + 4999) / 1000000;
307 		fqkhz = ((tsc_freq + 4999) / 10000) % 100;
308 		sbuf_printf(sb,
309 		    "cpu MHz\t\t: %d.%02d\n"
310 		    "bogomips\t: %d.%02d\n",
311 		    fqmhz, fqkhz, fqmhz, fqkhz);
312 	}
313 
314 	return (0);
315 }
316 #endif /* __i386__ || __amd64__ */
317 
318 /*
319  * Filler function for proc/mtab
320  *
321  * This file doesn't exist in Linux' procfs, but is included here so
322  * users can symlink /compat/linux/etc/mtab to /proc/mtab
323  */
324 static int
325 linprocfs_domtab(PFS_FILL_ARGS)
326 {
327 	struct nameidata nd;
328 	struct mount *mp;
329 	const char *lep;
330 	char *dlep, *flep, *mntto, *mntfrom, *fstype;
331 	size_t lep_len;
332 	int error;
333 
334 	/* resolve symlinks etc. in the emulation tree prefix */
335 	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td);
336 	flep = NULL;
337 	error = namei(&nd);
338 	lep = linux_emul_path;
339 	if (error == 0) {
340 		if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
341 			lep = dlep;
342 		vrele(nd.ni_vp);
343 		VFS_UNLOCK_GIANT(NDHASGIANT(&nd));
344 	}
345 	lep_len = strlen(lep);
346 
347 	mtx_lock(&mountlist_mtx);
348 	error = 0;
349 	TAILQ_FOREACH(mp, &mountlist, mnt_list) {
350 		/* determine device name */
351 		mntfrom = mp->mnt_stat.f_mntfromname;
352 
353 		/* determine mount point */
354 		mntto = mp->mnt_stat.f_mntonname;
355 		if (strncmp(mntto, lep, lep_len) == 0 &&
356 		    mntto[lep_len] == '/')
357 			mntto += lep_len;
358 
359 		/* determine fs type */
360 		fstype = mp->mnt_stat.f_fstypename;
361 		if (strcmp(fstype, pn->pn_info->pi_name) == 0)
362 			mntfrom = fstype = "proc";
363 		else if (strcmp(fstype, "procfs") == 0)
364 			continue;
365 
366 		if (strcmp(fstype, "linsysfs") == 0) {
367 			sbuf_printf(sb, "/sys %s sysfs %s", mntto,
368 			    mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
369 		} else {
370 			/* For Linux msdosfs is called vfat */
371 			if (strcmp(fstype, "msdosfs") == 0)
372 				fstype = "vfat";
373 			sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
374 			    mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
375 		}
376 #define ADD_OPTION(opt, name) \
377 	if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name);
378 		ADD_OPTION(MNT_SYNCHRONOUS,	"sync");
379 		ADD_OPTION(MNT_NOEXEC,		"noexec");
380 		ADD_OPTION(MNT_NOSUID,		"nosuid");
381 		ADD_OPTION(MNT_UNION,		"union");
382 		ADD_OPTION(MNT_ASYNC,		"async");
383 		ADD_OPTION(MNT_SUIDDIR,		"suiddir");
384 		ADD_OPTION(MNT_NOSYMFOLLOW,	"nosymfollow");
385 		ADD_OPTION(MNT_NOATIME,		"noatime");
386 #undef ADD_OPTION
387 		/* a real Linux mtab will also show NFS options */
388 		sbuf_printf(sb, " 0 0\n");
389 	}
390 	mtx_unlock(&mountlist_mtx);
391 	if (flep != NULL)
392 		free(flep, M_TEMP);
393 	return (error);
394 }
395 
396 /*
397  * Filler function for proc/partitions
398  *
399  */
400 static int
401 linprocfs_dopartitions(PFS_FILL_ARGS)
402 {
403 	struct g_class *cp;
404 	struct g_geom *gp;
405 	struct g_provider *pp;
406 	struct nameidata nd;
407 	const char *lep;
408 	char  *dlep, *flep;
409 	size_t lep_len;
410 	int error;
411 	int major, minor;
412 
413 	/* resolve symlinks etc. in the emulation tree prefix */
414 	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td);
415 	flep = NULL;
416 	error = namei(&nd);
417 	lep = linux_emul_path;
418 	if (error == 0) {
419 		if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
420 			lep = dlep;
421 		vrele(nd.ni_vp);
422 		VFS_UNLOCK_GIANT(NDHASGIANT(&nd));
423 	}
424 	lep_len = strlen(lep);
425 
426 	g_topology_lock();
427 	error = 0;
428 	sbuf_printf(sb, "major minor  #blocks  name rio rmerge rsect "
429 	    "ruse wio wmerge wsect wuse running use aveq\n");
430 
431 	LIST_FOREACH(cp, &g_classes, class) {
432 		if (strcmp(cp->name, "DISK") == 0 ||
433 		    strcmp(cp->name, "PART") == 0)
434 			LIST_FOREACH(gp, &cp->geom, geom) {
435 				LIST_FOREACH(pp, &gp->provider, provider) {
436 					if (linux_driver_get_major_minor(
437 					    pp->name, &major, &minor) != 0) {
438 						major = 0;
439 						minor = 0;
440 					}
441 					sbuf_printf(sb, "%d %d %lld %s "
442 					    "%d %d %d %d %d "
443 					     "%d %d %d %d %d %d\n",
444 					     major, minor,
445 					     (long long)pp->mediasize, pp->name,
446 					     0, 0, 0, 0, 0,
447 					     0, 0, 0, 0, 0, 0);
448 				}
449 			}
450 	}
451 	g_topology_unlock();
452 
453 	if (flep != NULL)
454 		free(flep, M_TEMP);
455 	return (error);
456 }
457 
458 
459 /*
460  * Filler function for proc/stat
461  */
462 static int
463 linprocfs_dostat(PFS_FILL_ARGS)
464 {
465 	struct pcpu *pcpu;
466 	long cp_time[CPUSTATES];
467 	long *cp;
468 	int i;
469 
470 	read_cpu_time(cp_time);
471 	sbuf_printf(sb, "cpu %ld %ld %ld %ld\n",
472 	    T2J(cp_time[CP_USER]),
473 	    T2J(cp_time[CP_NICE]),
474 	    T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
475 	    T2J(cp_time[CP_IDLE]));
476 	CPU_FOREACH(i) {
477 		pcpu = pcpu_find(i);
478 		cp = pcpu->pc_cp_time;
479 		sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i,
480 		    T2J(cp[CP_USER]),
481 		    T2J(cp[CP_NICE]),
482 		    T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/),
483 		    T2J(cp[CP_IDLE]));
484 	}
485 	sbuf_printf(sb,
486 	    "disk 0 0 0 0\n"
487 	    "page %u %u\n"
488 	    "swap %u %u\n"
489 	    "intr %u\n"
490 	    "ctxt %u\n"
491 	    "btime %lld\n",
492 	    cnt.v_vnodepgsin,
493 	    cnt.v_vnodepgsout,
494 	    cnt.v_swappgsin,
495 	    cnt.v_swappgsout,
496 	    cnt.v_intr,
497 	    cnt.v_swtch,
498 	    (long long)boottime.tv_sec);
499 	return (0);
500 }
501 
502 /*
503  * Filler function for proc/uptime
504  */
505 static int
506 linprocfs_douptime(PFS_FILL_ARGS)
507 {
508 	long cp_time[CPUSTATES];
509 	struct timeval tv;
510 
511 	getmicrouptime(&tv);
512 	read_cpu_time(cp_time);
513 	sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n",
514 	    (long long)tv.tv_sec, tv.tv_usec / 10000,
515 	    T2S(cp_time[CP_IDLE] / mp_ncpus),
516 	    T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100);
517 	return (0);
518 }
519 
520 /*
521  * Get OS build date
522  */
523 static void
524 linprocfs_osbuild(struct thread *td, struct sbuf *sb)
525 {
526 #if 0
527 	char osbuild[256];
528 	char *cp1, *cp2;
529 
530 	strncpy(osbuild, version, 256);
531 	osbuild[255] = '\0';
532 	cp1 = strstr(osbuild, "\n");
533 	cp2 = strstr(osbuild, ":");
534 	if (cp1 && cp2) {
535 		*cp1 = *cp2 = '\0';
536 		cp1 = strstr(osbuild, "#");
537 	} else
538 		cp1 = NULL;
539 	if (cp1)
540 		sbuf_printf(sb, "%s%s", cp1, cp2 + 1);
541 	else
542 #endif
543 		sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977");
544 }
545 
546 /*
547  * Get OS builder
548  */
549 static void
550 linprocfs_osbuilder(struct thread *td, struct sbuf *sb)
551 {
552 #if 0
553 	char builder[256];
554 	char *cp;
555 
556 	cp = strstr(version, "\n    ");
557 	if (cp) {
558 		strncpy(builder, cp + 5, 256);
559 		builder[255] = '\0';
560 		cp = strstr(builder, ":");
561 		if (cp)
562 			*cp = '\0';
563 	}
564 	if (cp)
565 		sbuf_cat(sb, builder);
566 	else
567 #endif
568 		sbuf_cat(sb, "des@freebsd.org");
569 }
570 
571 /*
572  * Filler function for proc/version
573  */
574 static int
575 linprocfs_doversion(PFS_FILL_ARGS)
576 {
577 	char osname[LINUX_MAX_UTSNAME];
578 	char osrelease[LINUX_MAX_UTSNAME];
579 
580 	linux_get_osname(td, osname);
581 	linux_get_osrelease(td, osrelease);
582 	sbuf_printf(sb, "%s version %s (", osname, osrelease);
583 	linprocfs_osbuilder(td, sb);
584 	sbuf_cat(sb, ") (gcc version " __VERSION__ ") ");
585 	linprocfs_osbuild(td, sb);
586 	sbuf_cat(sb, "\n");
587 
588 	return (0);
589 }
590 
591 /*
592  * Filler function for proc/loadavg
593  */
594 static int
595 linprocfs_doloadavg(PFS_FILL_ARGS)
596 {
597 
598 	sbuf_printf(sb,
599 	    "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
600 	    (int)(averunnable.ldavg[0] / averunnable.fscale),
601 	    (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
602 	    (int)(averunnable.ldavg[1] / averunnable.fscale),
603 	    (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
604 	    (int)(averunnable.ldavg[2] / averunnable.fscale),
605 	    (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
606 	    1,				/* number of running tasks */
607 	    nprocs,			/* number of tasks */
608 	    lastpid			/* the last pid */
609 	);
610 	return (0);
611 }
612 
613 /*
614  * Filler function for proc/pid/stat
615  */
616 static int
617 linprocfs_doprocstat(PFS_FILL_ARGS)
618 {
619 	struct kinfo_proc kp;
620 	char state;
621 	static int ratelimit = 0;
622 	vm_offset_t startcode, startdata;
623 
624 	PROC_LOCK(p);
625 	fill_kinfo_proc(p, &kp);
626 	if (p->p_vmspace) {
627 	   startcode = (vm_offset_t)p->p_vmspace->vm_taddr;
628 	   startdata = (vm_offset_t)p->p_vmspace->vm_daddr;
629 	} else {
630 	   startcode = 0;
631 	   startdata = 0;
632 	};
633 	sbuf_printf(sb, "%d", p->p_pid);
634 #define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
635 	PS_ADD("comm",		"(%s)",	p->p_comm);
636 	if (kp.ki_stat > sizeof(linux_state)) {
637 		state = 'R';
638 
639 		if (ratelimit == 0) {
640 			printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n",
641 			    kp.ki_stat, sizeof(linux_state));
642 			++ratelimit;
643 		}
644 	} else
645 		state = linux_state[kp.ki_stat - 1];
646 	PS_ADD("state",		"%c",	state);
647 	PS_ADD("ppid",		"%d",	p->p_pptr ? p->p_pptr->p_pid : 0);
648 	PS_ADD("pgrp",		"%d",	p->p_pgid);
649 	PS_ADD("session",	"%d",	p->p_session->s_sid);
650 	PROC_UNLOCK(p);
651 	PS_ADD("tty",		"%d",	kp.ki_tdev);
652 	PS_ADD("tpgid",		"%d",	kp.ki_tpgid);
653 	PS_ADD("flags",		"%u",	0); /* XXX */
654 	PS_ADD("minflt",	"%lu",	kp.ki_rusage.ru_minflt);
655 	PS_ADD("cminflt",	"%lu",	kp.ki_rusage_ch.ru_minflt);
656 	PS_ADD("majflt",	"%lu",	kp.ki_rusage.ru_majflt);
657 	PS_ADD("cmajflt",	"%lu",	kp.ki_rusage_ch.ru_majflt);
658 	PS_ADD("utime",		"%ld",	TV2J(&kp.ki_rusage.ru_utime));
659 	PS_ADD("stime",		"%ld",	TV2J(&kp.ki_rusage.ru_stime));
660 	PS_ADD("cutime",	"%ld",	TV2J(&kp.ki_rusage_ch.ru_utime));
661 	PS_ADD("cstime",	"%ld",	TV2J(&kp.ki_rusage_ch.ru_stime));
662 	PS_ADD("priority",	"%d",	kp.ki_pri.pri_user);
663 	PS_ADD("nice",		"%d",	kp.ki_nice); /* 19 (nicest) to -19 */
664 	PS_ADD("0",		"%d",	0); /* removed field */
665 	PS_ADD("itrealvalue",	"%d",	0); /* XXX */
666 	PS_ADD("starttime",	"%lu",	TV2J(&kp.ki_start) - TV2J(&boottime));
667 	PS_ADD("vsize",		"%ju",	P2K((uintmax_t)kp.ki_size));
668 	PS_ADD("rss",		"%ju",	(uintmax_t)kp.ki_rssize);
669 	PS_ADD("rlim",		"%lu",	kp.ki_rusage.ru_maxrss);
670 	PS_ADD("startcode",	"%ju",	(uintmax_t)startcode);
671 	PS_ADD("endcode",	"%ju",	(uintmax_t)startdata);
672 	PS_ADD("startstack",	"%u",	0); /* XXX */
673 	PS_ADD("kstkesp",	"%u",	0); /* XXX */
674 	PS_ADD("kstkeip",	"%u",	0); /* XXX */
675 	PS_ADD("signal",	"%u",	0); /* XXX */
676 	PS_ADD("blocked",	"%u",	0); /* XXX */
677 	PS_ADD("sigignore",	"%u",	0); /* XXX */
678 	PS_ADD("sigcatch",	"%u",	0); /* XXX */
679 	PS_ADD("wchan",		"%u",	0); /* XXX */
680 	PS_ADD("nswap",		"%lu",	kp.ki_rusage.ru_nswap);
681 	PS_ADD("cnswap",	"%lu",	kp.ki_rusage_ch.ru_nswap);
682 	PS_ADD("exitsignal",	"%d",	0); /* XXX */
683 	PS_ADD("processor",	"%u",	kp.ki_lastcpu);
684 	PS_ADD("rt_priority",	"%u",	0); /* XXX */ /* >= 2.5.19 */
685 	PS_ADD("policy",	"%u",	kp.ki_pri.pri_class); /* >= 2.5.19 */
686 #undef PS_ADD
687 	sbuf_putc(sb, '\n');
688 
689 	return (0);
690 }
691 
692 /*
693  * Filler function for proc/pid/statm
694  */
695 static int
696 linprocfs_doprocstatm(PFS_FILL_ARGS)
697 {
698 	struct kinfo_proc kp;
699 	segsz_t lsize;
700 
701 	PROC_LOCK(p);
702 	fill_kinfo_proc(p, &kp);
703 	PROC_UNLOCK(p);
704 
705 	/*
706 	 * See comments in linprocfs_doprocstatus() regarding the
707 	 * computation of lsize.
708 	 */
709 	/* size resident share trs drs lrs dt */
710 	sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size));
711 	sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize);
712 	sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */
713 	sbuf_printf(sb, "%ju ",	(uintmax_t)kp.ki_tsize);
714 	sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize));
715 	lsize = B2P(kp.ki_size) - kp.ki_dsize -
716 	    kp.ki_ssize - kp.ki_tsize - 1;
717 	sbuf_printf(sb, "%ju ", (uintmax_t)lsize);
718 	sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */
719 
720 	return (0);
721 }
722 
723 /*
724  * Filler function for proc/pid/status
725  */
726 static int
727 linprocfs_doprocstatus(PFS_FILL_ARGS)
728 {
729 	struct kinfo_proc kp;
730 	char *state;
731 	segsz_t lsize;
732 	struct thread *td2;
733 	struct sigacts *ps;
734 	int i;
735 
736 	PROC_LOCK(p);
737 	td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */
738 
739 	if (P_SHOULDSTOP(p)) {
740 		state = "T (stopped)";
741 	} else {
742 		PROC_SLOCK(p);
743 		switch(p->p_state) {
744 		case PRS_NEW:
745 			state = "I (idle)";
746 			break;
747 		case PRS_NORMAL:
748 			if (p->p_flag & P_WEXIT) {
749 				state = "X (exiting)";
750 				break;
751 			}
752 			switch(td2->td_state) {
753 			case TDS_INHIBITED:
754 				state = "S (sleeping)";
755 				break;
756 			case TDS_RUNQ:
757 			case TDS_RUNNING:
758 				state = "R (running)";
759 				break;
760 			default:
761 				state = "? (unknown)";
762 				break;
763 			}
764 			break;
765 		case PRS_ZOMBIE:
766 			state = "Z (zombie)";
767 			break;
768 		default:
769 			state = "? (unknown)";
770 			break;
771 		}
772 		PROC_SUNLOCK(p);
773 	}
774 
775 	fill_kinfo_proc(p, &kp);
776 	sbuf_printf(sb, "Name:\t%s\n",		p->p_comm); /* XXX escape */
777 	sbuf_printf(sb, "State:\t%s\n",		state);
778 
779 	/*
780 	 * Credentials
781 	 */
782 	sbuf_printf(sb, "Pid:\t%d\n",		p->p_pid);
783 	sbuf_printf(sb, "PPid:\t%d\n",		p->p_pptr ?
784 						p->p_pptr->p_pid : 0);
785 	sbuf_printf(sb, "Uid:\t%d %d %d %d\n",	p->p_ucred->cr_ruid,
786 						p->p_ucred->cr_uid,
787 						p->p_ucred->cr_svuid,
788 						/* FreeBSD doesn't have fsuid */
789 						p->p_ucred->cr_uid);
790 	sbuf_printf(sb, "Gid:\t%d %d %d %d\n",	p->p_ucred->cr_rgid,
791 						p->p_ucred->cr_gid,
792 						p->p_ucred->cr_svgid,
793 						/* FreeBSD doesn't have fsgid */
794 						p->p_ucred->cr_gid);
795 	sbuf_cat(sb, "Groups:\t");
796 	for (i = 0; i < p->p_ucred->cr_ngroups; i++)
797 		sbuf_printf(sb, "%d ",		p->p_ucred->cr_groups[i]);
798 	PROC_UNLOCK(p);
799 	sbuf_putc(sb, '\n');
800 
801 	/*
802 	 * Memory
803 	 *
804 	 * While our approximation of VmLib may not be accurate (I
805 	 * don't know of a simple way to verify it, and I'm not sure
806 	 * it has much meaning anyway), I believe it's good enough.
807 	 *
808 	 * The same code that could (I think) accurately compute VmLib
809 	 * could also compute VmLck, but I don't really care enough to
810 	 * implement it. Submissions are welcome.
811 	 */
812 	sbuf_printf(sb, "VmSize:\t%8ju kB\n",	B2K((uintmax_t)kp.ki_size));
813 	sbuf_printf(sb, "VmLck:\t%8u kB\n",	P2K(0)); /* XXX */
814 	sbuf_printf(sb, "VmRSS:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_rssize));
815 	sbuf_printf(sb, "VmData:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_dsize));
816 	sbuf_printf(sb, "VmStk:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_ssize));
817 	sbuf_printf(sb, "VmExe:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_tsize));
818 	lsize = B2P(kp.ki_size) - kp.ki_dsize -
819 	    kp.ki_ssize - kp.ki_tsize - 1;
820 	sbuf_printf(sb, "VmLib:\t%8ju kB\n",	P2K((uintmax_t)lsize));
821 
822 	/*
823 	 * Signal masks
824 	 *
825 	 * We support up to 128 signals, while Linux supports 32,
826 	 * but we only define 32 (the same 32 as Linux, to boot), so
827 	 * just show the lower 32 bits of each mask. XXX hack.
828 	 *
829 	 * NB: on certain platforms (Sparc at least) Linux actually
830 	 * supports 64 signals, but this code is a long way from
831 	 * running on anything but i386, so ignore that for now.
832 	 */
833 	PROC_LOCK(p);
834 	sbuf_printf(sb, "SigPnd:\t%08x\n",	p->p_siglist.__bits[0]);
835 	/*
836 	 * I can't seem to find out where the signal mask is in
837 	 * relation to struct proc, so SigBlk is left unimplemented.
838 	 */
839 	sbuf_printf(sb, "SigBlk:\t%08x\n",	0); /* XXX */
840 	ps = p->p_sigacts;
841 	mtx_lock(&ps->ps_mtx);
842 	sbuf_printf(sb, "SigIgn:\t%08x\n",	ps->ps_sigignore.__bits[0]);
843 	sbuf_printf(sb, "SigCgt:\t%08x\n",	ps->ps_sigcatch.__bits[0]);
844 	mtx_unlock(&ps->ps_mtx);
845 	PROC_UNLOCK(p);
846 
847 	/*
848 	 * Linux also prints the capability masks, but we don't have
849 	 * capabilities yet, and when we do get them they're likely to
850 	 * be meaningless to Linux programs, so we lie. XXX
851 	 */
852 	sbuf_printf(sb, "CapInh:\t%016x\n",	0);
853 	sbuf_printf(sb, "CapPrm:\t%016x\n",	0);
854 	sbuf_printf(sb, "CapEff:\t%016x\n",	0);
855 
856 	return (0);
857 }
858 
859 
860 /*
861  * Filler function for proc/pid/cwd
862  */
863 static int
864 linprocfs_doproccwd(PFS_FILL_ARGS)
865 {
866 	char *fullpath = "unknown";
867 	char *freepath = NULL;
868 
869 	vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath);
870 	sbuf_printf(sb, "%s", fullpath);
871 	if (freepath)
872 		free(freepath, M_TEMP);
873 	return (0);
874 }
875 
876 /*
877  * Filler function for proc/pid/root
878  */
879 static int
880 linprocfs_doprocroot(PFS_FILL_ARGS)
881 {
882 	struct vnode *rvp;
883 	char *fullpath = "unknown";
884 	char *freepath = NULL;
885 
886 	rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir;
887 	vn_fullpath(td, rvp, &fullpath, &freepath);
888 	sbuf_printf(sb, "%s", fullpath);
889 	if (freepath)
890 		free(freepath, M_TEMP);
891 	return (0);
892 }
893 
894 #define MAX_ARGV_STR	512	/* Max number of argv-like strings */
895 #define UIO_CHUNK_SZ	256	/* Max chunk size (bytes) for uiomove */
896 
897 static int
898 linprocfs_doargv(struct thread *td, struct proc *p, struct sbuf *sb,
899     void (*resolver)(const struct ps_strings, u_long *, int *))
900 {
901 	struct iovec iov;
902 	struct uio tmp_uio;
903 	struct ps_strings pss;
904 	int ret, i, n_elements, elm_len;
905 	u_long addr, pbegin;
906 	char **env_vector, *envp;
907 	char env_string[UIO_CHUNK_SZ];
908 #ifdef COMPAT_FREEBSD32
909 	struct freebsd32_ps_strings pss32;
910 	uint32_t *env_vector32;
911 #endif
912 
913 #define	UIO_HELPER(uio, iov, base, len, cnt, offset, sz, flg, rw, td)	\
914 do {									\
915 	iov.iov_base = (caddr_t)(base);					\
916 	iov.iov_len = (len); 						\
917 	uio.uio_iov = &(iov); 						\
918 	uio.uio_iovcnt = (cnt);	 					\
919 	uio.uio_offset = (off_t)(offset);				\
920 	uio.uio_resid = (sz); 						\
921 	uio.uio_segflg = (flg);						\
922 	uio.uio_rw = (rw); 						\
923 	uio.uio_td = (td);						\
924 } while (0)
925 
926 	env_vector = malloc(sizeof(char *) * MAX_ARGV_STR, M_TEMP, M_WAITOK);
927 
928 #ifdef COMPAT_FREEBSD32
929 	env_vector32 = NULL;
930 	if ((p->p_sysent->sv_flags & SV_ILP32) != 0) {
931 		env_vector32 = malloc(sizeof(*env_vector32) * MAX_ARGV_STR,
932 		    M_TEMP, M_WAITOK);
933 		elm_len = sizeof(int32_t);
934 		envp = (char *)env_vector32;
935 
936 		UIO_HELPER(tmp_uio, iov, &pss32, sizeof(pss32), 1,
937 		    (off_t)(p->p_sysent->sv_psstrings),
938 		    sizeof(pss32), UIO_SYSSPACE, UIO_READ, td);
939 		ret = proc_rwmem(p, &tmp_uio);
940 		if (ret != 0)
941 			goto done;
942 		pss.ps_argvstr = PTRIN(pss32.ps_argvstr);
943 		pss.ps_nargvstr = pss32.ps_nargvstr;
944 		pss.ps_envstr = PTRIN(pss32.ps_envstr);
945 		pss.ps_nenvstr = pss32.ps_nenvstr;
946 	} else {
947 #endif
948 		elm_len = sizeof(char *);
949 		envp = (char *)env_vector;
950 
951 		UIO_HELPER(tmp_uio, iov, &pss, sizeof(pss), 1,
952 		    (off_t)(p->p_sysent->sv_psstrings),
953 		    sizeof(pss), UIO_SYSSPACE, UIO_READ, td);
954 		ret = proc_rwmem(p, &tmp_uio);
955 		if (ret != 0)
956 			goto done;
957 #ifdef COMPAT_FREEBSD32
958 	}
959 #endif
960 
961 	/* Get the array address and the number of elements */
962 	resolver(pss, &addr, &n_elements);
963 
964 	/* Consistent with lib/libkvm/kvm_proc.c */
965 	if (n_elements > MAX_ARGV_STR) {
966 		ret = E2BIG;
967 		goto done;
968 	}
969 
970 	UIO_HELPER(tmp_uio, iov, envp, n_elements * elm_len, 1,
971 	    (vm_offset_t)(addr), iov.iov_len, UIO_SYSSPACE, UIO_READ, td);
972 	ret = proc_rwmem(p, &tmp_uio);
973 	if (ret != 0)
974 		goto done;
975 #ifdef COMPAT_FREEBSD32
976 	if (env_vector32 != NULL) {
977 		for (i = 0; i < n_elements; i++)
978 			env_vector[i] = PTRIN(env_vector32[i]);
979 	}
980 #endif
981 
982 	/* Now we can iterate through the list of strings */
983 	for (i = 0; i < n_elements; i++) {
984 		pbegin = (vm_offset_t)env_vector[i];
985 		for (;;) {
986 			UIO_HELPER(tmp_uio, iov, env_string, sizeof(env_string),
987 			    1, pbegin, iov.iov_len, UIO_SYSSPACE, UIO_READ, td);
988 			ret = proc_rwmem(p, &tmp_uio);
989 			if (ret != 0)
990 				goto done;
991 
992 			if (!strvalid(env_string, UIO_CHUNK_SZ)) {
993 				/*
994 				 * We didn't find the end of the string.
995 				 * Add the string to the buffer and move
996 				 * the pointer.  But do not allow strings
997 				 * of unlimited length.
998 				 */
999 				sbuf_bcat(sb, env_string, UIO_CHUNK_SZ);
1000 				if (sbuf_len(sb) >= ARG_MAX) {
1001 					ret = E2BIG;
1002 					goto done;
1003 				}
1004 				pbegin += UIO_CHUNK_SZ;
1005 			} else {
1006 				sbuf_cat(sb, env_string);
1007 				break;
1008 			}
1009 		}
1010 		sbuf_bcat(sb, "", 1);
1011 	}
1012 #undef UIO_HELPER
1013 
1014 done:
1015 	free(env_vector, M_TEMP);
1016 #ifdef COMPAT_FREEBSD32
1017 	free(env_vector32, M_TEMP);
1018 #endif
1019 	return (ret);
1020 }
1021 
1022 static void
1023 ps_string_argv(const struct ps_strings ps, u_long *addr, int *n)
1024 {
1025 
1026 	*addr = (u_long) ps.ps_argvstr;
1027 	*n = ps.ps_nargvstr;
1028 }
1029 
1030 static void
1031 ps_string_env(const struct ps_strings ps, u_long *addr, int *n)
1032 {
1033 
1034 	*addr = (u_long) ps.ps_envstr;
1035 	*n = ps.ps_nenvstr;
1036 }
1037 
1038 /*
1039  * Filler function for proc/pid/cmdline
1040  */
1041 static int
1042 linprocfs_doproccmdline(PFS_FILL_ARGS)
1043 {
1044 	int ret;
1045 
1046 	PROC_LOCK(p);
1047 	if ((ret = p_cansee(td, p)) != 0) {
1048 		PROC_UNLOCK(p);
1049 		return (ret);
1050 	}
1051 	if (p->p_args != NULL) {
1052 		sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
1053 		PROC_UNLOCK(p);
1054 		return (0);
1055 	}
1056 	PROC_UNLOCK(p);
1057 
1058 	ret = linprocfs_doargv(td, p, sb, ps_string_argv);
1059 	return (ret);
1060 }
1061 
1062 /*
1063  * Filler function for proc/pid/environ
1064  */
1065 static int
1066 linprocfs_doprocenviron(PFS_FILL_ARGS)
1067 {
1068 	int ret;
1069 
1070 	PROC_LOCK(p);
1071 	if ((ret = p_cansee(td, p)) != 0) {
1072 		PROC_UNLOCK(p);
1073 		return (ret);
1074 	}
1075 	PROC_UNLOCK(p);
1076 
1077 	ret = linprocfs_doargv(td, p, sb, ps_string_env);
1078 	return (ret);
1079 }
1080 
1081 /*
1082  * Filler function for proc/pid/maps
1083  */
1084 static int
1085 linprocfs_doprocmaps(PFS_FILL_ARGS)
1086 {
1087 	struct vmspace *vm;
1088 	vm_map_t map;
1089 	vm_map_entry_t entry, tmp_entry;
1090 	vm_object_t obj, tobj, lobj;
1091 	vm_offset_t e_start, e_end;
1092 	vm_ooffset_t off = 0;
1093 	vm_prot_t e_prot;
1094 	unsigned int last_timestamp;
1095 	char *name = "", *freename = NULL;
1096 	ino_t ino;
1097 	int ref_count, shadow_count, flags;
1098 	int error;
1099 	struct vnode *vp;
1100 	struct vattr vat;
1101 	int locked;
1102 
1103 	PROC_LOCK(p);
1104 	error = p_candebug(td, p);
1105 	PROC_UNLOCK(p);
1106 	if (error)
1107 		return (error);
1108 
1109 	if (uio->uio_rw != UIO_READ)
1110 		return (EOPNOTSUPP);
1111 
1112 	error = 0;
1113 	vm = vmspace_acquire_ref(p);
1114 	if (vm == NULL)
1115 		return (ESRCH);
1116 	map = &vm->vm_map;
1117 	vm_map_lock_read(map);
1118 	for (entry = map->header.next; entry != &map->header;
1119 	    entry = entry->next) {
1120 		name = "";
1121 		freename = NULL;
1122 		if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
1123 			continue;
1124 		e_prot = entry->protection;
1125 		e_start = entry->start;
1126 		e_end = entry->end;
1127 		obj = entry->object.vm_object;
1128 		for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) {
1129 			VM_OBJECT_LOCK(tobj);
1130 			if (lobj != obj)
1131 				VM_OBJECT_UNLOCK(lobj);
1132 			lobj = tobj;
1133 		}
1134 		last_timestamp = map->timestamp;
1135 		vm_map_unlock_read(map);
1136 		ino = 0;
1137 		if (lobj) {
1138 			off = IDX_TO_OFF(lobj->size);
1139 			if (lobj->type == OBJT_VNODE) {
1140 				vp = lobj->handle;
1141 				if (vp)
1142 					vref(vp);
1143 			}
1144 			else
1145 				vp = NULL;
1146 			if (lobj != obj)
1147 				VM_OBJECT_UNLOCK(lobj);
1148 			flags = obj->flags;
1149 			ref_count = obj->ref_count;
1150 			shadow_count = obj->shadow_count;
1151 			VM_OBJECT_UNLOCK(obj);
1152 			if (vp) {
1153 				vn_fullpath(td, vp, &name, &freename);
1154 				locked = VFS_LOCK_GIANT(vp->v_mount);
1155 				vn_lock(vp, LK_SHARED | LK_RETRY);
1156 				VOP_GETATTR(vp, &vat, td->td_ucred);
1157 				ino = vat.va_fileid;
1158 				vput(vp);
1159 				VFS_UNLOCK_GIANT(locked);
1160 			}
1161 		} else {
1162 			flags = 0;
1163 			ref_count = 0;
1164 			shadow_count = 0;
1165 		}
1166 
1167 		/*
1168 		 * format:
1169 		 *  start, end, access, offset, major, minor, inode, name.
1170 		 */
1171 		error = sbuf_printf(sb,
1172 		    "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n",
1173 		    (u_long)e_start, (u_long)e_end,
1174 		    (e_prot & VM_PROT_READ)?"r":"-",
1175 		    (e_prot & VM_PROT_WRITE)?"w":"-",
1176 		    (e_prot & VM_PROT_EXECUTE)?"x":"-",
1177 		    "p",
1178 		    (u_long)off,
1179 		    0,
1180 		    0,
1181 		    (u_long)ino,
1182 		    *name ? "     " : "",
1183 		    name
1184 		    );
1185 		if (freename)
1186 			free(freename, M_TEMP);
1187 		vm_map_lock_read(map);
1188 		if (error == -1) {
1189 			error = 0;
1190 			break;
1191 		}
1192 		if (last_timestamp != map->timestamp) {
1193 			/*
1194 			 * Look again for the entry because the map was
1195 			 * modified while it was unlocked.  Specifically,
1196 			 * the entry may have been clipped, merged, or deleted.
1197 			 */
1198 			vm_map_lookup_entry(map, e_end - 1, &tmp_entry);
1199 			entry = tmp_entry;
1200 		}
1201 	}
1202 	vm_map_unlock_read(map);
1203 	vmspace_free(vm);
1204 
1205 	return (error);
1206 }
1207 
1208 /*
1209  * Filler function for proc/net/dev
1210  */
1211 static int
1212 linprocfs_donetdev(PFS_FILL_ARGS)
1213 {
1214 	char ifname[16]; /* XXX LINUX_IFNAMSIZ */
1215 	struct ifnet *ifp;
1216 
1217 	sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n",
1218 	    "Inter-", "   Receive", "  Transmit", " face",
1219 	    "bytes    packets errs drop fifo frame compressed",
1220 	    "bytes    packets errs drop fifo frame compressed");
1221 
1222 	CURVNET_SET(TD_TO_VNET(curthread));
1223 	IFNET_RLOCK();
1224 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
1225 		linux_ifname(ifp, ifname, sizeof ifname);
1226 			sbuf_printf(sb, "%6.6s:", ifname);
1227 		sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ",
1228 		    0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
1229 		sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
1230 		    0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
1231 	}
1232 	IFNET_RUNLOCK();
1233 	CURVNET_RESTORE();
1234 
1235 	return (0);
1236 }
1237 
1238 /*
1239  * Filler function for proc/sys/kernel/osrelease
1240  */
1241 static int
1242 linprocfs_doosrelease(PFS_FILL_ARGS)
1243 {
1244 	char osrelease[LINUX_MAX_UTSNAME];
1245 
1246 	linux_get_osrelease(td, osrelease);
1247 	sbuf_printf(sb, "%s\n", osrelease);
1248 
1249 	return (0);
1250 }
1251 
1252 /*
1253  * Filler function for proc/sys/kernel/ostype
1254  */
1255 static int
1256 linprocfs_doostype(PFS_FILL_ARGS)
1257 {
1258 	char osname[LINUX_MAX_UTSNAME];
1259 
1260 	linux_get_osname(td, osname);
1261 	sbuf_printf(sb, "%s\n", osname);
1262 
1263 	return (0);
1264 }
1265 
1266 /*
1267  * Filler function for proc/sys/kernel/version
1268  */
1269 static int
1270 linprocfs_doosbuild(PFS_FILL_ARGS)
1271 {
1272 
1273 	linprocfs_osbuild(td, sb);
1274 	sbuf_cat(sb, "\n");
1275 	return (0);
1276 }
1277 
1278 /*
1279  * Filler function for proc/sys/kernel/msgmni
1280  */
1281 static int
1282 linprocfs_domsgmni(PFS_FILL_ARGS)
1283 {
1284 
1285 	sbuf_printf(sb, "%d\n", msginfo.msgmni);
1286 	return (0);
1287 }
1288 
1289 /*
1290  * Filler function for proc/sys/kernel/pid_max
1291  */
1292 static int
1293 linprocfs_dopid_max(PFS_FILL_ARGS)
1294 {
1295 
1296 	sbuf_printf(sb, "%i\n", PID_MAX);
1297 	return (0);
1298 }
1299 
1300 /*
1301  * Filler function for proc/sys/kernel/sem
1302  */
1303 static int
1304 linprocfs_dosem(PFS_FILL_ARGS)
1305 {
1306 
1307 	sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns,
1308 	    seminfo.semopm, seminfo.semmni);
1309 	return (0);
1310 }
1311 
1312 /*
1313  * Filler function for proc/scsi/device_info
1314  */
1315 static int
1316 linprocfs_doscsidevinfo(PFS_FILL_ARGS)
1317 {
1318 
1319 	return (0);
1320 }
1321 
1322 /*
1323  * Filler function for proc/scsi/scsi
1324  */
1325 static int
1326 linprocfs_doscsiscsi(PFS_FILL_ARGS)
1327 {
1328 
1329 	return (0);
1330 }
1331 
1332 extern struct cdevsw *cdevsw[];
1333 
1334 /*
1335  * Filler function for proc/devices
1336  */
1337 static int
1338 linprocfs_dodevices(PFS_FILL_ARGS)
1339 {
1340 	char *char_devices;
1341 	sbuf_printf(sb, "Character devices:\n");
1342 
1343 	char_devices = linux_get_char_devices();
1344 	sbuf_printf(sb, "%s", char_devices);
1345 	linux_free_get_char_devices(char_devices);
1346 
1347 	sbuf_printf(sb, "\nBlock devices:\n");
1348 
1349 	return (0);
1350 }
1351 
1352 /*
1353  * Filler function for proc/cmdline
1354  */
1355 static int
1356 linprocfs_docmdline(PFS_FILL_ARGS)
1357 {
1358 
1359 	sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
1360 	sbuf_printf(sb, " ro root=302\n");
1361 	return (0);
1362 }
1363 
1364 /*
1365  * Filler function for proc/filesystems
1366  */
1367 static int
1368 linprocfs_dofilesystems(PFS_FILL_ARGS)
1369 {
1370 	struct vfsconf *vfsp;
1371 
1372 	mtx_lock(&Giant);
1373 	TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
1374 		if (vfsp->vfc_flags & VFCF_SYNTHETIC)
1375 			sbuf_printf(sb, "nodev");
1376 		sbuf_printf(sb, "\t%s\n", vfsp->vfc_name);
1377 	}
1378 	mtx_unlock(&Giant);
1379 	return(0);
1380 }
1381 
1382 #if 0
1383 /*
1384  * Filler function for proc/modules
1385  */
1386 static int
1387 linprocfs_domodules(PFS_FILL_ARGS)
1388 {
1389 	struct linker_file *lf;
1390 
1391 	TAILQ_FOREACH(lf, &linker_files, link) {
1392 		sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
1393 		    (unsigned long)lf->size, lf->refs);
1394 	}
1395 	return (0);
1396 }
1397 #endif
1398 
1399 /*
1400  * Filler function for proc/pid/fd
1401  */
1402 static int
1403 linprocfs_dofdescfs(PFS_FILL_ARGS)
1404 {
1405 
1406 	if (p == curproc)
1407 		sbuf_printf(sb, "/dev/fd");
1408 	else
1409 		sbuf_printf(sb, "unknown");
1410 	return (0);
1411 }
1412 
1413 /*
1414  * Constructor
1415  */
1416 static int
1417 linprocfs_init(PFS_INIT_ARGS)
1418 {
1419 	struct pfs_node *root;
1420 	struct pfs_node *dir;
1421 
1422 	root = pi->pi_root;
1423 
1424 	/* /proc/... */
1425 	pfs_create_file(root, "cmdline", &linprocfs_docmdline,
1426 	    NULL, NULL, NULL, PFS_RD);
1427 	pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
1428 	    NULL, NULL, NULL, PFS_RD);
1429 	pfs_create_file(root, "devices", &linprocfs_dodevices,
1430 	    NULL, NULL, NULL, PFS_RD);
1431 	pfs_create_file(root, "filesystems", &linprocfs_dofilesystems,
1432 	    NULL, NULL, NULL, PFS_RD);
1433 	pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
1434 	    NULL, NULL, NULL, PFS_RD);
1435 	pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
1436 	    NULL, NULL, NULL, PFS_RD);
1437 #if 0
1438 	pfs_create_file(root, "modules", &linprocfs_domodules,
1439 	    NULL, NULL, NULL, PFS_RD);
1440 #endif
1441 	pfs_create_file(root, "mounts", &linprocfs_domtab,
1442 	    NULL, NULL, NULL, PFS_RD);
1443 	pfs_create_file(root, "mtab", &linprocfs_domtab,
1444 	    NULL, NULL, NULL, PFS_RD);
1445 	pfs_create_file(root, "partitions", &linprocfs_dopartitions,
1446 	    NULL, NULL, NULL, PFS_RD);
1447 	pfs_create_link(root, "self", &procfs_docurproc,
1448 	    NULL, NULL, NULL, 0);
1449 	pfs_create_file(root, "stat", &linprocfs_dostat,
1450 	    NULL, NULL, NULL, PFS_RD);
1451 	pfs_create_file(root, "uptime", &linprocfs_douptime,
1452 	    NULL, NULL, NULL, PFS_RD);
1453 	pfs_create_file(root, "version", &linprocfs_doversion,
1454 	    NULL, NULL, NULL, PFS_RD);
1455 
1456 	/* /proc/net/... */
1457 	dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
1458 	pfs_create_file(dir, "dev", &linprocfs_donetdev,
1459 	    NULL, NULL, NULL, PFS_RD);
1460 
1461 	/* /proc/<pid>/... */
1462 	dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
1463 	pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
1464 	    NULL, NULL, NULL, PFS_RD);
1465 	pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
1466 	    NULL, NULL, NULL, 0);
1467 	pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
1468 	    NULL, NULL, NULL, PFS_RD);
1469 	pfs_create_link(dir, "exe", &procfs_doprocfile,
1470 	    NULL, &procfs_notsystem, NULL, 0);
1471 	pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
1472 	    NULL, NULL, NULL, PFS_RD);
1473 	pfs_create_file(dir, "mem", &procfs_doprocmem,
1474 	    &procfs_attr, &procfs_candebug, NULL, PFS_RDWR|PFS_RAW);
1475 	pfs_create_link(dir, "root", &linprocfs_doprocroot,
1476 	    NULL, NULL, NULL, 0);
1477 	pfs_create_file(dir, "stat", &linprocfs_doprocstat,
1478 	    NULL, NULL, NULL, PFS_RD);
1479 	pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
1480 	    NULL, NULL, NULL, PFS_RD);
1481 	pfs_create_file(dir, "status", &linprocfs_doprocstatus,
1482 	    NULL, NULL, NULL, PFS_RD);
1483 	pfs_create_link(dir, "fd", &linprocfs_dofdescfs,
1484 	    NULL, NULL, NULL, 0);
1485 
1486 	/* /proc/scsi/... */
1487 	dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
1488 	pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
1489 	    NULL, NULL, NULL, PFS_RD);
1490 	pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
1491 	    NULL, NULL, NULL, PFS_RD);
1492 
1493 	/* /proc/sys/... */
1494 	dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
1495 	/* /proc/sys/kernel/... */
1496 	dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0);
1497 	pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
1498 	    NULL, NULL, NULL, PFS_RD);
1499 	pfs_create_file(dir, "ostype", &linprocfs_doostype,
1500 	    NULL, NULL, NULL, PFS_RD);
1501 	pfs_create_file(dir, "version", &linprocfs_doosbuild,
1502 	    NULL, NULL, NULL, PFS_RD);
1503 	pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
1504 	    NULL, NULL, NULL, PFS_RD);
1505 	pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
1506 	    NULL, NULL, NULL, PFS_RD);
1507 	pfs_create_file(dir, "sem", &linprocfs_dosem,
1508 	    NULL, NULL, NULL, PFS_RD);
1509 
1510 	return (0);
1511 }
1512 
1513 /*
1514  * Destructor
1515  */
1516 static int
1517 linprocfs_uninit(PFS_INIT_ARGS)
1518 {
1519 
1520 	/* nothing to do, pseudofs will GC */
1521 	return (0);
1522 }
1523 
1524 PSEUDOFS(linprocfs, 1);
1525 MODULE_DEPEND(linprocfs, linux, 1, 1, 1);
1526 MODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
1527 MODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);
1528 MODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1);
1529