blob: af63e860cd0bcfee29d45bbb56c3c1947257f6b3 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
/*
* BIGMEM common code and variables.
*
* (C) 1999 Andrea Arcangeli, SuSE GmbH, andrea@suse.de
* Gerhard Wichert, Siemens AG, Gerhard.Wichert@pdb.siemens.de
*/
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/bigmem.h>
unsigned long bigmem_mapnr;
int nr_free_bigpages = 0;
struct page * prepare_bigmem_swapout(struct page * page)
{
/* if this is a bigmem page so it can't be swapped out directly
otherwise the b_data buffer addresses will break
the lowlevel device drivers. */
if (PageBIGMEM(page)) {
unsigned long regular_page;
unsigned long vaddr;
regular_page = __get_free_page(GFP_ATOMIC);
if (!regular_page)
return NULL;
vaddr = kmap(page_address(page), KM_READ);
copy_page(regular_page, vaddr);
kunmap(vaddr, KM_READ);
/* ok, we can just forget about our bigmem page since
we stored its data into the new regular_page. */
__free_page(page);
page = MAP_NR(regular_page) + mem_map;
}
return page;
}
struct page * replace_with_bigmem(struct page * page)
{
if (!PageBIGMEM(page) && nr_free_bigpages) {
unsigned long kaddr;
kaddr = __get_free_page(GFP_ATOMIC|GFP_BIGMEM);
if (kaddr) {
struct page * bigmem_page;
bigmem_page = MAP_NR(kaddr) + mem_map;
if (PageBIGMEM(bigmem_page)) {
unsigned long vaddr;
vaddr = kmap(kaddr, KM_WRITE);
copy_page(vaddr, page_address(page));
kunmap(vaddr, KM_WRITE);
/* Preserve the caching of the swap_entry. */
bigmem_page->offset = page->offset;
/* We can just forget the old page since
we stored its data into the new
bigmem_page. */
__free_page(page);
page = bigmem_page;
}
}
}
return page;
}
|