diff --git a/servers/avfs/Makefile b/servers/avfs/Makefile index 3dad05917..ec0553f98 100644 --- a/servers/avfs/Makefile +++ b/servers/avfs/Makefile @@ -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 diff --git a/servers/avfs/coredump.c b/servers/avfs/coredump.c new file mode 100644 index 000000000..598409df7 --- /dev/null +++ b/servers/avfs/coredump.c @@ -0,0 +1,309 @@ +#include "fs.h" +#include +#include +#include "fproc.h" +#include +#include +#include +#include "param.h" + +/* Include ELF headers */ +#include + +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)); + } + } +} diff --git a/servers/avfs/device.c b/servers/avfs/device.c index 66a0ae40a..2f2f33b97 100644 --- a/servers/avfs/device.c +++ b/servers/avfs/device.c @@ -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) { diff --git a/servers/avfs/fproc.h b/servers/avfs/fproc.h index 43f2012d2..ce33ecd52 100644 --- a/servers/avfs/fproc.h +++ b/servers/avfs/fproc.h @@ -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 */ diff --git a/servers/avfs/main.c b/servers/avfs/main.c index 3179c64c4..ecf9c639f 100644 --- a/servers/avfs/main.c +++ b/servers/avfs/main.c @@ -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; diff --git a/servers/avfs/misc.c b/servers/avfs/misc.c index 849143563..89e8ac067 100644 --- a/servers/avfs/misc.c +++ b/servers/avfs/misc.c @@ -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); } diff --git a/servers/avfs/open.c b/servers/avfs/open.c index caac61df4..2b301dae7 100644 --- a/servers/avfs/open.c +++ b/servers/avfs/open.c @@ -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 */ diff --git a/servers/avfs/pipe.c b/servers/avfs/pipe.c index bfc918153..2a841ba19 100644 --- a/servers/avfs/pipe.c +++ b/servers/avfs/pipe.c @@ -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]; diff --git a/servers/avfs/proto.h b/servers/avfs/proto.h index d1766f5cd..12db0386e 100644 --- a/servers/avfs/proto.h +++ b/servers/avfs/proto.h @@ -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)) ); diff --git a/servers/avfs/read.c b/servers/avfs/read.c index ffde1f9db..46ee497cb 100644 --- a/servers/avfs/read.c +++ b/servers/avfs/read.c @@ -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); } } diff --git a/servers/avfs/write.c b/servers/avfs/write.c index b602eff1e..a3e9d636e 100644 --- a/servers/avfs/write.c +++ b/servers/avfs/write.c @@ -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)); } diff --git a/servers/vfs/elf_core_dump.c b/servers/vfs/elf_core_dump.c index 570ba43aa..c3425b529 100644 --- a/servers/vfs/elf_core_dump.c +++ b/servers/vfs/elf_core_dump.c @@ -9,7 +9,6 @@ /* Include ELF headers */ #include -#include FORWARD _PROTOTYPE( void fill_elf_header, (Elf32_Ehdr *elf_header, int phnum) );