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 "opt_compat.h"
44 #include <sys/cdefs.h>
45 __FBSDID("$FreeBSD$");
47 #include <sys/param.h>
48 #include <sys/queue.h>
49 #include <sys/blist.h>
52 #include <sys/fcntl.h>
53 #include <sys/filedesc.h>
55 #include <sys/kernel.h>
56 #include <sys/linker.h>
58 #include <sys/malloc.h>
59 #include <sys/mount.h>
61 #include <sys/mutex.h>
62 #include <sys/namei.h>
64 #include <sys/resourcevar.h>
68 #include <sys/socket.h>
69 #include <sys/sysctl.h>
70 #include <sys/systm.h>
74 #include <sys/vmmeter.h>
75 #include <sys/vnode.h>
76 #include <sys/vimage.h>
82 #include <vm/vm_map.h>
83 #include <vm/vm_param.h>
84 #include <vm/vm_object.h>
85 #include <vm/swap_pager.h>
87 #include <machine/clock.h>
89 #if defined(__i386__) || defined(__amd64__)
90 #include <machine/cputypes.h>
91 #include <machine/md_var.h>
92 #endif /* __i386__ || __amd64__ */
94 #ifdef COMPAT_LINUX32 /* XXX */
95 #include <machine/../linux32/linux.h>
97 #include <machine/../linux/linux.h>
99 #include <compat/linux/linux_ioctl.h>
100 #include <compat/linux/linux_mib.h>
101 #include <compat/linux/linux_util.h>
102 #include <fs/pseudofs/pseudofs.h>
103 #include <fs/procfs/procfs.h>
106 * Various conversion macros
108 #define T2J(x) (((x) * 100UL) / (stathz ? stathz : hz)) /* ticks to jiffies */
109 #define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */
110 #define B2K(x) ((x) >> 10) /* bytes to kbytes */
111 #define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */
112 #define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */
113 #define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */
116 * @brief Mapping of ki_stat in struct kinfo_proc to the linux state
118 * The linux procfs state field displays one of the characters RSDZTW to
119 * denote running, sleeping in an interruptible wait, waiting in an
120 * uninterruptible disk sleep, a zombie process, process is being traced
121 * or stopped, or process is paging respectively.
123 * Our struct kinfo_proc contains the variable ki_stat which contains a
124 * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK.
126 * This character array is used with ki_stati-1 as an index and tries to
127 * map our states to suitable linux states.
129 static char linux_state[] = "RRSTZDD";
132 * Filler function for proc/meminfo
135 linprocfs_domeminfo(PFS_FILL_ARGS)
137 unsigned long memtotal; /* total memory in bytes */
138 unsigned long memused; /* used memory in bytes */
139 unsigned long memfree; /* free memory in bytes */
140 unsigned long memshared; /* shared memory ??? */
141 unsigned long buffers, cached; /* buffer / cache memory ??? */
142 unsigned long long swaptotal; /* total swap space in bytes */
143 unsigned long long swapused; /* used swap space in bytes */
144 unsigned long long swapfree; /* free swap space in bytes */
148 memtotal = physmem * PAGE_SIZE;
150 * The correct thing here would be:
152 memfree = cnt.v_free_count * PAGE_SIZE;
153 memused = memtotal - memfree;
155 * but it might mislead linux binaries into thinking there
156 * is very little memory left, so we cheat and tell them that
157 * all memory that isn't wired down is free.
159 memused = cnt.v_wire_count * PAGE_SIZE;
160 memfree = memtotal - memused;
161 swap_pager_status(&i, &j);
162 swaptotal = (unsigned long long)i * PAGE_SIZE;
163 swapused = (unsigned long long)j * PAGE_SIZE;
164 swapfree = swaptotal - swapused;
166 mtx_lock(&vm_object_list_mtx);
167 TAILQ_FOREACH(object, &vm_object_list, object_list)
168 if (object->shadow_count > 1)
169 memshared += object->resident_page_count;
170 mtx_unlock(&vm_object_list_mtx);
171 memshared *= PAGE_SIZE;
173 * We'd love to be able to write:
177 * but bufspace is internal to vfs_bio.c and we don't feel
178 * like unstaticizing it just for linprocfs's sake.
181 cached = cnt.v_cache_count * PAGE_SIZE;
184 " total: used: free: shared: buffers: cached:\n"
185 "Mem: %lu %lu %lu %lu %lu %lu\n"
186 "Swap: %llu %llu %llu\n"
187 "MemTotal: %9lu kB\n"
189 "MemShared:%9lu kB\n"
192 "SwapTotal:%9llu kB\n"
193 "SwapFree: %9llu kB\n",
194 memtotal, memused, memfree, memshared, buffers, cached,
195 swaptotal, swapused, swapfree,
196 B2K(memtotal), B2K(memfree),
197 B2K(memshared), B2K(buffers), B2K(cached),
198 B2K(swaptotal), B2K(swapfree));
203 #if defined(__i386__) || defined(__amd64__)
205 * Filler function for proc/cpuinfo (i386 & amd64 version)
208 linprocfs_docpuinfo(PFS_FILL_ARGS)
213 int class, fqmhz, fqkhz;
217 * We default the flags to include all non-conflicting flags,
218 * and the Intel versions of conflicting flags.
220 static char *flags[] = {
221 "fpu", "vme", "de", "pse", "tsc",
222 "msr", "pae", "mce", "cx8", "apic",
223 "sep", "sep", "mtrr", "pge", "mca",
224 "cmov", "pat", "pse36", "pn", "b19",
225 "b20", "b21", "mmxext", "mmx", "fxsr",
226 "xmm", "sse2", "b27", "b28", "b29",
250 #else /* __amd64__ */
257 hw_model[0] = CTL_HW;
258 hw_model[1] = HW_MODEL;
260 size = sizeof(model);
261 if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0)
262 strcpy(model, "unknown");
263 for (i = 0; i < mp_ncpus; ++i) {
266 "vendor_id\t: %.20s\n"
271 i, cpu_vendor, class, cpu, model, cpu_id & 0xf);
272 /* XXX per-cpu vendor / class / model / id? */
278 if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) {
280 } else if (!strcmp(cpu_vendor, "CyrixInstead")) {
284 for (i = 0; i < 32; i++)
285 if (cpu_feature & (1 << i))
286 sbuf_printf(sb, " %s", flags[i]);
289 fqmhz = (tsc_freq + 4999) / 1000000;
290 fqkhz = ((tsc_freq + 4999) / 10000) % 100;
292 "cpu MHz\t\t: %d.%02d\n"
293 "bogomips\t: %d.%02d\n",
294 fqmhz, fqkhz, fqmhz, fqkhz);
299 #endif /* __i386__ || __amd64__ */
302 * Filler function for proc/mtab
304 * This file doesn't exist in Linux' procfs, but is included here so
305 * users can symlink /compat/linux/etc/mtab to /proc/mtab
308 linprocfs_domtab(PFS_FILL_ARGS)
313 char *dlep, *flep, *mntto, *mntfrom, *fstype;
317 /* resolve symlinks etc. in the emulation tree prefix */
318 NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td);
321 VFS_UNLOCK_GIANT(NDHASGIANT(&nd));
322 if (error != 0 || vn_fullpath(td, nd.ni_vp, &dlep, &flep) != 0)
323 lep = linux_emul_path;
326 lep_len = strlen(lep);
328 mtx_lock(&mountlist_mtx);
330 TAILQ_FOREACH(mp, &mountlist, mnt_list) {
331 /* determine device name */
332 mntfrom = mp->mnt_stat.f_mntfromname;
334 /* determine mount point */
335 mntto = mp->mnt_stat.f_mntonname;
336 if (strncmp(mntto, lep, lep_len) == 0 &&
337 mntto[lep_len] == '/')
340 /* determine fs type */
341 fstype = mp->mnt_stat.f_fstypename;
342 if (strcmp(fstype, pn->pn_info->pi_name) == 0)
343 mntfrom = fstype = "proc";
344 else if (strcmp(fstype, "procfs") == 0)
347 if (strcmp(fstype, "linsysfs") == 0) {
348 sbuf_printf(sb, "/sys %s sysfs %s", mntto,
349 mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
351 sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
352 mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
354 #define ADD_OPTION(opt, name) \
355 if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name);
356 ADD_OPTION(MNT_SYNCHRONOUS, "sync");
357 ADD_OPTION(MNT_NOEXEC, "noexec");
358 ADD_OPTION(MNT_NOSUID, "nosuid");
359 ADD_OPTION(MNT_UNION, "union");
360 ADD_OPTION(MNT_ASYNC, "async");
361 ADD_OPTION(MNT_SUIDDIR, "suiddir");
362 ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow");
363 ADD_OPTION(MNT_NOATIME, "noatime");
365 /* a real Linux mtab will also show NFS options */
366 sbuf_printf(sb, " 0 0\n");
368 mtx_unlock(&mountlist_mtx);
375 * Filler function for proc/stat
378 linprocfs_dostat(PFS_FILL_ARGS)
381 long cp_time[CPUSTATES];
385 read_cpu_time(cp_time);
386 sbuf_printf(sb, "cpu %ld %ld %ld %ld\n",
387 T2J(cp_time[CP_USER]),
388 T2J(cp_time[CP_NICE]),
389 T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
390 T2J(cp_time[CP_IDLE]));
391 for (i = 0; i <= mp_maxid; ++i) {
395 cp = pcpu->pc_cp_time;
396 sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i,
399 T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/),
415 (long long)boottime.tv_sec);
420 * Filler function for proc/uptime
423 linprocfs_douptime(PFS_FILL_ARGS)
425 long cp_time[CPUSTATES];
429 read_cpu_time(cp_time);
430 sbuf_printf(sb, "%lld.%02ld %ld.%02ld\n",
431 (long long)tv.tv_sec, tv.tv_usec / 10000,
432 T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100);
440 linprocfs_osbuild(struct thread *td, struct sbuf *sb)
446 strncpy(osbuild, version, 256);
448 cp1 = strstr(osbuild, "\n");
449 cp2 = strstr(osbuild, ":");
452 cp1 = strstr(osbuild, "#");
456 sbuf_printf(sb, "%s%s", cp1, cp2 + 1);
459 sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977");
466 linprocfs_osbuilder(struct thread *td, struct sbuf *sb)
472 cp = strstr(version, "\n ");
474 strncpy(builder, cp + 5, 256);
476 cp = strstr(builder, ":");
481 sbuf_cat(sb, builder);
484 sbuf_cat(sb, "des@freebsd.org");
488 * Filler function for proc/version
491 linprocfs_doversion(PFS_FILL_ARGS)
493 char osname[LINUX_MAX_UTSNAME];
494 char osrelease[LINUX_MAX_UTSNAME];
496 linux_get_osname(td, osname);
497 linux_get_osrelease(td, osrelease);
498 sbuf_printf(sb, "%s version %s (", osname, osrelease);
499 linprocfs_osbuilder(td, sb);
500 sbuf_cat(sb, ") (gcc version " __VERSION__ ") ");
501 linprocfs_osbuild(td, sb);
508 * Filler function for proc/loadavg
511 linprocfs_doloadavg(PFS_FILL_ARGS)
515 "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
516 (int)(averunnable.ldavg[0] / averunnable.fscale),
517 (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
518 (int)(averunnable.ldavg[1] / averunnable.fscale),
519 (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
520 (int)(averunnable.ldavg[2] / averunnable.fscale),
521 (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
522 1, /* number of running tasks */
523 nprocs, /* number of tasks */
524 lastpid /* the last pid */
530 * Filler function for proc/pid/stat
533 linprocfs_doprocstat(PFS_FILL_ARGS)
535 struct kinfo_proc kp;
537 static int ratelimit = 0;
540 fill_kinfo_proc(p, &kp);
541 sbuf_printf(sb, "%d", p->p_pid);
542 #define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
543 PS_ADD("comm", "(%s)", p->p_comm);
544 if (kp.ki_stat > sizeof(linux_state)) {
547 if (ratelimit == 0) {
548 printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n",
549 kp.ki_stat, sizeof(linux_state));
553 state = linux_state[kp.ki_stat - 1];
554 PS_ADD("state", "%c", state);
555 PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0);
556 PS_ADD("pgrp", "%d", p->p_pgid);
557 PS_ADD("session", "%d", p->p_session->s_sid);
559 PS_ADD("tty", "%d", 0); /* XXX */
560 PS_ADD("tpgid", "%d", kp.ki_tpgid);
561 PS_ADD("flags", "%u", 0); /* XXX */
562 PS_ADD("minflt", "%lu", kp.ki_rusage.ru_minflt);
563 PS_ADD("cminflt", "%lu", kp.ki_rusage_ch.ru_minflt);
564 PS_ADD("majflt", "%lu", kp.ki_rusage.ru_majflt);
565 PS_ADD("cmajflt", "%lu", kp.ki_rusage_ch.ru_majflt);
566 PS_ADD("utime", "%ld", T2J(tvtohz(&kp.ki_rusage.ru_utime)));
567 PS_ADD("stime", "%ld", T2J(tvtohz(&kp.ki_rusage.ru_stime)));
568 PS_ADD("cutime", "%ld", T2J(tvtohz(&kp.ki_rusage_ch.ru_utime)));
569 PS_ADD("cstime", "%ld", T2J(tvtohz(&kp.ki_rusage_ch.ru_stime)));
570 PS_ADD("priority", "%d", kp.ki_pri.pri_user);
571 PS_ADD("nice", "%d", kp.ki_nice); /* 19 (nicest) to -19 */
572 PS_ADD("0", "%d", 0); /* removed field */
573 PS_ADD("itrealvalue", "%d", 0); /* XXX */
574 /* XXX: starttime is not right, it is the _same_ for _every_ process.
575 It should be the number of jiffies between system boot and process
577 PS_ADD("starttime", "%lu", T2J(tvtohz(&kp.ki_start)));
578 PS_ADD("vsize", "%ju", P2K((uintmax_t)kp.ki_size));
579 PS_ADD("rss", "%ju", (uintmax_t)kp.ki_rssize);
580 PS_ADD("rlim", "%lu", kp.ki_rusage.ru_maxrss);
581 PS_ADD("startcode", "%u", (unsigned)0);
582 PS_ADD("endcode", "%u", 0); /* XXX */
583 PS_ADD("startstack", "%u", 0); /* XXX */
584 PS_ADD("kstkesp", "%u", 0); /* XXX */
585 PS_ADD("kstkeip", "%u", 0); /* XXX */
586 PS_ADD("signal", "%u", 0); /* XXX */
587 PS_ADD("blocked", "%u", 0); /* XXX */
588 PS_ADD("sigignore", "%u", 0); /* XXX */
589 PS_ADD("sigcatch", "%u", 0); /* XXX */
590 PS_ADD("wchan", "%u", 0); /* XXX */
591 PS_ADD("nswap", "%lu", kp.ki_rusage.ru_nswap);
592 PS_ADD("cnswap", "%lu", kp.ki_rusage_ch.ru_nswap);
593 PS_ADD("exitsignal", "%d", 0); /* XXX */
594 PS_ADD("processor", "%u", kp.ki_lastcpu);
595 PS_ADD("rt_priority", "%u", 0); /* XXX */ /* >= 2.5.19 */
596 PS_ADD("policy", "%u", kp.ki_pri.pri_class); /* >= 2.5.19 */
604 * Filler function for proc/pid/statm
607 linprocfs_doprocstatm(PFS_FILL_ARGS)
609 struct kinfo_proc kp;
613 fill_kinfo_proc(p, &kp);
617 * See comments in linprocfs_doprocstatus() regarding the
618 * computation of lsize.
620 /* size resident share trs drs lrs dt */
621 sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size));
622 sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize);
623 sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */
624 sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize);
625 sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize));
626 lsize = B2P(kp.ki_size) - kp.ki_dsize -
627 kp.ki_ssize - kp.ki_tsize - 1;
628 sbuf_printf(sb, "%ju ", (uintmax_t)lsize);
629 sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */
635 * Filler function for proc/pid/status
638 linprocfs_doprocstatus(PFS_FILL_ARGS)
640 struct kinfo_proc kp;
648 td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */
650 if (P_SHOULDSTOP(p)) {
651 state = "T (stopped)";
659 if (p->p_flag & P_WEXIT) {
660 state = "X (exiting)";
663 switch(td2->td_state) {
665 state = "S (sleeping)";
669 state = "R (running)";
672 state = "? (unknown)";
677 state = "Z (zombie)";
680 state = "? (unknown)";
686 fill_kinfo_proc(p, &kp);
687 sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */
688 sbuf_printf(sb, "State:\t%s\n", state);
693 sbuf_printf(sb, "Pid:\t%d\n", p->p_pid);
694 sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ?
695 p->p_pptr->p_pid : 0);
696 sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid,
698 p->p_ucred->cr_svuid,
699 /* FreeBSD doesn't have fsuid */
701 sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid,
703 p->p_ucred->cr_svgid,
704 /* FreeBSD doesn't have fsgid */
706 sbuf_cat(sb, "Groups:\t");
707 for (i = 0; i < p->p_ucred->cr_ngroups; i++)
708 sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]);
715 * While our approximation of VmLib may not be accurate (I
716 * don't know of a simple way to verify it, and I'm not sure
717 * it has much meaning anyway), I believe it's good enough.
719 * The same code that could (I think) accurately compute VmLib
720 * could also compute VmLck, but I don't really care enough to
721 * implement it. Submissions are welcome.
723 sbuf_printf(sb, "VmSize:\t%8ju kB\n", B2K((uintmax_t)kp.ki_size));
724 sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */
725 sbuf_printf(sb, "VmRss:\t%8ju kB\n", P2K((uintmax_t)kp.ki_rssize));
726 sbuf_printf(sb, "VmData:\t%8ju kB\n", P2K((uintmax_t)kp.ki_dsize));
727 sbuf_printf(sb, "VmStk:\t%8ju kB\n", P2K((uintmax_t)kp.ki_ssize));
728 sbuf_printf(sb, "VmExe:\t%8ju kB\n", P2K((uintmax_t)kp.ki_tsize));
729 lsize = B2P(kp.ki_size) - kp.ki_dsize -
730 kp.ki_ssize - kp.ki_tsize - 1;
731 sbuf_printf(sb, "VmLib:\t%8ju kB\n", P2K((uintmax_t)lsize));
736 * We support up to 128 signals, while Linux supports 32,
737 * but we only define 32 (the same 32 as Linux, to boot), so
738 * just show the lower 32 bits of each mask. XXX hack.
740 * NB: on certain platforms (Sparc at least) Linux actually
741 * supports 64 signals, but this code is a long way from
742 * running on anything but i386, so ignore that for now.
745 sbuf_printf(sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]);
747 * I can't seem to find out where the signal mask is in
748 * relation to struct proc, so SigBlk is left unimplemented.
750 sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */
752 mtx_lock(&ps->ps_mtx);
753 sbuf_printf(sb, "SigIgn:\t%08x\n", ps->ps_sigignore.__bits[0]);
754 sbuf_printf(sb, "SigCgt:\t%08x\n", ps->ps_sigcatch.__bits[0]);
755 mtx_unlock(&ps->ps_mtx);
759 * Linux also prints the capability masks, but we don't have
760 * capabilities yet, and when we do get them they're likely to
761 * be meaningless to Linux programs, so we lie. XXX
763 sbuf_printf(sb, "CapInh:\t%016x\n", 0);
764 sbuf_printf(sb, "CapPrm:\t%016x\n", 0);
765 sbuf_printf(sb, "CapEff:\t%016x\n", 0);
772 * Filler function for proc/pid/cwd
775 linprocfs_doproccwd(PFS_FILL_ARGS)
777 char *fullpath = "unknown";
778 char *freepath = NULL;
780 vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath);
781 sbuf_printf(sb, "%s", fullpath);
783 free(freepath, M_TEMP);
788 * Filler function for proc/pid/root
791 linprocfs_doprocroot(PFS_FILL_ARGS)
794 char *fullpath = "unknown";
795 char *freepath = NULL;
797 rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir;
798 vn_fullpath(td, rvp, &fullpath, &freepath);
799 sbuf_printf(sb, "%s", fullpath);
801 free(freepath, M_TEMP);
806 * Filler function for proc/pid/cmdline
809 linprocfs_doproccmdline(PFS_FILL_ARGS)
811 struct ps_strings pstr;
816 * If we are using the ps/cmdline caching, use that. Otherwise
817 * revert back to the old way which only implements full cmdline
818 * for the currept process and just p->p_comm for all other
820 * Note that if the argv is no longer available, we deliberately
821 * don't fall back on p->p_comm or return an error: the authentic
822 * Linux behaviour is to return zero-length in this case.
826 if (p->p_args && p_cansee(td, p) == 0) {
827 sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
829 } else if (p != td->td_proc) {
831 sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm);
834 error = copyin((void *)p->p_sysent->sv_psstrings, &pstr,
838 if (pstr.ps_nargvstr > ARG_MAX)
840 ps_argvstr = malloc(pstr.ps_nargvstr * sizeof(char *),
842 error = copyin((void *)pstr.ps_argvstr, ps_argvstr,
843 pstr.ps_nargvstr * sizeof(char *));
845 free(ps_argvstr, M_TEMP);
848 for (i = 0; i < pstr.ps_nargvstr; i++) {
849 sbuf_copyin(sb, ps_argvstr[i], 0);
850 sbuf_printf(sb, "%c", '\0');
852 free(ps_argvstr, M_TEMP);
859 * Filler function for proc/pid/environ
862 linprocfs_doprocenviron(PFS_FILL_ARGS)
865 sbuf_printf(sb, "doprocenviron\n%c", '\0');
870 * Filler function for proc/pid/maps
873 linprocfs_doprocmaps(PFS_FILL_ARGS)
875 vm_map_t map = &p->p_vmspace->vm_map;
876 vm_map_entry_t entry;
877 vm_object_t obj, tobj, lobj;
878 vm_offset_t saved_end;
879 vm_ooffset_t off = 0;
880 char *name = "", *freename = NULL;
882 int ref_count, shadow_count, flags;
889 error = p_candebug(td, p);
894 if (uio->uio_rw != UIO_READ)
898 vm_map_lock_read(map);
899 for (entry = map->header.next; entry != &map->header;
900 entry = entry->next) {
903 if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
905 saved_end = entry->end;
906 obj = entry->object.vm_object;
907 for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) {
908 VM_OBJECT_LOCK(tobj);
910 VM_OBJECT_UNLOCK(lobj);
915 off = IDX_TO_OFF(lobj->size);
916 if (lobj->type == OBJT_VNODE) {
924 VM_OBJECT_UNLOCK(lobj);
926 ref_count = obj->ref_count;
927 shadow_count = obj->shadow_count;
928 VM_OBJECT_UNLOCK(obj);
930 vn_fullpath(td, vp, &name, &freename);
931 locked = VFS_LOCK_GIANT(vp->v_mount);
932 vn_lock(vp, LK_SHARED | LK_RETRY);
933 VOP_GETATTR(vp, &vat, td->td_ucred);
936 VFS_UNLOCK_GIANT(locked);
946 * start, end, access, offset, major, minor, inode, name.
948 error = sbuf_printf(sb,
949 "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n",
950 (u_long)entry->start, (u_long)entry->end,
951 (entry->protection & VM_PROT_READ)?"r":"-",
952 (entry->protection & VM_PROT_WRITE)?"w":"-",
953 (entry->protection & VM_PROT_EXECUTE)?"x":"-",
963 free(freename, M_TEMP);
969 vm_map_unlock_read(map);
975 * Filler function for proc/net/dev
978 linprocfs_donetdev(PFS_FILL_ARGS)
980 INIT_VNET_NET(TD_TO_VNET(curthread));
981 char ifname[16]; /* XXX LINUX_IFNAMSIZ */
984 sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n",
985 "Inter-", " Receive", " Transmit", " face",
986 "bytes packets errs drop fifo frame compressed",
987 "bytes packets errs drop fifo frame compressed");
990 TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
991 linux_ifname(ifp, ifname, sizeof ifname);
992 sbuf_printf(sb, "%6.6s:", ifname);
993 sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ",
994 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
995 sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
996 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
1004 * Filler function for proc/sys/kernel/osrelease
1007 linprocfs_doosrelease(PFS_FILL_ARGS)
1009 char osrelease[LINUX_MAX_UTSNAME];
1011 linux_get_osrelease(td, osrelease);
1012 sbuf_printf(sb, "%s\n", osrelease);
1018 * Filler function for proc/sys/kernel/ostype
1021 linprocfs_doostype(PFS_FILL_ARGS)
1023 char osname[LINUX_MAX_UTSNAME];
1025 linux_get_osname(td, osname);
1026 sbuf_printf(sb, "%s\n", osname);
1032 * Filler function for proc/sys/kernel/version
1035 linprocfs_doosbuild(PFS_FILL_ARGS)
1038 linprocfs_osbuild(td, sb);
1044 * Filler function for proc/sys/kernel/msgmni
1047 linprocfs_domsgmni(PFS_FILL_ARGS)
1050 sbuf_printf(sb, "%d\n", msginfo.msgmni);
1055 * Filler function for proc/sys/kernel/pid_max
1058 linprocfs_dopid_max(PFS_FILL_ARGS)
1061 sbuf_printf(sb, "%i\n", PID_MAX);
1066 * Filler function for proc/sys/kernel/sem
1069 linprocfs_dosem(PFS_FILL_ARGS)
1072 sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns,
1073 seminfo.semopm, seminfo.semmni);
1078 * Filler function for proc/scsi/device_info
1081 linprocfs_doscsidevinfo(PFS_FILL_ARGS)
1088 * Filler function for proc/scsi/scsi
1091 linprocfs_doscsiscsi(PFS_FILL_ARGS)
1097 extern struct cdevsw *cdevsw[];
1100 * Filler function for proc/devices
1103 linprocfs_dodevices(PFS_FILL_ARGS)
1106 sbuf_printf(sb, "Character devices:\n");
1108 char_devices = linux_get_char_devices();
1109 sbuf_printf(sb, "%s", char_devices);
1110 linux_free_get_char_devices(char_devices);
1112 sbuf_printf(sb, "\nBlock devices:\n");
1118 * Filler function for proc/cmdline
1121 linprocfs_docmdline(PFS_FILL_ARGS)
1124 sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
1125 sbuf_printf(sb, " ro root=302\n");
1131 * Filler function for proc/modules
1134 linprocfs_domodules(PFS_FILL_ARGS)
1136 struct linker_file *lf;
1138 TAILQ_FOREACH(lf, &linker_files, link) {
1139 sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
1140 (unsigned long)lf->size, lf->refs);
1150 linprocfs_init(PFS_INIT_ARGS)
1152 struct pfs_node *root;
1153 struct pfs_node *dir;
1158 pfs_create_file(root, "cmdline", &linprocfs_docmdline,
1159 NULL, NULL, NULL, PFS_RD);
1160 pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
1161 NULL, NULL, NULL, PFS_RD);
1162 pfs_create_file(root, "devices", &linprocfs_dodevices,
1163 NULL, NULL, NULL, PFS_RD);
1164 pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
1165 NULL, NULL, NULL, PFS_RD);
1166 pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
1167 NULL, NULL, NULL, PFS_RD);
1169 pfs_create_file(root, "modules", &linprocfs_domodules,
1170 NULL, NULL, NULL, PFS_RD);
1172 pfs_create_file(root, "mounts", &linprocfs_domtab,
1173 NULL, NULL, NULL, PFS_RD);
1174 pfs_create_file(root, "mtab", &linprocfs_domtab,
1175 NULL, NULL, NULL, PFS_RD);
1176 pfs_create_link(root, "self", &procfs_docurproc,
1177 NULL, NULL, NULL, 0);
1178 pfs_create_file(root, "stat", &linprocfs_dostat,
1179 NULL, NULL, NULL, PFS_RD);
1180 pfs_create_file(root, "uptime", &linprocfs_douptime,
1181 NULL, NULL, NULL, PFS_RD);
1182 pfs_create_file(root, "version", &linprocfs_doversion,
1183 NULL, NULL, NULL, PFS_RD);
1186 dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
1187 pfs_create_file(dir, "dev", &linprocfs_donetdev,
1188 NULL, NULL, NULL, PFS_RD);
1190 /* /proc/<pid>/... */
1191 dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
1192 pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
1193 NULL, NULL, NULL, PFS_RD);
1194 pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
1195 NULL, NULL, NULL, 0);
1196 pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
1197 NULL, NULL, NULL, PFS_RD);
1198 pfs_create_link(dir, "exe", &procfs_doprocfile,
1199 NULL, &procfs_notsystem, NULL, 0);
1200 pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
1201 NULL, NULL, NULL, PFS_RD);
1202 pfs_create_file(dir, "mem", &procfs_doprocmem,
1203 &procfs_attr, &procfs_candebug, NULL, PFS_RDWR|PFS_RAW);
1204 pfs_create_link(dir, "root", &linprocfs_doprocroot,
1205 NULL, NULL, NULL, 0);
1206 pfs_create_file(dir, "stat", &linprocfs_doprocstat,
1207 NULL, NULL, NULL, PFS_RD);
1208 pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
1209 NULL, NULL, NULL, PFS_RD);
1210 pfs_create_file(dir, "status", &linprocfs_doprocstatus,
1211 NULL, NULL, NULL, PFS_RD);
1213 /* /proc/scsi/... */
1214 dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
1215 pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
1216 NULL, NULL, NULL, PFS_RD);
1217 pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
1218 NULL, NULL, NULL, PFS_RD);
1221 dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
1222 /* /proc/sys/kernel/... */
1223 dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0);
1224 pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
1225 NULL, NULL, NULL, PFS_RD);
1226 pfs_create_file(dir, "ostype", &linprocfs_doostype,
1227 NULL, NULL, NULL, PFS_RD);
1228 pfs_create_file(dir, "version", &linprocfs_doosbuild,
1229 NULL, NULL, NULL, PFS_RD);
1230 pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
1231 NULL, NULL, NULL, PFS_RD);
1232 pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
1233 NULL, NULL, NULL, PFS_RD);
1234 pfs_create_file(dir, "sem", &linprocfs_dosem,
1235 NULL, NULL, NULL, PFS_RD);
1244 linprocfs_uninit(PFS_INIT_ARGS)
1247 /* nothing to do, pseudofs will GC */
1251 PSEUDOFS(linprocfs, 1);
1252 MODULE_DEPEND(linprocfs, linux, 1, 1, 1);
1253 MODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
1254 MODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);
1255 MODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1);