direct-io.hg

changeset 9221:1439cfa5ee8c

The existing xc_domain_dumpcore is very specific to disk/file based
output. Refactor the code slightly to allow more user-specified
control. This is done by adding a parallel
xc_domain_dumpcore_via_callback, which allows the specification of a
callback routine and an opaque argument block. The existing dumpcore
routine is modified to use the callback for all write operations and
to turn the single seek into a small write (it's for page alignment).

Signed-off-by: Ben Thomas <bthomas@virtualiron.com>
author kaf24@firebug.cl.cam.ac.uk
date Mon Mar 13 11:47:56 2006 +0100 (2006-03-13)
parents 68b4edadd161
children 2625000d3145
files tools/libxc/xc_core.c tools/libxc/xenctrl.h
line diff
     1.1 --- a/tools/libxc/xc_core.c	Mon Mar 13 11:10:27 2006 +0100
     1.2 +++ b/tools/libxc/xc_core.c	Mon Mar 13 11:47:56 2006 +0100
     1.3 @@ -26,100 +26,152 @@ copy_from_domain_page(int xc_handle,
     1.4  }
     1.5  
     1.6  int 
     1.7 -xc_domain_dumpcore(int xc_handle,
     1.8 -                   uint32_t domid,
     1.9 -                   const char *corename)
    1.10 +xc_domain_dumpcore_via_callback(int xc_handle,
    1.11 +                                uint32_t domid,
    1.12 +                                void *args,
    1.13 +                                dumpcore_rtn_t dump_rtn)
    1.14  {
    1.15      unsigned long nr_pages;
    1.16      unsigned long *page_array;
    1.17      xc_dominfo_t info;
    1.18 -    int i, nr_vcpus = 0, dump_fd;
    1.19 +    int i, nr_vcpus = 0;
    1.20      char *dump_mem, *dump_mem_start = NULL;
    1.21      struct xc_core_header header;
    1.22      vcpu_guest_context_t  ctxt[MAX_VIRT_CPUS];
    1.23 +    char dummy[PAGE_SIZE];
    1.24 +    int dummy_len;
    1.25 +    int sts;
    1.26  
    1.27 - 
    1.28 -    if ((dump_fd = open(corename, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)) < 0) {
    1.29 -        PERROR("Could not open corefile %s: %s", corename, strerror(errno));
    1.30 -        goto error_out;
    1.31 -    }
    1.32 - 
    1.33 -    if ((dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL) {
    1.34 +    if ( (dump_mem_start = malloc(DUMP_INCREMENT*PAGE_SIZE)) == NULL )
    1.35 +    {
    1.36          PERROR("Could not allocate dump_mem");
    1.37          goto error_out;
    1.38      }
    1.39   
    1.40 -    if (xc_domain_getinfo(xc_handle, domid, 1, &info) != 1) {
    1.41 +    if ( xc_domain_getinfo(xc_handle, domid, 1, &info) != 1 )
    1.42 +    {
    1.43          PERROR("Could not get info for domain");
    1.44          goto error_out;
    1.45      }
    1.46   
    1.47 -    if (domid != info.domid) {
    1.48 +    if ( domid != info.domid )
    1.49 +    {
    1.50          PERROR("Domain %d does not exist", domid);
    1.51          goto error_out;
    1.52      }
    1.53  
    1.54 -    for (i = 0; i <= info.max_vcpu_id; i++)
    1.55 -        if (xc_vcpu_getcontext(xc_handle, domid,
    1.56 -                               i, &ctxt[nr_vcpus]) == 0)
    1.57 +    for ( i = 0; i <= info.max_vcpu_id; i++ )
    1.58 +        if ( xc_vcpu_getcontext(xc_handle, domid, i, &ctxt[nr_vcpus]) == 0)
    1.59              nr_vcpus++;
    1.60   
    1.61      nr_pages = info.nr_pages;
    1.62  
    1.63 -    header.xch_magic = XC_CORE_MAGIC;
    1.64 +    header.xch_magic = XC_CORE_MAGIC; 
    1.65      header.xch_nr_vcpus = nr_vcpus;
    1.66      header.xch_nr_pages = nr_pages;
    1.67      header.xch_ctxt_offset = sizeof(struct xc_core_header);
    1.68      header.xch_index_offset = sizeof(struct xc_core_header) +
    1.69          sizeof(vcpu_guest_context_t)*nr_vcpus;
    1.70 -    header.xch_pages_offset = round_pgup(sizeof(struct xc_core_header) +
    1.71 -                                         (sizeof(vcpu_guest_context_t) * nr_vcpus) +
    1.72 -                                         (nr_pages * sizeof(unsigned long)));
    1.73 +    dummy_len = (sizeof(struct xc_core_header) +
    1.74 +                 (sizeof(vcpu_guest_context_t) * nr_vcpus) +
    1.75 +                 (nr_pages * sizeof(unsigned long)));
    1.76 +    header.xch_pages_offset = round_pgup(dummy_len);
    1.77 +    
    1.78 +    sts = dump_rtn(args, (char *)&header, sizeof(struct xc_core_header));
    1.79 +    if ( sts != 0 )
    1.80 +        return sts;
    1.81  
    1.82 -    if (write(dump_fd, &header, sizeof(struct xc_core_header)) < 0 ||
    1.83 -        write(dump_fd, &ctxt, sizeof(ctxt[0]) * nr_vcpus) < 0)
    1.84 +    sts = dump_rtn(args, (char *)&ctxt, sizeof(ctxt[0]) * nr_vcpus);
    1.85 +    if ( sts != 0 )
    1.86 +        return sts;
    1.87 +
    1.88 +    if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL )
    1.89      {
    1.90 -        PERROR("write failed");
    1.91 -        goto error_out;
    1.92 -    }
    1.93 -
    1.94 -    if ((page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) {
    1.95          printf("Could not allocate memory\n");
    1.96          goto error_out;
    1.97      }
    1.98 -    if (xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages) {
    1.99 +    if ( xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages )
   1.100 +    {
   1.101          printf("Could not get the page frame list\n");
   1.102          goto error_out;
   1.103      }
   1.104 -    if (write(dump_fd, page_array, nr_pages * sizeof(unsigned long)) < 0)
   1.105 +    sts = dump_rtn(args, (char *)page_array, nr_pages * sizeof(unsigned long));
   1.106 +    if ( sts != 0 )
   1.107 +        return sts;
   1.108 +
   1.109 +    /* Pad the output data to page alignment. */
   1.110 +    memset(dummy, 0, PAGE_SIZE);
   1.111 +    sts = dump_rtn(args, dummy, header.xch_pages_offset - dummy_len);
   1.112 +    if ( sts != 0 )
   1.113 +        return sts;
   1.114 +
   1.115 +    for ( dump_mem = dump_mem_start, i = 0; i < nr_pages; i++ )
   1.116      {
   1.117 -        PERROR("write failed");
   1.118 -        goto error_out;
   1.119 -    }
   1.120 -    lseek(dump_fd, header.xch_pages_offset, SEEK_SET);
   1.121 -    for (dump_mem = dump_mem_start, i = 0; i < nr_pages; i++) {
   1.122          copy_from_domain_page(xc_handle, domid, page_array, i, dump_mem);
   1.123          dump_mem += PAGE_SIZE;
   1.124 -        if (((i + 1) % DUMP_INCREMENT == 0) || (i + 1) == nr_pages) {
   1.125 -            if (write(dump_fd, dump_mem_start, dump_mem - dump_mem_start) < 
   1.126 -                dump_mem - dump_mem_start) {
   1.127 -                PERROR("Partial write, file system full?");
   1.128 +        if ( ((i + 1) % DUMP_INCREMENT == 0) || ((i + 1) == nr_pages) )
   1.129 +        {
   1.130 +            sts = dump_rtn(args, dump_mem_start, dump_mem - dump_mem_start);
   1.131 +            if ( sts != 0 )
   1.132                  goto error_out;
   1.133 -            }
   1.134              dump_mem = dump_mem_start;
   1.135          }
   1.136      }
   1.137  
   1.138 -    close(dump_fd);
   1.139      free(dump_mem_start);
   1.140      return 0;
   1.141 +
   1.142   error_out:
   1.143 -    if (dump_fd != -1)
   1.144 -        close(dump_fd);
   1.145      free(dump_mem_start);
   1.146      return -1;
   1.147  }
   1.148  
   1.149 +/* Callback args for writing to a local dump file. */
   1.150 +struct dump_args {
   1.151 +    int     fd;
   1.152 +};
   1.153 +
   1.154 +/* Callback routine for writing to a local dump file. */
   1.155 +static int local_file_dump(void *args, char *buffer, unsigned int length)
   1.156 +{
   1.157 +    struct dump_args *da = args;
   1.158 +    int bytes, offset;
   1.159 +
   1.160 +    for ( offset = 0; offset < length; offset += bytes )
   1.161 +    {
   1.162 +        bytes = write(da->fd, &buffer[offset], length-offset);
   1.163 +        if ( bytes <= 0 )
   1.164 +        {
   1.165 +            PERROR("Failed to write buffer: %s", strerror(errno));
   1.166 +            return -errno;
   1.167 +        }
   1.168 +    }
   1.169 +
   1.170 +    return 0;
   1.171 +}
   1.172 +
   1.173 +int 
   1.174 +xc_domain_dumpcore(int xc_handle,
   1.175 +                   uint32_t domid,
   1.176 +                   const char *corename)
   1.177 +{
   1.178 +    struct dump_args da;
   1.179 +    int sts;
   1.180 +
   1.181 +    if ( (da.fd = open(corename, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)) < 0 )
   1.182 +    {
   1.183 +        PERROR("Could not open corefile %s: %s", corename, strerror(errno));
   1.184 +        return -errno;
   1.185 +    }
   1.186 + 
   1.187 +    sts = xc_domain_dumpcore_via_callback(
   1.188 +        xc_handle, domid, &da, &local_file_dump);
   1.189 +
   1.190 +    close(da.fd);
   1.191 +
   1.192 +    return sts;
   1.193 +}
   1.194 +
   1.195  /*
   1.196   * Local variables:
   1.197   * mode: C
     2.1 --- a/tools/libxc/xenctrl.h	Mon Mar 13 11:10:27 2006 +0100
     2.2 +++ b/tools/libxc/xenctrl.h	Mon Mar 13 11:47:56 2006 +0100
     2.3 @@ -139,10 +139,28 @@ int xc_domain_create(int xc_handle,
     2.4                       uint32_t *pdomid);
     2.5  
     2.6  
     2.7 +/* Functions to produce a dump of a given domain
     2.8 + *  xc_domain_dumpcore - produces a dump to a specified file
     2.9 + *  xc_domain_dumpcore_via_callback - produces a dump, using a specified
    2.10 + *                                    callback function
    2.11 + */
    2.12  int xc_domain_dumpcore(int xc_handle, 
    2.13                         uint32_t domid,
    2.14                         const char *corename);
    2.15  
    2.16 +/* Define the callback function type for xc_domain_dumpcore_via_callback.
    2.17 + *
    2.18 + * This function is called by the coredump code for every "write",
    2.19 + * and passes an opaque object for the use of the function and
    2.20 + * created by the caller of xc_domain_dumpcore_via_callback.
    2.21 + */
    2.22 +typedef int (dumpcore_rtn_t)(void *arg, char *buffer, unsigned int length);
    2.23 +
    2.24 +int xc_domain_dumpcore_via_callback(int xc_handle, 
    2.25 +                                    uint32_t domid,
    2.26 +                                    void *arg,
    2.27 +                                    dumpcore_rtn_t dump_rtn);
    2.28 +
    2.29  /*
    2.30   * This function sets the maximum number of vcpus that a domain may create.
    2.31   *
    2.32 @@ -372,13 +390,13 @@ int xc_domain_memory_increase_reservatio
    2.33                                            unsigned long nr_extents,
    2.34                                            unsigned int extent_order,
    2.35                                            unsigned int address_bits,
    2.36 -					  unsigned long *extent_start);
    2.37 +                                          unsigned long *extent_start);
    2.38  
    2.39  int xc_domain_memory_decrease_reservation(int xc_handle,
    2.40                                            uint32_t domid, 
    2.41                                            unsigned long nr_extents,
    2.42                                            unsigned int extent_order,
    2.43 -					  unsigned long *extent_start);
    2.44 +                                          unsigned long *extent_start);
    2.45  
    2.46  int xc_domain_memory_populate_physmap(int xc_handle,
    2.47                                        uint32_t domid,
    2.48 @@ -411,7 +429,7 @@ int xc_domain_iomem_permission(int xc_ha
    2.49                                 uint8_t allow_access);
    2.50  
    2.51  unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid, 
    2.52 -				    unsigned long mfn);
    2.53 +                                    unsigned long mfn);
    2.54  
    2.55  typedef dom0_perfc_desc_t xc_perfc_desc_t;
    2.56  /* IMPORTANT: The caller is responsible for mlock()'ing the @desc array. */
    2.57 @@ -457,7 +475,7 @@ void *xc_map_foreign_batch(int xc_handle
    2.58   * @parm virt the virtual address to translate
    2.59   */
    2.60  unsigned long xc_translate_foreign_address(int xc_handle, uint32_t dom,
    2.61 -					   int vcpu, unsigned long long virt);
    2.62 +                                           int vcpu, unsigned long long virt);
    2.63  
    2.64  int xc_get_pfn_list(int xc_handle, uint32_t domid, unsigned long *pfn_buf, 
    2.65                      unsigned long max_pfns);
    2.66 @@ -467,7 +485,7 @@ int xc_ia64_get_pfn_list(int xc_handle, 
    2.67                           unsigned int start_page, unsigned int nr_pages);
    2.68  
    2.69  int xc_copy_to_domain_page(int xc_handle, uint32_t domid,
    2.70 -			   unsigned long dst_pfn, const char *src_page);
    2.71 +                           unsigned long dst_pfn, const char *src_page);
    2.72  
    2.73  int xc_clear_domain_page(int xc_handle, uint32_t domid,
    2.74                           unsigned long dst_pfn);
    2.75 @@ -478,7 +496,7 @@ int xc_ia64_copy_to_domain_pages(int xc_
    2.76  long xc_get_max_pages(int xc_handle, uint32_t domid);
    2.77  
    2.78  int xc_mmuext_op(int xc_handle, struct mmuext_op *op, unsigned int nr_ops,
    2.79 -		 domid_t dom);
    2.80 +                 domid_t dom);
    2.81  
    2.82  int xc_memory_op(int xc_handle, int cmd, void *arg);
    2.83