]> Zhao Yanbai Git Server - minix.git/commitdiff
Provide core dumping support for AVFS
authorThomas Veerman <thomas@minix3.org>
Thu, 8 Dec 2011 10:47:11 +0000 (10:47 +0000)
committerThomas Veerman <thomas@minix3.org>
Thu, 8 Dec 2011 10:47:11 +0000 (10:47 +0000)
12 files changed:
servers/avfs/Makefile
servers/avfs/coredump.c [new file with mode: 0644]
servers/avfs/device.c
servers/avfs/fproc.h
servers/avfs/main.c
servers/avfs/misc.c
servers/avfs/open.c
servers/avfs/pipe.c
servers/avfs/proto.h
servers/avfs/read.c
servers/avfs/write.c
servers/vfs/elf_core_dump.c

index 3dad05917f243a19276544c8eecd9d9e974c2e62..ec0553f981a1650a3f2ac4aca7caba07778d3ca9 100644 (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
diff --git a/servers/avfs/coredump.c b/servers/avfs/coredump.c
new file mode 100644 (file)
index 0000000..598409d
--- /dev/null
@@ -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));
+       }
+  }
+}
index 66a0ae40a183ea58e9492bebd44df2d39da9142b..2f2f33b97772a7bfefb3e2607e307f6de6e3e354 100644 (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) {
index 43f2012d287d42e6525f952d4b7f5f434e192699..ce33ecd527490207571be511be991892d04a87ed 100644 (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 */
index 3179c64c41dc18d2232b683fc7dd634e009f8717..ecf9c639f12a374ca7a0d3cf87e4a02d6ab6efe7 100644 (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;
+
+  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);
@@ -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;
 
index 84914356359068079789f49754a1fecdf3655953..89e8ac067f79e06b56492f2dc44e22f2bb1c891b 100644 (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);
 }
 
index caac61df4074aa65a8c4616e14af3968e010b15b..2b301dae70b4dfb1aaa6ab90785bb79393f29662 100644 (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 */
index bfc918153d2d47d4a8a33dfe1fe06f2f50749f35..2a841ba19a6a6ea1a36645a666b08f38a2dc09d6 100644 (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];
index d1766f5cd217be080766ec4e6e6d79e4196ff59f..12db0386ee819cc2aa8bde7f6bf9460096d36d35 100644 (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))           );
index ffde1f9dbc7165ac3576182530986e1dfd2d1889..46ee497cbec2f00944353f0fe72bffa43b71f194 100644 (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);
                }
        }
index b602eff1e6da30cb11bfadb7707e50307d70d4a1..a3e9d636ee90d678bb5e5da223870574673a5ca4 100644 (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));
 }
index 570ba43aa49dcd909b246b0587562a08d15bb684..c3425b529a261e095a5618e5f7f632bf5edb83d9 100644 (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)                                                 );