aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/linux/highmem.h4
-rw-r--r--include/linux/page-flags.h42
2 files changed, 39 insertions, 7 deletions
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 61a5e5eb27f0..7dcbc82f3b7b 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -68,8 +68,6 @@ static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
68 void *addr = kmap_atomic(page, KM_USER0); 68 void *addr = kmap_atomic(page, KM_USER0);
69 clear_user_page(addr, vaddr, page); 69 clear_user_page(addr, vaddr, page);
70 kunmap_atomic(addr, KM_USER0); 70 kunmap_atomic(addr, KM_USER0);
71 /* Make sure this page is cleared on other CPU's too before using it */
72 smp_wmb();
73} 71}
74 72
75#ifndef __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE 73#ifndef __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
@@ -172,8 +170,6 @@ static inline void copy_user_highpage(struct page *to, struct page *from,
172 copy_user_page(vto, vfrom, vaddr, to); 170 copy_user_page(vto, vfrom, vaddr, to);
173 kunmap_atomic(vfrom, KM_USER0); 171 kunmap_atomic(vfrom, KM_USER0);
174 kunmap_atomic(vto, KM_USER1); 172 kunmap_atomic(vto, KM_USER1);
175 /* Make sure this page is cleared on other CPU's too before using it */
176 smp_wmb();
177} 173}
178 174
179#endif 175#endif
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 209d3a47f50f..bbad43fb8181 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -131,16 +131,52 @@
131#define ClearPageReferenced(page) clear_bit(PG_referenced, &(page)->flags) 131#define ClearPageReferenced(page) clear_bit(PG_referenced, &(page)->flags)
132#define TestClearPageReferenced(page) test_and_clear_bit(PG_referenced, &(page)->flags) 132#define TestClearPageReferenced(page) test_and_clear_bit(PG_referenced, &(page)->flags)
133 133
134#define PageUptodate(page) test_bit(PG_uptodate, &(page)->flags) 134static inline int PageUptodate(struct page *page)
135{
136 int ret = test_bit(PG_uptodate, &(page)->flags);
137
138 /*
139 * Must ensure that the data we read out of the page is loaded
140 * _after_ we've loaded page->flags to check for PageUptodate.
141 * We can skip the barrier if the page is not uptodate, because
142 * we wouldn't be reading anything from it.
143 *
144 * See SetPageUptodate() for the other side of the story.
145 */
146 if (ret)
147 smp_rmb();
148
149 return ret;
150}
151
152static inline void __SetPageUptodate(struct page *page)
153{
154 smp_wmb();
155 __set_bit(PG_uptodate, &(page)->flags);
135#ifdef CONFIG_S390 156#ifdef CONFIG_S390
157 page_clear_dirty(page);
158#endif
159}
160
136static inline void SetPageUptodate(struct page *page) 161static inline void SetPageUptodate(struct page *page)
137{ 162{
163#ifdef CONFIG_S390
138 if (!test_and_set_bit(PG_uptodate, &page->flags)) 164 if (!test_and_set_bit(PG_uptodate, &page->flags))
139 page_clear_dirty(page); 165 page_clear_dirty(page);
140}
141#else 166#else
142#define SetPageUptodate(page) set_bit(PG_uptodate, &(page)->flags) 167 /*
168 * Memory barrier must be issued before setting the PG_uptodate bit,
169 * so that all previous stores issued in order to bring the page
170 * uptodate are actually visible before PageUptodate becomes true.
171 *
172 * s390 doesn't need an explicit smp_wmb here because the test and
173 * set bit already provides full barriers.
174 */
175 smp_wmb();
176 set_bit(PG_uptodate, &(page)->flags);
143#endif 177#endif
178}
179
144#define ClearPageUptodate(page) clear_bit(PG_uptodate, &(page)->flags) 180#define ClearPageUptodate(page) clear_bit(PG_uptodate, &(page)->flags)
145 181
146#define PageDirty(page) test_bit(PG_dirty, &(page)->flags) 182#define PageDirty(page) test_bit(PG_dirty, &(page)->flags)