diff -ruNp 614-plugins.patch-old/kernel/power/suspend2_core/plugins.c 614-plugins.patch-new/kernel/power/suspend2_core/plugins.c --- 614-plugins.patch-old/kernel/power/suspend2_core/plugins.c 1970-01-01 10:00:00.000000000 +1000 +++ 614-plugins.patch-new/kernel/power/suspend2_core/plugins.c 2005-07-04 23:14:19.000000000 +1000 @@ -0,0 +1,341 @@ +/* + * kernel/power/plugins.c + * + * Copyright (C) 2004-2005 Nigel Cunningham <[EMAIL PROTECTED]> + * + */ + +#include <linux/suspend.h> +#include <linux/module.h> +#include "suspend.h" +#include "plugins.h" + +struct list_head suspend_filters, suspend_writers, suspend_plugins; +struct suspend_plugin_ops * active_writer = NULL; +static int num_filters = 0, num_ui = 0; +int num_writers = 0, num_plugins = 0; + +/* + * header_storage_for_plugins + * + * Returns the amount of space needed to store configuration + * data needed by the plugins prior to copying back the original + * kernel. We can exclude data for pageset2 because it will be + * available anyway once the kernel is copied back. + */ +unsigned long header_storage_for_plugins(void) +{ + struct suspend_plugin_ops * this_plugin; + unsigned long bytes = 0; + + list_for_each_entry(this_plugin, &suspend_plugins, plugin_list) { + if (this_plugin->disabled) + continue; + if (this_plugin->storage_needed) + bytes += this_plugin->storage_needed(); + } + + return bytes; +} + +/* + * expected_compression_ratio + * + * Returns the expected ratio between the amount of memory + * to be saved and the amount of space required on the + * storage device. + */ +int expected_compression_ratio(void) +{ + struct suspend_plugin_ops * this_filter; + unsigned long ratio = 100; + + list_for_each_entry(this_filter, &suspend_filters, ops.filter.filter_list) { + if (this_filter->disabled) + continue; + if (this_filter->ops.filter.expected_compression) + ratio = ratio * this_filter->ops.filter.expected_compression() / 100; + } + + return (int) ratio; +} + +/* + * memory_for_plugins + * + * Returns the amount of memory requested by plugins for + * doing their work during the cycle. + */ + +unsigned long memory_for_plugins(void) +{ + unsigned long bytes = 0; + struct suspend_plugin_ops * this_plugin; + + list_for_each_entry(this_plugin, &suspend_plugins, plugin_list) { + if (this_plugin->disabled) + continue; + if (this_plugin->memory_needed) + bytes += this_plugin->memory_needed(); + } + + return ((bytes + PAGE_SIZE - 1) >> PAGE_SHIFT); +} + +/* find_plugin_given_name + * Functionality : Return a plugin (if found), given a pointer + * to its name + */ + +struct suspend_plugin_ops * find_plugin_given_name(char * name) +{ + struct suspend_plugin_ops * this_plugin, * found_plugin = NULL; + + list_for_each_entry(this_plugin, &suspend_plugins, plugin_list) { + if (!strcmp(name, this_plugin->name)) { + found_plugin = this_plugin; + break; + } + } + + return found_plugin; +} + +/* + * print_plugin_debug_info + * Functionality : Get debugging info from plugins into a buffer. + */ +int print_plugin_debug_info(char * buffer, int buffer_size) +{ + struct suspend_plugin_ops *this_plugin; + int len = 0; + + list_for_each_entry(this_plugin, &suspend_plugins, plugin_list) { + if (this_plugin->disabled) + continue; + if (this_plugin->print_debug_info) { + int result; + result = this_plugin->print_debug_info(buffer + len, + buffer_size - len); + len += result; + } + } + + return len; +} + +/* + * suspend_register_plugin + * + * Register a plugin. + */ +int suspend_register_plugin(struct suspend_plugin_ops * plugin) +{ + if (find_plugin_given_name(plugin->name)) + return -EBUSY; + + switch (plugin->type) { + case FILTER_PLUGIN: + list_add_tail(&plugin->ops.filter.filter_list, + &suspend_filters); + num_filters++; + break; + + case WRITER_PLUGIN: + list_add_tail(&plugin->ops.writer.writer_list, + &suspend_writers); + num_writers++; + break; + + case MISC_PLUGIN: + break; + + default: + printk("Hmmm. Plugin '%s' has an invalid type." + " It has been ignored.\n", plugin->name); + return -EINVAL; + } + list_add_tail(&plugin->plugin_list, &suspend_plugins); + num_plugins++; + + return 0; +} + +/* + * suspend_unregister_plugin + * + * Remove a plugin. + */ +void suspend_unregister_plugin(struct suspend_plugin_ops * plugin) +{ + switch (plugin->type) { + case FILTER_PLUGIN: + list_del(&plugin->ops.filter.filter_list); + num_filters--; + break; + + case WRITER_PLUGIN: + list_del(&plugin->ops.writer.writer_list); + num_writers--; + if (active_writer == plugin) { + active_writer = NULL; + set_suspend_state(SUSPEND_DISABLED); + } + break; + + case MISC_PLUGIN: + break; + + default: + printk("Hmmm. Plugin '%s' has an invalid type." + " It has been ignored.\n", plugin->name); + return; + } + list_del(&plugin->plugin_list); + num_plugins--; +} + +/* + * suspend_move_plugin_tail + * + * Rearrange plugins when reloading the config. + */ +void suspend_move_plugin_tail(struct suspend_plugin_ops * plugin) +{ + switch (plugin->type) { + case FILTER_PLUGIN: + if (num_filters > 1) + list_move_tail(&plugin->ops.filter.filter_list, + &suspend_filters); + break; + + case WRITER_PLUGIN: + if (num_writers > 1) + list_move_tail(&plugin->ops.writer.writer_list, + &suspend_writers); + break; + + case MISC_PLUGIN: + break; + default: + printk("Hmmm. Plugin '%s' has an invalid type." + " It has been ignored.\n", plugin->name); + return; + } + if ((num_filters + num_writers + num_ui) > 1) + list_move_tail(&plugin->plugin_list, &suspend_plugins); +} + +/* + * suspend2_initialise_plugins + * + * Get ready to do some work! + */ +int suspend2_initialise_plugins(int starting_cycle) +{ + struct suspend_plugin_ops * this_plugin; + int result; + + list_for_each_entry(this_plugin, &suspend_plugins, plugin_list) { + if (this_plugin->disabled) + continue; + if (this_plugin->type == WRITER_PLUGIN && + this_plugin != active_writer) + continue; + if (this_plugin->initialise) { + suspend_message(SUSPEND_MEMORY, SUSPEND_MEDIUM, 1, + "Initialising plugin %s.\n", + this_plugin->name); + if ((result = this_plugin->initialise(starting_cycle))) { + printk("%s didn't initialise okay.\n", + this_plugin->name); + return result; + } + } + } + + return 0; +} + +/* + * suspend2_cleanup_plugins + * + * Tell plugins the work is done. + */ +void suspend2_cleanup_plugins(int finishing_cycle) +{ + struct suspend_plugin_ops * this_plugin; + + list_for_each_entry(this_plugin, &suspend_plugins, plugin_list) { + if (this_plugin->disabled) + continue; + if (this_plugin->type == WRITER_PLUGIN && + this_plugin != active_writer) + continue; + if (this_plugin->cleanup) { + suspend_message(SUSPEND_MEMORY, SUSPEND_MEDIUM, 1, + "Cleaning up plugin %s.\n", + this_plugin->name); + this_plugin->cleanup(finishing_cycle); + } + } +} + +/* + * get_next_filter + * + * Get the next filter in the pipeline. + */ +struct suspend_plugin_ops * +get_next_filter(struct suspend_plugin_ops * filter_sought) +{ + struct suspend_plugin_ops * last_filter = NULL, *this_filter = NULL; + + list_for_each_entry(this_filter, &suspend_filters, ops.filter.filter_list) { + if (this_filter->disabled) + continue; + if ((last_filter == filter_sought) || (!filter_sought)) + return this_filter; + last_filter = this_filter; + } + + return active_writer; +} + +/* suspend2_get_modules + * + * Take a reference to modules so they can't go away under us. + */ + +int suspend2_get_modules(void) +{ + struct suspend_plugin_ops * this_plugin; + + list_for_each_entry(this_plugin, &suspend_plugins, plugin_list) { + if (!try_module_get(this_plugin->module)) { + /* Failed! Reverse gets and return error */ + struct suspend_plugin_ops * this_plugin2; + list_for_each_entry(this_plugin2, &suspend_plugins, plugin_list) { + if (this_plugin == this_plugin2) + return -EINVAL; + module_put(this_plugin2->module); + } + } + } + + return 0; +} + +/* suspend2_put_modules + * + * Release our references to modules we used. + */ + +void suspend2_put_modules(void) +{ + struct suspend_plugin_ops * this_plugin; + + list_for_each_entry(this_plugin, &suspend_plugins, plugin_list) { + module_put(this_plugin->module); + } +} diff -ruNp 614-plugins.patch-old/kernel/power/suspend2_core/plugins.h 614-plugins.patch-new/kernel/power/suspend2_core/plugins.h --- 614-plugins.patch-old/kernel/power/suspend2_core/plugins.h 1970-01-01 10:00:00.000000000 +1000 +++ 614-plugins.patch-new/kernel/power/suspend2_core/plugins.h 2005-07-05 23:48:59.000000000 +1000 @@ -0,0 +1,172 @@ +/* + * kernel/power/plugin.h + * + * Copyright (C) 2004-2005 Nigel Cunningham <[EMAIL PROTECTED]> + * + * This file is released under the GPLv2. + * + * It contains declarations for plugins. Plugins are additions to + * suspend2 that provide facilities such as image compression or + * encryption, backends for storage of the image and user interfaces. + * + */ + +/* This is the maximum size we store in the image header for a plugin name */ +#define SUSPEND_MAX_PLUGIN_NAME_LENGTH 30 + +/* Per-plugin metadata */ +struct plugin_header { + char name[SUSPEND_MAX_PLUGIN_NAME_LENGTH]; + int disabled; + int type; + int index; + int data_length; + unsigned long signature; +}; + +extern int num_plugins, num_writers; + +#define FILTER_PLUGIN 1 +#define WRITER_PLUGIN 2 +#define MISC_PLUGIN 4 // Block writer, eg. +#define CHECKSUM_PLUGIN 5 + +#define SUSPEND_ASYNC 0 +#define SUSPEND_SYNC 1 + +#define SUSPEND_COMMON_IO_OPS \ + /* Writing the image proper */ \ + int (*write_chunk) (struct page * buffer_page); \ +\ + /* Reading the image proper */ \ + int (*read_chunk) (struct page * buffer_page, int sync); \ +\ + /* Reset plugin if image exists but reading aborted */ \ + void (*noresume_reset) (void); + +struct suspend_filter_ops { + SUSPEND_COMMON_IO_OPS + int (*expected_compression) (void); + struct list_head filter_list; +}; + +struct suspend_writer_ops { + + SUSPEND_COMMON_IO_OPS + + /* Calls for allocating storage */ + + int (*storage_available) (void); // Maximum size of image we can save + // (incl. space already allocated). + + int (*storage_allocated) (void); + // Amount of storage already allocated + int (*release_storage) (void); + + /* + * Header space is allocated separately. Note that allocation + * of space for the header might result in allocated space + * being stolen from the main pool if there is no unallocated + * space. We have to be able to allocate enough space for + * the header. We can eat memory to ensure there is enough + * for the main pool. + */ + int (*allocate_header_space) (int space_requested); + int (*allocate_storage) (int space_requested); + + /* Read and write the metadata */ + int (*write_header_init) (void); + int (*write_header_chunk) (char * buffer_start, int buffer_size); + int (*write_header_cleanup) (void); + + int (*read_header_init) (void); + int (*read_header_chunk) (char * buffer_start, int buffer_size); + int (*read_header_cleanup) (void); + + /* Prepare metadata to be saved (relativise/absolutise extents) */ + int (*serialise_extents) (void); + int (*load_extents) (void); + + /* Attempt to parse an image location */ + int (*parse_image_location) (char * buffer, int only_writer); + + /* Determine whether image exists that we can restore */ + int (*image_exists) (void); + + /* Mark the image as having tried to resume */ + void (*mark_resume_attempted) (void); + + /* Destroy image if one exists */ + int (*invalidate_image) (void); + + /* Wait on I/O */ + int (*wait_on_io) (int flush_all); + + struct list_head writer_list; +}; + +struct suspend_plugin_ops { + /* Functions common to all plugins */ + int type; + char * name; + struct module * module; + int disabled; + struct list_head plugin_list; + + /* Bytes! */ + unsigned long (*memory_needed) (void); + unsigned long (*storage_needed) (void); + + int (*print_debug_info) (char * buffer, int size); + int (*save_config_info) (char * buffer); + void (*load_config_info) (char * buffer, int len); + + /* Initialise & cleanup - general routines called + * at the start and end of a cycle. */ + int (*initialise) (int starting_cycle); + void (*cleanup) (int finishing_cycle); + + int (*write_init) (int stream_number); + int (*write_cleanup) (void); + + int (*read_init) (int stream_number); + int (*read_cleanup) (void); + + union { + struct suspend_filter_ops filter; + struct suspend_writer_ops writer; + } ops; +}; + +extern struct suspend_plugin_ops * active_writer; +extern struct list_head suspend_filters, suspend_writers, suspend_plugins; + +extern void prepare_console_plugins(void); +extern void cleanup_console_plugins(void); + +extern struct suspend_plugin_ops * find_plugin_given_name(char * name); +extern struct suspend_plugin_ops * get_next_filter(struct suspend_plugin_ops *); + +extern int suspend_register_plugin(struct suspend_plugin_ops * plugin); +extern void suspend_move_plugin_tail(struct suspend_plugin_ops * plugin); + +extern unsigned long header_storage_for_plugins(void); +extern unsigned long memory_for_plugins(void); + +extern int print_plugin_debug_info(char * buffer, int buffer_size); +extern int suspend_register_plugin(struct suspend_plugin_ops * plugin); +extern void suspend_unregister_plugin(struct suspend_plugin_ops * plugin); + +extern int suspend2_initialise_plugins(int starting_cycle); +extern void suspend2_cleanup_plugins(int finishing_cycle); + +int suspend2_get_modules(void); +void suspend2_put_modules(void); + +static inline void suspend_initialise_plugin_lists(void) { + INIT_LIST_HEAD(&suspend_filters); + INIT_LIST_HEAD(&suspend_writers); + INIT_LIST_HEAD(&suspend_plugins); +} + +extern int expected_compression_ratio(void);
- 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/