linprocfs.c revision 230755
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: stable/9/sys/compat/linprocfs/linprocfs.c 230755 2012-01-29 21:13:36Z trociny $");
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
104140214Sobrien#ifdef COMPAT_LINUX32				/* XXX */
105140214Sobrien#include <machine/../linux32/linux.h>
106140214Sobrien#else
10787275Srwatson#include <machine/../linux/linux.h>
108133822Stjr#endif
10985129Sdes#include <compat/linux/linux_ioctl.h>
11069995Sdes#include <compat/linux/linux_mib.h>
11185289Sdes#include <compat/linux/linux_util.h>
11278025Sdes#include <fs/pseudofs/pseudofs.h>
11384248Sdes#include <fs/procfs/procfs.h>
11459412Smsmith
11567588Sdes/*
11667588Sdes * Various conversion macros
11767588Sdes */
118206081Snetchild#define T2J(x) ((long)(((x) * 100ULL) / (stathz ? stathz : hz)))	/* ticks to jiffies */
119206081Snetchild#define T2CS(x) ((unsigned long)(((x) * 100ULL) / (stathz ? stathz : hz)))	/* ticks to centiseconds */
12067588Sdes#define T2S(x) ((x) / (stathz ? stathz : hz))		/* ticks to seconds */
12167588Sdes#define B2K(x) ((x) >> 10)				/* bytes to kbytes */
12269799Sdes#define B2P(x) ((x) >> PAGE_SHIFT)			/* bytes to pages */
12367588Sdes#define P2B(x) ((x) << PAGE_SHIFT)			/* pages to bytes */
12467588Sdes#define P2K(x) ((x) << (PAGE_SHIFT - 10))		/* pages to kbytes */
125206081Snetchild#define TV2J(x)	((x)->tv_sec * 100UL + (x)->tv_usec / 10000)
12674135Sjlemon
127159995Snetchild/**
128159995Snetchild * @brief Mapping of ki_stat in struct kinfo_proc to the linux state
129159995Snetchild *
130159995Snetchild * The linux procfs state field displays one of the characters RSDZTW to
131159995Snetchild * denote running, sleeping in an interruptible wait, waiting in an
132172568Skevlo * uninterruptible disk sleep, a zombie process, process is being traced
133159995Snetchild * or stopped, or process is paging respectively.
134159995Snetchild *
135159995Snetchild * Our struct kinfo_proc contains the variable ki_stat which contains a
136159995Snetchild * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK.
137159995Snetchild *
138159995Snetchild * This character array is used with ki_stati-1 as an index and tries to
139159995Snetchild * map our states to suitable linux states.
140159995Snetchild */
141166140Snetchildstatic char linux_state[] = "RRSTZDD";
142159995Snetchild
14378113Sdes/*
14478113Sdes * Filler function for proc/meminfo
14578113Sdes */
14678025Sdesstatic int
14778025Sdeslinprocfs_domeminfo(PFS_FILL_ARGS)
14859412Smsmith{
14959412Smsmith	unsigned long memtotal;		/* total memory in bytes */
15059412Smsmith	unsigned long memused;		/* used memory in bytes */
15159412Smsmith	unsigned long memfree;		/* free memory in bytes */
15259412Smsmith	unsigned long memshared;	/* shared memory ??? */
15359412Smsmith	unsigned long buffers, cached;	/* buffer / cache memory ??? */
154113574Sjhb	unsigned long long swaptotal;	/* total swap space in bytes */
155113574Sjhb	unsigned long long swapused;	/* used swap space in bytes */
156113574Sjhb	unsigned long long swapfree;	/* free swap space in bytes */
15760860Sdes	vm_object_t object;
158117723Sphk	int i, j;
15959412Smsmith
16059412Smsmith	memtotal = physmem * PAGE_SIZE;
16159412Smsmith	/*
16259412Smsmith	 * The correct thing here would be:
16359412Smsmith	 *
164170170Sattilio	memfree = cnt.v_free_count * PAGE_SIZE;
16559412Smsmith	memused = memtotal - memfree;
16659412Smsmith	 *
16759412Smsmith	 * but it might mislead linux binaries into thinking there
16859412Smsmith	 * is very little memory left, so we cheat and tell them that
16959412Smsmith	 * all memory that isn't wired down is free.
17059412Smsmith	 */
171170170Sattilio	memused = cnt.v_wire_count * PAGE_SIZE;
17259412Smsmith	memfree = memtotal - memused;
173117723Sphk	swap_pager_status(&i, &j);
174153310Smlaier	swaptotal = (unsigned long long)i * PAGE_SIZE;
175153310Smlaier	swapused = (unsigned long long)j * PAGE_SIZE;
176117723Sphk	swapfree = swaptotal - swapused;
17760860Sdes	memshared = 0;
178124082Salc	mtx_lock(&vm_object_list_mtx);
17971471Sjhb	TAILQ_FOREACH(object, &vm_object_list, object_list)
18060860Sdes		if (object->shadow_count > 1)
18160860Sdes			memshared += object->resident_page_count;
182124082Salc	mtx_unlock(&vm_object_list_mtx);
18360860Sdes	memshared *= PAGE_SIZE;
18459412Smsmith	/*
18559412Smsmith	 * We'd love to be able to write:
18659412Smsmith	 *
18759412Smsmith	buffers = bufspace;
18859412Smsmith	 *
18959412Smsmith	 * but bufspace is internal to vfs_bio.c and we don't feel
19059412Smsmith	 * like unstaticizing it just for linprocfs's sake.
19159412Smsmith	 */
19259412Smsmith	buffers = 0;
193170170Sattilio	cached = cnt.v_cache_count * PAGE_SIZE;
19459412Smsmith
19578025Sdes	sbuf_printf(sb,
19678031Sdes	    "	     total:    used:	free:  shared: buffers:	 cached:\n"
19769799Sdes	    "Mem:  %lu %lu %lu %lu %lu %lu\n"
19876839Sjlemon	    "Swap: %llu %llu %llu\n"
19969799Sdes	    "MemTotal: %9lu kB\n"
20069799Sdes	    "MemFree:  %9lu kB\n"
20169799Sdes	    "MemShared:%9lu kB\n"
20269799Sdes	    "Buffers:  %9lu kB\n"
20369799Sdes	    "Cached:   %9lu kB\n"
20476839Sjlemon	    "SwapTotal:%9llu kB\n"
20576839Sjlemon	    "SwapFree: %9llu kB\n",
20669799Sdes	    memtotal, memused, memfree, memshared, buffers, cached,
20769799Sdes	    swaptotal, swapused, swapfree,
20869799Sdes	    B2K(memtotal), B2K(memfree),
20969799Sdes	    B2K(memshared), B2K(buffers), B2K(cached),
21069799Sdes	    B2K(swaptotal), B2K(swapfree));
21159412Smsmith
21278025Sdes	return (0);
21359412Smsmith}
21459412Smsmith
215133822Stjr#if defined(__i386__) || defined(__amd64__)
21678113Sdes/*
217133822Stjr * Filler function for proc/cpuinfo (i386 & amd64 version)
21878113Sdes */
21978113Sdesstatic int
22078113Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS)
22178113Sdes{
222159544Sdes	int hw_model[2];
223159544Sdes	char model[128];
224220433Sjkim	uint64_t freq;
225159544Sdes	size_t size;
226123246Sdes	int class, fqmhz, fqkhz;
227118421Sdes	int i;
22859412Smsmith
22969799Sdes	/*
23078031Sdes	 * We default the flags to include all non-conflicting flags,
23178031Sdes	 * and the Intel versions of conflicting flags.
23269799Sdes	 */
23378031Sdes	static char *flags[] = {
23478031Sdes		"fpu",	    "vme",     "de",	   "pse",      "tsc",
23578031Sdes		"msr",	    "pae",     "mce",	   "cx8",      "apic",
23678031Sdes		"sep",	    "sep",     "mtrr",	   "pge",      "mca",
23778031Sdes		"cmov",	    "pat",     "pse36",	   "pn",       "b19",
23878031Sdes		"b20",	    "b21",     "mmxext",   "mmx",      "fxsr",
239183385Scognet		"xmm",	    "sse2",    "b27",	   "b28",      "b29",
24067589Sdes		"3dnowext", "3dnow"
24167589Sdes	};
24267589Sdes
24359412Smsmith	switch (cpu_class) {
244133822Stjr#ifdef __i386__
24559412Smsmith	case CPUCLASS_286:
24667589Sdes		class = 2;
24759412Smsmith		break;
24859412Smsmith	case CPUCLASS_386:
24967589Sdes		class = 3;
25059412Smsmith		break;
25159412Smsmith	case CPUCLASS_486:
25267589Sdes		class = 4;
25359412Smsmith		break;
25459412Smsmith	case CPUCLASS_586:
25567589Sdes		class = 5;
25659412Smsmith		break;
25759412Smsmith	case CPUCLASS_686:
25867589Sdes		class = 6;
25959412Smsmith		break;
26059412Smsmith	default:
26178031Sdes		class = 0;
26259412Smsmith		break;
263159170Sdes#else /* __amd64__ */
264133822Stjr	default:
265159170Sdes		class = 15;
266133822Stjr		break;
267133822Stjr#endif
26859412Smsmith	}
26959412Smsmith
270159544Sdes	hw_model[0] = CTL_HW;
271159544Sdes	hw_model[1] = HW_MODEL;
272159544Sdes	model[0] = '\0';
273159544Sdes	size = sizeof(model);
274159544Sdes	if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0)
275159544Sdes		strcpy(model, "unknown");
276123246Sdes	for (i = 0; i < mp_ncpus; ++i) {
277118421Sdes		sbuf_printf(sb,
278118421Sdes		    "processor\t: %d\n"
279118421Sdes		    "vendor_id\t: %.20s\n"
280214982Sdes		    "cpu family\t: %u\n"
281214982Sdes		    "model\t\t: %u\n"
282159544Sdes		    "model name\t: %s\n"
283214982Sdes		    "stepping\t: %u\n\n",
284214985Sdes		    i, cpu_vendor, CPUID_TO_FAMILY(cpu_id),
285214985Sdes		    CPUID_TO_MODEL(cpu_id), model, cpu_id & CPUID_STEPPING);
286159544Sdes		/* XXX per-cpu vendor / class / model / id? */
287118421Sdes	}
28859412Smsmith
289185766Skib	sbuf_cat(sb, "flags\t\t:");
29067589Sdes
291187594Sjkim#ifdef __i386__
292187594Sjkim	switch (cpu_vendor_id) {
293187594Sjkim	case CPU_VENDOR_AMD:
294187594Sjkim		if (class < 6)
295187594Sjkim			flags[16] = "fcmov";
296187594Sjkim		break;
297187594Sjkim	case CPU_VENDOR_CYRIX:
29867589Sdes		flags[24] = "cxmmx";
299187594Sjkim		break;
30078031Sdes	}
301187594Sjkim#endif
302119068Sdes
30378031Sdes	for (i = 0; i < 32; i++)
30467589Sdes		if (cpu_feature & (1 << i))
30578025Sdes			sbuf_printf(sb, " %s", flags[i]);
30678025Sdes	sbuf_cat(sb, "\n");
307220433Sjkim	freq = atomic_load_acq_64(&tsc_freq);
308220433Sjkim	if (freq != 0) {
309220433Sjkim		fqmhz = (freq + 4999) / 1000000;
310220433Sjkim		fqkhz = ((freq + 4999) / 10000) % 100;
31178025Sdes		sbuf_printf(sb,
31269799Sdes		    "cpu MHz\t\t: %d.%02d\n"
31369799Sdes		    "bogomips\t: %d.%02d\n",
31469799Sdes		    fqmhz, fqkhz, fqmhz, fqkhz);
31578031Sdes	}
31669995Sdes
31778025Sdes	return (0);
31859412Smsmith}
319133822Stjr#endif /* __i386__ || __amd64__ */
32065633Sdes
32178113Sdes/*
32285289Sdes * Filler function for proc/mtab
32385289Sdes *
32485289Sdes * This file doesn't exist in Linux' procfs, but is included here so
32585289Sdes * users can symlink /compat/linux/etc/mtab to /proc/mtab
32685289Sdes */
32785289Sdesstatic int
32885289Sdeslinprocfs_domtab(PFS_FILL_ARGS)
32985289Sdes{
33085289Sdes	struct nameidata nd;
33185289Sdes	struct mount *mp;
33291334Sjulian	const char *lep;
33391334Sjulian	char *dlep, *flep, *mntto, *mntfrom, *fstype;
33485289Sdes	size_t lep_len;
33585289Sdes	int error;
33685289Sdes
33785289Sdes	/* resolve symlinks etc. in the emulation tree prefix */
338168942Sdes	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td);
33985289Sdes	flep = NULL;
340168942Sdes	error = namei(&nd);
341184649Sjhb	lep = linux_emul_path;
342184649Sjhb	if (error == 0) {
343188579Sjhb		if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
344184649Sjhb			lep = dlep;
345184649Sjhb		vrele(nd.ni_vp);
346184649Sjhb		VFS_UNLOCK_GIANT(NDHASGIANT(&nd));
347184649Sjhb	}
34885289Sdes	lep_len = strlen(lep);
349119068Sdes
35085289Sdes	mtx_lock(&mountlist_mtx);
35185289Sdes	error = 0;
35285289Sdes	TAILQ_FOREACH(mp, &mountlist, mnt_list) {
35385289Sdes		/* determine device name */
35485289Sdes		mntfrom = mp->mnt_stat.f_mntfromname;
355119068Sdes
35685289Sdes		/* determine mount point */
35785289Sdes		mntto = mp->mnt_stat.f_mntonname;
35885289Sdes		if (strncmp(mntto, lep, lep_len) == 0 &&
35985289Sdes		    mntto[lep_len] == '/')
36085289Sdes			mntto += lep_len;
36185289Sdes
36285289Sdes		/* determine fs type */
36385289Sdes		fstype = mp->mnt_stat.f_fstypename;
36485289Sdes		if (strcmp(fstype, pn->pn_info->pi_name) == 0)
36585289Sdes			mntfrom = fstype = "proc";
36685289Sdes		else if (strcmp(fstype, "procfs") == 0)
36785289Sdes			continue;
368119068Sdes
369158311Sambrisko		if (strcmp(fstype, "linsysfs") == 0) {
370158311Sambrisko			sbuf_printf(sb, "/sys %s sysfs %s", mntto,
371158311Sambrisko			    mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
372158311Sambrisko		} else {
373190445Sambrisko			/* For Linux msdosfs is called vfat */
374190445Sambrisko			if (strcmp(fstype, "msdosfs") == 0)
375190445Sambrisko				fstype = "vfat";
376158311Sambrisko			sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
377158311Sambrisko			    mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
378158311Sambrisko		}
37985289Sdes#define ADD_OPTION(opt, name) \
38085289Sdes	if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name);
38185289Sdes		ADD_OPTION(MNT_SYNCHRONOUS,	"sync");
38285289Sdes		ADD_OPTION(MNT_NOEXEC,		"noexec");
38385289Sdes		ADD_OPTION(MNT_NOSUID,		"nosuid");
38485289Sdes		ADD_OPTION(MNT_UNION,		"union");
38585289Sdes		ADD_OPTION(MNT_ASYNC,		"async");
38685289Sdes		ADD_OPTION(MNT_SUIDDIR,		"suiddir");
38785289Sdes		ADD_OPTION(MNT_NOSYMFOLLOW,	"nosymfollow");
38885289Sdes		ADD_OPTION(MNT_NOATIME,		"noatime");
38985289Sdes#undef ADD_OPTION
39085289Sdes		/* a real Linux mtab will also show NFS options */
39185289Sdes		sbuf_printf(sb, " 0 0\n");
39285289Sdes	}
39385289Sdes	mtx_unlock(&mountlist_mtx);
39485289Sdes	if (flep != NULL)
39585289Sdes		free(flep, M_TEMP);
39685289Sdes	return (error);
39785289Sdes}
39885289Sdes
39985289Sdes/*
400190445Sambrisko * Filler function for proc/partitions
401190445Sambrisko *
402190445Sambrisko */
403190445Sambriskostatic int
404190445Sambriskolinprocfs_dopartitions(PFS_FILL_ARGS)
405190445Sambrisko{
406190445Sambrisko	struct g_class *cp;
407190445Sambrisko	struct g_geom *gp;
408190445Sambrisko	struct g_provider *pp;
409190445Sambrisko	struct nameidata nd;
410190445Sambrisko	const char *lep;
411190445Sambrisko	char  *dlep, *flep;
412190445Sambrisko	size_t lep_len;
413190445Sambrisko	int error;
414190445Sambrisko	int major, minor;
415190445Sambrisko
416190445Sambrisko	/* resolve symlinks etc. in the emulation tree prefix */
417190445Sambrisko	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td);
418190445Sambrisko	flep = NULL;
419190445Sambrisko	error = namei(&nd);
420190445Sambrisko	lep = linux_emul_path;
421190445Sambrisko	if (error == 0) {
422190445Sambrisko		if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
423190445Sambrisko			lep = dlep;
424190445Sambrisko		vrele(nd.ni_vp);
425190445Sambrisko		VFS_UNLOCK_GIANT(NDHASGIANT(&nd));
426190445Sambrisko	}
427190445Sambrisko	lep_len = strlen(lep);
428190445Sambrisko
429190445Sambrisko	g_topology_lock();
430190445Sambrisko	error = 0;
431190445Sambrisko	sbuf_printf(sb, "major minor  #blocks  name rio rmerge rsect "
432190445Sambrisko	    "ruse wio wmerge wsect wuse running use aveq\n");
433190445Sambrisko
434190445Sambrisko	LIST_FOREACH(cp, &g_classes, class) {
435190445Sambrisko		if (strcmp(cp->name, "DISK") == 0 ||
436190445Sambrisko		    strcmp(cp->name, "PART") == 0)
437190445Sambrisko			LIST_FOREACH(gp, &cp->geom, geom) {
438190445Sambrisko				LIST_FOREACH(pp, &gp->provider, provider) {
439190445Sambrisko					if (linux_driver_get_major_minor(
440190445Sambrisko					    pp->name, &major, &minor) != 0) {
441190445Sambrisko						major = 0;
442190445Sambrisko						minor = 0;
443190445Sambrisko					}
444190445Sambrisko					sbuf_printf(sb, "%d %d %lld %s "
445190445Sambrisko					    "%d %d %d %d %d "
446190445Sambrisko					     "%d %d %d %d %d %d\n",
447190445Sambrisko					     major, minor,
448190445Sambrisko					     (long long)pp->mediasize, pp->name,
449190445Sambrisko					     0, 0, 0, 0, 0,
450190445Sambrisko					     0, 0, 0, 0, 0, 0);
451190445Sambrisko				}
452190445Sambrisko			}
453190445Sambrisko	}
454190445Sambrisko	g_topology_unlock();
455190445Sambrisko
456190445Sambrisko	if (flep != NULL)
457190445Sambrisko		free(flep, M_TEMP);
458190445Sambrisko	return (error);
459190445Sambrisko}
460190445Sambrisko
461190445Sambrisko
462190445Sambrisko/*
46378113Sdes * Filler function for proc/stat
46478113Sdes */
46578025Sdesstatic int
46678025Sdeslinprocfs_dostat(PFS_FILL_ARGS)
46765633Sdes{
468174070Speter	struct pcpu *pcpu;
469174070Speter	long cp_time[CPUSTATES];
470174070Speter	long *cp;
471123246Sdes	int i;
472120339Sdes
473174070Speter	read_cpu_time(cp_time);
474120339Sdes	sbuf_printf(sb, "cpu %ld %ld %ld %ld\n",
475120339Sdes	    T2J(cp_time[CP_USER]),
476120339Sdes	    T2J(cp_time[CP_NICE]),
477120339Sdes	    T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
478120339Sdes	    T2J(cp_time[CP_IDLE]));
479209059Sjhb	CPU_FOREACH(i) {
480174070Speter		pcpu = pcpu_find(i);
481174070Speter		cp = pcpu->pc_cp_time;
482143194Ssobomax		sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i,
483174070Speter		    T2J(cp[CP_USER]),
484174070Speter		    T2J(cp[CP_NICE]),
485174070Speter		    T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/),
486174070Speter		    T2J(cp[CP_IDLE]));
487174070Speter	}
48878025Sdes	sbuf_printf(sb,
48969799Sdes	    "disk 0 0 0 0\n"
49069799Sdes	    "page %u %u\n"
49169799Sdes	    "swap %u %u\n"
49269799Sdes	    "intr %u\n"
49369799Sdes	    "ctxt %u\n"
49485657Sdillon	    "btime %lld\n",
495170170Sattilio	    cnt.v_vnodepgsin,
496170170Sattilio	    cnt.v_vnodepgsout,
497170170Sattilio	    cnt.v_swappgsin,
498170170Sattilio	    cnt.v_swappgsout,
499170170Sattilio	    cnt.v_intr,
500170170Sattilio	    cnt.v_swtch,
501113574Sjhb	    (long long)boottime.tv_sec);
50278025Sdes	return (0);
50365633Sdes}
50465633Sdes
505224582Skibstatic int
506224582Skiblinprocfs_doswaps(PFS_FILL_ARGS)
507224582Skib{
508224582Skib	struct xswdev xsw;
509224582Skib	uintmax_t total, used;
510224582Skib	int n;
511224582Skib	char devname[SPECNAMELEN + 1];
512224582Skib
513224582Skib	sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
514224582Skib	mtx_lock(&Giant);
515224582Skib	for (n = 0; ; n++) {
516224582Skib		if (swap_dev_info(n, &xsw, devname, sizeof(devname)) != 0)
517224582Skib			break;
518224582Skib		total = (uintmax_t)xsw.xsw_nblks * PAGE_SIZE / 1024;
519224582Skib		used  = (uintmax_t)xsw.xsw_used * PAGE_SIZE / 1024;
520224582Skib
521224582Skib		/*
522224582Skib		 * The space and not tab after the device name is on
523224582Skib		 * purpose.  Linux does so.
524224582Skib		 */
525224582Skib		sbuf_printf(sb, "/dev/%-34s unknown\t\t%jd\t%jd\t-1\n",
526224582Skib		    devname, total, used);
527224582Skib	}
528224582Skib	mtx_unlock(&Giant);
529224582Skib	return (0);
530224582Skib}
531224582Skib
53278113Sdes/*
53378113Sdes * Filler function for proc/uptime
53478113Sdes */
53578025Sdesstatic int
53678025Sdeslinprocfs_douptime(PFS_FILL_ARGS)
53765633Sdes{
538174070Speter	long cp_time[CPUSTATES];
53965633Sdes	struct timeval tv;
54065633Sdes
54165633Sdes	getmicrouptime(&tv);
542174070Speter	read_cpu_time(cp_time);
543206081Snetchild	sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n",
544113574Sjhb	    (long long)tv.tv_sec, tv.tv_usec / 10000,
545206081Snetchild	    T2S(cp_time[CP_IDLE] / mp_ncpus),
546206081Snetchild	    T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100);
54778025Sdes	return (0);
54865633Sdes}
54965633Sdes
55078113Sdes/*
551167159Sjkim * Get OS build date
552167159Sjkim */
553167159Sjkimstatic void
554167159Sjkimlinprocfs_osbuild(struct thread *td, struct sbuf *sb)
555167159Sjkim{
556167159Sjkim#if 0
557167159Sjkim	char osbuild[256];
558167159Sjkim	char *cp1, *cp2;
559167159Sjkim
560167159Sjkim	strncpy(osbuild, version, 256);
561167159Sjkim	osbuild[255] = '\0';
562167159Sjkim	cp1 = strstr(osbuild, "\n");
563167159Sjkim	cp2 = strstr(osbuild, ":");
564167159Sjkim	if (cp1 && cp2) {
565167159Sjkim		*cp1 = *cp2 = '\0';
566167159Sjkim		cp1 = strstr(osbuild, "#");
567167159Sjkim	} else
568167159Sjkim		cp1 = NULL;
569167159Sjkim	if (cp1)
570167159Sjkim		sbuf_printf(sb, "%s%s", cp1, cp2 + 1);
571167159Sjkim	else
572167159Sjkim#endif
573167159Sjkim		sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977");
574167159Sjkim}
575167159Sjkim
576167159Sjkim/*
577167159Sjkim * Get OS builder
578167159Sjkim */
579167159Sjkimstatic void
580167159Sjkimlinprocfs_osbuilder(struct thread *td, struct sbuf *sb)
581167159Sjkim{
582168762Sdes#if 0
583167159Sjkim	char builder[256];
584167159Sjkim	char *cp;
585167159Sjkim
586167159Sjkim	cp = strstr(version, "\n    ");
587167159Sjkim	if (cp) {
588167159Sjkim		strncpy(builder, cp + 5, 256);
589167159Sjkim		builder[255] = '\0';
590167159Sjkim		cp = strstr(builder, ":");
591167159Sjkim		if (cp)
592167159Sjkim			*cp = '\0';
593167159Sjkim	}
594167159Sjkim	if (cp)
595167159Sjkim		sbuf_cat(sb, builder);
596167159Sjkim	else
597168762Sdes#endif
598167159Sjkim		sbuf_cat(sb, "des@freebsd.org");
599167159Sjkim}
600167159Sjkim
601167159Sjkim/*
60278113Sdes * Filler function for proc/version
60378113Sdes */
60478025Sdesstatic int
60578025Sdeslinprocfs_doversion(PFS_FILL_ARGS)
60665633Sdes{
60787275Srwatson	char osname[LINUX_MAX_UTSNAME];
60887275Srwatson	char osrelease[LINUX_MAX_UTSNAME];
60987275Srwatson
610112206Sjhb	linux_get_osname(td, osname);
611112206Sjhb	linux_get_osrelease(td, osrelease);
612167159Sjkim	sbuf_printf(sb, "%s version %s (", osname, osrelease);
613167159Sjkim	linprocfs_osbuilder(td, sb);
614167159Sjkim	sbuf_cat(sb, ") (gcc version " __VERSION__ ") ");
615167159Sjkim	linprocfs_osbuild(td, sb);
616167159Sjkim	sbuf_cat(sb, "\n");
61787275Srwatson
61878025Sdes	return (0);
61965633Sdes}
62065633Sdes
62178113Sdes/*
62278113Sdes * Filler function for proc/loadavg
62378113Sdes */
62478025Sdesstatic int
62578025Sdeslinprocfs_doloadavg(PFS_FILL_ARGS)
62676839Sjlemon{
627168762Sdes
62878025Sdes	sbuf_printf(sb,
62976839Sjlemon	    "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
63076839Sjlemon	    (int)(averunnable.ldavg[0] / averunnable.fscale),
63176839Sjlemon	    (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
63276839Sjlemon	    (int)(averunnable.ldavg[1] / averunnable.fscale),
63376839Sjlemon	    (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
63476839Sjlemon	    (int)(averunnable.ldavg[2] / averunnable.fscale),
63576839Sjlemon	    (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
63676839Sjlemon	    1,				/* number of running tasks */
63776839Sjlemon	    nprocs,			/* number of tasks */
63878116Sdes	    lastpid			/* the last pid */
63976839Sjlemon	);
64078025Sdes	return (0);
64176839Sjlemon}
64276839Sjlemon
64378113Sdes/*
64478113Sdes * Filler function for proc/pid/stat
64578113Sdes */
64678025Sdesstatic int
64778025Sdeslinprocfs_doprocstat(PFS_FILL_ARGS)
64867588Sdes{
64969995Sdes	struct kinfo_proc kp;
650166140Snetchild	char state;
651166140Snetchild	static int ratelimit = 0;
652206081Snetchild	vm_offset_t startcode, startdata;
65367588Sdes
65494307Sjhb	PROC_LOCK(p);
65569995Sdes	fill_kinfo_proc(p, &kp);
656206081Snetchild	if (p->p_vmspace) {
657206081Snetchild	   startcode = (vm_offset_t)p->p_vmspace->vm_taddr;
658206081Snetchild	   startdata = (vm_offset_t)p->p_vmspace->vm_daddr;
659206081Snetchild	} else {
660206081Snetchild	   startcode = 0;
661206081Snetchild	   startdata = 0;
662206081Snetchild	};
66378025Sdes	sbuf_printf(sb, "%d", p->p_pid);
66478025Sdes#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
66567588Sdes	PS_ADD("comm",		"(%s)",	p->p_comm);
666166140Snetchild	if (kp.ki_stat > sizeof(linux_state)) {
667166140Snetchild		state = 'R';
668166140Snetchild
669166141Snetchild		if (ratelimit == 0) {
670166162Snetchild			printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n",
671166162Snetchild			    kp.ki_stat, sizeof(linux_state));
672166141Snetchild			++ratelimit;
673166141Snetchild		}
674166140Snetchild	} else
675166140Snetchild		state = linux_state[kp.ki_stat - 1];
676166140Snetchild	PS_ADD("state",		"%c",	state);
67773923Sjhb	PS_ADD("ppid",		"%d",	p->p_pptr ? p->p_pptr->p_pid : 0);
67867588Sdes	PS_ADD("pgrp",		"%d",	p->p_pgid);
67967588Sdes	PS_ADD("session",	"%d",	p->p_session->s_sid);
68091140Stanimura	PROC_UNLOCK(p);
681206081Snetchild	PS_ADD("tty",		"%d",	kp.ki_tdev);
682159995Snetchild	PS_ADD("tpgid",		"%d",	kp.ki_tpgid);
68367588Sdes	PS_ADD("flags",		"%u",	0); /* XXX */
684159995Snetchild	PS_ADD("minflt",	"%lu",	kp.ki_rusage.ru_minflt);
685159995Snetchild	PS_ADD("cminflt",	"%lu",	kp.ki_rusage_ch.ru_minflt);
686159995Snetchild	PS_ADD("majflt",	"%lu",	kp.ki_rusage.ru_majflt);
687159995Snetchild	PS_ADD("cmajflt",	"%lu",	kp.ki_rusage_ch.ru_majflt);
688206081Snetchild	PS_ADD("utime",		"%ld",	TV2J(&kp.ki_rusage.ru_utime));
689206081Snetchild	PS_ADD("stime",		"%ld",	TV2J(&kp.ki_rusage.ru_stime));
690206081Snetchild	PS_ADD("cutime",	"%ld",	TV2J(&kp.ki_rusage_ch.ru_utime));
691206081Snetchild	PS_ADD("cstime",	"%ld",	TV2J(&kp.ki_rusage_ch.ru_stime));
692159995Snetchild	PS_ADD("priority",	"%d",	kp.ki_pri.pri_user);
693159995Snetchild	PS_ADD("nice",		"%d",	kp.ki_nice); /* 19 (nicest) to -19 */
694159995Snetchild	PS_ADD("0",		"%d",	0); /* removed field */
695159995Snetchild	PS_ADD("itrealvalue",	"%d",	0); /* XXX */
696206081Snetchild	PS_ADD("starttime",	"%lu",	TV2J(&kp.ki_start) - TV2J(&boottime));
697159995Snetchild	PS_ADD("vsize",		"%ju",	P2K((uintmax_t)kp.ki_size));
698159995Snetchild	PS_ADD("rss",		"%ju",	(uintmax_t)kp.ki_rssize);
699159995Snetchild	PS_ADD("rlim",		"%lu",	kp.ki_rusage.ru_maxrss);
700206081Snetchild	PS_ADD("startcode",	"%ju",	(uintmax_t)startcode);
701206081Snetchild	PS_ADD("endcode",	"%ju",	(uintmax_t)startdata);
70267588Sdes	PS_ADD("startstack",	"%u",	0); /* XXX */
703159995Snetchild	PS_ADD("kstkesp",	"%u",	0); /* XXX */
704159995Snetchild	PS_ADD("kstkeip",	"%u",	0); /* XXX */
705159995Snetchild	PS_ADD("signal",	"%u",	0); /* XXX */
706159995Snetchild	PS_ADD("blocked",	"%u",	0); /* XXX */
707159995Snetchild	PS_ADD("sigignore",	"%u",	0); /* XXX */
708159995Snetchild	PS_ADD("sigcatch",	"%u",	0); /* XXX */
70967588Sdes	PS_ADD("wchan",		"%u",	0); /* XXX */
710159995Snetchild	PS_ADD("nswap",		"%lu",	kp.ki_rusage.ru_nswap);
711159995Snetchild	PS_ADD("cnswap",	"%lu",	kp.ki_rusage_ch.ru_nswap);
71269799Sdes	PS_ADD("exitsignal",	"%d",	0); /* XXX */
713159995Snetchild	PS_ADD("processor",	"%u",	kp.ki_lastcpu);
714159995Snetchild	PS_ADD("rt_priority",	"%u",	0); /* XXX */ /* >= 2.5.19 */
715159995Snetchild	PS_ADD("policy",	"%u",	kp.ki_pri.pri_class); /* >= 2.5.19 */
71667588Sdes#undef PS_ADD
71778025Sdes	sbuf_putc(sb, '\n');
718119068Sdes
71978025Sdes	return (0);
72067588Sdes}
72167588Sdes
72267588Sdes/*
723119911Sdes * Filler function for proc/pid/statm
724119911Sdes */
725119911Sdesstatic int
726119911Sdeslinprocfs_doprocstatm(PFS_FILL_ARGS)
727119911Sdes{
728119911Sdes	struct kinfo_proc kp;
729119911Sdes	segsz_t lsize;
730120340Sdes
731119911Sdes	PROC_LOCK(p);
732119911Sdes	fill_kinfo_proc(p, &kp);
733119911Sdes	PROC_UNLOCK(p);
734119911Sdes
735119911Sdes	/*
736119911Sdes	 * See comments in linprocfs_doprocstatus() regarding the
737119911Sdes	 * computation of lsize.
738119911Sdes	 */
739119911Sdes	/* size resident share trs drs lrs dt */
740119911Sdes	sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size));
741119911Sdes	sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize);
742119911Sdes	sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */
743119911Sdes	sbuf_printf(sb, "%ju ",	(uintmax_t)kp.ki_tsize);
744119911Sdes	sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize));
745119911Sdes	lsize = B2P(kp.ki_size) - kp.ki_dsize -
746119911Sdes	    kp.ki_ssize - kp.ki_tsize - 1;
747119911Sdes	sbuf_printf(sb, "%ju ", (uintmax_t)lsize);
748119911Sdes	sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */
749119911Sdes
750119911Sdes	return (0);
751119911Sdes}
752119911Sdes
753119911Sdes/*
75478113Sdes * Filler function for proc/pid/status
75578113Sdes */
75678025Sdesstatic int
75778025Sdeslinprocfs_doprocstatus(PFS_FILL_ARGS)
75867588Sdes{
75969995Sdes	struct kinfo_proc kp;
76067588Sdes	char *state;
76169799Sdes	segsz_t lsize;
76299072Sjulian	struct thread *td2;
763114983Sjhb	struct sigacts *ps;
76474135Sjlemon	int i;
76567588Sdes
766113611Sjhb	PROC_LOCK(p);
76799072Sjulian	td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */
76899072Sjulian
76999072Sjulian	if (P_SHOULDSTOP(p)) {
77099072Sjulian		state = "T (stopped)";
77199072Sjulian	} else {
77299072Sjulian		switch(p->p_state) {
77399072Sjulian		case PRS_NEW:
77499072Sjulian			state = "I (idle)";
77599072Sjulian			break;
77699072Sjulian		case PRS_NORMAL:
77799072Sjulian			if (p->p_flag & P_WEXIT) {
77899072Sjulian				state = "X (exiting)";
77999072Sjulian				break;
78099072Sjulian			}
78199072Sjulian			switch(td2->td_state) {
782103216Sjulian			case TDS_INHIBITED:
78399072Sjulian				state = "S (sleeping)";
78499072Sjulian				break;
78599072Sjulian			case TDS_RUNQ:
78699072Sjulian			case TDS_RUNNING:
78799072Sjulian				state = "R (running)";
78899072Sjulian				break;
78999072Sjulian			default:
79099072Sjulian				state = "? (unknown)";
79199072Sjulian				break;
79299072Sjulian			}
79399072Sjulian			break;
79499072Sjulian		case PRS_ZOMBIE:
79599072Sjulian			state = "Z (zombie)";
79699072Sjulian			break;
79799072Sjulian		default:
79899072Sjulian			state = "? (unknown)";
79999072Sjulian			break;
80099072Sjulian		}
80199072Sjulian	}
80267588Sdes
80369995Sdes	fill_kinfo_proc(p, &kp);
80478025Sdes	sbuf_printf(sb, "Name:\t%s\n",		p->p_comm); /* XXX escape */
80578031Sdes	sbuf_printf(sb, "State:\t%s\n",		state);
80667588Sdes
80767588Sdes	/*
80867588Sdes	 * Credentials
80967588Sdes	 */
81078025Sdes	sbuf_printf(sb, "Pid:\t%d\n",		p->p_pid);
81178025Sdes	sbuf_printf(sb, "PPid:\t%d\n",		p->p_pptr ?
81273923Sjhb						p->p_pptr->p_pid : 0);
81378031Sdes	sbuf_printf(sb, "Uid:\t%d %d %d %d\n",	p->p_ucred->cr_ruid,
81478031Sdes						p->p_ucred->cr_uid,
81578031Sdes						p->p_ucred->cr_svuid,
81678031Sdes						/* FreeBSD doesn't have fsuid */
81778031Sdes						p->p_ucred->cr_uid);
81878031Sdes	sbuf_printf(sb, "Gid:\t%d %d %d %d\n",	p->p_ucred->cr_rgid,
81978031Sdes						p->p_ucred->cr_gid,
82078031Sdes						p->p_ucred->cr_svgid,
82178031Sdes						/* FreeBSD doesn't have fsgid */
82278031Sdes						p->p_ucred->cr_gid);
82378025Sdes	sbuf_cat(sb, "Groups:\t");
82467588Sdes	for (i = 0; i < p->p_ucred->cr_ngroups; i++)
82578031Sdes		sbuf_printf(sb, "%d ",		p->p_ucred->cr_groups[i]);
82671471Sjhb	PROC_UNLOCK(p);
82778025Sdes	sbuf_putc(sb, '\n');
828119068Sdes
82967588Sdes	/*
83067588Sdes	 * Memory
83169799Sdes	 *
83269799Sdes	 * While our approximation of VmLib may not be accurate (I
83369799Sdes	 * don't know of a simple way to verify it, and I'm not sure
83469799Sdes	 * it has much meaning anyway), I believe it's good enough.
83569799Sdes	 *
83669799Sdes	 * The same code that could (I think) accurately compute VmLib
83769799Sdes	 * could also compute VmLck, but I don't really care enough to
83869799Sdes	 * implement it. Submissions are welcome.
83967588Sdes	 */
840113574Sjhb	sbuf_printf(sb, "VmSize:\t%8ju kB\n",	B2K((uintmax_t)kp.ki_size));
84178025Sdes	sbuf_printf(sb, "VmLck:\t%8u kB\n",	P2K(0)); /* XXX */
842206081Snetchild	sbuf_printf(sb, "VmRSS:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_rssize));
843113574Sjhb	sbuf_printf(sb, "VmData:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_dsize));
844113574Sjhb	sbuf_printf(sb, "VmStk:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_ssize));
845113574Sjhb	sbuf_printf(sb, "VmExe:\t%8ju kB\n",	P2K((uintmax_t)kp.ki_tsize));
84669995Sdes	lsize = B2P(kp.ki_size) - kp.ki_dsize -
84769995Sdes	    kp.ki_ssize - kp.ki_tsize - 1;
848113574Sjhb	sbuf_printf(sb, "VmLib:\t%8ju kB\n",	P2K((uintmax_t)lsize));
84967588Sdes
85067588Sdes	/*
85167588Sdes	 * Signal masks
85267588Sdes	 *
85367588Sdes	 * We support up to 128 signals, while Linux supports 32,
85467588Sdes	 * but we only define 32 (the same 32 as Linux, to boot), so
85567588Sdes	 * just show the lower 32 bits of each mask. XXX hack.
85667588Sdes	 *
85767588Sdes	 * NB: on certain platforms (Sparc at least) Linux actually
85867588Sdes	 * supports 64 signals, but this code is a long way from
85967588Sdes	 * running on anything but i386, so ignore that for now.
86067588Sdes	 */
86171471Sjhb	PROC_LOCK(p);
862104306Sjmallett	sbuf_printf(sb, "SigPnd:\t%08x\n",	p->p_siglist.__bits[0]);
86369799Sdes	/*
86469799Sdes	 * I can't seem to find out where the signal mask is in
86569799Sdes	 * relation to struct proc, so SigBlk is left unimplemented.
86669799Sdes	 */
86778025Sdes	sbuf_printf(sb, "SigBlk:\t%08x\n",	0); /* XXX */
868114983Sjhb	ps = p->p_sigacts;
869114983Sjhb	mtx_lock(&ps->ps_mtx);
870114983Sjhb	sbuf_printf(sb, "SigIgn:\t%08x\n",	ps->ps_sigignore.__bits[0]);
871114983Sjhb	sbuf_printf(sb, "SigCgt:\t%08x\n",	ps->ps_sigcatch.__bits[0]);
872114983Sjhb	mtx_unlock(&ps->ps_mtx);
87371471Sjhb	PROC_UNLOCK(p);
874119068Sdes
87567588Sdes	/*
87667588Sdes	 * Linux also prints the capability masks, but we don't have
87767588Sdes	 * capabilities yet, and when we do get them they're likely to
87867588Sdes	 * be meaningless to Linux programs, so we lie. XXX
87967588Sdes	 */
88078025Sdes	sbuf_printf(sb, "CapInh:\t%016x\n",	0);
88178025Sdes	sbuf_printf(sb, "CapPrm:\t%016x\n",	0);
88278025Sdes	sbuf_printf(sb, "CapEff:\t%016x\n",	0);
883119068Sdes
88478025Sdes	return (0);
88567588Sdes}
88674135Sjlemon
887119911Sdes
88878113Sdes/*
889119911Sdes * Filler function for proc/pid/cwd
890119911Sdes */
891119911Sdesstatic int
892119911Sdeslinprocfs_doproccwd(PFS_FILL_ARGS)
893119911Sdes{
894119911Sdes	char *fullpath = "unknown";
895119911Sdes	char *freepath = NULL;
896119911Sdes
897119911Sdes	vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath);
898119911Sdes	sbuf_printf(sb, "%s", fullpath);
899119911Sdes	if (freepath)
900119911Sdes		free(freepath, M_TEMP);
901119911Sdes	return (0);
902119911Sdes}
903119911Sdes
904119911Sdes/*
905119911Sdes * Filler function for proc/pid/root
906119911Sdes */
907119911Sdesstatic int
908119911Sdeslinprocfs_doprocroot(PFS_FILL_ARGS)
909119911Sdes{
910119911Sdes	struct vnode *rvp;
911119911Sdes	char *fullpath = "unknown";
912119911Sdes	char *freepath = NULL;
913119911Sdes
914119911Sdes	rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir;
915119911Sdes	vn_fullpath(td, rvp, &fullpath, &freepath);
916119911Sdes	sbuf_printf(sb, "%s", fullpath);
917119911Sdes	if (freepath)
918119911Sdes		free(freepath, M_TEMP);
919119911Sdes	return (0);
920119911Sdes}
921119911Sdes
92278113Sdes/*
923213246Skib * Filler function for proc/pid/cmdline
924213246Skib */
925213246Skibstatic int
926213246Skiblinprocfs_doproccmdline(PFS_FILL_ARGS)
927213246Skib{
928213246Skib	int ret;
929213246Skib
930213246Skib	PROC_LOCK(p);
931213246Skib	if ((ret = p_cansee(td, p)) != 0) {
932213246Skib		PROC_UNLOCK(p);
933213246Skib		return (ret);
934213246Skib	}
935223182Spluknet
936223182Spluknet	/*
937223182Spluknet	 * Mimic linux behavior and pass only processes with usermode
938223182Spluknet	 * address space as valid.  Return zero silently otherwize.
939223182Spluknet	 */
940223182Spluknet	if (p->p_vmspace == &vmspace0) {
941223182Spluknet		PROC_UNLOCK(p);
942223182Spluknet		return (0);
943223182Spluknet	}
944213246Skib	if (p->p_args != NULL) {
945213246Skib		sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
946213246Skib		PROC_UNLOCK(p);
947213246Skib		return (0);
948213246Skib	}
949230754Strociny
950230754Strociny	if ((p->p_flag & P_SYSTEM) != 0) {
951230754Strociny		PROC_UNLOCK(p);
952230754Strociny		return (0);
953230754Strociny	}
954230754Strociny
955213246Skib	PROC_UNLOCK(p);
956213246Skib
957230754Strociny	ret = proc_getargv(td, p, sb);
958213246Skib	return (ret);
959213246Skib}
960213246Skib
961213246Skib/*
962116173Sobrien * Filler function for proc/pid/environ
963116173Sobrien */
964116173Sobrienstatic int
965116173Sobrienlinprocfs_doprocenviron(PFS_FILL_ARGS)
966116173Sobrien{
967212723Sdes	int ret;
968168762Sdes
969212723Sdes	PROC_LOCK(p);
970230755Strociny	if ((ret = p_candebug(td, p)) != 0) {
971212723Sdes		PROC_UNLOCK(p);
972213246Skib		return (ret);
973212723Sdes	}
974223182Spluknet
975223182Spluknet	/*
976223182Spluknet	 * Mimic linux behavior and pass only processes with usermode
977223182Spluknet	 * address space as valid.  Return zero silently otherwize.
978223182Spluknet	 */
979223182Spluknet	if (p->p_vmspace == &vmspace0) {
980223182Spluknet		PROC_UNLOCK(p);
981223182Spluknet		return (0);
982223182Spluknet	}
983230754Strociny
984230754Strociny	if ((p->p_flag & P_SYSTEM) != 0) {
985230754Strociny		PROC_UNLOCK(p);
986230754Strociny		return (0);
987230754Strociny	}
988230754Strociny
989213246Skib	PROC_UNLOCK(p);
990212723Sdes
991230754Strociny	ret = proc_getenvv(td, p, sb);
992212723Sdes	return (ret);
993116173Sobrien}
994116173Sobrien
995116173Sobrien/*
996116173Sobrien * Filler function for proc/pid/maps
997116173Sobrien */
998116173Sobrienstatic int
999116173Sobrienlinprocfs_doprocmaps(PFS_FILL_ARGS)
1000116173Sobrien{
1001185984Skib	struct vmspace *vm;
1002185984Skib	vm_map_t map;
1003185765Skib	vm_map_entry_t entry, tmp_entry;
1004121265Scognet	vm_object_t obj, tobj, lobj;
1005185765Skib	vm_offset_t e_start, e_end;
1006121265Scognet	vm_ooffset_t off = 0;
1007185765Skib	vm_prot_t e_prot;
1008185765Skib	unsigned int last_timestamp;
1009121265Scognet	char *name = "", *freename = NULL;
1010121265Scognet	ino_t ino;
1011121265Scognet	int ref_count, shadow_count, flags;
1012121265Scognet	int error;
1013137507Sphk	struct vnode *vp;
1014137507Sphk	struct vattr vat;
1015161094Skib	int locked;
1016168762Sdes
1017121246Scognet	PROC_LOCK(p);
1018121246Scognet	error = p_candebug(td, p);
1019121246Scognet	PROC_UNLOCK(p);
1020121246Scognet	if (error)
1021121246Scognet		return (error);
1022168762Sdes
1023121246Scognet	if (uio->uio_rw != UIO_READ)
1024121246Scognet		return (EOPNOTSUPP);
1025168762Sdes
1026121246Scognet	error = 0;
1027185984Skib	vm = vmspace_acquire_ref(p);
1028185984Skib	if (vm == NULL)
1029185984Skib		return (ESRCH);
1030185984Skib	map = &vm->vm_map;
1031169156Salc	vm_map_lock_read(map);
1032183600Skib	for (entry = map->header.next; entry != &map->header;
1033121246Scognet	    entry = entry->next) {
1034121265Scognet		name = "";
1035121265Scognet		freename = NULL;
1036121246Scognet		if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
1037121246Scognet			continue;
1038185765Skib		e_prot = entry->protection;
1039185765Skib		e_start = entry->start;
1040185765Skib		e_end = entry->end;
1041121246Scognet		obj = entry->object.vm_object;
1042169156Salc		for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) {
1043169156Salc			VM_OBJECT_LOCK(tobj);
1044169156Salc			if (lobj != obj)
1045169156Salc				VM_OBJECT_UNLOCK(lobj);
1046121246Scognet			lobj = tobj;
1047169156Salc		}
1048185765Skib		last_timestamp = map->timestamp;
1049185765Skib		vm_map_unlock_read(map);
1050121246Scognet		ino = 0;
1051121246Scognet		if (lobj) {
1052121246Scognet			off = IDX_TO_OFF(lobj->size);
1053161094Skib			if (lobj->type == OBJT_VNODE) {
1054161094Skib				vp = lobj->handle;
1055161094Skib				if (vp)
1056161094Skib					vref(vp);
1057121246Scognet			}
1058161094Skib			else
1059161094Skib				vp = NULL;
1060169156Salc			if (lobj != obj)
1061169156Salc				VM_OBJECT_UNLOCK(lobj);
1062121246Scognet			flags = obj->flags;
1063121246Scognet			ref_count = obj->ref_count;
1064121246Scognet			shadow_count = obj->shadow_count;
1065169156Salc			VM_OBJECT_UNLOCK(obj);
1066161094Skib			if (vp) {
1067161094Skib				vn_fullpath(td, vp, &name, &freename);
1068161094Skib				locked = VFS_LOCK_GIANT(vp->v_mount);
1069175202Sattilio				vn_lock(vp, LK_SHARED | LK_RETRY);
1070182371Sattilio				VOP_GETATTR(vp, &vat, td->td_ucred);
1071161094Skib				ino = vat.va_fileid;
1072161094Skib				vput(vp);
1073161094Skib				VFS_UNLOCK_GIANT(locked);
1074161094Skib			}
1075121246Scognet		} else {
1076121246Scognet			flags = 0;
1077121246Scognet			ref_count = 0;
1078121246Scognet			shadow_count = 0;
1079121246Scognet		}
1080168762Sdes
1081121246Scognet		/*
1082168762Sdes		 * format:
1083121246Scognet		 *  start, end, access, offset, major, minor, inode, name.
1084121246Scognet		 */
1085183600Skib		error = sbuf_printf(sb,
1086121246Scognet		    "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n",
1087185765Skib		    (u_long)e_start, (u_long)e_end,
1088185765Skib		    (e_prot & VM_PROT_READ)?"r":"-",
1089185765Skib		    (e_prot & VM_PROT_WRITE)?"w":"-",
1090185765Skib		    (e_prot & VM_PROT_EXECUTE)?"x":"-",
1091121246Scognet		    "p",
1092121265Scognet		    (u_long)off,
1093121246Scognet		    0,
1094121246Scognet		    0,
1095121265Scognet		    (u_long)ino,
1096121246Scognet		    *name ? "     " : "",
1097121246Scognet		    name
1098121246Scognet		    );
1099121246Scognet		if (freename)
1100121246Scognet			free(freename, M_TEMP);
1101185864Skib		vm_map_lock_read(map);
1102183600Skib		if (error == -1) {
1103183600Skib			error = 0;
1104121246Scognet			break;
1105169156Salc		}
1106186563Skib		if (last_timestamp != map->timestamp) {
1107185765Skib			/*
1108185765Skib			 * Look again for the entry because the map was
1109185765Skib			 * modified while it was unlocked.  Specifically,
1110185765Skib			 * the entry may have been clipped, merged, or deleted.
1111185765Skib			 */
1112185765Skib			vm_map_lookup_entry(map, e_end - 1, &tmp_entry);
1113185765Skib			entry = tmp_entry;
1114185765Skib		}
1115121246Scognet	}
1116169156Salc	vm_map_unlock_read(map);
1117185984Skib	vmspace_free(vm);
1118168762Sdes
1119121246Scognet	return (error);
1120168762Sdes}
1121168762Sdes
1122116173Sobrien/*
112378113Sdes * Filler function for proc/net/dev
112478113Sdes */
112578025Sdesstatic int
112678025Sdeslinprocfs_donetdev(PFS_FILL_ARGS)
112774135Sjlemon{
112885129Sdes	char ifname[16]; /* XXX LINUX_IFNAMSIZ */
112974135Sjlemon	struct ifnet *ifp;
113074135Sjlemon
1131218114Sbz	sbuf_printf(sb, "%6s|%58s|%s\n"
1132218114Sbz	    "%6s|%58s|%58s\n",
1133218114Sbz	    "Inter-", "   Receive", "  Transmit",
1134218114Sbz	    " face",
1135218114Sbz	    "bytes    packets errs drop fifo frame compressed multicast",
1136218114Sbz	    "bytes    packets errs drop fifo colls carrier compressed");
113774135Sjlemon
1138196635Szec	CURVNET_SET(TD_TO_VNET(curthread));
1139108172Shsu	IFNET_RLOCK();
1140181803Sbz	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
114185129Sdes		linux_ifname(ifp, ifname, sizeof ifname);
1142218114Sbz		sbuf_printf(sb, "%6.6s: ", ifname);
1143218114Sbz		sbuf_printf(sb, "%7lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ",
1144218114Sbz		    ifp->if_ibytes,	/* rx_bytes */
1145218114Sbz		    ifp->if_ipackets,	/* rx_packets */
1146218114Sbz		    ifp->if_ierrors,	/* rx_errors */
1147218114Sbz		    ifp->if_iqdrops,	/* rx_dropped +
1148218114Sbz					 * rx_missed_errors */
1149218114Sbz		    0UL,		/* rx_fifo_errors */
1150218114Sbz		    0UL,		/* rx_length_errors +
1151218114Sbz					 * rx_over_errors +
1152218114Sbz		    			 * rx_crc_errors +
1153218114Sbz					 * rx_frame_errors */
1154218114Sbz		    0UL,		/* rx_compressed */
1155218114Sbz		    ifp->if_imcasts);	/* multicast, XXX-BZ rx only? */
115683926Sdes		sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
1157218114Sbz		    ifp->if_obytes,	/* tx_bytes */
1158218114Sbz		    ifp->if_opackets,	/* tx_packets */
1159218114Sbz		    ifp->if_oerrors,	/* tx_errors */
1160218114Sbz		    0UL,		/* tx_dropped */
1161218114Sbz		    0UL,		/* tx_fifo_errors */
1162218114Sbz		    ifp->if_collisions,	/* collisions */
1163218114Sbz		    0UL,		/* tx_carrier_errors +
1164218114Sbz					 * tx_aborted_errors +
1165218114Sbz					 * tx_window_errors +
1166218114Sbz					 * tx_heartbeat_errors */
1167218114Sbz		    0UL);		/* tx_compressed */
116874135Sjlemon	}
1169108172Shsu	IFNET_RUNLOCK();
1170196635Szec	CURVNET_RESTORE();
1171119068Sdes
117278025Sdes	return (0);
117374135Sjlemon}
117474135Sjlemon
1175158311Sambrisko/*
1176167159Sjkim * Filler function for proc/sys/kernel/osrelease
1177167159Sjkim */
1178167159Sjkimstatic int
1179167159Sjkimlinprocfs_doosrelease(PFS_FILL_ARGS)
1180167159Sjkim{
1181167159Sjkim	char osrelease[LINUX_MAX_UTSNAME];
1182167159Sjkim
1183167159Sjkim	linux_get_osrelease(td, osrelease);
1184167159Sjkim	sbuf_printf(sb, "%s\n", osrelease);
1185167159Sjkim
1186167159Sjkim	return (0);
1187167159Sjkim}
1188167159Sjkim
1189167159Sjkim/*
1190167159Sjkim * Filler function for proc/sys/kernel/ostype
1191167159Sjkim */
1192167159Sjkimstatic int
1193167159Sjkimlinprocfs_doostype(PFS_FILL_ARGS)
1194167159Sjkim{
1195167159Sjkim	char osname[LINUX_MAX_UTSNAME];
1196167159Sjkim
1197167159Sjkim	linux_get_osname(td, osname);
1198167159Sjkim	sbuf_printf(sb, "%s\n", osname);
1199167159Sjkim
1200167159Sjkim	return (0);
1201167159Sjkim}
1202167159Sjkim
1203167159Sjkim/*
1204167159Sjkim * Filler function for proc/sys/kernel/version
1205167159Sjkim */
1206167159Sjkimstatic int
1207167159Sjkimlinprocfs_doosbuild(PFS_FILL_ARGS)
1208167159Sjkim{
1209168762Sdes
1210167159Sjkim	linprocfs_osbuild(td, sb);
1211167159Sjkim	sbuf_cat(sb, "\n");
1212167159Sjkim	return (0);
1213167159Sjkim}
1214167159Sjkim
1215167159Sjkim/*
1216164692Sjkim * Filler function for proc/sys/kernel/msgmni
1217164692Sjkim */
1218164692Sjkimstatic int
1219164692Sjkimlinprocfs_domsgmni(PFS_FILL_ARGS)
1220164692Sjkim{
1221164692Sjkim
1222168067Sjkim	sbuf_printf(sb, "%d\n", msginfo.msgmni);
1223164692Sjkim	return (0);
1224164692Sjkim}
1225164692Sjkim
1226164692Sjkim/*
1227163251Skeramida * Filler function for proc/sys/kernel/pid_max
1228163129Snetchild */
1229163129Snetchildstatic int
1230163129Snetchildlinprocfs_dopid_max(PFS_FILL_ARGS)
1231163129Snetchild{
1232163757Snetchild
1233163129Snetchild	sbuf_printf(sb, "%i\n", PID_MAX);
1234163129Snetchild	return (0);
1235163129Snetchild}
1236163129Snetchild
1237163129Snetchild/*
1238164692Sjkim * Filler function for proc/sys/kernel/sem
1239164692Sjkim */
1240164692Sjkimstatic int
1241164692Sjkimlinprocfs_dosem(PFS_FILL_ARGS)
1242164692Sjkim{
1243164692Sjkim
1244168067Sjkim	sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns,
1245168067Sjkim	    seminfo.semopm, seminfo.semmni);
1246164692Sjkim	return (0);
1247164692Sjkim}
1248164692Sjkim
1249164692Sjkim/*
1250158311Sambrisko * Filler function for proc/scsi/device_info
1251158311Sambrisko */
1252158311Sambriskostatic int
1253158311Sambriskolinprocfs_doscsidevinfo(PFS_FILL_ARGS)
1254158311Sambrisko{
1255168762Sdes
1256158311Sambrisko	return (0);
1257158311Sambrisko}
1258158311Sambrisko
1259158311Sambrisko/*
1260158311Sambrisko * Filler function for proc/scsi/scsi
1261158311Sambrisko */
1262158311Sambriskostatic int
1263158311Sambriskolinprocfs_doscsiscsi(PFS_FILL_ARGS)
1264158311Sambrisko{
1265168762Sdes
1266158311Sambrisko	return (0);
1267158311Sambrisko}
1268158311Sambrisko
126985538Sphkextern struct cdevsw *cdevsw[];
127085538Sphk
127178113Sdes/*
127278113Sdes * Filler function for proc/devices
127378113Sdes */
127478025Sdesstatic int
127578025Sdeslinprocfs_dodevices(PFS_FILL_ARGS)
127674135Sjlemon{
1277158311Sambrisko	char *char_devices;
127878025Sdes	sbuf_printf(sb, "Character devices:\n");
127974135Sjlemon
1280158311Sambrisko	char_devices = linux_get_char_devices();
1281158311Sambrisko	sbuf_printf(sb, "%s", char_devices);
1282158311Sambrisko	linux_free_get_char_devices(char_devices);
128374135Sjlemon
128478025Sdes	sbuf_printf(sb, "\nBlock devices:\n");
1285119068Sdes
128678025Sdes	return (0);
128774135Sjlemon}
128874135Sjlemon
128978113Sdes/*
129078113Sdes * Filler function for proc/cmdline
129178113Sdes */
129278025Sdesstatic int
129378025Sdeslinprocfs_docmdline(PFS_FILL_ARGS)
129474135Sjlemon{
1295168762Sdes
129678025Sdes	sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
129778025Sdes	sbuf_printf(sb, " ro root=302\n");
129878025Sdes	return (0);
129978025Sdes}
130074135Sjlemon
1301205541Sjhb/*
1302205541Sjhb * Filler function for proc/filesystems
1303205541Sjhb */
1304205541Sjhbstatic int
1305205541Sjhblinprocfs_dofilesystems(PFS_FILL_ARGS)
1306205541Sjhb{
1307205541Sjhb	struct vfsconf *vfsp;
1308205541Sjhb
1309205592Sjhb	mtx_lock(&Giant);
1310205541Sjhb	TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
1311205541Sjhb		if (vfsp->vfc_flags & VFCF_SYNTHETIC)
1312205541Sjhb			sbuf_printf(sb, "nodev");
1313205541Sjhb		sbuf_printf(sb, "\t%s\n", vfsp->vfc_name);
1314205541Sjhb	}
1315205592Sjhb	mtx_unlock(&Giant);
1316205541Sjhb	return(0);
1317205541Sjhb}
1318205541Sjhb
131983926Sdes#if 0
132078025Sdes/*
132183926Sdes * Filler function for proc/modules
132283926Sdes */
132383926Sdesstatic int
132483926Sdeslinprocfs_domodules(PFS_FILL_ARGS)
132583926Sdes{
132683926Sdes	struct linker_file *lf;
1327119068Sdes
132883926Sdes	TAILQ_FOREACH(lf, &linker_files, link) {
132983926Sdes		sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
133083926Sdes		    (unsigned long)lf->size, lf->refs);
133183926Sdes	}
133283926Sdes	return (0);
133383926Sdes}
133483926Sdes#endif
133583926Sdes
133683926Sdes/*
1337204825Sed * Filler function for proc/pid/fd
1338204825Sed */
1339204825Sedstatic int
1340204825Sedlinprocfs_dofdescfs(PFS_FILL_ARGS)
1341204825Sed{
1342204825Sed
1343204825Sed	if (p == curproc)
1344204825Sed		sbuf_printf(sb, "/dev/fd");
1345204825Sed	else
1346204825Sed		sbuf_printf(sb, "unknown");
1347204825Sed	return (0);
1348204825Sed}
1349204825Sed
1350204825Sed/*
135185129Sdes * Constructor
135278025Sdes */
135385129Sdesstatic int
135485129Sdeslinprocfs_init(PFS_INIT_ARGS)
135585129Sdes{
135685129Sdes	struct pfs_node *root;
135785129Sdes	struct pfs_node *dir;
135874135Sjlemon
135985129Sdes	root = pi->pi_root;
136078025Sdes
1361119923Sdes	/* /proc/... */
1362119911Sdes	pfs_create_file(root, "cmdline", &linprocfs_docmdline,
1363167482Sdes	    NULL, NULL, NULL, PFS_RD);
1364119911Sdes	pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
1365167482Sdes	    NULL, NULL, NULL, PFS_RD);
1366119911Sdes	pfs_create_file(root, "devices", &linprocfs_dodevices,
1367167482Sdes	    NULL, NULL, NULL, PFS_RD);
1368205541Sjhb	pfs_create_file(root, "filesystems", &linprocfs_dofilesystems,
1369205541Sjhb	    NULL, NULL, NULL, PFS_RD);
1370119911Sdes	pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
1371167482Sdes	    NULL, NULL, NULL, PFS_RD);
1372119911Sdes	pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
1373167482Sdes	    NULL, NULL, NULL, PFS_RD);
137483926Sdes#if 0
1375119911Sdes	pfs_create_file(root, "modules", &linprocfs_domodules,
1376167482Sdes	    NULL, NULL, NULL, PFS_RD);
137783926Sdes#endif
1378158311Sambrisko	pfs_create_file(root, "mounts", &linprocfs_domtab,
1379167482Sdes	    NULL, NULL, NULL, PFS_RD);
1380119911Sdes	pfs_create_file(root, "mtab", &linprocfs_domtab,
1381167482Sdes	    NULL, NULL, NULL, PFS_RD);
1382190445Sambrisko	pfs_create_file(root, "partitions", &linprocfs_dopartitions,
1383190445Sambrisko	    NULL, NULL, NULL, PFS_RD);
138487543Sdes	pfs_create_link(root, "self", &procfs_docurproc,
1385167482Sdes	    NULL, NULL, NULL, 0);
1386119911Sdes	pfs_create_file(root, "stat", &linprocfs_dostat,
1387167482Sdes	    NULL, NULL, NULL, PFS_RD);
1388224582Skib	pfs_create_file(root, "swaps", &linprocfs_doswaps,
1389224582Skib	    NULL, NULL, NULL, PFS_RD);
1390119911Sdes	pfs_create_file(root, "uptime", &linprocfs_douptime,
1391167482Sdes	    NULL, NULL, NULL, PFS_RD);
1392119911Sdes	pfs_create_file(root, "version", &linprocfs_doversion,
1393167482Sdes	    NULL, NULL, NULL, PFS_RD);
139478025Sdes
1395119923Sdes	/* /proc/net/... */
1396167482Sdes	dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
139785129Sdes	pfs_create_file(dir, "dev", &linprocfs_donetdev,
1398167482Sdes	    NULL, NULL, NULL, PFS_RD);
139978025Sdes
1400119923Sdes	/* /proc/<pid>/... */
1401167482Sdes	dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
140285129Sdes	pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
1403167482Sdes	    NULL, NULL, NULL, PFS_RD);
1404119911Sdes	pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
1405167482Sdes	    NULL, NULL, NULL, 0);
1406116173Sobrien	pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
1407167482Sdes	    NULL, NULL, NULL, PFS_RD);
140887543Sdes	pfs_create_link(dir, "exe", &procfs_doprocfile,
1409167482Sdes	    NULL, &procfs_notsystem, NULL, 0);
1410116173Sobrien	pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
1411167482Sdes	    NULL, NULL, NULL, PFS_RD);
141285129Sdes	pfs_create_file(dir, "mem", &procfs_doprocmem,
1413167482Sdes	    &procfs_attr, &procfs_candebug, NULL, PFS_RDWR|PFS_RAW);
1414119911Sdes	pfs_create_link(dir, "root", &linprocfs_doprocroot,
1415167482Sdes	    NULL, NULL, NULL, 0);
141685129Sdes	pfs_create_file(dir, "stat", &linprocfs_doprocstat,
1417167482Sdes	    NULL, NULL, NULL, PFS_RD);
1418119911Sdes	pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
1419167482Sdes	    NULL, NULL, NULL, PFS_RD);
142085129Sdes	pfs_create_file(dir, "status", &linprocfs_doprocstatus,
1421167482Sdes	    NULL, NULL, NULL, PFS_RD);
1422204825Sed	pfs_create_link(dir, "fd", &linprocfs_dofdescfs,
1423204825Sed	    NULL, NULL, NULL, 0);
142485129Sdes
1425158311Sambrisko	/* /proc/scsi/... */
1426167482Sdes	dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
1427158311Sambrisko	pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
1428167482Sdes	    NULL, NULL, NULL, PFS_RD);
1429158311Sambrisko	pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
1430167482Sdes	    NULL, NULL, NULL, PFS_RD);
1431163129Snetchild
1432163129Snetchild	/* /proc/sys/... */
1433167482Sdes	dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
1434163129Snetchild	/* /proc/sys/kernel/... */
1435167482Sdes	dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0);
1436167159Sjkim	pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
1437167482Sdes	    NULL, NULL, NULL, PFS_RD);
1438167159Sjkim	pfs_create_file(dir, "ostype", &linprocfs_doostype,
1439167482Sdes	    NULL, NULL, NULL, PFS_RD);
1440167159Sjkim	pfs_create_file(dir, "version", &linprocfs_doosbuild,
1441167482Sdes	    NULL, NULL, NULL, PFS_RD);
1442164692Sjkim	pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
1443167482Sdes	    NULL, NULL, NULL, PFS_RD);
1444163129Snetchild	pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
1445167482Sdes	    NULL, NULL, NULL, PFS_RD);
1446164692Sjkim	pfs_create_file(dir, "sem", &linprocfs_dosem,
1447167482Sdes	    NULL, NULL, NULL, PFS_RD);
1448163129Snetchild
144985129Sdes	return (0);
145085129Sdes}
145185129Sdes
145285129Sdes/*
145385129Sdes * Destructor
145485129Sdes */
145585129Sdesstatic int
145685129Sdeslinprocfs_uninit(PFS_INIT_ARGS)
145785129Sdes{
145885129Sdes
145985129Sdes	/* nothing to do, pseudofs will GC */
146085129Sdes	return (0);
146185129Sdes}
146285129Sdes
146385129SdesPSEUDOFS(linprocfs, 1);
146478025SdesMODULE_DEPEND(linprocfs, linux, 1, 1, 1);
146578025SdesMODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
1466168440SjkimMODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);
1467168440SjkimMODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1);
1468