]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Peter Zijlstra <a.p.zijlstra@chello.nl> |
2 | Subject: mm: methods for teaching filesystems about PG_swapcache pages | |
3 | Patch-mainline: No | |
4 | References: FATE#303834 | |
5 | ||
6 | In order to teach filesystems to handle swap cache pages, three new page | |
7 | functions are introduced: | |
8 | ||
9 | pgoff_t page_file_index(struct page *); | |
10 | loff_t page_file_offset(struct page *); | |
11 | struct address_space *page_file_mapping(struct page *); | |
12 | ||
13 | page_file_index() - gives the offset of this page in the file in | |
14 | PAGE_CACHE_SIZE blocks. Like page->index is for mapped pages, this function | |
15 | also gives the correct index for PG_swapcache pages. | |
16 | ||
17 | page_file_offset() - uses page_file_index(), so that it will give the expected | |
18 | result, even for PG_swapcache pages. | |
19 | ||
20 | page_file_mapping() - gives the mapping backing the actual page; that is for | |
21 | swap cache pages it will give swap_file->f_mapping. | |
22 | ||
23 | Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> | |
24 | Acked-by: Neil Brown <neilb@suse.de> | |
25 | Acked-by: Suresh Jayaraman <sjayaraman@suse.de> | |
26 | ||
27 | --- | |
28 | include/linux/mm.h | 25 +++++++++++++++++++++++++ | |
29 | include/linux/pagemap.h | 5 +++++ | |
30 | mm/swapfile.c | 19 +++++++++++++++++++ | |
31 | 3 files changed, 49 insertions(+) | |
32 | ||
33 | --- a/include/linux/mm.h | |
34 | +++ b/include/linux/mm.h | |
35 | @@ -658,6 +658,17 @@ static inline struct address_space *page | |
36 | return mapping; | |
37 | } | |
38 | ||
39 | +extern struct address_space *__page_file_mapping(struct page *); | |
40 | + | |
41 | +static inline | |
42 | +struct address_space *page_file_mapping(struct page *page) | |
43 | +{ | |
44 | + if (unlikely(PageSwapCache(page))) | |
45 | + return __page_file_mapping(page); | |
46 | + | |
47 | + return page->mapping; | |
48 | +} | |
49 | + | |
50 | static inline int PageAnon(struct page *page) | |
51 | { | |
52 | return ((unsigned long)page->mapping & PAGE_MAPPING_ANON) != 0; | |
53 | @@ -674,6 +685,20 @@ static inline pgoff_t page_index(struct | |
54 | return page->index; | |
55 | } | |
56 | ||
57 | +extern pgoff_t __page_file_index(struct page *page); | |
58 | + | |
59 | +/* | |
60 | + * Return the file index of the page. Regular pagecache pages use ->index | |
61 | + * whereas swapcache pages use swp_offset(->private) | |
62 | + */ | |
63 | +static inline pgoff_t page_file_index(struct page *page) | |
64 | +{ | |
65 | + if (unlikely(PageSwapCache(page))) | |
66 | + return __page_file_index(page); | |
67 | + | |
68 | + return page->index; | |
69 | +} | |
70 | + | |
71 | /* | |
72 | * The atomic page->_mapcount, like _count, starts from -1: | |
73 | * so that transitions both from it and to it can be tracked, | |
74 | --- a/include/linux/pagemap.h | |
75 | +++ b/include/linux/pagemap.h | |
76 | @@ -259,6 +259,11 @@ static inline loff_t page_offset(struct | |
77 | return ((loff_t)page->index) << PAGE_CACHE_SHIFT; | |
78 | } | |
79 | ||
80 | +static inline loff_t page_file_offset(struct page *page) | |
81 | +{ | |
82 | + return ((loff_t)page_file_index(page)) << PAGE_CACHE_SHIFT; | |
83 | +} | |
84 | + | |
85 | static inline pgoff_t linear_page_index(struct vm_area_struct *vma, | |
86 | unsigned long address) | |
87 | { | |
88 | --- a/mm/swapfile.c | |
89 | +++ b/mm/swapfile.c | |
90 | @@ -1856,6 +1856,25 @@ struct swap_info_struct *page_swap_info( | |
91 | } | |
92 | ||
93 | /* | |
94 | + * out-of-line __page_file_ methods to avoid include hell. | |
95 | + */ | |
96 | + | |
97 | +struct address_space *__page_file_mapping(struct page *page) | |
98 | +{ | |
99 | + VM_BUG_ON(!PageSwapCache(page)); | |
100 | + return page_swap_info(page)->swap_file->f_mapping; | |
101 | +} | |
102 | +EXPORT_SYMBOL_GPL(__page_file_mapping); | |
103 | + | |
104 | +pgoff_t __page_file_index(struct page *page) | |
105 | +{ | |
106 | + swp_entry_t swap = { .val = page_private(page) }; | |
107 | + VM_BUG_ON(!PageSwapCache(page)); | |
108 | + return swp_offset(swap); | |
109 | +} | |
110 | +EXPORT_SYMBOL_GPL(__page_file_index); | |
111 | + | |
112 | +/* | |
113 | * swap_lock prevents swap_map being freed. Don't grab an extra | |
114 | * reference on the swaphandle, it doesn't matter if it becomes unused. | |
115 | */ |