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

Cache object: 3bdb2a9b1ef26ee6ca03984ce5a73080


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