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>
75263103Seadler#include <sys/uuid.h>
7683926Sdes#include <sys/vmmeter.h>
7759412Smsmith#include <sys/vnode.h>
78190445Sambrisko#include <sys/bus.h>
7959412Smsmith
8083926Sdes#include <net/if.h>
81185571Sbz#include <net/vnet.h>
8283926Sdes
8359412Smsmith#include <vm/vm.h>
84185984Skib#include <vm/vm_extern.h>
8559412Smsmith#include <vm/pmap.h>
8667588Sdes#include <vm/vm_map.h>
8759412Smsmith#include <vm/vm_param.h>
8860860Sdes#include <vm/vm_object.h>
8959412Smsmith#include <vm/swap_pager.h>
9069799Sdes
9167589Sdes#include <machine/clock.h>
9278113Sdes
93190445Sambrisko#include <geom/geom.h>
94190445Sambrisko#include <geom/geom_int.h>
95190445Sambrisko
96133822Stjr#if defined(__i386__) || defined(__amd64__)
9767589Sdes#include <machine/cputypes.h>
9859412Smsmith#include <machine/md_var.h>
99133822Stjr#endif /* __i386__ || __amd64__ */
10059412Smsmith
101213246Skib#ifdef COMPAT_FREEBSD32
102213246Skib#include <compat/freebsd32/freebsd32_util.h>
103213246Skib#endif
104213246Skib
105140214Sobrien#ifdef COMPAT_LINUX32				/* XXX */
106140214Sobrien#include <machine/../linux32/linux.h>
107140214Sobrien#else
10887275Srwatson#include <machine/../linux/linux.h>
109133822Stjr#endif
11085129Sdes#include <compat/linux/linux_ioctl.h>
11169995Sdes#include <compat/linux/linux_mib.h>
11285289Sdes#include <compat/linux/linux_util.h>
11378025Sdes#include <fs/pseudofs/pseudofs.h>
11484248Sdes#include <fs/procfs/procfs.h>
11559412Smsmith
11667588Sdes/*
11767588Sdes * Various conversion macros
11867588Sdes */
119206081Snetchild#define T2J(x) ((long)(((x) * 100ULL) / (stathz ? stathz : hz)))	/* ticks to jiffies */
120206081Snetchild#define T2CS(x) ((unsigned long)(((x) * 100ULL) / (stathz ? stathz : hz)))	/* ticks to centiseconds */
12167588Sdes#define T2S(x) ((x) / (stathz ? stathz : hz))		/* ticks to seconds */
12267588Sdes#define B2K(x) ((x) >> 10)				/* bytes to kbytes */
12369799Sdes#define B2P(x) ((x) >> PAGE_SHIFT)			/* bytes to pages */
12467588Sdes#define P2B(x) ((x) << PAGE_SHIFT)			/* pages to bytes */
12567588Sdes#define P2K(x) ((x) << (PAGE_SHIFT - 10))		/* pages to kbytes */
126206081Snetchild#define TV2J(x)	((x)->tv_sec * 100UL + (x)->tv_usec / 10000)
12774135Sjlemon
128159995Snetchild/**
129159995Snetchild * @brief Mapping of ki_stat in struct kinfo_proc to the linux state
130159995Snetchild *
131159995Snetchild * The linux procfs state field displays one of the characters RSDZTW to
132159995Snetchild * denote running, sleeping in an interruptible wait, waiting in an
133172568Skevlo * uninterruptible disk sleep, a zombie process, process is being traced
134159995Snetchild * or stopped, or process is paging respectively.
135159995Snetchild *
136159995Snetchild * Our struct kinfo_proc contains the variable ki_stat which contains a
137159995Snetchild * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK.
138159995Snetchild *
139159995Snetchild * This character array is used with ki_stati-1 as an index and tries to
140159995Snetchild * map our states to suitable linux states.
141159995Snetchild */
142166140Snetchildstatic char linux_state[] = "RRSTZDD";
143159995Snetchild
14478113Sdes/*
14578113Sdes * Filler function for proc/meminfo
14678113Sdes */
14778025Sdesstatic int
14878025Sdeslinprocfs_domeminfo(PFS_FILL_ARGS)
14959412Smsmith{
15059412Smsmith	unsigned long memtotal;		/* total memory in bytes */
15159412Smsmith	unsigned long memused;		/* used memory in bytes */
15259412Smsmith	unsigned long memfree;		/* free memory in bytes */
15359412Smsmith	unsigned long memshared;	/* shared memory ??? */
15459412Smsmith	unsigned long buffers, cached;	/* buffer / cache memory ??? */
155113574Sjhb	unsigned long long swaptotal;	/* total swap space in bytes */
156113574Sjhb	unsigned long long swapused;	/* used swap space in bytes */
157113574Sjhb	unsigned long long swapfree;	/* free swap space in bytes */
15860860Sdes	vm_object_t object;
159117723Sphk	int i, j;
16059412Smsmith
16159412Smsmith	memtotal = physmem * PAGE_SIZE;
16259412Smsmith	/*
16359412Smsmith	 * The correct thing here would be:
16459412Smsmith	 *
165170170Sattilio	memfree = cnt.v_free_count * PAGE_SIZE;
16659412Smsmith	memused = memtotal - memfree;
16759412Smsmith	 *
16859412Smsmith	 * but it might mislead linux binaries into thinking there
16959412Smsmith	 * is very little memory left, so we cheat and tell them that
17059412Smsmith	 * all memory that isn't wired down is free.
17159412Smsmith	 */
172170170Sattilio	memused = cnt.v_wire_count * PAGE_SIZE;
17359412Smsmith	memfree = memtotal - memused;
174117723Sphk	swap_pager_status(&i, &j);
175153310Smlaier	swaptotal = (unsigned long long)i * PAGE_SIZE;
176153310Smlaier	swapused = (unsigned long long)j * PAGE_SIZE;
177117723Sphk	swapfree = swaptotal - swapused;
17860860Sdes	memshared = 0;
179124082Salc	mtx_lock(&vm_object_list_mtx);
18071471Sjhb	TAILQ_FOREACH(object, &vm_object_list, object_list)
18160860Sdes		if (object->shadow_count > 1)
18260860Sdes			memshared += object->resident_page_count;
183124082Salc	mtx_unlock(&vm_object_list_mtx);
18460860Sdes	memshared *= PAGE_SIZE;
18559412Smsmith	/*
18659412Smsmith	 * We'd love to be able to write:
18759412Smsmith	 *
18859412Smsmith	buffers = bufspace;
18959412Smsmith	 *
19059412Smsmith	 * but bufspace is internal to vfs_bio.c and we don't feel
19159412Smsmith	 * like unstaticizing it just for linprocfs's sake.
19259412Smsmith	 */
19359412Smsmith	buffers = 0;
194170170Sattilio	cached = cnt.v_cache_count * PAGE_SIZE;
19559412Smsmith
19678025Sdes	sbuf_printf(sb,
19778031Sdes	    "	     total:    used:	free:  shared: buffers:	 cached:\n"
19869799Sdes	    "Mem:  %lu %lu %lu %lu %lu %lu\n"
19976839Sjlemon	    "Swap: %llu %llu %llu\n"
20069799Sdes	    "MemTotal: %9lu kB\n"
20169799Sdes	    "MemFree:  %9lu kB\n"
20269799Sdes	    "MemShared:%9lu kB\n"
20369799Sdes	    "Buffers:  %9lu kB\n"
20469799Sdes	    "Cached:   %9lu kB\n"
20576839Sjlemon	    "SwapTotal:%9llu kB\n"
20676839Sjlemon	    "SwapFree: %9llu kB\n",
20769799Sdes	    memtotal, memused, memfree, memshared, buffers, cached,
20869799Sdes	    swaptotal, swapused, swapfree,
20969799Sdes	    B2K(memtotal), B2K(memfree),
21069799Sdes	    B2K(memshared), B2K(buffers), B2K(cached),
21169799Sdes	    B2K(swaptotal), B2K(swapfree));
21259412Smsmith
21378025Sdes	return (0);
21459412Smsmith}
21559412Smsmith
216133822Stjr#if defined(__i386__) || defined(__amd64__)
21778113Sdes/*
218133822Stjr * Filler function for proc/cpuinfo (i386 & amd64 version)
21978113Sdes */
22078113Sdesstatic int
22178113Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS)
22278113Sdes{
223159544Sdes	int hw_model[2];
224159544Sdes	char model[128];
225220433Sjkim	uint64_t freq;
226159544Sdes	size_t size;
227123246Sdes	int class, fqmhz, fqkhz;
228118421Sdes	int i;
22959412Smsmith
23069799Sdes	/*
23178031Sdes	 * We default the flags to include all non-conflicting flags,
23278031Sdes	 * and the Intel versions of conflicting flags.
23369799Sdes	 */
23478031Sdes	static char *flags[] = {
23578031Sdes		"fpu",	    "vme",     "de",	   "pse",      "tsc",
23678031Sdes		"msr",	    "pae",     "mce",	   "cx8",      "apic",
23778031Sdes		"sep",	    "sep",     "mtrr",	   "pge",      "mca",
23878031Sdes		"cmov",	    "pat",     "pse36",	   "pn",       "b19",
23978031Sdes		"b20",	    "b21",     "mmxext",   "mmx",      "fxsr",
240183385Scognet		"xmm",	    "sse2",    "b27",	   "b28",      "b29",
24167589Sdes		"3dnowext", "3dnow"
24267589Sdes	};
24367589Sdes
24459412Smsmith	switch (cpu_class) {
245133822Stjr#ifdef __i386__
24659412Smsmith	case CPUCLASS_286:
24767589Sdes		class = 2;
24859412Smsmith		break;
24959412Smsmith	case CPUCLASS_386:
25067589Sdes		class = 3;
25159412Smsmith		break;
25259412Smsmith	case CPUCLASS_486:
25367589Sdes		class = 4;
25459412Smsmith		break;
25559412Smsmith	case CPUCLASS_586:
25667589Sdes		class = 5;
25759412Smsmith		break;
25859412Smsmith	case CPUCLASS_686:
25967589Sdes		class = 6;
26059412Smsmith		break;
26159412Smsmith	default:
26278031Sdes		class = 0;
26359412Smsmith		break;
264159170Sdes#else /* __amd64__ */
265133822Stjr	default:
266159170Sdes		class = 15;
267133822Stjr		break;
268133822Stjr#endif
26959412Smsmith	}
27059412Smsmith
271159544Sdes	hw_model[0] = CTL_HW;
272159544Sdes	hw_model[1] = HW_MODEL;
273159544Sdes	model[0] = '\0';
274159544Sdes	size = sizeof(model);
275159544Sdes	if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0)
276159544Sdes		strcpy(model, "unknown");
277123246Sdes	for (i = 0; i < mp_ncpus; ++i) {
278118421Sdes		sbuf_printf(sb,
279118421Sdes		    "processor\t: %d\n"
280118421Sdes		    "vendor_id\t: %.20s\n"
281214982Sdes		    "cpu family\t: %u\n"
282214982Sdes		    "model\t\t: %u\n"
283159544Sdes		    "model name\t: %s\n"
284214982Sdes		    "stepping\t: %u\n\n",
285214985Sdes		    i, cpu_vendor, CPUID_TO_FAMILY(cpu_id),
286214985Sdes		    CPUID_TO_MODEL(cpu_id), model, cpu_id & CPUID_STEPPING);
287159544Sdes		/* XXX per-cpu vendor / class / model / id? */
288118421Sdes	}
28959412Smsmith
290185766Skib	sbuf_cat(sb, "flags\t\t:");
29167589Sdes
292187594Sjkim#ifdef __i386__
293187594Sjkim	switch (cpu_vendor_id) {
294187594Sjkim	case CPU_VENDOR_AMD:
295187594Sjkim		if (class < 6)
296187594Sjkim			flags[16] = "fcmov";
297187594Sjkim		break;
298187594Sjkim	case CPU_VENDOR_CYRIX:
29967589Sdes		flags[24] = "cxmmx";
300187594Sjkim		break;
30178031Sdes	}
302187594Sjkim#endif
303119068Sdes
30478031Sdes	for (i = 0; i < 32; i++)
30567589Sdes		if (cpu_feature & (1 << i))
30678025Sdes			sbuf_printf(sb, " %s", flags[i]);
30778025Sdes	sbuf_cat(sb, "\n");
308220433Sjkim	freq = atomic_load_acq_64(&tsc_freq);
309220433Sjkim	if (freq != 0) {
310220433Sjkim		fqmhz = (freq + 4999) / 1000000;
311220433Sjkim		fqkhz = ((freq + 4999) / 10000) % 100;
31278025Sdes		sbuf_printf(sb,
31369799Sdes		    "cpu MHz\t\t: %d.%02d\n"
31469799Sdes		    "bogomips\t: %d.%02d\n",
31569799Sdes		    fqmhz, fqkhz, fqmhz, fqkhz);
31678031Sdes	}
31769995Sdes
31878025Sdes	return (0);
31959412Smsmith}
320133822Stjr#endif /* __i386__ || __amd64__ */
32165633Sdes
32278113Sdes/*
32385289Sdes * Filler function for proc/mtab
32485289Sdes *
32585289Sdes * This file doesn't exist in Linux' procfs, but is included here so
32685289Sdes * users can symlink /compat/linux/etc/mtab to /proc/mtab
32785289Sdes */
32885289Sdesstatic int
32985289Sdeslinprocfs_domtab(PFS_FILL_ARGS)
33085289Sdes{
33185289Sdes	struct nameidata nd;
33285289Sdes	struct mount *mp;
33391334Sjulian	const char *lep;
33491334Sjulian	char *dlep, *flep, *mntto, *mntfrom, *fstype;
33585289Sdes	size_t lep_len;
33685289Sdes	int error;
33785289Sdes
33885289Sdes	/* resolve symlinks etc. in the emulation tree prefix */
339168942Sdes	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td);
34085289Sdes	flep = NULL;
341168942Sdes	error = namei(&nd);
342184649Sjhb	lep = linux_emul_path;
343184649Sjhb	if (error == 0) {
344188579Sjhb		if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
345184649Sjhb			lep = dlep;
346184649Sjhb		vrele(nd.ni_vp);
347184649Sjhb		VFS_UNLOCK_GIANT(NDHASGIANT(&nd));
348184649Sjhb	}
34985289Sdes	lep_len = strlen(lep);
350119068Sdes
35185289Sdes	mtx_lock(&mountlist_mtx);
35285289Sdes	error = 0;
35385289Sdes	TAILQ_FOREACH(mp, &mountlist, mnt_list) {
35485289Sdes		/* determine device name */
35585289Sdes		mntfrom = mp->mnt_stat.f_mntfromname;
356119068Sdes
35785289Sdes		/* determine mount point */
35885289Sdes		mntto = mp->mnt_stat.f_mntonname;
35985289Sdes		if (strncmp(mntto, lep, lep_len) == 0 &&
36085289Sdes		    mntto[lep_len] == '/')
36185289Sdes			mntto += lep_len;
36285289Sdes
36385289Sdes		/* determine fs type */
36485289Sdes		fstype = mp->mnt_stat.f_fstypename;
36585289Sdes		if (strcmp(fstype, pn->pn_info->pi_name) == 0)
36685289Sdes			mntfrom = fstype = "proc";
36785289Sdes		else if (strcmp(fstype, "procfs") == 0)
36885289Sdes			continue;
369119068Sdes
370158311Sambrisko		if (strcmp(fstype, "linsysfs") == 0) {
371158311Sambrisko			sbuf_printf(sb, "/sys %s sysfs %s", mntto,
372158311Sambrisko			    mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
373158311Sambrisko		} else {
374190445Sambrisko			/* For Linux msdosfs is called vfat */
375190445Sambrisko			if (strcmp(fstype, "msdosfs") == 0)
376190445Sambrisko				fstype = "vfat";
377158311Sambrisko			sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
378158311Sambrisko			    mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
379158311Sambrisko		}
38085289Sdes#define ADD_OPTION(opt, name) \
38185289Sdes	if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name);
38285289Sdes		ADD_OPTION(MNT_SYNCHRONOUS,	"sync");
38385289Sdes		ADD_OPTION(MNT_NOEXEC,		"noexec");
38485289Sdes		ADD_OPTION(MNT_NOSUID,		"nosuid");
38585289Sdes		ADD_OPTION(MNT_UNION,		"union");
38685289Sdes		ADD_OPTION(MNT_ASYNC,		"async");
38785289Sdes		ADD_OPTION(MNT_SUIDDIR,		"suiddir");
38885289Sdes		ADD_OPTION(MNT_NOSYMFOLLOW,	"nosymfollow");
38985289Sdes		ADD_OPTION(MNT_NOATIME,		"noatime");
39085289Sdes#undef ADD_OPTION
39185289Sdes		/* a real Linux mtab will also show NFS options */
39285289Sdes		sbuf_printf(sb, " 0 0\n");
39385289Sdes	}
39485289Sdes	mtx_unlock(&mountlist_mtx);
39585289Sdes	if (flep != NULL)
39685289Sdes		free(flep, M_TEMP);
39785289Sdes	return (error);
39885289Sdes}
39985289Sdes
40085289Sdes/*
401190445Sambrisko * Filler function for proc/partitions
402190445Sambrisko *
403190445Sambrisko */
404190445Sambriskostatic int
405190445Sambriskolinprocfs_dopartitions(PFS_FILL_ARGS)
406190445Sambrisko{
407190445Sambrisko	struct g_class *cp;
408190445Sambrisko	struct g_geom *gp;
409190445Sambrisko	struct g_provider *pp;
410190445Sambrisko	struct nameidata nd;
411190445Sambrisko	const char *lep;
412190445Sambrisko	char  *dlep, *flep;
413190445Sambrisko	size_t lep_len;
414190445Sambrisko	int error;
415190445Sambrisko	int major, minor;
416190445Sambrisko
417190445Sambrisko	/* resolve symlinks etc. in the emulation tree prefix */
418190445Sambrisko	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td);
419190445Sambrisko	flep = NULL;
420190445Sambrisko	error = namei(&nd);
421190445Sambrisko	lep = linux_emul_path;
422190445Sambrisko	if (error == 0) {
423190445Sambrisko		if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
424190445Sambrisko			lep = dlep;
425190445Sambrisko		vrele(nd.ni_vp);
426190445Sambrisko		VFS_UNLOCK_GIANT(NDHASGIANT(&nd));
427190445Sambrisko	}
428190445Sambrisko	lep_len = strlen(lep);
429190445Sambrisko
430190445Sambrisko	g_topology_lock();
431190445Sambrisko	error = 0;
432190445Sambrisko	sbuf_printf(sb, "major minor  #blocks  name rio rmerge rsect "
433190445Sambrisko	    "ruse wio wmerge wsect wuse running use aveq\n");
434190445Sambrisko
435190445Sambrisko	LIST_FOREACH(cp, &g_classes, class) {
436190445Sambrisko		if (strcmp(cp->name, "DISK") == 0 ||
437190445Sambrisko		    strcmp(cp->name, "PART") == 0)
438190445Sambrisko			LIST_FOREACH(gp, &cp->geom, geom) {
439190445Sambrisko				LIST_FOREACH(pp, &gp->provider, provider) {
440190445Sambrisko					if (linux_driver_get_major_minor(
441190445Sambrisko					    pp->name, &major, &minor) != 0) {
442190445Sambrisko						major = 0;
443190445Sambrisko						minor = 0;
444190445Sambrisko					}
445190445Sambrisko					sbuf_printf(sb, "%d %d %lld %s "
446190445Sambrisko					    "%d %d %d %d %d "
447190445Sambrisko					     "%d %d %d %d %d %d\n",
448190445Sambrisko					     major, minor,
449190445Sambrisko					     (long long)pp->mediasize, pp->name,
450190445Sambrisko					     0, 0, 0, 0, 0,
451190445Sambrisko					     0, 0, 0, 0, 0, 0);
452190445Sambrisko				}
453190445Sambrisko			}
454190445Sambrisko	}
455190445Sambrisko	g_topology_unlock();
456190445Sambrisko
457190445Sambrisko	if (flep != NULL)
458190445Sambrisko		free(flep, M_TEMP);
459190445Sambrisko	return (error);
460190445Sambrisko}
461190445Sambrisko
462190445Sambrisko
463190445Sambrisko/*
46478113Sdes * Filler function for proc/stat
46578113Sdes */
46678025Sdesstatic int
46778025Sdeslinprocfs_dostat(PFS_FILL_ARGS)
46865633Sdes{
469174070Speter	struct pcpu *pcpu;
470174070Speter	long cp_time[CPUSTATES];
471174070Speter	long *cp;
472123246Sdes	int i;
473120339Sdes
474174070Speter	read_cpu_time(cp_time);
475120339Sdes	sbuf_printf(sb, "cpu %ld %ld %ld %ld\n",
476120339Sdes	    T2J(cp_time[CP_USER]),
477120339Sdes	    T2J(cp_time[CP_NICE]),
478120339Sdes	    T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
479120339Sdes	    T2J(cp_time[CP_IDLE]));
480209059Sjhb	CPU_FOREACH(i) {
481174070Speter		pcpu = pcpu_find(i);
482174070Speter		cp = pcpu->pc_cp_time;
483143194Ssobomax		sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i,
484174070Speter		    T2J(cp[CP_USER]),
485174070Speter		    T2J(cp[CP_NICE]),
486174070Speter		    T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/),
487174070Speter		    T2J(cp[CP_IDLE]));
488174070Speter	}
48978025Sdes	sbuf_printf(sb,
49069799Sdes	    "disk 0 0 0 0\n"
49169799Sdes	    "page %u %u\n"
49269799Sdes	    "swap %u %u\n"
49369799Sdes	    "intr %u\n"
49469799Sdes	    "ctxt %u\n"
49585657Sdillon	    "btime %lld\n",
496170170Sattilio	    cnt.v_vnodepgsin,
497170170Sattilio	    cnt.v_vnodepgsout,
498170170Sattilio	    cnt.v_swappgsin,
499170170Sattilio	    cnt.v_swappgsout,
500170170Sattilio	    cnt.v_intr,
501170170Sattilio	    cnt.v_swtch,
502113574Sjhb	    (long long)boottime.tv_sec);
50378025Sdes	return (0);
50465633Sdes}
50565633Sdes
506224582Skibstatic int
507224582Skiblinprocfs_doswaps(PFS_FILL_ARGS)
508224582Skib{
509224582Skib	struct xswdev xsw;
510224582Skib	uintmax_t total, used;
511224582Skib	int n;
512224582Skib	char devname[SPECNAMELEN + 1];
513224582Skib
514224582Skib	sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
515224582Skib	mtx_lock(&Giant);
516224582Skib	for (n = 0; ; n++) {
517224582Skib		if (swap_dev_info(n, &xsw, devname, sizeof(devname)) != 0)
518224582Skib			break;
519224582Skib		total = (uintmax_t)xsw.xsw_nblks * PAGE_SIZE / 1024;
520224582Skib		used  = (uintmax_t)xsw.xsw_used * PAGE_SIZE / 1024;
521224582Skib
522224582Skib		/*
523224582Skib		 * The space and not tab after the device name is on
524224582Skib		 * purpose.  Linux does so.
525224582Skib		 */
526224582Skib		sbuf_printf(sb, "/dev/%-34s unknown\t\t%jd\t%jd\t-1\n",
527224582Skib		    devname, total, used);
528224582Skib	}
529224582Skib	mtx_unlock(&Giant);
530224582Skib	return (0);
531224582Skib}
532224582Skib
53378113Sdes/*
53478113Sdes * Filler function for proc/uptime
53578113Sdes */
53678025Sdesstatic int
53778025Sdeslinprocfs_douptime(PFS_FILL_ARGS)
53865633Sdes{
539174070Speter	long cp_time[CPUSTATES];
54065633Sdes	struct timeval tv;
54165633Sdes
54265633Sdes	getmicrouptime(&tv);
543174070Speter	read_cpu_time(cp_time);
544206081Snetchild	sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n",
545113574Sjhb	    (long long)tv.tv_sec, tv.tv_usec / 10000,
546206081Snetchild	    T2S(cp_time[CP_IDLE] / mp_ncpus),
547206081Snetchild	    T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100);
54878025Sdes	return (0);
54965633Sdes}
55065633Sdes
55178113Sdes/*
552167159Sjkim * Get OS build date
553167159Sjkim */
554167159Sjkimstatic void
555167159Sjkimlinprocfs_osbuild(struct thread *td, struct sbuf *sb)
556167159Sjkim{
557167159Sjkim#if 0
558167159Sjkim	char osbuild[256];
559167159Sjkim	char *cp1, *cp2;
560167159Sjkim
561167159Sjkim	strncpy(osbuild, version, 256);
562167159Sjkim	osbuild[255] = '\0';
563167159Sjkim	cp1 = strstr(osbuild, "\n");
564167159Sjkim	cp2 = strstr(osbuild, ":");
565167159Sjkim	if (cp1 && cp2) {
566167159Sjkim		*cp1 = *cp2 = '\0';
567167159Sjkim		cp1 = strstr(osbuild, "#");
568167159Sjkim	} else
569167159Sjkim		cp1 = NULL;
570167159Sjkim	if (cp1)
571167159Sjkim		sbuf_printf(sb, "%s%s", cp1, cp2 + 1);
572167159Sjkim	else
573167159Sjkim#endif
574167159Sjkim		sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977");
575167159Sjkim}
576167159Sjkim
577167159Sjkim/*
578167159Sjkim * Get OS builder
579167159Sjkim */
580167159Sjkimstatic void
581167159Sjkimlinprocfs_osbuilder(struct thread *td, struct sbuf *sb)
582167159Sjkim{
583168762Sdes#if 0
584167159Sjkim	char builder[256];
585167159Sjkim	char *cp;
586167159Sjkim
587167159Sjkim	cp = strstr(version, "\n    ");
588167159Sjkim	if (cp) {
589167159Sjkim		strncpy(builder, cp + 5, 256);
590167159Sjkim		builder[255] = '\0';
591167159Sjkim		cp = strstr(builder, ":");
592167159Sjkim		if (cp)
593167159Sjkim			*cp = '\0';
594167159Sjkim	}
595167159Sjkim	if (cp)
596167159Sjkim		sbuf_cat(sb, builder);
597167159Sjkim	else
598168762Sdes#endif
599167159Sjkim		sbuf_cat(sb, "des@freebsd.org");
600167159Sjkim}
601167159Sjkim
602167159Sjkim/*
60378113Sdes * Filler function for proc/version
60478113Sdes */
60578025Sdesstatic int
60678025Sdeslinprocfs_doversion(PFS_FILL_ARGS)
60765633Sdes{
60887275Srwatson	char osname[LINUX_MAX_UTSNAME];
60987275Srwatson	char osrelease[LINUX_MAX_UTSNAME];
61087275Srwatson
611112206Sjhb	linux_get_osname(td, osname);
612112206Sjhb	linux_get_osrelease(td, osrelease);
613167159Sjkim	sbuf_printf(sb, "%s version %s (", osname, osrelease);
614167159Sjkim	linprocfs_osbuilder(td, sb);
615167159Sjkim	sbuf_cat(sb, ") (gcc version " __VERSION__ ") ");
616167159Sjkim	linprocfs_osbuild(td, sb);
617167159Sjkim	sbuf_cat(sb, "\n");
61887275Srwatson
61978025Sdes	return (0);
62065633Sdes}
62165633Sdes
62278113Sdes/*
62378113Sdes * Filler function for proc/loadavg
62478113Sdes */
62578025Sdesstatic int
62678025Sdeslinprocfs_doloadavg(PFS_FILL_ARGS)
62776839Sjlemon{
628168762Sdes
62978025Sdes	sbuf_printf(sb,
63076839Sjlemon	    "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
63176839Sjlemon	    (int)(averunnable.ldavg[0] / averunnable.fscale),
63276839Sjlemon	    (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
63376839Sjlemon	    (int)(averunnable.ldavg[1] / averunnable.fscale),
63476839Sjlemon	    (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
63576839Sjlemon	    (int)(averunnable.ldavg[2] / averunnable.fscale),
63676839Sjlemon	    (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
63776839Sjlemon	    1,				/* number of running tasks */
63876839Sjlemon	    nprocs,			/* number of tasks */
63978116Sdes	    lastpid			/* the last pid */
64076839Sjlemon	);
64178025Sdes	return (0);
64276839Sjlemon}
64376839Sjlemon
64478113Sdes/*
64578113Sdes * Filler function for proc/pid/stat
64678113Sdes */
64778025Sdesstatic int
64878025Sdeslinprocfs_doprocstat(PFS_FILL_ARGS)
64967588Sdes{
65069995Sdes	struct kinfo_proc kp;
651166140Snetchild	char state;
652166140Snetchild	static int ratelimit = 0;
653206081Snetchild	vm_offset_t startcode, startdata;
65467588Sdes
65594307Sjhb	PROC_LOCK(p);
65669995Sdes	fill_kinfo_proc(p, &kp);
657206081Snetchild	if (p->p_vmspace) {
658206081Snetchild	   startcode = (vm_offset_t)p->p_vmspace->vm_taddr;
659206081Snetchild	   startdata = (vm_offset_t)p->p_vmspace->vm_daddr;
660206081Snetchild	} else {
661206081Snetchild	   startcode = 0;
662206081Snetchild	   startdata = 0;
663206081Snetchild	};
66478025Sdes	sbuf_printf(sb, "%d", p->p_pid);
66578025Sdes#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
66667588Sdes	PS_ADD("comm",		"(%s)",	p->p_comm);
667166140Snetchild	if (kp.ki_stat > sizeof(linux_state)) {
668166140Snetchild		state = 'R';
669166140Snetchild
670166141Snetchild		if (ratelimit == 0) {
671166162Snetchild			printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n",
672166162Snetchild			    kp.ki_stat, sizeof(linux_state));
673166141Snetchild			++ratelimit;
674166141Snetchild		}
675166140Snetchild	} else
676166140Snetchild		state = linux_state[kp.ki_stat - 1];
677166140Snetchild	PS_ADD("state",		"%c",	state);
67873923Sjhb	PS_ADD("ppid",		"%d",	p->p_pptr ? p->p_pptr->p_pid : 0);
67967588Sdes	PS_ADD("pgrp",		"%d",	p->p_pgid);
68067588Sdes	PS_ADD("session",	"%d",	p->p_session->s_sid);
68191140Stanimura	PROC_UNLOCK(p);
682206081Snetchild	PS_ADD("tty",		"%d",	kp.ki_tdev);
683159995Snetchild	PS_ADD("tpgid",		"%d",	kp.ki_tpgid);
68467588Sdes	PS_ADD("flags",		"%u",	0); /* XXX */
685159995Snetchild	PS_ADD("minflt",	"%lu",	kp.ki_rusage.ru_minflt);
686159995Snetchild	PS_ADD("cminflt",	"%lu",	kp.ki_rusage_ch.ru_minflt);
687159995Snetchild	PS_ADD("majflt",	"%lu",	kp.ki_rusage.ru_majflt);
688159995Snetchild	PS_ADD("cmajflt",	"%lu",	kp.ki_rusage_ch.ru_majflt);
689206081Snetchild	PS_ADD("utime",		"%ld",	TV2J(&kp.ki_rusage.ru_utime));
690206081Snetchild	PS_ADD("stime",		"%ld",	TV2J(&kp.ki_rusage.ru_stime));
691206081Snetchild	PS_ADD("cutime",	"%ld",	TV2J(&kp.ki_rusage_ch.ru_utime));
692206081Snetchild	PS_ADD("cstime",	"%ld",	TV2J(&kp.ki_rusage_ch.ru_stime));
693159995Snetchild	PS_ADD("priority",	"%d",	kp.ki_pri.pri_user);
694159995Snetchild	PS_ADD("nice",		"%d",	kp.ki_nice); /* 19 (nicest) to -19 */
695159995Snetchild	PS_ADD("0",		"%d",	0); /* removed field */
696159995Snetchild	PS_ADD("itrealvalue",	"%d",	0); /* XXX */
697206081Snetchild	PS_ADD("starttime",	"%lu",	TV2J(&kp.ki_start) - TV2J(&boottime));
698159995Snetchild	PS_ADD("vsize",		"%ju",	P2K((uintmax_t)kp.ki_size));
699159995Snetchild	PS_ADD("rss",		"%ju",	(uintmax_t)kp.ki_rssize);
700159995Snetchild	PS_ADD("rlim",		"%lu",	kp.ki_rusage.ru_maxrss);
701206081Snetchild	PS_ADD("startcode",	"%ju",	(uintmax_t)startcode);
702206081Snetchild	PS_ADD("endcode",	"%ju",	(uintmax_t)startdata);
70367588Sdes	PS_ADD("startstack",	"%u",	0); /* XXX */
704159995Snetchild	PS_ADD("kstkesp",	"%u",	0); /* XXX */
705159995Snetchild	PS_ADD("kstkeip",	"%u",	0); /* XXX */
706159995Snetchild	PS_ADD("signal",	"%u",	0); /* XXX */
707159995Snetchild	PS_ADD("blocked",	"%u",	0); /* XXX */
708159995Snetchild	PS_ADD("sigignore",	"%u",	0); /* XXX */
709159995Snetchild	PS_ADD("sigcatch",	"%u",	0); /* XXX */
71067588Sdes	PS_ADD("wchan",		"%u",	0); /* XXX */
711159995Snetchild	PS_ADD("nswap",		"%lu",	kp.ki_rusage.ru_nswap);
712159995Snetchild	PS_ADD("cnswap",	"%lu",	kp.ki_rusage_ch.ru_nswap);
71369799Sdes	PS_ADD("exitsignal",	"%d",	0); /* XXX */
714159995Snetchild	PS_ADD("processor",	"%u",	kp.ki_lastcpu);
715159995Snetchild	PS_ADD("rt_priority",	"%u",	0); /* XXX */ /* >= 2.5.19 */
716159995Snetchild	PS_ADD("policy",	"%u",	kp.ki_pri.pri_class); /* >= 2.5.19 */
71767588Sdes#undef PS_ADD
71878025Sdes	sbuf_putc(sb, '\n');
719119068Sdes
72078025Sdes	return (0);
72167588Sdes}
72267588Sdes
72367588Sdes/*
724119911Sdes * Filler function for proc/pid/statm
725119911Sdes */
726119911Sdesstatic int
727119911Sdeslinprocfs_doprocstatm(PFS_FILL_ARGS)
728119911Sdes{
729119911Sdes	struct kinfo_proc kp;
730119911Sdes	segsz_t lsize;
731120340Sdes
732119911Sdes	PROC_LOCK(p);
733119911Sdes	fill_kinfo_proc(p, &kp);
734119911Sdes	PROC_UNLOCK(p);
735119911Sdes
736119911Sdes	/*
737119911Sdes	 * See comments in linprocfs_doprocstatus() regarding the
738119911Sdes	 * computation of lsize.
739119911Sdes	 */
740119911Sdes	/* size resident share trs drs lrs dt */
741119911Sdes	sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size));
742119911Sdes	sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize);
743119911Sdes	sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */
744119911Sdes	sbuf_printf(sb, "%ju ",	(uintmax_t)kp.ki_tsize);
745119911Sdes	sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize));
746119911Sdes	lsize = B2P(kp.ki_size) - kp.ki_dsize -
747119911Sdes	    kp.ki_ssize - kp.ki_tsize - 1;
748119911Sdes	sbuf_printf(sb, "%ju ", (uintmax_t)lsize);
749119911Sdes	sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */
750119911Sdes
751119911Sdes	return (0);
752119911Sdes}
753119911Sdes
754119911Sdes/*
75578113Sdes * Filler function for proc/pid/status
75678113Sdes */
75778025Sdesstatic int
75878025Sdeslinprocfs_doprocstatus(PFS_FILL_ARGS)
75967588Sdes{
76069995Sdes	struct kinfo_proc kp;
76167588Sdes	char *state;
76269799Sdes	segsz_t lsize;
76399072Sjulian	struct thread *td2;
764114983Sjhb	struct sigacts *ps;
76574135Sjlemon	int i;
76667588Sdes
767113611Sjhb	PROC_LOCK(p);
76899072Sjulian	td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */
76999072Sjulian
77099072Sjulian	if (P_SHOULDSTOP(p)) {
77199072Sjulian		state = "T (stopped)";
77299072Sjulian	} else {
77399072Sjulian		switch(p->p_state) {
77499072Sjulian		case PRS_NEW:
77599072Sjulian			state = "I (idle)";
77699072Sjulian			break;
77799072Sjulian		case PRS_NORMAL:
77899072Sjulian			if (p->p_flag & P_WEXIT) {
77999072Sjulian				state = "X (exiting)";
78099072Sjulian				break;
78199072Sjulian			}
78299072Sjulian			switch(td2->td_state) {
783103216Sjulian			case TDS_INHIBITED:
78499072Sjulian				state = "S (sleeping)";
78599072Sjulian				break;
78699072Sjulian			case TDS_RUNQ:
78799072Sjulian			case TDS_RUNNING:
78899072Sjulian				state = "R (running)";
78999072Sjulian				break;
79099072Sjulian			default:
79199072Sjulian				state = "? (unknown)";
79299072Sjulian				break;
79399072Sjulian			}
79499072Sjulian			break;
79599072Sjulian		case PRS_ZOMBIE:
79699072Sjulian			state = "Z (zombie)";
79799072Sjulian			break;
79899072Sjulian		default:
79999072Sjulian			state = "? (unknown)";
80099072Sjulian			break;
80199072Sjulian		}
80299072Sjulian	}
80367588Sdes
80469995Sdes	fill_kinfo_proc(p, &kp);
80578025Sdes	sbuf_printf(sb, "Name:\t%s\n",		p->p_comm); /* XXX escape */
80678031Sdes	sbuf_printf(sb, "State:\t%s\n",		state);
80767588Sdes
80867588Sdes	/*
80967588Sdes	 * Credentials
81067588Sdes	 */
81178025Sdes	sbuf_printf(sb, "Pid:\t%d\n",		p->p_pid);
81278025Sdes	sbuf_printf(sb, "PPid:\t%d\n",		p->p_pptr ?
81373923Sjhb						p->p_pptr->p_pid : 0);
81478031Sdes	sbuf_printf(sb, "Uid:\t%d %d %d %d\n",	p->p_ucred->cr_ruid,
81578031Sdes						p->p_ucred->cr_uid,
81678031Sdes						p->p_ucred->cr_svuid,
81778031Sdes						/* FreeBSD doesn't have fsuid */
81878031Sdes						p->p_ucred->cr_uid);
81978031Sdes	sbuf_printf(sb, "Gid:\t%d %d %d %d\n",	p->p_ucred->cr_rgid,
82078031Sdes						p->p_ucred->cr_gid,
82178031Sdes						p->p_ucred->cr_svgid,
82278031Sdes						/* FreeBSD doesn't have fsgid */
82378031Sdes						p->p_ucred->cr_gid);
82478025Sdes	sbuf_cat(sb, "Groups:\t");
82567588Sdes	for (i = 0; i < p->p_ucred->cr_ngroups; i++)
82678031Sdes		sbuf_printf(sb, "%d ",		p->p_ucred->cr_groups[i]);
82771471Sjhb	PROC_UNLOCK(p);
82878025Sdes	sbuf_putc(sb, '\n');
829119068Sdes
83067588Sdes	/*
83167588Sdes	 * Memory
83269799Sdes	 *
83369799Sdes	 * While our approximation of VmLib may not be accurate (I
83469799Sdes	 * don't know of a simple way to verify it, and I'm not sure
83569799Sdes	 * it has much meaning anyway), I believe it's good enough.
83669799Sdes	 *
83769799Sdes	 * The same code that could (I think) accurately compute VmLib
83869799Sdes	 * could also compute VmLck, but I don't really care enough to
83969799Sdes	 * implement it. Submissions are welcome.
84067588Sdes	 */
841113574Sjhb	sbuf_printf(sb, "VmSize:\t%8ju kB\n",	B2K((uintmax_t)kp.ki_size));
84278025Sdes	sbuf_printf(sb, "VmLck:\t%8u kB\n",	P2K(0)); /* XXX */
843206081Snetchild	sbuf_printf(sb, "VmRSS:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_rssize));
844113574Sjhb	sbuf_printf(sb, "VmData:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_dsize));
845113574Sjhb	sbuf_printf(sb, "VmStk:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_ssize));
846113574Sjhb	sbuf_printf(sb, "VmExe:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_tsize));
84769995Sdes	lsize = B2P(kp.ki_size) - kp.ki_dsize -
84869995Sdes	    kp.ki_ssize - kp.ki_tsize - 1;
849113574Sjhb	sbuf_printf(sb, "VmLib:\t%8ju kB\n",	P2K((uintmax_t)lsize));
85067588Sdes
85167588Sdes	/*
85267588Sdes	 * Signal masks
85367588Sdes	 *
85467588Sdes	 * We support up to 128 signals, while Linux supports 32,
85567588Sdes	 * but we only define 32 (the same 32 as Linux, to boot), so
85667588Sdes	 * just show the lower 32 bits of each mask. XXX hack.
85767588Sdes	 *
85867588Sdes	 * NB: on certain platforms (Sparc at least) Linux actually
85967588Sdes	 * supports 64 signals, but this code is a long way from
86067588Sdes	 * running on anything but i386, so ignore that for now.
86167588Sdes	 */
86271471Sjhb	PROC_LOCK(p);
863104306Sjmallett	sbuf_printf(sb, "SigPnd:\t%08x\n",	p->p_siglist.__bits[0]);
86469799Sdes	/*
86569799Sdes	 * I can't seem to find out where the signal mask is in
86669799Sdes	 * relation to struct proc, so SigBlk is left unimplemented.
86769799Sdes	 */
86878025Sdes	sbuf_printf(sb, "SigBlk:\t%08x\n",	0); /* XXX */
869114983Sjhb	ps = p->p_sigacts;
870114983Sjhb	mtx_lock(&ps->ps_mtx);
871114983Sjhb	sbuf_printf(sb, "SigIgn:\t%08x\n",	ps->ps_sigignore.__bits[0]);
872114983Sjhb	sbuf_printf(sb, "SigCgt:\t%08x\n",	ps->ps_sigcatch.__bits[0]);
873114983Sjhb	mtx_unlock(&ps->ps_mtx);
87471471Sjhb	PROC_UNLOCK(p);
875119068Sdes
87667588Sdes	/*
87767588Sdes	 * Linux also prints the capability masks, but we don't have
87867588Sdes	 * capabilities yet, and when we do get them they're likely to
87967588Sdes	 * be meaningless to Linux programs, so we lie. XXX
88067588Sdes	 */
88178025Sdes	sbuf_printf(sb, "CapInh:\t%016x\n",	0);
88278025Sdes	sbuf_printf(sb, "CapPrm:\t%016x\n",	0);
88378025Sdes	sbuf_printf(sb, "CapEff:\t%016x\n",	0);
884119068Sdes
88578025Sdes	return (0);
88667588Sdes}
88774135Sjlemon
888119911Sdes
88978113Sdes/*
890119911Sdes * Filler function for proc/pid/cwd
891119911Sdes */
892119911Sdesstatic int
893119911Sdeslinprocfs_doproccwd(PFS_FILL_ARGS)
894119911Sdes{
895119911Sdes	char *fullpath = "unknown";
896119911Sdes	char *freepath = NULL;
897119911Sdes
898119911Sdes	vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath);
899119911Sdes	sbuf_printf(sb, "%s", fullpath);
900119911Sdes	if (freepath)
901119911Sdes		free(freepath, M_TEMP);
902119911Sdes	return (0);
903119911Sdes}
904119911Sdes
905119911Sdes/*
906119911Sdes * Filler function for proc/pid/root
907119911Sdes */
908119911Sdesstatic int
909119911Sdeslinprocfs_doprocroot(PFS_FILL_ARGS)
910119911Sdes{
911119911Sdes	struct vnode *rvp;
912119911Sdes	char *fullpath = "unknown";
913119911Sdes	char *freepath = NULL;
914119911Sdes
915119911Sdes	rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir;
916119911Sdes	vn_fullpath(td, rvp, &fullpath, &freepath);
917119911Sdes	sbuf_printf(sb, "%s", fullpath);
918119911Sdes	if (freepath)
919119911Sdes		free(freepath, M_TEMP);
920119911Sdes	return (0);
921119911Sdes}
922119911Sdes
92378113Sdes/*
924213246Skib * Filler function for proc/pid/cmdline
925213246Skib */
926213246Skibstatic int
927213246Skiblinprocfs_doproccmdline(PFS_FILL_ARGS)
928213246Skib{
929213246Skib	int ret;
930213246Skib
931213246Skib	PROC_LOCK(p);
932213246Skib	if ((ret = p_cansee(td, p)) != 0) {
933213246Skib		PROC_UNLOCK(p);
934213246Skib		return (ret);
935213246Skib	}
936223182Spluknet
937223182Spluknet	/*
938223182Spluknet	 * Mimic linux behavior and pass only processes with usermode
939223182Spluknet	 * address space as valid.  Return zero silently otherwize.
940223182Spluknet	 */
941223182Spluknet	if (p->p_vmspace == &vmspace0) {
942223182Spluknet		PROC_UNLOCK(p);
943223182Spluknet		return (0);
944223182Spluknet	}
945213246Skib	if (p->p_args != NULL) {
946213246Skib		sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
947213246Skib		PROC_UNLOCK(p);
948213246Skib		return (0);
949213246Skib	}
950230754Strociny
951230754Strociny	if ((p->p_flag & P_SYSTEM) != 0) {
952230754Strociny		PROC_UNLOCK(p);
953230754Strociny		return (0);
954230754Strociny	}
955230754Strociny
956213246Skib	PROC_UNLOCK(p);
957213246Skib
958230754Strociny	ret = proc_getargv(td, p, sb);
959213246Skib	return (ret);
960213246Skib}
961213246Skib
962213246Skib/*
963116173Sobrien * Filler function for proc/pid/environ
964116173Sobrien */
965116173Sobrienstatic int
966116173Sobrienlinprocfs_doprocenviron(PFS_FILL_ARGS)
967116173Sobrien{
968212723Sdes	int ret;
969168762Sdes
970212723Sdes	PROC_LOCK(p);
971230755Strociny	if ((ret = p_candebug(td, p)) != 0) {
972212723Sdes		PROC_UNLOCK(p);
973213246Skib		return (ret);
974212723Sdes	}
975223182Spluknet
976223182Spluknet	/*
977223182Spluknet	 * Mimic linux behavior and pass only processes with usermode
978223182Spluknet	 * address space as valid.  Return zero silently otherwize.
979223182Spluknet	 */
980223182Spluknet	if (p->p_vmspace == &vmspace0) {
981223182Spluknet		PROC_UNLOCK(p);
982223182Spluknet		return (0);
983223182Spluknet	}
984230754Strociny
985230754Strociny	if ((p->p_flag & P_SYSTEM) != 0) {
986230754Strociny		PROC_UNLOCK(p);
987230754Strociny		return (0);
988230754Strociny	}
989230754Strociny
990213246Skib	PROC_UNLOCK(p);
991212723Sdes
992230754Strociny	ret = proc_getenvv(td, p, sb);
993212723Sdes	return (ret);
994116173Sobrien}
995116173Sobrien
996116173Sobrien/*
997116173Sobrien * Filler function for proc/pid/maps
998116173Sobrien */
999116173Sobrienstatic int
1000116173Sobrienlinprocfs_doprocmaps(PFS_FILL_ARGS)
1001116173Sobrien{
1002185984Skib	struct vmspace *vm;
1003185984Skib	vm_map_t map;
1004185765Skib	vm_map_entry_t entry, tmp_entry;
1005121265Scognet	vm_object_t obj, tobj, lobj;
1006185765Skib	vm_offset_t e_start, e_end;
1007121265Scognet	vm_ooffset_t off = 0;
1008185765Skib	vm_prot_t e_prot;
1009185765Skib	unsigned int last_timestamp;
1010121265Scognet	char *name = "", *freename = NULL;
1011121265Scognet	ino_t ino;
1012121265Scognet	int ref_count, shadow_count, flags;
1013121265Scognet	int error;
1014137507Sphk	struct vnode *vp;
1015137507Sphk	struct vattr vat;
1016161094Skib	int locked;
1017168762Sdes
1018121246Scognet	PROC_LOCK(p);
1019121246Scognet	error = p_candebug(td, p);
1020121246Scognet	PROC_UNLOCK(p);
1021121246Scognet	if (error)
1022121246Scognet		return (error);
1023168762Sdes
1024121246Scognet	if (uio->uio_rw != UIO_READ)
1025121246Scognet		return (EOPNOTSUPP);
1026168762Sdes
1027121246Scognet	error = 0;
1028185984Skib	vm = vmspace_acquire_ref(p);
1029185984Skib	if (vm == NULL)
1030185984Skib		return (ESRCH);
1031185984Skib	map = &vm->vm_map;
1032169156Salc	vm_map_lock_read(map);
1033183600Skib	for (entry = map->header.next; entry != &map->header;
1034121246Scognet	    entry = entry->next) {
1035121265Scognet		name = "";
1036121265Scognet		freename = NULL;
1037121246Scognet		if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
1038121246Scognet			continue;
1039185765Skib		e_prot = entry->protection;
1040185765Skib		e_start = entry->start;
1041185765Skib		e_end = entry->end;
1042121246Scognet		obj = entry->object.vm_object;
1043169156Salc		for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) {
1044169156Salc			VM_OBJECT_LOCK(tobj);
1045169156Salc			if (lobj != obj)
1046169156Salc				VM_OBJECT_UNLOCK(lobj);
1047121246Scognet			lobj = tobj;
1048169156Salc		}
1049185765Skib		last_timestamp = map->timestamp;
1050185765Skib		vm_map_unlock_read(map);
1051121246Scognet		ino = 0;
1052121246Scognet		if (lobj) {
1053121246Scognet			off = IDX_TO_OFF(lobj->size);
1054161094Skib			if (lobj->type == OBJT_VNODE) {
1055161094Skib				vp = lobj->handle;
1056161094Skib				if (vp)
1057161094Skib					vref(vp);
1058121246Scognet			}
1059161094Skib			else
1060161094Skib				vp = NULL;
1061169156Salc			if (lobj != obj)
1062169156Salc				VM_OBJECT_UNLOCK(lobj);
1063121246Scognet			flags = obj->flags;
1064121246Scognet			ref_count = obj->ref_count;
1065121246Scognet			shadow_count = obj->shadow_count;
1066169156Salc			VM_OBJECT_UNLOCK(obj);
1067161094Skib			if (vp) {
1068161094Skib				vn_fullpath(td, vp, &name, &freename);
1069161094Skib				locked = VFS_LOCK_GIANT(vp->v_mount);
1070175202Sattilio				vn_lock(vp, LK_SHARED | LK_RETRY);
1071182371Sattilio				VOP_GETATTR(vp, &vat, td->td_ucred);
1072161094Skib				ino = vat.va_fileid;
1073161094Skib				vput(vp);
1074161094Skib				VFS_UNLOCK_GIANT(locked);
1075161094Skib			}
1076121246Scognet		} else {
1077121246Scognet			flags = 0;
1078121246Scognet			ref_count = 0;
1079121246Scognet			shadow_count = 0;
1080121246Scognet		}
1081168762Sdes
1082121246Scognet		/*
1083168762Sdes		 * format:
1084121246Scognet		 *  start, end, access, offset, major, minor, inode, name.
1085121246Scognet		 */
1086183600Skib		error = sbuf_printf(sb,
1087121246Scognet		    "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n",
1088185765Skib		    (u_long)e_start, (u_long)e_end,
1089185765Skib		    (e_prot & VM_PROT_READ)?"r":"-",
1090185765Skib		    (e_prot & VM_PROT_WRITE)?"w":"-",
1091185765Skib		    (e_prot & VM_PROT_EXECUTE)?"x":"-",
1092121246Scognet		    "p",
1093121265Scognet		    (u_long)off,
1094121246Scognet		    0,
1095121246Scognet		    0,
1096121265Scognet		    (u_long)ino,
1097121246Scognet		    *name ? "     " : "",
1098121246Scognet		    name
1099121246Scognet		    );
1100121246Scognet		if (freename)
1101121246Scognet			free(freename, M_TEMP);
1102185864Skib		vm_map_lock_read(map);
1103183600Skib		if (error == -1) {
1104183600Skib			error = 0;
1105121246Scognet			break;
1106169156Salc		}
1107186563Skib		if (last_timestamp != map->timestamp) {
1108185765Skib			/*
1109185765Skib			 * Look again for the entry because the map was
1110185765Skib			 * modified while it was unlocked.  Specifically,
1111185765Skib			 * the entry may have been clipped, merged, or deleted.
1112185765Skib			 */
1113185765Skib			vm_map_lookup_entry(map, e_end - 1, &tmp_entry);
1114185765Skib			entry = tmp_entry;
1115185765Skib		}
1116121246Scognet	}
1117169156Salc	vm_map_unlock_read(map);
1118185984Skib	vmspace_free(vm);
1119168762Sdes
1120121246Scognet	return (error);
1121168762Sdes}
1122168762Sdes
1123116173Sobrien/*
112478113Sdes * Filler function for proc/net/dev
112578113Sdes */
112678025Sdesstatic int
112778025Sdeslinprocfs_donetdev(PFS_FILL_ARGS)
112874135Sjlemon{
112985129Sdes	char ifname[16]; /* XXX LINUX_IFNAMSIZ */
113074135Sjlemon	struct ifnet *ifp;
113174135Sjlemon
1132218114Sbz	sbuf_printf(sb, "%6s|%58s|%s\n"
1133218114Sbz	    "%6s|%58s|%58s\n",
1134218114Sbz	    "Inter-", "   Receive", "  Transmit",
1135218114Sbz	    " face",
1136218114Sbz	    "bytes    packets errs drop fifo frame compressed multicast",
1137218114Sbz	    "bytes    packets errs drop fifo colls carrier compressed");
113874135Sjlemon
1139196635Szec	CURVNET_SET(TD_TO_VNET(curthread));
1140108172Shsu	IFNET_RLOCK();
1141181803Sbz	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
114285129Sdes		linux_ifname(ifp, ifname, sizeof ifname);
1143218114Sbz		sbuf_printf(sb, "%6.6s: ", ifname);
1144218114Sbz		sbuf_printf(sb, "%7lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ",
1145218114Sbz		    ifp->if_ibytes,	/* rx_bytes */
1146218114Sbz		    ifp->if_ipackets,	/* rx_packets */
1147218114Sbz		    ifp->if_ierrors,	/* rx_errors */
1148218114Sbz		    ifp->if_iqdrops,	/* rx_dropped +
1149218114Sbz					 * rx_missed_errors */
1150218114Sbz		    0UL,		/* rx_fifo_errors */
1151218114Sbz		    0UL,		/* rx_length_errors +
1152218114Sbz					 * rx_over_errors +
1153218114Sbz		    			 * rx_crc_errors +
1154218114Sbz					 * rx_frame_errors */
1155218114Sbz		    0UL,		/* rx_compressed */
1156218114Sbz		    ifp->if_imcasts);	/* multicast, XXX-BZ rx only? */
115783926Sdes		sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
1158218114Sbz		    ifp->if_obytes,	/* tx_bytes */
1159218114Sbz		    ifp->if_opackets,	/* tx_packets */
1160218114Sbz		    ifp->if_oerrors,	/* tx_errors */
1161218114Sbz		    0UL,		/* tx_dropped */
1162218114Sbz		    0UL,		/* tx_fifo_errors */
1163218114Sbz		    ifp->if_collisions,	/* collisions */
1164218114Sbz		    0UL,		/* tx_carrier_errors +
1165218114Sbz					 * tx_aborted_errors +
1166218114Sbz					 * tx_window_errors +
1167218114Sbz					 * tx_heartbeat_errors */
1168218114Sbz		    0UL);		/* tx_compressed */
116974135Sjlemon	}
1170108172Shsu	IFNET_RUNLOCK();
1171196635Szec	CURVNET_RESTORE();
1172119068Sdes
117378025Sdes	return (0);
117474135Sjlemon}
117574135Sjlemon
1176158311Sambrisko/*
1177167159Sjkim * Filler function for proc/sys/kernel/osrelease
1178167159Sjkim */
1179167159Sjkimstatic int
1180167159Sjkimlinprocfs_doosrelease(PFS_FILL_ARGS)
1181167159Sjkim{
1182167159Sjkim	char osrelease[LINUX_MAX_UTSNAME];
1183167159Sjkim
1184167159Sjkim	linux_get_osrelease(td, osrelease);
1185167159Sjkim	sbuf_printf(sb, "%s\n", osrelease);
1186167159Sjkim
1187167159Sjkim	return (0);
1188167159Sjkim}
1189167159Sjkim
1190167159Sjkim/*
1191167159Sjkim * Filler function for proc/sys/kernel/ostype
1192167159Sjkim */
1193167159Sjkimstatic int
1194167159Sjkimlinprocfs_doostype(PFS_FILL_ARGS)
1195167159Sjkim{
1196167159Sjkim	char osname[LINUX_MAX_UTSNAME];
1197167159Sjkim
1198167159Sjkim	linux_get_osname(td, osname);
1199167159Sjkim	sbuf_printf(sb, "%s\n", osname);
1200167159Sjkim
1201167159Sjkim	return (0);
1202167159Sjkim}
1203167159Sjkim
1204167159Sjkim/*
1205167159Sjkim * Filler function for proc/sys/kernel/version
1206167159Sjkim */
1207167159Sjkimstatic int
1208167159Sjkimlinprocfs_doosbuild(PFS_FILL_ARGS)
1209167159Sjkim{
1210168762Sdes
1211167159Sjkim	linprocfs_osbuild(td, sb);
1212167159Sjkim	sbuf_cat(sb, "\n");
1213167159Sjkim	return (0);
1214167159Sjkim}
1215167159Sjkim
1216167159Sjkim/*
1217164692Sjkim * Filler function for proc/sys/kernel/msgmni
1218164692Sjkim */
1219164692Sjkimstatic int
1220164692Sjkimlinprocfs_domsgmni(PFS_FILL_ARGS)
1221164692Sjkim{
1222164692Sjkim
1223168067Sjkim	sbuf_printf(sb, "%d\n", msginfo.msgmni);
1224164692Sjkim	return (0);
1225164692Sjkim}
1226164692Sjkim
1227164692Sjkim/*
1228163251Skeramida * Filler function for proc/sys/kernel/pid_max
1229163129Snetchild */
1230163129Snetchildstatic int
1231163129Snetchildlinprocfs_dopid_max(PFS_FILL_ARGS)
1232163129Snetchild{
1233163757Snetchild
1234163129Snetchild	sbuf_printf(sb, "%i\n", PID_MAX);
1235163129Snetchild	return (0);
1236163129Snetchild}
1237163129Snetchild
1238163129Snetchild/*
1239164692Sjkim * Filler function for proc/sys/kernel/sem
1240164692Sjkim */
1241164692Sjkimstatic int
1242164692Sjkimlinprocfs_dosem(PFS_FILL_ARGS)
1243164692Sjkim{
1244164692Sjkim
1245168067Sjkim	sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns,
1246168067Sjkim	    seminfo.semopm, seminfo.semmni);
1247164692Sjkim	return (0);
1248164692Sjkim}
1249164692Sjkim
1250164692Sjkim/*
1251158311Sambrisko * Filler function for proc/scsi/device_info
1252158311Sambrisko */
1253158311Sambriskostatic int
1254158311Sambriskolinprocfs_doscsidevinfo(PFS_FILL_ARGS)
1255158311Sambrisko{
1256168762Sdes
1257158311Sambrisko	return (0);
1258158311Sambrisko}
1259158311Sambrisko
1260158311Sambrisko/*
1261158311Sambrisko * Filler function for proc/scsi/scsi
1262158311Sambrisko */
1263158311Sambriskostatic int
1264158311Sambriskolinprocfs_doscsiscsi(PFS_FILL_ARGS)
1265158311Sambrisko{
1266168762Sdes
1267158311Sambrisko	return (0);
1268158311Sambrisko}
1269158311Sambrisko
127085538Sphkextern struct cdevsw *cdevsw[];
127185538Sphk
127278113Sdes/*
127378113Sdes * Filler function for proc/devices
127478113Sdes */
127578025Sdesstatic int
127678025Sdeslinprocfs_dodevices(PFS_FILL_ARGS)
127774135Sjlemon{
1278158311Sambrisko	char *char_devices;
127978025Sdes	sbuf_printf(sb, "Character devices:\n");
128074135Sjlemon
1281158311Sambrisko	char_devices = linux_get_char_devices();
1282158311Sambrisko	sbuf_printf(sb, "%s", char_devices);
1283158311Sambrisko	linux_free_get_char_devices(char_devices);
128474135Sjlemon
128578025Sdes	sbuf_printf(sb, "\nBlock devices:\n");
1286119068Sdes
128778025Sdes	return (0);
128874135Sjlemon}
128974135Sjlemon
129078113Sdes/*
129178113Sdes * Filler function for proc/cmdline
129278113Sdes */
129378025Sdesstatic int
129478025Sdeslinprocfs_docmdline(PFS_FILL_ARGS)
129574135Sjlemon{
1296168762Sdes
129778025Sdes	sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
129878025Sdes	sbuf_printf(sb, " ro root=302\n");
129978025Sdes	return (0);
130078025Sdes}
130174135Sjlemon
1302205541Sjhb/*
1303205541Sjhb * Filler function for proc/filesystems
1304205541Sjhb */
1305205541Sjhbstatic int
1306205541Sjhblinprocfs_dofilesystems(PFS_FILL_ARGS)
1307205541Sjhb{
1308205541Sjhb	struct vfsconf *vfsp;
1309205541Sjhb
1310205592Sjhb	mtx_lock(&Giant);
1311205541Sjhb	TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
1312205541Sjhb		if (vfsp->vfc_flags & VFCF_SYNTHETIC)
1313205541Sjhb			sbuf_printf(sb, "nodev");
1314205541Sjhb		sbuf_printf(sb, "\t%s\n", vfsp->vfc_name);
1315205541Sjhb	}
1316205592Sjhb	mtx_unlock(&Giant);
1317205541Sjhb	return(0);
1318205541Sjhb}
1319205541Sjhb
132083926Sdes#if 0
132178025Sdes/*
132283926Sdes * Filler function for proc/modules
132383926Sdes */
132483926Sdesstatic int
132583926Sdeslinprocfs_domodules(PFS_FILL_ARGS)
132683926Sdes{
132783926Sdes	struct linker_file *lf;
1328119068Sdes
132983926Sdes	TAILQ_FOREACH(lf, &linker_files, link) {
133083926Sdes		sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
133183926Sdes		    (unsigned long)lf->size, lf->refs);
133283926Sdes	}
133383926Sdes	return (0);
133483926Sdes}
133583926Sdes#endif
133683926Sdes
133783926Sdes/*
1338204825Sed * Filler function for proc/pid/fd
1339204825Sed */
1340204825Sedstatic int
1341204825Sedlinprocfs_dofdescfs(PFS_FILL_ARGS)
1342204825Sed{
1343204825Sed
1344204825Sed	if (p == curproc)
1345204825Sed		sbuf_printf(sb, "/dev/fd");
1346204825Sed	else
1347204825Sed		sbuf_printf(sb, "unknown");
1348204825Sed	return (0);
1349204825Sed}
1350204825Sed
1351263103Seadler
1352204825Sed/*
1353263103Seadler * Filler function for proc/sys/kernel/random/uuid
1354263103Seadler */
1355263103Seadlerstatic int
1356263103Seadlerlinprocfs_douuid(PFS_FILL_ARGS)
1357263103Seadler{
1358263103Seadler	struct uuid uuid;
1359263103Seadler
1360263103Seadler	kern_uuidgen(&uuid, 1);
1361263103Seadler	sbuf_printf_uuid(sb, &uuid);
1362263103Seadler	sbuf_printf(sb, "\n");
1363263103Seadler	return(0);
1364263103Seadler}
1365263103Seadler
1366263103Seadler
1367263103Seadler/*
136885129Sdes * Constructor
136978025Sdes */
137085129Sdesstatic int
137185129Sdeslinprocfs_init(PFS_INIT_ARGS)
137285129Sdes{
137385129Sdes	struct pfs_node *root;
137485129Sdes	struct pfs_node *dir;
137574135Sjlemon
137685129Sdes	root = pi->pi_root;
137778025Sdes
1378119923Sdes	/* /proc/... */
1379119911Sdes	pfs_create_file(root, "cmdline", &linprocfs_docmdline,
1380167482Sdes	    NULL, NULL, NULL, PFS_RD);
1381119911Sdes	pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
1382167482Sdes	    NULL, NULL, NULL, PFS_RD);
1383119911Sdes	pfs_create_file(root, "devices", &linprocfs_dodevices,
1384167482Sdes	    NULL, NULL, NULL, PFS_RD);
1385205541Sjhb	pfs_create_file(root, "filesystems", &linprocfs_dofilesystems,
1386205541Sjhb	    NULL, NULL, NULL, PFS_RD);
1387119911Sdes	pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
1388167482Sdes	    NULL, NULL, NULL, PFS_RD);
1389119911Sdes	pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
1390167482Sdes	    NULL, NULL, NULL, PFS_RD);
139183926Sdes#if 0
1392119911Sdes	pfs_create_file(root, "modules", &linprocfs_domodules,
1393167482Sdes	    NULL, NULL, NULL, PFS_RD);
139483926Sdes#endif
1395158311Sambrisko	pfs_create_file(root, "mounts", &linprocfs_domtab,
1396167482Sdes	    NULL, NULL, NULL, PFS_RD);
1397119911Sdes	pfs_create_file(root, "mtab", &linprocfs_domtab,
1398167482Sdes	    NULL, NULL, NULL, PFS_RD);
1399190445Sambrisko	pfs_create_file(root, "partitions", &linprocfs_dopartitions,
1400190445Sambrisko	    NULL, NULL, NULL, PFS_RD);
140187543Sdes	pfs_create_link(root, "self", &procfs_docurproc,
1402167482Sdes	    NULL, NULL, NULL, 0);
1403119911Sdes	pfs_create_file(root, "stat", &linprocfs_dostat,
1404167482Sdes	    NULL, NULL, NULL, PFS_RD);
1405224582Skib	pfs_create_file(root, "swaps", &linprocfs_doswaps,
1406224582Skib	    NULL, NULL, NULL, PFS_RD);
1407119911Sdes	pfs_create_file(root, "uptime", &linprocfs_douptime,
1408167482Sdes	    NULL, NULL, NULL, PFS_RD);
1409119911Sdes	pfs_create_file(root, "version", &linprocfs_doversion,
1410167482Sdes	    NULL, NULL, NULL, PFS_RD);
141178025Sdes
1412119923Sdes	/* /proc/net/... */
1413167482Sdes	dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
141485129Sdes	pfs_create_file(dir, "dev", &linprocfs_donetdev,
1415167482Sdes	    NULL, NULL, NULL, PFS_RD);
141678025Sdes
1417119923Sdes	/* /proc/<pid>/... */
1418167482Sdes	dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
141985129Sdes	pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
1420167482Sdes	    NULL, NULL, NULL, PFS_RD);
1421119911Sdes	pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
1422167482Sdes	    NULL, NULL, NULL, 0);
1423116173Sobrien	pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
1424167482Sdes	    NULL, NULL, NULL, PFS_RD);
142587543Sdes	pfs_create_link(dir, "exe", &procfs_doprocfile,
1426167482Sdes	    NULL, &procfs_notsystem, NULL, 0);
1427116173Sobrien	pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
1428167482Sdes	    NULL, NULL, NULL, PFS_RD);
142985129Sdes	pfs_create_file(dir, "mem", &procfs_doprocmem,
1430167482Sdes	    &procfs_attr, &procfs_candebug, NULL, PFS_RDWR|PFS_RAW);
1431119911Sdes	pfs_create_link(dir, "root", &linprocfs_doprocroot,
1432167482Sdes	    NULL, NULL, NULL, 0);
143385129Sdes	pfs_create_file(dir, "stat", &linprocfs_doprocstat,
1434167482Sdes	    NULL, NULL, NULL, PFS_RD);
1435119911Sdes	pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
1436167482Sdes	    NULL, NULL, NULL, PFS_RD);
143785129Sdes	pfs_create_file(dir, "status", &linprocfs_doprocstatus,
1438167482Sdes	    NULL, NULL, NULL, PFS_RD);
1439204825Sed	pfs_create_link(dir, "fd", &linprocfs_dofdescfs,
1440204825Sed	    NULL, NULL, NULL, 0);
144185129Sdes
1442158311Sambrisko	/* /proc/scsi/... */
1443167482Sdes	dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
1444158311Sambrisko	pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
1445167482Sdes	    NULL, NULL, NULL, PFS_RD);
1446158311Sambrisko	pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
1447167482Sdes	    NULL, NULL, NULL, PFS_RD);
1448163129Snetchild
1449163129Snetchild	/* /proc/sys/... */
1450167482Sdes	dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
1451163129Snetchild	/* /proc/sys/kernel/... */
1452167482Sdes	dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0);
1453167159Sjkim	pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
1454167482Sdes	    NULL, NULL, NULL, PFS_RD);
1455167159Sjkim	pfs_create_file(dir, "ostype", &linprocfs_doostype,
1456167482Sdes	    NULL, NULL, NULL, PFS_RD);
1457167159Sjkim	pfs_create_file(dir, "version", &linprocfs_doosbuild,
1458167482Sdes	    NULL, NULL, NULL, PFS_RD);
1459164692Sjkim	pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
1460167482Sdes	    NULL, NULL, NULL, PFS_RD);
1461163129Snetchild	pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
1462167482Sdes	    NULL, NULL, NULL, PFS_RD);
1463164692Sjkim	pfs_create_file(dir, "sem", &linprocfs_dosem,
1464167482Sdes	    NULL, NULL, NULL, PFS_RD);
1465163129Snetchild
1466263103Seadler	/* /proc/sys/kernel/random/... */
1467263103Seadler	dir = pfs_create_dir(dir, "random", NULL, NULL, NULL, 0);
1468263103Seadler	pfs_create_file(dir, "uuid", &linprocfs_douuid,
1469263103Seadler	    NULL, NULL, NULL, PFS_RD);
1470263103Seadler
147185129Sdes	return (0);
147285129Sdes}
147385129Sdes
147485129Sdes/*
147585129Sdes * Destructor
147685129Sdes */
147785129Sdesstatic int
147885129Sdeslinprocfs_uninit(PFS_INIT_ARGS)
147985129Sdes{
148085129Sdes
148185129Sdes	/* nothing to do, pseudofs will GC */
148285129Sdes	return (0);
148385129Sdes}
148485129Sdes
1485232728SmmPSEUDOFS(linprocfs, 1, 0);
148678025SdesMODULE_DEPEND(linprocfs, linux, 1, 1, 1);
148778025SdesMODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
1488168440SjkimMODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);
1489168440SjkimMODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1);
1490