linprocfs.c revision 209059
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: head/sys/compat/linprocfs/linprocfs.c 209059 2010-06-11 18:46:34Z jhb $"); 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> 6465633Sdes#include <sys/resourcevar.h> 6569995Sdes#include <sys/sbuf.h> 66168067Sjkim#include <sys/sem.h> 67123246Sdes#include <sys/smp.h> 6883926Sdes#include <sys/socket.h> 6976839Sjlemon#include <sys/sysctl.h> 7083926Sdes#include <sys/systm.h> 71159995Snetchild#include <sys/time.h> 7265633Sdes#include <sys/tty.h> 7383926Sdes#include <sys/user.h> 7483926Sdes#include <sys/vmmeter.h> 7559412Smsmith#include <sys/vnode.h> 76190445Sambrisko#include <sys/bus.h> 7759412Smsmith 7883926Sdes#include <net/if.h> 79185571Sbz#include <net/vnet.h> 8083926Sdes 8159412Smsmith#include <vm/vm.h> 82185984Skib#include <vm/vm_extern.h> 8359412Smsmith#include <vm/pmap.h> 8467588Sdes#include <vm/vm_map.h> 8559412Smsmith#include <vm/vm_param.h> 8660860Sdes#include <vm/vm_object.h> 8759412Smsmith#include <vm/swap_pager.h> 8869799Sdes 8967589Sdes#include <machine/clock.h> 9078113Sdes 91190445Sambrisko#include <geom/geom.h> 92190445Sambrisko#include <geom/geom_int.h> 93190445Sambrisko 94133822Stjr#if defined(__i386__) || defined(__amd64__) 9567589Sdes#include <machine/cputypes.h> 9659412Smsmith#include <machine/md_var.h> 97133822Stjr#endif /* __i386__ || __amd64__ */ 9859412Smsmith 99140214Sobrien#ifdef COMPAT_LINUX32 /* XXX */ 100140214Sobrien#include <machine/../linux32/linux.h> 101140214Sobrien#else 10287275Srwatson#include <machine/../linux/linux.h> 103133822Stjr#endif 10485129Sdes#include <compat/linux/linux_ioctl.h> 10569995Sdes#include <compat/linux/linux_mib.h> 10685289Sdes#include <compat/linux/linux_util.h> 10778025Sdes#include <fs/pseudofs/pseudofs.h> 10884248Sdes#include <fs/procfs/procfs.h> 10959412Smsmith 11067588Sdes/* 11167588Sdes * Various conversion macros 11267588Sdes */ 113206081Snetchild#define T2J(x) ((long)(((x) * 100ULL) / (stathz ? stathz : hz))) /* ticks to jiffies */ 114206081Snetchild#define T2CS(x) ((unsigned long)(((x) * 100ULL) / (stathz ? stathz : hz))) /* ticks to centiseconds */ 11567588Sdes#define T2S(x) ((x) / (stathz ? stathz : hz)) /* ticks to seconds */ 11667588Sdes#define B2K(x) ((x) >> 10) /* bytes to kbytes */ 11769799Sdes#define B2P(x) ((x) >> PAGE_SHIFT) /* bytes to pages */ 11867588Sdes#define P2B(x) ((x) << PAGE_SHIFT) /* pages to bytes */ 11967588Sdes#define P2K(x) ((x) << (PAGE_SHIFT - 10)) /* pages to kbytes */ 120206081Snetchild#define TV2J(x) ((x)->tv_sec * 100UL + (x)->tv_usec / 10000) 12174135Sjlemon 122159995Snetchild/** 123159995Snetchild * @brief Mapping of ki_stat in struct kinfo_proc to the linux state 124159995Snetchild * 125159995Snetchild * The linux procfs state field displays one of the characters RSDZTW to 126159995Snetchild * denote running, sleeping in an interruptible wait, waiting in an 127172568Skevlo * uninterruptible disk sleep, a zombie process, process is being traced 128159995Snetchild * or stopped, or process is paging respectively. 129159995Snetchild * 130159995Snetchild * Our struct kinfo_proc contains the variable ki_stat which contains a 131159995Snetchild * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK. 132159995Snetchild * 133159995Snetchild * This character array is used with ki_stati-1 as an index and tries to 134159995Snetchild * map our states to suitable linux states. 135159995Snetchild */ 136166140Snetchildstatic char linux_state[] = "RRSTZDD"; 137159995Snetchild 13878113Sdes/* 13978113Sdes * Filler function for proc/meminfo 14078113Sdes */ 14178025Sdesstatic int 14278025Sdeslinprocfs_domeminfo(PFS_FILL_ARGS) 14359412Smsmith{ 14459412Smsmith unsigned long memtotal; /* total memory in bytes */ 14559412Smsmith unsigned long memused; /* used memory in bytes */ 14659412Smsmith unsigned long memfree; /* free memory in bytes */ 14759412Smsmith unsigned long memshared; /* shared memory ??? */ 14859412Smsmith unsigned long buffers, cached; /* buffer / cache memory ??? */ 149113574Sjhb unsigned long long swaptotal; /* total swap space in bytes */ 150113574Sjhb unsigned long long swapused; /* used swap space in bytes */ 151113574Sjhb unsigned long long swapfree; /* free swap space in bytes */ 15260860Sdes vm_object_t object; 153117723Sphk int i, j; 15459412Smsmith 15559412Smsmith memtotal = physmem * PAGE_SIZE; 15659412Smsmith /* 15759412Smsmith * The correct thing here would be: 15859412Smsmith * 159170170Sattilio memfree = cnt.v_free_count * PAGE_SIZE; 16059412Smsmith memused = memtotal - memfree; 16159412Smsmith * 16259412Smsmith * but it might mislead linux binaries into thinking there 16359412Smsmith * is very little memory left, so we cheat and tell them that 16459412Smsmith * all memory that isn't wired down is free. 16559412Smsmith */ 166170170Sattilio memused = cnt.v_wire_count * PAGE_SIZE; 16759412Smsmith memfree = memtotal - memused; 168117723Sphk swap_pager_status(&i, &j); 169153310Smlaier swaptotal = (unsigned long long)i * PAGE_SIZE; 170153310Smlaier swapused = (unsigned long long)j * PAGE_SIZE; 171117723Sphk swapfree = swaptotal - swapused; 17260860Sdes memshared = 0; 173124082Salc mtx_lock(&vm_object_list_mtx); 17471471Sjhb TAILQ_FOREACH(object, &vm_object_list, object_list) 17560860Sdes if (object->shadow_count > 1) 17660860Sdes memshared += object->resident_page_count; 177124082Salc mtx_unlock(&vm_object_list_mtx); 17860860Sdes memshared *= PAGE_SIZE; 17959412Smsmith /* 18059412Smsmith * We'd love to be able to write: 18159412Smsmith * 18259412Smsmith buffers = bufspace; 18359412Smsmith * 18459412Smsmith * but bufspace is internal to vfs_bio.c and we don't feel 18559412Smsmith * like unstaticizing it just for linprocfs's sake. 18659412Smsmith */ 18759412Smsmith buffers = 0; 188170170Sattilio cached = cnt.v_cache_count * PAGE_SIZE; 18959412Smsmith 19078025Sdes sbuf_printf(sb, 19178031Sdes " total: used: free: shared: buffers: cached:\n" 19269799Sdes "Mem: %lu %lu %lu %lu %lu %lu\n" 19376839Sjlemon "Swap: %llu %llu %llu\n" 19469799Sdes "MemTotal: %9lu kB\n" 19569799Sdes "MemFree: %9lu kB\n" 19669799Sdes "MemShared:%9lu kB\n" 19769799Sdes "Buffers: %9lu kB\n" 19869799Sdes "Cached: %9lu kB\n" 19976839Sjlemon "SwapTotal:%9llu kB\n" 20076839Sjlemon "SwapFree: %9llu kB\n", 20169799Sdes memtotal, memused, memfree, memshared, buffers, cached, 20269799Sdes swaptotal, swapused, swapfree, 20369799Sdes B2K(memtotal), B2K(memfree), 20469799Sdes B2K(memshared), B2K(buffers), B2K(cached), 20569799Sdes B2K(swaptotal), B2K(swapfree)); 20659412Smsmith 20778025Sdes return (0); 20859412Smsmith} 20959412Smsmith 210133822Stjr#if defined(__i386__) || defined(__amd64__) 21178113Sdes/* 212133822Stjr * Filler function for proc/cpuinfo (i386 & amd64 version) 21378113Sdes */ 21478113Sdesstatic int 21578113Sdeslinprocfs_docpuinfo(PFS_FILL_ARGS) 21678113Sdes{ 217159544Sdes int hw_model[2]; 218159544Sdes char model[128]; 219159544Sdes size_t size; 220123246Sdes int class, fqmhz, fqkhz; 221118421Sdes int i; 22259412Smsmith 22369799Sdes /* 22478031Sdes * We default the flags to include all non-conflicting flags, 22578031Sdes * and the Intel versions of conflicting flags. 22669799Sdes */ 22778031Sdes static char *flags[] = { 22878031Sdes "fpu", "vme", "de", "pse", "tsc", 22978031Sdes "msr", "pae", "mce", "cx8", "apic", 23078031Sdes "sep", "sep", "mtrr", "pge", "mca", 23178031Sdes "cmov", "pat", "pse36", "pn", "b19", 23278031Sdes "b20", "b21", "mmxext", "mmx", "fxsr", 233183385Scognet "xmm", "sse2", "b27", "b28", "b29", 23467589Sdes "3dnowext", "3dnow" 23567589Sdes }; 23667589Sdes 23759412Smsmith switch (cpu_class) { 238133822Stjr#ifdef __i386__ 23959412Smsmith case CPUCLASS_286: 24067589Sdes class = 2; 24159412Smsmith break; 24259412Smsmith case CPUCLASS_386: 24367589Sdes class = 3; 24459412Smsmith break; 24559412Smsmith case CPUCLASS_486: 24667589Sdes class = 4; 24759412Smsmith break; 24859412Smsmith case CPUCLASS_586: 24967589Sdes class = 5; 25059412Smsmith break; 25159412Smsmith case CPUCLASS_686: 25267589Sdes class = 6; 25359412Smsmith break; 25459412Smsmith default: 25578031Sdes class = 0; 25659412Smsmith break; 257159170Sdes#else /* __amd64__ */ 258133822Stjr default: 259159170Sdes class = 15; 260133822Stjr break; 261133822Stjr#endif 26259412Smsmith } 26359412Smsmith 264159544Sdes hw_model[0] = CTL_HW; 265159544Sdes hw_model[1] = HW_MODEL; 266159544Sdes model[0] = '\0'; 267159544Sdes size = sizeof(model); 268159544Sdes if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0) 269159544Sdes strcpy(model, "unknown"); 270123246Sdes for (i = 0; i < mp_ncpus; ++i) { 271118421Sdes sbuf_printf(sb, 272118421Sdes "processor\t: %d\n" 273118421Sdes "vendor_id\t: %.20s\n" 274118421Sdes "cpu family\t: %d\n" 275118421Sdes "model\t\t: %d\n" 276159544Sdes "model name\t: %s\n" 277206597Semaste "stepping\t: %d\n\n", 278159544Sdes i, cpu_vendor, class, cpu, model, cpu_id & 0xf); 279159544Sdes /* XXX per-cpu vendor / class / model / id? */ 280118421Sdes } 28159412Smsmith 282185766Skib sbuf_cat(sb, "flags\t\t:"); 28367589Sdes 284187594Sjkim#ifdef __i386__ 285187594Sjkim switch (cpu_vendor_id) { 286187594Sjkim case CPU_VENDOR_AMD: 287187594Sjkim if (class < 6) 288187594Sjkim flags[16] = "fcmov"; 289187594Sjkim break; 290187594Sjkim case CPU_VENDOR_CYRIX: 29167589Sdes flags[24] = "cxmmx"; 292187594Sjkim break; 29378031Sdes } 294187594Sjkim#endif 295119068Sdes 29678031Sdes for (i = 0; i < 32; i++) 29767589Sdes if (cpu_feature & (1 << i)) 29878025Sdes sbuf_printf(sb, " %s", flags[i]); 29978025Sdes sbuf_cat(sb, "\n"); 30078031Sdes if (class >= 5) { 30169799Sdes fqmhz = (tsc_freq + 4999) / 1000000; 30269799Sdes fqkhz = ((tsc_freq + 4999) / 10000) % 100; 30378025Sdes sbuf_printf(sb, 30469799Sdes "cpu MHz\t\t: %d.%02d\n" 30569799Sdes "bogomips\t: %d.%02d\n", 30669799Sdes fqmhz, fqkhz, fqmhz, fqkhz); 30778031Sdes } 30869995Sdes 30978025Sdes return (0); 31059412Smsmith} 311133822Stjr#endif /* __i386__ || __amd64__ */ 31265633Sdes 31378113Sdes/* 31485289Sdes * Filler function for proc/mtab 31585289Sdes * 31685289Sdes * This file doesn't exist in Linux' procfs, but is included here so 31785289Sdes * users can symlink /compat/linux/etc/mtab to /proc/mtab 31885289Sdes */ 31985289Sdesstatic int 32085289Sdeslinprocfs_domtab(PFS_FILL_ARGS) 32185289Sdes{ 32285289Sdes struct nameidata nd; 32385289Sdes struct mount *mp; 32491334Sjulian const char *lep; 32591334Sjulian char *dlep, *flep, *mntto, *mntfrom, *fstype; 32685289Sdes size_t lep_len; 32785289Sdes int error; 32885289Sdes 32985289Sdes /* resolve symlinks etc. in the emulation tree prefix */ 330168942Sdes NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td); 33185289Sdes flep = NULL; 332168942Sdes error = namei(&nd); 333184649Sjhb lep = linux_emul_path; 334184649Sjhb if (error == 0) { 335188579Sjhb if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0) 336184649Sjhb lep = dlep; 337184649Sjhb vrele(nd.ni_vp); 338184649Sjhb VFS_UNLOCK_GIANT(NDHASGIANT(&nd)); 339184649Sjhb } 34085289Sdes lep_len = strlen(lep); 341119068Sdes 34285289Sdes mtx_lock(&mountlist_mtx); 34385289Sdes error = 0; 34485289Sdes TAILQ_FOREACH(mp, &mountlist, mnt_list) { 34585289Sdes /* determine device name */ 34685289Sdes mntfrom = mp->mnt_stat.f_mntfromname; 347119068Sdes 34885289Sdes /* determine mount point */ 34985289Sdes mntto = mp->mnt_stat.f_mntonname; 35085289Sdes if (strncmp(mntto, lep, lep_len) == 0 && 35185289Sdes mntto[lep_len] == '/') 35285289Sdes mntto += lep_len; 35385289Sdes 35485289Sdes /* determine fs type */ 35585289Sdes fstype = mp->mnt_stat.f_fstypename; 35685289Sdes if (strcmp(fstype, pn->pn_info->pi_name) == 0) 35785289Sdes mntfrom = fstype = "proc"; 35885289Sdes else if (strcmp(fstype, "procfs") == 0) 35985289Sdes continue; 360119068Sdes 361158311Sambrisko if (strcmp(fstype, "linsysfs") == 0) { 362158311Sambrisko sbuf_printf(sb, "/sys %s sysfs %s", mntto, 363158311Sambrisko mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); 364158311Sambrisko } else { 365190445Sambrisko /* For Linux msdosfs is called vfat */ 366190445Sambrisko if (strcmp(fstype, "msdosfs") == 0) 367190445Sambrisko fstype = "vfat"; 368158311Sambrisko sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype, 369158311Sambrisko mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw"); 370158311Sambrisko } 37185289Sdes#define ADD_OPTION(opt, name) \ 37285289Sdes if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name); 37385289Sdes ADD_OPTION(MNT_SYNCHRONOUS, "sync"); 37485289Sdes ADD_OPTION(MNT_NOEXEC, "noexec"); 37585289Sdes ADD_OPTION(MNT_NOSUID, "nosuid"); 37685289Sdes ADD_OPTION(MNT_UNION, "union"); 37785289Sdes ADD_OPTION(MNT_ASYNC, "async"); 37885289Sdes ADD_OPTION(MNT_SUIDDIR, "suiddir"); 37985289Sdes ADD_OPTION(MNT_NOSYMFOLLOW, "nosymfollow"); 38085289Sdes ADD_OPTION(MNT_NOATIME, "noatime"); 38185289Sdes#undef ADD_OPTION 38285289Sdes /* a real Linux mtab will also show NFS options */ 38385289Sdes sbuf_printf(sb, " 0 0\n"); 38485289Sdes } 38585289Sdes mtx_unlock(&mountlist_mtx); 38685289Sdes if (flep != NULL) 38785289Sdes free(flep, M_TEMP); 38885289Sdes return (error); 38985289Sdes} 39085289Sdes 39185289Sdes/* 392190445Sambrisko * Filler function for proc/partitions 393190445Sambrisko * 394190445Sambrisko */ 395190445Sambriskostatic int 396190445Sambriskolinprocfs_dopartitions(PFS_FILL_ARGS) 397190445Sambrisko{ 398190445Sambrisko struct g_class *cp; 399190445Sambrisko struct g_geom *gp; 400190445Sambrisko struct g_provider *pp; 401190445Sambrisko struct nameidata nd; 402190445Sambrisko const char *lep; 403190445Sambrisko char *dlep, *flep; 404190445Sambrisko size_t lep_len; 405190445Sambrisko int error; 406190445Sambrisko int major, minor; 407190445Sambrisko 408190445Sambrisko /* resolve symlinks etc. in the emulation tree prefix */ 409190445Sambrisko NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td); 410190445Sambrisko flep = NULL; 411190445Sambrisko error = namei(&nd); 412190445Sambrisko lep = linux_emul_path; 413190445Sambrisko if (error == 0) { 414190445Sambrisko if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0) 415190445Sambrisko lep = dlep; 416190445Sambrisko vrele(nd.ni_vp); 417190445Sambrisko VFS_UNLOCK_GIANT(NDHASGIANT(&nd)); 418190445Sambrisko } 419190445Sambrisko lep_len = strlen(lep); 420190445Sambrisko 421190445Sambrisko g_topology_lock(); 422190445Sambrisko error = 0; 423190445Sambrisko sbuf_printf(sb, "major minor #blocks name rio rmerge rsect " 424190445Sambrisko "ruse wio wmerge wsect wuse running use aveq\n"); 425190445Sambrisko 426190445Sambrisko LIST_FOREACH(cp, &g_classes, class) { 427190445Sambrisko if (strcmp(cp->name, "DISK") == 0 || 428190445Sambrisko strcmp(cp->name, "PART") == 0) 429190445Sambrisko LIST_FOREACH(gp, &cp->geom, geom) { 430190445Sambrisko LIST_FOREACH(pp, &gp->provider, provider) { 431190445Sambrisko if (linux_driver_get_major_minor( 432190445Sambrisko pp->name, &major, &minor) != 0) { 433190445Sambrisko major = 0; 434190445Sambrisko minor = 0; 435190445Sambrisko } 436190445Sambrisko sbuf_printf(sb, "%d %d %lld %s " 437190445Sambrisko "%d %d %d %d %d " 438190445Sambrisko "%d %d %d %d %d %d\n", 439190445Sambrisko major, minor, 440190445Sambrisko (long long)pp->mediasize, pp->name, 441190445Sambrisko 0, 0, 0, 0, 0, 442190445Sambrisko 0, 0, 0, 0, 0, 0); 443190445Sambrisko } 444190445Sambrisko } 445190445Sambrisko } 446190445Sambrisko g_topology_unlock(); 447190445Sambrisko 448190445Sambrisko if (flep != NULL) 449190445Sambrisko free(flep, M_TEMP); 450190445Sambrisko return (error); 451190445Sambrisko} 452190445Sambrisko 453190445Sambrisko 454190445Sambrisko/* 45578113Sdes * Filler function for proc/stat 45678113Sdes */ 45778025Sdesstatic int 45878025Sdeslinprocfs_dostat(PFS_FILL_ARGS) 45965633Sdes{ 460174070Speter struct pcpu *pcpu; 461174070Speter long cp_time[CPUSTATES]; 462174070Speter long *cp; 463123246Sdes int i; 464120339Sdes 465174070Speter read_cpu_time(cp_time); 466120339Sdes sbuf_printf(sb, "cpu %ld %ld %ld %ld\n", 467120339Sdes T2J(cp_time[CP_USER]), 468120339Sdes T2J(cp_time[CP_NICE]), 469120339Sdes T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/), 470120339Sdes T2J(cp_time[CP_IDLE])); 471209059Sjhb CPU_FOREACH(i) { 472174070Speter pcpu = pcpu_find(i); 473174070Speter cp = pcpu->pc_cp_time; 474143194Ssobomax sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i, 475174070Speter T2J(cp[CP_USER]), 476174070Speter T2J(cp[CP_NICE]), 477174070Speter T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/), 478174070Speter T2J(cp[CP_IDLE])); 479174070Speter } 48078025Sdes sbuf_printf(sb, 48169799Sdes "disk 0 0 0 0\n" 48269799Sdes "page %u %u\n" 48369799Sdes "swap %u %u\n" 48469799Sdes "intr %u\n" 48569799Sdes "ctxt %u\n" 48685657Sdillon "btime %lld\n", 487170170Sattilio cnt.v_vnodepgsin, 488170170Sattilio cnt.v_vnodepgsout, 489170170Sattilio cnt.v_swappgsin, 490170170Sattilio cnt.v_swappgsout, 491170170Sattilio cnt.v_intr, 492170170Sattilio cnt.v_swtch, 493113574Sjhb (long long)boottime.tv_sec); 49478025Sdes return (0); 49565633Sdes} 49665633Sdes 49778113Sdes/* 49878113Sdes * Filler function for proc/uptime 49978113Sdes */ 50078025Sdesstatic int 50178025Sdeslinprocfs_douptime(PFS_FILL_ARGS) 50265633Sdes{ 503174070Speter long cp_time[CPUSTATES]; 50465633Sdes struct timeval tv; 50565633Sdes 50665633Sdes getmicrouptime(&tv); 507174070Speter read_cpu_time(cp_time); 508206081Snetchild sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n", 509113574Sjhb (long long)tv.tv_sec, tv.tv_usec / 10000, 510206081Snetchild T2S(cp_time[CP_IDLE] / mp_ncpus), 511206081Snetchild T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100); 51278025Sdes return (0); 51365633Sdes} 51465633Sdes 51578113Sdes/* 516167159Sjkim * Get OS build date 517167159Sjkim */ 518167159Sjkimstatic void 519167159Sjkimlinprocfs_osbuild(struct thread *td, struct sbuf *sb) 520167159Sjkim{ 521167159Sjkim#if 0 522167159Sjkim char osbuild[256]; 523167159Sjkim char *cp1, *cp2; 524167159Sjkim 525167159Sjkim strncpy(osbuild, version, 256); 526167159Sjkim osbuild[255] = '\0'; 527167159Sjkim cp1 = strstr(osbuild, "\n"); 528167159Sjkim cp2 = strstr(osbuild, ":"); 529167159Sjkim if (cp1 && cp2) { 530167159Sjkim *cp1 = *cp2 = '\0'; 531167159Sjkim cp1 = strstr(osbuild, "#"); 532167159Sjkim } else 533167159Sjkim cp1 = NULL; 534167159Sjkim if (cp1) 535167159Sjkim sbuf_printf(sb, "%s%s", cp1, cp2 + 1); 536167159Sjkim else 537167159Sjkim#endif 538167159Sjkim sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977"); 539167159Sjkim} 540167159Sjkim 541167159Sjkim/* 542167159Sjkim * Get OS builder 543167159Sjkim */ 544167159Sjkimstatic void 545167159Sjkimlinprocfs_osbuilder(struct thread *td, struct sbuf *sb) 546167159Sjkim{ 547168762Sdes#if 0 548167159Sjkim char builder[256]; 549167159Sjkim char *cp; 550167159Sjkim 551167159Sjkim cp = strstr(version, "\n "); 552167159Sjkim if (cp) { 553167159Sjkim strncpy(builder, cp + 5, 256); 554167159Sjkim builder[255] = '\0'; 555167159Sjkim cp = strstr(builder, ":"); 556167159Sjkim if (cp) 557167159Sjkim *cp = '\0'; 558167159Sjkim } 559167159Sjkim if (cp) 560167159Sjkim sbuf_cat(sb, builder); 561167159Sjkim else 562168762Sdes#endif 563167159Sjkim sbuf_cat(sb, "des@freebsd.org"); 564167159Sjkim} 565167159Sjkim 566167159Sjkim/* 56778113Sdes * Filler function for proc/version 56878113Sdes */ 56978025Sdesstatic int 57078025Sdeslinprocfs_doversion(PFS_FILL_ARGS) 57165633Sdes{ 57287275Srwatson char osname[LINUX_MAX_UTSNAME]; 57387275Srwatson char osrelease[LINUX_MAX_UTSNAME]; 57487275Srwatson 575112206Sjhb linux_get_osname(td, osname); 576112206Sjhb linux_get_osrelease(td, osrelease); 577167159Sjkim sbuf_printf(sb, "%s version %s (", osname, osrelease); 578167159Sjkim linprocfs_osbuilder(td, sb); 579167159Sjkim sbuf_cat(sb, ") (gcc version " __VERSION__ ") "); 580167159Sjkim linprocfs_osbuild(td, sb); 581167159Sjkim sbuf_cat(sb, "\n"); 58287275Srwatson 58378025Sdes return (0); 58465633Sdes} 58565633Sdes 58678113Sdes/* 58778113Sdes * Filler function for proc/loadavg 58878113Sdes */ 58978025Sdesstatic int 59078025Sdeslinprocfs_doloadavg(PFS_FILL_ARGS) 59176839Sjlemon{ 592168762Sdes 59378025Sdes sbuf_printf(sb, 59476839Sjlemon "%d.%02d %d.%02d %d.%02d %d/%d %d\n", 59576839Sjlemon (int)(averunnable.ldavg[0] / averunnable.fscale), 59676839Sjlemon (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100), 59776839Sjlemon (int)(averunnable.ldavg[1] / averunnable.fscale), 59876839Sjlemon (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100), 59976839Sjlemon (int)(averunnable.ldavg[2] / averunnable.fscale), 60076839Sjlemon (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100), 60176839Sjlemon 1, /* number of running tasks */ 60276839Sjlemon nprocs, /* number of tasks */ 60378116Sdes lastpid /* the last pid */ 60476839Sjlemon ); 60578025Sdes return (0); 60676839Sjlemon} 60776839Sjlemon 60878113Sdes/* 60978113Sdes * Filler function for proc/pid/stat 61078113Sdes */ 61178025Sdesstatic int 61278025Sdeslinprocfs_doprocstat(PFS_FILL_ARGS) 61367588Sdes{ 61469995Sdes struct kinfo_proc kp; 615166140Snetchild char state; 616166140Snetchild static int ratelimit = 0; 617206081Snetchild vm_offset_t startcode, startdata; 61867588Sdes 61994307Sjhb PROC_LOCK(p); 62069995Sdes fill_kinfo_proc(p, &kp); 621206081Snetchild if (p->p_vmspace) { 622206081Snetchild startcode = (vm_offset_t)p->p_vmspace->vm_taddr; 623206081Snetchild startdata = (vm_offset_t)p->p_vmspace->vm_daddr; 624206081Snetchild } else { 625206081Snetchild startcode = 0; 626206081Snetchild startdata = 0; 627206081Snetchild }; 62878025Sdes sbuf_printf(sb, "%d", p->p_pid); 62978025Sdes#define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg) 63067588Sdes PS_ADD("comm", "(%s)", p->p_comm); 631166140Snetchild if (kp.ki_stat > sizeof(linux_state)) { 632166140Snetchild state = 'R'; 633166140Snetchild 634166141Snetchild if (ratelimit == 0) { 635166162Snetchild printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n", 636166162Snetchild kp.ki_stat, sizeof(linux_state)); 637166141Snetchild ++ratelimit; 638166141Snetchild } 639166140Snetchild } else 640166140Snetchild state = linux_state[kp.ki_stat - 1]; 641166140Snetchild PS_ADD("state", "%c", state); 64273923Sjhb PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0); 64367588Sdes PS_ADD("pgrp", "%d", p->p_pgid); 64467588Sdes PS_ADD("session", "%d", p->p_session->s_sid); 64591140Stanimura PROC_UNLOCK(p); 646206081Snetchild PS_ADD("tty", "%d", kp.ki_tdev); 647159995Snetchild PS_ADD("tpgid", "%d", kp.ki_tpgid); 64867588Sdes PS_ADD("flags", "%u", 0); /* XXX */ 649159995Snetchild PS_ADD("minflt", "%lu", kp.ki_rusage.ru_minflt); 650159995Snetchild PS_ADD("cminflt", "%lu", kp.ki_rusage_ch.ru_minflt); 651159995Snetchild PS_ADD("majflt", "%lu", kp.ki_rusage.ru_majflt); 652159995Snetchild PS_ADD("cmajflt", "%lu", kp.ki_rusage_ch.ru_majflt); 653206081Snetchild PS_ADD("utime", "%ld", TV2J(&kp.ki_rusage.ru_utime)); 654206081Snetchild PS_ADD("stime", "%ld", TV2J(&kp.ki_rusage.ru_stime)); 655206081Snetchild PS_ADD("cutime", "%ld", TV2J(&kp.ki_rusage_ch.ru_utime)); 656206081Snetchild PS_ADD("cstime", "%ld", TV2J(&kp.ki_rusage_ch.ru_stime)); 657159995Snetchild PS_ADD("priority", "%d", kp.ki_pri.pri_user); 658159995Snetchild PS_ADD("nice", "%d", kp.ki_nice); /* 19 (nicest) to -19 */ 659159995Snetchild PS_ADD("0", "%d", 0); /* removed field */ 660159995Snetchild PS_ADD("itrealvalue", "%d", 0); /* XXX */ 661206081Snetchild PS_ADD("starttime", "%lu", TV2J(&kp.ki_start) - TV2J(&boottime)); 662159995Snetchild PS_ADD("vsize", "%ju", P2K((uintmax_t)kp.ki_size)); 663159995Snetchild PS_ADD("rss", "%ju", (uintmax_t)kp.ki_rssize); 664159995Snetchild PS_ADD("rlim", "%lu", kp.ki_rusage.ru_maxrss); 665206081Snetchild PS_ADD("startcode", "%ju", (uintmax_t)startcode); 666206081Snetchild PS_ADD("endcode", "%ju", (uintmax_t)startdata); 66767588Sdes PS_ADD("startstack", "%u", 0); /* XXX */ 668159995Snetchild PS_ADD("kstkesp", "%u", 0); /* XXX */ 669159995Snetchild PS_ADD("kstkeip", "%u", 0); /* XXX */ 670159995Snetchild PS_ADD("signal", "%u", 0); /* XXX */ 671159995Snetchild PS_ADD("blocked", "%u", 0); /* XXX */ 672159995Snetchild PS_ADD("sigignore", "%u", 0); /* XXX */ 673159995Snetchild PS_ADD("sigcatch", "%u", 0); /* XXX */ 67467588Sdes PS_ADD("wchan", "%u", 0); /* XXX */ 675159995Snetchild PS_ADD("nswap", "%lu", kp.ki_rusage.ru_nswap); 676159995Snetchild PS_ADD("cnswap", "%lu", kp.ki_rusage_ch.ru_nswap); 67769799Sdes PS_ADD("exitsignal", "%d", 0); /* XXX */ 678159995Snetchild PS_ADD("processor", "%u", kp.ki_lastcpu); 679159995Snetchild PS_ADD("rt_priority", "%u", 0); /* XXX */ /* >= 2.5.19 */ 680159995Snetchild PS_ADD("policy", "%u", kp.ki_pri.pri_class); /* >= 2.5.19 */ 68167588Sdes#undef PS_ADD 68278025Sdes sbuf_putc(sb, '\n'); 683119068Sdes 68478025Sdes return (0); 68567588Sdes} 68667588Sdes 68767588Sdes/* 688119911Sdes * Filler function for proc/pid/statm 689119911Sdes */ 690119911Sdesstatic int 691119911Sdeslinprocfs_doprocstatm(PFS_FILL_ARGS) 692119911Sdes{ 693119911Sdes struct kinfo_proc kp; 694119911Sdes segsz_t lsize; 695120340Sdes 696119911Sdes PROC_LOCK(p); 697119911Sdes fill_kinfo_proc(p, &kp); 698119911Sdes PROC_UNLOCK(p); 699119911Sdes 700119911Sdes /* 701119911Sdes * See comments in linprocfs_doprocstatus() regarding the 702119911Sdes * computation of lsize. 703119911Sdes */ 704119911Sdes /* size resident share trs drs lrs dt */ 705119911Sdes sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size)); 706119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize); 707119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */ 708119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize); 709119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize)); 710119911Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 711119911Sdes kp.ki_ssize - kp.ki_tsize - 1; 712119911Sdes sbuf_printf(sb, "%ju ", (uintmax_t)lsize); 713119911Sdes sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */ 714119911Sdes 715119911Sdes return (0); 716119911Sdes} 717119911Sdes 718119911Sdes/* 71978113Sdes * Filler function for proc/pid/status 72078113Sdes */ 72178025Sdesstatic int 72278025Sdeslinprocfs_doprocstatus(PFS_FILL_ARGS) 72367588Sdes{ 72469995Sdes struct kinfo_proc kp; 72567588Sdes char *state; 72669799Sdes segsz_t lsize; 72799072Sjulian struct thread *td2; 728114983Sjhb struct sigacts *ps; 72974135Sjlemon int i; 73067588Sdes 731113611Sjhb PROC_LOCK(p); 73299072Sjulian td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */ 73399072Sjulian 73499072Sjulian if (P_SHOULDSTOP(p)) { 73599072Sjulian state = "T (stopped)"; 73699072Sjulian } else { 737170307Sjeff PROC_SLOCK(p); 73899072Sjulian switch(p->p_state) { 73999072Sjulian case PRS_NEW: 74099072Sjulian state = "I (idle)"; 74199072Sjulian break; 74299072Sjulian case PRS_NORMAL: 74399072Sjulian if (p->p_flag & P_WEXIT) { 74499072Sjulian state = "X (exiting)"; 74599072Sjulian break; 74699072Sjulian } 74799072Sjulian switch(td2->td_state) { 748103216Sjulian case TDS_INHIBITED: 74999072Sjulian state = "S (sleeping)"; 75099072Sjulian break; 75199072Sjulian case TDS_RUNQ: 75299072Sjulian case TDS_RUNNING: 75399072Sjulian state = "R (running)"; 75499072Sjulian break; 75599072Sjulian default: 75699072Sjulian state = "? (unknown)"; 75799072Sjulian break; 75899072Sjulian } 75999072Sjulian break; 76099072Sjulian case PRS_ZOMBIE: 76199072Sjulian state = "Z (zombie)"; 76299072Sjulian break; 76399072Sjulian default: 76499072Sjulian state = "? (unknown)"; 76599072Sjulian break; 76699072Sjulian } 767170307Sjeff PROC_SUNLOCK(p); 76899072Sjulian } 76967588Sdes 77069995Sdes fill_kinfo_proc(p, &kp); 77178025Sdes sbuf_printf(sb, "Name:\t%s\n", p->p_comm); /* XXX escape */ 77278031Sdes sbuf_printf(sb, "State:\t%s\n", state); 77367588Sdes 77467588Sdes /* 77567588Sdes * Credentials 77667588Sdes */ 77778025Sdes sbuf_printf(sb, "Pid:\t%d\n", p->p_pid); 77878025Sdes sbuf_printf(sb, "PPid:\t%d\n", p->p_pptr ? 77973923Sjhb p->p_pptr->p_pid : 0); 78078031Sdes sbuf_printf(sb, "Uid:\t%d %d %d %d\n", p->p_ucred->cr_ruid, 78178031Sdes p->p_ucred->cr_uid, 78278031Sdes p->p_ucred->cr_svuid, 78378031Sdes /* FreeBSD doesn't have fsuid */ 78478031Sdes p->p_ucred->cr_uid); 78578031Sdes sbuf_printf(sb, "Gid:\t%d %d %d %d\n", p->p_ucred->cr_rgid, 78678031Sdes p->p_ucred->cr_gid, 78778031Sdes p->p_ucred->cr_svgid, 78878031Sdes /* FreeBSD doesn't have fsgid */ 78978031Sdes p->p_ucred->cr_gid); 79078025Sdes sbuf_cat(sb, "Groups:\t"); 79167588Sdes for (i = 0; i < p->p_ucred->cr_ngroups; i++) 79278031Sdes sbuf_printf(sb, "%d ", p->p_ucred->cr_groups[i]); 79371471Sjhb PROC_UNLOCK(p); 79478025Sdes sbuf_putc(sb, '\n'); 795119068Sdes 79667588Sdes /* 79767588Sdes * Memory 79869799Sdes * 79969799Sdes * While our approximation of VmLib may not be accurate (I 80069799Sdes * don't know of a simple way to verify it, and I'm not sure 80169799Sdes * it has much meaning anyway), I believe it's good enough. 80269799Sdes * 80369799Sdes * The same code that could (I think) accurately compute VmLib 80469799Sdes * could also compute VmLck, but I don't really care enough to 80569799Sdes * implement it. Submissions are welcome. 80667588Sdes */ 807113574Sjhb sbuf_printf(sb, "VmSize:\t%8ju kB\n", B2K((uintmax_t)kp.ki_size)); 80878025Sdes sbuf_printf(sb, "VmLck:\t%8u kB\n", P2K(0)); /* XXX */ 809206081Snetchild sbuf_printf(sb, "VmRSS:\t%8ju kB\n", P2K((uintmax_t)kp.ki_rssize)); 810113574Sjhb sbuf_printf(sb, "VmData:\t%8ju kB\n", P2K((uintmax_t)kp.ki_dsize)); 811113574Sjhb sbuf_printf(sb, "VmStk:\t%8ju kB\n", P2K((uintmax_t)kp.ki_ssize)); 812113574Sjhb sbuf_printf(sb, "VmExe:\t%8ju kB\n", P2K((uintmax_t)kp.ki_tsize)); 81369995Sdes lsize = B2P(kp.ki_size) - kp.ki_dsize - 81469995Sdes kp.ki_ssize - kp.ki_tsize - 1; 815113574Sjhb sbuf_printf(sb, "VmLib:\t%8ju kB\n", P2K((uintmax_t)lsize)); 81667588Sdes 81767588Sdes /* 81867588Sdes * Signal masks 81967588Sdes * 82067588Sdes * We support up to 128 signals, while Linux supports 32, 82167588Sdes * but we only define 32 (the same 32 as Linux, to boot), so 82267588Sdes * just show the lower 32 bits of each mask. XXX hack. 82367588Sdes * 82467588Sdes * NB: on certain platforms (Sparc at least) Linux actually 82567588Sdes * supports 64 signals, but this code is a long way from 82667588Sdes * running on anything but i386, so ignore that for now. 82767588Sdes */ 82871471Sjhb PROC_LOCK(p); 829104306Sjmallett sbuf_printf(sb, "SigPnd:\t%08x\n", p->p_siglist.__bits[0]); 83069799Sdes /* 83169799Sdes * I can't seem to find out where the signal mask is in 83269799Sdes * relation to struct proc, so SigBlk is left unimplemented. 83369799Sdes */ 83478025Sdes sbuf_printf(sb, "SigBlk:\t%08x\n", 0); /* XXX */ 835114983Sjhb ps = p->p_sigacts; 836114983Sjhb mtx_lock(&ps->ps_mtx); 837114983Sjhb sbuf_printf(sb, "SigIgn:\t%08x\n", ps->ps_sigignore.__bits[0]); 838114983Sjhb sbuf_printf(sb, "SigCgt:\t%08x\n", ps->ps_sigcatch.__bits[0]); 839114983Sjhb mtx_unlock(&ps->ps_mtx); 84071471Sjhb PROC_UNLOCK(p); 841119068Sdes 84267588Sdes /* 84367588Sdes * Linux also prints the capability masks, but we don't have 84467588Sdes * capabilities yet, and when we do get them they're likely to 84567588Sdes * be meaningless to Linux programs, so we lie. XXX 84667588Sdes */ 84778025Sdes sbuf_printf(sb, "CapInh:\t%016x\n", 0); 84878025Sdes sbuf_printf(sb, "CapPrm:\t%016x\n", 0); 84978025Sdes sbuf_printf(sb, "CapEff:\t%016x\n", 0); 850119068Sdes 85178025Sdes return (0); 85267588Sdes} 85374135Sjlemon 854119911Sdes 85578113Sdes/* 856119911Sdes * Filler function for proc/pid/cwd 857119911Sdes */ 858119911Sdesstatic int 859119911Sdeslinprocfs_doproccwd(PFS_FILL_ARGS) 860119911Sdes{ 861119911Sdes char *fullpath = "unknown"; 862119911Sdes char *freepath = NULL; 863119911Sdes 864119911Sdes vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath); 865119911Sdes sbuf_printf(sb, "%s", fullpath); 866119911Sdes if (freepath) 867119911Sdes free(freepath, M_TEMP); 868119911Sdes return (0); 869119911Sdes} 870119911Sdes 871119911Sdes/* 872119911Sdes * Filler function for proc/pid/root 873119911Sdes */ 874119911Sdesstatic int 875119911Sdeslinprocfs_doprocroot(PFS_FILL_ARGS) 876119911Sdes{ 877119911Sdes struct vnode *rvp; 878119911Sdes char *fullpath = "unknown"; 879119911Sdes char *freepath = NULL; 880119911Sdes 881119911Sdes rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir; 882119911Sdes vn_fullpath(td, rvp, &fullpath, &freepath); 883119911Sdes sbuf_printf(sb, "%s", fullpath); 884119911Sdes if (freepath) 885119911Sdes free(freepath, M_TEMP); 886119911Sdes return (0); 887119911Sdes} 888119911Sdes 889119911Sdes/* 89078113Sdes * Filler function for proc/pid/cmdline 89178113Sdes */ 89278025Sdesstatic int 89378113Sdeslinprocfs_doproccmdline(PFS_FILL_ARGS) 89478113Sdes{ 89578113Sdes struct ps_strings pstr; 896138281Scperciva char **ps_argvstr; 89778113Sdes int error, i; 89878113Sdes 89978113Sdes /* 90078113Sdes * If we are using the ps/cmdline caching, use that. Otherwise 90178113Sdes * revert back to the old way which only implements full cmdline 90278113Sdes * for the currept process and just p->p_comm for all other 90378113Sdes * processes. 90478113Sdes * Note that if the argv is no longer available, we deliberately 90578113Sdes * don't fall back on p->p_comm or return an error: the authentic 90678113Sdes * Linux behaviour is to return zero-length in this case. 90778113Sdes */ 90878113Sdes 90994620Sjhb PROC_LOCK(p); 910127694Spjd if (p->p_args && p_cansee(td, p) == 0) { 91194620Sjhb sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length); 91294620Sjhb PROC_UNLOCK(p); 91394620Sjhb } else if (p != td->td_proc) { 91494620Sjhb PROC_UNLOCK(p); 91594620Sjhb sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm); 91694620Sjhb } else { 91794620Sjhb PROC_UNLOCK(p); 918103767Sjake error = copyin((void *)p->p_sysent->sv_psstrings, &pstr, 919103767Sjake sizeof(pstr)); 92094620Sjhb if (error) 92194620Sjhb return (error); 922138281Scperciva if (pstr.ps_nargvstr > ARG_MAX) 923138281Scperciva return (E2BIG); 924138281Scperciva ps_argvstr = malloc(pstr.ps_nargvstr * sizeof(char *), 925138281Scperciva M_TEMP, M_WAITOK); 926138281Scperciva error = copyin((void *)pstr.ps_argvstr, ps_argvstr, 927138281Scperciva pstr.ps_nargvstr * sizeof(char *)); 928138281Scperciva if (error) { 929138281Scperciva free(ps_argvstr, M_TEMP); 930138281Scperciva return (error); 931138281Scperciva } 93294620Sjhb for (i = 0; i < pstr.ps_nargvstr; i++) { 933138281Scperciva sbuf_copyin(sb, ps_argvstr[i], 0); 93494620Sjhb sbuf_printf(sb, "%c", '\0'); 93578113Sdes } 936138281Scperciva free(ps_argvstr, M_TEMP); 93778113Sdes } 93878113Sdes 93978113Sdes return (0); 94078113Sdes} 94178113Sdes 94278113Sdes/* 943116173Sobrien * Filler function for proc/pid/environ 944116173Sobrien */ 945116173Sobrienstatic int 946116173Sobrienlinprocfs_doprocenviron(PFS_FILL_ARGS) 947116173Sobrien{ 948168762Sdes 949116173Sobrien sbuf_printf(sb, "doprocenviron\n%c", '\0'); 950116173Sobrien return (0); 951116173Sobrien} 952116173Sobrien 953116173Sobrien/* 954116173Sobrien * Filler function for proc/pid/maps 955116173Sobrien */ 956116173Sobrienstatic int 957116173Sobrienlinprocfs_doprocmaps(PFS_FILL_ARGS) 958116173Sobrien{ 959185984Skib struct vmspace *vm; 960185984Skib vm_map_t map; 961185765Skib vm_map_entry_t entry, tmp_entry; 962121265Scognet vm_object_t obj, tobj, lobj; 963185765Skib vm_offset_t e_start, e_end; 964121265Scognet vm_ooffset_t off = 0; 965185765Skib vm_prot_t e_prot; 966185765Skib unsigned int last_timestamp; 967121265Scognet char *name = "", *freename = NULL; 968121265Scognet ino_t ino; 969121265Scognet int ref_count, shadow_count, flags; 970121265Scognet int error; 971137507Sphk struct vnode *vp; 972137507Sphk struct vattr vat; 973161094Skib int locked; 974168762Sdes 975121246Scognet PROC_LOCK(p); 976121246Scognet error = p_candebug(td, p); 977121246Scognet PROC_UNLOCK(p); 978121246Scognet if (error) 979121246Scognet return (error); 980168762Sdes 981121246Scognet if (uio->uio_rw != UIO_READ) 982121246Scognet return (EOPNOTSUPP); 983168762Sdes 984121246Scognet error = 0; 985185984Skib vm = vmspace_acquire_ref(p); 986185984Skib if (vm == NULL) 987185984Skib return (ESRCH); 988185984Skib map = &vm->vm_map; 989169156Salc vm_map_lock_read(map); 990183600Skib for (entry = map->header.next; entry != &map->header; 991121246Scognet entry = entry->next) { 992121265Scognet name = ""; 993121265Scognet freename = NULL; 994121246Scognet if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) 995121246Scognet continue; 996185765Skib e_prot = entry->protection; 997185765Skib e_start = entry->start; 998185765Skib e_end = entry->end; 999121246Scognet obj = entry->object.vm_object; 1000169156Salc for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) { 1001169156Salc VM_OBJECT_LOCK(tobj); 1002169156Salc if (lobj != obj) 1003169156Salc VM_OBJECT_UNLOCK(lobj); 1004121246Scognet lobj = tobj; 1005169156Salc } 1006185765Skib last_timestamp = map->timestamp; 1007185765Skib vm_map_unlock_read(map); 1008121246Scognet ino = 0; 1009121246Scognet if (lobj) { 1010121246Scognet off = IDX_TO_OFF(lobj->size); 1011161094Skib if (lobj->type == OBJT_VNODE) { 1012161094Skib vp = lobj->handle; 1013161094Skib if (vp) 1014161094Skib vref(vp); 1015121246Scognet } 1016161094Skib else 1017161094Skib vp = NULL; 1018169156Salc if (lobj != obj) 1019169156Salc VM_OBJECT_UNLOCK(lobj); 1020121246Scognet flags = obj->flags; 1021121246Scognet ref_count = obj->ref_count; 1022121246Scognet shadow_count = obj->shadow_count; 1023169156Salc VM_OBJECT_UNLOCK(obj); 1024161094Skib if (vp) { 1025161094Skib vn_fullpath(td, vp, &name, &freename); 1026161094Skib locked = VFS_LOCK_GIANT(vp->v_mount); 1027175202Sattilio vn_lock(vp, LK_SHARED | LK_RETRY); 1028182371Sattilio VOP_GETATTR(vp, &vat, td->td_ucred); 1029161094Skib ino = vat.va_fileid; 1030161094Skib vput(vp); 1031161094Skib VFS_UNLOCK_GIANT(locked); 1032161094Skib } 1033121246Scognet } else { 1034121246Scognet flags = 0; 1035121246Scognet ref_count = 0; 1036121246Scognet shadow_count = 0; 1037121246Scognet } 1038168762Sdes 1039121246Scognet /* 1040168762Sdes * format: 1041121246Scognet * start, end, access, offset, major, minor, inode, name. 1042121246Scognet */ 1043183600Skib error = sbuf_printf(sb, 1044121246Scognet "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n", 1045185765Skib (u_long)e_start, (u_long)e_end, 1046185765Skib (e_prot & VM_PROT_READ)?"r":"-", 1047185765Skib (e_prot & VM_PROT_WRITE)?"w":"-", 1048185765Skib (e_prot & VM_PROT_EXECUTE)?"x":"-", 1049121246Scognet "p", 1050121265Scognet (u_long)off, 1051121246Scognet 0, 1052121246Scognet 0, 1053121265Scognet (u_long)ino, 1054121246Scognet *name ? " " : "", 1055121246Scognet name 1056121246Scognet ); 1057121246Scognet if (freename) 1058121246Scognet free(freename, M_TEMP); 1059185864Skib vm_map_lock_read(map); 1060183600Skib if (error == -1) { 1061183600Skib error = 0; 1062121246Scognet break; 1063169156Salc } 1064186563Skib if (last_timestamp != map->timestamp) { 1065185765Skib /* 1066185765Skib * Look again for the entry because the map was 1067185765Skib * modified while it was unlocked. Specifically, 1068185765Skib * the entry may have been clipped, merged, or deleted. 1069185765Skib */ 1070185765Skib vm_map_lookup_entry(map, e_end - 1, &tmp_entry); 1071185765Skib entry = tmp_entry; 1072185765Skib } 1073121246Scognet } 1074169156Salc vm_map_unlock_read(map); 1075185984Skib vmspace_free(vm); 1076168762Sdes 1077121246Scognet return (error); 1078168762Sdes} 1079168762Sdes 1080116173Sobrien/* 108178113Sdes * Filler function for proc/net/dev 108278113Sdes */ 108378025Sdesstatic int 108478025Sdeslinprocfs_donetdev(PFS_FILL_ARGS) 108574135Sjlemon{ 108685129Sdes char ifname[16]; /* XXX LINUX_IFNAMSIZ */ 108774135Sjlemon struct ifnet *ifp; 108874135Sjlemon 108985129Sdes sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n", 109083926Sdes "Inter-", " Receive", " Transmit", " face", 109185129Sdes "bytes packets errs drop fifo frame compressed", 109283926Sdes "bytes packets errs drop fifo frame compressed"); 109374135Sjlemon 1094196635Szec CURVNET_SET(TD_TO_VNET(curthread)); 1095108172Shsu IFNET_RLOCK(); 1096181803Sbz TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 109785129Sdes linux_ifname(ifp, ifname, sizeof ifname); 109885129Sdes sbuf_printf(sb, "%6.6s:", ifname); 109983926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ", 110083926Sdes 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); 110183926Sdes sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n", 110283926Sdes 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL); 110374135Sjlemon } 1104108172Shsu IFNET_RUNLOCK(); 1105196635Szec CURVNET_RESTORE(); 1106119068Sdes 110778025Sdes return (0); 110874135Sjlemon} 110974135Sjlemon 1110158311Sambrisko/* 1111167159Sjkim * Filler function for proc/sys/kernel/osrelease 1112167159Sjkim */ 1113167159Sjkimstatic int 1114167159Sjkimlinprocfs_doosrelease(PFS_FILL_ARGS) 1115167159Sjkim{ 1116167159Sjkim char osrelease[LINUX_MAX_UTSNAME]; 1117167159Sjkim 1118167159Sjkim linux_get_osrelease(td, osrelease); 1119167159Sjkim sbuf_printf(sb, "%s\n", osrelease); 1120167159Sjkim 1121167159Sjkim return (0); 1122167159Sjkim} 1123167159Sjkim 1124167159Sjkim/* 1125167159Sjkim * Filler function for proc/sys/kernel/ostype 1126167159Sjkim */ 1127167159Sjkimstatic int 1128167159Sjkimlinprocfs_doostype(PFS_FILL_ARGS) 1129167159Sjkim{ 1130167159Sjkim char osname[LINUX_MAX_UTSNAME]; 1131167159Sjkim 1132167159Sjkim linux_get_osname(td, osname); 1133167159Sjkim sbuf_printf(sb, "%s\n", osname); 1134167159Sjkim 1135167159Sjkim return (0); 1136167159Sjkim} 1137167159Sjkim 1138167159Sjkim/* 1139167159Sjkim * Filler function for proc/sys/kernel/version 1140167159Sjkim */ 1141167159Sjkimstatic int 1142167159Sjkimlinprocfs_doosbuild(PFS_FILL_ARGS) 1143167159Sjkim{ 1144168762Sdes 1145167159Sjkim linprocfs_osbuild(td, sb); 1146167159Sjkim sbuf_cat(sb, "\n"); 1147167159Sjkim return (0); 1148167159Sjkim} 1149167159Sjkim 1150167159Sjkim/* 1151164692Sjkim * Filler function for proc/sys/kernel/msgmni 1152164692Sjkim */ 1153164692Sjkimstatic int 1154164692Sjkimlinprocfs_domsgmni(PFS_FILL_ARGS) 1155164692Sjkim{ 1156164692Sjkim 1157168067Sjkim sbuf_printf(sb, "%d\n", msginfo.msgmni); 1158164692Sjkim return (0); 1159164692Sjkim} 1160164692Sjkim 1161164692Sjkim/* 1162163251Skeramida * Filler function for proc/sys/kernel/pid_max 1163163129Snetchild */ 1164163129Snetchildstatic int 1165163129Snetchildlinprocfs_dopid_max(PFS_FILL_ARGS) 1166163129Snetchild{ 1167163757Snetchild 1168163129Snetchild sbuf_printf(sb, "%i\n", PID_MAX); 1169163129Snetchild return (0); 1170163129Snetchild} 1171163129Snetchild 1172163129Snetchild/* 1173164692Sjkim * Filler function for proc/sys/kernel/sem 1174164692Sjkim */ 1175164692Sjkimstatic int 1176164692Sjkimlinprocfs_dosem(PFS_FILL_ARGS) 1177164692Sjkim{ 1178164692Sjkim 1179168067Sjkim sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns, 1180168067Sjkim seminfo.semopm, seminfo.semmni); 1181164692Sjkim return (0); 1182164692Sjkim} 1183164692Sjkim 1184164692Sjkim/* 1185158311Sambrisko * Filler function for proc/scsi/device_info 1186158311Sambrisko */ 1187158311Sambriskostatic int 1188158311Sambriskolinprocfs_doscsidevinfo(PFS_FILL_ARGS) 1189158311Sambrisko{ 1190168762Sdes 1191158311Sambrisko return (0); 1192158311Sambrisko} 1193158311Sambrisko 1194158311Sambrisko/* 1195158311Sambrisko * Filler function for proc/scsi/scsi 1196158311Sambrisko */ 1197158311Sambriskostatic int 1198158311Sambriskolinprocfs_doscsiscsi(PFS_FILL_ARGS) 1199158311Sambrisko{ 1200168762Sdes 1201158311Sambrisko return (0); 1202158311Sambrisko} 1203158311Sambrisko 120485538Sphkextern struct cdevsw *cdevsw[]; 120585538Sphk 120678113Sdes/* 120778113Sdes * Filler function for proc/devices 120878113Sdes */ 120978025Sdesstatic int 121078025Sdeslinprocfs_dodevices(PFS_FILL_ARGS) 121174135Sjlemon{ 1212158311Sambrisko char *char_devices; 121378025Sdes sbuf_printf(sb, "Character devices:\n"); 121474135Sjlemon 1215158311Sambrisko char_devices = linux_get_char_devices(); 1216158311Sambrisko sbuf_printf(sb, "%s", char_devices); 1217158311Sambrisko linux_free_get_char_devices(char_devices); 121874135Sjlemon 121978025Sdes sbuf_printf(sb, "\nBlock devices:\n"); 1220119068Sdes 122178025Sdes return (0); 122274135Sjlemon} 122374135Sjlemon 122478113Sdes/* 122578113Sdes * Filler function for proc/cmdline 122678113Sdes */ 122778025Sdesstatic int 122878025Sdeslinprocfs_docmdline(PFS_FILL_ARGS) 122974135Sjlemon{ 1230168762Sdes 123178025Sdes sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname); 123278025Sdes sbuf_printf(sb, " ro root=302\n"); 123378025Sdes return (0); 123478025Sdes} 123574135Sjlemon 1236205541Sjhb/* 1237205541Sjhb * Filler function for proc/filesystems 1238205541Sjhb */ 1239205541Sjhbstatic int 1240205541Sjhblinprocfs_dofilesystems(PFS_FILL_ARGS) 1241205541Sjhb{ 1242205541Sjhb struct vfsconf *vfsp; 1243205541Sjhb 1244205592Sjhb mtx_lock(&Giant); 1245205541Sjhb TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) { 1246205541Sjhb if (vfsp->vfc_flags & VFCF_SYNTHETIC) 1247205541Sjhb sbuf_printf(sb, "nodev"); 1248205541Sjhb sbuf_printf(sb, "\t%s\n", vfsp->vfc_name); 1249205541Sjhb } 1250205592Sjhb mtx_unlock(&Giant); 1251205541Sjhb return(0); 1252205541Sjhb} 1253205541Sjhb 125483926Sdes#if 0 125578025Sdes/* 125683926Sdes * Filler function for proc/modules 125783926Sdes */ 125883926Sdesstatic int 125983926Sdeslinprocfs_domodules(PFS_FILL_ARGS) 126083926Sdes{ 126183926Sdes struct linker_file *lf; 1262119068Sdes 126383926Sdes TAILQ_FOREACH(lf, &linker_files, link) { 126483926Sdes sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename, 126583926Sdes (unsigned long)lf->size, lf->refs); 126683926Sdes } 126783926Sdes return (0); 126883926Sdes} 126983926Sdes#endif 127083926Sdes 127183926Sdes/* 1272204825Sed * Filler function for proc/pid/fd 1273204825Sed */ 1274204825Sedstatic int 1275204825Sedlinprocfs_dofdescfs(PFS_FILL_ARGS) 1276204825Sed{ 1277204825Sed 1278204825Sed if (p == curproc) 1279204825Sed sbuf_printf(sb, "/dev/fd"); 1280204825Sed else 1281204825Sed sbuf_printf(sb, "unknown"); 1282204825Sed return (0); 1283204825Sed} 1284204825Sed 1285204825Sed/* 128685129Sdes * Constructor 128778025Sdes */ 128885129Sdesstatic int 128985129Sdeslinprocfs_init(PFS_INIT_ARGS) 129085129Sdes{ 129185129Sdes struct pfs_node *root; 129285129Sdes struct pfs_node *dir; 129374135Sjlemon 129485129Sdes root = pi->pi_root; 129578025Sdes 1296119923Sdes /* /proc/... */ 1297119911Sdes pfs_create_file(root, "cmdline", &linprocfs_docmdline, 1298167482Sdes NULL, NULL, NULL, PFS_RD); 1299119911Sdes pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo, 1300167482Sdes NULL, NULL, NULL, PFS_RD); 1301119911Sdes pfs_create_file(root, "devices", &linprocfs_dodevices, 1302167482Sdes NULL, NULL, NULL, PFS_RD); 1303205541Sjhb pfs_create_file(root, "filesystems", &linprocfs_dofilesystems, 1304205541Sjhb NULL, NULL, NULL, PFS_RD); 1305119911Sdes pfs_create_file(root, "loadavg", &linprocfs_doloadavg, 1306167482Sdes NULL, NULL, NULL, PFS_RD); 1307119911Sdes pfs_create_file(root, "meminfo", &linprocfs_domeminfo, 1308167482Sdes NULL, NULL, NULL, PFS_RD); 130983926Sdes#if 0 1310119911Sdes pfs_create_file(root, "modules", &linprocfs_domodules, 1311167482Sdes NULL, NULL, NULL, PFS_RD); 131283926Sdes#endif 1313158311Sambrisko pfs_create_file(root, "mounts", &linprocfs_domtab, 1314167482Sdes NULL, NULL, NULL, PFS_RD); 1315119911Sdes pfs_create_file(root, "mtab", &linprocfs_domtab, 1316167482Sdes NULL, NULL, NULL, PFS_RD); 1317190445Sambrisko pfs_create_file(root, "partitions", &linprocfs_dopartitions, 1318190445Sambrisko NULL, NULL, NULL, PFS_RD); 131987543Sdes pfs_create_link(root, "self", &procfs_docurproc, 1320167482Sdes NULL, NULL, NULL, 0); 1321119911Sdes pfs_create_file(root, "stat", &linprocfs_dostat, 1322167482Sdes NULL, NULL, NULL, PFS_RD); 1323119911Sdes pfs_create_file(root, "uptime", &linprocfs_douptime, 1324167482Sdes NULL, NULL, NULL, PFS_RD); 1325119911Sdes pfs_create_file(root, "version", &linprocfs_doversion, 1326167482Sdes NULL, NULL, NULL, PFS_RD); 132778025Sdes 1328119923Sdes /* /proc/net/... */ 1329167482Sdes dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0); 133085129Sdes pfs_create_file(dir, "dev", &linprocfs_donetdev, 1331167482Sdes NULL, NULL, NULL, PFS_RD); 133278025Sdes 1333119923Sdes /* /proc/<pid>/... */ 1334167482Sdes dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP); 133585129Sdes pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline, 1336167482Sdes NULL, NULL, NULL, PFS_RD); 1337119911Sdes pfs_create_link(dir, "cwd", &linprocfs_doproccwd, 1338167482Sdes NULL, NULL, NULL, 0); 1339116173Sobrien pfs_create_file(dir, "environ", &linprocfs_doprocenviron, 1340167482Sdes NULL, NULL, NULL, PFS_RD); 134187543Sdes pfs_create_link(dir, "exe", &procfs_doprocfile, 1342167482Sdes NULL, &procfs_notsystem, NULL, 0); 1343116173Sobrien pfs_create_file(dir, "maps", &linprocfs_doprocmaps, 1344167482Sdes NULL, NULL, NULL, PFS_RD); 134585129Sdes pfs_create_file(dir, "mem", &procfs_doprocmem, 1346167482Sdes &procfs_attr, &procfs_candebug, NULL, PFS_RDWR|PFS_RAW); 1347119911Sdes pfs_create_link(dir, "root", &linprocfs_doprocroot, 1348167482Sdes NULL, NULL, NULL, 0); 134985129Sdes pfs_create_file(dir, "stat", &linprocfs_doprocstat, 1350167482Sdes NULL, NULL, NULL, PFS_RD); 1351119911Sdes pfs_create_file(dir, "statm", &linprocfs_doprocstatm, 1352167482Sdes NULL, NULL, NULL, PFS_RD); 135385129Sdes pfs_create_file(dir, "status", &linprocfs_doprocstatus, 1354167482Sdes NULL, NULL, NULL, PFS_RD); 1355204825Sed pfs_create_link(dir, "fd", &linprocfs_dofdescfs, 1356204825Sed NULL, NULL, NULL, 0); 135785129Sdes 1358158311Sambrisko /* /proc/scsi/... */ 1359167482Sdes dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0); 1360158311Sambrisko pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo, 1361167482Sdes NULL, NULL, NULL, PFS_RD); 1362158311Sambrisko pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi, 1363167482Sdes NULL, NULL, NULL, PFS_RD); 1364163129Snetchild 1365163129Snetchild /* /proc/sys/... */ 1366167482Sdes dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0); 1367163129Snetchild /* /proc/sys/kernel/... */ 1368167482Sdes dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0); 1369167159Sjkim pfs_create_file(dir, "osrelease", &linprocfs_doosrelease, 1370167482Sdes NULL, NULL, NULL, PFS_RD); 1371167159Sjkim pfs_create_file(dir, "ostype", &linprocfs_doostype, 1372167482Sdes NULL, NULL, NULL, PFS_RD); 1373167159Sjkim pfs_create_file(dir, "version", &linprocfs_doosbuild, 1374167482Sdes NULL, NULL, NULL, PFS_RD); 1375164692Sjkim pfs_create_file(dir, "msgmni", &linprocfs_domsgmni, 1376167482Sdes NULL, NULL, NULL, PFS_RD); 1377163129Snetchild pfs_create_file(dir, "pid_max", &linprocfs_dopid_max, 1378167482Sdes NULL, NULL, NULL, PFS_RD); 1379164692Sjkim pfs_create_file(dir, "sem", &linprocfs_dosem, 1380167482Sdes NULL, NULL, NULL, PFS_RD); 1381163129Snetchild 138285129Sdes return (0); 138385129Sdes} 138485129Sdes 138585129Sdes/* 138685129Sdes * Destructor 138785129Sdes */ 138885129Sdesstatic int 138985129Sdeslinprocfs_uninit(PFS_INIT_ARGS) 139085129Sdes{ 139185129Sdes 139285129Sdes /* nothing to do, pseudofs will GC */ 139385129Sdes return (0); 139485129Sdes} 139585129Sdes 139685129SdesPSEUDOFS(linprocfs, 1); 139778025SdesMODULE_DEPEND(linprocfs, linux, 1, 1, 1); 139878025SdesMODULE_DEPEND(linprocfs, procfs, 1, 1, 1); 1399168440SjkimMODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1); 1400168440SjkimMODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1); 1401