Read the configurations used when writing the image, prior to loading the
data. Modules which are loaded now, and weren't when we suspended are
disabled. If a module which is needed is not available, we complain and
abort resuming. When built as modules, support for (say) encryption and
compression can end up loaded in the wrong order. We therefore also reorder
the modules to match the order used when suspending.
Signed-off-by: Nigel Cunningham <[email protected]>
kernel/power/io.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 126 insertions(+), 0 deletions(-)
diff --git a/kernel/power/io.c b/kernel/power/io.c
index a0aabd1..b179c50 100644
--- a/kernel/power/io.c
+++ b/kernel/power/io.c
@@ -488,3 +488,129 @@ static int write_module_configs(void)
return 0;
}
+/* read_module_configs()
+ *
+ * Description: Reload module configurations from the image header.
+ * Returns: Int. Zero on success, error value otherwise.
+ */
+
+static int read_module_configs(void)
+{
+ struct suspend_module_ops *this_module;
+ char *buffer = (char *) get_zeroed_page(GFP_ATOMIC);
+ int len, result = 0;
+ struct suspend_module_header suspend_module_header;
+
+ if (!buffer) {
+ printk("Failed to allocate a buffer for reloading module "
+ "configuration info.\n");
+ return -ENOMEM;
+ }
+
+ /* All modules are initially disabled. That way, if we have a module
+ * loaded now that wasn't loaded when we suspended, it won't be used
+ * in trying to read the data.
+ */
+ list_for_each_entry(this_module, &suspend_modules, module_list)
+ this_module->disabled = 1;
+
+ /* Get the first module header */
+ result = suspend_active_writer->rw_header_chunk(READ, NULL,
+ (char *) &suspend_module_header, sizeof(suspend_module_header));
+ if (!result) {
+ printk("Failed to read the next module header.\n");
+ free_page((unsigned long) buffer);
+ return -EINVAL;
+ }
+
+ /* For each module (in registration order) */
+ while (suspend_module_header.name[0]) {
+
+ /* Find the module */
+ this_module = suspend_find_module_given_name(suspend_module_header.name);
+
+ if (!this_module) {
+ /*
+ * Is it used? Only need to worry about filters. The active
+ * writer must be loaded!
+ */
+ if (!suspend_module_header.disabled) {
+ suspend_early_boot_message(1, SUSPEND_CONTINUE_REQ,
+ "It looks like we need module %s for "
+ "reading the image but it hasn't been "
+ "registered.\n",
+ suspend_module_header.name);
+ if (!(test_suspend_state(SUSPEND_CONTINUE_REQ))) {
+ suspend_active_writer->invalidate_image();
+ free_page((unsigned long) buffer);
+ return -EINVAL;
+ }
+ } else
+ printk("Module %s configuration data found, but the module "
+ "hasn't registered. Looks like it was disabled, so "
+ "we're ignoring it's data.",
+ suspend_module_header.name);
+ }
+
+ /* Get the length of the data (if any) */
+ result = suspend_active_writer->rw_header_chunk(READ, NULL,
+ (char *) &len, sizeof(int));
+ if (!result) {
+ printk("Failed to read the length of the module %s's"
+ " configuration data.\n",
+ suspend_module_header.name);
+ free_page((unsigned long) buffer);
+ return -EINVAL;
+ }
+
+ /* Read any data and pass to the module (if we found one) */
+ if (len) {
+ suspend_active_writer->rw_header_chunk(READ, NULL,
+ buffer, len);
+ if (this_module) {
+ if (!this_module->save_config_info) {
+ printk("Huh? Module %s appears to have "
+ "a save_config_info, but not a "
+ "load_config_info function!\n",
+ this_module->name);
+ } else
+ this_module->load_config_info(buffer, len);
+ }
+ }
+
+ if (this_module) {
+ /* Now move this module to the tail of its lists. This
+ * will put it in order. Any new modules will end up at
+ * the top of the lists. They should have been set to
+ * disabled when loaded (people will normally not edit
+ * an initrd to load a new module and then suspend
+ * without using it!).
+ */
+
+ suspend_move_module_tail(this_module);
+
+ /*
+ * We apply the disabled state; modules don't need to
+ * save whether they were disabled and if they do, we
+ * override them anyway.
+ */
+ this_module->disabled = suspend_module_header.disabled;
+ }
+
+ /* Get the next module header */
+ result = suspend_active_writer->rw_header_chunk(READ, NULL,
+ (char *) &suspend_module_header,
+ sizeof(suspend_module_header));
+
+ if (!result) {
+ printk("Failed to read the next module header.\n");
+ free_page((unsigned long) buffer);
+ return -EINVAL;
+ }
+
+ }
+
+ free_page((unsigned long) buffer);
+ return 0;
+}
+
--
Nigel Cunningham nigel at suspend2 dot net
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]