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
--- /dev/null
+#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(®s, 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 *) ®s, 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));
+ }
+ }
+}
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");
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) {
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 */
*===========================================================================*/
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);
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;
+
+ locktype = (call_nr == READ) ? VNODE_READ : VNODE_WRITE;
+ op = (call_nr == READ) ? READING : WRITING;
+ lock_filp(f, locktype);
- r = rw_pipe((call_nr == READ) ? READING : WRITING, who_e, fd_nr, f,
- fp->fp_buffer, fp->fp_nbytes);
+ 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);
*===========================================================================*/
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;
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,
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;
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 */
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;
/*===========================================================================*
* 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);
}
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,
/*===========================================================================*
* 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;
/*===========================================================================*
* 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
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) {
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 */
#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.
/*===========================================================================*
* 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;
{
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;
}
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;
/* 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)
* 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);
}
} 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 {
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];
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));
_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 */
_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) );
_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
_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,
_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)) );
*===========================================================================*/
PUBLIC int do_read()
{
- return(read_write(READING));
+ return(do_read_write(READING));
}
}
/*===========================================================================*
- * 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) {
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;
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);
}
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;
} 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;
}
/* 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))
}
f->filp_pos = position;
- unlock_filp(f);
if (r == OK) return(cum_io);
return(r);
}
-
/*===========================================================================*
* 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;
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);
}
* 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);
}
}
PUBLIC int do_write()
{
/* Perform the write(fd, buffer, nbytes) system call. */
- return(read_write(WRITING));
+ return(do_read_write(WRITING));
}
/* Include ELF headers */
#include <sys/elf_core.h>
-#include <sys/procfs.h>
FORWARD _PROTOTYPE( void fill_elf_header, (Elf32_Ehdr *elf_header,
int phnum) );