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