mirror of https://github.com/ipxe/ipxe.git
[comboot] Fix reference counting on replacement images
When chaining COMBOOT images, the old images now get freed correctly.pull/1/head
parent
8904cd55f1
commit
14eafc5b8d
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue