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

Cache object: 1de714a50f24a42f891e96a575b7696b


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