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> 75263103Seadler#include <sys/uuid.h> 7683926Sdes#include <sys/vmmeter.h> 7759412Smsmith#include <sys/vnode.h> 78190445Sambrisko#include <sys/bus.h> 7959412Smsmith 8083926Sdes#include <net/if.h> 81185571Sbz#include <net/vnet.h> 8283926Sdes 8359412Smsmith#include <vm/vm.h> 84185984Skib#include <vm/vm_extern.h> 8559412Smsmith#include <vm/pmap.h> 8667588Sdes#include <vm/vm_map.h> 8759412Smsmith#include <vm/vm_param.h> 8860860Sdes#include <vm/vm_object.h> 8959412Smsmith#include <vm/swap_pager.h> 9069799Sdes 9167589Sdes#include <machine/clock.h> 9278113Sdes 93190445Sambrisko#include <geom/geom.h> 94190445Sambrisko#include <geom/geom_int.h> 95190445Sambrisko 96133822Stjr#if defined(__i386__) || defined(__amd64__) 9767589Sdes#include <machine/cputypes.h> 9859412Smsmith#include <machine/md_var.h> 99133822Stjr#endif /* __i386__ || __amd64__ */ 10059412Smsmith 101213246Skib#ifdef COMPAT_FREEBSD32 102213246Skib#include <compat/freebsd32/freebsd32_util.h> 103213246Skib#endif 104213246Skib 105140214Sobrien#ifdef COMPAT_LINUX32 /* XXX */ 106140214Sobrien#include <machine/../linux32/linux.h> 107140214Sobrien#else 10887275Srwatson#include <machine/../linux/linux.h> 109133822Stjr#endif 11085129Sdes#include <compat/linux/linux_ioctl.h> 11169995Sdes#include <compat/linux/linux_mib.h> 11285289Sdes#include <compat/linux/linux_util.h> 11378025Sdes#include <fs/pseudofs/pseudofs.h> 11484248Sdes#include <fs/procfs/procfs.h> 11559412Smsmith 11667588Sdes/* 11767588Sdes * Various conversion macros 11867588Sdes */ 119206081Snetchild#define T2J(x) ((long)(((x) * 100ULL) / (stathz ? stathz : hz))) /* ticks to jiffies */ 120206081Snetchild#define T2CS(x) ((unsigned long)(((x) * 100ULL) / (stathz ? stathz : hz))) /* ticks to centiseconds */ 12167588Sdes#define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */ 12267588Sdes#define B2K(x) ((x) >> 10) /* bytes to kbytes */ 12369799Sdes#define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */ 12467588Sdes#define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */ 12567588Sdes#define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */ 126206081Snetchild#define TV2J(x) ((x)->tv_sec * 100UL + (x)->tv_usec / 10000) 12774135Sjlemon 128159995Snetchild/** 129159995Snetchild * @brief Mapping of ki_stat in struct kinfo_proc to the linux state 130159995Snetchild * 131159995Snetchild * The linux procfs state field displays one of the characters RSDZTW to 132159995Snetchild * denote running, sleeping in an interruptible wait, waiting in an 133172568Skevlo * uninterruptible disk sleep, a zombie process, process is being traced 134159995Snetchild * or stopped, or process is paging respectively. 135159995Snetchild * 136159995Snetchild * Our struct kinfo_proc contains the variable ki_stat which contains a 137159995Snetchild * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK. 138159995Snetchild * 139159995Snetchild * This character array is used with ki_stati-1 as an index and tries to 140159995Snetchild * map our states to suitable linux states. 141159995Snetchild */ 142166140Snetchildstatic char linux_state[] = "RRSTZDD"; 143159995Snetchild 14478113Sdes/* 14578113Sdes * Filler function for proc/meminfo 14678113Sdes */ 14778025Sdesstatic int 14878025Sdeslinprocfs_domeminfo(PFS_FILL_ARGS) 14959412Smsmith{ 15059412Smsmith unsigned long memtotal; /* total memory in bytes */ 15159412Smsmith unsigned long memused; /* used memory in bytes */ 15259412Smsmith unsigned long memfree; /* free memory in bytes */ 15359412Smsmith unsigned long memshared; /* shared memory ??? */ 15459412Smsmith unsigned long buffers, cached; /* buffer / cache memory ??? */ 155113574Sjhb unsigned long long swaptotal; /* total swap space in bytes */ 156113574Sjhb unsigned long long swapused; /* used swap space in bytes */ 157113574Sjhb unsigned long long swapfree; /* free swap space in bytes */ 15860860Sdes vm_object_t object; 159117723Sphk int i, j; 16059412Smsmith 16159412Smsmith memtotal = physmem * PAGE_SIZE; 16259412Smsmith /* 16359412Smsmith * The correct thing here would be: 16459412Smsmith * 165170170Sattilio memfree = cnt.v_free_count * PAGE_SIZE; 16659412Smsmith memused = memtotal - memfree; 16759412Smsmith * 16859412Smsmith * but it might mislead linux binaries into thinking there 16959412Smsmith * is very little memory left, so we cheat and tell them that 17059412Smsmith * all memory that isn't wired down is free. 17159412Smsmith */ 172170170Sattilio memused = cnt.v_wire_count * PAGE_SIZE; 17359412Smsmith memfree = memtotal - memused; 174117723Sphk swap_pager_status(&i, &j); 175153310Smlaier swaptotal = (unsigned long long)i * PAGE_SIZE; 176153310Smlaier swapused = (unsigned long long)j * PAGE_SIZE; 177117723Sphk swapfree = swaptotal - swapused; 17860860Sdes memshared = 0; 179124082Salc mtx_lock(&vm_object_list_mtx); 18071471Sjhb TAILQ_FOREACH(object, &vm_object_list, object_list) 18160860Sdes if (object->shadow_count > 1) 18260860Sdes memshared += object->resident_page_count; 183124082Salc mtx_unlock(&vm_object_list_mtx); 18460860Sdes memshared *= PAGE_SIZE; 18559412Smsmith /* 18659412Smsmith * We'd love to be able to write: 18759412Smsmith * 18859412Smsmith buffers = bufspace; 18959412Smsmith * 19059412Smsmith * but bufspace is internal to vfs_bio.c and we don't feel 19159412Smsmith * like unstaticizing it just for linprocfs's sake. 19259412Smsmith */ 19359412Smsmith buffers = 0; 194170170Sattilio cached = cnt.v_cache_count * PAGE_SIZE; 19559412Smsmith 19678025Sdes sbuf_printf(sb, 19778031Sdes " total: used: free: shared: buffers: cached:\n" 19869799Sdes "Mem: %lu %lu %lu %lu %lu %lu\n" 19976839Sjlemon "Swap: %llu %llu %llu\n" 20069799Sdes "MemTotal: %9lu kB\n" 20169799Sdes "MemFree: %9lu kB\n" 20269799Sdes "MemShared:%9lu kB\n" 20369799Sdes "Buffers: %9lu kB\n" 20469799Sdes "Cached: %9lu kB\n" 20576839Sjlemon "SwapTotal:%9llu kB\n" 20676839Sjlemon "SwapFree: %9llu kB\n", 20769799Sdes memtotal, memused, memfree, memshared, buffers, cached, 20869799Sdes swaptotal, swapused, swapfree, 20969799Sdes B2K(memtotal), B2K(memfree), 21069799Sdes B2K(memshared), B2K(buffers), B2K(cached), 21169799Sdes B2K(swaptotal), B2K(swapfree)); 21259412Smsmith 21378025Sdes return (0); 21459412Smsmith} 21559412Smsmith 216133822Stjr#if defined(__i386__) || defined(__amd64__) 21778113Sdes/* 218133822Stjr * Filler function for proc/cpuinfo (i386 & amd64 version) 21978113Sdes */ 22078113Sdesstatic int 22178113Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS) 22278113Sdes{ 223159544Sdes int hw_model[2]; 224159544Sdes char model[128]; 225220433Sjkim uint64_t freq; 226159544Sdes size_t size; 227123246Sdes int class, fqmhz, fqkhz; 228118421Sdes int i; 22959412Smsmith 23069799Sdes /* 23178031Sdes * We default the flags to include all non-conflicting flags, 23278031Sdes * and the Intel versions of conflicting flags. 23369799Sdes */ 23478031Sdes static char *flags[] = { 23578031Sdes "fpu", "vme", "de", "pse", "tsc", 23678031Sdes "msr", "pae", "mce", "cx8", "apic", 23778031Sdes "sep", "sep", "mtrr", "pge", "mca", 23878031Sdes "cmov", "pat", "pse36", "pn", "b19", 23978031Sdes "b20", "b21", "mmxext", "mmx", "fxsr", 240183385Scognet "xmm", "sse2", "b27", "b28", "b29", 24167589Sdes "3dnowext", "3dnow" 24267589Sdes }; 24367589Sdes 24459412Smsmith switch (cpu_class) { 245133822Stjr#ifdef __i386__ 24659412Smsmith case CPUCLASS_286: 24767589Sdes class = 2; 24859412Smsmith break; 24959412Smsmith case CPUCLASS_386: 25067589Sdes class = 3; 25159412Smsmith break; 25259412Smsmith case CPUCLASS_486: 25367589Sdes class = 4; 25459412Smsmith break; 25559412Smsmith case CPUCLASS_586: 25667589Sdes class = 5; 25759412Smsmith break; 25859412Smsmith case CPUCLASS_686: 25967589Sdes class = 6; 26059412Smsmith break; 26159412Smsmith default: 26278031Sdes class = 0; 26359412Smsmith break; 264159170Sdes#else /* __amd64__ */ 265133822Stjr default: 266159170Sdes class = 15; 267133822Stjr break; 268133822Stjr#endif 26959412Smsmith } 27059412Smsmith 271159544Sdes hw_model[0] = CTL_HW; 272159544Sdes hw_model[1] = HW_MODEL; 273159544Sdes model[0] = '\0'; 274159544Sdes size = sizeof(model); 275159544Sdes if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0) 276159544Sdes strcpy(model, "unknown"); 277123246Sdes for (i = 0; i < mp_ncpus; ++i) { 278118421Sdes sbuf_printf(sb, 279118421Sdes "processor\t: %d\n" 280118421Sdes "vendor_id\t: %.20s\n" 281214982Sdes "cpu family\t: %u\n" 282214982Sdes "model\t\t: %u\n" 283159544Sdes "model name\t: %s\n" 284214982Sdes "stepping\t: %u\n\n", 285214985Sdes i, cpu_vendor, CPUID_TO_FAMILY(cpu_id), 286214985Sdes CPUID_TO_MODEL(cpu_id), model, cpu_id & CPUID_STEPPING); 287159544Sdes /* XXX per-cpu vendor / class / model / id? */ 288118421Sdes } 28959412Smsmith 290185766Skib sbuf_cat(sb, "flags\t\t:"); 29167589Sdes 292187594Sjkim#ifdef __i386__ 293187594Sjkim switch (cpu_vendor_id) { 294187594Sjkim case CPU_VENDOR_AMD: 295187594Sjkim if (class < 6) 296187594Sjkim flags[16] = "fcmov"; 297187594Sjkim break; 298187594Sjkim case CPU_VENDOR_CYRIX: 29967589Sdes flags[24] = "cxmmx"; 300187594Sjkim break; 30178031Sdes } 302187594Sjkim#endif 303119068Sdes 30478031Sdes for (i = 0; i < 32; i++) 30567589Sdes if (cpu_feature & (1 << i)) 30678025Sdes sbuf_printf(sb, " %s", flags[i]); 30778025Sdes sbuf_cat(sb, "\n"); 308220433Sjkim freq = atomic_load_acq_64(&tsc_freq); 309220433Sjkim if (freq != 0) { 310220433Sjkim fqmhz = (freq + 4999) / 1000000; 311220433Sjkim fqkhz = ((freq + 4999) / 10000) % 100; 31278025Sdes sbuf_printf(sb, 31369799Sdes "cpu MHz\t\t: %d.%02d\n" 31469799Sdes "bogomips\t: %d.%02d\n", 31569799Sdes fqmhz, fqkhz, fqmhz, fqkhz); 31678031Sdes } 31769995Sdes 31878025Sdes return (0); 31959412Smsmith} 320133822Stjr#endif /* __i386__ || __amd64__ */ 32165633Sdes 32278113Sdes/* 32385289Sdes * Filler function for proc/mtab 32485289Sdes * 32585289Sdes * This file doesn't exist in Linux' procfs, but is included here so 32685289Sdes * users can symlink /compat/linux/etc/mtab to /proc/mtab 32785289Sdes */ 32885289Sdesstatic int 32985289Sdeslinprocfs_domtab(PFS_FILL_ARGS) 33085289Sdes{ 33185289Sdes struct nameidata nd; 33285289Sdes struct mount *mp; 33391334Sjulian const char *lep; 33491334Sjulian char *dlep, *flep, *mntto, *mntfrom, *fstype; 33585289Sdes size_t lep_len; 33685289Sdes int error; 33785289Sdes 33885289Sdes /* resolve symlinks etc. in the emulation tree prefix */ 339168942Sdes NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td); 34085289Sdes flep = NULL; 341168942Sdes error = namei(&nd); 342184649Sjhb lep = linux_emul_path; 343184649Sjhb if (error == 0) { 344188579Sjhb if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0) 345184649Sjhb lep = dlep; 346184649Sjhb vrele(nd.ni_vp); 347184649Sjhb VFS_UNLOCK_GIANT(NDHASGIANT(&nd)); 348184649Sjhb } 34985289Sdes lep_len = strlen(lep); 350119068Sdes 35185289Sdes mtx_lock(&mountlist_mtx); 35285289Sdes error = 0; 35385289Sdes TAILQ_FOREACH(mp, &mountlist, mnt_list) { 35485289Sdes /* determine device name */ 35585289Sdes mntfrom = mp->mnt_stat.f_mntfromname; 356119068Sdes 35785289Sdes /* determine mount point */ 35885289Sdes mntto = mp->mnt_stat.f_mntonname; 35985289Sdes if (strncmp(mntto, lep, lep_len) == 0 && 36085289Sdes mntto[lep_len] == '/') 36185289Sdes mntto += lep_len; 36285289Sdes 36385289Sdes /* determine fs type */ 36485289Sdes fstype = mp->mnt_stat.f_fstypename; 36585289Sdes if (strcmp(fstype, pn->pn_info->pi_name) == 0) 36685289Sdes mntfrom = fstype = "proc"; 36785289Sdes else if (strcmp(fstype, "procfs") == 0) 36885289Sdes continue; 369119068Sdes 370158311Sambrisko if (strcmp(fstype, "linsysfs") == 0) { 371158311Sambrisko sbuf_printf(sb, "/sys %s sysfs %s", mntto, 372158311Sambrisko mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); 373158311Sambrisko } else { 374190445Sambrisko /* For Linux msdosfs is called vfat */ 375190445Sambrisko if (strcmp(fstype, "msdosfs") == 0) 376190445Sambrisko fstype = "vfat"; 377158311Sambrisko sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype, 378158311Sambrisko mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); 379158311Sambrisko } 38085289Sdes#define ADD_OPTION(opt, name) \ 38185289Sdes if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name); 38285289Sdes ADD_OPTION(MNT_SYNCHRONOUS, "sync"); 38385289Sdes ADD_OPTION(MNT_NOEXEC, "noexec"); 38485289Sdes ADD_OPTION(MNT_NOSUID, "nosuid"); 38585289Sdes ADD_OPTION(MNT_UNION, "union"); 38685289Sdes ADD_OPTION(MNT_ASYNC, "async"); 38785289Sdes ADD_OPTION(MNT_SUIDDIR, "suiddir"); 38885289Sdes ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow"); 38985289Sdes ADD_OPTION(MNT_NOATIME, "noatime"); 39085289Sdes#undef ADD_OPTION 39185289Sdes /* a real Linux mtab will also show NFS options */ 39285289Sdes sbuf_printf(sb, " 0 0\n"); 39385289Sdes } 39485289Sdes mtx_unlock(&mountlist_mtx); 39585289Sdes if (flep != NULL) 39685289Sdes free(flep, M_TEMP); 39785289Sdes return (error); 39885289Sdes} 39985289Sdes 40085289Sdes/* 401190445Sambrisko * Filler function for proc/partitions 402190445Sambrisko * 403190445Sambrisko */ 404190445Sambriskostatic int 405190445Sambriskolinprocfs_dopartitions(PFS_FILL_ARGS) 406190445Sambrisko{ 407190445Sambrisko struct g_class *cp; 408190445Sambrisko struct g_geom *gp; 409190445Sambrisko struct g_provider *pp; 410190445Sambrisko struct nameidata nd; 411190445Sambrisko const char *lep; 412190445Sambrisko char *dlep, *flep; 413190445Sambrisko size_t lep_len; 414190445Sambrisko int error; 415190445Sambrisko int major, minor; 416190445Sambrisko 417190445Sambrisko /* resolve symlinks etc. in the emulation tree prefix */ 418190445Sambrisko NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td); 419190445Sambrisko flep = NULL; 420190445Sambrisko error = namei(&nd); 421190445Sambrisko lep = linux_emul_path; 422190445Sambrisko if (error == 0) { 423190445Sambrisko if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0) 424190445Sambrisko lep = dlep; 425190445Sambrisko vrele(nd.ni_vp); 426190445Sambrisko VFS_UNLOCK_GIANT(NDHASGIANT(&nd)); 427190445Sambrisko } 428190445Sambrisko lep_len = strlen(lep); 429190445Sambrisko 430190445Sambrisko g_topology_lock(); 431190445Sambrisko error = 0; 432190445Sambrisko sbuf_printf(sb, "major minor #blocks name rio rmerge rsect " 433190445Sambrisko "ruse wio wmerge wsect wuse running use aveq\n"); 434190445Sambrisko 435190445Sambrisko LIST_FOREACH(cp, &g_classes, class) { 436190445Sambrisko if (strcmp(cp->name, "DISK") == 0 || 437190445Sambrisko strcmp(cp->name, "PART") == 0) 438190445Sambrisko LIST_FOREACH(gp, &cp->geom, geom) { 439190445Sambrisko LIST_FOREACH(pp, &gp->provider, provider) { 440190445Sambrisko if (linux_driver_get_major_minor( 441190445Sambrisko pp->name, &major, &minor) != 0) { 442190445Sambrisko major = 0; 443190445Sambrisko minor = 0; 444190445Sambrisko } 445190445Sambrisko sbuf_printf(sb, "%d %d %lld %s " 446190445Sambrisko "%d %d %d %d %d " 447190445Sambrisko "%d %d %d %d %d %d\n", 448190445Sambrisko major, minor, 449190445Sambrisko (long long)pp->mediasize, pp->name, 450190445Sambrisko 0, 0, 0, 0, 0, 451190445Sambrisko 0, 0, 0, 0, 0, 0); 452190445Sambrisko } 453190445Sambrisko } 454190445Sambrisko } 455190445Sambrisko g_topology_unlock(); 456190445Sambrisko 457190445Sambrisko if (flep != NULL) 458190445Sambrisko free(flep, M_TEMP); 459190445Sambrisko return (error); 460190445Sambrisko} 461190445Sambrisko 462190445Sambrisko 463190445Sambrisko/* 46478113Sdes * Filler function for proc/stat 46578113Sdes */ 46678025Sdesstatic int 46778025Sdeslinprocfs_dostat(PFS_FILL_ARGS) 46865633Sdes{ 469174070Speter struct pcpu *pcpu; 470174070Speter long cp_time[CPUSTATES]; 471174070Speter long *cp; 472123246Sdes int i; 473120339Sdes 474174070Speter read_cpu_time(cp_time); 475120339Sdes sbuf_printf(sb, "cpu %ld %ld %ld %ld\n", 476120339Sdes T2J(cp_time[CP_USER]), 477120339Sdes T2J(cp_time[CP_NICE]), 478120339Sdes T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/), 479120339Sdes T2J(cp_time[CP_IDLE])); 480209059Sjhb CPU_FOREACH(i) { 481174070Speter pcpu = pcpu_find(i); 482174070Speter cp = pcpu->pc_cp_time; 483143194Ssobomax sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i, 484174070Speter T2J(cp[CP_USER]), 485174070Speter T2J(cp[CP_NICE]), 486174070Speter T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/), 487174070Speter T2J(cp[CP_IDLE])); 488174070Speter } 48978025Sdes sbuf_printf(sb, 49069799Sdes "disk 0 0 0 0\n" 49169799Sdes "page %u %u\n" 49269799Sdes "swap %u %u\n" 49369799Sdes "intr %u\n" 49469799Sdes "ctxt %u\n" 49585657Sdillon "btime %lld\n", 496170170Sattilio cnt.v_vnodepgsin, 497170170Sattilio cnt.v_vnodepgsout, 498170170Sattilio cnt.v_swappgsin, 499170170Sattilio cnt.v_swappgsout, 500170170Sattilio cnt.v_intr, 501170170Sattilio cnt.v_swtch, 502113574Sjhb (long long)boottime.tv_sec); 50378025Sdes return (0); 50465633Sdes} 50565633Sdes 506224582Skibstatic int 507224582Skiblinprocfs_doswaps(PFS_FILL_ARGS) 508224582Skib{ 509224582Skib struct xswdev xsw; 510224582Skib uintmax_t total, used; 511224582Skib int n; 512224582Skib char devname[SPECNAMELEN + 1]; 513224582Skib 514224582Skib sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"); 515224582Skib mtx_lock(&Giant); 516224582Skib for (n = 0; ; n++) { 517224582Skib if (swap_dev_info(n, &xsw, devname, sizeof(devname)) != 0) 518224582Skib break; 519224582Skib total = (uintmax_t)xsw.xsw_nblks * PAGE_SIZE / 1024; 520224582Skib used = (uintmax_t)xsw.xsw_used * PAGE_SIZE / 1024; 521224582Skib 522224582Skib /* 523224582Skib * The space and not tab after the device name is on 524224582Skib * purpose. Linux does so. 525224582Skib */ 526224582Skib sbuf_printf(sb, "/dev/%-34s unknown\t\t%jd\t%jd\t-1\n", 527224582Skib devname, total, used); 528224582Skib } 529224582Skib mtx_unlock(&Giant); 530224582Skib return (0); 531224582Skib} 532224582Skib 53378113Sdes/* 53478113Sdes * Filler function for proc/uptime 53578113Sdes */ 53678025Sdesstatic int 53778025Sdeslinprocfs_douptime(PFS_FILL_ARGS) 53865633Sdes{ 539174070Speter long cp_time[CPUSTATES]; 54065633Sdes struct timeval tv; 54165633Sdes 54265633Sdes getmicrouptime(&tv); 543174070Speter read_cpu_time(cp_time); 544206081Snetchild sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n", 545113574Sjhb (long long)tv.tv_sec, tv.tv_usec / 10000, 546206081Snetchild T2S(cp_time[CP_IDLE] / mp_ncpus), 547206081Snetchild T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100); 54878025Sdes return (0); 54965633Sdes} 55065633Sdes 55178113Sdes/* 552167159Sjkim * Get OS build date 553167159Sjkim */ 554167159Sjkimstatic void 555167159Sjkimlinprocfs_osbuild(struct thread *td, struct sbuf *sb) 556167159Sjkim{ 557167159Sjkim#if 0 558167159Sjkim char osbuild[256]; 559167159Sjkim char *cp1, *cp2; 560167159Sjkim 561167159Sjkim strncpy(osbuild, version, 256); 562167159Sjkim osbuild[255] = '\0'; 563167159Sjkim cp1 = strstr(osbuild, "\n"); 564167159Sjkim cp2 = strstr(osbuild, ":"); 565167159Sjkim if (cp1 && cp2) { 566167159Sjkim *cp1 = *cp2 = '\0'; 567167159Sjkim cp1 = strstr(osbuild, "#"); 568167159Sjkim } else 569167159Sjkim cp1 = NULL; 570167159Sjkim if (cp1) 571167159Sjkim sbuf_printf(sb, "%s%s", cp1, cp2 + 1); 572167159Sjkim else 573167159Sjkim#endif 574167159Sjkim sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977"); 575167159Sjkim} 576167159Sjkim 577167159Sjkim/* 578167159Sjkim * Get OS builder 579167159Sjkim */ 580167159Sjkimstatic void 581167159Sjkimlinprocfs_osbuilder(struct thread *td, struct sbuf *sb) 582167159Sjkim{ 583168762Sdes#if 0 584167159Sjkim char builder[256]; 585167159Sjkim char *cp; 586167159Sjkim 587167159Sjkim cp = strstr(version, "\n "); 588167159Sjkim if (cp) { 589167159Sjkim strncpy(builder, cp + 5, 256); 590167159Sjkim builder[255] = '\0'; 591167159Sjkim cp = strstr(builder, ":"); 592167159Sjkim if (cp) 593167159Sjkim *cp = '\0'; 594167159Sjkim } 595167159Sjkim if (cp) 596167159Sjkim sbuf_cat(sb, builder); 597167159Sjkim else 598168762Sdes#endif 599167159Sjkim sbuf_cat(sb, "des@freebsd.org"); 600167159Sjkim} 601167159Sjkim 602167159Sjkim/* 60378113Sdes * Filler function for proc/version 60478113Sdes */ 60578025Sdesstatic int 60678025Sdeslinprocfs_doversion(PFS_FILL_ARGS) 60765633Sdes{ 60887275Srwatson char osname[LINUX_MAX_UTSNAME]; 60987275Srwatson char osrelease[LINUX_MAX_UTSNAME]; 61087275Srwatson 611112206Sjhb linux_get_osname(td, osname); 612112206Sjhb linux_get_osrelease(td, osrelease); 613167159Sjkim sbuf_printf(sb, "%s version %s (", osname, osrelease); 614167159Sjkim linprocfs_osbuilder(td, sb); 615167159Sjkim sbuf_cat(sb, ") (gcc version " __VERSION__ ") "); 616167159Sjkim linprocfs_osbuild(td, sb); 617167159Sjkim sbuf_cat(sb, "\n"); 61887275Srwatson 61978025Sdes return (0); 62065633Sdes} 62165633Sdes 62278113Sdes/* 62378113Sdes * Filler function for proc/loadavg 62478113Sdes */ 62578025Sdesstatic int 62678025Sdeslinprocfs_doloadavg(PFS_FILL_ARGS) 62776839Sjlemon{ 628168762Sdes 62978025Sdes sbuf_printf(sb, 63076839Sjlemon "%d.%02d %d.%02d %d.%02d %d/%d %d\n", 63176839Sjlemon (int)(averunnable.ldavg[0] / averunnable.fscale), 63276839Sjlemon (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100), 63376839Sjlemon (int)(averunnable.ldavg[1] / averunnable.fscale), 63476839Sjlemon (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100), 63576839Sjlemon (int)(averunnable.ldavg[2] / averunnable.fscale), 63676839Sjlemon (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100), 63776839Sjlemon 1, /* number of running tasks */ 63876839Sjlemon nprocs, /* number of tasks */ 63978116Sdes lastpid /* the last pid */ 64076839Sjlemon ); 64178025Sdes return (0); 64276839Sjlemon} 64376839Sjlemon 64478113Sdes/* 64578113Sdes * Filler function for proc/pid/stat 64678113Sdes */ 64778025Sdesstatic int 64878025Sdeslinprocfs_doprocstat(PFS_FILL_ARGS) 64967588Sdes{ 65069995Sdes struct kinfo_proc kp; 651166140Snetchild char state; 652166140Snetchild static int ratelimit = 0; 653206081Snetchild vm_offset_t startcode, startdata; 65467588Sdes 65594307Sjhb PROC_LOCK(p); 65669995Sdes fill_kinfo_proc(p, &kp); 657206081Snetchild if (p->p_vmspace) { 658206081Snetchild startcode = (vm_offset_t)p->p_vmspace->vm_taddr; 659206081Snetchild startdata = (vm_offset_t)p->p_vmspace->vm_daddr; 660206081Snetchild } else { 661206081Snetchild startcode = 0; 662206081Snetchild startdata = 0; 663206081Snetchild }; 66478025Sdes sbuf_printf(sb, "%d", p->p_pid); 66578025Sdes#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg) 66667588Sdes PS_ADD("comm", "(%s)", p->p_comm); 667166140Snetchild if (kp.ki_stat > sizeof(linux_state)) { 668166140Snetchild state = 'R'; 669166140Snetchild 670166141Snetchild if (ratelimit == 0) { 671166162Snetchild printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n", 672166162Snetchild kp.ki_stat, sizeof(linux_state)); 673166141Snetchild ++ratelimit; 674166141Snetchild } 675166140Snetchild } else 676166140Snetchild state = linux_state[kp.ki_stat - 1]; 677166140Snetchild PS_ADD("state", "%c", state); 67873923Sjhb PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0); 67967588Sdes PS_ADD("pgrp", "%d", p->p_pgid); 68067588Sdes PS_ADD("session", "%d", p->p_session->s_sid); 68191140Stanimura PROC_UNLOCK(p); 682206081Snetchild PS_ADD("tty", "%d", kp.ki_tdev); 683159995Snetchild PS_ADD("tpgid", "%d", kp.ki_tpgid); 68467588Sdes PS_ADD("flags", "%u", 0); /* XXX */ 685159995Snetchild PS_ADD("minflt", "%lu", kp.ki_rusage.ru_minflt); 686159995Snetchild PS_ADD("cminflt", "%lu", kp.ki_rusage_ch.ru_minflt); 687159995Snetchild PS_ADD("majflt", "%lu", kp.ki_rusage.ru_majflt); 688159995Snetchild PS_ADD("cmajflt", "%lu", kp.ki_rusage_ch.ru_majflt); 689206081Snetchild PS_ADD("utime", "%ld", TV2J(&kp.ki_rusage.ru_utime)); 690206081Snetchild PS_ADD("stime", "%ld", TV2J(&kp.ki_rusage.ru_stime)); 691206081Snetchild PS_ADD("cutime", "%ld", TV2J(&kp.ki_rusage_ch.ru_utime)); 692206081Snetchild PS_ADD("cstime", "%ld", TV2J(&kp.ki_rusage_ch.ru_stime)); 693159995Snetchild PS_ADD("priority", "%d", kp.ki_pri.pri_user); 694159995Snetchild PS_ADD("nice", "%d", kp.ki_nice); /* 19 (nicest) to -19 */ 695159995Snetchild PS_ADD("0", "%d", 0); /* removed field */ 696159995Snetchild PS_ADD("itrealvalue", "%d", 0); /* XXX */ 697206081Snetchild PS_ADD("starttime", "%lu", TV2J(&kp.ki_start) - TV2J(&boottime)); 698159995Snetchild PS_ADD("vsize", "%ju", P2K((uintmax_t)kp.ki_size)); 699159995Snetchild PS_ADD("rss", "%ju", (uintmax_t)kp.ki_rssize); 700159995Snetchild PS_ADD("rlim", "%lu", kp.ki_rusage.ru_maxrss); 701206081Snetchild PS_ADD("startcode", "%ju", (uintmax_t)startcode); 702206081Snetchild PS_ADD("endcode", "%ju", (uintmax_t)startdata); 70367588Sdes PS_ADD("startstack", "%u", 0); /* XXX */ 704159995Snetchild PS_ADD("kstkesp", "%u", 0); /* XXX */ 705159995Snetchild PS_ADD("kstkeip", "%u", 0); /* XXX */ 706159995Snetchild PS_ADD("signal", "%u", 0); /* XXX */ 707159995Snetchild PS_ADD("blocked", "%u", 0); /* XXX */ 708159995Snetchild PS_ADD("sigignore", "%u", 0); /* XXX */ 709159995Snetchild PS_ADD("sigcatch", "%u", 0); /* XXX */ 71067588Sdes PS_ADD("wchan", "%u", 0); /* XXX */ 711159995Snetchild PS_ADD("nswap", "%lu", kp.ki_rusage.ru_nswap); 712159995Snetchild PS_ADD("cnswap", "%lu", kp.ki_rusage_ch.ru_nswap); 71369799Sdes PS_ADD("exitsignal", "%d", 0); /* XXX */ 714159995Snetchild PS_ADD("processor", "%u", kp.ki_lastcpu); 715159995Snetchild PS_ADD("rt_priority", "%u", 0); /* XXX */ /* >= 2.5.19 */ 716159995Snetchild PS_ADD("policy", "%u", kp.ki_pri.pri_class); /* >= 2.5.19 */ 71767588Sdes#undef PS_ADD 71878025Sdes sbuf_putc(sb, '\n'); 719119068Sdes 72078025Sdes return (0); 72167588Sdes} 72267588Sdes 72367588Sdes/* 724119911Sdes * Filler function for proc/pid/statm 725119911Sdes */ 726119911Sdesstatic int 727119911Sdeslinprocfs_doprocstatm(PFS_FILL_ARGS) 728119911Sdes{ 729119911Sdes struct kinfo_proc kp; 730119911Sdes segsz_t lsize; 731120340Sdes 732119911Sdes PROC_LOCK(p); 733119911Sdes fill_kinfo_proc(p, &kp); 734119911Sdes PROC_UNLOCK(p); 735119911Sdes 736119911Sdes /* 737119911Sdes * See comments in linprocfs_doprocstatus() regarding the 738119911Sdes * computation of lsize. 739119911Sdes */ 740119911Sdes /* size resident share trs drs lrs dt */ 741119911Sdes sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size)); 742119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize); 743119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */ 744119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize); 745119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize)); 746119911Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 747119911Sdes kp.ki_ssize - kp.ki_tsize - 1; 748119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)lsize); 749119911Sdes sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */ 750119911Sdes 751119911Sdes return (0); 752119911Sdes} 753119911Sdes 754119911Sdes/* 75578113Sdes * Filler function for proc/pid/status 75678113Sdes */ 75778025Sdesstatic int 75878025Sdeslinprocfs_doprocstatus(PFS_FILL_ARGS) 75967588Sdes{ 76069995Sdes struct kinfo_proc kp; 76167588Sdes char *state; 76269799Sdes segsz_t lsize; 76399072Sjulian struct thread *td2; 764114983Sjhb struct sigacts *ps; 76574135Sjlemon int i; 76667588Sdes 767113611Sjhb PROC_LOCK(p); 76899072Sjulian td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */ 76999072Sjulian 77099072Sjulian if (P_SHOULDSTOP(p)) { 77199072Sjulian state = "T (stopped)"; 77299072Sjulian } else { 77399072Sjulian switch(p->p_state) { 77499072Sjulian case PRS_NEW: 77599072Sjulian state = "I (idle)"; 77699072Sjulian break; 77799072Sjulian case PRS_NORMAL: 77899072Sjulian if (p->p_flag & P_WEXIT) { 77999072Sjulian state = "X (exiting)"; 78099072Sjulian break; 78199072Sjulian } 78299072Sjulian switch(td2->td_state) { 783103216Sjulian case TDS_INHIBITED: 78499072Sjulian state = "S (sleeping)"; 78599072Sjulian break; 78699072Sjulian case TDS_RUNQ: 78799072Sjulian case TDS_RUNNING: 78899072Sjulian state = "R (running)"; 78999072Sjulian break; 79099072Sjulian default: 79199072Sjulian state = "? (unknown)"; 79299072Sjulian break; 79399072Sjulian } 79499072Sjulian break; 79599072Sjulian case PRS_ZOMBIE: 79699072Sjulian state = "Z (zombie)"; 79799072Sjulian break; 79899072Sjulian default: 79999072Sjulian state = "? (unknown)"; 80099072Sjulian break; 80199072Sjulian } 80299072Sjulian } 80367588Sdes 80469995Sdes fill_kinfo_proc(p, &kp); 80578025Sdes sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */ 80678031Sdes sbuf_printf(sb, "State:\t%s\n", state); 80767588Sdes 80867588Sdes /* 80967588Sdes * Credentials 81067588Sdes */ 81178025Sdes sbuf_printf(sb, "Pid:\t%d\n", p->p_pid); 81278025Sdes sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ? 81373923Sjhb p->p_pptr->p_pid : 0); 81478031Sdes sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid, 81578031Sdes p->p_ucred->cr_uid, 81678031Sdes p->p_ucred->cr_svuid, 81778031Sdes /* FreeBSD doesn't have fsuid */ 81878031Sdes p->p_ucred->cr_uid); 81978031Sdes sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid, 82078031Sdes p->p_ucred->cr_gid, 82178031Sdes p->p_ucred->cr_svgid, 82278031Sdes /* FreeBSD doesn't have fsgid */ 82378031Sdes p->p_ucred->cr_gid); 82478025Sdes sbuf_cat(sb, "Groups:\t"); 82567588Sdes for (i = 0; i < p->p_ucred->cr_ngroups; i++) 82678031Sdes sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]); 82771471Sjhb PROC_UNLOCK(p); 82878025Sdes sbuf_putc(sb, '\n'); 829119068Sdes 83067588Sdes /* 83167588Sdes * Memory 83269799Sdes * 83369799Sdes * While our approximation of VmLib may not be accurate (I 83469799Sdes * don't know of a simple way to verify it, and I'm not sure 83569799Sdes * it has much meaning anyway), I believe it's good enough. 83669799Sdes * 83769799Sdes * The same code that could (I think) accurately compute VmLib 83869799Sdes * could also compute VmLck, but I don't really care enough to 83969799Sdes * implement it. Submissions are welcome. 84067588Sdes */ 841113574Sjhb sbuf_printf(sb, "VmSize:\t%8ju kB\n", B2K((uintmax_t)kp.ki_size)); 84278025Sdes sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */ 843206081Snetchild sbuf_printf(sb, "VmRSS:\t%8ju kB\n", P2K((uintmax_t)kp.ki_rssize)); 844113574Sjhb sbuf_printf(sb, "VmData:\t%8ju kB\n", P2K((uintmax_t)kp.ki_dsize)); 845113574Sjhb sbuf_printf(sb, "VmStk:\t%8ju kB\n", P2K((uintmax_t)kp.ki_ssize)); 846113574Sjhb sbuf_printf(sb, "VmExe:\t%8ju kB\n", P2K((uintmax_t)kp.ki_tsize)); 84769995Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 84869995Sdes kp.ki_ssize - kp.ki_tsize - 1; 849113574Sjhb sbuf_printf(sb, "VmLib:\t%8ju kB\n", P2K((uintmax_t)lsize)); 85067588Sdes 85167588Sdes /* 85267588Sdes * Signal masks 85367588Sdes * 85467588Sdes * We support up to 128 signals, while Linux supports 32, 85567588Sdes * but we only define 32 (the same 32 as Linux, to boot), so 85667588Sdes * just show the lower 32 bits of each mask. XXX hack. 85767588Sdes * 85867588Sdes * NB: on certain platforms (Sparc at least) Linux actually 85967588Sdes * supports 64 signals, but this code is a long way from 86067588Sdes * running on anything but i386, so ignore that for now. 86167588Sdes */ 86271471Sjhb PROC_LOCK(p); 863104306Sjmallett sbuf_printf(sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]); 86469799Sdes /* 86569799Sdes * I can't seem to find out where the signal mask is in 86669799Sdes * relation to struct proc, so SigBlk is left unimplemented. 86769799Sdes */ 86878025Sdes sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */ 869114983Sjhb ps = p->p_sigacts; 870114983Sjhb mtx_lock(&ps->ps_mtx); 871114983Sjhb sbuf_printf(sb, "SigIgn:\t%08x\n", ps->ps_sigignore.__bits[0]); 872114983Sjhb sbuf_printf(sb, "SigCgt:\t%08x\n", ps->ps_sigcatch.__bits[0]); 873114983Sjhb mtx_unlock(&ps->ps_mtx); 87471471Sjhb PROC_UNLOCK(p); 875119068Sdes 87667588Sdes /* 87767588Sdes * Linux also prints the capability masks, but we don't have 87867588Sdes * capabilities yet, and when we do get them they're likely to 87967588Sdes * be meaningless to Linux programs, so we lie. XXX 88067588Sdes */ 88178025Sdes sbuf_printf(sb, "CapInh:\t%016x\n", 0); 88278025Sdes sbuf_printf(sb, "CapPrm:\t%016x\n", 0); 88378025Sdes sbuf_printf(sb, "CapEff:\t%016x\n", 0); 884119068Sdes 88578025Sdes return (0); 88667588Sdes} 88774135Sjlemon 888119911Sdes 88978113Sdes/* 890119911Sdes * Filler function for proc/pid/cwd 891119911Sdes */ 892119911Sdesstatic int 893119911Sdeslinprocfs_doproccwd(PFS_FILL_ARGS) 894119911Sdes{ 895119911Sdes char *fullpath = "unknown"; 896119911Sdes char *freepath = NULL; 897119911Sdes 898119911Sdes vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath); 899119911Sdes sbuf_printf(sb, "%s", fullpath); 900119911Sdes if (freepath) 901119911Sdes free(freepath, M_TEMP); 902119911Sdes return (0); 903119911Sdes} 904119911Sdes 905119911Sdes/* 906119911Sdes * Filler function for proc/pid/root 907119911Sdes */ 908119911Sdesstatic int 909119911Sdeslinprocfs_doprocroot(PFS_FILL_ARGS) 910119911Sdes{ 911119911Sdes struct vnode *rvp; 912119911Sdes char *fullpath = "unknown"; 913119911Sdes char *freepath = NULL; 914119911Sdes 915119911Sdes rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir; 916119911Sdes vn_fullpath(td, rvp, &fullpath, &freepath); 917119911Sdes sbuf_printf(sb, "%s", fullpath); 918119911Sdes if (freepath) 919119911Sdes free(freepath, M_TEMP); 920119911Sdes return (0); 921119911Sdes} 922119911Sdes 92378113Sdes/* 924213246Skib * Filler function for proc/pid/cmdline 925213246Skib */ 926213246Skibstatic int 927213246Skiblinprocfs_doproccmdline(PFS_FILL_ARGS) 928213246Skib{ 929213246Skib int ret; 930213246Skib 931213246Skib PROC_LOCK(p); 932213246Skib if ((ret = p_cansee(td, p)) != 0) { 933213246Skib PROC_UNLOCK(p); 934213246Skib return (ret); 935213246Skib } 936223182Spluknet 937223182Spluknet /* 938223182Spluknet * Mimic linux behavior and pass only processes with usermode 939223182Spluknet * address space as valid. Return zero silently otherwize. 940223182Spluknet */ 941223182Spluknet if (p->p_vmspace == &vmspace0) { 942223182Spluknet PROC_UNLOCK(p); 943223182Spluknet return (0); 944223182Spluknet } 945213246Skib if (p->p_args != NULL) { 946213246Skib sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length); 947213246Skib PROC_UNLOCK(p); 948213246Skib return (0); 949213246Skib } 950230754Strociny 951230754Strociny if ((p->p_flag & P_SYSTEM) != 0) { 952230754Strociny PROC_UNLOCK(p); 953230754Strociny return (0); 954230754Strociny } 955230754Strociny 956213246Skib PROC_UNLOCK(p); 957213246Skib 958230754Strociny ret = proc_getargv(td, p, sb); 959213246Skib return (ret); 960213246Skib} 961213246Skib 962213246Skib/* 963116173Sobrien * Filler function for proc/pid/environ 964116173Sobrien */ 965116173Sobrienstatic int 966116173Sobrienlinprocfs_doprocenviron(PFS_FILL_ARGS) 967116173Sobrien{ 968212723Sdes int ret; 969168762Sdes 970212723Sdes PROC_LOCK(p); 971230755Strociny if ((ret = p_candebug(td, p)) != 0) { 972212723Sdes PROC_UNLOCK(p); 973213246Skib return (ret); 974212723Sdes } 975223182Spluknet 976223182Spluknet /* 977223182Spluknet * Mimic linux behavior and pass only processes with usermode 978223182Spluknet * address space as valid. Return zero silently otherwize. 979223182Spluknet */ 980223182Spluknet if (p->p_vmspace == &vmspace0) { 981223182Spluknet PROC_UNLOCK(p); 982223182Spluknet return (0); 983223182Spluknet } 984230754Strociny 985230754Strociny if ((p->p_flag & P_SYSTEM) != 0) { 986230754Strociny PROC_UNLOCK(p); 987230754Strociny return (0); 988230754Strociny } 989230754Strociny 990213246Skib PROC_UNLOCK(p); 991212723Sdes 992230754Strociny ret = proc_getenvv(td, p, sb); 993212723Sdes return (ret); 994116173Sobrien} 995116173Sobrien 996116173Sobrien/* 997116173Sobrien * Filler function for proc/pid/maps 998116173Sobrien */ 999116173Sobrienstatic int 1000116173Sobrienlinprocfs_doprocmaps(PFS_FILL_ARGS) 1001116173Sobrien{ 1002185984Skib struct vmspace *vm; 1003185984Skib vm_map_t map; 1004185765Skib vm_map_entry_t entry, tmp_entry; 1005121265Scognet vm_object_t obj, tobj, lobj; 1006185765Skib vm_offset_t e_start, e_end; 1007121265Scognet vm_ooffset_t off = 0; 1008185765Skib vm_prot_t e_prot; 1009185765Skib unsigned int last_timestamp; 1010121265Scognet char *name = "", *freename = NULL; 1011121265Scognet ino_t ino; 1012121265Scognet int ref_count, shadow_count, flags; 1013121265Scognet int error; 1014137507Sphk struct vnode *vp; 1015137507Sphk struct vattr vat; 1016161094Skib int locked; 1017168762Sdes 1018121246Scognet PROC_LOCK(p); 1019121246Scognet error = p_candebug(td, p); 1020121246Scognet PROC_UNLOCK(p); 1021121246Scognet if (error) 1022121246Scognet return (error); 1023168762Sdes 1024121246Scognet if (uio->uio_rw != UIO_READ) 1025121246Scognet return (EOPNOTSUPP); 1026168762Sdes 1027121246Scognet error = 0; 1028185984Skib vm = vmspace_acquire_ref(p); 1029185984Skib if (vm == NULL) 1030185984Skib return (ESRCH); 1031185984Skib map = &vm->vm_map; 1032169156Salc vm_map_lock_read(map); 1033183600Skib for (entry = map->header.next; entry != &map->header; 1034121246Scognet entry = entry->next) { 1035121265Scognet name = ""; 1036121265Scognet freename = NULL; 1037121246Scognet if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) 1038121246Scognet continue; 1039185765Skib e_prot = entry->protection; 1040185765Skib e_start = entry->start; 1041185765Skib e_end = entry->end; 1042121246Scognet obj = entry->object.vm_object; 1043169156Salc for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) { 1044169156Salc VM_OBJECT_LOCK(tobj); 1045169156Salc if (lobj != obj) 1046169156Salc VM_OBJECT_UNLOCK(lobj); 1047121246Scognet lobj = tobj; 1048169156Salc } 1049185765Skib last_timestamp = map->timestamp; 1050185765Skib vm_map_unlock_read(map); 1051121246Scognet ino = 0; 1052121246Scognet if (lobj) { 1053121246Scognet off = IDX_TO_OFF(lobj->size); 1054161094Skib if (lobj->type == OBJT_VNODE) { 1055161094Skib vp = lobj->handle; 1056161094Skib if (vp) 1057161094Skib vref(vp); 1058121246Scognet } 1059161094Skib else 1060161094Skib vp = NULL; 1061169156Salc if (lobj != obj) 1062169156Salc VM_OBJECT_UNLOCK(lobj); 1063121246Scognet flags = obj->flags; 1064121246Scognet ref_count = obj->ref_count; 1065121246Scognet shadow_count = obj->shadow_count; 1066169156Salc VM_OBJECT_UNLOCK(obj); 1067161094Skib if (vp) { 1068161094Skib vn_fullpath(td, vp, &name, &freename); 1069161094Skib locked = VFS_LOCK_GIANT(vp->v_mount); 1070175202Sattilio vn_lock(vp, LK_SHARED | LK_RETRY); 1071182371Sattilio VOP_GETATTR(vp, &vat, td->td_ucred); 1072161094Skib ino = vat.va_fileid; 1073161094Skib vput(vp); 1074161094Skib VFS_UNLOCK_GIANT(locked); 1075161094Skib } 1076121246Scognet } else { 1077121246Scognet flags = 0; 1078121246Scognet ref_count = 0; 1079121246Scognet shadow_count = 0; 1080121246Scognet } 1081168762Sdes 1082121246Scognet /* 1083168762Sdes * format: 1084121246Scognet * start, end, access, offset, major, minor, inode, name. 1085121246Scognet */ 1086183600Skib error = sbuf_printf(sb, 1087121246Scognet "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n", 1088185765Skib (u_long)e_start, (u_long)e_end, 1089185765Skib (e_prot & VM_PROT_READ)?"r":"-", 1090185765Skib (e_prot & VM_PROT_WRITE)?"w":"-", 1091185765Skib (e_prot & VM_PROT_EXECUTE)?"x":"-", 1092121246Scognet "p", 1093121265Scognet (u_long)off, 1094121246Scognet 0, 1095121246Scognet 0, 1096121265Scognet (u_long)ino, 1097121246Scognet *name ? " " : "", 1098121246Scognet name 1099121246Scognet ); 1100121246Scognet if (freename) 1101121246Scognet free(freename, M_TEMP); 1102185864Skib vm_map_lock_read(map); 1103183600Skib if (error == -1) { 1104183600Skib error = 0; 1105121246Scognet break; 1106169156Salc } 1107186563Skib if (last_timestamp != map->timestamp) { 1108185765Skib /* 1109185765Skib * Look again for the entry because the map was 1110185765Skib * modified while it was unlocked. Specifically, 1111185765Skib * the entry may have been clipped, merged, or deleted. 1112185765Skib */ 1113185765Skib vm_map_lookup_entry(map, e_end - 1, &tmp_entry); 1114185765Skib entry = tmp_entry; 1115185765Skib } 1116121246Scognet } 1117169156Salc vm_map_unlock_read(map); 1118185984Skib vmspace_free(vm); 1119168762Sdes 1120121246Scognet return (error); 1121168762Sdes} 1122168762Sdes 1123116173Sobrien/* 112478113Sdes * Filler function for proc/net/dev 112578113Sdes */ 112678025Sdesstatic int 112778025Sdeslinprocfs_donetdev(PFS_FILL_ARGS) 112874135Sjlemon{ 112985129Sdes char ifname[16]; /* XXX LINUX_IFNAMSIZ */ 113074135Sjlemon struct ifnet *ifp; 113174135Sjlemon 1132218114Sbz sbuf_printf(sb, "%6s|%58s|%s\n" 1133218114Sbz "%6s|%58s|%58s\n", 1134218114Sbz "Inter-", " Receive", " Transmit", 1135218114Sbz " face", 1136218114Sbz "bytes packets errs drop fifo frame compressed multicast", 1137218114Sbz "bytes packets errs drop fifo colls carrier compressed"); 113874135Sjlemon 1139196635Szec CURVNET_SET(TD_TO_VNET(curthread)); 1140108172Shsu IFNET_RLOCK(); 1141181803Sbz TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 114285129Sdes linux_ifname(ifp, ifname, sizeof ifname); 1143218114Sbz sbuf_printf(sb, "%6.6s: ", ifname); 1144218114Sbz sbuf_printf(sb, "%7lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ", 1145218114Sbz ifp->if_ibytes, /* rx_bytes */ 1146218114Sbz ifp->if_ipackets, /* rx_packets */ 1147218114Sbz ifp->if_ierrors, /* rx_errors */ 1148218114Sbz ifp->if_iqdrops, /* rx_dropped + 1149218114Sbz * rx_missed_errors */ 1150218114Sbz 0UL, /* rx_fifo_errors */ 1151218114Sbz 0UL, /* rx_length_errors + 1152218114Sbz * rx_over_errors + 1153218114Sbz * rx_crc_errors + 1154218114Sbz * rx_frame_errors */ 1155218114Sbz 0UL, /* rx_compressed */ 1156218114Sbz ifp->if_imcasts); /* multicast, XXX-BZ rx only? */ 115783926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", 1158218114Sbz ifp->if_obytes, /* tx_bytes */ 1159218114Sbz ifp->if_opackets, /* tx_packets */ 1160218114Sbz ifp->if_oerrors, /* tx_errors */ 1161218114Sbz 0UL, /* tx_dropped */ 1162218114Sbz 0UL, /* tx_fifo_errors */ 1163218114Sbz ifp->if_collisions, /* collisions */ 1164218114Sbz 0UL, /* tx_carrier_errors + 1165218114Sbz * tx_aborted_errors + 1166218114Sbz * tx_window_errors + 1167218114Sbz * tx_heartbeat_errors */ 1168218114Sbz 0UL); /* tx_compressed */ 116974135Sjlemon } 1170108172Shsu IFNET_RUNLOCK(); 1171196635Szec CURVNET_RESTORE(); 1172119068Sdes 117378025Sdes return (0); 117474135Sjlemon} 117574135Sjlemon 1176158311Sambrisko/* 1177167159Sjkim * Filler function for proc/sys/kernel/osrelease 1178167159Sjkim */ 1179167159Sjkimstatic int 1180167159Sjkimlinprocfs_doosrelease(PFS_FILL_ARGS) 1181167159Sjkim{ 1182167159Sjkim char osrelease[LINUX_MAX_UTSNAME]; 1183167159Sjkim 1184167159Sjkim linux_get_osrelease(td, osrelease); 1185167159Sjkim sbuf_printf(sb, "%s\n", osrelease); 1186167159Sjkim 1187167159Sjkim return (0); 1188167159Sjkim} 1189167159Sjkim 1190167159Sjkim/* 1191167159Sjkim * Filler function for proc/sys/kernel/ostype 1192167159Sjkim */ 1193167159Sjkimstatic int 1194167159Sjkimlinprocfs_doostype(PFS_FILL_ARGS) 1195167159Sjkim{ 1196167159Sjkim char osname[LINUX_MAX_UTSNAME]; 1197167159Sjkim 1198167159Sjkim linux_get_osname(td, osname); 1199167159Sjkim sbuf_printf(sb, "%s\n", osname); 1200167159Sjkim 1201167159Sjkim return (0); 1202167159Sjkim} 1203167159Sjkim 1204167159Sjkim/* 1205167159Sjkim * Filler function for proc/sys/kernel/version 1206167159Sjkim */ 1207167159Sjkimstatic int 1208167159Sjkimlinprocfs_doosbuild(PFS_FILL_ARGS) 1209167159Sjkim{ 1210168762Sdes 1211167159Sjkim linprocfs_osbuild(td, sb); 1212167159Sjkim sbuf_cat(sb, "\n"); 1213167159Sjkim return (0); 1214167159Sjkim} 1215167159Sjkim 1216167159Sjkim/* 1217164692Sjkim * Filler function for proc/sys/kernel/msgmni 1218164692Sjkim */ 1219164692Sjkimstatic int 1220164692Sjkimlinprocfs_domsgmni(PFS_FILL_ARGS) 1221164692Sjkim{ 1222164692Sjkim 1223168067Sjkim sbuf_printf(sb, "%d\n", msginfo.msgmni); 1224164692Sjkim return (0); 1225164692Sjkim} 1226164692Sjkim 1227164692Sjkim/* 1228163251Skeramida * Filler function for proc/sys/kernel/pid_max 1229163129Snetchild */ 1230163129Snetchildstatic int 1231163129Snetchildlinprocfs_dopid_max(PFS_FILL_ARGS) 1232163129Snetchild{ 1233163757Snetchild 1234163129Snetchild sbuf_printf(sb, "%i\n", PID_MAX); 1235163129Snetchild return (0); 1236163129Snetchild} 1237163129Snetchild 1238163129Snetchild/* 1239164692Sjkim * Filler function for proc/sys/kernel/sem 1240164692Sjkim */ 1241164692Sjkimstatic int 1242164692Sjkimlinprocfs_dosem(PFS_FILL_ARGS) 1243164692Sjkim{ 1244164692Sjkim 1245168067Sjkim sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns, 1246168067Sjkim seminfo.semopm, seminfo.semmni); 1247164692Sjkim return (0); 1248164692Sjkim} 1249164692Sjkim 1250164692Sjkim/* 1251158311Sambrisko * Filler function for proc/scsi/device_info 1252158311Sambrisko */ 1253158311Sambriskostatic int 1254158311Sambriskolinprocfs_doscsidevinfo(PFS_FILL_ARGS) 1255158311Sambrisko{ 1256168762Sdes 1257158311Sambrisko return (0); 1258158311Sambrisko} 1259158311Sambrisko 1260158311Sambrisko/* 1261158311Sambrisko * Filler function for proc/scsi/scsi 1262158311Sambrisko */ 1263158311Sambriskostatic int 1264158311Sambriskolinprocfs_doscsiscsi(PFS_FILL_ARGS) 1265158311Sambrisko{ 1266168762Sdes 1267158311Sambrisko return (0); 1268158311Sambrisko} 1269158311Sambrisko 127085538Sphkextern struct cdevsw *cdevsw[]; 127185538Sphk 127278113Sdes/* 127378113Sdes * Filler function for proc/devices 127478113Sdes */ 127578025Sdesstatic int 127678025Sdeslinprocfs_dodevices(PFS_FILL_ARGS) 127774135Sjlemon{ 1278158311Sambrisko char *char_devices; 127978025Sdes sbuf_printf(sb, "Character devices:\n"); 128074135Sjlemon 1281158311Sambrisko char_devices = linux_get_char_devices(); 1282158311Sambrisko sbuf_printf(sb, "%s", char_devices); 1283158311Sambrisko linux_free_get_char_devices(char_devices); 128474135Sjlemon 128578025Sdes sbuf_printf(sb, "\nBlock devices:\n"); 1286119068Sdes 128778025Sdes return (0); 128874135Sjlemon} 128974135Sjlemon 129078113Sdes/* 129178113Sdes * Filler function for proc/cmdline 129278113Sdes */ 129378025Sdesstatic int 129478025Sdeslinprocfs_docmdline(PFS_FILL_ARGS) 129574135Sjlemon{ 1296168762Sdes 129778025Sdes sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname); 129878025Sdes sbuf_printf(sb, " ro root=302\n"); 129978025Sdes return (0); 130078025Sdes} 130174135Sjlemon 1302205541Sjhb/* 1303205541Sjhb * Filler function for proc/filesystems 1304205541Sjhb */ 1305205541Sjhbstatic int 1306205541Sjhblinprocfs_dofilesystems(PFS_FILL_ARGS) 1307205541Sjhb{ 1308205541Sjhb struct vfsconf *vfsp; 1309205541Sjhb 1310205592Sjhb mtx_lock(&Giant); 1311205541Sjhb TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) { 1312205541Sjhb if (vfsp->vfc_flags & VFCF_SYNTHETIC) 1313205541Sjhb sbuf_printf(sb, "nodev"); 1314205541Sjhb sbuf_printf(sb, "\t%s\n", vfsp->vfc_name); 1315205541Sjhb } 1316205592Sjhb mtx_unlock(&Giant); 1317205541Sjhb return(0); 1318205541Sjhb} 1319205541Sjhb 132083926Sdes#if 0 132178025Sdes/* 132283926Sdes * Filler function for proc/modules 132383926Sdes */ 132483926Sdesstatic int 132583926Sdeslinprocfs_domodules(PFS_FILL_ARGS) 132683926Sdes{ 132783926Sdes struct linker_file *lf; 1328119068Sdes 132983926Sdes TAILQ_FOREACH(lf, &linker_files, link) { 133083926Sdes sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename, 133183926Sdes (unsigned long)lf->size, lf->refs); 133283926Sdes } 133383926Sdes return (0); 133483926Sdes} 133583926Sdes#endif 133683926Sdes 133783926Sdes/* 1338204825Sed * Filler function for proc/pid/fd 1339204825Sed */ 1340204825Sedstatic int 1341204825Sedlinprocfs_dofdescfs(PFS_FILL_ARGS) 1342204825Sed{ 1343204825Sed 1344204825Sed if (p == curproc) 1345204825Sed sbuf_printf(sb, "/dev/fd"); 1346204825Sed else 1347204825Sed sbuf_printf(sb, "unknown"); 1348204825Sed return (0); 1349204825Sed} 1350204825Sed 1351263103Seadler 1352204825Sed/* 1353263103Seadler * Filler function for proc/sys/kernel/random/uuid 1354263103Seadler */ 1355263103Seadlerstatic int 1356263103Seadlerlinprocfs_douuid(PFS_FILL_ARGS) 1357263103Seadler{ 1358263103Seadler struct uuid uuid; 1359263103Seadler 1360263103Seadler kern_uuidgen(&uuid, 1); 1361263103Seadler sbuf_printf_uuid(sb, &uuid); 1362263103Seadler sbuf_printf(sb, "\n"); 1363263103Seadler return(0); 1364263103Seadler} 1365263103Seadler 1366263103Seadler 1367263103Seadler/* 136885129Sdes * Constructor 136978025Sdes */ 137085129Sdesstatic int 137185129Sdeslinprocfs_init(PFS_INIT_ARGS) 137285129Sdes{ 137385129Sdes struct pfs_node *root; 137485129Sdes struct pfs_node *dir; 137574135Sjlemon 137685129Sdes root = pi->pi_root; 137778025Sdes 1378119923Sdes /* /proc/... */ 1379119911Sdes pfs_create_file(root, "cmdline", &linprocfs_docmdline, 1380167482Sdes NULL, NULL, NULL, PFS_RD); 1381119911Sdes pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo, 1382167482Sdes NULL, NULL, NULL, PFS_RD); 1383119911Sdes pfs_create_file(root, "devices", &linprocfs_dodevices, 1384167482Sdes NULL, NULL, NULL, PFS_RD); 1385205541Sjhb pfs_create_file(root, "filesystems", &linprocfs_dofilesystems, 1386205541Sjhb NULL, NULL, NULL, PFS_RD); 1387119911Sdes pfs_create_file(root, "loadavg", &linprocfs_doloadavg, 1388167482Sdes NULL, NULL, NULL, PFS_RD); 1389119911Sdes pfs_create_file(root, "meminfo", &linprocfs_domeminfo, 1390167482Sdes NULL, NULL, NULL, PFS_RD); 139183926Sdes#if 0 1392119911Sdes pfs_create_file(root, "modules", &linprocfs_domodules, 1393167482Sdes NULL, NULL, NULL, PFS_RD); 139483926Sdes#endif 1395158311Sambrisko pfs_create_file(root, "mounts", &linprocfs_domtab, 1396167482Sdes NULL, NULL, NULL, PFS_RD); 1397119911Sdes pfs_create_file(root, "mtab", &linprocfs_domtab, 1398167482Sdes NULL, NULL, NULL, PFS_RD); 1399190445Sambrisko pfs_create_file(root, "partitions", &linprocfs_dopartitions, 1400190445Sambrisko NULL, NULL, NULL, PFS_RD); 140187543Sdes pfs_create_link(root, "self", &procfs_docurproc, 1402167482Sdes NULL, NULL, NULL, 0); 1403119911Sdes pfs_create_file(root, "stat", &linprocfs_dostat, 1404167482Sdes NULL, NULL, NULL, PFS_RD); 1405224582Skib pfs_create_file(root, "swaps", &linprocfs_doswaps, 1406224582Skib NULL, NULL, NULL, PFS_RD); 1407119911Sdes pfs_create_file(root, "uptime", &linprocfs_douptime, 1408167482Sdes NULL, NULL, NULL, PFS_RD); 1409119911Sdes pfs_create_file(root, "version", &linprocfs_doversion, 1410167482Sdes NULL, NULL, NULL, PFS_RD); 141178025Sdes 1412119923Sdes /* /proc/net/... */ 1413167482Sdes dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0); 141485129Sdes pfs_create_file(dir, "dev", &linprocfs_donetdev, 1415167482Sdes NULL, NULL, NULL, PFS_RD); 141678025Sdes 1417119923Sdes /* /proc/<pid>/... */ 1418167482Sdes dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP); 141985129Sdes pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline, 1420167482Sdes NULL, NULL, NULL, PFS_RD); 1421119911Sdes pfs_create_link(dir, "cwd", &linprocfs_doproccwd, 1422167482Sdes NULL, NULL, NULL, 0); 1423116173Sobrien pfs_create_file(dir, "environ", &linprocfs_doprocenviron, 1424167482Sdes NULL, NULL, NULL, PFS_RD); 142587543Sdes pfs_create_link(dir, "exe", &procfs_doprocfile, 1426167482Sdes NULL, &procfs_notsystem, NULL, 0); 1427116173Sobrien pfs_create_file(dir, "maps", &linprocfs_doprocmaps, 1428167482Sdes NULL, NULL, NULL, PFS_RD); 142985129Sdes pfs_create_file(dir, "mem", &procfs_doprocmem, 1430167482Sdes &procfs_attr, &procfs_candebug, NULL, PFS_RDWR|PFS_RAW); 1431119911Sdes pfs_create_link(dir, "root", &linprocfs_doprocroot, 1432167482Sdes NULL, NULL, NULL, 0); 143385129Sdes pfs_create_file(dir, "stat", &linprocfs_doprocstat, 1434167482Sdes NULL, NULL, NULL, PFS_RD); 1435119911Sdes pfs_create_file(dir, "statm", &linprocfs_doprocstatm, 1436167482Sdes NULL, NULL, NULL, PFS_RD); 143785129Sdes pfs_create_file(dir, "status", &linprocfs_doprocstatus, 1438167482Sdes NULL, NULL, NULL, PFS_RD); 1439204825Sed pfs_create_link(dir, "fd", &linprocfs_dofdescfs, 1440204825Sed NULL, NULL, NULL, 0); 144185129Sdes 1442158311Sambrisko /* /proc/scsi/... */ 1443167482Sdes dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0); 1444158311Sambrisko pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo, 1445167482Sdes NULL, NULL, NULL, PFS_RD); 1446158311Sambrisko pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi, 1447167482Sdes NULL, NULL, NULL, PFS_RD); 1448163129Snetchild 1449163129Snetchild /* /proc/sys/... */ 1450167482Sdes dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0); 1451163129Snetchild /* /proc/sys/kernel/... */ 1452167482Sdes dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0); 1453167159Sjkim pfs_create_file(dir, "osrelease", &linprocfs_doosrelease, 1454167482Sdes NULL, NULL, NULL, PFS_RD); 1455167159Sjkim pfs_create_file(dir, "ostype", &linprocfs_doostype, 1456167482Sdes NULL, NULL, NULL, PFS_RD); 1457167159Sjkim pfs_create_file(dir, "version", &linprocfs_doosbuild, 1458167482Sdes NULL, NULL, NULL, PFS_RD); 1459164692Sjkim pfs_create_file(dir, "msgmni", &linprocfs_domsgmni, 1460167482Sdes NULL, NULL, NULL, PFS_RD); 1461163129Snetchild pfs_create_file(dir, "pid_max", &linprocfs_dopid_max, 1462167482Sdes NULL, NULL, NULL, PFS_RD); 1463164692Sjkim pfs_create_file(dir, "sem", &linprocfs_dosem, 1464167482Sdes NULL, NULL, NULL, PFS_RD); 1465163129Snetchild 1466263103Seadler /* /proc/sys/kernel/random/... */ 1467263103Seadler dir = pfs_create_dir(dir, "random", NULL, NULL, NULL, 0); 1468263103Seadler pfs_create_file(dir, "uuid", &linprocfs_douuid, 1469263103Seadler NULL, NULL, NULL, PFS_RD); 1470263103Seadler 147185129Sdes return (0); 147285129Sdes} 147385129Sdes 147485129Sdes/* 147585129Sdes * Destructor 147685129Sdes */ 147785129Sdesstatic int 147885129Sdeslinprocfs_uninit(PFS_INIT_ARGS) 147985129Sdes{ 148085129Sdes 148185129Sdes /* nothing to do, pseudofs will GC */ 148285129Sdes return (0); 148385129Sdes} 148485129Sdes 1485232728SmmPSEUDOFS(linprocfs, 1, 0); 148678025SdesMODULE_DEPEND(linprocfs, linux, 1, 1, 1); 148778025SdesMODULE_DEPEND(linprocfs, procfs, 1, 1, 1); 1488168440SjkimMODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1); 1489168440SjkimMODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1); 1490