From: Jeremy Kerr Date: Mon, 2 Dec 2013 03:20:04 +0000 (+0800) Subject: discover/device-handler: Ensure we free unresolved boot options on remove X-Git-Tag: v1.0.0~297 X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=commitdiff_plain;h=d27570168fd6d5a2144553002c8082ae626b7e84;ds=sidebyside discover/device-handler: Ensure we free unresolved boot options on remove When we remove a device, some options may still be unresolved, and so won't be deallocated through freeing the device. This chagne explicitly removes & frees any currently-unresolved options for this device. Signed-off-by: Jeremy Kerr --- diff --git a/discover/device-handler.c b/discover/device-handler.c index 9033c4f..d3256fa 100644 --- a/discover/device-handler.c +++ b/discover/device-handler.c @@ -279,6 +279,7 @@ struct device_handler *device_handler_init(struct discover_server *server, void device_handler_remove(struct device_handler *handler, struct discover_device *device) { + struct discover_boot_option *opt, *tmp; unsigned int i; for (i = 0; i < handler->n_devices; i++) @@ -290,6 +291,16 @@ void device_handler_remove(struct device_handler *handler, return; } + /* Free any unresolved options, as they're currently allocated + * against the handler */ + list_for_each_entry_safe(&handler->unresolved_boot_options, + opt, tmp, list) { + if (opt->device != device) + continue; + list_remove(&opt->list); + talloc_free(opt); + } + handler->n_devices--; memmove(&handler->devices[i], &handler->devices[i + 1], (handler->n_devices - i) * sizeof(handler->devices[0])); diff --git a/test/parser/Makefile.am b/test/parser/Makefile.am index f2ee67e..46f87ce 100644 --- a/test/parser/Makefile.am +++ b/test/parser/Makefile.am @@ -57,7 +57,8 @@ TESTS = \ test-pxe-mac-without-conf \ test-pxe-ip-without-conf \ test-pxe-non-url-conf \ - test-pxe-local + test-pxe-local \ + test-unresolved-remove $(TESTS): %: %.embedded-config.o $(TESTS): LDADD += $@.embedded-config.o diff --git a/test/parser/parser-test.h b/test/parser/parser-test.h index 7e4ffa2..c23a7b0 100644 --- a/test/parser/parser-test.h +++ b/test/parser/parser-test.h @@ -31,6 +31,7 @@ void test_read_conf_file(struct parser_test *test, const char *filename, int test_run_parser(struct parser_test *test, const char *parser_name); void test_hotplug_device(struct parser_test *test, struct discover_device *dev); +void test_remove_device(struct parser_test *test, struct discover_device *dev); void test_add_file_data(struct parser_test *test, struct discover_device *dev, const char *filename, const void *data, int size); diff --git a/test/parser/test-unresolved-remove.c b/test/parser/test-unresolved-remove.c new file mode 100644 index 0000000..7e0a306 --- /dev/null +++ b/test/parser/test-unresolved-remove.c @@ -0,0 +1,35 @@ + +#include "parser-test.h" + +#if 0 /* PARSER_EMBEDDED_CONFIG */ +menuentry 'Linux' { + search --set=root ec50d321-aab1-4335-8a87-aa8fadd80a09 + linux /vmlinux +} +#endif + +void run_test(struct parser_test *test) +{ + struct discover_boot_option *opt; + struct discover_context *ctx; + struct discover_device *dev; + + test_read_conf_embedded(test, "/grub.cfg"); + + test_run_parser(test, "grub2"); + + ctx = test->ctx; + + check_boot_option_count(ctx, 1); + opt = get_boot_option(ctx, 0); + check_name(opt, "Linux"); + check_unresolved_resource(opt->boot_image); + + test_remove_device(test, test->ctx->device); + + dev = test_create_device(test, "external"); + dev->uuid = "ec50d321-aab1-4335-8a87-aa8fadd80a09"; + test_hotplug_device(test, dev); + + check_boot_option_count(ctx, 0); +} diff --git a/test/parser/utils.c b/test/parser/utils.c index b80e0e1..8011793 100644 --- a/test/parser/utils.c +++ b/test/parser/utils.c @@ -301,6 +301,21 @@ void test_hotplug_device(struct parser_test *test, struct discover_device *dev) boot_option_resolve(test->handler, opt); } +void test_remove_device(struct parser_test *test, struct discover_device *dev) +{ + struct discover_boot_option *opt, *tmp; + + if (dev == test->ctx->device) { + list_for_each_entry_safe(&test->ctx->boot_options, + opt, tmp, list) { + list_remove(&opt->list); + talloc_free(opt); + } + } + + device_handler_remove(test->handler, dev); +} + struct discover_boot_option *get_boot_option(struct discover_context *ctx, int idx) {