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

Cache object: 4c2f5b8b80e90df08f7b1c1fd03a80f1


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