The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/linprocfs/linprocfs.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-4-Clause
    3  *
    4  * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav
    5  * Copyright (c) 1999 Pierre Beyssac
    6  * Copyright (c) 1993 Jan-Simon Pendry
    7  * Copyright (c) 1993
    8  *      The Regents of the University of California.  All rights reserved.
    9  *
   10  * This code is derived from software contributed to Berkeley by
   11  * Jan-Simon Pendry.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 3. All advertising materials mentioning features or use of this software
   22  *    must display the following acknowledgement:
   23  *      This product includes software developed by the University of
   24  *      California, Berkeley and its contributors.
   25  * 4. Neither the name of the University nor the names of its contributors
   26  *    may be used to endorse or promote products derived from this software
   27  *    without specific prior written permission.
   28  *
   29  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   30  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   32  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   39  * SUCH DAMAGE.
   40  *
   41  *      @(#)procfs_status.c     8.4 (Berkeley) 6/15/94
   42  */
   43 
   44 #include <sys/cdefs.h>
   45 __FBSDID("$FreeBSD: releng/12.0/sys/compat/linprocfs/linprocfs.c 335516 2018-06-22 00:02:05Z chuck $");
   46 
   47 #include <sys/param.h>
   48 #include <sys/queue.h>
   49 #include <sys/blist.h>
   50 #include <sys/conf.h>
   51 #include <sys/exec.h>
   52 #include <sys/fcntl.h>
   53 #include <sys/filedesc.h>
   54 #include <sys/jail.h>
   55 #include <sys/kernel.h>
   56 #include <sys/limits.h>
   57 #include <sys/linker.h>
   58 #include <sys/lock.h>
   59 #include <sys/malloc.h>
   60 #include <sys/msg.h>
   61 #include <sys/mutex.h>
   62 #include <sys/namei.h>
   63 #include <sys/proc.h>
   64 #include <sys/ptrace.h>
   65 #include <sys/resourcevar.h>
   66 #include <sys/resource.h>
   67 #include <sys/sbuf.h>
   68 #include <sys/sem.h>
   69 #include <sys/smp.h>
   70 #include <sys/socket.h>
   71 #include <sys/syscallsubr.h>
   72 #include <sys/sysctl.h>
   73 #include <sys/sysent.h>
   74 #include <sys/systm.h>
   75 #include <sys/time.h>
   76 #include <sys/tty.h>
   77 #include <sys/user.h>
   78 #include <sys/uuid.h>
   79 #include <sys/vmmeter.h>
   80 #include <sys/vnode.h>
   81 #include <sys/bus.h>
   82 
   83 #include <net/if.h>
   84 #include <net/if_var.h>
   85 #include <net/if_types.h>
   86 
   87 #include <vm/vm.h>
   88 #include <vm/vm_extern.h>
   89 #include <vm/pmap.h>
   90 #include <vm/vm_map.h>
   91 #include <vm/vm_param.h>
   92 #include <vm/vm_object.h>
   93 #include <vm/swap_pager.h>
   94 
   95 #include <machine/clock.h>
   96 
   97 #include <geom/geom.h>
   98 #include <geom/geom_int.h>
   99 
  100 #if defined(__i386__) || defined(__amd64__)
  101 #include <machine/cputypes.h>
  102 #include <machine/md_var.h>
  103 #endif /* __i386__ || __amd64__ */
  104 
  105 #include <compat/linux/linux.h>
  106 #include <compat/linux/linux_mib.h>
  107 #include <compat/linux/linux_misc.h>
  108 #include <compat/linux/linux_util.h>
  109 #include <fs/pseudofs/pseudofs.h>
  110 #include <fs/procfs/procfs.h>
  111 
  112 /*
  113  * Various conversion macros
  114  */
  115 #define T2J(x) ((long)(((x) * 100ULL) / (stathz ? stathz : hz)))        /* ticks to jiffies */
  116 #define T2CS(x) ((unsigned long)(((x) * 100ULL) / (stathz ? stathz : hz)))      /* ticks to centiseconds */
  117 #define T2S(x) ((x) / (stathz ? stathz : hz))           /* ticks to seconds */
  118 #define B2K(x) ((x) >> 10)                              /* bytes to kbytes */
  119 #define B2P(x) ((x) >> PAGE_SHIFT)                      /* bytes to pages */
  120 #define P2B(x) ((x) << PAGE_SHIFT)                      /* pages to bytes */
  121 #define P2K(x) ((x) << (PAGE_SHIFT - 10))               /* pages to kbytes */
  122 #define TV2J(x) ((x)->tv_sec * 100UL + (x)->tv_usec / 10000)
  123 
  124 /**
  125  * @brief Mapping of ki_stat in struct kinfo_proc to the linux state
  126  *
  127  * The linux procfs state field displays one of the characters RSDZTW to
  128  * denote running, sleeping in an interruptible wait, waiting in an
  129  * uninterruptible disk sleep, a zombie process, process is being traced
  130  * or stopped, or process is paging respectively.
  131  *
  132  * Our struct kinfo_proc contains the variable ki_stat which contains a
  133  * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK.
  134  *
  135  * This character array is used with ki_stati-1 as an index and tries to
  136  * map our states to suitable linux states.
  137  */
  138 static char linux_state[] = "RRSTZDD";
  139 
  140 /*
  141  * Filler function for proc/meminfo
  142  */
  143 static int
  144 linprocfs_domeminfo(PFS_FILL_ARGS)
  145 {
  146         unsigned long memtotal;         /* total memory in bytes */
  147         unsigned long memused;          /* used memory in bytes */
  148         unsigned long memfree;          /* free memory in bytes */
  149         unsigned long buffers, cached;  /* buffer / cache memory ??? */
  150         unsigned long long swaptotal;   /* total swap space in bytes */
  151         unsigned long long swapused;    /* used swap space in bytes */
  152         unsigned long long swapfree;    /* free swap space in bytes */
  153         int i, j;
  154 
  155         memtotal = physmem * PAGE_SIZE;
  156         /*
  157          * The correct thing here would be:
  158          *
  159         memfree = vm_free_count() * PAGE_SIZE;
  160         memused = memtotal - memfree;
  161          *
  162          * but it might mislead linux binaries into thinking there
  163          * is very little memory left, so we cheat and tell them that
  164          * all memory that isn't wired down is free.
  165          */
  166         memused = vm_wire_count() * PAGE_SIZE;
  167         memfree = memtotal - memused;
  168         swap_pager_status(&i, &j);
  169         swaptotal = (unsigned long long)i * PAGE_SIZE;
  170         swapused = (unsigned long long)j * PAGE_SIZE;
  171         swapfree = swaptotal - swapused;
  172         /*
  173          * We'd love to be able to write:
  174          *
  175         buffers = bufspace;
  176          *
  177          * but bufspace is internal to vfs_bio.c and we don't feel
  178          * like unstaticizing it just for linprocfs's sake.
  179          */
  180         buffers = 0;
  181         cached = vm_inactive_count() * PAGE_SIZE;
  182 
  183         sbuf_printf(sb,
  184             "MemTotal: %9lu kB\n"
  185             "MemFree:  %9lu kB\n"
  186             "Buffers:  %9lu kB\n"
  187             "Cached:   %9lu kB\n"
  188             "SwapTotal:%9llu kB\n"
  189             "SwapFree: %9llu kB\n",
  190             B2K(memtotal), B2K(memfree), B2K(buffers),
  191             B2K(cached), B2K(swaptotal), B2K(swapfree));
  192 
  193         return (0);
  194 }
  195 
  196 #if defined(__i386__) || defined(__amd64__)
  197 /*
  198  * Filler function for proc/cpuinfo (i386 & amd64 version)
  199  */
  200 static int
  201 linprocfs_docpuinfo(PFS_FILL_ARGS)
  202 {
  203         int hw_model[2];
  204         char model[128];
  205         uint64_t freq;
  206         size_t size;
  207         u_int cache_size[4];
  208         int fqmhz, fqkhz;
  209         int i, j;
  210 
  211         /*
  212          * We default the flags to include all non-conflicting flags,
  213          * and the Intel versions of conflicting flags.
  214          */
  215         static char *flags[] = {
  216                 "fpu",      "vme",     "de",       "pse",      "tsc",
  217                 "msr",      "pae",     "mce",      "cx8",      "apic",
  218                 "sep",      "sep",     "mtrr",     "pge",      "mca",
  219                 "cmov",     "pat",     "pse36",    "pn",       "b19",
  220                 "b20",      "b21",     "mmxext",   "mmx",      "fxsr",
  221                 "xmm",      "sse2",    "b27",      "b28",      "b29",
  222                 "3dnowext", "3dnow"
  223         };
  224 
  225         static char *power_flags[] = {
  226                 "ts",           "fid",          "vid",
  227                 "ttp",          "tm",           "stc",
  228                 "100mhzsteps",  "hwpstate",     "",
  229                 "cpb",          "eff_freq_ro",  "proc_feedback",
  230                 "acc_power",
  231         };
  232 
  233         hw_model[0] = CTL_HW;
  234         hw_model[1] = HW_MODEL;
  235         model[0] = '\0';
  236         size = sizeof(model);
  237         if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0)
  238                 strcpy(model, "unknown");
  239 #ifdef __i386__
  240         switch (cpu_vendor_id) {
  241         case CPU_VENDOR_AMD:
  242                 if (cpu_class < CPUCLASS_686)
  243                         flags[16] = "fcmov";
  244                 break;
  245         case CPU_VENDOR_CYRIX:
  246                 flags[24] = "cxmmx";
  247                 break;
  248         }
  249 #endif
  250         if (cpu_exthigh >= 0x80000006)
  251                 do_cpuid(0x80000006, cache_size);
  252         else
  253                 memset(cache_size, 0, sizeof(cache_size));
  254         for (i = 0; i < mp_ncpus; ++i) {
  255                 fqmhz = 0;
  256                 fqkhz = 0;
  257                 freq = atomic_load_acq_64(&tsc_freq);
  258                 if (freq != 0) {
  259                         fqmhz = (freq + 4999) / 1000000;
  260                         fqkhz = ((freq + 4999) / 10000) % 100;
  261                 }
  262                 sbuf_printf(sb,
  263                     "processor\t: %d\n"
  264                     "vendor_id\t: %.20s\n"
  265                     "cpu family\t: %u\n"
  266                     "model\t\t: %u\n"
  267                     "model name\t: %s\n"
  268                     "stepping\t: %u\n"
  269                     "cpu MHz\t\t: %d.%02d\n"
  270                     "cache size\t: %d KB\n"
  271                     "physical id\t: %d\n"
  272                     "siblings\t: %d\n"
  273                     "core id\t\t: %d\n"
  274                     "cpu cores\t: %d\n"
  275                     "apicid\t\t: %d\n"
  276                     "initial apicid\t: %d\n"
  277                     "fpu\t\t: %s\n"
  278                     "fpu_exception\t: %s\n"
  279                     "cpuid level\t: %d\n"
  280                     "wp\t\t: %s\n",
  281                     i, cpu_vendor, CPUID_TO_FAMILY(cpu_id),
  282                     CPUID_TO_MODEL(cpu_id), model, cpu_id & CPUID_STEPPING,
  283                     fqmhz, fqkhz,
  284                     (cache_size[2] >> 16), 0, mp_ncpus, i, mp_ncpus,
  285                     i, i, /*cpu_id & CPUID_LOCAL_APIC_ID ??*/
  286                     (cpu_feature & CPUID_FPU) ? "yes" : "no", "yes",
  287                     CPUID_TO_FAMILY(cpu_id), "yes");
  288                 sbuf_cat(sb, "flags\t\t:");
  289                 for (j = 0; j < nitems(flags); j++)
  290                         if (cpu_feature & (1 << j))
  291                                 sbuf_printf(sb, " %s", flags[j]);
  292                 sbuf_cat(sb, "\n");
  293                 sbuf_printf(sb,
  294                     "bugs\t\t: %s\n"
  295                     "bogomips\t: %d.%02d\n"
  296                     "clflush size\t: %d\n"
  297                     "cache_alignment\t: %d\n"
  298                     "address sizes\t: %d bits physical, %d bits virtual\n",
  299 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
  300                     (has_f00f_bug) ? "Intel F00F" : "",
  301 #else
  302                     "",
  303 #endif
  304                     fqmhz, fqkhz,
  305                     cpu_clflush_line_size, cpu_clflush_line_size,
  306                     cpu_maxphyaddr,
  307                     (cpu_maxphyaddr > 32) ? 48 : 0);
  308                 sbuf_cat(sb, "power management: ");
  309                 for (j = 0; j < nitems(power_flags); j++)
  310                         if (amd_pminfo & (1 << j))
  311                                 sbuf_printf(sb, " %s", power_flags[j]);
  312                 sbuf_cat(sb, "\n\n");
  313 
  314                 /* XXX per-cpu vendor / class / model / id? */
  315         }
  316         sbuf_cat(sb, "\n");
  317 
  318         return (0);
  319 }
  320 #else
  321 /* ARM64TODO: implement non-stubbed linprocfs_docpuinfo */
  322 static int
  323 linprocfs_docpuinfo(PFS_FILL_ARGS)
  324 {
  325         int i;
  326 
  327         for (i = 0; i < mp_ncpus; ++i) {
  328                 sbuf_printf(sb,
  329                     "processor\t: %d\n"
  330                     "BogoMIPS\t: %d.%02d\n",
  331                     i, 0, 0);
  332                 sbuf_cat(sb, "Features\t: ");
  333                 sbuf_cat(sb, "\n");
  334                 sbuf_printf(sb,
  335                     "CPU implementer\t: \n"
  336                     "CPU architecture: \n"
  337                     "CPU variant\t: 0x%x\n"
  338                     "CPU part\t: 0x%x\n"
  339                     "CPU revision\t: %d\n",
  340                     0, 0, 0);
  341                 sbuf_cat(sb, "\n");
  342         }
  343 
  344         return (0);
  345 }
  346 #endif /* __i386__ || __amd64__ */
  347 
  348 /*
  349  * Filler function for proc/mtab
  350  *
  351  * This file doesn't exist in Linux' procfs, but is included here so
  352  * users can symlink /compat/linux/etc/mtab to /proc/mtab
  353  */
  354 static int
  355 linprocfs_domtab(PFS_FILL_ARGS)
  356 {
  357         struct nameidata nd;
  358         const char *lep;
  359         char *dlep, *flep, *mntto, *mntfrom, *fstype;
  360         size_t lep_len;
  361         int error;
  362         struct statfs *buf, *sp;
  363         size_t count;
  364 
  365         /* resolve symlinks etc. in the emulation tree prefix */
  366         NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td);
  367         flep = NULL;
  368         error = namei(&nd);
  369         lep = linux_emul_path;
  370         if (error == 0) {
  371                 if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
  372                         lep = dlep;
  373                 vrele(nd.ni_vp);
  374         }
  375         lep_len = strlen(lep);
  376 
  377         buf = NULL;
  378         error = kern_getfsstat(td, &buf, SIZE_T_MAX, &count,
  379             UIO_SYSSPACE, MNT_WAIT);
  380         if (error != 0) {
  381                 free(buf, M_TEMP);
  382                 free(flep, M_TEMP);
  383                 return (error);
  384         }
  385 
  386         for (sp = buf; count > 0; sp++, count--) {
  387                 /* determine device name */
  388                 mntfrom = sp->f_mntfromname;
  389 
  390                 /* determine mount point */
  391                 mntto = sp->f_mntonname;
  392                 if (strncmp(mntto, lep, lep_len) == 0 && mntto[lep_len] == '/')
  393                         mntto += lep_len;
  394 
  395                 /* determine fs type */
  396                 fstype = sp->f_fstypename;
  397                 if (strcmp(fstype, pn->pn_info->pi_name) == 0)
  398                         mntfrom = fstype = "proc";
  399                 else if (strcmp(fstype, "procfs") == 0)
  400                         continue;
  401 
  402                 if (strcmp(fstype, "linsysfs") == 0) {
  403                         sbuf_printf(sb, "/sys %s sysfs %s", mntto,
  404                             sp->f_flags & MNT_RDONLY ? "ro" : "rw");
  405                 } else {
  406                         /* For Linux msdosfs is called vfat */
  407                         if (strcmp(fstype, "msdosfs") == 0)
  408                                 fstype = "vfat";
  409                         sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
  410                             sp->f_flags & MNT_RDONLY ? "ro" : "rw");
  411                 }
  412 #define ADD_OPTION(opt, name) \
  413         if (sp->f_flags & (opt)) sbuf_printf(sb, "," name);
  414                 ADD_OPTION(MNT_SYNCHRONOUS,     "sync");
  415                 ADD_OPTION(MNT_NOEXEC,          "noexec");
  416                 ADD_OPTION(MNT_NOSUID,          "nosuid");
  417                 ADD_OPTION(MNT_UNION,           "union");
  418                 ADD_OPTION(MNT_ASYNC,           "async");
  419                 ADD_OPTION(MNT_SUIDDIR,         "suiddir");
  420                 ADD_OPTION(MNT_NOSYMFOLLOW,     "nosymfollow");
  421                 ADD_OPTION(MNT_NOATIME,         "noatime");
  422 #undef ADD_OPTION
  423                 /* a real Linux mtab will also show NFS options */
  424                 sbuf_printf(sb, " 0 0\n");
  425         }
  426 
  427         free(buf, M_TEMP);
  428         free(flep, M_TEMP);
  429         return (error);
  430 }
  431 
  432 /*
  433  * Filler function for proc/partitions
  434  */
  435 static int
  436 linprocfs_dopartitions(PFS_FILL_ARGS)
  437 {
  438         struct g_class *cp;
  439         struct g_geom *gp;
  440         struct g_provider *pp;
  441         int major, minor;
  442 
  443         g_topology_lock();
  444         sbuf_printf(sb, "major minor  #blocks  name rio rmerge rsect "
  445             "ruse wio wmerge wsect wuse running use aveq\n");
  446 
  447         LIST_FOREACH(cp, &g_classes, class) {
  448                 if (strcmp(cp->name, "DISK") == 0 ||
  449                     strcmp(cp->name, "PART") == 0)
  450                         LIST_FOREACH(gp, &cp->geom, geom) {
  451                                 LIST_FOREACH(pp, &gp->provider, provider) {
  452                                         if (linux_driver_get_major_minor(
  453                                             pp->name, &major, &minor) != 0) {
  454                                                 major = 0;
  455                                                 minor = 0;
  456                                         }
  457                                         sbuf_printf(sb, "%d %d %lld %s "
  458                                             "%d %d %d %d %d "
  459                                              "%d %d %d %d %d %d\n",
  460                                              major, minor,
  461                                              (long long)pp->mediasize, pp->name,
  462                                              0, 0, 0, 0, 0,
  463                                              0, 0, 0, 0, 0, 0);
  464                                 }
  465                         }
  466         }
  467         g_topology_unlock();
  468 
  469         return (0);
  470 }
  471 
  472 /*
  473  * Filler function for proc/stat
  474  *
  475  * Output depends on kernel version:
  476  *
  477  * v2.5.40 <=
  478  *   user nice system idle
  479  * v2.5.41
  480  *   user nice system idle iowait
  481  * v2.6.11
  482  *   user nice system idle iowait irq softirq steal
  483  * v2.6.24
  484  *   user nice system idle iowait irq softirq steal guest
  485  * v2.6.33 >=
  486  *   user nice system idle iowait irq softirq steal guest guest_nice
  487  */
  488 static int
  489 linprocfs_dostat(PFS_FILL_ARGS)
  490 {
  491         struct pcpu *pcpu;
  492         long cp_time[CPUSTATES];
  493         long *cp;
  494         struct timeval boottime;
  495         int i;
  496         char *zero_pad;
  497         bool has_intr = true;
  498 
  499         if (linux_kernver(td) >= LINUX_KERNVER(2,6,33)) {
  500                 zero_pad = " 0 0 0 0\n";
  501         } else if (linux_kernver(td) >= LINUX_KERNVER(2,6,24)) {
  502                 zero_pad = " 0 0 0\n";
  503         } else if (linux_kernver(td) >= LINUX_KERNVER(2,6,11)) {
  504                 zero_pad = " 0 0\n";
  505         } else if (linux_kernver(td) >= LINUX_KERNVER(2,5,41)) {
  506                 has_intr = false;
  507                 zero_pad = " 0\n";
  508         } else {
  509                 has_intr = false;
  510                 zero_pad = "\n";
  511         }
  512 
  513         read_cpu_time(cp_time);
  514         getboottime(&boottime);
  515         /* Parameters common to all versions */
  516         sbuf_printf(sb, "cpu %lu %lu %lu %lu",
  517             T2J(cp_time[CP_USER]),
  518             T2J(cp_time[CP_NICE]),
  519             T2J(cp_time[CP_SYS]),
  520             T2J(cp_time[CP_IDLE]));
  521 
  522         /* Print interrupt stats if available */
  523         if (has_intr) {
  524                 sbuf_printf(sb, " 0 %lu", T2J(cp_time[CP_INTR]));
  525         }
  526 
  527         /* Pad out remaining fields depending on version */
  528         sbuf_printf(sb, "%s", zero_pad);
  529 
  530         CPU_FOREACH(i) {
  531                 pcpu = pcpu_find(i);
  532                 cp = pcpu->pc_cp_time;
  533                 sbuf_printf(sb, "cpu%d %lu %lu %lu %lu", i,
  534                     T2J(cp[CP_USER]),
  535                     T2J(cp[CP_NICE]),
  536                     T2J(cp[CP_SYS]),
  537                     T2J(cp[CP_IDLE]));
  538 
  539                 if (has_intr) {
  540                         sbuf_printf(sb, " 0 %lu", T2J(cp[CP_INTR]));
  541                 }
  542 
  543                 sbuf_printf(sb, "%s", zero_pad);
  544         }
  545         sbuf_printf(sb,
  546             "disk 0 0 0 0\n"
  547             "page %ju %ju\n"
  548             "swap %ju %ju\n"
  549             "intr %ju\n"
  550             "ctxt %ju\n"
  551             "btime %lld\n",
  552             (uintmax_t)VM_CNT_FETCH(v_vnodepgsin),
  553             (uintmax_t)VM_CNT_FETCH(v_vnodepgsout),
  554             (uintmax_t)VM_CNT_FETCH(v_swappgsin),
  555             (uintmax_t)VM_CNT_FETCH(v_swappgsout),
  556             (uintmax_t)VM_CNT_FETCH(v_intr),
  557             (uintmax_t)VM_CNT_FETCH(v_swtch),
  558             (long long)boottime.tv_sec);
  559         return (0);
  560 }
  561 
  562 static int
  563 linprocfs_doswaps(PFS_FILL_ARGS)
  564 {
  565         struct xswdev xsw;
  566         uintmax_t total, used;
  567         int n;
  568         char devname[SPECNAMELEN + 1];
  569 
  570         sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
  571         for (n = 0; ; n++) {
  572                 if (swap_dev_info(n, &xsw, devname, sizeof(devname)) != 0)
  573                         break;
  574                 total = (uintmax_t)xsw.xsw_nblks * PAGE_SIZE / 1024;
  575                 used  = (uintmax_t)xsw.xsw_used * PAGE_SIZE / 1024;
  576 
  577                 /*
  578                  * The space and not tab after the device name is on
  579                  * purpose.  Linux does so.
  580                  */
  581                 sbuf_printf(sb, "/dev/%-34s unknown\t\t%jd\t%jd\t-1\n",
  582                     devname, total, used);
  583         }
  584         return (0);
  585 }
  586 
  587 /*
  588  * Filler function for proc/uptime
  589  */
  590 static int
  591 linprocfs_douptime(PFS_FILL_ARGS)
  592 {
  593         long cp_time[CPUSTATES];
  594         struct timeval tv;
  595 
  596         getmicrouptime(&tv);
  597         read_cpu_time(cp_time);
  598         sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n",
  599             (long long)tv.tv_sec, tv.tv_usec / 10000,
  600             T2S(cp_time[CP_IDLE] / mp_ncpus),
  601             T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100);
  602         return (0);
  603 }
  604 
  605 /*
  606  * Get OS build date
  607  */
  608 static void
  609 linprocfs_osbuild(struct thread *td, struct sbuf *sb)
  610 {
  611 #if 0
  612         char osbuild[256];
  613         char *cp1, *cp2;
  614 
  615         strncpy(osbuild, version, 256);
  616         osbuild[255] = '\0';
  617         cp1 = strstr(osbuild, "\n");
  618         cp2 = strstr(osbuild, ":");
  619         if (cp1 && cp2) {
  620                 *cp1 = *cp2 = '\0';
  621                 cp1 = strstr(osbuild, "#");
  622         } else
  623                 cp1 = NULL;
  624         if (cp1)
  625                 sbuf_printf(sb, "%s%s", cp1, cp2 + 1);
  626         else
  627 #endif
  628                 sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977");
  629 }
  630 
  631 /*
  632  * Get OS builder
  633  */
  634 static void
  635 linprocfs_osbuilder(struct thread *td, struct sbuf *sb)
  636 {
  637 #if 0
  638         char builder[256];
  639         char *cp;
  640 
  641         cp = strstr(version, "\n    ");
  642         if (cp) {
  643                 strncpy(builder, cp + 5, 256);
  644                 builder[255] = '\0';
  645                 cp = strstr(builder, ":");
  646                 if (cp)
  647                         *cp = '\0';
  648         }
  649         if (cp)
  650                 sbuf_cat(sb, builder);
  651         else
  652 #endif
  653                 sbuf_cat(sb, "des@freebsd.org");
  654 }
  655 
  656 /*
  657  * Filler function for proc/version
  658  */
  659 static int
  660 linprocfs_doversion(PFS_FILL_ARGS)
  661 {
  662         char osname[LINUX_MAX_UTSNAME];
  663         char osrelease[LINUX_MAX_UTSNAME];
  664 
  665         linux_get_osname(td, osname);
  666         linux_get_osrelease(td, osrelease);
  667         sbuf_printf(sb, "%s version %s (", osname, osrelease);
  668         linprocfs_osbuilder(td, sb);
  669         sbuf_cat(sb, ") (gcc version " __VERSION__ ") ");
  670         linprocfs_osbuild(td, sb);
  671         sbuf_cat(sb, "\n");
  672 
  673         return (0);
  674 }
  675 
  676 /*
  677  * Filler function for proc/loadavg
  678  */
  679 static int
  680 linprocfs_doloadavg(PFS_FILL_ARGS)
  681 {
  682 
  683         sbuf_printf(sb,
  684             "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
  685             (int)(averunnable.ldavg[0] / averunnable.fscale),
  686             (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
  687             (int)(averunnable.ldavg[1] / averunnable.fscale),
  688             (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
  689             (int)(averunnable.ldavg[2] / averunnable.fscale),
  690             (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
  691             1,                          /* number of running tasks */
  692             nprocs,                     /* number of tasks */
  693             lastpid                     /* the last pid */
  694         );
  695         return (0);
  696 }
  697 
  698 /*
  699  * Filler function for proc/pid/stat
  700  */
  701 static int
  702 linprocfs_doprocstat(PFS_FILL_ARGS)
  703 {
  704         struct kinfo_proc kp;
  705         struct timeval boottime;
  706         char state;
  707         static int ratelimit = 0;
  708         vm_offset_t startcode, startdata;
  709 
  710         getboottime(&boottime);
  711         sx_slock(&proctree_lock);
  712         PROC_LOCK(p);
  713         fill_kinfo_proc(p, &kp);
  714         sx_sunlock(&proctree_lock);
  715         if (p->p_vmspace) {
  716            startcode = (vm_offset_t)p->p_vmspace->vm_taddr;
  717            startdata = (vm_offset_t)p->p_vmspace->vm_daddr;
  718         } else {
  719            startcode = 0;
  720            startdata = 0;
  721         }
  722         sbuf_printf(sb, "%d", p->p_pid);
  723 #define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
  724         PS_ADD("comm",          "(%s)", p->p_comm);
  725         if (kp.ki_stat > sizeof(linux_state)) {
  726                 state = 'R';
  727 
  728                 if (ratelimit == 0) {
  729                         printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n",
  730                             kp.ki_stat, sizeof(linux_state));
  731                         ++ratelimit;
  732                 }
  733         } else
  734                 state = linux_state[kp.ki_stat - 1];
  735         PS_ADD("state",         "%c",   state);
  736         PS_ADD("ppid",          "%d",   p->p_pptr ? p->p_pptr->p_pid : 0);
  737         PS_ADD("pgrp",          "%d",   p->p_pgid);
  738         PS_ADD("session",       "%d",   p->p_session->s_sid);
  739         PROC_UNLOCK(p);
  740         PS_ADD("tty",           "%ju",  (uintmax_t)kp.ki_tdev);
  741         PS_ADD("tpgid",         "%d",   kp.ki_tpgid);
  742         PS_ADD("flags",         "%u",   0); /* XXX */
  743         PS_ADD("minflt",        "%lu",  kp.ki_rusage.ru_minflt);
  744         PS_ADD("cminflt",       "%lu",  kp.ki_rusage_ch.ru_minflt);
  745         PS_ADD("majflt",        "%lu",  kp.ki_rusage.ru_majflt);
  746         PS_ADD("cmajflt",       "%lu",  kp.ki_rusage_ch.ru_majflt);
  747         PS_ADD("utime",         "%ld",  TV2J(&kp.ki_rusage.ru_utime));
  748         PS_ADD("stime",         "%ld",  TV2J(&kp.ki_rusage.ru_stime));
  749         PS_ADD("cutime",        "%ld",  TV2J(&kp.ki_rusage_ch.ru_utime));
  750         PS_ADD("cstime",        "%ld",  TV2J(&kp.ki_rusage_ch.ru_stime));
  751         PS_ADD("priority",      "%d",   kp.ki_pri.pri_user);
  752         PS_ADD("nice",          "%d",   kp.ki_nice); /* 19 (nicest) to -19 */
  753         PS_ADD("",             "%d",   0); /* removed field */
  754         PS_ADD("itrealvalue",   "%d",   0); /* XXX */
  755         PS_ADD("starttime",     "%lu",  TV2J(&kp.ki_start) - TV2J(&boottime));
  756         PS_ADD("vsize",         "%ju",  P2K((uintmax_t)kp.ki_size));
  757         PS_ADD("rss",           "%ju",  (uintmax_t)kp.ki_rssize);
  758         PS_ADD("rlim",          "%lu",  kp.ki_rusage.ru_maxrss);
  759         PS_ADD("startcode",     "%ju",  (uintmax_t)startcode);
  760         PS_ADD("endcode",       "%ju",  (uintmax_t)startdata);
  761         PS_ADD("startstack",    "%u",   0); /* XXX */
  762         PS_ADD("kstkesp",       "%u",   0); /* XXX */
  763         PS_ADD("kstkeip",       "%u",   0); /* XXX */
  764         PS_ADD("signal",        "%u",   0); /* XXX */
  765         PS_ADD("blocked",       "%u",   0); /* XXX */
  766         PS_ADD("sigignore",     "%u",   0); /* XXX */
  767         PS_ADD("sigcatch",      "%u",   0); /* XXX */
  768         PS_ADD("wchan",         "%u",   0); /* XXX */
  769         PS_ADD("nswap",         "%lu",  kp.ki_rusage.ru_nswap);
  770         PS_ADD("cnswap",        "%lu",  kp.ki_rusage_ch.ru_nswap);
  771         PS_ADD("exitsignal",    "%d",   0); /* XXX */
  772         PS_ADD("processor",     "%u",   kp.ki_lastcpu);
  773         PS_ADD("rt_priority",   "%u",   0); /* XXX */ /* >= 2.5.19 */
  774         PS_ADD("policy",        "%u",   kp.ki_pri.pri_class); /* >= 2.5.19 */
  775 #undef PS_ADD
  776         sbuf_putc(sb, '\n');
  777 
  778         return (0);
  779 }
  780 
  781 /*
  782  * Filler function for proc/pid/statm
  783  */
  784 static int
  785 linprocfs_doprocstatm(PFS_FILL_ARGS)
  786 {
  787         struct kinfo_proc kp;
  788         segsz_t lsize;
  789 
  790         sx_slock(&proctree_lock);
  791         PROC_LOCK(p);
  792         fill_kinfo_proc(p, &kp);
  793         PROC_UNLOCK(p);
  794         sx_sunlock(&proctree_lock);
  795 
  796         /*
  797          * See comments in linprocfs_doprocstatus() regarding the
  798          * computation of lsize.
  799          */
  800         /* size resident share trs drs lrs dt */
  801         sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size));
  802         sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize);
  803         sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */
  804         sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize);
  805         sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize));
  806         lsize = B2P(kp.ki_size) - kp.ki_dsize -
  807             kp.ki_ssize - kp.ki_tsize - 1;
  808         sbuf_printf(sb, "%ju ", (uintmax_t)lsize);
  809         sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */
  810 
  811         return (0);
  812 }
  813 
  814 /*
  815  * Filler function for proc/pid/status
  816  */
  817 static int
  818 linprocfs_doprocstatus(PFS_FILL_ARGS)
  819 {
  820         struct kinfo_proc kp;
  821         char *state;
  822         segsz_t lsize;
  823         struct thread *td2;
  824         struct sigacts *ps;
  825         l_sigset_t siglist, sigignore, sigcatch;
  826         int i;
  827 
  828         sx_slock(&proctree_lock);
  829         PROC_LOCK(p);
  830         td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */
  831 
  832         if (P_SHOULDSTOP(p)) {
  833                 state = "T (stopped)";
  834         } else {
  835                 switch(p->p_state) {
  836                 case PRS_NEW:
  837                         state = "I (idle)";
  838                         break;
  839                 case PRS_NORMAL:
  840                         if (p->p_flag & P_WEXIT) {
  841                                 state = "X (exiting)";
  842                                 break;
  843                         }
  844                         switch(td2->td_state) {
  845                         case TDS_INHIBITED:
  846                                 state = "S (sleeping)";
  847                                 break;
  848                         case TDS_RUNQ:
  849                         case TDS_RUNNING:
  850                                 state = "R (running)";
  851                                 break;
  852                         default:
  853                                 state = "? (unknown)";
  854                                 break;
  855                         }
  856                         break;
  857                 case PRS_ZOMBIE:
  858                         state = "Z (zombie)";
  859                         break;
  860                 default:
  861                         state = "? (unknown)";
  862                         break;
  863                 }
  864         }
  865 
  866         fill_kinfo_proc(p, &kp);
  867         sx_sunlock(&proctree_lock);
  868 
  869         sbuf_printf(sb, "Name:\t%s\n",          p->p_comm); /* XXX escape */
  870         sbuf_printf(sb, "State:\t%s\n",         state);
  871 
  872         /*
  873          * Credentials
  874          */
  875         sbuf_printf(sb, "Pid:\t%d\n",           p->p_pid);
  876         sbuf_printf(sb, "PPid:\t%d\n",          kp.ki_ppid );
  877         sbuf_printf(sb, "TracerPid:\t%d\n",     kp.ki_tracer );
  878         sbuf_printf(sb, "Uid:\t%d %d %d %d\n",  p->p_ucred->cr_ruid,
  879                                                 p->p_ucred->cr_uid,
  880                                                 p->p_ucred->cr_svuid,
  881                                                 /* FreeBSD doesn't have fsuid */
  882                                                 p->p_ucred->cr_uid);
  883         sbuf_printf(sb, "Gid:\t%d %d %d %d\n",  p->p_ucred->cr_rgid,
  884                                                 p->p_ucred->cr_gid,
  885                                                 p->p_ucred->cr_svgid,
  886                                                 /* FreeBSD doesn't have fsgid */
  887                                                 p->p_ucred->cr_gid);
  888         sbuf_cat(sb, "Groups:\t");
  889         for (i = 0; i < p->p_ucred->cr_ngroups; i++)
  890                 sbuf_printf(sb, "%d ",          p->p_ucred->cr_groups[i]);
  891         PROC_UNLOCK(p);
  892         sbuf_putc(sb, '\n');
  893 
  894         /*
  895          * Memory
  896          *
  897          * While our approximation of VmLib may not be accurate (I
  898          * don't know of a simple way to verify it, and I'm not sure
  899          * it has much meaning anyway), I believe it's good enough.
  900          *
  901          * The same code that could (I think) accurately compute VmLib
  902          * could also compute VmLck, but I don't really care enough to
  903          * implement it. Submissions are welcome.
  904          */
  905         sbuf_printf(sb, "VmSize:\t%8ju kB\n",   B2K((uintmax_t)kp.ki_size));
  906         sbuf_printf(sb, "VmLck:\t%8u kB\n",     P2K(0)); /* XXX */
  907         sbuf_printf(sb, "VmRSS:\t%8ju kB\n",    P2K((uintmax_t)kp.ki_rssize));
  908         sbuf_printf(sb, "VmData:\t%8ju kB\n",   P2K((uintmax_t)kp.ki_dsize));
  909         sbuf_printf(sb, "VmStk:\t%8ju kB\n",    P2K((uintmax_t)kp.ki_ssize));
  910         sbuf_printf(sb, "VmExe:\t%8ju kB\n",    P2K((uintmax_t)kp.ki_tsize));
  911         lsize = B2P(kp.ki_size) - kp.ki_dsize -
  912             kp.ki_ssize - kp.ki_tsize - 1;
  913         sbuf_printf(sb, "VmLib:\t%8ju kB\n",    P2K((uintmax_t)lsize));
  914 
  915         /*
  916          * Signal masks
  917          */
  918         PROC_LOCK(p);
  919         bsd_to_linux_sigset(&p->p_siglist, &siglist);
  920         ps = p->p_sigacts;
  921         mtx_lock(&ps->ps_mtx);
  922         bsd_to_linux_sigset(&ps->ps_sigignore, &sigignore);
  923         bsd_to_linux_sigset(&ps->ps_sigcatch, &sigcatch);
  924         mtx_unlock(&ps->ps_mtx);
  925         PROC_UNLOCK(p);
  926 
  927         sbuf_printf(sb, "SigPnd:\t%016jx\n",    siglist.__mask);
  928         /*
  929          * XXX. SigBlk - target thread's signal mask, td_sigmask.
  930          * To implement SigBlk pseudofs should support proc/tid dir entries.
  931          */
  932         sbuf_printf(sb, "SigBlk:\t%016x\n",     0);
  933         sbuf_printf(sb, "SigIgn:\t%016jx\n",    sigignore.__mask);
  934         sbuf_printf(sb, "SigCgt:\t%016jx\n",    sigcatch.__mask);
  935 
  936         /*
  937          * Linux also prints the capability masks, but we don't have
  938          * capabilities yet, and when we do get them they're likely to
  939          * be meaningless to Linux programs, so we lie. XXX
  940          */
  941         sbuf_printf(sb, "CapInh:\t%016x\n",     0);
  942         sbuf_printf(sb, "CapPrm:\t%016x\n",     0);
  943         sbuf_printf(sb, "CapEff:\t%016x\n",     0);
  944 
  945         return (0);
  946 }
  947 
  948 
  949 /*
  950  * Filler function for proc/pid/cwd
  951  */
  952 static int
  953 linprocfs_doproccwd(PFS_FILL_ARGS)
  954 {
  955         struct filedesc *fdp;
  956         struct vnode *vp;
  957         char *fullpath = "unknown";
  958         char *freepath = NULL;
  959 
  960         fdp = p->p_fd;
  961         FILEDESC_SLOCK(fdp);
  962         vp = fdp->fd_cdir;
  963         if (vp != NULL)
  964                 VREF(vp);
  965         FILEDESC_SUNLOCK(fdp);
  966         vn_fullpath(td, vp, &fullpath, &freepath);
  967         if (vp != NULL)
  968                 vrele(vp);
  969         sbuf_printf(sb, "%s", fullpath);
  970         if (freepath)
  971                 free(freepath, M_TEMP);
  972         return (0);
  973 }
  974 
  975 /*
  976  * Filler function for proc/pid/root
  977  */
  978 static int
  979 linprocfs_doprocroot(PFS_FILL_ARGS)
  980 {
  981         struct filedesc *fdp;
  982         struct vnode *vp;
  983         char *fullpath = "unknown";
  984         char *freepath = NULL;
  985 
  986         fdp = p->p_fd;
  987         FILEDESC_SLOCK(fdp);
  988         vp = jailed(p->p_ucred) ? fdp->fd_jdir : fdp->fd_rdir;
  989         if (vp != NULL)
  990                 VREF(vp);
  991         FILEDESC_SUNLOCK(fdp);
  992         vn_fullpath(td, vp, &fullpath, &freepath);
  993         if (vp != NULL)
  994                 vrele(vp);
  995         sbuf_printf(sb, "%s", fullpath);
  996         if (freepath)
  997                 free(freepath, M_TEMP);
  998         return (0);
  999 }
 1000 
 1001 /*
 1002  * Filler function for proc/pid/cmdline
 1003  */
 1004 static int
 1005 linprocfs_doproccmdline(PFS_FILL_ARGS)
 1006 {
 1007         int ret;
 1008 
 1009         PROC_LOCK(p);
 1010         if ((ret = p_cansee(td, p)) != 0) {
 1011                 PROC_UNLOCK(p);
 1012                 return (ret);
 1013         }
 1014 
 1015         /*
 1016          * Mimic linux behavior and pass only processes with usermode
 1017          * address space as valid.  Return zero silently otherwize.
 1018          */
 1019         if (p->p_vmspace == &vmspace0) {
 1020                 PROC_UNLOCK(p);
 1021                 return (0);
 1022         }
 1023         if (p->p_args != NULL) {
 1024                 sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
 1025                 PROC_UNLOCK(p);
 1026                 return (0);
 1027         }
 1028 
 1029         if ((p->p_flag & P_SYSTEM) != 0) {
 1030                 PROC_UNLOCK(p);
 1031                 return (0);
 1032         }
 1033 
 1034         PROC_UNLOCK(p);
 1035 
 1036         ret = proc_getargv(td, p, sb);
 1037         return (ret);
 1038 }
 1039 
 1040 /*
 1041  * Filler function for proc/pid/environ
 1042  */
 1043 static int
 1044 linprocfs_doprocenviron(PFS_FILL_ARGS)
 1045 {
 1046 
 1047         /*
 1048          * Mimic linux behavior and pass only processes with usermode
 1049          * address space as valid.  Return zero silently otherwize.
 1050          */
 1051         if (p->p_vmspace == &vmspace0)
 1052                 return (0);
 1053 
 1054         return (proc_getenvv(td, p, sb));
 1055 }
 1056 
 1057 static char l32_map_str[] = "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n";
 1058 static char l64_map_str[] = "%016lx-%016lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n";
 1059 static char vdso_str[] = "      [vdso]";
 1060 static char stack_str[] = "      [stack]";
 1061 
 1062 /*
 1063  * Filler function for proc/pid/maps
 1064  */
 1065 static int
 1066 linprocfs_doprocmaps(PFS_FILL_ARGS)
 1067 {
 1068         struct vmspace *vm;
 1069         vm_map_t map;
 1070         vm_map_entry_t entry, tmp_entry;
 1071         vm_object_t obj, tobj, lobj;
 1072         vm_offset_t e_start, e_end;
 1073         vm_ooffset_t off = 0;
 1074         vm_prot_t e_prot;
 1075         unsigned int last_timestamp;
 1076         char *name = "", *freename = NULL;
 1077         const char *l_map_str;
 1078         ino_t ino;
 1079         int ref_count, shadow_count, flags;
 1080         int error;
 1081         struct vnode *vp;
 1082         struct vattr vat;
 1083 
 1084         PROC_LOCK(p);
 1085         error = p_candebug(td, p);
 1086         PROC_UNLOCK(p);
 1087         if (error)
 1088                 return (error);
 1089 
 1090         if (uio->uio_rw != UIO_READ)
 1091                 return (EOPNOTSUPP);
 1092 
 1093         error = 0;
 1094         vm = vmspace_acquire_ref(p);
 1095         if (vm == NULL)
 1096                 return (ESRCH);
 1097 
 1098         if (SV_CURPROC_FLAG(SV_LP64))
 1099                 l_map_str = l64_map_str;
 1100         else
 1101                 l_map_str = l32_map_str;
 1102         map = &vm->vm_map;
 1103         vm_map_lock_read(map);
 1104         for (entry = map->header.next; entry != &map->header;
 1105             entry = entry->next) {
 1106                 name = "";
 1107                 freename = NULL;
 1108                 if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
 1109                         continue;
 1110                 e_prot = entry->protection;
 1111                 e_start = entry->start;
 1112                 e_end = entry->end;
 1113                 obj = entry->object.vm_object;
 1114                 for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) {
 1115                         VM_OBJECT_RLOCK(tobj);
 1116                         if (lobj != obj)
 1117                                 VM_OBJECT_RUNLOCK(lobj);
 1118                         lobj = tobj;
 1119                 }
 1120                 last_timestamp = map->timestamp;
 1121                 vm_map_unlock_read(map);
 1122                 ino = 0;
 1123                 if (lobj) {
 1124                         off = IDX_TO_OFF(lobj->size);
 1125                         vp = vm_object_vnode(lobj);
 1126                         if (vp != NULL)
 1127                                 vref(vp);
 1128                         if (lobj != obj)
 1129                                 VM_OBJECT_RUNLOCK(lobj);
 1130                         flags = obj->flags;
 1131                         ref_count = obj->ref_count;
 1132                         shadow_count = obj->shadow_count;
 1133                         VM_OBJECT_RUNLOCK(obj);
 1134                         if (vp != NULL) {
 1135                                 vn_fullpath(td, vp, &name, &freename);
 1136                                 vn_lock(vp, LK_SHARED | LK_RETRY);
 1137                                 VOP_GETATTR(vp, &vat, td->td_ucred);
 1138                                 ino = vat.va_fileid;
 1139                                 vput(vp);
 1140                         } else if (SV_PROC_ABI(p) == SV_ABI_LINUX) {
 1141                                 if (e_start == p->p_sysent->sv_shared_page_base)
 1142                                         name = vdso_str;
 1143                                 if (e_end == p->p_sysent->sv_usrstack)
 1144                                         name = stack_str;
 1145                         }
 1146                 } else {
 1147                         flags = 0;
 1148                         ref_count = 0;
 1149                         shadow_count = 0;
 1150                 }
 1151 
 1152                 /*
 1153                  * format:
 1154                  *  start, end, access, offset, major, minor, inode, name.
 1155                  */
 1156                 error = sbuf_printf(sb, l_map_str,
 1157                     (u_long)e_start, (u_long)e_end,
 1158                     (e_prot & VM_PROT_READ)?"r":"-",
 1159                     (e_prot & VM_PROT_WRITE)?"w":"-",
 1160                     (e_prot & VM_PROT_EXECUTE)?"x":"-",
 1161                     "p",
 1162                     (u_long)off,
 1163                     0,
 1164                     0,
 1165                     (u_long)ino,
 1166                     *name ? "     " : "",
 1167                     name
 1168                     );
 1169                 if (freename)
 1170                         free(freename, M_TEMP);
 1171                 vm_map_lock_read(map);
 1172                 if (error == -1) {
 1173                         error = 0;
 1174                         break;
 1175                 }
 1176                 if (last_timestamp != map->timestamp) {
 1177                         /*
 1178                          * Look again for the entry because the map was
 1179                          * modified while it was unlocked.  Specifically,
 1180                          * the entry may have been clipped, merged, or deleted.
 1181                          */
 1182                         vm_map_lookup_entry(map, e_end - 1, &tmp_entry);
 1183                         entry = tmp_entry;
 1184                 }
 1185         }
 1186         vm_map_unlock_read(map);
 1187         vmspace_free(vm);
 1188 
 1189         return (error);
 1190 }
 1191 
 1192 /*
 1193  * Criteria for interface name translation
 1194  */
 1195 #define IFP_IS_ETH(ifp) (ifp->if_type == IFT_ETHER)
 1196 
 1197 static int
 1198 linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen)
 1199 {
 1200         struct ifnet *ifscan;
 1201         int ethno;
 1202 
 1203         IFNET_RLOCK_ASSERT();
 1204 
 1205         /* Short-circuit non ethernet interfaces */
 1206         if (!IFP_IS_ETH(ifp))
 1207                 return (strlcpy(buffer, ifp->if_xname, buflen));
 1208 
 1209         /* Determine the (relative) unit number for ethernet interfaces */
 1210         ethno = 0;
 1211         CK_STAILQ_FOREACH(ifscan, &V_ifnet, if_link) {
 1212                 if (ifscan == ifp)
 1213                         return (snprintf(buffer, buflen, "eth%d", ethno));
 1214                 if (IFP_IS_ETH(ifscan))
 1215                         ethno++;
 1216         }
 1217 
 1218         return (0);
 1219 }
 1220 
 1221 /*
 1222  * Filler function for proc/net/dev
 1223  */
 1224 static int
 1225 linprocfs_donetdev(PFS_FILL_ARGS)
 1226 {
 1227         char ifname[16]; /* XXX LINUX_IFNAMSIZ */
 1228         struct ifnet *ifp;
 1229 
 1230         sbuf_printf(sb, "%6s|%58s|%s\n"
 1231             "%6s|%58s|%58s\n",
 1232             "Inter-", "   Receive", "  Transmit",
 1233             " face",
 1234             "bytes    packets errs drop fifo frame compressed multicast",
 1235             "bytes    packets errs drop fifo colls carrier compressed");
 1236 
 1237         CURVNET_SET(TD_TO_VNET(curthread));
 1238         IFNET_RLOCK();
 1239         CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 1240                 linux_ifname(ifp, ifname, sizeof ifname);
 1241                 sbuf_printf(sb, "%6.6s: ", ifname);
 1242                 sbuf_printf(sb, "%7ju %7ju %4ju %4ju %4lu %5lu %10lu %9ju ",
 1243                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IBYTES),
 1244                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IPACKETS),
 1245                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IERRORS),
 1246                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IQDROPS),
 1247                                                         /* rx_missed_errors */
 1248                     0UL,                                /* rx_fifo_errors */
 1249                     0UL,                                /* rx_length_errors +
 1250                                                          * rx_over_errors +
 1251                                                          * rx_crc_errors +
 1252                                                          * rx_frame_errors */
 1253                     0UL,                                /* rx_compressed */
 1254                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IMCASTS));
 1255                                                         /* XXX-BZ rx only? */
 1256                 sbuf_printf(sb, "%8ju %7ju %4ju %4ju %4lu %5ju %7lu %10lu\n",
 1257                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OBYTES),
 1258                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OPACKETS),
 1259                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OERRORS),
 1260                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OQDROPS),
 1261                     0UL,                                /* tx_fifo_errors */
 1262                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_COLLISIONS),
 1263                     0UL,                                /* tx_carrier_errors +
 1264                                                          * tx_aborted_errors +
 1265                                                          * tx_window_errors +
 1266                                                          * tx_heartbeat_errors*/
 1267                     0UL);                               /* tx_compressed */
 1268         }
 1269         IFNET_RUNLOCK();
 1270         CURVNET_RESTORE();
 1271 
 1272         return (0);
 1273 }
 1274 
 1275 /*
 1276  * Filler function for proc/sys/kernel/osrelease
 1277  */
 1278 static int
 1279 linprocfs_doosrelease(PFS_FILL_ARGS)
 1280 {
 1281         char osrelease[LINUX_MAX_UTSNAME];
 1282 
 1283         linux_get_osrelease(td, osrelease);
 1284         sbuf_printf(sb, "%s\n", osrelease);
 1285 
 1286         return (0);
 1287 }
 1288 
 1289 /*
 1290  * Filler function for proc/sys/kernel/ostype
 1291  */
 1292 static int
 1293 linprocfs_doostype(PFS_FILL_ARGS)
 1294 {
 1295         char osname[LINUX_MAX_UTSNAME];
 1296 
 1297         linux_get_osname(td, osname);
 1298         sbuf_printf(sb, "%s\n", osname);
 1299 
 1300         return (0);
 1301 }
 1302 
 1303 /*
 1304  * Filler function for proc/sys/kernel/version
 1305  */
 1306 static int
 1307 linprocfs_doosbuild(PFS_FILL_ARGS)
 1308 {
 1309 
 1310         linprocfs_osbuild(td, sb);
 1311         sbuf_cat(sb, "\n");
 1312         return (0);
 1313 }
 1314 
 1315 /*
 1316  * Filler function for proc/sys/kernel/msgmni
 1317  */
 1318 static int
 1319 linprocfs_domsgmni(PFS_FILL_ARGS)
 1320 {
 1321 
 1322         sbuf_printf(sb, "%d\n", msginfo.msgmni);
 1323         return (0);
 1324 }
 1325 
 1326 /*
 1327  * Filler function for proc/sys/kernel/pid_max
 1328  */
 1329 static int
 1330 linprocfs_dopid_max(PFS_FILL_ARGS)
 1331 {
 1332 
 1333         sbuf_printf(sb, "%i\n", PID_MAX);
 1334         return (0);
 1335 }
 1336 
 1337 /*
 1338  * Filler function for proc/sys/kernel/sem
 1339  */
 1340 static int
 1341 linprocfs_dosem(PFS_FILL_ARGS)
 1342 {
 1343 
 1344         sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns,
 1345             seminfo.semopm, seminfo.semmni);
 1346         return (0);
 1347 }
 1348 
 1349 /*
 1350  * Filler function for proc/sys/vm/min_free_kbytes
 1351  *
 1352  * This mirrors the approach in illumos to return zero for reads. Effectively,
 1353  * it says, no memory is kept in reserve for "atomic allocations". This class
 1354  * of allocation can be used at times when a thread cannot be suspended.
 1355  */
 1356 static int
 1357 linprocfs_dominfree(PFS_FILL_ARGS)
 1358 {
 1359 
 1360         sbuf_printf(sb, "%d\n", 0);
 1361         return (0);
 1362 }
 1363 
 1364 /*
 1365  * Filler function for proc/scsi/device_info
 1366  */
 1367 static int
 1368 linprocfs_doscsidevinfo(PFS_FILL_ARGS)
 1369 {
 1370 
 1371         return (0);
 1372 }
 1373 
 1374 /*
 1375  * Filler function for proc/scsi/scsi
 1376  */
 1377 static int
 1378 linprocfs_doscsiscsi(PFS_FILL_ARGS)
 1379 {
 1380 
 1381         return (0);
 1382 }
 1383 
 1384 /*
 1385  * Filler function for proc/devices
 1386  */
 1387 static int
 1388 linprocfs_dodevices(PFS_FILL_ARGS)
 1389 {
 1390         char *char_devices;
 1391         sbuf_printf(sb, "Character devices:\n");
 1392 
 1393         char_devices = linux_get_char_devices();
 1394         sbuf_printf(sb, "%s", char_devices);
 1395         linux_free_get_char_devices(char_devices);
 1396 
 1397         sbuf_printf(sb, "\nBlock devices:\n");
 1398 
 1399         return (0);
 1400 }
 1401 
 1402 /*
 1403  * Filler function for proc/cmdline
 1404  */
 1405 static int
 1406 linprocfs_docmdline(PFS_FILL_ARGS)
 1407 {
 1408 
 1409         sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
 1410         sbuf_printf(sb, " ro root=302\n");
 1411         return (0);
 1412 }
 1413 
 1414 /*
 1415  * Filler function for proc/filesystems
 1416  */
 1417 static int
 1418 linprocfs_dofilesystems(PFS_FILL_ARGS)
 1419 {
 1420         struct vfsconf *vfsp;
 1421 
 1422         vfsconf_slock();
 1423         TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
 1424                 if (vfsp->vfc_flags & VFCF_SYNTHETIC)
 1425                         sbuf_printf(sb, "nodev");
 1426                 sbuf_printf(sb, "\t%s\n", vfsp->vfc_name);
 1427         }
 1428         vfsconf_sunlock();
 1429         return(0);
 1430 }
 1431 
 1432 #if 0
 1433 /*
 1434  * Filler function for proc/modules
 1435  */
 1436 static int
 1437 linprocfs_domodules(PFS_FILL_ARGS)
 1438 {
 1439         struct linker_file *lf;
 1440 
 1441         TAILQ_FOREACH(lf, &linker_files, link) {
 1442                 sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
 1443                     (unsigned long)lf->size, lf->refs);
 1444         }
 1445         return (0);
 1446 }
 1447 #endif
 1448 
 1449 /*
 1450  * Filler function for proc/pid/fd
 1451  */
 1452 static int
 1453 linprocfs_dofdescfs(PFS_FILL_ARGS)
 1454 {
 1455 
 1456         if (p == curproc)
 1457                 sbuf_printf(sb, "/dev/fd");
 1458         else
 1459                 sbuf_printf(sb, "unknown");
 1460         return (0);
 1461 }
 1462 
 1463 /*
 1464  * Filler function for proc/pid/limits
 1465  */
 1466 static const struct linux_rlimit_ident {
 1467         const char      *desc;
 1468         const char      *unit;
 1469         unsigned int    rlim_id;
 1470 } linux_rlimits_ident[] = {
 1471         { "Max cpu time",       "seconds",      RLIMIT_CPU },
 1472         { "Max file size",      "bytes",        RLIMIT_FSIZE },
 1473         { "Max data size",      "bytes",        RLIMIT_DATA },
 1474         { "Max stack size",     "bytes",        RLIMIT_STACK },
 1475         { "Max core file size",  "bytes",       RLIMIT_CORE },
 1476         { "Max resident set",   "bytes",        RLIMIT_RSS },
 1477         { "Max processes",      "processes",    RLIMIT_NPROC },
 1478         { "Max open files",     "files",        RLIMIT_NOFILE },
 1479         { "Max locked memory",  "bytes",        RLIMIT_MEMLOCK },
 1480         { "Max address space",  "bytes",        RLIMIT_AS },
 1481         { "Max file locks",     "locks",        LINUX_RLIMIT_LOCKS },
 1482         { "Max pending signals", "signals",     LINUX_RLIMIT_SIGPENDING },
 1483         { "Max msgqueue size",  "bytes",        LINUX_RLIMIT_MSGQUEUE },
 1484         { "Max nice priority",          "",     LINUX_RLIMIT_NICE },
 1485         { "Max realtime priority",      "",     LINUX_RLIMIT_RTPRIO },
 1486         { "Max realtime timeout",       "us",   LINUX_RLIMIT_RTTIME },
 1487         { 0, 0, 0 }
 1488 };
 1489 
 1490 static int
 1491 linprocfs_doproclimits(PFS_FILL_ARGS)
 1492 {
 1493         const struct linux_rlimit_ident *li;
 1494         struct plimit *limp;
 1495         struct rlimit rl;
 1496         ssize_t size;
 1497         int res, error;
 1498 
 1499         error = 0;
 1500 
 1501         PROC_LOCK(p);
 1502         limp = lim_hold(p->p_limit);
 1503         PROC_UNLOCK(p);
 1504         size = sizeof(res);
 1505         sbuf_printf(sb, "%-26s%-21s%-21s%-21s\n", "Limit", "Soft Limit",
 1506                         "Hard Limit", "Units");
 1507         for (li = linux_rlimits_ident; li->desc != NULL; ++li) {
 1508                 switch (li->rlim_id)
 1509                 {
 1510                 case LINUX_RLIMIT_LOCKS:
 1511                         /* FALLTHROUGH */
 1512                 case LINUX_RLIMIT_RTTIME:
 1513                         rl.rlim_cur = RLIM_INFINITY;
 1514                         break;
 1515                 case LINUX_RLIMIT_SIGPENDING:
 1516                         error = kernel_sysctlbyname(td,
 1517                             "kern.sigqueue.max_pending_per_proc",
 1518                             &res, &size, 0, 0, 0, 0);
 1519                         if (error != 0)
 1520                                 goto out;
 1521                         rl.rlim_cur = res;
 1522                         rl.rlim_max = res;
 1523                         break;
 1524                 case LINUX_RLIMIT_MSGQUEUE:
 1525                         error = kernel_sysctlbyname(td,
 1526                             "kern.ipc.msgmnb", &res, &size, 0, 0, 0, 0);
 1527                         if (error != 0)
 1528                                 goto out;
 1529                         rl.rlim_cur = res;
 1530                         rl.rlim_max = res;
 1531                         break;
 1532                 case LINUX_RLIMIT_NICE:
 1533                         /* FALLTHROUGH */
 1534                 case LINUX_RLIMIT_RTPRIO:
 1535                         rl.rlim_cur = 0;
 1536                         rl.rlim_max = 0;
 1537                         break;
 1538                 default:
 1539                         rl = limp->pl_rlimit[li->rlim_id];
 1540                         break;
 1541                 }
 1542                 if (rl.rlim_cur == RLIM_INFINITY)
 1543                         sbuf_printf(sb, "%-26s%-21s%-21s%-10s\n",
 1544                             li->desc, "unlimited", "unlimited", li->unit);
 1545                 else
 1546                         sbuf_printf(sb, "%-26s%-21llu%-21llu%-10s\n",
 1547                             li->desc, (unsigned long long)rl.rlim_cur,
 1548                             (unsigned long long)rl.rlim_max, li->unit);
 1549         }
 1550 out:
 1551         lim_free(limp);
 1552         return (error);
 1553 }
 1554 
 1555 /*
 1556  * Filler function for proc/sys/kernel/random/uuid
 1557  */
 1558 static int
 1559 linprocfs_douuid(PFS_FILL_ARGS)
 1560 {
 1561         struct uuid uuid;
 1562 
 1563         kern_uuidgen(&uuid, 1);
 1564         sbuf_printf_uuid(sb, &uuid);
 1565         sbuf_printf(sb, "\n");
 1566         return(0);
 1567 }
 1568 
 1569 /*
 1570  * Filler function for proc/pid/auxv
 1571  */
 1572 static int
 1573 linprocfs_doauxv(PFS_FILL_ARGS)
 1574 {
 1575         struct sbuf *asb;
 1576         off_t buflen, resid;
 1577         int error;
 1578 
 1579         /*
 1580          * Mimic linux behavior and pass only processes with usermode
 1581          * address space as valid. Return zero silently otherwise.
 1582          */
 1583         if (p->p_vmspace == &vmspace0)
 1584                 return (0);
 1585 
 1586         if (uio->uio_resid == 0)
 1587                 return (0);
 1588         if (uio->uio_offset < 0 || uio->uio_resid < 0)
 1589                 return (EINVAL);
 1590 
 1591         asb = sbuf_new_auto();
 1592         if (asb == NULL)
 1593                 return (ENOMEM);
 1594         error = proc_getauxv(td, p, asb);
 1595         if (error == 0)
 1596                 error = sbuf_finish(asb);
 1597 
 1598         resid = sbuf_len(asb) - uio->uio_offset;
 1599         if (resid > uio->uio_resid)
 1600                 buflen = uio->uio_resid;
 1601         else
 1602                 buflen = resid;
 1603         if (buflen > IOSIZE_MAX)
 1604                 return (EINVAL);
 1605         if (buflen > MAXPHYS)
 1606                 buflen = MAXPHYS;
 1607         if (resid <= 0)
 1608                 return (0);
 1609 
 1610         if (error == 0)
 1611                 error = uiomove(sbuf_data(asb) + uio->uio_offset, buflen, uio);
 1612         sbuf_delete(asb);
 1613         return (error);
 1614 }
 1615 
 1616 /*
 1617  * Constructor
 1618  */
 1619 static int
 1620 linprocfs_init(PFS_INIT_ARGS)
 1621 {
 1622         struct pfs_node *root;
 1623         struct pfs_node *dir;
 1624         struct pfs_node *sys;
 1625 
 1626         root = pi->pi_root;
 1627 
 1628         /* /proc/... */
 1629         pfs_create_file(root, "cmdline", &linprocfs_docmdline,
 1630             NULL, NULL, NULL, PFS_RD);
 1631         pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
 1632             NULL, NULL, NULL, PFS_RD);
 1633         pfs_create_file(root, "devices", &linprocfs_dodevices,
 1634             NULL, NULL, NULL, PFS_RD);
 1635         pfs_create_file(root, "filesystems", &linprocfs_dofilesystems,
 1636             NULL, NULL, NULL, PFS_RD);
 1637         pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
 1638             NULL, NULL, NULL, PFS_RD);
 1639         pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
 1640             NULL, NULL, NULL, PFS_RD);
 1641 #if 0
 1642         pfs_create_file(root, "modules", &linprocfs_domodules,
 1643             NULL, NULL, NULL, PFS_RD);
 1644 #endif
 1645         pfs_create_file(root, "mounts", &linprocfs_domtab,
 1646             NULL, NULL, NULL, PFS_RD);
 1647         pfs_create_file(root, "mtab", &linprocfs_domtab,
 1648             NULL, NULL, NULL, PFS_RD);
 1649         pfs_create_file(root, "partitions", &linprocfs_dopartitions,
 1650             NULL, NULL, NULL, PFS_RD);
 1651         pfs_create_link(root, "self", &procfs_docurproc,
 1652             NULL, NULL, NULL, 0);
 1653         pfs_create_file(root, "stat", &linprocfs_dostat,
 1654             NULL, NULL, NULL, PFS_RD);
 1655         pfs_create_file(root, "swaps", &linprocfs_doswaps,
 1656             NULL, NULL, NULL, PFS_RD);
 1657         pfs_create_file(root, "uptime", &linprocfs_douptime,
 1658             NULL, NULL, NULL, PFS_RD);
 1659         pfs_create_file(root, "version", &linprocfs_doversion,
 1660             NULL, NULL, NULL, PFS_RD);
 1661 
 1662         /* /proc/net/... */
 1663         dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
 1664         pfs_create_file(dir, "dev", &linprocfs_donetdev,
 1665             NULL, NULL, NULL, PFS_RD);
 1666 
 1667         /* /proc/<pid>/... */
 1668         dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
 1669         pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
 1670             NULL, NULL, NULL, PFS_RD);
 1671         pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
 1672             NULL, NULL, NULL, 0);
 1673         pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
 1674             NULL, &procfs_candebug, NULL, PFS_RD);
 1675         pfs_create_link(dir, "exe", &procfs_doprocfile,
 1676             NULL, &procfs_notsystem, NULL, 0);
 1677         pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
 1678             NULL, NULL, NULL, PFS_RD);
 1679         pfs_create_file(dir, "mem", &procfs_doprocmem,
 1680             procfs_attr_rw, &procfs_candebug, NULL, PFS_RDWR | PFS_RAW);
 1681         pfs_create_file(dir, "mounts", &linprocfs_domtab,
 1682             NULL, NULL, NULL, PFS_RD);
 1683         pfs_create_link(dir, "root", &linprocfs_doprocroot,
 1684             NULL, NULL, NULL, 0);
 1685         pfs_create_file(dir, "stat", &linprocfs_doprocstat,
 1686             NULL, NULL, NULL, PFS_RD);
 1687         pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
 1688             NULL, NULL, NULL, PFS_RD);
 1689         pfs_create_file(dir, "status", &linprocfs_doprocstatus,
 1690             NULL, NULL, NULL, PFS_RD);
 1691         pfs_create_link(dir, "fd", &linprocfs_dofdescfs,
 1692             NULL, NULL, NULL, 0);
 1693         pfs_create_file(dir, "auxv", &linprocfs_doauxv,
 1694             NULL, &procfs_candebug, NULL, PFS_RD|PFS_RAWRD);
 1695         pfs_create_file(dir, "limits", &linprocfs_doproclimits,
 1696             NULL, NULL, NULL, PFS_RD);
 1697 
 1698         /* /proc/scsi/... */
 1699         dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
 1700         pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
 1701             NULL, NULL, NULL, PFS_RD);
 1702         pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
 1703             NULL, NULL, NULL, PFS_RD);
 1704 
 1705         /* /proc/sys/... */
 1706         sys = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
 1707         /* /proc/sys/kernel/... */
 1708         dir = pfs_create_dir(sys, "kernel", NULL, NULL, NULL, 0);
 1709         pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
 1710             NULL, NULL, NULL, PFS_RD);
 1711         pfs_create_file(dir, "ostype", &linprocfs_doostype,
 1712             NULL, NULL, NULL, PFS_RD);
 1713         pfs_create_file(dir, "version", &linprocfs_doosbuild,
 1714             NULL, NULL, NULL, PFS_RD);
 1715         pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
 1716             NULL, NULL, NULL, PFS_RD);
 1717         pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
 1718             NULL, NULL, NULL, PFS_RD);
 1719         pfs_create_file(dir, "sem", &linprocfs_dosem,
 1720             NULL, NULL, NULL, PFS_RD);
 1721 
 1722         /* /proc/sys/kernel/random/... */
 1723         dir = pfs_create_dir(dir, "random", NULL, NULL, NULL, 0);
 1724         pfs_create_file(dir, "uuid", &linprocfs_douuid,
 1725             NULL, NULL, NULL, PFS_RD);
 1726 
 1727         /* /proc/sys/vm/.... */
 1728         dir = pfs_create_dir(sys, "vm", NULL, NULL, NULL, 0);
 1729         pfs_create_file(dir, "min_free_kbytes", &linprocfs_dominfree,
 1730             NULL, NULL, NULL, PFS_RD);
 1731 
 1732         return (0);
 1733 }
 1734 
 1735 /*
 1736  * Destructor
 1737  */
 1738 static int
 1739 linprocfs_uninit(PFS_INIT_ARGS)
 1740 {
 1741 
 1742         /* nothing to do, pseudofs will GC */
 1743         return (0);
 1744 }
 1745 
 1746 PSEUDOFS(linprocfs, 1, VFCF_JAIL);
 1747 #if defined(__aarch64__) || defined(__amd64__)
 1748 MODULE_DEPEND(linprocfs, linux_common, 1, 1, 1);
 1749 #else
 1750 MODULE_DEPEND(linprocfs, linux, 1, 1, 1);
 1751 #endif
 1752 MODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
 1753 MODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);
 1754 MODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1);

Cache object: 890ec03ad94bdbf078887afe625c92fe


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.