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 memshared; /* shared memory ??? */
148 unsigned long buffers, cached; /* buffer / cache memory ??? */
149 unsigned long long swaptotal; /* total swap space in bytes */
150 unsigned long long swapused; /* used swap space in bytes */
151 unsigned long long swapfree; /* free swap space in bytes */
155 memtotal = physmem * PAGE_SIZE;
157 * The correct thing here would be:
159 memfree = vm_cnt.v_free_count * PAGE_SIZE;
160 memused = memtotal - memfree;
162 * but it might mislead linux binaries into thinking there
163 * is very little memory left, so we cheat and tell them that
164 * all memory that isn't wired down is free.
166 memused = vm_cnt.v_wire_count * PAGE_SIZE;
167 memfree = memtotal - memused;
168 swap_pager_status(&i, &j);
169 swaptotal = (unsigned long long)i * PAGE_SIZE;
170 swapused = (unsigned long long)j * PAGE_SIZE;
171 swapfree = swaptotal - swapused;
173 mtx_lock(&vm_object_list_mtx);
174 TAILQ_FOREACH(object, &vm_object_list, object_list)
175 if (object->shadow_count > 1)
176 memshared += object->resident_page_count;
177 mtx_unlock(&vm_object_list_mtx);
178 memshared *= PAGE_SIZE;
180 * We'd love to be able to write:
184 * but bufspace is internal to vfs_bio.c and we don't feel
185 * like unstaticizing it just for linprocfs's sake.
188 cached = vm_cnt.v_cache_count * PAGE_SIZE;
191 " total: used: free: shared: buffers: cached:\n"
192 "Mem: %lu %lu %lu %lu %lu %lu\n"
193 "Swap: %llu %llu %llu\n"
194 "MemTotal: %9lu kB\n"
196 "MemShared:%9lu kB\n"
199 "SwapTotal:%9llu kB\n"
200 "SwapFree: %9llu kB\n",
201 memtotal, memused, memfree, memshared, buffers, cached,
202 swaptotal, swapused, swapfree,
203 B2K(memtotal), B2K(memfree),
204 B2K(memshared), B2K(buffers), B2K(cached),
205 B2K(swaptotal), B2K(swapfree));
210 #if defined(__i386__) || defined(__amd64__)
212 * Filler function for proc/cpuinfo (i386 & amd64 version)
215 linprocfs_docpuinfo(PFS_FILL_ARGS)
221 int class, fqmhz, fqkhz;
225 * We default the flags to include all non-conflicting flags,
226 * and the Intel versions of conflicting flags.
228 static char *flags[] = {
229 "fpu", "vme", "de", "pse", "tsc",
230 "msr", "pae", "mce", "cx8", "apic",
231 "sep", "sep", "mtrr", "pge", "mca",
232 "cmov", "pat", "pse36", "pn", "b19",
233 "b20", "b21", "mmxext", "mmx", "fxsr",
234 "xmm", "sse2", "b27", "b28", "b29",
258 #else /* __amd64__ */
265 hw_model[0] = CTL_HW;
266 hw_model[1] = HW_MODEL;
268 size = sizeof(model);
269 if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0)
270 strcpy(model, "unknown");
271 for (i = 0; i < mp_ncpus; ++i) {
274 "vendor_id\t: %.20s\n"
278 "stepping\t: %u\n\n",
279 i, cpu_vendor, CPUID_TO_FAMILY(cpu_id),
280 CPUID_TO_MODEL(cpu_id), model, cpu_id & CPUID_STEPPING);
281 /* XXX per-cpu vendor / class / model / id? */
284 sbuf_cat(sb, "flags\t\t:");
287 switch (cpu_vendor_id) {
292 case CPU_VENDOR_CYRIX:
298 for (i = 0; i < 32; i++)
299 if (cpu_feature & (1 << i))
300 sbuf_printf(sb, " %s", flags[i]);
302 freq = atomic_load_acq_64(&tsc_freq);
304 fqmhz = (freq + 4999) / 1000000;
305 fqkhz = ((freq + 4999) / 10000) % 100;
307 "cpu MHz\t\t: %d.%02d\n"
308 "bogomips\t: %d.%02d\n",
309 fqmhz, fqkhz, fqmhz, fqkhz);
314 #endif /* __i386__ || __amd64__ */
317 * Filler function for proc/mtab
319 * This file doesn't exist in Linux' procfs, but is included here so
320 * users can symlink /compat/linux/etc/mtab to /proc/mtab
323 linprocfs_domtab(PFS_FILL_ARGS)
327 char *dlep, *flep, *mntto, *mntfrom, *fstype;
330 struct statfs *buf, *sp;
333 /* resolve symlinks etc. in the emulation tree prefix */
334 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td);
337 lep = linux_emul_path;
339 if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
343 lep_len = strlen(lep);
346 error = kern_getfsstat(td, &buf, SIZE_T_MAX, &count,
347 UIO_SYSSPACE, MNT_WAIT);
354 for (sp = buf; count > 0; sp++, count--) {
355 /* determine device name */
356 mntfrom = sp->f_mntfromname;
358 /* determine mount point */
359 mntto = sp->f_mntonname;
360 if (strncmp(mntto, lep, lep_len) == 0 && mntto[lep_len] == '/')
363 /* determine fs type */
364 fstype = sp->f_fstypename;
365 if (strcmp(fstype, pn->pn_info->pi_name) == 0)
366 mntfrom = fstype = "proc";
367 else if (strcmp(fstype, "procfs") == 0)
370 if (strcmp(fstype, "linsysfs") == 0) {
371 sbuf_printf(sb, "/sys %s sysfs %s", mntto,
372 sp->f_flags & MNT_RDONLY ? "ro" : "rw");
374 /* For Linux msdosfs is called vfat */
375 if (strcmp(fstype, "msdosfs") == 0)
377 sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
378 sp->f_flags & MNT_RDONLY ? "ro" : "rw");
380 #define ADD_OPTION(opt, name) \
381 if (sp->f_flags & (opt)) sbuf_printf(sb, "," name);
382 ADD_OPTION(MNT_SYNCHRONOUS, "sync");
383 ADD_OPTION(MNT_NOEXEC, "noexec");
384 ADD_OPTION(MNT_NOSUID, "nosuid");
385 ADD_OPTION(MNT_UNION, "union");
386 ADD_OPTION(MNT_ASYNC, "async");
387 ADD_OPTION(MNT_SUIDDIR, "suiddir");
388 ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow");
389 ADD_OPTION(MNT_NOATIME, "noatime");
391 /* a real Linux mtab will also show NFS options */
392 sbuf_printf(sb, " 0 0\n");
401 * Filler function for proc/partitions
404 linprocfs_dopartitions(PFS_FILL_ARGS)
408 struct g_provider *pp;
412 sbuf_printf(sb, "major minor #blocks name rio rmerge rsect "
413 "ruse wio wmerge wsect wuse running use aveq\n");
415 LIST_FOREACH(cp, &g_classes, class) {
416 if (strcmp(cp->name, "DISK") == 0 ||
417 strcmp(cp->name, "PART") == 0)
418 LIST_FOREACH(gp, &cp->geom, geom) {
419 LIST_FOREACH(pp, &gp->provider, provider) {
420 if (linux_driver_get_major_minor(
421 pp->name, &major, &minor) != 0) {
425 sbuf_printf(sb, "%d %d %lld %s "
427 "%d %d %d %d %d %d\n",
429 (long long)pp->mediasize, pp->name,
442 * Filler function for proc/stat
445 linprocfs_dostat(PFS_FILL_ARGS)
448 long cp_time[CPUSTATES];
452 read_cpu_time(cp_time);
453 sbuf_printf(sb, "cpu %ld %ld %ld %ld\n",
454 T2J(cp_time[CP_USER]),
455 T2J(cp_time[CP_NICE]),
456 T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
457 T2J(cp_time[CP_IDLE]));
460 cp = pcpu->pc_cp_time;
461 sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i,
464 T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/),
475 vm_cnt.v_vnodepgsout,
480 (long long)boottime.tv_sec);
485 linprocfs_doswaps(PFS_FILL_ARGS)
488 uintmax_t total, used;
490 char devname[SPECNAMELEN + 1];
492 sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
495 if (swap_dev_info(n, &xsw, devname, sizeof(devname)) != 0)
497 total = (uintmax_t)xsw.xsw_nblks * PAGE_SIZE / 1024;
498 used = (uintmax_t)xsw.xsw_used * PAGE_SIZE / 1024;
501 * The space and not tab after the device name is on
502 * purpose. Linux does so.
504 sbuf_printf(sb, "/dev/%-34s unknown\t\t%jd\t%jd\t-1\n",
505 devname, total, used);
512 * Filler function for proc/uptime
515 linprocfs_douptime(PFS_FILL_ARGS)
517 long cp_time[CPUSTATES];
521 read_cpu_time(cp_time);
522 sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n",
523 (long long)tv.tv_sec, tv.tv_usec / 10000,
524 T2S(cp_time[CP_IDLE] / mp_ncpus),
525 T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100);
533 linprocfs_osbuild(struct thread *td, struct sbuf *sb)
539 strncpy(osbuild, version, 256);
541 cp1 = strstr(osbuild, "\n");
542 cp2 = strstr(osbuild, ":");
545 cp1 = strstr(osbuild, "#");
549 sbuf_printf(sb, "%s%s", cp1, cp2 + 1);
552 sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977");
559 linprocfs_osbuilder(struct thread *td, struct sbuf *sb)
565 cp = strstr(version, "\n ");
567 strncpy(builder, cp + 5, 256);
569 cp = strstr(builder, ":");
574 sbuf_cat(sb, builder);
577 sbuf_cat(sb, "des@freebsd.org");
581 * Filler function for proc/version
584 linprocfs_doversion(PFS_FILL_ARGS)
586 char osname[LINUX_MAX_UTSNAME];
587 char osrelease[LINUX_MAX_UTSNAME];
589 linux_get_osname(td, osname);
590 linux_get_osrelease(td, osrelease);
591 sbuf_printf(sb, "%s version %s (", osname, osrelease);
592 linprocfs_osbuilder(td, sb);
593 sbuf_cat(sb, ") (gcc version " __VERSION__ ") ");
594 linprocfs_osbuild(td, sb);
601 * Filler function for proc/loadavg
604 linprocfs_doloadavg(PFS_FILL_ARGS)
608 "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
609 (int)(averunnable.ldavg[0] / averunnable.fscale),
610 (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
611 (int)(averunnable.ldavg[1] / averunnable.fscale),
612 (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
613 (int)(averunnable.ldavg[2] / averunnable.fscale),
614 (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
615 1, /* number of running tasks */
616 nprocs, /* number of tasks */
617 lastpid /* the last pid */
623 * Filler function for proc/pid/stat
626 linprocfs_doprocstat(PFS_FILL_ARGS)
628 struct kinfo_proc kp;
630 static int ratelimit = 0;
631 vm_offset_t startcode, startdata;
633 sx_slock(&proctree_lock);
635 fill_kinfo_proc(p, &kp);
636 sx_sunlock(&proctree_lock);
638 startcode = (vm_offset_t)p->p_vmspace->vm_taddr;
639 startdata = (vm_offset_t)p->p_vmspace->vm_daddr;
644 sbuf_printf(sb, "%d", p->p_pid);
645 #define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
646 PS_ADD("comm", "(%s)", p->p_comm);
647 if (kp.ki_stat > sizeof(linux_state)) {
650 if (ratelimit == 0) {
651 printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n",
652 kp.ki_stat, sizeof(linux_state));
656 state = linux_state[kp.ki_stat - 1];
657 PS_ADD("state", "%c", state);
658 PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0);
659 PS_ADD("pgrp", "%d", p->p_pgid);
660 PS_ADD("session", "%d", p->p_session->s_sid);
662 PS_ADD("tty", "%ju", (uintmax_t)kp.ki_tdev);
663 PS_ADD("tpgid", "%d", kp.ki_tpgid);
664 PS_ADD("flags", "%u", 0); /* XXX */
665 PS_ADD("minflt", "%lu", kp.ki_rusage.ru_minflt);
666 PS_ADD("cminflt", "%lu", kp.ki_rusage_ch.ru_minflt);
667 PS_ADD("majflt", "%lu", kp.ki_rusage.ru_majflt);
668 PS_ADD("cmajflt", "%lu", kp.ki_rusage_ch.ru_majflt);
669 PS_ADD("utime", "%ld", TV2J(&kp.ki_rusage.ru_utime));
670 PS_ADD("stime", "%ld", TV2J(&kp.ki_rusage.ru_stime));
671 PS_ADD("cutime", "%ld", TV2J(&kp.ki_rusage_ch.ru_utime));
672 PS_ADD("cstime", "%ld", TV2J(&kp.ki_rusage_ch.ru_stime));
673 PS_ADD("priority", "%d", kp.ki_pri.pri_user);
674 PS_ADD("nice", "%d", kp.ki_nice); /* 19 (nicest) to -19 */
675 PS_ADD("0", "%d", 0); /* removed field */
676 PS_ADD("itrealvalue", "%d", 0); /* XXX */
677 PS_ADD("starttime", "%lu", TV2J(&kp.ki_start) - TV2J(&boottime));
678 PS_ADD("vsize", "%ju", P2K((uintmax_t)kp.ki_size));
679 PS_ADD("rss", "%ju", (uintmax_t)kp.ki_rssize);
680 PS_ADD("rlim", "%lu", kp.ki_rusage.ru_maxrss);
681 PS_ADD("startcode", "%ju", (uintmax_t)startcode);
682 PS_ADD("endcode", "%ju", (uintmax_t)startdata);
683 PS_ADD("startstack", "%u", 0); /* XXX */
684 PS_ADD("kstkesp", "%u", 0); /* XXX */
685 PS_ADD("kstkeip", "%u", 0); /* XXX */
686 PS_ADD("signal", "%u", 0); /* XXX */
687 PS_ADD("blocked", "%u", 0); /* XXX */
688 PS_ADD("sigignore", "%u", 0); /* XXX */
689 PS_ADD("sigcatch", "%u", 0); /* XXX */
690 PS_ADD("wchan", "%u", 0); /* XXX */
691 PS_ADD("nswap", "%lu", kp.ki_rusage.ru_nswap);
692 PS_ADD("cnswap", "%lu", kp.ki_rusage_ch.ru_nswap);
693 PS_ADD("exitsignal", "%d", 0); /* XXX */
694 PS_ADD("processor", "%u", kp.ki_lastcpu);
695 PS_ADD("rt_priority", "%u", 0); /* XXX */ /* >= 2.5.19 */
696 PS_ADD("policy", "%u", kp.ki_pri.pri_class); /* >= 2.5.19 */
704 * Filler function for proc/pid/statm
707 linprocfs_doprocstatm(PFS_FILL_ARGS)
709 struct kinfo_proc kp;
712 sx_slock(&proctree_lock);
714 fill_kinfo_proc(p, &kp);
716 sx_sunlock(&proctree_lock);
719 * See comments in linprocfs_doprocstatus() regarding the
720 * computation of lsize.
722 /* size resident share trs drs lrs dt */
723 sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size));
724 sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize);
725 sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */
726 sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize);
727 sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize));
728 lsize = B2P(kp.ki_size) - kp.ki_dsize -
729 kp.ki_ssize - kp.ki_tsize - 1;
730 sbuf_printf(sb, "%ju ", (uintmax_t)lsize);
731 sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */
737 * Filler function for proc/pid/status
740 linprocfs_doprocstatus(PFS_FILL_ARGS)
742 struct kinfo_proc kp;
747 l_sigset_t siglist, sigignore, sigcatch;
750 sx_slock(&proctree_lock);
752 td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */
754 if (P_SHOULDSTOP(p)) {
755 state = "T (stopped)";
762 if (p->p_flag & P_WEXIT) {
763 state = "X (exiting)";
766 switch(td2->td_state) {
768 state = "S (sleeping)";
772 state = "R (running)";
775 state = "? (unknown)";
780 state = "Z (zombie)";
783 state = "? (unknown)";
788 fill_kinfo_proc(p, &kp);
789 sx_sunlock(&proctree_lock);
791 sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */
792 sbuf_printf(sb, "State:\t%s\n", state);
797 sbuf_printf(sb, "Pid:\t%d\n", p->p_pid);
798 sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ?
799 p->p_pptr->p_pid : 0);
800 sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid,
802 p->p_ucred->cr_svuid,
803 /* FreeBSD doesn't have fsuid */
805 sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid,
807 p->p_ucred->cr_svgid,
808 /* FreeBSD doesn't have fsgid */
810 sbuf_cat(sb, "Groups:\t");
811 for (i = 0; i < p->p_ucred->cr_ngroups; i++)
812 sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]);
819 * While our approximation of VmLib may not be accurate (I
820 * don't know of a simple way to verify it, and I'm not sure
821 * it has much meaning anyway), I believe it's good enough.
823 * The same code that could (I think) accurately compute VmLib
824 * could also compute VmLck, but I don't really care enough to
825 * implement it. Submissions are welcome.
827 sbuf_printf(sb, "VmSize:\t%8ju kB\n", B2K((uintmax_t)kp.ki_size));
828 sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */
829 sbuf_printf(sb, "VmRSS:\t%8ju kB\n", P2K((uintmax_t)kp.ki_rssize));
830 sbuf_printf(sb, "VmData:\t%8ju kB\n", P2K((uintmax_t)kp.ki_dsize));
831 sbuf_printf(sb, "VmStk:\t%8ju kB\n", P2K((uintmax_t)kp.ki_ssize));
832 sbuf_printf(sb, "VmExe:\t%8ju kB\n", P2K((uintmax_t)kp.ki_tsize));
833 lsize = B2P(kp.ki_size) - kp.ki_dsize -
834 kp.ki_ssize - kp.ki_tsize - 1;
835 sbuf_printf(sb, "VmLib:\t%8ju kB\n", P2K((uintmax_t)lsize));
841 bsd_to_linux_sigset(&p->p_siglist, &siglist);
843 mtx_lock(&ps->ps_mtx);
844 bsd_to_linux_sigset(&ps->ps_sigignore, &sigignore);
845 bsd_to_linux_sigset(&ps->ps_sigcatch, &sigcatch);
846 mtx_unlock(&ps->ps_mtx);
849 sbuf_printf(sb, "SigPnd:\t%016jx\n", siglist.__mask);
851 * XXX. SigBlk - target thread's signal mask, td_sigmask.
852 * To implement SigBlk pseudofs should support proc/tid dir entries.
854 sbuf_printf(sb, "SigBlk:\t%016x\n", 0);
855 sbuf_printf(sb, "SigIgn:\t%016jx\n", sigignore.__mask);
856 sbuf_printf(sb, "SigCgt:\t%016jx\n", sigcatch.__mask);
859 * Linux also prints the capability masks, but we don't have
860 * capabilities yet, and when we do get them they're likely to
861 * be meaningless to Linux programs, so we lie. XXX
863 sbuf_printf(sb, "CapInh:\t%016x\n", 0);
864 sbuf_printf(sb, "CapPrm:\t%016x\n", 0);
865 sbuf_printf(sb, "CapEff:\t%016x\n", 0);
872 * Filler function for proc/pid/cwd
875 linprocfs_doproccwd(PFS_FILL_ARGS)
877 struct filedesc *fdp;
879 char *fullpath = "unknown";
880 char *freepath = NULL;
887 FILEDESC_SUNLOCK(fdp);
888 vn_fullpath(td, vp, &fullpath, &freepath);
891 sbuf_printf(sb, "%s", fullpath);
893 free(freepath, M_TEMP);
898 * Filler function for proc/pid/root
901 linprocfs_doprocroot(PFS_FILL_ARGS)
903 struct filedesc *fdp;
905 char *fullpath = "unknown";
906 char *freepath = NULL;
910 vp = jailed(p->p_ucred) ? fdp->fd_jdir : fdp->fd_rdir;
913 FILEDESC_SUNLOCK(fdp);
914 vn_fullpath(td, vp, &fullpath, &freepath);
917 sbuf_printf(sb, "%s", fullpath);
919 free(freepath, M_TEMP);
924 * Filler function for proc/pid/cmdline
927 linprocfs_doproccmdline(PFS_FILL_ARGS)
932 if ((ret = p_cansee(td, p)) != 0) {
938 * Mimic linux behavior and pass only processes with usermode
939 * address space as valid. Return zero silently otherwize.
941 if (p->p_vmspace == &vmspace0) {
945 if (p->p_args != NULL) {
946 sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
951 if ((p->p_flag & P_SYSTEM) != 0) {
958 ret = proc_getargv(td, p, sb);
963 * Filler function for proc/pid/environ
966 linprocfs_doprocenviron(PFS_FILL_ARGS)
970 * Mimic linux behavior and pass only processes with usermode
971 * address space as valid. Return zero silently otherwize.
973 if (p->p_vmspace == &vmspace0)
976 return (proc_getenvv(td, p, sb));
979 static char l32_map_str[] = "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n";
980 static char l64_map_str[] = "%016lx-%016lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n";
981 static char vdso_str[] = " [vdso]";
982 static char stack_str[] = " [stack]";
985 * Filler function for proc/pid/maps
988 linprocfs_doprocmaps(PFS_FILL_ARGS)
992 vm_map_entry_t entry, tmp_entry;
993 vm_object_t obj, tobj, lobj;
994 vm_offset_t e_start, e_end;
995 vm_ooffset_t off = 0;
997 unsigned int last_timestamp;
998 char *name = "", *freename = NULL;
999 const char *l_map_str;
1001 int ref_count, shadow_count, flags;
1007 error = p_candebug(td, p);
1012 if (uio->uio_rw != UIO_READ)
1013 return (EOPNOTSUPP);
1016 vm = vmspace_acquire_ref(p);
1020 if (SV_CURPROC_FLAG(SV_LP64))
1021 l_map_str = l64_map_str;
1023 l_map_str = l32_map_str;
1025 vm_map_lock_read(map);
1026 for (entry = map->header.next; entry != &map->header;
1027 entry = entry->next) {
1030 if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
1032 e_prot = entry->protection;
1033 e_start = entry->start;
1035 obj = entry->object.vm_object;
1036 for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) {
1037 VM_OBJECT_RLOCK(tobj);
1039 VM_OBJECT_RUNLOCK(lobj);
1042 last_timestamp = map->timestamp;
1043 vm_map_unlock_read(map);
1046 off = IDX_TO_OFF(lobj->size);
1047 vp = vm_object_vnode(lobj);
1051 VM_OBJECT_RUNLOCK(lobj);
1053 ref_count = obj->ref_count;
1054 shadow_count = obj->shadow_count;
1055 VM_OBJECT_RUNLOCK(obj);
1057 vn_fullpath(td, vp, &name, &freename);
1058 vn_lock(vp, LK_SHARED | LK_RETRY);
1059 VOP_GETATTR(vp, &vat, td->td_ucred);
1060 ino = vat.va_fileid;
1062 } else if (SV_PROC_ABI(p) == SV_ABI_LINUX) {
1063 if (e_start == p->p_sysent->sv_shared_page_base)
1065 if (e_end == p->p_sysent->sv_usrstack)
1076 * start, end, access, offset, major, minor, inode, name.
1078 error = sbuf_printf(sb, l_map_str,
1079 (u_long)e_start, (u_long)e_end,
1080 (e_prot & VM_PROT_READ)?"r":"-",
1081 (e_prot & VM_PROT_WRITE)?"w":"-",
1082 (e_prot & VM_PROT_EXECUTE)?"x":"-",
1092 free(freename, M_TEMP);
1093 vm_map_lock_read(map);
1098 if (last_timestamp != map->timestamp) {
1100 * Look again for the entry because the map was
1101 * modified while it was unlocked. Specifically,
1102 * the entry may have been clipped, merged, or deleted.
1104 vm_map_lookup_entry(map, e_end - 1, &tmp_entry);
1108 vm_map_unlock_read(map);
1115 * Criteria for interface name translation
1117 #define IFP_IS_ETH(ifp) (ifp->if_type == IFT_ETHER)
1120 linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen)
1122 struct ifnet *ifscan;
1125 IFNET_RLOCK_ASSERT();
1127 /* Short-circuit non ethernet interfaces */
1128 if (!IFP_IS_ETH(ifp))
1129 return (strlcpy(buffer, ifp->if_xname, buflen));
1131 /* Determine the (relative) unit number for ethernet interfaces */
1133 TAILQ_FOREACH(ifscan, &V_ifnet, if_link) {
1135 return (snprintf(buffer, buflen, "eth%d", ethno));
1136 if (IFP_IS_ETH(ifscan))
1144 * Filler function for proc/net/dev
1147 linprocfs_donetdev(PFS_FILL_ARGS)
1149 char ifname[16]; /* XXX LINUX_IFNAMSIZ */
1152 sbuf_printf(sb, "%6s|%58s|%s\n"
1154 "Inter-", " Receive", " Transmit",
1156 "bytes packets errs drop fifo frame compressed multicast",
1157 "bytes packets errs drop fifo colls carrier compressed");
1159 CURVNET_SET(TD_TO_VNET(curthread));
1161 TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
1162 linux_ifname(ifp, ifname, sizeof ifname);
1163 sbuf_printf(sb, "%6.6s: ", ifname);
1164 sbuf_printf(sb, "%7ju %7ju %4ju %4ju %4lu %5lu %10lu %9ju ",
1165 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IBYTES),
1166 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IPACKETS),
1167 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IERRORS),
1168 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IQDROPS),
1169 /* rx_missed_errors */
1170 0UL, /* rx_fifo_errors */
1171 0UL, /* rx_length_errors +
1174 * rx_frame_errors */
1175 0UL, /* rx_compressed */
1176 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IMCASTS));
1177 /* XXX-BZ rx only? */
1178 sbuf_printf(sb, "%8ju %7ju %4ju %4ju %4lu %5ju %7lu %10lu\n",
1179 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OBYTES),
1180 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OPACKETS),
1181 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OERRORS),
1182 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OQDROPS),
1183 0UL, /* tx_fifo_errors */
1184 (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_COLLISIONS),
1185 0UL, /* tx_carrier_errors +
1186 * tx_aborted_errors +
1187 * tx_window_errors +
1188 * tx_heartbeat_errors*/
1189 0UL); /* tx_compressed */
1198 * Filler function for proc/sys/kernel/osrelease
1201 linprocfs_doosrelease(PFS_FILL_ARGS)
1203 char osrelease[LINUX_MAX_UTSNAME];
1205 linux_get_osrelease(td, osrelease);
1206 sbuf_printf(sb, "%s\n", osrelease);
1212 * Filler function for proc/sys/kernel/ostype
1215 linprocfs_doostype(PFS_FILL_ARGS)
1217 char osname[LINUX_MAX_UTSNAME];
1219 linux_get_osname(td, osname);
1220 sbuf_printf(sb, "%s\n", osname);
1226 * Filler function for proc/sys/kernel/version
1229 linprocfs_doosbuild(PFS_FILL_ARGS)
1232 linprocfs_osbuild(td, sb);
1238 * Filler function for proc/sys/kernel/msgmni
1241 linprocfs_domsgmni(PFS_FILL_ARGS)
1244 sbuf_printf(sb, "%d\n", msginfo.msgmni);
1249 * Filler function for proc/sys/kernel/pid_max
1252 linprocfs_dopid_max(PFS_FILL_ARGS)
1255 sbuf_printf(sb, "%i\n", PID_MAX);
1260 * Filler function for proc/sys/kernel/sem
1263 linprocfs_dosem(PFS_FILL_ARGS)
1266 sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns,
1267 seminfo.semopm, seminfo.semmni);
1272 * Filler function for proc/scsi/device_info
1275 linprocfs_doscsidevinfo(PFS_FILL_ARGS)
1282 * Filler function for proc/scsi/scsi
1285 linprocfs_doscsiscsi(PFS_FILL_ARGS)
1292 * Filler function for proc/devices
1295 linprocfs_dodevices(PFS_FILL_ARGS)
1298 sbuf_printf(sb, "Character devices:\n");
1300 char_devices = linux_get_char_devices();
1301 sbuf_printf(sb, "%s", char_devices);
1302 linux_free_get_char_devices(char_devices);
1304 sbuf_printf(sb, "\nBlock devices:\n");
1310 * Filler function for proc/cmdline
1313 linprocfs_docmdline(PFS_FILL_ARGS)
1316 sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
1317 sbuf_printf(sb, " ro root=302\n");
1322 * Filler function for proc/filesystems
1325 linprocfs_dofilesystems(PFS_FILL_ARGS)
1327 struct vfsconf *vfsp;
1330 TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
1331 if (vfsp->vfc_flags & VFCF_SYNTHETIC)
1332 sbuf_printf(sb, "nodev");
1333 sbuf_printf(sb, "\t%s\n", vfsp->vfc_name);
1341 * Filler function for proc/modules
1344 linprocfs_domodules(PFS_FILL_ARGS)
1346 struct linker_file *lf;
1348 TAILQ_FOREACH(lf, &linker_files, link) {
1349 sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
1350 (unsigned long)lf->size, lf->refs);
1357 * Filler function for proc/pid/fd
1360 linprocfs_dofdescfs(PFS_FILL_ARGS)
1364 sbuf_printf(sb, "/dev/fd");
1366 sbuf_printf(sb, "unknown");
1371 * Filler function for proc/pid/limits
1373 static const struct linux_rlimit_ident {
1376 unsigned int rlim_id;
1377 } linux_rlimits_ident[] = {
1378 { "Max cpu time", "seconds", RLIMIT_CPU },
1379 { "Max file size", "bytes", RLIMIT_FSIZE },
1380 { "Max data size", "bytes", RLIMIT_DATA },
1381 { "Max stack size", "bytes", RLIMIT_STACK },
1382 { "Max core file size", "bytes", RLIMIT_CORE },
1383 { "Max resident set", "bytes", RLIMIT_RSS },
1384 { "Max processes", "processes", RLIMIT_NPROC },
1385 { "Max open files", "files", RLIMIT_NOFILE },
1386 { "Max locked memory", "bytes", RLIMIT_MEMLOCK },
1387 { "Max address space", "bytes", RLIMIT_AS },
1388 { "Max file locks", "locks", LINUX_RLIMIT_LOCKS },
1389 { "Max pending signals", "signals", LINUX_RLIMIT_SIGPENDING },
1390 { "Max msgqueue size", "bytes", LINUX_RLIMIT_MSGQUEUE },
1391 { "Max nice priority", "", LINUX_RLIMIT_NICE },
1392 { "Max realtime priority", "", LINUX_RLIMIT_RTPRIO },
1393 { "Max realtime timeout", "us", LINUX_RLIMIT_RTTIME },
1398 linprocfs_doproclimits(PFS_FILL_ARGS)
1400 const struct linux_rlimit_ident *li;
1401 struct plimit *limp;
1407 limp = lim_hold(p->p_limit);
1410 sbuf_printf(sb, "%-26s%-21s%-21s%-21s\n", "Limit", "Soft Limit",
1411 "Hard Limit", "Units");
1412 for (li = linux_rlimits_ident; li->desc != NULL; ++li) {
1413 switch (li->rlim_id)
1415 case LINUX_RLIMIT_LOCKS:
1417 case LINUX_RLIMIT_RTTIME:
1418 rl.rlim_cur = RLIM_INFINITY;
1420 case LINUX_RLIMIT_SIGPENDING:
1421 error = kernel_sysctlbyname(td,
1422 "kern.sigqueue.max_pending_per_proc",
1423 &res, &size, 0, 0, 0, 0);
1429 case LINUX_RLIMIT_MSGQUEUE:
1430 error = kernel_sysctlbyname(td,
1431 "kern.ipc.msgmnb", &res, &size, 0, 0, 0, 0);
1437 case LINUX_RLIMIT_NICE:
1439 case LINUX_RLIMIT_RTPRIO:
1444 rl = limp->pl_rlimit[li->rlim_id];
1447 if (rl.rlim_cur == RLIM_INFINITY)
1448 sbuf_printf(sb, "%-26s%-21s%-21s%-10s\n",
1449 li->desc, "unlimited", "unlimited", li->unit);
1451 sbuf_printf(sb, "%-26s%-21llu%-21llu%-10s\n",
1452 li->desc, (unsigned long long)rl.rlim_cur,
1453 (unsigned long long)rl.rlim_max, li->unit);
1460 * Filler function for proc/sys/kernel/random/uuid
1463 linprocfs_douuid(PFS_FILL_ARGS)
1467 kern_uuidgen(&uuid, 1);
1468 sbuf_printf_uuid(sb, &uuid);
1469 sbuf_printf(sb, "\n");
1474 * Filler function for proc/pid/auxv
1477 linprocfs_doauxv(PFS_FILL_ARGS)
1480 off_t buflen, resid;
1484 * Mimic linux behavior and pass only processes with usermode
1485 * address space as valid. Return zero silently otherwise.
1487 if (p->p_vmspace == &vmspace0)
1490 if (uio->uio_resid == 0)
1492 if (uio->uio_offset < 0 || uio->uio_resid < 0)
1495 asb = sbuf_new_auto();
1498 error = proc_getauxv(td, p, asb);
1500 error = sbuf_finish(asb);
1502 resid = sbuf_len(asb) - uio->uio_offset;
1503 if (resid > uio->uio_resid)
1504 buflen = uio->uio_resid;
1507 if (buflen > IOSIZE_MAX)
1509 if (buflen > MAXPHYS)
1515 error = uiomove(sbuf_data(asb) + uio->uio_offset, buflen, uio);
1524 linprocfs_init(PFS_INIT_ARGS)
1526 struct pfs_node *root;
1527 struct pfs_node *dir;
1532 pfs_create_file(root, "cmdline", &linprocfs_docmdline,
1533 NULL, NULL, NULL, PFS_RD);
1534 pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
1535 NULL, NULL, NULL, PFS_RD);
1536 pfs_create_file(root, "devices", &linprocfs_dodevices,
1537 NULL, NULL, NULL, PFS_RD);
1538 pfs_create_file(root, "filesystems", &linprocfs_dofilesystems,
1539 NULL, NULL, NULL, PFS_RD);
1540 pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
1541 NULL, NULL, NULL, PFS_RD);
1542 pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
1543 NULL, NULL, NULL, PFS_RD);
1545 pfs_create_file(root, "modules", &linprocfs_domodules,
1546 NULL, NULL, NULL, PFS_RD);
1548 pfs_create_file(root, "mounts", &linprocfs_domtab,
1549 NULL, NULL, NULL, PFS_RD);
1550 pfs_create_file(root, "mtab", &linprocfs_domtab,
1551 NULL, NULL, NULL, PFS_RD);
1552 pfs_create_file(root, "partitions", &linprocfs_dopartitions,
1553 NULL, NULL, NULL, PFS_RD);
1554 pfs_create_link(root, "self", &procfs_docurproc,
1555 NULL, NULL, NULL, 0);
1556 pfs_create_file(root, "stat", &linprocfs_dostat,
1557 NULL, NULL, NULL, PFS_RD);
1558 pfs_create_file(root, "swaps", &linprocfs_doswaps,
1559 NULL, NULL, NULL, PFS_RD);
1560 pfs_create_file(root, "uptime", &linprocfs_douptime,
1561 NULL, NULL, NULL, PFS_RD);
1562 pfs_create_file(root, "version", &linprocfs_doversion,
1563 NULL, NULL, NULL, PFS_RD);
1566 dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
1567 pfs_create_file(dir, "dev", &linprocfs_donetdev,
1568 NULL, NULL, NULL, PFS_RD);
1570 /* /proc/<pid>/... */
1571 dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
1572 pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
1573 NULL, NULL, NULL, PFS_RD);
1574 pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
1575 NULL, NULL, NULL, 0);
1576 pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
1577 NULL, &procfs_candebug, NULL, PFS_RD);
1578 pfs_create_link(dir, "exe", &procfs_doprocfile,
1579 NULL, &procfs_notsystem, NULL, 0);
1580 pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
1581 NULL, NULL, NULL, PFS_RD);
1582 pfs_create_file(dir, "mem", &procfs_doprocmem,
1583 &procfs_attr, &procfs_candebug, NULL, PFS_RDWR|PFS_RAW);
1584 pfs_create_link(dir, "root", &linprocfs_doprocroot,
1585 NULL, NULL, NULL, 0);
1586 pfs_create_file(dir, "stat", &linprocfs_doprocstat,
1587 NULL, NULL, NULL, PFS_RD);
1588 pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
1589 NULL, NULL, NULL, PFS_RD);
1590 pfs_create_file(dir, "status", &linprocfs_doprocstatus,
1591 NULL, NULL, NULL, PFS_RD);
1592 pfs_create_link(dir, "fd", &linprocfs_dofdescfs,
1593 NULL, NULL, NULL, 0);
1594 pfs_create_file(dir, "auxv", &linprocfs_doauxv,
1595 NULL, &procfs_candebug, NULL, PFS_RD|PFS_RAWRD);
1596 pfs_create_file(dir, "limits", &linprocfs_doproclimits,
1597 NULL, NULL, NULL, PFS_RD);
1599 /* /proc/scsi/... */
1600 dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
1601 pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
1602 NULL, NULL, NULL, PFS_RD);
1603 pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
1604 NULL, NULL, NULL, PFS_RD);
1607 dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
1608 /* /proc/sys/kernel/... */
1609 dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0);
1610 pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
1611 NULL, NULL, NULL, PFS_RD);
1612 pfs_create_file(dir, "ostype", &linprocfs_doostype,
1613 NULL, NULL, NULL, PFS_RD);
1614 pfs_create_file(dir, "version", &linprocfs_doosbuild,
1615 NULL, NULL, NULL, PFS_RD);
1616 pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
1617 NULL, NULL, NULL, PFS_RD);
1618 pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
1619 NULL, NULL, NULL, PFS_RD);
1620 pfs_create_file(dir, "sem", &linprocfs_dosem,
1621 NULL, NULL, NULL, PFS_RD);
1623 /* /proc/sys/kernel/random/... */
1624 dir = pfs_create_dir(dir, "random", NULL, NULL, NULL, 0);
1625 pfs_create_file(dir, "uuid", &linprocfs_douuid,
1626 NULL, NULL, NULL, PFS_RD);
1635 linprocfs_uninit(PFS_INIT_ARGS)
1638 /* nothing to do, pseudofs will GC */
1642 PSEUDOFS(linprocfs, 1, PR_ALLOW_MOUNT_LINPROCFS);
1643 #if defined(__amd64__)
1644 MODULE_DEPEND(linprocfs, linux_common, 1, 1, 1);
1646 MODULE_DEPEND(linprocfs, linux, 1, 1, 1);
1648 MODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
1649 MODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);
1650 MODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1);