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  * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav
    3  * Copyright (c) 1999 Pierre Beyssac
    4  * Copyright (c) 1993 Jan-Simon Pendry
    5  * Copyright (c) 1993
    6  *      The Regents of the University of California.  All rights reserved.
    7  *
    8  * This code is derived from software contributed to Berkeley by
    9  * Jan-Simon Pendry.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *      This product includes software developed by the University of
   22  *      California, Berkeley and its contributors.
   23  * 4. Neither the name of the University nor the names of its contributors
   24  *    may be used to endorse or promote products derived from this software
   25  *    without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   37  * SUCH DAMAGE.
   38  *
   39  *      @(#)procfs_status.c     8.4 (Berkeley) 6/15/94
   40  */
   41 
   42 #include "opt_compat.h"
   43 
   44 #include <sys/cdefs.h>
   45 __FBSDID("$FreeBSD: releng/8.0/sys/compat/linprocfs/linprocfs.c 196691 2009-08-31 09:46:09Z zec $");
   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/linker.h>
   57 #include <sys/lock.h>
   58 #include <sys/malloc.h>
   59 #include <sys/mount.h>
   60 #include <sys/msg.h>
   61 #include <sys/mutex.h>
   62 #include <sys/namei.h>
   63 #include <sys/proc.h>
   64 #include <sys/resourcevar.h>
   65 #include <sys/sbuf.h>
   66 #include <sys/sem.h>
   67 #include <sys/smp.h>
   68 #include <sys/socket.h>
   69 #include <sys/sysctl.h>
   70 #include <sys/systm.h>
   71 #include <sys/time.h>
   72 #include <sys/tty.h>
   73 #include <sys/user.h>
   74 #include <sys/vmmeter.h>
   75 #include <sys/vnode.h>
   76 #include <sys/bus.h>
   77 
   78 #include <net/if.h>
   79 #include <net/vnet.h>
   80 
   81 #include <vm/vm.h>
   82 #include <vm/vm_extern.h>
   83 #include <vm/pmap.h>
   84 #include <vm/vm_map.h>
   85 #include <vm/vm_param.h>
   86 #include <vm/vm_object.h>
   87 #include <vm/swap_pager.h>
   88 
   89 #include <machine/clock.h>
   90 
   91 #include <geom/geom.h>
   92 #include <geom/geom_int.h>
   93 
   94 #if defined(__i386__) || defined(__amd64__)
   95 #include <machine/cputypes.h>
   96 #include <machine/md_var.h>
   97 #endif /* __i386__ || __amd64__ */
   98 
   99 #ifdef COMPAT_LINUX32                           /* XXX */
  100 #include <machine/../linux32/linux.h>
  101 #else
  102 #include <machine/../linux/linux.h>
  103 #endif
  104 #include <compat/linux/linux_ioctl.h>
  105 #include <compat/linux/linux_mib.h>
  106 #include <compat/linux/linux_util.h>
  107 #include <fs/pseudofs/pseudofs.h>
  108 #include <fs/procfs/procfs.h>
  109 
  110 /*
  111  * Various conversion macros
  112  */
  113 #define T2J(x) (((x) * 100UL) / (stathz ? stathz : hz)) /* ticks to jiffies */
  114 #define T2S(x) ((x) / (stathz ? stathz : hz))           /* ticks to seconds */
  115 #define B2K(x) ((x) >> 10)                              /* bytes to kbytes */
  116 #define B2P(x) ((x) >> PAGE_SHIFT)                      /* bytes to pages */
  117 #define P2B(x) ((x) << PAGE_SHIFT)                      /* pages to bytes */
  118 #define P2K(x) ((x) << (PAGE_SHIFT - 10))               /* pages to kbytes */
  119 
  120 /**
  121  * @brief Mapping of ki_stat in struct kinfo_proc to the linux state
  122  *
  123  * The linux procfs state field displays one of the characters RSDZTW to
  124  * denote running, sleeping in an interruptible wait, waiting in an
  125  * uninterruptible disk sleep, a zombie process, process is being traced
  126  * or stopped, or process is paging respectively.
  127  *
  128  * Our struct kinfo_proc contains the variable ki_stat which contains a
  129  * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK.
  130  *
  131  * This character array is used with ki_stati-1 as an index and tries to
  132  * map our states to suitable linux states.
  133  */
  134 static char linux_state[] = "RRSTZDD";
  135 
  136 /*
  137  * Filler function for proc/meminfo
  138  */
  139 static int
  140 linprocfs_domeminfo(PFS_FILL_ARGS)
  141 {
  142         unsigned long memtotal;         /* total memory in bytes */
  143         unsigned long memused;          /* used memory in bytes */
  144         unsigned long memfree;          /* free memory in bytes */
  145         unsigned long memshared;        /* shared memory ??? */
  146         unsigned long buffers, cached;  /* buffer / cache memory ??? */
  147         unsigned long long swaptotal;   /* total swap space in bytes */
  148         unsigned long long swapused;    /* used swap space in bytes */
  149         unsigned long long swapfree;    /* free swap space in bytes */
  150         vm_object_t object;
  151         int i, j;
  152 
  153         memtotal = physmem * PAGE_SIZE;
  154         /*
  155          * The correct thing here would be:
  156          *
  157         memfree = cnt.v_free_count * PAGE_SIZE;
  158         memused = memtotal - memfree;
  159          *
  160          * but it might mislead linux binaries into thinking there
  161          * is very little memory left, so we cheat and tell them that
  162          * all memory that isn't wired down is free.
  163          */
  164         memused = cnt.v_wire_count * PAGE_SIZE;
  165         memfree = memtotal - memused;
  166         swap_pager_status(&i, &j);
  167         swaptotal = (unsigned long long)i * PAGE_SIZE;
  168         swapused = (unsigned long long)j * PAGE_SIZE;
  169         swapfree = swaptotal - swapused;
  170         memshared = 0;
  171         mtx_lock(&vm_object_list_mtx);
  172         TAILQ_FOREACH(object, &vm_object_list, object_list)
  173                 if (object->shadow_count > 1)
  174                         memshared += object->resident_page_count;
  175         mtx_unlock(&vm_object_list_mtx);
  176         memshared *= PAGE_SIZE;
  177         /*
  178          * We'd love to be able to write:
  179          *
  180         buffers = bufspace;
  181          *
  182          * but bufspace is internal to vfs_bio.c and we don't feel
  183          * like unstaticizing it just for linprocfs's sake.
  184          */
  185         buffers = 0;
  186         cached = cnt.v_cache_count * PAGE_SIZE;
  187 
  188         sbuf_printf(sb,
  189             "        total:    used:    free:  shared: buffers:  cached:\n"
  190             "Mem:  %lu %lu %lu %lu %lu %lu\n"
  191             "Swap: %llu %llu %llu\n"
  192             "MemTotal: %9lu kB\n"
  193             "MemFree:  %9lu kB\n"
  194             "MemShared:%9lu kB\n"
  195             "Buffers:  %9lu kB\n"
  196             "Cached:   %9lu kB\n"
  197             "SwapTotal:%9llu kB\n"
  198             "SwapFree: %9llu kB\n",
  199             memtotal, memused, memfree, memshared, buffers, cached,
  200             swaptotal, swapused, swapfree,
  201             B2K(memtotal), B2K(memfree),
  202             B2K(memshared), B2K(buffers), B2K(cached),
  203             B2K(swaptotal), B2K(swapfree));
  204 
  205         return (0);
  206 }
  207 
  208 #if defined(__i386__) || defined(__amd64__)
  209 /*
  210  * Filler function for proc/cpuinfo (i386 & amd64 version)
  211  */
  212 static int
  213 linprocfs_docpuinfo(PFS_FILL_ARGS)
  214 {
  215         int hw_model[2];
  216         char model[128];
  217         size_t size;
  218         int class, fqmhz, fqkhz;
  219         int i;
  220 
  221         /*
  222          * We default the flags to include all non-conflicting flags,
  223          * and the Intel versions of conflicting flags.
  224          */
  225         static char *flags[] = {
  226                 "fpu",      "vme",     "de",       "pse",      "tsc",
  227                 "msr",      "pae",     "mce",      "cx8",      "apic",
  228                 "sep",      "sep",     "mtrr",     "pge",      "mca",
  229                 "cmov",     "pat",     "pse36",    "pn",       "b19",
  230                 "b20",      "b21",     "mmxext",   "mmx",      "fxsr",
  231                 "xmm",      "sse2",    "b27",      "b28",      "b29",
  232                 "3dnowext", "3dnow"
  233         };
  234 
  235         switch (cpu_class) {
  236 #ifdef __i386__
  237         case CPUCLASS_286:
  238                 class = 2;
  239                 break;
  240         case CPUCLASS_386:
  241                 class = 3;
  242                 break;
  243         case CPUCLASS_486:
  244                 class = 4;
  245                 break;
  246         case CPUCLASS_586:
  247                 class = 5;
  248                 break;
  249         case CPUCLASS_686:
  250                 class = 6;
  251                 break;
  252         default:
  253                 class = 0;
  254                 break;
  255 #else /* __amd64__ */
  256         default:
  257                 class = 15;
  258                 break;
  259 #endif
  260         }
  261 
  262         hw_model[0] = CTL_HW;
  263         hw_model[1] = HW_MODEL;
  264         model[0] = '\0';
  265         size = sizeof(model);
  266         if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0)
  267                 strcpy(model, "unknown");
  268         for (i = 0; i < mp_ncpus; ++i) {
  269                 sbuf_printf(sb,
  270                     "processor\t: %d\n"
  271                     "vendor_id\t: %.20s\n"
  272                     "cpu family\t: %d\n"
  273                     "model\t\t: %d\n"
  274                     "model name\t: %s\n"
  275                     "stepping\t: %d\n",
  276                     i, cpu_vendor, class, cpu, model, cpu_id & 0xf);
  277                 /* XXX per-cpu vendor / class / model / id? */
  278         }
  279 
  280         sbuf_cat(sb, "flags\t\t:");
  281 
  282 #ifdef __i386__
  283         switch (cpu_vendor_id) {
  284         case CPU_VENDOR_AMD:
  285                 if (class < 6)
  286                         flags[16] = "fcmov";
  287                 break;
  288         case CPU_VENDOR_CYRIX:
  289                 flags[24] = "cxmmx";
  290                 break;
  291         }
  292 #endif
  293 
  294         for (i = 0; i < 32; i++)
  295                 if (cpu_feature & (1 << i))
  296                         sbuf_printf(sb, " %s", flags[i]);
  297         sbuf_cat(sb, "\n");
  298         if (class >= 5) {
  299                 fqmhz = (tsc_freq + 4999) / 1000000;
  300                 fqkhz = ((tsc_freq + 4999) / 10000) % 100;
  301                 sbuf_printf(sb,
  302                     "cpu MHz\t\t: %d.%02d\n"
  303                     "bogomips\t: %d.%02d\n",
  304                     fqmhz, fqkhz, fqmhz, fqkhz);
  305         }
  306 
  307         return (0);
  308 }
  309 #endif /* __i386__ || __amd64__ */
  310 
  311 /*
  312  * Filler function for proc/mtab
  313  *
  314  * This file doesn't exist in Linux' procfs, but is included here so
  315  * users can symlink /compat/linux/etc/mtab to /proc/mtab
  316  */
  317 static int
  318 linprocfs_domtab(PFS_FILL_ARGS)
  319 {
  320         struct nameidata nd;
  321         struct mount *mp;
  322         const char *lep;
  323         char *dlep, *flep, *mntto, *mntfrom, *fstype;
  324         size_t lep_len;
  325         int error;
  326 
  327         /* resolve symlinks etc. in the emulation tree prefix */
  328         NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td);
  329         flep = NULL;
  330         error = namei(&nd);
  331         lep = linux_emul_path;
  332         if (error == 0) {
  333                 if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
  334                         lep = dlep;
  335                 vrele(nd.ni_vp);
  336                 VFS_UNLOCK_GIANT(NDHASGIANT(&nd));
  337         }
  338         lep_len = strlen(lep);
  339 
  340         mtx_lock(&mountlist_mtx);
  341         error = 0;
  342         TAILQ_FOREACH(mp, &mountlist, mnt_list) {
  343                 /* determine device name */
  344                 mntfrom = mp->mnt_stat.f_mntfromname;
  345 
  346                 /* determine mount point */
  347                 mntto = mp->mnt_stat.f_mntonname;
  348                 if (strncmp(mntto, lep, lep_len) == 0 &&
  349                     mntto[lep_len] == '/')
  350                         mntto += lep_len;
  351 
  352                 /* determine fs type */
  353                 fstype = mp->mnt_stat.f_fstypename;
  354                 if (strcmp(fstype, pn->pn_info->pi_name) == 0)
  355                         mntfrom = fstype = "proc";
  356                 else if (strcmp(fstype, "procfs") == 0)
  357                         continue;
  358 
  359                 if (strcmp(fstype, "linsysfs") == 0) {
  360                         sbuf_printf(sb, "/sys %s sysfs %s", mntto,
  361                             mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
  362                 } else {
  363                         /* For Linux msdosfs is called vfat */
  364                         if (strcmp(fstype, "msdosfs") == 0)
  365                                 fstype = "vfat";
  366                         sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
  367                             mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
  368                 }
  369 #define ADD_OPTION(opt, name) \
  370         if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name);
  371                 ADD_OPTION(MNT_SYNCHRONOUS,     "sync");
  372                 ADD_OPTION(MNT_NOEXEC,          "noexec");
  373                 ADD_OPTION(MNT_NOSUID,          "nosuid");
  374                 ADD_OPTION(MNT_UNION,           "union");
  375                 ADD_OPTION(MNT_ASYNC,           "async");
  376                 ADD_OPTION(MNT_SUIDDIR,         "suiddir");
  377                 ADD_OPTION(MNT_NOSYMFOLLOW,     "nosymfollow");
  378                 ADD_OPTION(MNT_NOATIME,         "noatime");
  379 #undef ADD_OPTION
  380                 /* a real Linux mtab will also show NFS options */
  381                 sbuf_printf(sb, " 0 0\n");
  382         }
  383         mtx_unlock(&mountlist_mtx);
  384         if (flep != NULL)
  385                 free(flep, M_TEMP);
  386         return (error);
  387 }
  388 
  389 /*
  390  * Filler function for proc/partitions
  391  *
  392  */
  393 static int
  394 linprocfs_dopartitions(PFS_FILL_ARGS)
  395 {
  396         struct g_class *cp;
  397         struct g_geom *gp;
  398         struct g_provider *pp;
  399         struct nameidata nd;
  400         const char *lep;
  401         char  *dlep, *flep;
  402         size_t lep_len;
  403         int error;
  404         int major, minor;
  405 
  406         /* resolve symlinks etc. in the emulation tree prefix */
  407         NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td);
  408         flep = NULL;
  409         error = namei(&nd);
  410         lep = linux_emul_path;
  411         if (error == 0) {
  412                 if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
  413                         lep = dlep;
  414                 vrele(nd.ni_vp);
  415                 VFS_UNLOCK_GIANT(NDHASGIANT(&nd));
  416         }
  417         lep_len = strlen(lep);
  418 
  419         g_topology_lock();
  420         error = 0;
  421         sbuf_printf(sb, "major minor  #blocks  name rio rmerge rsect "
  422             "ruse wio wmerge wsect wuse running use aveq\n");
  423 
  424         LIST_FOREACH(cp, &g_classes, class) {
  425                 if (strcmp(cp->name, "DISK") == 0 ||
  426                     strcmp(cp->name, "PART") == 0)
  427                         LIST_FOREACH(gp, &cp->geom, geom) {
  428                                 LIST_FOREACH(pp, &gp->provider, provider) {
  429                                         if (linux_driver_get_major_minor(
  430                                             pp->name, &major, &minor) != 0) {
  431                                                 major = 0;
  432                                                 minor = 0;
  433                                         }
  434                                         sbuf_printf(sb, "%d %d %lld %s "
  435                                             "%d %d %d %d %d "
  436                                              "%d %d %d %d %d %d\n",
  437                                              major, minor,
  438                                              (long long)pp->mediasize, pp->name,
  439                                              0, 0, 0, 0, 0,
  440                                              0, 0, 0, 0, 0, 0);
  441                                 }
  442                         }
  443         }
  444         g_topology_unlock();
  445 
  446         if (flep != NULL)
  447                 free(flep, M_TEMP);
  448         return (error);
  449 }
  450 
  451 
  452 /*
  453  * Filler function for proc/stat
  454  */
  455 static int
  456 linprocfs_dostat(PFS_FILL_ARGS)
  457 {
  458         struct pcpu *pcpu;
  459         long cp_time[CPUSTATES];
  460         long *cp;
  461         int i;
  462 
  463         read_cpu_time(cp_time);
  464         sbuf_printf(sb, "cpu %ld %ld %ld %ld\n",
  465             T2J(cp_time[CP_USER]),
  466             T2J(cp_time[CP_NICE]),
  467             T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
  468             T2J(cp_time[CP_IDLE]));
  469         for (i = 0; i <= mp_maxid; ++i) {
  470                 if (CPU_ABSENT(i))
  471                         continue;
  472                 pcpu = pcpu_find(i);
  473                 cp = pcpu->pc_cp_time;
  474                 sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i,
  475                     T2J(cp[CP_USER]),
  476                     T2J(cp[CP_NICE]),
  477                     T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/),
  478                     T2J(cp[CP_IDLE]));
  479         }
  480         sbuf_printf(sb,
  481             "disk 0 0 0 0\n"
  482             "page %u %u\n"
  483             "swap %u %u\n"
  484             "intr %u\n"
  485             "ctxt %u\n"
  486             "btime %lld\n",
  487             cnt.v_vnodepgsin,
  488             cnt.v_vnodepgsout,
  489             cnt.v_swappgsin,
  490             cnt.v_swappgsout,
  491             cnt.v_intr,
  492             cnt.v_swtch,
  493             (long long)boottime.tv_sec);
  494         return (0);
  495 }
  496 
  497 /*
  498  * Filler function for proc/uptime
  499  */
  500 static int
  501 linprocfs_douptime(PFS_FILL_ARGS)
  502 {
  503         long cp_time[CPUSTATES];
  504         struct timeval tv;
  505 
  506         getmicrouptime(&tv);
  507         read_cpu_time(cp_time);
  508         sbuf_printf(sb, "%lld.%02ld %ld.%02ld\n",
  509             (long long)tv.tv_sec, tv.tv_usec / 10000,
  510             T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100);
  511         return (0);
  512 }
  513 
  514 /*
  515  * Get OS build date
  516  */
  517 static void
  518 linprocfs_osbuild(struct thread *td, struct sbuf *sb)
  519 {
  520 #if 0
  521         char osbuild[256];
  522         char *cp1, *cp2;
  523 
  524         strncpy(osbuild, version, 256);
  525         osbuild[255] = '\0';
  526         cp1 = strstr(osbuild, "\n");
  527         cp2 = strstr(osbuild, ":");
  528         if (cp1 && cp2) {
  529                 *cp1 = *cp2 = '\0';
  530                 cp1 = strstr(osbuild, "#");
  531         } else
  532                 cp1 = NULL;
  533         if (cp1)
  534                 sbuf_printf(sb, "%s%s", cp1, cp2 + 1);
  535         else
  536 #endif
  537                 sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977");
  538 }
  539 
  540 /*
  541  * Get OS builder
  542  */
  543 static void
  544 linprocfs_osbuilder(struct thread *td, struct sbuf *sb)
  545 {
  546 #if 0
  547         char builder[256];
  548         char *cp;
  549 
  550         cp = strstr(version, "\n    ");
  551         if (cp) {
  552                 strncpy(builder, cp + 5, 256);
  553                 builder[255] = '\0';
  554                 cp = strstr(builder, ":");
  555                 if (cp)
  556                         *cp = '\0';
  557         }
  558         if (cp)
  559                 sbuf_cat(sb, builder);
  560         else
  561 #endif
  562                 sbuf_cat(sb, "des@freebsd.org");
  563 }
  564 
  565 /*
  566  * Filler function for proc/version
  567  */
  568 static int
  569 linprocfs_doversion(PFS_FILL_ARGS)
  570 {
  571         char osname[LINUX_MAX_UTSNAME];
  572         char osrelease[LINUX_MAX_UTSNAME];
  573 
  574         linux_get_osname(td, osname);
  575         linux_get_osrelease(td, osrelease);
  576         sbuf_printf(sb, "%s version %s (", osname, osrelease);
  577         linprocfs_osbuilder(td, sb);
  578         sbuf_cat(sb, ") (gcc version " __VERSION__ ") ");
  579         linprocfs_osbuild(td, sb);
  580         sbuf_cat(sb, "\n");
  581 
  582         return (0);
  583 }
  584 
  585 /*
  586  * Filler function for proc/loadavg
  587  */
  588 static int
  589 linprocfs_doloadavg(PFS_FILL_ARGS)
  590 {
  591 
  592         sbuf_printf(sb,
  593             "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
  594             (int)(averunnable.ldavg[0] / averunnable.fscale),
  595             (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
  596             (int)(averunnable.ldavg[1] / averunnable.fscale),
  597             (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
  598             (int)(averunnable.ldavg[2] / averunnable.fscale),
  599             (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
  600             1,                          /* number of running tasks */
  601             nprocs,                     /* number of tasks */
  602             lastpid                     /* the last pid */
  603         );
  604         return (0);
  605 }
  606 
  607 /*
  608  * Filler function for proc/pid/stat
  609  */
  610 static int
  611 linprocfs_doprocstat(PFS_FILL_ARGS)
  612 {
  613         struct kinfo_proc kp;
  614         char state;
  615         static int ratelimit = 0;
  616 
  617         PROC_LOCK(p);
  618         fill_kinfo_proc(p, &kp);
  619         sbuf_printf(sb, "%d", p->p_pid);
  620 #define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
  621         PS_ADD("comm",          "(%s)", p->p_comm);
  622         if (kp.ki_stat > sizeof(linux_state)) {
  623                 state = 'R';
  624 
  625                 if (ratelimit == 0) {
  626                         printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n",
  627                             kp.ki_stat, sizeof(linux_state));
  628                         ++ratelimit;
  629                 }
  630         } else
  631                 state = linux_state[kp.ki_stat - 1];
  632         PS_ADD("state",         "%c",   state);
  633         PS_ADD("ppid",          "%d",   p->p_pptr ? p->p_pptr->p_pid : 0);
  634         PS_ADD("pgrp",          "%d",   p->p_pgid);
  635         PS_ADD("session",       "%d",   p->p_session->s_sid);
  636         PROC_UNLOCK(p);
  637         PS_ADD("tty",           "%d",   0); /* XXX */
  638         PS_ADD("tpgid",         "%d",   kp.ki_tpgid);
  639         PS_ADD("flags",         "%u",   0); /* XXX */
  640         PS_ADD("minflt",        "%lu",  kp.ki_rusage.ru_minflt);
  641         PS_ADD("cminflt",       "%lu",  kp.ki_rusage_ch.ru_minflt);
  642         PS_ADD("majflt",        "%lu",  kp.ki_rusage.ru_majflt);
  643         PS_ADD("cmajflt",       "%lu",  kp.ki_rusage_ch.ru_majflt);
  644         PS_ADD("utime",         "%ld",  T2J(tvtohz(&kp.ki_rusage.ru_utime)));
  645         PS_ADD("stime",         "%ld",  T2J(tvtohz(&kp.ki_rusage.ru_stime)));
  646         PS_ADD("cutime",        "%ld",  T2J(tvtohz(&kp.ki_rusage_ch.ru_utime)));
  647         PS_ADD("cstime",        "%ld",  T2J(tvtohz(&kp.ki_rusage_ch.ru_stime)));
  648         PS_ADD("priority",      "%d",   kp.ki_pri.pri_user);
  649         PS_ADD("nice",          "%d",   kp.ki_nice); /* 19 (nicest) to -19 */
  650         PS_ADD("",             "%d",   0); /* removed field */
  651         PS_ADD("itrealvalue",   "%d",   0); /* XXX */
  652         /* XXX: starttime is not right, it is the _same_ for _every_ process.
  653            It should be the number of jiffies between system boot and process
  654            start. */
  655         PS_ADD("starttime",     "%lu",  T2J(tvtohz(&kp.ki_start)));
  656         PS_ADD("vsize",         "%ju",  P2K((uintmax_t)kp.ki_size));
  657         PS_ADD("rss",           "%ju",  (uintmax_t)kp.ki_rssize);
  658         PS_ADD("rlim",          "%lu",  kp.ki_rusage.ru_maxrss);
  659         PS_ADD("startcode",     "%u",   (unsigned)0);
  660         PS_ADD("endcode",       "%u",   0); /* XXX */
  661         PS_ADD("startstack",    "%u",   0); /* XXX */
  662         PS_ADD("kstkesp",       "%u",   0); /* XXX */
  663         PS_ADD("kstkeip",       "%u",   0); /* XXX */
  664         PS_ADD("signal",        "%u",   0); /* XXX */
  665         PS_ADD("blocked",       "%u",   0); /* XXX */
  666         PS_ADD("sigignore",     "%u",   0); /* XXX */
  667         PS_ADD("sigcatch",      "%u",   0); /* XXX */
  668         PS_ADD("wchan",         "%u",   0); /* XXX */
  669         PS_ADD("nswap",         "%lu",  kp.ki_rusage.ru_nswap);
  670         PS_ADD("cnswap",        "%lu",  kp.ki_rusage_ch.ru_nswap);
  671         PS_ADD("exitsignal",    "%d",   0); /* XXX */
  672         PS_ADD("processor",     "%u",   kp.ki_lastcpu);
  673         PS_ADD("rt_priority",   "%u",   0); /* XXX */ /* >= 2.5.19 */
  674         PS_ADD("policy",        "%u",   kp.ki_pri.pri_class); /* >= 2.5.19 */
  675 #undef PS_ADD
  676         sbuf_putc(sb, '\n');
  677 
  678         return (0);
  679 }
  680 
  681 /*
  682  * Filler function for proc/pid/statm
  683  */
  684 static int
  685 linprocfs_doprocstatm(PFS_FILL_ARGS)
  686 {
  687         struct kinfo_proc kp;
  688         segsz_t lsize;
  689 
  690         PROC_LOCK(p);
  691         fill_kinfo_proc(p, &kp);
  692         PROC_UNLOCK(p);
  693 
  694         /*
  695          * See comments in linprocfs_doprocstatus() regarding the
  696          * computation of lsize.
  697          */
  698         /* size resident share trs drs lrs dt */
  699         sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size));
  700         sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize);
  701         sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */
  702         sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize);
  703         sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize));
  704         lsize = B2P(kp.ki_size) - kp.ki_dsize -
  705             kp.ki_ssize - kp.ki_tsize - 1;
  706         sbuf_printf(sb, "%ju ", (uintmax_t)lsize);
  707         sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */
  708 
  709         return (0);
  710 }
  711 
  712 /*
  713  * Filler function for proc/pid/status
  714  */
  715 static int
  716 linprocfs_doprocstatus(PFS_FILL_ARGS)
  717 {
  718         struct kinfo_proc kp;
  719         char *state;
  720         segsz_t lsize;
  721         struct thread *td2;
  722         struct sigacts *ps;
  723         int i;
  724 
  725         PROC_LOCK(p);
  726         td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */
  727 
  728         if (P_SHOULDSTOP(p)) {
  729                 state = "T (stopped)";
  730         } else {
  731                 PROC_SLOCK(p);
  732                 switch(p->p_state) {
  733                 case PRS_NEW:
  734                         state = "I (idle)";
  735                         break;
  736                 case PRS_NORMAL:
  737                         if (p->p_flag & P_WEXIT) {
  738                                 state = "X (exiting)";
  739                                 break;
  740                         }
  741                         switch(td2->td_state) {
  742                         case TDS_INHIBITED:
  743                                 state = "S (sleeping)";
  744                                 break;
  745                         case TDS_RUNQ:
  746                         case TDS_RUNNING:
  747                                 state = "R (running)";
  748                                 break;
  749                         default:
  750                                 state = "? (unknown)";
  751                                 break;
  752                         }
  753                         break;
  754                 case PRS_ZOMBIE:
  755                         state = "Z (zombie)";
  756                         break;
  757                 default:
  758                         state = "? (unknown)";
  759                         break;
  760                 }
  761                 PROC_SUNLOCK(p);
  762         }
  763 
  764         fill_kinfo_proc(p, &kp);
  765         sbuf_printf(sb, "Name:\t%s\n",          p->p_comm); /* XXX escape */
  766         sbuf_printf(sb, "State:\t%s\n",         state);
  767 
  768         /*
  769          * Credentials
  770          */
  771         sbuf_printf(sb, "Pid:\t%d\n",           p->p_pid);
  772         sbuf_printf(sb, "PPid:\t%d\n",          p->p_pptr ?
  773                                                 p->p_pptr->p_pid : 0);
  774         sbuf_printf(sb, "Uid:\t%d %d %d %d\n",  p->p_ucred->cr_ruid,
  775                                                 p->p_ucred->cr_uid,
  776                                                 p->p_ucred->cr_svuid,
  777                                                 /* FreeBSD doesn't have fsuid */
  778                                                 p->p_ucred->cr_uid);
  779         sbuf_printf(sb, "Gid:\t%d %d %d %d\n",  p->p_ucred->cr_rgid,
  780                                                 p->p_ucred->cr_gid,
  781                                                 p->p_ucred->cr_svgid,
  782                                                 /* FreeBSD doesn't have fsgid */
  783                                                 p->p_ucred->cr_gid);
  784         sbuf_cat(sb, "Groups:\t");
  785         for (i = 0; i < p->p_ucred->cr_ngroups; i++)
  786                 sbuf_printf(sb, "%d ",          p->p_ucred->cr_groups[i]);
  787         PROC_UNLOCK(p);
  788         sbuf_putc(sb, '\n');
  789 
  790         /*
  791          * Memory
  792          *
  793          * While our approximation of VmLib may not be accurate (I
  794          * don't know of a simple way to verify it, and I'm not sure
  795          * it has much meaning anyway), I believe it's good enough.
  796          *
  797          * The same code that could (I think) accurately compute VmLib
  798          * could also compute VmLck, but I don't really care enough to
  799          * implement it. Submissions are welcome.
  800          */
  801         sbuf_printf(sb, "VmSize:\t%8ju kB\n",   B2K((uintmax_t)kp.ki_size));
  802         sbuf_printf(sb, "VmLck:\t%8u kB\n",     P2K(0)); /* XXX */
  803         sbuf_printf(sb, "VmRss:\t%8ju kB\n",    P2K((uintmax_t)kp.ki_rssize));
  804         sbuf_printf(sb, "VmData:\t%8ju kB\n",   P2K((uintmax_t)kp.ki_dsize));
  805         sbuf_printf(sb, "VmStk:\t%8ju kB\n",    P2K((uintmax_t)kp.ki_ssize));
  806         sbuf_printf(sb, "VmExe:\t%8ju kB\n",    P2K((uintmax_t)kp.ki_tsize));
  807         lsize = B2P(kp.ki_size) - kp.ki_dsize -
  808             kp.ki_ssize - kp.ki_tsize - 1;
  809         sbuf_printf(sb, "VmLib:\t%8ju kB\n",    P2K((uintmax_t)lsize));
  810 
  811         /*
  812          * Signal masks
  813          *
  814          * We support up to 128 signals, while Linux supports 32,
  815          * but we only define 32 (the same 32 as Linux, to boot), so
  816          * just show the lower 32 bits of each mask. XXX hack.
  817          *
  818          * NB: on certain platforms (Sparc at least) Linux actually
  819          * supports 64 signals, but this code is a long way from
  820          * running on anything but i386, so ignore that for now.
  821          */
  822         PROC_LOCK(p);
  823         sbuf_printf(sb, "SigPnd:\t%08x\n",      p->p_siglist.__bits[0]);
  824         /*
  825          * I can't seem to find out where the signal mask is in
  826          * relation to struct proc, so SigBlk is left unimplemented.
  827          */
  828         sbuf_printf(sb, "SigBlk:\t%08x\n",      0); /* XXX */
  829         ps = p->p_sigacts;
  830         mtx_lock(&ps->ps_mtx);
  831         sbuf_printf(sb, "SigIgn:\t%08x\n",      ps->ps_sigignore.__bits[0]);
  832         sbuf_printf(sb, "SigCgt:\t%08x\n",      ps->ps_sigcatch.__bits[0]);
  833         mtx_unlock(&ps->ps_mtx);
  834         PROC_UNLOCK(p);
  835 
  836         /*
  837          * Linux also prints the capability masks, but we don't have
  838          * capabilities yet, and when we do get them they're likely to
  839          * be meaningless to Linux programs, so we lie. XXX
  840          */
  841         sbuf_printf(sb, "CapInh:\t%016x\n",     0);
  842         sbuf_printf(sb, "CapPrm:\t%016x\n",     0);
  843         sbuf_printf(sb, "CapEff:\t%016x\n",     0);
  844 
  845         return (0);
  846 }
  847 
  848 
  849 /*
  850  * Filler function for proc/pid/cwd
  851  */
  852 static int
  853 linprocfs_doproccwd(PFS_FILL_ARGS)
  854 {
  855         char *fullpath = "unknown";
  856         char *freepath = NULL;
  857 
  858         vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath);
  859         sbuf_printf(sb, "%s", fullpath);
  860         if (freepath)
  861                 free(freepath, M_TEMP);
  862         return (0);
  863 }
  864 
  865 /*
  866  * Filler function for proc/pid/root
  867  */
  868 static int
  869 linprocfs_doprocroot(PFS_FILL_ARGS)
  870 {
  871         struct vnode *rvp;
  872         char *fullpath = "unknown";
  873         char *freepath = NULL;
  874 
  875         rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir;
  876         vn_fullpath(td, rvp, &fullpath, &freepath);
  877         sbuf_printf(sb, "%s", fullpath);
  878         if (freepath)
  879                 free(freepath, M_TEMP);
  880         return (0);
  881 }
  882 
  883 /*
  884  * Filler function for proc/pid/cmdline
  885  */
  886 static int
  887 linprocfs_doproccmdline(PFS_FILL_ARGS)
  888 {
  889         struct ps_strings pstr;
  890         char **ps_argvstr;
  891         int error, i;
  892 
  893         /*
  894          * If we are using the ps/cmdline caching, use that.  Otherwise
  895          * revert back to the old way which only implements full cmdline
  896          * for the currept process and just p->p_comm for all other
  897          * processes.
  898          * Note that if the argv is no longer available, we deliberately
  899          * don't fall back on p->p_comm or return an error: the authentic
  900          * Linux behaviour is to return zero-length in this case.
  901          */
  902 
  903         PROC_LOCK(p);
  904         if (p->p_args && p_cansee(td, p) == 0) {
  905                 sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
  906                 PROC_UNLOCK(p);
  907         } else if (p != td->td_proc) {
  908                 PROC_UNLOCK(p);
  909                 sbuf_printf(sb, "%.*s", MAXCOMLEN, p->p_comm);
  910         } else {
  911                 PROC_UNLOCK(p);
  912                 error = copyin((void *)p->p_sysent->sv_psstrings, &pstr,
  913                     sizeof(pstr));
  914                 if (error)
  915                         return (error);
  916                 if (pstr.ps_nargvstr > ARG_MAX)
  917                         return (E2BIG);
  918                 ps_argvstr = malloc(pstr.ps_nargvstr * sizeof(char *),
  919                     M_TEMP, M_WAITOK);
  920                 error = copyin((void *)pstr.ps_argvstr, ps_argvstr,
  921                     pstr.ps_nargvstr * sizeof(char *));
  922                 if (error) {
  923                         free(ps_argvstr, M_TEMP);
  924                         return (error);
  925                 }
  926                 for (i = 0; i < pstr.ps_nargvstr; i++) {
  927                         sbuf_copyin(sb, ps_argvstr[i], 0);
  928                         sbuf_printf(sb, "%c", '\0');
  929                 }
  930                 free(ps_argvstr, M_TEMP);
  931         }
  932 
  933         return (0);
  934 }
  935 
  936 /*
  937  * Filler function for proc/pid/environ
  938  */
  939 static int
  940 linprocfs_doprocenviron(PFS_FILL_ARGS)
  941 {
  942 
  943         sbuf_printf(sb, "doprocenviron\n%c", '\0');
  944         return (0);
  945 }
  946 
  947 /*
  948  * Filler function for proc/pid/maps
  949  */
  950 static int
  951 linprocfs_doprocmaps(PFS_FILL_ARGS)
  952 {
  953         struct vmspace *vm;
  954         vm_map_t map;
  955         vm_map_entry_t entry, tmp_entry;
  956         vm_object_t obj, tobj, lobj;
  957         vm_offset_t e_start, e_end;
  958         vm_ooffset_t off = 0;
  959         vm_prot_t e_prot;
  960         unsigned int last_timestamp;
  961         char *name = "", *freename = NULL;
  962         ino_t ino;
  963         int ref_count, shadow_count, flags;
  964         int error;
  965         struct vnode *vp;
  966         struct vattr vat;
  967         int locked;
  968 
  969         PROC_LOCK(p);
  970         error = p_candebug(td, p);
  971         PROC_UNLOCK(p);
  972         if (error)
  973                 return (error);
  974 
  975         if (uio->uio_rw != UIO_READ)
  976                 return (EOPNOTSUPP);
  977 
  978         error = 0;
  979         vm = vmspace_acquire_ref(p);
  980         if (vm == NULL)
  981                 return (ESRCH);
  982         map = &vm->vm_map;
  983         vm_map_lock_read(map);
  984         for (entry = map->header.next; entry != &map->header;
  985             entry = entry->next) {
  986                 name = "";
  987                 freename = NULL;
  988                 if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
  989                         continue;
  990                 e_prot = entry->protection;
  991                 e_start = entry->start;
  992                 e_end = entry->end;
  993                 obj = entry->object.vm_object;
  994                 for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) {
  995                         VM_OBJECT_LOCK(tobj);
  996                         if (lobj != obj)
  997                                 VM_OBJECT_UNLOCK(lobj);
  998                         lobj = tobj;
  999                 }
 1000                 last_timestamp = map->timestamp;
 1001                 vm_map_unlock_read(map);
 1002                 ino = 0;
 1003                 if (lobj) {
 1004                         off = IDX_TO_OFF(lobj->size);
 1005                         if (lobj->type == OBJT_VNODE) {
 1006                                 vp = lobj->handle;
 1007                                 if (vp)
 1008                                         vref(vp);
 1009                         }
 1010                         else
 1011                                 vp = NULL;
 1012                         if (lobj != obj)
 1013                                 VM_OBJECT_UNLOCK(lobj);
 1014                         flags = obj->flags;
 1015                         ref_count = obj->ref_count;
 1016                         shadow_count = obj->shadow_count;
 1017                         VM_OBJECT_UNLOCK(obj);
 1018                         if (vp) {
 1019                                 vn_fullpath(td, vp, &name, &freename);
 1020                                 locked = VFS_LOCK_GIANT(vp->v_mount);
 1021                                 vn_lock(vp, LK_SHARED | LK_RETRY);
 1022                                 VOP_GETATTR(vp, &vat, td->td_ucred);
 1023                                 ino = vat.va_fileid;
 1024                                 vput(vp);
 1025                                 VFS_UNLOCK_GIANT(locked);
 1026                         }
 1027                 } else {
 1028                         flags = 0;
 1029                         ref_count = 0;
 1030                         shadow_count = 0;
 1031                 }
 1032 
 1033                 /*
 1034                  * format:
 1035                  *  start, end, access, offset, major, minor, inode, name.
 1036                  */
 1037                 error = sbuf_printf(sb,
 1038                     "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n",
 1039                     (u_long)e_start, (u_long)e_end,
 1040                     (e_prot & VM_PROT_READ)?"r":"-",
 1041                     (e_prot & VM_PROT_WRITE)?"w":"-",
 1042                     (e_prot & VM_PROT_EXECUTE)?"x":"-",
 1043                     "p",
 1044                     (u_long)off,
 1045                     0,
 1046                     0,
 1047                     (u_long)ino,
 1048                     *name ? "     " : "",
 1049                     name
 1050                     );
 1051                 if (freename)
 1052                         free(freename, M_TEMP);
 1053                 vm_map_lock_read(map);
 1054                 if (error == -1) {
 1055                         error = 0;
 1056                         break;
 1057                 }
 1058                 if (last_timestamp != map->timestamp) {
 1059                         /*
 1060                          * Look again for the entry because the map was
 1061                          * modified while it was unlocked.  Specifically,
 1062                          * the entry may have been clipped, merged, or deleted.
 1063                          */
 1064                         vm_map_lookup_entry(map, e_end - 1, &tmp_entry);
 1065                         entry = tmp_entry;
 1066                 }
 1067         }
 1068         vm_map_unlock_read(map);
 1069         vmspace_free(vm);
 1070 
 1071         return (error);
 1072 }
 1073 
 1074 /*
 1075  * Filler function for proc/net/dev
 1076  */
 1077 static int
 1078 linprocfs_donetdev(PFS_FILL_ARGS)
 1079 {
 1080         char ifname[16]; /* XXX LINUX_IFNAMSIZ */
 1081         struct ifnet *ifp;
 1082 
 1083         sbuf_printf(sb, "%6s|%58s|%s\n%6s|%58s|%58s\n",
 1084             "Inter-", "   Receive", "  Transmit", " face",
 1085             "bytes    packets errs drop fifo frame compressed",
 1086             "bytes    packets errs drop fifo frame compressed");
 1087 
 1088         CURVNET_SET(TD_TO_VNET(curthread));
 1089         IFNET_RLOCK();
 1090         TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 1091                 linux_ifname(ifp, ifname, sizeof ifname);
 1092                         sbuf_printf(sb, "%6.6s:", ifname);
 1093                 sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ",
 1094                     0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
 1095                 sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
 1096                     0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL);
 1097         }
 1098         IFNET_RUNLOCK();
 1099         CURVNET_RESTORE();
 1100 
 1101         return (0);
 1102 }
 1103 
 1104 /*
 1105  * Filler function for proc/sys/kernel/osrelease
 1106  */
 1107 static int
 1108 linprocfs_doosrelease(PFS_FILL_ARGS)
 1109 {
 1110         char osrelease[LINUX_MAX_UTSNAME];
 1111 
 1112         linux_get_osrelease(td, osrelease);
 1113         sbuf_printf(sb, "%s\n", osrelease);
 1114 
 1115         return (0);
 1116 }
 1117 
 1118 /*
 1119  * Filler function for proc/sys/kernel/ostype
 1120  */
 1121 static int
 1122 linprocfs_doostype(PFS_FILL_ARGS)
 1123 {
 1124         char osname[LINUX_MAX_UTSNAME];
 1125 
 1126         linux_get_osname(td, osname);
 1127         sbuf_printf(sb, "%s\n", osname);
 1128 
 1129         return (0);
 1130 }
 1131 
 1132 /*
 1133  * Filler function for proc/sys/kernel/version
 1134  */
 1135 static int
 1136 linprocfs_doosbuild(PFS_FILL_ARGS)
 1137 {
 1138 
 1139         linprocfs_osbuild(td, sb);
 1140         sbuf_cat(sb, "\n");
 1141         return (0);
 1142 }
 1143 
 1144 /*
 1145  * Filler function for proc/sys/kernel/msgmni
 1146  */
 1147 static int
 1148 linprocfs_domsgmni(PFS_FILL_ARGS)
 1149 {
 1150 
 1151         sbuf_printf(sb, "%d\n", msginfo.msgmni);
 1152         return (0);
 1153 }
 1154 
 1155 /*
 1156  * Filler function for proc/sys/kernel/pid_max
 1157  */
 1158 static int
 1159 linprocfs_dopid_max(PFS_FILL_ARGS)
 1160 {
 1161 
 1162         sbuf_printf(sb, "%i\n", PID_MAX);
 1163         return (0);
 1164 }
 1165 
 1166 /*
 1167  * Filler function for proc/sys/kernel/sem
 1168  */
 1169 static int
 1170 linprocfs_dosem(PFS_FILL_ARGS)
 1171 {
 1172 
 1173         sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns,
 1174             seminfo.semopm, seminfo.semmni);
 1175         return (0);
 1176 }
 1177 
 1178 /*
 1179  * Filler function for proc/scsi/device_info
 1180  */
 1181 static int
 1182 linprocfs_doscsidevinfo(PFS_FILL_ARGS)
 1183 {
 1184 
 1185         return (0);
 1186 }
 1187 
 1188 /*
 1189  * Filler function for proc/scsi/scsi
 1190  */
 1191 static int
 1192 linprocfs_doscsiscsi(PFS_FILL_ARGS)
 1193 {
 1194 
 1195         return (0);
 1196 }
 1197 
 1198 extern struct cdevsw *cdevsw[];
 1199 
 1200 /*
 1201  * Filler function for proc/devices
 1202  */
 1203 static int
 1204 linprocfs_dodevices(PFS_FILL_ARGS)
 1205 {
 1206         char *char_devices;
 1207         sbuf_printf(sb, "Character devices:\n");
 1208 
 1209         char_devices = linux_get_char_devices();
 1210         sbuf_printf(sb, "%s", char_devices);
 1211         linux_free_get_char_devices(char_devices);
 1212 
 1213         sbuf_printf(sb, "\nBlock devices:\n");
 1214 
 1215         return (0);
 1216 }
 1217 
 1218 /*
 1219  * Filler function for proc/cmdline
 1220  */
 1221 static int
 1222 linprocfs_docmdline(PFS_FILL_ARGS)
 1223 {
 1224 
 1225         sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
 1226         sbuf_printf(sb, " ro root=302\n");
 1227         return (0);
 1228 }
 1229 
 1230 #if 0
 1231 /*
 1232  * Filler function for proc/modules
 1233  */
 1234 static int
 1235 linprocfs_domodules(PFS_FILL_ARGS)
 1236 {
 1237         struct linker_file *lf;
 1238 
 1239         TAILQ_FOREACH(lf, &linker_files, link) {
 1240                 sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
 1241                     (unsigned long)lf->size, lf->refs);
 1242         }
 1243         return (0);
 1244 }
 1245 #endif
 1246 
 1247 /*
 1248  * Constructor
 1249  */
 1250 static int
 1251 linprocfs_init(PFS_INIT_ARGS)
 1252 {
 1253         struct pfs_node *root;
 1254         struct pfs_node *dir;
 1255 
 1256         root = pi->pi_root;
 1257 
 1258         /* /proc/... */
 1259         pfs_create_file(root, "cmdline", &linprocfs_docmdline,
 1260             NULL, NULL, NULL, PFS_RD);
 1261         pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
 1262             NULL, NULL, NULL, PFS_RD);
 1263         pfs_create_file(root, "devices", &linprocfs_dodevices,
 1264             NULL, NULL, NULL, PFS_RD);
 1265         pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
 1266             NULL, NULL, NULL, PFS_RD);
 1267         pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
 1268             NULL, NULL, NULL, PFS_RD);
 1269 #if 0
 1270         pfs_create_file(root, "modules", &linprocfs_domodules,
 1271             NULL, NULL, NULL, PFS_RD);
 1272 #endif
 1273         pfs_create_file(root, "mounts", &linprocfs_domtab,
 1274             NULL, NULL, NULL, PFS_RD);
 1275         pfs_create_file(root, "mtab", &linprocfs_domtab,
 1276             NULL, NULL, NULL, PFS_RD);
 1277         pfs_create_file(root, "partitions", &linprocfs_dopartitions,
 1278             NULL, NULL, NULL, PFS_RD);
 1279         pfs_create_link(root, "self", &procfs_docurproc,
 1280             NULL, NULL, NULL, 0);
 1281         pfs_create_file(root, "stat", &linprocfs_dostat,
 1282             NULL, NULL, NULL, PFS_RD);
 1283         pfs_create_file(root, "uptime", &linprocfs_douptime,
 1284             NULL, NULL, NULL, PFS_RD);
 1285         pfs_create_file(root, "version", &linprocfs_doversion,
 1286             NULL, NULL, NULL, PFS_RD);
 1287 
 1288         /* /proc/net/... */
 1289         dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
 1290         pfs_create_file(dir, "dev", &linprocfs_donetdev,
 1291             NULL, NULL, NULL, PFS_RD);
 1292 
 1293         /* /proc/<pid>/... */
 1294         dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
 1295         pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
 1296             NULL, NULL, NULL, PFS_RD);
 1297         pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
 1298             NULL, NULL, NULL, 0);
 1299         pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
 1300             NULL, NULL, NULL, PFS_RD);
 1301         pfs_create_link(dir, "exe", &procfs_doprocfile,
 1302             NULL, &procfs_notsystem, NULL, 0);
 1303         pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
 1304             NULL, NULL, NULL, PFS_RD);
 1305         pfs_create_file(dir, "mem", &procfs_doprocmem,
 1306             &procfs_attr, &procfs_candebug, NULL, PFS_RDWR|PFS_RAW);
 1307         pfs_create_link(dir, "root", &linprocfs_doprocroot,
 1308             NULL, NULL, NULL, 0);
 1309         pfs_create_file(dir, "stat", &linprocfs_doprocstat,
 1310             NULL, NULL, NULL, PFS_RD);
 1311         pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
 1312             NULL, NULL, NULL, PFS_RD);
 1313         pfs_create_file(dir, "status", &linprocfs_doprocstatus,
 1314             NULL, NULL, NULL, PFS_RD);
 1315 
 1316         /* /proc/scsi/... */
 1317         dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
 1318         pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
 1319             NULL, NULL, NULL, PFS_RD);
 1320         pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
 1321             NULL, NULL, NULL, PFS_RD);
 1322 
 1323         /* /proc/sys/... */
 1324         dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
 1325         /* /proc/sys/kernel/... */
 1326         dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0);
 1327         pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
 1328             NULL, NULL, NULL, PFS_RD);
 1329         pfs_create_file(dir, "ostype", &linprocfs_doostype,
 1330             NULL, NULL, NULL, PFS_RD);
 1331         pfs_create_file(dir, "version", &linprocfs_doosbuild,
 1332             NULL, NULL, NULL, PFS_RD);
 1333         pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
 1334             NULL, NULL, NULL, PFS_RD);
 1335         pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
 1336             NULL, NULL, NULL, PFS_RD);
 1337         pfs_create_file(dir, "sem", &linprocfs_dosem,
 1338             NULL, NULL, NULL, PFS_RD);
 1339 
 1340         return (0);
 1341 }
 1342 
 1343 /*
 1344  * Destructor
 1345  */
 1346 static int
 1347 linprocfs_uninit(PFS_INIT_ARGS)
 1348 {
 1349 
 1350         /* nothing to do, pseudofs will GC */
 1351         return (0);
 1352 }
 1353 
 1354 PSEUDOFS(linprocfs, 1);
 1355 MODULE_DEPEND(linprocfs, linux, 1, 1, 1);
 1356 MODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
 1357 MODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);
 1358 MODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1);

Cache object: ac1cf948232be8b639b8b6a85b9ec6e6


[ 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.