linprocfs.c revision 232728
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: stable/9/sys/compat/linprocfs/linprocfs.c 232728 2012-03-09 16:17:46Z mm $"); 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 104140214Sobrien#ifdef COMPAT_LINUX32 /* XXX */ 105140214Sobrien#include <machine/../linux32/linux.h> 106140214Sobrien#else 10787275Srwatson#include <machine/../linux/linux.h> 108133822Stjr#endif 10985129Sdes#include <compat/linux/linux_ioctl.h> 11069995Sdes#include <compat/linux/linux_mib.h> 11185289Sdes#include <compat/linux/linux_util.h> 11278025Sdes#include <fs/pseudofs/pseudofs.h> 11384248Sdes#include <fs/procfs/procfs.h> 11459412Smsmith 11567588Sdes/* 11667588Sdes * Various conversion macros 11767588Sdes */ 118206081Snetchild#define T2J(x) ((long)(((x) * 100ULL) / (stathz ? stathz : hz))) /* ticks to jiffies */ 119206081Snetchild#define T2CS(x) ((unsigned long)(((x) * 100ULL) / (stathz ? stathz : hz))) /* ticks to centiseconds */ 12067588Sdes#define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */ 12167588Sdes#define B2K(x) ((x) >> 10) /* bytes to kbytes */ 12269799Sdes#define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */ 12367588Sdes#define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */ 12467588Sdes#define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */ 125206081Snetchild#define TV2J(x) ((x)->tv_sec * 100UL + (x)->tv_usec / 10000) 12674135Sjlemon 127159995Snetchild/** 128159995Snetchild * @brief Mapping of ki_stat in struct kinfo_proc to the linux state 129159995Snetchild * 130159995Snetchild * The linux procfs state field displays one of the characters RSDZTW to 131159995Snetchild * denote running, sleeping in an interruptible wait, waiting in an 132172568Skevlo * uninterruptible disk sleep, a zombie process, process is being traced 133159995Snetchild * or stopped, or process is paging respectively. 134159995Snetchild * 135159995Snetchild * Our struct kinfo_proc contains the variable ki_stat which contains a 136159995Snetchild * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK. 137159995Snetchild * 138159995Snetchild * This character array is used with ki_stati-1 as an index and tries to 139159995Snetchild * map our states to suitable linux states. 140159995Snetchild */ 141166140Snetchildstatic char linux_state[] = "RRSTZDD"; 142159995Snetchild 14378113Sdes/* 14478113Sdes * Filler function for proc/meminfo 14578113Sdes */ 14678025Sdesstatic int 14778025Sdeslinprocfs_domeminfo(PFS_FILL_ARGS) 14859412Smsmith{ 14959412Smsmith unsigned long memtotal; /* total memory in bytes */ 15059412Smsmith unsigned long memused; /* used memory in bytes */ 15159412Smsmith unsigned long memfree; /* free memory in bytes */ 15259412Smsmith unsigned long memshared; /* shared memory ??? */ 15359412Smsmith unsigned long buffers, cached; /* buffer / cache memory ??? */ 154113574Sjhb unsigned long long swaptotal; /* total swap space in bytes */ 155113574Sjhb unsigned long long swapused; /* used swap space in bytes */ 156113574Sjhb unsigned long long swapfree; /* free swap space in bytes */ 15760860Sdes vm_object_t object; 158117723Sphk int i, j; 15959412Smsmith 16059412Smsmith memtotal = physmem * PAGE_SIZE; 16159412Smsmith /* 16259412Smsmith * The correct thing here would be: 16359412Smsmith * 164170170Sattilio memfree = cnt.v_free_count * PAGE_SIZE; 16559412Smsmith memused = memtotal - memfree; 16659412Smsmith * 16759412Smsmith * but it might mislead linux binaries into thinking there 16859412Smsmith * is very little memory left, so we cheat and tell them that 16959412Smsmith * all memory that isn't wired down is free. 17059412Smsmith */ 171170170Sattilio memused = cnt.v_wire_count * PAGE_SIZE; 17259412Smsmith memfree = memtotal - memused; 173117723Sphk swap_pager_status(&i, &j); 174153310Smlaier swaptotal = (unsigned long long)i * PAGE_SIZE; 175153310Smlaier swapused = (unsigned long long)j * PAGE_SIZE; 176117723Sphk swapfree = swaptotal - swapused; 17760860Sdes memshared = 0; 178124082Salc mtx_lock(&vm_object_list_mtx); 17971471Sjhb TAILQ_FOREACH(object, &vm_object_list, object_list) 18060860Sdes if (object->shadow_count > 1) 18160860Sdes memshared += object->resident_page_count; 182124082Salc mtx_unlock(&vm_object_list_mtx); 18360860Sdes memshared *= PAGE_SIZE; 18459412Smsmith /* 18559412Smsmith * We'd love to be able to write: 18659412Smsmith * 18759412Smsmith buffers = bufspace; 18859412Smsmith * 18959412Smsmith * but bufspace is internal to vfs_bio.c and we don't feel 19059412Smsmith * like unstaticizing it just for linprocfs's sake. 19159412Smsmith */ 19259412Smsmith buffers = 0; 193170170Sattilio cached = cnt.v_cache_count * PAGE_SIZE; 19459412Smsmith 19578025Sdes sbuf_printf(sb, 19678031Sdes " total: used: free: shared: buffers: cached:\n" 19769799Sdes "Mem: %lu %lu %lu %lu %lu %lu\n" 19876839Sjlemon "Swap: %llu %llu %llu\n" 19969799Sdes "MemTotal: %9lu kB\n" 20069799Sdes "MemFree: %9lu kB\n" 20169799Sdes "MemShared:%9lu kB\n" 20269799Sdes "Buffers: %9lu kB\n" 20369799Sdes "Cached: %9lu kB\n" 20476839Sjlemon "SwapTotal:%9llu kB\n" 20576839Sjlemon "SwapFree: %9llu kB\n", 20669799Sdes memtotal, memused, memfree, memshared, buffers, cached, 20769799Sdes swaptotal, swapused, swapfree, 20869799Sdes B2K(memtotal), B2K(memfree), 20969799Sdes B2K(memshared), B2K(buffers), B2K(cached), 21069799Sdes B2K(swaptotal), B2K(swapfree)); 21159412Smsmith 21278025Sdes return (0); 21359412Smsmith} 21459412Smsmith 215133822Stjr#if defined(__i386__) || defined(__amd64__) 21678113Sdes/* 217133822Stjr * Filler function for proc/cpuinfo (i386 & amd64 version) 21878113Sdes */ 21978113Sdesstatic int 22078113Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS) 22178113Sdes{ 222159544Sdes int hw_model[2]; 223159544Sdes char model[128]; 224220433Sjkim uint64_t freq; 225159544Sdes size_t size; 226123246Sdes int class, fqmhz, fqkhz; 227118421Sdes int i; 22859412Smsmith 22969799Sdes /* 23078031Sdes * We default the flags to include all non-conflicting flags, 23178031Sdes * and the Intel versions of conflicting flags. 23269799Sdes */ 23378031Sdes static char *flags[] = { 23478031Sdes "fpu", "vme", "de", "pse", "tsc", 23578031Sdes "msr", "pae", "mce", "cx8", "apic", 23678031Sdes "sep", "sep", "mtrr", "pge", "mca", 23778031Sdes "cmov", "pat", "pse36", "pn", "b19", 23878031Sdes "b20", "b21", "mmxext", "mmx", "fxsr", 239183385Scognet "xmm", "sse2", "b27", "b28", "b29", 24067589Sdes "3dnowext", "3dnow" 24167589Sdes }; 24267589Sdes 24359412Smsmith switch (cpu_class) { 244133822Stjr#ifdef __i386__ 24559412Smsmith case CPUCLASS_286: 24667589Sdes class = 2; 24759412Smsmith break; 24859412Smsmith case CPUCLASS_386: 24967589Sdes class = 3; 25059412Smsmith break; 25159412Smsmith case CPUCLASS_486: 25267589Sdes class = 4; 25359412Smsmith break; 25459412Smsmith case CPUCLASS_586: 25567589Sdes class = 5; 25659412Smsmith break; 25759412Smsmith case CPUCLASS_686: 25867589Sdes class = 6; 25959412Smsmith break; 26059412Smsmith default: 26178031Sdes class = 0; 26259412Smsmith break; 263159170Sdes#else /* __amd64__ */ 264133822Stjr default: 265159170Sdes class = 15; 266133822Stjr break; 267133822Stjr#endif 26859412Smsmith } 26959412Smsmith 270159544Sdes hw_model[0] = CTL_HW; 271159544Sdes hw_model[1] = HW_MODEL; 272159544Sdes model[0] = '\0'; 273159544Sdes size = sizeof(model); 274159544Sdes if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0) 275159544Sdes strcpy(model, "unknown"); 276123246Sdes for (i = 0; i < mp_ncpus; ++i) { 277118421Sdes sbuf_printf(sb, 278118421Sdes "processor\t: %d\n" 279118421Sdes "vendor_id\t: %.20s\n" 280214982Sdes "cpu family\t: %u\n" 281214982Sdes "model\t\t: %u\n" 282159544Sdes "model name\t: %s\n" 283214982Sdes "stepping\t: %u\n\n", 284214985Sdes i, cpu_vendor, CPUID_TO_FAMILY(cpu_id), 285214985Sdes CPUID_TO_MODEL(cpu_id), model, cpu_id & CPUID_STEPPING); 286159544Sdes /* XXX per-cpu vendor / class / model / id? */ 287118421Sdes } 28859412Smsmith 289185766Skib sbuf_cat(sb, "flags\t\t:"); 29067589Sdes 291187594Sjkim#ifdef __i386__ 292187594Sjkim switch (cpu_vendor_id) { 293187594Sjkim case CPU_VENDOR_AMD: 294187594Sjkim if (class < 6) 295187594Sjkim flags[16] = "fcmov"; 296187594Sjkim break; 297187594Sjkim case CPU_VENDOR_CYRIX: 29867589Sdes flags[24] = "cxmmx"; 299187594Sjkim break; 30078031Sdes } 301187594Sjkim#endif 302119068Sdes 30378031Sdes for (i = 0; i < 32; i++) 30467589Sdes if (cpu_feature & (1 << i)) 30578025Sdes sbuf_printf(sb, " %s", flags[i]); 30678025Sdes sbuf_cat(sb, "\n"); 307220433Sjkim freq = atomic_load_acq_64(&tsc_freq); 308220433Sjkim if (freq != 0) { 309220433Sjkim fqmhz = (freq + 4999) / 1000000; 310220433Sjkim fqkhz = ((freq + 4999) / 10000) % 100; 31178025Sdes sbuf_printf(sb, 31269799Sdes "cpu MHz\t\t: %d.%02d\n" 31369799Sdes "bogomips\t: %d.%02d\n", 31469799Sdes fqmhz, fqkhz, fqmhz, fqkhz); 31578031Sdes } 31669995Sdes 31778025Sdes return (0); 31859412Smsmith} 319133822Stjr#endif /* __i386__ || __amd64__ */ 32065633Sdes 32178113Sdes/* 32285289Sdes * Filler function for proc/mtab 32385289Sdes * 32485289Sdes * This file doesn't exist in Linux' procfs, but is included here so 32585289Sdes * users can symlink /compat/linux/etc/mtab to /proc/mtab 32685289Sdes */ 32785289Sdesstatic int 32885289Sdeslinprocfs_domtab(PFS_FILL_ARGS) 32985289Sdes{ 33085289Sdes struct nameidata nd; 33185289Sdes struct mount *mp; 33291334Sjulian const char *lep; 33391334Sjulian char *dlep, *flep, *mntto, *mntfrom, *fstype; 33485289Sdes size_t lep_len; 33585289Sdes int error; 33685289Sdes 33785289Sdes /* resolve symlinks etc. in the emulation tree prefix */ 338168942Sdes NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td); 33985289Sdes flep = NULL; 340168942Sdes error = namei(&nd); 341184649Sjhb lep = linux_emul_path; 342184649Sjhb if (error == 0) { 343188579Sjhb if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0) 344184649Sjhb lep = dlep; 345184649Sjhb vrele(nd.ni_vp); 346184649Sjhb VFS_UNLOCK_GIANT(NDHASGIANT(&nd)); 347184649Sjhb } 34885289Sdes lep_len = strlen(lep); 349119068Sdes 35085289Sdes mtx_lock(&mountlist_mtx); 35185289Sdes error = 0; 35285289Sdes TAILQ_FOREACH(mp, &mountlist, mnt_list) { 35385289Sdes /* determine device name */ 35485289Sdes mntfrom = mp->mnt_stat.f_mntfromname; 355119068Sdes 35685289Sdes /* determine mount point */ 35785289Sdes mntto = mp->mnt_stat.f_mntonname; 35885289Sdes if (strncmp(mntto, lep, lep_len) == 0 && 35985289Sdes mntto[lep_len] == '/') 36085289Sdes mntto += lep_len; 36185289Sdes 36285289Sdes /* determine fs type */ 36385289Sdes fstype = mp->mnt_stat.f_fstypename; 36485289Sdes if (strcmp(fstype, pn->pn_info->pi_name) == 0) 36585289Sdes mntfrom = fstype = "proc"; 36685289Sdes else if (strcmp(fstype, "procfs") == 0) 36785289Sdes continue; 368119068Sdes 369158311Sambrisko if (strcmp(fstype, "linsysfs") == 0) { 370158311Sambrisko sbuf_printf(sb, "/sys %s sysfs %s", mntto, 371158311Sambrisko mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); 372158311Sambrisko } else { 373190445Sambrisko /* For Linux msdosfs is called vfat */ 374190445Sambrisko if (strcmp(fstype, "msdosfs") == 0) 375190445Sambrisko fstype = "vfat"; 376158311Sambrisko sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype, 377158311Sambrisko mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); 378158311Sambrisko } 37985289Sdes#define ADD_OPTION(opt, name) \ 38085289Sdes if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name); 38185289Sdes ADD_OPTION(MNT_SYNCHRONOUS, "sync"); 38285289Sdes ADD_OPTION(MNT_NOEXEC, "noexec"); 38385289Sdes ADD_OPTION(MNT_NOSUID, "nosuid"); 38485289Sdes ADD_OPTION(MNT_UNION, "union"); 38585289Sdes ADD_OPTION(MNT_ASYNC, "async"); 38685289Sdes ADD_OPTION(MNT_SUIDDIR, "suiddir"); 38785289Sdes ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow"); 38885289Sdes ADD_OPTION(MNT_NOATIME, "noatime"); 38985289Sdes#undef ADD_OPTION 39085289Sdes /* a real Linux mtab will also show NFS options */ 39185289Sdes sbuf_printf(sb, " 0 0\n"); 39285289Sdes } 39385289Sdes mtx_unlock(&mountlist_mtx); 39485289Sdes if (flep != NULL) 39585289Sdes free(flep, M_TEMP); 39685289Sdes return (error); 39785289Sdes} 39885289Sdes 39985289Sdes/* 400190445Sambrisko * Filler function for proc/partitions 401190445Sambrisko * 402190445Sambrisko */ 403190445Sambriskostatic int 404190445Sambriskolinprocfs_dopartitions(PFS_FILL_ARGS) 405190445Sambrisko{ 406190445Sambrisko struct g_class *cp; 407190445Sambrisko struct g_geom *gp; 408190445Sambrisko struct g_provider *pp; 409190445Sambrisko struct nameidata nd; 410190445Sambrisko const char *lep; 411190445Sambrisko char *dlep, *flep; 412190445Sambrisko size_t lep_len; 413190445Sambrisko int error; 414190445Sambrisko int major, minor; 415190445Sambrisko 416190445Sambrisko /* resolve symlinks etc. in the emulation tree prefix */ 417190445Sambrisko NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td); 418190445Sambrisko flep = NULL; 419190445Sambrisko error = namei(&nd); 420190445Sambrisko lep = linux_emul_path; 421190445Sambrisko if (error == 0) { 422190445Sambrisko if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0) 423190445Sambrisko lep = dlep; 424190445Sambrisko vrele(nd.ni_vp); 425190445Sambrisko VFS_UNLOCK_GIANT(NDHASGIANT(&nd)); 426190445Sambrisko } 427190445Sambrisko lep_len = strlen(lep); 428190445Sambrisko 429190445Sambrisko g_topology_lock(); 430190445Sambrisko error = 0; 431190445Sambrisko sbuf_printf(sb, "major minor #blocks name rio rmerge rsect " 432190445Sambrisko "ruse wio wmerge wsect wuse running use aveq\n"); 433190445Sambrisko 434190445Sambrisko LIST_FOREACH(cp, &g_classes, class) { 435190445Sambrisko if (strcmp(cp->name, "DISK") == 0 || 436190445Sambrisko strcmp(cp->name, "PART") == 0) 437190445Sambrisko LIST_FOREACH(gp, &cp->geom, geom) { 438190445Sambrisko LIST_FOREACH(pp, &gp->provider, provider) { 439190445Sambrisko if (linux_driver_get_major_minor( 440190445Sambrisko pp->name, &major, &minor) != 0) { 441190445Sambrisko major = 0; 442190445Sambrisko minor = 0; 443190445Sambrisko } 444190445Sambrisko sbuf_printf(sb, "%d %d %lld %s " 445190445Sambrisko "%d %d %d %d %d " 446190445Sambrisko "%d %d %d %d %d %d\n", 447190445Sambrisko major, minor, 448190445Sambrisko (long long)pp->mediasize, pp->name, 449190445Sambrisko 0, 0, 0, 0, 0, 450190445Sambrisko 0, 0, 0, 0, 0, 0); 451190445Sambrisko } 452190445Sambrisko } 453190445Sambrisko } 454190445Sambrisko g_topology_unlock(); 455190445Sambrisko 456190445Sambrisko if (flep != NULL) 457190445Sambrisko free(flep, M_TEMP); 458190445Sambrisko return (error); 459190445Sambrisko} 460190445Sambrisko 461190445Sambrisko 462190445Sambrisko/* 46378113Sdes * Filler function for proc/stat 46478113Sdes */ 46578025Sdesstatic int 46678025Sdeslinprocfs_dostat(PFS_FILL_ARGS) 46765633Sdes{ 468174070Speter struct pcpu *pcpu; 469174070Speter long cp_time[CPUSTATES]; 470174070Speter long *cp; 471123246Sdes int i; 472120339Sdes 473174070Speter read_cpu_time(cp_time); 474120339Sdes sbuf_printf(sb, "cpu %ld %ld %ld %ld\n", 475120339Sdes T2J(cp_time[CP_USER]), 476120339Sdes T2J(cp_time[CP_NICE]), 477120339Sdes T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/), 478120339Sdes T2J(cp_time[CP_IDLE])); 479209059Sjhb CPU_FOREACH(i) { 480174070Speter pcpu = pcpu_find(i); 481174070Speter cp = pcpu->pc_cp_time; 482143194Ssobomax sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i, 483174070Speter T2J(cp[CP_USER]), 484174070Speter T2J(cp[CP_NICE]), 485174070Speter T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/), 486174070Speter T2J(cp[CP_IDLE])); 487174070Speter } 48878025Sdes sbuf_printf(sb, 48969799Sdes "disk 0 0 0 0\n" 49069799Sdes "page %u %u\n" 49169799Sdes "swap %u %u\n" 49269799Sdes "intr %u\n" 49369799Sdes "ctxt %u\n" 49485657Sdillon "btime %lld\n", 495170170Sattilio cnt.v_vnodepgsin, 496170170Sattilio cnt.v_vnodepgsout, 497170170Sattilio cnt.v_swappgsin, 498170170Sattilio cnt.v_swappgsout, 499170170Sattilio cnt.v_intr, 500170170Sattilio cnt.v_swtch, 501113574Sjhb (long long)boottime.tv_sec); 50278025Sdes return (0); 50365633Sdes} 50465633Sdes 505224582Skibstatic int 506224582Skiblinprocfs_doswaps(PFS_FILL_ARGS) 507224582Skib{ 508224582Skib struct xswdev xsw; 509224582Skib uintmax_t total, used; 510224582Skib int n; 511224582Skib char devname[SPECNAMELEN + 1]; 512224582Skib 513224582Skib sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n"); 514224582Skib mtx_lock(&Giant); 515224582Skib for (n = 0; ; n++) { 516224582Skib if (swap_dev_info(n, &xsw, devname, sizeof(devname)) != 0) 517224582Skib break; 518224582Skib total = (uintmax_t)xsw.xsw_nblks * PAGE_SIZE / 1024; 519224582Skib used = (uintmax_t)xsw.xsw_used * PAGE_SIZE / 1024; 520224582Skib 521224582Skib /* 522224582Skib * The space and not tab after the device name is on 523224582Skib * purpose. Linux does so. 524224582Skib */ 525224582Skib sbuf_printf(sb, "/dev/%-34s unknown\t\t%jd\t%jd\t-1\n", 526224582Skib devname, total, used); 527224582Skib } 528224582Skib mtx_unlock(&Giant); 529224582Skib return (0); 530224582Skib} 531224582Skib 53278113Sdes/* 53378113Sdes * Filler function for proc/uptime 53478113Sdes */ 53578025Sdesstatic int 53678025Sdeslinprocfs_douptime(PFS_FILL_ARGS) 53765633Sdes{ 538174070Speter long cp_time[CPUSTATES]; 53965633Sdes struct timeval tv; 54065633Sdes 54165633Sdes getmicrouptime(&tv); 542174070Speter read_cpu_time(cp_time); 543206081Snetchild sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n", 544113574Sjhb (long long)tv.tv_sec, tv.tv_usec / 10000, 545206081Snetchild T2S(cp_time[CP_IDLE] / mp_ncpus), 546206081Snetchild T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100); 54778025Sdes return (0); 54865633Sdes} 54965633Sdes 55078113Sdes/* 551167159Sjkim * Get OS build date 552167159Sjkim */ 553167159Sjkimstatic void 554167159Sjkimlinprocfs_osbuild(struct thread *td, struct sbuf *sb) 555167159Sjkim{ 556167159Sjkim#if 0 557167159Sjkim char osbuild[256]; 558167159Sjkim char *cp1, *cp2; 559167159Sjkim 560167159Sjkim strncpy(osbuild, version, 256); 561167159Sjkim osbuild[255] = '\0'; 562167159Sjkim cp1 = strstr(osbuild, "\n"); 563167159Sjkim cp2 = strstr(osbuild, ":"); 564167159Sjkim if (cp1 && cp2) { 565167159Sjkim *cp1 = *cp2 = '\0'; 566167159Sjkim cp1 = strstr(osbuild, "#"); 567167159Sjkim } else 568167159Sjkim cp1 = NULL; 569167159Sjkim if (cp1) 570167159Sjkim sbuf_printf(sb, "%s%s", cp1, cp2 + 1); 571167159Sjkim else 572167159Sjkim#endif 573167159Sjkim sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977"); 574167159Sjkim} 575167159Sjkim 576167159Sjkim/* 577167159Sjkim * Get OS builder 578167159Sjkim */ 579167159Sjkimstatic void 580167159Sjkimlinprocfs_osbuilder(struct thread *td, struct sbuf *sb) 581167159Sjkim{ 582168762Sdes#if 0 583167159Sjkim char builder[256]; 584167159Sjkim char *cp; 585167159Sjkim 586167159Sjkim cp = strstr(version, "\n "); 587167159Sjkim if (cp) { 588167159Sjkim strncpy(builder, cp + 5, 256); 589167159Sjkim builder[255] = '\0'; 590167159Sjkim cp = strstr(builder, ":"); 591167159Sjkim if (cp) 592167159Sjkim *cp = '\0'; 593167159Sjkim } 594167159Sjkim if (cp) 595167159Sjkim sbuf_cat(sb, builder); 596167159Sjkim else 597168762Sdes#endif 598167159Sjkim sbuf_cat(sb, "des@freebsd.org"); 599167159Sjkim} 600167159Sjkim 601167159Sjkim/* 60278113Sdes * Filler function for proc/version 60378113Sdes */ 60478025Sdesstatic int 60578025Sdeslinprocfs_doversion(PFS_FILL_ARGS) 60665633Sdes{ 60787275Srwatson char osname[LINUX_MAX_UTSNAME]; 60887275Srwatson char osrelease[LINUX_MAX_UTSNAME]; 60987275Srwatson 610112206Sjhb linux_get_osname(td, osname); 611112206Sjhb linux_get_osrelease(td, osrelease); 612167159Sjkim sbuf_printf(sb, "%s version %s (", osname, osrelease); 613167159Sjkim linprocfs_osbuilder(td, sb); 614167159Sjkim sbuf_cat(sb, ") (gcc version " __VERSION__ ") "); 615167159Sjkim linprocfs_osbuild(td, sb); 616167159Sjkim sbuf_cat(sb, "\n"); 61787275Srwatson 61878025Sdes return (0); 61965633Sdes} 62065633Sdes 62178113Sdes/* 62278113Sdes * Filler function for proc/loadavg 62378113Sdes */ 62478025Sdesstatic int 62578025Sdeslinprocfs_doloadavg(PFS_FILL_ARGS) 62676839Sjlemon{ 627168762Sdes 62878025Sdes sbuf_printf(sb, 62976839Sjlemon "%d.%02d %d.%02d %d.%02d %d/%d %d\n", 63076839Sjlemon (int)(averunnable.ldavg[0] / averunnable.fscale), 63176839Sjlemon (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100), 63276839Sjlemon (int)(averunnable.ldavg[1] / averunnable.fscale), 63376839Sjlemon (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100), 63476839Sjlemon (int)(averunnable.ldavg[2] / averunnable.fscale), 63576839Sjlemon (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100), 63676839Sjlemon 1, /* number of running tasks */ 63776839Sjlemon nprocs, /* number of tasks */ 63878116Sdes lastpid /* the last pid */ 63976839Sjlemon ); 64078025Sdes return (0); 64176839Sjlemon} 64276839Sjlemon 64378113Sdes/* 64478113Sdes * Filler function for proc/pid/stat 64578113Sdes */ 64678025Sdesstatic int 64778025Sdeslinprocfs_doprocstat(PFS_FILL_ARGS) 64867588Sdes{ 64969995Sdes struct kinfo_proc kp; 650166140Snetchild char state; 651166140Snetchild static int ratelimit = 0; 652206081Snetchild vm_offset_t startcode, startdata; 65367588Sdes 65494307Sjhb PROC_LOCK(p); 65569995Sdes fill_kinfo_proc(p, &kp); 656206081Snetchild if (p->p_vmspace) { 657206081Snetchild startcode = (vm_offset_t)p->p_vmspace->vm_taddr; 658206081Snetchild startdata = (vm_offset_t)p->p_vmspace->vm_daddr; 659206081Snetchild } else { 660206081Snetchild startcode = 0; 661206081Snetchild startdata = 0; 662206081Snetchild }; 66378025Sdes sbuf_printf(sb, "%d", p->p_pid); 66478025Sdes#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg) 66567588Sdes PS_ADD("comm", "(%s)", p->p_comm); 666166140Snetchild if (kp.ki_stat > sizeof(linux_state)) { 667166140Snetchild state = 'R'; 668166140Snetchild 669166141Snetchild if (ratelimit == 0) { 670166162Snetchild printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n", 671166162Snetchild kp.ki_stat, sizeof(linux_state)); 672166141Snetchild ++ratelimit; 673166141Snetchild } 674166140Snetchild } else 675166140Snetchild state = linux_state[kp.ki_stat - 1]; 676166140Snetchild PS_ADD("state", "%c", state); 67773923Sjhb PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0); 67867588Sdes PS_ADD("pgrp", "%d", p->p_pgid); 67967588Sdes PS_ADD("session", "%d", p->p_session->s_sid); 68091140Stanimura PROC_UNLOCK(p); 681206081Snetchild PS_ADD("tty", "%d", kp.ki_tdev); 682159995Snetchild PS_ADD("tpgid", "%d", kp.ki_tpgid); 68367588Sdes PS_ADD("flags", "%u", 0); /* XXX */ 684159995Snetchild PS_ADD("minflt", "%lu", kp.ki_rusage.ru_minflt); 685159995Snetchild PS_ADD("cminflt", "%lu", kp.ki_rusage_ch.ru_minflt); 686159995Snetchild PS_ADD("majflt", "%lu", kp.ki_rusage.ru_majflt); 687159995Snetchild PS_ADD("cmajflt", "%lu", kp.ki_rusage_ch.ru_majflt); 688206081Snetchild PS_ADD("utime", "%ld", TV2J(&kp.ki_rusage.ru_utime)); 689206081Snetchild PS_ADD("stime", "%ld", TV2J(&kp.ki_rusage.ru_stime)); 690206081Snetchild PS_ADD("cutime", "%ld", TV2J(&kp.ki_rusage_ch.ru_utime)); 691206081Snetchild PS_ADD("cstime", "%ld", TV2J(&kp.ki_rusage_ch.ru_stime)); 692159995Snetchild PS_ADD("priority", "%d", kp.ki_pri.pri_user); 693159995Snetchild PS_ADD("nice", "%d", kp.ki_nice); /* 19 (nicest) to -19 */ 694159995Snetchild PS_ADD("0", "%d", 0); /* removed field */ 695159995Snetchild PS_ADD("itrealvalue", "%d", 0); /* XXX */ 696206081Snetchild PS_ADD("starttime", "%lu", TV2J(&kp.ki_start) - TV2J(&boottime)); 697159995Snetchild PS_ADD("vsize", "%ju", P2K((uintmax_t)kp.ki_size)); 698159995Snetchild PS_ADD("rss", "%ju", (uintmax_t)kp.ki_rssize); 699159995Snetchild PS_ADD("rlim", "%lu", kp.ki_rusage.ru_maxrss); 700206081Snetchild PS_ADD("startcode", "%ju", (uintmax_t)startcode); 701206081Snetchild PS_ADD("endcode", "%ju", (uintmax_t)startdata); 70267588Sdes PS_ADD("startstack", "%u", 0); /* XXX */ 703159995Snetchild PS_ADD("kstkesp", "%u", 0); /* XXX */ 704159995Snetchild PS_ADD("kstkeip", "%u", 0); /* XXX */ 705159995Snetchild PS_ADD("signal", "%u", 0); /* XXX */ 706159995Snetchild PS_ADD("blocked", "%u", 0); /* XXX */ 707159995Snetchild PS_ADD("sigignore", "%u", 0); /* XXX */ 708159995Snetchild PS_ADD("sigcatch", "%u", 0); /* XXX */ 70967588Sdes PS_ADD("wchan", "%u", 0); /* XXX */ 710159995Snetchild PS_ADD("nswap", "%lu", kp.ki_rusage.ru_nswap); 711159995Snetchild PS_ADD("cnswap", "%lu", kp.ki_rusage_ch.ru_nswap); 71269799Sdes PS_ADD("exitsignal", "%d", 0); /* XXX */ 713159995Snetchild PS_ADD("processor", "%u", kp.ki_lastcpu); 714159995Snetchild PS_ADD("rt_priority", "%u", 0); /* XXX */ /* >= 2.5.19 */ 715159995Snetchild PS_ADD("policy", "%u", kp.ki_pri.pri_class); /* >= 2.5.19 */ 71667588Sdes#undef PS_ADD 71778025Sdes sbuf_putc(sb, '\n'); 718119068Sdes 71978025Sdes return (0); 72067588Sdes} 72167588Sdes 72267588Sdes/* 723119911Sdes * Filler function for proc/pid/statm 724119911Sdes */ 725119911Sdesstatic int 726119911Sdeslinprocfs_doprocstatm(PFS_FILL_ARGS) 727119911Sdes{ 728119911Sdes struct kinfo_proc kp; 729119911Sdes segsz_t lsize; 730120340Sdes 731119911Sdes PROC_LOCK(p); 732119911Sdes fill_kinfo_proc(p, &kp); 733119911Sdes PROC_UNLOCK(p); 734119911Sdes 735119911Sdes /* 736119911Sdes * See comments in linprocfs_doprocstatus() regarding the 737119911Sdes * computation of lsize. 738119911Sdes */ 739119911Sdes /* size resident share trs drs lrs dt */ 740119911Sdes sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size)); 741119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize); 742119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */ 743119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize); 744119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize)); 745119911Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 746119911Sdes kp.ki_ssize - kp.ki_tsize - 1; 747119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)lsize); 748119911Sdes sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */ 749119911Sdes 750119911Sdes return (0); 751119911Sdes} 752119911Sdes 753119911Sdes/* 75478113Sdes * Filler function for proc/pid/status 75578113Sdes */ 75678025Sdesstatic int 75778025Sdeslinprocfs_doprocstatus(PFS_FILL_ARGS) 75867588Sdes{ 75969995Sdes struct kinfo_proc kp; 76067588Sdes char *state; 76169799Sdes segsz_t lsize; 76299072Sjulian struct thread *td2; 763114983Sjhb struct sigacts *ps; 76474135Sjlemon int i; 76567588Sdes 766113611Sjhb PROC_LOCK(p); 76799072Sjulian td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */ 76899072Sjulian 76999072Sjulian if (P_SHOULDSTOP(p)) { 77099072Sjulian state = "T (stopped)"; 77199072Sjulian } else { 77299072Sjulian switch(p->p_state) { 77399072Sjulian case PRS_NEW: 77499072Sjulian state = "I (idle)"; 77599072Sjulian break; 77699072Sjulian case PRS_NORMAL: 77799072Sjulian if (p->p_flag & P_WEXIT) { 77899072Sjulian state = "X (exiting)"; 77999072Sjulian break; 78099072Sjulian } 78199072Sjulian switch(td2->td_state) { 782103216Sjulian case TDS_INHIBITED: 78399072Sjulian state = "S (sleeping)"; 78499072Sjulian break; 78599072Sjulian case TDS_RUNQ: 78699072Sjulian case TDS_RUNNING: 78799072Sjulian state = "R (running)"; 78899072Sjulian break; 78999072Sjulian default: 79099072Sjulian state = "? (unknown)"; 79199072Sjulian break; 79299072Sjulian } 79399072Sjulian break; 79499072Sjulian case PRS_ZOMBIE: 79599072Sjulian state = "Z (zombie)"; 79699072Sjulian break; 79799072Sjulian default: 79899072Sjulian state = "? (unknown)"; 79999072Sjulian break; 80099072Sjulian } 80199072Sjulian } 80267588Sdes 80369995Sdes fill_kinfo_proc(p, &kp); 80478025Sdes sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */ 80578031Sdes sbuf_printf(sb, "State:\t%s\n", state); 80667588Sdes 80767588Sdes /* 80867588Sdes * Credentials 80967588Sdes */ 81078025Sdes sbuf_printf(sb, "Pid:\t%d\n", p->p_pid); 81178025Sdes sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ? 81273923Sjhb p->p_pptr->p_pid : 0); 81378031Sdes sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid, 81478031Sdes p->p_ucred->cr_uid, 81578031Sdes p->p_ucred->cr_svuid, 81678031Sdes /* FreeBSD doesn't have fsuid */ 81778031Sdes p->p_ucred->cr_uid); 81878031Sdes sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid, 81978031Sdes p->p_ucred->cr_gid, 82078031Sdes p->p_ucred->cr_svgid, 82178031Sdes /* FreeBSD doesn't have fsgid */ 82278031Sdes p->p_ucred->cr_gid); 82378025Sdes sbuf_cat(sb, "Groups:\t"); 82467588Sdes for (i = 0; i < p->p_ucred->cr_ngroups; i++) 82578031Sdes sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]); 82671471Sjhb PROC_UNLOCK(p); 82778025Sdes sbuf_putc(sb, '\n'); 828119068Sdes 82967588Sdes /* 83067588Sdes * Memory 83169799Sdes * 83269799Sdes * While our approximation of VmLib may not be accurate (I 83369799Sdes * don't know of a simple way to verify it, and I'm not sure 83469799Sdes * it has much meaning anyway), I believe it's good enough. 83569799Sdes * 83669799Sdes * The same code that could (I think) accurately compute VmLib 83769799Sdes * could also compute VmLck, but I don't really care enough to 83869799Sdes * implement it. Submissions are welcome. 83967588Sdes */ 840113574Sjhb sbuf_printf(sb, "VmSize:\t%8ju kB\n", B2K((uintmax_t)kp.ki_size)); 84178025Sdes sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */ 842206081Snetchild sbuf_printf(sb, "VmRSS:\t%8ju kB\n", P2K((uintmax_t)kp.ki_rssize)); 843113574Sjhb sbuf_printf(sb, "VmData:\t%8ju kB\n", P2K((uintmax_t)kp.ki_dsize)); 844113574Sjhb sbuf_printf(sb, "VmStk:\t%8ju kB\n", P2K((uintmax_t)kp.ki_ssize)); 845113574Sjhb sbuf_printf(sb, "VmExe:\t%8ju kB\n", P2K((uintmax_t)kp.ki_tsize)); 84669995Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 84769995Sdes kp.ki_ssize - kp.ki_tsize - 1; 848113574Sjhb sbuf_printf(sb, "VmLib:\t%8ju kB\n", P2K((uintmax_t)lsize)); 84967588Sdes 85067588Sdes /* 85167588Sdes * Signal masks 85267588Sdes * 85367588Sdes * We support up to 128 signals, while Linux supports 32, 85467588Sdes * but we only define 32 (the same 32 as Linux, to boot), so 85567588Sdes * just show the lower 32 bits of each mask. XXX hack. 85667588Sdes * 85767588Sdes * NB: on certain platforms (Sparc at least) Linux actually 85867588Sdes * supports 64 signals, but this code is a long way from 85967588Sdes * running on anything but i386, so ignore that for now. 86067588Sdes */ 86171471Sjhb PROC_LOCK(p); 862104306Sjmallett sbuf_printf(sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]); 86369799Sdes /* 86469799Sdes * I can't seem to find out where the signal mask is in 86569799Sdes * relation to struct proc, so SigBlk is left unimplemented. 86669799Sdes */ 86778025Sdes sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */ 868114983Sjhb ps = p->p_sigacts; 869114983Sjhb mtx_lock(&ps->ps_mtx); 870114983Sjhb sbuf_printf(sb, "SigIgn:\t%08x\n", ps->ps_sigignore.__bits[0]); 871114983Sjhb sbuf_printf(sb, "SigCgt:\t%08x\n", ps->ps_sigcatch.__bits[0]); 872114983Sjhb mtx_unlock(&ps->ps_mtx); 87371471Sjhb PROC_UNLOCK(p); 874119068Sdes 87567588Sdes /* 87667588Sdes * Linux also prints the capability masks, but we don't have 87767588Sdes * capabilities yet, and when we do get them they're likely to 87867588Sdes * be meaningless to Linux programs, so we lie. XXX 87967588Sdes */ 88078025Sdes sbuf_printf(sb, "CapInh:\t%016x\n", 0); 88178025Sdes sbuf_printf(sb, "CapPrm:\t%016x\n", 0); 88278025Sdes sbuf_printf(sb, "CapEff:\t%016x\n", 0); 883119068Sdes 88478025Sdes return (0); 88567588Sdes} 88674135Sjlemon 887119911Sdes 88878113Sdes/* 889119911Sdes * Filler function for proc/pid/cwd 890119911Sdes */ 891119911Sdesstatic int 892119911Sdeslinprocfs_doproccwd(PFS_FILL_ARGS) 893119911Sdes{ 894119911Sdes char *fullpath = "unknown"; 895119911Sdes char *freepath = NULL; 896119911Sdes 897119911Sdes vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath); 898119911Sdes sbuf_printf(sb, "%s", fullpath); 899119911Sdes if (freepath) 900119911Sdes free(freepath, M_TEMP); 901119911Sdes return (0); 902119911Sdes} 903119911Sdes 904119911Sdes/* 905119911Sdes * Filler function for proc/pid/root 906119911Sdes */ 907119911Sdesstatic int 908119911Sdeslinprocfs_doprocroot(PFS_FILL_ARGS) 909119911Sdes{ 910119911Sdes struct vnode *rvp; 911119911Sdes char *fullpath = "unknown"; 912119911Sdes char *freepath = NULL; 913119911Sdes 914119911Sdes rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir; 915119911Sdes vn_fullpath(td, rvp, &fullpath, &freepath); 916119911Sdes sbuf_printf(sb, "%s", fullpath); 917119911Sdes if (freepath) 918119911Sdes free(freepath, M_TEMP); 919119911Sdes return (0); 920119911Sdes} 921119911Sdes 92278113Sdes/* 923213246Skib * Filler function for proc/pid/cmdline 924213246Skib */ 925213246Skibstatic int 926213246Skiblinprocfs_doproccmdline(PFS_FILL_ARGS) 927213246Skib{ 928213246Skib int ret; 929213246Skib 930213246Skib PROC_LOCK(p); 931213246Skib if ((ret = p_cansee(td, p)) != 0) { 932213246Skib PROC_UNLOCK(p); 933213246Skib return (ret); 934213246Skib } 935223182Spluknet 936223182Spluknet /* 937223182Spluknet * Mimic linux behavior and pass only processes with usermode 938223182Spluknet * address space as valid. Return zero silently otherwize. 939223182Spluknet */ 940223182Spluknet if (p->p_vmspace == &vmspace0) { 941223182Spluknet PROC_UNLOCK(p); 942223182Spluknet return (0); 943223182Spluknet } 944213246Skib if (p->p_args != NULL) { 945213246Skib sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length); 946213246Skib PROC_UNLOCK(p); 947213246Skib return (0); 948213246Skib } 949230754Strociny 950230754Strociny if ((p->p_flag & P_SYSTEM) != 0) { 951230754Strociny PROC_UNLOCK(p); 952230754Strociny return (0); 953230754Strociny } 954230754Strociny 955213246Skib PROC_UNLOCK(p); 956213246Skib 957230754Strociny ret = proc_getargv(td, p, sb); 958213246Skib return (ret); 959213246Skib} 960213246Skib 961213246Skib/* 962116173Sobrien * Filler function for proc/pid/environ 963116173Sobrien */ 964116173Sobrienstatic int 965116173Sobrienlinprocfs_doprocenviron(PFS_FILL_ARGS) 966116173Sobrien{ 967212723Sdes int ret; 968168762Sdes 969212723Sdes PROC_LOCK(p); 970230755Strociny if ((ret = p_candebug(td, p)) != 0) { 971212723Sdes PROC_UNLOCK(p); 972213246Skib return (ret); 973212723Sdes } 974223182Spluknet 975223182Spluknet /* 976223182Spluknet * Mimic linux behavior and pass only processes with usermode 977223182Spluknet * address space as valid. Return zero silently otherwize. 978223182Spluknet */ 979223182Spluknet if (p->p_vmspace == &vmspace0) { 980223182Spluknet PROC_UNLOCK(p); 981223182Spluknet return (0); 982223182Spluknet } 983230754Strociny 984230754Strociny if ((p->p_flag & P_SYSTEM) != 0) { 985230754Strociny PROC_UNLOCK(p); 986230754Strociny return (0); 987230754Strociny } 988230754Strociny 989213246Skib PROC_UNLOCK(p); 990212723Sdes 991230754Strociny ret = proc_getenvv(td, p, sb); 992212723Sdes return (ret); 993116173Sobrien} 994116173Sobrien 995116173Sobrien/* 996116173Sobrien * Filler function for proc/pid/maps 997116173Sobrien */ 998116173Sobrienstatic int 999116173Sobrienlinprocfs_doprocmaps(PFS_FILL_ARGS) 1000116173Sobrien{ 1001185984Skib struct vmspace *vm; 1002185984Skib vm_map_t map; 1003185765Skib vm_map_entry_t entry, tmp_entry; 1004121265Scognet vm_object_t obj, tobj, lobj; 1005185765Skib vm_offset_t e_start, e_end; 1006121265Scognet vm_ooffset_t off = 0; 1007185765Skib vm_prot_t e_prot; 1008185765Skib unsigned int last_timestamp; 1009121265Scognet char *name = "", *freename = NULL; 1010121265Scognet ino_t ino; 1011121265Scognet int ref_count, shadow_count, flags; 1012121265Scognet int error; 1013137507Sphk struct vnode *vp; 1014137507Sphk struct vattr vat; 1015161094Skib int locked; 1016168762Sdes 1017121246Scognet PROC_LOCK(p); 1018121246Scognet error = p_candebug(td, p); 1019121246Scognet PROC_UNLOCK(p); 1020121246Scognet if (error) 1021121246Scognet return (error); 1022168762Sdes 1023121246Scognet if (uio->uio_rw != UIO_READ) 1024121246Scognet return (EOPNOTSUPP); 1025168762Sdes 1026121246Scognet error = 0; 1027185984Skib vm = vmspace_acquire_ref(p); 1028185984Skib if (vm == NULL) 1029185984Skib return (ESRCH); 1030185984Skib map = &vm->vm_map; 1031169156Salc vm_map_lock_read(map); 1032183600Skib for (entry = map->header.next; entry != &map->header; 1033121246Scognet entry = entry->next) { 1034121265Scognet name = ""; 1035121265Scognet freename = NULL; 1036121246Scognet if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) 1037121246Scognet continue; 1038185765Skib e_prot = entry->protection; 1039185765Skib e_start = entry->start; 1040185765Skib e_end = entry->end; 1041121246Scognet obj = entry->object.vm_object; 1042169156Salc for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) { 1043169156Salc VM_OBJECT_LOCK(tobj); 1044169156Salc if (lobj != obj) 1045169156Salc VM_OBJECT_UNLOCK(lobj); 1046121246Scognet lobj = tobj; 1047169156Salc } 1048185765Skib last_timestamp = map->timestamp; 1049185765Skib vm_map_unlock_read(map); 1050121246Scognet ino = 0; 1051121246Scognet if (lobj) { 1052121246Scognet off = IDX_TO_OFF(lobj->size); 1053161094Skib if (lobj->type == OBJT_VNODE) { 1054161094Skib vp = lobj->handle; 1055161094Skib if (vp) 1056161094Skib vref(vp); 1057121246Scognet } 1058161094Skib else 1059161094Skib vp = NULL; 1060169156Salc if (lobj != obj) 1061169156Salc VM_OBJECT_UNLOCK(lobj); 1062121246Scognet flags = obj->flags; 1063121246Scognet ref_count = obj->ref_count; 1064121246Scognet shadow_count = obj->shadow_count; 1065169156Salc VM_OBJECT_UNLOCK(obj); 1066161094Skib if (vp) { 1067161094Skib vn_fullpath(td, vp, &name, &freename); 1068161094Skib locked = VFS_LOCK_GIANT(vp->v_mount); 1069175202Sattilio vn_lock(vp, LK_SHARED | LK_RETRY); 1070182371Sattilio VOP_GETATTR(vp, &vat, td->td_ucred); 1071161094Skib ino = vat.va_fileid; 1072161094Skib vput(vp); 1073161094Skib VFS_UNLOCK_GIANT(locked); 1074161094Skib } 1075121246Scognet } else { 1076121246Scognet flags = 0; 1077121246Scognet ref_count = 0; 1078121246Scognet shadow_count = 0; 1079121246Scognet } 1080168762Sdes 1081121246Scognet /* 1082168762Sdes * format: 1083121246Scognet * start, end, access, offset, major, minor, inode, name. 1084121246Scognet */ 1085183600Skib error = sbuf_printf(sb, 1086121246Scognet "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n", 1087185765Skib (u_long)e_start, (u_long)e_end, 1088185765Skib (e_prot & VM_PROT_READ)?"r":"-", 1089185765Skib (e_prot & VM_PROT_WRITE)?"w":"-", 1090185765Skib (e_prot & VM_PROT_EXECUTE)?"x":"-", 1091121246Scognet "p", 1092121265Scognet (u_long)off, 1093121246Scognet 0, 1094121246Scognet 0, 1095121265Scognet (u_long)ino, 1096121246Scognet *name ? " " : "", 1097121246Scognet name 1098121246Scognet ); 1099121246Scognet if (freename) 1100121246Scognet free(freename, M_TEMP); 1101185864Skib vm_map_lock_read(map); 1102183600Skib if (error == -1) { 1103183600Skib error = 0; 1104121246Scognet break; 1105169156Salc } 1106186563Skib if (last_timestamp != map->timestamp) { 1107185765Skib /* 1108185765Skib * Look again for the entry because the map was 1109185765Skib * modified while it was unlocked. Specifically, 1110185765Skib * the entry may have been clipped, merged, or deleted. 1111185765Skib */ 1112185765Skib vm_map_lookup_entry(map, e_end - 1, &tmp_entry); 1113185765Skib entry = tmp_entry; 1114185765Skib } 1115121246Scognet } 1116169156Salc vm_map_unlock_read(map); 1117185984Skib vmspace_free(vm); 1118168762Sdes 1119121246Scognet return (error); 1120168762Sdes} 1121168762Sdes 1122116173Sobrien/* 112378113Sdes * Filler function for proc/net/dev 112478113Sdes */ 112578025Sdesstatic int 112678025Sdeslinprocfs_donetdev(PFS_FILL_ARGS) 112774135Sjlemon{ 112885129Sdes char ifname[16]; /* XXX LINUX_IFNAMSIZ */ 112974135Sjlemon struct ifnet *ifp; 113074135Sjlemon 1131218114Sbz sbuf_printf(sb, "%6s|%58s|%s\n" 1132218114Sbz "%6s|%58s|%58s\n", 1133218114Sbz "Inter-", " Receive", " Transmit", 1134218114Sbz " face", 1135218114Sbz "bytes packets errs drop fifo frame compressed multicast", 1136218114Sbz "bytes packets errs drop fifo colls carrier compressed"); 113774135Sjlemon 1138196635Szec CURVNET_SET(TD_TO_VNET(curthread)); 1139108172Shsu IFNET_RLOCK(); 1140181803Sbz TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 114185129Sdes linux_ifname(ifp, ifname, sizeof ifname); 1142218114Sbz sbuf_printf(sb, "%6.6s: ", ifname); 1143218114Sbz sbuf_printf(sb, "%7lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ", 1144218114Sbz ifp->if_ibytes, /* rx_bytes */ 1145218114Sbz ifp->if_ipackets, /* rx_packets */ 1146218114Sbz ifp->if_ierrors, /* rx_errors */ 1147218114Sbz ifp->if_iqdrops, /* rx_dropped + 1148218114Sbz * rx_missed_errors */ 1149218114Sbz 0UL, /* rx_fifo_errors */ 1150218114Sbz 0UL, /* rx_length_errors + 1151218114Sbz * rx_over_errors + 1152218114Sbz * rx_crc_errors + 1153218114Sbz * rx_frame_errors */ 1154218114Sbz 0UL, /* rx_compressed */ 1155218114Sbz ifp->if_imcasts); /* multicast, XXX-BZ rx only? */ 115683926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", 1157218114Sbz ifp->if_obytes, /* tx_bytes */ 1158218114Sbz ifp->if_opackets, /* tx_packets */ 1159218114Sbz ifp->if_oerrors, /* tx_errors */ 1160218114Sbz 0UL, /* tx_dropped */ 1161218114Sbz 0UL, /* tx_fifo_errors */ 1162218114Sbz ifp->if_collisions, /* collisions */ 1163218114Sbz 0UL, /* tx_carrier_errors + 1164218114Sbz * tx_aborted_errors + 1165218114Sbz * tx_window_errors + 1166218114Sbz * tx_heartbeat_errors */ 1167218114Sbz 0UL); /* tx_compressed */ 116874135Sjlemon } 1169108172Shsu IFNET_RUNLOCK(); 1170196635Szec CURVNET_RESTORE(); 1171119068Sdes 117278025Sdes return (0); 117374135Sjlemon} 117474135Sjlemon 1175158311Sambrisko/* 1176167159Sjkim * Filler function for proc/sys/kernel/osrelease 1177167159Sjkim */ 1178167159Sjkimstatic int 1179167159Sjkimlinprocfs_doosrelease(PFS_FILL_ARGS) 1180167159Sjkim{ 1181167159Sjkim char osrelease[LINUX_MAX_UTSNAME]; 1182167159Sjkim 1183167159Sjkim linux_get_osrelease(td, osrelease); 1184167159Sjkim sbuf_printf(sb, "%s\n", osrelease); 1185167159Sjkim 1186167159Sjkim return (0); 1187167159Sjkim} 1188167159Sjkim 1189167159Sjkim/* 1190167159Sjkim * Filler function for proc/sys/kernel/ostype 1191167159Sjkim */ 1192167159Sjkimstatic int 1193167159Sjkimlinprocfs_doostype(PFS_FILL_ARGS) 1194167159Sjkim{ 1195167159Sjkim char osname[LINUX_MAX_UTSNAME]; 1196167159Sjkim 1197167159Sjkim linux_get_osname(td, osname); 1198167159Sjkim sbuf_printf(sb, "%s\n", osname); 1199167159Sjkim 1200167159Sjkim return (0); 1201167159Sjkim} 1202167159Sjkim 1203167159Sjkim/* 1204167159Sjkim * Filler function for proc/sys/kernel/version 1205167159Sjkim */ 1206167159Sjkimstatic int 1207167159Sjkimlinprocfs_doosbuild(PFS_FILL_ARGS) 1208167159Sjkim{ 1209168762Sdes 1210167159Sjkim linprocfs_osbuild(td, sb); 1211167159Sjkim sbuf_cat(sb, "\n"); 1212167159Sjkim return (0); 1213167159Sjkim} 1214167159Sjkim 1215167159Sjkim/* 1216164692Sjkim * Filler function for proc/sys/kernel/msgmni 1217164692Sjkim */ 1218164692Sjkimstatic int 1219164692Sjkimlinprocfs_domsgmni(PFS_FILL_ARGS) 1220164692Sjkim{ 1221164692Sjkim 1222168067Sjkim sbuf_printf(sb, "%d\n", msginfo.msgmni); 1223164692Sjkim return (0); 1224164692Sjkim} 1225164692Sjkim 1226164692Sjkim/* 1227163251Skeramida * Filler function for proc/sys/kernel/pid_max 1228163129Snetchild */ 1229163129Snetchildstatic int 1230163129Snetchildlinprocfs_dopid_max(PFS_FILL_ARGS) 1231163129Snetchild{ 1232163757Snetchild 1233163129Snetchild sbuf_printf(sb, "%i\n", PID_MAX); 1234163129Snetchild return (0); 1235163129Snetchild} 1236163129Snetchild 1237163129Snetchild/* 1238164692Sjkim * Filler function for proc/sys/kernel/sem 1239164692Sjkim */ 1240164692Sjkimstatic int 1241164692Sjkimlinprocfs_dosem(PFS_FILL_ARGS) 1242164692Sjkim{ 1243164692Sjkim 1244168067Sjkim sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns, 1245168067Sjkim seminfo.semopm, seminfo.semmni); 1246164692Sjkim return (0); 1247164692Sjkim} 1248164692Sjkim 1249164692Sjkim/* 1250158311Sambrisko * Filler function for proc/scsi/device_info 1251158311Sambrisko */ 1252158311Sambriskostatic int 1253158311Sambriskolinprocfs_doscsidevinfo(PFS_FILL_ARGS) 1254158311Sambrisko{ 1255168762Sdes 1256158311Sambrisko return (0); 1257158311Sambrisko} 1258158311Sambrisko 1259158311Sambrisko/* 1260158311Sambrisko * Filler function for proc/scsi/scsi 1261158311Sambrisko */ 1262158311Sambriskostatic int 1263158311Sambriskolinprocfs_doscsiscsi(PFS_FILL_ARGS) 1264158311Sambrisko{ 1265168762Sdes 1266158311Sambrisko return (0); 1267158311Sambrisko} 1268158311Sambrisko 126985538Sphkextern struct cdevsw *cdevsw[]; 127085538Sphk 127178113Sdes/* 127278113Sdes * Filler function for proc/devices 127378113Sdes */ 127478025Sdesstatic int 127578025Sdeslinprocfs_dodevices(PFS_FILL_ARGS) 127674135Sjlemon{ 1277158311Sambrisko char *char_devices; 127878025Sdes sbuf_printf(sb, "Character devices:\n"); 127974135Sjlemon 1280158311Sambrisko char_devices = linux_get_char_devices(); 1281158311Sambrisko sbuf_printf(sb, "%s", char_devices); 1282158311Sambrisko linux_free_get_char_devices(char_devices); 128374135Sjlemon 128478025Sdes sbuf_printf(sb, "\nBlock devices:\n"); 1285119068Sdes 128678025Sdes return (0); 128774135Sjlemon} 128874135Sjlemon 128978113Sdes/* 129078113Sdes * Filler function for proc/cmdline 129178113Sdes */ 129278025Sdesstatic int 129378025Sdeslinprocfs_docmdline(PFS_FILL_ARGS) 129474135Sjlemon{ 1295168762Sdes 129678025Sdes sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname); 129778025Sdes sbuf_printf(sb, " ro root=302\n"); 129878025Sdes return (0); 129978025Sdes} 130074135Sjlemon 1301205541Sjhb/* 1302205541Sjhb * Filler function for proc/filesystems 1303205541Sjhb */ 1304205541Sjhbstatic int 1305205541Sjhblinprocfs_dofilesystems(PFS_FILL_ARGS) 1306205541Sjhb{ 1307205541Sjhb struct vfsconf *vfsp; 1308205541Sjhb 1309205592Sjhb mtx_lock(&Giant); 1310205541Sjhb TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) { 1311205541Sjhb if (vfsp->vfc_flags & VFCF_SYNTHETIC) 1312205541Sjhb sbuf_printf(sb, "nodev"); 1313205541Sjhb sbuf_printf(sb, "\t%s\n", vfsp->vfc_name); 1314205541Sjhb } 1315205592Sjhb mtx_unlock(&Giant); 1316205541Sjhb return(0); 1317205541Sjhb} 1318205541Sjhb 131983926Sdes#if 0 132078025Sdes/* 132183926Sdes * Filler function for proc/modules 132283926Sdes */ 132383926Sdesstatic int 132483926Sdeslinprocfs_domodules(PFS_FILL_ARGS) 132583926Sdes{ 132683926Sdes struct linker_file *lf; 1327119068Sdes 132883926Sdes TAILQ_FOREACH(lf, &linker_files, link) { 132983926Sdes sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename, 133083926Sdes (unsigned long)lf->size, lf->refs); 133183926Sdes } 133283926Sdes return (0); 133383926Sdes} 133483926Sdes#endif 133583926Sdes 133683926Sdes/* 1337204825Sed * Filler function for proc/pid/fd 1338204825Sed */ 1339204825Sedstatic int 1340204825Sedlinprocfs_dofdescfs(PFS_FILL_ARGS) 1341204825Sed{ 1342204825Sed 1343204825Sed if (p == curproc) 1344204825Sed sbuf_printf(sb, "/dev/fd"); 1345204825Sed else 1346204825Sed sbuf_printf(sb, "unknown"); 1347204825Sed return (0); 1348204825Sed} 1349204825Sed 1350204825Sed/* 135185129Sdes * Constructor 135278025Sdes */ 135385129Sdesstatic int 135485129Sdeslinprocfs_init(PFS_INIT_ARGS) 135585129Sdes{ 135685129Sdes struct pfs_node *root; 135785129Sdes struct pfs_node *dir; 135874135Sjlemon 135985129Sdes root = pi->pi_root; 136078025Sdes 1361119923Sdes /* /proc/... */ 1362119911Sdes pfs_create_file(root, "cmdline", &linprocfs_docmdline, 1363167482Sdes NULL, NULL, NULL, PFS_RD); 1364119911Sdes pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo, 1365167482Sdes NULL, NULL, NULL, PFS_RD); 1366119911Sdes pfs_create_file(root, "devices", &linprocfs_dodevices, 1367167482Sdes NULL, NULL, NULL, PFS_RD); 1368205541Sjhb pfs_create_file(root, "filesystems", &linprocfs_dofilesystems, 1369205541Sjhb NULL, NULL, NULL, PFS_RD); 1370119911Sdes pfs_create_file(root, "loadavg", &linprocfs_doloadavg, 1371167482Sdes NULL, NULL, NULL, PFS_RD); 1372119911Sdes pfs_create_file(root, "meminfo", &linprocfs_domeminfo, 1373167482Sdes NULL, NULL, NULL, PFS_RD); 137483926Sdes#if 0 1375119911Sdes pfs_create_file(root, "modules", &linprocfs_domodules, 1376167482Sdes NULL, NULL, NULL, PFS_RD); 137783926Sdes#endif 1378158311Sambrisko pfs_create_file(root, "mounts", &linprocfs_domtab, 1379167482Sdes NULL, NULL, NULL, PFS_RD); 1380119911Sdes pfs_create_file(root, "mtab", &linprocfs_domtab, 1381167482Sdes NULL, NULL, NULL, PFS_RD); 1382190445Sambrisko pfs_create_file(root, "partitions", &linprocfs_dopartitions, 1383190445Sambrisko NULL, NULL, NULL, PFS_RD); 138487543Sdes pfs_create_link(root, "self", &procfs_docurproc, 1385167482Sdes NULL, NULL, NULL, 0); 1386119911Sdes pfs_create_file(root, "stat", &linprocfs_dostat, 1387167482Sdes NULL, NULL, NULL, PFS_RD); 1388224582Skib pfs_create_file(root, "swaps", &linprocfs_doswaps, 1389224582Skib NULL, NULL, NULL, PFS_RD); 1390119911Sdes pfs_create_file(root, "uptime", &linprocfs_douptime, 1391167482Sdes NULL, NULL, NULL, PFS_RD); 1392119911Sdes pfs_create_file(root, "version", &linprocfs_doversion, 1393167482Sdes NULL, NULL, NULL, PFS_RD); 139478025Sdes 1395119923Sdes /* /proc/net/... */ 1396167482Sdes dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0); 139785129Sdes pfs_create_file(dir, "dev", &linprocfs_donetdev, 1398167482Sdes NULL, NULL, NULL, PFS_RD); 139978025Sdes 1400119923Sdes /* /proc/<pid>/... */ 1401167482Sdes dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP); 140285129Sdes pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline, 1403167482Sdes NULL, NULL, NULL, PFS_RD); 1404119911Sdes pfs_create_link(dir, "cwd", &linprocfs_doproccwd, 1405167482Sdes NULL, NULL, NULL, 0); 1406116173Sobrien pfs_create_file(dir, "environ", &linprocfs_doprocenviron, 1407167482Sdes NULL, NULL, NULL, PFS_RD); 140887543Sdes pfs_create_link(dir, "exe", &procfs_doprocfile, 1409167482Sdes NULL, &procfs_notsystem, NULL, 0); 1410116173Sobrien pfs_create_file(dir, "maps", &linprocfs_doprocmaps, 1411167482Sdes NULL, NULL, NULL, PFS_RD); 141285129Sdes pfs_create_file(dir, "mem", &procfs_doprocmem, 1413167482Sdes &procfs_attr, &procfs_candebug, NULL, PFS_RDWR|PFS_RAW); 1414119911Sdes pfs_create_link(dir, "root", &linprocfs_doprocroot, 1415167482Sdes NULL, NULL, NULL, 0); 141685129Sdes pfs_create_file(dir, "stat", &linprocfs_doprocstat, 1417167482Sdes NULL, NULL, NULL, PFS_RD); 1418119911Sdes pfs_create_file(dir, "statm", &linprocfs_doprocstatm, 1419167482Sdes NULL, NULL, NULL, PFS_RD); 142085129Sdes pfs_create_file(dir, "status", &linprocfs_doprocstatus, 1421167482Sdes NULL, NULL, NULL, PFS_RD); 1422204825Sed pfs_create_link(dir, "fd", &linprocfs_dofdescfs, 1423204825Sed NULL, NULL, NULL, 0); 142485129Sdes 1425158311Sambrisko /* /proc/scsi/... */ 1426167482Sdes dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0); 1427158311Sambrisko pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo, 1428167482Sdes NULL, NULL, NULL, PFS_RD); 1429158311Sambrisko pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi, 1430167482Sdes NULL, NULL, NULL, PFS_RD); 1431163129Snetchild 1432163129Snetchild /* /proc/sys/... */ 1433167482Sdes dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0); 1434163129Snetchild /* /proc/sys/kernel/... */ 1435167482Sdes dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0); 1436167159Sjkim pfs_create_file(dir, "osrelease", &linprocfs_doosrelease, 1437167482Sdes NULL, NULL, NULL, PFS_RD); 1438167159Sjkim pfs_create_file(dir, "ostype", &linprocfs_doostype, 1439167482Sdes NULL, NULL, NULL, PFS_RD); 1440167159Sjkim pfs_create_file(dir, "version", &linprocfs_doosbuild, 1441167482Sdes NULL, NULL, NULL, PFS_RD); 1442164692Sjkim pfs_create_file(dir, "msgmni", &linprocfs_domsgmni, 1443167482Sdes NULL, NULL, NULL, PFS_RD); 1444163129Snetchild pfs_create_file(dir, "pid_max", &linprocfs_dopid_max, 1445167482Sdes NULL, NULL, NULL, PFS_RD); 1446164692Sjkim pfs_create_file(dir, "sem", &linprocfs_dosem, 1447167482Sdes NULL, NULL, NULL, PFS_RD); 1448163129Snetchild 144985129Sdes return (0); 145085129Sdes} 145185129Sdes 145285129Sdes/* 145385129Sdes * Destructor 145485129Sdes */ 145585129Sdesstatic int 145685129Sdeslinprocfs_uninit(PFS_INIT_ARGS) 145785129Sdes{ 145885129Sdes 145985129Sdes /* nothing to do, pseudofs will GC */ 146085129Sdes return (0); 146185129Sdes} 146285129Sdes 1463232728SmmPSEUDOFS(linprocfs, 1, 0); 146478025SdesMODULE_DEPEND(linprocfs, linux, 1, 1, 1); 146578025SdesMODULE_DEPEND(linprocfs, procfs, 1, 1, 1); 1466168440SjkimMODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1); 1467168440SjkimMODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1); 1468