WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] Make xc_linux_build() load the initrd page-by-page rathe

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Make xc_linux_build() load the initrd page-by-page rather
From: Xen patchbot -unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 09 Mar 2006 16:28:07 +0000
Delivery-date: Thu, 09 Mar 2006 16:28:55 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID d4a2af362e5eae4d201e2b02366948cf87a57e2a
# Parent  a1fcee3b2abe44e6cece13a91f1bf012008bf2b0
Make xc_linux_build() load the initrd page-by-page rather
than all in one go, to conserve memory. This always has been
the behaviour, but it was changed by a changeset earlier today.

Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>

diff -r a1fcee3b2abe -r d4a2af362e5e tools/libxc/xc_hvm_build.c
--- a/tools/libxc/xc_hvm_build.c        Thu Mar  9 13:35:36 2006
+++ b/tools/libxc/xc_hvm_build.c        Thu Mar  9 14:16:35 2006
@@ -641,7 +641,7 @@
     if ( (image_buffer == NULL) || (image_size == 0) )
     {
         ERROR("kernel image buffer not present");
-        return -EINVAL;
+        return -1;
     }
 
     img = xc_inflate_buffer(image_buffer, image_size, &img_len);
diff -r a1fcee3b2abe -r d4a2af362e5e tools/libxc/xc_linux_build.c
--- a/tools/libxc/xc_linux_build.c      Thu Mar  9 13:35:36 2006
+++ b/tools/libxc/xc_linux_build.c      Thu Mar  9 14:16:35 2006
@@ -45,6 +45,15 @@
 #ifdef __ia64__
 #define probe_aout9(image,image_size,load_funcs) 1
 #endif
+
+struct initrd_info {
+    enum { INITRD_none, INITRD_file, INITRD_mem } type;
+    unsigned long len;
+    union {
+        gzFile file_handle;
+        char *mem_addr;
+    } u;
+};
 
 static const char *feature_names[XENFEAT_NR_SUBMAPS*32] = {
     [XENFEAT_writable_page_tables]       = "writable_page_tables",
@@ -127,6 +136,42 @@
     {
         ERROR( "Unrecognized image format" );
         return -EINVAL;
+    }
+
+    return 0;
+}
+
+int load_initrd(int xc_handle, domid_t dom,
+                struct initrd_info *initrd,
+                unsigned long physbase,
+                unsigned long *phys_to_mach)
+{
+    char page[PAGE_SIZE];
+    unsigned long pfn_start, pfn, nr_pages;
+
+    if ( initrd->type == INITRD_none )
+        return 0;
+
+    pfn_start = physbase >> PAGE_SHIFT;
+    nr_pages  = (initrd->len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+    for ( pfn = pfn_start; pfn < (pfn_start + nr_pages); pfn++ )
+    {
+        if ( initrd->type == INITRD_mem )
+        {
+            xc_copy_to_domain_page(
+                xc_handle, dom, phys_to_mach[pfn],
+                &initrd->u.mem_addr[(pfn - pfn_start) << PAGE_SHIFT]);
+        }
+        else
+        {
+            if ( gzread(initrd->u.file_handle, page, PAGE_SIZE) == -1 )
+            {
+                PERROR("Error reading initrd image, could not");
+                return -EINVAL;
+            }
+            xc_copy_to_domain_page(xc_handle, dom, phys_to_mach[pfn], page);
+        }
     }
 
     return 0;
@@ -407,7 +452,7 @@
 static int setup_guest(int xc_handle,
                        uint32_t dom,
                        const char *image, unsigned long image_size,
-                       const char *initrd, unsigned long initrd_len,
+                       struct initrd_info *initrd,
                        unsigned long nr_pages,
                        unsigned long *pvsi, unsigned long *pvke,
                        unsigned long *pvss, vcpu_guest_context_t *ctxt,
@@ -441,7 +486,7 @@
 
     dsi.v_start      = round_pgdown(dsi.v_start);
     vinitrd_start    = round_pgup(dsi.v_end);
-    vinitrd_end      = vinitrd_start + initrd_len;
+    vinitrd_end      = vinitrd_start + initrd->len;
     v_end            = round_pgup(vinitrd_end);
 
     start_page = dsi.v_start >> PAGE_SHIFT;
@@ -452,7 +497,8 @@
         goto error_out;
     }
 
-    if ( xc_ia64_get_pfn_list(xc_handle, dom, page_array, start_page, pgnr) != 
pgnr )
+    if ( xc_ia64_get_pfn_list(xc_handle, dom, page_array,
+                              start_page, pgnr) != pgnr )
     {
         PERROR("Could not get the page frame list");
         goto error_out;
@@ -472,17 +518,9 @@
     (load_funcs.loadimage)(image, image_size, xc_handle, dom, page_array,
                            &dsi);
 
-    /* Load the initial ramdisk image, if present */
-    if ( initrd_len != 0 )
-    {
-        /* Pages are not contiguous, so do the copy one page at a time */
-        for ( i = (vinitrd_start - dsi.v_start), offset = 0; 
-              i < (vinitrd_end - dsi.v_start);
-              i += PAGE_SIZE, offset += PAGE_SIZE )
-            xc_copy_to_domain_page(xc_handle, dom,
-                                   page_array[i>>PAGE_SHIFT],
-                                   &initrd[offset]);
-    }
+    if ( load_initrd(xc_handle, dom, initrd,
+                     vinitrd_start - dsi.v_start, page_array) )
+        goto error_out;
 
     *pvke = dsi.v_kernentry;
 
@@ -513,10 +551,10 @@
     start_info->console_mfn   = nr_pages - 1;
     start_info->console_evtchn = console_evtchn;
     start_info->nr_pages       = nr_pages; // FIXME?: nr_pages - 2 ????
-    if ( initrd_len != 0 )
+    if ( initrd->len != 0 )
     {
         ctxt->initrd.start    = vinitrd_start;
-        ctxt->initrd.size     = initrd_len;
+        ctxt->initrd.size     = initrd->len;
     }
     else
     {
@@ -541,7 +579,7 @@
 static int setup_guest(int xc_handle,
                        uint32_t dom,
                        const char *image, unsigned long image_size,
-                       const char *initrd, unsigned long initrd_len,
+                       struct initrd_info *initrd,
                        unsigned long nr_pages,
                        unsigned long *pvsi, unsigned long *pvke,
                        unsigned long *pvss, vcpu_guest_context_t *ctxt,
@@ -610,7 +648,7 @@
      * which we solve by exhaustive search.
      */
     vinitrd_start    = round_pgup(dsi.v_end);
-    vinitrd_end      = vinitrd_start + initrd_len;
+    vinitrd_end      = vinitrd_start + initrd->len;
     vphysmap_start   = round_pgup(vinitrd_end);
     vphysmap_end     = vphysmap_start + (nr_pages * sizeof(unsigned long));
     vstartinfo_start = round_pgup(vphysmap_end);
@@ -731,20 +769,12 @@
         }
     }
 
-    shadow_mode_enabled = test_feature_bit(XENFEAT_auto_translated_physmap, 
required_features);
-
-    /* Load the initial ramdisk image, if present. */
-    if ( initrd_len != 0 )
-    {
-        int offset;
-        /* Pages are not contiguous, so do the inflation a page at a time. */
-        for ( i = (vinitrd_start - dsi.v_start), offset = 0;
-              i < (vinitrd_end - dsi.v_start);
-              i += PAGE_SIZE, offset += PAGE_SIZE )
-            xc_copy_to_domain_page(xc_handle, dom,
-                                   page_array[i>>PAGE_SHIFT],
-                                   &initrd[offset]);
-    }
+    shadow_mode_enabled = test_feature_bit(
+        XENFEAT_auto_translated_physmap, required_features);
+
+    if ( load_initrd(xc_handle, dom, initrd,
+                     vinitrd_start - dsi.v_start, page_array) )
+        goto error_out;
 
     /* setup page tables */
 #if defined(__i386__)
@@ -901,10 +931,10 @@
     start_info->store_evtchn = store_evtchn;
     start_info->console_mfn   = guest_console_mfn;
     start_info->console_evtchn = console_evtchn;
-    if ( initrd_len != 0 )
+    if ( initrd->len != 0 )
     {
         start_info->mod_start    = vinitrd_start;
-        start_info->mod_len      = initrd_len;
+        start_info->mod_len      = initrd->len;
     }
     if ( cmdline != NULL )
     { 
@@ -961,8 +991,7 @@
                                    uint32_t domid,
                                    char *image,
                                    unsigned long image_size,
-                                   char *initrd,
-                                   unsigned long initrd_len,
+                                   struct initrd_info *initrd,
                                    const char *cmdline,
                                    const char *features,
                                    unsigned long flags,
@@ -1016,7 +1045,7 @@
     memset(ctxt, 0, sizeof(*ctxt));
 
     if ( setup_guest(xc_handle, domid, image, image_size, 
-                     initrd, initrd_len,
+                     initrd,
                      nr_pages, 
                      &vstartinfo_start, &vkern_entry,
                      &vstack_start, ctxt, cmdline,
@@ -1132,14 +1161,15 @@
                        unsigned long *console_mfn)
 {
     int            sts;
-    char          *img_buf, *ram_buf;
-    unsigned long  img_len, ram_len;
+    char          *img_buf;
+    unsigned long  img_len;
+    struct initrd_info initrd_info = { .type = INITRD_none };
 
     /* A kernel buffer is required */
     if ( (image_buffer == NULL) || (image_size == 0) )
     {
         ERROR("kernel image buffer not present");
-        return EINVAL;
+        return -1;
     }
 
     /* If it's gzipped, inflate it;  otherwise, use as is */
@@ -1149,28 +1179,25 @@
     if ( img_buf == NULL )
     {
         ERROR("unable to inflate kernel image buffer");
-        return EFAULT;
+        return -1;
     }
 
     /* RAM disks are optional; if we get one, inflate it */
     if ( initrd != NULL )
     {
-        ram_buf = xc_inflate_buffer(initrd, initrd_len, &ram_len);
-        if ( ram_buf == NULL )
+        initrd_info.type = INITRD_mem;
+        initrd_info.u.mem_addr = xc_inflate_buffer(
+            initrd, initrd_len, &initrd_info.len);
+        if ( initrd_info.u.mem_addr == NULL )
         {
             ERROR("unable to inflate ram disk buffer");
             sts = -1;
             goto out;
         }
     }
-    else
-    {
-        ram_buf = (char *)initrd;
-        ram_len = initrd_len;
-    }
 
     sts = xc_linux_build_internal(xc_handle, domid, img_buf, img_len,
-                                  ram_buf, ram_len, cmdline, features, flags,
+                                  &initrd_info, cmdline, features, flags,
                                   store_evtchn, store_mfn,
                                   console_evtchn, console_mfn);
 
@@ -1180,8 +1207,9 @@
     /* Don't unnecessarily annoy/surprise/confound the caller */
     if ( (img_buf != NULL) && (img_buf != image_buffer) )
         free(img_buf);
-    if ( (ram_buf != NULL) && (ram_buf != initrd) )
-        free(ram_buf);
+    if ( (initrd_info.u.mem_addr != NULL) &&
+         (initrd_info.u.mem_addr != initrd) )
+        free(initrd_info.u.mem_addr);
 
     return sts;
 }
@@ -1198,28 +1226,44 @@
                    unsigned int console_evtchn,
                    unsigned long *console_mfn)
 {
-    char *image, *ram = NULL;
-    unsigned long image_size, ram_size = 0;
-    int  sts;
+    char *image = NULL;
+    unsigned long image_size;
+    struct initrd_info initrd_info = { .type = INITRD_none };
+    int fd = -1, sts = -1;
 
     if ( (image_name == NULL) ||
          ((image = xc_read_image(image_name, &image_size)) == NULL ))
         return -1;
 
-    if ( (initrd_name != NULL) && (strlen(initrd_name) != 0) &&
-         ((ram = xc_read_image(initrd_name, &ram_size)) == NULL) )
-    {
-        free(image);
-        return -1;
+    if ( (initrd_name != NULL) && (strlen(initrd_name) != 0) )
+    {
+        initrd_info.type = INITRD_file;
+
+        if ( (fd = open(initrd_name, O_RDONLY)) < 0 )
+        {
+            PERROR("Could not open the initial ramdisk image");
+            goto error_out;
+        }
+
+        initrd_info.len = xc_get_filesz(fd);
+        if ( (initrd_info.u.file_handle = gzdopen(fd, "rb")) == NULL )
+        {
+            PERROR("Could not allocate decompression state for initrd");
+            goto error_out;
+        }
     }
 
     sts = xc_linux_build_internal(xc_handle, domid, image, image_size,
-                                  ram, ram_size, cmdline, features, flags,
+                                  &initrd_info, cmdline, features, flags,
                                   store_evtchn, store_mfn,
                                   console_evtchn, console_mfn);
 
+ error_out:
     free(image);
-    free(ram);
+    if ( fd >= 0 )
+        close(fd);
+    if ( initrd_info.u.file_handle )
+        gzclose(initrd_info.u.file_handle);
 
     return sts;
 }

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Make xc_linux_build() load the initrd page-by-page rather, Xen patchbot -unstable <=