xref: /freebsd/sys/compat/linprocfs/linprocfs.c (revision 884a2a699669ec61e2366e3e358342dbc94be24a)
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$");
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/vmmeter.h>
76 #include <sys/vnode.h>
77 #include <sys/bus.h>
78 
79 #include <net/if.h>
80 #include <net/vnet.h>
81 
82 #include <vm/vm.h>
83 #include <vm/vm_extern.h>
84 #include <vm/pmap.h>
85 #include <vm/vm_map.h>
86 #include <vm/vm_param.h>
87 #include <vm/vm_object.h>
88 #include <vm/swap_pager.h>
89 
90 #include <machine/clock.h>
91 
92 #include <geom/geom.h>
93 #include <geom/geom_int.h>
94 
95 #if defined(__i386__) || defined(__amd64__)
96 #include <machine/cputypes.h>
97 #include <machine/md_var.h>
98 #endif /* __i386__ || __amd64__ */
99 
100 #ifdef COMPAT_FREEBSD32
101 #include <compat/freebsd32/freebsd32_util.h>
102 #endif
103 
104 #ifdef COMPAT_LINUX32				/* XXX */
105 #include <machine/../linux32/linux.h>
106 #else
107 #include <machine/../linux/linux.h>
108 #endif
109 #include <compat/linux/linux_ioctl.h>
110 #include <compat/linux/linux_mib.h>
111 #include <compat/linux/linux_util.h>
112 #include <fs/pseudofs/pseudofs.h>
113 #include <fs/procfs/procfs.h>
114 
115 /*
116  * Various conversion macros
117  */
118 #define T2J(x) ((long)(((x) * 100ULL) / (stathz ? stathz : hz)))	/* ticks to jiffies */
119 #define T2CS(x) ((unsigned long)(((x) * 100ULL) / (stathz ? stathz : hz)))	/* ticks to centiseconds */
120 #define T2S(x) ((x) / (stathz ? stathz : hz))		/* ticks to seconds */
121 #define B2K(x) ((x) >> 10)				/* bytes to kbytes */
122 #define B2P(x) ((x) >> PAGE_SHIFT)			/* bytes to pages */
123 #define P2B(x) ((x) << PAGE_SHIFT)			/* pages to bytes */
124 #define P2K(x) ((x) << (PAGE_SHIFT - 10))		/* pages to kbytes */
125 #define TV2J(x)	((x)->tv_sec * 100UL + (x)->tv_usec / 10000)
126 
127 /**
128  * @brief Mapping of ki_stat in struct kinfo_proc to the linux state
129  *
130  * The linux procfs state field displays one of the characters RSDZTW to
131  * denote running, sleeping in an interruptible wait, waiting in an
132  * uninterruptible disk sleep, a zombie process, process is being traced
133  * or stopped, or process is paging respectively.
134  *
135  * Our struct kinfo_proc contains the variable ki_stat which contains a
136  * value out of SIDL, SRUN, SSLEEP, SSTOP, SZOMB, SWAIT and SLOCK.
137  *
138  * This character array is used with ki_stati-1 as an index and tries to
139  * map our states to suitable linux states.
140  */
141 static char linux_state[] = "RRSTZDD";
142 
143 /*
144  * Filler function for proc/meminfo
145  */
146 static int
147 linprocfs_domeminfo(PFS_FILL_ARGS)
148 {
149 	unsigned long memtotal;		/* total memory in bytes */
150 	unsigned long memused;		/* used memory in bytes */
151 	unsigned long memfree;		/* free memory in bytes */
152 	unsigned long memshared;	/* shared memory ??? */
153 	unsigned long buffers, cached;	/* buffer / cache memory ??? */
154 	unsigned long long swaptotal;	/* total swap space in bytes */
155 	unsigned long long swapused;	/* used swap space in bytes */
156 	unsigned long long swapfree;	/* free swap space in bytes */
157 	vm_object_t object;
158 	int i, j;
159 
160 	memtotal = physmem * PAGE_SIZE;
161 	/*
162 	 * The correct thing here would be:
163 	 *
164 	memfree = cnt.v_free_count * PAGE_SIZE;
165 	memused = memtotal - memfree;
166 	 *
167 	 * but it might mislead linux binaries into thinking there
168 	 * is very little memory left, so we cheat and tell them that
169 	 * all memory that isn't wired down is free.
170 	 */
171 	memused = cnt.v_wire_count * PAGE_SIZE;
172 	memfree = memtotal - memused;
173 	swap_pager_status(&i, &j);
174 	swaptotal = (unsigned long long)i * PAGE_SIZE;
175 	swapused = (unsigned long long)j * PAGE_SIZE;
176 	swapfree = swaptotal - swapused;
177 	memshared = 0;
178 	mtx_lock(&vm_object_list_mtx);
179 	TAILQ_FOREACH(object, &vm_object_list, object_list)
180 		if (object->shadow_count > 1)
181 			memshared += object->resident_page_count;
182 	mtx_unlock(&vm_object_list_mtx);
183 	memshared *= PAGE_SIZE;
184 	/*
185 	 * We'd love to be able to write:
186 	 *
187 	buffers = bufspace;
188 	 *
189 	 * but bufspace is internal to vfs_bio.c and we don't feel
190 	 * like unstaticizing it just for linprocfs's sake.
191 	 */
192 	buffers = 0;
193 	cached = cnt.v_cache_count * PAGE_SIZE;
194 
195 	sbuf_printf(sb,
196 	    "	     total:    used:	free:  shared: buffers:	 cached:\n"
197 	    "Mem:  %lu %lu %lu %lu %lu %lu\n"
198 	    "Swap: %llu %llu %llu\n"
199 	    "MemTotal: %9lu kB\n"
200 	    "MemFree:  %9lu kB\n"
201 	    "MemShared:%9lu kB\n"
202 	    "Buffers:  %9lu kB\n"
203 	    "Cached:   %9lu kB\n"
204 	    "SwapTotal:%9llu kB\n"
205 	    "SwapFree: %9llu kB\n",
206 	    memtotal, memused, memfree, memshared, buffers, cached,
207 	    swaptotal, swapused, swapfree,
208 	    B2K(memtotal), B2K(memfree),
209 	    B2K(memshared), B2K(buffers), B2K(cached),
210 	    B2K(swaptotal), B2K(swapfree));
211 
212 	return (0);
213 }
214 
215 #if defined(__i386__) || defined(__amd64__)
216 /*
217  * Filler function for proc/cpuinfo (i386 & amd64 version)
218  */
219 static int
220 linprocfs_docpuinfo(PFS_FILL_ARGS)
221 {
222 	int hw_model[2];
223 	char model[128];
224 	uint64_t freq;
225 	size_t size;
226 	int class, fqmhz, fqkhz;
227 	int i;
228 
229 	/*
230 	 * We default the flags to include all non-conflicting flags,
231 	 * and the Intel versions of conflicting flags.
232 	 */
233 	static char *flags[] = {
234 		"fpu",	    "vme",     "de",	   "pse",      "tsc",
235 		"msr",	    "pae",     "mce",	   "cx8",      "apic",
236 		"sep",	    "sep",     "mtrr",	   "pge",      "mca",
237 		"cmov",	    "pat",     "pse36",	   "pn",       "b19",
238 		"b20",	    "b21",     "mmxext",   "mmx",      "fxsr",
239 		"xmm",	    "sse2",    "b27",	   "b28",      "b29",
240 		"3dnowext", "3dnow"
241 	};
242 
243 	switch (cpu_class) {
244 #ifdef __i386__
245 	case CPUCLASS_286:
246 		class = 2;
247 		break;
248 	case CPUCLASS_386:
249 		class = 3;
250 		break;
251 	case CPUCLASS_486:
252 		class = 4;
253 		break;
254 	case CPUCLASS_586:
255 		class = 5;
256 		break;
257 	case CPUCLASS_686:
258 		class = 6;
259 		break;
260 	default:
261 		class = 0;
262 		break;
263 #else /* __amd64__ */
264 	default:
265 		class = 15;
266 		break;
267 #endif
268 	}
269 
270 	hw_model[0] = CTL_HW;
271 	hw_model[1] = HW_MODEL;
272 	model[0] = '\0';
273 	size = sizeof(model);
274 	if (kernel_sysctl(td, hw_model, 2, &model, &size, 0, 0, 0, 0) != 0)
275 		strcpy(model, "unknown");
276 	for (i = 0; i < mp_ncpus; ++i) {
277 		sbuf_printf(sb,
278 		    "processor\t: %d\n"
279 		    "vendor_id\t: %.20s\n"
280 		    "cpu family\t: %u\n"
281 		    "model\t\t: %u\n"
282 		    "model name\t: %s\n"
283 		    "stepping\t: %u\n\n",
284 		    i, cpu_vendor, CPUID_TO_FAMILY(cpu_id),
285 		    CPUID_TO_MODEL(cpu_id), model, cpu_id & CPUID_STEPPING);
286 		/* XXX per-cpu vendor / class / model / id? */
287 	}
288 
289 	sbuf_cat(sb, "flags\t\t:");
290 
291 #ifdef __i386__
292 	switch (cpu_vendor_id) {
293 	case CPU_VENDOR_AMD:
294 		if (class < 6)
295 			flags[16] = "fcmov";
296 		break;
297 	case CPU_VENDOR_CYRIX:
298 		flags[24] = "cxmmx";
299 		break;
300 	}
301 #endif
302 
303 	for (i = 0; i < 32; i++)
304 		if (cpu_feature & (1 << i))
305 			sbuf_printf(sb, " %s", flags[i]);
306 	sbuf_cat(sb, "\n");
307 	freq = atomic_load_acq_64(&tsc_freq);
308 	if (freq != 0) {
309 		fqmhz = (freq + 4999) / 1000000;
310 		fqkhz = ((freq + 4999) / 10000) % 100;
311 		sbuf_printf(sb,
312 		    "cpu MHz\t\t: %d.%02d\n"
313 		    "bogomips\t: %d.%02d\n",
314 		    fqmhz, fqkhz, fqmhz, fqkhz);
315 	}
316 
317 	return (0);
318 }
319 #endif /* __i386__ || __amd64__ */
320 
321 /*
322  * Filler function for proc/mtab
323  *
324  * This file doesn't exist in Linux' procfs, but is included here so
325  * users can symlink /compat/linux/etc/mtab to /proc/mtab
326  */
327 static int
328 linprocfs_domtab(PFS_FILL_ARGS)
329 {
330 	struct nameidata nd;
331 	struct mount *mp;
332 	const char *lep;
333 	char *dlep, *flep, *mntto, *mntfrom, *fstype;
334 	size_t lep_len;
335 	int error;
336 
337 	/* resolve symlinks etc. in the emulation tree prefix */
338 	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td);
339 	flep = NULL;
340 	error = namei(&nd);
341 	lep = linux_emul_path;
342 	if (error == 0) {
343 		if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
344 			lep = dlep;
345 		vrele(nd.ni_vp);
346 		VFS_UNLOCK_GIANT(NDHASGIANT(&nd));
347 	}
348 	lep_len = strlen(lep);
349 
350 	mtx_lock(&mountlist_mtx);
351 	error = 0;
352 	TAILQ_FOREACH(mp, &mountlist, mnt_list) {
353 		/* determine device name */
354 		mntfrom = mp->mnt_stat.f_mntfromname;
355 
356 		/* determine mount point */
357 		mntto = mp->mnt_stat.f_mntonname;
358 		if (strncmp(mntto, lep, lep_len) == 0 &&
359 		    mntto[lep_len] == '/')
360 			mntto += lep_len;
361 
362 		/* determine fs type */
363 		fstype = mp->mnt_stat.f_fstypename;
364 		if (strcmp(fstype, pn->pn_info->pi_name) == 0)
365 			mntfrom = fstype = "proc";
366 		else if (strcmp(fstype, "procfs") == 0)
367 			continue;
368 
369 		if (strcmp(fstype, "linsysfs") == 0) {
370 			sbuf_printf(sb, "/sys %s sysfs %s", mntto,
371 			    mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
372 		} else {
373 			/* For Linux msdosfs is called vfat */
374 			if (strcmp(fstype, "msdosfs") == 0)
375 				fstype = "vfat";
376 			sbuf_printf(sb, "%s %s %s %s", mntfrom, mntto, fstype,
377 			    mp->mnt_stat.f_flags & MNT_RDONLY ? "ro" : "rw");
378 		}
379 #define ADD_OPTION(opt, name) \
380 	if (mp->mnt_stat.f_flags & (opt)) sbuf_printf(sb, "," name);
381 		ADD_OPTION(MNT_SYNCHRONOUS,	"sync");
382 		ADD_OPTION(MNT_NOEXEC,		"noexec");
383 		ADD_OPTION(MNT_NOSUID,		"nosuid");
384 		ADD_OPTION(MNT_UNION,		"union");
385 		ADD_OPTION(MNT_ASYNC,		"async");
386 		ADD_OPTION(MNT_SUIDDIR,		"suiddir");
387 		ADD_OPTION(MNT_NOSYMFOLLOW,	"nosymfollow");
388 		ADD_OPTION(MNT_NOATIME,		"noatime");
389 #undef ADD_OPTION
390 		/* a real Linux mtab will also show NFS options */
391 		sbuf_printf(sb, " 0 0\n");
392 	}
393 	mtx_unlock(&mountlist_mtx);
394 	if (flep != NULL)
395 		free(flep, M_TEMP);
396 	return (error);
397 }
398 
399 /*
400  * Filler function for proc/partitions
401  *
402  */
403 static int
404 linprocfs_dopartitions(PFS_FILL_ARGS)
405 {
406 	struct g_class *cp;
407 	struct g_geom *gp;
408 	struct g_provider *pp;
409 	struct nameidata nd;
410 	const char *lep;
411 	char  *dlep, *flep;
412 	size_t lep_len;
413 	int error;
414 	int major, minor;
415 
416 	/* resolve symlinks etc. in the emulation tree prefix */
417 	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, linux_emul_path, td);
418 	flep = NULL;
419 	error = namei(&nd);
420 	lep = linux_emul_path;
421 	if (error == 0) {
422 		if (vn_fullpath(td, nd.ni_vp, &dlep, &flep) == 0)
423 			lep = dlep;
424 		vrele(nd.ni_vp);
425 		VFS_UNLOCK_GIANT(NDHASGIANT(&nd));
426 	}
427 	lep_len = strlen(lep);
428 
429 	g_topology_lock();
430 	error = 0;
431 	sbuf_printf(sb, "major minor  #blocks  name rio rmerge rsect "
432 	    "ruse wio wmerge wsect wuse running use aveq\n");
433 
434 	LIST_FOREACH(cp, &g_classes, class) {
435 		if (strcmp(cp->name, "DISK") == 0 ||
436 		    strcmp(cp->name, "PART") == 0)
437 			LIST_FOREACH(gp, &cp->geom, geom) {
438 				LIST_FOREACH(pp, &gp->provider, provider) {
439 					if (linux_driver_get_major_minor(
440 					    pp->name, &major, &minor) != 0) {
441 						major = 0;
442 						minor = 0;
443 					}
444 					sbuf_printf(sb, "%d %d %lld %s "
445 					    "%d %d %d %d %d "
446 					     "%d %d %d %d %d %d\n",
447 					     major, minor,
448 					     (long long)pp->mediasize, pp->name,
449 					     0, 0, 0, 0, 0,
450 					     0, 0, 0, 0, 0, 0);
451 				}
452 			}
453 	}
454 	g_topology_unlock();
455 
456 	if (flep != NULL)
457 		free(flep, M_TEMP);
458 	return (error);
459 }
460 
461 
462 /*
463  * Filler function for proc/stat
464  */
465 static int
466 linprocfs_dostat(PFS_FILL_ARGS)
467 {
468 	struct pcpu *pcpu;
469 	long cp_time[CPUSTATES];
470 	long *cp;
471 	int i;
472 
473 	read_cpu_time(cp_time);
474 	sbuf_printf(sb, "cpu %ld %ld %ld %ld\n",
475 	    T2J(cp_time[CP_USER]),
476 	    T2J(cp_time[CP_NICE]),
477 	    T2J(cp_time[CP_SYS] /*+ cp_time[CP_INTR]*/),
478 	    T2J(cp_time[CP_IDLE]));
479 	CPU_FOREACH(i) {
480 		pcpu = pcpu_find(i);
481 		cp = pcpu->pc_cp_time;
482 		sbuf_printf(sb, "cpu%d %ld %ld %ld %ld\n", i,
483 		    T2J(cp[CP_USER]),
484 		    T2J(cp[CP_NICE]),
485 		    T2J(cp[CP_SYS] /*+ cp[CP_INTR]*/),
486 		    T2J(cp[CP_IDLE]));
487 	}
488 	sbuf_printf(sb,
489 	    "disk 0 0 0 0\n"
490 	    "page %u %u\n"
491 	    "swap %u %u\n"
492 	    "intr %u\n"
493 	    "ctxt %u\n"
494 	    "btime %lld\n",
495 	    cnt.v_vnodepgsin,
496 	    cnt.v_vnodepgsout,
497 	    cnt.v_swappgsin,
498 	    cnt.v_swappgsout,
499 	    cnt.v_intr,
500 	    cnt.v_swtch,
501 	    (long long)boottime.tv_sec);
502 	return (0);
503 }
504 
505 /*
506  * Filler function for proc/uptime
507  */
508 static int
509 linprocfs_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  */
526 static void
527 linprocfs_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  */
552 static void
553 linprocfs_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  */
577 static int
578 linprocfs_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  */
597 static int
598 linprocfs_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  */
619 static int
620 linprocfs_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  */
698 static int
699 linprocfs_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  */
729 static int
730 linprocfs_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  */
864 static int
865 linprocfs_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  */
880 static int
881 linprocfs_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 #define MAX_ARGV_STR	512	/* Max number of argv-like strings */
896 #define UIO_CHUNK_SZ	256	/* Max chunk size (bytes) for uiomove */
897 
898 static int
899 linprocfs_doargv(struct thread *td, struct proc *p, struct sbuf *sb,
900     void (*resolver)(const struct ps_strings, u_long *, int *))
901 {
902 	struct iovec iov;
903 	struct uio tmp_uio;
904 	struct ps_strings pss;
905 	int ret, i, n_elements, elm_len;
906 	u_long addr, pbegin;
907 	char **env_vector, *envp;
908 	char env_string[UIO_CHUNK_SZ];
909 #ifdef COMPAT_FREEBSD32
910 	struct freebsd32_ps_strings pss32;
911 	uint32_t *env_vector32;
912 #endif
913 
914 #define	UIO_HELPER(uio, iov, base, len, cnt, offset, sz, flg, rw, td)	\
915 do {									\
916 	iov.iov_base = (caddr_t)(base);					\
917 	iov.iov_len = (len); 						\
918 	uio.uio_iov = &(iov); 						\
919 	uio.uio_iovcnt = (cnt);	 					\
920 	uio.uio_offset = (off_t)(offset);				\
921 	uio.uio_resid = (sz); 						\
922 	uio.uio_segflg = (flg);						\
923 	uio.uio_rw = (rw); 						\
924 	uio.uio_td = (td);						\
925 } while (0)
926 
927 	env_vector = malloc(sizeof(char *) * MAX_ARGV_STR, M_TEMP, M_WAITOK);
928 
929 #ifdef COMPAT_FREEBSD32
930 	env_vector32 = NULL;
931 	if (SV_PROC_FLAG(p, SV_ILP32) != 0) {
932 		env_vector32 = malloc(sizeof(*env_vector32) * MAX_ARGV_STR,
933 		    M_TEMP, M_WAITOK);
934 		elm_len = sizeof(int32_t);
935 		envp = (char *)env_vector32;
936 
937 		UIO_HELPER(tmp_uio, iov, &pss32, sizeof(pss32), 1,
938 		    (off_t)(p->p_sysent->sv_psstrings),
939 		    sizeof(pss32), UIO_SYSSPACE, UIO_READ, td);
940 		ret = proc_rwmem(p, &tmp_uio);
941 		if (ret != 0)
942 			goto done;
943 		pss.ps_argvstr = PTRIN(pss32.ps_argvstr);
944 		pss.ps_nargvstr = pss32.ps_nargvstr;
945 		pss.ps_envstr = PTRIN(pss32.ps_envstr);
946 		pss.ps_nenvstr = pss32.ps_nenvstr;
947 	} else {
948 #endif
949 		elm_len = sizeof(char *);
950 		envp = (char *)env_vector;
951 
952 		UIO_HELPER(tmp_uio, iov, &pss, sizeof(pss), 1,
953 		    (off_t)(p->p_sysent->sv_psstrings),
954 		    sizeof(pss), UIO_SYSSPACE, UIO_READ, td);
955 		ret = proc_rwmem(p, &tmp_uio);
956 		if (ret != 0)
957 			goto done;
958 #ifdef COMPAT_FREEBSD32
959 	}
960 #endif
961 
962 	/* Get the array address and the number of elements */
963 	resolver(pss, &addr, &n_elements);
964 
965 	/* Consistent with lib/libkvm/kvm_proc.c */
966 	if (n_elements > MAX_ARGV_STR) {
967 		ret = E2BIG;
968 		goto done;
969 	}
970 
971 	UIO_HELPER(tmp_uio, iov, envp, n_elements * elm_len, 1,
972 	    (vm_offset_t)(addr), iov.iov_len, UIO_SYSSPACE, UIO_READ, td);
973 	ret = proc_rwmem(p, &tmp_uio);
974 	if (ret != 0)
975 		goto done;
976 #ifdef COMPAT_FREEBSD32
977 	if (env_vector32 != NULL) {
978 		for (i = 0; i < n_elements; i++)
979 			env_vector[i] = PTRIN(env_vector32[i]);
980 	}
981 #endif
982 
983 	/* Now we can iterate through the list of strings */
984 	for (i = 0; i < n_elements; i++) {
985 		pbegin = (vm_offset_t)env_vector[i];
986 		for (;;) {
987 			UIO_HELPER(tmp_uio, iov, env_string, sizeof(env_string),
988 			    1, pbegin, iov.iov_len, UIO_SYSSPACE, UIO_READ, td);
989 			ret = proc_rwmem(p, &tmp_uio);
990 			if (ret != 0)
991 				goto done;
992 
993 			if (!strvalid(env_string, UIO_CHUNK_SZ)) {
994 				/*
995 				 * We didn't find the end of the string.
996 				 * Add the string to the buffer and move
997 				 * the pointer.  But do not allow strings
998 				 * of unlimited length.
999 				 */
1000 				sbuf_bcat(sb, env_string, UIO_CHUNK_SZ);
1001 				if (sbuf_len(sb) >= ARG_MAX) {
1002 					ret = E2BIG;
1003 					goto done;
1004 				}
1005 				pbegin += UIO_CHUNK_SZ;
1006 			} else {
1007 				sbuf_cat(sb, env_string);
1008 				break;
1009 			}
1010 		}
1011 		sbuf_bcat(sb, "", 1);
1012 	}
1013 #undef UIO_HELPER
1014 
1015 done:
1016 	free(env_vector, M_TEMP);
1017 #ifdef COMPAT_FREEBSD32
1018 	free(env_vector32, M_TEMP);
1019 #endif
1020 	return (ret);
1021 }
1022 
1023 static void
1024 ps_string_argv(const struct ps_strings ps, u_long *addr, int *n)
1025 {
1026 
1027 	*addr = (u_long) ps.ps_argvstr;
1028 	*n = ps.ps_nargvstr;
1029 }
1030 
1031 static void
1032 ps_string_env(const struct ps_strings ps, u_long *addr, int *n)
1033 {
1034 
1035 	*addr = (u_long) ps.ps_envstr;
1036 	*n = ps.ps_nenvstr;
1037 }
1038 
1039 /*
1040  * Filler function for proc/pid/cmdline
1041  */
1042 static int
1043 linprocfs_doproccmdline(PFS_FILL_ARGS)
1044 {
1045 	int ret;
1046 
1047 	PROC_LOCK(p);
1048 	if ((ret = p_cansee(td, p)) != 0) {
1049 		PROC_UNLOCK(p);
1050 		return (ret);
1051 	}
1052 	if (p->p_args != NULL) {
1053 		sbuf_bcpy(sb, p->p_args->ar_args, p->p_args->ar_length);
1054 		PROC_UNLOCK(p);
1055 		return (0);
1056 	}
1057 	PROC_UNLOCK(p);
1058 
1059 	ret = linprocfs_doargv(td, p, sb, ps_string_argv);
1060 	return (ret);
1061 }
1062 
1063 /*
1064  * Filler function for proc/pid/environ
1065  */
1066 static int
1067 linprocfs_doprocenviron(PFS_FILL_ARGS)
1068 {
1069 	int ret;
1070 
1071 	PROC_LOCK(p);
1072 	if ((ret = p_cansee(td, p)) != 0) {
1073 		PROC_UNLOCK(p);
1074 		return (ret);
1075 	}
1076 	PROC_UNLOCK(p);
1077 
1078 	ret = linprocfs_doargv(td, p, sb, ps_string_env);
1079 	return (ret);
1080 }
1081 
1082 /*
1083  * Filler function for proc/pid/maps
1084  */
1085 static int
1086 linprocfs_doprocmaps(PFS_FILL_ARGS)
1087 {
1088 	struct vmspace *vm;
1089 	vm_map_t map;
1090 	vm_map_entry_t entry, tmp_entry;
1091 	vm_object_t obj, tobj, lobj;
1092 	vm_offset_t e_start, e_end;
1093 	vm_ooffset_t off = 0;
1094 	vm_prot_t e_prot;
1095 	unsigned int last_timestamp;
1096 	char *name = "", *freename = NULL;
1097 	ino_t ino;
1098 	int ref_count, shadow_count, flags;
1099 	int error;
1100 	struct vnode *vp;
1101 	struct vattr vat;
1102 	int locked;
1103 
1104 	PROC_LOCK(p);
1105 	error = p_candebug(td, p);
1106 	PROC_UNLOCK(p);
1107 	if (error)
1108 		return (error);
1109 
1110 	if (uio->uio_rw != UIO_READ)
1111 		return (EOPNOTSUPP);
1112 
1113 	error = 0;
1114 	vm = vmspace_acquire_ref(p);
1115 	if (vm == NULL)
1116 		return (ESRCH);
1117 	map = &vm->vm_map;
1118 	vm_map_lock_read(map);
1119 	for (entry = map->header.next; entry != &map->header;
1120 	    entry = entry->next) {
1121 		name = "";
1122 		freename = NULL;
1123 		if (entry->eflags & MAP_ENTRY_IS_SUB_MAP)
1124 			continue;
1125 		e_prot = entry->protection;
1126 		e_start = entry->start;
1127 		e_end = entry->end;
1128 		obj = entry->object.vm_object;
1129 		for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) {
1130 			VM_OBJECT_LOCK(tobj);
1131 			if (lobj != obj)
1132 				VM_OBJECT_UNLOCK(lobj);
1133 			lobj = tobj;
1134 		}
1135 		last_timestamp = map->timestamp;
1136 		vm_map_unlock_read(map);
1137 		ino = 0;
1138 		if (lobj) {
1139 			off = IDX_TO_OFF(lobj->size);
1140 			if (lobj->type == OBJT_VNODE) {
1141 				vp = lobj->handle;
1142 				if (vp)
1143 					vref(vp);
1144 			}
1145 			else
1146 				vp = NULL;
1147 			if (lobj != obj)
1148 				VM_OBJECT_UNLOCK(lobj);
1149 			flags = obj->flags;
1150 			ref_count = obj->ref_count;
1151 			shadow_count = obj->shadow_count;
1152 			VM_OBJECT_UNLOCK(obj);
1153 			if (vp) {
1154 				vn_fullpath(td, vp, &name, &freename);
1155 				locked = VFS_LOCK_GIANT(vp->v_mount);
1156 				vn_lock(vp, LK_SHARED | LK_RETRY);
1157 				VOP_GETATTR(vp, &vat, td->td_ucred);
1158 				ino = vat.va_fileid;
1159 				vput(vp);
1160 				VFS_UNLOCK_GIANT(locked);
1161 			}
1162 		} else {
1163 			flags = 0;
1164 			ref_count = 0;
1165 			shadow_count = 0;
1166 		}
1167 
1168 		/*
1169 		 * format:
1170 		 *  start, end, access, offset, major, minor, inode, name.
1171 		 */
1172 		error = sbuf_printf(sb,
1173 		    "%08lx-%08lx %s%s%s%s %08lx %02x:%02x %lu%s%s\n",
1174 		    (u_long)e_start, (u_long)e_end,
1175 		    (e_prot & VM_PROT_READ)?"r":"-",
1176 		    (e_prot & VM_PROT_WRITE)?"w":"-",
1177 		    (e_prot & VM_PROT_EXECUTE)?"x":"-",
1178 		    "p",
1179 		    (u_long)off,
1180 		    0,
1181 		    0,
1182 		    (u_long)ino,
1183 		    *name ? "     " : "",
1184 		    name
1185 		    );
1186 		if (freename)
1187 			free(freename, M_TEMP);
1188 		vm_map_lock_read(map);
1189 		if (error == -1) {
1190 			error = 0;
1191 			break;
1192 		}
1193 		if (last_timestamp != map->timestamp) {
1194 			/*
1195 			 * Look again for the entry because the map was
1196 			 * modified while it was unlocked.  Specifically,
1197 			 * the entry may have been clipped, merged, or deleted.
1198 			 */
1199 			vm_map_lookup_entry(map, e_end - 1, &tmp_entry);
1200 			entry = tmp_entry;
1201 		}
1202 	}
1203 	vm_map_unlock_read(map);
1204 	vmspace_free(vm);
1205 
1206 	return (error);
1207 }
1208 
1209 /*
1210  * Filler function for proc/net/dev
1211  */
1212 static int
1213 linprocfs_donetdev(PFS_FILL_ARGS)
1214 {
1215 	char ifname[16]; /* XXX LINUX_IFNAMSIZ */
1216 	struct ifnet *ifp;
1217 
1218 	sbuf_printf(sb, "%6s|%58s|%s\n"
1219 	    "%6s|%58s|%58s\n",
1220 	    "Inter-", "   Receive", "  Transmit",
1221 	    " face",
1222 	    "bytes    packets errs drop fifo frame compressed multicast",
1223 	    "bytes    packets errs drop fifo colls carrier compressed");
1224 
1225 	CURVNET_SET(TD_TO_VNET(curthread));
1226 	IFNET_RLOCK();
1227 	TAILQ_FOREACH(ifp, &V_ifnet, if_link) {
1228 		linux_ifname(ifp, ifname, sizeof ifname);
1229 		sbuf_printf(sb, "%6.6s: ", ifname);
1230 		sbuf_printf(sb, "%7lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu ",
1231 		    ifp->if_ibytes,	/* rx_bytes */
1232 		    ifp->if_ipackets,	/* rx_packets */
1233 		    ifp->if_ierrors,	/* rx_errors */
1234 		    ifp->if_iqdrops,	/* rx_dropped +
1235 					 * rx_missed_errors */
1236 		    0UL,		/* rx_fifo_errors */
1237 		    0UL,		/* rx_length_errors +
1238 					 * rx_over_errors +
1239 		    			 * rx_crc_errors +
1240 					 * rx_frame_errors */
1241 		    0UL,		/* rx_compressed */
1242 		    ifp->if_imcasts);	/* multicast, XXX-BZ rx only? */
1243 		sbuf_printf(sb, "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
1244 		    ifp->if_obytes,	/* tx_bytes */
1245 		    ifp->if_opackets,	/* tx_packets */
1246 		    ifp->if_oerrors,	/* tx_errors */
1247 		    0UL,		/* tx_dropped */
1248 		    0UL,		/* tx_fifo_errors */
1249 		    ifp->if_collisions,	/* collisions */
1250 		    0UL,		/* tx_carrier_errors +
1251 					 * tx_aborted_errors +
1252 					 * tx_window_errors +
1253 					 * tx_heartbeat_errors */
1254 		    0UL);		/* tx_compressed */
1255 	}
1256 	IFNET_RUNLOCK();
1257 	CURVNET_RESTORE();
1258 
1259 	return (0);
1260 }
1261 
1262 /*
1263  * Filler function for proc/sys/kernel/osrelease
1264  */
1265 static int
1266 linprocfs_doosrelease(PFS_FILL_ARGS)
1267 {
1268 	char osrelease[LINUX_MAX_UTSNAME];
1269 
1270 	linux_get_osrelease(td, osrelease);
1271 	sbuf_printf(sb, "%s\n", osrelease);
1272 
1273 	return (0);
1274 }
1275 
1276 /*
1277  * Filler function for proc/sys/kernel/ostype
1278  */
1279 static int
1280 linprocfs_doostype(PFS_FILL_ARGS)
1281 {
1282 	char osname[LINUX_MAX_UTSNAME];
1283 
1284 	linux_get_osname(td, osname);
1285 	sbuf_printf(sb, "%s\n", osname);
1286 
1287 	return (0);
1288 }
1289 
1290 /*
1291  * Filler function for proc/sys/kernel/version
1292  */
1293 static int
1294 linprocfs_doosbuild(PFS_FILL_ARGS)
1295 {
1296 
1297 	linprocfs_osbuild(td, sb);
1298 	sbuf_cat(sb, "\n");
1299 	return (0);
1300 }
1301 
1302 /*
1303  * Filler function for proc/sys/kernel/msgmni
1304  */
1305 static int
1306 linprocfs_domsgmni(PFS_FILL_ARGS)
1307 {
1308 
1309 	sbuf_printf(sb, "%d\n", msginfo.msgmni);
1310 	return (0);
1311 }
1312 
1313 /*
1314  * Filler function for proc/sys/kernel/pid_max
1315  */
1316 static int
1317 linprocfs_dopid_max(PFS_FILL_ARGS)
1318 {
1319 
1320 	sbuf_printf(sb, "%i\n", PID_MAX);
1321 	return (0);
1322 }
1323 
1324 /*
1325  * Filler function for proc/sys/kernel/sem
1326  */
1327 static int
1328 linprocfs_dosem(PFS_FILL_ARGS)
1329 {
1330 
1331 	sbuf_printf(sb, "%d %d %d %d\n", seminfo.semmsl, seminfo.semmns,
1332 	    seminfo.semopm, seminfo.semmni);
1333 	return (0);
1334 }
1335 
1336 /*
1337  * Filler function for proc/scsi/device_info
1338  */
1339 static int
1340 linprocfs_doscsidevinfo(PFS_FILL_ARGS)
1341 {
1342 
1343 	return (0);
1344 }
1345 
1346 /*
1347  * Filler function for proc/scsi/scsi
1348  */
1349 static int
1350 linprocfs_doscsiscsi(PFS_FILL_ARGS)
1351 {
1352 
1353 	return (0);
1354 }
1355 
1356 extern struct cdevsw *cdevsw[];
1357 
1358 /*
1359  * Filler function for proc/devices
1360  */
1361 static int
1362 linprocfs_dodevices(PFS_FILL_ARGS)
1363 {
1364 	char *char_devices;
1365 	sbuf_printf(sb, "Character devices:\n");
1366 
1367 	char_devices = linux_get_char_devices();
1368 	sbuf_printf(sb, "%s", char_devices);
1369 	linux_free_get_char_devices(char_devices);
1370 
1371 	sbuf_printf(sb, "\nBlock devices:\n");
1372 
1373 	return (0);
1374 }
1375 
1376 /*
1377  * Filler function for proc/cmdline
1378  */
1379 static int
1380 linprocfs_docmdline(PFS_FILL_ARGS)
1381 {
1382 
1383 	sbuf_printf(sb, "BOOT_IMAGE=%s", kernelname);
1384 	sbuf_printf(sb, " ro root=302\n");
1385 	return (0);
1386 }
1387 
1388 /*
1389  * Filler function for proc/filesystems
1390  */
1391 static int
1392 linprocfs_dofilesystems(PFS_FILL_ARGS)
1393 {
1394 	struct vfsconf *vfsp;
1395 
1396 	mtx_lock(&Giant);
1397 	TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
1398 		if (vfsp->vfc_flags & VFCF_SYNTHETIC)
1399 			sbuf_printf(sb, "nodev");
1400 		sbuf_printf(sb, "\t%s\n", vfsp->vfc_name);
1401 	}
1402 	mtx_unlock(&Giant);
1403 	return(0);
1404 }
1405 
1406 #if 0
1407 /*
1408  * Filler function for proc/modules
1409  */
1410 static int
1411 linprocfs_domodules(PFS_FILL_ARGS)
1412 {
1413 	struct linker_file *lf;
1414 
1415 	TAILQ_FOREACH(lf, &linker_files, link) {
1416 		sbuf_printf(sb, "%-20s%8lu%4d\n", lf->filename,
1417 		    (unsigned long)lf->size, lf->refs);
1418 	}
1419 	return (0);
1420 }
1421 #endif
1422 
1423 /*
1424  * Filler function for proc/pid/fd
1425  */
1426 static int
1427 linprocfs_dofdescfs(PFS_FILL_ARGS)
1428 {
1429 
1430 	if (p == curproc)
1431 		sbuf_printf(sb, "/dev/fd");
1432 	else
1433 		sbuf_printf(sb, "unknown");
1434 	return (0);
1435 }
1436 
1437 /*
1438  * Constructor
1439  */
1440 static int
1441 linprocfs_init(PFS_INIT_ARGS)
1442 {
1443 	struct pfs_node *root;
1444 	struct pfs_node *dir;
1445 
1446 	root = pi->pi_root;
1447 
1448 	/* /proc/... */
1449 	pfs_create_file(root, "cmdline", &linprocfs_docmdline,
1450 	    NULL, NULL, NULL, PFS_RD);
1451 	pfs_create_file(root, "cpuinfo", &linprocfs_docpuinfo,
1452 	    NULL, NULL, NULL, PFS_RD);
1453 	pfs_create_file(root, "devices", &linprocfs_dodevices,
1454 	    NULL, NULL, NULL, PFS_RD);
1455 	pfs_create_file(root, "filesystems", &linprocfs_dofilesystems,
1456 	    NULL, NULL, NULL, PFS_RD);
1457 	pfs_create_file(root, "loadavg", &linprocfs_doloadavg,
1458 	    NULL, NULL, NULL, PFS_RD);
1459 	pfs_create_file(root, "meminfo", &linprocfs_domeminfo,
1460 	    NULL, NULL, NULL, PFS_RD);
1461 #if 0
1462 	pfs_create_file(root, "modules", &linprocfs_domodules,
1463 	    NULL, NULL, NULL, PFS_RD);
1464 #endif
1465 	pfs_create_file(root, "mounts", &linprocfs_domtab,
1466 	    NULL, NULL, NULL, PFS_RD);
1467 	pfs_create_file(root, "mtab", &linprocfs_domtab,
1468 	    NULL, NULL, NULL, PFS_RD);
1469 	pfs_create_file(root, "partitions", &linprocfs_dopartitions,
1470 	    NULL, NULL, NULL, PFS_RD);
1471 	pfs_create_link(root, "self", &procfs_docurproc,
1472 	    NULL, NULL, NULL, 0);
1473 	pfs_create_file(root, "stat", &linprocfs_dostat,
1474 	    NULL, NULL, NULL, PFS_RD);
1475 	pfs_create_file(root, "uptime", &linprocfs_douptime,
1476 	    NULL, NULL, NULL, PFS_RD);
1477 	pfs_create_file(root, "version", &linprocfs_doversion,
1478 	    NULL, NULL, NULL, PFS_RD);
1479 
1480 	/* /proc/net/... */
1481 	dir = pfs_create_dir(root, "net", NULL, NULL, NULL, 0);
1482 	pfs_create_file(dir, "dev", &linprocfs_donetdev,
1483 	    NULL, NULL, NULL, PFS_RD);
1484 
1485 	/* /proc/<pid>/... */
1486 	dir = pfs_create_dir(root, "pid", NULL, NULL, NULL, PFS_PROCDEP);
1487 	pfs_create_file(dir, "cmdline", &linprocfs_doproccmdline,
1488 	    NULL, NULL, NULL, PFS_RD);
1489 	pfs_create_link(dir, "cwd", &linprocfs_doproccwd,
1490 	    NULL, NULL, NULL, 0);
1491 	pfs_create_file(dir, "environ", &linprocfs_doprocenviron,
1492 	    NULL, NULL, NULL, PFS_RD);
1493 	pfs_create_link(dir, "exe", &procfs_doprocfile,
1494 	    NULL, &procfs_notsystem, NULL, 0);
1495 	pfs_create_file(dir, "maps", &linprocfs_doprocmaps,
1496 	    NULL, NULL, NULL, PFS_RD);
1497 	pfs_create_file(dir, "mem", &procfs_doprocmem,
1498 	    &procfs_attr, &procfs_candebug, NULL, PFS_RDWR|PFS_RAW);
1499 	pfs_create_link(dir, "root", &linprocfs_doprocroot,
1500 	    NULL, NULL, NULL, 0);
1501 	pfs_create_file(dir, "stat", &linprocfs_doprocstat,
1502 	    NULL, NULL, NULL, PFS_RD);
1503 	pfs_create_file(dir, "statm", &linprocfs_doprocstatm,
1504 	    NULL, NULL, NULL, PFS_RD);
1505 	pfs_create_file(dir, "status", &linprocfs_doprocstatus,
1506 	    NULL, NULL, NULL, PFS_RD);
1507 	pfs_create_link(dir, "fd", &linprocfs_dofdescfs,
1508 	    NULL, NULL, NULL, 0);
1509 
1510 	/* /proc/scsi/... */
1511 	dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0);
1512 	pfs_create_file(dir, "device_info", &linprocfs_doscsidevinfo,
1513 	    NULL, NULL, NULL, PFS_RD);
1514 	pfs_create_file(dir, "scsi", &linprocfs_doscsiscsi,
1515 	    NULL, NULL, NULL, PFS_RD);
1516 
1517 	/* /proc/sys/... */
1518 	dir = pfs_create_dir(root, "sys", NULL, NULL, NULL, 0);
1519 	/* /proc/sys/kernel/... */
1520 	dir = pfs_create_dir(dir, "kernel", NULL, NULL, NULL, 0);
1521 	pfs_create_file(dir, "osrelease", &linprocfs_doosrelease,
1522 	    NULL, NULL, NULL, PFS_RD);
1523 	pfs_create_file(dir, "ostype", &linprocfs_doostype,
1524 	    NULL, NULL, NULL, PFS_RD);
1525 	pfs_create_file(dir, "version", &linprocfs_doosbuild,
1526 	    NULL, NULL, NULL, PFS_RD);
1527 	pfs_create_file(dir, "msgmni", &linprocfs_domsgmni,
1528 	    NULL, NULL, NULL, PFS_RD);
1529 	pfs_create_file(dir, "pid_max", &linprocfs_dopid_max,
1530 	    NULL, NULL, NULL, PFS_RD);
1531 	pfs_create_file(dir, "sem", &linprocfs_dosem,
1532 	    NULL, NULL, NULL, PFS_RD);
1533 
1534 	return (0);
1535 }
1536 
1537 /*
1538  * Destructor
1539  */
1540 static int
1541 linprocfs_uninit(PFS_INIT_ARGS)
1542 {
1543 
1544 	/* nothing to do, pseudofs will GC */
1545 	return (0);
1546 }
1547 
1548 PSEUDOFS(linprocfs, 1);
1549 MODULE_DEPEND(linprocfs, linux, 1, 1, 1);
1550 MODULE_DEPEND(linprocfs, procfs, 1, 1, 1);
1551 MODULE_DEPEND(linprocfs, sysvmsg, 1, 1, 1);
1552 MODULE_DEPEND(linprocfs, sysvsem, 1, 1, 1);
1553