linprocfs.c revision 119923
159412Smsmith/* 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 119923 2003-09-09 19:22:55Z 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> 6283926Sdes#include <sys/socket.h> 6376839Sjlemon#include <sys/sysctl.h> 6483926Sdes#include <sys/systm.h> 6565633Sdes#include <sys/tty.h> 6683926Sdes#include <sys/user.h> 6783926Sdes#include <sys/vmmeter.h> 6859412Smsmith#include <sys/vnode.h> 6959412Smsmith 7083926Sdes#include <net/if.h> 7183926Sdes 7259412Smsmith#include <vm/vm.h> 7359412Smsmith#include <vm/pmap.h> 7467588Sdes#include <vm/vm_map.h> 7559412Smsmith#include <vm/vm_param.h> 7660860Sdes#include <vm/vm_object.h> 7759412Smsmith#include <vm/swap_pager.h> 7869799Sdes 7967589Sdes#include <machine/clock.h> 8078113Sdes 8178113Sdes#ifdef __alpha__ 8278113Sdes#include <machine/alpha_cpu.h> 8378113Sdes#include <machine/cpuconf.h> 8478113Sdes#include <machine/rpb.h> 8578113Sdesextern int ncpus; 8678113Sdes#endif /* __alpha__ */ 8778113Sdes 8878113Sdes#ifdef __i386__ 8967589Sdes#include <machine/cputypes.h> 9059412Smsmith#include <machine/md_var.h> 9178113Sdes#endif /* __i386__ */ 9259412Smsmith 9387275Srwatson#include <machine/../linux/linux.h> 9485129Sdes#include <compat/linux/linux_ioctl.h> 9569995Sdes#include <compat/linux/linux_mib.h> 9685289Sdes#include <compat/linux/linux_util.h> 9778025Sdes#include <fs/pseudofs/pseudofs.h> 9884248Sdes#include <fs/procfs/procfs.h> 9959412Smsmith 10067588Sdes/* 10167588Sdes * Various conversion macros 10267588Sdes */ 10376405Sdes#define T2J(x) (((x) * 100UL) / (stathz ? stathz : hz)) /* ticks to jiffies */ 10467588Sdes#define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */ 10567588Sdes#define B2K(x) ((x) >> 10) /* bytes to kbytes */ 10669799Sdes#define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */ 10767588Sdes#define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */ 10867588Sdes#define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */ 10974135Sjlemon 11078113Sdes/* 11178113Sdes * Filler function for proc/meminfo 11278113Sdes */ 11378025Sdesstatic int 11478025Sdeslinprocfs_domeminfo(PFS_FILL_ARGS) 11559412Smsmith{ 11659412Smsmith unsigned long memtotal; /* total memory in bytes */ 11759412Smsmith unsigned long memused; /* used memory in bytes */ 11859412Smsmith unsigned long memfree; /* free memory in bytes */ 11959412Smsmith unsigned long memshared; /* shared memory ??? */ 12059412Smsmith unsigned long buffers, cached; /* buffer / cache memory ??? */ 121113574Sjhb unsigned long long swaptotal; /* total swap space in bytes */ 122113574Sjhb unsigned long long swapused; /* used swap space in bytes */ 123113574Sjhb unsigned long long swapfree; /* free swap space in bytes */ 12460860Sdes vm_object_t object; 125117723Sphk int i, j; 12659412Smsmith 12759412Smsmith memtotal = physmem * PAGE_SIZE; 12859412Smsmith /* 12959412Smsmith * The correct thing here would be: 13059412Smsmith * 13159412Smsmith memfree = cnt.v_free_count * PAGE_SIZE; 13259412Smsmith memused = memtotal - memfree; 13359412Smsmith * 13459412Smsmith * but it might mislead linux binaries into thinking there 13559412Smsmith * is very little memory left, so we cheat and tell them that 13659412Smsmith * all memory that isn't wired down is free. 13759412Smsmith */ 13859412Smsmith memused = cnt.v_wire_count * PAGE_SIZE; 13959412Smsmith memfree = memtotal - memused; 140117723Sphk swap_pager_status(&i, &j); 141117723Sphk swaptotal = i * PAGE_SIZE; 142117723Sphk swapused = j * PAGE_SIZE; 143117723Sphk swapfree = swaptotal - swapused; 14460860Sdes memshared = 0; 14571471Sjhb TAILQ_FOREACH(object, &vm_object_list, object_list) 14660860Sdes if (object->shadow_count > 1) 14760860Sdes memshared += object->resident_page_count; 14860860Sdes memshared *= PAGE_SIZE; 14959412Smsmith /* 15059412Smsmith * We'd love to be able to write: 15159412Smsmith * 15259412Smsmith buffers = bufspace; 15359412Smsmith * 15459412Smsmith * but bufspace is internal to vfs_bio.c and we don't feel 15559412Smsmith * like unstaticizing it just for linprocfs's sake. 15659412Smsmith */ 15759412Smsmith buffers = 0; 15859412Smsmith cached = cnt.v_cache_count * PAGE_SIZE; 15959412Smsmith 16078025Sdes sbuf_printf(sb, 16178031Sdes " total: used: free: shared: buffers: cached:\n" 16269799Sdes "Mem: %lu %lu %lu %lu %lu %lu\n" 16376839Sjlemon "Swap: %llu %llu %llu\n" 16469799Sdes "MemTotal: %9lu kB\n" 16569799Sdes "MemFree: %9lu kB\n" 16669799Sdes "MemShared:%9lu kB\n" 16769799Sdes "Buffers: %9lu kB\n" 16869799Sdes "Cached: %9lu kB\n" 16976839Sjlemon "SwapTotal:%9llu kB\n" 17076839Sjlemon "SwapFree: %9llu kB\n", 17169799Sdes memtotal, memused, memfree, memshared, buffers, cached, 17269799Sdes swaptotal, swapused, swapfree, 17369799Sdes B2K(memtotal), B2K(memfree), 17469799Sdes B2K(memshared), B2K(buffers), B2K(cached), 17569799Sdes B2K(swaptotal), B2K(swapfree)); 17659412Smsmith 17778025Sdes return (0); 17859412Smsmith} 17959412Smsmith 18078113Sdes#ifdef __alpha__ 181119008Smarcelextern struct rpb *hwrpb; 18278113Sdes/* 18378113Sdes * Filler function for proc/cpuinfo (Alpha version) 18478113Sdes */ 18578025Sdesstatic int 18678025Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS) 18759412Smsmith{ 18878113Sdes u_int64_t type, major; 18978113Sdes struct pcs *pcsp; 19078113Sdes const char *model, *sysname; 19178113Sdes 19278113Sdes static const char *cpuname[] = { 19378113Sdes "EV3", "EV4", "Simulate", "LCA4", "EV5", "EV45", "EV56", 19478113Sdes "EV6", "PCA56", "PCA57", "EV67", "EV68CB", "EV68AL" 19578113Sdes }; 19678113Sdes 19778113Sdes pcsp = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id); 19878113Sdes type = pcsp->pcs_proc_type; 19978113Sdes major = (type & PCS_PROC_MAJOR) >> PCS_PROC_MAJORSHIFT; 20078113Sdes if (major < sizeof(cpuname)/sizeof(char *)) { 20178113Sdes model = cpuname[major - 1]; 20278113Sdes } else { 20378113Sdes model = "unknown"; 20478113Sdes } 205119068Sdes 20678113Sdes sysname = alpha_dsr_sysname(); 207119068Sdes 20878113Sdes sbuf_printf(sb, 20978113Sdes "cpu\t\t\t: Alpha\n" 21078113Sdes "cpu model\t\t: %s\n" 21178113Sdes "cpu variation\t\t: %ld\n" 212113574Sjhb "cpu revision\t\t: %d\n" 21378113Sdes "cpu serial number\t: %s\n" 21478113Sdes "system type\t\t: %s\n" 21578113Sdes "system variation\t: %s\n" 216113574Sjhb "system revision\t\t: %d\n" 21778113Sdes "system serial number\t: %s\n" 21878113Sdes "cycle frequency [Hz]\t: %lu\n" 219113574Sjhb "timer frequency [Hz]\t: %u\n" 22078113Sdes "page size [bytes]\t: %ld\n" 22178113Sdes "phys. address bits\t: %ld\n" 22278113Sdes "max. addr. space #\t: %ld\n" 223113574Sjhb "BogoMIPS\t\t: %u.%02u\n" 224113574Sjhb "kernel unaligned acc\t: %d (pc=%x,va=%x)\n" 225113574Sjhb "user unaligned acc\t: %d (pc=%x,va=%x)\n" 22678113Sdes "platform string\t\t: %s\n" 22778113Sdes "cpus detected\t\t: %d\n" 22878113Sdes , 22978113Sdes model, 23078113Sdes pcsp->pcs_proc_var, 23178113Sdes *(int *)hwrpb->rpb_revision, 23278113Sdes " ", 23378113Sdes " ", 23478113Sdes "0", 23578113Sdes 0, 23678113Sdes " ", 23778113Sdes hwrpb->rpb_cc_freq, 23878113Sdes hz, 23978113Sdes hwrpb->rpb_page_size, 24078113Sdes hwrpb->rpb_phys_addr_size, 24178113Sdes hwrpb->rpb_max_asn, 24278113Sdes 0, 0, 24378113Sdes 0, 0, 0, 24478113Sdes 0, 0, 0, 24578113Sdes sysname, 24678113Sdes ncpus); 24778113Sdes return (0); 24878113Sdes} 24978113Sdes#endif /* __alpha__ */ 25078113Sdes 25178113Sdes#ifdef __i386__ 25278113Sdes/* 25378113Sdes * Filler function for proc/cpuinfo (i386 version) 25478113Sdes */ 25578113Sdesstatic int 25678113Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS) 25778113Sdes{ 258118421Sdes int class, fqmhz, fqkhz, ncpu; 259118421Sdes int name[2], olen, plen; 260118421Sdes int i; 26159412Smsmith 262118421Sdes name[0] = CTL_HW; 263118421Sdes name[1] = HW_NCPU; 264118421Sdes if (kernel_sysctl(td, name, 2, &ncpu, &olen, NULL, 0, &plen) != 0) 265118421Sdes ncpu = 1; 266118421Sdes 26769799Sdes /* 26878031Sdes * We default the flags to include all non-conflicting flags, 26978031Sdes * and the Intel versions of conflicting flags. 27069799Sdes */ 27178031Sdes static char *flags[] = { 27278031Sdes "fpu", "vme", "de", "pse", "tsc", 27378031Sdes "msr", "pae", "mce", "cx8", "apic", 27478031Sdes "sep", "sep", "mtrr", "pge", "mca", 27578031Sdes "cmov", "pat", "pse36", "pn", "b19", 27678031Sdes "b20", "b21", "mmxext", "mmx", "fxsr", 27778031Sdes "xmm", "b26", "b27", "b28", "b29", 27867589Sdes "3dnowext", "3dnow" 27967589Sdes }; 28067589Sdes 28159412Smsmith switch (cpu_class) { 28259412Smsmith case CPUCLASS_286: 28367589Sdes class = 2; 28459412Smsmith break; 28559412Smsmith case CPUCLASS_386: 28667589Sdes class = 3; 28759412Smsmith break; 28859412Smsmith case CPUCLASS_486: 28967589Sdes class = 4; 29059412Smsmith break; 29159412Smsmith case CPUCLASS_586: 29267589Sdes class = 5; 29359412Smsmith break; 29459412Smsmith case CPUCLASS_686: 29567589Sdes class = 6; 29659412Smsmith break; 29759412Smsmith default: 29878031Sdes class = 0; 29959412Smsmith break; 30059412Smsmith } 30159412Smsmith 302118421Sdes for (i = 0; i < ncpu; ++i) { 303118421Sdes sbuf_printf(sb, 304118421Sdes "processor\t: %d\n" 305118421Sdes "vendor_id\t: %.20s\n" 306118421Sdes "cpu family\t: %d\n" 307118421Sdes "model\t\t: %d\n" 308118421Sdes "stepping\t: %d\n", 309118421Sdes i, cpu_vendor, class, cpu, cpu_id & 0xf); 310118421Sdes /* XXX per-cpu vendor / class / id? */ 311118421Sdes } 31259412Smsmith 31378031Sdes sbuf_cat(sb, 31478031Sdes "flags\t\t:"); 31567589Sdes 31678031Sdes if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) { 31767589Sdes flags[16] = "fcmov"; 31878031Sdes } else if (!strcmp(cpu_vendor, "CyrixInstead")) { 31967589Sdes flags[24] = "cxmmx"; 32078031Sdes } 321119068Sdes 32278031Sdes for (i = 0; i < 32; i++) 32367589Sdes if (cpu_feature & (1 << i)) 32478025Sdes sbuf_printf(sb, " %s", flags[i]); 32578025Sdes sbuf_cat(sb, "\n"); 32678031Sdes if (class >= 5) { 32769799Sdes fqmhz = (tsc_freq + 4999) / 1000000; 32869799Sdes fqkhz = ((tsc_freq + 4999) / 10000) % 100; 32978025Sdes sbuf_printf(sb, 33069799Sdes "cpu MHz\t\t: %d.%02d\n" 33169799Sdes "bogomips\t: %d.%02d\n", 33269799Sdes fqmhz, fqkhz, fqmhz, fqkhz); 33378031Sdes } 33469995Sdes 33578025Sdes return (0); 33659412Smsmith} 33778113Sdes#endif /* __i386__ */ 33865633Sdes 33978113Sdes/* 34085289Sdes * Filler function for proc/mtab 34185289Sdes * 34285289Sdes * This file doesn't exist in Linux' procfs, but is included here so 34385289Sdes * users can symlink /compat/linux/etc/mtab to /proc/mtab 34485289Sdes */ 34585289Sdesstatic int 34685289Sdeslinprocfs_domtab(PFS_FILL_ARGS) 34785289Sdes{ 34885289Sdes struct nameidata nd; 34985289Sdes struct mount *mp; 35091334Sjulian const char *lep; 35191334Sjulian char *dlep, *flep, *mntto, *mntfrom, *fstype; 35285289Sdes size_t lep_len; 35385289Sdes int error; 35485289Sdes 35585289Sdes /* resolve symlinks etc. in the emulation tree prefix */ 35685289Sdes NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td); 35785289Sdes flep = NULL; 35891334Sjulian if (namei(&nd) != 0 || vn_fullpath(td, nd.ni_vp, &dlep, &flep) == -1) 35985289Sdes lep = linux_emul_path; 36091334Sjulian else 36191334Sjulian lep = dlep; 36285289Sdes lep_len = strlen(lep); 363119068Sdes 36485289Sdes mtx_lock(&mountlist_mtx); 36585289Sdes error = 0; 36685289Sdes TAILQ_FOREACH(mp, &mountlist, mnt_list) { 36785289Sdes error = VFS_STATFS(mp, &mp->mnt_stat, td); 36885289Sdes if (error) 36985289Sdes break; 37085289Sdes 37185289Sdes /* determine device name */ 37285289Sdes mntfrom = mp->mnt_stat.f_mntfromname; 373119068Sdes 37485289Sdes /* determine mount point */ 37585289Sdes mntto = mp->mnt_stat.f_mntonname; 37685289Sdes if (strncmp(mntto, lep, lep_len) == 0 && 37785289Sdes mntto[lep_len] == '/') 37885289Sdes mntto += lep_len; 37985289Sdes 38085289Sdes /* determine fs type */ 38185289Sdes fstype = mp->mnt_stat.f_fstypename; 38285289Sdes if (strcmp(fstype, pn->pn_info->pi_name) == 0) 38385289Sdes mntfrom = fstype = "proc"; 38485289Sdes else if (strcmp(fstype, "procfs") == 0) 38585289Sdes continue; 386119068Sdes 38785289Sdes sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype, 38885289Sdes mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); 38985289Sdes#define ADD_OPTION(opt, name) \ 39085289Sdes if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name); 39185289Sdes ADD_OPTION(MNT_SYNCHRONOUS, "sync"); 39285289Sdes ADD_OPTION(MNT_NOEXEC, "noexec"); 39385289Sdes ADD_OPTION(MNT_NOSUID, "nosuid"); 39485289Sdes ADD_OPTION(MNT_NODEV, "nodev"); 39585289Sdes ADD_OPTION(MNT_UNION, "union"); 39685289Sdes ADD_OPTION(MNT_ASYNC, "async"); 39785289Sdes ADD_OPTION(MNT_SUIDDIR, "suiddir"); 39885289Sdes ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow"); 39985289Sdes ADD_OPTION(MNT_NOATIME, "noatime"); 40085289Sdes#undef ADD_OPTION 40185289Sdes /* a real Linux mtab will also show NFS options */ 40285289Sdes sbuf_printf(sb, " 0 0\n"); 40385289Sdes } 40485289Sdes mtx_unlock(&mountlist_mtx); 40585289Sdes if (flep != NULL) 40685289Sdes free(flep, M_TEMP); 40785289Sdes return (error); 40885289Sdes} 40985289Sdes 41085289Sdes/* 41178113Sdes * Filler function for proc/stat 41278113Sdes */ 41378025Sdesstatic int 41478025Sdeslinprocfs_dostat(PFS_FILL_ARGS) 41565633Sdes{ 41678025Sdes sbuf_printf(sb, 41769799Sdes "cpu %ld %ld %ld %ld\n" 41869799Sdes "disk 0 0 0 0\n" 41969799Sdes "page %u %u\n" 42069799Sdes "swap %u %u\n" 42169799Sdes "intr %u\n" 42269799Sdes "ctxt %u\n" 42385657Sdillon "btime %lld\n", 42469799Sdes T2J(cp_time[CP_USER]), 42569799Sdes T2J(cp_time[CP_NICE]), 42669799Sdes T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/), 42769799Sdes T2J(cp_time[CP_IDLE]), 42869799Sdes cnt.v_vnodepgsin, 42969799Sdes cnt.v_vnodepgsout, 43069799Sdes cnt.v_swappgsin, 43169799Sdes cnt.v_swappgsout, 43269799Sdes cnt.v_intr, 43369799Sdes cnt.v_swtch, 434113574Sjhb (long long)boottime.tv_sec); 43578025Sdes return (0); 43665633Sdes} 43765633Sdes 43878113Sdes/* 43978113Sdes * Filler function for proc/uptime 44078113Sdes */ 44178025Sdesstatic int 44278025Sdeslinprocfs_douptime(PFS_FILL_ARGS) 44365633Sdes{ 44465633Sdes struct timeval tv; 44565633Sdes 44665633Sdes getmicrouptime(&tv); 44785657Sdillon sbuf_printf(sb, "%lld.%02ld %ld.%02ld\n", 448113574Sjhb (long long)tv.tv_sec, tv.tv_usec / 10000, 44969799Sdes T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100); 45078025Sdes return (0); 45165633Sdes} 45265633Sdes 45378113Sdes/* 45478113Sdes * Filler function for proc/version 45578113Sdes */ 45678025Sdesstatic int 45778025Sdeslinprocfs_doversion(PFS_FILL_ARGS) 45865633Sdes{ 45987275Srwatson char osname[LINUX_MAX_UTSNAME]; 46087275Srwatson char osrelease[LINUX_MAX_UTSNAME]; 46187275Srwatson 462112206Sjhb linux_get_osname(td, osname); 463112206Sjhb linux_get_osrelease(td, osrelease); 46487275Srwatson 46578025Sdes sbuf_printf(sb, 46669995Sdes "%s version %s (des@freebsd.org) (gcc version " __VERSION__ ")" 46787275Srwatson " #4 Sun Dec 18 04:30:00 CET 1977\n", osname, osrelease); 46878025Sdes return (0); 46965633Sdes} 47065633Sdes 47178113Sdes/* 47278113Sdes * Filler function for proc/loadavg 47378113Sdes */ 47478025Sdesstatic int 47578025Sdeslinprocfs_doloadavg(PFS_FILL_ARGS) 47676839Sjlemon{ 47778025Sdes sbuf_printf(sb, 47876839Sjlemon "%d.%02d %d.%02d %d.%02d %d/%d %d\n", 47976839Sjlemon (int)(averunnable.ldavg[0] / averunnable.fscale), 48076839Sjlemon (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100), 48176839Sjlemon (int)(averunnable.ldavg[1] / averunnable.fscale), 48276839Sjlemon (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100), 48376839Sjlemon (int)(averunnable.ldavg[2] / averunnable.fscale), 48476839Sjlemon (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100), 48576839Sjlemon 1, /* number of running tasks */ 48676839Sjlemon nprocs, /* number of tasks */ 48778116Sdes lastpid /* the last pid */ 48876839Sjlemon ); 489119068Sdes 49078025Sdes return (0); 49176839Sjlemon} 49276839Sjlemon 49378113Sdes/* 49478113Sdes * Filler function for proc/pid/stat 49578113Sdes */ 49678025Sdesstatic int 49778025Sdeslinprocfs_doprocstat(PFS_FILL_ARGS) 49867588Sdes{ 49969995Sdes struct kinfo_proc kp; 50067588Sdes 50194307Sjhb PROC_LOCK(p); 50269995Sdes fill_kinfo_proc(p, &kp); 50378025Sdes sbuf_printf(sb, "%d", p->p_pid); 50478025Sdes#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg) 50567588Sdes PS_ADD("comm", "(%s)", p->p_comm); 50667588Sdes PS_ADD("statr", "%c", '0'); /* XXX */ 50773923Sjhb PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0); 50867588Sdes PS_ADD("pgrp", "%d", p->p_pgid); 50967588Sdes PS_ADD("session", "%d", p->p_session->s_sid); 51091140Stanimura PROC_UNLOCK(p); 51167588Sdes PS_ADD("tty", "%d", 0); /* XXX */ 51267588Sdes PS_ADD("tpgid", "%d", 0); /* XXX */ 51367588Sdes PS_ADD("flags", "%u", 0); /* XXX */ 51467588Sdes PS_ADD("minflt", "%u", 0); /* XXX */ 51567588Sdes PS_ADD("cminflt", "%u", 0); /* XXX */ 51667588Sdes PS_ADD("majflt", "%u", 0); /* XXX */ 51767588Sdes PS_ADD("cminflt", "%u", 0); /* XXX */ 51867588Sdes PS_ADD("utime", "%d", 0); /* XXX */ 51967588Sdes PS_ADD("stime", "%d", 0); /* XXX */ 52067588Sdes PS_ADD("cutime", "%d", 0); /* XXX */ 52167588Sdes PS_ADD("cstime", "%d", 0); /* XXX */ 52267588Sdes PS_ADD("counter", "%d", 0); /* XXX */ 52367588Sdes PS_ADD("priority", "%d", 0); /* XXX */ 52467588Sdes PS_ADD("timeout", "%u", 0); /* XXX */ 52567588Sdes PS_ADD("itrealvalue", "%u", 0); /* XXX */ 52667588Sdes PS_ADD("starttime", "%d", 0); /* XXX */ 527113574Sjhb PS_ADD("vsize", "%ju", (uintmax_t)kp.ki_size); 528113574Sjhb PS_ADD("rss", "%ju", P2K((uintmax_t)kp.ki_rssize)); 52967588Sdes PS_ADD("rlim", "%u", 0); /* XXX */ 53069995Sdes PS_ADD("startcode", "%u", (unsigned)0); 53167588Sdes PS_ADD("endcode", "%u", 0); /* XXX */ 53267588Sdes PS_ADD("startstack", "%u", 0); /* XXX */ 53369799Sdes PS_ADD("esp", "%u", 0); /* XXX */ 53469799Sdes PS_ADD("eip", "%u", 0); /* XXX */ 53567588Sdes PS_ADD("signal", "%d", 0); /* XXX */ 53667588Sdes PS_ADD("blocked", "%d", 0); /* XXX */ 53767588Sdes PS_ADD("sigignore", "%d", 0); /* XXX */ 53867588Sdes PS_ADD("sigcatch", "%d", 0); /* XXX */ 53967588Sdes PS_ADD("wchan", "%u", 0); /* XXX */ 54069799Sdes PS_ADD("nswap", "%lu", (long unsigned)0); /* XXX */ 54169799Sdes PS_ADD("cnswap", "%lu", (long unsigned)0); /* XXX */ 54269799Sdes PS_ADD("exitsignal", "%d", 0); /* XXX */ 54369799Sdes PS_ADD("processor", "%d", 0); /* XXX */ 54467588Sdes#undef PS_ADD 54578025Sdes sbuf_putc(sb, '\n'); 546119068Sdes 54778025Sdes return (0); 54867588Sdes} 54967588Sdes 55067588Sdes/* 551119911Sdes * Filler function for proc/pid/statm 552119911Sdes */ 553119911Sdesstatic int 554119911Sdeslinprocfs_doprocstatm(PFS_FILL_ARGS) 555119911Sdes{ 556119911Sdes struct kinfo_proc kp; 557119911Sdes segsz_t lsize; 558119911Sdes 559119911Sdes PROC_LOCK(p); 560119911Sdes fill_kinfo_proc(p, &kp); 561119911Sdes PROC_UNLOCK(p); 562119911Sdes 563119911Sdes /* 564119911Sdes * See comments in linprocfs_doprocstatus() regarding the 565119911Sdes * computation of lsize. 566119911Sdes */ 567119911Sdes /* size resident share trs drs lrs dt */ 568119911Sdes sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size)); 569119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize); 570119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */ 571119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize); 572119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize)); 573119911Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 574119911Sdes kp.ki_ssize - kp.ki_tsize - 1; 575119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)lsize); 576119911Sdes sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */ 577119911Sdes 578119911Sdes return (0); 579119911Sdes} 580119911Sdes 581119911Sdes/* 58278113Sdes * Filler function for proc/pid/status 58378113Sdes */ 58478025Sdesstatic int 58578025Sdeslinprocfs_doprocstatus(PFS_FILL_ARGS) 58667588Sdes{ 58769995Sdes struct kinfo_proc kp; 58867588Sdes char *state; 58969799Sdes segsz_t lsize; 59099072Sjulian struct thread *td2; 591114983Sjhb struct sigacts *ps; 59274135Sjlemon int i; 59367588Sdes 594113611Sjhb PROC_LOCK(p); 59599072Sjulian td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */ 59699072Sjulian 59799072Sjulian if (P_SHOULDSTOP(p)) { 59899072Sjulian state = "T (stopped)"; 59999072Sjulian } else { 600113611Sjhb mtx_lock_spin(&sched_lock); 60199072Sjulian switch(p->p_state) { 60299072Sjulian case PRS_NEW: 60399072Sjulian state = "I (idle)"; 60499072Sjulian break; 60599072Sjulian case PRS_NORMAL: 60699072Sjulian if (p->p_flag & P_WEXIT) { 60799072Sjulian state = "X (exiting)"; 60899072Sjulian break; 60999072Sjulian } 61099072Sjulian switch(td2->td_state) { 611103216Sjulian case TDS_INHIBITED: 61299072Sjulian state = "S (sleeping)"; 61399072Sjulian break; 61499072Sjulian case TDS_RUNQ: 61599072Sjulian case TDS_RUNNING: 61699072Sjulian state = "R (running)"; 61799072Sjulian break; 61899072Sjulian default: 61999072Sjulian state = "? (unknown)"; 62099072Sjulian break; 62199072Sjulian } 62299072Sjulian break; 62399072Sjulian case PRS_ZOMBIE: 62499072Sjulian state = "Z (zombie)"; 62599072Sjulian break; 62699072Sjulian default: 62799072Sjulian state = "? (unknown)"; 62899072Sjulian break; 62999072Sjulian } 630113611Sjhb mtx_unlock_spin(&sched_lock); 63199072Sjulian } 63267588Sdes 63369995Sdes fill_kinfo_proc(p, &kp); 63478025Sdes sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */ 63578031Sdes sbuf_printf(sb, "State:\t%s\n", state); 63667588Sdes 63767588Sdes /* 63867588Sdes * Credentials 63967588Sdes */ 64078025Sdes sbuf_printf(sb, "Pid:\t%d\n", p->p_pid); 64178025Sdes sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ? 64273923Sjhb p->p_pptr->p_pid : 0); 64378031Sdes sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid, 64478031Sdes p->p_ucred->cr_uid, 64578031Sdes p->p_ucred->cr_svuid, 64678031Sdes /* FreeBSD doesn't have fsuid */ 64778031Sdes p->p_ucred->cr_uid); 64878031Sdes sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid, 64978031Sdes p->p_ucred->cr_gid, 65078031Sdes p->p_ucred->cr_svgid, 65178031Sdes /* FreeBSD doesn't have fsgid */ 65278031Sdes p->p_ucred->cr_gid); 65378025Sdes sbuf_cat(sb, "Groups:\t"); 65467588Sdes for (i = 0; i < p->p_ucred->cr_ngroups; i++) 65578031Sdes sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]); 65671471Sjhb PROC_UNLOCK(p); 65778025Sdes sbuf_putc(sb, '\n'); 658119068Sdes 65967588Sdes /* 66067588Sdes * Memory 66169799Sdes * 66269799Sdes * While our approximation of VmLib may not be accurate (I 66369799Sdes * don't know of a simple way to verify it, and I'm not sure 66469799Sdes * it has much meaning anyway), I believe it's good enough. 66569799Sdes * 66669799Sdes * The same code that could (I think) accurately compute VmLib 66769799Sdes * could also compute VmLck, but I don't really care enough to 66869799Sdes * implement it. Submissions are welcome. 66967588Sdes */ 670113574Sjhb sbuf_printf(sb, "VmSize:\t%8ju kB\n", B2K((uintmax_t)kp.ki_size)); 67178025Sdes sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */ 672113574Sjhb sbuf_printf(sb, "VmRss:\t%8ju kB\n", P2K((uintmax_t)kp.ki_rssize)); 673113574Sjhb sbuf_printf(sb, "VmData:\t%8ju kB\n", P2K((uintmax_t)kp.ki_dsize)); 674113574Sjhb sbuf_printf(sb, "VmStk:\t%8ju kB\n", P2K((uintmax_t)kp.ki_ssize)); 675113574Sjhb sbuf_printf(sb, "VmExe:\t%8ju kB\n", P2K((uintmax_t)kp.ki_tsize)); 67669995Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 67769995Sdes kp.ki_ssize - kp.ki_tsize - 1; 678113574Sjhb sbuf_printf(sb, "VmLib:\t%8ju kB\n", P2K((uintmax_t)lsize)); 67967588Sdes 68067588Sdes /* 68167588Sdes * Signal masks 68267588Sdes * 68367588Sdes * We support up to 128 signals, while Linux supports 32, 68467588Sdes * but we only define 32 (the same 32 as Linux, to boot), so 68567588Sdes * just show the lower 32 bits of each mask. XXX hack. 68667588Sdes * 68767588Sdes * NB: on certain platforms (Sparc at least) Linux actually 68867588Sdes * supports 64 signals, but this code is a long way from 68967588Sdes * running on anything but i386, so ignore that for now. 69067588Sdes */ 69171471Sjhb PROC_LOCK(p); 692104306Sjmallett sbuf_printf(sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]); 69369799Sdes /* 69469799Sdes * I can't seem to find out where the signal mask is in 69569799Sdes * relation to struct proc, so SigBlk is left unimplemented. 69669799Sdes */ 69778025Sdes sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */ 698114983Sjhb ps = p->p_sigacts; 699114983Sjhb mtx_lock(&ps->ps_mtx); 700114983Sjhb sbuf_printf(sb, "SigIgn:\t%08x\n", ps->ps_sigignore.__bits[0]); 701114983Sjhb sbuf_printf(sb, "SigCgt:\t%08x\n", ps->ps_sigcatch.__bits[0]); 702114983Sjhb mtx_unlock(&ps->ps_mtx); 70371471Sjhb PROC_UNLOCK(p); 704119068Sdes 70567588Sdes /* 70667588Sdes * Linux also prints the capability masks, but we don't have 70767588Sdes * capabilities yet, and when we do get them they're likely to 70867588Sdes * be meaningless to Linux programs, so we lie. XXX 70967588Sdes */ 71078025Sdes sbuf_printf(sb, "CapInh:\t%016x\n", 0); 71178025Sdes sbuf_printf(sb, "CapPrm:\t%016x\n", 0); 71278025Sdes sbuf_printf(sb, "CapEff:\t%016x\n", 0); 713119068Sdes 71478025Sdes return (0); 71567588Sdes} 71674135Sjlemon 717119911Sdes 71878113Sdes/* 719119911Sdes * Filler function for proc/pid/cwd 720119911Sdes */ 721119911Sdesstatic int 722119911Sdeslinprocfs_doproccwd(PFS_FILL_ARGS) 723119911Sdes{ 724119911Sdes char *fullpath = "unknown"; 725119911Sdes char *freepath = NULL; 726119911Sdes 727119911Sdes vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath); 728119911Sdes sbuf_printf(sb, "%s", fullpath); 729119911Sdes if (freepath) 730119911Sdes free(freepath, M_TEMP); 731119911Sdes return (0); 732119911Sdes} 733119911Sdes 734119911Sdes/* 735119911Sdes * Filler function for proc/pid/root 736119911Sdes */ 737119911Sdesstatic int 738119911Sdeslinprocfs_doprocroot(PFS_FILL_ARGS) 739119911Sdes{ 740119911Sdes struct vnode *rvp; 741119911Sdes char *fullpath = "unknown"; 742119911Sdes char *freepath = NULL; 743119911Sdes 744119911Sdes rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir; 745119911Sdes vn_fullpath(td, rvp, &fullpath, &freepath); 746119911Sdes sbuf_printf(sb, "%s", fullpath); 747119911Sdes if (freepath) 748119911Sdes free(freepath, M_TEMP); 749119911Sdes return (0); 750119911Sdes} 751119911Sdes 752119911Sdes/* 75378113Sdes * Filler function for proc/pid/cmdline 75478113Sdes */ 75578025Sdesstatic int 75678113Sdeslinprocfs_doproccmdline(PFS_FILL_ARGS) 75778113Sdes{ 75878113Sdes struct ps_strings pstr; 75978113Sdes int error, i; 76078113Sdes 76178113Sdes /* 76278113Sdes * If we are using the ps/cmdline caching, use that. Otherwise 76378113Sdes * revert back to the old way which only implements full cmdline 76478113Sdes * for the currept process and just p->p_comm for all other 76578113Sdes * processes. 76678113Sdes * Note that if the argv is no longer available, we deliberately 76778113Sdes * don't fall back on p->p_comm or return an error: the authentic 76878113Sdes * Linux behaviour is to return zero-length in this case. 76978113Sdes */ 77078113Sdes 77194620Sjhb PROC_LOCK(p); 77296886Sjhb if (p->p_args && (ps_argsopen || !p_cansee(td, p))) { 77394620Sjhb sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length); 77494620Sjhb PROC_UNLOCK(p); 77594620Sjhb } else if (p != td->td_proc) { 77694620Sjhb PROC_UNLOCK(p); 77794620Sjhb sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm); 77894620Sjhb } else { 77994620Sjhb PROC_UNLOCK(p); 780103767Sjake error = copyin((void *)p->p_sysent->sv_psstrings, &pstr, 781103767Sjake sizeof(pstr)); 78294620Sjhb if (error) 78394620Sjhb return (error); 78494620Sjhb for (i = 0; i < pstr.ps_nargvstr; i++) { 78594620Sjhb sbuf_copyin(sb, pstr.ps_argvstr[i], 0); 78694620Sjhb sbuf_printf(sb, "%c", '\0'); 78778113Sdes } 78878113Sdes } 78978113Sdes 79078113Sdes return (0); 79178113Sdes} 79278113Sdes 79378113Sdes/* 794116173Sobrien * Filler function for proc/pid/environ 795116173Sobrien */ 796116173Sobrienstatic int 797116173Sobrienlinprocfs_doprocenviron(PFS_FILL_ARGS) 798116173Sobrien{ 799116173Sobrien sbuf_printf(sb, "doprocenviron\n%c", '\0'); 800116173Sobrien 801116173Sobrien return (0); 802116173Sobrien} 803116173Sobrien 804116173Sobrien/* 805116173Sobrien * Filler function for proc/pid/maps 806116173Sobrien */ 807116173Sobrienstatic int 808116173Sobrienlinprocfs_doprocmaps(PFS_FILL_ARGS) 809116173Sobrien{ 810116173Sobrien sbuf_printf(sb, "doprocmaps\n%c", '\0'); 811116173Sobrien 812116173Sobrien return (0); 813116173Sobrien} 814116173Sobrien 815116173Sobrien/* 81678113Sdes * Filler function for proc/net/dev 81778113Sdes */ 81878025Sdesstatic int 81978025Sdeslinprocfs_donetdev(PFS_FILL_ARGS) 82074135Sjlemon{ 82185129Sdes char ifname[16]; /* XXX LINUX_IFNAMSIZ */ 82274135Sjlemon struct ifnet *ifp; 82374135Sjlemon 82485129Sdes sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n", 82583926Sdes "Inter-", " Receive", " Transmit", " face", 82685129Sdes "bytes packets errs drop fifo frame compressed", 82783926Sdes "bytes packets errs drop fifo frame compressed"); 82874135Sjlemon 829108172Shsu IFNET_RLOCK(); 83074135Sjlemon TAILQ_FOREACH(ifp, &ifnet, if_link) { 83185129Sdes linux_ifname(ifp, ifname, sizeof ifname); 83285129Sdes sbuf_printf(sb, "%6.6s:", ifname); 83383926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ", 83483926Sdes 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); 83583926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", 83683926Sdes 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); 83774135Sjlemon } 838108172Shsu IFNET_RUNLOCK(); 839119068Sdes 84078025Sdes return (0); 84174135Sjlemon} 84274135Sjlemon 84385538Sphk#if 0 84485538Sphkextern struct cdevsw *cdevsw[]; 84585538Sphk 84678113Sdes/* 84778113Sdes * Filler function for proc/devices 84878113Sdes */ 84978025Sdesstatic int 85078025Sdeslinprocfs_dodevices(PFS_FILL_ARGS) 85174135Sjlemon{ 85274135Sjlemon int i; 85374135Sjlemon 85478025Sdes sbuf_printf(sb, "Character devices:\n"); 85574135Sjlemon 85678025Sdes for (i = 0; i < NUMCDEVSW; i++) 85774135Sjlemon if (cdevsw[i] != NULL) 85878025Sdes sbuf_printf(sb, "%3d %s\n", i, cdevsw[i]->d_name); 85974135Sjlemon 86078025Sdes sbuf_printf(sb, "\nBlock devices:\n"); 861119068Sdes 86278025Sdes return (0); 86374135Sjlemon} 86485538Sphk#endif 86574135Sjlemon 86678113Sdes/* 86778113Sdes * Filler function for proc/cmdline 86878113Sdes */ 86978025Sdesstatic int 87078025Sdeslinprocfs_docmdline(PFS_FILL_ARGS) 87174135Sjlemon{ 87278025Sdes sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname); 87378025Sdes sbuf_printf(sb, " ro root=302\n"); 87478025Sdes return (0); 87578025Sdes} 87674135Sjlemon 87783926Sdes#if 0 87878025Sdes/* 87983926Sdes * Filler function for proc/modules 88083926Sdes */ 88183926Sdesstatic int 88283926Sdeslinprocfs_domodules(PFS_FILL_ARGS) 88383926Sdes{ 88483926Sdes struct linker_file *lf; 885119068Sdes 88683926Sdes TAILQ_FOREACH(lf, &linker_files, link) { 88783926Sdes sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename, 88883926Sdes (unsigned long)lf->size, lf->refs); 88983926Sdes } 89083926Sdes return (0); 89183926Sdes} 89283926Sdes#endif 89383926Sdes 89483926Sdes/* 89585129Sdes * Constructor 89678025Sdes */ 89785129Sdesstatic int 89885129Sdeslinprocfs_init(PFS_INIT_ARGS) 89985129Sdes{ 90085129Sdes struct pfs_node *root; 90185129Sdes struct pfs_node *dir; 90274135Sjlemon 90385129Sdes root = pi->pi_root; 90478025Sdes 905119923Sdes /* /proc/... */ 906119911Sdes pfs_create_file(root, "cmdline", &linprocfs_docmdline, 907119911Sdes NULL, NULL, PFS_RD); 908119911Sdes pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo, 909119911Sdes NULL, NULL, PFS_RD); 91085538Sphk#if 0 911119911Sdes pfs_create_file(root, "devices", &linprocfs_dodevices, 912119911Sdes NULL, NULL, PFS_RD); 91385538Sphk#endif 914119911Sdes pfs_create_file(root, "loadavg", &linprocfs_doloadavg, 915119911Sdes NULL, NULL, PFS_RD); 916119911Sdes pfs_create_file(root, "meminfo", &linprocfs_domeminfo, 917119911Sdes NULL, NULL, PFS_RD); 91883926Sdes#if 0 919119911Sdes pfs_create_file(root, "modules", &linprocfs_domodules, 920119911Sdes NULL, NULL, PFS_RD); 92183926Sdes#endif 922119911Sdes pfs_create_file(root, "mtab", &linprocfs_domtab, 923119911Sdes NULL, NULL, PFS_RD); 92487543Sdes pfs_create_link(root, "self", &procfs_docurproc, 92585129Sdes NULL, NULL, 0); 926119911Sdes pfs_create_file(root, "stat", &linprocfs_dostat, 927119911Sdes NULL, NULL, PFS_RD); 928119911Sdes pfs_create_file(root, "uptime", &linprocfs_douptime, 929119911Sdes NULL, NULL, PFS_RD); 930119911Sdes pfs_create_file(root, "version", &linprocfs_doversion, 931119911Sdes NULL, NULL, PFS_RD); 93278025Sdes 933119923Sdes /* /proc/net/... */ 93485129Sdes dir = pfs_create_dir(root, "net", NULL, NULL, 0); 93585129Sdes pfs_create_file(dir, "dev", &linprocfs_donetdev, 93685129Sdes NULL, NULL, PFS_RD); 93778025Sdes 938119923Sdes /* /proc/<pid>/... */ 93985129Sdes dir = pfs_create_dir(root, "pid", NULL, NULL, PFS_PROCDEP); 94085129Sdes pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline, 94185129Sdes NULL, NULL, PFS_RD); 942119911Sdes pfs_create_link(dir, "cwd", &linprocfs_doproccwd, 943119911Sdes NULL, NULL, 0); 944116173Sobrien pfs_create_file(dir, "environ", &linprocfs_doprocenviron, 945116173Sobrien NULL, NULL, PFS_RD); 94687543Sdes pfs_create_link(dir, "exe", &procfs_doprocfile, 94787543Sdes NULL, &procfs_notsystem, 0); 948116173Sobrien pfs_create_file(dir, "maps", &linprocfs_doprocmaps, 949116173Sobrien NULL, NULL, PFS_RD); 95085129Sdes pfs_create_file(dir, "mem", &procfs_doprocmem, 95185129Sdes &procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW); 952119911Sdes pfs_create_link(dir, "root", &linprocfs_doprocroot, 953119911Sdes NULL, NULL, 0); 95485129Sdes pfs_create_file(dir, "stat", &linprocfs_doprocstat, 95585129Sdes NULL, NULL, PFS_RD); 956119911Sdes pfs_create_file(dir, "statm", &linprocfs_doprocstatm, 957119911Sdes NULL, NULL, PFS_RD); 95885129Sdes pfs_create_file(dir, "status", &linprocfs_doprocstatus, 95985129Sdes NULL, NULL, PFS_RD); 96085129Sdes 96185129Sdes return (0); 96285129Sdes} 96385129Sdes 96485129Sdes/* 96585129Sdes * Destructor 96685129Sdes */ 96785129Sdesstatic int 96885129Sdeslinprocfs_uninit(PFS_INIT_ARGS) 96985129Sdes{ 97085129Sdes 97185129Sdes /* nothing to do, pseudofs will GC */ 97285129Sdes return (0); 97385129Sdes} 97485129Sdes 97585129SdesPSEUDOFS(linprocfs, 1); 97678025SdesMODULE_DEPEND(linprocfs, linux, 1, 1, 1); 97778025SdesMODULE_DEPEND(linprocfs, procfs, 1, 1, 1); 978