procfs: convert to KNF
Change-Id: Ib4252f199af0f9597745dcd2c11a7f761738671f
This commit is contained in:
parent
52be5c0afb
commit
f1abbce725
13 changed files with 501 additions and 556 deletions
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
|
||||
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.
|
||||
/*
|
||||
* Add formatted text to the end of the buffer.
|
||||
*/
|
||||
void
|
||||
buf_printf(char * fmt, ...)
|
||||
{
|
||||
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)
|
||||
|
@ -82,13 +82,12 @@ void buf_printf(char *fmt, ...)
|
|||
left -= len;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* buf_append *
|
||||
*===========================================================================*/
|
||||
void buf_append(char *data, size_t len)
|
||||
{
|
||||
/* Add arbitrary data to the end of the buffer.
|
||||
/*
|
||||
* Add arbitrary data to the end of the buffer.
|
||||
*/
|
||||
void
|
||||
buf_append(char * data, size_t len)
|
||||
{
|
||||
|
||||
if (left == 0)
|
||||
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.
|
||||
/*
|
||||
* Return the resulting number of bytes produced, not counting the trailing
|
||||
* null character in the buffer.
|
||||
*/
|
||||
ssize_t
|
||||
buf_result(void)
|
||||
{
|
||||
|
||||
return used;
|
||||
}
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
#ifndef _PROCFS_CONST_H
|
||||
#define _PROCFS_CONST_H
|
||||
|
||||
/* The minimum number of inodes depends on a number of factors:
|
||||
/*
|
||||
* 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
|
||||
* 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
|
||||
|
|
|
@ -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,8 +96,13 @@ 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__)
|
||||
|
@ -105,7 +116,7 @@ static void print_cpu(struct cpu_info * cpu_info, unsigned id)
|
|||
buf_printf("%-16s: %s\n", "model name", "AMD");
|
||||
break;
|
||||
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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef __PROCFS_CPUINFO_H__
|
||||
#define __PROCFS_CPUINFO_H__
|
||||
|
||||
void root_cpuinfo(void);
|
||||
|
||||
#endif /* __PROCFS_CPUINFO_H__ */
|
|
@ -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"
|
||||
|
|
|
@ -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.
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
struct file *file;
|
||||
struct inode *node;
|
||||
struct inode_stat stat;
|
||||
|
@ -45,13 +43,12 @@ static void construct_tree(struct inode *dir, struct file *files)
|
|||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* init_hook *
|
||||
*===========================================================================*/
|
||||
static void init_hook(void)
|
||||
{
|
||||
/* Initialization hook. Generate the static part of the tree.
|
||||
/*
|
||||
* Initialization hook. Generate the static part of the tree.
|
||||
*/
|
||||
static void
|
||||
init_hook(void)
|
||||
{
|
||||
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)
|
||||
|
|
|
@ -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?
|
||||
/*
|
||||
* Is the given slot a zombie process?
|
||||
*/
|
||||
static int
|
||||
is_zombie(int slot)
|
||||
{
|
||||
|
||||
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).
|
||||
/*
|
||||
* Print information used by ps(1) and top(1).
|
||||
*/
|
||||
static void
|
||||
pid_psinfo(int i)
|
||||
{
|
||||
int pi, task, state, type, p_state, f_state;
|
||||
char name[PROC_NAME_LEN+1], *p;
|
||||
struct vm_usage_info vui;
|
||||
|
@ -90,8 +90,9 @@ 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 */
|
||||
|
@ -138,7 +139,7 @@ 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",
|
||||
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 */
|
||||
|
@ -149,56 +150,55 @@ static void pid_psinfo(int i)
|
|||
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 */
|
||||
(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));
|
||||
|
||||
/* 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.
|
||||
/*
|
||||
* If we allocated memory dynamically during a call to get_frame(), free it up
|
||||
* here.
|
||||
*/
|
||||
static void
|
||||
put_frame(void)
|
||||
{
|
||||
|
||||
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).
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
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
|
||||
/*
|
||||
* 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().
|
||||
|
@ -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;
|
||||
|
@ -229,7 +229,8 @@ 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) {
|
||||
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.
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
vir_bytes base, size, ptr;
|
||||
size_t i, len, nargs;
|
||||
char **argv;
|
||||
|
@ -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.
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
vir_bytes base, size, ptr;
|
||||
size_t nargs, off, len;
|
||||
char **envp;
|
||||
|
@ -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.
|
||||
/*
|
||||
* Print the virtual memory regions of a process.
|
||||
*/
|
||||
static void
|
||||
dump_regions(int slot)
|
||||
{
|
||||
struct vm_region_info vri[MAX_VRI_COUNT];
|
||||
vir_bytes next;
|
||||
int i, r, count;
|
||||
|
@ -339,15 +337,13 @@ static int dump_regions(int slot)
|
|||
r = vm_info_region(proc[slot].p_endpoint, vri, MAX_VRI_COUNT,
|
||||
&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_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' : '-');
|
||||
|
@ -355,26 +351,20 @@ static int dump_regions(int slot)
|
|||
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 if
|
||||
* possible; otherwise fall back on segments from the kernel.
|
||||
/*
|
||||
* Print a memory map of the process. Obtain the information from VM.
|
||||
*/
|
||||
static void
|
||||
pid_map(int slot)
|
||||
{
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
/*
|
||||
* Print the system clock frequency.
|
||||
*/
|
||||
static void
|
||||
root_hz(void)
|
||||
{
|
||||
|
||||
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.
|
||||
/*
|
||||
* Print load averages.
|
||||
*/
|
||||
static void
|
||||
root_loadavg(void)
|
||||
{
|
||||
struct load loads[3];
|
||||
ldiv_t avg[3];
|
||||
|
||||
|
@ -71,13 +68,12 @@ static void root_loadavg(void)
|
|||
avg[2].quot, avg[2].rem);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* root_uptime *
|
||||
*===========================================================================*/
|
||||
static void root_uptime(void)
|
||||
{
|
||||
/* Print the current uptime.
|
||||
/*
|
||||
* Print the current uptime.
|
||||
*/
|
||||
static void
|
||||
root_uptime(void)
|
||||
{
|
||||
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.
|
||||
/*
|
||||
* Print general kernel information.
|
||||
*/
|
||||
static void
|
||||
root_kinfo(void)
|
||||
{
|
||||
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.
|
||||
/*
|
||||
* Print general memory information.
|
||||
*/
|
||||
static void
|
||||
root_meminfo(void)
|
||||
{
|
||||
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.
|
||||
/*
|
||||
* Print information about PCI devices present in the system.
|
||||
*/
|
||||
static void
|
||||
root_pci(void)
|
||||
{
|
||||
u16_t vid, did, subvid, subdid;
|
||||
u8_t bcr, scr, pifr, rev;
|
||||
char *slot_name, *dev_name;
|
||||
|
@ -163,10 +156,11 @@ static void root_pci(void)
|
|||
}
|
||||
#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;
|
||||
|
@ -183,26 +177,31 @@ static void root_dmap(void)
|
|||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* 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)
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
/*
|
||||
* Return whether the given slot is in use by a process.
|
||||
*/
|
||||
static int
|
||||
slot_in_use(int slot)
|
||||
{
|
||||
|
||||
/* 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.
|
||||
* 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);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* 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
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
struct inode_stat stat;
|
||||
|
||||
if (slot < NR_TASKS) return TRUE;
|
||||
|
@ -48,14 +47,13 @@ static int check_owner(struct inode *node, int slot)
|
|||
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).
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
|
||||
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.
|
||||
/*
|
||||
* Return whether the given node is a PID directory.
|
||||
*/
|
||||
static int
|
||||
dir_is_pid(struct inode *node)
|
||||
{
|
||||
|
||||
return (get_parent_inode(node) == get_root_inode() &&
|
||||
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.
|
||||
/*
|
||||
* Get the process table from the kernel. Check the magic number in the table
|
||||
* entries.
|
||||
*/
|
||||
static int
|
||||
update_proc_table(void)
|
||||
{
|
||||
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.
|
||||
/*
|
||||
* Get the process table from PM. Check the magic number in the table entries.
|
||||
*/
|
||||
static int
|
||||
update_mproc_table(void)
|
||||
{
|
||||
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.
|
||||
/*
|
||||
* Get the process table from VFS.
|
||||
*/
|
||||
static int
|
||||
update_fproc_table(void)
|
||||
{
|
||||
|
||||
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.
|
||||
/*
|
||||
* Get the process tables from the kernel, PM, and VFS.
|
||||
*/
|
||||
static int
|
||||
update_tables(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
if ((r = update_proc_table()) != OK) return r;
|
||||
|
@ -162,21 +154,21 @@ 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.
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
int i, r;
|
||||
|
||||
if ((r = update_tables()) != OK)
|
||||
return r;
|
||||
|
||||
/* Get the maximum number of entries that we may add to each PID's
|
||||
/*
|
||||
* 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?
|
||||
*/
|
||||
|
@ -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.
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
static int warned = FALSE;
|
||||
|
||||
if (warned == FALSE) {
|
||||
|
@ -207,15 +197,15 @@ 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
|
||||
* 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
|
||||
|
@ -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)) {
|
||||
|
@ -251,7 +242,8 @@ static void construct_pid_dirs(void)
|
|||
else
|
||||
pid = mproc[i - NR_TASKS].mp_pid;
|
||||
|
||||
/* If there is an old entry, see if the pid matches the current
|
||||
/*
|
||||
* 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
|
||||
|
@ -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)
|
||||
|
@ -294,14 +287,13 @@ static void construct_pid_dirs(void)
|
|||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* 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.
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
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.
|
||||
/*
|
||||
* Construct all files in a PID directory.
|
||||
*/
|
||||
static void
|
||||
make_all_pid_entries(struct inode * parent, int slot)
|
||||
{
|
||||
struct inode *node;
|
||||
struct inode_stat stat;
|
||||
int i;
|
||||
|
@ -353,14 +344,12 @@ static void make_all_pid_entries(struct inode *parent, int slot)
|
|||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* 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.
|
||||
/*
|
||||
* Construct one requested file entry, or all file entries, in a PID directory.
|
||||
*/
|
||||
static void
|
||||
construct_pid_entries(struct inode * parent, char * name)
|
||||
{
|
||||
int slot;
|
||||
|
||||
slot = get_inode_index(parent);
|
||||
|
@ -373,7 +362,8 @@ 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
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
@ -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
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
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);
|
||||
|
@ -408,14 +398,13 @@ static void pid_read(struct inode *node)
|
|||
((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.
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
|
||||
/* 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.
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
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.
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
|
||||
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 {
|
||||
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.
|
||||
/*
|
||||
* Symbolic link resolution hook. Not used yet.
|
||||
*/
|
||||
int
|
||||
rdlink_hook(struct inode * node, char * ptr, size_t max,
|
||||
cbdata_t __unused cbdata)
|
||||
{
|
||||
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);
|
||||
|
||||
|
|
|
@ -8,7 +8,8 @@ struct load {
|
|||
long proc_load; /* .. the CPU had this load */
|
||||
};
|
||||
|
||||
/* ProcFS supports two groups of files: dynamic files, which are created within
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
|
@ -33,29 +34,30 @@ struct load {
|
|||
* 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
|
||||
* 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
|
||||
* 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
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
/* 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.
|
||||
/*
|
||||
* Retrieve system load average information.
|
||||
*/
|
||||
int
|
||||
procfs_getloadavg(struct load * loadavg, int nelem)
|
||||
{
|
||||
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;
|
||||
|
||||
|
@ -33,12 +33,12 @@ int procfs_getloadavg(struct load *loadavg, int nelem)
|
|||
ticks_per_slot - (loadinfo.last_clock % ticks_per_slot);
|
||||
|
||||
for (p = 0; p < nelem; p++) {
|
||||
int h, slots;
|
||||
int latest = loadinfo.proc_last_slot;
|
||||
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
|
||||
/*
|
||||
* 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
|
||||
|
@ -46,14 +46,14 @@ int procfs_getloadavg(struct load *loadavg, int nelem)
|
|||
* which is the number of slots of history kept.
|
||||
*/
|
||||
for (h = 0; h < slots; h++) {
|
||||
int slot;
|
||||
slot = (latest - h + _LOAD_HISTORY) % _LOAD_HISTORY;
|
||||
loadavg[p].proc_load +=
|
||||
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.
|
||||
|
|
Loading…
Reference in a new issue