1139743Simp/*- 2184691Sdes * 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 42182141Sjulian#include "opt_compat.h" 43182141Sjulian 44116173Sobrien#include <sys/cdefs.h> 45116173Sobrien__FBSDID("$FreeBSD$"); 46116173Sobrien 4759412Smsmith#include <sys/param.h> 4883926Sdes#include <sys/queue.h> 4976166Smarkm#include <sys/blist.h> 5074135Sjlemon#include <sys/conf.h> 5183926Sdes#include <sys/exec.h> 52177785Skib#include <sys/fcntl.h> 53119911Sdes#include <sys/filedesc.h> 5476166Smarkm#include <sys/jail.h> 5565633Sdes#include <sys/kernel.h> 5683926Sdes#include <sys/linker.h> 5776166Smarkm#include <sys/lock.h> 5874135Sjlemon#include <sys/malloc.h> 5978025Sdes#include <sys/mount.h> 60168067Sjkim#include <sys/msg.h> 6176827Salfred#include <sys/mutex.h> 6285289Sdes#include <sys/namei.h> 6365633Sdes#include <sys/proc.h> 64213246Skib#include <sys/ptrace.h> 6565633Sdes#include <sys/resourcevar.h> 6669995Sdes#include <sys/sbuf.h> 67168067Sjkim#include <sys/sem.h> 68123246Sdes#include <sys/smp.h> 6983926Sdes#include <sys/socket.h> 7076839Sjlemon#include <sys/sysctl.h> 7183926Sdes#include <sys/systm.h> 72159995Snetchild#include <sys/time.h> 7365633Sdes#include <sys/tty.h> 7483926Sdes#include <sys/user.h> 7583926Sdes#include <sys/vmmeter.h> 7659412Smsmith#include <sys/vnode.h> 77190445Sambrisko#include <sys/bus.h> 7859412Smsmith 7983926Sdes#include <net/if.h> 80185571Sbz#include <net/vnet.h> 8183926Sdes 8259412Smsmith#include <vm/vm.h> 83185984Skib#include <vm/vm_extern.h> 8459412Smsmith#include <vm/pmap.h> 8567588Sdes#include <vm/vm_map.h> 8659412Smsmith#include <vm/vm_param.h> 8760860Sdes#include <vm/vm_object.h> 8859412Smsmith#include <vm/swap_pager.h> 8969799Sdes 9067589Sdes#include <machine/clock.h> 9178113Sdes 92190445Sambrisko#include <geom/geom.h> 93190445Sambrisko#include <geom/geom_int.h> 94190445Sambrisko 95133822Stjr#if defined(__i386__) || defined(__amd64__) 9667589Sdes#include <machine/cputypes.h> 9759412Smsmith#include <machine/md_var.h> 98133822Stjr#endif /* __i386__ || __amd64__ */ 9959412Smsmith 100213246Skib#ifdef COMPAT_FREEBSD32 101213246Skib#include <compat/freebsd32/freebsd32_util.h> 102213246Skib#endif 103213246Skib 10485129Sdes#include <compat/linux/linux_ioctl.h> 10569995Sdes#include <compat/linux/linux_mib.h> 106246085Sjhb#include <compat/linux/linux_misc.h> 10785289Sdes#include <compat/linux/linux_util.h> 10878025Sdes#include <fs/pseudofs/pseudofs.h> 10984248Sdes#include <fs/procfs/procfs.h> 11059412Smsmith 11167588Sdes/* 11267588Sdes * Various conversion macros 11367588Sdes */ 114206081Snetchild#define T2J(x) ((long)(((x) * 100ULL) / (stathz ? stathz : hz))) /* ticks to jiffies */ 115206081Snetchild#define T2CS(x) ((unsigned long)(((x) * 100ULL) / (stathz ? stathz : hz))) /* ticks to centiseconds */ 11667588Sdes#define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */ 11767588Sdes#define B2K(x) ((x) >> 10) /* bytes to kbytes */ 11869799Sdes#define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */ 11967588Sdes#define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */ 12067588Sdes#define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */ 121206081Snetchild#define TV2J(x) ((x)->tv_sec * 100UL + (x)->tv_usec / 10000) 12274135Sjlemon 123159995Snetchild/** 124159995Snetchild * @brief Mapping of ki_stat in struct kinfo_proc to the linux state 125159995Snetchild * 126159995Snetchild * The linux procfs state field displays one of the characters RSDZTW to 127159995Snetchild * denote running, sleeping in an interruptible wait, waiting in an 128172568Skevlo * uninterruptible disk sleep, a zombie process, process is being traced 129159995Snetchild * or stopped, or process is paging respectively. 130159995Snetchild * 131159995Snetchild * Our struct kinfo_proc contains the variable ki_stat which contains a 132159995Snetchild * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK. 133159995Snetchild * 134159995Snetchild * This character array is used with ki_stati-1 as an index and tries to 135159995Snetchild * map our states to suitable linux states. 136159995Snetchild */ 137166140Snetchildstatic char linux_state[] = "RRSTZDD"; 138159995Snetchild 13978113Sdes/* 14078113Sdes * Filler function for proc/meminfo 14178113Sdes */ 14278025Sdesstatic int 14378025Sdeslinprocfs_domeminfo(PFS_FILL_ARGS) 14459412Smsmith{ 14559412Smsmith unsigned long memtotal; /* total memory in bytes */ 14659412Smsmith unsigned long memused; /* used memory in bytes */ 14759412Smsmith unsigned long memfree; /* free memory in bytes */ 14859412Smsmith unsigned long memshared; /* shared memory ??? */ 14959412Smsmith unsigned long buffers, cached; /* buffer / cache memory ??? */ 150113574Sjhb unsigned long long swaptotal; /* total swap space in bytes */ 151113574Sjhb unsigned long long swapused; /* used swap space in bytes */ 152113574Sjhb unsigned long long swapfree; /* free swap space in bytes */ 15360860Sdes vm_object_t object; 154117723Sphk int i, j; 15559412Smsmith 15659412Smsmith memtotal = physmem * PAGE_SIZE; 15759412Smsmith /* 15859412Smsmith * The correct thing here would be: 15959412Smsmith * 160170170Sattilio memfree = cnt.v_free_count * PAGE_SIZE; 16159412Smsmith memused = memtotal - memfree; 16259412Smsmith * 16359412Smsmith * but it might mislead linux binaries into thinking there 16459412Smsmith * is very little memory left, so we cheat and tell them that 16559412Smsmith * all memory that isn't wired down is free. 16659412Smsmith */ 167170170Sattilio memused = cnt.v_wire_count * PAGE_SIZE; 16859412Smsmith memfree = memtotal - memused; 169117723Sphk swap_pager_status(&i, &j); 170153310Smlaier swaptotal = (unsigned long long)i * PAGE_SIZE; 171153310Smlaier swapused = (unsigned long long)j * PAGE_SIZE; 172117723Sphk swapfree = swaptotal - swapused; 17360860Sdes memshared = 0; 174124082Salc mtx_lock(&vm_object_list_mtx); 17571471Sjhb TAILQ_FOREACH(object, &vm_object_list, object_list) 17660860Sdes if (object->shadow_count > 1) 17760860Sdes memshared += object->resident_page_count; 178124082Salc mtx_unlock(&vm_object_list_mtx); 17960860Sdes memshared *= PAGE_SIZE; 18059412Smsmith /* 18159412Smsmith * We'd love to be able to write: 18259412Smsmith * 18359412Smsmith buffers = bufspace; 18459412Smsmith * 18559412Smsmith * but bufspace is internal to vfs_bio.c and we don't feel 18659412Smsmith * like unstaticizing it just for linprocfs's sake. 18759412Smsmith */ 18859412Smsmith buffers = 0; 189170170Sattilio cached = cnt.v_cache_count * PAGE_SIZE; 19059412Smsmith 19178025Sdes sbuf_printf(sb, 19278031Sdes " total: used: free: shared: buffers: cached:\n" 19369799Sdes "Mem: %lu %lu %lu %lu %lu %lu\n" 19476839Sjlemon "Swap: %llu %llu %llu\n" 19569799Sdes "MemTotal: %9lu kB\n" 19669799Sdes "MemFree: %9lu kB\n" 19769799Sdes "MemShared:%9lu kB\n" 19869799Sdes "Buffers: %9lu kB\n" 19969799Sdes "Cached: %9lu kB\n" 20076839Sjlemon "SwapTotal:%9llu kB\n" 20176839Sjlemon "SwapFree: %9llu kB\n", 20269799Sdes memtotal, memused, memfree, memshared, buffers, cached, 20369799Sdes swaptotal, swapused, swapfree, 20469799Sdes B2K(memtotal), B2K(memfree), 20569799Sdes B2K(memshared), B2K(buffers), B2K(cached), 20669799Sdes B2K(swaptotal), B2K(swapfree)); 20759412Smsmith 20878025Sdes return (0); 20959412Smsmith} 21059412Smsmith 211133822Stjr#if defined(__i386__) || defined(__amd64__) 21278113Sdes/* 213133822Stjr * Filler function for proc/cpuinfo (i386 & amd64 version) 21478113Sdes */ 21578113Sdesstatic int 21678113Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS) 21778113Sdes{ 218159544Sdes int hw_model[2]; 219159544Sdes char model[128]; 220220433Sjkim uint64_t freq; 221159544Sdes size_t size; 222123246Sdes int class, fqmhz, fqkhz; 223118421Sdes int i; 22459412Smsmith 22569799Sdes /* 22678031Sdes * We default the flags to include all non-conflicting flags, 22778031Sdes * and the Intel versions of conflicting flags. 22869799Sdes */ 22978031Sdes static char *flags[] = { 23078031Sdes "fpu", "vme", "de", "pse", "tsc", 23178031Sdes "msr", "pae", "mce", "cx8", "apic", 23278031Sdes "sep", "sep", "mtrr", "pge", "mca", 23378031Sdes "cmov", "pat", "pse36", "pn", "b19", 23478031Sdes "b20", "b21", "mmxext", "mmx", "fxsr", 235183385Scognet "xmm", "sse2", "b27", "b28", "b29", 23667589Sdes "3dnowext", "3dnow" 23767589Sdes }; 23867589Sdes 23959412Smsmith switch (cpu_class) { 240133822Stjr#ifdef __i386__ 24159412Smsmith case CPUCLASS_286: 24267589Sdes class = 2; 24359412Smsmith break; 24459412Smsmith case CPUCLASS_386: 24567589Sdes class = 3; 24659412Smsmith break; 24759412Smsmith case CPUCLASS_486: 24867589Sdes class = 4; 24959412Smsmith break; 25059412Smsmith case CPUCLASS_586: 25167589Sdes class = 5; 25259412Smsmith break; 25359412Smsmith case CPUCLASS_686: 25467589Sdes class = 6; 25559412Smsmith break; 25659412Smsmith default: 25778031Sdes class = 0; 25859412Smsmith break; 259159170Sdes#else /* __amd64__ */ 260133822Stjr default: 261159170Sdes class = 15; 262133822Stjr break; 263133822Stjr#endif 26459412Smsmith } 26559412Smsmith 266159544Sdes hw_model[0] = CTL_HW; 267159544Sdes hw_model[1] = HW_MODEL; 268159544Sdes model[0] = '\0'; 269159544Sdes size = sizeof(model); 270159544Sdes if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0) 271159544Sdes strcpy(model, "unknown"); 272123246Sdes for (i = 0; i < mp_ncpus; ++i) { 273118421Sdes sbuf_printf(sb, 274118421Sdes "processor\t: %d\n" 275118421Sdes "vendor_id\t: %.20s\n" 276214982Sdes "cpu family\t: %u\n" 277214982Sdes "model\t\t: %u\n" 278159544Sdes "model name\t: %s\n" 279214982Sdes "stepping\t: %u\n\n", 280214985Sdes i, cpu_vendor, CPUID_TO_FAMILY(cpu_id), 281214985Sdes CPUID_TO_MODEL(cpu_id), model, cpu_id & CPUID_STEPPING); 282159544Sdes /* XXX per-cpu vendor / class / model / id? */ 283118421Sdes } 28459412Smsmith 285185766Skib sbuf_cat(sb, "flags\t\t:"); 28667589Sdes 287187594Sjkim#ifdef __i386__ 288187594Sjkim switch (cpu_vendor_id) { 289187594Sjkim case CPU_VENDOR_AMD: 290187594Sjkim if (class < 6) 291187594Sjkim flags[16] = "fcmov"; 292187594Sjkim break; 293187594Sjkim case CPU_VENDOR_CYRIX: 29467589Sdes flags[24] = "cxmmx"; 295187594Sjkim break; 29678031Sdes } 297187594Sjkim#endif 298119068Sdes 29978031Sdes for (i = 0; i < 32; i++) 30067589Sdes if (cpu_feature & (1 << i)) 30178025Sdes sbuf_printf(sb, " %s", flags[i]); 30278025Sdes sbuf_cat(sb, "\n"); 303220433Sjkim freq = atomic_load_acq_64(&tsc_freq); 304220433Sjkim if (freq != 0) { 305220433Sjkim fqmhz = (freq + 4999) / 1000000; 306220433Sjkim fqkhz = ((freq + 4999) / 10000) % 100; 30778025Sdes sbuf_printf(sb, 30869799Sdes "cpu MHz\t\t: %d.%02d\n" 30969799Sdes "bogomips\t: %d.%02d\n", 31069799Sdes fqmhz, fqkhz, fqmhz, fqkhz); 31178031Sdes } 31269995Sdes 31378025Sdes return (0); 31459412Smsmith} 315133822Stjr#endif /* __i386__ || __amd64__ */ 31665633Sdes 31778113Sdes/* 31885289Sdes * Filler function for proc/mtab 31985289Sdes * 32085289Sdes * This file doesn't exist in Linux' procfs, but is included here so 32185289Sdes * users can symlink /compat/linux/etc/mtab to /proc/mtab 32285289Sdes */ 32385289Sdesstatic int 32485289Sdeslinprocfs_domtab(PFS_FILL_ARGS) 32585289Sdes{ 32685289Sdes struct nameidata nd; 32785289Sdes struct mount *mp; 32891334Sjulian const char *lep; 32991334Sjulian char *dlep, *flep, *mntto, *mntfrom, *fstype; 33085289Sdes size_t lep_len; 33185289Sdes int error; 33285289Sdes 33385289Sdes /* resolve symlinks etc. in the emulation tree prefix */ 334241896Skib NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td); 33585289Sdes flep = NULL; 336168942Sdes error = namei(&nd); 337184649Sjhb lep = linux_emul_path; 338184649Sjhb if (error == 0) { 339188579Sjhb if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0) 340184649Sjhb lep = dlep; 341184649Sjhb vrele(nd.ni_vp); 342184649Sjhb } 34385289Sdes lep_len = strlen(lep); 344119068Sdes 34585289Sdes mtx_lock(&mountlist_mtx); 34685289Sdes error = 0; 34785289Sdes TAILQ_FOREACH(mp, &mountlist, mnt_list) { 34885289Sdes /* determine device name */ 34985289Sdes mntfrom = mp->mnt_stat.f_mntfromname; 350119068Sdes 35185289Sdes /* determine mount point */ 35285289Sdes mntto = mp->mnt_stat.f_mntonname; 35385289Sdes if (strncmp(mntto, lep, lep_len) == 0 && 35485289Sdes mntto[lep_len] == '/') 35585289Sdes mntto += lep_len; 35685289Sdes 35785289Sdes /* determine fs type */ 35885289Sdes fstype = mp->mnt_stat.f_fstypename; 35985289Sdes if (strcmp(fstype, pn->pn_info->pi_name) == 0) 36085289Sdes mntfrom = fstype = "proc"; 36185289Sdes else if (strcmp(fstype, "procfs") == 0) 36285289Sdes continue; 363119068Sdes 364158311Sambrisko if (strcmp(fstype, "linsysfs") == 0) { 365158311Sambrisko sbuf_printf(sb, "/sys %s sysfs %s", mntto, 366158311Sambrisko mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); 367158311Sambrisko } else { 368190445Sambrisko /* For Linux msdosfs is called vfat */ 369190445Sambrisko if (strcmp(fstype, "msdosfs") == 0) 370190445Sambrisko fstype = "vfat"; 371158311Sambrisko sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype, 372158311Sambrisko mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); 373158311Sambrisko } 37485289Sdes#define ADD_OPTION(opt, name) \ 37585289Sdes if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name); 37685289Sdes ADD_OPTION(MNT_SYNCHRONOUS, "sync"); 37785289Sdes ADD_OPTION(MNT_NOEXEC, "noexec"); 37885289Sdes ADD_OPTION(MNT_NOSUID, "nosuid"); 37985289Sdes ADD_OPTION(MNT_UNION, "union"); 38085289Sdes ADD_OPTION(MNT_ASYNC, "async"); 38185289Sdes ADD_OPTION(MNT_SUIDDIR, "suiddir"); 38285289Sdes ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow"); 38385289Sdes ADD_OPTION(MNT_NOATIME, "noatime"); 38485289Sdes#undef ADD_OPTION 38585289Sdes /* a real Linux mtab will also show NFS options */ 38685289Sdes sbuf_printf(sb, " 0 0\n"); 38785289Sdes } 38885289Sdes mtx_unlock(&mountlist_mtx); 389247764Seadler free(flep, M_TEMP); 39085289Sdes return (error); 39185289Sdes} 39285289Sdes 39385289Sdes/* 394190445Sambrisko * Filler function for proc/partitions 395190445Sambrisko * 396190445Sambrisko */ 397190445Sambriskostatic int 398190445Sambriskolinprocfs_dopartitions(PFS_FILL_ARGS) 399190445Sambrisko{ 400190445Sambrisko struct g_class *cp; 401190445Sambrisko struct g_geom *gp; 402190445Sambrisko struct g_provider *pp; 403190445Sambrisko struct nameidata nd; 404190445Sambrisko const char *lep; 405190445Sambrisko char *dlep, *flep; 406190445Sambrisko size_t lep_len; 407190445Sambrisko int error; 408190445Sambrisko int major, minor; 409190445Sambrisko 410190445Sambrisko /* resolve symlinks etc. in the emulation tree prefix */ 411241896Skib NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td); 412190445Sambrisko flep = NULL; 413190445Sambrisko error = namei(&nd); 414190445Sambrisko lep = linux_emul_path; 415190445Sambrisko if (error == 0) { 416190445Sambrisko if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0) 417190445Sambrisko lep = dlep; 418190445Sambrisko vrele(nd.ni_vp); 419190445Sambrisko } 420190445Sambrisko lep_len = strlen(lep); 421190445Sambrisko 422190445Sambrisko g_topology_lock(); 423190445Sambrisko error = 0; 424190445Sambrisko sbuf_printf(sb, "major minor #blocks name rio rmerge rsect " 425190445Sambrisko "ruse wio wmerge wsect wuse running use aveq\n"); 426190445Sambrisko 427190445Sambrisko LIST_FOREACH(cp, &g_classes, class) { 428190445Sambrisko if (strcmp(cp->name, "DISK") == 0 || 429190445Sambrisko strcmp(cp->name, "PART") == 0) 430190445Sambrisko LIST_FOREACH(gp, &cp->geom, geom) { 431190445Sambrisko LIST_FOREACH(pp, &gp->provider, provider) { 432190445Sambrisko if (linux_driver_get_major_minor( 433190445Sambrisko pp->name, &major, &minor) != 0) { 434190445Sambrisko major = 0; 435190445Sambrisko minor = 0; 436190445Sambrisko } 437190445Sambrisko sbuf_printf(sb, "%d %d %lld %s " 438190445Sambrisko "%d %d %d %d %d " 439190445Sambrisko "%d %d %d %d %d %d\n", 440190445Sambrisko major, minor, 441190445Sambrisko (long long)pp->mediasize, pp->name, 442190445Sambrisko 0, 0, 0, 0, 0, 443190445Sambrisko 0, 0, 0, 0, 0, 0); 444190445Sambrisko } 445190445Sambrisko } 446190445Sambrisko } 447190445Sambrisko g_topology_unlock(); 448190445Sambrisko 449247764Seadler free(flep, M_TEMP); 450190445Sambrisko return (error); 451190445Sambrisko} 452190445Sambrisko 453190445Sambrisko 454190445Sambrisko/* 45578113Sdes * Filler function for proc/stat 45678113Sdes */ 45778025Sdesstatic int 45878025Sdeslinprocfs_dostat(PFS_FILL_ARGS) 45965633Sdes{ 460174070Speter struct pcpu *pcpu; 461174070Speter long cp_time[CPUSTATES]; 462174070Speter long *cp; 463123246Sdes int i; 464120339Sdes 465174070Speter read_cpu_time(cp_time); 466120339Sdes sbuf_printf(sb, "cpu %ld %ld %ld %ld\n", 467120339Sdes T2J(cp_time[CP_USER]), 468120339Sdes T2J(cp_time[CP_NICE]), 469120339Sdes T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/), 470120339Sdes T2J(cp_time[CP_IDLE])); 471209059Sjhb CPU_FOREACH(i) { 472174070Speter pcpu = pcpu_find(i); 473174070Speter cp = pcpu->pc_cp_time; 474143194Ssobomax sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i, 475174070Speter T2J(cp[CP_USER]), 476174070Speter T2J(cp[CP_NICE]), 477174070Speter T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/), 478174070Speter T2J(cp[CP_IDLE])); 479174070Speter } 48078025Sdes sbuf_printf(sb, 48169799Sdes "disk 0 0 0 0\n" 48269799Sdes "page %u %u\n" 48369799Sdes "swap %u %u\n" 48469799Sdes "intr %u\n" 48569799Sdes "ctxt %u\n" 48685657Sdillon "btime %lld\n", 487170170Sattilio cnt.v_vnodepgsin, 488170170Sattilio cnt.v_vnodepgsout, 489170170Sattilio cnt.v_swappgsin, 490170170Sattilio cnt.v_swappgsout, 491170170Sattilio cnt.v_intr, 492170170Sattilio cnt.v_swtch, 493113574Sjhb (long long)boottime.tv_sec); 49478025Sdes return (0); 49565633Sdes} 49665633Sdes 497224582Skibstatic int 498224582Skiblinprocfs_doswaps(PFS_FILL_ARGS) 499224582Skib{ 500224582Skib struct xswdev xsw; 501224582Skib uintmax_t total, used; 502224582Skib int n; 503224582Skib char devname[SPECNAMELEN + 1]; 504224582Skib 505224582Skib sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"); 506224582Skib mtx_lock(&Giant); 507224582Skib for (n = 0; ; n++) { 508224582Skib if (swap_dev_info(n, &xsw, devname, sizeof(devname)) != 0) 509224582Skib break; 510224582Skib total = (uintmax_t)xsw.xsw_nblks * PAGE_SIZE / 1024; 511224582Skib used = (uintmax_t)xsw.xsw_used * PAGE_SIZE / 1024; 512224582Skib 513224582Skib /* 514224582Skib * The space and not tab after the device name is on 515224582Skib * purpose. Linux does so. 516224582Skib */ 517224582Skib sbuf_printf(sb, "/dev/%-34s unknown\t\t%jd\t%jd\t-1\n", 518224582Skib devname, total, used); 519224582Skib } 520224582Skib mtx_unlock(&Giant); 521224582Skib return (0); 522224582Skib} 523224582Skib 52478113Sdes/* 52578113Sdes * Filler function for proc/uptime 52678113Sdes */ 52778025Sdesstatic int 52878025Sdeslinprocfs_douptime(PFS_FILL_ARGS) 52965633Sdes{ 530174070Speter long cp_time[CPUSTATES]; 53165633Sdes struct timeval tv; 53265633Sdes 53365633Sdes getmicrouptime(&tv); 534174070Speter read_cpu_time(cp_time); 535206081Snetchild sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n", 536113574Sjhb (long long)tv.tv_sec, tv.tv_usec / 10000, 537206081Snetchild T2S(cp_time[CP_IDLE] / mp_ncpus), 538206081Snetchild T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100); 53978025Sdes return (0); 54065633Sdes} 54165633Sdes 54278113Sdes/* 543167159Sjkim * Get OS build date 544167159Sjkim */ 545167159Sjkimstatic void 546167159Sjkimlinprocfs_osbuild(struct thread *td, struct sbuf *sb) 547167159Sjkim{ 548167159Sjkim#if 0 549167159Sjkim char osbuild[256]; 550167159Sjkim char *cp1, *cp2; 551167159Sjkim 552167159Sjkim strncpy(osbuild, version, 256); 553167159Sjkim osbuild[255] = '\0'; 554167159Sjkim cp1 = strstr(osbuild, "\n"); 555167159Sjkim cp2 = strstr(osbuild, ":"); 556167159Sjkim if (cp1 && cp2) { 557167159Sjkim *cp1 = *cp2 = '\0'; 558167159Sjkim cp1 = strstr(osbuild, "#"); 559167159Sjkim } else 560167159Sjkim cp1 = NULL; 561167159Sjkim if (cp1) 562167159Sjkim sbuf_printf(sb, "%s%s", cp1, cp2 + 1); 563167159Sjkim else 564167159Sjkim#endif 565167159Sjkim sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977"); 566167159Sjkim} 567167159Sjkim 568167159Sjkim/* 569167159Sjkim * Get OS builder 570167159Sjkim */ 571167159Sjkimstatic void 572167159Sjkimlinprocfs_osbuilder(struct thread *td, struct sbuf *sb) 573167159Sjkim{ 574168762Sdes#if 0 575167159Sjkim char builder[256]; 576167159Sjkim char *cp; 577167159Sjkim 578167159Sjkim cp = strstr(version, "\n "); 579167159Sjkim if (cp) { 580167159Sjkim strncpy(builder, cp + 5, 256); 581167159Sjkim builder[255] = '\0'; 582167159Sjkim cp = strstr(builder, ":"); 583167159Sjkim if (cp) 584167159Sjkim *cp = '\0'; 585167159Sjkim } 586167159Sjkim if (cp) 587167159Sjkim sbuf_cat(sb, builder); 588167159Sjkim else 589168762Sdes#endif 590167159Sjkim sbuf_cat(sb, "des@freebsd.org"); 591167159Sjkim} 592167159Sjkim 593167159Sjkim/* 59478113Sdes * Filler function for proc/version 59578113Sdes */ 59678025Sdesstatic int 59778025Sdeslinprocfs_doversion(PFS_FILL_ARGS) 59865633Sdes{ 59987275Srwatson char osname[LINUX_MAX_UTSNAME]; 60087275Srwatson char osrelease[LINUX_MAX_UTSNAME]; 60187275Srwatson 602112206Sjhb linux_get_osname(td, osname); 603112206Sjhb linux_get_osrelease(td, osrelease); 604167159Sjkim sbuf_printf(sb, "%s version %s (", osname, osrelease); 605167159Sjkim linprocfs_osbuilder(td, sb); 606167159Sjkim sbuf_cat(sb, ") (gcc version " __VERSION__ ") "); 607167159Sjkim linprocfs_osbuild(td, sb); 608167159Sjkim sbuf_cat(sb, "\n"); 60987275Srwatson 61078025Sdes return (0); 61165633Sdes} 61265633Sdes 61378113Sdes/* 61478113Sdes * Filler function for proc/loadavg 61578113Sdes */ 61678025Sdesstatic int 61778025Sdeslinprocfs_doloadavg(PFS_FILL_ARGS) 61876839Sjlemon{ 619168762Sdes 62078025Sdes sbuf_printf(sb, 62176839Sjlemon "%d.%02d %d.%02d %d.%02d %d/%d %d\n", 62276839Sjlemon (int)(averunnable.ldavg[0] / averunnable.fscale), 62376839Sjlemon (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100), 62476839Sjlemon (int)(averunnable.ldavg[1] / averunnable.fscale), 62576839Sjlemon (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100), 62676839Sjlemon (int)(averunnable.ldavg[2] / averunnable.fscale), 62776839Sjlemon (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100), 62876839Sjlemon 1, /* number of running tasks */ 62976839Sjlemon nprocs, /* number of tasks */ 63078116Sdes lastpid /* the last pid */ 63176839Sjlemon ); 63278025Sdes return (0); 63376839Sjlemon} 63476839Sjlemon 63578113Sdes/* 63678113Sdes * Filler function for proc/pid/stat 63778113Sdes */ 63878025Sdesstatic int 63978025Sdeslinprocfs_doprocstat(PFS_FILL_ARGS) 64067588Sdes{ 64169995Sdes struct kinfo_proc kp; 642166140Snetchild char state; 643166140Snetchild static int ratelimit = 0; 644206081Snetchild vm_offset_t startcode, startdata; 64567588Sdes 64694307Sjhb PROC_LOCK(p); 64769995Sdes fill_kinfo_proc(p, &kp); 648206081Snetchild if (p->p_vmspace) { 649206081Snetchild startcode = (vm_offset_t)p->p_vmspace->vm_taddr; 650206081Snetchild startdata = (vm_offset_t)p->p_vmspace->vm_daddr; 651206081Snetchild } else { 652206081Snetchild startcode = 0; 653206081Snetchild startdata = 0; 654206081Snetchild }; 65578025Sdes sbuf_printf(sb, "%d", p->p_pid); 65678025Sdes#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg) 65767588Sdes PS_ADD("comm", "(%s)", p->p_comm); 658166140Snetchild if (kp.ki_stat > sizeof(linux_state)) { 659166140Snetchild state = 'R'; 660166140Snetchild 661166141Snetchild if (ratelimit == 0) { 662166162Snetchild printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n", 663166162Snetchild kp.ki_stat, sizeof(linux_state)); 664166141Snetchild ++ratelimit; 665166141Snetchild } 666166140Snetchild } else 667166140Snetchild state = linux_state[kp.ki_stat - 1]; 668166140Snetchild PS_ADD("state", "%c", state); 66973923Sjhb PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0); 67067588Sdes PS_ADD("pgrp", "%d", p->p_pgid); 67167588Sdes PS_ADD("session", "%d", p->p_session->s_sid); 67291140Stanimura PROC_UNLOCK(p); 673206081Snetchild PS_ADD("tty", "%d", kp.ki_tdev); 674159995Snetchild PS_ADD("tpgid", "%d", kp.ki_tpgid); 67567588Sdes PS_ADD("flags", "%u", 0); /* XXX */ 676159995Snetchild PS_ADD("minflt", "%lu", kp.ki_rusage.ru_minflt); 677159995Snetchild PS_ADD("cminflt", "%lu", kp.ki_rusage_ch.ru_minflt); 678159995Snetchild PS_ADD("majflt", "%lu", kp.ki_rusage.ru_majflt); 679159995Snetchild PS_ADD("cmajflt", "%lu", kp.ki_rusage_ch.ru_majflt); 680206081Snetchild PS_ADD("utime", "%ld", TV2J(&kp.ki_rusage.ru_utime)); 681206081Snetchild PS_ADD("stime", "%ld", TV2J(&kp.ki_rusage.ru_stime)); 682206081Snetchild PS_ADD("cutime", "%ld", TV2J(&kp.ki_rusage_ch.ru_utime)); 683206081Snetchild PS_ADD("cstime", "%ld", TV2J(&kp.ki_rusage_ch.ru_stime)); 684159995Snetchild PS_ADD("priority", "%d", kp.ki_pri.pri_user); 685159995Snetchild PS_ADD("nice", "%d", kp.ki_nice); /* 19 (nicest) to -19 */ 686159995Snetchild PS_ADD("0", "%d", 0); /* removed field */ 687159995Snetchild PS_ADD("itrealvalue", "%d", 0); /* XXX */ 688206081Snetchild PS_ADD("starttime", "%lu", TV2J(&kp.ki_start) - TV2J(&boottime)); 689159995Snetchild PS_ADD("vsize", "%ju", P2K((uintmax_t)kp.ki_size)); 690159995Snetchild PS_ADD("rss", "%ju", (uintmax_t)kp.ki_rssize); 691159995Snetchild PS_ADD("rlim", "%lu", kp.ki_rusage.ru_maxrss); 692206081Snetchild PS_ADD("startcode", "%ju", (uintmax_t)startcode); 693206081Snetchild PS_ADD("endcode", "%ju", (uintmax_t)startdata); 69467588Sdes PS_ADD("startstack", "%u", 0); /* XXX */ 695159995Snetchild PS_ADD("kstkesp", "%u", 0); /* XXX */ 696159995Snetchild PS_ADD("kstkeip", "%u", 0); /* XXX */ 697159995Snetchild PS_ADD("signal", "%u", 0); /* XXX */ 698159995Snetchild PS_ADD("blocked", "%u", 0); /* XXX */ 699159995Snetchild PS_ADD("sigignore", "%u", 0); /* XXX */ 700159995Snetchild PS_ADD("sigcatch", "%u", 0); /* XXX */ 70167588Sdes PS_ADD("wchan", "%u", 0); /* XXX */ 702159995Snetchild PS_ADD("nswap", "%lu", kp.ki_rusage.ru_nswap); 703159995Snetchild PS_ADD("cnswap", "%lu", kp.ki_rusage_ch.ru_nswap); 70469799Sdes PS_ADD("exitsignal", "%d", 0); /* XXX */ 705159995Snetchild PS_ADD("processor", "%u", kp.ki_lastcpu); 706159995Snetchild PS_ADD("rt_priority", "%u", 0); /* XXX */ /* >= 2.5.19 */ 707159995Snetchild PS_ADD("policy", "%u", kp.ki_pri.pri_class); /* >= 2.5.19 */ 70867588Sdes#undef PS_ADD 70978025Sdes sbuf_putc(sb, '\n'); 710119068Sdes 71178025Sdes return (0); 71267588Sdes} 71367588Sdes 71467588Sdes/* 715119911Sdes * Filler function for proc/pid/statm 716119911Sdes */ 717119911Sdesstatic int 718119911Sdeslinprocfs_doprocstatm(PFS_FILL_ARGS) 719119911Sdes{ 720119911Sdes struct kinfo_proc kp; 721119911Sdes segsz_t lsize; 722120340Sdes 723119911Sdes PROC_LOCK(p); 724119911Sdes fill_kinfo_proc(p, &kp); 725119911Sdes PROC_UNLOCK(p); 726119911Sdes 727119911Sdes /* 728119911Sdes * See comments in linprocfs_doprocstatus() regarding the 729119911Sdes * computation of lsize. 730119911Sdes */ 731119911Sdes /* size resident share trs drs lrs dt */ 732119911Sdes sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size)); 733119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize); 734119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */ 735119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize); 736119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize)); 737119911Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 738119911Sdes kp.ki_ssize - kp.ki_tsize - 1; 739119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)lsize); 740119911Sdes sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */ 741119911Sdes 742119911Sdes return (0); 743119911Sdes} 744119911Sdes 745119911Sdes/* 74678113Sdes * Filler function for proc/pid/status 74778113Sdes */ 74878025Sdesstatic int 74978025Sdeslinprocfs_doprocstatus(PFS_FILL_ARGS) 75067588Sdes{ 75169995Sdes struct kinfo_proc kp; 75267588Sdes char *state; 75369799Sdes segsz_t lsize; 75499072Sjulian struct thread *td2; 755114983Sjhb struct sigacts *ps; 75674135Sjlemon int i; 75767588Sdes 758113611Sjhb PROC_LOCK(p); 75999072Sjulian td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */ 76099072Sjulian 76199072Sjulian if (P_SHOULDSTOP(p)) { 76299072Sjulian state = "T (stopped)"; 76399072Sjulian } else { 76499072Sjulian switch(p->p_state) { 76599072Sjulian case PRS_NEW: 76699072Sjulian state = "I (idle)"; 76799072Sjulian break; 76899072Sjulian case PRS_NORMAL: 76999072Sjulian if (p->p_flag & P_WEXIT) { 77099072Sjulian state = "X (exiting)"; 77199072Sjulian break; 77299072Sjulian } 77399072Sjulian switch(td2->td_state) { 774103216Sjulian case TDS_INHIBITED: 77599072Sjulian state = "S (sleeping)"; 77699072Sjulian break; 77799072Sjulian case TDS_RUNQ: 77899072Sjulian case TDS_RUNNING: 77999072Sjulian state = "R (running)"; 78099072Sjulian break; 78199072Sjulian default: 78299072Sjulian state = "? (unknown)"; 78399072Sjulian break; 78499072Sjulian } 78599072Sjulian break; 78699072Sjulian case PRS_ZOMBIE: 78799072Sjulian state = "Z (zombie)"; 78899072Sjulian break; 78999072Sjulian default: 79099072Sjulian state = "? (unknown)"; 79199072Sjulian break; 79299072Sjulian } 79399072Sjulian } 79467588Sdes 79569995Sdes fill_kinfo_proc(p, &kp); 79678025Sdes sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */ 79778031Sdes sbuf_printf(sb, "State:\t%s\n", state); 79867588Sdes 79967588Sdes /* 80067588Sdes * Credentials 80167588Sdes */ 80278025Sdes sbuf_printf(sb, "Pid:\t%d\n", p->p_pid); 80378025Sdes sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ? 80473923Sjhb p->p_pptr->p_pid : 0); 80578031Sdes sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid, 80678031Sdes p->p_ucred->cr_uid, 80778031Sdes p->p_ucred->cr_svuid, 80878031Sdes /* FreeBSD doesn't have fsuid */ 80978031Sdes p->p_ucred->cr_uid); 81078031Sdes sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid, 81178031Sdes p->p_ucred->cr_gid, 81278031Sdes p->p_ucred->cr_svgid, 81378031Sdes /* FreeBSD doesn't have fsgid */ 81478031Sdes p->p_ucred->cr_gid); 81578025Sdes sbuf_cat(sb, "Groups:\t"); 81667588Sdes for (i = 0; i < p->p_ucred->cr_ngroups; i++) 81778031Sdes sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]); 81871471Sjhb PROC_UNLOCK(p); 81978025Sdes sbuf_putc(sb, '\n'); 820119068Sdes 82167588Sdes /* 82267588Sdes * Memory 82369799Sdes * 82469799Sdes * While our approximation of VmLib may not be accurate (I 82569799Sdes * don't know of a simple way to verify it, and I'm not sure 82669799Sdes * it has much meaning anyway), I believe it's good enough. 82769799Sdes * 82869799Sdes * The same code that could (I think) accurately compute VmLib 82969799Sdes * could also compute VmLck, but I don't really care enough to 83069799Sdes * implement it. Submissions are welcome. 83167588Sdes */ 832113574Sjhb sbuf_printf(sb, "VmSize:\t%8ju kB\n", B2K((uintmax_t)kp.ki_size)); 83378025Sdes sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */ 834206081Snetchild sbuf_printf(sb, "VmRSS:\t%8ju kB\n", P2K((uintmax_t)kp.ki_rssize)); 835113574Sjhb sbuf_printf(sb, "VmData:\t%8ju kB\n", P2K((uintmax_t)kp.ki_dsize)); 836113574Sjhb sbuf_printf(sb, "VmStk:\t%8ju kB\n", P2K((uintmax_t)kp.ki_ssize)); 837113574Sjhb sbuf_printf(sb, "VmExe:\t%8ju kB\n", P2K((uintmax_t)kp.ki_tsize)); 83869995Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 83969995Sdes kp.ki_ssize - kp.ki_tsize - 1; 840113574Sjhb sbuf_printf(sb, "VmLib:\t%8ju kB\n", P2K((uintmax_t)lsize)); 84167588Sdes 84267588Sdes /* 84367588Sdes * Signal masks 84467588Sdes * 84567588Sdes * We support up to 128 signals, while Linux supports 32, 84667588Sdes * but we only define 32 (the same 32 as Linux, to boot), so 84767588Sdes * just show the lower 32 bits of each mask. XXX hack. 84867588Sdes * 84967588Sdes * NB: on certain platforms (Sparc at least) Linux actually 85067588Sdes * supports 64 signals, but this code is a long way from 85167588Sdes * running on anything but i386, so ignore that for now. 85267588Sdes */ 85371471Sjhb PROC_LOCK(p); 854104306Sjmallett sbuf_printf(sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]); 85569799Sdes /* 85669799Sdes * I can't seem to find out where the signal mask is in 85769799Sdes * relation to struct proc, so SigBlk is left unimplemented. 85869799Sdes */ 85978025Sdes sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */ 860114983Sjhb ps = p->p_sigacts; 861114983Sjhb mtx_lock(&ps->ps_mtx); 862114983Sjhb sbuf_printf(sb, "SigIgn:\t%08x\n", ps->ps_sigignore.__bits[0]); 863114983Sjhb sbuf_printf(sb, "SigCgt:\t%08x\n", ps->ps_sigcatch.__bits[0]); 864114983Sjhb mtx_unlock(&ps->ps_mtx); 86571471Sjhb PROC_UNLOCK(p); 866119068Sdes 86767588Sdes /* 86867588Sdes * Linux also prints the capability masks, but we don't have 86967588Sdes * capabilities yet, and when we do get them they're likely to 87067588Sdes * be meaningless to Linux programs, so we lie. XXX 87167588Sdes */ 87278025Sdes sbuf_printf(sb, "CapInh:\t%016x\n", 0); 87378025Sdes sbuf_printf(sb, "CapPrm:\t%016x\n", 0); 87478025Sdes sbuf_printf(sb, "CapEff:\t%016x\n", 0); 875119068Sdes 87678025Sdes return (0); 87767588Sdes} 87874135Sjlemon 879119911Sdes 88078113Sdes/* 881119911Sdes * Filler function for proc/pid/cwd 882119911Sdes */ 883119911Sdesstatic int 884119911Sdeslinprocfs_doproccwd(PFS_FILL_ARGS) 885119911Sdes{ 886119911Sdes char *fullpath = "unknown"; 887119911Sdes char *freepath = NULL; 888119911Sdes 889119911Sdes vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath); 890119911Sdes sbuf_printf(sb, "%s", fullpath); 891119911Sdes if (freepath) 892119911Sdes free(freepath, M_TEMP); 893119911Sdes return (0); 894119911Sdes} 895119911Sdes 896119911Sdes/* 897119911Sdes * Filler function for proc/pid/root 898119911Sdes */ 899119911Sdesstatic int 900119911Sdeslinprocfs_doprocroot(PFS_FILL_ARGS) 901119911Sdes{ 902119911Sdes struct vnode *rvp; 903119911Sdes char *fullpath = "unknown"; 904119911Sdes char *freepath = NULL; 905119911Sdes 906119911Sdes rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir; 907119911Sdes vn_fullpath(td, rvp, &fullpath, &freepath); 908119911Sdes sbuf_printf(sb, "%s", fullpath); 909119911Sdes if (freepath) 910119911Sdes free(freepath, M_TEMP); 911119911Sdes return (0); 912119911Sdes} 913119911Sdes 91478113Sdes/* 915213246Skib * Filler function for proc/pid/cmdline 916213246Skib */ 917213246Skibstatic int 918213246Skiblinprocfs_doproccmdline(PFS_FILL_ARGS) 919213246Skib{ 920213246Skib int ret; 921213246Skib 922213246Skib PROC_LOCK(p); 923213246Skib if ((ret = p_cansee(td, p)) != 0) { 924213246Skib PROC_UNLOCK(p); 925213246Skib return (ret); 926213246Skib } 927223182Spluknet 928223182Spluknet /* 929223182Spluknet * Mimic linux behavior and pass only processes with usermode 930223182Spluknet * address space as valid. Return zero silently otherwize. 931223182Spluknet */ 932223182Spluknet if (p->p_vmspace == &vmspace0) { 933223182Spluknet PROC_UNLOCK(p); 934223182Spluknet return (0); 935223182Spluknet } 936213246Skib if (p->p_args != NULL) { 937213246Skib sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length); 938213246Skib PROC_UNLOCK(p); 939213246Skib return (0); 940213246Skib } 941227836Strociny 942227836Strociny if ((p->p_flag & P_SYSTEM) != 0) { 943227836Strociny PROC_UNLOCK(p); 944227836Strociny return (0); 945227836Strociny } 946227836Strociny 947213246Skib PROC_UNLOCK(p); 948213246Skib 949230145Strociny ret = proc_getargv(td, p, sb); 950213246Skib return (ret); 951213246Skib} 952213246Skib 953213246Skib/* 954116173Sobrien * Filler function for proc/pid/environ 955116173Sobrien */ 956116173Sobrienstatic int 957116173Sobrienlinprocfs_doprocenviron(PFS_FILL_ARGS) 958116173Sobrien{ 959212723Sdes int ret; 960168762Sdes 961212723Sdes PROC_LOCK(p); 962228268Strociny if ((ret = p_candebug(td, p)) != 0) { 963212723Sdes PROC_UNLOCK(p); 964213246Skib return (ret); 965212723Sdes } 966223182Spluknet 967223182Spluknet /* 968223182Spluknet * Mimic linux behavior and pass only processes with usermode 969223182Spluknet * address space as valid. Return zero silently otherwize. 970223182Spluknet */ 971223182Spluknet if (p->p_vmspace == &vmspace0) { 972223182Spluknet PROC_UNLOCK(p); 973223182Spluknet return (0); 974223182Spluknet } 975227836Strociny 976227836Strociny if ((p->p_flag & P_SYSTEM) != 0) { 977227836Strociny PROC_UNLOCK(p); 978227836Strociny return (0); 979227836Strociny } 980227836Strociny 981213246Skib PROC_UNLOCK(p); 982212723Sdes 983230145Strociny ret = proc_getenvv(td, p, sb); 984212723Sdes return (ret); 985116173Sobrien} 986116173Sobrien 987116173Sobrien/* 988116173Sobrien * Filler function for proc/pid/maps 989116173Sobrien */ 990116173Sobrienstatic int 991116173Sobrienlinprocfs_doprocmaps(PFS_FILL_ARGS) 992116173Sobrien{ 993185984Skib struct vmspace *vm; 994185984Skib vm_map_t map; 995185765Skib vm_map_entry_t entry, tmp_entry; 996121265Scognet vm_object_t obj, tobj, lobj; 997185765Skib vm_offset_t e_start, e_end; 998121265Scognet vm_ooffset_t off = 0; 999185765Skib vm_prot_t e_prot; 1000185765Skib unsigned int last_timestamp; 1001121265Scognet char *name = "", *freename = NULL; 1002121265Scognet ino_t ino; 1003121265Scognet int ref_count, shadow_count, flags; 1004121265Scognet int error; 1005137507Sphk struct vnode *vp; 1006137507Sphk struct vattr vat; 1007168762Sdes 1008121246Scognet PROC_LOCK(p); 1009121246Scognet error = p_candebug(td, p); 1010121246Scognet PROC_UNLOCK(p); 1011121246Scognet if (error) 1012121246Scognet return (error); 1013168762Sdes 1014121246Scognet if (uio->uio_rw != UIO_READ) 1015121246Scognet return (EOPNOTSUPP); 1016168762Sdes 1017121246Scognet error = 0; 1018185984Skib vm = vmspace_acquire_ref(p); 1019185984Skib if (vm == NULL) 1020185984Skib return (ESRCH); 1021185984Skib map = &vm->vm_map; 1022169156Salc vm_map_lock_read(map); 1023183600Skib for (entry = map->header.next; entry != &map->header; 1024121246Scognet entry = entry->next) { 1025121265Scognet name = ""; 1026121265Scognet freename = NULL; 1027121246Scognet if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) 1028121246Scognet continue; 1029185765Skib e_prot = entry->protection; 1030185765Skib e_start = entry->start; 1031185765Skib e_end = entry->end; 1032121246Scognet obj = entry->object.vm_object; 1033169156Salc for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) { 1034251423Salc VM_OBJECT_RLOCK(tobj); 1035169156Salc if (lobj != obj) 1036251423Salc VM_OBJECT_RUNLOCK(lobj); 1037121246Scognet lobj = tobj; 1038169156Salc } 1039185765Skib last_timestamp = map->timestamp; 1040185765Skib vm_map_unlock_read(map); 1041121246Scognet ino = 0; 1042121246Scognet if (lobj) { 1043121246Scognet off = IDX_TO_OFF(lobj->size); 1044161094Skib if (lobj->type == OBJT_VNODE) { 1045161094Skib vp = lobj->handle; 1046161094Skib if (vp) 1047161094Skib vref(vp); 1048121246Scognet } 1049161094Skib else 1050161094Skib vp = NULL; 1051169156Salc if (lobj != obj) 1052251423Salc VM_OBJECT_RUNLOCK(lobj); 1053121246Scognet flags = obj->flags; 1054121246Scognet ref_count = obj->ref_count; 1055121246Scognet shadow_count = obj->shadow_count; 1056251423Salc VM_OBJECT_RUNLOCK(obj); 1057161094Skib if (vp) { 1058161094Skib vn_fullpath(td, vp, &name, &freename); 1059175202Sattilio vn_lock(vp, LK_SHARED | LK_RETRY); 1060182371Sattilio VOP_GETATTR(vp, &vat, td->td_ucred); 1061161094Skib ino = vat.va_fileid; 1062161094Skib vput(vp); 1063161094Skib } 1064121246Scognet } else { 1065121246Scognet flags = 0; 1066121246Scognet ref_count = 0; 1067121246Scognet shadow_count = 0; 1068121246Scognet } 1069168762Sdes 1070121246Scognet /* 1071168762Sdes * format: 1072121246Scognet * start, end, access, offset, major, minor, inode, name. 1073121246Scognet */ 1074183600Skib error = sbuf_printf(sb, 1075121246Scognet "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n", 1076185765Skib (u_long)e_start, (u_long)e_end, 1077185765Skib (e_prot & VM_PROT_READ)?"r":"-", 1078185765Skib (e_prot & VM_PROT_WRITE)?"w":"-", 1079185765Skib (e_prot & VM_PROT_EXECUTE)?"x":"-", 1080121246Scognet "p", 1081121265Scognet (u_long)off, 1082121246Scognet 0, 1083121246Scognet 0, 1084121265Scognet (u_long)ino, 1085121246Scognet *name ? " " : "", 1086121246Scognet name 1087121246Scognet ); 1088121246Scognet if (freename) 1089121246Scognet free(freename, M_TEMP); 1090185864Skib vm_map_lock_read(map); 1091183600Skib if (error == -1) { 1092183600Skib error = 0; 1093121246Scognet break; 1094169156Salc } 1095186563Skib if (last_timestamp != map->timestamp) { 1096185765Skib /* 1097185765Skib * Look again for the entry because the map was 1098185765Skib * modified while it was unlocked. Specifically, 1099185765Skib * the entry may have been clipped, merged, or deleted. 1100185765Skib */ 1101185765Skib vm_map_lookup_entry(map, e_end - 1, &tmp_entry); 1102185765Skib entry = tmp_entry; 1103185765Skib } 1104121246Scognet } 1105169156Salc vm_map_unlock_read(map); 1106185984Skib vmspace_free(vm); 1107168762Sdes 1108121246Scognet return (error); 1109168762Sdes} 1110168762Sdes 1111116173Sobrien/* 111278113Sdes * Filler function for proc/net/dev 111378113Sdes */ 111478025Sdesstatic int 111578025Sdeslinprocfs_donetdev(PFS_FILL_ARGS) 111674135Sjlemon{ 111785129Sdes char ifname[16]; /* XXX LINUX_IFNAMSIZ */ 111874135Sjlemon struct ifnet *ifp; 111974135Sjlemon 1120218114Sbz sbuf_printf(sb, "%6s|%58s|%s\n" 1121218114Sbz "%6s|%58s|%58s\n", 1122218114Sbz "Inter-", " Receive", " Transmit", 1123218114Sbz " face", 1124218114Sbz "bytes packets errs drop fifo frame compressed multicast", 1125218114Sbz "bytes packets errs drop fifo colls carrier compressed"); 112674135Sjlemon 1127196635Szec CURVNET_SET(TD_TO_VNET(curthread)); 1128108172Shsu IFNET_RLOCK(); 1129181803Sbz TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 113085129Sdes linux_ifname(ifp, ifname, sizeof ifname); 1131218114Sbz sbuf_printf(sb, "%6.6s: ", ifname); 1132218114Sbz sbuf_printf(sb, "%7lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ", 1133218114Sbz ifp->if_ibytes, /* rx_bytes */ 1134218114Sbz ifp->if_ipackets, /* rx_packets */ 1135218114Sbz ifp->if_ierrors, /* rx_errors */ 1136218114Sbz ifp->if_iqdrops, /* rx_dropped + 1137218114Sbz * rx_missed_errors */ 1138218114Sbz 0UL, /* rx_fifo_errors */ 1139218114Sbz 0UL, /* rx_length_errors + 1140218114Sbz * rx_over_errors + 1141218114Sbz * rx_crc_errors + 1142218114Sbz * rx_frame_errors */ 1143218114Sbz 0UL, /* rx_compressed */ 1144218114Sbz ifp->if_imcasts); /* multicast, XXX-BZ rx only? */ 114583926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", 1146218114Sbz ifp->if_obytes, /* tx_bytes */ 1147218114Sbz ifp->if_opackets, /* tx_packets */ 1148218114Sbz ifp->if_oerrors, /* tx_errors */ 1149218114Sbz 0UL, /* tx_dropped */ 1150218114Sbz 0UL, /* tx_fifo_errors */ 1151218114Sbz ifp->if_collisions, /* collisions */ 1152218114Sbz 0UL, /* tx_carrier_errors + 1153218114Sbz * tx_aborted_errors + 1154218114Sbz * tx_window_errors + 1155218114Sbz * tx_heartbeat_errors */ 1156218114Sbz 0UL); /* tx_compressed */ 115774135Sjlemon } 1158108172Shsu IFNET_RUNLOCK(); 1159196635Szec CURVNET_RESTORE(); 1160119068Sdes 116178025Sdes return (0); 116274135Sjlemon} 116374135Sjlemon 1164158311Sambrisko/* 1165167159Sjkim * Filler function for proc/sys/kernel/osrelease 1166167159Sjkim */ 1167167159Sjkimstatic int 1168167159Sjkimlinprocfs_doosrelease(PFS_FILL_ARGS) 1169167159Sjkim{ 1170167159Sjkim char osrelease[LINUX_MAX_UTSNAME]; 1171167159Sjkim 1172167159Sjkim linux_get_osrelease(td, osrelease); 1173167159Sjkim sbuf_printf(sb, "%s\n", osrelease); 1174167159Sjkim 1175167159Sjkim return (0); 1176167159Sjkim} 1177167159Sjkim 1178167159Sjkim/* 1179167159Sjkim * Filler function for proc/sys/kernel/ostype 1180167159Sjkim */ 1181167159Sjkimstatic int 1182167159Sjkimlinprocfs_doostype(PFS_FILL_ARGS) 1183167159Sjkim{ 1184167159Sjkim char osname[LINUX_MAX_UTSNAME]; 1185167159Sjkim 1186167159Sjkim linux_get_osname(td, osname); 1187167159Sjkim sbuf_printf(sb, "%s\n", osname); 1188167159Sjkim 1189167159Sjkim return (0); 1190167159Sjkim} 1191167159Sjkim 1192167159Sjkim/* 1193167159Sjkim * Filler function for proc/sys/kernel/version 1194167159Sjkim */ 1195167159Sjkimstatic int 1196167159Sjkimlinprocfs_doosbuild(PFS_FILL_ARGS) 1197167159Sjkim{ 1198168762Sdes 1199167159Sjkim linprocfs_osbuild(td, sb); 1200167159Sjkim sbuf_cat(sb, "\n"); 1201167159Sjkim return (0); 1202167159Sjkim} 1203167159Sjkim 1204167159Sjkim/* 1205164692Sjkim * Filler function for proc/sys/kernel/msgmni 1206164692Sjkim */ 1207164692Sjkimstatic int 1208164692Sjkimlinprocfs_domsgmni(PFS_FILL_ARGS) 1209164692Sjkim{ 1210164692Sjkim 1211168067Sjkim sbuf_printf(sb, "%d\n", msginfo.msgmni); 1212164692Sjkim return (0); 1213164692Sjkim} 1214164692Sjkim 1215164692Sjkim/* 1216163251Skeramida * Filler function for proc/sys/kernel/pid_max 1217163129Snetchild */ 1218163129Snetchildstatic int 1219163129Snetchildlinprocfs_dopid_max(PFS_FILL_ARGS) 1220163129Snetchild{ 1221163757Snetchild 1222163129Snetchild sbuf_printf(sb, "%i\n", PID_MAX); 1223163129Snetchild return (0); 1224163129Snetchild} 1225163129Snetchild 1226163129Snetchild/* 1227164692Sjkim * Filler function for proc/sys/kernel/sem 1228164692Sjkim */ 1229164692Sjkimstatic int 1230164692Sjkimlinprocfs_dosem(PFS_FILL_ARGS) 1231164692Sjkim{ 1232164692Sjkim 1233168067Sjkim sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns, 1234168067Sjkim seminfo.semopm, seminfo.semmni); 1235164692Sjkim return (0); 1236164692Sjkim} 1237164692Sjkim 1238164692Sjkim/* 1239158311Sambrisko * Filler function for proc/scsi/device_info 1240158311Sambrisko */ 1241158311Sambriskostatic int 1242158311Sambriskolinprocfs_doscsidevinfo(PFS_FILL_ARGS) 1243158311Sambrisko{ 1244168762Sdes 1245158311Sambrisko return (0); 1246158311Sambrisko} 1247158311Sambrisko 1248158311Sambrisko/* 1249158311Sambrisko * Filler function for proc/scsi/scsi 1250158311Sambrisko */ 1251158311Sambriskostatic int 1252158311Sambriskolinprocfs_doscsiscsi(PFS_FILL_ARGS) 1253158311Sambrisko{ 1254168762Sdes 1255158311Sambrisko return (0); 1256158311Sambrisko} 1257158311Sambrisko 125885538Sphkextern struct cdevsw *cdevsw[]; 125985538Sphk 126078113Sdes/* 126178113Sdes * Filler function for proc/devices 126278113Sdes */ 126378025Sdesstatic int 126478025Sdeslinprocfs_dodevices(PFS_FILL_ARGS) 126574135Sjlemon{ 1266158311Sambrisko char *char_devices; 126778025Sdes sbuf_printf(sb, "Character devices:\n"); 126874135Sjlemon 1269158311Sambrisko char_devices = linux_get_char_devices(); 1270158311Sambrisko sbuf_printf(sb, "%s", char_devices); 1271158311Sambrisko linux_free_get_char_devices(char_devices); 127274135Sjlemon 127378025Sdes sbuf_printf(sb, "\nBlock devices:\n"); 1274119068Sdes 127578025Sdes return (0); 127674135Sjlemon} 127774135Sjlemon 127878113Sdes/* 127978113Sdes * Filler function for proc/cmdline 128078113Sdes */ 128178025Sdesstatic int 128278025Sdeslinprocfs_docmdline(PFS_FILL_ARGS) 128374135Sjlemon{ 1284168762Sdes 128578025Sdes sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname); 128678025Sdes sbuf_printf(sb, " ro root=302\n"); 128778025Sdes return (0); 128878025Sdes} 128974135Sjlemon 1290205541Sjhb/* 1291205541Sjhb * Filler function for proc/filesystems 1292205541Sjhb */ 1293205541Sjhbstatic int 1294205541Sjhblinprocfs_dofilesystems(PFS_FILL_ARGS) 1295205541Sjhb{ 1296205541Sjhb struct vfsconf *vfsp; 1297205541Sjhb 1298205592Sjhb mtx_lock(&Giant); 1299205541Sjhb TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) { 1300205541Sjhb if (vfsp->vfc_flags & VFCF_SYNTHETIC) 1301205541Sjhb sbuf_printf(sb, "nodev"); 1302205541Sjhb sbuf_printf(sb, "\t%s\n", vfsp->vfc_name); 1303205541Sjhb } 1304205592Sjhb mtx_unlock(&Giant); 1305205541Sjhb return(0); 1306205541Sjhb} 1307205541Sjhb 130883926Sdes#if 0 130978025Sdes/* 131083926Sdes * Filler function for proc/modules 131183926Sdes */ 131283926Sdesstatic int 131383926Sdeslinprocfs_domodules(PFS_FILL_ARGS) 131483926Sdes{ 131583926Sdes struct linker_file *lf; 1316119068Sdes 131783926Sdes TAILQ_FOREACH(lf, &linker_files, link) { 131883926Sdes sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename, 131983926Sdes (unsigned long)lf->size, lf->refs); 132083926Sdes } 132183926Sdes return (0); 132283926Sdes} 132383926Sdes#endif 132483926Sdes 132583926Sdes/* 1326204825Sed * Filler function for proc/pid/fd 1327204825Sed */ 1328204825Sedstatic int 1329204825Sedlinprocfs_dofdescfs(PFS_FILL_ARGS) 1330204825Sed{ 1331204825Sed 1332204825Sed if (p == curproc) 1333204825Sed sbuf_printf(sb, "/dev/fd"); 1334204825Sed else 1335204825Sed sbuf_printf(sb, "unknown"); 1336204825Sed return (0); 1337204825Sed} 1338204825Sed 1339204825Sed/* 134085129Sdes * Constructor 134178025Sdes */ 134285129Sdesstatic int 134385129Sdeslinprocfs_init(PFS_INIT_ARGS) 134485129Sdes{ 134585129Sdes struct pfs_node *root; 134685129Sdes struct pfs_node *dir; 134774135Sjlemon 134885129Sdes root = pi->pi_root; 134978025Sdes 1350119923Sdes /* /proc/... */ 1351119911Sdes pfs_create_file(root, "cmdline", &linprocfs_docmdline, 1352167482Sdes NULL, NULL, NULL, PFS_RD); 1353119911Sdes pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo, 1354167482Sdes NULL, NULL, NULL, PFS_RD); 1355119911Sdes pfs_create_file(root, "devices", &linprocfs_dodevices, 1356167482Sdes NULL, NULL, NULL, PFS_RD); 1357205541Sjhb pfs_create_file(root, "filesystems", &linprocfs_dofilesystems, 1358205541Sjhb NULL, NULL, NULL, PFS_RD); 1359119911Sdes pfs_create_file(root, "loadavg", &linprocfs_doloadavg, 1360167482Sdes NULL, NULL, NULL, PFS_RD); 1361119911Sdes pfs_create_file(root, "meminfo", &linprocfs_domeminfo, 1362167482Sdes NULL, NULL, NULL, PFS_RD); 136383926Sdes#if 0 1364119911Sdes pfs_create_file(root, "modules", &linprocfs_domodules, 1365167482Sdes NULL, NULL, NULL, PFS_RD); 136683926Sdes#endif 1367158311Sambrisko pfs_create_file(root, "mounts", &linprocfs_domtab, 1368167482Sdes NULL, NULL, NULL, PFS_RD); 1369119911Sdes pfs_create_file(root, "mtab", &linprocfs_domtab, 1370167482Sdes NULL, NULL, NULL, PFS_RD); 1371190445Sambrisko pfs_create_file(root, "partitions", &linprocfs_dopartitions, 1372190445Sambrisko NULL, NULL, NULL, PFS_RD); 137387543Sdes pfs_create_link(root, "self", &procfs_docurproc, 1374167482Sdes NULL, NULL, NULL, 0); 1375119911Sdes pfs_create_file(root, "stat", &linprocfs_dostat, 1376167482Sdes NULL, NULL, NULL, PFS_RD); 1377224582Skib pfs_create_file(root, "swaps", &linprocfs_doswaps, 1378224582Skib NULL, NULL, NULL, PFS_RD); 1379119911Sdes pfs_create_file(root, "uptime", &linprocfs_douptime, 1380167482Sdes NULL, NULL, NULL, PFS_RD); 1381119911Sdes pfs_create_file(root, "version", &linprocfs_doversion, 1382167482Sdes NULL, NULL, NULL, PFS_RD); 138378025Sdes 1384119923Sdes /* /proc/net/... */ 1385167482Sdes dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0); 138685129Sdes pfs_create_file(dir, "dev", &linprocfs_donetdev, 1387167482Sdes NULL, NULL, NULL, PFS_RD); 138878025Sdes 1389119923Sdes /* /proc/<pid>/... */ 1390167482Sdes dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP); 139185129Sdes pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline, 1392167482Sdes NULL, NULL, NULL, PFS_RD); 1393119911Sdes pfs_create_link(dir, "cwd", &linprocfs_doproccwd, 1394167482Sdes NULL, NULL, NULL, 0); 1395116173Sobrien pfs_create_file(dir, "environ", &linprocfs_doprocenviron, 1396167482Sdes NULL, NULL, NULL, PFS_RD); 139787543Sdes pfs_create_link(dir, "exe", &procfs_doprocfile, 1398167482Sdes NULL, &procfs_notsystem, NULL, 0); 1399116173Sobrien pfs_create_file(dir, "maps", &linprocfs_doprocmaps, 1400167482Sdes NULL, NULL, NULL, PFS_RD); 140185129Sdes pfs_create_file(dir, "mem", &procfs_doprocmem, 1402167482Sdes &procfs_attr, &procfs_candebug, NULL, PFS_RDWR|PFS_RAW); 1403119911Sdes pfs_create_link(dir, "root", &linprocfs_doprocroot, 1404167482Sdes NULL, NULL, NULL, 0); 140585129Sdes pfs_create_file(dir, "stat", &linprocfs_doprocstat, 1406167482Sdes NULL, NULL, NULL, PFS_RD); 1407119911Sdes pfs_create_file(dir, "statm", &linprocfs_doprocstatm, 1408167482Sdes NULL, NULL, NULL, PFS_RD); 140985129Sdes pfs_create_file(dir, "status", &linprocfs_doprocstatus, 1410167482Sdes NULL, NULL, NULL, PFS_RD); 1411204825Sed pfs_create_link(dir, "fd", &linprocfs_dofdescfs, 1412204825Sed NULL, NULL, NULL, 0); 141385129Sdes 1414158311Sambrisko /* /proc/scsi/... */ 1415167482Sdes dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0); 1416158311Sambrisko pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo, 1417167482Sdes NULL, NULL, NULL, PFS_RD); 1418158311Sambrisko pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi, 1419167482Sdes NULL, NULL, NULL, PFS_RD); 1420163129Snetchild 1421163129Snetchild /* /proc/sys/... */ 1422167482Sdes dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0); 1423163129Snetchild /* /proc/sys/kernel/... */ 1424167482Sdes dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0); 1425167159Sjkim pfs_create_file(dir, "osrelease", &linprocfs_doosrelease, 1426167482Sdes NULL, NULL, NULL, PFS_RD); 1427167159Sjkim pfs_create_file(dir, "ostype", &linprocfs_doostype, 1428167482Sdes NULL, NULL, NULL, PFS_RD); 1429167159Sjkim pfs_create_file(dir, "version", &linprocfs_doosbuild, 1430167482Sdes NULL, NULL, NULL, PFS_RD); 1431164692Sjkim pfs_create_file(dir, "msgmni", &linprocfs_domsgmni, 1432167482Sdes NULL, NULL, NULL, PFS_RD); 1433163129Snetchild pfs_create_file(dir, "pid_max", &linprocfs_dopid_max, 1434167482Sdes NULL, NULL, NULL, PFS_RD); 1435164692Sjkim pfs_create_file(dir, "sem", &linprocfs_dosem, 1436167482Sdes NULL, NULL, NULL, PFS_RD); 1437163129Snetchild 143885129Sdes return (0); 143985129Sdes} 144085129Sdes 144185129Sdes/* 144285129Sdes * Destructor 144385129Sdes */ 144485129Sdesstatic int 144585129Sdeslinprocfs_uninit(PFS_INIT_ARGS) 144685129Sdes{ 144785129Sdes 144885129Sdes /* nothing to do, pseudofs will GC */ 144985129Sdes return (0); 145085129Sdes} 145185129Sdes 1452232278SmmPSEUDOFS(linprocfs, 1, 0); 145378025SdesMODULE_DEPEND(linprocfs, linux, 1, 1, 1); 145478025SdesMODULE_DEPEND(linprocfs, procfs, 1, 1, 1); 1455168440SjkimMODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1); 1456168440SjkimMODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1); 1457