diff -ruNp 610-extent.patch-old/kernel/power/suspend2_core/extent.c 610-extent.patch-new/kernel/power/suspend2_core/extent.c
--- 610-extent.patch-old/kernel/power/suspend2_core/extent.c 1970-01-01 10:00:00.000000000 +1000
+++ 610-extent.patch-new/kernel/power/suspend2_core/extent.c 2005-07-04 23:14:19.000000000 +1000
@@ -0,0 +1,206 @@
+/*
+ * kernel/power/suspend2_core/extent.c
+ *
+ * Suspend2 routines for manipulating extents.
+ *
+ * (C) 2003-2005 Nigel Cunningham <[email protected]>
+ *
+ * Distributed under GPLv2.
+ *
+ * These functions encapsulate the manipulation of extents.
+ * They work like this:
+ *
+ * A lot of the data that suspend saves involves continguous extents of memory
+ * or storage. Let's say that we're storing data on disk in blocks 1-32768 and
+ * 49152-49848 of a swap partition. Rather than recording 1, 2, 3... in arrays
+ * pointing to the locations, we simply use:
+ *
+ * struct extent {
+ * unsigned long min;
+ * unsigned long max;
+ * struct extent * next;
+ * }
+ *
+ * We can then store 1-32768 and 49152-49848 in 2 struct extents, using 24 bytes
+ * instead of something like 133,860. This is of course inefficient where a extent
+ * covers only one or two values, but the benefits gained by the much larger
+ * extents more than outweigh these instances.
+ *
+ * When _all_ the metadata was stored in extents, we used to have fancier code that
+ * stored them in pages and was optimised for our usage. Nowadays they are only
+ * used for storage information. We therefore kmalloc them as required, and
+ * provide a far simpler routine to serialise them in the image header.
+ */
+
+#include <linux/module.h>
+#include <linux/suspend.h>
+#include "plugins.h"
+#include "extent.h"
+#include "ui.h"
+
+int extents_allocated = 0, max_extents_used = 0;
+
+/* get_extent
+ *
+ * Returns a free extent.
+ * May fail, returning NULL instead.
+ */
+
+static struct extent * get_extent(void)
+{
+ struct extent * result;
+
+ if (!(result = kmalloc(sizeof(struct extent), GFP_ATOMIC)))
+ return NULL;
+
+ extents_allocated++;
+ if (extents_allocated > max_extents_used)
+ max_extents_used++;
+ result->minimum = result->maximum = 0;
+ result->next = NULL;
+ return result;
+}
+
+/*
+ * put_extent.
+ *
+ * Frees an extent.
+ *
+ * Assumes unlinking is done by the caller.
+ */
+void put_extent(struct extent * extent)
+{
+ if (!extent) {
+ printk("Error! put_extent called with NULL extent.\n");
+ return;
+ }
+ kfree(extent);
+ extents_allocated--;
+}
+
+/*
+ * put_extent_chain.
+ *
+ * Frees a whole chain of extents.
+ */
+void put_extent_chain(struct extentchain * chain)
+{
+ struct extent * this;
+
+ this = chain->first;
+
+ if (!this)
+ return;
+
+ while(this) {
+ struct extent * next = this->next;
+ kfree(this);
+ chain->frees++;
+ extents_allocated --;
+ this = next;
+ }
+
+ BUG_ON(chain->frees != chain->allocs);
+ chain->first = chain->last = NULL;
+ chain->size = chain->allocs = chain->frees = 0;
+}
+
+/*
+ * append_extent_to_extent_chain
+ *
+ * Used where we know a extent is to be added to the end of the list
+ * and does not need merging with the current last extent.
+ */
+
+int append_extent_to_extent_chain(struct extentchain * chain,
+ unsigned long minimum, unsigned long maximum)
+{
+ struct extent * newextent = NULL;
+
+ newextent = get_extent();
+ if (!newextent) {
+ printk("Error unable to append a new extent to the chain.\n");
+ return 2;
+ }
+
+ chain->allocs++;
+ chain->size+= (maximum - minimum + 1);
+ newextent->minimum = minimum;
+ newextent->maximum = maximum;
+ newextent->next = NULL;
+
+ if (chain->last) {
+ chain->last->next = newextent;
+ chain->last = newextent;
+ } else
+ chain->last = chain->first = newextent;
+
+ /* No need to reset optimisation info since added to end */
+ return 0;
+}
+
+/*
+ * serialise_extent_chain
+ *
+ * Write a chain in the image.
+ */
+int serialise_extent_chain(struct extentchain * chain)
+{
+ struct extent * this;
+ int ret, i = 1;
+
+ if ((ret = active_writer->ops.writer.write_header_chunk((char *) chain,
+ sizeof(struct extentchain) - 2 * sizeof(struct extent *)))) {
+ printk("Write header chunk returned %d - aborting serialising chain.\n",
+ ret);
+ return ret;
+ }
+
+ this = chain->first;
+ while (this) {
+ if ((ret = active_writer->ops.writer.write_header_chunk((char *) this,
+ 2 * sizeof(unsigned long)))) {
+ printk("Failed to write extent.\n");
+ return ret;
+ }
+ this = this->next;
+ i++;
+ }
+ return ret;
+}
+
+/*
+ * load_extent_chain
+ *
+ * Read back a chain saved in the image.
+ */
+int load_extent_chain(struct extentchain * chain)
+{
+ struct extent * this, * last = NULL;
+ int i, ret;
+
+ if (!(ret = active_writer->ops.writer.read_header_chunk((char *) chain,
+ sizeof(struct extentchain) - 2 * sizeof(struct extent *)))) {
+ printk("Read header chunk returned %d - aborting serialising chain.\n",
+ ret);
+ return ret;
+ }
+
+ for (i = 0; i < (chain->allocs - chain->frees); i++) {
+ this = kmalloc(sizeof(struct extent), GFP_ATOMIC);
+ BUG_ON(!this); /* Shouldn't run out of memory trying this! */
+ this->next = NULL;
+ if (!(ret = active_writer->ops.writer.read_header_chunk((char *) this,
+ 2 * sizeof(unsigned long)))) {
+ printk("Failed to read extent.\n");
+ return ret;
+ }
+ if (last)
+ last->next = this;
+ else
+ chain->first = this;
+ last = this;
+ }
+ chain->last = last;
+ return ret;
+}
diff -ruNp 610-extent.patch-old/kernel/power/suspend2_core/extent.h 610-extent.patch-new/kernel/power/suspend2_core/extent.h
--- 610-extent.patch-old/kernel/power/suspend2_core/extent.h 1970-01-01 10:00:00.000000000 +1000
+++ 610-extent.patch-new/kernel/power/suspend2_core/extent.h 2005-07-05 23:48:59.000000000 +1000
@@ -0,0 +1,84 @@
+/*
+ * kernel/power/extent.h
+ *
+ * Copyright (C) 2004-2005 Nigel Cunningham <[email protected]>
+ *
+ * This file is released under the GPLv2.
+ *
+ * It contains declarations related to extents. Extents are
+ * suspend's method of storing some of the metadata for the image.
+ * See extent.c for more info.
+ *
+ */
+
+#ifndef EXTENT_H
+#define EXTENT_H
+struct extentchain {
+ int size; /* size of the extent ie sum (max-min+1) */
+ int allocs;
+ int frees;
+ int debug;
+ int timesusedoptimisation;
+ char * name;
+ struct extent * first;
+ struct extent * last;
+};
+
+/*
+ * We rely on extents not fitting evenly into a page.
+ * The last four bytes are used to store the number
+ * of the page, to make saving & reloading pages simpler.
+ */
+struct extent {
+ unsigned long minimum;
+ unsigned long maximum;
+ struct extent * next;
+};
+
+
+#define extent_for_each(extentchain, extentpointer, value) \
+if ((extentchain)->first) \
+ for ((extentpointer) = (extentchain)->first, (value) = \
+ (extentpointer)->minimum; \
+ ((extentpointer) && ((extentpointer)->next || (value) <= \
+ (extentpointer)->maximum)); \
+ (((value) == (extentpointer)->maximum) ? \
+ ((extentpointer) = (extentpointer)->next, (value) = \
+ ((extentpointer) ? (extentpointer)->minimum : 0)) : \
+ (value)++))
+
+/*
+ * When using compression and expected_compression > 0,
+ * we allocate fewer swap entries, so GET_EXTENT_NEXT can
+ * validly run out of data to return.
+ */
+#define GET_EXTENT_NEXT(currentextent, currentval) \
+{ \
+ if (currentextent) { \
+ if ((currentval) == (currentextent)->maximum) { \
+ if ((currentextent)->next) { \
+ (currentextent) = (currentextent)->next; \
+ (currentval) = (currentextent)->minimum; \
+ } else { \
+ (currentextent) = NULL; \
+ (currentval) = 0; \
+ } \
+ } else \
+ currentval++; \
+ } \
+}
+
+extern int max_extents_used, extents_allocated;
+void put_extent(struct extent * extent);
+void put_extent_chain(struct extentchain * chain);
+int append_extent_to_extent_chain(struct extentchain * chain,
+ unsigned long minimum, unsigned long maximum);
+int serialise_extent_chain(struct extentchain * chain);
+int load_extent_chain(struct extentchain * chain);
+
+/* swap_entry_to_extent_val & extent_val_to_swap_entry:
+ * We are putting offset in the low bits so consecutive swap entries
+ * make consecutive extent values */
+#define swap_entry_to_extent_val(swp_entry) (swp_entry.val)
+#define extent_val_to_swap_entry(val) (swp_entry_t) { (val) }
+#endif
-
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]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
|
|