linprocfs.c revision 120339
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 120339 2003-09-22 15:52:32Z 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{ 416120339Sdes int name[2], olen, plen; 417120339Sdes int i, ncpu; 418120339Sdes 419120339Sdes name[0] = CTL_HW; 420120339Sdes name[1] = HW_NCPU; 421120339Sdes if (kernel_sysctl(td, name, 2, &ncpu, &olen, NULL, 0, &plen) != 0) 422120339Sdes ncpu = 0; 423120339Sdes sbuf_printf(sb, "cpu %ld %ld %ld %ld\n", 424120339Sdes T2J(cp_time[CP_USER]), 425120339Sdes T2J(cp_time[CP_NICE]), 426120339Sdes T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/), 427120339Sdes T2J(cp_time[CP_IDLE])); 428120339Sdes for (i = 0; i < ncpu; ++i) 429120339Sdes sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i, 430120339Sdes T2J(cp_time[CP_USER]) / ncpu, 431120339Sdes T2J(cp_time[CP_NICE]) / ncpu, 432120339Sdes T2J(cp_time[CP_SYS]) / ncpu, 433120339Sdes T2J(cp_time[CP_IDLE]) / ncpu); 43478025Sdes sbuf_printf(sb, 43569799Sdes "disk 0 0 0 0\n" 43669799Sdes "page %u %u\n" 43769799Sdes "swap %u %u\n" 43869799Sdes "intr %u\n" 43969799Sdes "ctxt %u\n" 44085657Sdillon "btime %lld\n", 44169799Sdes cnt.v_vnodepgsin, 44269799Sdes cnt.v_vnodepgsout, 44369799Sdes cnt.v_swappgsin, 44469799Sdes cnt.v_swappgsout, 44569799Sdes cnt.v_intr, 44669799Sdes cnt.v_swtch, 447113574Sjhb (long long)boottime.tv_sec); 44878025Sdes return (0); 44965633Sdes} 45065633Sdes 45178113Sdes/* 45278113Sdes * Filler function for proc/uptime 45378113Sdes */ 45478025Sdesstatic int 45578025Sdeslinprocfs_douptime(PFS_FILL_ARGS) 45665633Sdes{ 45765633Sdes struct timeval tv; 45865633Sdes 45965633Sdes getmicrouptime(&tv); 46085657Sdillon sbuf_printf(sb, "%lld.%02ld %ld.%02ld\n", 461113574Sjhb (long long)tv.tv_sec, tv.tv_usec / 10000, 46269799Sdes T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100); 46378025Sdes return (0); 46465633Sdes} 46565633Sdes 46678113Sdes/* 46778113Sdes * Filler function for proc/version 46878113Sdes */ 46978025Sdesstatic int 47078025Sdeslinprocfs_doversion(PFS_FILL_ARGS) 47165633Sdes{ 47287275Srwatson char osname[LINUX_MAX_UTSNAME]; 47387275Srwatson char osrelease[LINUX_MAX_UTSNAME]; 47487275Srwatson 475112206Sjhb linux_get_osname(td, osname); 476112206Sjhb linux_get_osrelease(td, osrelease); 47787275Srwatson 47878025Sdes sbuf_printf(sb, 47969995Sdes "%s version %s (des@freebsd.org) (gcc version " __VERSION__ ")" 48087275Srwatson " #4 Sun Dec 18 04:30:00 CET 1977\n", osname, osrelease); 48178025Sdes return (0); 48265633Sdes} 48365633Sdes 48478113Sdes/* 48578113Sdes * Filler function for proc/loadavg 48678113Sdes */ 48778025Sdesstatic int 48878025Sdeslinprocfs_doloadavg(PFS_FILL_ARGS) 48976839Sjlemon{ 49078025Sdes sbuf_printf(sb, 49176839Sjlemon "%d.%02d %d.%02d %d.%02d %d/%d %d\n", 49276839Sjlemon (int)(averunnable.ldavg[0] / averunnable.fscale), 49376839Sjlemon (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100), 49476839Sjlemon (int)(averunnable.ldavg[1] / averunnable.fscale), 49576839Sjlemon (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100), 49676839Sjlemon (int)(averunnable.ldavg[2] / averunnable.fscale), 49776839Sjlemon (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100), 49876839Sjlemon 1, /* number of running tasks */ 49976839Sjlemon nprocs, /* number of tasks */ 50078116Sdes lastpid /* the last pid */ 50176839Sjlemon ); 502119068Sdes 50378025Sdes return (0); 50476839Sjlemon} 50576839Sjlemon 50678113Sdes/* 50778113Sdes * Filler function for proc/pid/stat 50878113Sdes */ 50978025Sdesstatic int 51078025Sdeslinprocfs_doprocstat(PFS_FILL_ARGS) 51167588Sdes{ 51269995Sdes struct kinfo_proc kp; 51367588Sdes 51494307Sjhb PROC_LOCK(p); 51569995Sdes fill_kinfo_proc(p, &kp); 51678025Sdes sbuf_printf(sb, "%d", p->p_pid); 51778025Sdes#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg) 51867588Sdes PS_ADD("comm", "(%s)", p->p_comm); 51967588Sdes PS_ADD("statr", "%c", '0'); /* XXX */ 52073923Sjhb PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0); 52167588Sdes PS_ADD("pgrp", "%d", p->p_pgid); 52267588Sdes PS_ADD("session", "%d", p->p_session->s_sid); 52391140Stanimura PROC_UNLOCK(p); 52467588Sdes PS_ADD("tty", "%d", 0); /* XXX */ 52567588Sdes PS_ADD("tpgid", "%d", 0); /* XXX */ 52667588Sdes PS_ADD("flags", "%u", 0); /* XXX */ 52767588Sdes PS_ADD("minflt", "%u", 0); /* XXX */ 52867588Sdes PS_ADD("cminflt", "%u", 0); /* XXX */ 52967588Sdes PS_ADD("majflt", "%u", 0); /* XXX */ 53067588Sdes PS_ADD("cminflt", "%u", 0); /* XXX */ 53167588Sdes PS_ADD("utime", "%d", 0); /* XXX */ 53267588Sdes PS_ADD("stime", "%d", 0); /* XXX */ 53367588Sdes PS_ADD("cutime", "%d", 0); /* XXX */ 53467588Sdes PS_ADD("cstime", "%d", 0); /* XXX */ 53567588Sdes PS_ADD("counter", "%d", 0); /* XXX */ 53667588Sdes PS_ADD("priority", "%d", 0); /* XXX */ 53767588Sdes PS_ADD("timeout", "%u", 0); /* XXX */ 53867588Sdes PS_ADD("itrealvalue", "%u", 0); /* XXX */ 53967588Sdes PS_ADD("starttime", "%d", 0); /* XXX */ 540113574Sjhb PS_ADD("vsize", "%ju", (uintmax_t)kp.ki_size); 541113574Sjhb PS_ADD("rss", "%ju", P2K((uintmax_t)kp.ki_rssize)); 54267588Sdes PS_ADD("rlim", "%u", 0); /* XXX */ 54369995Sdes PS_ADD("startcode", "%u", (unsigned)0); 54467588Sdes PS_ADD("endcode", "%u", 0); /* XXX */ 54567588Sdes PS_ADD("startstack", "%u", 0); /* XXX */ 54669799Sdes PS_ADD("esp", "%u", 0); /* XXX */ 54769799Sdes PS_ADD("eip", "%u", 0); /* XXX */ 54867588Sdes PS_ADD("signal", "%d", 0); /* XXX */ 54967588Sdes PS_ADD("blocked", "%d", 0); /* XXX */ 55067588Sdes PS_ADD("sigignore", "%d", 0); /* XXX */ 55167588Sdes PS_ADD("sigcatch", "%d", 0); /* XXX */ 55267588Sdes PS_ADD("wchan", "%u", 0); /* XXX */ 55369799Sdes PS_ADD("nswap", "%lu", (long unsigned)0); /* XXX */ 55469799Sdes PS_ADD("cnswap", "%lu", (long unsigned)0); /* XXX */ 55569799Sdes PS_ADD("exitsignal", "%d", 0); /* XXX */ 55669799Sdes PS_ADD("processor", "%d", 0); /* XXX */ 55767588Sdes#undef PS_ADD 55878025Sdes sbuf_putc(sb, '\n'); 559119068Sdes 56078025Sdes return (0); 56167588Sdes} 56267588Sdes 56367588Sdes/* 564119911Sdes * Filler function for proc/pid/statm 565119911Sdes */ 566119911Sdesstatic int 567119911Sdeslinprocfs_doprocstatm(PFS_FILL_ARGS) 568119911Sdes{ 569119911Sdes struct kinfo_proc kp; 570119911Sdes segsz_t lsize; 571119911Sdes 572119911Sdes PROC_LOCK(p); 573119911Sdes fill_kinfo_proc(p, &kp); 574119911Sdes PROC_UNLOCK(p); 575119911Sdes 576119911Sdes /* 577119911Sdes * See comments in linprocfs_doprocstatus() regarding the 578119911Sdes * computation of lsize. 579119911Sdes */ 580119911Sdes /* size resident share trs drs lrs dt */ 581119911Sdes sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size)); 582119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize); 583119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */ 584119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize); 585119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize)); 586119911Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 587119911Sdes kp.ki_ssize - kp.ki_tsize - 1; 588119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)lsize); 589119911Sdes sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */ 590119911Sdes 591119911Sdes return (0); 592119911Sdes} 593119911Sdes 594119911Sdes/* 59578113Sdes * Filler function for proc/pid/status 59678113Sdes */ 59778025Sdesstatic int 59878025Sdeslinprocfs_doprocstatus(PFS_FILL_ARGS) 59967588Sdes{ 60069995Sdes struct kinfo_proc kp; 60167588Sdes char *state; 60269799Sdes segsz_t lsize; 60399072Sjulian struct thread *td2; 604114983Sjhb struct sigacts *ps; 60574135Sjlemon int i; 60667588Sdes 607113611Sjhb PROC_LOCK(p); 60899072Sjulian td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */ 60999072Sjulian 61099072Sjulian if (P_SHOULDSTOP(p)) { 61199072Sjulian state = "T (stopped)"; 61299072Sjulian } else { 613113611Sjhb mtx_lock_spin(&sched_lock); 61499072Sjulian switch(p->p_state) { 61599072Sjulian case PRS_NEW: 61699072Sjulian state = "I (idle)"; 61799072Sjulian break; 61899072Sjulian case PRS_NORMAL: 61999072Sjulian if (p->p_flag & P_WEXIT) { 62099072Sjulian state = "X (exiting)"; 62199072Sjulian break; 62299072Sjulian } 62399072Sjulian switch(td2->td_state) { 624103216Sjulian case TDS_INHIBITED: 62599072Sjulian state = "S (sleeping)"; 62699072Sjulian break; 62799072Sjulian case TDS_RUNQ: 62899072Sjulian case TDS_RUNNING: 62999072Sjulian state = "R (running)"; 63099072Sjulian break; 63199072Sjulian default: 63299072Sjulian state = "? (unknown)"; 63399072Sjulian break; 63499072Sjulian } 63599072Sjulian break; 63699072Sjulian case PRS_ZOMBIE: 63799072Sjulian state = "Z (zombie)"; 63899072Sjulian break; 63999072Sjulian default: 64099072Sjulian state = "? (unknown)"; 64199072Sjulian break; 64299072Sjulian } 643113611Sjhb mtx_unlock_spin(&sched_lock); 64499072Sjulian } 64567588Sdes 64669995Sdes fill_kinfo_proc(p, &kp); 64778025Sdes sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */ 64878031Sdes sbuf_printf(sb, "State:\t%s\n", state); 64967588Sdes 65067588Sdes /* 65167588Sdes * Credentials 65267588Sdes */ 65378025Sdes sbuf_printf(sb, "Pid:\t%d\n", p->p_pid); 65478025Sdes sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ? 65573923Sjhb p->p_pptr->p_pid : 0); 65678031Sdes sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid, 65778031Sdes p->p_ucred->cr_uid, 65878031Sdes p->p_ucred->cr_svuid, 65978031Sdes /* FreeBSD doesn't have fsuid */ 66078031Sdes p->p_ucred->cr_uid); 66178031Sdes sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid, 66278031Sdes p->p_ucred->cr_gid, 66378031Sdes p->p_ucred->cr_svgid, 66478031Sdes /* FreeBSD doesn't have fsgid */ 66578031Sdes p->p_ucred->cr_gid); 66678025Sdes sbuf_cat(sb, "Groups:\t"); 66767588Sdes for (i = 0; i < p->p_ucred->cr_ngroups; i++) 66878031Sdes sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]); 66971471Sjhb PROC_UNLOCK(p); 67078025Sdes sbuf_putc(sb, '\n'); 671119068Sdes 67267588Sdes /* 67367588Sdes * Memory 67469799Sdes * 67569799Sdes * While our approximation of VmLib may not be accurate (I 67669799Sdes * don't know of a simple way to verify it, and I'm not sure 67769799Sdes * it has much meaning anyway), I believe it's good enough. 67869799Sdes * 67969799Sdes * The same code that could (I think) accurately compute VmLib 68069799Sdes * could also compute VmLck, but I don't really care enough to 68169799Sdes * implement it. Submissions are welcome. 68267588Sdes */ 683113574Sjhb sbuf_printf(sb, "VmSize:\t%8ju kB\n", B2K((uintmax_t)kp.ki_size)); 68478025Sdes sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */ 685113574Sjhb sbuf_printf(sb, "VmRss:\t%8ju kB\n", P2K((uintmax_t)kp.ki_rssize)); 686113574Sjhb sbuf_printf(sb, "VmData:\t%8ju kB\n", P2K((uintmax_t)kp.ki_dsize)); 687113574Sjhb sbuf_printf(sb, "VmStk:\t%8ju kB\n", P2K((uintmax_t)kp.ki_ssize)); 688113574Sjhb sbuf_printf(sb, "VmExe:\t%8ju kB\n", P2K((uintmax_t)kp.ki_tsize)); 68969995Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 69069995Sdes kp.ki_ssize - kp.ki_tsize - 1; 691113574Sjhb sbuf_printf(sb, "VmLib:\t%8ju kB\n", P2K((uintmax_t)lsize)); 69267588Sdes 69367588Sdes /* 69467588Sdes * Signal masks 69567588Sdes * 69667588Sdes * We support up to 128 signals, while Linux supports 32, 69767588Sdes * but we only define 32 (the same 32 as Linux, to boot), so 69867588Sdes * just show the lower 32 bits of each mask. XXX hack. 69967588Sdes * 70067588Sdes * NB: on certain platforms (Sparc at least) Linux actually 70167588Sdes * supports 64 signals, but this code is a long way from 70267588Sdes * running on anything but i386, so ignore that for now. 70367588Sdes */ 70471471Sjhb PROC_LOCK(p); 705104306Sjmallett sbuf_printf(sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]); 70669799Sdes /* 70769799Sdes * I can't seem to find out where the signal mask is in 70869799Sdes * relation to struct proc, so SigBlk is left unimplemented. 70969799Sdes */ 71078025Sdes sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */ 711114983Sjhb ps = p->p_sigacts; 712114983Sjhb mtx_lock(&ps->ps_mtx); 713114983Sjhb sbuf_printf(sb, "SigIgn:\t%08x\n", ps->ps_sigignore.__bits[0]); 714114983Sjhb sbuf_printf(sb, "SigCgt:\t%08x\n", ps->ps_sigcatch.__bits[0]); 715114983Sjhb mtx_unlock(&ps->ps_mtx); 71671471Sjhb PROC_UNLOCK(p); 717119068Sdes 71867588Sdes /* 71967588Sdes * Linux also prints the capability masks, but we don't have 72067588Sdes * capabilities yet, and when we do get them they're likely to 72167588Sdes * be meaningless to Linux programs, so we lie. XXX 72267588Sdes */ 72378025Sdes sbuf_printf(sb, "CapInh:\t%016x\n", 0); 72478025Sdes sbuf_printf(sb, "CapPrm:\t%016x\n", 0); 72578025Sdes sbuf_printf(sb, "CapEff:\t%016x\n", 0); 726119068Sdes 72778025Sdes return (0); 72867588Sdes} 72974135Sjlemon 730119911Sdes 73178113Sdes/* 732119911Sdes * Filler function for proc/pid/cwd 733119911Sdes */ 734119911Sdesstatic int 735119911Sdeslinprocfs_doproccwd(PFS_FILL_ARGS) 736119911Sdes{ 737119911Sdes char *fullpath = "unknown"; 738119911Sdes char *freepath = NULL; 739119911Sdes 740119911Sdes vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath); 741119911Sdes sbuf_printf(sb, "%s", fullpath); 742119911Sdes if (freepath) 743119911Sdes free(freepath, M_TEMP); 744119911Sdes return (0); 745119911Sdes} 746119911Sdes 747119911Sdes/* 748119911Sdes * Filler function for proc/pid/root 749119911Sdes */ 750119911Sdesstatic int 751119911Sdeslinprocfs_doprocroot(PFS_FILL_ARGS) 752119911Sdes{ 753119911Sdes struct vnode *rvp; 754119911Sdes char *fullpath = "unknown"; 755119911Sdes char *freepath = NULL; 756119911Sdes 757119911Sdes rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir; 758119911Sdes vn_fullpath(td, rvp, &fullpath, &freepath); 759119911Sdes sbuf_printf(sb, "%s", fullpath); 760119911Sdes if (freepath) 761119911Sdes free(freepath, M_TEMP); 762119911Sdes return (0); 763119911Sdes} 764119911Sdes 765119911Sdes/* 76678113Sdes * Filler function for proc/pid/cmdline 76778113Sdes */ 76878025Sdesstatic int 76978113Sdeslinprocfs_doproccmdline(PFS_FILL_ARGS) 77078113Sdes{ 77178113Sdes struct ps_strings pstr; 77278113Sdes int error, i; 77378113Sdes 77478113Sdes /* 77578113Sdes * If we are using the ps/cmdline caching, use that. Otherwise 77678113Sdes * revert back to the old way which only implements full cmdline 77778113Sdes * for the currept process and just p->p_comm for all other 77878113Sdes * processes. 77978113Sdes * Note that if the argv is no longer available, we deliberately 78078113Sdes * don't fall back on p->p_comm or return an error: the authentic 78178113Sdes * Linux behaviour is to return zero-length in this case. 78278113Sdes */ 78378113Sdes 78494620Sjhb PROC_LOCK(p); 78596886Sjhb if (p->p_args && (ps_argsopen || !p_cansee(td, p))) { 78694620Sjhb sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length); 78794620Sjhb PROC_UNLOCK(p); 78894620Sjhb } else if (p != td->td_proc) { 78994620Sjhb PROC_UNLOCK(p); 79094620Sjhb sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm); 79194620Sjhb } else { 79294620Sjhb PROC_UNLOCK(p); 793103767Sjake error = copyin((void *)p->p_sysent->sv_psstrings, &pstr, 794103767Sjake sizeof(pstr)); 79594620Sjhb if (error) 79694620Sjhb return (error); 79794620Sjhb for (i = 0; i < pstr.ps_nargvstr; i++) { 79894620Sjhb sbuf_copyin(sb, pstr.ps_argvstr[i], 0); 79994620Sjhb sbuf_printf(sb, "%c", '\0'); 80078113Sdes } 80178113Sdes } 80278113Sdes 80378113Sdes return (0); 80478113Sdes} 80578113Sdes 80678113Sdes/* 807116173Sobrien * Filler function for proc/pid/environ 808116173Sobrien */ 809116173Sobrienstatic int 810116173Sobrienlinprocfs_doprocenviron(PFS_FILL_ARGS) 811116173Sobrien{ 812116173Sobrien sbuf_printf(sb, "doprocenviron\n%c", '\0'); 813116173Sobrien 814116173Sobrien return (0); 815116173Sobrien} 816116173Sobrien 817116173Sobrien/* 818116173Sobrien * Filler function for proc/pid/maps 819116173Sobrien */ 820116173Sobrienstatic int 821116173Sobrienlinprocfs_doprocmaps(PFS_FILL_ARGS) 822116173Sobrien{ 823116173Sobrien sbuf_printf(sb, "doprocmaps\n%c", '\0'); 824116173Sobrien 825116173Sobrien return (0); 826116173Sobrien} 827116173Sobrien 828116173Sobrien/* 82978113Sdes * Filler function for proc/net/dev 83078113Sdes */ 83178025Sdesstatic int 83278025Sdeslinprocfs_donetdev(PFS_FILL_ARGS) 83374135Sjlemon{ 83485129Sdes char ifname[16]; /* XXX LINUX_IFNAMSIZ */ 83574135Sjlemon struct ifnet *ifp; 83674135Sjlemon 83785129Sdes sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n", 83883926Sdes "Inter-", " Receive", " Transmit", " face", 83985129Sdes "bytes packets errs drop fifo frame compressed", 84083926Sdes "bytes packets errs drop fifo frame compressed"); 84174135Sjlemon 842108172Shsu IFNET_RLOCK(); 84374135Sjlemon TAILQ_FOREACH(ifp, &ifnet, if_link) { 84485129Sdes linux_ifname(ifp, ifname, sizeof ifname); 84585129Sdes sbuf_printf(sb, "%6.6s:", ifname); 84683926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ", 84783926Sdes 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); 84883926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", 84983926Sdes 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); 85074135Sjlemon } 851108172Shsu IFNET_RUNLOCK(); 852119068Sdes 85378025Sdes return (0); 85474135Sjlemon} 85574135Sjlemon 85685538Sphk#if 0 85785538Sphkextern struct cdevsw *cdevsw[]; 85885538Sphk 85978113Sdes/* 86078113Sdes * Filler function for proc/devices 86178113Sdes */ 86278025Sdesstatic int 86378025Sdeslinprocfs_dodevices(PFS_FILL_ARGS) 86474135Sjlemon{ 86574135Sjlemon int i; 86674135Sjlemon 86778025Sdes sbuf_printf(sb, "Character devices:\n"); 86874135Sjlemon 86978025Sdes for (i = 0; i < NUMCDEVSW; i++) 87074135Sjlemon if (cdevsw[i] != NULL) 87178025Sdes sbuf_printf(sb, "%3d %s\n", i, cdevsw[i]->d_name); 87274135Sjlemon 87378025Sdes sbuf_printf(sb, "\nBlock devices:\n"); 874119068Sdes 87578025Sdes return (0); 87674135Sjlemon} 87785538Sphk#endif 87874135Sjlemon 87978113Sdes/* 88078113Sdes * Filler function for proc/cmdline 88178113Sdes */ 88278025Sdesstatic int 88378025Sdeslinprocfs_docmdline(PFS_FILL_ARGS) 88474135Sjlemon{ 88578025Sdes sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname); 88678025Sdes sbuf_printf(sb, " ro root=302\n"); 88778025Sdes return (0); 88878025Sdes} 88974135Sjlemon 89083926Sdes#if 0 89178025Sdes/* 89283926Sdes * Filler function for proc/modules 89383926Sdes */ 89483926Sdesstatic int 89583926Sdeslinprocfs_domodules(PFS_FILL_ARGS) 89683926Sdes{ 89783926Sdes struct linker_file *lf; 898119068Sdes 89983926Sdes TAILQ_FOREACH(lf, &linker_files, link) { 90083926Sdes sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename, 90183926Sdes (unsigned long)lf->size, lf->refs); 90283926Sdes } 90383926Sdes return (0); 90483926Sdes} 90583926Sdes#endif 90683926Sdes 90783926Sdes/* 90885129Sdes * Constructor 90978025Sdes */ 91085129Sdesstatic int 91185129Sdeslinprocfs_init(PFS_INIT_ARGS) 91285129Sdes{ 91385129Sdes struct pfs_node *root; 91485129Sdes struct pfs_node *dir; 91574135Sjlemon 91685129Sdes root = pi->pi_root; 91778025Sdes 918119923Sdes /* /proc/... */ 919119911Sdes pfs_create_file(root, "cmdline", &linprocfs_docmdline, 920119911Sdes NULL, NULL, PFS_RD); 921119911Sdes pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo, 922119911Sdes NULL, NULL, PFS_RD); 92385538Sphk#if 0 924119911Sdes pfs_create_file(root, "devices", &linprocfs_dodevices, 925119911Sdes NULL, NULL, PFS_RD); 92685538Sphk#endif 927119911Sdes pfs_create_file(root, "loadavg", &linprocfs_doloadavg, 928119911Sdes NULL, NULL, PFS_RD); 929119911Sdes pfs_create_file(root, "meminfo", &linprocfs_domeminfo, 930119911Sdes NULL, NULL, PFS_RD); 93183926Sdes#if 0 932119911Sdes pfs_create_file(root, "modules", &linprocfs_domodules, 933119911Sdes NULL, NULL, PFS_RD); 93483926Sdes#endif 935119911Sdes pfs_create_file(root, "mtab", &linprocfs_domtab, 936119911Sdes NULL, NULL, PFS_RD); 93787543Sdes pfs_create_link(root, "self", &procfs_docurproc, 93885129Sdes NULL, NULL, 0); 939119911Sdes pfs_create_file(root, "stat", &linprocfs_dostat, 940119911Sdes NULL, NULL, PFS_RD); 941119911Sdes pfs_create_file(root, "uptime", &linprocfs_douptime, 942119911Sdes NULL, NULL, PFS_RD); 943119911Sdes pfs_create_file(root, "version", &linprocfs_doversion, 944119911Sdes NULL, NULL, PFS_RD); 94578025Sdes 946119923Sdes /* /proc/net/... */ 94785129Sdes dir = pfs_create_dir(root, "net", NULL, NULL, 0); 94885129Sdes pfs_create_file(dir, "dev", &linprocfs_donetdev, 94985129Sdes NULL, NULL, PFS_RD); 95078025Sdes 951119923Sdes /* /proc/<pid>/... */ 95285129Sdes dir = pfs_create_dir(root, "pid", NULL, NULL, PFS_PROCDEP); 95385129Sdes pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline, 95485129Sdes NULL, NULL, PFS_RD); 955119911Sdes pfs_create_link(dir, "cwd", &linprocfs_doproccwd, 956119911Sdes NULL, NULL, 0); 957116173Sobrien pfs_create_file(dir, "environ", &linprocfs_doprocenviron, 958116173Sobrien NULL, NULL, PFS_RD); 95987543Sdes pfs_create_link(dir, "exe", &procfs_doprocfile, 96087543Sdes NULL, &procfs_notsystem, 0); 961116173Sobrien pfs_create_file(dir, "maps", &linprocfs_doprocmaps, 962116173Sobrien NULL, NULL, PFS_RD); 96385129Sdes pfs_create_file(dir, "mem", &procfs_doprocmem, 96485129Sdes &procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW); 965119911Sdes pfs_create_link(dir, "root", &linprocfs_doprocroot, 966119911Sdes NULL, NULL, 0); 96785129Sdes pfs_create_file(dir, "stat", &linprocfs_doprocstat, 96885129Sdes NULL, NULL, PFS_RD); 969119911Sdes pfs_create_file(dir, "statm", &linprocfs_doprocstatm, 970119911Sdes NULL, NULL, PFS_RD); 97185129Sdes pfs_create_file(dir, "status", &linprocfs_doprocstatus, 97285129Sdes NULL, NULL, PFS_RD); 97385129Sdes 97485129Sdes return (0); 97585129Sdes} 97685129Sdes 97785129Sdes/* 97885129Sdes * Destructor 97985129Sdes */ 98085129Sdesstatic int 98185129Sdeslinprocfs_uninit(PFS_INIT_ARGS) 98285129Sdes{ 98385129Sdes 98485129Sdes /* nothing to do, pseudofs will GC */ 98585129Sdes return (0); 98685129Sdes} 98785129Sdes 98885129SdesPSEUDOFS(linprocfs, 1); 98978025SdesMODULE_DEPEND(linprocfs, linux, 1, 1, 1); 99078025SdesMODULE_DEPEND(linprocfs, procfs, 1, 1, 1); 991