linprocfs.c revision 159544
1139743Simp/*- 265577Sdes * Copyright (c) 2000 Dag-Erling Co�dan Sm�rgrav 365577Sdes * Copyright (c) 1999 Pierre Beyssac 459412Smsmith * Copyright (c) 1993 Jan-Simon Pendry 559412Smsmith * Copyright (c) 1993 659412Smsmith * The Regents of the University of California. All rights reserved. 759412Smsmith * 859412Smsmith * This code is derived from software contributed to Berkeley by 959412Smsmith * Jan-Simon Pendry. 1059412Smsmith * 1159412Smsmith * Redistribution and use in source and binary forms, with or without 1259412Smsmith * modification, are permitted provided that the following conditions 1359412Smsmith * are met: 1459412Smsmith * 1. Redistributions of source code must retain the above copyright 1559412Smsmith * notice, this list of conditions and the following disclaimer. 1659412Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1759412Smsmith * notice, this list of conditions and the following disclaimer in the 1859412Smsmith * documentation and/or other materials provided with the distribution. 1959412Smsmith * 3. All advertising materials mentioning features or use of this software 2059412Smsmith * must display the following acknowledgement: 2159412Smsmith * This product includes software developed by the University of 2259412Smsmith * California, Berkeley and its contributors. 2359412Smsmith * 4. Neither the name of the University nor the names of its contributors 2459412Smsmith * may be used to endorse or promote products derived from this software 2559412Smsmith * without specific prior written permission. 2659412Smsmith * 2759412Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2859412Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2959412Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3059412Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3159412Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3259412Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3359412Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3459412Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3559412Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3659412Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3759412Smsmith * SUCH DAMAGE. 3859412Smsmith * 3959412Smsmith * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94 4059412Smsmith */ 4159412Smsmith 42116173Sobrien#include <sys/cdefs.h> 43116173Sobrien__FBSDID("$FreeBSD: head/sys/compat/linprocfs/linprocfs.c 159544 2006-06-12 18:14:49Z des $"); 44116173Sobrien 4559412Smsmith#include <sys/param.h> 4683926Sdes#include <sys/queue.h> 4776166Smarkm#include <sys/blist.h> 4874135Sjlemon#include <sys/conf.h> 4983926Sdes#include <sys/exec.h> 50119911Sdes#include <sys/filedesc.h> 5176166Smarkm#include <sys/jail.h> 5265633Sdes#include <sys/kernel.h> 5383926Sdes#include <sys/linker.h> 5476166Smarkm#include <sys/lock.h> 5574135Sjlemon#include <sys/malloc.h> 5678025Sdes#include <sys/mount.h> 5776827Salfred#include <sys/mutex.h> 5885289Sdes#include <sys/namei.h> 5965633Sdes#include <sys/proc.h> 6065633Sdes#include <sys/resourcevar.h> 6169995Sdes#include <sys/sbuf.h> 62123246Sdes#include <sys/smp.h> 6383926Sdes#include <sys/socket.h> 6476839Sjlemon#include <sys/sysctl.h> 6583926Sdes#include <sys/systm.h> 6665633Sdes#include <sys/tty.h> 6783926Sdes#include <sys/user.h> 6883926Sdes#include <sys/vmmeter.h> 6959412Smsmith#include <sys/vnode.h> 7059412Smsmith 7183926Sdes#include <net/if.h> 7283926Sdes 7359412Smsmith#include <vm/vm.h> 7459412Smsmith#include <vm/pmap.h> 7567588Sdes#include <vm/vm_map.h> 7659412Smsmith#include <vm/vm_param.h> 7760860Sdes#include <vm/vm_object.h> 7859412Smsmith#include <vm/swap_pager.h> 7969799Sdes 8067589Sdes#include <machine/clock.h> 8178113Sdes 82133822Stjr#if defined(__i386__) || defined(__amd64__) 8367589Sdes#include <machine/cputypes.h> 8459412Smsmith#include <machine/md_var.h> 85133822Stjr#endif /* __i386__ || __amd64__ */ 8659412Smsmith 87133822Stjr#include "opt_compat.h" 88140214Sobrien#ifdef COMPAT_LINUX32 /* XXX */ 89140214Sobrien#include <machine/../linux32/linux.h> 90140214Sobrien#else 9187275Srwatson#include <machine/../linux/linux.h> 92133822Stjr#endif 9385129Sdes#include <compat/linux/linux_ioctl.h> 9469995Sdes#include <compat/linux/linux_mib.h> 9585289Sdes#include <compat/linux/linux_util.h> 9678025Sdes#include <fs/pseudofs/pseudofs.h> 9784248Sdes#include <fs/procfs/procfs.h> 9859412Smsmith 9967588Sdes/* 10067588Sdes * Various conversion macros 10167588Sdes */ 10276405Sdes#define T2J(x) (((x) * 100UL) / (stathz ? stathz : hz)) /* ticks to jiffies */ 10367588Sdes#define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */ 10467588Sdes#define B2K(x) ((x) >> 10) /* bytes to kbytes */ 10569799Sdes#define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */ 10667588Sdes#define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */ 10767588Sdes#define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */ 10874135Sjlemon 10978113Sdes/* 11078113Sdes * Filler function for proc/meminfo 11178113Sdes */ 11278025Sdesstatic int 11378025Sdeslinprocfs_domeminfo(PFS_FILL_ARGS) 11459412Smsmith{ 11559412Smsmith unsigned long memtotal; /* total memory in bytes */ 11659412Smsmith unsigned long memused; /* used memory in bytes */ 11759412Smsmith unsigned long memfree; /* free memory in bytes */ 11859412Smsmith unsigned long memshared; /* shared memory ??? */ 11959412Smsmith unsigned long buffers, cached; /* buffer / cache memory ??? */ 120113574Sjhb unsigned long long swaptotal; /* total swap space in bytes */ 121113574Sjhb unsigned long long swapused; /* used swap space in bytes */ 122113574Sjhb unsigned long long swapfree; /* free swap space in bytes */ 12360860Sdes vm_object_t object; 124117723Sphk int i, j; 12559412Smsmith 12659412Smsmith memtotal = physmem * PAGE_SIZE; 12759412Smsmith /* 12859412Smsmith * The correct thing here would be: 12959412Smsmith * 13059412Smsmith memfree = cnt.v_free_count * PAGE_SIZE; 13159412Smsmith memused = memtotal - memfree; 13259412Smsmith * 13359412Smsmith * but it might mislead linux binaries into thinking there 13459412Smsmith * is very little memory left, so we cheat and tell them that 13559412Smsmith * all memory that isn't wired down is free. 13659412Smsmith */ 13759412Smsmith memused = cnt.v_wire_count * PAGE_SIZE; 13859412Smsmith memfree = memtotal - memused; 139117723Sphk swap_pager_status(&i, &j); 140153310Smlaier swaptotal = (unsigned long long)i * PAGE_SIZE; 141153310Smlaier swapused = (unsigned long long)j * PAGE_SIZE; 142117723Sphk swapfree = swaptotal - swapused; 14360860Sdes memshared = 0; 144124082Salc mtx_lock(&vm_object_list_mtx); 14571471Sjhb TAILQ_FOREACH(object, &vm_object_list, object_list) 14660860Sdes if (object->shadow_count > 1) 14760860Sdes memshared += object->resident_page_count; 148124082Salc mtx_unlock(&vm_object_list_mtx); 14960860Sdes memshared *= PAGE_SIZE; 15059412Smsmith /* 15159412Smsmith * We'd love to be able to write: 15259412Smsmith * 15359412Smsmith buffers = bufspace; 15459412Smsmith * 15559412Smsmith * but bufspace is internal to vfs_bio.c and we don't feel 15659412Smsmith * like unstaticizing it just for linprocfs's sake. 15759412Smsmith */ 15859412Smsmith buffers = 0; 15959412Smsmith cached = cnt.v_cache_count * PAGE_SIZE; 16059412Smsmith 16178025Sdes sbuf_printf(sb, 16278031Sdes " total: used: free: shared: buffers: cached:\n" 16369799Sdes "Mem: %lu %lu %lu %lu %lu %lu\n" 16476839Sjlemon "Swap: %llu %llu %llu\n" 16569799Sdes "MemTotal: %9lu kB\n" 16669799Sdes "MemFree: %9lu kB\n" 16769799Sdes "MemShared:%9lu kB\n" 16869799Sdes "Buffers: %9lu kB\n" 16969799Sdes "Cached: %9lu kB\n" 17076839Sjlemon "SwapTotal:%9llu kB\n" 17176839Sjlemon "SwapFree: %9llu kB\n", 17269799Sdes memtotal, memused, memfree, memshared, buffers, cached, 17369799Sdes swaptotal, swapused, swapfree, 17469799Sdes B2K(memtotal), B2K(memfree), 17569799Sdes B2K(memshared), B2K(buffers), B2K(cached), 17669799Sdes B2K(swaptotal), B2K(swapfree)); 17759412Smsmith 17878025Sdes return (0); 17959412Smsmith} 18059412Smsmith 181133822Stjr#if defined(__i386__) || defined(__amd64__) 18278113Sdes/* 183133822Stjr * Filler function for proc/cpuinfo (i386 & amd64 version) 18478113Sdes */ 18578113Sdesstatic int 18678113Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS) 18778113Sdes{ 188159544Sdes int hw_model[2]; 189159544Sdes char model[128]; 190159544Sdes size_t size; 191123246Sdes int class, fqmhz, fqkhz; 192118421Sdes int i; 19359412Smsmith 19469799Sdes /* 19578031Sdes * We default the flags to include all non-conflicting flags, 19678031Sdes * and the Intel versions of conflicting flags. 19769799Sdes */ 19878031Sdes static char *flags[] = { 19978031Sdes "fpu", "vme", "de", "pse", "tsc", 20078031Sdes "msr", "pae", "mce", "cx8", "apic", 20178031Sdes "sep", "sep", "mtrr", "pge", "mca", 20278031Sdes "cmov", "pat", "pse36", "pn", "b19", 20378031Sdes "b20", "b21", "mmxext", "mmx", "fxsr", 20478031Sdes "xmm", "b26", "b27", "b28", "b29", 20567589Sdes "3dnowext", "3dnow" 20667589Sdes }; 20767589Sdes 20859412Smsmith switch (cpu_class) { 209133822Stjr#ifdef __i386__ 21059412Smsmith case CPUCLASS_286: 21167589Sdes class = 2; 21259412Smsmith break; 21359412Smsmith case CPUCLASS_386: 21467589Sdes class = 3; 21559412Smsmith break; 21659412Smsmith case CPUCLASS_486: 21767589Sdes class = 4; 21859412Smsmith break; 21959412Smsmith case CPUCLASS_586: 22067589Sdes class = 5; 22159412Smsmith break; 22259412Smsmith case CPUCLASS_686: 22367589Sdes class = 6; 22459412Smsmith break; 22559412Smsmith default: 22678031Sdes class = 0; 22759412Smsmith break; 228159170Sdes#else /* __amd64__ */ 229133822Stjr default: 230159170Sdes class = 15; 231133822Stjr break; 232133822Stjr#endif 23359412Smsmith } 23459412Smsmith 235159544Sdes hw_model[0] = CTL_HW; 236159544Sdes hw_model[1] = HW_MODEL; 237159544Sdes model[0] = '\0'; 238159544Sdes size = sizeof(model); 239159544Sdes if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0) 240159544Sdes strcpy(model, "unknown"); 241123246Sdes for (i = 0; i < mp_ncpus; ++i) { 242118421Sdes sbuf_printf(sb, 243118421Sdes "processor\t: %d\n" 244118421Sdes "vendor_id\t: %.20s\n" 245118421Sdes "cpu family\t: %d\n" 246118421Sdes "model\t\t: %d\n" 247159544Sdes "model name\t: %s\n" 248118421Sdes "stepping\t: %d\n", 249159544Sdes i, cpu_vendor, class, cpu, model, cpu_id & 0xf); 250159544Sdes /* XXX per-cpu vendor / class / model / id? */ 251118421Sdes } 25259412Smsmith 25378031Sdes sbuf_cat(sb, 25478031Sdes "flags\t\t:"); 25567589Sdes 25678031Sdes if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) { 25767589Sdes flags[16] = "fcmov"; 25878031Sdes } else if (!strcmp(cpu_vendor, "CyrixInstead")) { 25967589Sdes flags[24] = "cxmmx"; 26078031Sdes } 261119068Sdes 26278031Sdes for (i = 0; i < 32; i++) 26367589Sdes if (cpu_feature & (1 << i)) 26478025Sdes sbuf_printf(sb, " %s", flags[i]); 26578025Sdes sbuf_cat(sb, "\n"); 26678031Sdes if (class >= 5) { 26769799Sdes fqmhz = (tsc_freq + 4999) / 1000000; 26869799Sdes fqkhz = ((tsc_freq + 4999) / 10000) % 100; 26978025Sdes sbuf_printf(sb, 27069799Sdes "cpu MHz\t\t: %d.%02d\n" 27169799Sdes "bogomips\t: %d.%02d\n", 27269799Sdes fqmhz, fqkhz, fqmhz, fqkhz); 27378031Sdes } 27469995Sdes 27578025Sdes return (0); 27659412Smsmith} 277133822Stjr#endif /* __i386__ || __amd64__ */ 27865633Sdes 27978113Sdes/* 28085289Sdes * Filler function for proc/mtab 28185289Sdes * 28285289Sdes * This file doesn't exist in Linux' procfs, but is included here so 28385289Sdes * users can symlink /compat/linux/etc/mtab to /proc/mtab 28485289Sdes */ 28585289Sdesstatic int 28685289Sdeslinprocfs_domtab(PFS_FILL_ARGS) 28785289Sdes{ 28885289Sdes struct nameidata nd; 28985289Sdes struct mount *mp; 29091334Sjulian const char *lep; 29191334Sjulian char *dlep, *flep, *mntto, *mntfrom, *fstype; 29285289Sdes size_t lep_len; 29385289Sdes int error; 29485289Sdes 29585289Sdes /* resolve symlinks etc. in the emulation tree prefix */ 29685289Sdes NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td); 29785289Sdes flep = NULL; 298124407Srwatson if (namei(&nd) != 0 || vn_fullpath(td, nd.ni_vp, &dlep, &flep) != 0) 29985289Sdes lep = linux_emul_path; 30091334Sjulian else 30191334Sjulian lep = dlep; 30285289Sdes lep_len = strlen(lep); 303119068Sdes 30485289Sdes mtx_lock(&mountlist_mtx); 30585289Sdes error = 0; 30685289Sdes TAILQ_FOREACH(mp, &mountlist, mnt_list) { 30785289Sdes /* determine device name */ 30885289Sdes mntfrom = mp->mnt_stat.f_mntfromname; 309119068Sdes 31085289Sdes /* determine mount point */ 31185289Sdes mntto = mp->mnt_stat.f_mntonname; 31285289Sdes if (strncmp(mntto, lep, lep_len) == 0 && 31385289Sdes mntto[lep_len] == '/') 31485289Sdes mntto += lep_len; 31585289Sdes 31685289Sdes /* determine fs type */ 31785289Sdes fstype = mp->mnt_stat.f_fstypename; 31885289Sdes if (strcmp(fstype, pn->pn_info->pi_name) == 0) 31985289Sdes mntfrom = fstype = "proc"; 32085289Sdes else if (strcmp(fstype, "procfs") == 0) 32185289Sdes continue; 322119068Sdes 323158311Sambrisko if (strcmp(fstype, "linsysfs") == 0) { 324158311Sambrisko sbuf_printf(sb, "/sys %s sysfs %s", mntto, 325158311Sambrisko mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); 326158311Sambrisko } else { 327158311Sambrisko sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype, 328158311Sambrisko mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); 329158311Sambrisko } 33085289Sdes#define ADD_OPTION(opt, name) \ 33185289Sdes if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name); 33285289Sdes ADD_OPTION(MNT_SYNCHRONOUS, "sync"); 33385289Sdes ADD_OPTION(MNT_NOEXEC, "noexec"); 33485289Sdes ADD_OPTION(MNT_NOSUID, "nosuid"); 33585289Sdes ADD_OPTION(MNT_UNION, "union"); 33685289Sdes ADD_OPTION(MNT_ASYNC, "async"); 33785289Sdes ADD_OPTION(MNT_SUIDDIR, "suiddir"); 33885289Sdes ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow"); 33985289Sdes ADD_OPTION(MNT_NOATIME, "noatime"); 34085289Sdes#undef ADD_OPTION 34185289Sdes /* a real Linux mtab will also show NFS options */ 34285289Sdes sbuf_printf(sb, " 0 0\n"); 34385289Sdes } 34485289Sdes mtx_unlock(&mountlist_mtx); 34585289Sdes if (flep != NULL) 34685289Sdes free(flep, M_TEMP); 34785289Sdes return (error); 34885289Sdes} 34985289Sdes 35085289Sdes/* 35178113Sdes * Filler function for proc/stat 35278113Sdes */ 35378025Sdesstatic int 35478025Sdeslinprocfs_dostat(PFS_FILL_ARGS) 35565633Sdes{ 356123246Sdes int i; 357120339Sdes 358120339Sdes sbuf_printf(sb, "cpu %ld %ld %ld %ld\n", 359120339Sdes T2J(cp_time[CP_USER]), 360120339Sdes T2J(cp_time[CP_NICE]), 361120339Sdes T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/), 362120339Sdes T2J(cp_time[CP_IDLE])); 363143194Ssobomax for (i = 0; i < mp_ncpus; ++i) 364143194Ssobomax sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i, 365143194Ssobomax T2J(cp_time[CP_USER]) / mp_ncpus, 366143194Ssobomax T2J(cp_time[CP_NICE]) / mp_ncpus, 367143194Ssobomax T2J(cp_time[CP_SYS]) / mp_ncpus, 368143194Ssobomax T2J(cp_time[CP_IDLE]) / mp_ncpus); 36978025Sdes sbuf_printf(sb, 37069799Sdes "disk 0 0 0 0\n" 37169799Sdes "page %u %u\n" 37269799Sdes "swap %u %u\n" 37369799Sdes "intr %u\n" 37469799Sdes "ctxt %u\n" 37585657Sdillon "btime %lld\n", 37669799Sdes cnt.v_vnodepgsin, 37769799Sdes cnt.v_vnodepgsout, 37869799Sdes cnt.v_swappgsin, 37969799Sdes cnt.v_swappgsout, 38069799Sdes cnt.v_intr, 38169799Sdes cnt.v_swtch, 382113574Sjhb (long long)boottime.tv_sec); 38378025Sdes return (0); 38465633Sdes} 38565633Sdes 38678113Sdes/* 38778113Sdes * Filler function for proc/uptime 38878113Sdes */ 38978025Sdesstatic int 39078025Sdeslinprocfs_douptime(PFS_FILL_ARGS) 39165633Sdes{ 39265633Sdes struct timeval tv; 39365633Sdes 39465633Sdes getmicrouptime(&tv); 39585657Sdillon sbuf_printf(sb, "%lld.%02ld %ld.%02ld\n", 396113574Sjhb (long long)tv.tv_sec, tv.tv_usec / 10000, 39769799Sdes T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100); 39878025Sdes return (0); 39965633Sdes} 40065633Sdes 40178113Sdes/* 40278113Sdes * Filler function for proc/version 40378113Sdes */ 40478025Sdesstatic int 40578025Sdeslinprocfs_doversion(PFS_FILL_ARGS) 40665633Sdes{ 40787275Srwatson char osname[LINUX_MAX_UTSNAME]; 40887275Srwatson char osrelease[LINUX_MAX_UTSNAME]; 40987275Srwatson 410112206Sjhb linux_get_osname(td, osname); 411112206Sjhb linux_get_osrelease(td, osrelease); 41287275Srwatson 41378025Sdes sbuf_printf(sb, 41469995Sdes "%s version %s (des@freebsd.org) (gcc version " __VERSION__ ")" 41587275Srwatson " #4 Sun Dec 18 04:30:00 CET 1977\n", osname, osrelease); 41678025Sdes return (0); 41765633Sdes} 41865633Sdes 41978113Sdes/* 42078113Sdes * Filler function for proc/loadavg 42178113Sdes */ 42278025Sdesstatic int 42378025Sdeslinprocfs_doloadavg(PFS_FILL_ARGS) 42476839Sjlemon{ 42578025Sdes sbuf_printf(sb, 42676839Sjlemon "%d.%02d %d.%02d %d.%02d %d/%d %d\n", 42776839Sjlemon (int)(averunnable.ldavg[0] / averunnable.fscale), 42876839Sjlemon (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100), 42976839Sjlemon (int)(averunnable.ldavg[1] / averunnable.fscale), 43076839Sjlemon (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100), 43176839Sjlemon (int)(averunnable.ldavg[2] / averunnable.fscale), 43276839Sjlemon (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100), 43376839Sjlemon 1, /* number of running tasks */ 43476839Sjlemon nprocs, /* number of tasks */ 43578116Sdes lastpid /* the last pid */ 43676839Sjlemon ); 437119068Sdes 43878025Sdes return (0); 43976839Sjlemon} 44076839Sjlemon 44178113Sdes/* 44278113Sdes * Filler function for proc/pid/stat 44378113Sdes */ 44478025Sdesstatic int 44578025Sdeslinprocfs_doprocstat(PFS_FILL_ARGS) 44667588Sdes{ 44769995Sdes struct kinfo_proc kp; 44867588Sdes 44994307Sjhb PROC_LOCK(p); 45069995Sdes fill_kinfo_proc(p, &kp); 45178025Sdes sbuf_printf(sb, "%d", p->p_pid); 45278025Sdes#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg) 45367588Sdes PS_ADD("comm", "(%s)", p->p_comm); 45467588Sdes PS_ADD("statr", "%c", '0'); /* XXX */ 45573923Sjhb PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0); 45667588Sdes PS_ADD("pgrp", "%d", p->p_pgid); 45767588Sdes PS_ADD("session", "%d", p->p_session->s_sid); 45891140Stanimura PROC_UNLOCK(p); 45967588Sdes PS_ADD("tty", "%d", 0); /* XXX */ 46067588Sdes PS_ADD("tpgid", "%d", 0); /* XXX */ 46167588Sdes PS_ADD("flags", "%u", 0); /* XXX */ 46267588Sdes PS_ADD("minflt", "%u", 0); /* XXX */ 46367588Sdes PS_ADD("cminflt", "%u", 0); /* XXX */ 46467588Sdes PS_ADD("majflt", "%u", 0); /* XXX */ 46567588Sdes PS_ADD("cminflt", "%u", 0); /* XXX */ 46667588Sdes PS_ADD("utime", "%d", 0); /* XXX */ 46767588Sdes PS_ADD("stime", "%d", 0); /* XXX */ 46867588Sdes PS_ADD("cutime", "%d", 0); /* XXX */ 46967588Sdes PS_ADD("cstime", "%d", 0); /* XXX */ 47067588Sdes PS_ADD("counter", "%d", 0); /* XXX */ 47167588Sdes PS_ADD("priority", "%d", 0); /* XXX */ 47267588Sdes PS_ADD("timeout", "%u", 0); /* XXX */ 47367588Sdes PS_ADD("itrealvalue", "%u", 0); /* XXX */ 47467588Sdes PS_ADD("starttime", "%d", 0); /* XXX */ 475113574Sjhb PS_ADD("vsize", "%ju", (uintmax_t)kp.ki_size); 476113574Sjhb PS_ADD("rss", "%ju", P2K((uintmax_t)kp.ki_rssize)); 47767588Sdes PS_ADD("rlim", "%u", 0); /* XXX */ 47869995Sdes PS_ADD("startcode", "%u", (unsigned)0); 47967588Sdes PS_ADD("endcode", "%u", 0); /* XXX */ 48067588Sdes PS_ADD("startstack", "%u", 0); /* XXX */ 48169799Sdes PS_ADD("esp", "%u", 0); /* XXX */ 48269799Sdes PS_ADD("eip", "%u", 0); /* XXX */ 48367588Sdes PS_ADD("signal", "%d", 0); /* XXX */ 48467588Sdes PS_ADD("blocked", "%d", 0); /* XXX */ 48567588Sdes PS_ADD("sigignore", "%d", 0); /* XXX */ 48667588Sdes PS_ADD("sigcatch", "%d", 0); /* XXX */ 48767588Sdes PS_ADD("wchan", "%u", 0); /* XXX */ 48869799Sdes PS_ADD("nswap", "%lu", (long unsigned)0); /* XXX */ 48969799Sdes PS_ADD("cnswap", "%lu", (long unsigned)0); /* XXX */ 49069799Sdes PS_ADD("exitsignal", "%d", 0); /* XXX */ 49169799Sdes PS_ADD("processor", "%d", 0); /* XXX */ 49267588Sdes#undef PS_ADD 49378025Sdes sbuf_putc(sb, '\n'); 494119068Sdes 49578025Sdes return (0); 49667588Sdes} 49767588Sdes 49867588Sdes/* 499119911Sdes * Filler function for proc/pid/statm 500119911Sdes */ 501119911Sdesstatic int 502119911Sdeslinprocfs_doprocstatm(PFS_FILL_ARGS) 503119911Sdes{ 504119911Sdes struct kinfo_proc kp; 505119911Sdes segsz_t lsize; 506120340Sdes 507119911Sdes PROC_LOCK(p); 508119911Sdes fill_kinfo_proc(p, &kp); 509119911Sdes PROC_UNLOCK(p); 510119911Sdes 511119911Sdes /* 512119911Sdes * See comments in linprocfs_doprocstatus() regarding the 513119911Sdes * computation of lsize. 514119911Sdes */ 515119911Sdes /* size resident share trs drs lrs dt */ 516119911Sdes sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size)); 517119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize); 518119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */ 519119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize); 520119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize)); 521119911Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 522119911Sdes kp.ki_ssize - kp.ki_tsize - 1; 523119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)lsize); 524119911Sdes sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */ 525119911Sdes 526119911Sdes return (0); 527119911Sdes} 528119911Sdes 529119911Sdes/* 53078113Sdes * Filler function for proc/pid/status 53178113Sdes */ 53278025Sdesstatic int 53378025Sdeslinprocfs_doprocstatus(PFS_FILL_ARGS) 53467588Sdes{ 53569995Sdes struct kinfo_proc kp; 53667588Sdes char *state; 53769799Sdes segsz_t lsize; 53899072Sjulian struct thread *td2; 539114983Sjhb struct sigacts *ps; 54074135Sjlemon int i; 54167588Sdes 542113611Sjhb PROC_LOCK(p); 54399072Sjulian td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */ 54499072Sjulian 54599072Sjulian if (P_SHOULDSTOP(p)) { 54699072Sjulian state = "T (stopped)"; 54799072Sjulian } else { 548113611Sjhb mtx_lock_spin(&sched_lock); 54999072Sjulian switch(p->p_state) { 55099072Sjulian case PRS_NEW: 55199072Sjulian state = "I (idle)"; 55299072Sjulian break; 55399072Sjulian case PRS_NORMAL: 55499072Sjulian if (p->p_flag & P_WEXIT) { 55599072Sjulian state = "X (exiting)"; 55699072Sjulian break; 55799072Sjulian } 55899072Sjulian switch(td2->td_state) { 559103216Sjulian case TDS_INHIBITED: 56099072Sjulian state = "S (sleeping)"; 56199072Sjulian break; 56299072Sjulian case TDS_RUNQ: 56399072Sjulian case TDS_RUNNING: 56499072Sjulian state = "R (running)"; 56599072Sjulian break; 56699072Sjulian default: 56799072Sjulian state = "? (unknown)"; 56899072Sjulian break; 56999072Sjulian } 57099072Sjulian break; 57199072Sjulian case PRS_ZOMBIE: 57299072Sjulian state = "Z (zombie)"; 57399072Sjulian break; 57499072Sjulian default: 57599072Sjulian state = "? (unknown)"; 57699072Sjulian break; 57799072Sjulian } 578113611Sjhb mtx_unlock_spin(&sched_lock); 57999072Sjulian } 58067588Sdes 58169995Sdes fill_kinfo_proc(p, &kp); 58278025Sdes sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */ 58378031Sdes sbuf_printf(sb, "State:\t%s\n", state); 58467588Sdes 58567588Sdes /* 58667588Sdes * Credentials 58767588Sdes */ 58878025Sdes sbuf_printf(sb, "Pid:\t%d\n", p->p_pid); 58978025Sdes sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ? 59073923Sjhb p->p_pptr->p_pid : 0); 59178031Sdes sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid, 59278031Sdes p->p_ucred->cr_uid, 59378031Sdes p->p_ucred->cr_svuid, 59478031Sdes /* FreeBSD doesn't have fsuid */ 59578031Sdes p->p_ucred->cr_uid); 59678031Sdes sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid, 59778031Sdes p->p_ucred->cr_gid, 59878031Sdes p->p_ucred->cr_svgid, 59978031Sdes /* FreeBSD doesn't have fsgid */ 60078031Sdes p->p_ucred->cr_gid); 60178025Sdes sbuf_cat(sb, "Groups:\t"); 60267588Sdes for (i = 0; i < p->p_ucred->cr_ngroups; i++) 60378031Sdes sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]); 60471471Sjhb PROC_UNLOCK(p); 60578025Sdes sbuf_putc(sb, '\n'); 606119068Sdes 60767588Sdes /* 60867588Sdes * Memory 60969799Sdes * 61069799Sdes * While our approximation of VmLib may not be accurate (I 61169799Sdes * don't know of a simple way to verify it, and I'm not sure 61269799Sdes * it has much meaning anyway), I believe it's good enough. 61369799Sdes * 61469799Sdes * The same code that could (I think) accurately compute VmLib 61569799Sdes * could also compute VmLck, but I don't really care enough to 61669799Sdes * implement it. Submissions are welcome. 61767588Sdes */ 618113574Sjhb sbuf_printf(sb, "VmSize:\t%8ju kB\n", B2K((uintmax_t)kp.ki_size)); 61978025Sdes sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */ 620113574Sjhb sbuf_printf(sb, "VmRss:\t%8ju kB\n", P2K((uintmax_t)kp.ki_rssize)); 621113574Sjhb sbuf_printf(sb, "VmData:\t%8ju kB\n", P2K((uintmax_t)kp.ki_dsize)); 622113574Sjhb sbuf_printf(sb, "VmStk:\t%8ju kB\n", P2K((uintmax_t)kp.ki_ssize)); 623113574Sjhb sbuf_printf(sb, "VmExe:\t%8ju kB\n", P2K((uintmax_t)kp.ki_tsize)); 62469995Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 62569995Sdes kp.ki_ssize - kp.ki_tsize - 1; 626113574Sjhb sbuf_printf(sb, "VmLib:\t%8ju kB\n", P2K((uintmax_t)lsize)); 62767588Sdes 62867588Sdes /* 62967588Sdes * Signal masks 63067588Sdes * 63167588Sdes * We support up to 128 signals, while Linux supports 32, 63267588Sdes * but we only define 32 (the same 32 as Linux, to boot), so 63367588Sdes * just show the lower 32 bits of each mask. XXX hack. 63467588Sdes * 63567588Sdes * NB: on certain platforms (Sparc at least) Linux actually 63667588Sdes * supports 64 signals, but this code is a long way from 63767588Sdes * running on anything but i386, so ignore that for now. 63867588Sdes */ 63971471Sjhb PROC_LOCK(p); 640104306Sjmallett sbuf_printf(sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]); 64169799Sdes /* 64269799Sdes * I can't seem to find out where the signal mask is in 64369799Sdes * relation to struct proc, so SigBlk is left unimplemented. 64469799Sdes */ 64578025Sdes sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */ 646114983Sjhb ps = p->p_sigacts; 647114983Sjhb mtx_lock(&ps->ps_mtx); 648114983Sjhb sbuf_printf(sb, "SigIgn:\t%08x\n", ps->ps_sigignore.__bits[0]); 649114983Sjhb sbuf_printf(sb, "SigCgt:\t%08x\n", ps->ps_sigcatch.__bits[0]); 650114983Sjhb mtx_unlock(&ps->ps_mtx); 65171471Sjhb PROC_UNLOCK(p); 652119068Sdes 65367588Sdes /* 65467588Sdes * Linux also prints the capability masks, but we don't have 65567588Sdes * capabilities yet, and when we do get them they're likely to 65667588Sdes * be meaningless to Linux programs, so we lie. XXX 65767588Sdes */ 65878025Sdes sbuf_printf(sb, "CapInh:\t%016x\n", 0); 65978025Sdes sbuf_printf(sb, "CapPrm:\t%016x\n", 0); 66078025Sdes sbuf_printf(sb, "CapEff:\t%016x\n", 0); 661119068Sdes 66278025Sdes return (0); 66367588Sdes} 66474135Sjlemon 665119911Sdes 66678113Sdes/* 667119911Sdes * Filler function for proc/pid/cwd 668119911Sdes */ 669119911Sdesstatic int 670119911Sdeslinprocfs_doproccwd(PFS_FILL_ARGS) 671119911Sdes{ 672119911Sdes char *fullpath = "unknown"; 673119911Sdes char *freepath = NULL; 674119911Sdes 675119911Sdes vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath); 676119911Sdes sbuf_printf(sb, "%s", fullpath); 677119911Sdes if (freepath) 678119911Sdes free(freepath, M_TEMP); 679119911Sdes return (0); 680119911Sdes} 681119911Sdes 682119911Sdes/* 683119911Sdes * Filler function for proc/pid/root 684119911Sdes */ 685119911Sdesstatic int 686119911Sdeslinprocfs_doprocroot(PFS_FILL_ARGS) 687119911Sdes{ 688119911Sdes struct vnode *rvp; 689119911Sdes char *fullpath = "unknown"; 690119911Sdes char *freepath = NULL; 691119911Sdes 692119911Sdes rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir; 693119911Sdes vn_fullpath(td, rvp, &fullpath, &freepath); 694119911Sdes sbuf_printf(sb, "%s", fullpath); 695119911Sdes if (freepath) 696119911Sdes free(freepath, M_TEMP); 697119911Sdes return (0); 698119911Sdes} 699119911Sdes 700119911Sdes/* 70178113Sdes * Filler function for proc/pid/cmdline 70278113Sdes */ 70378025Sdesstatic int 70478113Sdeslinprocfs_doproccmdline(PFS_FILL_ARGS) 70578113Sdes{ 70678113Sdes struct ps_strings pstr; 707138281Scperciva char **ps_argvstr; 70878113Sdes int error, i; 70978113Sdes 71078113Sdes /* 71178113Sdes * If we are using the ps/cmdline caching, use that. Otherwise 71278113Sdes * revert back to the old way which only implements full cmdline 71378113Sdes * for the currept process and just p->p_comm for all other 71478113Sdes * processes. 71578113Sdes * Note that if the argv is no longer available, we deliberately 71678113Sdes * don't fall back on p->p_comm or return an error: the authentic 71778113Sdes * Linux behaviour is to return zero-length in this case. 71878113Sdes */ 71978113Sdes 72094620Sjhb PROC_LOCK(p); 721127694Spjd if (p->p_args && p_cansee(td, p) == 0) { 72294620Sjhb sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length); 72394620Sjhb PROC_UNLOCK(p); 72494620Sjhb } else if (p != td->td_proc) { 72594620Sjhb PROC_UNLOCK(p); 72694620Sjhb sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm); 72794620Sjhb } else { 72894620Sjhb PROC_UNLOCK(p); 729103767Sjake error = copyin((void *)p->p_sysent->sv_psstrings, &pstr, 730103767Sjake sizeof(pstr)); 73194620Sjhb if (error) 73294620Sjhb return (error); 733138281Scperciva if (pstr.ps_nargvstr > ARG_MAX) 734138281Scperciva return (E2BIG); 735138281Scperciva ps_argvstr = malloc(pstr.ps_nargvstr * sizeof(char *), 736138281Scperciva M_TEMP, M_WAITOK); 737138281Scperciva error = copyin((void *)pstr.ps_argvstr, ps_argvstr, 738138281Scperciva pstr.ps_nargvstr * sizeof(char *)); 739138281Scperciva if (error) { 740138281Scperciva free(ps_argvstr, M_TEMP); 741138281Scperciva return (error); 742138281Scperciva } 74394620Sjhb for (i = 0; i < pstr.ps_nargvstr; i++) { 744138281Scperciva sbuf_copyin(sb, ps_argvstr[i], 0); 74594620Sjhb sbuf_printf(sb, "%c", '\0'); 74678113Sdes } 747138281Scperciva free(ps_argvstr, M_TEMP); 74878113Sdes } 74978113Sdes 75078113Sdes return (0); 75178113Sdes} 75278113Sdes 75378113Sdes/* 754116173Sobrien * Filler function for proc/pid/environ 755116173Sobrien */ 756116173Sobrienstatic int 757116173Sobrienlinprocfs_doprocenviron(PFS_FILL_ARGS) 758116173Sobrien{ 759116173Sobrien sbuf_printf(sb, "doprocenviron\n%c", '\0'); 760116173Sobrien 761116173Sobrien return (0); 762116173Sobrien} 763116173Sobrien 764116173Sobrien/* 765116173Sobrien * Filler function for proc/pid/maps 766116173Sobrien */ 767116173Sobrienstatic int 768116173Sobrienlinprocfs_doprocmaps(PFS_FILL_ARGS) 769116173Sobrien{ 770121265Scognet char mebuffer[512]; 771121246Scognet vm_map_t map = &p->p_vmspace->vm_map; 772121246Scognet vm_map_entry_t entry; 773121265Scognet vm_object_t obj, tobj, lobj; 774121265Scognet vm_ooffset_t off = 0; 775121265Scognet char *name = "", *freename = NULL; 776121265Scognet size_t len; 777121265Scognet ino_t ino; 778121265Scognet int ref_count, shadow_count, flags; 779121265Scognet int error; 780137507Sphk struct vnode *vp; 781137507Sphk struct vattr vat; 782121246Scognet 783121246Scognet PROC_LOCK(p); 784121246Scognet error = p_candebug(td, p); 785121246Scognet PROC_UNLOCK(p); 786121246Scognet if (error) 787121246Scognet return (error); 788121246Scognet 789121246Scognet if (uio->uio_rw != UIO_READ) 790121246Scognet return (EOPNOTSUPP); 791121246Scognet 792121246Scognet if (uio->uio_offset != 0) 793121246Scognet return (0); 794121246Scognet 795121246Scognet error = 0; 796121246Scognet if (map != &curthread->td_proc->p_vmspace->vm_map) 797121246Scognet vm_map_lock_read(map); 798121246Scognet for (entry = map->header.next; 799121246Scognet ((uio->uio_resid > 0) && (entry != &map->header)); 800121246Scognet entry = entry->next) { 801121265Scognet name = ""; 802121265Scognet freename = NULL; 803121246Scognet if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) 804121246Scognet continue; 805121246Scognet obj = entry->object.vm_object; 806121246Scognet for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) 807121246Scognet lobj = tobj; 808121246Scognet ino = 0; 809121246Scognet if (lobj) { 810137507Sphk vp = lobj->handle; 811121246Scognet VM_OBJECT_LOCK(lobj); 812121246Scognet off = IDX_TO_OFF(lobj->size); 813121246Scognet if (lobj->type == OBJT_VNODE && lobj->handle) { 814137507Sphk vn_fullpath(td, vp, &name, &freename); 815137507Sphk VOP_GETATTR(vp, &vat, td->td_ucred, td); 816137507Sphk ino = vat.va_fileid; 817121246Scognet } 818121246Scognet flags = obj->flags; 819121246Scognet ref_count = obj->ref_count; 820121246Scognet shadow_count = obj->shadow_count; 821121246Scognet VM_OBJECT_UNLOCK(lobj); 822121246Scognet } else { 823121246Scognet flags = 0; 824121246Scognet ref_count = 0; 825121246Scognet shadow_count = 0; 826121246Scognet } 827121246Scognet 828121246Scognet /* 829121246Scognet * format: 830121246Scognet * start, end, access, offset, major, minor, inode, name. 831121246Scognet */ 832121246Scognet snprintf(mebuffer, sizeof mebuffer, 833121246Scognet "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n", 834121246Scognet (u_long)entry->start, (u_long)entry->end, 835121246Scognet (entry->protection & VM_PROT_READ)?"r":"-", 836121246Scognet (entry->protection & VM_PROT_WRITE)?"w":"-", 837121246Scognet (entry->protection & VM_PROT_EXECUTE)?"x":"-", 838121246Scognet "p", 839121265Scognet (u_long)off, 840121246Scognet 0, 841121246Scognet 0, 842121265Scognet (u_long)ino, 843121246Scognet *name ? " " : "", 844121246Scognet name 845121246Scognet ); 846121246Scognet if (freename) 847121246Scognet free(freename, M_TEMP); 848121246Scognet len = strlen(mebuffer); 849121246Scognet if (len > uio->uio_resid) 850121246Scognet len = uio->uio_resid; /* 851121246Scognet * XXX We should probably return 852121246Scognet * EFBIG here, as in procfs. 853121246Scognet */ 854121246Scognet error = uiomove(mebuffer, len, uio); 855121246Scognet if (error) 856121246Scognet break; 857121246Scognet } 858121246Scognet if (map != &curthread->td_proc->p_vmspace->vm_map) 859121246Scognet vm_map_unlock_read(map); 860121246Scognet 861121246Scognet return (error); 862121246Scognet} 863121246Scognet 864116173Sobrien/* 86578113Sdes * Filler function for proc/net/dev 86678113Sdes */ 86778025Sdesstatic int 86878025Sdeslinprocfs_donetdev(PFS_FILL_ARGS) 86974135Sjlemon{ 87085129Sdes char ifname[16]; /* XXX LINUX_IFNAMSIZ */ 87174135Sjlemon struct ifnet *ifp; 87274135Sjlemon 87385129Sdes sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n", 87483926Sdes "Inter-", " Receive", " Transmit", " face", 87585129Sdes "bytes packets errs drop fifo frame compressed", 87683926Sdes "bytes packets errs drop fifo frame compressed"); 87774135Sjlemon 878108172Shsu IFNET_RLOCK(); 87974135Sjlemon TAILQ_FOREACH(ifp, &ifnet, if_link) { 88085129Sdes linux_ifname(ifp, ifname, sizeof ifname); 88185129Sdes sbuf_printf(sb, "%6.6s:", ifname); 88283926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ", 88383926Sdes 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); 88483926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", 88583926Sdes 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); 88674135Sjlemon } 887108172Shsu IFNET_RUNLOCK(); 888119068Sdes 88978025Sdes return (0); 89074135Sjlemon} 89174135Sjlemon 892158311Sambrisko/* 893158311Sambrisko * Filler function for proc/scsi/device_info 894158311Sambrisko */ 895158311Sambriskostatic int 896158311Sambriskolinprocfs_doscsidevinfo(PFS_FILL_ARGS) 897158311Sambrisko{ 898158311Sambrisko return (0); 899158311Sambrisko} 900158311Sambrisko 901158311Sambrisko/* 902158311Sambrisko * Filler function for proc/scsi/scsi 903158311Sambrisko */ 904158311Sambriskostatic int 905158311Sambriskolinprocfs_doscsiscsi(PFS_FILL_ARGS) 906158311Sambrisko{ 907158311Sambrisko return (0); 908158311Sambrisko} 909158311Sambrisko 91085538Sphkextern struct cdevsw *cdevsw[]; 91185538Sphk 91278113Sdes/* 91378113Sdes * Filler function for proc/devices 91478113Sdes */ 91578025Sdesstatic int 91678025Sdeslinprocfs_dodevices(PFS_FILL_ARGS) 91774135Sjlemon{ 918158311Sambrisko char *char_devices; 91978025Sdes sbuf_printf(sb, "Character devices:\n"); 92074135Sjlemon 921158311Sambrisko char_devices = linux_get_char_devices(); 922158311Sambrisko sbuf_printf(sb, "%s", char_devices); 923158311Sambrisko linux_free_get_char_devices(char_devices); 92474135Sjlemon 92578025Sdes sbuf_printf(sb, "\nBlock devices:\n"); 926119068Sdes 92778025Sdes return (0); 92874135Sjlemon} 92974135Sjlemon 93078113Sdes/* 93178113Sdes * Filler function for proc/cmdline 93278113Sdes */ 93378025Sdesstatic int 93478025Sdeslinprocfs_docmdline(PFS_FILL_ARGS) 93574135Sjlemon{ 93678025Sdes sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname); 93778025Sdes sbuf_printf(sb, " ro root=302\n"); 93878025Sdes return (0); 93978025Sdes} 94074135Sjlemon 94183926Sdes#if 0 94278025Sdes/* 94383926Sdes * Filler function for proc/modules 94483926Sdes */ 94583926Sdesstatic int 94683926Sdeslinprocfs_domodules(PFS_FILL_ARGS) 94783926Sdes{ 94883926Sdes struct linker_file *lf; 949119068Sdes 95083926Sdes TAILQ_FOREACH(lf, &linker_files, link) { 95183926Sdes sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename, 95283926Sdes (unsigned long)lf->size, lf->refs); 95383926Sdes } 95483926Sdes return (0); 95583926Sdes} 95683926Sdes#endif 95783926Sdes 95883926Sdes/* 95985129Sdes * Constructor 96078025Sdes */ 96185129Sdesstatic int 96285129Sdeslinprocfs_init(PFS_INIT_ARGS) 96385129Sdes{ 96485129Sdes struct pfs_node *root; 96585129Sdes struct pfs_node *dir; 96674135Sjlemon 96785129Sdes root = pi->pi_root; 96878025Sdes 969119923Sdes /* /proc/... */ 970119911Sdes pfs_create_file(root, "cmdline", &linprocfs_docmdline, 971119911Sdes NULL, NULL, PFS_RD); 972119911Sdes pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo, 973119911Sdes NULL, NULL, PFS_RD); 974119911Sdes pfs_create_file(root, "devices", &linprocfs_dodevices, 975119911Sdes NULL, NULL, PFS_RD); 976119911Sdes pfs_create_file(root, "loadavg", &linprocfs_doloadavg, 977119911Sdes NULL, NULL, PFS_RD); 978119911Sdes pfs_create_file(root, "meminfo", &linprocfs_domeminfo, 979119911Sdes NULL, NULL, PFS_RD); 98083926Sdes#if 0 981119911Sdes pfs_create_file(root, "modules", &linprocfs_domodules, 982119911Sdes NULL, NULL, PFS_RD); 98383926Sdes#endif 984158311Sambrisko pfs_create_file(root, "mounts", &linprocfs_domtab, 985158311Sambrisko NULL, NULL, PFS_RD); 986119911Sdes pfs_create_file(root, "mtab", &linprocfs_domtab, 987119911Sdes NULL, NULL, PFS_RD); 98887543Sdes pfs_create_link(root, "self", &procfs_docurproc, 98985129Sdes NULL, NULL, 0); 990119911Sdes pfs_create_file(root, "stat", &linprocfs_dostat, 991119911Sdes NULL, NULL, PFS_RD); 992119911Sdes pfs_create_file(root, "uptime", &linprocfs_douptime, 993119911Sdes NULL, NULL, PFS_RD); 994119911Sdes pfs_create_file(root, "version", &linprocfs_doversion, 995119911Sdes NULL, NULL, PFS_RD); 99678025Sdes 997119923Sdes /* /proc/net/... */ 99885129Sdes dir = pfs_create_dir(root, "net", NULL, NULL, 0); 99985129Sdes pfs_create_file(dir, "dev", &linprocfs_donetdev, 100085129Sdes NULL, NULL, PFS_RD); 100178025Sdes 1002119923Sdes /* /proc/<pid>/... */ 100385129Sdes dir = pfs_create_dir(root, "pid", NULL, NULL, PFS_PROCDEP); 100485129Sdes pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline, 100585129Sdes NULL, NULL, PFS_RD); 1006119911Sdes pfs_create_link(dir, "cwd", &linprocfs_doproccwd, 1007119911Sdes NULL, NULL, 0); 1008116173Sobrien pfs_create_file(dir, "environ", &linprocfs_doprocenviron, 1009116173Sobrien NULL, NULL, PFS_RD); 101087543Sdes pfs_create_link(dir, "exe", &procfs_doprocfile, 101187543Sdes NULL, &procfs_notsystem, 0); 1012116173Sobrien pfs_create_file(dir, "maps", &linprocfs_doprocmaps, 1013116173Sobrien NULL, NULL, PFS_RD); 101485129Sdes pfs_create_file(dir, "mem", &procfs_doprocmem, 101585129Sdes &procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW); 1016119911Sdes pfs_create_link(dir, "root", &linprocfs_doprocroot, 1017119911Sdes NULL, NULL, 0); 101885129Sdes pfs_create_file(dir, "stat", &linprocfs_doprocstat, 101985129Sdes NULL, NULL, PFS_RD); 1020119911Sdes pfs_create_file(dir, "statm", &linprocfs_doprocstatm, 1021119911Sdes NULL, NULL, PFS_RD); 102285129Sdes pfs_create_file(dir, "status", &linprocfs_doprocstatus, 102385129Sdes NULL, NULL, PFS_RD); 102485129Sdes 1025158311Sambrisko /* /proc/scsi/... */ 1026158311Sambrisko dir = pfs_create_dir(root, "scsi", NULL, NULL, 0); 1027158311Sambrisko pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo, 1028158311Sambrisko NULL, NULL, PFS_RD); 1029158311Sambrisko pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi, 1030158311Sambrisko NULL, NULL, PFS_RD); 103185129Sdes return (0); 103285129Sdes} 103385129Sdes 103485129Sdes/* 103585129Sdes * Destructor 103685129Sdes */ 103785129Sdesstatic int 103885129Sdeslinprocfs_uninit(PFS_INIT_ARGS) 103985129Sdes{ 104085129Sdes 104185129Sdes /* nothing to do, pseudofs will GC */ 104285129Sdes return (0); 104385129Sdes} 104485129Sdes 104585129SdesPSEUDOFS(linprocfs, 1); 104678025SdesMODULE_DEPEND(linprocfs, linux, 1, 1, 1); 104778025SdesMODULE_DEPEND(linprocfs, procfs, 1, 1, 1); 1048