[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.