1139743Simp/*-
2184691Sdes * Copyright (c) 2000 Dag-Erling Co��dan Sm��rgrav
365577Sdes * Copyright (c) 1999 Pierre Beyssac
459412Smsmith * Copyright (c) 1993 Jan-Simon Pendry
559412Smsmith * Copyright (c) 1993
659412Smsmith *	The Regents of the University of California.  All rights reserved.
759412Smsmith *
859412Smsmith * This code is derived from software contributed to Berkeley by
959412Smsmith * Jan-Simon Pendry.
1059412Smsmith *
1159412Smsmith * Redistribution and use in source and binary forms, with or without
1259412Smsmith * modification, are permitted provided that the following conditions
1359412Smsmith * are met:
1459412Smsmith * 1. Redistributions of source code must retain the above copyright
1559412Smsmith *    notice, this list of conditions and the following disclaimer.
1659412Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1759412Smsmith *    notice, this list of conditions and the following disclaimer in the
1859412Smsmith *    documentation and/or other materials provided with the distribution.
1959412Smsmith * 3. All advertising materials mentioning features or use of this software
2059412Smsmith *    must display the following acknowledgement:
2159412Smsmith *	This product includes software developed by the University of
2259412Smsmith *	California, Berkeley and its contributors.
2359412Smsmith * 4. Neither the name of the University nor the names of its contributors
2459412Smsmith *    may be used to endorse or promote products derived from this software
2559412Smsmith *    without specific prior written permission.
2659412Smsmith *
2759412Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2859412Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2959412Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3059412Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3159412Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3259412Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3359412Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3459412Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3559412Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3659412Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3759412Smsmith * SUCH DAMAGE.
3859412Smsmith *
3959412Smsmith *	@(#)procfs_status.c	8.4 (Berkeley) 6/15/94
4059412Smsmith */
4159412Smsmith
42182141Sjulian#include "opt_compat.h"
43182141Sjulian
44116173Sobrien#include <sys/cdefs.h>
45116173Sobrien__FBSDID("$FreeBSD$");
46116173Sobrien
4759412Smsmith#include <sys/param.h>
4883926Sdes#include <sys/queue.h>
4976166Smarkm#include <sys/blist.h>
5074135Sjlemon#include <sys/conf.h>
5183926Sdes#include <sys/exec.h>
52177785Skib#include <sys/fcntl.h>
53119911Sdes#include <sys/filedesc.h>
5476166Smarkm#include <sys/jail.h>
5565633Sdes#include <sys/kernel.h>
5683926Sdes#include <sys/linker.h>
5776166Smarkm#include <sys/lock.h>
5874135Sjlemon#include <sys/malloc.h>
5978025Sdes#include <sys/mount.h>
60168067Sjkim#include <sys/msg.h>
6176827Salfred#include <sys/mutex.h>
6285289Sdes#include <sys/namei.h>
6365633Sdes#include <sys/proc.h>
64213246Skib#include <sys/ptrace.h>
6565633Sdes#include <sys/resourcevar.h>
6669995Sdes#include <sys/sbuf.h>
67168067Sjkim#include <sys/sem.h>
68123246Sdes#include <sys/smp.h>
6983926Sdes#include <sys/socket.h>
7076839Sjlemon#include <sys/sysctl.h>
7183926Sdes#include <sys/systm.h>
72159995Snetchild#include <sys/time.h>
7365633Sdes#include <sys/tty.h>
7483926Sdes#include <sys/user.h>
7583926Sdes#include <sys/vmmeter.h>
7659412Smsmith#include <sys/vnode.h>
77190445Sambrisko#include <sys/bus.h>
7859412Smsmith
7983926Sdes#include <net/if.h>
80185571Sbz#include <net/vnet.h>
8183926Sdes
8259412Smsmith#include <vm/vm.h>
83185984Skib#include <vm/vm_extern.h>
8459412Smsmith#include <vm/pmap.h>
8567588Sdes#include <vm/vm_map.h>
8659412Smsmith#include <vm/vm_param.h>
8760860Sdes#include <vm/vm_object.h>
8859412Smsmith#include <vm/swap_pager.h>
8969799Sdes
9067589Sdes#include <machine/clock.h>
9178113Sdes
92190445Sambrisko#include <geom/geom.h>
93190445Sambrisko#include <geom/geom_int.h>
94190445Sambrisko
95133822Stjr#if defined(__i386__) || defined(__amd64__)
9667589Sdes#include <machine/cputypes.h>
9759412Smsmith#include <machine/md_var.h>
98133822Stjr#endif /* __i386__ || __amd64__ */
9959412Smsmith
100213246Skib#ifdef COMPAT_FREEBSD32
101213246Skib#include <compat/freebsd32/freebsd32_util.h>
102213246Skib#endif
103213246Skib
10485129Sdes#include <compat/linux/linux_ioctl.h>
10569995Sdes#include <compat/linux/linux_mib.h>
106246085Sjhb#include <compat/linux/linux_misc.h>
10785289Sdes#include <compat/linux/linux_util.h>
10878025Sdes#include <fs/pseudofs/pseudofs.h>
10984248Sdes#include <fs/procfs/procfs.h>
11059412Smsmith
11167588Sdes/*
11267588Sdes * Various conversion macros
11367588Sdes */
114206081Snetchild#define T2J(x) ((long)(((x) * 100ULL) / (stathz ? stathz : hz)))	/* ticks to jiffies */
115206081Snetchild#define T2CS(x) ((unsigned long)(((x) * 100ULL) / (stathz ? stathz : hz)))	/* ticks to centiseconds */
11667588Sdes#define T2S(x) ((x) / (stathz ? stathz : hz))		/* ticks to seconds */
11767588Sdes#define B2K(x) ((x) >> 10)				/* bytes to kbytes */
11869799Sdes#define B2P(x) ((x) >> PAGE_SHIFT)			/* bytes to pages */
11967588Sdes#define P2B(x) ((x) << PAGE_SHIFT)			/* pages to bytes */
12067588Sdes#define P2K(x) ((x) << (PAGE_SHIFT - 10))		/* pages to kbytes */
121206081Snetchild#define TV2J(x)	((x)->tv_sec * 100UL + (x)->tv_usec / 10000)
12274135Sjlemon
123159995Snetchild/**
124159995Snetchild * @brief Mapping of ki_stat in struct kinfo_proc to the linux state
125159995Snetchild *
126159995Snetchild * The linux procfs state field displays one of the characters RSDZTW to
127159995Snetchild * denote running, sleeping in an interruptible wait, waiting in an
128172568Skevlo * uninterruptible disk sleep, a zombie process, process is being traced
129159995Snetchild * or stopped, or process is paging respectively.
130159995Snetchild *
131159995Snetchild * Our struct kinfo_proc contains the variable ki_stat which contains a
132159995Snetchild * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK.
133159995Snetchild *
134159995Snetchild * This character array is used with ki_stati-1 as an index and tries to
135159995Snetchild * map our states to suitable linux states.
136159995Snetchild */
137166140Snetchildstatic char linux_state[] = "RRSTZDD";
138159995Snetchild
13978113Sdes/*
14078113Sdes * Filler function for proc/meminfo
14178113Sdes */
14278025Sdesstatic int
14378025Sdeslinprocfs_domeminfo(PFS_FILL_ARGS)
14459412Smsmith{
14559412Smsmith	unsigned long memtotal;		/* total memory in bytes */
14659412Smsmith	unsigned long memused;		/* used memory in bytes */
14759412Smsmith	unsigned long memfree;		/* free memory in bytes */
14859412Smsmith	unsigned long memshared;	/* shared memory ??? */
14959412Smsmith	unsigned long buffers, cached;	/* buffer / cache memory ??? */
150113574Sjhb	unsigned long long swaptotal;	/* total swap space in bytes */
151113574Sjhb	unsigned long long swapused;	/* used swap space in bytes */
152113574Sjhb	unsigned long long swapfree;	/* free swap space in bytes */
15360860Sdes	vm_object_t object;
154117723Sphk	int i, j;
15559412Smsmith
15659412Smsmith	memtotal = physmem * PAGE_SIZE;
15759412Smsmith	/*
15859412Smsmith	 * The correct thing here would be:
15959412Smsmith	 *
160170170Sattilio	memfree = cnt.v_free_count * PAGE_SIZE;
16159412Smsmith	memused = memtotal - memfree;
16259412Smsmith	 *
16359412Smsmith	 * but it might mislead linux binaries into thinking there
16459412Smsmith	 * is very little memory left, so we cheat and tell them that
16559412Smsmith	 * all memory that isn't wired down is free.
16659412Smsmith	 */
167170170Sattilio	memused = cnt.v_wire_count * PAGE_SIZE;
16859412Smsmith	memfree = memtotal - memused;
169117723Sphk	swap_pager_status(&i, &j);
170153310Smlaier	swaptotal = (unsigned long long)i * PAGE_SIZE;
171153310Smlaier	swapused = (unsigned long long)j * PAGE_SIZE;
172117723Sphk	swapfree = swaptotal - swapused;
17360860Sdes	memshared = 0;
174124082Salc	mtx_lock(&vm_object_list_mtx);
17571471Sjhb	TAILQ_FOREACH(object, &vm_object_list, object_list)
17660860Sdes		if (object->shadow_count > 1)
17760860Sdes			memshared += object->resident_page_count;
178124082Salc	mtx_unlock(&vm_object_list_mtx);
17960860Sdes	memshared *= PAGE_SIZE;
18059412Smsmith	/*
18159412Smsmith	 * We'd love to be able to write:
18259412Smsmith	 *
18359412Smsmith	buffers = bufspace;
18459412Smsmith	 *
18559412Smsmith	 * but bufspace is internal to vfs_bio.c and we don't feel
18659412Smsmith	 * like unstaticizing it just for linprocfs's sake.
18759412Smsmith	 */
18859412Smsmith	buffers = 0;
189170170Sattilio	cached = cnt.v_cache_count * PAGE_SIZE;
19059412Smsmith
19178025Sdes	sbuf_printf(sb,
19278031Sdes	    "	     total:    used:	free:  shared: buffers:	 cached:\n"
19369799Sdes	    "Mem:  %lu %lu %lu %lu %lu %lu\n"
19476839Sjlemon	    "Swap: %llu %llu %llu\n"
19569799Sdes	    "MemTotal: %9lu kB\n"
19669799Sdes	    "MemFree:  %9lu kB\n"
19769799Sdes	    "MemShared:%9lu kB\n"
19869799Sdes	    "Buffers:  %9lu kB\n"
19969799Sdes	    "Cached:   %9lu kB\n"
20076839Sjlemon	    "SwapTotal:%9llu kB\n"
20176839Sjlemon	    "SwapFree: %9llu kB\n",
20269799Sdes	    memtotal, memused, memfree, memshared, buffers, cached,
20369799Sdes	    swaptotal, swapused, swapfree,
20469799Sdes	    B2K(memtotal), B2K(memfree),
20569799Sdes	    B2K(memshared), B2K(buffers), B2K(cached),
20669799Sdes	    B2K(swaptotal), B2K(swapfree));
20759412Smsmith
20878025Sdes	return (0);
20959412Smsmith}
21059412Smsmith
211133822Stjr#if defined(__i386__) || defined(__amd64__)
21278113Sdes/*
213133822Stjr * Filler function for proc/cpuinfo (i386 & amd64 version)
21478113Sdes */
21578113Sdesstatic int
21678113Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS)
21778113Sdes{
218159544Sdes	int hw_model[2];
219159544Sdes	char model[128];
220220433Sjkim	uint64_t freq;
221159544Sdes	size_t size;
222123246Sdes	int class, fqmhz, fqkhz;
223118421Sdes	int i;
22459412Smsmith
22569799Sdes	/*
22678031Sdes	 * We default the flags to include all non-conflicting flags,
22778031Sdes	 * and the Intel versions of conflicting flags.
22869799Sdes	 */
22978031Sdes	static char *flags[] = {
23078031Sdes		"fpu",	    "vme",     "de",	   "pse",      "tsc",
23178031Sdes		"msr",	    "pae",     "mce",	   "cx8",      "apic",
23278031Sdes		"sep",	    "sep",     "mtrr",	   "pge",      "mca",
23378031Sdes		"cmov",	    "pat",     "pse36",	   "pn",       "b19",
23478031Sdes		"b20",	    "b21",     "mmxext",   "mmx",      "fxsr",
235183385Scognet		"xmm",	    "sse2",    "b27",	   "b28",      "b29",
23667589Sdes		"3dnowext", "3dnow"
23767589Sdes	};
23867589Sdes
23959412Smsmith	switch (cpu_class) {
240133822Stjr#ifdef __i386__
24159412Smsmith	case CPUCLASS_286:
24267589Sdes		class = 2;
24359412Smsmith		break;
24459412Smsmith	case CPUCLASS_386:
24567589Sdes		class = 3;
24659412Smsmith		break;
24759412Smsmith	case CPUCLASS_486:
24867589Sdes		class = 4;
24959412Smsmith		break;
25059412Smsmith	case CPUCLASS_586:
25167589Sdes		class = 5;
25259412Smsmith		break;
25359412Smsmith	case CPUCLASS_686:
25467589Sdes		class = 6;
25559412Smsmith		break;
25659412Smsmith	default:
25778031Sdes		class = 0;
25859412Smsmith		break;
259159170Sdes#else /* __amd64__ */
260133822Stjr	default:
261159170Sdes		class = 15;
262133822Stjr		break;
263133822Stjr#endif
26459412Smsmith	}
26559412Smsmith
266159544Sdes	hw_model[0] = CTL_HW;
267159544Sdes	hw_model[1] = HW_MODEL;
268159544Sdes	model[0] = '\0';
269159544Sdes	size = sizeof(model);
270159544Sdes	if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0)
271159544Sdes		strcpy(model, "unknown");
272123246Sdes	for (i = 0; i < mp_ncpus; ++i) {
273118421Sdes		sbuf_printf(sb,
274118421Sdes		    "processor\t: %d\n"
275118421Sdes		    "vendor_id\t: %.20s\n"
276214982Sdes		    "cpu family\t: %u\n"
277214982Sdes		    "model\t\t: %u\n"
278159544Sdes		    "model name\t: %s\n"
279214982Sdes		    "stepping\t: %u\n\n",
280214985Sdes		    i, cpu_vendor, CPUID_TO_FAMILY(cpu_id),
281214985Sdes		    CPUID_TO_MODEL(cpu_id), model, cpu_id & CPUID_STEPPING);
282159544Sdes		/* XXX per-cpu vendor / class / model / id? */
283118421Sdes	}
28459412Smsmith
285185766Skib	sbuf_cat(sb, "flags\t\t:");
28667589Sdes
287187594Sjkim#ifdef __i386__
288187594Sjkim	switch (cpu_vendor_id) {
289187594Sjkim	case CPU_VENDOR_AMD:
290187594Sjkim		if (class < 6)
291187594Sjkim			flags[16] = "fcmov";
292187594Sjkim		break;
293187594Sjkim	case CPU_VENDOR_CYRIX:
29467589Sdes		flags[24] = "cxmmx";
295187594Sjkim		break;
29678031Sdes	}
297187594Sjkim#endif
298119068Sdes
29978031Sdes	for (i = 0; i < 32; i++)
30067589Sdes		if (cpu_feature & (1 << i))
30178025Sdes			sbuf_printf(sb, " %s", flags[i]);
30278025Sdes	sbuf_cat(sb, "\n");
303220433Sjkim	freq = atomic_load_acq_64(&tsc_freq);
304220433Sjkim	if (freq != 0) {
305220433Sjkim		fqmhz = (freq + 4999) / 1000000;
306220433Sjkim		fqkhz = ((freq + 4999) / 10000) % 100;
30778025Sdes		sbuf_printf(sb,
30869799Sdes		    "cpu MHz\t\t: %d.%02d\n"
30969799Sdes		    "bogomips\t: %d.%02d\n",
31069799Sdes		    fqmhz, fqkhz, fqmhz, fqkhz);
31178031Sdes	}
31269995Sdes
31378025Sdes	return (0);
31459412Smsmith}
315133822Stjr#endif /* __i386__ || __amd64__ */
31665633Sdes
31778113Sdes/*
31885289Sdes * Filler function for proc/mtab
31985289Sdes *
32085289Sdes * This file doesn't exist in Linux' procfs, but is included here so
32185289Sdes * users can symlink /compat/linux/etc/mtab to /proc/mtab
32285289Sdes */
32385289Sdesstatic int
32485289Sdeslinprocfs_domtab(PFS_FILL_ARGS)
32585289Sdes{
32685289Sdes	struct nameidata nd;
32785289Sdes	struct mount *mp;
32891334Sjulian	const char *lep;
32991334Sjulian	char *dlep, *flep, *mntto, *mntfrom, *fstype;
33085289Sdes	size_t lep_len;
33185289Sdes	int error;
33285289Sdes
33385289Sdes	/* resolve symlinks etc. in the emulation tree prefix */
334241896Skib	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td);
33585289Sdes	flep = NULL;
336168942Sdes	error = namei(&nd);
337184649Sjhb	lep = linux_emul_path;
338184649Sjhb	if (error == 0) {
339188579Sjhb		if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
340184649Sjhb			lep = dlep;
341184649Sjhb		vrele(nd.ni_vp);
342184649Sjhb	}
34385289Sdes	lep_len = strlen(lep);
344119068Sdes
34585289Sdes	mtx_lock(&mountlist_mtx);
34685289Sdes	error = 0;
34785289Sdes	TAILQ_FOREACH(mp, &mountlist, mnt_list) {
34885289Sdes		/* determine device name */
34985289Sdes		mntfrom = mp->mnt_stat.f_mntfromname;
350119068Sdes
35185289Sdes		/* determine mount point */
35285289Sdes		mntto = mp->mnt_stat.f_mntonname;
35385289Sdes		if (strncmp(mntto, lep, lep_len) == 0 &&
35485289Sdes		    mntto[lep_len] == '/')
35585289Sdes			mntto += lep_len;
35685289Sdes
35785289Sdes		/* determine fs type */
35885289Sdes		fstype = mp->mnt_stat.f_fstypename;
35985289Sdes		if (strcmp(fstype, pn->pn_info->pi_name) == 0)
36085289Sdes			mntfrom = fstype = "proc";
36185289Sdes		else if (strcmp(fstype, "procfs") == 0)
36285289Sdes			continue;
363119068Sdes
364158311Sambrisko		if (strcmp(fstype, "linsysfs") == 0) {
365158311Sambrisko			sbuf_printf(sb, "/sys %s sysfs %s", mntto,
366158311Sambrisko			    mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
367158311Sambrisko		} else {
368190445Sambrisko			/* For Linux msdosfs is called vfat */
369190445Sambrisko			if (strcmp(fstype, "msdosfs") == 0)
370190445Sambrisko				fstype = "vfat";
371158311Sambrisko			sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
372158311Sambrisko			    mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
373158311Sambrisko		}
37485289Sdes#define ADD_OPTION(opt, name) \
37585289Sdes	if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name);
37685289Sdes		ADD_OPTION(MNT_SYNCHRONOUS,	"sync");
37785289Sdes		ADD_OPTION(MNT_NOEXEC,		"noexec");
37885289Sdes		ADD_OPTION(MNT_NOSUID,		"nosuid");
37985289Sdes		ADD_OPTION(MNT_UNION,		"union");
38085289Sdes		ADD_OPTION(MNT_ASYNC,		"async");
38185289Sdes		ADD_OPTION(MNT_SUIDDIR,		"suiddir");
38285289Sdes		ADD_OPTION(MNT_NOSYMFOLLOW,	"nosymfollow");
38385289Sdes		ADD_OPTION(MNT_NOATIME,		"noatime");
38485289Sdes#undef ADD_OPTION
38585289Sdes		/* a real Linux mtab will also show NFS options */
38685289Sdes		sbuf_printf(sb, " 0 0\n");
38785289Sdes	}
38885289Sdes	mtx_unlock(&mountlist_mtx);
389247764Seadler	free(flep, M_TEMP);
39085289Sdes	return (error);
39185289Sdes}
39285289Sdes
39385289Sdes/*
394190445Sambrisko * Filler function for proc/partitions
395190445Sambrisko *
396190445Sambrisko */
397190445Sambriskostatic int
398190445Sambriskolinprocfs_dopartitions(PFS_FILL_ARGS)
399190445Sambrisko{
400190445Sambrisko	struct g_class *cp;
401190445Sambrisko	struct g_geom *gp;
402190445Sambrisko	struct g_provider *pp;
403190445Sambrisko	struct nameidata nd;
404190445Sambrisko	const char *lep;
405190445Sambrisko	char  *dlep, *flep;
406190445Sambrisko	size_t lep_len;
407190445Sambrisko	int error;
408190445Sambrisko	int major, minor;
409190445Sambrisko
410190445Sambrisko	/* resolve symlinks etc. in the emulation tree prefix */
411241896Skib	NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td);
412190445Sambrisko	flep = NULL;
413190445Sambrisko	error = namei(&nd);
414190445Sambrisko	lep = linux_emul_path;
415190445Sambrisko	if (error == 0) {
416190445Sambrisko		if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
417190445Sambrisko			lep = dlep;
418190445Sambrisko		vrele(nd.ni_vp);
419190445Sambrisko	}
420190445Sambrisko	lep_len = strlen(lep);
421190445Sambrisko
422190445Sambrisko	g_topology_lock();
423190445Sambrisko	error = 0;
424190445Sambrisko	sbuf_printf(sb, "major minor  #blocks  name rio rmerge rsect "
425190445Sambrisko	    "ruse wio wmerge wsect wuse running use aveq\n");
426190445Sambrisko
427190445Sambrisko	LIST_FOREACH(cp, &g_classes, class) {
428190445Sambrisko		if (strcmp(cp->name, "DISK") == 0 ||
429190445Sambrisko		    strcmp(cp->name, "PART") == 0)
430190445Sambrisko			LIST_FOREACH(gp, &cp->geom, geom) {
431190445Sambrisko				LIST_FOREACH(pp, &gp->provider, provider) {
432190445Sambrisko					if (linux_driver_get_major_minor(
433190445Sambrisko					    pp->name, &major, &minor) != 0) {
434190445Sambrisko						major = 0;
435190445Sambrisko						minor = 0;
436190445Sambrisko					}
437190445Sambrisko					sbuf_printf(sb, "%d %d %lld %s "
438190445Sambrisko					    "%d %d %d %d %d "
439190445Sambrisko					     "%d %d %d %d %d %d\n",
440190445Sambrisko					     major, minor,
441190445Sambrisko					     (long long)pp->mediasize, pp->name,
442190445Sambrisko					     0, 0, 0, 0, 0,
443190445Sambrisko					     0, 0, 0, 0, 0, 0);
444190445Sambrisko				}
445190445Sambrisko			}
446190445Sambrisko	}
447190445Sambrisko	g_topology_unlock();
448190445Sambrisko
449247764Seadler	free(flep, M_TEMP);
450190445Sambrisko	return (error);
451190445Sambrisko}
452190445Sambrisko
453190445Sambrisko
454190445Sambrisko/*
45578113Sdes * Filler function for proc/stat
45678113Sdes */
45778025Sdesstatic int
45878025Sdeslinprocfs_dostat(PFS_FILL_ARGS)
45965633Sdes{
460174070Speter	struct pcpu *pcpu;
461174070Speter	long cp_time[CPUSTATES];
462174070Speter	long *cp;
463123246Sdes	int i;
464120339Sdes
465174070Speter	read_cpu_time(cp_time);
466120339Sdes	sbuf_printf(sb, "cpu %ld %ld %ld %ld\n",
467120339Sdes	    T2J(cp_time[CP_USER]),
468120339Sdes	    T2J(cp_time[CP_NICE]),
469120339Sdes	    T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
470120339Sdes	    T2J(cp_time[CP_IDLE]));
471209059Sjhb	CPU_FOREACH(i) {
472174070Speter		pcpu = pcpu_find(i);
473174070Speter		cp = pcpu->pc_cp_time;
474143194Ssobomax		sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i,
475174070Speter		    T2J(cp[CP_USER]),
476174070Speter		    T2J(cp[CP_NICE]),
477174070Speter		    T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/),
478174070Speter		    T2J(cp[CP_IDLE]));
479174070Speter	}
48078025Sdes	sbuf_printf(sb,
48169799Sdes	    "disk 0 0 0 0\n"
48269799Sdes	    "page %u %u\n"
48369799Sdes	    "swap %u %u\n"
48469799Sdes	    "intr %u\n"
48569799Sdes	    "ctxt %u\n"
48685657Sdillon	    "btime %lld\n",
487170170Sattilio	    cnt.v_vnodepgsin,
488170170Sattilio	    cnt.v_vnodepgsout,
489170170Sattilio	    cnt.v_swappgsin,
490170170Sattilio	    cnt.v_swappgsout,
491170170Sattilio	    cnt.v_intr,
492170170Sattilio	    cnt.v_swtch,
493113574Sjhb	    (long long)boottime.tv_sec);
49478025Sdes	return (0);
49565633Sdes}
49665633Sdes
497224582Skibstatic int
498224582Skiblinprocfs_doswaps(PFS_FILL_ARGS)
499224582Skib{
500224582Skib	struct xswdev xsw;
501224582Skib	uintmax_t total, used;
502224582Skib	int n;
503224582Skib	char devname[SPECNAMELEN + 1];
504224582Skib
505224582Skib	sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
506224582Skib	mtx_lock(&Giant);
507224582Skib	for (n = 0; ; n++) {
508224582Skib		if (swap_dev_info(n, &xsw, devname, sizeof(devname)) != 0)
509224582Skib			break;
510224582Skib		total = (uintmax_t)xsw.xsw_nblks * PAGE_SIZE / 1024;
511224582Skib		used  = (uintmax_t)xsw.xsw_used * PAGE_SIZE / 1024;
512224582Skib
513224582Skib		/*
514224582Skib		 * The space and not tab after the device name is on
515224582Skib		 * purpose.  Linux does so.
516224582Skib		 */
517224582Skib		sbuf_printf(sb, "/dev/%-34s unknown\t\t%jd\t%jd\t-1\n",
518224582Skib		    devname, total, used);
519224582Skib	}
520224582Skib	mtx_unlock(&Giant);
521224582Skib	return (0);
522224582Skib}
523224582Skib
52478113Sdes/*
52578113Sdes * Filler function for proc/uptime
52678113Sdes */
52778025Sdesstatic int
52878025Sdeslinprocfs_douptime(PFS_FILL_ARGS)
52965633Sdes{
530174070Speter	long cp_time[CPUSTATES];
53165633Sdes	struct timeval tv;
53265633Sdes
53365633Sdes	getmicrouptime(&tv);
534174070Speter	read_cpu_time(cp_time);
535206081Snetchild	sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n",
536113574Sjhb	    (long long)tv.tv_sec, tv.tv_usec / 10000,
537206081Snetchild	    T2S(cp_time[CP_IDLE] / mp_ncpus),
538206081Snetchild	    T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100);
53978025Sdes	return (0);
54065633Sdes}
54165633Sdes
54278113Sdes/*
543167159Sjkim * Get OS build date
544167159Sjkim */
545167159Sjkimstatic void
546167159Sjkimlinprocfs_osbuild(struct thread *td, struct sbuf *sb)
547167159Sjkim{
548167159Sjkim#if 0
549167159Sjkim	char osbuild[256];
550167159Sjkim	char *cp1, *cp2;
551167159Sjkim
552167159Sjkim	strncpy(osbuild, version, 256);
553167159Sjkim	osbuild[255] = '\0';
554167159Sjkim	cp1 = strstr(osbuild, "\n");
555167159Sjkim	cp2 = strstr(osbuild, ":");
556167159Sjkim	if (cp1 && cp2) {
557167159Sjkim		*cp1 = *cp2 = '\0';
558167159Sjkim		cp1 = strstr(osbuild, "#");
559167159Sjkim	} else
560167159Sjkim		cp1 = NULL;
561167159Sjkim	if (cp1)
562167159Sjkim		sbuf_printf(sb, "%s%s", cp1, cp2 + 1);
563167159Sjkim	else
564167159Sjkim#endif
565167159Sjkim		sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977");
566167159Sjkim}
567167159Sjkim
568167159Sjkim/*
569167159Sjkim * Get OS builder
570167159Sjkim */
571167159Sjkimstatic void
572167159Sjkimlinprocfs_osbuilder(struct thread *td, struct sbuf *sb)
573167159Sjkim{
574168762Sdes#if 0
575167159Sjkim	char builder[256];
576167159Sjkim	char *cp;
577167159Sjkim
578167159Sjkim	cp = strstr(version, "\n    ");
579167159Sjkim	if (cp) {
580167159Sjkim		strncpy(builder, cp + 5, 256);
581167159Sjkim		builder[255] = '\0';
582167159Sjkim		cp = strstr(builder, ":");
583167159Sjkim		if (cp)
584167159Sjkim			*cp = '\0';
585167159Sjkim	}
586167159Sjkim	if (cp)
587167159Sjkim		sbuf_cat(sb, builder);
588167159Sjkim	else
589168762Sdes#endif
590167159Sjkim		sbuf_cat(sb, "des@freebsd.org");
591167159Sjkim}
592167159Sjkim
593167159Sjkim/*
59478113Sdes * Filler function for proc/version
59578113Sdes */
59678025Sdesstatic int
59778025Sdeslinprocfs_doversion(PFS_FILL_ARGS)
59865633Sdes{
59987275Srwatson	char osname[LINUX_MAX_UTSNAME];
60087275Srwatson	char osrelease[LINUX_MAX_UTSNAME];
60187275Srwatson
602112206Sjhb	linux_get_osname(td, osname);
603112206Sjhb	linux_get_osrelease(td, osrelease);
604167159Sjkim	sbuf_printf(sb, "%s version %s (", osname, osrelease);
605167159Sjkim	linprocfs_osbuilder(td, sb);
606167159Sjkim	sbuf_cat(sb, ") (gcc version " __VERSION__ ") ");
607167159Sjkim	linprocfs_osbuild(td, sb);
608167159Sjkim	sbuf_cat(sb, "\n");
60987275Srwatson
61078025Sdes	return (0);
61165633Sdes}
61265633Sdes
61378113Sdes/*
61478113Sdes * Filler function for proc/loadavg
61578113Sdes */
61678025Sdesstatic int
61778025Sdeslinprocfs_doloadavg(PFS_FILL_ARGS)
61876839Sjlemon{
619168762Sdes
62078025Sdes	sbuf_printf(sb,
62176839Sjlemon	    "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
62276839Sjlemon	    (int)(averunnable.ldavg[0] / averunnable.fscale),
62376839Sjlemon	    (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
62476839Sjlemon	    (int)(averunnable.ldavg[1] / averunnable.fscale),
62576839Sjlemon	    (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
62676839Sjlemon	    (int)(averunnable.ldavg[2] / averunnable.fscale),
62776839Sjlemon	    (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
62876839Sjlemon	    1,				/* number of running tasks */
62976839Sjlemon	    nprocs,			/* number of tasks */
63078116Sdes	    lastpid			/* the last pid */
63176839Sjlemon	);
63278025Sdes	return (0);
63376839Sjlemon}
63476839Sjlemon
63578113Sdes/*
63678113Sdes * Filler function for proc/pid/stat
63778113Sdes */
63878025Sdesstatic int
63978025Sdeslinprocfs_doprocstat(PFS_FILL_ARGS)
64067588Sdes{
64169995Sdes	struct kinfo_proc kp;
642166140Snetchild	char state;
643166140Snetchild	static int ratelimit = 0;
644206081Snetchild	vm_offset_t startcode, startdata;
64567588Sdes
64694307Sjhb	PROC_LOCK(p);
64769995Sdes	fill_kinfo_proc(p, &kp);
648206081Snetchild	if (p->p_vmspace) {
649206081Snetchild	   startcode = (vm_offset_t)p->p_vmspace->vm_taddr;
650206081Snetchild	   startdata = (vm_offset_t)p->p_vmspace->vm_daddr;
651206081Snetchild	} else {
652206081Snetchild	   startcode = 0;
653206081Snetchild	   startdata = 0;
654206081Snetchild	};
65578025Sdes	sbuf_printf(sb, "%d", p->p_pid);
65678025Sdes#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
65767588Sdes	PS_ADD("comm",		"(%s)",	p->p_comm);
658166140Snetchild	if (kp.ki_stat > sizeof(linux_state)) {
659166140Snetchild		state = 'R';
660166140Snetchild
661166141Snetchild		if (ratelimit == 0) {
662166162Snetchild			printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n",
663166162Snetchild			    kp.ki_stat, sizeof(linux_state));
664166141Snetchild			++ratelimit;
665166141Snetchild		}
666166140Snetchild	} else
667166140Snetchild		state = linux_state[kp.ki_stat - 1];
668166140Snetchild	PS_ADD("state",		"%c",	state);
66973923Sjhb	PS_ADD("ppid",		"%d",	p->p_pptr ? p->p_pptr->p_pid : 0);
67067588Sdes	PS_ADD("pgrp",		"%d",	p->p_pgid);
67167588Sdes	PS_ADD("session",	"%d",	p->p_session->s_sid);
67291140Stanimura	PROC_UNLOCK(p);
673206081Snetchild	PS_ADD("tty",		"%d",	kp.ki_tdev);
674159995Snetchild	PS_ADD("tpgid",		"%d",	kp.ki_tpgid);
67567588Sdes	PS_ADD("flags",		"%u",	0); /* XXX */
676159995Snetchild	PS_ADD("minflt",	"%lu",	kp.ki_rusage.ru_minflt);
677159995Snetchild	PS_ADD("cminflt",	"%lu",	kp.ki_rusage_ch.ru_minflt);
678159995Snetchild	PS_ADD("majflt",	"%lu",	kp.ki_rusage.ru_majflt);
679159995Snetchild	PS_ADD("cmajflt",	"%lu",	kp.ki_rusage_ch.ru_majflt);
680206081Snetchild	PS_ADD("utime",		"%ld",	TV2J(&kp.ki_rusage.ru_utime));
681206081Snetchild	PS_ADD("stime",		"%ld",	TV2J(&kp.ki_rusage.ru_stime));
682206081Snetchild	PS_ADD("cutime",	"%ld",	TV2J(&kp.ki_rusage_ch.ru_utime));
683206081Snetchild	PS_ADD("cstime",	"%ld",	TV2J(&kp.ki_rusage_ch.ru_stime));
684159995Snetchild	PS_ADD("priority",	"%d",	kp.ki_pri.pri_user);
685159995Snetchild	PS_ADD("nice",		"%d",	kp.ki_nice); /* 19 (nicest) to -19 */
686159995Snetchild	PS_ADD("0",		"%d",	0); /* removed field */
687159995Snetchild	PS_ADD("itrealvalue",	"%d",	0); /* XXX */
688206081Snetchild	PS_ADD("starttime",	"%lu",	TV2J(&kp.ki_start) - TV2J(&boottime));
689159995Snetchild	PS_ADD("vsize",		"%ju",	P2K((uintmax_t)kp.ki_size));
690159995Snetchild	PS_ADD("rss",		"%ju",	(uintmax_t)kp.ki_rssize);
691159995Snetchild	PS_ADD("rlim",		"%lu",	kp.ki_rusage.ru_maxrss);
692206081Snetchild	PS_ADD("startcode",	"%ju",	(uintmax_t)startcode);
693206081Snetchild	PS_ADD("endcode",	"%ju",	(uintmax_t)startdata);
69467588Sdes	PS_ADD("startstack",	"%u",	0); /* XXX */
695159995Snetchild	PS_ADD("kstkesp",	"%u",	0); /* XXX */
696159995Snetchild	PS_ADD("kstkeip",	"%u",	0); /* XXX */
697159995Snetchild	PS_ADD("signal",	"%u",	0); /* XXX */
698159995Snetchild	PS_ADD("blocked",	"%u",	0); /* XXX */
699159995Snetchild	PS_ADD("sigignore",	"%u",	0); /* XXX */
700159995Snetchild	PS_ADD("sigcatch",	"%u",	0); /* XXX */
70167588Sdes	PS_ADD("wchan",		"%u",	0); /* XXX */
702159995Snetchild	PS_ADD("nswap",		"%lu",	kp.ki_rusage.ru_nswap);
703159995Snetchild	PS_ADD("cnswap",	"%lu",	kp.ki_rusage_ch.ru_nswap);
70469799Sdes	PS_ADD("exitsignal",	"%d",	0); /* XXX */
705159995Snetchild	PS_ADD("processor",	"%u",	kp.ki_lastcpu);
706159995Snetchild	PS_ADD("rt_priority",	"%u",	0); /* XXX */ /* >= 2.5.19 */
707159995Snetchild	PS_ADD("policy",	"%u",	kp.ki_pri.pri_class); /* >= 2.5.19 */
70867588Sdes#undef PS_ADD
70978025Sdes	sbuf_putc(sb, '\n');
710119068Sdes
71178025Sdes	return (0);
71267588Sdes}
71367588Sdes
71467588Sdes/*
715119911Sdes * Filler function for proc/pid/statm
716119911Sdes */
717119911Sdesstatic int
718119911Sdeslinprocfs_doprocstatm(PFS_FILL_ARGS)
719119911Sdes{
720119911Sdes	struct kinfo_proc kp;
721119911Sdes	segsz_t lsize;
722120340Sdes
723119911Sdes	PROC_LOCK(p);
724119911Sdes	fill_kinfo_proc(p, &kp);
725119911Sdes	PROC_UNLOCK(p);
726119911Sdes
727119911Sdes	/*
728119911Sdes	 * See comments in linprocfs_doprocstatus() regarding the
729119911Sdes	 * computation of lsize.
730119911Sdes	 */
731119911Sdes	/* size resident share trs drs lrs dt */
732119911Sdes	sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size));
733119911Sdes	sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize);
734119911Sdes	sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */
735119911Sdes	sbuf_printf(sb, "%ju ",	(uintmax_t)kp.ki_tsize);
736119911Sdes	sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize));
737119911Sdes	lsize = B2P(kp.ki_size) - kp.ki_dsize -
738119911Sdes	    kp.ki_ssize - kp.ki_tsize - 1;
739119911Sdes	sbuf_printf(sb, "%ju ", (uintmax_t)lsize);
740119911Sdes	sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */
741119911Sdes
742119911Sdes	return (0);
743119911Sdes}
744119911Sdes
745119911Sdes/*
74678113Sdes * Filler function for proc/pid/status
74778113Sdes */
74878025Sdesstatic int
74978025Sdeslinprocfs_doprocstatus(PFS_FILL_ARGS)
75067588Sdes{
75169995Sdes	struct kinfo_proc kp;
75267588Sdes	char *state;
75369799Sdes	segsz_t lsize;
75499072Sjulian	struct thread *td2;
755114983Sjhb	struct sigacts *ps;
75674135Sjlemon	int i;
75767588Sdes
758113611Sjhb	PROC_LOCK(p);
75999072Sjulian	td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */
76099072Sjulian
76199072Sjulian	if (P_SHOULDSTOP(p)) {
76299072Sjulian		state = "T (stopped)";
76399072Sjulian	} else {
76499072Sjulian		switch(p->p_state) {
76599072Sjulian		case PRS_NEW:
76699072Sjulian			state = "I (idle)";
76799072Sjulian			break;
76899072Sjulian		case PRS_NORMAL:
76999072Sjulian			if (p->p_flag & P_WEXIT) {
77099072Sjulian				state = "X (exiting)";
77199072Sjulian				break;
77299072Sjulian			}
77399072Sjulian			switch(td2->td_state) {
774103216Sjulian			case TDS_INHIBITED:
77599072Sjulian				state = "S (sleeping)";
77699072Sjulian				break;
77799072Sjulian			case TDS_RUNQ:
77899072Sjulian			case TDS_RUNNING:
77999072Sjulian				state = "R (running)";
78099072Sjulian				break;
78199072Sjulian			default:
78299072Sjulian				state = "? (unknown)";
78399072Sjulian				break;
78499072Sjulian			}
78599072Sjulian			break;
78699072Sjulian		case PRS_ZOMBIE:
78799072Sjulian			state = "Z (zombie)";
78899072Sjulian			break;
78999072Sjulian		default:
79099072Sjulian			state = "? (unknown)";
79199072Sjulian			break;
79299072Sjulian		}
79399072Sjulian	}
79467588Sdes
79569995Sdes	fill_kinfo_proc(p, &kp);
79678025Sdes	sbuf_printf(sb, "Name:\t%s\n",		p->p_comm); /* XXX escape */
79778031Sdes	sbuf_printf(sb, "State:\t%s\n",		state);
79867588Sdes
79967588Sdes	/*
80067588Sdes	 * Credentials
80167588Sdes	 */
80278025Sdes	sbuf_printf(sb, "Pid:\t%d\n",		p->p_pid);
80378025Sdes	sbuf_printf(sb, "PPid:\t%d\n",		p->p_pptr ?
80473923Sjhb						p->p_pptr->p_pid : 0);
80578031Sdes	sbuf_printf(sb, "Uid:\t%d %d %d %d\n",	p->p_ucred->cr_ruid,
80678031Sdes						p->p_ucred->cr_uid,
80778031Sdes						p->p_ucred->cr_svuid,
80878031Sdes						/* FreeBSD doesn't have fsuid */
80978031Sdes						p->p_ucred->cr_uid);
81078031Sdes	sbuf_printf(sb, "Gid:\t%d %d %d %d\n",	p->p_ucred->cr_rgid,
81178031Sdes						p->p_ucred->cr_gid,
81278031Sdes						p->p_ucred->cr_svgid,
81378031Sdes						/* FreeBSD doesn't have fsgid */
81478031Sdes						p->p_ucred->cr_gid);
81578025Sdes	sbuf_cat(sb, "Groups:\t");
81667588Sdes	for (i = 0; i < p->p_ucred->cr_ngroups; i++)
81778031Sdes		sbuf_printf(sb, "%d ",		p->p_ucred->cr_groups[i]);
81871471Sjhb	PROC_UNLOCK(p);
81978025Sdes	sbuf_putc(sb, '\n');
820119068Sdes
82167588Sdes	/*
82267588Sdes	 * Memory
82369799Sdes	 *
82469799Sdes	 * While our approximation of VmLib may not be accurate (I
82569799Sdes	 * don't know of a simple way to verify it, and I'm not sure
82669799Sdes	 * it has much meaning anyway), I believe it's good enough.
82769799Sdes	 *
82869799Sdes	 * The same code that could (I think) accurately compute VmLib
82969799Sdes	 * could also compute VmLck, but I don't really care enough to
83069799Sdes	 * implement it. Submissions are welcome.
83167588Sdes	 */
832113574Sjhb	sbuf_printf(sb, "VmSize:\t%8ju kB\n",	B2K((uintmax_t)kp.ki_size));
83378025Sdes	sbuf_printf(sb, "VmLck:\t%8u kB\n",	P2K(0)); /* XXX */
834206081Snetchild	sbuf_printf(sb, "VmRSS:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_rssize));
835113574Sjhb	sbuf_printf(sb, "VmData:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_dsize));
836113574Sjhb	sbuf_printf(sb, "VmStk:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_ssize));
837113574Sjhb	sbuf_printf(sb, "VmExe:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_tsize));
83869995Sdes	lsize = B2P(kp.ki_size) - kp.ki_dsize -
83969995Sdes	    kp.ki_ssize - kp.ki_tsize - 1;
840113574Sjhb	sbuf_printf(sb, "VmLib:\t%8ju kB\n",	P2K((uintmax_t)lsize));
84167588Sdes
84267588Sdes	/*
84367588Sdes	 * Signal masks
84467588Sdes	 *
84567588Sdes	 * We support up to 128 signals, while Linux supports 32,
84667588Sdes	 * but we only define 32 (the same 32 as Linux, to boot), so
84767588Sdes	 * just show the lower 32 bits of each mask. XXX hack.
84867588Sdes	 *
84967588Sdes	 * NB: on certain platforms (Sparc at least) Linux actually
85067588Sdes	 * supports 64 signals, but this code is a long way from
85167588Sdes	 * running on anything but i386, so ignore that for now.
85267588Sdes	 */
85371471Sjhb	PROC_LOCK(p);
854104306Sjmallett	sbuf_printf(sb, "SigPnd:\t%08x\n",	p->p_siglist.__bits[0]);
85569799Sdes	/*
85669799Sdes	 * I can't seem to find out where the signal mask is in
85769799Sdes	 * relation to struct proc, so SigBlk is left unimplemented.
85869799Sdes	 */
85978025Sdes	sbuf_printf(sb, "SigBlk:\t%08x\n",	0); /* XXX */
860114983Sjhb	ps = p->p_sigacts;
861114983Sjhb	mtx_lock(&ps->ps_mtx);
862114983Sjhb	sbuf_printf(sb, "SigIgn:\t%08x\n",	ps->ps_sigignore.__bits[0]);
863114983Sjhb	sbuf_printf(sb, "SigCgt:\t%08x\n",	ps->ps_sigcatch.__bits[0]);
864114983Sjhb	mtx_unlock(&ps->ps_mtx);
86571471Sjhb	PROC_UNLOCK(p);
866119068Sdes
86767588Sdes	/*
86867588Sdes	 * Linux also prints the capability masks, but we don't have
86967588Sdes	 * capabilities yet, and when we do get them they're likely to
87067588Sdes	 * be meaningless to Linux programs, so we lie. XXX
87167588Sdes	 */
87278025Sdes	sbuf_printf(sb, "CapInh:\t%016x\n",	0);
87378025Sdes	sbuf_printf(sb, "CapPrm:\t%016x\n",	0);
87478025Sdes	sbuf_printf(sb, "CapEff:\t%016x\n",	0);
875119068Sdes
87678025Sdes	return (0);
87767588Sdes}
87874135Sjlemon
879119911Sdes
88078113Sdes/*
881119911Sdes * Filler function for proc/pid/cwd
882119911Sdes */
883119911Sdesstatic int
884119911Sdeslinprocfs_doproccwd(PFS_FILL_ARGS)
885119911Sdes{
886119911Sdes	char *fullpath = "unknown";
887119911Sdes	char *freepath = NULL;
888119911Sdes
889119911Sdes	vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath);
890119911Sdes	sbuf_printf(sb, "%s", fullpath);
891119911Sdes	if (freepath)
892119911Sdes		free(freepath, M_TEMP);
893119911Sdes	return (0);
894119911Sdes}
895119911Sdes
896119911Sdes/*
897119911Sdes * Filler function for proc/pid/root
898119911Sdes */
899119911Sdesstatic int
900119911Sdeslinprocfs_doprocroot(PFS_FILL_ARGS)
901119911Sdes{
902119911Sdes	struct vnode *rvp;
903119911Sdes	char *fullpath = "unknown";
904119911Sdes	char *freepath = NULL;
905119911Sdes
906119911Sdes	rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir;
907119911Sdes	vn_fullpath(td, rvp, &fullpath, &freepath);
908119911Sdes	sbuf_printf(sb, "%s", fullpath);
909119911Sdes	if (freepath)
910119911Sdes		free(freepath, M_TEMP);
911119911Sdes	return (0);
912119911Sdes}
913119911Sdes
91478113Sdes/*
915213246Skib * Filler function for proc/pid/cmdline
916213246Skib */
917213246Skibstatic int
918213246Skiblinprocfs_doproccmdline(PFS_FILL_ARGS)
919213246Skib{
920213246Skib	int ret;
921213246Skib
922213246Skib	PROC_LOCK(p);
923213246Skib	if ((ret = p_cansee(td, p)) != 0) {
924213246Skib		PROC_UNLOCK(p);
925213246Skib		return (ret);
926213246Skib	}
927223182Spluknet
928223182Spluknet	/*
929223182Spluknet	 * Mimic linux behavior and pass only processes with usermode
930223182Spluknet	 * address space as valid.  Return zero silently otherwize.
931223182Spluknet	 */
932223182Spluknet	if (p->p_vmspace == &vmspace0) {
933223182Spluknet		PROC_UNLOCK(p);
934223182Spluknet		return (0);
935223182Spluknet	}
936213246Skib	if (p->p_args != NULL) {
937213246Skib		sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
938213246Skib		PROC_UNLOCK(p);
939213246Skib		return (0);
940213246Skib	}
941227836Strociny
942227836Strociny	if ((p->p_flag & P_SYSTEM) != 0) {
943227836Strociny		PROC_UNLOCK(p);
944227836Strociny		return (0);
945227836Strociny	}
946227836Strociny
947213246Skib	PROC_UNLOCK(p);
948213246Skib
949230145Strociny	ret = proc_getargv(td, p, sb);
950213246Skib	return (ret);
951213246Skib}
952213246Skib
953213246Skib/*
954116173Sobrien * Filler function for proc/pid/environ
955116173Sobrien */
956116173Sobrienstatic int
957116173Sobrienlinprocfs_doprocenviron(PFS_FILL_ARGS)
958116173Sobrien{
959212723Sdes	int ret;
960168762Sdes
961212723Sdes	PROC_LOCK(p);
962228268Strociny	if ((ret = p_candebug(td, p)) != 0) {
963212723Sdes		PROC_UNLOCK(p);
964213246Skib		return (ret);
965212723Sdes	}
966223182Spluknet
967223182Spluknet	/*
968223182Spluknet	 * Mimic linux behavior and pass only processes with usermode
969223182Spluknet	 * address space as valid.  Return zero silently otherwize.
970223182Spluknet	 */
971223182Spluknet	if (p->p_vmspace == &vmspace0) {
972223182Spluknet		PROC_UNLOCK(p);
973223182Spluknet		return (0);
974223182Spluknet	}
975227836Strociny
976227836Strociny	if ((p->p_flag & P_SYSTEM) != 0) {
977227836Strociny		PROC_UNLOCK(p);
978227836Strociny		return (0);
979227836Strociny	}
980227836Strociny
981213246Skib	PROC_UNLOCK(p);
982212723Sdes
983230145Strociny	ret = proc_getenvv(td, p, sb);
984212723Sdes	return (ret);
985116173Sobrien}
986116173Sobrien
987116173Sobrien/*
988116173Sobrien * Filler function for proc/pid/maps
989116173Sobrien */
990116173Sobrienstatic int
991116173Sobrienlinprocfs_doprocmaps(PFS_FILL_ARGS)
992116173Sobrien{
993185984Skib	struct vmspace *vm;
994185984Skib	vm_map_t map;
995185765Skib	vm_map_entry_t entry, tmp_entry;
996121265Scognet	vm_object_t obj, tobj, lobj;
997185765Skib	vm_offset_t e_start, e_end;
998121265Scognet	vm_ooffset_t off = 0;
999185765Skib	vm_prot_t e_prot;
1000185765Skib	unsigned int last_timestamp;
1001121265Scognet	char *name = "", *freename = NULL;
1002121265Scognet	ino_t ino;
1003121265Scognet	int ref_count, shadow_count, flags;
1004121265Scognet	int error;
1005137507Sphk	struct vnode *vp;
1006137507Sphk	struct vattr vat;
1007168762Sdes
1008121246Scognet	PROC_LOCK(p);
1009121246Scognet	error = p_candebug(td, p);
1010121246Scognet	PROC_UNLOCK(p);
1011121246Scognet	if (error)
1012121246Scognet		return (error);
1013168762Sdes
1014121246Scognet	if (uio->uio_rw != UIO_READ)
1015121246Scognet		return (EOPNOTSUPP);
1016168762Sdes
1017121246Scognet	error = 0;
1018185984Skib	vm = vmspace_acquire_ref(p);
1019185984Skib	if (vm == NULL)
1020185984Skib		return (ESRCH);
1021185984Skib	map = &vm->vm_map;
1022169156Salc	vm_map_lock_read(map);
1023183600Skib	for (entry = map->header.next; entry != &map->header;
1024121246Scognet	    entry = entry->next) {
1025121265Scognet		name = "";
1026121265Scognet		freename = NULL;
1027121246Scognet		if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
1028121246Scognet			continue;
1029185765Skib		e_prot = entry->protection;
1030185765Skib		e_start = entry->start;
1031185765Skib		e_end = entry->end;
1032121246Scognet		obj = entry->object.vm_object;
1033169156Salc		for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) {
1034251423Salc			VM_OBJECT_RLOCK(tobj);
1035169156Salc			if (lobj != obj)
1036251423Salc				VM_OBJECT_RUNLOCK(lobj);
1037121246Scognet			lobj = tobj;
1038169156Salc		}
1039185765Skib		last_timestamp = map->timestamp;
1040185765Skib		vm_map_unlock_read(map);
1041121246Scognet		ino = 0;
1042121246Scognet		if (lobj) {
1043121246Scognet			off = IDX_TO_OFF(lobj->size);
1044161094Skib			if (lobj->type == OBJT_VNODE) {
1045161094Skib				vp = lobj->handle;
1046161094Skib				if (vp)
1047161094Skib					vref(vp);
1048121246Scognet			}
1049161094Skib			else
1050161094Skib				vp = NULL;
1051169156Salc			if (lobj != obj)
1052251423Salc				VM_OBJECT_RUNLOCK(lobj);
1053121246Scognet			flags = obj->flags;
1054121246Scognet			ref_count = obj->ref_count;
1055121246Scognet			shadow_count = obj->shadow_count;
1056251423Salc			VM_OBJECT_RUNLOCK(obj);
1057161094Skib			if (vp) {
1058161094Skib				vn_fullpath(td, vp, &name, &freename);
1059175202Sattilio				vn_lock(vp, LK_SHARED | LK_RETRY);
1060182371Sattilio				VOP_GETATTR(vp, &vat, td->td_ucred);
1061161094Skib				ino = vat.va_fileid;
1062161094Skib				vput(vp);
1063161094Skib			}
1064121246Scognet		} else {
1065121246Scognet			flags = 0;
1066121246Scognet			ref_count = 0;
1067121246Scognet			shadow_count = 0;
1068121246Scognet		}
1069168762Sdes
1070121246Scognet		/*
1071168762Sdes		 * format:
1072121246Scognet		 *  start, end, access, offset, major, minor, inode, name.
1073121246Scognet		 */
1074183600Skib		error = sbuf_printf(sb,
1075121246Scognet		    "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n",
1076185765Skib		    (u_long)e_start, (u_long)e_end,
1077185765Skib		    (e_prot & VM_PROT_READ)?"r":"-",
1078185765Skib		    (e_prot & VM_PROT_WRITE)?"w":"-",
1079185765Skib		    (e_prot & VM_PROT_EXECUTE)?"x":"-",
1080121246Scognet		    "p",
1081121265Scognet		    (u_long)off,
1082121246Scognet		    0,
1083121246Scognet		    0,
1084121265Scognet		    (u_long)ino,
1085121246Scognet		    *name ? "     " : "",
1086121246Scognet		    name
1087121246Scognet		    );
1088121246Scognet		if (freename)
1089121246Scognet			free(freename, M_TEMP);
1090185864Skib		vm_map_lock_read(map);
1091183600Skib		if (error == -1) {
1092183600Skib			error = 0;
1093121246Scognet			break;
1094169156Salc		}
1095186563Skib		if (last_timestamp != map->timestamp) {
1096185765Skib			/*
1097185765Skib			 * Look again for the entry because the map was
1098185765Skib			 * modified while it was unlocked.  Specifically,
1099185765Skib			 * the entry may have been clipped, merged, or deleted.
1100185765Skib			 */
1101185765Skib			vm_map_lookup_entry(map, e_end - 1, &tmp_entry);
1102185765Skib			entry = tmp_entry;
1103185765Skib		}
1104121246Scognet	}
1105169156Salc	vm_map_unlock_read(map);
1106185984Skib	vmspace_free(vm);
1107168762Sdes
1108121246Scognet	return (error);
1109168762Sdes}
1110168762Sdes
1111116173Sobrien/*
111278113Sdes * Filler function for proc/net/dev
111378113Sdes */
111478025Sdesstatic int
111578025Sdeslinprocfs_donetdev(PFS_FILL_ARGS)
111674135Sjlemon{
111785129Sdes	char ifname[16]; /* XXX LINUX_IFNAMSIZ */
111874135Sjlemon	struct ifnet *ifp;
111974135Sjlemon
1120218114Sbz	sbuf_printf(sb, "%6s|%58s|%s\n"
1121218114Sbz	    "%6s|%58s|%58s\n",
1122218114Sbz	    "Inter-", "   Receive", "  Transmit",
1123218114Sbz	    " face",
1124218114Sbz	    "bytes    packets errs drop fifo frame compressed multicast",
1125218114Sbz	    "bytes    packets errs drop fifo colls carrier compressed");
112674135Sjlemon
1127196635Szec	CURVNET_SET(TD_TO_VNET(curthread));
1128108172Shsu	IFNET_RLOCK();
1129181803Sbz	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
113085129Sdes		linux_ifname(ifp, ifname, sizeof ifname);
1131218114Sbz		sbuf_printf(sb, "%6.6s: ", ifname);
1132218114Sbz		sbuf_printf(sb, "%7lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ",
1133218114Sbz		    ifp->if_ibytes,	/* rx_bytes */
1134218114Sbz		    ifp->if_ipackets,	/* rx_packets */
1135218114Sbz		    ifp->if_ierrors,	/* rx_errors */
1136218114Sbz		    ifp->if_iqdrops,	/* rx_dropped +
1137218114Sbz					 * rx_missed_errors */
1138218114Sbz		    0UL,		/* rx_fifo_errors */
1139218114Sbz		    0UL,		/* rx_length_errors +
1140218114Sbz					 * rx_over_errors +
1141218114Sbz		    			 * rx_crc_errors +
1142218114Sbz					 * rx_frame_errors */
1143218114Sbz		    0UL,		/* rx_compressed */
1144218114Sbz		    ifp->if_imcasts);	/* multicast, XXX-BZ rx only? */
114583926Sdes		sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
1146218114Sbz		    ifp->if_obytes,	/* tx_bytes */
1147218114Sbz		    ifp->if_opackets,	/* tx_packets */
1148218114Sbz		    ifp->if_oerrors,	/* tx_errors */
1149218114Sbz		    0UL,		/* tx_dropped */
1150218114Sbz		    0UL,		/* tx_fifo_errors */
1151218114Sbz		    ifp->if_collisions,	/* collisions */
1152218114Sbz		    0UL,		/* tx_carrier_errors +
1153218114Sbz					 * tx_aborted_errors +
1154218114Sbz					 * tx_window_errors +
1155218114Sbz					 * tx_heartbeat_errors */
1156218114Sbz		    0UL);		/* tx_compressed */
115774135Sjlemon	}
1158108172Shsu	IFNET_RUNLOCK();
1159196635Szec	CURVNET_RESTORE();
1160119068Sdes
116178025Sdes	return (0);
116274135Sjlemon}
116374135Sjlemon
1164158311Sambrisko/*
1165167159Sjkim * Filler function for proc/sys/kernel/osrelease
1166167159Sjkim */
1167167159Sjkimstatic int
1168167159Sjkimlinprocfs_doosrelease(PFS_FILL_ARGS)
1169167159Sjkim{
1170167159Sjkim	char osrelease[LINUX_MAX_UTSNAME];
1171167159Sjkim
1172167159Sjkim	linux_get_osrelease(td, osrelease);
1173167159Sjkim	sbuf_printf(sb, "%s\n", osrelease);
1174167159Sjkim
1175167159Sjkim	return (0);
1176167159Sjkim}
1177167159Sjkim
1178167159Sjkim/*
1179167159Sjkim * Filler function for proc/sys/kernel/ostype
1180167159Sjkim */
1181167159Sjkimstatic int
1182167159Sjkimlinprocfs_doostype(PFS_FILL_ARGS)
1183167159Sjkim{
1184167159Sjkim	char osname[LINUX_MAX_UTSNAME];
1185167159Sjkim
1186167159Sjkim	linux_get_osname(td, osname);
1187167159Sjkim	sbuf_printf(sb, "%s\n", osname);
1188167159Sjkim
1189167159Sjkim	return (0);
1190167159Sjkim}
1191167159Sjkim
1192167159Sjkim/*
1193167159Sjkim * Filler function for proc/sys/kernel/version
1194167159Sjkim */
1195167159Sjkimstatic int
1196167159Sjkimlinprocfs_doosbuild(PFS_FILL_ARGS)
1197167159Sjkim{
1198168762Sdes
1199167159Sjkim	linprocfs_osbuild(td, sb);
1200167159Sjkim	sbuf_cat(sb, "\n");
1201167159Sjkim	return (0);
1202167159Sjkim}
1203167159Sjkim
1204167159Sjkim/*
1205164692Sjkim * Filler function for proc/sys/kernel/msgmni
1206164692Sjkim */
1207164692Sjkimstatic int
1208164692Sjkimlinprocfs_domsgmni(PFS_FILL_ARGS)
1209164692Sjkim{
1210164692Sjkim
1211168067Sjkim	sbuf_printf(sb, "%d\n", msginfo.msgmni);
1212164692Sjkim	return (0);
1213164692Sjkim}
1214164692Sjkim
1215164692Sjkim/*
1216163251Skeramida * Filler function for proc/sys/kernel/pid_max
1217163129Snetchild */
1218163129Snetchildstatic int
1219163129Snetchildlinprocfs_dopid_max(PFS_FILL_ARGS)
1220163129Snetchild{
1221163757Snetchild
1222163129Snetchild	sbuf_printf(sb, "%i\n", PID_MAX);
1223163129Snetchild	return (0);
1224163129Snetchild}
1225163129Snetchild
1226163129Snetchild/*
1227164692Sjkim * Filler function for proc/sys/kernel/sem
1228164692Sjkim */
1229164692Sjkimstatic int
1230164692Sjkimlinprocfs_dosem(PFS_FILL_ARGS)
1231164692Sjkim{
1232164692Sjkim
1233168067Sjkim	sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns,
1234168067Sjkim	    seminfo.semopm, seminfo.semmni);
1235164692Sjkim	return (0);
1236164692Sjkim}
1237164692Sjkim
1238164692Sjkim/*
1239158311Sambrisko * Filler function for proc/scsi/device_info
1240158311Sambrisko */
1241158311Sambriskostatic int
1242158311Sambriskolinprocfs_doscsidevinfo(PFS_FILL_ARGS)
1243158311Sambrisko{
1244168762Sdes
1245158311Sambrisko	return (0);
1246158311Sambrisko}
1247158311Sambrisko
1248158311Sambrisko/*
1249158311Sambrisko * Filler function for proc/scsi/scsi
1250158311Sambrisko */
1251158311Sambriskostatic int
1252158311Sambriskolinprocfs_doscsiscsi(PFS_FILL_ARGS)
1253158311Sambrisko{
1254168762Sdes
1255158311Sambrisko	return (0);
1256158311Sambrisko}
1257158311Sambrisko
125885538Sphkextern struct cdevsw *cdevsw[];
125985538Sphk
126078113Sdes/*
126178113Sdes * Filler function for proc/devices
126278113Sdes */
126378025Sdesstatic int
126478025Sdeslinprocfs_dodevices(PFS_FILL_ARGS)
126574135Sjlemon{
1266158311Sambrisko	char *char_devices;
126778025Sdes	sbuf_printf(sb, "Character devices:\n");
126874135Sjlemon
1269158311Sambrisko	char_devices = linux_get_char_devices();
1270158311Sambrisko	sbuf_printf(sb, "%s", char_devices);
1271158311Sambrisko	linux_free_get_char_devices(char_devices);
127274135Sjlemon
127378025Sdes	sbuf_printf(sb, "\nBlock devices:\n");
1274119068Sdes
127578025Sdes	return (0);
127674135Sjlemon}
127774135Sjlemon
127878113Sdes/*
127978113Sdes * Filler function for proc/cmdline
128078113Sdes */
128178025Sdesstatic int
128278025Sdeslinprocfs_docmdline(PFS_FILL_ARGS)
128374135Sjlemon{
1284168762Sdes
128578025Sdes	sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
128678025Sdes	sbuf_printf(sb, " ro root=302\n");
128778025Sdes	return (0);
128878025Sdes}
128974135Sjlemon
1290205541Sjhb/*
1291205541Sjhb * Filler function for proc/filesystems
1292205541Sjhb */
1293205541Sjhbstatic int
1294205541Sjhblinprocfs_dofilesystems(PFS_FILL_ARGS)
1295205541Sjhb{
1296205541Sjhb	struct vfsconf *vfsp;
1297205541Sjhb
1298205592Sjhb	mtx_lock(&Giant);
1299205541Sjhb	TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
1300205541Sjhb		if (vfsp->vfc_flags & VFCF_SYNTHETIC)
1301205541Sjhb			sbuf_printf(sb, "nodev");
1302205541Sjhb		sbuf_printf(sb, "\t%s\n", vfsp->vfc_name);
1303205541Sjhb	}
1304205592Sjhb	mtx_unlock(&Giant);
1305205541Sjhb	return(0);
1306205541Sjhb}
1307205541Sjhb
130883926Sdes#if 0
130978025Sdes/*
131083926Sdes * Filler function for proc/modules
131183926Sdes */
131283926Sdesstatic int
131383926Sdeslinprocfs_domodules(PFS_FILL_ARGS)
131483926Sdes{
131583926Sdes	struct linker_file *lf;
1316119068Sdes
131783926Sdes	TAILQ_FOREACH(lf, &linker_files, link) {
131883926Sdes		sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
131983926Sdes		    (unsigned long)lf->size, lf->refs);
132083926Sdes	}
132183926Sdes	return (0);
132283926Sdes}
132383926Sdes#endif
132483926Sdes
132583926Sdes/*
1326204825Sed * Filler function for proc/pid/fd
1327204825Sed */
1328204825Sedstatic int
1329204825Sedlinprocfs_dofdescfs(PFS_FILL_ARGS)
1330204825Sed{
1331204825Sed
1332204825Sed	if (p == curproc)
1333204825Sed		sbuf_printf(sb, "/dev/fd");
1334204825Sed	else
1335204825Sed		sbuf_printf(sb, "unknown");
1336204825Sed	return (0);
1337204825Sed}
1338204825Sed
1339204825Sed/*
134085129Sdes * Constructor
134178025Sdes */
134285129Sdesstatic int
134385129Sdeslinprocfs_init(PFS_INIT_ARGS)
134485129Sdes{
134585129Sdes	struct pfs_node *root;
134685129Sdes	struct pfs_node *dir;
134774135Sjlemon
134885129Sdes	root = pi->pi_root;
134978025Sdes
1350119923Sdes	/* /proc/... */
1351119911Sdes	pfs_create_file(root, "cmdline", &linprocfs_docmdline,
1352167482Sdes	    NULL, NULL, NULL, PFS_RD);
1353119911Sdes	pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
1354167482Sdes	    NULL, NULL, NULL, PFS_RD);
1355119911Sdes	pfs_create_file(root, "devices", &linprocfs_dodevices,
1356167482Sdes	    NULL, NULL, NULL, PFS_RD);
1357205541Sjhb	pfs_create_file(root, "filesystems", &linprocfs_dofilesystems,
1358205541Sjhb	    NULL, NULL, NULL, PFS_RD);
1359119911Sdes	pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
1360167482Sdes	    NULL, NULL, NULL, PFS_RD);
1361119911Sdes	pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
1362167482Sdes	    NULL, NULL, NULL, PFS_RD);
136383926Sdes#if 0
1364119911Sdes	pfs_create_file(root, "modules", &linprocfs_domodules,
1365167482Sdes	    NULL, NULL, NULL, PFS_RD);
136683926Sdes#endif
1367158311Sambrisko	pfs_create_file(root, "mounts", &linprocfs_domtab,
1368167482Sdes	    NULL, NULL, NULL, PFS_RD);
1369119911Sdes	pfs_create_file(root, "mtab", &linprocfs_domtab,
1370167482Sdes	    NULL, NULL, NULL, PFS_RD);
1371190445Sambrisko	pfs_create_file(root, "partitions", &linprocfs_dopartitions,
1372190445Sambrisko	    NULL, NULL, NULL, PFS_RD);
137387543Sdes	pfs_create_link(root, "self", &procfs_docurproc,
1374167482Sdes	    NULL, NULL, NULL, 0);
1375119911Sdes	pfs_create_file(root, "stat", &linprocfs_dostat,
1376167482Sdes	    NULL, NULL, NULL, PFS_RD);
1377224582Skib	pfs_create_file(root, "swaps", &linprocfs_doswaps,
1378224582Skib	    NULL, NULL, NULL, PFS_RD);
1379119911Sdes	pfs_create_file(root, "uptime", &linprocfs_douptime,
1380167482Sdes	    NULL, NULL, NULL, PFS_RD);
1381119911Sdes	pfs_create_file(root, "version", &linprocfs_doversion,
1382167482Sdes	    NULL, NULL, NULL, PFS_RD);
138378025Sdes
1384119923Sdes	/* /proc/net/... */
1385167482Sdes	dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
138685129Sdes	pfs_create_file(dir, "dev", &linprocfs_donetdev,
1387167482Sdes	    NULL, NULL, NULL, PFS_RD);
138878025Sdes
1389119923Sdes	/* /proc/<pid>/... */
1390167482Sdes	dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
139185129Sdes	pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
1392167482Sdes	    NULL, NULL, NULL, PFS_RD);
1393119911Sdes	pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
1394167482Sdes	    NULL, NULL, NULL, 0);
1395116173Sobrien	pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
1396167482Sdes	    NULL, NULL, NULL, PFS_RD);
139787543Sdes	pfs_create_link(dir, "exe", &procfs_doprocfile,
1398167482Sdes	    NULL, &procfs_notsystem, NULL, 0);
1399116173Sobrien	pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
1400167482Sdes	    NULL, NULL, NULL, PFS_RD);
140185129Sdes	pfs_create_file(dir, "mem", &procfs_doprocmem,
1402167482Sdes	    &procfs_attr, &procfs_candebug, NULL, PFS_RDWR|PFS_RAW);
1403119911Sdes	pfs_create_link(dir, "root", &linprocfs_doprocroot,
1404167482Sdes	    NULL, NULL, NULL, 0);
140585129Sdes	pfs_create_file(dir, "stat", &linprocfs_doprocstat,
1406167482Sdes	    NULL, NULL, NULL, PFS_RD);
1407119911Sdes	pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
1408167482Sdes	    NULL, NULL, NULL, PFS_RD);
140985129Sdes	pfs_create_file(dir, "status", &linprocfs_doprocstatus,
1410167482Sdes	    NULL, NULL, NULL, PFS_RD);
1411204825Sed	pfs_create_link(dir, "fd", &linprocfs_dofdescfs,
1412204825Sed	    NULL, NULL, NULL, 0);
141385129Sdes
1414158311Sambrisko	/* /proc/scsi/... */
1415167482Sdes	dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
1416158311Sambrisko	pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
1417167482Sdes	    NULL, NULL, NULL, PFS_RD);
1418158311Sambrisko	pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
1419167482Sdes	    NULL, NULL, NULL, PFS_RD);
1420163129Snetchild
1421163129Snetchild	/* /proc/sys/... */
1422167482Sdes	dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
1423163129Snetchild	/* /proc/sys/kernel/... */
1424167482Sdes	dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0);
1425167159Sjkim	pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
1426167482Sdes	    NULL, NULL, NULL, PFS_RD);
1427167159Sjkim	pfs_create_file(dir, "ostype", &linprocfs_doostype,
1428167482Sdes	    NULL, NULL, NULL, PFS_RD);
1429167159Sjkim	pfs_create_file(dir, "version", &linprocfs_doosbuild,
1430167482Sdes	    NULL, NULL, NULL, PFS_RD);
1431164692Sjkim	pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
1432167482Sdes	    NULL, NULL, NULL, PFS_RD);
1433163129Snetchild	pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
1434167482Sdes	    NULL, NULL, NULL, PFS_RD);
1435164692Sjkim	pfs_create_file(dir, "sem", &linprocfs_dosem,
1436167482Sdes	    NULL, NULL, NULL, PFS_RD);
1437163129Snetchild
143885129Sdes	return (0);
143985129Sdes}
144085129Sdes
144185129Sdes/*
144285129Sdes * Destructor
144385129Sdes */
144485129Sdesstatic int
144585129Sdeslinprocfs_uninit(PFS_INIT_ARGS)
144685129Sdes{
144785129Sdes
144885129Sdes	/* nothing to do, pseudofs will GC */
144985129Sdes	return (0);
145085129Sdes}
145185129Sdes
1452232278SmmPSEUDOFS(linprocfs, 1, 0);
145378025SdesMODULE_DEPEND(linprocfs, linux, 1, 1, 1);
145478025SdesMODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
1455168440SjkimMODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);
1456168440SjkimMODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1);
1457