[Suspend2][ 3/9] [Suspend2] Allocate extra memory for the atomic copy.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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]
  Powered by Linux