Provide core dumping support for AVFS

This commit is contained in:
Thomas Veerman 2011-12-08 10:47:11 +00:00
parent 5acd97c7e0
commit 0a61519eea
12 changed files with 457 additions and 96 deletions

View file

@ -7,7 +7,7 @@ SRCS= main.c open.c read.c write.c pipe.c dmap.c \
filedes.c stadir.c protect.c time.c \
lock.c misc.c utility.c select.c table.c \
vnode.c vmnt.c request.c fscall.c \
tll.c comm.c worker.c
tll.c comm.c worker.c coredump.c
.if ${MKCOVERAGE} != "no"
SRCS+= gcov.c

309
servers/avfs/coredump.c Normal file
View file

@ -0,0 +1,309 @@
#include "fs.h"
#include <fcntl.h>
#include <string.h>
#include "fproc.h"
#include <minix/vm.h>
#include <sys/mman.h>
#include <machine/elf.h>
#include "param.h"
/* Include ELF headers */
#include <sys/elf_core.h>
FORWARD _PROTOTYPE( void fill_elf_header, (Elf32_Ehdr *elf_header, int phnum));
FORWARD _PROTOTYPE( void fill_prog_header, (Elf32_Phdr *prog_header,
Elf32_Word p_type, Elf32_Off p_offset, Elf32_Addr p_vaddr,
Elf32_Word p_flags, Elf32_Word p_filesz, Elf32_Word p_memsz) );
FORWARD _PROTOTYPE( int get_memory_regions, (Elf32_Phdr phdrs[]) );
FORWARD _PROTOTYPE( void fill_note_segment_and_entries_hdrs,
(Elf32_Phdr phdrs[], Elf32_Nhdr nhdrs[]));
FORWARD _PROTOTYPE( void adjust_offsets, (Elf32_Phdr phdrs[], int phnum));
FORWARD _PROTOTYPE( void dump_elf_header, (struct filp *f,
Elf32_Ehdr elf_header) );
FORWARD _PROTOTYPE( void dump_notes, (struct filp *f, Elf32_Nhdr nhdrs[],
int csig, char *proc_name) );
FORWARD _PROTOTYPE( void dump_program_headers, (struct filp *f,
Elf_Phdr phdrs[], int phnum));
FORWARD _PROTOTYPE( void dump_segments, (struct filp *f, Elf32_Phdr phdrs[],
int phnum) );
FORWARD _PROTOTYPE( void write_buf, (struct filp *f, char *buf, size_t size));
/*===========================================================================*
* write_elf_core_file *
*===========================================================================*/
PUBLIC void write_elf_core_file(struct filp *f, int csig, char *proc_name)
{
/* First, fill in all the required headers, second, adjust the offsets,
* third, dump everything into the core file
*/
#define MAX_REGIONS 20
#define NR_NOTE_ENTRIES 2
Elf_Ehdr elf_header;
Elf_Phdr phdrs[MAX_REGIONS + 1];
Elf_Nhdr nhdrs[NR_NOTE_ENTRIES];
int phnum;
/* Fill in the NOTE Program Header - at phdrs[0] - and
* note entries' headers
*/
fill_note_segment_and_entries_hdrs(phdrs, nhdrs);
/* Get the memory segments and fill in the Program headers */
phnum = get_memory_regions(phdrs) + 1;
/* Fill in the ELF header */
fill_elf_header(&elf_header, phnum);
/* Adjust offsets in program headers - The layout in the ELF core file
* is the following: the ELF Header, the Note Program Header,
* the rest of Program Headers (memory segments), Note contents,
* the program segments' contents
*/
adjust_offsets(phdrs, phnum);
/* Write ELF header */
dump_elf_header(f, elf_header);
/* Write Program headers (Including the NOTE) */
dump_program_headers(f, phdrs, phnum);
/* Write NOTE contents */
dump_notes(f, nhdrs, csig, proc_name);
/* Write segments' contents */
dump_segments(f, phdrs, phnum);
}
/*===========================================================================*
* fill_elf_header *
*===========================================================================*/
PRIVATE void fill_elf_header (Elf_Ehdr *elf_header, int phnum)
{
memset((void *) elf_header, 0, sizeof(Elf_Ehdr));
elf_header->e_ident[EI_MAG0] = ELFMAG0;
elf_header->e_ident[EI_MAG1] = ELFMAG1;
elf_header->e_ident[EI_MAG2] = ELFMAG2;
elf_header->e_ident[EI_MAG3] = ELFMAG3;
elf_header->e_ident[EI_CLASS] = ELF_TARG_CLASS;
elf_header->e_ident[EI_DATA] = ELF_TARG_DATA;
elf_header->e_ident[EI_VERSION] = EV_CURRENT;
elf_header->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
elf_header->e_type = ET_CORE;
elf_header->e_machine = ELF_TARG_MACH;
elf_header->e_version = EV_CURRENT;
elf_header->e_ehsize = sizeof(Elf_Ehdr);
elf_header->e_phoff = sizeof(Elf_Ehdr);
elf_header->e_phentsize = sizeof(Elf_Phdr);
elf_header->e_phnum = phnum;
}
/*===========================================================================*
* fill_prog_header *
*===========================================================================*/
PRIVATE void fill_prog_header (Elf_Phdr *prog_header, Elf_Word p_type,
Elf_Off p_offset, Elf_Addr p_vaddr, Elf_Word p_flags,
Elf_Word p_filesz, Elf_Word p_memsz)
{
memset((void *) prog_header, 0, sizeof(Elf_Phdr));
prog_header->p_type = p_type;
prog_header->p_offset = p_offset;
prog_header->p_vaddr = p_vaddr;
prog_header->p_flags = p_flags;
prog_header->p_filesz = p_filesz;
prog_header->p_memsz = p_memsz;
}
#define PADBYTES 4
#define PAD_LEN(x) ((x + (PADBYTES - 1)) & ~(PADBYTES - 1))
/*===========================================================================*
* fill_note_segment_and_entries_hdrs *
*===========================================================================*/
PRIVATE void fill_note_segment_and_entries_hdrs(Elf_Phdr phdrs[],
Elf_Nhdr nhdrs[])
{
int filesize;
const char *note_name = ELF_NOTE_MINIX_ELFCORE_NAME "\0";
int name_len, mei_len, gregs_len;
/* Size of notes in the core file is rather fixed:
* sizeof(minix_elfcore_info_t) +
* 2 * sizeof(Elf_Nhdr) + the size of the padded name of the note
* - i.e. "MINIX-CORE\0" padded to 4-byte alignment => 2 * 8 bytes
*/
name_len = strlen(note_name) + 1;
mei_len = sizeof(minix_elfcore_info_t);
gregs_len = sizeof(gregset_t);
/* Make sure to also count the padding bytes */
filesize = PAD_LEN(mei_len) + PAD_LEN(gregs_len) +
2 * sizeof(Elf_Nhdr) + 2 * PAD_LEN(name_len);
fill_prog_header(&phdrs[0], PT_NOTE, 0, 0, PF_R, filesize, 0);
/* First note entry header */
nhdrs[0].n_namesz = name_len;
nhdrs[0].n_descsz = sizeof(minix_elfcore_info_t);
nhdrs[0].n_type = NT_MINIX_ELFCORE_INFO;
/* Second note entry header */
nhdrs[1].n_namesz = name_len;
nhdrs[1].n_descsz = sizeof(gregset_t);
nhdrs[1].n_type = NT_MINIX_ELFCORE_GREGS;
}
/*===========================================================================*
* adjust_offset *
*===========================================================================*/
PRIVATE void adjust_offsets(Elf_Phdr phdrs[], int phnum)
{
int i;
long offset = sizeof(Elf_Ehdr) + phnum * sizeof(Elf_Phdr);
for (i = 0; i < phnum; i++) {
phdrs[i].p_offset = offset;
offset += phdrs[i].p_filesz;
}
}
/*===========================================================================*
* write_buf *
*===========================================================================*/
PRIVATE void write_buf(struct filp *f, char *buf, size_t size)
{
read_write(WRITING, f, buf, size, VFS_PROC_NR);
}
/*===========================================================================*
* get_memory_regions *
*===========================================================================*/
PRIVATE int get_memory_regions(Elf_Phdr phdrs[])
{
/* Print the virtual memory regions of a process. */
/* The same as dump_regions from procfs/pid.c */
struct vm_region_info vri[MAX_VRI_COUNT];
vir_bytes next;
int i, r, count;
Elf_Word pflags;
count = 0;
next = 0;
do {
r = vm_info_region(fp->fp_endpoint, vri, MAX_VRI_COUNT, &next);
if (r < 0) return r;
if (r == 0) break;
for (i = 0; i < r; i++) {
pflags = (vri[i].vri_prot & PROT_READ ? PF_R : 0)
| (vri[i].vri_prot & PROT_WRITE ? PF_W : 0)
| (vri[i].vri_prot & PROT_EXEC ? PF_X : 0);
fill_prog_header (&phdrs[count + 1], PT_LOAD,
0, vri[i].vri_addr, pflags,
vri[i].vri_length, vri[i].vri_length);
count++;
if (count >= MAX_REGIONS) {
printf("VFS: get_memory_regions Warning: "
"Program has too many regions\n");
return(count);
}
}
} while (r == MAX_VRI_COUNT);
return(count);
}
/*===========================================================================*
* dump_notes *
*===========================================================================*/
PRIVATE void dump_notes(struct filp *f, Elf_Nhdr nhdrs[], int csig,
char *proc_name)
{
char *note_name = ELF_NOTE_MINIX_ELFCORE_NAME "\0";
char pad[4];
minix_elfcore_info_t mei;
int mei_len = sizeof(minix_elfcore_info_t);
int gregs_len = sizeof(gregset_t);
struct stackframe_s regs;
/* Dump first note entry */
mei.mei_version = MINIX_ELFCORE_VERSION;
mei.mei_meisize = mei_len;
mei.mei_signo = csig;
mei.mei_pid = fp->fp_pid;
memcpy(mei.mei_command, proc_name, sizeof(mei.mei_command));
write_buf(f, (char *) &nhdrs[0], sizeof(Elf_Nhdr));
write_buf(f, note_name, nhdrs[0].n_namesz);
write_buf(f, pad, PAD_LEN(nhdrs[0].n_namesz) - nhdrs[0].n_namesz);
write_buf(f, (char *) &mei, mei_len);
write_buf(f, pad, PAD_LEN(mei_len) - mei_len);
/* Get registers */
if (sys_getregs(&regs, fp->fp_endpoint) != OK)
printf("VFS: Could not read registers\n");
if (sizeof(regs) != gregs_len)
printf("VFS: Wrong core register structure size\n");
/* Dump second note entry - the general registers */
write_buf(f, (char *) &nhdrs[1], sizeof(Elf_Nhdr));
write_buf(f, note_name, nhdrs[1].n_namesz);
write_buf(f, pad, PAD_LEN(nhdrs[1].n_namesz) - nhdrs[1].n_namesz);
write_buf(f, (char *) &regs, gregs_len);
write_buf(f, pad, PAD_LEN(gregs_len) - gregs_len);
}
/*===========================================================================*
* dump_elf_header *
*===========================================================================*/
PRIVATE void dump_elf_header(struct filp *f, Elf_Ehdr elf_header)
{
write_buf(f, (char *) &elf_header, sizeof(Elf_Ehdr));
}
/*===========================================================================*
* dump_program_headers *
*===========================================================================*/
PRIVATE void dump_program_headers(struct filp *f, Elf_Phdr phdrs[], int phnum)
{
int i;
for (i = 0; i < phnum; i++)
write_buf(f, (char *) &phdrs[i], sizeof(Elf_Phdr));
}
/*===========================================================================*
* dump_segments *
*===========================================================================*/
PRIVATE void dump_segments(struct filp *f, Elf_Phdr phdrs[], int phnum)
{
int i;
vir_bytes len;
off_t off, seg_off;
int r;
static u8_t buf[CLICK_SIZE];
for (i = 1; i < phnum; i++) {
len = phdrs[i].p_memsz;
seg_off = phdrs[i].p_vaddr;
for (off = 0; off < len; off += CLICK_SIZE) {
r = sys_vircopy(fp->fp_endpoint, D,
(vir_bytes) (seg_off + off),
SELF, D, (vir_bytes) buf,
(phys_bytes) CLICK_SIZE);
write_buf(f, (char *) buf, (off + CLICK_SIZE <= len) ?
CLICK_SIZE : (len - off));
}
}
}

View file

@ -983,8 +983,8 @@ PUBLIC void cdev_up(int maj)
if(rfp->fp_blocked_on != FP_BLOCKED_ON_DOPEN) continue;
printf("VFS: dev_up: found process in FP_BLOCKED_ON_DOPEN, fd %d\n",
rfp->fp_block_fd);
fd_nr = rfp->fp_block_fd;
rfp->fp_blocked.fd_nr);
fd_nr = rfp->fp_blocked.fd_nr;
rfilp = rfp->fp_filp[fd_nr];
vp = rfilp->filp_vno;
if (!vp) panic("VFS: restart_reopen: no vp");
@ -1090,9 +1090,9 @@ int maj;
if (rfp->fp_blocked_on == FP_BLOCKED_ON_DOPEN ||
!(rfp->fp_flags & FP_SUSP_REOPEN)) continue;
printf("VFS: restart_reopen: found process in FP_BLOCKED_ON_DOPEN, fd %d\n",
rfp->fp_block_fd);
fd_nr = rfp->fp_block_fd;
fd_nr = rfp->fp_blocked.fd_nr;
printf("VFS: restart_reopen: process in FP_BLOCKED_ON_DOPEN fd=%d\n",
fd_nr);
rfilp = rfp->fp_filp[fd_nr];
if (!rfilp) {

View file

@ -25,13 +25,16 @@ EXTERN struct fproc {
fd_set fp_cloexec_set; /* bit map for POSIX Table 6-2 FD_CLOEXEC */
dev_t fp_tty; /* major/minor of controlling tty */
int fp_block_fd; /* place to save fd if rd/wr can't finish */
int fp_blocked_on; /* what is it blocked on */
int fp_block_callnr; /* blocked call if rd/wr can't finish */
union blocked {
int fd_nr; /* place to save fd if rd/wr can't finish */
struct filp *bfilp; /* place to save filp if rd/wr can't finish */
} fp_blocked;
char *fp_buffer; /* place to save buffer if rd/wr can't finish*/
int fp_nbytes; /* place to save bytes if rd/wr can't finish */
int fp_cum_io_partial; /* partial byte count if rd/wr can't finish */
endpoint_t fp_task; /* which task is proc suspended on */
int fp_blocked_on; /* what is it blocked on */
endpoint_t fp_ioproc; /* proc no. in suspended-on i/o message */
cp_grant_id_t fp_grant; /* revoke this grant on unsuspend if > -1 */

View file

@ -337,9 +337,9 @@ PRIVATE void *do_pm(void *arg)
*===========================================================================*/
PRIVATE void *do_pending_pipe(void *arg)
{
int r, fd_nr;
struct filp *f;
int r, op;
struct job my_job;
struct filp *f;
tll_access_t locktype;
my_job = *((struct job *) arg);
@ -348,13 +348,15 @@ PRIVATE void *do_pending_pipe(void *arg)
lock_proc(fp, 1 /* force lock */);
fd_nr = fp->fp_block_fd;
locktype = (call_nr == READ) ? VNODE_READ : VNODE_WRITE;
f = get_filp(fd_nr, locktype);
f = fp->fp_blocked.bfilp;
assert(f != NULL);
fp->fp_blocked.bfilp = NULL;
r = rw_pipe((call_nr == READ) ? READING : WRITING, who_e, fd_nr, f,
fp->fp_buffer, fp->fp_nbytes);
locktype = (call_nr == READ) ? VNODE_READ : VNODE_WRITE;
op = (call_nr == READ) ? READING : WRITING;
lock_filp(f, locktype);
r = rw_pipe(op, who_e, f, fp->fp_buffer, fp->fp_nbytes);
if (r != SUSPEND) /* Do we have results to report? */
reply(who_e, r);
@ -391,9 +393,8 @@ PUBLIC void *do_dummy(void *arg)
*===========================================================================*/
PRIVATE void *do_work(void *arg)
{
int error, i;
int error;
struct job my_job;
struct fproc *rfp;
my_job = *((struct job *) arg);
fp = my_job.j_fp;
@ -792,14 +793,6 @@ PRIVATE void service_pm_postponed(void)
int r;
vir_bytes pc;
#if 0
printf("executing postponed: ");
if (call_nr == PM_EXEC) printf("PM_EXEC");
if (call_nr == PM_EXIT) printf("PM_EXIT");
if (call_nr == PM_DUMPCORE) printf("PM_DUMPCORE");
printf("\n");
#endif
switch(call_nr) {
case PM_EXEC:
r = pm_exec(m_in.PM_PROC, m_in.PM_PATH, m_in.PM_PATH_LEN,
@ -823,13 +816,17 @@ PRIVATE void service_pm_postponed(void)
break;
case PM_DUMPCORE:
r = pm_dumpcore(m_in.PM_PROC,
NULL /* (struct mem_map *) m_in.PM_SEGPTR */);
/* Reply status to PM */
/* Copy parameters first. m_in gets overwritten when creating core
* file.
*/
m_out.m_type = PM_CORE_REPLY;
m_out.PM_PROC = m_in.PM_PROC;
m_out.PM_TRACED_PROC = m_in.PM_TRACED_PROC;
r = pm_dumpcore(m_in.PM_PROC, m_in.PM_TERM_SIG,
(vir_bytes) m_in.PM_PATH);
/* Reply status to PM */
m_out.PM_STATUS = r;
break;
@ -886,14 +883,6 @@ PRIVATE void service_pm()
fp->fp_job.j_m_in = m_in;
fp->fp_flags |= FP_PM_PENDING;
#if 0
printf("Postponing: ");
if (call_nr == PM_EXEC) printf("PM_EXEC");
if (call_nr == PM_EXIT) printf("PM_EXIT");
if (call_nr == PM_DUMPCORE) printf("PM_DUMPCORE");
printf("\n");
#endif
/* PM requests on behalf of a proc are handled after the system call
* that might be in progress for that proc has finished. If the proc
* is not busy, we start a dummy call */
@ -962,7 +951,7 @@ struct fproc *rfp;
fp = rfp;
blocked_on = rfp->fp_blocked_on;
m_in.m_type = rfp->fp_block_callnr;
m_in.fd = rfp->fp_block_fd;
m_in.fd = rfp->fp_blocked.fd_nr;
m_in.buffer = rfp->fp_buffer;
m_in.nbytes = rfp->fp_nbytes;

View file

@ -586,14 +586,33 @@ PUBLIC int do_svrctl()
/*===========================================================================*
* pm_dumpcore *
*===========================================================================*/
PUBLIC int pm_dumpcore(proc_e, seg_ptr)
int proc_e;
struct mem_map *seg_ptr;
PUBLIC int pm_dumpcore(endpoint_t proc_e, int csig, vir_bytes exe_name)
{
int slot;
int slot, r, core_fd;
struct filp *f;
char core_path[PATH_MAX];
char proc_name[PROC_NAME_LEN];
okendpt(proc_e, &slot);
free_proc(&fproc[slot], FP_EXITING);
fp = &fproc[slot];
/* open core file */
snprintf(core_path, PATH_MAX, "%s.%d", CORE_NAME, fp->fp_pid);
core_fd = common_open(core_path, O_WRONLY | O_CREAT | O_TRUNC, CORE_MODE);
if (core_fd < 0) return(core_fd);
/* get process' name */
r = sys_datacopy(PM_PROC_NR, exe_name, VFS_PROC_NR, (vir_bytes) proc_name,
PROC_NAME_LEN);
if (r != OK) return(r);
proc_name[PROC_NAME_LEN - 1] = '\0';
if ((f = get_filp(core_fd, VNODE_WRITE)) == NULL) return(EBADF);
write_elf_core_file(f, csig, proc_name);
unlock_filp(f);
(void) close_fd(fp, core_fd); /* ignore failure, we're exiting anyway */
free_proc(fp, FP_EXITING);
return(OK);
}

View file

@ -33,8 +33,6 @@
PUBLIC char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
FORWARD _PROTOTYPE( int common_open, (char path[PATH_MAX], int oflags,
mode_t omode) );
FORWARD _PROTOTYPE( struct vnode *new_node, (struct lookup *resolve,
int oflags, mode_t bits) );
FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp, mode_t bits,
@ -84,7 +82,7 @@ PUBLIC int do_open()
/*===========================================================================*
* common_open *
*===========================================================================*/
PRIVATE int common_open(char path[PATH_MAX], int oflags, mode_t omode)
PUBLIC int common_open(char path[PATH_MAX], int oflags, mode_t omode)
{
/* Common code from do_creat and do_open. */
int b, r, exist = TRUE, major_dev;
@ -463,8 +461,7 @@ printf("XXX: dangling symlink needs re-resolving\n");
/*===========================================================================*
* pipe_open *
*===========================================================================*/
PRIVATE int pipe_open(register struct vnode *vp, register mode_t bits,
register int oflags)
PRIVATE int pipe_open(struct vnode *vp, mode_t bits, int oflags)
{
/* This function is called from common_open. It checks if
* there is at least one reader/writer pair for the pipe, if not
@ -474,7 +471,7 @@ PRIVATE int pipe_open(register struct vnode *vp, register mode_t bits,
vp->v_pipe = I_PIPE;
if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) return(ENXIO);
if ((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) return(ENXIO);
/* Find the reader/writer at the other end of the pipe */
if (find_filp(vp, bits & W_BIT ? R_BIT : W_BIT) == NULL) {
@ -483,7 +480,7 @@ PRIVATE int pipe_open(register struct vnode *vp, register mode_t bits,
if (bits & W_BIT) return(ENXIO);
} else {
/* Let's wait for the other side to show up */
suspend(FP_BLOCKED_ON_POPEN); /* suspend caller */
suspend(FP_BLOCKED_ON_POPEN);
return(SUSPEND);
}
} else if (susp_count > 0) { /* revive blocked processes */

View file

@ -295,12 +295,17 @@ PUBLIC void suspend(int why)
#endif
if (why == FP_BLOCKED_ON_POPEN)
/* #procs susp'ed on pipe*/
susp_count++;
/* #procs susp'ed on pipe*/
susp_count++;
if (why == FP_BLOCKED_ON_POPEN || why == FP_BLOCKED_ON_DOPEN ||
why == FP_BLOCKED_ON_LOCK || why == FP_BLOCKED_ON_OTHER)
fp->fp_blocked.fd_nr = m_in.fd;
else
fp->fp_blocked.fd_nr = 0;
fp->fp_blocked_on = why;
assert(fp->fp_grant == GRANT_INVALID || !GRANT_VALID(fp->fp_grant));
fp->fp_block_fd = m_in.fd;
fp->fp_block_callnr = call_nr;
fp->fp_flags &= ~FP_SUSP_REOPEN; /* Clear this flag. The caller
* can set it when needed.
@ -329,9 +334,9 @@ PUBLIC void wait_for(endpoint_t who)
/*===========================================================================*
* pipe_suspend *
*===========================================================================*/
PUBLIC void pipe_suspend(rw_flag, fd_nr, buf, size)
PUBLIC void pipe_suspend(rw_flag, filp, buf, size)
int rw_flag;
int fd_nr;
struct filp *filp;
char *buf;
size_t size;
{
@ -349,8 +354,8 @@ size_t size;
susp_count++; /* #procs susp'ed on pipe*/
fp->fp_blocked_on = FP_BLOCKED_ON_PIPE;
assert(!GRANT_VALID(fp->fp_grant));
fp->fp_block_fd = fd_nr;
fp->fp_block_callnr = ((rw_flag == READING) ? READ : WRITE);
fp->fp_blocked.bfilp = filp;
fp->fp_block_callnr = (rw_flag == READING) ? READ : WRITE;
fp->fp_buffer = buf;
fp->fp_nbytes = size;
}
@ -387,9 +392,8 @@ register struct vnode *vp; /* inode of pipe */
int op; /* READ, WRITE, OPEN or CREAT */
int count; /* max number of processes to release */
{
/* Check to see if any process is hanging on the pipe whose inode is in 'ip'.
* If one is, and it was trying to perform the call indicated by 'call_nr',
* release it.
/* Check to see if any process is hanging on vnode 'vp'. If one is, and it
* was trying to perform the call indicated by 'call_nr', release it.
*/
register struct fproc *rp;
@ -417,9 +421,27 @@ int count; /* max number of processes to release */
/* Search the proc table. */
for (rp = &fproc[0]; rp < &fproc[NR_PROCS] && count > 0; rp++) {
if (rp->fp_pid != PID_FREE && fp_is_blocked(rp) &&
!(rp->fp_flags & FP_REVIVED) && rp->fp_block_callnr == op &&
rp->fp_filp[rp->fp_block_fd] != NULL &&
rp->fp_filp[rp->fp_block_fd]->filp_vno == vp) {
!(rp->fp_flags & FP_REVIVED) && rp->fp_block_callnr == op) {
/* Find the vnode. Depending on the reason the process was
* suspended, there are different ways of finding it.
*/
if (rp->fp_blocked_on == FP_BLOCKED_ON_POPEN ||
rp->fp_blocked_on == FP_BLOCKED_ON_DOPEN ||
rp->fp_blocked_on == FP_BLOCKED_ON_LOCK ||
rp->fp_blocked_on == FP_BLOCKED_ON_OTHER) {
if (rp->fp_filp[rp->fp_blocked.fd_nr] == NULL)
continue;
if (rp->fp_filp[rp->fp_blocked.fd_nr]->filp_vno != vp)
continue;
} else {
if (rp->fp_blocked.bfilp == NULL)
continue;
if (rp->fp_blocked.bfilp->filp_vno != vp)
continue;
}
/* We found the vnode. Revive process. */
revive(rp->fp_endpoint, 0);
susp_count--; /* keep track of who is suspended */
if(susp_count < 0)
@ -456,13 +478,14 @@ int returned; /* if hanging on task, how many bytes read */
* the proc must be restarted so it can try again.
*/
blocked_on = rfp->fp_blocked_on;
fd_nr = rfp->fp_blocked.fd_nr;
if (blocked_on == FP_BLOCKED_ON_PIPE || blocked_on == FP_BLOCKED_ON_LOCK) {
/* Revive a process suspended on a pipe or lock. */
rfp->fp_flags |= FP_REVIVED;
reviving++; /* process was waiting on pipe or lock */
} else if (blocked_on == FP_BLOCKED_ON_DOPEN) {
rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
fd_nr = rfp->fp_block_fd;
rfp->fp_blocked.fd_nr = 0;
if (returned < 0) {
fil_ptr = rfp->fp_filp[fd_nr];
lock_filp(fil_ptr, VNODE_OPCL);
@ -482,9 +505,10 @@ int returned; /* if hanging on task, how many bytes read */
}
} else {
rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
rfp->fp_blocked.fd_nr = 0;
if (blocked_on == FP_BLOCKED_ON_POPEN) {
/* process blocked in open or create */
reply(proc_nr_e, rfp->fp_block_fd);
reply(proc_nr_e, fd_nr);
} else if (blocked_on == FP_BLOCKED_ON_SELECT) {
reply(proc_nr_e, returned);
} else {
@ -568,7 +592,7 @@ int proc_nr_e;
break;
}
fild = rfp->fp_block_fd;
fild = rfp->fp_blocked.fd_nr;
if (fild < 0 || fild >= OPEN_MAX)
panic("file descriptor out-of-range");
f = rfp->fp_filp[fild];

View file

@ -67,6 +67,10 @@ _PROTOTYPE( int map_driver, (const char *label, int major, endpoint_t proc_nr,
int dev_style, int flags) );
_PROTOTYPE( int map_service, (struct rprocpub *rpub) );
/* elf_core_dump.c */
_PROTOTYPE( void write_elf_core_file, (struct filp *f, int csig,
char *exe_name) );
/* exec.c */
_PROTOTYPE( int pm_exec, (int proc_e, char *path, vir_bytes path_len,
char *frame, vir_bytes frame_len, vir_bytes *pc));
@ -137,7 +141,8 @@ _PROTOTYPE( int do_fsync, (void) );
_PROTOTYPE( void pm_reboot, (void) );
_PROTOTYPE( int do_svrctl, (void) );
_PROTOTYPE( int do_getsysinfo, (void) );
_PROTOTYPE( int pm_dumpcore, (int proc_e, struct mem_map *seg_ptr) );
_PROTOTYPE( int pm_dumpcore, (endpoint_t proc_e, int sig,
vir_bytes exe_name) );
_PROTOTYPE( void ds_event, (void) );
/* mount.c */
@ -156,6 +161,8 @@ _PROTOTYPE( void unmount_all, (void) );
_PROTOTYPE( int do_close, (void) );
_PROTOTYPE( int close_fd, (struct fproc *rfp, int fd_nr) );
_PROTOTYPE( void close_reply, (void) );
_PROTOTYPE( int common_open, (char path[PATH_MAX], int oflags,
mode_t omode) );
_PROTOTYPE( int do_creat, (void) );
_PROTOTYPE( int do_lseek, (void) );
_PROTOTYPE( int do_llseek, (void) );
@ -189,8 +196,8 @@ _PROTOTYPE( int pipe_check, (struct vnode *vp, int rw_flag,
_PROTOTYPE( void release, (struct vnode *vp, int call_nr, int count) );
_PROTOTYPE( void revive, (int proc_nr, int bytes) );
_PROTOTYPE( void suspend, (int task) );
_PROTOTYPE( void pipe_suspend, (int rw_flag, int fd_nr, char *buf,
size_t size) );
_PROTOTYPE( void pipe_suspend, (int rw_flag, struct filp *rfilp,
char *buf, size_t size) );
_PROTOTYPE( void unsuspend_by_endpt, (endpoint_t) );
_PROTOTYPE( void wait_for, (endpoint_t) );
#if DO_SANITYCHECKS
@ -210,9 +217,11 @@ _PROTOTYPE( int do_read, (void) );
_PROTOTYPE( int do_getdents, (void) );
_PROTOTYPE( void lock_bsf, (void) );
_PROTOTYPE( void unlock_bsf, (void) );
_PROTOTYPE( int read_write, (int rw_flag) );
_PROTOTYPE( int rw_pipe, (int rw_flag, endpoint_t usr,
int fd_nr, struct filp *f, char *buf, size_t req_size) );
_PROTOTYPE( int do_read_write, (int rw_flag) );
_PROTOTYPE( int read_write, (int rw_flag, struct filp *f, char *buffer,
size_t nbytes, endpoint_t for_e) );
_PROTOTYPE( int rw_pipe, (int rw_flag, endpoint_t usr, struct filp *f,
char *buf, size_t req_size) );
/* request.c */
_PROTOTYPE( int req_breadwrite, (endpoint_t fs_e, endpoint_t user_e,
@ -372,6 +381,7 @@ _PROTOTYPE( struct worker_thread *worker_self, (void) );
_PROTOTYPE( void worker_signal, (struct worker_thread *worker) );
_PROTOTYPE( void worker_start, (void *(*func)(void *arg)) );
_PROTOTYPE( void worker_stop, (struct worker_thread *worker) );
_PROTOTYPE( void worker_stop_by_endpt, (endpoint_t proc_e) );
_PROTOTYPE( void worker_wait, (void) );
_PROTOTYPE( void sys_worker_start, (void *(*func)(void *arg)) );
_PROTOTYPE( void dl_worker_start, (void *(*func)(void *arg)) );

View file

@ -30,7 +30,7 @@
*===========================================================================*/
PUBLIC int do_read()
{
return(read_write(READING));
return(do_read_write(READING));
}
@ -64,22 +64,19 @@ PUBLIC void unlock_bsf(void)
}
/*===========================================================================*
* read_write *
* do_read_write *
*===========================================================================*/
PUBLIC int read_write(rw_flag)
PUBLIC int do_read_write(rw_flag)
int rw_flag; /* READING or WRITING */
{
/* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */
register struct filp *f;
register struct vnode *vp;
u64_t position, res_pos, new_pos;
unsigned int cum_io, cum_io_incr, res_cum_io;
int op, oflags, r, block_spec, char_spec, regular;
struct filp *f;
tll_access_t locktype;
mode_t mode_word;
int r;
/* If the file descriptor is valid, get the vnode, size and mode. */
if (m_in.nbytes < 0) return(EINVAL);
locktype = (rw_flag == READING) ? VNODE_READ : VNODE_WRITE;
if ((f = get_filp(m_in.fd, locktype)) == NULL) return(err_code);
if (((f->filp_mode) & (rw_flag == READING ? R_BIT : W_BIT)) == 0) {
@ -91,6 +88,24 @@ int rw_flag; /* READING or WRITING */
return(0); /* so char special files need not check for 0*/
}
r = read_write(rw_flag, f, m_in.buffer, m_in.nbytes, who_e);
unlock_filp(f);
return(r);
}
/*===========================================================================*
* read_write *
*===========================================================================*/
PUBLIC int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
endpoint_t for_e)
{
register struct vnode *vp;
u64_t position, res_pos, new_pos;
unsigned int cum_io, cum_io_incr, res_cum_io;
int op, oflags, r, block_spec, char_spec, regular;
mode_t mode_word;
position = f->filp_pos;
oflags = f->filp_flags;
vp = f->filp_vno;
@ -101,8 +116,7 @@ int rw_flag; /* READING or WRITING */
if (fp->fp_cum_io_partial != 0) {
panic("VFS: read_write: fp_cum_io_partial not clear");
}
r = rw_pipe(rw_flag, who_e, m_in.fd, f, m_in.buffer, m_in.nbytes);
unlock_filp(f);
r = rw_pipe(rw_flag, for_e, f, buf, size);
return(r);
}
@ -127,7 +141,7 @@ int rw_flag; /* READING or WRITING */
suspend_reopen = (f->filp_state != FS_NORMAL);
dev = (dev_t) vp->v_sdev;
r = dev_io(op, dev, who_e, m_in.buffer, position, m_in.nbytes, oflags,
r = dev_io(op, dev, for_e, buf, position, size, oflags,
suspend_reopen);
if (r >= 0) {
cum_io = r;
@ -137,8 +151,8 @@ int rw_flag; /* READING or WRITING */
} else if (block_spec) { /* Block special files. */
lock_bsf();
r = req_breadwrite(vp->v_bfs_e, who_e, vp->v_sdev, position,
m_in.nbytes, m_in.buffer, rw_flag, &res_pos, &res_cum_io);
r = req_breadwrite(vp->v_bfs_e, for_e, vp->v_sdev, position, size,
buf, rw_flag, &res_pos, &res_cum_io);
if (r == OK) {
position = res_pos;
cum_io += res_cum_io;
@ -152,8 +166,8 @@ int rw_flag; /* READING or WRITING */
}
/* Issue request */
r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, position, rw_flag, who_e,
m_in.buffer, m_in.nbytes, &new_pos, &cum_io_incr);
r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, position, rw_flag, for_e,
buf, size, &new_pos, &cum_io_incr);
if (r >= 0) {
if (ex64hi(new_pos))
@ -177,13 +191,11 @@ int rw_flag; /* READING or WRITING */
}
f->filp_pos = position;
unlock_filp(f);
if (r == OK) return(cum_io);
return(r);
}
/*===========================================================================*
* do_getdents *
*===========================================================================*/
@ -220,10 +232,9 @@ PUBLIC int do_getdents()
/*===========================================================================*
* rw_pipe *
*===========================================================================*/
PUBLIC int rw_pipe(rw_flag, usr_e, fd_nr, f, buf, req_size)
PUBLIC int rw_pipe(rw_flag, usr_e, f, buf, req_size)
int rw_flag; /* READING or WRITING */
endpoint_t usr_e;
int fd_nr;
struct filp *f;
char *buf;
size_t req_size;
@ -246,7 +257,7 @@ size_t req_size;
r = pipe_check(vp, rw_flag, oflags, req_size, position, 0);
if (r <= 0) {
if (r == SUSPEND) pipe_suspend(rw_flag, fd_nr, buf, req_size);
if (r == SUSPEND) pipe_suspend(rw_flag, f, buf, req_size);
return(r);
}
@ -314,7 +325,7 @@ size_t req_size;
* non-atomic
*/
fp->fp_cum_io_partial = cum_io;
pipe_suspend(rw_flag, fd_nr, buf, req_size);
pipe_suspend(rw_flag, f, buf, req_size);
return(SUSPEND);
}
}

View file

@ -15,5 +15,5 @@
PUBLIC int do_write()
{
/* Perform the write(fd, buffer, nbytes) system call. */
return(read_write(WRITING));
return(do_read_write(WRITING));
}

View file

@ -9,7 +9,6 @@
/* Include ELF headers */
#include <sys/elf_core.h>
#include <sys/procfs.h>
FORWARD _PROTOTYPE( void fill_elf_header, (Elf32_Ehdr *elf_header,
int phnum) );