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  * SPDX-License-Identifier: BSD-4-Clause
    3  *
    4  * Copyright (c) 2000 Dag-Erling Coïdan Smørgrav
    5  * Copyright (c) 1999 Pierre Beyssac
    6  * Copyright (c) 1993 Jan-Simon Pendry
    7  * Copyright (c) 1993
    8  *      The Regents of the University of California.  All rights reserved.
    9  *
   10  * This code is derived from software contributed to Berkeley by
   11  * Jan-Simon Pendry.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 3. All advertising materials mentioning features or use of this software
   22  *    must display the following acknowledgement:
   23  *      This product includes software developed by the University of
   24  *      California, Berkeley and its contributors.
   25  * 4. Neither the name of the University nor the names of its contributors
   26  *    may be used to endorse or promote products derived from this software
   27  *    without specific prior written permission.
   28  *
   29  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   30  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   31  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   32  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   33  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   34  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   35  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   37  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   38  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   39  * SUCH DAMAGE.
   40  *
   41  *      @(#)procfs_status.c     8.4 (Berkeley) 6/15/94
   42  */
   43 
   44 #include <sys/cdefs.h>
   45 __FBSDID("$FreeBSD$");
   46 
   47 #include <sys/param.h>
   48 #include <sys/queue.h>
   49 #include <sys/blist.h>
   50 #include <sys/conf.h>
   51 #include <sys/exec.h>
   52 #include <sys/fcntl.h>
   53 #include <sys/filedesc.h>
   54 #include <sys/jail.h>
   55 #include <sys/kernel.h>
   56 #include <sys/limits.h>
   57 #include <sys/linker.h>
   58 #include <sys/lock.h>
   59 #include <sys/malloc.h>
   60 #include <sys/msg.h>
   61 #include <sys/mutex.h>
   62 #include <sys/namei.h>
   63 #include <sys/proc.h>
   64 #include <sys/ptrace.h>
   65 #include <sys/resourcevar.h>
   66 #include <sys/resource.h>
   67 #include <sys/sbuf.h>
   68 #include <sys/sem.h>
   69 #include <sys/shm.h>
   70 #include <sys/smp.h>
   71 #include <sys/socket.h>
   72 #include <sys/syscallsubr.h>
   73 #include <sys/sysctl.h>
   74 #include <sys/sysent.h>
   75 #include <sys/systm.h>
   76 #include <sys/time.h>
   77 #include <sys/tty.h>
   78 #include <sys/user.h>
   79 #include <sys/uuid.h>
   80 #include <sys/vmmeter.h>
   81 #include <sys/vnode.h>
   82 #include <sys/bus.h>
   83 
   84 #include <net/if.h>
   85 #include <net/if_var.h>
   86 #include <net/if_types.h>
   87 
   88 #include <vm/vm.h>
   89 #include <vm/vm_extern.h>
   90 #include <vm/pmap.h>
   91 #include <vm/vm_map.h>
   92 #include <vm/vm_param.h>
   93 #include <vm/vm_object.h>
   94 #include <vm/swap_pager.h>
   95 
   96 #include <machine/clock.h>
   97 
   98 #include <geom/geom.h>
   99 #include <geom/geom_int.h>
  100 
  101 #if defined(__i386__) || defined(__amd64__)
  102 #include <machine/cputypes.h>
  103 #include <machine/md_var.h>
  104 #endif /* __i386__ || __amd64__ */
  105 
  106 #include <compat/linux/linux.h>
  107 #include <compat/linux/linux_mib.h>
  108 #include <compat/linux/linux_misc.h>
  109 #include <compat/linux/linux_util.h>
  110 #include <fs/pseudofs/pseudofs.h>
  111 #include <fs/procfs/procfs.h>
  112 
  113 /*
  114  * Various conversion macros
  115  */
  116 #define T2J(x) ((long)(((x) * 100ULL) / (stathz ? stathz : hz)))        /* ticks to jiffies */
  117 #define T2CS(x) ((unsigned long)(((x) * 100ULL) / (stathz ? stathz : hz)))      /* ticks to centiseconds */
  118 #define T2S(x) ((x) / (stathz ? stathz : hz))           /* ticks to seconds */
  119 #define B2K(x) ((x) >> 10)                              /* bytes to kbytes */
  120 #define B2P(x) ((x) >> PAGE_SHIFT)                      /* bytes to pages */
  121 #define P2B(x) ((x) << PAGE_SHIFT)                      /* pages to bytes */
  122 #define P2K(x) ((x) << (PAGE_SHIFT - 10))               /* pages to kbytes */
  123 #define TV2J(x) ((x)->tv_sec * 100UL + (x)->tv_usec / 10000)
  124 
  125 /**
  126  * @brief Mapping of ki_stat in struct kinfo_proc to the linux state
  127  *
  128  * The linux procfs state field displays one of the characters RSDZTW to
  129  * denote running, sleeping in an interruptible wait, waiting in an
  130  * uninterruptible disk sleep, a zombie process, process is being traced
  131  * or stopped, or process is paging respectively.
  132  *
  133  * Our struct kinfo_proc contains the variable ki_stat which contains a
  134  * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK.
  135  *
  136  * This character array is used with ki_stati-1 as an index and tries to
  137  * map our states to suitable linux states.
  138  */
  139 static char linux_state[] = "RRSTZDD";
  140 
  141 /*
  142  * Filler function for proc/meminfo
  143  */
  144 static int
  145 linprocfs_domeminfo(PFS_FILL_ARGS)
  146 {
  147         unsigned long memtotal;         /* total memory in bytes */
  148         unsigned long memfree;          /* free memory in bytes */
  149         unsigned long cached;           /* page cache */
  150         unsigned long buffers;          /* buffer cache */
  151         unsigned long long swaptotal;   /* total swap space in bytes */
  152         unsigned long long swapused;    /* used swap space in bytes */
  153         unsigned long long swapfree;    /* free swap space in bytes */
  154         size_t sz;
  155         int error, i, j;
  156 
  157         memtotal = physmem * PAGE_SIZE;
  158         memfree = (unsigned long)vm_free_count() * PAGE_SIZE;
  159         swap_pager_status(&i, &j);
  160         swaptotal = (unsigned long long)i * PAGE_SIZE;
  161         swapused = (unsigned long long)j * PAGE_SIZE;
  162         swapfree = swaptotal - swapused;
  163 
  164         /*
  165          * This value may exclude wired pages, but we have no good way of
  166          * accounting for that.
  167          */
  168         cached =
  169             (vm_active_count() + vm_inactive_count() + vm_laundry_count()) *
  170             PAGE_SIZE;
  171 
  172         sz = sizeof(buffers);
  173         error = kernel_sysctlbyname(curthread, "vfs.bufspace", &buffers, &sz,
  174             NULL, 0, 0, 0);
  175         if (error != 0)
  176                 buffers = 0;
  177 
  178         sbuf_printf(sb,
  179             "MemTotal: %9lu kB\n"
  180             "MemFree:  %9lu kB\n"
  181             "Buffers:  %9lu kB\n"
  182             "Cached:   %9lu kB\n"
  183             "SwapTotal:%9llu kB\n"
  184             "SwapFree: %9llu kB\n",
  185             B2K(memtotal), B2K(memfree), B2K(buffers),
  186             B2K(cached), B2K(swaptotal), B2K(swapfree));
  187 
  188         return (0);
  189 }
  190 
  191 #if defined(__i386__) || defined(__amd64__)
  192 /*
  193  * Filler function for proc/cpuinfo (i386 & amd64 version)
  194  */
  195 static int
  196 linprocfs_docpuinfo(PFS_FILL_ARGS)
  197 {
  198         int hw_model[2];
  199         char model[128];
  200         uint64_t freq;
  201         size_t size;
  202         u_int cache_size[4];
  203         int fqmhz, fqkhz;
  204         int i, j;
  205 
  206         /*
  207          * We default the flags to include all non-conflicting flags,
  208          * and the Intel versions of conflicting flags.
  209          */
  210         static char *cpu_feature_names[] = {
  211                 /*  0 */ "fpu", "vme", "de", "pse",
  212                 /*  4 */ "tsc", "msr", "pae", "mce",
  213                 /*  8 */ "cx8", "apic", "", "sep",
  214                 /* 12 */ "mtrr", "pge", "mca", "cmov",
  215                 /* 16 */ "pat", "pse36", "pn", "clflush",
  216                 /* 20 */ "", "dts", "acpi", "mmx",
  217                 /* 24 */ "fxsr", "sse", "sse2", "ss",
  218                 /* 28 */ "ht", "tm", "ia64", "pbe"
  219         };
  220 
  221         static char *amd_feature_names[] = {
  222                 /*  0 */ "", "", "", "",
  223                 /*  4 */ "", "", "", "",
  224                 /*  8 */ "", "", "", "syscall",
  225                 /* 12 */ "", "", "", "",
  226                 /* 16 */ "", "", "", "mp",
  227                 /* 20 */ "nx", "", "mmxext", "",
  228                 /* 24 */ "", "fxsr_opt", "pdpe1gb", "rdtscp",
  229                 /* 28 */ "", "lm", "3dnowext", "3dnow"
  230         };
  231 
  232         static char *cpu_feature2_names[] = {
  233                 /*  0 */ "pni", "pclmulqdq", "dtes64", "monitor",
  234                 /*  4 */ "ds_cpl", "vmx", "smx", "est",
  235                 /*  8 */ "tm2", "ssse3", "cid", "sdbg",
  236                 /* 12 */ "fma", "cx16", "xtpr", "pdcm",
  237                 /* 16 */ "", "pcid", "dca", "sse4_1",
  238                 /* 20 */ "sse4_2", "x2apic", "movbe", "popcnt",
  239                 /* 24 */ "tsc_deadline_timer", "aes", "xsave", "",
  240                 /* 28 */ "avx", "f16c", "rdrand", "hypervisor"
  241         };
  242 
  243         static char *amd_feature2_names[] = {
  244                 /*  0 */ "lahf_lm", "cmp_legacy", "svm", "extapic",
  245                 /*  4 */ "cr8_legacy", "abm", "sse4a", "misalignsse",
  246                 /*  8 */ "3dnowprefetch", "osvw", "ibs", "xop",
  247                 /* 12 */ "skinit", "wdt", "", "lwp",
  248                 /* 16 */ "fma4", "tce", "", "nodeid_msr",
  249                 /* 20 */ "", "tbm", "topoext", "perfctr_core",
  250                 /* 24 */ "perfctr_nb", "", "bpext", "ptsc",
  251                 /* 28 */ "perfctr_llc", "mwaitx", "", ""
  252         };
  253 
  254         static char *cpu_stdext_feature_names[] = {
  255                 /*  0 */ "fsgsbase", "tsc_adjust", "", "bmi1",
  256                 /*  4 */ "hle", "avx2", "", "smep",
  257                 /*  8 */ "bmi2", "erms", "invpcid", "rtm",
  258                 /* 12 */ "cqm", "", "mpx", "rdt_a",
  259                 /* 16 */ "avx512f", "avx512dq", "rdseed", "adx",
  260                 /* 20 */ "smap", "avx512ifma", "", "clflushopt",
  261                 /* 24 */ "clwb", "intel_pt", "avx512pf", "avx512er",
  262                 /* 28 */ "avx512cd", "sha_ni", "avx512bw", "avx512vl"
  263         };
  264 
  265         static char *power_flags[] = {
  266                 "ts",           "fid",          "vid",
  267                 "ttp",          "tm",           "stc",
  268                 "100mhzsteps",  "hwpstate",     "",
  269                 "cpb",          "eff_freq_ro",  "proc_feedback",
  270                 "acc_power",
  271         };
  272 
  273         hw_model[0] = CTL_HW;
  274         hw_model[1] = HW_MODEL;
  275         model[0] = '\0';
  276         size = sizeof(model);
  277         if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0)
  278                 strcpy(model, "unknown");
  279 #ifdef __i386__
  280         switch (cpu_vendor_id) {
  281         case CPU_VENDOR_AMD:
  282                 if (cpu_class < CPUCLASS_686)
  283                         cpu_feature_names[16] = "fcmov";
  284                 break;
  285         case CPU_VENDOR_CYRIX:
  286                 cpu_feature_names[24] = "cxmmx";
  287                 break;
  288         }
  289 #endif
  290         if (cpu_exthigh >= 0x80000006)
  291                 do_cpuid(0x80000006, cache_size);
  292         else
  293                 memset(cache_size, 0, sizeof(cache_size));
  294         for (i = 0; i < mp_ncpus; ++i) {
  295                 fqmhz = 0;
  296                 fqkhz = 0;
  297                 freq = atomic_load_acq_64(&tsc_freq);
  298                 if (freq != 0) {
  299                         fqmhz = (freq + 4999) / 1000000;
  300                         fqkhz = ((freq + 4999) / 10000) % 100;
  301                 }
  302                 sbuf_printf(sb,
  303                     "processor\t: %d\n"
  304                     "vendor_id\t: %.20s\n"
  305                     "cpu family\t: %u\n"
  306                     "model\t\t: %u\n"
  307                     "model name\t: %s\n"
  308                     "stepping\t: %u\n"
  309                     "cpu MHz\t\t: %d.%02d\n"
  310                     "cache size\t: %d KB\n"
  311                     "physical id\t: %d\n"
  312                     "siblings\t: %d\n"
  313                     "core id\t\t: %d\n"
  314                     "cpu cores\t: %d\n"
  315                     "apicid\t\t: %d\n"
  316                     "initial apicid\t: %d\n"
  317                     "fpu\t\t: %s\n"
  318                     "fpu_exception\t: %s\n"
  319                     "cpuid level\t: %d\n"
  320                     "wp\t\t: %s\n",
  321                     i, cpu_vendor, CPUID_TO_FAMILY(cpu_id),
  322                     CPUID_TO_MODEL(cpu_id), model, cpu_id & CPUID_STEPPING,
  323                     fqmhz, fqkhz,
  324                     (cache_size[2] >> 16), 0, mp_ncpus, i, mp_ncpus,
  325                     i, i, /*cpu_id & CPUID_LOCAL_APIC_ID ??*/
  326                     (cpu_feature & CPUID_FPU) ? "yes" : "no", "yes",
  327                     CPUID_TO_FAMILY(cpu_id), "yes");
  328                 sbuf_cat(sb, "flags\t\t:");
  329                 for (j = 0; j < nitems(cpu_feature_names); j++)
  330                         if (cpu_feature & (1 << j) &&
  331                             cpu_feature_names[j][0] != '\0')
  332                                 sbuf_printf(sb, " %s", cpu_feature_names[j]);
  333                 for (j = 0; j < nitems(amd_feature_names); j++)
  334                         if (amd_feature & (1 << j) &&
  335                             amd_feature_names[j][0] != '\0')
  336                                 sbuf_printf(sb, " %s", amd_feature_names[j]);
  337                 for (j = 0; j < nitems(cpu_feature2_names); j++)
  338                         if (cpu_feature2 & (1 << j) &&
  339                             cpu_feature2_names[j][0] != '\0')
  340                                 sbuf_printf(sb, " %s", cpu_feature2_names[j]);
  341                 for (j = 0; j < nitems(amd_feature2_names); j++)
  342                         if (amd_feature2 & (1 << j) &&
  343                             amd_feature2_names[j][0] != '\0')
  344                                 sbuf_printf(sb, " %s", amd_feature2_names[j]);
  345                 for (j = 0; j < nitems(cpu_stdext_feature_names); j++)
  346                         if (cpu_stdext_feature & (1 << j) &&
  347                             cpu_stdext_feature_names[j][0] != '\0')
  348                                 sbuf_printf(sb, " %s",
  349                                     cpu_stdext_feature_names[j]);
  350                 sbuf_cat(sb, "\n");
  351                 sbuf_printf(sb,
  352                     "bugs\t\t: %s\n"
  353                     "bogomips\t: %d.%02d\n"
  354                     "clflush size\t: %d\n"
  355                     "cache_alignment\t: %d\n"
  356                     "address sizes\t: %d bits physical, %d bits virtual\n",
  357 #if defined(I586_CPU) && !defined(NO_F00F_HACK)
  358                     (has_f00f_bug) ? "Intel F00F" : "",
  359 #else
  360                     "",
  361 #endif
  362                     fqmhz * 2, fqkhz,
  363                     cpu_clflush_line_size, cpu_clflush_line_size,
  364                     cpu_maxphyaddr,
  365                     (cpu_maxphyaddr > 32) ? 48 : 0);
  366                 sbuf_cat(sb, "power management: ");
  367                 for (j = 0; j < nitems(power_flags); j++)
  368                         if (amd_pminfo & (1 << j))
  369                                 sbuf_printf(sb, " %s", power_flags[j]);
  370                 sbuf_cat(sb, "\n\n");
  371 
  372                 /* XXX per-cpu vendor / class / model / id? */
  373         }
  374         sbuf_cat(sb, "\n");
  375 
  376         return (0);
  377 }
  378 #else
  379 /* ARM64TODO: implement non-stubbed linprocfs_docpuinfo */
  380 static int
  381 linprocfs_docpuinfo(PFS_FILL_ARGS)
  382 {
  383         int i;
  384 
  385         for (i = 0; i < mp_ncpus; ++i) {
  386                 sbuf_printf(sb,
  387                     "processor\t: %d\n"
  388                     "BogoMIPS\t: %d.%02d\n",
  389                     i, 0, 0);
  390                 sbuf_cat(sb, "Features\t: ");
  391                 sbuf_cat(sb, "\n");
  392                 sbuf_printf(sb,
  393                     "CPU implementer\t: \n"
  394                     "CPU architecture: \n"
  395                     "CPU variant\t: 0x%x\n"
  396                     "CPU part\t: 0x%x\n"
  397                     "CPU revision\t: %d\n",
  398                     0, 0, 0);
  399                 sbuf_cat(sb, "\n");
  400         }
  401 
  402         return (0);
  403 }
  404 #endif /* __i386__ || __amd64__ */
  405 
  406 /*
  407  * Filler function for proc/mtab
  408  *
  409  * This file doesn't exist in Linux' procfs, but is included here so
  410  * users can symlink /compat/linux/etc/mtab to /proc/mtab
  411  */
  412 static int
  413 linprocfs_domtab(PFS_FILL_ARGS)
  414 {
  415         struct nameidata nd;
  416         const char *lep;
  417         char *dlep, *flep, *mntto, *mntfrom, *fstype;
  418         size_t lep_len;
  419         int error;
  420         struct statfs *buf, *sp;
  421         size_t count;
  422 
  423         /* resolve symlinks etc. in the emulation tree prefix */
  424         NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, linux_emul_path, td);
  425         flep = NULL;
  426         error = namei(&nd);
  427         lep = linux_emul_path;
  428         if (error == 0) {
  429                 if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
  430                         lep = dlep;
  431                 vrele(nd.ni_vp);
  432         }
  433         lep_len = strlen(lep);
  434 
  435         buf = NULL;
  436         error = kern_getfsstat(td, &buf, SIZE_T_MAX, &count,
  437             UIO_SYSSPACE, MNT_WAIT);
  438         if (error != 0) {
  439                 free(buf, M_TEMP);
  440                 free(flep, M_TEMP);
  441                 return (error);
  442         }
  443 
  444         for (sp = buf; count > 0; sp++, count--) {
  445                 /* determine device name */
  446                 mntfrom = sp->f_mntfromname;
  447 
  448                 /* determine mount point */
  449                 mntto = sp->f_mntonname;
  450                 if (strncmp(mntto, lep, lep_len) == 0 && mntto[lep_len] == '/')
  451                         mntto += lep_len;
  452 
  453                 /* determine fs type */
  454                 fstype = sp->f_fstypename;
  455                 if (strcmp(fstype, pn->pn_info->pi_name) == 0)
  456                         mntfrom = fstype = "proc";
  457                 else if (strcmp(fstype, "procfs") == 0)
  458                         continue;
  459 
  460                 if (strcmp(fstype, "autofs") == 0) {
  461                         /*
  462                          * FreeBSD uses eg "map -hosts", whereas Linux
  463                          * expects just "-hosts".
  464                          */
  465                         if (strncmp(mntfrom, "map ", 4) == 0)
  466                                 mntfrom += 4;
  467                 }
  468 
  469                 if (strcmp(fstype, "linsysfs") == 0) {
  470                         sbuf_printf(sb, "/sys %s sysfs %s", mntto,
  471                             sp->f_flags & MNT_RDONLY ? "ro" : "rw");
  472                 } else {
  473                         /* For Linux msdosfs is called vfat */
  474                         if (strcmp(fstype, "msdosfs") == 0)
  475                                 fstype = "vfat";
  476                         sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
  477                             sp->f_flags & MNT_RDONLY ? "ro" : "rw");
  478                 }
  479 #define ADD_OPTION(opt, name) \
  480         if (sp->f_flags & (opt)) sbuf_printf(sb, "," name);
  481                 ADD_OPTION(MNT_SYNCHRONOUS,     "sync");
  482                 ADD_OPTION(MNT_NOEXEC,          "noexec");
  483                 ADD_OPTION(MNT_NOSUID,          "nosuid");
  484                 ADD_OPTION(MNT_UNION,           "union");
  485                 ADD_OPTION(MNT_ASYNC,           "async");
  486                 ADD_OPTION(MNT_SUIDDIR,         "suiddir");
  487                 ADD_OPTION(MNT_NOSYMFOLLOW,     "nosymfollow");
  488                 ADD_OPTION(MNT_NOATIME,         "noatime");
  489 #undef ADD_OPTION
  490                 /* a real Linux mtab will also show NFS options */
  491                 sbuf_printf(sb, " 0 0\n");
  492         }
  493 
  494         free(buf, M_TEMP);
  495         free(flep, M_TEMP);
  496         return (error);
  497 }
  498 
  499 /*
  500  * Filler function for proc/partitions
  501  */
  502 static int
  503 linprocfs_dopartitions(PFS_FILL_ARGS)
  504 {
  505         struct g_class *cp;
  506         struct g_geom *gp;
  507         struct g_provider *pp;
  508         int major, minor;
  509 
  510         g_topology_lock();
  511         sbuf_printf(sb, "major minor  #blocks  name rio rmerge rsect "
  512             "ruse wio wmerge wsect wuse running use aveq\n");
  513 
  514         LIST_FOREACH(cp, &g_classes, class) {
  515                 if (strcmp(cp->name, "DISK") == 0 ||
  516                     strcmp(cp->name, "PART") == 0)
  517                         LIST_FOREACH(gp, &cp->geom, geom) {
  518                                 LIST_FOREACH(pp, &gp->provider, provider) {
  519                                         if (linux_driver_get_major_minor(
  520                                             pp->name, &major, &minor) != 0) {
  521                                                 major = 0;
  522                                                 minor = 0;
  523                                         }
  524                                         sbuf_printf(sb, "%d %d %lld %s "
  525                                             "%d %d %d %d %d "
  526                                              "%d %d %d %d %d %d\n",
  527                                              major, minor,
  528                                              (long long)pp->mediasize, pp->name,
  529                                              0, 0, 0, 0, 0,
  530                                              0, 0, 0, 0, 0, 0);
  531                                 }
  532                         }
  533         }
  534         g_topology_unlock();
  535 
  536         return (0);
  537 }
  538 
  539 /*
  540  * Filler function for proc/stat
  541  *
  542  * Output depends on kernel version:
  543  *
  544  * v2.5.40 <=
  545  *   user nice system idle
  546  * v2.5.41
  547  *   user nice system idle iowait
  548  * v2.6.11
  549  *   user nice system idle iowait irq softirq steal
  550  * v2.6.24
  551  *   user nice system idle iowait irq softirq steal guest
  552  * v2.6.33 >=
  553  *   user nice system idle iowait irq softirq steal guest guest_nice
  554  */
  555 static int
  556 linprocfs_dostat(PFS_FILL_ARGS)
  557 {
  558         struct pcpu *pcpu;
  559         long cp_time[CPUSTATES];
  560         long *cp;
  561         struct timeval boottime;
  562         int i;
  563         char *zero_pad;
  564         bool has_intr = true;
  565 
  566         if (linux_kernver(td) >= LINUX_KERNVER(2,6,33)) {
  567                 zero_pad = " 0 0 0 0\n";
  568         } else if (linux_kernver(td) >= LINUX_KERNVER(2,6,24)) {
  569                 zero_pad = " 0 0 0\n";
  570         } else if (linux_kernver(td) >= LINUX_KERNVER(2,6,11)) {
  571                 zero_pad = " 0 0\n";
  572         } else if (linux_kernver(td) >= LINUX_KERNVER(2,5,41)) {
  573                 has_intr = false;
  574                 zero_pad = " 0\n";
  575         } else {
  576                 has_intr = false;
  577                 zero_pad = "\n";
  578         }
  579 
  580         read_cpu_time(cp_time);
  581         getboottime(&boottime);
  582         /* Parameters common to all versions */
  583         sbuf_printf(sb, "cpu %lu %lu %lu %lu",
  584             T2J(cp_time[CP_USER]),
  585             T2J(cp_time[CP_NICE]),
  586             T2J(cp_time[CP_SYS]),
  587             T2J(cp_time[CP_IDLE]));
  588 
  589         /* Print interrupt stats if available */
  590         if (has_intr) {
  591                 sbuf_printf(sb, " 0 %lu", T2J(cp_time[CP_INTR]));
  592         }
  593 
  594         /* Pad out remaining fields depending on version */
  595         sbuf_printf(sb, "%s", zero_pad);
  596 
  597         CPU_FOREACH(i) {
  598                 pcpu = pcpu_find(i);
  599                 cp = pcpu->pc_cp_time;
  600                 sbuf_printf(sb, "cpu%d %lu %lu %lu %lu", i,
  601                     T2J(cp[CP_USER]),
  602                     T2J(cp[CP_NICE]),
  603                     T2J(cp[CP_SYS]),
  604                     T2J(cp[CP_IDLE]));
  605 
  606                 if (has_intr) {
  607                         sbuf_printf(sb, " 0 %lu", T2J(cp[CP_INTR]));
  608                 }
  609 
  610                 sbuf_printf(sb, "%s", zero_pad);
  611         }
  612         sbuf_printf(sb,
  613             "disk 0 0 0 0\n"
  614             "page %ju %ju\n"
  615             "swap %ju %ju\n"
  616             "intr %ju\n"
  617             "ctxt %ju\n"
  618             "btime %lld\n",
  619             (uintmax_t)VM_CNT_FETCH(v_vnodepgsin),
  620             (uintmax_t)VM_CNT_FETCH(v_vnodepgsout),
  621             (uintmax_t)VM_CNT_FETCH(v_swappgsin),
  622             (uintmax_t)VM_CNT_FETCH(v_swappgsout),
  623             (uintmax_t)VM_CNT_FETCH(v_intr),
  624             (uintmax_t)VM_CNT_FETCH(v_swtch),
  625             (long long)boottime.tv_sec);
  626         return (0);
  627 }
  628 
  629 static int
  630 linprocfs_doswaps(PFS_FILL_ARGS)
  631 {
  632         struct xswdev xsw;
  633         uintmax_t total, used;
  634         int n;
  635         char devname[SPECNAMELEN + 1];
  636 
  637         sbuf_printf(sb, "Filename\t\t\t\tType\t\tSize\tUsed\tPriority\n");
  638         for (n = 0; ; n++) {
  639                 if (swap_dev_info(n, &xsw, devname, sizeof(devname)) != 0)
  640                         break;
  641                 total = (uintmax_t)xsw.xsw_nblks * PAGE_SIZE / 1024;
  642                 used  = (uintmax_t)xsw.xsw_used * PAGE_SIZE / 1024;
  643 
  644                 /*
  645                  * The space and not tab after the device name is on
  646                  * purpose.  Linux does so.
  647                  */
  648                 sbuf_printf(sb, "/dev/%-34s unknown\t\t%jd\t%jd\t-1\n",
  649                     devname, total, used);
  650         }
  651         return (0);
  652 }
  653 
  654 /*
  655  * Filler function for proc/uptime
  656  */
  657 static int
  658 linprocfs_douptime(PFS_FILL_ARGS)
  659 {
  660         long cp_time[CPUSTATES];
  661         struct timeval tv;
  662 
  663         getmicrouptime(&tv);
  664         read_cpu_time(cp_time);
  665         sbuf_printf(sb, "%lld.%02ld %ld.%02lu\n",
  666             (long long)tv.tv_sec, tv.tv_usec / 10000,
  667             T2S(cp_time[CP_IDLE] / mp_ncpus),
  668             T2CS(cp_time[CP_IDLE] / mp_ncpus) % 100);
  669         return (0);
  670 }
  671 
  672 /*
  673  * Get OS build date
  674  */
  675 static void
  676 linprocfs_osbuild(struct thread *td, struct sbuf *sb)
  677 {
  678 #if 0
  679         char osbuild[256];
  680         char *cp1, *cp2;
  681 
  682         strncpy(osbuild, version, 256);
  683         osbuild[255] = '\0';
  684         cp1 = strstr(osbuild, "\n");
  685         cp2 = strstr(osbuild, ":");
  686         if (cp1 && cp2) {
  687                 *cp1 = *cp2 = '\0';
  688                 cp1 = strstr(osbuild, "#");
  689         } else
  690                 cp1 = NULL;
  691         if (cp1)
  692                 sbuf_printf(sb, "%s%s", cp1, cp2 + 1);
  693         else
  694 #endif
  695                 sbuf_cat(sb, "#4 Sun Dec 18 04:30:00 CET 1977");
  696 }
  697 
  698 /*
  699  * Get OS builder
  700  */
  701 static void
  702 linprocfs_osbuilder(struct thread *td, struct sbuf *sb)
  703 {
  704 #if 0
  705         char builder[256];
  706         char *cp;
  707 
  708         cp = strstr(version, "\n    ");
  709         if (cp) {
  710                 strncpy(builder, cp + 5, 256);
  711                 builder[255] = '\0';
  712                 cp = strstr(builder, ":");
  713                 if (cp)
  714                         *cp = '\0';
  715         }
  716         if (cp)
  717                 sbuf_cat(sb, builder);
  718         else
  719 #endif
  720                 sbuf_cat(sb, "des@freebsd.org");
  721 }
  722 
  723 /*
  724  * Filler function for proc/version
  725  */
  726 static int
  727 linprocfs_doversion(PFS_FILL_ARGS)
  728 {
  729         char osname[LINUX_MAX_UTSNAME];
  730         char osrelease[LINUX_MAX_UTSNAME];
  731 
  732         linux_get_osname(td, osname);
  733         linux_get_osrelease(td, osrelease);
  734         sbuf_printf(sb, "%s version %s (", osname, osrelease);
  735         linprocfs_osbuilder(td, sb);
  736         sbuf_cat(sb, ") (gcc version " __VERSION__ ") ");
  737         linprocfs_osbuild(td, sb);
  738         sbuf_cat(sb, "\n");
  739 
  740         return (0);
  741 }
  742 
  743 /*
  744  * Filler function for proc/loadavg
  745  */
  746 static int
  747 linprocfs_doloadavg(PFS_FILL_ARGS)
  748 {
  749 
  750         sbuf_printf(sb,
  751             "%d.%02d %d.%02d %d.%02d %d/%d %d\n",
  752             (int)(averunnable.ldavg[0] / averunnable.fscale),
  753             (int)(averunnable.ldavg[0] * 100 / averunnable.fscale % 100),
  754             (int)(averunnable.ldavg[1] / averunnable.fscale),
  755             (int)(averunnable.ldavg[1] * 100 / averunnable.fscale % 100),
  756             (int)(averunnable.ldavg[2] / averunnable.fscale),
  757             (int)(averunnable.ldavg[2] * 100 / averunnable.fscale % 100),
  758             1,                          /* number of running tasks */
  759             nprocs,                     /* number of tasks */
  760             lastpid                     /* the last pid */
  761         );
  762         return (0);
  763 }
  764 
  765 static int
  766 linprocfs_get_tty_nr(struct proc *p)
  767 {
  768         struct session *sp;
  769         const char *ttyname;
  770         int error, major, minor, nr;
  771 
  772         PROC_LOCK_ASSERT(p, MA_OWNED);
  773         sx_assert(&proctree_lock, SX_LOCKED);
  774 
  775         if ((p->p_flag & P_CONTROLT) == 0)
  776                 return (-1);
  777 
  778         sp = p->p_pgrp->pg_session;
  779         if (sp == NULL)
  780                 return (-1);
  781 
  782         ttyname = devtoname(sp->s_ttyp->t_dev);
  783         error = linux_driver_get_major_minor(ttyname, &major, &minor);
  784         if (error != 0)
  785                 return (-1);
  786 
  787         nr = makedev(major, minor);
  788         return (nr);
  789 }
  790 
  791 /*
  792  * Filler function for proc/pid/stat
  793  */
  794 static int
  795 linprocfs_doprocstat(PFS_FILL_ARGS)
  796 {
  797         struct kinfo_proc kp;
  798         struct timeval boottime;
  799         char state;
  800         static int ratelimit = 0;
  801         int tty_nr;
  802         vm_offset_t startcode, startdata;
  803 
  804         getboottime(&boottime);
  805         sx_slock(&proctree_lock);
  806         PROC_LOCK(p);
  807         fill_kinfo_proc(p, &kp);
  808         tty_nr = linprocfs_get_tty_nr(p);
  809         sx_sunlock(&proctree_lock);
  810         if (p->p_vmspace) {
  811            startcode = (vm_offset_t)p->p_vmspace->vm_taddr;
  812            startdata = (vm_offset_t)p->p_vmspace->vm_daddr;
  813         } else {
  814            startcode = 0;
  815            startdata = 0;
  816         }
  817         sbuf_printf(sb, "%d", p->p_pid);
  818 #define PS_ADD(name, fmt, arg) sbuf_printf(sb, " " fmt, arg)
  819         PS_ADD("comm",          "(%s)", p->p_comm);
  820         if (kp.ki_stat > sizeof(linux_state)) {
  821                 state = 'R';
  822 
  823                 if (ratelimit == 0) {
  824                         printf("linprocfs: don't know how to handle unknown FreeBSD state %d/%zd, mapping to R\n",
  825                             kp.ki_stat, sizeof(linux_state));
  826                         ++ratelimit;
  827                 }
  828         } else
  829                 state = linux_state[kp.ki_stat - 1];
  830         PS_ADD("state",         "%c",   state);
  831         PS_ADD("ppid",          "%d",   p->p_pptr ? p->p_pptr->p_pid : 0);
  832         PS_ADD("pgrp",          "%d",   p->p_pgid);
  833         PS_ADD("session",       "%d",   p->p_session->s_sid);
  834         PROC_UNLOCK(p);
  835         PS_ADD("tty",           "%d",   tty_nr);
  836         PS_ADD("tpgid",         "%d",   kp.ki_tpgid);
  837         PS_ADD("flags",         "%u",   0); /* XXX */
  838         PS_ADD("minflt",        "%lu",  kp.ki_rusage.ru_minflt);
  839         PS_ADD("cminflt",       "%lu",  kp.ki_rusage_ch.ru_minflt);
  840         PS_ADD("majflt",        "%lu",  kp.ki_rusage.ru_majflt);
  841         PS_ADD("cmajflt",       "%lu",  kp.ki_rusage_ch.ru_majflt);
  842         PS_ADD("utime",         "%ld",  TV2J(&kp.ki_rusage.ru_utime));
  843         PS_ADD("stime",         "%ld",  TV2J(&kp.ki_rusage.ru_stime));
  844         PS_ADD("cutime",        "%ld",  TV2J(&kp.ki_rusage_ch.ru_utime));
  845         PS_ADD("cstime",        "%ld",  TV2J(&kp.ki_rusage_ch.ru_stime));
  846         PS_ADD("priority",      "%d",   kp.ki_pri.pri_user);
  847         PS_ADD("nice",          "%d",   kp.ki_nice); /* 19 (nicest) to -19 */
  848         PS_ADD("",             "%d",   0); /* removed field */
  849         PS_ADD("itrealvalue",   "%d",   0); /* XXX */
  850         PS_ADD("starttime",     "%lu",  TV2J(&kp.ki_start) - TV2J(&boottime));
  851         PS_ADD("vsize",         "%ju",  P2K((uintmax_t)kp.ki_size));
  852         PS_ADD("rss",           "%ju",  (uintmax_t)kp.ki_rssize);
  853         PS_ADD("rlim",          "%lu",  kp.ki_rusage.ru_maxrss);
  854         PS_ADD("startcode",     "%ju",  (uintmax_t)startcode);
  855         PS_ADD("endcode",       "%ju",  (uintmax_t)startdata);
  856         PS_ADD("startstack",    "%u",   0); /* XXX */
  857         PS_ADD("kstkesp",       "%u",   0); /* XXX */
  858         PS_ADD("kstkeip",       "%u",   0); /* XXX */
  859         PS_ADD("signal",        "%u",   0); /* XXX */
  860         PS_ADD("blocked",       "%u",   0); /* XXX */
  861         PS_ADD("sigignore",     "%u",   0); /* XXX */
  862         PS_ADD("sigcatch",      "%u",   0); /* XXX */
  863         PS_ADD("wchan",         "%u",   0); /* XXX */
  864         PS_ADD("nswap",         "%lu",  kp.ki_rusage.ru_nswap);
  865         PS_ADD("cnswap",        "%lu",  kp.ki_rusage_ch.ru_nswap);
  866         PS_ADD("exitsignal",    "%d",   0); /* XXX */
  867         PS_ADD("processor",     "%u",   kp.ki_lastcpu);
  868         PS_ADD("rt_priority",   "%u",   0); /* XXX */ /* >= 2.5.19 */
  869         PS_ADD("policy",        "%u",   kp.ki_pri.pri_class); /* >= 2.5.19 */
  870 #undef PS_ADD
  871         sbuf_putc(sb, '\n');
  872 
  873         return (0);
  874 }
  875 
  876 /*
  877  * Filler function for proc/pid/statm
  878  */
  879 static int
  880 linprocfs_doprocstatm(PFS_FILL_ARGS)
  881 {
  882         struct kinfo_proc kp;
  883         segsz_t lsize;
  884 
  885         sx_slock(&proctree_lock);
  886         PROC_LOCK(p);
  887         fill_kinfo_proc(p, &kp);
  888         PROC_UNLOCK(p);
  889         sx_sunlock(&proctree_lock);
  890 
  891         /*
  892          * See comments in linprocfs_doprocstatus() regarding the
  893          * computation of lsize.
  894          */
  895         /* size resident share trs drs lrs dt */
  896         sbuf_printf(sb, "%ju ", B2P((uintmax_t)kp.ki_size));
  897         sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_rssize);
  898         sbuf_printf(sb, "%ju ", (uintmax_t)0); /* XXX */
  899         sbuf_printf(sb, "%ju ", (uintmax_t)kp.ki_tsize);
  900         sbuf_printf(sb, "%ju ", (uintmax_t)(kp.ki_dsize + kp.ki_ssize));
  901         lsize = B2P(kp.ki_size) - kp.ki_dsize -
  902             kp.ki_ssize - kp.ki_tsize - 1;
  903         sbuf_printf(sb, "%ju ", (uintmax_t)lsize);
  904         sbuf_printf(sb, "%ju\n", (uintmax_t)0); /* XXX */
  905 
  906         return (0);
  907 }
  908 
  909 /*
  910  * Filler function for proc/pid/status
  911  */
  912 static int
  913 linprocfs_doprocstatus(PFS_FILL_ARGS)
  914 {
  915         struct kinfo_proc kp;
  916         char *state;
  917         segsz_t lsize;
  918         struct thread *td2;
  919         struct sigacts *ps;
  920         l_sigset_t siglist, sigignore, sigcatch;
  921         int i;
  922 
  923         sx_slock(&proctree_lock);
  924         PROC_LOCK(p);
  925         td2 = FIRST_THREAD_IN_PROC(p); /* XXXKSE pretend only one thread */
  926 
  927         if (P_SHOULDSTOP(p)) {
  928                 state = "T (stopped)";
  929         } else {
  930                 switch(p->p_state) {
  931                 case PRS_NEW:
  932                         state = "I (idle)";
  933                         break;
  934                 case PRS_NORMAL:
  935                         if (p->p_flag & P_WEXIT) {
  936                                 state = "X (exiting)";
  937                                 break;
  938                         }
  939                         switch(td2->td_state) {
  940                         case TDS_INHIBITED:
  941                                 state = "S (sleeping)";
  942                                 break;
  943                         case TDS_RUNQ:
  944                         case TDS_RUNNING:
  945                                 state = "R (running)";
  946                                 break;
  947                         default:
  948                                 state = "? (unknown)";
  949                                 break;
  950                         }
  951                         break;
  952                 case PRS_ZOMBIE:
  953                         state = "Z (zombie)";
  954                         break;
  955                 default:
  956                         state = "? (unknown)";
  957                         break;
  958                 }
  959         }
  960 
  961         fill_kinfo_proc(p, &kp);
  962         sx_sunlock(&proctree_lock);
  963 
  964         sbuf_printf(sb, "Name:\t%s\n",          p->p_comm); /* XXX escape */
  965         sbuf_printf(sb, "State:\t%s\n",         state);
  966 
  967         /*
  968          * Credentials
  969          */
  970         sbuf_printf(sb, "Tgid:\t%d\n",          p->p_pid);
  971         sbuf_printf(sb, "Pid:\t%d\n",           p->p_pid);
  972         sbuf_printf(sb, "PPid:\t%d\n",          kp.ki_ppid );
  973         sbuf_printf(sb, "TracerPid:\t%d\n",     kp.ki_tracer );
  974         sbuf_printf(sb, "Uid:\t%d %d %d %d\n",  p->p_ucred->cr_ruid,
  975                                                 p->p_ucred->cr_uid,
  976                                                 p->p_ucred->cr_svuid,
  977                                                 /* FreeBSD doesn't have fsuid */
  978                                                 p->p_ucred->cr_uid);
  979         sbuf_printf(sb, "Gid:\t%d %d %d %d\n",  p->p_ucred->cr_rgid,
  980                                                 p->p_ucred->cr_gid,
  981                                                 p->p_ucred->cr_svgid,
  982                                                 /* FreeBSD doesn't have fsgid */
  983                                                 p->p_ucred->cr_gid);
  984         sbuf_cat(sb, "Groups:\t");
  985         for (i = 0; i < p->p_ucred->cr_ngroups; i++)
  986                 sbuf_printf(sb, "%d ",          p->p_ucred->cr_groups[i]);
  987         PROC_UNLOCK(p);
  988         sbuf_putc(sb, '\n');
  989 
  990         /*
  991          * Memory
  992          *
  993          * While our approximation of VmLib may not be accurate (I
  994          * don't know of a simple way to verify it, and I'm not sure
  995          * it has much meaning anyway), I believe it's good enough.
  996          *
  997          * The same code that could (I think) accurately compute VmLib
  998          * could also compute VmLck, but I don't really care enough to
  999          * implement it. Submissions are welcome.
 1000          */
 1001         sbuf_printf(sb, "VmSize:\t%8ju kB\n",   B2K((uintmax_t)kp.ki_size));
 1002         sbuf_printf(sb, "VmLck:\t%8u kB\n",     P2K(0)); /* XXX */
 1003         sbuf_printf(sb, "VmRSS:\t%8ju kB\n",    P2K((uintmax_t)kp.ki_rssize));
 1004         sbuf_printf(sb, "VmData:\t%8ju kB\n",   P2K((uintmax_t)kp.ki_dsize));
 1005         sbuf_printf(sb, "VmStk:\t%8ju kB\n",    P2K((uintmax_t)kp.ki_ssize));
 1006         sbuf_printf(sb, "VmExe:\t%8ju kB\n",    P2K((uintmax_t)kp.ki_tsize));
 1007         lsize = B2P(kp.ki_size) - kp.ki_dsize -
 1008             kp.ki_ssize - kp.ki_tsize - 1;
 1009         sbuf_printf(sb, "VmLib:\t%8ju kB\n",    P2K((uintmax_t)lsize));
 1010 
 1011         /*
 1012          * Signal masks
 1013          */
 1014         PROC_LOCK(p);
 1015         bsd_to_linux_sigset(&p->p_siglist, &siglist);
 1016         ps = p->p_sigacts;
 1017         mtx_lock(&ps->ps_mtx);
 1018         bsd_to_linux_sigset(&ps->ps_sigignore, &sigignore);
 1019         bsd_to_linux_sigset(&ps->ps_sigcatch, &sigcatch);
 1020         mtx_unlock(&ps->ps_mtx);
 1021         PROC_UNLOCK(p);
 1022 
 1023         sbuf_printf(sb, "SigPnd:\t%016jx\n",    siglist.__mask);
 1024         /*
 1025          * XXX. SigBlk - target thread's signal mask, td_sigmask.
 1026          * To implement SigBlk pseudofs should support proc/tid dir entries.
 1027          */
 1028         sbuf_printf(sb, "SigBlk:\t%016x\n",     0);
 1029         sbuf_printf(sb, "SigIgn:\t%016jx\n",    sigignore.__mask);
 1030         sbuf_printf(sb, "SigCgt:\t%016jx\n",    sigcatch.__mask);
 1031 
 1032         /*
 1033          * Linux also prints the capability masks, but we don't have
 1034          * capabilities yet, and when we do get them they're likely to
 1035          * be meaningless to Linux programs, so we lie. XXX
 1036          */
 1037         sbuf_printf(sb, "CapInh:\t%016x\n",     0);
 1038         sbuf_printf(sb, "CapPrm:\t%016x\n",     0);
 1039         sbuf_printf(sb, "CapEff:\t%016x\n",     0);
 1040 
 1041         return (0);
 1042 }
 1043 
 1044 
 1045 /*
 1046  * Filler function for proc/pid/cwd
 1047  */
 1048 static int
 1049 linprocfs_doproccwd(PFS_FILL_ARGS)
 1050 {
 1051         struct filedesc *fdp;
 1052         struct vnode *vp;
 1053         char *fullpath = "unknown";
 1054         char *freepath = NULL;
 1055 
 1056         fdp = p->p_fd;
 1057         FILEDESC_SLOCK(fdp);
 1058         vp = fdp->fd_cdir;
 1059         if (vp != NULL)
 1060                 VREF(vp);
 1061         FILEDESC_SUNLOCK(fdp);
 1062         vn_fullpath(td, vp, &fullpath, &freepath);
 1063         if (vp != NULL)
 1064                 vrele(vp);
 1065         sbuf_printf(sb, "%s", fullpath);
 1066         if (freepath)
 1067                 free(freepath, M_TEMP);
 1068         return (0);
 1069 }
 1070 
 1071 /*
 1072  * Filler function for proc/pid/root
 1073  */
 1074 static int
 1075 linprocfs_doprocroot(PFS_FILL_ARGS)
 1076 {
 1077         struct filedesc *fdp;
 1078         struct vnode *vp;
 1079         char *fullpath = "unknown";
 1080         char *freepath = NULL;
 1081 
 1082         fdp = p->p_fd;
 1083         FILEDESC_SLOCK(fdp);
 1084         vp = jailed(p->p_ucred) ? fdp->fd_jdir : fdp->fd_rdir;
 1085         if (vp != NULL)
 1086                 VREF(vp);
 1087         FILEDESC_SUNLOCK(fdp);
 1088         vn_fullpath(td, vp, &fullpath, &freepath);
 1089         if (vp != NULL)
 1090                 vrele(vp);
 1091         sbuf_printf(sb, "%s", fullpath);
 1092         if (freepath)
 1093                 free(freepath, M_TEMP);
 1094         return (0);
 1095 }
 1096 
 1097 /*
 1098  * Filler function for proc/pid/cmdline
 1099  */
 1100 static int
 1101 linprocfs_doproccmdline(PFS_FILL_ARGS)
 1102 {
 1103         int ret;
 1104 
 1105         PROC_LOCK(p);
 1106         if ((ret = p_cansee(td, p)) != 0) {
 1107                 PROC_UNLOCK(p);
 1108                 return (ret);
 1109         }
 1110 
 1111         /*
 1112          * Mimic linux behavior and pass only processes with usermode
 1113          * address space as valid.  Return zero silently otherwize.
 1114          */
 1115         if (p->p_vmspace == &vmspace0) {
 1116                 PROC_UNLOCK(p);
 1117                 return (0);
 1118         }
 1119         if (p->p_args != NULL) {
 1120                 sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
 1121                 PROC_UNLOCK(p);
 1122                 return (0);
 1123         }
 1124 
 1125         if ((p->p_flag & P_SYSTEM) != 0) {
 1126                 PROC_UNLOCK(p);
 1127                 return (0);
 1128         }
 1129 
 1130         PROC_UNLOCK(p);
 1131 
 1132         ret = proc_getargv(td, p, sb);
 1133         return (ret);
 1134 }
 1135 
 1136 /*
 1137  * Filler function for proc/pid/environ
 1138  */
 1139 static int
 1140 linprocfs_doprocenviron(PFS_FILL_ARGS)
 1141 {
 1142 
 1143         /*
 1144          * Mimic linux behavior and pass only processes with usermode
 1145          * address space as valid.  Return zero silently otherwize.
 1146          */
 1147         if (p->p_vmspace == &vmspace0)
 1148                 return (0);
 1149 
 1150         return (proc_getenvv(td, p, sb));
 1151 }
 1152 
 1153 static char l32_map_str[] = "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n";
 1154 static char l64_map_str[] = "%016lx-%016lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n";
 1155 static char vdso_str[] = "      [vdso]";
 1156 static char stack_str[] = "      [stack]";
 1157 
 1158 /*
 1159  * Filler function for proc/pid/maps
 1160  */
 1161 static int
 1162 linprocfs_doprocmaps(PFS_FILL_ARGS)
 1163 {
 1164         struct vmspace *vm;
 1165         vm_map_t map;
 1166         vm_map_entry_t entry, tmp_entry;
 1167         vm_object_t obj, tobj, lobj;
 1168         vm_offset_t e_start, e_end;
 1169         vm_ooffset_t off;
 1170         vm_prot_t e_prot;
 1171         unsigned int last_timestamp;
 1172         char *name = "", *freename = NULL;
 1173         const char *l_map_str;
 1174         ino_t ino;
 1175         int ref_count, shadow_count, flags;
 1176         int error;
 1177         struct vnode *vp;
 1178         struct vattr vat;
 1179         bool private;
 1180 
 1181         PROC_LOCK(p);
 1182         error = p_candebug(td, p);
 1183         PROC_UNLOCK(p);
 1184         if (error)
 1185                 return (error);
 1186 
 1187         if (uio->uio_rw != UIO_READ)
 1188                 return (EOPNOTSUPP);
 1189 
 1190         error = 0;
 1191         vm = vmspace_acquire_ref(p);
 1192         if (vm == NULL)
 1193                 return (ESRCH);
 1194 
 1195         if (SV_CURPROC_FLAG(SV_LP64))
 1196                 l_map_str = l64_map_str;
 1197         else
 1198                 l_map_str = l32_map_str;
 1199         map = &vm->vm_map;
 1200         vm_map_lock_read(map);
 1201         for (entry = map->header.next; entry != &map->header;
 1202             entry = entry->next) {
 1203                 name = "";
 1204                 freename = NULL;
 1205                 if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
 1206                         continue;
 1207                 e_prot = entry->protection;
 1208                 e_start = entry->start;
 1209                 e_end = entry->end;
 1210                 obj = entry->object.vm_object;
 1211                 off = entry->offset;
 1212                 for (lobj = tobj = obj; tobj != NULL;
 1213                     lobj = tobj, tobj = tobj->backing_object) {
 1214                         VM_OBJECT_RLOCK(tobj);
 1215                         off += lobj->backing_object_offset;
 1216                         if (lobj != obj)
 1217                                 VM_OBJECT_RUNLOCK(lobj);
 1218                 }
 1219                 private = (entry->eflags & MAP_ENTRY_COW) != 0 || obj == NULL ||
 1220                     ((obj->type == OBJT_DEFAULT || obj->type == OBJT_SWAP) &&
 1221                     (obj->flags & OBJ_NOSPLIT) == 0);
 1222                 last_timestamp = map->timestamp;
 1223                 vm_map_unlock_read(map);
 1224                 ino = 0;
 1225                 if (lobj) {
 1226                         vp = vm_object_vnode(lobj);
 1227                         if (vp != NULL)
 1228                                 vref(vp);
 1229                         if (lobj != obj)
 1230                                 VM_OBJECT_RUNLOCK(lobj);
 1231                         flags = obj->flags;
 1232                         ref_count = obj->ref_count;
 1233                         shadow_count = obj->shadow_count;
 1234                         VM_OBJECT_RUNLOCK(obj);
 1235                         if (vp != NULL) {
 1236                                 vn_fullpath(td, vp, &name, &freename);
 1237                                 vn_lock(vp, LK_SHARED | LK_RETRY);
 1238                                 VOP_GETATTR(vp, &vat, td->td_ucred);
 1239                                 ino = vat.va_fileid;
 1240                                 vput(vp);
 1241                         } else if (SV_PROC_ABI(p) == SV_ABI_LINUX) {
 1242                                 if (e_start == p->p_sysent->sv_shared_page_base)
 1243                                         name = vdso_str;
 1244                                 if (e_end == p->p_sysent->sv_usrstack)
 1245                                         name = stack_str;
 1246                         }
 1247                 } else {
 1248                         flags = 0;
 1249                         ref_count = 0;
 1250                         shadow_count = 0;
 1251                 }
 1252 
 1253                 /*
 1254                  * format:
 1255                  *  start, end, access, offset, major, minor, inode, name.
 1256                  */
 1257                 error = sbuf_printf(sb, l_map_str,
 1258                     (u_long)e_start, (u_long)e_end,
 1259                     (e_prot & VM_PROT_READ)?"r":"-",
 1260                     (e_prot & VM_PROT_WRITE)?"w":"-",
 1261                     (e_prot & VM_PROT_EXECUTE)?"x":"-",
 1262                     private ? "p" : "s",
 1263                     (u_long)off,
 1264                     0,
 1265                     0,
 1266                     (u_long)ino,
 1267                     *name ? "     " : "",
 1268                     name
 1269                     );
 1270                 if (freename)
 1271                         free(freename, M_TEMP);
 1272                 vm_map_lock_read(map);
 1273                 if (error == -1) {
 1274                         error = 0;
 1275                         break;
 1276                 }
 1277                 if (last_timestamp != map->timestamp) {
 1278                         /*
 1279                          * Look again for the entry because the map was
 1280                          * modified while it was unlocked.  Specifically,
 1281                          * the entry may have been clipped, merged, or deleted.
 1282                          */
 1283                         vm_map_lookup_entry(map, e_end - 1, &tmp_entry);
 1284                         entry = tmp_entry;
 1285                 }
 1286         }
 1287         vm_map_unlock_read(map);
 1288         vmspace_free(vm);
 1289 
 1290         return (error);
 1291 }
 1292 
 1293 /*
 1294  * Criteria for interface name translation
 1295  */
 1296 #define IFP_IS_ETH(ifp) (ifp->if_type == IFT_ETHER)
 1297 
 1298 static int
 1299 linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen)
 1300 {
 1301         struct ifnet *ifscan;
 1302         int ethno;
 1303 
 1304         IFNET_RLOCK_ASSERT();
 1305 
 1306         /* Short-circuit non ethernet interfaces */
 1307         if (!IFP_IS_ETH(ifp))
 1308                 return (strlcpy(buffer, ifp->if_xname, buflen));
 1309 
 1310         /* Determine the (relative) unit number for ethernet interfaces */
 1311         ethno = 0;
 1312         CK_STAILQ_FOREACH(ifscan, &V_ifnet, if_link) {
 1313                 if (ifscan == ifp)
 1314                         return (snprintf(buffer, buflen, "eth%d", ethno));
 1315                 if (IFP_IS_ETH(ifscan))
 1316                         ethno++;
 1317         }
 1318 
 1319         return (0);
 1320 }
 1321 
 1322 /*
 1323  * Filler function for proc/net/dev
 1324  */
 1325 static int
 1326 linprocfs_donetdev(PFS_FILL_ARGS)
 1327 {
 1328         char ifname[16]; /* XXX LINUX_IFNAMSIZ */
 1329         struct ifnet *ifp;
 1330 
 1331         sbuf_printf(sb, "%6s|%58s|%s\n"
 1332             "%6s|%58s|%58s\n",
 1333             "Inter-", "   Receive", "  Transmit",
 1334             " face",
 1335             "bytes    packets errs drop fifo frame compressed multicast",
 1336             "bytes    packets errs drop fifo colls carrier compressed");
 1337 
 1338         CURVNET_SET(TD_TO_VNET(curthread));
 1339         IFNET_RLOCK();
 1340         CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
 1341                 linux_ifname(ifp, ifname, sizeof ifname);
 1342                 sbuf_printf(sb, "%6.6s: ", ifname);
 1343                 sbuf_printf(sb, "%7ju %7ju %4ju %4ju %4lu %5lu %10lu %9ju ",
 1344                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IBYTES),
 1345                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IPACKETS),
 1346                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IERRORS),
 1347                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IQDROPS),
 1348                                                         /* rx_missed_errors */
 1349                     0UL,                                /* rx_fifo_errors */
 1350                     0UL,                                /* rx_length_errors +
 1351                                                          * rx_over_errors +
 1352                                                          * rx_crc_errors +
 1353                                                          * rx_frame_errors */
 1354                     0UL,                                /* rx_compressed */
 1355                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_IMCASTS));
 1356                                                         /* XXX-BZ rx only? */
 1357                 sbuf_printf(sb, "%8ju %7ju %4ju %4ju %4lu %5ju %7lu %10lu\n",
 1358                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OBYTES),
 1359                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OPACKETS),
 1360                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OERRORS),
 1361                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_OQDROPS),
 1362                     0UL,                                /* tx_fifo_errors */
 1363                     (uintmax_t )ifp->if_get_counter(ifp, IFCOUNTER_COLLISIONS),
 1364                     0UL,                                /* tx_carrier_errors +
 1365                                                          * tx_aborted_errors +
 1366                                                          * tx_window_errors +
 1367                                                          * tx_heartbeat_errors*/
 1368                     0UL);                               /* tx_compressed */
 1369         }
 1370         IFNET_RUNLOCK();
 1371         CURVNET_RESTORE();
 1372 
 1373         return (0);
 1374 }
 1375 
 1376 /*
 1377  * Filler function for proc/sys/kernel/osrelease
 1378  */
 1379 static int
 1380 linprocfs_doosrelease(PFS_FILL_ARGS)
 1381 {
 1382         char osrelease[LINUX_MAX_UTSNAME];
 1383 
 1384         linux_get_osrelease(td, osrelease);
 1385         sbuf_printf(sb, "%s\n", osrelease);
 1386 
 1387         return (0);
 1388 }
 1389 
 1390 /*
 1391  * Filler function for proc/sys/kernel/ostype
 1392  */
 1393 static int
 1394 linprocfs_doostype(PFS_FILL_ARGS)
 1395 {
 1396         char osname[LINUX_MAX_UTSNAME];
 1397 
 1398         linux_get_osname(td, osname);
 1399         sbuf_printf(sb, "%s\n", osname);
 1400 
 1401         return (0);
 1402 }
 1403 
 1404 /*
 1405  * Filler function for proc/sys/kernel/version
 1406  */
 1407 static int
 1408 linprocfs_doosbuild(PFS_FILL_ARGS)
 1409 {
 1410 
 1411         linprocfs_osbuild(td, sb);
 1412         sbuf_cat(sb, "\n");
 1413         return (0);
 1414 }
 1415 
 1416 /*
 1417  * Filler function for proc/sys/kernel/msgmax
 1418  */
 1419 static int
 1420 linprocfs_domsgmax(PFS_FILL_ARGS)
 1421 {
 1422 
 1423         sbuf_printf(sb, "%d\n", msginfo.msgmax);
 1424         return (0);
 1425 }
 1426 
 1427 /*
 1428  * Filler function for proc/sys/kernel/msgmni
 1429  */
 1430 static int
 1431 linprocfs_domsgmni(PFS_FILL_ARGS)
 1432 {
 1433 
 1434         sbuf_printf(sb, "%d\n", msginfo.msgmni);
 1435         return (0);
 1436 }
 1437 
 1438 /*
 1439  * Filler function for proc/sys/kernel/msgmnb
 1440  */
 1441 static int
 1442 linprocfs_domsgmnb(PFS_FILL_ARGS)
 1443 {
 1444 
 1445         sbuf_printf(sb, "%d\n", msginfo.msgmnb);
 1446         return (0);
 1447 }
 1448 
 1449 /*
 1450  * Filler function for proc/sys/kernel/pid_max
 1451  */
 1452 static int
 1453 linprocfs_dopid_max(PFS_FILL_ARGS)
 1454 {
 1455 
 1456         sbuf_printf(sb, "%i\n", PID_MAX);
 1457         return (0);
 1458 }
 1459 
 1460 /*
 1461  * Filler function for proc/sys/kernel/sem
 1462  */
 1463 static int
 1464 linprocfs_dosem(PFS_FILL_ARGS)
 1465 {
 1466 
 1467         sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns,
 1468             seminfo.semopm, seminfo.semmni);
 1469         return (0);
 1470 }
 1471 
 1472 /*
 1473  * Filler function for proc/sys/kernel/shmall
 1474  */
 1475 static int
 1476 linprocfs_doshmall(PFS_FILL_ARGS)
 1477 {
 1478 
 1479         sbuf_printf(sb, "%lu\n", shminfo.shmall);
 1480         return (0);
 1481 }
 1482 
 1483 /*
 1484  * Filler function for proc/sys/kernel/shmmax
 1485  */
 1486 static int
 1487 linprocfs_doshmmax(PFS_FILL_ARGS)
 1488 {
 1489 
 1490         sbuf_printf(sb, "%lu\n", shminfo.shmmax);
 1491         return (0);
 1492 }
 1493 
 1494 /*
 1495  * Filler function for proc/sys/kernel/shmmni
 1496  */
 1497 static int
 1498 linprocfs_doshmmni(PFS_FILL_ARGS)
 1499 {
 1500 
 1501         sbuf_printf(sb, "%lu\n", shminfo.shmmni);
 1502         return (0);
 1503 }
 1504 
 1505 /*
 1506  * Filler function for proc/sys/kernel/tainted
 1507  */
 1508 static int
 1509 linprocfs_dotainted(PFS_FILL_ARGS)
 1510 {
 1511 
 1512         sbuf_printf(sb, "\n");
 1513         return (0);
 1514 }
 1515 
 1516 /*
 1517  * Filler function for proc/sys/vm/min_free_kbytes
 1518  *
 1519  * This mirrors the approach in illumos to return zero for reads. Effectively,
 1520  * it says, no memory is kept in reserve for "atomic allocations". This class
 1521  * of allocation can be used at times when a thread cannot be suspended.
 1522  */
 1523 static int
 1524 linprocfs_dominfree(PFS_FILL_ARGS)
 1525 {
 1526 
 1527         sbuf_printf(sb, "%d\n", 0);
 1528         return (0);
 1529 }
 1530 
 1531 /*
 1532  * Filler function for proc/scsi/device_info
 1533  */
 1534 static int
 1535 linprocfs_doscsidevinfo(PFS_FILL_ARGS)
 1536 {
 1537 
 1538         return (0);
 1539 }
 1540 
 1541 /*
 1542  * Filler function for proc/scsi/scsi
 1543  */
 1544 static int
 1545 linprocfs_doscsiscsi(PFS_FILL_ARGS)
 1546 {
 1547 
 1548         return (0);
 1549 }
 1550 
 1551 /*
 1552  * Filler function for proc/devices
 1553  */
 1554 static int
 1555 linprocfs_dodevices(PFS_FILL_ARGS)
 1556 {
 1557         char *char_devices;
 1558         sbuf_printf(sb, "Character devices:\n");
 1559 
 1560         char_devices = linux_get_char_devices();
 1561         sbuf_printf(sb, "%s", char_devices);
 1562         linux_free_get_char_devices(char_devices);
 1563 
 1564         sbuf_printf(sb, "\nBlock devices:\n");
 1565 
 1566         return (0);
 1567 }
 1568 
 1569 /*
 1570  * Filler function for proc/cmdline
 1571  */
 1572 static int
 1573 linprocfs_docmdline(PFS_FILL_ARGS)
 1574 {
 1575 
 1576         sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
 1577         sbuf_printf(sb, " ro root=302\n");
 1578         return (0);
 1579 }
 1580 
 1581 /*
 1582  * Filler function for proc/filesystems
 1583  */
 1584 static int
 1585 linprocfs_dofilesystems(PFS_FILL_ARGS)
 1586 {
 1587         struct vfsconf *vfsp;
 1588 
 1589         vfsconf_slock();
 1590         TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
 1591                 if (vfsp->vfc_flags & VFCF_SYNTHETIC)
 1592                         sbuf_printf(sb, "nodev");
 1593                 sbuf_printf(sb, "\t%s\n", vfsp->vfc_name);
 1594         }
 1595         vfsconf_sunlock();
 1596         return(0);
 1597 }
 1598 
 1599 /*
 1600  * Filler function for proc/modules
 1601  */
 1602 static int
 1603 linprocfs_domodules(PFS_FILL_ARGS)
 1604 {
 1605 #if 0
 1606         struct linker_file *lf;
 1607 
 1608         TAILQ_FOREACH(lf, &linker_files, link) {
 1609                 sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
 1610                     (unsigned long)lf->size, lf->refs);
 1611         }
 1612 #endif
 1613         return (0);
 1614 }
 1615 
 1616 /*
 1617  * Filler function for proc/pid/fd
 1618  */
 1619 static int
 1620 linprocfs_dofdescfs(PFS_FILL_ARGS)
 1621 {
 1622 
 1623         if (p == curproc)
 1624                 sbuf_printf(sb, "/dev/fd");
 1625         else
 1626                 sbuf_printf(sb, "unknown");
 1627         return (0);
 1628 }
 1629 
 1630 /*
 1631  * Filler function for proc/pid/limits
 1632  */
 1633 static const struct linux_rlimit_ident {
 1634         const char      *desc;
 1635         const char      *unit;
 1636         unsigned int    rlim_id;
 1637 } linux_rlimits_ident[] = {
 1638         { "Max cpu time",       "seconds",      RLIMIT_CPU },
 1639         { "Max file size",      "bytes",        RLIMIT_FSIZE },
 1640         { "Max data size",      "bytes",        RLIMIT_DATA },
 1641         { "Max stack size",     "bytes",        RLIMIT_STACK },
 1642         { "Max core file size",  "bytes",       RLIMIT_CORE },
 1643         { "Max resident set",   "bytes",        RLIMIT_RSS },
 1644         { "Max processes",      "processes",    RLIMIT_NPROC },
 1645         { "Max open files",     "files",        RLIMIT_NOFILE },
 1646         { "Max locked memory",  "bytes",        RLIMIT_MEMLOCK },
 1647         { "Max address space",  "bytes",        RLIMIT_AS },
 1648         { "Max file locks",     "locks",        LINUX_RLIMIT_LOCKS },
 1649         { "Max pending signals", "signals",     LINUX_RLIMIT_SIGPENDING },
 1650         { "Max msgqueue size",  "bytes",        LINUX_RLIMIT_MSGQUEUE },
 1651         { "Max nice priority",          "",     LINUX_RLIMIT_NICE },
 1652         { "Max realtime priority",      "",     LINUX_RLIMIT_RTPRIO },
 1653         { "Max realtime timeout",       "us",   LINUX_RLIMIT_RTTIME },
 1654         { 0, 0, 0 }
 1655 };
 1656 
 1657 static int
 1658 linprocfs_doproclimits(PFS_FILL_ARGS)
 1659 {
 1660         const struct linux_rlimit_ident *li;
 1661         struct plimit *limp;
 1662         struct rlimit rl;
 1663         ssize_t size;
 1664         int res, error;
 1665 
 1666         error = 0;
 1667 
 1668         PROC_LOCK(p);
 1669         limp = lim_hold(p->p_limit);
 1670         PROC_UNLOCK(p);
 1671         size = sizeof(res);
 1672         sbuf_printf(sb, "%-26s%-21s%-21s%-21s\n", "Limit", "Soft Limit",
 1673                         "Hard Limit", "Units");
 1674         for (li = linux_rlimits_ident; li->desc != NULL; ++li) {
 1675                 switch (li->rlim_id)
 1676                 {
 1677                 case LINUX_RLIMIT_LOCKS:
 1678                         /* FALLTHROUGH */
 1679                 case LINUX_RLIMIT_RTTIME:
 1680                         rl.rlim_cur = RLIM_INFINITY;
 1681                         break;
 1682                 case LINUX_RLIMIT_SIGPENDING:
 1683                         error = kernel_sysctlbyname(td,
 1684                             "kern.sigqueue.max_pending_per_proc",
 1685                             &res, &size, 0, 0, 0, 0);
 1686                         if (error != 0)
 1687                                 goto out;
 1688                         rl.rlim_cur = res;
 1689                         rl.rlim_max = res;
 1690                         break;
 1691                 case LINUX_RLIMIT_MSGQUEUE:
 1692                         error = kernel_sysctlbyname(td,
 1693                             "kern.ipc.msgmnb", &res, &size, 0, 0, 0, 0);
 1694                         if (error != 0)
 1695                                 goto out;
 1696                         rl.rlim_cur = res;
 1697                         rl.rlim_max = res;
 1698                         break;
 1699                 case LINUX_RLIMIT_NICE:
 1700                         /* FALLTHROUGH */
 1701                 case LINUX_RLIMIT_RTPRIO:
 1702                         rl.rlim_cur = 0;
 1703                         rl.rlim_max = 0;
 1704                         break;
 1705                 default:
 1706                         rl = limp->pl_rlimit[li->rlim_id];
 1707                         break;
 1708                 }
 1709                 if (rl.rlim_cur == RLIM_INFINITY)
 1710                         sbuf_printf(sb, "%-26s%-21s%-21s%-10s\n",
 1711                             li->desc, "unlimited", "unlimited", li->unit);
 1712                 else
 1713                         sbuf_printf(sb, "%-26s%-21llu%-21llu%-10s\n",
 1714                             li->desc, (unsigned long long)rl.rlim_cur,
 1715                             (unsigned long long)rl.rlim_max, li->unit);
 1716         }
 1717 out:
 1718         lim_free(limp);
 1719         return (error);
 1720 }
 1721 
 1722 /*
 1723  * The point of the following two functions is to work around
 1724  * an assertion in Chromium; see kern/240991 for details.
 1725  */
 1726 static int
 1727 linprocfs_dotaskattr(PFS_ATTR_ARGS)
 1728 {
 1729 
 1730         vap->va_nlink = 3;
 1731         return (0);
 1732 }
 1733 
 1734 /*
 1735  * Filler function for proc/<pid>/task/.dummy
 1736  */
 1737 static int
 1738 linprocfs_dotaskdummy(PFS_FILL_ARGS)
 1739 {
 1740 
 1741         return (0);
 1742 }
 1743 
 1744 /*
 1745  * Filler function for proc/sys/kernel/random/uuid
 1746  */
 1747 static int
 1748 linprocfs_douuid(PFS_FILL_ARGS)
 1749 {
 1750         struct uuid uuid;
 1751 
 1752         kern_uuidgen(&uuid, 1);
 1753         sbuf_printf_uuid(sb, &uuid);
 1754         sbuf_printf(sb, "\n");
 1755         return(0);
 1756 }
 1757 
 1758 /*
 1759  * Filler function for proc/pid/auxv
 1760  */
 1761 static int
 1762 linprocfs_doauxv(PFS_FILL_ARGS)
 1763 {
 1764         struct sbuf *asb;
 1765         off_t buflen, resid;
 1766         int error;
 1767 
 1768         /*
 1769          * Mimic linux behavior and pass only processes with usermode
 1770          * address space as valid. Return zero silently otherwise.
 1771          */
 1772         if (p->p_vmspace == &vmspace0)
 1773                 return (0);
 1774 
 1775         if (uio->uio_resid == 0)
 1776                 return (0);
 1777         if (uio->uio_offset < 0 || uio->uio_resid < 0)
 1778                 return (EINVAL);
 1779 
 1780         asb = sbuf_new_auto();
 1781         if (asb == NULL)
 1782                 return (ENOMEM);
 1783         error = proc_getauxv(td, p, asb);
 1784         if (error == 0)
 1785                 error = sbuf_finish(asb);
 1786 
 1787         resid = sbuf_len(asb) - uio->uio_offset;
 1788         if (resid > uio->uio_resid)
 1789                 buflen = uio->uio_resid;
 1790         else
 1791                 buflen = resid;
 1792         if (buflen > IOSIZE_MAX)
 1793                 return (EINVAL);
 1794         if (buflen > MAXPHYS)
 1795                 buflen = MAXPHYS;
 1796         if (resid <= 0)
 1797                 return (0);
 1798 
 1799         if (error == 0)
 1800                 error = uiomove(sbuf_data(asb) + uio->uio_offset, buflen, uio);
 1801         sbuf_delete(asb);
 1802         return (error);
 1803 }
 1804 
 1805 /*
 1806  * Constructor
 1807  */
 1808 static int
 1809 linprocfs_init(PFS_INIT_ARGS)
 1810 {
 1811         struct pfs_node *root;
 1812         struct pfs_node *dir;
 1813         struct pfs_node *sys;
 1814 
 1815         root = pi->pi_root;
 1816 
 1817         /* /proc/... */
 1818         pfs_create_file(root, "cmdline", &linprocfs_docmdline,
 1819             NULL, NULL, NULL, PFS_RD);
 1820         pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
 1821             NULL, NULL, NULL, PFS_RD);
 1822         pfs_create_file(root, "devices", &linprocfs_dodevices,
 1823             NULL, NULL, NULL, PFS_RD);
 1824         pfs_create_file(root, "filesystems", &linprocfs_dofilesystems,
 1825             NULL, NULL, NULL, PFS_RD);
 1826         pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
 1827             NULL, NULL, NULL, PFS_RD);
 1828         pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
 1829             NULL, NULL, NULL, PFS_RD);
 1830         pfs_create_file(root, "modules", &linprocfs_domodules,
 1831             NULL, NULL, NULL, PFS_RD);
 1832         pfs_create_file(root, "mounts", &linprocfs_domtab,
 1833             NULL, NULL, NULL, PFS_RD);
 1834         pfs_create_file(root, "mtab", &linprocfs_domtab,
 1835             NULL, NULL, NULL, PFS_RD);
 1836         pfs_create_file(root, "partitions", &linprocfs_dopartitions,
 1837             NULL, NULL, NULL, PFS_RD);
 1838         pfs_create_link(root, "self", &procfs_docurproc,
 1839             NULL, NULL, NULL, 0);
 1840         pfs_create_file(root, "stat", &linprocfs_dostat,
 1841             NULL, NULL, NULL, PFS_RD);
 1842         pfs_create_file(root, "swaps", &linprocfs_doswaps,
 1843             NULL, NULL, NULL, PFS_RD);
 1844         pfs_create_file(root, "uptime", &linprocfs_douptime,
 1845             NULL, NULL, NULL, PFS_RD);
 1846         pfs_create_file(root, "version", &linprocfs_doversion,
 1847             NULL, NULL, NULL, PFS_RD);
 1848 
 1849         /* /proc/bus/... */
 1850         dir = pfs_create_dir(root, "bus", NULL, NULL, NULL, 0);
 1851         dir = pfs_create_dir(dir, "pci", NULL, NULL, NULL, 0);
 1852         dir = pfs_create_dir(dir, "devices", NULL, NULL, NULL, 0);
 1853 
 1854         /* /proc/net/... */
 1855         dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
 1856         pfs_create_file(dir, "dev", &linprocfs_donetdev,
 1857             NULL, NULL, NULL, PFS_RD);
 1858 
 1859         /* /proc/<pid>/... */
 1860         dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
 1861         pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
 1862             NULL, NULL, NULL, PFS_RD);
 1863         pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
 1864             NULL, NULL, NULL, 0);
 1865         pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
 1866             NULL, &procfs_candebug, NULL, PFS_RD);
 1867         pfs_create_link(dir, "exe", &procfs_doprocfile,
 1868             NULL, &procfs_notsystem, NULL, 0);
 1869         pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
 1870             NULL, NULL, NULL, PFS_RD);
 1871         pfs_create_file(dir, "mem", &procfs_doprocmem,
 1872             procfs_attr_rw, &procfs_candebug, NULL, PFS_RDWR | PFS_RAW);
 1873         pfs_create_file(dir, "mounts", &linprocfs_domtab,
 1874             NULL, NULL, NULL, PFS_RD);
 1875         pfs_create_link(dir, "root", &linprocfs_doprocroot,
 1876             NULL, NULL, NULL, 0);
 1877         pfs_create_file(dir, "stat", &linprocfs_doprocstat,
 1878             NULL, NULL, NULL, PFS_RD);
 1879         pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
 1880             NULL, NULL, NULL, PFS_RD);
 1881         pfs_create_file(dir, "status", &linprocfs_doprocstatus,
 1882             NULL, NULL, NULL, PFS_RD);
 1883         pfs_create_link(dir, "fd", &linprocfs_dofdescfs,
 1884             NULL, NULL, NULL, 0);
 1885         pfs_create_file(dir, "auxv", &linprocfs_doauxv,
 1886             NULL, &procfs_candebug, NULL, PFS_RD|PFS_RAWRD);
 1887         pfs_create_file(dir, "limits", &linprocfs_doproclimits,
 1888             NULL, NULL, NULL, PFS_RD);
 1889 
 1890         /* /proc/<pid>/task/... */
 1891         dir = pfs_create_dir(dir, "task", linprocfs_dotaskattr, NULL, NULL, 0);
 1892         pfs_create_file(dir, ".dummy", &linprocfs_dotaskdummy,
 1893             NULL, NULL, NULL, PFS_RD);
 1894 
 1895         /* /proc/scsi/... */
 1896         dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
 1897         pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
 1898             NULL, NULL, NULL, PFS_RD);
 1899         pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
 1900             NULL, NULL, NULL, PFS_RD);
 1901 
 1902         /* /proc/sys/... */
 1903         sys = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
 1904 
 1905         /* /proc/sys/kernel/... */
 1906         dir = pfs_create_dir(sys, "kernel", NULL, NULL, NULL, 0);
 1907         pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
 1908             NULL, NULL, NULL, PFS_RD);
 1909         pfs_create_file(dir, "ostype", &linprocfs_doostype,
 1910             NULL, NULL, NULL, PFS_RD);
 1911         pfs_create_file(dir, "version", &linprocfs_doosbuild,
 1912             NULL, NULL, NULL, PFS_RD);
 1913         pfs_create_file(dir, "msgmax", &linprocfs_domsgmax,
 1914             NULL, NULL, NULL, PFS_RD);
 1915         pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
 1916             NULL, NULL, NULL, PFS_RD);
 1917         pfs_create_file(dir, "msgmnb", &linprocfs_domsgmnb,
 1918             NULL, NULL, NULL, PFS_RD);
 1919         pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
 1920             NULL, NULL, NULL, PFS_RD);
 1921         pfs_create_file(dir, "sem", &linprocfs_dosem,
 1922             NULL, NULL, NULL, PFS_RD);
 1923         pfs_create_file(dir, "shmall", &linprocfs_doshmall,
 1924             NULL, NULL, NULL, PFS_RD);
 1925         pfs_create_file(dir, "shmmax", &linprocfs_doshmmax,
 1926             NULL, NULL, NULL, PFS_RD);
 1927         pfs_create_file(dir, "shmmni", &linprocfs_doshmmni,
 1928             NULL, NULL, NULL, PFS_RD);
 1929         pfs_create_file(dir, "tainted", &linprocfs_dotainted,
 1930             NULL, NULL, NULL, PFS_RD);
 1931 
 1932         /* /proc/sys/kernel/random/... */
 1933         dir = pfs_create_dir(dir, "random", NULL, NULL, NULL, 0);
 1934         pfs_create_file(dir, "uuid", &linprocfs_douuid,
 1935             NULL, NULL, NULL, PFS_RD);
 1936 
 1937         /* /proc/sys/vm/.... */
 1938         dir = pfs_create_dir(sys, "vm", NULL, NULL, NULL, 0);
 1939         pfs_create_file(dir, "min_free_kbytes", &linprocfs_dominfree,
 1940             NULL, NULL, NULL, PFS_RD);
 1941 
 1942         return (0);
 1943 }
 1944 
 1945 /*
 1946  * Destructor
 1947  */
 1948 static int
 1949 linprocfs_uninit(PFS_INIT_ARGS)
 1950 {
 1951 
 1952         /* nothing to do, pseudofs will GC */
 1953         return (0);
 1954 }
 1955 
 1956 PSEUDOFS(linprocfs, 1, VFCF_JAIL);
 1957 #if defined(__aarch64__) || defined(__amd64__)
 1958 MODULE_DEPEND(linprocfs, linux_common, 1, 1, 1);
 1959 #else
 1960 MODULE_DEPEND(linprocfs, linux, 1, 1, 1);
 1961 #endif
 1962 MODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
 1963 MODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);
 1964 MODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1);
 1965 MODULE_DEPEND(linprocfs, sysvshm, 1, 1, 1);

Cache object: c8736373eab546caafa1800393a0597c


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