2 * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav
3 * Copyright (c) 1999 Pierre Beyssac
4 * Copyright (c) 1993 Jan-Simon Pendry
6 * The Regents of the University of California. All rights reserved.
8 * This code is derived from software contributed to Berkeley by
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD$");
45 #include <sys/param.h>
46 #include <sys/queue.h>
47 #include <sys/blist.h>
50 #include <sys/fcntl.h>
51 #include <sys/filedesc.h>
53 #include <sys/kernel.h>
54 #include <sys/limits.h>
55 #include <sys/linker.h>
57 #include <sys/malloc.h>
59 #include <sys/mutex.h>
60 #include <sys/namei.h>
62 #include <sys/ptrace.h>
63 #include <sys/resourcevar.h>
64 #include <sys/resource.h>
68 #include <sys/socket.h>
69 #include <sys/syscallsubr.h>
70 #include <sys/sysctl.h>
71 #include <sys/sysent.h>
72 #include <sys/systm.h>
77 #include <sys/vmmeter.h>
78 #include <sys/vnode.h>
82 #include <net/if_var.h>
83 #include <net/if_types.h>
86 #include <vm/vm_extern.h>
88 #include <vm/vm_map.h>
89 #include <vm/vm_param.h>
90 #include <vm/vm_object.h>
91 #include <vm/swap_pager.h>
93 #include <machine/clock.h>
95 #include <geom/geom.h>
96 #include <geom/geom_int.h>
98 #if defined(__i386__) || defined(__amd64__)
99 #include <machine/cputypes.h>
100 #include <machine/md_var.h>
101 #endif /* __i386__ || __amd64__ */
103 #include <compat/linux/linux.h>
104 #include <compat/linux/linux_mib.h>
105 #include <compat/linux/linux_misc.h>
106 #include <compat/linux/linux_util.h>
107 #include <fs/pseudofs/pseudofs.h>
108 #include <fs/procfs/procfs.h>
111 * Various conversion macros
113 #define T2J(x) ((long)(((x) * 100ULL) / (stathz ? stathz : hz))) /* ticks to jiffies */
114 #define T2CS(x) ((unsigned long)(((x) * 100ULL) / (stathz ? stathz : hz))) /* ticks to centiseconds */
115 #define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */
116 #define B2K(x) ((x) >> 10) /* bytes to kbytes */
117 #define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */
118 #define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */
119 #define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */
120 #define TV2J(x) ((x)->tv_sec * 100UL + (x)->tv_usec / 10000)
123 * @brief Mapping of ki_stat in struct kinfo_proc to the linux state
125 * The linux procfs state field displays one of the characters RSDZTW to
126 * denote running, sleeping in an interruptible wait, waiting in an
127 * uninterruptible disk sleep, a zombie process, process is being traced
128 * or stopped, or process is paging respectively.
130 * Our struct kinfo_proc contains the variable ki_stat which contains a
131 * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK.
133 * This character array is used with ki_stati-1 as an index and tries to
134 * map our states to suitable linux states.
136 static char linux_state[] = "RRSTZDD";
139 * Filler function for proc/meminfo
142 linprocfs_domeminfo(PFS_FILL_ARGS)
144 unsigned long memtotal; /* total memory in bytes */
145 unsigned long memused; /* used memory in bytes */
146 unsigned long memfree; /* free memory in bytes */
147 unsigned long buffers, cached; /* buffer / cache memory ??? */
148 unsigned long long swaptotal; /* total swap space in bytes */
149 unsigned long long swapused; /* used swap space in bytes */
150 unsigned long long swapfree; /* free swap space in bytes */
153 memtotal = physmem * PAGE_SIZE;
155 * The correct thing here would be:
157 memfree = vm_cnt.v_free_count * PAGE_SIZE;
158 memused = memtotal - memfree;
160 * but it might mislead linux binaries into thinking there
161 * is very little memory left, so we cheat and tell them that
162 * all memory that isn't wired down is free.
164 memused = vm_cnt.v_wire_count * PAGE_SIZE;
165 memfree = memtotal - memused;
166 swap_pager_status(&i, &j);
167 swaptotal = (unsigned long long)i * PAGE_SIZE;
168 swapused = (unsigned long long)j * PAGE_SIZE;
169 swapfree = swaptotal - swapused;
171 * We'd love to be able to write:
175 * but bufspace is internal to vfs_bio.c and we don't feel
176 * like unstaticizing it just for linprocfs's sake.
179 cached = vm_cnt.v_inactive_count * PAGE_SIZE;
182 "MemTotal: %9lu kB\n"
186 "SwapTotal:%9llu kB\n"
187 "SwapFree: %9llu kB\n",
188 B2K(memtotal), B2K(memfree), B2K(buffers),
189 B2K(cached), B2K(swaptotal), B2K(swapfree));
194 #if defined(__i386__) || defined(__amd64__)
196 * Filler function for proc/cpuinfo (i386 & amd64 version)
199 linprocfs_docpuinfo(PFS_FILL_ARGS)
210 * We default the flags to include all non-conflicting flags,
211 * and the Intel versions of conflicting flags.
213 static char *flags[] = {
214 "fpu", "vme", "de", "pse", "tsc",
215 "msr", "pae", "mce", "cx8", "apic",
216 "sep", "sep", "mtrr", "pge", "mca",
217 "cmov", "pat", "pse36", "pn", "b19",
218 "b20", "b21", "mmxext", "mmx", "fxsr",
219 "xmm", "sse2", "b27", "b28", "b29",
223 static char *power_flags[] = {
226 "100mhzsteps", "hwpstate", "",
227 "cpb", "eff_freq_ro", "proc_feedback",
231 hw_model[0] = CTL_HW;
232 hw_model[1] = HW_MODEL;
234 size = sizeof(model);
235 if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0)
236 strcpy(model, "unknown");
238 switch (cpu_vendor_id) {
240 if (cpu_class < CPUCLASS_686)
243 case CPU_VENDOR_CYRIX:
248 if (cpu_exthigh >= 0x80000006)
249 do_cpuid(0x80000006, cache_size);
251 memset(cache_size, 0, sizeof(cache_size));
252 for (i = 0; i < mp_ncpus; ++i) {
255 freq = atomic_load_acq_64(&tsc_freq);
257 fqmhz = (freq + 4999) / 1000000;
258 fqkhz = ((freq + 4999) / 10000) % 100;
262 "vendor_id\t: %.20s\n"
267 "cpu MHz\t\t: %d.%02d\n"
268 "cache size\t: %d KB\n"
269 "physical id\t: %d\n"
274 "initial apicid\t: %d\n"
276 "fpu_exception\t: %s\n"
277 "cpuid level\t: %d\n"
279 i, cpu_vendor, CPUID_TO_FAMILY(cpu_id),
280 CPUID_TO_MODEL(cpu_id), model, cpu_id & CPUID_STEPPING,
282 (cache_size[2] >> 16), 0, mp_ncpus, i, mp_ncpus,
283 i, i, /*cpu_id & CPUID_LOCAL_APIC_ID ??*/
284 (cpu_feature & CPUID_FPU) ? "yes" : "no", "yes",
285 CPUID_TO_FAMILY(cpu_id), "yes");
286 sbuf_cat(sb, "flags\t\t:");
287 for (j = 0; j < nitems(flags); j++)
288 if (cpu_feature & (1 << j))
289 sbuf_printf(sb, " %s", flags[j]);
293 "bogomips\t: %d.%02d\n"
294 "clflush size\t: %d\n"
295 "cache_alignment\t: %d\n"
296 "address sizes\t: %d bits physical, %d bits virtual\n",
297 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
298 (has_f00f_bug) ? "Intel F00F" : "",
303 cpu_clflush_line_size, cpu_clflush_line_size,
305 (cpu_maxphyaddr > 32) ? 48 : 0);
306 sbuf_cat(sb, "power management: ");
307 for (j = 0; j < nitems(power_flags); j++)
308 if (amd_pminfo & (1 << j))
309 sbuf_printf(sb, " %s", power_flags[j]);
310 sbuf_cat(sb, "\n\n");
312 /* XXX per-cpu vendor / class / model / id? */
318 #endif /* __i386__ || __amd64__ */
321 * Filler function for proc/mtab
323 * This file doesn't exist in Linux' procfs, but is included here so
324 * users can symlink /compat/linux/etc/mtab to /proc/mtab
327 linprocfs_domtab(PFS_FILL_ARGS)
331 char *dlep, *flep, *mntto, *mntfrom, *fstype;
334 struct statfs *buf, *sp;
337 /* resolve symlinks etc. in the emulation tree prefix */
338 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td);
341 lep = linux_emul_path;
343 if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
347 lep_len = strlen(lep);
350 error = kern_getfsstat(td, &buf, SIZE_T_MAX, &count,
351 UIO_SYSSPACE, MNT_WAIT);
358 for (sp = buf; count > 0; sp++, count--) {
359 /* determine device name */
360 mntfrom = sp->f_mntfromname;
362 /* determine mount point */
363 mntto = sp->f_mntonname;
364 if (strncmp(mntto, lep, lep_len) == 0 && mntto[lep_len] == '/')
367 /* determine fs type */
368 fstype = sp->f_fstypename;
369 if (strcmp(fstype, pn->pn_info->pi_name) == 0)
370 mntfrom = fstype = "proc";
371 else if (strcmp(fstype, "procfs") == 0)
374 if (strcmp(fstype, "linsysfs") == 0) {
375 sbuf_printf(sb, "/sys %s sysfs %s", mntto,
376 sp->f_flags & MNT_RDONLY ? "ro" : "rw");
378 /* For Linux msdosfs is called vfat */
379 if (strcmp(fstype, "msdosfs") == 0)
381 sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
382 sp->f_flags & MNT_RDONLY ? "ro" : "rw");
384 #define ADD_OPTION(opt, name) \
385 if (sp->f_flags & (opt)) sbuf_printf(sb, "," name);
386 ADD_OPTION(MNT_SYNCHRONOUS, "sync");
387 ADD_OPTION(MNT_NOEXEC, "noexec");
388 ADD_OPTION(MNT_NOSUID, "nosuid");
389 ADD_OPTION(MNT_UNION, "union");
390 ADD_OPTION(MNT_ASYNC, "async");
391 ADD_OPTION(MNT_SUIDDIR, "suiddir");
392 ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow");
393 ADD_OPTION(MNT_NOATIME, "noatime");
395 /* a real Linux mtab will also show NFS options */
396 sbuf_printf(sb, " 0 0\n");
405 * Filler function for proc/partitions
408 linprocfs_dopartitions(PFS_FILL_ARGS)
412 struct g_provider *pp;
416 sbuf_printf(sb, "major minor #blocks name rio rmerge rsect "
417 "ruse wio wmerge wsect wuse running use aveq\n");
419 LIST_FOREACH(cp, &g_classes, class) {
420 if (strcmp(cp->name, "DISK") == 0 ||
421 strcmp(cp->name, "PART") == 0)
422 LIST_FOREACH(gp, &cp->geom, geom) {
423 LIST_FOREACH(pp, &gp->provider, provider) {
424 if (linux_driver_get_major_minor(
425 pp->name, &major, &minor) != 0) {
429 sbuf_printf(sb, "%d %d %lld %s "
431 "%d %d %d %d %d %d\n",
433 (long long)pp->mediasize, pp->name,
446 * Filler function for proc/stat
449 linprocfs_dostat(PFS_FILL_ARGS)
452 long cp_time[CPUSTATES];
454 struct timeval boottime;
457 read_cpu_time(cp_time);
458 getboottime(&boottime);
459 sbuf_printf(sb, "cpu %ld %ld %ld %ld\n",
460 T2J(cp_time[CP_USER]),
461 T2J(cp_time[CP_NICE]),
462 T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
463 T2J(cp_time[CP_IDLE]));
466 cp = pcpu->pc_cp_time;
467 sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i,
470 T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/),
480 (uintmax_t)VM_CNT_FETCH(v_vnodepgsin),
481 (uintmax_t)VM_CNT_FETCH(v_vnodepgsout),
482 (uintmax_t)VM_CNT_FETCH(v_swappgsin),
483 (uintmax_t)VM_CNT_FETCH(v_swappgsout),
484 (uintmax_t)VM_CNT_FETCH(v_intr),
485 (uintmax_t)VM_CNT_FETCH(v_swtch),
486 (long long)boottime.tv_sec);
491 linprocfs_doswaps(PFS_FILL_ARGS)
494 uintmax_t total, used;
496 char devname[SPECNAMELEN + 1];
498 sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
500 if (swap_dev_info(n, &xsw, devname, sizeof(devname)) != 0)
502 total = (uintmax_t)xsw.xsw_nblks * PAGE_SIZE / 1024;
503 used = (uintmax_t)xsw.xsw_used * PAGE_SIZE / 1024;
506 * The space and not tab after the device name is on
507 * purpose. Linux does so.
509 sbuf_printf(sb, "/dev/%-34s unknown\t\t%jd\t%jd\t-1\n",
510 devname, total, used);
516 * Filler function for proc/uptime
519 linprocfs_douptime(PFS_FILL_ARGS)
521 long cp_time[CPUSTATES];
525 read_cpu_time(cp_time);
526 sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n",
527 (long long)tv.tv_sec, tv.tv_usec / 10000,
528 T2S(cp_time[CP_IDLE] / mp_ncpus),
529 T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100);
537 linprocfs_osbuild(struct thread *td, struct sbuf *sb)
543 strncpy(osbuild, version, 256);
545 cp1 = strstr(osbuild, "\n");
546 cp2 = strstr(osbuild, ":");
549 cp1 = strstr(osbuild, "#");
553 sbuf_printf(sb, "%s%s", cp1, cp2 + 1);
556 sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977");
563 linprocfs_osbuilder(struct thread *td, struct sbuf *sb)
569 cp = strstr(version, "\n ");
571 strncpy(builder, cp + 5, 256);
573 cp = strstr(builder, ":");
578 sbuf_cat(sb, builder);
581 sbuf_cat(sb, "des@freebsd.org");
585 * Filler function for proc/version
588 linprocfs_doversion(PFS_FILL_ARGS)
590 char osname[LINUX_MAX_UTSNAME];
591 char osrelease[LINUX_MAX_UTSNAME];
593 linux_get_osname(td, osname);
594 linux_get_osrelease(td, osrelease);
595 sbuf_printf(sb, "%s version %s (", osname, osrelease);
596 linprocfs_osbuilder(td, sb);
597 sbuf_cat(sb, ") (gcc version " __VERSION__ ") ");
598 linprocfs_osbuild(td, sb);
605 * Filler function for proc/loadavg
608 linprocfs_doloadavg(PFS_FILL_ARGS)
612 "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
613 (int)(averunnable.ldavg[0] / averunnable.fscale),
614 (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
615 (int)(averunnable.ldavg[1] / averunnable.fscale),
616 (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
617 (int)(averunnable.ldavg[2] / averunnable.fscale),
618 (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
619 1, /* number of running tasks */
620 nprocs, /* number of tasks */
621 lastpid /* the last pid */
627 * Filler function for proc/pid/stat
630 linprocfs_doprocstat(PFS_FILL_ARGS)
632 struct kinfo_proc kp;
633 struct timeval boottime;
635 static int ratelimit = 0;
636 vm_offset_t startcode, startdata;
638 getboottime(&boottime);
639 sx_slock(&proctree_lock);
641 fill_kinfo_proc(p, &kp);
642 sx_sunlock(&proctree_lock);
644 startcode = (vm_offset_t)p->p_vmspace->vm_taddr;
645 startdata = (vm_offset_t)p->p_vmspace->vm_daddr;
650 sbuf_printf(sb, "%d", p->p_pid);
651 #define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
652 PS_ADD("comm", "(%s)", p->p_comm);
653 if (kp.ki_stat > sizeof(linux_state)) {
656 if (ratelimit == 0) {
657 printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n",
658 kp.ki_stat, sizeof(linux_state));
662 state = linux_state[kp.ki_stat - 1];
663 PS_ADD("state", "%c", state);
664 PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0);
665 PS_ADD("pgrp", "%d", p->p_pgid);
666 PS_ADD("session", "%d", p->p_session->s_sid);
668 PS_ADD("tty", "%ju", (uintmax_t)kp.ki_tdev);
669 PS_ADD("tpgid", "%d", kp.ki_tpgid);
670 PS_ADD("flags", "%u", 0); /* XXX */
671 PS_ADD("minflt", "%lu", kp.ki_rusage.ru_minflt);
672 PS_ADD("cminflt", "%lu", kp.ki_rusage_ch.ru_minflt);
673 PS_ADD("majflt", "%lu", kp.ki_rusage.ru_majflt);
674 PS_ADD("cmajflt", "%lu", kp.ki_rusage_ch.ru_majflt);
675 PS_ADD("utime", "%ld", TV2J(&kp.ki_rusage.ru_utime));
676 PS_ADD("stime", "%ld", TV2J(&kp.ki_rusage.ru_stime));
677 PS_ADD("cutime", "%ld", TV2J(&kp.ki_rusage_ch.ru_utime));
678 PS_ADD("cstime", "%ld", TV2J(&kp.ki_rusage_ch.ru_stime));
679 PS_ADD("priority", "%d", kp.ki_pri.pri_user);
680 PS_ADD("nice", "%d", kp.ki_nice); /* 19 (nicest) to -19 */
681 PS_ADD("0", "%d", 0); /* removed field */
682 PS_ADD("itrealvalue", "%d", 0); /* XXX */
683 PS_ADD("starttime", "%lu", TV2J(&kp.ki_start) - TV2J(&boottime));
684 PS_ADD("vsize", "%ju", P2K((uintmax_t)kp.ki_size));
685 PS_ADD("rss", "%ju", (uintmax_t)kp.ki_rssize);
686 PS_ADD("rlim", "%lu", kp.ki_rusage.ru_maxrss);
687 PS_ADD("startcode", "%ju", (uintmax_t)startcode);
688 PS_ADD("endcode", "%ju", (uintmax_t)startdata);
689 PS_ADD("startstack", "%u", 0); /* XXX */
690 PS_ADD("kstkesp", "%u", 0); /* XXX */
691 PS_ADD("kstkeip", "%u", 0); /* XXX */
692 PS_ADD("signal", "%u", 0); /* XXX */
693 PS_ADD("blocked", "%u", 0); /* XXX */
694 PS_ADD("sigignore", "%u", 0); /* XXX */
695 PS_ADD("sigcatch", "%u", 0); /* XXX */
696 PS_ADD("wchan", "%u", 0); /* XXX */
697 PS_ADD("nswap", "%lu", kp.ki_rusage.ru_nswap);
698 PS_ADD("cnswap", "%lu", kp.ki_rusage_ch.ru_nswap);
699 PS_ADD("exitsignal", "%d", 0); /* XXX */
700 PS_ADD("processor", "%u", kp.ki_lastcpu);
701 PS_ADD("rt_priority", "%u", 0); /* XXX */ /* >= 2.5.19 */
702 PS_ADD("policy", "%u", kp.ki_pri.pri_class); /* >= 2.5.19 */
710 * Filler function for proc/pid/statm
713 linprocfs_doprocstatm(PFS_FILL_ARGS)
715 struct kinfo_proc kp;
718 sx_slock(&proctree_lock);
720 fill_kinfo_proc(p, &kp);
722 sx_sunlock(&proctree_lock);
725 * See comments in linprocfs_doprocstatus() regarding the
726 * computation of lsize.
728 /* size resident share trs drs lrs dt */
729 sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size));
730 sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize);
731 sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */
732 sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize);
733 sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize));
734 lsize = B2P(kp.ki_size) - kp.ki_dsize -
735 kp.ki_ssize - kp.ki_tsize - 1;
736 sbuf_printf(sb, "%ju ", (uintmax_t)lsize);
737 sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */
743 * Filler function for proc/pid/status
746 linprocfs_doprocstatus(PFS_FILL_ARGS)
748 struct kinfo_proc kp;
753 l_sigset_t siglist, sigignore, sigcatch;
756 sx_slock(&proctree_lock);
758 td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */
760 if (P_SHOULDSTOP(p)) {
761 state = "T (stopped)";
768 if (p->p_flag & P_WEXIT) {
769 state = "X (exiting)";
772 switch(td2->td_state) {
774 state = "S (sleeping)";
778 state = "R (running)";
781 state = "? (unknown)";
786 state = "Z (zombie)";
789 state = "? (unknown)";
794 fill_kinfo_proc(p, &kp);
795 sx_sunlock(&proctree_lock);
797 sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */
798 sbuf_printf(sb, "State:\t%s\n", state);
803 sbuf_printf(sb, "Pid:\t%d\n", p->p_pid);
804 sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ?
805 p->p_pptr->p_pid : 0);
806 sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid,
808 p->p_ucred->cr_svuid,
809 /* FreeBSD doesn't have fsuid */
811 sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid,
813 p->p_ucred->cr_svgid,
814 /* FreeBSD doesn't have fsgid */
816 sbuf_cat(sb, "Groups:\t");
817 for (i = 0; i < p->p_ucred->cr_ngroups; i++)
818 sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]);
825 * While our approximation of VmLib may not be accurate (I
826 * don't know of a simple way to verify it, and I'm not sure
827 * it has much meaning anyway), I believe it's good enough.
829 * The same code that could (I think) accurately compute VmLib
830 * could also compute VmLck, but I don't really care enough to
831 * implement it. Submissions are welcome.
833 sbuf_printf(sb, "VmSize:\t%8ju kB\n", B2K((uintmax_t)kp.ki_size));
834 sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */
835 sbuf_printf(sb, "VmRSS:\t%8ju kB\n", P2K((uintmax_t)kp.ki_rssize));
836 sbuf_printf(sb, "VmData:\t%8ju kB\n", P2K((uintmax_t)kp.ki_dsize));
837 sbuf_printf(sb, "VmStk:\t%8ju kB\n", P2K((uintmax_t)kp.ki_ssize));
838 sbuf_printf(sb, "VmExe:\t%8ju kB\n", P2K((uintmax_t)kp.ki_tsize));
839 lsize = B2P(kp.ki_size) - kp.ki_dsize -
840 kp.ki_ssize - kp.ki_tsize - 1;
841 sbuf_printf(sb, "VmLib:\t%8ju kB\n", P2K((uintmax_t)lsize));
847 bsd_to_linux_sigset(&p->p_siglist, &siglist);
849 mtx_lock(&ps->ps_mtx);
850 bsd_to_linux_sigset(&ps->ps_sigignore, &sigignore);
851 bsd_to_linux_sigset(&ps->ps_sigcatch, &sigcatch);
852 mtx_unlock(&ps->ps_mtx);
855 sbuf_printf(sb, "SigPnd:\t%016jx\n", siglist.__mask);
857 * XXX. SigBlk - target thread's signal mask, td_sigmask.
858 * To implement SigBlk pseudofs should support proc/tid dir entries.
860 sbuf_printf(sb, "SigBlk:\t%016x\n", 0);
861 sbuf_printf(sb, "SigIgn:\t%016jx\n", sigignore.__mask);
862 sbuf_printf(sb, "SigCgt:\t%016jx\n", sigcatch.__mask);
865 * Linux also prints the capability masks, but we don't have
866 * capabilities yet, and when we do get them they're likely to
867 * be meaningless to Linux programs, so we lie. XXX
869 sbuf_printf(sb, "CapInh:\t%016x\n", 0);
870 sbuf_printf(sb, "CapPrm:\t%016x\n", 0);
871 sbuf_printf(sb, "CapEff:\t%016x\n", 0);
878 * Filler function for proc/pid/cwd
881 linprocfs_doproccwd(PFS_FILL_ARGS)
883 struct filedesc *fdp;
885 char *fullpath = "unknown";
886 char *freepath = NULL;
893 FILEDESC_SUNLOCK(fdp);
894 vn_fullpath(td, vp, &fullpath, &freepath);
897 sbuf_printf(sb, "%s", fullpath);
899 free(freepath, M_TEMP);
904 * Filler function for proc/pid/root
907 linprocfs_doprocroot(PFS_FILL_ARGS)
909 struct filedesc *fdp;
911 char *fullpath = "unknown";
912 char *freepath = NULL;
916 vp = jailed(p->p_ucred) ? fdp->fd_jdir : fdp->fd_rdir;
919 FILEDESC_SUNLOCK(fdp);
920 vn_fullpath(td, vp, &fullpath, &freepath);
923 sbuf_printf(sb, "%s", fullpath);
925 free(freepath, M_TEMP);
930 * Filler function for proc/pid/cmdline
933 linprocfs_doproccmdline(PFS_FILL_ARGS)
938 if ((ret = p_cansee(td, p)) != 0) {
944 * Mimic linux behavior and pass only processes with usermode
945 * address space as valid. Return zero silently otherwize.
947 if (p->p_vmspace == &vmspace0) {
951 if (p->p_args != NULL) {
952 sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
957 if ((p->p_flag & P_SYSTEM) != 0) {
964 ret = proc_getargv(td, p, sb);
969 * Filler function for proc/pid/environ
972 linprocfs_doprocenviron(PFS_FILL_ARGS)
976 * Mimic linux behavior and pass only processes with usermode
977 * address space as valid. Return zero silently otherwize.
979 if (p->p_vmspace == &vmspace0)
982 return (proc_getenvv(td, p, sb));
985 static char l32_map_str[] = "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n";
986 static char l64_map_str[] = "%016lx-%016lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n";
987 static char vdso_str[] = " [vdso]";
988 static char stack_str[] = " [stack]";
991 * Filler function for proc/pid/maps
994 linprocfs_doprocmaps(PFS_FILL_ARGS)
998 vm_map_entry_t entry, tmp_entry;
999 vm_object_t obj, tobj, lobj;
1000 vm_offset_t e_start, e_end;
1001 vm_ooffset_t off = 0;
1003 unsigned int last_timestamp;
1004 char *name = "", *freename = NULL;
1005 const char *l_map_str;
1007 int ref_count, shadow_count, flags;
1013 error = p_candebug(td, p);
1018 if (uio->uio_rw != UIO_READ)
1019 return (EOPNOTSUPP);
1022 vm = vmspace_acquire_ref(p);
1026 if (SV_CURPROC_FLAG(SV_LP64))
1027 l_map_str = l64_map_str;
1029 l_map_str = l32_map_str;
1031 vm_map_lock_read(map);
1032 for (entry = map->header.next; entry != &map->header;
1033 entry = entry->next) {
1036 if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
1038 e_prot = entry->protection;
1039 e_start = entry->start;
1041 obj = entry->object.vm_object;
1042 for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) {
1043 VM_OBJECT_RLOCK(tobj);
1045 VM_OBJECT_RUNLOCK(lobj);
1048 last_timestamp = map->timestamp;
1049 vm_map_unlock_read(map);
1052 off = IDX_TO_OFF(lobj->size);
1053 vp = vm_object_vnode(lobj);
1057 VM_OBJECT_RUNLOCK(lobj);
1059 ref_count = obj->ref_count;
1060 shadow_count = obj->shadow_count;
1061 VM_OBJECT_RUNLOCK(obj);
1063 vn_fullpath(td, vp, &name, &freename);
1064 vn_lock(vp, LK_SHARED | LK_RETRY);
1065 VOP_GETATTR(vp, &vat, td->td_ucred);
1066 ino = vat.va_fileid;
1068 } else if (SV_PROC_ABI(p) == SV_ABI_LINUX) {
1069 if (e_start == p->p_sysent->sv_shared_page_base)
1071 if (e_end == p->p_sysent->sv_usrstack)
1082 * start, end, access, offset, major, minor, inode, name.
1084 error = sbuf_printf(sb, l_map_str,
1085 (u_long)e_start, (u_long)e_end,
1086 (e_prot & VM_PROT_READ)?"r":"-",
1087 (e_prot & VM_PROT_WRITE)?"w":"-",
1088 (e_prot & VM_PROT_EXECUTE)?"x":"-",
1098 free(freename, M_TEMP);
1099 vm_map_lock_read(map);
1104 if (last_timestamp != map->timestamp) {
1106 * Look again for the entry because the map was
1107 * modified while it was unlocked. Specifically,
1108 * the entry may have been clipped, merged, or deleted.
1110 vm_map_lookup_entry(map, e_end - 1, &tmp_entry);
1114 vm_map_unlock_read(map);
1121 * Criteria for interface name translation
1123 #define IFP_IS_ETH(ifp) (ifp->if_type == IFT_ETHER)
1126 linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen)
1128 struct ifnet *ifscan;
1131 IFNET_RLOCK_ASSERT();
1133 /* Short-circuit non ethernet interfaces */
1134 if (!IFP_IS_ETH(ifp))
1135 return (strlcpy(buffer, ifp->if_xname, buflen));
1137 /* Determine the (relative) unit number for ethernet interfaces */
1139 TAILQ_FOREACH(ifscan, &V_ifnet, if_link) {
1141 return (snprintf(buffer, buflen, "eth%d", ethno));
1142 if (IFP_IS_ETH(ifscan))
1150 * Filler function for proc/net/dev
1153 linprocfs_donetdev(PFS_FILL_ARGS)
1155 char ifname[16]; /* XXX LINUX_IFNAMSIZ */
1158 sbuf_printf(sb, "%6s|%58s|%s\n"
1160 "Inter-", " Receive", " Transmit",
1162 "bytes packets errs drop fifo frame compressed multicast",
1163 "bytes packets errs drop fifo colls carrier compressed");
1165 CURVNET_SET(TD_TO_VNET(curthread));
1167 TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
1168 linux_ifname(ifp, ifname, sizeof ifname);
1169 sbuf_printf(sb, "%6.6s: ", ifname);
1170 sbuf_printf(sb, "%7ju %7ju %4ju %4ju %4lu %5lu %10lu %9ju ",
1171 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IBYTES),
1172 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IPACKETS),
1173 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IERRORS),
1174 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IQDROPS),
1175 /* rx_missed_errors */
1176 0UL, /* rx_fifo_errors */
1177 0UL, /* rx_length_errors +
1180 * rx_frame_errors */
1181 0UL, /* rx_compressed */
1182 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IMCASTS));
1183 /* XXX-BZ rx only? */
1184 sbuf_printf(sb, "%8ju %7ju %4ju %4ju %4lu %5ju %7lu %10lu\n",
1185 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OBYTES),
1186 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OPACKETS),
1187 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OERRORS),
1188 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OQDROPS),
1189 0UL, /* tx_fifo_errors */
1190 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_COLLISIONS),
1191 0UL, /* tx_carrier_errors +
1192 * tx_aborted_errors +
1193 * tx_window_errors +
1194 * tx_heartbeat_errors*/
1195 0UL); /* tx_compressed */
1204 * Filler function for proc/sys/kernel/osrelease
1207 linprocfs_doosrelease(PFS_FILL_ARGS)
1209 char osrelease[LINUX_MAX_UTSNAME];
1211 linux_get_osrelease(td, osrelease);
1212 sbuf_printf(sb, "%s\n", osrelease);
1218 * Filler function for proc/sys/kernel/ostype
1221 linprocfs_doostype(PFS_FILL_ARGS)
1223 char osname[LINUX_MAX_UTSNAME];
1225 linux_get_osname(td, osname);
1226 sbuf_printf(sb, "%s\n", osname);
1232 * Filler function for proc/sys/kernel/version
1235 linprocfs_doosbuild(PFS_FILL_ARGS)
1238 linprocfs_osbuild(td, sb);
1244 * Filler function for proc/sys/kernel/msgmni
1247 linprocfs_domsgmni(PFS_FILL_ARGS)
1250 sbuf_printf(sb, "%d\n", msginfo.msgmni);
1255 * Filler function for proc/sys/kernel/pid_max
1258 linprocfs_dopid_max(PFS_FILL_ARGS)
1261 sbuf_printf(sb, "%i\n", PID_MAX);
1266 * Filler function for proc/sys/kernel/sem
1269 linprocfs_dosem(PFS_FILL_ARGS)
1272 sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns,
1273 seminfo.semopm, seminfo.semmni);
1278 * Filler function for proc/scsi/device_info
1281 linprocfs_doscsidevinfo(PFS_FILL_ARGS)
1288 * Filler function for proc/scsi/scsi
1291 linprocfs_doscsiscsi(PFS_FILL_ARGS)
1298 * Filler function for proc/devices
1301 linprocfs_dodevices(PFS_FILL_ARGS)
1304 sbuf_printf(sb, "Character devices:\n");
1306 char_devices = linux_get_char_devices();
1307 sbuf_printf(sb, "%s", char_devices);
1308 linux_free_get_char_devices(char_devices);
1310 sbuf_printf(sb, "\nBlock devices:\n");
1316 * Filler function for proc/cmdline
1319 linprocfs_docmdline(PFS_FILL_ARGS)
1322 sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
1323 sbuf_printf(sb, " ro root=302\n");
1328 * Filler function for proc/filesystems
1331 linprocfs_dofilesystems(PFS_FILL_ARGS)
1333 struct vfsconf *vfsp;
1336 TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
1337 if (vfsp->vfc_flags & VFCF_SYNTHETIC)
1338 sbuf_printf(sb, "nodev");
1339 sbuf_printf(sb, "\t%s\n", vfsp->vfc_name);
1347 * Filler function for proc/modules
1350 linprocfs_domodules(PFS_FILL_ARGS)
1352 struct linker_file *lf;
1354 TAILQ_FOREACH(lf, &linker_files, link) {
1355 sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
1356 (unsigned long)lf->size, lf->refs);
1363 * Filler function for proc/pid/fd
1366 linprocfs_dofdescfs(PFS_FILL_ARGS)
1370 sbuf_printf(sb, "/dev/fd");
1372 sbuf_printf(sb, "unknown");
1377 * Filler function for proc/pid/limits
1379 static const struct linux_rlimit_ident {
1382 unsigned int rlim_id;
1383 } linux_rlimits_ident[] = {
1384 { "Max cpu time", "seconds", RLIMIT_CPU },
1385 { "Max file size", "bytes", RLIMIT_FSIZE },
1386 { "Max data size", "bytes", RLIMIT_DATA },
1387 { "Max stack size", "bytes", RLIMIT_STACK },
1388 { "Max core file size", "bytes", RLIMIT_CORE },
1389 { "Max resident set", "bytes", RLIMIT_RSS },
1390 { "Max processes", "processes", RLIMIT_NPROC },
1391 { "Max open files", "files", RLIMIT_NOFILE },
1392 { "Max locked memory", "bytes", RLIMIT_MEMLOCK },
1393 { "Max address space", "bytes", RLIMIT_AS },
1394 { "Max file locks", "locks", LINUX_RLIMIT_LOCKS },
1395 { "Max pending signals", "signals", LINUX_RLIMIT_SIGPENDING },
1396 { "Max msgqueue size", "bytes", LINUX_RLIMIT_MSGQUEUE },
1397 { "Max nice priority", "", LINUX_RLIMIT_NICE },
1398 { "Max realtime priority", "", LINUX_RLIMIT_RTPRIO },
1399 { "Max realtime timeout", "us", LINUX_RLIMIT_RTTIME },
1404 linprocfs_doproclimits(PFS_FILL_ARGS)
1406 const struct linux_rlimit_ident *li;
1407 struct plimit *limp;
1415 limp = lim_hold(p->p_limit);
1418 sbuf_printf(sb, "%-26s%-21s%-21s%-21s\n", "Limit", "Soft Limit",
1419 "Hard Limit", "Units");
1420 for (li = linux_rlimits_ident; li->desc != NULL; ++li) {
1421 switch (li->rlim_id)
1423 case LINUX_RLIMIT_LOCKS:
1425 case LINUX_RLIMIT_RTTIME:
1426 rl.rlim_cur = RLIM_INFINITY;
1428 case LINUX_RLIMIT_SIGPENDING:
1429 error = kernel_sysctlbyname(td,
1430 "kern.sigqueue.max_pending_per_proc",
1431 &res, &size, 0, 0, 0, 0);
1437 case LINUX_RLIMIT_MSGQUEUE:
1438 error = kernel_sysctlbyname(td,
1439 "kern.ipc.msgmnb", &res, &size, 0, 0, 0, 0);
1445 case LINUX_RLIMIT_NICE:
1447 case LINUX_RLIMIT_RTPRIO:
1452 rl = limp->pl_rlimit[li->rlim_id];
1455 if (rl.rlim_cur == RLIM_INFINITY)
1456 sbuf_printf(sb, "%-26s%-21s%-21s%-10s\n",
1457 li->desc, "unlimited", "unlimited", li->unit);
1459 sbuf_printf(sb, "%-26s%-21llu%-21llu%-10s\n",
1460 li->desc, (unsigned long long)rl.rlim_cur,
1461 (unsigned long long)rl.rlim_max, li->unit);
1469 * Filler function for proc/sys/kernel/random/uuid
1472 linprocfs_douuid(PFS_FILL_ARGS)
1476 kern_uuidgen(&uuid, 1);
1477 sbuf_printf_uuid(sb, &uuid);
1478 sbuf_printf(sb, "\n");
1483 * Filler function for proc/pid/auxv
1486 linprocfs_doauxv(PFS_FILL_ARGS)
1489 off_t buflen, resid;
1493 * Mimic linux behavior and pass only processes with usermode
1494 * address space as valid. Return zero silently otherwise.
1496 if (p->p_vmspace == &vmspace0)
1499 if (uio->uio_resid == 0)
1501 if (uio->uio_offset < 0 || uio->uio_resid < 0)
1504 asb = sbuf_new_auto();
1507 error = proc_getauxv(td, p, asb);
1509 error = sbuf_finish(asb);
1511 resid = sbuf_len(asb) - uio->uio_offset;
1512 if (resid > uio->uio_resid)
1513 buflen = uio->uio_resid;
1516 if (buflen > IOSIZE_MAX)
1518 if (buflen > MAXPHYS)
1524 error = uiomove(sbuf_data(asb) + uio->uio_offset, buflen, uio);
1533 linprocfs_init(PFS_INIT_ARGS)
1535 struct pfs_node *root;
1536 struct pfs_node *dir;
1541 pfs_create_file(root, "cmdline", &linprocfs_docmdline,
1542 NULL, NULL, NULL, PFS_RD);
1543 pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
1544 NULL, NULL, NULL, PFS_RD);
1545 pfs_create_file(root, "devices", &linprocfs_dodevices,
1546 NULL, NULL, NULL, PFS_RD);
1547 pfs_create_file(root, "filesystems", &linprocfs_dofilesystems,
1548 NULL, NULL, NULL, PFS_RD);
1549 pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
1550 NULL, NULL, NULL, PFS_RD);
1551 pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
1552 NULL, NULL, NULL, PFS_RD);
1554 pfs_create_file(root, "modules", &linprocfs_domodules,
1555 NULL, NULL, NULL, PFS_RD);
1557 pfs_create_file(root, "mounts", &linprocfs_domtab,
1558 NULL, NULL, NULL, PFS_RD);
1559 pfs_create_file(root, "mtab", &linprocfs_domtab,
1560 NULL, NULL, NULL, PFS_RD);
1561 pfs_create_file(root, "partitions", &linprocfs_dopartitions,
1562 NULL, NULL, NULL, PFS_RD);
1563 pfs_create_link(root, "self", &procfs_docurproc,
1564 NULL, NULL, NULL, 0);
1565 pfs_create_file(root, "stat", &linprocfs_dostat,
1566 NULL, NULL, NULL, PFS_RD);
1567 pfs_create_file(root, "swaps", &linprocfs_doswaps,
1568 NULL, NULL, NULL, PFS_RD);
1569 pfs_create_file(root, "uptime", &linprocfs_douptime,
1570 NULL, NULL, NULL, PFS_RD);
1571 pfs_create_file(root, "version", &linprocfs_doversion,
1572 NULL, NULL, NULL, PFS_RD);
1575 dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
1576 pfs_create_file(dir, "dev", &linprocfs_donetdev,
1577 NULL, NULL, NULL, PFS_RD);
1579 /* /proc/<pid>/... */
1580 dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
1581 pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
1582 NULL, NULL, NULL, PFS_RD);
1583 pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
1584 NULL, NULL, NULL, 0);
1585 pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
1586 NULL, &procfs_candebug, NULL, PFS_RD);
1587 pfs_create_link(dir, "exe", &procfs_doprocfile,
1588 NULL, &procfs_notsystem, NULL, 0);
1589 pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
1590 NULL, NULL, NULL, PFS_RD);
1591 pfs_create_file(dir, "mem", &procfs_doprocmem,
1592 &procfs_attr, &procfs_candebug, NULL, PFS_RDWR|PFS_RAW);
1593 pfs_create_file(dir, "mounts", &linprocfs_domtab,
1594 NULL, NULL, NULL, PFS_RD);
1595 pfs_create_link(dir, "root", &linprocfs_doprocroot,
1596 NULL, NULL, NULL, 0);
1597 pfs_create_file(dir, "stat", &linprocfs_doprocstat,
1598 NULL, NULL, NULL, PFS_RD);
1599 pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
1600 NULL, NULL, NULL, PFS_RD);
1601 pfs_create_file(dir, "status", &linprocfs_doprocstatus,
1602 NULL, NULL, NULL, PFS_RD);
1603 pfs_create_link(dir, "fd", &linprocfs_dofdescfs,
1604 NULL, NULL, NULL, 0);
1605 pfs_create_file(dir, "auxv", &linprocfs_doauxv,
1606 NULL, &procfs_candebug, NULL, PFS_RD|PFS_RAWRD);
1607 pfs_create_file(dir, "limits", &linprocfs_doproclimits,
1608 NULL, NULL, NULL, PFS_RD);
1610 /* /proc/scsi/... */
1611 dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
1612 pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
1613 NULL, NULL, NULL, PFS_RD);
1614 pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
1615 NULL, NULL, NULL, PFS_RD);
1618 dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
1619 /* /proc/sys/kernel/... */
1620 dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0);
1621 pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
1622 NULL, NULL, NULL, PFS_RD);
1623 pfs_create_file(dir, "ostype", &linprocfs_doostype,
1624 NULL, NULL, NULL, PFS_RD);
1625 pfs_create_file(dir, "version", &linprocfs_doosbuild,
1626 NULL, NULL, NULL, PFS_RD);
1627 pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
1628 NULL, NULL, NULL, PFS_RD);
1629 pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
1630 NULL, NULL, NULL, PFS_RD);
1631 pfs_create_file(dir, "sem", &linprocfs_dosem,
1632 NULL, NULL, NULL, PFS_RD);
1634 /* /proc/sys/kernel/random/... */
1635 dir = pfs_create_dir(dir, "random", NULL, NULL, NULL, 0);
1636 pfs_create_file(dir, "uuid", &linprocfs_douuid,
1637 NULL, NULL, NULL, PFS_RD);
1646 linprocfs_uninit(PFS_INIT_ARGS)
1649 /* nothing to do, pseudofs will GC */
1653 PSEUDOFS(linprocfs, 1, PR_ALLOW_MOUNT_LINPROCFS);
1654 #if defined(__amd64__)
1655 MODULE_DEPEND(linprocfs, linux_common, 1, 1, 1);
1657 MODULE_DEPEND(linprocfs, linux, 1, 1, 1);
1659 MODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
1660 MODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);
1661 MODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1);