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/filedesc.h>
52 #include <sys/kernel.h>
53 #include <sys/linker.h>
55 #include <sys/malloc.h>
56 #include <sys/mount.h>
58 #include <sys/mutex.h>
59 #include <sys/namei.h>
61 #include <sys/resourcevar.h>
65 #include <sys/socket.h>
66 #include <sys/sysctl.h>
67 #include <sys/systm.h>
71 #include <sys/vmmeter.h>
72 #include <sys/vnode.h>
77 #include <vm/vm_extern.h>
79 #include <vm/vm_map.h>
80 #include <vm/vm_param.h>
81 #include <vm/vm_object.h>
82 #include <vm/swap_pager.h>
84 #include <machine/clock.h>
86 #if defined(__i386__) || defined(__amd64__)
87 #include <machine/cputypes.h>
88 #include <machine/md_var.h>
89 #endif /* __i386__ || __amd64__ */
91 #include "opt_compat.h"
92 #ifdef COMPAT_LINUX32 /* XXX */
93 #include <machine/../linux32/linux.h>
95 #include <machine/../linux/linux.h>
97 #include <compat/linux/linux_ioctl.h>
98 #include <compat/linux/linux_mib.h>
99 #include <compat/linux/linux_util.h>
100 #include <fs/pseudofs/pseudofs.h>
101 #include <fs/procfs/procfs.h>
104 * Various conversion macros
106 #define T2J(x) (((x) * 100UL) / (stathz ? stathz : hz)) /* ticks to jiffies */
107 #define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */
108 #define B2K(x) ((x) >> 10) /* bytes to kbytes */
109 #define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */
110 #define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */
111 #define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */
114 * @brief Mapping of ki_stat in struct kinfo_proc to the linux state
116 * The linux procfs state field displays one of the characters RSDZTW to
117 * denote running, sleeping in an interruptible wait, waiting in an
118 * uninterruptible disk sleep, a zombie process, process is being traced
119 * or stopped, or process is paging respectively.
121 * Our struct kinfo_proc contains the variable ki_stat which contains a
122 * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK.
124 * This character array is used with ki_stati-1 as an index and tries to
125 * map our states to suitable linux states.
127 static char linux_state[] = "RRSTZDD";
130 * Filler function for proc/meminfo
133 linprocfs_domeminfo(PFS_FILL_ARGS)
135 unsigned long memtotal; /* total memory in bytes */
136 unsigned long memused; /* used memory in bytes */
137 unsigned long memfree; /* free memory in bytes */
138 unsigned long memshared; /* shared memory ??? */
139 unsigned long buffers, cached; /* buffer / cache memory ??? */
140 unsigned long long swaptotal; /* total swap space in bytes */
141 unsigned long long swapused; /* used swap space in bytes */
142 unsigned long long swapfree; /* free swap space in bytes */
146 memtotal = physmem * PAGE_SIZE;
148 * The correct thing here would be:
150 memfree = cnt.v_free_count * PAGE_SIZE;
151 memused = memtotal - memfree;
153 * but it might mislead linux binaries into thinking there
154 * is very little memory left, so we cheat and tell them that
155 * all memory that isn't wired down is free.
157 memused = cnt.v_wire_count * PAGE_SIZE;
158 memfree = memtotal - memused;
159 swap_pager_status(&i, &j);
160 swaptotal = (unsigned long long)i * PAGE_SIZE;
161 swapused = (unsigned long long)j * PAGE_SIZE;
162 swapfree = swaptotal - swapused;
164 mtx_lock(&vm_object_list_mtx);
165 TAILQ_FOREACH(object, &vm_object_list, object_list)
166 if (object->shadow_count > 1)
167 memshared += object->resident_page_count;
168 mtx_unlock(&vm_object_list_mtx);
169 memshared *= PAGE_SIZE;
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 = cnt.v_cache_count * PAGE_SIZE;
182 " total: used: free: shared: buffers: cached:\n"
183 "Mem: %lu %lu %lu %lu %lu %lu\n"
184 "Swap: %llu %llu %llu\n"
185 "MemTotal: %9lu kB\n"
187 "MemShared:%9lu kB\n"
190 "SwapTotal:%9llu kB\n"
191 "SwapFree: %9llu kB\n",
192 memtotal, memused, memfree, memshared, buffers, cached,
193 swaptotal, swapused, swapfree,
194 B2K(memtotal), B2K(memfree),
195 B2K(memshared), B2K(buffers), B2K(cached),
196 B2K(swaptotal), B2K(swapfree));
201 #if defined(__i386__) || defined(__amd64__)
203 * Filler function for proc/cpuinfo (i386 & amd64 version)
206 linprocfs_docpuinfo(PFS_FILL_ARGS)
211 int class, fqmhz, fqkhz;
215 * We default the flags to include all non-conflicting flags,
216 * and the Intel versions of conflicting flags.
218 static char *flags[] = {
219 "fpu", "vme", "de", "pse", "tsc",
220 "msr", "pae", "mce", "cx8", "apic",
221 "sep", "sep", "mtrr", "pge", "mca",
222 "cmov", "pat", "pse36", "pn", "b19",
223 "b20", "b21", "mmxext", "mmx", "fxsr",
224 "xmm", "b26", "b27", "b28", "b29",
248 #else /* __amd64__ */
255 hw_model[0] = CTL_HW;
256 hw_model[1] = HW_MODEL;
258 size = sizeof(model);
259 if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0)
260 strcpy(model, "unknown");
261 for (i = 0; i < mp_ncpus; ++i) {
264 "vendor_id\t: %.20s\n"
269 i, cpu_vendor, class, cpu, model, cpu_id & 0xf);
270 /* XXX per-cpu vendor / class / model / id? */
273 sbuf_cat(sb, "flags\t\t:");
275 if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) {
277 } else if (!strcmp(cpu_vendor, "CyrixInstead")) {
281 for (i = 0; i < 32; i++)
282 if (cpu_feature & (1 << i))
283 sbuf_printf(sb, " %s", flags[i]);
286 fqmhz = (tsc_freq + 4999) / 1000000;
287 fqkhz = ((tsc_freq + 4999) / 10000) % 100;
289 "cpu MHz\t\t: %d.%02d\n"
290 "bogomips\t: %d.%02d\n",
291 fqmhz, fqkhz, fqmhz, fqkhz);
296 #endif /* __i386__ || __amd64__ */
299 * Filler function for proc/mtab
301 * This file doesn't exist in Linux' procfs, but is included here so
302 * users can symlink /compat/linux/etc/mtab to /proc/mtab
305 linprocfs_domtab(PFS_FILL_ARGS)
310 char *dlep, *flep, *mntto, *mntfrom, *fstype;
314 /* resolve symlinks etc. in the emulation tree prefix */
315 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td);
318 lep = linux_emul_path;
320 if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
323 VFS_UNLOCK_GIANT(NDHASGIANT(&nd));
325 lep_len = strlen(lep);
327 mtx_lock(&mountlist_mtx);
329 TAILQ_FOREACH(mp, &mountlist, mnt_list) {
330 /* determine device name */
331 mntfrom = mp->mnt_stat.f_mntfromname;
333 /* determine mount point */
334 mntto = mp->mnt_stat.f_mntonname;
335 if (strncmp(mntto, lep, lep_len) == 0 &&
336 mntto[lep_len] == '/')
339 /* determine fs type */
340 fstype = mp->mnt_stat.f_fstypename;
341 if (strcmp(fstype, pn->pn_info->pi_name) == 0)
342 mntfrom = fstype = "proc";
343 else if (strcmp(fstype, "procfs") == 0)
346 if (strcmp(fstype, "linsysfs") == 0) {
347 sbuf_printf(sb, "/sys %s sysfs %s", mntto,
348 mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
350 sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
351 mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
353 #define ADD_OPTION(opt, name) \
354 if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name);
355 ADD_OPTION(MNT_SYNCHRONOUS, "sync");
356 ADD_OPTION(MNT_NOEXEC, "noexec");
357 ADD_OPTION(MNT_NOSUID, "nosuid");
358 ADD_OPTION(MNT_UNION, "union");
359 ADD_OPTION(MNT_ASYNC, "async");
360 ADD_OPTION(MNT_SUIDDIR, "suiddir");
361 ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow");
362 ADD_OPTION(MNT_NOATIME, "noatime");
364 /* a real Linux mtab will also show NFS options */
365 sbuf_printf(sb, " 0 0\n");
367 mtx_unlock(&mountlist_mtx);
374 * Filler function for proc/stat
377 linprocfs_dostat(PFS_FILL_ARGS)
380 long cp_time[CPUSTATES];
384 read_cpu_time(cp_time);
385 sbuf_printf(sb, "cpu %ld %ld %ld %ld\n",
386 T2J(cp_time[CP_USER]),
387 T2J(cp_time[CP_NICE]),
388 T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
389 T2J(cp_time[CP_IDLE]));
390 for (i = 0; i <= mp_maxid; ++i) {
394 cp = pcpu->pc_cp_time;
395 sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i,
398 T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/),
414 (long long)boottime.tv_sec);
419 * Filler function for proc/uptime
422 linprocfs_douptime(PFS_FILL_ARGS)
424 long cp_time[CPUSTATES];
428 read_cpu_time(cp_time);
429 sbuf_printf(sb, "%lld.%02ld %ld.%02ld\n",
430 (long long)tv.tv_sec, tv.tv_usec / 10000,
431 T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100);
439 linprocfs_osbuild(struct thread *td, struct sbuf *sb)
445 strncpy(osbuild, version, 256);
447 cp1 = strstr(osbuild, "\n");
448 cp2 = strstr(osbuild, ":");
451 cp1 = strstr(osbuild, "#");
455 sbuf_printf(sb, "%s%s", cp1, cp2 + 1);
458 sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977");
465 linprocfs_osbuilder(struct thread *td, struct sbuf *sb)
471 cp = strstr(version, "\n ");
473 strncpy(builder, cp + 5, 256);
475 cp = strstr(builder, ":");
480 sbuf_cat(sb, builder);
483 sbuf_cat(sb, "des@freebsd.org");
487 * Filler function for proc/version
490 linprocfs_doversion(PFS_FILL_ARGS)
492 char osname[LINUX_MAX_UTSNAME];
493 char osrelease[LINUX_MAX_UTSNAME];
495 linux_get_osname(td, osname);
496 linux_get_osrelease(td, osrelease);
497 sbuf_printf(sb, "%s version %s (", osname, osrelease);
498 linprocfs_osbuilder(td, sb);
499 sbuf_cat(sb, ") (gcc version " __VERSION__ ") ");
500 linprocfs_osbuild(td, sb);
507 * Filler function for proc/loadavg
510 linprocfs_doloadavg(PFS_FILL_ARGS)
514 "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
515 (int)(averunnable.ldavg[0] / averunnable.fscale),
516 (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
517 (int)(averunnable.ldavg[1] / averunnable.fscale),
518 (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
519 (int)(averunnable.ldavg[2] / averunnable.fscale),
520 (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
521 1, /* number of running tasks */
522 nprocs, /* number of tasks */
523 lastpid /* the last pid */
529 * Filler function for proc/pid/stat
532 linprocfs_doprocstat(PFS_FILL_ARGS)
534 struct kinfo_proc kp;
536 static int ratelimit = 0;
539 fill_kinfo_proc(p, &kp);
540 sbuf_printf(sb, "%d", p->p_pid);
541 #define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
542 PS_ADD("comm", "(%s)", p->p_comm);
543 if (kp.ki_stat > sizeof(linux_state)) {
546 if (ratelimit == 0) {
547 printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n",
548 kp.ki_stat, sizeof(linux_state));
552 state = linux_state[kp.ki_stat - 1];
553 PS_ADD("state", "%c", state);
554 PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0);
555 PS_ADD("pgrp", "%d", p->p_pgid);
556 PS_ADD("session", "%d", p->p_session->s_sid);
558 PS_ADD("tty", "%d", 0); /* XXX */
559 PS_ADD("tpgid", "%d", kp.ki_tpgid);
560 PS_ADD("flags", "%u", 0); /* XXX */
561 PS_ADD("minflt", "%lu", kp.ki_rusage.ru_minflt);
562 PS_ADD("cminflt", "%lu", kp.ki_rusage_ch.ru_minflt);
563 PS_ADD("majflt", "%lu", kp.ki_rusage.ru_majflt);
564 PS_ADD("cmajflt", "%lu", kp.ki_rusage_ch.ru_majflt);
565 PS_ADD("utime", "%ld", T2J(tvtohz(&kp.ki_rusage.ru_utime)));
566 PS_ADD("stime", "%ld", T2J(tvtohz(&kp.ki_rusage.ru_stime)));
567 PS_ADD("cutime", "%ld", T2J(tvtohz(&kp.ki_rusage_ch.ru_utime)));
568 PS_ADD("cstime", "%ld", T2J(tvtohz(&kp.ki_rusage_ch.ru_stime)));
569 PS_ADD("priority", "%d", kp.ki_pri.pri_user);
570 PS_ADD("nice", "%d", kp.ki_nice); /* 19 (nicest) to -19 */
571 PS_ADD("0", "%d", 0); /* removed field */
572 PS_ADD("itrealvalue", "%d", 0); /* XXX */
573 /* XXX: starttime is not right, it is the _same_ for _every_ process.
574 It should be the number of jiffies between system boot and process
576 PS_ADD("starttime", "%lu", T2J(tvtohz(&kp.ki_start)));
577 PS_ADD("vsize", "%ju", P2K((uintmax_t)kp.ki_size));
578 PS_ADD("rss", "%ju", (uintmax_t)kp.ki_rssize);
579 PS_ADD("rlim", "%lu", kp.ki_rusage.ru_maxrss);
580 PS_ADD("startcode", "%u", (unsigned)0);
581 PS_ADD("endcode", "%u", 0); /* XXX */
582 PS_ADD("startstack", "%u", 0); /* XXX */
583 PS_ADD("kstkesp", "%u", 0); /* XXX */
584 PS_ADD("kstkeip", "%u", 0); /* XXX */
585 PS_ADD("signal", "%u", 0); /* XXX */
586 PS_ADD("blocked", "%u", 0); /* XXX */
587 PS_ADD("sigignore", "%u", 0); /* XXX */
588 PS_ADD("sigcatch", "%u", 0); /* XXX */
589 PS_ADD("wchan", "%u", 0); /* XXX */
590 PS_ADD("nswap", "%lu", kp.ki_rusage.ru_nswap);
591 PS_ADD("cnswap", "%lu", kp.ki_rusage_ch.ru_nswap);
592 PS_ADD("exitsignal", "%d", 0); /* XXX */
593 PS_ADD("processor", "%u", kp.ki_lastcpu);
594 PS_ADD("rt_priority", "%u", 0); /* XXX */ /* >= 2.5.19 */
595 PS_ADD("policy", "%u", kp.ki_pri.pri_class); /* >= 2.5.19 */
603 * Filler function for proc/pid/statm
606 linprocfs_doprocstatm(PFS_FILL_ARGS)
608 struct kinfo_proc kp;
612 fill_kinfo_proc(p, &kp);
616 * See comments in linprocfs_doprocstatus() regarding the
617 * computation of lsize.
619 /* size resident share trs drs lrs dt */
620 sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size));
621 sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize);
622 sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */
623 sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize);
624 sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize));
625 lsize = B2P(kp.ki_size) - kp.ki_dsize -
626 kp.ki_ssize - kp.ki_tsize - 1;
627 sbuf_printf(sb, "%ju ", (uintmax_t)lsize);
628 sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */
634 * Filler function for proc/pid/status
637 linprocfs_doprocstatus(PFS_FILL_ARGS)
639 struct kinfo_proc kp;
647 td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */
649 if (P_SHOULDSTOP(p)) {
650 state = "T (stopped)";
658 if (p->p_flag & P_WEXIT) {
659 state = "X (exiting)";
662 switch(td2->td_state) {
664 state = "S (sleeping)";
668 state = "R (running)";
671 state = "? (unknown)";
676 state = "Z (zombie)";
679 state = "? (unknown)";
685 fill_kinfo_proc(p, &kp);
686 sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */
687 sbuf_printf(sb, "State:\t%s\n", state);
692 sbuf_printf(sb, "Pid:\t%d\n", p->p_pid);
693 sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ?
694 p->p_pptr->p_pid : 0);
695 sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid,
697 p->p_ucred->cr_svuid,
698 /* FreeBSD doesn't have fsuid */
700 sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid,
702 p->p_ucred->cr_svgid,
703 /* FreeBSD doesn't have fsgid */
705 sbuf_cat(sb, "Groups:\t");
706 for (i = 0; i < p->p_ucred->cr_ngroups; i++)
707 sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]);
714 * While our approximation of VmLib may not be accurate (I
715 * don't know of a simple way to verify it, and I'm not sure
716 * it has much meaning anyway), I believe it's good enough.
718 * The same code that could (I think) accurately compute VmLib
719 * could also compute VmLck, but I don't really care enough to
720 * implement it. Submissions are welcome.
722 sbuf_printf(sb, "VmSize:\t%8ju kB\n", B2K((uintmax_t)kp.ki_size));
723 sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */
724 sbuf_printf(sb, "VmRss:\t%8ju kB\n", P2K((uintmax_t)kp.ki_rssize));
725 sbuf_printf(sb, "VmData:\t%8ju kB\n", P2K((uintmax_t)kp.ki_dsize));
726 sbuf_printf(sb, "VmStk:\t%8ju kB\n", P2K((uintmax_t)kp.ki_ssize));
727 sbuf_printf(sb, "VmExe:\t%8ju kB\n", P2K((uintmax_t)kp.ki_tsize));
728 lsize = B2P(kp.ki_size) - kp.ki_dsize -
729 kp.ki_ssize - kp.ki_tsize - 1;
730 sbuf_printf(sb, "VmLib:\t%8ju kB\n", P2K((uintmax_t)lsize));
735 * We support up to 128 signals, while Linux supports 32,
736 * but we only define 32 (the same 32 as Linux, to boot), so
737 * just show the lower 32 bits of each mask. XXX hack.
739 * NB: on certain platforms (Sparc at least) Linux actually
740 * supports 64 signals, but this code is a long way from
741 * running on anything but i386, so ignore that for now.
744 sbuf_printf(sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]);
746 * I can't seem to find out where the signal mask is in
747 * relation to struct proc, so SigBlk is left unimplemented.
749 sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */
751 mtx_lock(&ps->ps_mtx);
752 sbuf_printf(sb, "SigIgn:\t%08x\n", ps->ps_sigignore.__bits[0]);
753 sbuf_printf(sb, "SigCgt:\t%08x\n", ps->ps_sigcatch.__bits[0]);
754 mtx_unlock(&ps->ps_mtx);
758 * Linux also prints the capability masks, but we don't have
759 * capabilities yet, and when we do get them they're likely to
760 * be meaningless to Linux programs, so we lie. XXX
762 sbuf_printf(sb, "CapInh:\t%016x\n", 0);
763 sbuf_printf(sb, "CapPrm:\t%016x\n", 0);
764 sbuf_printf(sb, "CapEff:\t%016x\n", 0);
771 * Filler function for proc/pid/cwd
774 linprocfs_doproccwd(PFS_FILL_ARGS)
776 char *fullpath = "unknown";
777 char *freepath = NULL;
779 vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath);
780 sbuf_printf(sb, "%s", fullpath);
782 free(freepath, M_TEMP);
787 * Filler function for proc/pid/root
790 linprocfs_doprocroot(PFS_FILL_ARGS)
793 char *fullpath = "unknown";
794 char *freepath = NULL;
796 rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir;
797 vn_fullpath(td, rvp, &fullpath, &freepath);
798 sbuf_printf(sb, "%s", fullpath);
800 free(freepath, M_TEMP);
805 * Filler function for proc/pid/cmdline
808 linprocfs_doproccmdline(PFS_FILL_ARGS)
810 struct ps_strings pstr;
815 * If we are using the ps/cmdline caching, use that. Otherwise
816 * revert back to the old way which only implements full cmdline
817 * for the currept process and just p->p_comm for all other
819 * Note that if the argv is no longer available, we deliberately
820 * don't fall back on p->p_comm or return an error: the authentic
821 * Linux behaviour is to return zero-length in this case.
825 if (p->p_args && p_cansee(td, p) == 0) {
826 sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
828 } else if (p != td->td_proc) {
830 sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm);
833 error = copyin((void *)p->p_sysent->sv_psstrings, &pstr,
837 if (pstr.ps_nargvstr > ARG_MAX)
839 ps_argvstr = malloc(pstr.ps_nargvstr * sizeof(char *),
841 error = copyin((void *)pstr.ps_argvstr, ps_argvstr,
842 pstr.ps_nargvstr * sizeof(char *));
844 free(ps_argvstr, M_TEMP);
847 for (i = 0; i < pstr.ps_nargvstr; i++) {
848 sbuf_copyin(sb, ps_argvstr[i], 0);
849 sbuf_printf(sb, "%c", '\0');
851 free(ps_argvstr, M_TEMP);
858 * Filler function for proc/pid/environ
861 linprocfs_doprocenviron(PFS_FILL_ARGS)
864 sbuf_printf(sb, "doprocenviron\n%c", '\0');
869 * Filler function for proc/pid/maps
872 linprocfs_doprocmaps(PFS_FILL_ARGS)
876 vm_map_entry_t entry, tmp_entry;
877 vm_object_t obj, tobj, lobj;
878 vm_offset_t e_start, e_end;
879 vm_ooffset_t off = 0;
881 unsigned int last_timestamp;
882 char *name = "", *freename = NULL;
884 int ref_count, shadow_count, flags;
891 error = p_candebug(td, p);
896 if (uio->uio_rw != UIO_READ)
900 vm = vmspace_acquire_ref(p);
904 vm_map_lock_read(map);
905 for (entry = map->header.next; entry != &map->header;
906 entry = entry->next) {
909 if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
911 e_prot = entry->protection;
912 e_start = entry->start;
914 obj = entry->object.vm_object;
915 for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) {
916 VM_OBJECT_LOCK(tobj);
918 VM_OBJECT_UNLOCK(lobj);
921 last_timestamp = map->timestamp;
922 vm_map_unlock_read(map);
925 off = IDX_TO_OFF(lobj->size);
926 if (lobj->type == OBJT_VNODE) {
934 VM_OBJECT_UNLOCK(lobj);
936 ref_count = obj->ref_count;
937 shadow_count = obj->shadow_count;
938 VM_OBJECT_UNLOCK(obj);
940 vn_fullpath(td, vp, &name, &freename);
941 locked = VFS_LOCK_GIANT(vp->v_mount);
942 vn_lock(vp, LK_SHARED | LK_RETRY, td);
943 VOP_GETATTR(vp, &vat, td->td_ucred, td);
946 VFS_UNLOCK_GIANT(locked);
956 * start, end, access, offset, major, minor, inode, name.
958 error = sbuf_printf(sb,
959 "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n",
960 (u_long)e_start, (u_long)e_end,
961 (e_prot & VM_PROT_READ)?"r":"-",
962 (e_prot & VM_PROT_WRITE)?"w":"-",
963 (e_prot & VM_PROT_EXECUTE)?"x":"-",
973 free(freename, M_TEMP);
974 vm_map_lock_read(map);
979 if (last_timestamp != map->timestamp) {
981 * Look again for the entry because the map was
982 * modified while it was unlocked. Specifically,
983 * the entry may have been clipped, merged, or deleted.
985 vm_map_lookup_entry(map, e_end - 1, &tmp_entry);
989 vm_map_unlock_read(map);
996 * Filler function for proc/net/dev
999 linprocfs_donetdev(PFS_FILL_ARGS)
1001 char ifname[16]; /* XXX LINUX_IFNAMSIZ */
1004 sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n",
1005 "Inter-", " Receive", " Transmit", " face",
1006 "bytes packets errs drop fifo frame compressed",
1007 "bytes packets errs drop fifo frame compressed");
1010 TAILQ_FOREACH(ifp, &ifnet, if_link) {
1011 linux_ifname(ifp, ifname, sizeof ifname);
1012 sbuf_printf(sb, "%6.6s:", ifname);
1013 sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ",
1014 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
1015 sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
1016 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
1024 * Filler function for proc/sys/kernel/osrelease
1027 linprocfs_doosrelease(PFS_FILL_ARGS)
1029 char osrelease[LINUX_MAX_UTSNAME];
1031 linux_get_osrelease(td, osrelease);
1032 sbuf_printf(sb, "%s\n", osrelease);
1038 * Filler function for proc/sys/kernel/ostype
1041 linprocfs_doostype(PFS_FILL_ARGS)
1043 char osname[LINUX_MAX_UTSNAME];
1045 linux_get_osname(td, osname);
1046 sbuf_printf(sb, "%s\n", osname);
1052 * Filler function for proc/sys/kernel/version
1055 linprocfs_doosbuild(PFS_FILL_ARGS)
1058 linprocfs_osbuild(td, sb);
1064 * Filler function for proc/sys/kernel/msgmni
1067 linprocfs_domsgmni(PFS_FILL_ARGS)
1070 sbuf_printf(sb, "%d\n", msginfo.msgmni);
1075 * Filler function for proc/sys/kernel/pid_max
1078 linprocfs_dopid_max(PFS_FILL_ARGS)
1081 sbuf_printf(sb, "%i\n", PID_MAX);
1086 * Filler function for proc/sys/kernel/sem
1089 linprocfs_dosem(PFS_FILL_ARGS)
1092 sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns,
1093 seminfo.semopm, seminfo.semmni);
1098 * Filler function for proc/scsi/device_info
1101 linprocfs_doscsidevinfo(PFS_FILL_ARGS)
1108 * Filler function for proc/scsi/scsi
1111 linprocfs_doscsiscsi(PFS_FILL_ARGS)
1117 extern struct cdevsw *cdevsw[];
1120 * Filler function for proc/devices
1123 linprocfs_dodevices(PFS_FILL_ARGS)
1126 sbuf_printf(sb, "Character devices:\n");
1128 char_devices = linux_get_char_devices();
1129 sbuf_printf(sb, "%s", char_devices);
1130 linux_free_get_char_devices(char_devices);
1132 sbuf_printf(sb, "\nBlock devices:\n");
1138 * Filler function for proc/cmdline
1141 linprocfs_docmdline(PFS_FILL_ARGS)
1144 sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
1145 sbuf_printf(sb, " ro root=302\n");
1151 * Filler function for proc/modules
1154 linprocfs_domodules(PFS_FILL_ARGS)
1156 struct linker_file *lf;
1158 TAILQ_FOREACH(lf, &linker_files, link) {
1159 sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
1160 (unsigned long)lf->size, lf->refs);
1170 linprocfs_init(PFS_INIT_ARGS)
1172 struct pfs_node *root;
1173 struct pfs_node *dir;
1178 pfs_create_file(root, "cmdline", &linprocfs_docmdline,
1179 NULL, NULL, NULL, PFS_RD);
1180 pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
1181 NULL, NULL, NULL, PFS_RD);
1182 pfs_create_file(root, "devices", &linprocfs_dodevices,
1183 NULL, NULL, NULL, PFS_RD);
1184 pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
1185 NULL, NULL, NULL, PFS_RD);
1186 pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
1187 NULL, NULL, NULL, PFS_RD);
1189 pfs_create_file(root, "modules", &linprocfs_domodules,
1190 NULL, NULL, NULL, PFS_RD);
1192 pfs_create_file(root, "mounts", &linprocfs_domtab,
1193 NULL, NULL, NULL, PFS_RD);
1194 pfs_create_file(root, "mtab", &linprocfs_domtab,
1195 NULL, NULL, NULL, PFS_RD);
1196 pfs_create_link(root, "self", &procfs_docurproc,
1197 NULL, NULL, NULL, 0);
1198 pfs_create_file(root, "stat", &linprocfs_dostat,
1199 NULL, NULL, NULL, PFS_RD);
1200 pfs_create_file(root, "uptime", &linprocfs_douptime,
1201 NULL, NULL, NULL, PFS_RD);
1202 pfs_create_file(root, "version", &linprocfs_doversion,
1203 NULL, NULL, NULL, PFS_RD);
1206 dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
1207 pfs_create_file(dir, "dev", &linprocfs_donetdev,
1208 NULL, NULL, NULL, PFS_RD);
1210 /* /proc/<pid>/... */
1211 dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
1212 pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
1213 NULL, NULL, NULL, PFS_RD);
1214 pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
1215 NULL, NULL, NULL, 0);
1216 pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
1217 NULL, NULL, NULL, PFS_RD);
1218 pfs_create_link(dir, "exe", &procfs_doprocfile,
1219 NULL, &procfs_notsystem, NULL, 0);
1220 pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
1221 NULL, NULL, NULL, PFS_RD);
1222 pfs_create_file(dir, "mem", &procfs_doprocmem,
1223 &procfs_attr, &procfs_candebug, NULL, PFS_RDWR|PFS_RAW);
1224 pfs_create_link(dir, "root", &linprocfs_doprocroot,
1225 NULL, NULL, NULL, 0);
1226 pfs_create_file(dir, "stat", &linprocfs_doprocstat,
1227 NULL, NULL, NULL, PFS_RD);
1228 pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
1229 NULL, NULL, NULL, PFS_RD);
1230 pfs_create_file(dir, "status", &linprocfs_doprocstatus,
1231 NULL, NULL, NULL, PFS_RD);
1233 /* /proc/scsi/... */
1234 dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
1235 pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
1236 NULL, NULL, NULL, PFS_RD);
1237 pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
1238 NULL, NULL, NULL, PFS_RD);
1241 dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
1242 /* /proc/sys/kernel/... */
1243 dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0);
1244 pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
1245 NULL, NULL, NULL, PFS_RD);
1246 pfs_create_file(dir, "ostype", &linprocfs_doostype,
1247 NULL, NULL, NULL, PFS_RD);
1248 pfs_create_file(dir, "version", &linprocfs_doosbuild,
1249 NULL, NULL, NULL, PFS_RD);
1250 pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
1251 NULL, NULL, NULL, PFS_RD);
1252 pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
1253 NULL, NULL, NULL, PFS_RD);
1254 pfs_create_file(dir, "sem", &linprocfs_dosem,
1255 NULL, NULL, NULL, PFS_RD);
1264 linprocfs_uninit(PFS_INIT_ARGS)
1267 /* nothing to do, pseudofs will GC */
1271 PSEUDOFS(linprocfs, 1);
1272 MODULE_DEPEND(linprocfs, linux, 1, 1, 1);
1273 MODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
1274 MODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);
1275 MODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1);