Allocate extra memory needed for an atomic copy when the page cache is too
small to store it.
Signed-off-by: Nigel Cunningham <[email protected]>
kernel/power/pagedir.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 75 insertions(+), 0 deletions(-)
diff --git a/kernel/power/pagedir.c b/kernel/power/pagedir.c
index 9c26990..76da2e5 100644
--- a/kernel/power/pagedir.c
+++ b/kernel/power/pagedir.c
@@ -54,3 +54,78 @@ void suspend_free_extra_pagedir_memory(v
extra_pagedir_pages_allocated = 0;
}
+/* suspend_allocate_extra_pagedir_memory
+ *
+ * Description: Allocate memory for making the atomic copy of pagedir1 in the
+ * case where it is bigger than pagedir2.
+ * Arguments: struct pagedir *: The pagedir for which we should
+ * allocate memory.
+ * int: Size of pageset 1.
+ * int: Size of pageset 2.
+ * Result: int. Zero on success. One if unable to allocate enough memory.
+ */
+int suspend_allocate_extra_pagedir_memory(struct pagedir *p, int pageset_size,
+ int alloc_from)
+{
+ int num_to_alloc = pageset_size - alloc_from - extra_pagedir_pages_allocated;
+ int j, order, num_added = 0;
+
+ if (num_to_alloc < 1)
+ num_to_alloc = 0;
+
+ if (num_to_alloc) {
+ order = fls(num_to_alloc);
+ if (order >= MAX_ORDER)
+ order = MAX_ORDER - 1;
+
+ while (num_added < num_to_alloc) {
+ struct page *newpage;
+ unsigned long virt;
+ struct extras *extras_entry;
+
+ while ((1 << order) > (num_to_alloc - num_added))
+ order--;
+
+ virt = __get_free_pages(GFP_ATOMIC | __GFP_NOWARN, order);
+ while ((!virt) && (order > 0)) {
+ order--;
+ virt = __get_free_pages(GFP_ATOMIC | __GFP_NOWARN, order);
+ }
+
+ if (!virt) {
+ p->pageset_size += num_added;
+ extra_pagedir_pages_allocated += num_added;
+ return 1;
+ }
+
+ newpage = virt_to_page(virt);
+
+ extras_entry = (struct extras *) kmalloc(sizeof(struct extras), GFP_ATOMIC);
+
+ if (!extras_entry) {
+ __free_pages(newpage, order);
+ extra_pagedir_pages_allocated += num_added;
+ return 1;
+ }
+
+ extras_entry->page = newpage;
+ extras_entry->order = order;
+ extras_entry->next = NULL;
+
+ if (extras_list)
+ extras_entry->next = extras_list;
+
+ extras_list = extras_entry;
+
+ for (j = 0; j < (1 << order); j++) {
+ SetPageNosave(newpage + j);
+ SetPagePageset1Copy(newpage + j);
+ }
+ num_added+= (1 << order);
+ }
+ }
+
+ extra_pagedir_pages_allocated += num_added;
+ 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]