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>
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/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 <stdarg.h>
@ -7,17 +7,16 @@ static char *buf;
static size_t left, used;
static off_t skip;
/*===========================================================================*
* buf_init *
*===========================================================================*/
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.
*/
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;
skip = start;
@ -25,20 +24,20 @@ void buf_init(char *ptr, size_t len, off_t start)
used = 0;
}
/*===========================================================================*
* buf_printf *
*===========================================================================*/
void buf_printf(char *fmt, ...)
/*
* Add formatted text to the end of the buffer.
*/
void
buf_printf(char * fmt, ...)
{
/* Add formatted text to the end of the buffer.
*/
va_list args;
ssize_t len, max;
if (left == 0)
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.
* 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
@ -50,7 +49,8 @@ void buf_printf(char *fmt, ...)
len = vsnprintf(&buf[used], max, fmt, 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 (len >= BUF_SIZE)
@ -75,26 +75,25 @@ void buf_printf(char *fmt, ...)
assert(len >= 0);
assert((ssize_t) left >= 0);
if (len > (ssize_t) left)
if (len > (ssize_t)left)
len = left;
used += len;
left -= len;
}
/*===========================================================================*
* buf_append *
*===========================================================================*/
void buf_append(char *data, size_t len)
/*
* Add arbitrary data to the end of the buffer.
*/
void
buf_append(char * data, size_t len)
{
/* Add arbitrary data to the end of the buffer.
*/
if (left == 0)
return;
if (skip > 0) {
if (skip >= (ssize_t) len) {
if (skip >= (ssize_t)len) {
skip -= len;
return;
@ -114,14 +113,13 @@ void buf_append(char *data, size_t len)
left -= len;
}
/*===========================================================================*
* buf_result *
*===========================================================================*/
ssize_t buf_result(void)
/*
* Return the resulting number of bytes produced, not counting the trailing
* null character in the buffer.
*/
ssize_t
buf_result(void)
{
/* Return the resulting number of bytes produced, not counting the
* trailing null character in the buffer.
*/
return used;
}

View file

@ -1,24 +1,26 @@
#ifndef _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.
* - 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
* retained as well (to allow the user to "cd .." out). VTreeFS already takes
* care of this. In the case of ProcFS, only PID-based directories can be
* deleted; no other directories are dynamically created. These directories
* currently do not contain subdirectories, either. Hence, for deleted open
* inodes, we need to reserve at most NR_VNODES inodes in the worst case.
* retained as well (to allow the user to "cd .." out). VTreeFS already
* takes care of this. In the case of ProcFS, only PID-based directories can
* be deleted; no other directories are dynamically created. These
* directories currently do not contain subdirectories, either. Hence, for
* 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,
* 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.
* 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
* 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.
*
* 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"
#if defined(__i386__)
#include "../../kernel/arch/i386/include/archconst.h"
#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;
for (i = 0; i < 2; i++) {
for (j = 0; j < 32; j++) {
if (flags[i] & (1 << j) &&
x86_flag[i * 32 + j][0])
if (flags[i] & (1 << j) && x86_flag[i * 32 + j][0])
buf_printf("%s ", x86_flag[i * 32 + j]);
}
}
@ -90,22 +96,27 @@ static void print_x86_cpu_flags(u32_t * flags)
}
#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);
#if defined(__i386__)
switch (cpu_info->vendor) {
case CPU_VENDOR_INTEL:
buf_printf("%-16s: %s\n", "vendor_id", "GenuineIntel");
buf_printf("%-16s: %s\n", "model name", "Intel");
break;
case CPU_VENDOR_AMD:
buf_printf("%-16s: %s\n", "vendor_id", "AuthenticAMD");
buf_printf("%-16s: %s\n", "model name", "AMD");
break;
default:
buf_printf("%-16: %s\n", "vendor_id", "unknown");
case CPU_VENDOR_INTEL:
buf_printf("%-16s: %s\n", "vendor_id", "GenuineIntel");
buf_printf("%-16s: %s\n", "model name", "Intel");
break;
case CPU_VENDOR_AMD:
buf_printf("%-16s: %s\n", "vendor_id", "AuthenticAMD");
buf_printf("%-16s: %s\n", "model name", "AMD");
break;
default:
buf_printf("%-16s: %s\n", "vendor_id", "unknown");
}
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
}
void root_cpuinfo(void)
/*
* Generate the contents of /proc/cpuinfo.
*/
void
root_cpuinfo(void)
{
struct cpu_info cpu_info[CONFIG_MAX_CPUS];
struct machine machine;
unsigned c;
unsigned int c;
if (sys_getmachine(&machine)) {
printf("PROCFS: cannot get machine\n");
return;
}
if (sys_getcpuinfo(&cpu_info)) {
printf("PROCFS: cannot get cpu info\n");
printf("PROCFS: cannot get CPU info\n");
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
#define _PROCFS_INC_H
#define _SYSTEM 1
#include <minix/config.h>
#include <limits.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <minix/drivers.h>
#include <minix/sysinfo.h>
#include <minix/vtreefs.h>
#include <minix/procfs.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 "kernel/const.h"
@ -49,9 +16,6 @@
#include "vfs/fproc.h"
#include "vfs/dmap.h"
#include <minix/vtreefs.h>
#include <minix/procfs.h>
#include "const.h"
#include "type.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 "cpuinfo.h"
static void init_hook(void);
@ -14,15 +13,14 @@ static struct fs_hooks hooks = {
.rdlink_hook = rdlink_hook,
};
/*===========================================================================*
* construct_tree *
*===========================================================================*/
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.
*/
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 inode *node;
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++) {
stat.mode = file->mode;
node = add_inode(dir, file->name, NO_INDEX, &stat, (index_t) 0,
(cbdata_t) file->data);
node = add_inode(dir, file->name, NO_INDEX, &stat, (index_t)0,
(cbdata_t)file->data);
assert(node != NULL);
if (S_ISDIR(file->mode))
construct_tree(node, (struct file *) file->data);
construct_tree(node, (struct file *)file->data);
}
}
/*===========================================================================*
* init_hook *
*===========================================================================*/
static void init_hook(void)
/*
* Initialization hook. Generate the static part of the tree.
*/
static void
init_hook(void)
{
/* Initialization hook. Generate the static part of the tree.
*/
static int first_time = 1;
struct inode *root;
@ -64,17 +61,16 @@ static void init_hook(void)
}
}
/*===========================================================================*
* main *
*===========================================================================*/
/*
* ProcFS entry point.
*/
int main(void)
{
/* ProcFS entry point.
*/
struct inode_stat stat;
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.
*/
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"
@ -14,8 +14,10 @@ static void pid_cmdline(int slot);
static void pid_environ(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[] = {
{ "psinfo", REG_ALL_MODE, (data_t) pid_psinfo },
@ -25,25 +27,23 @@ struct file pid_files[] = {
{ NULL, 0, (data_t) NULL }
};
/*===========================================================================*
* is_zombie *
*===========================================================================*/
static int is_zombie(int slot)
/*
* Is the given slot a zombie process?
*/
static int
is_zombie(int slot)
{
/* Is the given slot a zombie process?
*/
return (slot >= NR_TASKS &&
(mproc[slot - NR_TASKS].mp_flags & (TRACE_ZOMBIE | ZOMBIE)));
}
/*===========================================================================*
* pid_psinfo *
*===========================================================================*/
static void pid_psinfo(int i)
/*
* Print information used by ps(1) and top(1).
*/
static void
pid_psinfo(int i)
{
/* Print information used by ps(1) and top(1).
*/
int pi, task, state, type, p_state, f_state;
char name[PROC_NAME_LEN+1], *p;
struct vm_usage_info vui;
@ -78,7 +78,7 @@ static void pid_psinfo(int i)
else if (proc[i].p_rts_flags == 0)
state = STATE_RUN; /* in run-queue */
else if (fp_is_blocked(&fproc[pi]) ||
(mproc[pi].mp_flags & (WAITING | SIGSUSPENDED)))
(mproc[pi].mp_flags & (WAITING | SIGSUSPENDED)))
state = STATE_SLEEP; /* sleeping */
else
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
* proc entry still contains the old (but valid) information. Currently
* this is true, but in the future we may have to filter some fields.
* proc entry still contains the old (although valid) information.
* 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",
PSINFO_VERSION, /* information version */
type, /* process type */
(int) proc[i].p_endpoint, /* process endpoint */
name, /* process name */
state, /* process state letter */
(int) P_BLOCKEDON(&proc[i]), /* endpt blocked on, or NONE */
(int) proc[i].p_priority, /* process priority */
(long) proc[i].p_user_time, /* user time */
(long) proc[i].p_sys_time, /* system time */
ex64hi(proc[i].p_cycles), /* execution cycles */
ex64lo(proc[i].p_cycles)
PSINFO_VERSION, /* information version */
type, /* process type */
(int)proc[i].p_endpoint, /* process endpoint */
name, /* process name */
state, /* process state letter */
(int)P_BLOCKEDON(&proc[i]), /* endpt blocked on, or NONE */
(int)proc[i].p_priority, /* process priority */
(long)proc[i].p_user_time, /* user time */
(long)proc[i].p_sys_time, /* system time */
ex64hi(proc[i].p_cycles), /* execution cycles */
ex64lo(proc[i].p_cycles)
);
memset(&vui, 0, sizeof(vui));
if (!is_zombie(i)) {
/* 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. */
@ -138,69 +139,68 @@ static void pid_psinfo(int i)
default: f_state = FSTATE_UNKNOWN;
}
buf_printf(" %lu %lu %lu %c %d %u %u %u %d %c %d %u",
vui.vui_total, /* total memory */
vui.vui_common, /* common memory */
vui.vui_shared, /* shared memory */
p_state, /* sleep state */
ppid, /* parent PID */
mproc[pi].mp_realuid, /* real UID */
mproc[pi].mp_effuid, /* effective UID */
mproc[pi].mp_procgrp, /* process group */
mproc[pi].mp_nice, /* nice value */
f_state, /* VFS block state */
(int) (fproc[pi].fp_blocked_on == FP_BLOCKED_ON_OTHER)
? fproc[pi].fp_task : NONE, /* block proc */
fproc[pi].fp_tty /* controlling tty */
buf_printf(" %lu %lu %lu %c %d %u %u %u %d %c %d %llu",
vui.vui_total, /* total memory */
vui.vui_common, /* common memory */
vui.vui_shared, /* shared memory */
p_state, /* sleep state */
ppid, /* parent PID */
mproc[pi].mp_realuid, /* real UID */
mproc[pi].mp_effuid, /* effective UID */
mproc[pi].mp_procgrp, /* process group */
mproc[pi].mp_nice, /* nice value */
f_state, /* VFS block state */
(int)(fproc[pi].fp_blocked_on == FP_BLOCKED_ON_OTHER) ?
fproc[pi].fp_task : NONE, /* block proc */
fproc[pi].fp_tty /* controlling tty */
);
}
/* always add kernel cycles */
/* Always add kernel cycles. */
buf_printf(" %lu %lu %lu %lu",
ex64hi(proc[i].p_kipc_cycles),
ex64lo(proc[i].p_kipc_cycles),
ex64hi(proc[i].p_kcall_cycles),
ex64lo(proc[i].p_kcall_cycles));
ex64hi(proc[i].p_kipc_cycles),
ex64lo(proc[i].p_kipc_cycles),
ex64hi(proc[i].p_kcall_cycles),
ex64lo(proc[i].p_kcall_cycles));
/* add total memory for tasks at the end */
if(task) buf_printf(" %lu", vui.vui_total);
/* Add total memory for tasks at the end. */
if (task)
buf_printf(" %lu", vui.vui_total);
/* Newline at the end of the file. */
buf_printf("\n");
}
/*===========================================================================*
* put_frame *
*===========================================================================*/
static void put_frame(void)
/*
* If we allocated memory dynamically during a call to get_frame(), free it up
* here.
*/
static void
put_frame(void)
{
/* If we allocated memory dynamically during a call to get_frame(),
* free it up here.
*/
if (frame != s_frame)
free(frame);
}
/*===========================================================================*
* get_frame *
*===========================================================================*/
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).
*/
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;
size_t nargs;
if (proc[slot].p_nr < 0 || is_zombie(slot))
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
* the entire frame, allocate memory dynamically. It is then later
/*
* 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
* the entire frame, allocate memory dynamically. It is then later
* freed by put_frame().
*/
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)
return FALSE;
}
else frame = s_frame;
} else
frame = s_frame;
/* Copy in the complete process frame. */
if (sys_datacopy(proc[slot].p_endpoint, base,
SELF, (vir_bytes) frame, (phys_bytes) size) != OK) {
if (sys_datacopy(proc[slot].p_endpoint, base, SELF, (vir_bytes)frame,
(phys_bytes)size) != OK) {
put_frame();
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 */
nargs = * (size_t *) frame;
if (nargs < 1 || sizeof(size_t) + sizeof(char *) * (nargs + 1) > size) {
nargs = *(size_t *)frame;
if (nargs < 1 ||
sizeof(size_t) + sizeof(char *) * (nargs + 1) > size) {
put_frame();
return FALSE;
@ -243,14 +244,13 @@ static int get_frame(int slot, vir_bytes *basep, vir_bytes *sizep,
return TRUE;
}
/*===========================================================================*
* pid_cmdline *
*===========================================================================*/
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.
*/
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;
size_t i, len, nargs;
char **argv;
@ -258,13 +258,13 @@ static void pid_cmdline(int slot)
if (!get_frame(slot, &base, &size, &nargs))
return;
argv = (char **) &frame[sizeof(size_t)];
argv = (char **)&frame[sizeof(size_t)];
for (i = 0; i < nargs; i++) {
ptr = (vir_bytes) argv[i] - base;
ptr = (vir_bytes)argv[i] - base;
/* Check for bad pointers. */
if ((long) ptr < 0L || ptr >= size)
if ((long)ptr < 0L || ptr >= size)
break;
len = strlen(&frame[ptr]) + 1;
@ -275,14 +275,13 @@ static void pid_cmdline(int slot)
put_frame();
}
/*===========================================================================*
* pid_environ *
*===========================================================================*/
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.
*/
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;
size_t nargs, off, len;
char **envp;
@ -291,7 +290,7 @@ static void pid_environ(int slot)
return;
off = sizeof(size_t) + sizeof(char *) * (nargs + 1);
envp = (char **) &frame[off];
envp = (char **)&frame[off];
for (;;) {
/* Make sure there is no buffer overrun. */
@ -307,7 +306,7 @@ static void pid_environ(int slot)
ptr -= base;
/* Check for bad pointers. */
if ((long) ptr < 0L || ptr >= size)
if ((long)ptr < 0L || ptr >= size)
break;
len = strlen(&frame[ptr]) + 1;
@ -321,13 +320,12 @@ static void pid_environ(int slot)
put_frame();
}
/*===========================================================================*
* dump_regions *
*===========================================================================*/
static int dump_regions(int slot)
/*
* Print the virtual memory regions of a process.
*/
static void
dump_regions(int slot)
{
/* Print the virtual memory regions of a process.
*/
struct vm_region_info vri[MAX_VRI_COUNT];
vir_bytes next;
int i, r, count;
@ -337,44 +335,36 @@ static int dump_regions(int slot)
do {
r = vm_info_region(proc[slot].p_endpoint, vri, MAX_VRI_COUNT,
&next);
&next);
if (r < 0)
return r;
if (r == 0)
if (r <= 0)
break;
for (i = 0; i < r; i++) {
buf_printf("%08lx-%08lx %c%c%c\n",
vri[i].vri_addr, vri[i].vri_addr + vri[i].vri_length,
(vri[i].vri_prot & PROT_READ) ? 'r' : '-',
(vri[i].vri_prot & PROT_WRITE) ? 'w' : '-',
(vri[i].vri_prot & PROT_EXEC) ? 'x' : '-');
vri[i].vri_addr,
vri[i].vri_addr + vri[i].vri_length,
(vri[i].vri_prot & PROT_READ) ? 'r' : '-',
(vri[i].vri_prot & PROT_WRITE) ? 'w' : '-',
(vri[i].vri_prot & PROT_EXEC) ? 'x' : '-');
count++;
}
} while (r == MAX_VRI_COUNT);
return count;
}
/*===========================================================================*
* pid_map *
*===========================================================================*/
static void pid_map(int slot)
/*
* Print a memory map of the process. Obtain the information from VM.
*/
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. */
if (is_zombie(slot))
return;
/* Kernel tasks also have no memory. */
if (proc[slot].p_nr >= 0) {
if (dump_regions(slot) != 0)
return;
}
if (proc[slot].p_nr >= 0)
dump_regions(slot);
}

View file

@ -3,10 +3,13 @@
/* buf.c */
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);
ssize_t buf_result(void);
/* cpuinfo.c */
void root_cpuinfo(void);
/* tree.c */
int init_tree(void);
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"
@ -6,7 +6,6 @@
#include <machine/pci.h>
#endif
#include <minix/dmap.h>
#include "cpuinfo.h"
static void root_hz(void);
static void root_uptime(void);
@ -38,24 +37,22 @@ struct file root_files[] = {
{ NULL, 0, NULL }
};
/*===========================================================================*
* root_hz *
*===========================================================================*/
static void root_hz(void)
/*
* Print the system clock frequency.
*/
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 *
*===========================================================================*/
static void root_loadavg(void)
/*
* Print load averages.
*/
static void
root_loadavg(void)
{
/* Print load averages.
*/
struct load loads[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);
buf_printf("%ld.%02ld %ld.%02ld %ld.%02ld\n",
avg[0].quot, avg[0].rem, avg[1].quot, avg[1].rem,
avg[2].quot, avg[2].rem);
avg[0].quot, avg[0].rem, avg[1].quot, avg[1].rem,
avg[2].quot, avg[2].rem);
}
/*===========================================================================*
* root_uptime *
*===========================================================================*/
static void root_uptime(void)
/*
* Print the current uptime.
*/
static void
root_uptime(void)
{
/* Print the current uptime.
*/
clock_t ticks;
ldiv_t division;
@ -88,13 +84,12 @@ static void root_uptime(void)
buf_printf("%ld.%0.2ld\n", division.quot, division.rem);
}
/*===========================================================================*
* root_kinfo *
*===========================================================================*/
static void root_kinfo(void)
/*
* Print general kernel information.
*/
static void
root_kinfo(void)
{
/* Print general kernel information.
*/
struct kinfo kinfo;
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);
}
/*===========================================================================*
* root_meminfo *
*===========================================================================*/
static void root_meminfo(void)
/*
* Print general memory information.
*/
static void
root_meminfo(void)
{
/* Print general memory information.
*/
struct vm_stats_info vsi;
if (vm_info_stats(&vsi) != OK)
return;
buf_printf("%u %lu %lu %lu %lu\n", vsi.vsi_pagesize,
vsi.vsi_total, vsi.vsi_free, vsi.vsi_largest, vsi.vsi_cached);
buf_printf("%u %lu %lu %lu %lu\n", vsi.vsi_pagesize, vsi.vsi_total,
vsi.vsi_free, vsi.vsi_largest, vsi.vsi_cached);
}
/*===========================================================================*
* root_pci *
*===========================================================================*/
#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;
u8_t bcr, scr, pifr, rev;
char *slot_name, *dev_name;
@ -153,20 +146,21 @@ static void root_pci(void)
subdid = pci_attr_r16(devind, PCI_SUBDID);
buf_printf("%s %x/%x/%x/%x %04X:%04X:%04X:%04X %s\n",
slot_name ? slot_name : "-1.-1.-1.-1",
bcr, scr, pifr, rev,
vid, did, subvid, subdid,
dev_name ? dev_name : "");
slot_name ? slot_name : "-1.-1.-1.-1",
bcr, scr, pifr, rev,
vid, did, subvid, subdid,
dev_name ? dev_name : "");
r = pci_next_dev(&devind, &vid, &did);
}
}
#endif /* defined(__i386__) */
/*===========================================================================*
* root_dmap *
*===========================================================================*/
static void root_dmap(void)
/*
* Print a list of drivers that have been assigned major device numbers.
*/
static void
root_dmap(void)
{
struct dmap dmap[NR_DEVICES];
int i;
@ -179,30 +173,35 @@ static void root_dmap(void)
continue;
buf_printf("%u %s %u\n", i, dmap[i].dmap_label,
dmap[i].dmap_driver);
dmap[i].dmap_driver);
}
}
/*===========================================================================*
* root_ipcvecs *
*===========================================================================*/
static void root_ipcvecs(void)
/*
* Print a list of IPC vectors with their addresses.
*/
static void
root_ipcvecs(void)
{
extern struct minix_kerninfo *_minix_kerninfo;
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
* binary.
/*
* 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 binary.
*/
if(!_minix_kerninfo || !(_minix_kerninfo->ki_flags & MINIX_KIF_IPCVECS))
if (!_minix_kerninfo ||
!(_minix_kerninfo->ki_flags & MINIX_KIF_IPCVECS))
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.
*/
#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(send);
@ -213,9 +212,9 @@ static void root_ipcvecs(void)
PRINT_ENTRYPOINT(do_kernel_call);
}
/*===========================================================================*
* root_mounts *
*===========================================================================*/
/*
* Print the list of mounted file systems.
*/
static void
root_mounts(void)
{
@ -227,7 +226,7 @@ root_mounts(void)
for (i = 0; i < count; i++) {
buf_printf("%s on %s type %s (%s)\n", buf[i].f_mntfromname,
buf[i].f_mntonname, buf[i].f_fstypename,
(buf[i].f_flag & ST_RDONLY) ? "ro" : "rw");
}
buf[i].f_mntonname, buf[i].f_fstypename,
(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"
@ -8,36 +8,35 @@ struct fproc fproc[NR_PROCS];
static int nr_pid_entries;
/*===========================================================================*
* slot_in_use *
*===========================================================================*/
static int slot_in_use(int slot)
/*
* Return whether the given slot is in use by a process.
*/
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.
*/
if (slot < NR_TASKS)
return (proc[slot].p_rts_flags != RTS_SLOT_FREE);
/* For regular processes, check only the PM slot. Do not check the
* kernel slot, because that would skip zombie processes. The PID check
* should be redundant, but if it fails, procfs could crash.
/* For regular processes, check only the PM slot. Do not check the
* kernel slot, because that would skip zombie processes. The PID
* check should be redundant, but if it fails, procfs could crash.
*/
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 *
*===========================================================================*/
static int check_owner(struct inode *node, int slot)
/*
* 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)
{
/* 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;
if (slot < NR_TASKS) return TRUE;
@ -45,17 +44,16 @@ static int check_owner(struct inode *node, int slot)
get_inode_stat(node, &stat);
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 *
*===========================================================================*/
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).
*/
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)
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;
}
/*===========================================================================*
* dir_is_pid *
*===========================================================================*/
static int dir_is_pid(struct inode *node)
/*
* Return whether the given node is a PID directory.
*/
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() &&
get_inode_index(node) != NO_INDEX);
get_inode_index(node) != NO_INDEX);
}
/*===========================================================================*
* update_proc_table *
*===========================================================================*/
static int update_proc_table(void)
/*
* Get the process table from the kernel. Check the magic number in the table
* entries.
*/
static int
update_proc_table(void)
{
/* Get the process table from the kernel.
* Check the magic number in the table entries.
*/
int r, slot;
if ((r = sys_getproctab(proc)) != OK) return r;
@ -109,14 +105,12 @@ static int update_proc_table(void)
return OK;
}
/*===========================================================================*
* update_mproc_table *
*===========================================================================*/
static int update_mproc_table(void)
/*
* Get the process table from PM. Check the magic number in the table entries.
*/
static int
update_mproc_table(void)
{
/* Get the process table from PM.
* Check the magic number in the table entries.
*/
int r, slot;
r = getsysinfo(PM_PROC_NR, SI_PROC_TAB, mproc, sizeof(mproc));
@ -133,24 +127,22 @@ static int update_mproc_table(void)
return OK;
}
/*===========================================================================*
* update_fproc_table *
*===========================================================================*/
static int update_fproc_table(void)
/*
* Get the process table from VFS.
*/
static int
update_fproc_table(void)
{
/* Get the process table from VFS.
*/
return getsysinfo(VFS_PROC_NR, SI_PROC_TAB, fproc, sizeof(fproc));
}
/*===========================================================================*
* update_tables *
*===========================================================================*/
static int update_tables(void)
/*
* Get the process tables from the kernel, PM, and VFS.
*/
static int
update_tables(void)
{
/* Get the process tables from the kernel, PM, and VFS.
*/
int r;
if ((r = update_proc_table()) != OK) return r;
@ -162,22 +154,22 @@ static int update_tables(void)
return OK;
}
/*===========================================================================*
* init_tree *
*===========================================================================*/
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
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;
if ((r = update_tables()) != OK)
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?
*/
for (i = 0; pid_files[i].name != NULL; i++);
@ -187,17 +179,15 @@ int init_tree(void)
return OK;
}
/*===========================================================================*
* out_of_inodes *
*===========================================================================*/
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 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;
if (warned == FALSE) {
@ -207,18 +197,18 @@ static void out_of_inodes(void)
}
}
/*===========================================================================*
* construct_pid_dirs *
*===========================================================================*/
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 appropriate;
* 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
* appropriate; leave unchanged those that should remain the same.
*
* We have to make two passes. Otherwise, we would trigger a vtreefs
/*
* 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
* 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.
*/
struct inode *root, *node;
@ -236,7 +226,8 @@ static void construct_pid_dirs(void)
if (node == NULL)
continue;
/* If the process slot is not in use, delete the associated
/*
* If the process slot is not in use, delete the associated
* inode.
*/
if (!slot_in_use(i)) {
@ -247,19 +238,20 @@ static void construct_pid_dirs(void)
/* Otherwise, get the process ID. */
if (i < NR_TASKS)
pid = (pid_t) (i - NR_TASKS);
pid = (pid_t)(i - NR_TASKS);
else
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
* the old entry first. We reconstruct the entire subtree even
/*
* If there is an old entry, see if the pid matches the current
* 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
* process could keep open a file or directory across the owner
* change, it might be able to access information it shouldn't.
*/
if (pid != (pid_t) get_inode_cbdata(node) ||
!check_owner(node, i))
if (pid != (pid_t)get_inode_cbdata(node) ||
!check_owner(node, i))
delete_inode(node);
}
@ -269,7 +261,8 @@ static void construct_pid_dirs(void)
if (!slot_in_use(i))
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.
*/
if (get_inode_by_index(root, i) != NULL)
@ -277,7 +270,7 @@ static void construct_pid_dirs(void)
/* Get the process ID. */
if (i < NR_TASKS)
pid = (pid_t) (i - NR_TASKS);
pid = (pid_t)(i - NR_TASKS);
else
pid = mproc[i - NR_TASKS].mp_pid;
@ -287,21 +280,20 @@ static void construct_pid_dirs(void)
make_stat(&stat, i, NO_INDEX);
node = add_inode(root, name, i, &stat, nr_pid_entries,
(cbdata_t) pid);
(cbdata_t)pid);
if (node == NULL)
out_of_inodes();
}
}
/*===========================================================================*
* make_one_pid_entry *
*===========================================================================*/
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.
*/
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_stat stat;
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)) {
make_stat(&stat, slot, i);
node = add_inode(parent, name, i, &stat,
(index_t) 0, (cbdata_t) 0);
node = add_inode(parent, name, i, &stat, (index_t)0,
(cbdata_t)0);
if (node == NULL)
out_of_inodes();
@ -327,13 +319,12 @@ static void make_one_pid_entry(struct inode *parent, char *name, int slot)
}
}
/*===========================================================================*
* make_all_pid_entries *
*===========================================================================*/
static void make_all_pid_entries(struct inode *parent, int slot)
/*
* Construct all files in a PID directory.
*/
static void
make_all_pid_entries(struct inode * parent, int slot)
{
/* Construct all files in a PID directory.
*/
struct inode *node;
struct inode_stat stat;
int i;
@ -346,21 +337,19 @@ static void make_all_pid_entries(struct inode *parent, int slot)
make_stat(&stat, slot, i);
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)
out_of_inodes();
}
}
/*===========================================================================*
* construct_pid_entries *
*===========================================================================*/
static void construct_pid_entries(struct inode *parent, char *name)
/*
* Construct one requested file entry, or all file entries, in a PID directory.
*/
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;
slot = get_inode_index(parent);
@ -373,8 +362,9 @@ static void construct_pid_entries(struct inode *parent, char *name)
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.
*/
if (name != NULL)
@ -383,18 +373,18 @@ static void construct_pid_entries(struct inode *parent, char *name)
make_all_pid_entries(parent, slot);
}
/*===========================================================================*
* pid_read *
*===========================================================================*/
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.
*/
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;
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.
*/
parent = get_parent_inode(node);
@ -405,17 +395,16 @@ static void pid_read(struct inode *node)
index = get_inode_index(node);
/* Call the handler procedure for the file. */
((void (*) (int)) pid_files[index].data)(slot);
((void (*)(int))pid_files[index].data)(slot);
}
/*===========================================================================*
* pid_link *
*===========================================================================*/
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.
*/
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. */
strlcpy(ptr, "", max);
@ -423,21 +412,20 @@ static int pid_link(struct inode *UNUSED(node), char *ptr, int max)
return OK;
}
/*===========================================================================*
* lookup_hook *
*===========================================================================*/
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.
*/
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;
clock_t now;
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?
*/
if ((r = getticks(&now)) != OK)
@ -449,85 +437,79 @@ int lookup_hook(struct inode *parent, char *name,
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.
* We must update the entire tree at once; if we update individual
* entries, we risk name collisions.
*/
if (parent == get_root_inode()) {
construct_pid_dirs();
}
/* If the parent is a process directory, we may need to (re)construct
*
* If the parent is a process directory, we may need to (re)construct
* the entry being looked up.
*/
else if (dir_is_pid(parent)) {
/* We might now have deleted our current containing directory;
if (parent == get_root_inode())
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(parent, name);
}
return OK;
}
/*===========================================================================*
* getdents_hook *
*===========================================================================*/
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.
*/
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()) {
update_tables();
construct_pid_dirs();
} else if (dir_is_pid(node)) {
} else if (dir_is_pid(node))
construct_pid_entries(node, NULL /*name*/);
}
return OK;
}
/*===========================================================================*
* read_hook *
*===========================================================================*/
ssize_t read_hook(struct inode *node, char *ptr, size_t len, off_t off,
/*
* 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,
cbdata_t cbdata)
{
/* Regular file read hook. Call the appropriate callback function to
* generate and return the data.
*/
buf_init(ptr, len, off);
/* Populate the buffer with the proper content. */
if (get_inode_index(node) != NO_INDEX) {
if (get_inode_index(node) != NO_INDEX)
pid_read(node);
} else {
((void (*) (void)) cbdata)();
}
else
((void (*)(void))cbdata)();
return buf_result();
}
/*===========================================================================*
* rdlink_hook *
*===========================================================================*/
int rdlink_hook(struct inode *node, char *ptr, size_t max,
cbdata_t UNUSED(cbdata))
/*
* Symbolic link resolution hook. Not used yet.
*/
int
rdlink_hook(struct inode * node, char * ptr, size_t max,
cbdata_t __unused cbdata)
{
/* Symbolic link resolution hook. Not used yet.
*/
struct inode *parent;
/* Get the parent inode. */
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))
pid_link(node, ptr, max);

View file

@ -8,8 +8,9 @@ struct 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.
*
* 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;
* '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
* 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.
*
* 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'
* 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:
*
* void (*)(void)
*
* 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,
* there is no slot number.
* supposed to "fill" the file using buf_printf(). Obviously, for static
* files, there is no slot number.
*
* 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
* 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:
* - Dynamic directories are always PID directories in the root directory.
* They are generated automatically, and are not specified using a "struct
* 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
* the process associated with that dynamic directory, for the purpose of
* 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 the process associated with that dynamic directory, for the purpose of
* comparing old and new PIDs after updating process tables (without having
* to atoi() the directory's name).
* - 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
* 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
* recreating them without index would again risk possibly inconsistent
* - 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
* 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.
* Recreating them without index would again risk possibly inconsistent
* 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.
* - Static directories have no index (they are not and must not be deletable),
* and although their cbdata is their associated 'data' field from their
* "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.
* - 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,
* 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"
/*===========================================================================*
* procfs_getloadavg *
*===========================================================================*/
int procfs_getloadavg(struct load *loadavg, int nelem)
/*
* Retrieve system load average information.
*/
int
procfs_getloadavg(struct load * loadavg, int nelem)
{
/* Retrieve system load average information.
*/
struct loadinfo loadinfo;
u32_t system_hz, ticks_per_slot;
int p, unfilled_ticks;
int h, slots, latest, slot;
int minutes[3] = { 1, 5, 15 };
ssize_t l;
if(nelem < 1) {
if (nelem < 1) {
errno = ENOSPC;
return -1;
}
system_hz = sys_hz();
if((l=sys_getloadinfo(&loadinfo)) != OK)
if ((l = sys_getloadinfo(&loadinfo)) != OK)
return -1;
if(nelem > 3)
if (nelem > 3)
nelem = 3;
/* How many ticks are missing from the newest-filled slot? */
ticks_per_slot = _LOAD_UNIT_SECS * system_hz;
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++) {
int h, slots;
int latest = loadinfo.proc_last_slot;
for (p = 0; p < nelem; p++) {
latest = loadinfo.proc_last_slot;
slots = minutes[p] * 60 / _LOAD_UNIT_SECS;
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
* 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,
* which is the number of slots of history kept.
*/
for(h = 0; h < slots; h++) {
int slot;
for (h = 0; h < slots; h++) {
slot = (latest - h + _LOAD_HISTORY) % _LOAD_HISTORY;
loadavg[p].proc_load +=
loadinfo.proc_load_history[slot];
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
* counting the number of ticks the last slot hasn't been
* around yet.