procfs: convert to KNF

Change-Id: Ib4252f199af0f9597745dcd2c11a7f761738671f
This commit is contained in:
David van Moolenbroek 2014-11-09 15:17:44 +00:00
parent 52be5c0afb
commit f1abbce725
13 changed files with 501 additions and 556 deletions

View File

@ -2,7 +2,7 @@
.include <bsd.own.mk> .include <bsd.own.mk>
PROG= procfs PROG= procfs
SRCS= buf.c main.c pid.c root.c tree.c util.c cpuinfo.c SRCS= buf.c cpuinfo.c main.c pid.c root.c tree.c util.c
CPPFLAGS+= -I${NETBSDSRCDIR}/minix CPPFLAGS+= -I${NETBSDSRCDIR}/minix
CPPFLAGS+= -I${NETBSDSRCDIR}/minix/fs CPPFLAGS+= -I${NETBSDSRCDIR}/minix/fs

View File

@ -1,4 +1,4 @@
/* ProcFS - buf.c - by Alen Stojanov and David van Moolenbroek */ /* ProcFS - buf.c - output buffer management for read calls */
#include "inc.h" #include "inc.h"
#include <stdarg.h> #include <stdarg.h>
@ -7,17 +7,16 @@ static char *buf;
static size_t left, used; static size_t left, used;
static off_t skip; static off_t skip;
/*===========================================================================* /*
* buf_init * * Initialize the buffer for fresh use. The output is to be stored into 'ptr'
*===========================================================================*/ * which is BUF_SIZE bytes in size, since that is the size we requested. Due
void buf_init(char *ptr, size_t len, off_t start) * to the way vsnprintf works, we cannot use the last byte of this buffer. The
* first 'start' bytes of the produced output are to be skipped. After that, a
* total of 'len' bytes are requested.
*/
void
buf_init(char * ptr, size_t len, off_t start)
{ {
/* Initialize the buffer for fresh use. The output is to be stored into
* 'ptr' which is BUF_SIZE bytes in size, since that is the size we
* requested. Due to the way vsnprintf works, we cannot use the last
* byte of this buffer. The first 'start' bytes of the produced output
* are to be skipped. After that, a total of 'len' bytes are requested.
*/
buf = ptr; buf = ptr;
skip = start; skip = start;
@ -25,20 +24,20 @@ void buf_init(char *ptr, size_t len, off_t start)
used = 0; used = 0;
} }
/*===========================================================================* /*
* buf_printf * * Add formatted text to the end of the buffer.
*===========================================================================*/ */
void buf_printf(char *fmt, ...) void
buf_printf(char * fmt, ...)
{ {
/* Add formatted text to the end of the buffer.
*/
va_list args; va_list args;
ssize_t len, max; ssize_t len, max;
if (left == 0) if (left == 0)
return; return;
/* There is no way to estimate how much space the result will take, so /*
* There is no way to estimate how much space the result will take, so
* we need to produce the string even when skipping part of the start. * we need to produce the string even when skipping part of the start.
* The null terminating character is not part of the result, so room * The null terminating character is not part of the result, so room
* must be given for it to be stored after completely filling up the * must be given for it to be stored after completely filling up the
@ -50,7 +49,8 @@ void buf_printf(char *fmt, ...)
len = vsnprintf(&buf[used], max, fmt, args); len = vsnprintf(&buf[used], max, fmt, args);
va_end(args); va_end(args);
/* The snprintf family returns the number of bytes that would be stored /*
* The snprintf family returns the number of bytes that would be stored
* if the buffer were large enough, excluding the null terminator. * if the buffer were large enough, excluding the null terminator.
*/ */
if (len >= BUF_SIZE) if (len >= BUF_SIZE)
@ -75,26 +75,25 @@ void buf_printf(char *fmt, ...)
assert(len >= 0); assert(len >= 0);
assert((ssize_t) left >= 0); assert((ssize_t) left >= 0);
if (len > (ssize_t) left) if (len > (ssize_t)left)
len = left; len = left;
used += len; used += len;
left -= len; left -= len;
} }
/*===========================================================================* /*
* buf_append * * Add arbitrary data to the end of the buffer.
*===========================================================================*/ */
void buf_append(char *data, size_t len) void
buf_append(char * data, size_t len)
{ {
/* Add arbitrary data to the end of the buffer.
*/
if (left == 0) if (left == 0)
return; return;
if (skip > 0) { if (skip > 0) {
if (skip >= (ssize_t) len) { if (skip >= (ssize_t)len) {
skip -= len; skip -= len;
return; return;
@ -114,14 +113,13 @@ void buf_append(char *data, size_t len)
left -= len; left -= len;
} }
/*===========================================================================* /*
* buf_result * * Return the resulting number of bytes produced, not counting the trailing
*===========================================================================*/ * null character in the buffer.
ssize_t buf_result(void) */
ssize_t
buf_result(void)
{ {
/* Return the resulting number of bytes produced, not counting the
* trailing null character in the buffer.
*/
return used; return used;
} }

View File

@ -1,24 +1,26 @@
#ifndef _PROCFS_CONST_H #ifndef _PROCFS_CONST_H
#define _PROCFS_CONST_H #define _PROCFS_CONST_H
/* The minimum number of inodes depends on a number of factors: /*
* - Each statically created inode (e.g., /proc/hz) needs an inode. As of * The minimum number of inodes depends on a number of factors:
* - Each statically created inode (e.g., /proc/hz) needs an inode. As of
* writing, this requires about a dozen inodes. * writing, this requires about a dozen inodes.
* - Deleted inodes that are still in use by VFS must be retained. For deleted * - Deleted inodes that are still in use by VFS must be retained. For deleted
* directories, all their containing directories up to the root must be * directories, all their containing directories up to the root must be
* retained as well (to allow the user to "cd .." out). VTreeFS already takes * retained as well (to allow the user to "cd .." out). VTreeFS already
* care of this. In the case of ProcFS, only PID-based directories can be * takes care of this. In the case of ProcFS, only PID-based directories can
* deleted; no other directories are dynamically created. These directories * be deleted; no other directories are dynamically created. These
* currently do not contain subdirectories, either. Hence, for deleted open * directories currently do not contain subdirectories, either. Hence, for
* inodes, we need to reserve at most NR_VNODES inodes in the worst case. * deleted open inodes, we need to reserve at most NR_VNODES inodes in the
* worst case.
* - In order for getdents to be able to return all PID-based directories, * - In order for getdents to be able to return all PID-based directories,
* inodes must not be recycled while generating the list of these PID-based * inodes must not be recycled while generating the list of these PID-based
* directories. In the worst case, this means (NR_TASKS + NR_PROCS) extra * directories. In the worst case, this means (NR_TASKS + NR_PROCS) extra
* inodes. * inodes.
* The sum of these is the bare minimum for correct operation in all possible * The sum of these is the bare minimum for correct operation in all possible
* circumstances. In practice, not all open files will be deleted files in * circumstances. In practice, not all open files will be deleted files in
* ProcFS, and not all process slots will be in use either, so the average use * ProcFS, and not all process slots will be in use either, so the average use
* will be a lot less. However, setting the value too low allows for a * will be a lot less. However, setting the value too low allows for a
* potential denial-of-service attack by a non-root user. * potential denial-of-service attack by a non-root user.
* *
* For the moment, we simply set this value to something reasonable. * For the moment, we simply set this value to something reasonable.

View File

@ -1,4 +1,7 @@
/* ProcFS - cpuinfo.c - generator for the cpuinfo file */
#include "inc.h" #include "inc.h"
#if defined(__i386__) #if defined(__i386__)
#include "../../kernel/arch/i386/include/archconst.h" #include "../../kernel/arch/i386/include/archconst.h"
#endif #endif
@ -75,14 +78,17 @@ static const char * x86_flag[] = {
"", "",
}; };
static void print_x86_cpu_flags(u32_t * flags) /*
* Output a space-separated list of supported CPU flags. x86 only.
*/
static void
print_x86_cpu_flags(u32_t * flags)
{ {
int i, j; int i, j;
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
for (j = 0; j < 32; j++) { for (j = 0; j < 32; j++) {
if (flags[i] & (1 << j) && if (flags[i] & (1 << j) && x86_flag[i * 32 + j][0])
x86_flag[i * 32 + j][0])
buf_printf("%s ", x86_flag[i * 32 + j]); buf_printf("%s ", x86_flag[i * 32 + j]);
} }
} }
@ -90,22 +96,27 @@ static void print_x86_cpu_flags(u32_t * flags)
} }
#endif #endif
static void print_cpu(struct cpu_info * cpu_info, unsigned id) /*
* Print information for a single CPU.
*/
static void
print_cpu(struct cpu_info * cpu_info, unsigned id)
{ {
buf_printf("%-16s: %d\n", "processor", id); buf_printf("%-16s: %d\n", "processor", id);
#if defined(__i386__) #if defined(__i386__)
switch (cpu_info->vendor) { switch (cpu_info->vendor) {
case CPU_VENDOR_INTEL: case CPU_VENDOR_INTEL:
buf_printf("%-16s: %s\n", "vendor_id", "GenuineIntel"); buf_printf("%-16s: %s\n", "vendor_id", "GenuineIntel");
buf_printf("%-16s: %s\n", "model name", "Intel"); buf_printf("%-16s: %s\n", "model name", "Intel");
break; break;
case CPU_VENDOR_AMD: case CPU_VENDOR_AMD:
buf_printf("%-16s: %s\n", "vendor_id", "AuthenticAMD"); buf_printf("%-16s: %s\n", "vendor_id", "AuthenticAMD");
buf_printf("%-16s: %s\n", "model name", "AMD"); buf_printf("%-16s: %s\n", "model name", "AMD");
break; break;
default: default:
buf_printf("%-16: %s\n", "vendor_id", "unknown"); buf_printf("%-16s: %s\n", "vendor_id", "unknown");
} }
buf_printf("%-16s: %d\n", "cpu family", cpu_info->family); buf_printf("%-16s: %d\n", "cpu family", cpu_info->family);
@ -118,18 +129,22 @@ static void print_cpu(struct cpu_info * cpu_info, unsigned id)
#endif #endif
} }
void root_cpuinfo(void) /*
* Generate the contents of /proc/cpuinfo.
*/
void
root_cpuinfo(void)
{ {
struct cpu_info cpu_info[CONFIG_MAX_CPUS]; struct cpu_info cpu_info[CONFIG_MAX_CPUS];
struct machine machine; struct machine machine;
unsigned c; unsigned int c;
if (sys_getmachine(&machine)) { if (sys_getmachine(&machine)) {
printf("PROCFS: cannot get machine\n"); printf("PROCFS: cannot get machine\n");
return; return;
} }
if (sys_getcpuinfo(&cpu_info)) { if (sys_getcpuinfo(&cpu_info)) {
printf("PROCFS: cannot get cpu info\n"); printf("PROCFS: cannot get CPU info\n");
return; return;
} }

View File

@ -1,6 +0,0 @@
#ifndef __PROCFS_CPUINFO_H__
#define __PROCFS_CPUINFO_H__
void root_cpuinfo(void);
#endif /* __PROCFS_CPUINFO_H__ */

View File

@ -1,44 +1,11 @@
#ifndef _PROCFS_INC_H #ifndef _PROCFS_INC_H
#define _PROCFS_INC_H #define _PROCFS_INC_H
#define _SYSTEM 1 #include <minix/drivers.h>
#include <minix/sysinfo.h>
#include <minix/config.h> #include <minix/vtreefs.h>
#include <limits.h> #include <minix/procfs.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h> #include <assert.h>
#include <fcntl.h>
#include <lib.h>
#include <minix/timers.h>
#include <sys/dirent.h>
#include <minix/callnr.h>
#include <minix/type.h>
#include <minix/const.h>
#include <minix/com.h>
#include <minix/syslib.h>
#include <minix/sysutil.h>
#include <minix/bitmap.h>
#include <minix/vfsif.h>
#include <minix/endpoint.h>
#include <minix/sysinfo.h>
#include <minix/u64.h>
#include <minix/sysinfo.h>
#include <minix/type.h>
#include <minix/ipc.h>
#include <sys/utsname.h>
#include <sys/time.h>
#include <sys/times.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <machine/archtypes.h> #include <machine/archtypes.h>
#include "kernel/const.h" #include "kernel/const.h"
@ -49,9 +16,6 @@
#include "vfs/fproc.h" #include "vfs/fproc.h"
#include "vfs/dmap.h" #include "vfs/dmap.h"
#include <minix/vtreefs.h>
#include <minix/procfs.h>
#include "const.h" #include "const.h"
#include "type.h" #include "type.h"
#include "proto.h" #include "proto.h"

View File

@ -1,7 +1,6 @@
/* ProcFS - main.c - by Alen Stojanov and David van Moolenbroek */ /* ProcFS - main.c - main functions of the process file system */
#include "inc.h" #include "inc.h"
#include "cpuinfo.h"
static void init_hook(void); static void init_hook(void);
@ -14,15 +13,14 @@ static struct fs_hooks hooks = {
.rdlink_hook = rdlink_hook, .rdlink_hook = rdlink_hook,
}; };
/*===========================================================================* /*
* construct_tree * * Construct a tree of static files from a null-terminated array of file
*===========================================================================*/ * structures, recursively creating directories which have their associated
static void construct_tree(struct inode *dir, struct file *files) * data point to child file structures.
*/
static void
construct_tree(struct inode * dir, struct file * files)
{ {
/* Construct a tree of static files from a null-terminated array of
* file structures, recursively creating directories which have their
* associated data point to child file structures.
*/
struct file *file; struct file *file;
struct inode *node; struct inode *node;
struct inode_stat stat; struct inode_stat stat;
@ -35,23 +33,22 @@ static void construct_tree(struct inode *dir, struct file *files)
for (file = files; file->name != NULL; file++) { for (file = files; file->name != NULL; file++) {
stat.mode = file->mode; stat.mode = file->mode;
node = add_inode(dir, file->name, NO_INDEX, &stat, (index_t) 0, node = add_inode(dir, file->name, NO_INDEX, &stat, (index_t)0,
(cbdata_t) file->data); (cbdata_t)file->data);
assert(node != NULL); assert(node != NULL);
if (S_ISDIR(file->mode)) if (S_ISDIR(file->mode))
construct_tree(node, (struct file *) file->data); construct_tree(node, (struct file *)file->data);
} }
} }
/*===========================================================================* /*
* init_hook * * Initialization hook. Generate the static part of the tree.
*===========================================================================*/ */
static void init_hook(void) static void
init_hook(void)
{ {
/* Initialization hook. Generate the static part of the tree.
*/
static int first_time = 1; static int first_time = 1;
struct inode *root; struct inode *root;
@ -64,17 +61,16 @@ static void init_hook(void)
} }
} }
/*===========================================================================* /*
* main * * ProcFS entry point.
*===========================================================================*/ */
int main(void) int main(void)
{ {
/* ProcFS entry point.
*/
struct inode_stat stat; struct inode_stat stat;
int r; int r;
/* Initialize some state. If we are incompatible with the kernel, exit /*
* Initialize some state. If we are incompatible with the kernel, exit
* immediately. * immediately.
*/ */
if ((r = init_tree()) != OK) if ((r = init_tree()) != OK)

View File

@ -1,4 +1,4 @@
/* ProcFS - pid.c - by Alen Stojanov and David van Moolenbroek */ /* ProcFS - pid.c - generators for PID-specific files */
#include "inc.h" #include "inc.h"
@ -14,8 +14,10 @@ static void pid_cmdline(int slot);
static void pid_environ(int slot); static void pid_environ(int slot);
static void pid_map(int slot); static void pid_map(int slot);
/* The files that are dynamically created in each PID directory. The data field /*
* contains each file's read function. Subdirectories are not yet supported. * The files that are dynamically created in each PID directory. The data
* field contains each file's read function. Subdirectories are not yet
* supported.
*/ */
struct file pid_files[] = { struct file pid_files[] = {
{ "psinfo", REG_ALL_MODE, (data_t) pid_psinfo }, { "psinfo", REG_ALL_MODE, (data_t) pid_psinfo },
@ -25,25 +27,23 @@ struct file pid_files[] = {
{ NULL, 0, (data_t) NULL } { NULL, 0, (data_t) NULL }
}; };
/*===========================================================================* /*
* is_zombie * * Is the given slot a zombie process?
*===========================================================================*/ */
static int is_zombie(int slot) static int
is_zombie(int slot)
{ {
/* Is the given slot a zombie process?
*/
return (slot >= NR_TASKS && return (slot >= NR_TASKS &&
(mproc[slot - NR_TASKS].mp_flags & (TRACE_ZOMBIE | ZOMBIE))); (mproc[slot - NR_TASKS].mp_flags & (TRACE_ZOMBIE | ZOMBIE)));
} }
/*===========================================================================* /*
* pid_psinfo * * Print information used by ps(1) and top(1).
*===========================================================================*/ */
static void pid_psinfo(int i) static void
pid_psinfo(int i)
{ {
/* Print information used by ps(1) and top(1).
*/
int pi, task, state, type, p_state, f_state; int pi, task, state, type, p_state, f_state;
char name[PROC_NAME_LEN+1], *p; char name[PROC_NAME_LEN+1], *p;
struct vm_usage_info vui; struct vm_usage_info vui;
@ -78,7 +78,7 @@ static void pid_psinfo(int i)
else if (proc[i].p_rts_flags == 0) else if (proc[i].p_rts_flags == 0)
state = STATE_RUN; /* in run-queue */ state = STATE_RUN; /* in run-queue */
else if (fp_is_blocked(&fproc[pi]) || else if (fp_is_blocked(&fproc[pi]) ||
(mproc[pi].mp_flags & (WAITING | SIGSUSPENDED))) (mproc[pi].mp_flags & (WAITING | SIGSUSPENDED)))
state = STATE_SLEEP; /* sleeping */ state = STATE_SLEEP; /* sleeping */
else else
state = STATE_WAIT; /* waiting */ state = STATE_WAIT; /* waiting */
@ -90,28 +90,29 @@ static void pid_psinfo(int i)
} }
/* We assume that even if a process has become a zombie, its kernel /* We assume that even if a process has become a zombie, its kernel
* proc entry still contains the old (but valid) information. Currently * proc entry still contains the old (although valid) information.
* this is true, but in the future we may have to filter some fields. * Currently this is true, but in the future we may have to filter some
* fields.
*/ */
buf_printf("%d %c %d %s %c %d %d %lu %lu %lu %lu", buf_printf("%d %c %d %s %c %d %d %lu %lu %lu %lu",
PSINFO_VERSION, /* information version */ PSINFO_VERSION, /* information version */
type, /* process type */ type, /* process type */
(int) proc[i].p_endpoint, /* process endpoint */ (int)proc[i].p_endpoint, /* process endpoint */
name, /* process name */ name, /* process name */
state, /* process state letter */ state, /* process state letter */
(int) P_BLOCKEDON(&proc[i]), /* endpt blocked on, or NONE */ (int)P_BLOCKEDON(&proc[i]), /* endpt blocked on, or NONE */
(int) proc[i].p_priority, /* process priority */ (int)proc[i].p_priority, /* process priority */
(long) proc[i].p_user_time, /* user time */ (long)proc[i].p_user_time, /* user time */
(long) proc[i].p_sys_time, /* system time */ (long)proc[i].p_sys_time, /* system time */
ex64hi(proc[i].p_cycles), /* execution cycles */ ex64hi(proc[i].p_cycles), /* execution cycles */
ex64lo(proc[i].p_cycles) ex64lo(proc[i].p_cycles)
); );
memset(&vui, 0, sizeof(vui)); memset(&vui, 0, sizeof(vui));
if (!is_zombie(i)) { if (!is_zombie(i)) {
/* We don't care if this fails. */ /* We don't care if this fails. */
(void) vm_info_usage(proc[i].p_endpoint, &vui); (void)vm_info_usage(proc[i].p_endpoint, &vui);
} }
/* If the process is not a kernel task, we add some extra info. */ /* If the process is not a kernel task, we add some extra info. */
@ -138,69 +139,68 @@ static void pid_psinfo(int i)
default: f_state = FSTATE_UNKNOWN; default: f_state = FSTATE_UNKNOWN;
} }
buf_printf(" %lu %lu %lu %c %d %u %u %u %d %c %d %u", buf_printf(" %lu %lu %lu %c %d %u %u %u %d %c %d %llu",
vui.vui_total, /* total memory */ vui.vui_total, /* total memory */
vui.vui_common, /* common memory */ vui.vui_common, /* common memory */
vui.vui_shared, /* shared memory */ vui.vui_shared, /* shared memory */
p_state, /* sleep state */ p_state, /* sleep state */
ppid, /* parent PID */ ppid, /* parent PID */
mproc[pi].mp_realuid, /* real UID */ mproc[pi].mp_realuid, /* real UID */
mproc[pi].mp_effuid, /* effective UID */ mproc[pi].mp_effuid, /* effective UID */
mproc[pi].mp_procgrp, /* process group */ mproc[pi].mp_procgrp, /* process group */
mproc[pi].mp_nice, /* nice value */ mproc[pi].mp_nice, /* nice value */
f_state, /* VFS block state */ f_state, /* VFS block state */
(int) (fproc[pi].fp_blocked_on == FP_BLOCKED_ON_OTHER) (int)(fproc[pi].fp_blocked_on == FP_BLOCKED_ON_OTHER) ?
? fproc[pi].fp_task : NONE, /* block proc */ fproc[pi].fp_task : NONE, /* block proc */
fproc[pi].fp_tty /* controlling tty */ fproc[pi].fp_tty /* controlling tty */
); );
} }
/* always add kernel cycles */ /* Always add kernel cycles. */
buf_printf(" %lu %lu %lu %lu", buf_printf(" %lu %lu %lu %lu",
ex64hi(proc[i].p_kipc_cycles), ex64hi(proc[i].p_kipc_cycles),
ex64lo(proc[i].p_kipc_cycles), ex64lo(proc[i].p_kipc_cycles),
ex64hi(proc[i].p_kcall_cycles), ex64hi(proc[i].p_kcall_cycles),
ex64lo(proc[i].p_kcall_cycles)); ex64lo(proc[i].p_kcall_cycles));
/* add total memory for tasks at the end */ /* Add total memory for tasks at the end. */
if(task) buf_printf(" %lu", vui.vui_total); if (task)
buf_printf(" %lu", vui.vui_total);
/* Newline at the end of the file. */ /* Newline at the end of the file. */
buf_printf("\n"); buf_printf("\n");
} }
/*===========================================================================* /*
* put_frame * * If we allocated memory dynamically during a call to get_frame(), free it up
*===========================================================================*/ * here.
static void put_frame(void) */
static void
put_frame(void)
{ {
/* If we allocated memory dynamically during a call to get_frame(),
* free it up here.
*/
if (frame != s_frame) if (frame != s_frame)
free(frame); free(frame);
} }
/*===========================================================================* /*
* get_frame * * Get the execution frame from the top of the given process's stack. It may
*===========================================================================*/ * be very large, in which case we temporarily allocate memory for it (up to a
static int get_frame(int slot, vir_bytes *basep, vir_bytes *sizep, * certain size).
size_t *nargsp) */
static int
get_frame(int slot, vir_bytes * basep, vir_bytes * sizep, size_t * nargsp)
{ {
/* Get the execution frame from the top of the given process's stack.
* It may be very large, in which case we temporarily allocate memory
* for it (up to a certain size).
*/
vir_bytes base, size; vir_bytes base, size;
size_t nargs; size_t nargs;
if (proc[slot].p_nr < 0 || is_zombie(slot)) if (proc[slot].p_nr < 0 || is_zombie(slot))
return FALSE; return FALSE;
/* Get the frame base address and size. Limit the size to whatever we /*
* can handle. If our static buffer is not sufficiently large to store * Get the frame base address and size. Limit the size to whatever we
* the entire frame, allocate memory dynamically. It is then later * can handle. If our static buffer is not sufficiently large to store
* the entire frame, allocate memory dynamically. It is then later
* freed by put_frame(). * freed by put_frame().
*/ */
base = mproc[slot - NR_TASKS].mp_frame_addr; base = mproc[slot - NR_TASKS].mp_frame_addr;
@ -215,12 +215,12 @@ static int get_frame(int slot, vir_bytes *basep, vir_bytes *sizep,
if (frame == NULL) if (frame == NULL)
return FALSE; return FALSE;
} } else
else frame = s_frame; frame = s_frame;
/* Copy in the complete process frame. */ /* Copy in the complete process frame. */
if (sys_datacopy(proc[slot].p_endpoint, base, if (sys_datacopy(proc[slot].p_endpoint, base, SELF, (vir_bytes)frame,
SELF, (vir_bytes) frame, (phys_bytes) size) != OK) { (phys_bytes)size) != OK) {
put_frame(); put_frame();
return FALSE; return FALSE;
@ -228,8 +228,9 @@ static int get_frame(int slot, vir_bytes *basep, vir_bytes *sizep,
frame[size] = 0; /* terminate any last string */ frame[size] = 0; /* terminate any last string */
nargs = * (size_t *) frame; nargs = *(size_t *)frame;
if (nargs < 1 || sizeof(size_t) + sizeof(char *) * (nargs + 1) > size) { if (nargs < 1 ||
sizeof(size_t) + sizeof(char *) * (nargs + 1) > size) {
put_frame(); put_frame();
return FALSE; return FALSE;
@ -243,14 +244,13 @@ static int get_frame(int slot, vir_bytes *basep, vir_bytes *sizep,
return TRUE; return TRUE;
} }
/*===========================================================================* /*
* pid_cmdline * * Dump the process's command line as it is contained in the process itself.
*===========================================================================*/ * Each argument is terminated with a null character.
static void pid_cmdline(int slot) */
static void
pid_cmdline(int slot)
{ {
/* Dump the process's command line as it is contained in the process
* itself. Each argument is terminated with a null character.
*/
vir_bytes base, size, ptr; vir_bytes base, size, ptr;
size_t i, len, nargs; size_t i, len, nargs;
char **argv; char **argv;
@ -258,13 +258,13 @@ static void pid_cmdline(int slot)
if (!get_frame(slot, &base, &size, &nargs)) if (!get_frame(slot, &base, &size, &nargs))
return; return;
argv = (char **) &frame[sizeof(size_t)]; argv = (char **)&frame[sizeof(size_t)];
for (i = 0; i < nargs; i++) { for (i = 0; i < nargs; i++) {
ptr = (vir_bytes) argv[i] - base; ptr = (vir_bytes)argv[i] - base;
/* Check for bad pointers. */ /* Check for bad pointers. */
if ((long) ptr < 0L || ptr >= size) if ((long)ptr < 0L || ptr >= size)
break; break;
len = strlen(&frame[ptr]) + 1; len = strlen(&frame[ptr]) + 1;
@ -275,14 +275,13 @@ static void pid_cmdline(int slot)
put_frame(); put_frame();
} }
/*===========================================================================* /*
* pid_environ * * Dump the process's initial environment as it is contained in the process
*===========================================================================*/ * itself. Each entry is terminated with a null character.
static void pid_environ(int slot) */
static void
pid_environ(int slot)
{ {
/* Dump the process's initial environment as it is contained in the
* process itself. Each entry is terminated with a null character.
*/
vir_bytes base, size, ptr; vir_bytes base, size, ptr;
size_t nargs, off, len; size_t nargs, off, len;
char **envp; char **envp;
@ -291,7 +290,7 @@ static void pid_environ(int slot)
return; return;
off = sizeof(size_t) + sizeof(char *) * (nargs + 1); off = sizeof(size_t) + sizeof(char *) * (nargs + 1);
envp = (char **) &frame[off]; envp = (char **)&frame[off];
for (;;) { for (;;) {
/* Make sure there is no buffer overrun. */ /* Make sure there is no buffer overrun. */
@ -307,7 +306,7 @@ static void pid_environ(int slot)
ptr -= base; ptr -= base;
/* Check for bad pointers. */ /* Check for bad pointers. */
if ((long) ptr < 0L || ptr >= size) if ((long)ptr < 0L || ptr >= size)
break; break;
len = strlen(&frame[ptr]) + 1; len = strlen(&frame[ptr]) + 1;
@ -321,13 +320,12 @@ static void pid_environ(int slot)
put_frame(); put_frame();
} }
/*===========================================================================* /*
* dump_regions * * Print the virtual memory regions of a process.
*===========================================================================*/ */
static int dump_regions(int slot) static void
dump_regions(int slot)
{ {
/* Print the virtual memory regions of a process.
*/
struct vm_region_info vri[MAX_VRI_COUNT]; struct vm_region_info vri[MAX_VRI_COUNT];
vir_bytes next; vir_bytes next;
int i, r, count; int i, r, count;
@ -337,44 +335,36 @@ static int dump_regions(int slot)
do { do {
r = vm_info_region(proc[slot].p_endpoint, vri, MAX_VRI_COUNT, r = vm_info_region(proc[slot].p_endpoint, vri, MAX_VRI_COUNT,
&next); &next);
if (r < 0) if (r <= 0)
return r;
if (r == 0)
break; break;
for (i = 0; i < r; i++) { for (i = 0; i < r; i++) {
buf_printf("%08lx-%08lx %c%c%c\n", buf_printf("%08lx-%08lx %c%c%c\n",
vri[i].vri_addr, vri[i].vri_addr + vri[i].vri_length, vri[i].vri_addr,
(vri[i].vri_prot & PROT_READ) ? 'r' : '-', vri[i].vri_addr + vri[i].vri_length,
(vri[i].vri_prot & PROT_WRITE) ? 'w' : '-', (vri[i].vri_prot & PROT_READ) ? 'r' : '-',
(vri[i].vri_prot & PROT_EXEC) ? 'x' : '-'); (vri[i].vri_prot & PROT_WRITE) ? 'w' : '-',
(vri[i].vri_prot & PROT_EXEC) ? 'x' : '-');
count++; count++;
} }
} while (r == MAX_VRI_COUNT); } while (r == MAX_VRI_COUNT);
return count;
} }
/*===========================================================================* /*
* pid_map * * Print a memory map of the process. Obtain the information from VM.
*===========================================================================*/ */
static void pid_map(int slot) static void
pid_map(int slot)
{ {
/* Print a memory map of the process. Obtain the information from VM if
* possible; otherwise fall back on segments from the kernel.
*/
/* Zombies have no memory. */ /* Zombies have no memory. */
if (is_zombie(slot)) if (is_zombie(slot))
return; return;
/* Kernel tasks also have no memory. */ /* Kernel tasks also have no memory. */
if (proc[slot].p_nr >= 0) { if (proc[slot].p_nr >= 0)
if (dump_regions(slot) != 0) dump_regions(slot);
return;
}
} }

View File

@ -3,10 +3,13 @@
/* buf.c */ /* buf.c */
void buf_init(char *ptr, size_t len, off_t start); void buf_init(char *ptr, size_t len, off_t start);
void buf_printf(char *fmt, ...); void buf_printf(char *fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
void buf_append(char *data, size_t len); void buf_append(char *data, size_t len);
ssize_t buf_result(void); ssize_t buf_result(void);
/* cpuinfo.c */
void root_cpuinfo(void);
/* tree.c */ /* tree.c */
int init_tree(void); int init_tree(void);
int lookup_hook(struct inode *parent, char *name, cbdata_t cbdata); int lookup_hook(struct inode *parent, char *name, cbdata_t cbdata);

View File

@ -1,4 +1,4 @@
/* ProcFS - root.c - by Alen Stojanov and David van Moolenbroek */ /* ProcFS - root.c - generators for static files in the root directory */
#include "inc.h" #include "inc.h"
@ -6,7 +6,6 @@
#include <machine/pci.h> #include <machine/pci.h>
#endif #endif
#include <minix/dmap.h> #include <minix/dmap.h>
#include "cpuinfo.h"
static void root_hz(void); static void root_hz(void);
static void root_uptime(void); static void root_uptime(void);
@ -38,24 +37,22 @@ struct file root_files[] = {
{ NULL, 0, NULL } { NULL, 0, NULL }
}; };
/*===========================================================================* /*
* root_hz * * Print the system clock frequency.
*===========================================================================*/ */
static void root_hz(void) static void
root_hz(void)
{ {
/* Print the system clock frequency.
*/
buf_printf("%lu\n", (long) sys_hz()); buf_printf("%lu\n", (unsigned long)sys_hz());
} }
/*===========================================================================* /*
* root_loadavg * * Print load averages.
*===========================================================================*/ */
static void root_loadavg(void) static void
root_loadavg(void)
{ {
/* Print load averages.
*/
struct load loads[3]; struct load loads[3];
ldiv_t avg[3]; ldiv_t avg[3];
@ -67,17 +64,16 @@ static void root_loadavg(void)
avg[2] = ldiv(100L * loads[2].proc_load / loads[2].ticks, 100); avg[2] = ldiv(100L * loads[2].proc_load / loads[2].ticks, 100);
buf_printf("%ld.%02ld %ld.%02ld %ld.%02ld\n", buf_printf("%ld.%02ld %ld.%02ld %ld.%02ld\n",
avg[0].quot, avg[0].rem, avg[1].quot, avg[1].rem, avg[0].quot, avg[0].rem, avg[1].quot, avg[1].rem,
avg[2].quot, avg[2].rem); avg[2].quot, avg[2].rem);
} }
/*===========================================================================* /*
* root_uptime * * Print the current uptime.
*===========================================================================*/ */
static void root_uptime(void) static void
root_uptime(void)
{ {
/* Print the current uptime.
*/
clock_t ticks; clock_t ticks;
ldiv_t division; ldiv_t division;
@ -88,13 +84,12 @@ static void root_uptime(void)
buf_printf("%ld.%0.2ld\n", division.quot, division.rem); buf_printf("%ld.%0.2ld\n", division.quot, division.rem);
} }
/*===========================================================================* /*
* root_kinfo * * Print general kernel information.
*===========================================================================*/ */
static void root_kinfo(void) static void
root_kinfo(void)
{ {
/* Print general kernel information.
*/
struct kinfo kinfo; struct kinfo kinfo;
if (sys_getkinfo(&kinfo) != OK) if (sys_getkinfo(&kinfo) != OK)
@ -103,30 +98,28 @@ static void root_kinfo(void)
buf_printf("%u %u\n", kinfo.nr_procs, kinfo.nr_tasks); buf_printf("%u %u\n", kinfo.nr_procs, kinfo.nr_tasks);
} }
/*===========================================================================* /*
* root_meminfo * * Print general memory information.
*===========================================================================*/ */
static void root_meminfo(void) static void
root_meminfo(void)
{ {
/* Print general memory information.
*/
struct vm_stats_info vsi; struct vm_stats_info vsi;
if (vm_info_stats(&vsi) != OK) if (vm_info_stats(&vsi) != OK)
return; return;
buf_printf("%u %lu %lu %lu %lu\n", vsi.vsi_pagesize, buf_printf("%u %lu %lu %lu %lu\n", vsi.vsi_pagesize, vsi.vsi_total,
vsi.vsi_total, vsi.vsi_free, vsi.vsi_largest, vsi.vsi_cached); vsi.vsi_free, vsi.vsi_largest, vsi.vsi_cached);
} }
/*===========================================================================*
* root_pci *
*===========================================================================*/
#if defined(__i386__) #if defined(__i386__)
static void root_pci(void) /*
* Print information about PCI devices present in the system.
*/
static void
root_pci(void)
{ {
/* Print information about PCI devices present in the system.
*/
u16_t vid, did, subvid, subdid; u16_t vid, did, subvid, subdid;
u8_t bcr, scr, pifr, rev; u8_t bcr, scr, pifr, rev;
char *slot_name, *dev_name; char *slot_name, *dev_name;
@ -153,20 +146,21 @@ static void root_pci(void)
subdid = pci_attr_r16(devind, PCI_SUBDID); subdid = pci_attr_r16(devind, PCI_SUBDID);
buf_printf("%s %x/%x/%x/%x %04X:%04X:%04X:%04X %s\n", buf_printf("%s %x/%x/%x/%x %04X:%04X:%04X:%04X %s\n",
slot_name ? slot_name : "-1.-1.-1.-1", slot_name ? slot_name : "-1.-1.-1.-1",
bcr, scr, pifr, rev, bcr, scr, pifr, rev,
vid, did, subvid, subdid, vid, did, subvid, subdid,
dev_name ? dev_name : ""); dev_name ? dev_name : "");
r = pci_next_dev(&devind, &vid, &did); r = pci_next_dev(&devind, &vid, &did);
} }
} }
#endif /* defined(__i386__) */ #endif /* defined(__i386__) */
/*===========================================================================* /*
* root_dmap * * Print a list of drivers that have been assigned major device numbers.
*===========================================================================*/ */
static void root_dmap(void) static void
root_dmap(void)
{ {
struct dmap dmap[NR_DEVICES]; struct dmap dmap[NR_DEVICES];
int i; int i;
@ -179,30 +173,35 @@ static void root_dmap(void)
continue; continue;
buf_printf("%u %s %u\n", i, dmap[i].dmap_label, buf_printf("%u %s %u\n", i, dmap[i].dmap_label,
dmap[i].dmap_driver); dmap[i].dmap_driver);
} }
} }
/*===========================================================================* /*
* root_ipcvecs * * Print a list of IPC vectors with their addresses.
*===========================================================================*/ */
static void root_ipcvecs(void) static void
root_ipcvecs(void)
{ {
extern struct minix_kerninfo *_minix_kerninfo; extern struct minix_kerninfo *_minix_kerninfo;
extern struct minix_ipcvecs _minix_ipcvecs; extern struct minix_ipcvecs _minix_ipcvecs;
/* only print this if the kernel provides the info; otherwise binaries /*
* will be using their own in-libc vectors that are normal symbols in the * Only print this if the kernel provides the info; otherwise binaries
* binary. * will be using their own in-libc vectors that are normal symbols in
* the binary.
*/ */
if(!_minix_kerninfo || !(_minix_kerninfo->ki_flags & MINIX_KIF_IPCVECS)) if (!_minix_kerninfo ||
!(_minix_kerninfo->ki_flags & MINIX_KIF_IPCVECS))
return; return;
/* print the vectors with an descriptive name and the additional (k) /*
* Print the vectors with an descriptive name and the additional (k)
* to distinguish them from regular symbols. * to distinguish them from regular symbols.
*/ */
#define PRINT_ENTRYPOINT(name) \ #define PRINT_ENTRYPOINT(name) \
buf_printf("%08lx T %s(k)\n", _minix_ipcvecs.name, #name) buf_printf("%08lx T %s(k)\n", \
(unsigned long)_minix_ipcvecs.name, #name)
PRINT_ENTRYPOINT(sendrec); PRINT_ENTRYPOINT(sendrec);
PRINT_ENTRYPOINT(send); PRINT_ENTRYPOINT(send);
@ -213,9 +212,9 @@ static void root_ipcvecs(void)
PRINT_ENTRYPOINT(do_kernel_call); PRINT_ENTRYPOINT(do_kernel_call);
} }
/*===========================================================================* /*
* root_mounts * * Print the list of mounted file systems.
*===========================================================================*/ */
static void static void
root_mounts(void) root_mounts(void)
{ {
@ -227,7 +226,7 @@ root_mounts(void)
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
buf_printf("%s on %s type %s (%s)\n", buf[i].f_mntfromname, buf_printf("%s on %s type %s (%s)\n", buf[i].f_mntfromname,
buf[i].f_mntonname, buf[i].f_fstypename, buf[i].f_mntonname, buf[i].f_fstypename,
(buf[i].f_flag & ST_RDONLY) ? "ro" : "rw"); (buf[i].f_flag & ST_RDONLY) ? "ro" : "rw");
} }
} }

View File

@ -1,4 +1,4 @@
/* ProcFS - tree.c - by Alen Stojanov and David van Moolenbroek */ /* ProcFS - tree.c - dynamic PID tree management and hook implementations */
#include "inc.h" #include "inc.h"
@ -8,36 +8,35 @@ struct fproc fproc[NR_PROCS];
static int nr_pid_entries; static int nr_pid_entries;
/*===========================================================================* /*
* slot_in_use * * Return whether the given slot is in use by a process.
*===========================================================================*/ */
static int slot_in_use(int slot) static int
slot_in_use(int slot)
{ {
/* Return whether the given slot is in use by a process.
*/
/* For kernel tasks, check only the kernel slot. Tasks do not have a /*
* For kernel tasks, check only the kernel slot. Tasks do not have a
* PM/VFS process slot. * PM/VFS process slot.
*/ */
if (slot < NR_TASKS) if (slot < NR_TASKS)
return (proc[slot].p_rts_flags != RTS_SLOT_FREE); return (proc[slot].p_rts_flags != RTS_SLOT_FREE);
/* For regular processes, check only the PM slot. Do not check the /* For regular processes, check only the PM slot. Do not check the
* kernel slot, because that would skip zombie processes. The PID check * kernel slot, because that would skip zombie processes. The PID
* should be redundant, but if it fails, procfs could crash. * check should be redundant, but if it fails, procfs could crash.
*/ */
return ((mproc[slot - NR_TASKS].mp_flags & IN_USE) && return ((mproc[slot - NR_TASKS].mp_flags & IN_USE) &&
mproc[slot - NR_TASKS].mp_pid != 0); mproc[slot - NR_TASKS].mp_pid != 0);
} }
/*===========================================================================* /*
* check_owner * * Check if the owner user and group ID of the inode are still in sync with
*===========================================================================*/ * the current effective user and group ID of the given process.
static int check_owner(struct inode *node, int slot) */
static int
check_owner(struct inode * node, int slot)
{ {
/* Check if the owner user and group ID of the inode are still in sync
* the current effective user and group ID of the given process.
*/
struct inode_stat stat; struct inode_stat stat;
if (slot < NR_TASKS) return TRUE; if (slot < NR_TASKS) return TRUE;
@ -45,17 +44,16 @@ static int check_owner(struct inode *node, int slot)
get_inode_stat(node, &stat); get_inode_stat(node, &stat);
return (stat.uid == mproc[slot - NR_TASKS].mp_effuid && return (stat.uid == mproc[slot - NR_TASKS].mp_effuid &&
stat.gid == mproc[slot - NR_TASKS].mp_effgid); stat.gid == mproc[slot - NR_TASKS].mp_effgid);
} }
/*===========================================================================* /*
* make_stat * * Fill in an inode_stat structure for the given process slot and per-PID file
*===========================================================================*/ * index (or NO_INDEX for the process subdirectory root).
static void make_stat(struct inode_stat *stat, int slot, int index) */
static void
make_stat(struct inode_stat * stat, int slot, int index)
{ {
/* Fill in an inode_stat structure for the given process slot and
* per-pid file index (or NO_INDEX for the process subdirectory root).
*/
if (index == NO_INDEX) if (index == NO_INDEX)
stat->mode = DIR_ALL_MODE; stat->mode = DIR_ALL_MODE;
@ -74,26 +72,24 @@ static void make_stat(struct inode_stat *stat, int slot, int index)
stat->dev = NO_DEV; stat->dev = NO_DEV;
} }
/*===========================================================================* /*
* dir_is_pid * * Return whether the given node is a PID directory.
*===========================================================================*/ */
static int dir_is_pid(struct inode *node) static int
dir_is_pid(struct inode *node)
{ {
/* Return whether the given node is a PID directory.
*/
return (get_parent_inode(node) == get_root_inode() && return (get_parent_inode(node) == get_root_inode() &&
get_inode_index(node) != NO_INDEX); get_inode_index(node) != NO_INDEX);
} }
/*===========================================================================* /*
* update_proc_table * * Get the process table from the kernel. Check the magic number in the table
*===========================================================================*/ * entries.
static int update_proc_table(void) */
static int
update_proc_table(void)
{ {
/* Get the process table from the kernel.
* Check the magic number in the table entries.
*/
int r, slot; int r, slot;
if ((r = sys_getproctab(proc)) != OK) return r; if ((r = sys_getproctab(proc)) != OK) return r;
@ -109,14 +105,12 @@ static int update_proc_table(void)
return OK; return OK;
} }
/*===========================================================================* /*
* update_mproc_table * * Get the process table from PM. Check the magic number in the table entries.
*===========================================================================*/ */
static int update_mproc_table(void) static int
update_mproc_table(void)
{ {
/* Get the process table from PM.
* Check the magic number in the table entries.
*/
int r, slot; int r, slot;
r = getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc, sizeof(mproc)); r = getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc, sizeof(mproc));
@ -133,24 +127,22 @@ static int update_mproc_table(void)
return OK; return OK;
} }
/*===========================================================================* /*
* update_fproc_table * * Get the process table from VFS.
*===========================================================================*/ */
static int update_fproc_table(void) static int
update_fproc_table(void)
{ {
/* Get the process table from VFS.
*/
return getsysinfo(VFS_PROC_NR, SI_PROC_TAB, fproc, sizeof(fproc)); return getsysinfo(VFS_PROC_NR, SI_PROC_TAB, fproc, sizeof(fproc));
} }
/*===========================================================================* /*
* update_tables * * Get the process tables from the kernel, PM, and VFS.
*===========================================================================*/ */
static int update_tables(void) static int
update_tables(void)
{ {
/* Get the process tables from the kernel, PM, and VFS.
*/
int r; int r;
if ((r = update_proc_table()) != OK) return r; if ((r = update_proc_table()) != OK) return r;
@ -162,22 +154,22 @@ static int update_tables(void)
return OK; return OK;
} }
/*===========================================================================* /*
* init_tree * * Initialize this module, before VTreeFS is started. As part of the process,
*===========================================================================*/ * check if we're not compiled against a kernel different from the one that is
int init_tree(void) * running at the moment.
*/
int
init_tree(void)
{ {
/* Initialize this module, before VTreeFS is started. As part of the
* process, check if we're not compiled against a kernel different from
* the one that is running at the moment.
*/
int i, r; int i, r;
if ((r = update_tables()) != OK) if ((r = update_tables()) != OK)
return r; return r;
/* Get the maximum number of entries that we may add to each PID's /*
* directory. We could just default to a large value, but why not get * Get the maximum number of entries that we may add to each PID's
* directory. We could just default to a large value, but why not get
* it right? * it right?
*/ */
for (i = 0; pid_files[i].name != NULL; i++); for (i = 0; pid_files[i].name != NULL; i++);
@ -187,17 +179,15 @@ int init_tree(void)
return OK; return OK;
} }
/*===========================================================================* /*
* out_of_inodes * * Out of inodes - the NR_INODES value is set too low. We can not do much, but
*===========================================================================*/ * we might be able to continue with degraded functionality, so do not panic.
static void out_of_inodes(void) * If the NR_INODES value is not below the *crucial* minimum, the symptom of
* this case will be an incomplete listing of the main proc directory.
*/
static void
out_of_inodes(void)
{ {
/* Out of inodes - the NR_INODES value is set too low. We can not do
* much, but we might be able to continue with degraded functionality,
* so do not panic. If the NR_INODES value is not below the *crucial*
* minimum, the symptom of this case will be an incomplete listing of
* the main proc directory.
*/
static int warned = FALSE; static int warned = FALSE;
if (warned == FALSE) { if (warned == FALSE) {
@ -207,18 +197,18 @@ static void out_of_inodes(void)
} }
} }
/*===========================================================================* /*
* construct_pid_dirs * * Regenerate the set of PID directories in the root directory of the file
*===========================================================================*/ * system. Add new directories and delete old directories as appropriate;
static void construct_pid_dirs(void) * leave unchanged those that should remain the same.
*/
static void
construct_pid_dirs(void)
{ {
/* Regenerate the set of PID directories in the root directory of the /*
* file system. Add new directories and delete old directories as * We have to make two passes. Otherwise, we would trigger a vtreefs
* appropriate; leave unchanged those that should remain the same.
*
* We have to make two passes. Otherwise, we would trigger a vtreefs
* assert when we add an entry for a PID before deleting the previous * assert when we add an entry for a PID before deleting the previous
* entry for that PID. While rare, such rapid PID reuse does occur in * entry for that PID. While rare, such rapid PID reuse does occur in
* practice. * practice.
*/ */
struct inode *root, *node; struct inode *root, *node;
@ -236,7 +226,8 @@ static void construct_pid_dirs(void)
if (node == NULL) if (node == NULL)
continue; continue;
/* If the process slot is not in use, delete the associated /*
* If the process slot is not in use, delete the associated
* inode. * inode.
*/ */
if (!slot_in_use(i)) { if (!slot_in_use(i)) {
@ -247,19 +238,20 @@ static void construct_pid_dirs(void)
/* Otherwise, get the process ID. */ /* Otherwise, get the process ID. */
if (i < NR_TASKS) if (i < NR_TASKS)
pid = (pid_t) (i - NR_TASKS); pid = (pid_t)(i - NR_TASKS);
else else
pid = mproc[i - NR_TASKS].mp_pid; pid = mproc[i - NR_TASKS].mp_pid;
/* If there is an old entry, see if the pid matches the current /*
* entry, and the owner is still the same. Otherwise, delete * If there is an old entry, see if the pid matches the current
* the old entry first. We reconstruct the entire subtree even * entry, and the owner is still the same. Otherwise, delete
* the old entry first. We reconstruct the entire subtree even
* if only the owner changed, for security reasons: if a * if only the owner changed, for security reasons: if a
* process could keep open a file or directory across the owner * process could keep open a file or directory across the owner
* change, it might be able to access information it shouldn't. * change, it might be able to access information it shouldn't.
*/ */
if (pid != (pid_t) get_inode_cbdata(node) || if (pid != (pid_t)get_inode_cbdata(node) ||
!check_owner(node, i)) !check_owner(node, i))
delete_inode(node); delete_inode(node);
} }
@ -269,7 +261,8 @@ static void construct_pid_dirs(void)
if (!slot_in_use(i)) if (!slot_in_use(i))
continue; continue;
/* If we have an inode associated with this slot, we have /*
* If we have an inode associated with this slot, we have
* already checked it to be up-to-date above. * already checked it to be up-to-date above.
*/ */
if (get_inode_by_index(root, i) != NULL) if (get_inode_by_index(root, i) != NULL)
@ -277,7 +270,7 @@ static void construct_pid_dirs(void)
/* Get the process ID. */ /* Get the process ID. */
if (i < NR_TASKS) if (i < NR_TASKS)
pid = (pid_t) (i - NR_TASKS); pid = (pid_t)(i - NR_TASKS);
else else
pid = mproc[i - NR_TASKS].mp_pid; pid = mproc[i - NR_TASKS].mp_pid;
@ -287,21 +280,20 @@ static void construct_pid_dirs(void)
make_stat(&stat, i, NO_INDEX); make_stat(&stat, i, NO_INDEX);
node = add_inode(root, name, i, &stat, nr_pid_entries, node = add_inode(root, name, i, &stat, nr_pid_entries,
(cbdata_t) pid); (cbdata_t)pid);
if (node == NULL) if (node == NULL)
out_of_inodes(); out_of_inodes();
} }
} }
/*===========================================================================* /*
* make_one_pid_entry * * Construct one file in a PID directory, if a file with the given name should
*===========================================================================*/ * exist at all.
static void make_one_pid_entry(struct inode *parent, char *name, int slot) */
static void
make_one_pid_entry(struct inode * parent, char * name, int slot)
{ {
/* Construct one file in a PID directory, if a file with the given name
* should exist at all.
*/
struct inode *node; struct inode *node;
struct inode_stat stat; struct inode_stat stat;
int i; int i;
@ -316,8 +308,8 @@ static void make_one_pid_entry(struct inode *parent, char *name, int slot)
if (!strcmp(name, pid_files[i].name)) { if (!strcmp(name, pid_files[i].name)) {
make_stat(&stat, slot, i); make_stat(&stat, slot, i);
node = add_inode(parent, name, i, &stat, node = add_inode(parent, name, i, &stat, (index_t)0,
(index_t) 0, (cbdata_t) 0); (cbdata_t)0);
if (node == NULL) if (node == NULL)
out_of_inodes(); out_of_inodes();
@ -327,13 +319,12 @@ static void make_one_pid_entry(struct inode *parent, char *name, int slot)
} }
} }
/*===========================================================================* /*
* make_all_pid_entries * * Construct all files in a PID directory.
*===========================================================================*/ */
static void make_all_pid_entries(struct inode *parent, int slot) static void
make_all_pid_entries(struct inode * parent, int slot)
{ {
/* Construct all files in a PID directory.
*/
struct inode *node; struct inode *node;
struct inode_stat stat; struct inode_stat stat;
int i; int i;
@ -346,21 +337,19 @@ static void make_all_pid_entries(struct inode *parent, int slot)
make_stat(&stat, slot, i); make_stat(&stat, slot, i);
node = add_inode(parent, pid_files[i].name, i, &stat, node = add_inode(parent, pid_files[i].name, i, &stat,
(index_t) 0, (cbdata_t) 0); (index_t)0, (cbdata_t)0);
if (node == NULL) if (node == NULL)
out_of_inodes(); out_of_inodes();
} }
} }
/*===========================================================================* /*
* construct_pid_entries * * Construct one requested file entry, or all file entries, in a PID directory.
*===========================================================================*/ */
static void construct_pid_entries(struct inode *parent, char *name) static void
construct_pid_entries(struct inode * parent, char * name)
{ {
/* Construct one requested file entry, or all file entries, in a PID
* directory.
*/
int slot; int slot;
slot = get_inode_index(parent); slot = get_inode_index(parent);
@ -373,8 +362,9 @@ static void construct_pid_entries(struct inode *parent, char *name)
return; return;
} }
/* If a specific file name is being looked up, see if we have to add /*
* an inode for that file. If the directory contents are being * If a specific file name is being looked up, see if we have to add
* an inode for that file. If the directory contents are being
* retrieved, add all files that have not yet been added. * retrieved, add all files that have not yet been added.
*/ */
if (name != NULL) if (name != NULL)
@ -383,18 +373,18 @@ static void construct_pid_entries(struct inode *parent, char *name)
make_all_pid_entries(parent, slot); make_all_pid_entries(parent, slot);
} }
/*===========================================================================* /*
* pid_read * * Data is requested from one of the files in a PID directory. Call the
*===========================================================================*/ * function that is responsible for generating the data for that file.
static void pid_read(struct inode *node) */
static void
pid_read(struct inode * node)
{ {
/* Data is requested from one of the files in a PID directory. Call the
* function that is responsible for generating the data for that file.
*/
struct inode *parent; struct inode *parent;
int slot, index; int slot, index;
/* Get the slot number of the process. Note that this currently will /*
* Get the slot number of the process. Note that this currently will
* not work for files not in the top-level pid subdirectory. * not work for files not in the top-level pid subdirectory.
*/ */
parent = get_parent_inode(node); parent = get_parent_inode(node);
@ -405,17 +395,16 @@ static void pid_read(struct inode *node)
index = get_inode_index(node); index = get_inode_index(node);
/* Call the handler procedure for the file. */ /* Call the handler procedure for the file. */
((void (*) (int)) pid_files[index].data)(slot); ((void (*)(int))pid_files[index].data)(slot);
} }
/*===========================================================================* /*
* pid_link * * The contents of a symbolic link in a PID directory are requested. This
*===========================================================================*/ * function is a placeholder for future use.
static int pid_link(struct inode *UNUSED(node), char *ptr, int max) */
static int
pid_link(struct inode * __unused node, char * ptr, int max)
{ {
/* The contents of a symbolic link in a PID directory are requested.
* This function is a placeholder for future use.
*/
/* Nothing yet. */ /* Nothing yet. */
strlcpy(ptr, "", max); strlcpy(ptr, "", max);
@ -423,21 +412,20 @@ static int pid_link(struct inode *UNUSED(node), char *ptr, int max)
return OK; return OK;
} }
/*===========================================================================* /*
* lookup_hook * * Path name resolution hook, for a specific parent and name pair. If needed,
*===========================================================================*/ * update our own view of the system first; after that, determine whether we
int lookup_hook(struct inode *parent, char *name, * need to (re)generate certain files.
cbdata_t UNUSED(cbdata)) */
int
lookup_hook(struct inode * parent, char * name, cbdata_t __unused cbdata)
{ {
/* Path name resolution hook, for a specific parent and name pair.
* If needed, update our own view of the system first; after that,
* determine whether we need to (re)generate certain files.
*/
static clock_t last_update = 0; static clock_t last_update = 0;
clock_t now; clock_t now;
int r; int r;
/* Update lazily for lookups, as this gets too expensive otherwise. /*
* Update lazily for lookups, as this gets too expensive otherwise.
* Alternative: pull in only PM's table? * Alternative: pull in only PM's table?
*/ */
if ((r = getticks(&now)) != OK) if ((r = getticks(&now)) != OK)
@ -449,85 +437,79 @@ int lookup_hook(struct inode *parent, char *name,
last_update = now; last_update = now;
} }
/* If the parent is the root directory, we must now reconstruct all /*
* If the parent is the root directory, we must now reconstruct all
* entries, because some of them might have been garbage collected. * entries, because some of them might have been garbage collected.
* We must update the entire tree at once; if we update individual * We must update the entire tree at once; if we update individual
* entries, we risk name collisions. * entries, we risk name collisions.
*/ *
if (parent == get_root_inode()) { * If the parent is a process directory, we may need to (re)construct
construct_pid_dirs();
}
/* If the parent is a process directory, we may need to (re)construct
* the entry being looked up. * the entry being looked up.
*/ */
else if (dir_is_pid(parent)) { if (parent == get_root_inode())
/* We might now have deleted our current containing directory; construct_pid_dirs();
else if (dir_is_pid(parent))
/*
* We might now have deleted our current containing directory;
* construct_pid_entries() will take care of this case. * construct_pid_entries() will take care of this case.
*/ */
construct_pid_entries(parent, name); construct_pid_entries(parent, name);
}
return OK; return OK;
} }
/*===========================================================================* /*
* getdents_hook * * Directory entry retrieval hook, for potentially all files in a directory.
*===========================================================================*/ * Make sure that all files that are supposed to be returned, are actually part
int getdents_hook(struct inode *node, cbdata_t UNUSED(cbdata)) * of the virtual tree.
*/
int
getdents_hook(struct inode * node, cbdata_t __unused cbdata)
{ {
/* Directory entry retrieval hook, for potentially all files in a
* directory. Make sure that all files that are supposed to be
* returned, are actually part of the virtual tree.
*/
if (node == get_root_inode()) { if (node == get_root_inode()) {
update_tables(); update_tables();
construct_pid_dirs(); construct_pid_dirs();
} else if (dir_is_pid(node)) { } else if (dir_is_pid(node))
construct_pid_entries(node, NULL /*name*/); construct_pid_entries(node, NULL /*name*/);
}
return OK; return OK;
} }
/*===========================================================================* /*
* read_hook * * Regular file read hook. Call the appropriate callback function to generate
*===========================================================================*/ * and return the data.
ssize_t read_hook(struct inode *node, char *ptr, size_t len, off_t off, */
ssize_t
read_hook(struct inode * node, char * ptr, size_t len, off_t off,
cbdata_t cbdata) cbdata_t cbdata)
{ {
/* Regular file read hook. Call the appropriate callback function to
* generate and return the data.
*/
buf_init(ptr, len, off); buf_init(ptr, len, off);
/* Populate the buffer with the proper content. */ /* Populate the buffer with the proper content. */
if (get_inode_index(node) != NO_INDEX) { if (get_inode_index(node) != NO_INDEX)
pid_read(node); pid_read(node);
} else { else
((void (*) (void)) cbdata)(); ((void (*)(void))cbdata)();
}
return buf_result(); return buf_result();
} }
/*===========================================================================* /*
* rdlink_hook * * Symbolic link resolution hook. Not used yet.
*===========================================================================*/ */
int rdlink_hook(struct inode *node, char *ptr, size_t max, int
cbdata_t UNUSED(cbdata)) rdlink_hook(struct inode * node, char * ptr, size_t max,
cbdata_t __unused cbdata)
{ {
/* Symbolic link resolution hook. Not used yet.
*/
struct inode *parent; struct inode *parent;
/* Get the parent inode. */ /* Get the parent inode. */
parent = get_parent_inode(node); parent = get_parent_inode(node);
/* If the parent inode is a pid directory, call the pid handler. /* If the parent inode is a pid directory, call the pid handler. */
*/
if (parent != NULL && dir_is_pid(parent)) if (parent != NULL && dir_is_pid(parent))
pid_link(node, ptr, max); pid_link(node, ptr, max);

View File

@ -8,8 +8,9 @@ struct load {
long proc_load; /* .. the CPU had this load */ long proc_load; /* .. the CPU had this load */
}; };
/* ProcFS supports two groups of files: dynamic files, which are created within /*
* process-specific (PID) directories, and static files, which are global. For * ProcFS supports two groups of files: dynamic files, which are created within
* process-specific (PID) directories, and static files, which are global. For
* both, the following structure is used to construct the files. * both, the following structure is used to construct the files.
* *
* For dynamic files, the rules are simple: only regular files are supported * For dynamic files, the rules are simple: only regular files are supported
@ -21,48 +22,49 @@ struct load {
* The function will be called whenever a read request for the file is made; * The function will be called whenever a read request for the file is made;
* 'slot' contains the kernel slot number of the process being queried (so for * 'slot' contains the kernel slot number of the process being queried (so for
* the PM and VFS process tables, NR_TASKS has to be subtracted from the slot * the PM and VFS process tables, NR_TASKS has to be subtracted from the slot
* number to find the right slot). The function is expected to produce * number to find the right slot). The function is expected to produce
* appropriate output using the buf_printf() function. * appropriate output using the buf_printf() function.
* *
* For static files, regular files and directories are supported. For * For static files, regular files and directories are supported. For
* directories, the 'data' field must be a pointer to another 'struct file' * directories, the 'data' field must be a pointer to another 'struct file'
* array that specifies the contents of the directory - this directory will * array that specifies the contents of the directory - this directory will
* the be created recursively. For regular files, the 'data' field must point * the be created recursively. For regular files, the 'data' field must point
* to a function of the type: * to a function of the type:
* *
* void (*)(void) * void (*)(void)
* *
* Here too, the function will be called upon a read request, and it is * Here too, the function will be called upon a read request, and it is
* supposed to "fill" the file using buf_printf(). Obviously, for static files, * supposed to "fill" the file using buf_printf(). Obviously, for static
* there is no slot number. * files, there is no slot number.
* *
* For both static and dynamic files, 'mode' must specify the file type as well * For both static and dynamic files, 'mode' must specify the file type as well
* as the access mode, and in both cases, each array is terminated with an * as the access mode, and in both cases, each array is terminated with an
* entry that has its name set to NULL. * entry that has its name set to NULL.
*/ */
/* The internal link between static/dynamic files/directories and VTreeFS' /*
* The internal link between static/dynamic files/directories and VTreeFS'
* indexes and cbdata values is as follows: * indexes and cbdata values is as follows:
* - Dynamic directories are always PID directories in the root directory. * - Dynamic directories are always PID directories in the root directory.
* They are generated automatically, and are not specified using a "struct * They are generated automatically, and are not specified using a "struct
* file" structure. Their index is their slot number, so that getdents() * file" structure. Their index is their slot number, so that getdents()
* calls always return any PID at most once. Their cbdata value is the PID of * calls always return any PID at most once. Their cbdata value is the PID
* the process associated with that dynamic directory, for the purpose of * of the process associated with that dynamic directory, for the purpose of
* comparing old and new PIDs after updating process tables (without having * comparing old and new PIDs after updating process tables (without having
* to atoi() the directory's name). * to atoi() the directory's name).
* - Dynamic files are always in such a dynamic directory. Their index is the * - Dynamic files are always in such a dynamic directory. Their index is the
* array index into the "struct file" array of pid files (pid_files[]). They * array index into the "struct file" array of pid files (pid_files[]). They
* are indexed at all, because they may be deleted at any time due to inode * are indexed at all because they may be deleted at any time due to inode
* shortages, independently of other dynamic files in the same directory, and * shortages, independently of other dynamic files in the same directory.
* recreating them without index would again risk possibly inconsistent * Recreating them without index would again risk possibly inconsistent
* getdents() results, where for example the same file shows up twice. * getdents() results, where for example the same file shows up twice.
* VTreeFS currently does not distinguish between indexed and delatable files * VTreeFS currently does not distinguish between indexed and deletable files
* and hence, all dynamic files must be indexed so as to be deletable anyway. * and hence, all dynamic files must be indexed so as to be deletable anyway.
* - Static directories have no index (they are not and must not be deletable), * - Static directories have no index (they are not and must not be deletable),
* and although their cbdata is their associated 'data' field from their * and although their cbdata is their associated 'data' field from their
* "struct file" entries, their cbdata value is currently not relied on * "struct file" entries, their cbdata value is currently not relied on
* anywhere. Then again, as of writing, there are no static directories at * anywhere. Then again, as of writing, there are no static directories at
* all. * all.
* - Static files have no index either (for the same reason). Their cbdata is * - Static files have no index either (for the same reason). Their cbdata is
* also their 'data' field from the "struct file" entry creating the file, * also their 'data' field from the "struct file" entry creating the file,
* and this is used to actually call the callback function directly. * and this is used to actually call the callback function directly.
*/ */

View File

@ -1,59 +1,59 @@
/* ProcFS - util.c - by Alen Stojanov and David van Moolenbroek */ /* ProcFS - util.c - utility functions */
#include "inc.h" #include "inc.h"
/*===========================================================================* /*
* procfs_getloadavg * * Retrieve system load average information.
*===========================================================================*/ */
int procfs_getloadavg(struct load *loadavg, int nelem) int
procfs_getloadavg(struct load * loadavg, int nelem)
{ {
/* Retrieve system load average information.
*/
struct loadinfo loadinfo; struct loadinfo loadinfo;
u32_t system_hz, ticks_per_slot; u32_t system_hz, ticks_per_slot;
int p, unfilled_ticks; int p, unfilled_ticks;
int h, slots, latest, slot;
int minutes[3] = { 1, 5, 15 }; int minutes[3] = { 1, 5, 15 };
ssize_t l; ssize_t l;
if(nelem < 1) { if (nelem < 1) {
errno = ENOSPC; errno = ENOSPC;
return -1; return -1;
} }
system_hz = sys_hz(); system_hz = sys_hz();
if((l=sys_getloadinfo(&loadinfo)) != OK) if ((l = sys_getloadinfo(&loadinfo)) != OK)
return -1; return -1;
if(nelem > 3) if (nelem > 3)
nelem = 3; nelem = 3;
/* How many ticks are missing from the newest-filled slot? */ /* How many ticks are missing from the newest-filled slot? */
ticks_per_slot = _LOAD_UNIT_SECS * system_hz; ticks_per_slot = _LOAD_UNIT_SECS * system_hz;
unfilled_ticks = unfilled_ticks =
ticks_per_slot - (loadinfo.last_clock % ticks_per_slot); ticks_per_slot - (loadinfo.last_clock % ticks_per_slot);
for(p = 0; p < nelem; p++) { for (p = 0; p < nelem; p++) {
int h, slots; latest = loadinfo.proc_last_slot;
int latest = loadinfo.proc_last_slot;
slots = minutes[p] * 60 / _LOAD_UNIT_SECS; slots = minutes[p] * 60 / _LOAD_UNIT_SECS;
loadavg[p].proc_load = 0; loadavg[p].proc_load = 0;
/* Add up the total number of process ticks for this number /*
* of minutes (minutes[p]). Start with the newest slot, which * Add up the total number of process ticks for this number
* of minutes (minutes[p]). Start with the newest slot, which
* is latest, and count back for the number of slots that * is latest, and count back for the number of slots that
* correspond to the right number of minutes. Take wraparound * correspond to the right number of minutes. Take wraparound
* into account by calculating the index modulo _LOAD_HISTORY, * into account by calculating the index modulo _LOAD_HISTORY,
* which is the number of slots of history kept. * which is the number of slots of history kept.
*/ */
for(h = 0; h < slots; h++) { for (h = 0; h < slots; h++) {
int slot;
slot = (latest - h + _LOAD_HISTORY) % _LOAD_HISTORY; slot = (latest - h + _LOAD_HISTORY) % _LOAD_HISTORY;
loadavg[p].proc_load += loadavg[p].proc_load +=
loadinfo.proc_load_history[slot]; loadinfo.proc_load_history[slot];
l += (ssize_t) loadinfo.proc_load_history[slot]; l += (ssize_t) loadinfo.proc_load_history[slot];
} }
/* The load average over this number of minutes is the number /*
* The load average over this number of minutes is the number
* of process-ticks divided by the number of ticks, not * of process-ticks divided by the number of ticks, not
* counting the number of ticks the last slot hasn't been * counting the number of ticks the last slot hasn't been
* around yet. * around yet.