summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2004-04-17 20:54:52 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-04-17 20:54:52 -0700
commitc4d92e6b147b133848e8d89a734efdd2c3302d14 (patch)
treee314afe99ab66b3ddc53f08d02ad4ff096e4e3dd /include
parent1896ae13fb37ccbd62aab739b4ee6ff2be9e21d9 (diff)
[PATCH] rmap: flush_dcache revisited
From: Hugh Dickins <hugh@veritas.com> One of the callers of flush_dcache_page is do_generic_mapping_read, where file is read without i_sem and without page lock: concurrent truncation may at any moment remove page from cache, NULLing ->mapping, making flush_dcache_page liable to oops. Put result of page_mapping in a local variable and apply mapping_mapped to that (if we were to check for NULL within mapping_mapped, it's unclear whether to say yes or no). parisc and arm do have other locking unsafety in their i_mmap(_shared) searching, but that's a larger issue to be dealt with down the line.
Diffstat (limited to 'include')
-rw-r--r--include/asm-arm/cacheflush.h4
-rw-r--r--include/asm-parisc/cacheflush.h4
-rw-r--r--include/asm-sh/pgalloc.h7
3 files changed, 9 insertions, 6 deletions
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
index 9a950ec8de4d..0e053301c09f 100644
--- a/include/asm-arm/cacheflush.h
+++ b/include/asm-arm/cacheflush.h
@@ -295,7 +295,9 @@ extern void __flush_dcache_page(struct page *);
static inline void flush_dcache_page(struct page *page)
{
- if (page_mapping(page) && !mapping_mapped(page->mapping))
+ struct address_space *mapping = page_mapping(page);
+
+ if (mapping && !mapping_mapped(mapping))
set_bit(PG_dcache_dirty, &page->flags);
else
__flush_dcache_page(page);
diff --git a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h
index 7a77986e3738..224b3e6a5dd7 100644
--- a/include/asm-parisc/cacheflush.h
+++ b/include/asm-parisc/cacheflush.h
@@ -69,7 +69,9 @@ extern void __flush_dcache_page(struct page *page);
static inline void flush_dcache_page(struct page *page)
{
- if (page_mapping(page) && !mapping_mapped(page->mapping)) {
+ struct address_space *mapping = page_mapping(page);
+
+ if (mapping && !mapping_mapped(mapping)) {
set_bit(PG_dcache_dirty, &page->flags);
} else {
__flush_dcache_page(page);
diff --git a/include/asm-sh/pgalloc.h b/include/asm-sh/pgalloc.h
index 4584c9e37a75..9b7038442cd6 100644
--- a/include/asm-sh/pgalloc.h
+++ b/include/asm-sh/pgalloc.h
@@ -97,12 +97,11 @@ static inline pte_t ptep_get_and_clear(pte_t *ptep)
pte_clear(ptep);
if (!pte_not_present(pte)) {
- struct page *page;
unsigned long pfn = pte_pfn(pte);
if (pfn_valid(pfn)) {
- page = pfn_to_page(pfn);
- if (!page_mapping(page) ||
- !mapping_writably_mapped(page->mapping))
+ struct page *page = pfn_to_page(pfn);
+ struct address_space *mapping = page_mapping(page);
+ if (!mapping || !mapping_writably_mapped(mapping))
__clear_bit(PG_mapped, &page->flags);
}
}