[comboot] Fix reference counting on replacement images

When chaining COMBOOT images, the old images now get freed correctly.
pull/1/head
Michael Brown 2009-02-17 01:45:12 +00:00
parent 8904cd55f1
commit 14eafc5b8d
5 changed files with 22 additions and 17 deletions

View File

@ -122,6 +122,7 @@ static int com32_exec ( struct image *image ) {
DBGC ( image, "COM32 %p: exited to run kernel %p\n", DBGC ( image, "COM32 %p: exited to run kernel %p\n",
image, comboot_replacement_image ); image, comboot_replacement_image );
image->replacement = comboot_replacement_image; image->replacement = comboot_replacement_image;
comboot_replacement_image = NULL;
image_autoload ( image->replacement ); image_autoload ( image->replacement );
break; break;

View File

@ -191,6 +191,7 @@ static int comboot_exec ( struct image *image ) {
DBGC ( image, "COMBOOT %p: exited to run kernel %p\n", DBGC ( image, "COMBOOT %p: exited to run kernel %p\n",
image, comboot_replacement_image ); image, comboot_replacement_image );
image->replacement = comboot_replacement_image; image->replacement = comboot_replacement_image;
comboot_replacement_image = NULL;
image_autoload ( image->replacement ); image_autoload ( image->replacement );
break; break;

View File

@ -157,7 +157,7 @@ void comboot_force_text_mode ( void ) {
* Fetch kernel and optional initrd * Fetch kernel and optional initrd
*/ */
static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) { static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) {
struct image *kernel; struct image *kernel = NULL;
struct image *initrd = NULL; struct image *initrd = NULL;
char *initrd_file; char *initrd_file;
int rc; int rc;
@ -181,13 +181,13 @@ static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) {
if ( ! initrd ) { if ( ! initrd ) {
DBG ( "COMBOOT: could not allocate initrd\n" ); DBG ( "COMBOOT: could not allocate initrd\n" );
rc = -ENOMEM; rc = -ENOMEM;
goto err_alloc_initrd; goto out;
} }
if ( ( rc = imgfetch ( initrd, initrd_file, if ( ( rc = imgfetch ( initrd, initrd_file,
register_image ) ) != 0 ) { register_image ) ) != 0 ) {
DBG ( "COMBOOT: could not fetch initrd: %s\n", DBG ( "COMBOOT: could not fetch initrd: %s\n",
strerror ( rc ) ); strerror ( rc ) );
goto err_fetch_initrd; goto out;
} }
/* Restore space after initrd name, if applicable */ /* Restore space after initrd name, if applicable */
@ -202,32 +202,31 @@ static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) {
if ( ! kernel ) { if ( ! kernel ) {
DBG ( "COMBOOT: could not allocate kernel\n" ); DBG ( "COMBOOT: could not allocate kernel\n" );
rc = -ENOMEM; rc = -ENOMEM;
goto err_alloc_kernel; goto out;
} }
if ( ( rc = imgfetch ( kernel, kernel_file, if ( ( rc = imgfetch ( kernel, kernel_file,
register_image ) ) != 0 ) { register_image ) ) != 0 ) {
DBG ( "COMBOOT: could not fetch kernel: %s\n", DBG ( "COMBOOT: could not fetch kernel: %s\n",
strerror ( rc ) ); strerror ( rc ) );
goto err_fetch_kernel; goto out;
} }
if ( ( rc = image_set_cmdline ( kernel, cmdline ) ) != 0 ) { if ( ( rc = image_set_cmdline ( kernel, cmdline ) ) != 0 ) {
DBG ( "COMBOOT: could not set kernel command line: %s\n", DBG ( "COMBOOT: could not set kernel command line: %s\n",
strerror ( rc ) ); strerror ( rc ) );
goto err_set_cmdline; goto out;
} }
/* Store kernel as replacement image */ /* Store kernel as replacement image */
comboot_replacement_image = kernel; assert ( comboot_replacement_image == NULL );
comboot_replacement_image = image_get ( kernel );
return 0; out:
/* Drop image references unconditionally; either we want to
err_set_cmdline: * discard them, or they have been registered and we should
err_fetch_kernel: * drop out local reference.
*/
image_put ( kernel ); image_put ( kernel );
err_alloc_kernel:
err_fetch_initrd:
image_put ( initrd ); image_put ( initrd );
err_alloc_initrd:
return rc; return rc;
} }

View File

@ -275,8 +275,7 @@ int image_exec ( struct image *image ) {
/* Pick up replacement image before we drop the original /* Pick up replacement image before we drop the original
* image's temporary reference. * image's temporary reference.
*/ */
if ( ( replacement = image->replacement ) != NULL ) replacement = image->replacement;
image_get ( replacement );
/* Drop temporary reference to the original image */ /* Drop temporary reference to the original image */
image_put ( image ); image_put ( image );

View File

@ -53,7 +53,12 @@ struct image {
* style similar to a Unix exec() call) should return from its * style similar to a Unix exec() call) should return from its
* exec() method with the replacement image set to point to * exec() method with the replacement image set to point to
* the new image. The new image must already be in a suitable * the new image. The new image must already be in a suitable
* state for execution. * state for execution (i.e. loaded).
*
* If an image unregisters itself as a result of being
* executed, it must make sure that its replacement image (if
* any) is registered, otherwise the replacement is likely to
* be freed before it can be executed.
*/ */
struct image *replacement; struct image *replacement;
}; };