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/10.2/sys/compat/linprocfs/linprocfs.c 263101 2014-03-13 03:42:00Z eadler $");
   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/ptrace.h>
   65 #include <sys/resourcevar.h>
   66 #include <sys/sbuf.h>
   67 #include <sys/sem.h>
   68 #include <sys/smp.h>
   69 #include <sys/socket.h>
   70 #include <sys/sysctl.h>
   71 #include <sys/systm.h>
   72 #include <sys/time.h>
   73 #include <sys/tty.h>
   74 #include <sys/user.h>
   75 #include <sys/uuid.h>
   76 #include <sys/vmmeter.h>
   77 #include <sys/vnode.h>
   78 #include <sys/bus.h>
   79 
   80 #include <net/if.h>
   81 #include <net/vnet.h>
   82 
   83 #include <vm/vm.h>
   84 #include <vm/vm_extern.h>
   85 #include <vm/pmap.h>
   86 #include <vm/vm_map.h>
   87 #include <vm/vm_param.h>
   88 #include <vm/vm_object.h>
   89 #include <vm/swap_pager.h>
   90 
   91 #include <machine/clock.h>
   92 
   93 #include <geom/geom.h>
   94 #include <geom/geom_int.h>
   95 
   96 #if defined(__i386__) || defined(__amd64__)
   97 #include <machine/cputypes.h>
   98 #include <machine/md_var.h>
   99 #endif /* __i386__ || __amd64__ */
  100 
  101 #ifdef COMPAT_FREEBSD32
  102 #include <compat/freebsd32/freebsd32_util.h>
  103 #endif
  104 
  105 #include <compat/linux/linux_ioctl.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 memshared;        /* shared memory ??? */
  150         unsigned long buffers, cached;  /* buffer / cache memory ??? */
  151         unsigned long long swaptotal;   /* total swap space in bytes */
  152         unsigned long long swapused;    /* used swap space in bytes */
  153         unsigned long long swapfree;    /* free swap space in bytes */
  154         vm_object_t object;
  155         int i, j;
  156 
  157         memtotal = physmem * PAGE_SIZE;
  158         /*
  159          * The correct thing here would be:
  160          *
  161         memfree = cnt.v_free_count * PAGE_SIZE;
  162         memused = memtotal - memfree;
  163          *
  164          * but it might mislead linux binaries into thinking there
  165          * is very little memory left, so we cheat and tell them that
  166          * all memory that isn't wired down is free.
  167          */
  168         memused = cnt.v_wire_count * PAGE_SIZE;
  169         memfree = memtotal - memused;
  170         swap_pager_status(&i, &j);
  171         swaptotal = (unsigned long long)i * PAGE_SIZE;
  172         swapused = (unsigned long long)j * PAGE_SIZE;
  173         swapfree = swaptotal - swapused;
  174         memshared = 0;
  175         mtx_lock(&vm_object_list_mtx);
  176         TAILQ_FOREACH(object, &vm_object_list, object_list)
  177                 if (object->shadow_count > 1)
  178                         memshared += object->resident_page_count;
  179         mtx_unlock(&vm_object_list_mtx);
  180         memshared *= PAGE_SIZE;
  181         /*
  182          * We'd love to be able to write:
  183          *
  184         buffers = bufspace;
  185          *
  186          * but bufspace is internal to vfs_bio.c and we don't feel
  187          * like unstaticizing it just for linprocfs's sake.
  188          */
  189         buffers = 0;
  190         cached = cnt.v_cache_count * PAGE_SIZE;
  191 
  192         sbuf_printf(sb,
  193             "        total:    used:    free:  shared: buffers:  cached:\n"
  194             "Mem:  %lu %lu %lu %lu %lu %lu\n"
  195             "Swap: %llu %llu %llu\n"
  196             "MemTotal: %9lu kB\n"
  197             "MemFree:  %9lu kB\n"
  198             "MemShared:%9lu kB\n"
  199             "Buffers:  %9lu kB\n"
  200             "Cached:   %9lu kB\n"
  201             "SwapTotal:%9llu kB\n"
  202             "SwapFree: %9llu kB\n",
  203             memtotal, memused, memfree, memshared, buffers, cached,
  204             swaptotal, swapused, swapfree,
  205             B2K(memtotal), B2K(memfree),
  206             B2K(memshared), B2K(buffers), B2K(cached),
  207             B2K(swaptotal), B2K(swapfree));
  208 
  209         return (0);
  210 }
  211 
  212 #if defined(__i386__) || defined(__amd64__)
  213 /*
  214  * Filler function for proc/cpuinfo (i386 & amd64 version)
  215  */
  216 static int
  217 linprocfs_docpuinfo(PFS_FILL_ARGS)
  218 {
  219         int hw_model[2];
  220         char model[128];
  221         uint64_t freq;
  222         size_t size;
  223         int class, fqmhz, fqkhz;
  224         int i;
  225 
  226         /*
  227          * We default the flags to include all non-conflicting flags,
  228          * and the Intel versions of conflicting flags.
  229          */
  230         static char *flags[] = {
  231                 "fpu",      "vme",     "de",       "pse",      "tsc",
  232                 "msr",      "pae",     "mce",      "cx8",      "apic",
  233                 "sep",      "sep",     "mtrr",     "pge",      "mca",
  234                 "cmov",     "pat",     "pse36",    "pn",       "b19",
  235                 "b20",      "b21",     "mmxext",   "mmx",      "fxsr",
  236                 "xmm",      "sse2",    "b27",      "b28",      "b29",
  237                 "3dnowext", "3dnow"
  238         };
  239 
  240         switch (cpu_class) {
  241 #ifdef __i386__
  242         case CPUCLASS_286:
  243                 class = 2;
  244                 break;
  245         case CPUCLASS_386:
  246                 class = 3;
  247                 break;
  248         case CPUCLASS_486:
  249                 class = 4;
  250                 break;
  251         case CPUCLASS_586:
  252                 class = 5;
  253                 break;
  254         case CPUCLASS_686:
  255                 class = 6;
  256                 break;
  257         default:
  258                 class = 0;
  259                 break;
  260 #else /* __amd64__ */
  261         default:
  262                 class = 15;
  263                 break;
  264 #endif
  265         }
  266 
  267         hw_model[0] = CTL_HW;
  268         hw_model[1] = HW_MODEL;
  269         model[0] = '\0';
  270         size = sizeof(model);
  271         if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0)
  272                 strcpy(model, "unknown");
  273         for (i = 0; i < mp_ncpus; ++i) {
  274                 sbuf_printf(sb,
  275                     "processor\t: %d\n"
  276                     "vendor_id\t: %.20s\n"
  277                     "cpu family\t: %u\n"
  278                     "model\t\t: %u\n"
  279                     "model name\t: %s\n"
  280                     "stepping\t: %u\n\n",
  281                     i, cpu_vendor, CPUID_TO_FAMILY(cpu_id),
  282                     CPUID_TO_MODEL(cpu_id), model, cpu_id & CPUID_STEPPING);
  283                 /* XXX per-cpu vendor / class / model / id? */
  284         }
  285 
  286         sbuf_cat(sb, "flags\t\t:");
  287 
  288 #ifdef __i386__
  289         switch (cpu_vendor_id) {
  290         case CPU_VENDOR_AMD:
  291                 if (class < 6)
  292                         flags[16] = "fcmov";
  293                 break;
  294         case CPU_VENDOR_CYRIX:
  295                 flags[24] = "cxmmx";
  296                 break;
  297         }
  298 #endif
  299 
  300         for (i = 0; i < 32; i++)
  301                 if (cpu_feature & (1 << i))
  302                         sbuf_printf(sb, " %s", flags[i]);
  303         sbuf_cat(sb, "\n");
  304         freq = atomic_load_acq_64(&tsc_freq);
  305         if (freq != 0) {
  306                 fqmhz = (freq + 4999) / 1000000;
  307                 fqkhz = ((freq + 4999) / 10000) % 100;
  308                 sbuf_printf(sb,
  309                     "cpu MHz\t\t: %d.%02d\n"
  310                     "bogomips\t: %d.%02d\n",
  311                     fqmhz, fqkhz, fqmhz, fqkhz);
  312         }
  313 
  314         return (0);
  315 }
  316 #endif /* __i386__ || __amd64__ */
  317 
  318 /*
  319  * Filler function for proc/mtab
  320  *
  321  * This file doesn't exist in Linux' procfs, but is included here so
  322  * users can symlink /compat/linux/etc/mtab to /proc/mtab
  323  */
  324 static int
  325 linprocfs_domtab(PFS_FILL_ARGS)
  326 {
  327         struct nameidata nd;
  328         struct mount *mp;
  329         const char *lep;
  330         char *dlep, *flep, *mntto, *mntfrom, *fstype;
  331         size_t lep_len;
  332         int error;
  333 
  334         /* resolve symlinks etc. in the emulation tree prefix */
  335         NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td);
  336         flep = NULL;
  337         error = namei(&nd);
  338         lep = linux_emul_path;
  339         if (error == 0) {
  340                 if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
  341                         lep = dlep;
  342                 vrele(nd.ni_vp);
  343         }
  344         lep_len = strlen(lep);
  345 
  346         mtx_lock(&mountlist_mtx);
  347         error = 0;
  348         TAILQ_FOREACH(mp, &mountlist, mnt_list) {
  349                 /* determine device name */
  350                 mntfrom = mp->mnt_stat.f_mntfromname;
  351 
  352                 /* determine mount point */
  353                 mntto = mp->mnt_stat.f_mntonname;
  354                 if (strncmp(mntto, lep, lep_len) == 0 &&
  355                     mntto[lep_len] == '/')
  356                         mntto += lep_len;
  357 
  358                 /* determine fs type */
  359                 fstype = mp->mnt_stat.f_fstypename;
  360                 if (strcmp(fstype, pn->pn_info->pi_name) == 0)
  361                         mntfrom = fstype = "proc";
  362                 else if (strcmp(fstype, "procfs") == 0)
  363                         continue;
  364 
  365                 if (strcmp(fstype, "linsysfs") == 0) {
  366                         sbuf_printf(sb, "/sys %s sysfs %s", mntto,
  367                             mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
  368                 } else {
  369                         /* For Linux msdosfs is called vfat */
  370                         if (strcmp(fstype, "msdosfs") == 0)
  371                                 fstype = "vfat";
  372                         sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
  373                             mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
  374                 }
  375 #define ADD_OPTION(opt, name) \
  376         if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name);
  377                 ADD_OPTION(MNT_SYNCHRONOUS,     "sync");
  378                 ADD_OPTION(MNT_NOEXEC,          "noexec");
  379                 ADD_OPTION(MNT_NOSUID,          "nosuid");
  380                 ADD_OPTION(MNT_UNION,           "union");
  381                 ADD_OPTION(MNT_ASYNC,           "async");
  382                 ADD_OPTION(MNT_SUIDDIR,         "suiddir");
  383                 ADD_OPTION(MNT_NOSYMFOLLOW,     "nosymfollow");
  384                 ADD_OPTION(MNT_NOATIME,         "noatime");
  385 #undef ADD_OPTION
  386                 /* a real Linux mtab will also show NFS options */
  387                 sbuf_printf(sb, " 0 0\n");
  388         }
  389         mtx_unlock(&mountlist_mtx);
  390         free(flep, M_TEMP);
  391         return (error);
  392 }
  393 
  394 /*
  395  * Filler function for proc/partitions
  396  *
  397  */
  398 static int
  399 linprocfs_dopartitions(PFS_FILL_ARGS)
  400 {
  401         struct g_class *cp;
  402         struct g_geom *gp;
  403         struct g_provider *pp;
  404         struct nameidata nd;
  405         const char *lep;
  406         char  *dlep, *flep;
  407         size_t lep_len;
  408         int error;
  409         int major, minor;
  410 
  411         /* resolve symlinks etc. in the emulation tree prefix */
  412         NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td);
  413         flep = NULL;
  414         error = namei(&nd);
  415         lep = linux_emul_path;
  416         if (error == 0) {
  417                 if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
  418                         lep = dlep;
  419                 vrele(nd.ni_vp);
  420         }
  421         lep_len = strlen(lep);
  422 
  423         g_topology_lock();
  424         error = 0;
  425         sbuf_printf(sb, "major minor  #blocks  name rio rmerge rsect "
  426             "ruse wio wmerge wsect wuse running use aveq\n");
  427 
  428         LIST_FOREACH(cp, &g_classes, class) {
  429                 if (strcmp(cp->name, "DISK") == 0 ||
  430                     strcmp(cp->name, "PART") == 0)
  431                         LIST_FOREACH(gp, &cp->geom, geom) {
  432                                 LIST_FOREACH(pp, &gp->provider, provider) {
  433                                         if (linux_driver_get_major_minor(
  434                                             pp->name, &major, &minor) != 0) {
  435                                                 major = 0;
  436                                                 minor = 0;
  437                                         }
  438                                         sbuf_printf(sb, "%d %d %lld %s "
  439                                             "%d %d %d %d %d "
  440                                              "%d %d %d %d %d %d\n",
  441                                              major, minor,
  442                                              (long long)pp->mediasize, pp->name,
  443                                              0, 0, 0, 0, 0,
  444                                              0, 0, 0, 0, 0, 0);
  445                                 }
  446                         }
  447         }
  448         g_topology_unlock();
  449 
  450         free(flep, M_TEMP);
  451         return (error);
  452 }
  453 
  454 
  455 /*
  456  * Filler function for proc/stat
  457  */
  458 static int
  459 linprocfs_dostat(PFS_FILL_ARGS)
  460 {
  461         struct pcpu *pcpu;
  462         long cp_time[CPUSTATES];
  463         long *cp;
  464         int i;
  465 
  466         read_cpu_time(cp_time);
  467         sbuf_printf(sb, "cpu %ld %ld %ld %ld\n",
  468             T2J(cp_time[CP_USER]),
  469             T2J(cp_time[CP_NICE]),
  470             T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
  471             T2J(cp_time[CP_IDLE]));
  472         CPU_FOREACH(i) {
  473                 pcpu = pcpu_find(i);
  474                 cp = pcpu->pc_cp_time;
  475                 sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i,
  476                     T2J(cp[CP_USER]),
  477                     T2J(cp[CP_NICE]),
  478                     T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/),
  479                     T2J(cp[CP_IDLE]));
  480         }
  481         sbuf_printf(sb,
  482             "disk 0 0 0 0\n"
  483             "page %u %u\n"
  484             "swap %u %u\n"
  485             "intr %u\n"
  486             "ctxt %u\n"
  487             "btime %lld\n",
  488             cnt.v_vnodepgsin,
  489             cnt.v_vnodepgsout,
  490             cnt.v_swappgsin,
  491             cnt.v_swappgsout,
  492             cnt.v_intr,
  493             cnt.v_swtch,
  494             (long long)boottime.tv_sec);
  495         return (0);
  496 }
  497 
  498 static int
  499 linprocfs_doswaps(PFS_FILL_ARGS)
  500 {
  501         struct xswdev xsw;
  502         uintmax_t total, used;
  503         int n;
  504         char devname[SPECNAMELEN + 1];
  505 
  506         sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
  507         mtx_lock(&Giant);
  508         for (n = 0; ; n++) {
  509                 if (swap_dev_info(n, &xsw, devname, sizeof(devname)) != 0)
  510                         break;
  511                 total = (uintmax_t)xsw.xsw_nblks * PAGE_SIZE / 1024;
  512                 used  = (uintmax_t)xsw.xsw_used * PAGE_SIZE / 1024;
  513 
  514                 /*
  515                  * The space and not tab after the device name is on
  516                  * purpose.  Linux does so.
  517                  */
  518                 sbuf_printf(sb, "/dev/%-34s unknown\t\t%jd\t%jd\t-1\n",
  519                     devname, total, used);
  520         }
  521         mtx_unlock(&Giant);
  522         return (0);
  523 }
  524 
  525 /*
  526  * Filler function for proc/uptime
  527  */
  528 static int
  529 linprocfs_douptime(PFS_FILL_ARGS)
  530 {
  531         long cp_time[CPUSTATES];
  532         struct timeval tv;
  533 
  534         getmicrouptime(&tv);
  535         read_cpu_time(cp_time);
  536         sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n",
  537             (long long)tv.tv_sec, tv.tv_usec / 10000,
  538             T2S(cp_time[CP_IDLE] / mp_ncpus),
  539             T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100);
  540         return (0);
  541 }
  542 
  543 /*
  544  * Get OS build date
  545  */
  546 static void
  547 linprocfs_osbuild(struct thread *td, struct sbuf *sb)
  548 {
  549 #if 0
  550         char osbuild[256];
  551         char *cp1, *cp2;
  552 
  553         strncpy(osbuild, version, 256);
  554         osbuild[255] = '\0';
  555         cp1 = strstr(osbuild, "\n");
  556         cp2 = strstr(osbuild, ":");
  557         if (cp1 && cp2) {
  558                 *cp1 = *cp2 = '\0';
  559                 cp1 = strstr(osbuild, "#");
  560         } else
  561                 cp1 = NULL;
  562         if (cp1)
  563                 sbuf_printf(sb, "%s%s", cp1, cp2 + 1);
  564         else
  565 #endif
  566                 sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977");
  567 }
  568 
  569 /*
  570  * Get OS builder
  571  */
  572 static void
  573 linprocfs_osbuilder(struct thread *td, struct sbuf *sb)
  574 {
  575 #if 0
  576         char builder[256];
  577         char *cp;
  578 
  579         cp = strstr(version, "\n    ");
  580         if (cp) {
  581                 strncpy(builder, cp + 5, 256);
  582                 builder[255] = '\0';
  583                 cp = strstr(builder, ":");
  584                 if (cp)
  585                         *cp = '\0';
  586         }
  587         if (cp)
  588                 sbuf_cat(sb, builder);
  589         else
  590 #endif
  591                 sbuf_cat(sb, "des@freebsd.org");
  592 }
  593 
  594 /*
  595  * Filler function for proc/version
  596  */
  597 static int
  598 linprocfs_doversion(PFS_FILL_ARGS)
  599 {
  600         char osname[LINUX_MAX_UTSNAME];
  601         char osrelease[LINUX_MAX_UTSNAME];
  602 
  603         linux_get_osname(td, osname);
  604         linux_get_osrelease(td, osrelease);
  605         sbuf_printf(sb, "%s version %s (", osname, osrelease);
  606         linprocfs_osbuilder(td, sb);
  607         sbuf_cat(sb, ") (gcc version " __VERSION__ ") ");
  608         linprocfs_osbuild(td, sb);
  609         sbuf_cat(sb, "\n");
  610 
  611         return (0);
  612 }
  613 
  614 /*
  615  * Filler function for proc/loadavg
  616  */
  617 static int
  618 linprocfs_doloadavg(PFS_FILL_ARGS)
  619 {
  620 
  621         sbuf_printf(sb,
  622             "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
  623             (int)(averunnable.ldavg[0] / averunnable.fscale),
  624             (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
  625             (int)(averunnable.ldavg[1] / averunnable.fscale),
  626             (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
  627             (int)(averunnable.ldavg[2] / averunnable.fscale),
  628             (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
  629             1,                          /* number of running tasks */
  630             nprocs,                     /* number of tasks */
  631             lastpid                     /* the last pid */
  632         );
  633         return (0);
  634 }
  635 
  636 /*
  637  * Filler function for proc/pid/stat
  638  */
  639 static int
  640 linprocfs_doprocstat(PFS_FILL_ARGS)
  641 {
  642         struct kinfo_proc kp;
  643         char state;
  644         static int ratelimit = 0;
  645         vm_offset_t startcode, startdata;
  646 
  647         PROC_LOCK(p);
  648         fill_kinfo_proc(p, &kp);
  649         if (p->p_vmspace) {
  650            startcode = (vm_offset_t)p->p_vmspace->vm_taddr;
  651            startdata = (vm_offset_t)p->p_vmspace->vm_daddr;
  652         } else {
  653            startcode = 0;
  654            startdata = 0;
  655         };
  656         sbuf_printf(sb, "%d", p->p_pid);
  657 #define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
  658         PS_ADD("comm",          "(%s)", p->p_comm);
  659         if (kp.ki_stat > sizeof(linux_state)) {
  660                 state = 'R';
  661 
  662                 if (ratelimit == 0) {
  663                         printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n",
  664                             kp.ki_stat, sizeof(linux_state));
  665                         ++ratelimit;
  666                 }
  667         } else
  668                 state = linux_state[kp.ki_stat - 1];
  669         PS_ADD("state",         "%c",   state);
  670         PS_ADD("ppid",          "%d",   p->p_pptr ? p->p_pptr->p_pid : 0);
  671         PS_ADD("pgrp",          "%d",   p->p_pgid);
  672         PS_ADD("session",       "%d",   p->p_session->s_sid);
  673         PROC_UNLOCK(p);
  674         PS_ADD("tty",           "%d",   kp.ki_tdev);
  675         PS_ADD("tpgid",         "%d",   kp.ki_tpgid);
  676         PS_ADD("flags",         "%u",   0); /* XXX */
  677         PS_ADD("minflt",        "%lu",  kp.ki_rusage.ru_minflt);
  678         PS_ADD("cminflt",       "%lu",  kp.ki_rusage_ch.ru_minflt);
  679         PS_ADD("majflt",        "%lu",  kp.ki_rusage.ru_majflt);
  680         PS_ADD("cmajflt",       "%lu",  kp.ki_rusage_ch.ru_majflt);
  681         PS_ADD("utime",         "%ld",  TV2J(&kp.ki_rusage.ru_utime));
  682         PS_ADD("stime",         "%ld",  TV2J(&kp.ki_rusage.ru_stime));
  683         PS_ADD("cutime",        "%ld",  TV2J(&kp.ki_rusage_ch.ru_utime));
  684         PS_ADD("cstime",        "%ld",  TV2J(&kp.ki_rusage_ch.ru_stime));
  685         PS_ADD("priority",      "%d",   kp.ki_pri.pri_user);
  686         PS_ADD("nice",          "%d",   kp.ki_nice); /* 19 (nicest) to -19 */
  687         PS_ADD("",             "%d",   0); /* removed field */
  688         PS_ADD("itrealvalue",   "%d",   0); /* XXX */
  689         PS_ADD("starttime",     "%lu",  TV2J(&kp.ki_start) - TV2J(&boottime));
  690         PS_ADD("vsize",         "%ju",  P2K((uintmax_t)kp.ki_size));
  691         PS_ADD("rss",           "%ju",  (uintmax_t)kp.ki_rssize);
  692         PS_ADD("rlim",          "%lu",  kp.ki_rusage.ru_maxrss);
  693         PS_ADD("startcode",     "%ju",  (uintmax_t)startcode);
  694         PS_ADD("endcode",       "%ju",  (uintmax_t)startdata);
  695         PS_ADD("startstack",    "%u",   0); /* XXX */
  696         PS_ADD("kstkesp",       "%u",   0); /* XXX */
  697         PS_ADD("kstkeip",       "%u",   0); /* XXX */
  698         PS_ADD("signal",        "%u",   0); /* XXX */
  699         PS_ADD("blocked",       "%u",   0); /* XXX */
  700         PS_ADD("sigignore",     "%u",   0); /* XXX */
  701         PS_ADD("sigcatch",      "%u",   0); /* XXX */
  702         PS_ADD("wchan",         "%u",   0); /* XXX */
  703         PS_ADD("nswap",         "%lu",  kp.ki_rusage.ru_nswap);
  704         PS_ADD("cnswap",        "%lu",  kp.ki_rusage_ch.ru_nswap);
  705         PS_ADD("exitsignal",    "%d",   0); /* XXX */
  706         PS_ADD("processor",     "%u",   kp.ki_lastcpu);
  707         PS_ADD("rt_priority",   "%u",   0); /* XXX */ /* >= 2.5.19 */
  708         PS_ADD("policy",        "%u",   kp.ki_pri.pri_class); /* >= 2.5.19 */
  709 #undef PS_ADD
  710         sbuf_putc(sb, '\n');
  711 
  712         return (0);
  713 }
  714 
  715 /*
  716  * Filler function for proc/pid/statm
  717  */
  718 static int
  719 linprocfs_doprocstatm(PFS_FILL_ARGS)
  720 {
  721         struct kinfo_proc kp;
  722         segsz_t lsize;
  723 
  724         PROC_LOCK(p);
  725         fill_kinfo_proc(p, &kp);
  726         PROC_UNLOCK(p);
  727 
  728         /*
  729          * See comments in linprocfs_doprocstatus() regarding the
  730          * computation of lsize.
  731          */
  732         /* size resident share trs drs lrs dt */
  733         sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size));
  734         sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize);
  735         sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */
  736         sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize);
  737         sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize));
  738         lsize = B2P(kp.ki_size) - kp.ki_dsize -
  739             kp.ki_ssize - kp.ki_tsize - 1;
  740         sbuf_printf(sb, "%ju ", (uintmax_t)lsize);
  741         sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */
  742 
  743         return (0);
  744 }
  745 
  746 /*
  747  * Filler function for proc/pid/status
  748  */
  749 static int
  750 linprocfs_doprocstatus(PFS_FILL_ARGS)
  751 {
  752         struct kinfo_proc kp;
  753         char *state;
  754         segsz_t lsize;
  755         struct thread *td2;
  756         struct sigacts *ps;
  757         int i;
  758 
  759         PROC_LOCK(p);
  760         td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */
  761 
  762         if (P_SHOULDSTOP(p)) {
  763                 state = "T (stopped)";
  764         } else {
  765                 switch(p->p_state) {
  766                 case PRS_NEW:
  767                         state = "I (idle)";
  768                         break;
  769                 case PRS_NORMAL:
  770                         if (p->p_flag & P_WEXIT) {
  771                                 state = "X (exiting)";
  772                                 break;
  773                         }
  774                         switch(td2->td_state) {
  775                         case TDS_INHIBITED:
  776                                 state = "S (sleeping)";
  777                                 break;
  778                         case TDS_RUNQ:
  779                         case TDS_RUNNING:
  780                                 state = "R (running)";
  781                                 break;
  782                         default:
  783                                 state = "? (unknown)";
  784                                 break;
  785                         }
  786                         break;
  787                 case PRS_ZOMBIE:
  788                         state = "Z (zombie)";
  789                         break;
  790                 default:
  791                         state = "? (unknown)";
  792                         break;
  793                 }
  794         }
  795 
  796         fill_kinfo_proc(p, &kp);
  797         sbuf_printf(sb, "Name:\t%s\n",          p->p_comm); /* XXX escape */
  798         sbuf_printf(sb, "State:\t%s\n",         state);
  799 
  800         /*
  801          * Credentials
  802          */
  803         sbuf_printf(sb, "Pid:\t%d\n",           p->p_pid);
  804         sbuf_printf(sb, "PPid:\t%d\n",          p->p_pptr ?
  805                                                 p->p_pptr->p_pid : 0);
  806         sbuf_printf(sb, "Uid:\t%d %d %d %d\n",  p->p_ucred->cr_ruid,
  807                                                 p->p_ucred->cr_uid,
  808                                                 p->p_ucred->cr_svuid,
  809                                                 /* FreeBSD doesn't have fsuid */
  810                                                 p->p_ucred->cr_uid);
  811         sbuf_printf(sb, "Gid:\t%d %d %d %d\n",  p->p_ucred->cr_rgid,
  812                                                 p->p_ucred->cr_gid,
  813                                                 p->p_ucred->cr_svgid,
  814                                                 /* FreeBSD doesn't have fsgid */
  815                                                 p->p_ucred->cr_gid);
  816         sbuf_cat(sb, "Groups:\t");
  817         for (i = 0; i < p->p_ucred->cr_ngroups; i++)
  818                 sbuf_printf(sb, "%d ",          p->p_ucred->cr_groups[i]);
  819         PROC_UNLOCK(p);
  820         sbuf_putc(sb, '\n');
  821 
  822         /*
  823          * Memory
  824          *
  825          * While our approximation of VmLib may not be accurate (I
  826          * don't know of a simple way to verify it, and I'm not sure
  827          * it has much meaning anyway), I believe it's good enough.
  828          *
  829          * The same code that could (I think) accurately compute VmLib
  830          * could also compute VmLck, but I don't really care enough to
  831          * implement it. Submissions are welcome.
  832          */
  833         sbuf_printf(sb, "VmSize:\t%8ju kB\n",   B2K((uintmax_t)kp.ki_size));
  834         sbuf_printf(sb, "VmLck:\t%8u kB\n",     P2K(0)); /* XXX */
  835         sbuf_printf(sb, "VmRSS:\t%8ju kB\n",    P2K((uintmax_t)kp.ki_rssize));
  836         sbuf_printf(sb, "VmData:\t%8ju kB\n",   P2K((uintmax_t)kp.ki_dsize));
  837         sbuf_printf(sb, "VmStk:\t%8ju kB\n",    P2K((uintmax_t)kp.ki_ssize));
  838         sbuf_printf(sb, "VmExe:\t%8ju kB\n",    P2K((uintmax_t)kp.ki_tsize));
  839         lsize = B2P(kp.ki_size) - kp.ki_dsize -
  840             kp.ki_ssize - kp.ki_tsize - 1;
  841         sbuf_printf(sb, "VmLib:\t%8ju kB\n",    P2K((uintmax_t)lsize));
  842 
  843         /*
  844          * Signal masks
  845          *
  846          * We support up to 128 signals, while Linux supports 32,
  847          * but we only define 32 (the same 32 as Linux, to boot), so
  848          * just show the lower 32 bits of each mask. XXX hack.
  849          *
  850          * NB: on certain platforms (Sparc at least) Linux actually
  851          * supports 64 signals, but this code is a long way from
  852          * running on anything but i386, so ignore that for now.
  853          */
  854         PROC_LOCK(p);
  855         sbuf_printf(sb, "SigPnd:\t%08x\n",      p->p_siglist.__bits[0]);
  856         /*
  857          * I can't seem to find out where the signal mask is in
  858          * relation to struct proc, so SigBlk is left unimplemented.
  859          */
  860         sbuf_printf(sb, "SigBlk:\t%08x\n",      0); /* XXX */
  861         ps = p->p_sigacts;
  862         mtx_lock(&ps->ps_mtx);
  863         sbuf_printf(sb, "SigIgn:\t%08x\n",      ps->ps_sigignore.__bits[0]);
  864         sbuf_printf(sb, "SigCgt:\t%08x\n",      ps->ps_sigcatch.__bits[0]);
  865         mtx_unlock(&ps->ps_mtx);
  866         PROC_UNLOCK(p);
  867 
  868         /*
  869          * Linux also prints the capability masks, but we don't have
  870          * capabilities yet, and when we do get them they're likely to
  871          * be meaningless to Linux programs, so we lie. XXX
  872          */
  873         sbuf_printf(sb, "CapInh:\t%016x\n",     0);
  874         sbuf_printf(sb, "CapPrm:\t%016x\n",     0);
  875         sbuf_printf(sb, "CapEff:\t%016x\n",     0);
  876 
  877         return (0);
  878 }
  879 
  880 
  881 /*
  882  * Filler function for proc/pid/cwd
  883  */
  884 static int
  885 linprocfs_doproccwd(PFS_FILL_ARGS)
  886 {
  887         char *fullpath = "unknown";
  888         char *freepath = NULL;
  889 
  890         vn_fullpath(td, p->p_fd->fd_cdir, &fullpath, &freepath);
  891         sbuf_printf(sb, "%s", fullpath);
  892         if (freepath)
  893                 free(freepath, M_TEMP);
  894         return (0);
  895 }
  896 
  897 /*
  898  * Filler function for proc/pid/root
  899  */
  900 static int
  901 linprocfs_doprocroot(PFS_FILL_ARGS)
  902 {
  903         struct vnode *rvp;
  904         char *fullpath = "unknown";
  905         char *freepath = NULL;
  906 
  907         rvp = jailed(p->p_ucred) ? p->p_fd->fd_jdir : p->p_fd->fd_rdir;
  908         vn_fullpath(td, rvp, &fullpath, &freepath);
  909         sbuf_printf(sb, "%s", fullpath);
  910         if (freepath)
  911                 free(freepath, M_TEMP);
  912         return (0);
  913 }
  914 
  915 /*
  916  * Filler function for proc/pid/cmdline
  917  */
  918 static int
  919 linprocfs_doproccmdline(PFS_FILL_ARGS)
  920 {
  921         int ret;
  922 
  923         PROC_LOCK(p);
  924         if ((ret = p_cansee(td, p)) != 0) {
  925                 PROC_UNLOCK(p);
  926                 return (ret);
  927         }
  928 
  929         /*
  930          * Mimic linux behavior and pass only processes with usermode
  931          * address space as valid.  Return zero silently otherwize.
  932          */
  933         if (p->p_vmspace == &vmspace0) {
  934                 PROC_UNLOCK(p);
  935                 return (0);
  936         }
  937         if (p->p_args != NULL) {
  938                 sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
  939                 PROC_UNLOCK(p);
  940                 return (0);
  941         }
  942 
  943         if ((p->p_flag & P_SYSTEM) != 0) {
  944                 PROC_UNLOCK(p);
  945                 return (0);
  946         }
  947 
  948         PROC_UNLOCK(p);
  949 
  950         ret = proc_getargv(td, p, sb);
  951         return (ret);
  952 }
  953 
  954 /*
  955  * Filler function for proc/pid/environ
  956  */
  957 static int
  958 linprocfs_doprocenviron(PFS_FILL_ARGS)
  959 {
  960         int ret;
  961 
  962         PROC_LOCK(p);
  963         if ((ret = p_candebug(td, p)) != 0) {
  964                 PROC_UNLOCK(p);
  965                 return (ret);
  966         }
  967 
  968         /*
  969          * Mimic linux behavior and pass only processes with usermode
  970          * address space as valid.  Return zero silently otherwize.
  971          */
  972         if (p->p_vmspace == &vmspace0) {
  973                 PROC_UNLOCK(p);
  974                 return (0);
  975         }
  976 
  977         if ((p->p_flag & P_SYSTEM) != 0) {
  978                 PROC_UNLOCK(p);
  979                 return (0);
  980         }
  981 
  982         PROC_UNLOCK(p);
  983 
  984         ret = proc_getenvv(td, p, sb);
  985         return (ret);
  986 }
  987 
  988 /*
  989  * Filler function for proc/pid/maps
  990  */
  991 static int
  992 linprocfs_doprocmaps(PFS_FILL_ARGS)
  993 {
  994         struct vmspace *vm;
  995         vm_map_t map;
  996         vm_map_entry_t entry, tmp_entry;
  997         vm_object_t obj, tobj, lobj;
  998         vm_offset_t e_start, e_end;
  999         vm_ooffset_t off = 0;
 1000         vm_prot_t e_prot;
 1001         unsigned int last_timestamp;
 1002         char *name = "", *freename = NULL;
 1003         ino_t ino;
 1004         int ref_count, shadow_count, flags;
 1005         int error;
 1006         struct vnode *vp;
 1007         struct vattr vat;
 1008 
 1009         PROC_LOCK(p);
 1010         error = p_candebug(td, p);
 1011         PROC_UNLOCK(p);
 1012         if (error)
 1013                 return (error);
 1014 
 1015         if (uio->uio_rw != UIO_READ)
 1016                 return (EOPNOTSUPP);
 1017 
 1018         error = 0;
 1019         vm = vmspace_acquire_ref(p);
 1020         if (vm == NULL)
 1021                 return (ESRCH);
 1022         map = &vm->vm_map;
 1023         vm_map_lock_read(map);
 1024         for (entry = map->header.next; entry != &map->header;
 1025             entry = entry->next) {
 1026                 name = "";
 1027                 freename = NULL;
 1028                 if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
 1029                         continue;
 1030                 e_prot = entry->protection;
 1031                 e_start = entry->start;
 1032                 e_end = entry->end;
 1033                 obj = entry->object.vm_object;
 1034                 for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) {
 1035                         VM_OBJECT_RLOCK(tobj);
 1036                         if (lobj != obj)
 1037                                 VM_OBJECT_RUNLOCK(lobj);
 1038                         lobj = tobj;
 1039                 }
 1040                 last_timestamp = map->timestamp;
 1041                 vm_map_unlock_read(map);
 1042                 ino = 0;
 1043                 if (lobj) {
 1044                         off = IDX_TO_OFF(lobj->size);
 1045                         if (lobj->type == OBJT_VNODE) {
 1046                                 vp = lobj->handle;
 1047                                 if (vp)
 1048                                         vref(vp);
 1049                         }
 1050                         else
 1051                                 vp = NULL;
 1052                         if (lobj != obj)
 1053                                 VM_OBJECT_RUNLOCK(lobj);
 1054                         flags = obj->flags;
 1055                         ref_count = obj->ref_count;
 1056                         shadow_count = obj->shadow_count;
 1057                         VM_OBJECT_RUNLOCK(obj);
 1058                         if (vp) {
 1059                                 vn_fullpath(td, vp, &name, &freename);
 1060                                 vn_lock(vp, LK_SHARED | LK_RETRY);
 1061                                 VOP_GETATTR(vp, &vat, td->td_ucred);
 1062                                 ino = vat.va_fileid;
 1063                                 vput(vp);
 1064                         }
 1065                 } else {
 1066                         flags = 0;
 1067                         ref_count = 0;
 1068                         shadow_count = 0;
 1069                 }
 1070 
 1071                 /*
 1072                  * format:
 1073                  *  start, end, access, offset, major, minor, inode, name.
 1074                  */
 1075                 error = sbuf_printf(sb,
 1076                     "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n",
 1077                     (u_long)e_start, (u_long)e_end,
 1078                     (e_prot & VM_PROT_READ)?"r":"-",
 1079                     (e_prot & VM_PROT_WRITE)?"w":"-",
 1080                     (e_prot & VM_PROT_EXECUTE)?"x":"-",
 1081                     "p",
 1082                     (u_long)off,
 1083                     0,
 1084                     0,
 1085                     (u_long)ino,
 1086                     *name ? "     " : "",
 1087                     name
 1088                     );
 1089                 if (freename)
 1090                         free(freename, M_TEMP);
 1091                 vm_map_lock_read(map);
 1092                 if (error == -1) {
 1093                         error = 0;
 1094                         break;
 1095                 }
 1096                 if (last_timestamp != map->timestamp) {
 1097                         /*
 1098                          * Look again for the entry because the map was
 1099                          * modified while it was unlocked.  Specifically,
 1100                          * the entry may have been clipped, merged, or deleted.
 1101                          */
 1102                         vm_map_lookup_entry(map, e_end - 1, &tmp_entry);
 1103                         entry = tmp_entry;
 1104                 }
 1105         }
 1106         vm_map_unlock_read(map);
 1107         vmspace_free(vm);
 1108 
 1109         return (error);
 1110 }
 1111 
 1112 /*
 1113  * Filler function for proc/net/dev
 1114  */
 1115 static int
 1116 linprocfs_donetdev(PFS_FILL_ARGS)
 1117 {
 1118         char ifname[16]; /* XXX LINUX_IFNAMSIZ */
 1119         struct ifnet *ifp;
 1120 
 1121         sbuf_printf(sb, "%6s|%58s|%s\n"
 1122             "%6s|%58s|%58s\n",
 1123             "Inter-", "   Receive", "  Transmit",
 1124             " face",
 1125             "bytes    packets errs drop fifo frame compressed multicast",
 1126             "bytes    packets errs drop fifo colls carrier compressed");
 1127 
 1128         CURVNET_SET(TD_TO_VNET(curthread));
 1129         IFNET_RLOCK();
 1130         TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 1131                 linux_ifname(ifp, ifname, sizeof ifname);
 1132                 sbuf_printf(sb, "%6.6s: ", ifname);
 1133                 sbuf_printf(sb, "%7lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ",
 1134                     ifp->if_ibytes,     /* rx_bytes */
 1135                     ifp->if_ipackets,   /* rx_packets */
 1136                     ifp->if_ierrors,    /* rx_errors */
 1137                     ifp->if_iqdrops,    /* rx_dropped +
 1138                                          * rx_missed_errors */
 1139                     0UL,                /* rx_fifo_errors */
 1140                     0UL,                /* rx_length_errors +
 1141                                          * rx_over_errors +
 1142                                          * rx_crc_errors +
 1143                                          * rx_frame_errors */
 1144                     0UL,                /* rx_compressed */
 1145                     ifp->if_imcasts);   /* multicast, XXX-BZ rx only? */
 1146                 sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
 1147                     ifp->if_obytes,     /* tx_bytes */
 1148                     ifp->if_opackets,   /* tx_packets */
 1149                     ifp->if_oerrors,    /* tx_errors */
 1150                     0UL,                /* tx_dropped */
 1151                     0UL,                /* tx_fifo_errors */
 1152                     ifp->if_collisions, /* collisions */
 1153                     0UL,                /* tx_carrier_errors +
 1154                                          * tx_aborted_errors +
 1155                                          * tx_window_errors +
 1156                                          * tx_heartbeat_errors */
 1157                     0UL);               /* tx_compressed */
 1158         }
 1159         IFNET_RUNLOCK();
 1160         CURVNET_RESTORE();
 1161 
 1162         return (0);
 1163 }
 1164 
 1165 /*
 1166  * Filler function for proc/sys/kernel/osrelease
 1167  */
 1168 static int
 1169 linprocfs_doosrelease(PFS_FILL_ARGS)
 1170 {
 1171         char osrelease[LINUX_MAX_UTSNAME];
 1172 
 1173         linux_get_osrelease(td, osrelease);
 1174         sbuf_printf(sb, "%s\n", osrelease);
 1175 
 1176         return (0);
 1177 }
 1178 
 1179 /*
 1180  * Filler function for proc/sys/kernel/ostype
 1181  */
 1182 static int
 1183 linprocfs_doostype(PFS_FILL_ARGS)
 1184 {
 1185         char osname[LINUX_MAX_UTSNAME];
 1186 
 1187         linux_get_osname(td, osname);
 1188         sbuf_printf(sb, "%s\n", osname);
 1189 
 1190         return (0);
 1191 }
 1192 
 1193 /*
 1194  * Filler function for proc/sys/kernel/version
 1195  */
 1196 static int
 1197 linprocfs_doosbuild(PFS_FILL_ARGS)
 1198 {
 1199 
 1200         linprocfs_osbuild(td, sb);
 1201         sbuf_cat(sb, "\n");
 1202         return (0);
 1203 }
 1204 
 1205 /*
 1206  * Filler function for proc/sys/kernel/msgmni
 1207  */
 1208 static int
 1209 linprocfs_domsgmni(PFS_FILL_ARGS)
 1210 {
 1211 
 1212         sbuf_printf(sb, "%d\n", msginfo.msgmni);
 1213         return (0);
 1214 }
 1215 
 1216 /*
 1217  * Filler function for proc/sys/kernel/pid_max
 1218  */
 1219 static int
 1220 linprocfs_dopid_max(PFS_FILL_ARGS)
 1221 {
 1222 
 1223         sbuf_printf(sb, "%i\n", PID_MAX);
 1224         return (0);
 1225 }
 1226 
 1227 /*
 1228  * Filler function for proc/sys/kernel/sem
 1229  */
 1230 static int
 1231 linprocfs_dosem(PFS_FILL_ARGS)
 1232 {
 1233 
 1234         sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns,
 1235             seminfo.semopm, seminfo.semmni);
 1236         return (0);
 1237 }
 1238 
 1239 /*
 1240  * Filler function for proc/scsi/device_info
 1241  */
 1242 static int
 1243 linprocfs_doscsidevinfo(PFS_FILL_ARGS)
 1244 {
 1245 
 1246         return (0);
 1247 }
 1248 
 1249 /*
 1250  * Filler function for proc/scsi/scsi
 1251  */
 1252 static int
 1253 linprocfs_doscsiscsi(PFS_FILL_ARGS)
 1254 {
 1255 
 1256         return (0);
 1257 }
 1258 
 1259 extern struct cdevsw *cdevsw[];
 1260 
 1261 /*
 1262  * Filler function for proc/devices
 1263  */
 1264 static int
 1265 linprocfs_dodevices(PFS_FILL_ARGS)
 1266 {
 1267         char *char_devices;
 1268         sbuf_printf(sb, "Character devices:\n");
 1269 
 1270         char_devices = linux_get_char_devices();
 1271         sbuf_printf(sb, "%s", char_devices);
 1272         linux_free_get_char_devices(char_devices);
 1273 
 1274         sbuf_printf(sb, "\nBlock devices:\n");
 1275 
 1276         return (0);
 1277 }
 1278 
 1279 /*
 1280  * Filler function for proc/cmdline
 1281  */
 1282 static int
 1283 linprocfs_docmdline(PFS_FILL_ARGS)
 1284 {
 1285 
 1286         sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
 1287         sbuf_printf(sb, " ro root=302\n");
 1288         return (0);
 1289 }
 1290 
 1291 /*
 1292  * Filler function for proc/filesystems
 1293  */
 1294 static int
 1295 linprocfs_dofilesystems(PFS_FILL_ARGS)
 1296 {
 1297         struct vfsconf *vfsp;
 1298 
 1299         mtx_lock(&Giant);
 1300         TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
 1301                 if (vfsp->vfc_flags & VFCF_SYNTHETIC)
 1302                         sbuf_printf(sb, "nodev");
 1303                 sbuf_printf(sb, "\t%s\n", vfsp->vfc_name);
 1304         }
 1305         mtx_unlock(&Giant);
 1306         return(0);
 1307 }
 1308 
 1309 #if 0
 1310 /*
 1311  * Filler function for proc/modules
 1312  */
 1313 static int
 1314 linprocfs_domodules(PFS_FILL_ARGS)
 1315 {
 1316         struct linker_file *lf;
 1317 
 1318         TAILQ_FOREACH(lf, &linker_files, link) {
 1319                 sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
 1320                     (unsigned long)lf->size, lf->refs);
 1321         }
 1322         return (0);
 1323 }
 1324 #endif
 1325 
 1326 /*
 1327  * Filler function for proc/pid/fd
 1328  */
 1329 static int
 1330 linprocfs_dofdescfs(PFS_FILL_ARGS)
 1331 {
 1332 
 1333         if (p == curproc)
 1334                 sbuf_printf(sb, "/dev/fd");
 1335         else
 1336                 sbuf_printf(sb, "unknown");
 1337         return (0);
 1338 }
 1339 
 1340 
 1341 /*
 1342  * Filler function for proc/sys/kernel/random/uuid
 1343  */
 1344 static int
 1345 linprocfs_douuid(PFS_FILL_ARGS)
 1346 {
 1347         struct uuid uuid;
 1348 
 1349         kern_uuidgen(&uuid, 1);
 1350         sbuf_printf_uuid(sb, &uuid);
 1351         sbuf_printf(sb, "\n");
 1352         return(0);
 1353 }
 1354 
 1355 
 1356 /*
 1357  * Constructor
 1358  */
 1359 static int
 1360 linprocfs_init(PFS_INIT_ARGS)
 1361 {
 1362         struct pfs_node *root;
 1363         struct pfs_node *dir;
 1364 
 1365         root = pi->pi_root;
 1366 
 1367         /* /proc/... */
 1368         pfs_create_file(root, "cmdline", &linprocfs_docmdline,
 1369             NULL, NULL, NULL, PFS_RD);
 1370         pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
 1371             NULL, NULL, NULL, PFS_RD);
 1372         pfs_create_file(root, "devices", &linprocfs_dodevices,
 1373             NULL, NULL, NULL, PFS_RD);
 1374         pfs_create_file(root, "filesystems", &linprocfs_dofilesystems,
 1375             NULL, NULL, NULL, PFS_RD);
 1376         pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
 1377             NULL, NULL, NULL, PFS_RD);
 1378         pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
 1379             NULL, NULL, NULL, PFS_RD);
 1380 #if 0
 1381         pfs_create_file(root, "modules", &linprocfs_domodules,
 1382             NULL, NULL, NULL, PFS_RD);
 1383 #endif
 1384         pfs_create_file(root, "mounts", &linprocfs_domtab,
 1385             NULL, NULL, NULL, PFS_RD);
 1386         pfs_create_file(root, "mtab", &linprocfs_domtab,
 1387             NULL, NULL, NULL, PFS_RD);
 1388         pfs_create_file(root, "partitions", &linprocfs_dopartitions,
 1389             NULL, NULL, NULL, PFS_RD);
 1390         pfs_create_link(root, "self", &procfs_docurproc,
 1391             NULL, NULL, NULL, 0);
 1392         pfs_create_file(root, "stat", &linprocfs_dostat,
 1393             NULL, NULL, NULL, PFS_RD);
 1394         pfs_create_file(root, "swaps", &linprocfs_doswaps,
 1395             NULL, NULL, NULL, PFS_RD);
 1396         pfs_create_file(root, "uptime", &linprocfs_douptime,
 1397             NULL, NULL, NULL, PFS_RD);
 1398         pfs_create_file(root, "version", &linprocfs_doversion,
 1399             NULL, NULL, NULL, PFS_RD);
 1400 
 1401         /* /proc/net/... */
 1402         dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
 1403         pfs_create_file(dir, "dev", &linprocfs_donetdev,
 1404             NULL, NULL, NULL, PFS_RD);
 1405 
 1406         /* /proc/<pid>/... */
 1407         dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
 1408         pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
 1409             NULL, NULL, NULL, PFS_RD);
 1410         pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
 1411             NULL, NULL, NULL, 0);
 1412         pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
 1413             NULL, NULL, NULL, PFS_RD);
 1414         pfs_create_link(dir, "exe", &procfs_doprocfile,
 1415             NULL, &procfs_notsystem, NULL, 0);
 1416         pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
 1417             NULL, NULL, NULL, PFS_RD);
 1418         pfs_create_file(dir, "mem", &procfs_doprocmem,
 1419             &procfs_attr, &procfs_candebug, NULL, PFS_RDWR|PFS_RAW);
 1420         pfs_create_link(dir, "root", &linprocfs_doprocroot,
 1421             NULL, NULL, NULL, 0);
 1422         pfs_create_file(dir, "stat", &linprocfs_doprocstat,
 1423             NULL, NULL, NULL, PFS_RD);
 1424         pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
 1425             NULL, NULL, NULL, PFS_RD);
 1426         pfs_create_file(dir, "status", &linprocfs_doprocstatus,
 1427             NULL, NULL, NULL, PFS_RD);
 1428         pfs_create_link(dir, "fd", &linprocfs_dofdescfs,
 1429             NULL, NULL, NULL, 0);
 1430 
 1431         /* /proc/scsi/... */
 1432         dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
 1433         pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
 1434             NULL, NULL, NULL, PFS_RD);
 1435         pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
 1436             NULL, NULL, NULL, PFS_RD);
 1437 
 1438         /* /proc/sys/... */
 1439         dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
 1440         /* /proc/sys/kernel/... */
 1441         dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0);
 1442         pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
 1443             NULL, NULL, NULL, PFS_RD);
 1444         pfs_create_file(dir, "ostype", &linprocfs_doostype,
 1445             NULL, NULL, NULL, PFS_RD);
 1446         pfs_create_file(dir, "version", &linprocfs_doosbuild,
 1447             NULL, NULL, NULL, PFS_RD);
 1448         pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
 1449             NULL, NULL, NULL, PFS_RD);
 1450         pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
 1451             NULL, NULL, NULL, PFS_RD);
 1452         pfs_create_file(dir, "sem", &linprocfs_dosem,
 1453             NULL, NULL, NULL, PFS_RD);
 1454 
 1455         /* /proc/sys/kernel/random/... */
 1456         dir = pfs_create_dir(dir, "random", NULL, NULL, NULL, 0);
 1457         pfs_create_file(dir, "uuid", &linprocfs_douuid,
 1458             NULL, NULL, NULL, PFS_RD);
 1459 
 1460         return (0);
 1461 }
 1462 
 1463 /*
 1464  * Destructor
 1465  */
 1466 static int
 1467 linprocfs_uninit(PFS_INIT_ARGS)
 1468 {
 1469 
 1470         /* nothing to do, pseudofs will GC */
 1471         return (0);
 1472 }
 1473 
 1474 PSEUDOFS(linprocfs, 1, 0);
 1475 MODULE_DEPEND(linprocfs, linux, 1, 1, 1);
 1476 MODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
 1477 MODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);
 1478 MODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1);

Cache object: c6732c10e383c56b9cca2cfc7046408e


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