linprocfs.c revision 127694
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 127694 2004-04-01 00:04:23Z pjd $"); 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 8278113Sdes#ifdef __alpha__ 8378113Sdes#include <machine/alpha_cpu.h> 8478113Sdes#include <machine/cpuconf.h> 8578113Sdes#include <machine/rpb.h> 8678113Sdesextern int ncpus; 8778113Sdes#endif /* __alpha__ */ 8878113Sdes 8978113Sdes#ifdef __i386__ 9067589Sdes#include <machine/cputypes.h> 9159412Smsmith#include <machine/md_var.h> 9278113Sdes#endif /* __i386__ */ 9359412Smsmith 9487275Srwatson#include <machine/../linux/linux.h> 9585129Sdes#include <compat/linux/linux_ioctl.h> 9669995Sdes#include <compat/linux/linux_mib.h> 9785289Sdes#include <compat/linux/linux_util.h> 9878025Sdes#include <fs/pseudofs/pseudofs.h> 9984248Sdes#include <fs/procfs/procfs.h> 10059412Smsmith 10167588Sdes/* 10267588Sdes * Various conversion macros 10367588Sdes */ 10476405Sdes#define T2J(x) (((x) * 100UL) / (stathz ? stathz : hz)) /* ticks to jiffies */ 10567588Sdes#define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */ 10667588Sdes#define B2K(x) ((x) >> 10) /* bytes to kbytes */ 10769799Sdes#define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */ 10867588Sdes#define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */ 10967588Sdes#define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */ 11074135Sjlemon 11178113Sdes/* 11278113Sdes * Filler function for proc/meminfo 11378113Sdes */ 11478025Sdesstatic int 11578025Sdeslinprocfs_domeminfo(PFS_FILL_ARGS) 11659412Smsmith{ 11759412Smsmith unsigned long memtotal; /* total memory in bytes */ 11859412Smsmith unsigned long memused; /* used memory in bytes */ 11959412Smsmith unsigned long memfree; /* free memory in bytes */ 12059412Smsmith unsigned long memshared; /* shared memory ??? */ 12159412Smsmith unsigned long buffers, cached; /* buffer / cache memory ??? */ 122113574Sjhb unsigned long long swaptotal; /* total swap space in bytes */ 123113574Sjhb unsigned long long swapused; /* used swap space in bytes */ 124113574Sjhb unsigned long long swapfree; /* free swap space in bytes */ 12560860Sdes vm_object_t object; 126117723Sphk int i, j; 12759412Smsmith 12859412Smsmith memtotal = physmem * PAGE_SIZE; 12959412Smsmith /* 13059412Smsmith * The correct thing here would be: 13159412Smsmith * 13259412Smsmith memfree = cnt.v_free_count * PAGE_SIZE; 13359412Smsmith memused = memtotal - memfree; 13459412Smsmith * 13559412Smsmith * but it might mislead linux binaries into thinking there 13659412Smsmith * is very little memory left, so we cheat and tell them that 13759412Smsmith * all memory that isn't wired down is free. 13859412Smsmith */ 13959412Smsmith memused = cnt.v_wire_count * PAGE_SIZE; 14059412Smsmith memfree = memtotal - memused; 141117723Sphk swap_pager_status(&i, &j); 142117723Sphk swaptotal = i * PAGE_SIZE; 143117723Sphk swapused = j * PAGE_SIZE; 144117723Sphk swapfree = swaptotal - swapused; 14560860Sdes memshared = 0; 146124082Salc mtx_lock(&vm_object_list_mtx); 14771471Sjhb TAILQ_FOREACH(object, &vm_object_list, object_list) 14860860Sdes if (object->shadow_count > 1) 14960860Sdes memshared += object->resident_page_count; 150124082Salc mtx_unlock(&vm_object_list_mtx); 15160860Sdes memshared *= PAGE_SIZE; 15259412Smsmith /* 15359412Smsmith * We'd love to be able to write: 15459412Smsmith * 15559412Smsmith buffers = bufspace; 15659412Smsmith * 15759412Smsmith * but bufspace is internal to vfs_bio.c and we don't feel 15859412Smsmith * like unstaticizing it just for linprocfs's sake. 15959412Smsmith */ 16059412Smsmith buffers = 0; 16159412Smsmith cached = cnt.v_cache_count * PAGE_SIZE; 16259412Smsmith 16378025Sdes sbuf_printf(sb, 16478031Sdes " total: used: free: shared: buffers: cached:\n" 16569799Sdes "Mem: %lu %lu %lu %lu %lu %lu\n" 16676839Sjlemon "Swap: %llu %llu %llu\n" 16769799Sdes "MemTotal: %9lu kB\n" 16869799Sdes "MemFree: %9lu kB\n" 16969799Sdes "MemShared:%9lu kB\n" 17069799Sdes "Buffers: %9lu kB\n" 17169799Sdes "Cached: %9lu kB\n" 17276839Sjlemon "SwapTotal:%9llu kB\n" 17376839Sjlemon "SwapFree: %9llu kB\n", 17469799Sdes memtotal, memused, memfree, memshared, buffers, cached, 17569799Sdes swaptotal, swapused, swapfree, 17669799Sdes B2K(memtotal), B2K(memfree), 17769799Sdes B2K(memshared), B2K(buffers), B2K(cached), 17869799Sdes B2K(swaptotal), B2K(swapfree)); 17959412Smsmith 18078025Sdes return (0); 18159412Smsmith} 18259412Smsmith 18378113Sdes#ifdef __alpha__ 184119008Smarcelextern struct rpb *hwrpb; 18578113Sdes/* 18678113Sdes * Filler function for proc/cpuinfo (Alpha version) 18778113Sdes */ 18878025Sdesstatic int 18978025Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS) 19059412Smsmith{ 19178113Sdes u_int64_t type, major; 19278113Sdes struct pcs *pcsp; 19378113Sdes const char *model, *sysname; 19478113Sdes 19578113Sdes static const char *cpuname[] = { 19678113Sdes "EV3", "EV4", "Simulate", "LCA4", "EV5", "EV45", "EV56", 19778113Sdes "EV6", "PCA56", "PCA57", "EV67", "EV68CB", "EV68AL" 19878113Sdes }; 19978113Sdes 20078113Sdes pcsp = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id); 20178113Sdes type = pcsp->pcs_proc_type; 20278113Sdes major = (type & PCS_PROC_MAJOR) >> PCS_PROC_MAJORSHIFT; 20378113Sdes if (major < sizeof(cpuname)/sizeof(char *)) { 20478113Sdes model = cpuname[major - 1]; 20578113Sdes } else { 20678113Sdes model = "unknown"; 20778113Sdes } 208119068Sdes 20978113Sdes sysname = alpha_dsr_sysname(); 210119068Sdes 21178113Sdes sbuf_printf(sb, 21278113Sdes "cpu\t\t\t: Alpha\n" 21378113Sdes "cpu model\t\t: %s\n" 21478113Sdes "cpu variation\t\t: %ld\n" 215113574Sjhb "cpu revision\t\t: %d\n" 21678113Sdes "cpu serial number\t: %s\n" 21778113Sdes "system type\t\t: %s\n" 21878113Sdes "system variation\t: %s\n" 219113574Sjhb "system revision\t\t: %d\n" 22078113Sdes "system serial number\t: %s\n" 22178113Sdes "cycle frequency [Hz]\t: %lu\n" 222113574Sjhb "timer frequency [Hz]\t: %u\n" 22378113Sdes "page size [bytes]\t: %ld\n" 22478113Sdes "phys. address bits\t: %ld\n" 22578113Sdes "max. addr. space #\t: %ld\n" 226113574Sjhb "BogoMIPS\t\t: %u.%02u\n" 227113574Sjhb "kernel unaligned acc\t: %d (pc=%x,va=%x)\n" 228113574Sjhb "user unaligned acc\t: %d (pc=%x,va=%x)\n" 22978113Sdes "platform string\t\t: %s\n" 23078113Sdes "cpus detected\t\t: %d\n" 23178113Sdes , 23278113Sdes model, 23378113Sdes pcsp->pcs_proc_var, 23478113Sdes *(int *)hwrpb->rpb_revision, 23578113Sdes " ", 23678113Sdes " ", 23778113Sdes "0", 23878113Sdes 0, 23978113Sdes " ", 24078113Sdes hwrpb->rpb_cc_freq, 24178113Sdes hz, 24278113Sdes hwrpb->rpb_page_size, 24378113Sdes hwrpb->rpb_phys_addr_size, 24478113Sdes hwrpb->rpb_max_asn, 24578113Sdes 0, 0, 24678113Sdes 0, 0, 0, 24778113Sdes 0, 0, 0, 24878113Sdes sysname, 24978113Sdes ncpus); 25078113Sdes return (0); 25178113Sdes} 25278113Sdes#endif /* __alpha__ */ 25378113Sdes 25478113Sdes#ifdef __i386__ 25578113Sdes/* 25678113Sdes * Filler function for proc/cpuinfo (i386 version) 25778113Sdes */ 25878113Sdesstatic int 25978113Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS) 26078113Sdes{ 261123246Sdes int class, fqmhz, fqkhz; 262118421Sdes int i; 26359412Smsmith 26469799Sdes /* 26578031Sdes * We default the flags to include all non-conflicting flags, 26678031Sdes * and the Intel versions of conflicting flags. 26769799Sdes */ 26878031Sdes static char *flags[] = { 26978031Sdes "fpu", "vme", "de", "pse", "tsc", 27078031Sdes "msr", "pae", "mce", "cx8", "apic", 27178031Sdes "sep", "sep", "mtrr", "pge", "mca", 27278031Sdes "cmov", "pat", "pse36", "pn", "b19", 27378031Sdes "b20", "b21", "mmxext", "mmx", "fxsr", 27478031Sdes "xmm", "b26", "b27", "b28", "b29", 27567589Sdes "3dnowext", "3dnow" 27667589Sdes }; 27767589Sdes 27859412Smsmith switch (cpu_class) { 27959412Smsmith case CPUCLASS_286: 28067589Sdes class = 2; 28159412Smsmith break; 28259412Smsmith case CPUCLASS_386: 28367589Sdes class = 3; 28459412Smsmith break; 28559412Smsmith case CPUCLASS_486: 28667589Sdes class = 4; 28759412Smsmith break; 28859412Smsmith case CPUCLASS_586: 28967589Sdes class = 5; 29059412Smsmith break; 29159412Smsmith case CPUCLASS_686: 29267589Sdes class = 6; 29359412Smsmith break; 29459412Smsmith default: 29578031Sdes class = 0; 29659412Smsmith break; 29759412Smsmith } 29859412Smsmith 299123246Sdes for (i = 0; i < mp_ncpus; ++i) { 300118421Sdes sbuf_printf(sb, 301118421Sdes "processor\t: %d\n" 302118421Sdes "vendor_id\t: %.20s\n" 303118421Sdes "cpu family\t: %d\n" 304118421Sdes "model\t\t: %d\n" 305118421Sdes "stepping\t: %d\n", 306118421Sdes i, cpu_vendor, class, cpu, cpu_id & 0xf); 307118421Sdes /* XXX per-cpu vendor / class / id? */ 308118421Sdes } 30959412Smsmith 31078031Sdes sbuf_cat(sb, 31178031Sdes "flags\t\t:"); 31267589Sdes 31378031Sdes if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) { 31467589Sdes flags[16] = "fcmov"; 31578031Sdes } else if (!strcmp(cpu_vendor, "CyrixInstead")) { 31667589Sdes flags[24] = "cxmmx"; 31778031Sdes } 318119068Sdes 31978031Sdes for (i = 0; i < 32; i++) 32067589Sdes if (cpu_feature & (1 << i)) 32178025Sdes sbuf_printf(sb, " %s", flags[i]); 32278025Sdes sbuf_cat(sb, "\n"); 32378031Sdes if (class >= 5) { 32469799Sdes fqmhz = (tsc_freq + 4999) / 1000000; 32569799Sdes fqkhz = ((tsc_freq + 4999) / 10000) % 100; 32678025Sdes sbuf_printf(sb, 32769799Sdes "cpu MHz\t\t: %d.%02d\n" 32869799Sdes "bogomips\t: %d.%02d\n", 32969799Sdes fqmhz, fqkhz, fqmhz, fqkhz); 33078031Sdes } 33169995Sdes 33278025Sdes return (0); 33359412Smsmith} 33478113Sdes#endif /* __i386__ */ 33565633Sdes 33678113Sdes/* 33785289Sdes * Filler function for proc/mtab 33885289Sdes * 33985289Sdes * This file doesn't exist in Linux' procfs, but is included here so 34085289Sdes * users can symlink /compat/linux/etc/mtab to /proc/mtab 34185289Sdes */ 34285289Sdesstatic int 34385289Sdeslinprocfs_domtab(PFS_FILL_ARGS) 34485289Sdes{ 34585289Sdes struct nameidata nd; 34685289Sdes struct mount *mp; 34791334Sjulian const char *lep; 34891334Sjulian char *dlep, *flep, *mntto, *mntfrom, *fstype; 34985289Sdes size_t lep_len; 35085289Sdes int error; 35185289Sdes 35285289Sdes /* resolve symlinks etc. in the emulation tree prefix */ 35385289Sdes NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td); 35485289Sdes flep = NULL; 355124407Srwatson if (namei(&nd) != 0 || vn_fullpath(td, nd.ni_vp, &dlep, &flep) != 0) 35685289Sdes lep = linux_emul_path; 35791334Sjulian else 35891334Sjulian lep = dlep; 35985289Sdes lep_len = strlen(lep); 360119068Sdes 36185289Sdes mtx_lock(&mountlist_mtx); 36285289Sdes error = 0; 36385289Sdes TAILQ_FOREACH(mp, &mountlist, mnt_list) { 36485289Sdes /* determine device name */ 36585289Sdes mntfrom = mp->mnt_stat.f_mntfromname; 366119068Sdes 36785289Sdes /* determine mount point */ 36885289Sdes mntto = mp->mnt_stat.f_mntonname; 36985289Sdes if (strncmp(mntto, lep, lep_len) == 0 && 37085289Sdes mntto[lep_len] == '/') 37185289Sdes mntto += lep_len; 37285289Sdes 37385289Sdes /* determine fs type */ 37485289Sdes fstype = mp->mnt_stat.f_fstypename; 37585289Sdes if (strcmp(fstype, pn->pn_info->pi_name) == 0) 37685289Sdes mntfrom = fstype = "proc"; 37785289Sdes else if (strcmp(fstype, "procfs") == 0) 37885289Sdes continue; 379119068Sdes 38085289Sdes sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype, 38185289Sdes mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); 38285289Sdes#define ADD_OPTION(opt, name) \ 38385289Sdes if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name); 38485289Sdes ADD_OPTION(MNT_SYNCHRONOUS, "sync"); 38585289Sdes ADD_OPTION(MNT_NOEXEC, "noexec"); 38685289Sdes ADD_OPTION(MNT_NOSUID, "nosuid"); 38785289Sdes ADD_OPTION(MNT_NODEV, "nodev"); 38885289Sdes ADD_OPTION(MNT_UNION, "union"); 38985289Sdes ADD_OPTION(MNT_ASYNC, "async"); 39085289Sdes ADD_OPTION(MNT_SUIDDIR, "suiddir"); 39185289Sdes ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow"); 39285289Sdes ADD_OPTION(MNT_NOATIME, "noatime"); 39385289Sdes#undef ADD_OPTION 39485289Sdes /* a real Linux mtab will also show NFS options */ 39585289Sdes sbuf_printf(sb, " 0 0\n"); 39685289Sdes } 39785289Sdes mtx_unlock(&mountlist_mtx); 39885289Sdes if (flep != NULL) 39985289Sdes free(flep, M_TEMP); 40085289Sdes return (error); 40185289Sdes} 40285289Sdes 40385289Sdes/* 40478113Sdes * Filler function for proc/stat 40578113Sdes */ 40678025Sdesstatic int 40778025Sdeslinprocfs_dostat(PFS_FILL_ARGS) 40865633Sdes{ 409123246Sdes int i; 410120339Sdes 411120339Sdes sbuf_printf(sb, "cpu %ld %ld %ld %ld\n", 412120339Sdes T2J(cp_time[CP_USER]), 413120339Sdes T2J(cp_time[CP_NICE]), 414120339Sdes T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/), 415120339Sdes T2J(cp_time[CP_IDLE])); 416123246Sdes if (mp_ncpus > 1) 417123246Sdes for (i = 0; i < mp_ncpus; ++i) 418120340Sdes sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i, 419123246Sdes T2J(cp_time[CP_USER]) / mp_ncpus, 420123246Sdes T2J(cp_time[CP_NICE]) / mp_ncpus, 421123246Sdes T2J(cp_time[CP_SYS]) / mp_ncpus, 422123246Sdes T2J(cp_time[CP_IDLE]) / mp_ncpus); 42378025Sdes sbuf_printf(sb, 42469799Sdes "disk 0 0 0 0\n" 42569799Sdes "page %u %u\n" 42669799Sdes "swap %u %u\n" 42769799Sdes "intr %u\n" 42869799Sdes "ctxt %u\n" 42985657Sdillon "btime %lld\n", 43069799Sdes cnt.v_vnodepgsin, 43169799Sdes cnt.v_vnodepgsout, 43269799Sdes cnt.v_swappgsin, 43369799Sdes cnt.v_swappgsout, 43469799Sdes cnt.v_intr, 43569799Sdes cnt.v_swtch, 436113574Sjhb (long long)boottime.tv_sec); 43778025Sdes return (0); 43865633Sdes} 43965633Sdes 44078113Sdes/* 44178113Sdes * Filler function for proc/uptime 44278113Sdes */ 44378025Sdesstatic int 44478025Sdeslinprocfs_douptime(PFS_FILL_ARGS) 44565633Sdes{ 44665633Sdes struct timeval tv; 44765633Sdes 44865633Sdes getmicrouptime(&tv); 44985657Sdillon sbuf_printf(sb, "%lld.%02ld %ld.%02ld\n", 450113574Sjhb (long long)tv.tv_sec, tv.tv_usec / 10000, 45169799Sdes T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100); 45278025Sdes return (0); 45365633Sdes} 45465633Sdes 45578113Sdes/* 45678113Sdes * Filler function for proc/version 45778113Sdes */ 45878025Sdesstatic int 45978025Sdeslinprocfs_doversion(PFS_FILL_ARGS) 46065633Sdes{ 46187275Srwatson char osname[LINUX_MAX_UTSNAME]; 46287275Srwatson char osrelease[LINUX_MAX_UTSNAME]; 46387275Srwatson 464112206Sjhb linux_get_osname(td, osname); 465112206Sjhb linux_get_osrelease(td, osrelease); 46687275Srwatson 46778025Sdes sbuf_printf(sb, 46869995Sdes "%s version %s (des@freebsd.org) (gcc version " __VERSION__ ")" 46987275Srwatson " #4 Sun Dec 18 04:30:00 CET 1977\n", osname, osrelease); 47078025Sdes return (0); 47165633Sdes} 47265633Sdes 47378113Sdes/* 47478113Sdes * Filler function for proc/loadavg 47578113Sdes */ 47678025Sdesstatic int 47778025Sdeslinprocfs_doloadavg(PFS_FILL_ARGS) 47876839Sjlemon{ 47978025Sdes sbuf_printf(sb, 48076839Sjlemon "%d.%02d %d.%02d %d.%02d %d/%d %d\n", 48176839Sjlemon (int)(averunnable.ldavg[0] / averunnable.fscale), 48276839Sjlemon (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100), 48376839Sjlemon (int)(averunnable.ldavg[1] / averunnable.fscale), 48476839Sjlemon (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100), 48576839Sjlemon (int)(averunnable.ldavg[2] / averunnable.fscale), 48676839Sjlemon (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100), 48776839Sjlemon 1, /* number of running tasks */ 48876839Sjlemon nprocs, /* number of tasks */ 48978116Sdes lastpid /* the last pid */ 49076839Sjlemon ); 491119068Sdes 49278025Sdes return (0); 49376839Sjlemon} 49476839Sjlemon 49578113Sdes/* 49678113Sdes * Filler function for proc/pid/stat 49778113Sdes */ 49878025Sdesstatic int 49978025Sdeslinprocfs_doprocstat(PFS_FILL_ARGS) 50067588Sdes{ 50169995Sdes struct kinfo_proc kp; 50267588Sdes 50394307Sjhb PROC_LOCK(p); 50469995Sdes fill_kinfo_proc(p, &kp); 50578025Sdes sbuf_printf(sb, "%d", p->p_pid); 50678025Sdes#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg) 50767588Sdes PS_ADD("comm", "(%s)", p->p_comm); 50867588Sdes PS_ADD("statr", "%c", '0'); /* XXX */ 50973923Sjhb PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0); 51067588Sdes PS_ADD("pgrp", "%d", p->p_pgid); 51167588Sdes PS_ADD("session", "%d", p->p_session->s_sid); 51291140Stanimura PROC_UNLOCK(p); 51367588Sdes PS_ADD("tty", "%d", 0); /* XXX */ 51467588Sdes PS_ADD("tpgid", "%d", 0); /* XXX */ 51567588Sdes PS_ADD("flags", "%u", 0); /* XXX */ 51667588Sdes PS_ADD("minflt", "%u", 0); /* XXX */ 51767588Sdes PS_ADD("cminflt", "%u", 0); /* XXX */ 51867588Sdes PS_ADD("majflt", "%u", 0); /* XXX */ 51967588Sdes PS_ADD("cminflt", "%u", 0); /* XXX */ 52067588Sdes PS_ADD("utime", "%d", 0); /* XXX */ 52167588Sdes PS_ADD("stime", "%d", 0); /* XXX */ 52267588Sdes PS_ADD("cutime", "%d", 0); /* XXX */ 52367588Sdes PS_ADD("cstime", "%d", 0); /* XXX */ 52467588Sdes PS_ADD("counter", "%d", 0); /* XXX */ 52567588Sdes PS_ADD("priority", "%d", 0); /* XXX */ 52667588Sdes PS_ADD("timeout", "%u", 0); /* XXX */ 52767588Sdes PS_ADD("itrealvalue", "%u", 0); /* XXX */ 52867588Sdes PS_ADD("starttime", "%d", 0); /* XXX */ 529113574Sjhb PS_ADD("vsize", "%ju", (uintmax_t)kp.ki_size); 530113574Sjhb PS_ADD("rss", "%ju", P2K((uintmax_t)kp.ki_rssize)); 53167588Sdes PS_ADD("rlim", "%u", 0); /* XXX */ 53269995Sdes PS_ADD("startcode", "%u", (unsigned)0); 53367588Sdes PS_ADD("endcode", "%u", 0); /* XXX */ 53467588Sdes PS_ADD("startstack", "%u", 0); /* XXX */ 53569799Sdes PS_ADD("esp", "%u", 0); /* XXX */ 53669799Sdes PS_ADD("eip", "%u", 0); /* XXX */ 53767588Sdes PS_ADD("signal", "%d", 0); /* XXX */ 53867588Sdes PS_ADD("blocked", "%d", 0); /* XXX */ 53967588Sdes PS_ADD("sigignore", "%d", 0); /* XXX */ 54067588Sdes PS_ADD("sigcatch", "%d", 0); /* XXX */ 54167588Sdes PS_ADD("wchan", "%u", 0); /* XXX */ 54269799Sdes PS_ADD("nswap", "%lu", (long unsigned)0); /* XXX */ 54369799Sdes PS_ADD("cnswap", "%lu", (long unsigned)0); /* XXX */ 54469799Sdes PS_ADD("exitsignal", "%d", 0); /* XXX */ 54569799Sdes PS_ADD("processor", "%d", 0); /* XXX */ 54667588Sdes#undef PS_ADD 54778025Sdes sbuf_putc(sb, '\n'); 548119068Sdes 54978025Sdes return (0); 55067588Sdes} 55167588Sdes 55267588Sdes/* 553119911Sdes * Filler function for proc/pid/statm 554119911Sdes */ 555119911Sdesstatic int 556119911Sdeslinprocfs_doprocstatm(PFS_FILL_ARGS) 557119911Sdes{ 558119911Sdes struct kinfo_proc kp; 559119911Sdes segsz_t lsize; 560120340Sdes 561119911Sdes PROC_LOCK(p); 562119911Sdes fill_kinfo_proc(p, &kp); 563119911Sdes PROC_UNLOCK(p); 564119911Sdes 565119911Sdes /* 566119911Sdes * See comments in linprocfs_doprocstatus() regarding the 567119911Sdes * computation of lsize. 568119911Sdes */ 569119911Sdes /* size resident share trs drs lrs dt */ 570119911Sdes sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size)); 571119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize); 572119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */ 573119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize); 574119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize)); 575119911Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 576119911Sdes kp.ki_ssize - kp.ki_tsize - 1; 577119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)lsize); 578119911Sdes sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */ 579119911Sdes 580119911Sdes return (0); 581119911Sdes} 582119911Sdes 583119911Sdes/* 58478113Sdes * Filler function for proc/pid/status 58578113Sdes */ 58678025Sdesstatic int 58778025Sdeslinprocfs_doprocstatus(PFS_FILL_ARGS) 58867588Sdes{ 58969995Sdes struct kinfo_proc kp; 59067588Sdes char *state; 59169799Sdes segsz_t lsize; 59299072Sjulian struct thread *td2; 593114983Sjhb struct sigacts *ps; 59474135Sjlemon int i; 59567588Sdes 596113611Sjhb PROC_LOCK(p); 59799072Sjulian td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */ 59899072Sjulian 59999072Sjulian if (P_SHOULDSTOP(p)) { 60099072Sjulian state = "T (stopped)"; 60199072Sjulian } else { 602113611Sjhb mtx_lock_spin(&sched_lock); 60399072Sjulian switch(p->p_state) { 60499072Sjulian case PRS_NEW: 60599072Sjulian state = "I (idle)"; 60699072Sjulian break; 60799072Sjulian case PRS_NORMAL: 60899072Sjulian if (p->p_flag & P_WEXIT) { 60999072Sjulian state = "X (exiting)"; 61099072Sjulian break; 61199072Sjulian } 61299072Sjulian switch(td2->td_state) { 613103216Sjulian case TDS_INHIBITED: 61499072Sjulian state = "S (sleeping)"; 61599072Sjulian break; 61699072Sjulian case TDS_RUNQ: 61799072Sjulian case TDS_RUNNING: 61899072Sjulian state = "R (running)"; 61999072Sjulian break; 62099072Sjulian default: 62199072Sjulian state = "? (unknown)"; 62299072Sjulian break; 62399072Sjulian } 62499072Sjulian break; 62599072Sjulian case PRS_ZOMBIE: 62699072Sjulian state = "Z (zombie)"; 62799072Sjulian break; 62899072Sjulian default: 62999072Sjulian state = "? (unknown)"; 63099072Sjulian break; 63199072Sjulian } 632113611Sjhb mtx_unlock_spin(&sched_lock); 63399072Sjulian } 63467588Sdes 63569995Sdes fill_kinfo_proc(p, &kp); 63678025Sdes sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */ 63778031Sdes sbuf_printf(sb, "State:\t%s\n", state); 63867588Sdes 63967588Sdes /* 64067588Sdes * Credentials 64167588Sdes */ 64278025Sdes sbuf_printf(sb, "Pid:\t%d\n", p->p_pid); 64378025Sdes sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ? 64473923Sjhb p->p_pptr->p_pid : 0); 64578031Sdes sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid, 64678031Sdes p->p_ucred->cr_uid, 64778031Sdes p->p_ucred->cr_svuid, 64878031Sdes /* FreeBSD doesn't have fsuid */ 64978031Sdes p->p_ucred->cr_uid); 65078031Sdes sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid, 65178031Sdes p->p_ucred->cr_gid, 65278031Sdes p->p_ucred->cr_svgid, 65378031Sdes /* FreeBSD doesn't have fsgid */ 65478031Sdes p->p_ucred->cr_gid); 65578025Sdes sbuf_cat(sb, "Groups:\t"); 65667588Sdes for (i = 0; i < p->p_ucred->cr_ngroups; i++) 65778031Sdes sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]); 65871471Sjhb PROC_UNLOCK(p); 65978025Sdes sbuf_putc(sb, '\n'); 660119068Sdes 66167588Sdes /* 66267588Sdes * Memory 66369799Sdes * 66469799Sdes * While our approximation of VmLib may not be accurate (I 66569799Sdes * don't know of a simple way to verify it, and I'm not sure 66669799Sdes * it has much meaning anyway), I believe it's good enough. 66769799Sdes * 66869799Sdes * The same code that could (I think) accurately compute VmLib 66969799Sdes * could also compute VmLck, but I don't really care enough to 67069799Sdes * implement it. Submissions are welcome. 67167588Sdes */ 672113574Sjhb sbuf_printf(sb, "VmSize:\t%8ju kB\n", B2K((uintmax_t)kp.ki_size)); 67378025Sdes sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */ 674113574Sjhb sbuf_printf(sb, "VmRss:\t%8ju kB\n", P2K((uintmax_t)kp.ki_rssize)); 675113574Sjhb sbuf_printf(sb, "VmData:\t%8ju kB\n", P2K((uintmax_t)kp.ki_dsize)); 676113574Sjhb sbuf_printf(sb, "VmStk:\t%8ju kB\n", P2K((uintmax_t)kp.ki_ssize)); 677113574Sjhb sbuf_printf(sb, "VmExe:\t%8ju kB\n", P2K((uintmax_t)kp.ki_tsize)); 67869995Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 67969995Sdes kp.ki_ssize - kp.ki_tsize - 1; 680113574Sjhb sbuf_printf(sb, "VmLib:\t%8ju kB\n", P2K((uintmax_t)lsize)); 68167588Sdes 68267588Sdes /* 68367588Sdes * Signal masks 68467588Sdes * 68567588Sdes * We support up to 128 signals, while Linux supports 32, 68667588Sdes * but we only define 32 (the same 32 as Linux, to boot), so 68767588Sdes * just show the lower 32 bits of each mask. XXX hack. 68867588Sdes * 68967588Sdes * NB: on certain platforms (Sparc at least) Linux actually 69067588Sdes * supports 64 signals, but this code is a long way from 69167588Sdes * running on anything but i386, so ignore that for now. 69267588Sdes */ 69371471Sjhb PROC_LOCK(p); 694104306Sjmallett sbuf_printf(sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]); 69569799Sdes /* 69669799Sdes * I can't seem to find out where the signal mask is in 69769799Sdes * relation to struct proc, so SigBlk is left unimplemented. 69869799Sdes */ 69978025Sdes sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */ 700114983Sjhb ps = p->p_sigacts; 701114983Sjhb mtx_lock(&ps->ps_mtx); 702114983Sjhb sbuf_printf(sb, "SigIgn:\t%08x\n", ps->ps_sigignore.__bits[0]); 703114983Sjhb sbuf_printf(sb, "SigCgt:\t%08x\n", ps->ps_sigcatch.__bits[0]); 704114983Sjhb mtx_unlock(&ps->ps_mtx); 70571471Sjhb PROC_UNLOCK(p); 706119068Sdes 70767588Sdes /* 70867588Sdes * Linux also prints the capability masks, but we don't have 70967588Sdes * capabilities yet, and when we do get them they're likely to 71067588Sdes * be meaningless to Linux programs, so we lie. XXX 71167588Sdes */ 71278025Sdes sbuf_printf(sb, "CapInh:\t%016x\n", 0); 71378025Sdes sbuf_printf(sb, "CapPrm:\t%016x\n", 0); 71478025Sdes sbuf_printf(sb, "CapEff:\t%016x\n", 0); 715119068Sdes 71678025Sdes return (0); 71767588Sdes} 71874135Sjlemon 719119911Sdes 72078113Sdes/* 721119911Sdes * Filler function for proc/pid/cwd 722119911Sdes */ 723119911Sdesstatic int 724119911Sdeslinprocfs_doproccwd(PFS_FILL_ARGS) 725119911Sdes{ 726119911Sdes char *fullpath = "unknown"; 727119911Sdes char *freepath = NULL; 728119911Sdes 729119911Sdes vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath); 730119911Sdes sbuf_printf(sb, "%s", fullpath); 731119911Sdes if (freepath) 732119911Sdes free(freepath, M_TEMP); 733119911Sdes return (0); 734119911Sdes} 735119911Sdes 736119911Sdes/* 737119911Sdes * Filler function for proc/pid/root 738119911Sdes */ 739119911Sdesstatic int 740119911Sdeslinprocfs_doprocroot(PFS_FILL_ARGS) 741119911Sdes{ 742119911Sdes struct vnode *rvp; 743119911Sdes char *fullpath = "unknown"; 744119911Sdes char *freepath = NULL; 745119911Sdes 746119911Sdes rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir; 747119911Sdes vn_fullpath(td, rvp, &fullpath, &freepath); 748119911Sdes sbuf_printf(sb, "%s", fullpath); 749119911Sdes if (freepath) 750119911Sdes free(freepath, M_TEMP); 751119911Sdes return (0); 752119911Sdes} 753119911Sdes 754119911Sdes/* 75578113Sdes * Filler function for proc/pid/cmdline 75678113Sdes */ 75778025Sdesstatic int 75878113Sdeslinprocfs_doproccmdline(PFS_FILL_ARGS) 75978113Sdes{ 76078113Sdes struct ps_strings pstr; 76178113Sdes int error, i; 76278113Sdes 76378113Sdes /* 76478113Sdes * If we are using the ps/cmdline caching, use that. Otherwise 76578113Sdes * revert back to the old way which only implements full cmdline 76678113Sdes * for the currept process and just p->p_comm for all other 76778113Sdes * processes. 76878113Sdes * Note that if the argv is no longer available, we deliberately 76978113Sdes * don't fall back on p->p_comm or return an error: the authentic 77078113Sdes * Linux behaviour is to return zero-length in this case. 77178113Sdes */ 77278113Sdes 77394620Sjhb PROC_LOCK(p); 774127694Spjd if (p->p_args && p_cansee(td, p) == 0) { 77594620Sjhb sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length); 77694620Sjhb PROC_UNLOCK(p); 77794620Sjhb } else if (p != td->td_proc) { 77894620Sjhb PROC_UNLOCK(p); 77994620Sjhb sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm); 78094620Sjhb } else { 78194620Sjhb PROC_UNLOCK(p); 782103767Sjake error = copyin((void *)p->p_sysent->sv_psstrings, &pstr, 783103767Sjake sizeof(pstr)); 78494620Sjhb if (error) 78594620Sjhb return (error); 78694620Sjhb for (i = 0; i < pstr.ps_nargvstr; i++) { 78794620Sjhb sbuf_copyin(sb, pstr.ps_argvstr[i], 0); 78894620Sjhb sbuf_printf(sb, "%c", '\0'); 78978113Sdes } 79078113Sdes } 79178113Sdes 79278113Sdes return (0); 79378113Sdes} 79478113Sdes 79578113Sdes/* 796116173Sobrien * Filler function for proc/pid/environ 797116173Sobrien */ 798116173Sobrienstatic int 799116173Sobrienlinprocfs_doprocenviron(PFS_FILL_ARGS) 800116173Sobrien{ 801116173Sobrien sbuf_printf(sb, "doprocenviron\n%c", '\0'); 802116173Sobrien 803116173Sobrien return (0); 804116173Sobrien} 805116173Sobrien 806116173Sobrien/* 807116173Sobrien * Filler function for proc/pid/maps 808116173Sobrien */ 809116173Sobrienstatic int 810116173Sobrienlinprocfs_doprocmaps(PFS_FILL_ARGS) 811116173Sobrien{ 812121265Scognet char mebuffer[512]; 813121246Scognet vm_map_t map = &p->p_vmspace->vm_map; 814121246Scognet vm_map_entry_t entry; 815121265Scognet vm_object_t obj, tobj, lobj; 816121265Scognet vm_ooffset_t off = 0; 817121265Scognet char *name = "", *freename = NULL; 818121265Scognet size_t len; 819121265Scognet ino_t ino; 820121265Scognet int ref_count, shadow_count, flags; 821121265Scognet int error; 822121246Scognet 823121246Scognet PROC_LOCK(p); 824121246Scognet error = p_candebug(td, p); 825121246Scognet PROC_UNLOCK(p); 826121246Scognet if (error) 827121246Scognet return (error); 828121246Scognet 829121246Scognet if (uio->uio_rw != UIO_READ) 830121246Scognet return (EOPNOTSUPP); 831121246Scognet 832121246Scognet if (uio->uio_offset != 0) 833121246Scognet return (0); 834121246Scognet 835121246Scognet error = 0; 836121246Scognet if (map != &curthread->td_proc->p_vmspace->vm_map) 837121246Scognet vm_map_lock_read(map); 838121246Scognet for (entry = map->header.next; 839121246Scognet ((uio->uio_resid > 0) && (entry != &map->header)); 840121246Scognet entry = entry->next) { 841121265Scognet name = ""; 842121265Scognet freename = NULL; 843121246Scognet if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) 844121246Scognet continue; 845121246Scognet obj = entry->object.vm_object; 846121246Scognet for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) 847121246Scognet lobj = tobj; 848121246Scognet ino = 0; 849121246Scognet if (lobj) { 850121246Scognet VM_OBJECT_LOCK(lobj); 851121246Scognet off = IDX_TO_OFF(lobj->size); 852121246Scognet if (lobj->type == OBJT_VNODE && lobj->handle) { 853121246Scognet vn_fullpath(td, (struct vnode *)lobj->handle, 854121246Scognet &name, &freename); 855121246Scognet ino = ((struct vnode *) 856121246Scognet lobj->handle)->v_cachedid; 857121246Scognet } 858121246Scognet flags = obj->flags; 859121246Scognet ref_count = obj->ref_count; 860121246Scognet shadow_count = obj->shadow_count; 861121246Scognet VM_OBJECT_UNLOCK(lobj); 862121246Scognet } else { 863121246Scognet flags = 0; 864121246Scognet ref_count = 0; 865121246Scognet shadow_count = 0; 866121246Scognet } 867121246Scognet 868121246Scognet /* 869121246Scognet * format: 870121246Scognet * start, end, access, offset, major, minor, inode, name. 871121246Scognet */ 872121246Scognet snprintf(mebuffer, sizeof mebuffer, 873121246Scognet "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n", 874121246Scognet (u_long)entry->start, (u_long)entry->end, 875121246Scognet (entry->protection & VM_PROT_READ)?"r":"-", 876121246Scognet (entry->protection & VM_PROT_WRITE)?"w":"-", 877121246Scognet (entry->protection & VM_PROT_EXECUTE)?"x":"-", 878121246Scognet "p", 879121265Scognet (u_long)off, 880121246Scognet 0, 881121246Scognet 0, 882121265Scognet (u_long)ino, 883121246Scognet *name ? " " : "", 884121246Scognet name 885121246Scognet ); 886121246Scognet if (freename) 887121246Scognet free(freename, M_TEMP); 888121246Scognet len = strlen(mebuffer); 889121246Scognet if (len > uio->uio_resid) 890121246Scognet len = uio->uio_resid; /* 891121246Scognet * XXX We should probably return 892121246Scognet * EFBIG here, as in procfs. 893121246Scognet */ 894121246Scognet error = uiomove(mebuffer, len, uio); 895121246Scognet if (error) 896121246Scognet break; 897121246Scognet } 898121246Scognet if (map != &curthread->td_proc->p_vmspace->vm_map) 899121246Scognet vm_map_unlock_read(map); 900121246Scognet 901121246Scognet return (error); 902121246Scognet} 903121246Scognet 904116173Sobrien/* 90578113Sdes * Filler function for proc/net/dev 90678113Sdes */ 90778025Sdesstatic int 90878025Sdeslinprocfs_donetdev(PFS_FILL_ARGS) 90974135Sjlemon{ 91085129Sdes char ifname[16]; /* XXX LINUX_IFNAMSIZ */ 91174135Sjlemon struct ifnet *ifp; 91274135Sjlemon 91385129Sdes sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n", 91483926Sdes "Inter-", " Receive", " Transmit", " face", 91585129Sdes "bytes packets errs drop fifo frame compressed", 91683926Sdes "bytes packets errs drop fifo frame compressed"); 91774135Sjlemon 918108172Shsu IFNET_RLOCK(); 91974135Sjlemon TAILQ_FOREACH(ifp, &ifnet, if_link) { 92085129Sdes linux_ifname(ifp, ifname, sizeof ifname); 92185129Sdes sbuf_printf(sb, "%6.6s:", ifname); 92283926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ", 92383926Sdes 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); 92483926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", 92583926Sdes 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); 92674135Sjlemon } 927108172Shsu IFNET_RUNLOCK(); 928119068Sdes 92978025Sdes return (0); 93074135Sjlemon} 93174135Sjlemon 93285538Sphk#if 0 93385538Sphkextern struct cdevsw *cdevsw[]; 93485538Sphk 93578113Sdes/* 93678113Sdes * Filler function for proc/devices 93778113Sdes */ 93878025Sdesstatic int 93978025Sdeslinprocfs_dodevices(PFS_FILL_ARGS) 94074135Sjlemon{ 94174135Sjlemon int i; 94274135Sjlemon 94378025Sdes sbuf_printf(sb, "Character devices:\n"); 94474135Sjlemon 94578025Sdes for (i = 0; i < NUMCDEVSW; i++) 94674135Sjlemon if (cdevsw[i] != NULL) 94778025Sdes sbuf_printf(sb, "%3d %s\n", i, cdevsw[i]->d_name); 94874135Sjlemon 94978025Sdes sbuf_printf(sb, "\nBlock devices:\n"); 950119068Sdes 95178025Sdes return (0); 95274135Sjlemon} 95385538Sphk#endif 95474135Sjlemon 95578113Sdes/* 95678113Sdes * Filler function for proc/cmdline 95778113Sdes */ 95878025Sdesstatic int 95978025Sdeslinprocfs_docmdline(PFS_FILL_ARGS) 96074135Sjlemon{ 96178025Sdes sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname); 96278025Sdes sbuf_printf(sb, " ro root=302\n"); 96378025Sdes return (0); 96478025Sdes} 96574135Sjlemon 96683926Sdes#if 0 96778025Sdes/* 96883926Sdes * Filler function for proc/modules 96983926Sdes */ 97083926Sdesstatic int 97183926Sdeslinprocfs_domodules(PFS_FILL_ARGS) 97283926Sdes{ 97383926Sdes struct linker_file *lf; 974119068Sdes 97583926Sdes TAILQ_FOREACH(lf, &linker_files, link) { 97683926Sdes sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename, 97783926Sdes (unsigned long)lf->size, lf->refs); 97883926Sdes } 97983926Sdes return (0); 98083926Sdes} 98183926Sdes#endif 98283926Sdes 98383926Sdes/* 98485129Sdes * Constructor 98578025Sdes */ 98685129Sdesstatic int 98785129Sdeslinprocfs_init(PFS_INIT_ARGS) 98885129Sdes{ 98985129Sdes struct pfs_node *root; 99085129Sdes struct pfs_node *dir; 99174135Sjlemon 99285129Sdes root = pi->pi_root; 99378025Sdes 994119923Sdes /* /proc/... */ 995119911Sdes pfs_create_file(root, "cmdline", &linprocfs_docmdline, 996119911Sdes NULL, NULL, PFS_RD); 997119911Sdes pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo, 998119911Sdes NULL, NULL, PFS_RD); 99985538Sphk#if 0 1000119911Sdes pfs_create_file(root, "devices", &linprocfs_dodevices, 1001119911Sdes NULL, NULL, PFS_RD); 100285538Sphk#endif 1003119911Sdes pfs_create_file(root, "loadavg", &linprocfs_doloadavg, 1004119911Sdes NULL, NULL, PFS_RD); 1005119911Sdes pfs_create_file(root, "meminfo", &linprocfs_domeminfo, 1006119911Sdes NULL, NULL, PFS_RD); 100783926Sdes#if 0 1008119911Sdes pfs_create_file(root, "modules", &linprocfs_domodules, 1009119911Sdes NULL, NULL, PFS_RD); 101083926Sdes#endif 1011119911Sdes pfs_create_file(root, "mtab", &linprocfs_domtab, 1012119911Sdes NULL, NULL, PFS_RD); 101387543Sdes pfs_create_link(root, "self", &procfs_docurproc, 101485129Sdes NULL, NULL, 0); 1015119911Sdes pfs_create_file(root, "stat", &linprocfs_dostat, 1016119911Sdes NULL, NULL, PFS_RD); 1017119911Sdes pfs_create_file(root, "uptime", &linprocfs_douptime, 1018119911Sdes NULL, NULL, PFS_RD); 1019119911Sdes pfs_create_file(root, "version", &linprocfs_doversion, 1020119911Sdes NULL, NULL, PFS_RD); 102178025Sdes 1022119923Sdes /* /proc/net/... */ 102385129Sdes dir = pfs_create_dir(root, "net", NULL, NULL, 0); 102485129Sdes pfs_create_file(dir, "dev", &linprocfs_donetdev, 102585129Sdes NULL, NULL, PFS_RD); 102678025Sdes 1027119923Sdes /* /proc/<pid>/... */ 102885129Sdes dir = pfs_create_dir(root, "pid", NULL, NULL, PFS_PROCDEP); 102985129Sdes pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline, 103085129Sdes NULL, NULL, PFS_RD); 1031119911Sdes pfs_create_link(dir, "cwd", &linprocfs_doproccwd, 1032119911Sdes NULL, NULL, 0); 1033116173Sobrien pfs_create_file(dir, "environ", &linprocfs_doprocenviron, 1034116173Sobrien NULL, NULL, PFS_RD); 103587543Sdes pfs_create_link(dir, "exe", &procfs_doprocfile, 103687543Sdes NULL, &procfs_notsystem, 0); 1037116173Sobrien pfs_create_file(dir, "maps", &linprocfs_doprocmaps, 1038116173Sobrien NULL, NULL, PFS_RD); 103985129Sdes pfs_create_file(dir, "mem", &procfs_doprocmem, 104085129Sdes &procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW); 1041119911Sdes pfs_create_link(dir, "root", &linprocfs_doprocroot, 1042119911Sdes NULL, NULL, 0); 104385129Sdes pfs_create_file(dir, "stat", &linprocfs_doprocstat, 104485129Sdes NULL, NULL, PFS_RD); 1045119911Sdes pfs_create_file(dir, "statm", &linprocfs_doprocstatm, 1046119911Sdes NULL, NULL, PFS_RD); 104785129Sdes pfs_create_file(dir, "status", &linprocfs_doprocstatus, 104885129Sdes NULL, NULL, PFS_RD); 104985129Sdes 105085129Sdes return (0); 105185129Sdes} 105285129Sdes 105385129Sdes/* 105485129Sdes * Destructor 105585129Sdes */ 105685129Sdesstatic int 105785129Sdeslinprocfs_uninit(PFS_INIT_ARGS) 105885129Sdes{ 105985129Sdes 106085129Sdes /* nothing to do, pseudofs will GC */ 106185129Sdes return (0); 106285129Sdes} 106385129Sdes 106485129SdesPSEUDOFS(linprocfs, 1); 106578025SdesMODULE_DEPEND(linprocfs, linux, 1, 1, 1); 106678025SdesMODULE_DEPEND(linprocfs, procfs, 1, 1, 1); 1067