linprocfs.c revision 139743
1139743Simp/*- 265577Sdes * Copyright (c) 2000 Dag-Erling Co�dan Sm�rgrav 365577Sdes * Copyright (c) 1999 Pierre Beyssac 459412Smsmith * Copyright (c) 1993 Jan-Simon Pendry 559412Smsmith * Copyright (c) 1993 659412Smsmith * The Regents of the University of California. All rights reserved. 759412Smsmith * 859412Smsmith * This code is derived from software contributed to Berkeley by 959412Smsmith * Jan-Simon Pendry. 1059412Smsmith * 1159412Smsmith * Redistribution and use in source and binary forms, with or without 1259412Smsmith * modification, are permitted provided that the following conditions 1359412Smsmith * are met: 1459412Smsmith * 1. Redistributions of source code must retain the above copyright 1559412Smsmith * notice, this list of conditions and the following disclaimer. 1659412Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1759412Smsmith * notice, this list of conditions and the following disclaimer in the 1859412Smsmith * documentation and/or other materials provided with the distribution. 1959412Smsmith * 3. All advertising materials mentioning features or use of this software 2059412Smsmith * must display the following acknowledgement: 2159412Smsmith * This product includes software developed by the University of 2259412Smsmith * California, Berkeley and its contributors. 2359412Smsmith * 4. Neither the name of the University nor the names of its contributors 2459412Smsmith * may be used to endorse or promote products derived from this software 2559412Smsmith * without specific prior written permission. 2659412Smsmith * 2759412Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2859412Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2959412Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3059412Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 3159412Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3259412Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3359412Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3459412Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3559412Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3659412Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3759412Smsmith * SUCH DAMAGE. 3859412Smsmith * 3959412Smsmith * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94 4059412Smsmith */ 4159412Smsmith 42116173Sobrien#include <sys/cdefs.h> 43116173Sobrien__FBSDID("$FreeBSD: head/sys/compat/linprocfs/linprocfs.c 139743 2005-01-05 22:34:37Z imp $"); 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 89133822Stjr#if defined(__i386__) || defined(__amd64__) 9067589Sdes#include <machine/cputypes.h> 9159412Smsmith#include <machine/md_var.h> 92133822Stjr#endif /* __i386__ || __amd64__ */ 9359412Smsmith 94133822Stjr#include "opt_compat.h" 95133822Stjr#if !COMPAT_LINUX32 /* XXX */ 9687275Srwatson#include <machine/../linux/linux.h> 97133822Stjr#else 98133822Stjr#include <machine/../linux32/linux.h> 99133822Stjr#endif 10085129Sdes#include <compat/linux/linux_ioctl.h> 10169995Sdes#include <compat/linux/linux_mib.h> 10285289Sdes#include <compat/linux/linux_util.h> 10378025Sdes#include <fs/pseudofs/pseudofs.h> 10484248Sdes#include <fs/procfs/procfs.h> 10559412Smsmith 10667588Sdes/* 10767588Sdes * Various conversion macros 10867588Sdes */ 10976405Sdes#define T2J(x) (((x) * 100UL) / (stathz ? stathz : hz)) /* ticks to jiffies */ 11067588Sdes#define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */ 11167588Sdes#define B2K(x) ((x) >> 10) /* bytes to kbytes */ 11269799Sdes#define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */ 11367588Sdes#define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */ 11467588Sdes#define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */ 11574135Sjlemon 11678113Sdes/* 11778113Sdes * Filler function for proc/meminfo 11878113Sdes */ 11978025Sdesstatic int 12078025Sdeslinprocfs_domeminfo(PFS_FILL_ARGS) 12159412Smsmith{ 12259412Smsmith unsigned long memtotal; /* total memory in bytes */ 12359412Smsmith unsigned long memused; /* used memory in bytes */ 12459412Smsmith unsigned long memfree; /* free memory in bytes */ 12559412Smsmith unsigned long memshared; /* shared memory ??? */ 12659412Smsmith unsigned long buffers, cached; /* buffer / cache memory ??? */ 127113574Sjhb unsigned long long swaptotal; /* total swap space in bytes */ 128113574Sjhb unsigned long long swapused; /* used swap space in bytes */ 129113574Sjhb unsigned long long swapfree; /* free swap space in bytes */ 13060860Sdes vm_object_t object; 131117723Sphk int i, j; 13259412Smsmith 13359412Smsmith memtotal = physmem * PAGE_SIZE; 13459412Smsmith /* 13559412Smsmith * The correct thing here would be: 13659412Smsmith * 13759412Smsmith memfree = cnt.v_free_count * PAGE_SIZE; 13859412Smsmith memused = memtotal - memfree; 13959412Smsmith * 14059412Smsmith * but it might mislead linux binaries into thinking there 14159412Smsmith * is very little memory left, so we cheat and tell them that 14259412Smsmith * all memory that isn't wired down is free. 14359412Smsmith */ 14459412Smsmith memused = cnt.v_wire_count * PAGE_SIZE; 14559412Smsmith memfree = memtotal - memused; 146117723Sphk swap_pager_status(&i, &j); 147117723Sphk swaptotal = i * PAGE_SIZE; 148117723Sphk swapused = j * PAGE_SIZE; 149117723Sphk swapfree = swaptotal - swapused; 15060860Sdes memshared = 0; 151124082Salc mtx_lock(&vm_object_list_mtx); 15271471Sjhb TAILQ_FOREACH(object, &vm_object_list, object_list) 15360860Sdes if (object->shadow_count > 1) 15460860Sdes memshared += object->resident_page_count; 155124082Salc mtx_unlock(&vm_object_list_mtx); 15660860Sdes memshared *= PAGE_SIZE; 15759412Smsmith /* 15859412Smsmith * We'd love to be able to write: 15959412Smsmith * 16059412Smsmith buffers = bufspace; 16159412Smsmith * 16259412Smsmith * but bufspace is internal to vfs_bio.c and we don't feel 16359412Smsmith * like unstaticizing it just for linprocfs's sake. 16459412Smsmith */ 16559412Smsmith buffers = 0; 16659412Smsmith cached = cnt.v_cache_count * PAGE_SIZE; 16759412Smsmith 16878025Sdes sbuf_printf(sb, 16978031Sdes " total: used: free: shared: buffers: cached:\n" 17069799Sdes "Mem: %lu %lu %lu %lu %lu %lu\n" 17176839Sjlemon "Swap: %llu %llu %llu\n" 17269799Sdes "MemTotal: %9lu kB\n" 17369799Sdes "MemFree: %9lu kB\n" 17469799Sdes "MemShared:%9lu kB\n" 17569799Sdes "Buffers: %9lu kB\n" 17669799Sdes "Cached: %9lu kB\n" 17776839Sjlemon "SwapTotal:%9llu kB\n" 17876839Sjlemon "SwapFree: %9llu kB\n", 17969799Sdes memtotal, memused, memfree, memshared, buffers, cached, 18069799Sdes swaptotal, swapused, swapfree, 18169799Sdes B2K(memtotal), B2K(memfree), 18269799Sdes B2K(memshared), B2K(buffers), B2K(cached), 18369799Sdes B2K(swaptotal), B2K(swapfree)); 18459412Smsmith 18578025Sdes return (0); 18659412Smsmith} 18759412Smsmith 18878113Sdes#ifdef __alpha__ 189119008Smarcelextern struct rpb *hwrpb; 19078113Sdes/* 19178113Sdes * Filler function for proc/cpuinfo (Alpha version) 19278113Sdes */ 19378025Sdesstatic int 19478025Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS) 19559412Smsmith{ 19678113Sdes u_int64_t type, major; 19778113Sdes struct pcs *pcsp; 19878113Sdes const char *model, *sysname; 19978113Sdes 20078113Sdes static const char *cpuname[] = { 20178113Sdes "EV3", "EV4", "Simulate", "LCA4", "EV5", "EV45", "EV56", 20278113Sdes "EV6", "PCA56", "PCA57", "EV67", "EV68CB", "EV68AL" 20378113Sdes }; 20478113Sdes 20578113Sdes pcsp = LOCATE_PCS(hwrpb, hwrpb->rpb_primary_cpu_id); 20678113Sdes type = pcsp->pcs_proc_type; 20778113Sdes major = (type & PCS_PROC_MAJOR) >> PCS_PROC_MAJORSHIFT; 20878113Sdes if (major < sizeof(cpuname)/sizeof(char *)) { 20978113Sdes model = cpuname[major - 1]; 21078113Sdes } else { 21178113Sdes model = "unknown"; 21278113Sdes } 213119068Sdes 21478113Sdes sysname = alpha_dsr_sysname(); 215119068Sdes 21678113Sdes sbuf_printf(sb, 21778113Sdes "cpu\t\t\t: Alpha\n" 21878113Sdes "cpu model\t\t: %s\n" 21978113Sdes "cpu variation\t\t: %ld\n" 220113574Sjhb "cpu revision\t\t: %d\n" 22178113Sdes "cpu serial number\t: %s\n" 22278113Sdes "system type\t\t: %s\n" 22378113Sdes "system variation\t: %s\n" 224113574Sjhb "system revision\t\t: %d\n" 22578113Sdes "system serial number\t: %s\n" 22678113Sdes "cycle frequency [Hz]\t: %lu\n" 227113574Sjhb "timer frequency [Hz]\t: %u\n" 22878113Sdes "page size [bytes]\t: %ld\n" 22978113Sdes "phys. address bits\t: %ld\n" 23078113Sdes "max. addr. space #\t: %ld\n" 231113574Sjhb "BogoMIPS\t\t: %u.%02u\n" 232113574Sjhb "kernel unaligned acc\t: %d (pc=%x,va=%x)\n" 233113574Sjhb "user unaligned acc\t: %d (pc=%x,va=%x)\n" 23478113Sdes "platform string\t\t: %s\n" 23578113Sdes "cpus detected\t\t: %d\n" 23678113Sdes , 23778113Sdes model, 23878113Sdes pcsp->pcs_proc_var, 23978113Sdes *(int *)hwrpb->rpb_revision, 24078113Sdes " ", 24178113Sdes " ", 24278113Sdes "0", 24378113Sdes 0, 24478113Sdes " ", 24578113Sdes hwrpb->rpb_cc_freq, 24678113Sdes hz, 24778113Sdes hwrpb->rpb_page_size, 24878113Sdes hwrpb->rpb_phys_addr_size, 24978113Sdes hwrpb->rpb_max_asn, 25078113Sdes 0, 0, 25178113Sdes 0, 0, 0, 25278113Sdes 0, 0, 0, 25378113Sdes sysname, 25478113Sdes ncpus); 25578113Sdes return (0); 25678113Sdes} 25778113Sdes#endif /* __alpha__ */ 25878113Sdes 259133822Stjr#if defined(__i386__) || defined(__amd64__) 26078113Sdes/* 261133822Stjr * Filler function for proc/cpuinfo (i386 & amd64 version) 26278113Sdes */ 26378113Sdesstatic int 26478113Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS) 26578113Sdes{ 266123246Sdes int class, fqmhz, fqkhz; 267118421Sdes int i; 26859412Smsmith 26969799Sdes /* 27078031Sdes * We default the flags to include all non-conflicting flags, 27178031Sdes * and the Intel versions of conflicting flags. 27269799Sdes */ 27378031Sdes static char *flags[] = { 27478031Sdes "fpu", "vme", "de", "pse", "tsc", 27578031Sdes "msr", "pae", "mce", "cx8", "apic", 27678031Sdes "sep", "sep", "mtrr", "pge", "mca", 27778031Sdes "cmov", "pat", "pse36", "pn", "b19", 27878031Sdes "b20", "b21", "mmxext", "mmx", "fxsr", 27978031Sdes "xmm", "b26", "b27", "b28", "b29", 28067589Sdes "3dnowext", "3dnow" 28167589Sdes }; 28267589Sdes 28359412Smsmith switch (cpu_class) { 284133822Stjr#ifdef __i386__ 28559412Smsmith case CPUCLASS_286: 28667589Sdes class = 2; 28759412Smsmith break; 28859412Smsmith case CPUCLASS_386: 28967589Sdes class = 3; 29059412Smsmith break; 29159412Smsmith case CPUCLASS_486: 29267589Sdes class = 4; 29359412Smsmith break; 29459412Smsmith case CPUCLASS_586: 29567589Sdes class = 5; 29659412Smsmith break; 29759412Smsmith case CPUCLASS_686: 29867589Sdes class = 6; 29959412Smsmith break; 30059412Smsmith default: 30178031Sdes class = 0; 30259412Smsmith break; 303133822Stjr#else 304133822Stjr default: 305133822Stjr class = 6; 306133822Stjr break; 307133822Stjr#endif 30859412Smsmith } 30959412Smsmith 310123246Sdes for (i = 0; i < mp_ncpus; ++i) { 311118421Sdes sbuf_printf(sb, 312118421Sdes "processor\t: %d\n" 313118421Sdes "vendor_id\t: %.20s\n" 314118421Sdes "cpu family\t: %d\n" 315118421Sdes "model\t\t: %d\n" 316118421Sdes "stepping\t: %d\n", 317118421Sdes i, cpu_vendor, class, cpu, cpu_id & 0xf); 318118421Sdes /* XXX per-cpu vendor / class / id? */ 319118421Sdes } 32059412Smsmith 32178031Sdes sbuf_cat(sb, 32278031Sdes "flags\t\t:"); 32367589Sdes 32478031Sdes if (!strcmp(cpu_vendor, "AuthenticAMD") && (class < 6)) { 32567589Sdes flags[16] = "fcmov"; 32678031Sdes } else if (!strcmp(cpu_vendor, "CyrixInstead")) { 32767589Sdes flags[24] = "cxmmx"; 32878031Sdes } 329119068Sdes 33078031Sdes for (i = 0; i < 32; i++) 33167589Sdes if (cpu_feature & (1 << i)) 33278025Sdes sbuf_printf(sb, " %s", flags[i]); 33378025Sdes sbuf_cat(sb, "\n"); 33478031Sdes if (class >= 5) { 33569799Sdes fqmhz = (tsc_freq + 4999) / 1000000; 33669799Sdes fqkhz = ((tsc_freq + 4999) / 10000) % 100; 33778025Sdes sbuf_printf(sb, 33869799Sdes "cpu MHz\t\t: %d.%02d\n" 33969799Sdes "bogomips\t: %d.%02d\n", 34069799Sdes fqmhz, fqkhz, fqmhz, fqkhz); 34178031Sdes } 34269995Sdes 34378025Sdes return (0); 34459412Smsmith} 345133822Stjr#endif /* __i386__ || __amd64__ */ 34665633Sdes 34778113Sdes/* 34885289Sdes * Filler function for proc/mtab 34985289Sdes * 35085289Sdes * This file doesn't exist in Linux' procfs, but is included here so 35185289Sdes * users can symlink /compat/linux/etc/mtab to /proc/mtab 35285289Sdes */ 35385289Sdesstatic int 35485289Sdeslinprocfs_domtab(PFS_FILL_ARGS) 35585289Sdes{ 35685289Sdes struct nameidata nd; 35785289Sdes struct mount *mp; 35891334Sjulian const char *lep; 35991334Sjulian char *dlep, *flep, *mntto, *mntfrom, *fstype; 36085289Sdes size_t lep_len; 36185289Sdes int error; 36285289Sdes 36385289Sdes /* resolve symlinks etc. in the emulation tree prefix */ 36485289Sdes NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td); 36585289Sdes flep = NULL; 366124407Srwatson if (namei(&nd) != 0 || vn_fullpath(td, nd.ni_vp, &dlep, &flep) != 0) 36785289Sdes lep = linux_emul_path; 36891334Sjulian else 36991334Sjulian lep = dlep; 37085289Sdes lep_len = strlen(lep); 371119068Sdes 37285289Sdes mtx_lock(&mountlist_mtx); 37385289Sdes error = 0; 37485289Sdes TAILQ_FOREACH(mp, &mountlist, mnt_list) { 37585289Sdes /* determine device name */ 37685289Sdes mntfrom = mp->mnt_stat.f_mntfromname; 377119068Sdes 37885289Sdes /* determine mount point */ 37985289Sdes mntto = mp->mnt_stat.f_mntonname; 38085289Sdes if (strncmp(mntto, lep, lep_len) == 0 && 38185289Sdes mntto[lep_len] == '/') 38285289Sdes mntto += lep_len; 38385289Sdes 38485289Sdes /* determine fs type */ 38585289Sdes fstype = mp->mnt_stat.f_fstypename; 38685289Sdes if (strcmp(fstype, pn->pn_info->pi_name) == 0) 38785289Sdes mntfrom = fstype = "proc"; 38885289Sdes else if (strcmp(fstype, "procfs") == 0) 38985289Sdes continue; 390119068Sdes 39185289Sdes sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype, 39285289Sdes mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); 39385289Sdes#define ADD_OPTION(opt, name) \ 39485289Sdes if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name); 39585289Sdes ADD_OPTION(MNT_SYNCHRONOUS, "sync"); 39685289Sdes ADD_OPTION(MNT_NOEXEC, "noexec"); 39785289Sdes ADD_OPTION(MNT_NOSUID, "nosuid"); 39885289Sdes ADD_OPTION(MNT_NODEV, "nodev"); 39985289Sdes ADD_OPTION(MNT_UNION, "union"); 40085289Sdes ADD_OPTION(MNT_ASYNC, "async"); 40185289Sdes ADD_OPTION(MNT_SUIDDIR, "suiddir"); 40285289Sdes ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow"); 40385289Sdes ADD_OPTION(MNT_NOATIME, "noatime"); 40485289Sdes#undef ADD_OPTION 40585289Sdes /* a real Linux mtab will also show NFS options */ 40685289Sdes sbuf_printf(sb, " 0 0\n"); 40785289Sdes } 40885289Sdes mtx_unlock(&mountlist_mtx); 40985289Sdes if (flep != NULL) 41085289Sdes free(flep, M_TEMP); 41185289Sdes return (error); 41285289Sdes} 41385289Sdes 41485289Sdes/* 41578113Sdes * Filler function for proc/stat 41678113Sdes */ 41778025Sdesstatic int 41878025Sdeslinprocfs_dostat(PFS_FILL_ARGS) 41965633Sdes{ 420123246Sdes int i; 421120339Sdes 422120339Sdes sbuf_printf(sb, "cpu %ld %ld %ld %ld\n", 423120339Sdes T2J(cp_time[CP_USER]), 424120339Sdes T2J(cp_time[CP_NICE]), 425120339Sdes T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/), 426120339Sdes T2J(cp_time[CP_IDLE])); 427123246Sdes if (mp_ncpus > 1) 428123246Sdes for (i = 0; i < mp_ncpus; ++i) 429120340Sdes sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i, 430123246Sdes T2J(cp_time[CP_USER]) / mp_ncpus, 431123246Sdes T2J(cp_time[CP_NICE]) / mp_ncpus, 432123246Sdes T2J(cp_time[CP_SYS]) / mp_ncpus, 433123246Sdes T2J(cp_time[CP_IDLE]) / mp_ncpus); 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; 571120340Sdes 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; 772138281Scperciva char **ps_argvstr; 77378113Sdes int error, i; 77478113Sdes 77578113Sdes /* 77678113Sdes * If we are using the ps/cmdline caching, use that. Otherwise 77778113Sdes * revert back to the old way which only implements full cmdline 77878113Sdes * for the currept process and just p->p_comm for all other 77978113Sdes * processes. 78078113Sdes * Note that if the argv is no longer available, we deliberately 78178113Sdes * don't fall back on p->p_comm or return an error: the authentic 78278113Sdes * Linux behaviour is to return zero-length in this case. 78378113Sdes */ 78478113Sdes 78594620Sjhb PROC_LOCK(p); 786127694Spjd if (p->p_args && p_cansee(td, p) == 0) { 78794620Sjhb sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length); 78894620Sjhb PROC_UNLOCK(p); 78994620Sjhb } else if (p != td->td_proc) { 79094620Sjhb PROC_UNLOCK(p); 79194620Sjhb sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm); 79294620Sjhb } else { 79394620Sjhb PROC_UNLOCK(p); 794103767Sjake error = copyin((void *)p->p_sysent->sv_psstrings, &pstr, 795103767Sjake sizeof(pstr)); 79694620Sjhb if (error) 79794620Sjhb return (error); 798138281Scperciva if (pstr.ps_nargvstr > ARG_MAX) 799138281Scperciva return (E2BIG); 800138281Scperciva ps_argvstr = malloc(pstr.ps_nargvstr * sizeof(char *), 801138281Scperciva M_TEMP, M_WAITOK); 802138281Scperciva error = copyin((void *)pstr.ps_argvstr, ps_argvstr, 803138281Scperciva pstr.ps_nargvstr * sizeof(char *)); 804138281Scperciva if (error) { 805138281Scperciva free(ps_argvstr, M_TEMP); 806138281Scperciva return (error); 807138281Scperciva } 80894620Sjhb for (i = 0; i < pstr.ps_nargvstr; i++) { 809138281Scperciva sbuf_copyin(sb, ps_argvstr[i], 0); 81094620Sjhb sbuf_printf(sb, "%c", '\0'); 81178113Sdes } 812138281Scperciva free(ps_argvstr, M_TEMP); 81378113Sdes } 81478113Sdes 81578113Sdes return (0); 81678113Sdes} 81778113Sdes 81878113Sdes/* 819116173Sobrien * Filler function for proc/pid/environ 820116173Sobrien */ 821116173Sobrienstatic int 822116173Sobrienlinprocfs_doprocenviron(PFS_FILL_ARGS) 823116173Sobrien{ 824116173Sobrien sbuf_printf(sb, "doprocenviron\n%c", '\0'); 825116173Sobrien 826116173Sobrien return (0); 827116173Sobrien} 828116173Sobrien 829116173Sobrien/* 830116173Sobrien * Filler function for proc/pid/maps 831116173Sobrien */ 832116173Sobrienstatic int 833116173Sobrienlinprocfs_doprocmaps(PFS_FILL_ARGS) 834116173Sobrien{ 835121265Scognet char mebuffer[512]; 836121246Scognet vm_map_t map = &p->p_vmspace->vm_map; 837121246Scognet vm_map_entry_t entry; 838121265Scognet vm_object_t obj, tobj, lobj; 839121265Scognet vm_ooffset_t off = 0; 840121265Scognet char *name = "", *freename = NULL; 841121265Scognet size_t len; 842121265Scognet ino_t ino; 843121265Scognet int ref_count, shadow_count, flags; 844121265Scognet int error; 845137507Sphk struct vnode *vp; 846137507Sphk struct vattr vat; 847121246Scognet 848121246Scognet PROC_LOCK(p); 849121246Scognet error = p_candebug(td, p); 850121246Scognet PROC_UNLOCK(p); 851121246Scognet if (error) 852121246Scognet return (error); 853121246Scognet 854121246Scognet if (uio->uio_rw != UIO_READ) 855121246Scognet return (EOPNOTSUPP); 856121246Scognet 857121246Scognet if (uio->uio_offset != 0) 858121246Scognet return (0); 859121246Scognet 860121246Scognet error = 0; 861121246Scognet if (map != &curthread->td_proc->p_vmspace->vm_map) 862121246Scognet vm_map_lock_read(map); 863121246Scognet for (entry = map->header.next; 864121246Scognet ((uio->uio_resid > 0) && (entry != &map->header)); 865121246Scognet entry = entry->next) { 866121265Scognet name = ""; 867121265Scognet freename = NULL; 868121246Scognet if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) 869121246Scognet continue; 870121246Scognet obj = entry->object.vm_object; 871121246Scognet for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) 872121246Scognet lobj = tobj; 873121246Scognet ino = 0; 874121246Scognet if (lobj) { 875137507Sphk vp = lobj->handle; 876121246Scognet VM_OBJECT_LOCK(lobj); 877121246Scognet off = IDX_TO_OFF(lobj->size); 878121246Scognet if (lobj->type == OBJT_VNODE && lobj->handle) { 879137507Sphk vn_fullpath(td, vp, &name, &freename); 880137507Sphk VOP_GETATTR(vp, &vat, td->td_ucred, td); 881137507Sphk ino = vat.va_fileid; 882121246Scognet } 883121246Scognet flags = obj->flags; 884121246Scognet ref_count = obj->ref_count; 885121246Scognet shadow_count = obj->shadow_count; 886121246Scognet VM_OBJECT_UNLOCK(lobj); 887121246Scognet } else { 888121246Scognet flags = 0; 889121246Scognet ref_count = 0; 890121246Scognet shadow_count = 0; 891121246Scognet } 892121246Scognet 893121246Scognet /* 894121246Scognet * format: 895121246Scognet * start, end, access, offset, major, minor, inode, name. 896121246Scognet */ 897121246Scognet snprintf(mebuffer, sizeof mebuffer, 898121246Scognet "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n", 899121246Scognet (u_long)entry->start, (u_long)entry->end, 900121246Scognet (entry->protection & VM_PROT_READ)?"r":"-", 901121246Scognet (entry->protection & VM_PROT_WRITE)?"w":"-", 902121246Scognet (entry->protection & VM_PROT_EXECUTE)?"x":"-", 903121246Scognet "p", 904121265Scognet (u_long)off, 905121246Scognet 0, 906121246Scognet 0, 907121265Scognet (u_long)ino, 908121246Scognet *name ? " " : "", 909121246Scognet name 910121246Scognet ); 911121246Scognet if (freename) 912121246Scognet free(freename, M_TEMP); 913121246Scognet len = strlen(mebuffer); 914121246Scognet if (len > uio->uio_resid) 915121246Scognet len = uio->uio_resid; /* 916121246Scognet * XXX We should probably return 917121246Scognet * EFBIG here, as in procfs. 918121246Scognet */ 919121246Scognet error = uiomove(mebuffer, len, uio); 920121246Scognet if (error) 921121246Scognet break; 922121246Scognet } 923121246Scognet if (map != &curthread->td_proc->p_vmspace->vm_map) 924121246Scognet vm_map_unlock_read(map); 925121246Scognet 926121246Scognet return (error); 927121246Scognet} 928121246Scognet 929116173Sobrien/* 93078113Sdes * Filler function for proc/net/dev 93178113Sdes */ 93278025Sdesstatic int 93378025Sdeslinprocfs_donetdev(PFS_FILL_ARGS) 93474135Sjlemon{ 93585129Sdes char ifname[16]; /* XXX LINUX_IFNAMSIZ */ 93674135Sjlemon struct ifnet *ifp; 93774135Sjlemon 93885129Sdes sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n", 93983926Sdes "Inter-", " Receive", " Transmit", " face", 94085129Sdes "bytes packets errs drop fifo frame compressed", 94183926Sdes "bytes packets errs drop fifo frame compressed"); 94274135Sjlemon 943108172Shsu IFNET_RLOCK(); 94474135Sjlemon TAILQ_FOREACH(ifp, &ifnet, if_link) { 94585129Sdes linux_ifname(ifp, ifname, sizeof ifname); 94685129Sdes sbuf_printf(sb, "%6.6s:", ifname); 94783926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ", 94883926Sdes 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); 94983926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", 95083926Sdes 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); 95174135Sjlemon } 952108172Shsu IFNET_RUNLOCK(); 953119068Sdes 95478025Sdes return (0); 95574135Sjlemon} 95674135Sjlemon 95785538Sphk#if 0 95885538Sphkextern struct cdevsw *cdevsw[]; 95985538Sphk 96078113Sdes/* 96178113Sdes * Filler function for proc/devices 96278113Sdes */ 96378025Sdesstatic int 96478025Sdeslinprocfs_dodevices(PFS_FILL_ARGS) 96574135Sjlemon{ 96674135Sjlemon int i; 96774135Sjlemon 96878025Sdes sbuf_printf(sb, "Character devices:\n"); 96974135Sjlemon 97078025Sdes for (i = 0; i < NUMCDEVSW; i++) 97174135Sjlemon if (cdevsw[i] != NULL) 97278025Sdes sbuf_printf(sb, "%3d %s\n", i, cdevsw[i]->d_name); 97374135Sjlemon 97478025Sdes sbuf_printf(sb, "\nBlock devices:\n"); 975119068Sdes 97678025Sdes return (0); 97774135Sjlemon} 97885538Sphk#endif 97974135Sjlemon 98078113Sdes/* 98178113Sdes * Filler function for proc/cmdline 98278113Sdes */ 98378025Sdesstatic int 98478025Sdeslinprocfs_docmdline(PFS_FILL_ARGS) 98574135Sjlemon{ 98678025Sdes sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname); 98778025Sdes sbuf_printf(sb, " ro root=302\n"); 98878025Sdes return (0); 98978025Sdes} 99074135Sjlemon 99183926Sdes#if 0 99278025Sdes/* 99383926Sdes * Filler function for proc/modules 99483926Sdes */ 99583926Sdesstatic int 99683926Sdeslinprocfs_domodules(PFS_FILL_ARGS) 99783926Sdes{ 99883926Sdes struct linker_file *lf; 999119068Sdes 100083926Sdes TAILQ_FOREACH(lf, &linker_files, link) { 100183926Sdes sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename, 100283926Sdes (unsigned long)lf->size, lf->refs); 100383926Sdes } 100483926Sdes return (0); 100583926Sdes} 100683926Sdes#endif 100783926Sdes 100883926Sdes/* 100985129Sdes * Constructor 101078025Sdes */ 101185129Sdesstatic int 101285129Sdeslinprocfs_init(PFS_INIT_ARGS) 101385129Sdes{ 101485129Sdes struct pfs_node *root; 101585129Sdes struct pfs_node *dir; 101674135Sjlemon 101785129Sdes root = pi->pi_root; 101878025Sdes 1019119923Sdes /* /proc/... */ 1020119911Sdes pfs_create_file(root, "cmdline", &linprocfs_docmdline, 1021119911Sdes NULL, NULL, PFS_RD); 1022119911Sdes pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo, 1023119911Sdes NULL, NULL, PFS_RD); 102485538Sphk#if 0 1025119911Sdes pfs_create_file(root, "devices", &linprocfs_dodevices, 1026119911Sdes NULL, NULL, PFS_RD); 102785538Sphk#endif 1028119911Sdes pfs_create_file(root, "loadavg", &linprocfs_doloadavg, 1029119911Sdes NULL, NULL, PFS_RD); 1030119911Sdes pfs_create_file(root, "meminfo", &linprocfs_domeminfo, 1031119911Sdes NULL, NULL, PFS_RD); 103283926Sdes#if 0 1033119911Sdes pfs_create_file(root, "modules", &linprocfs_domodules, 1034119911Sdes NULL, NULL, PFS_RD); 103583926Sdes#endif 1036119911Sdes pfs_create_file(root, "mtab", &linprocfs_domtab, 1037119911Sdes NULL, NULL, PFS_RD); 103887543Sdes pfs_create_link(root, "self", &procfs_docurproc, 103985129Sdes NULL, NULL, 0); 1040119911Sdes pfs_create_file(root, "stat", &linprocfs_dostat, 1041119911Sdes NULL, NULL, PFS_RD); 1042119911Sdes pfs_create_file(root, "uptime", &linprocfs_douptime, 1043119911Sdes NULL, NULL, PFS_RD); 1044119911Sdes pfs_create_file(root, "version", &linprocfs_doversion, 1045119911Sdes NULL, NULL, PFS_RD); 104678025Sdes 1047119923Sdes /* /proc/net/... */ 104885129Sdes dir = pfs_create_dir(root, "net", NULL, NULL, 0); 104985129Sdes pfs_create_file(dir, "dev", &linprocfs_donetdev, 105085129Sdes NULL, NULL, PFS_RD); 105178025Sdes 1052119923Sdes /* /proc/<pid>/... */ 105385129Sdes dir = pfs_create_dir(root, "pid", NULL, NULL, PFS_PROCDEP); 105485129Sdes pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline, 105585129Sdes NULL, NULL, PFS_RD); 1056119911Sdes pfs_create_link(dir, "cwd", &linprocfs_doproccwd, 1057119911Sdes NULL, NULL, 0); 1058116173Sobrien pfs_create_file(dir, "environ", &linprocfs_doprocenviron, 1059116173Sobrien NULL, NULL, PFS_RD); 106087543Sdes pfs_create_link(dir, "exe", &procfs_doprocfile, 106187543Sdes NULL, &procfs_notsystem, 0); 1062116173Sobrien pfs_create_file(dir, "maps", &linprocfs_doprocmaps, 1063116173Sobrien NULL, NULL, PFS_RD); 106485129Sdes pfs_create_file(dir, "mem", &procfs_doprocmem, 106585129Sdes &procfs_attr, &procfs_candebug, PFS_RDWR|PFS_RAW); 1066119911Sdes pfs_create_link(dir, "root", &linprocfs_doprocroot, 1067119911Sdes NULL, NULL, 0); 106885129Sdes pfs_create_file(dir, "stat", &linprocfs_doprocstat, 106985129Sdes NULL, NULL, PFS_RD); 1070119911Sdes pfs_create_file(dir, "statm", &linprocfs_doprocstatm, 1071119911Sdes NULL, NULL, PFS_RD); 107285129Sdes pfs_create_file(dir, "status", &linprocfs_doprocstatus, 107385129Sdes NULL, NULL, PFS_RD); 107485129Sdes 107585129Sdes return (0); 107685129Sdes} 107785129Sdes 107885129Sdes/* 107985129Sdes * Destructor 108085129Sdes */ 108185129Sdesstatic int 108285129Sdeslinprocfs_uninit(PFS_INIT_ARGS) 108385129Sdes{ 108485129Sdes 108585129Sdes /* nothing to do, pseudofs will GC */ 108685129Sdes return (0); 108785129Sdes} 108885129Sdes 108985129SdesPSEUDOFS(linprocfs, 1); 109078025SdesMODULE_DEPEND(linprocfs, linux, 1, 1, 1); 109178025SdesMODULE_DEPEND(linprocfs, procfs, 1, 1, 1); 1092