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