[PATCH 2.5.63] Teach page_mapped about the anon flag

Dave McCracken
2003-03-03T21:06:21Z

[-- Attachment #1: Type: text/plain, Size: 1177 bytes --]

--On Thursday, February 27, 2003 14:24:50 -0800 Andrew Morton
<akpm@digeo.com> wrote:

> I'm just looking at page_mapped(). It is now implicitly assuming that the
> architecture's representation of a zero-count atomic_t is all-bits-zero.
>
> This is not true on sparc32 if some other CPU is in the middle of an
> atomic_foo() against that counter. Maybe the assumption is false on other
> architectures too.
>
> So page_mapped() really should be performing an atomic_read() if that is
> appropriate to the particular page. I guess this involves testing
> page->mapping. Which is stable only when the page is locked or
> mapping->page_lock is held.
>
> It appears that all page_mapped() callers are inside lock_page() at
> present, so a quick audit and addition of a comment would be appropriate
> there please.

I'm not at all confident that page_mapped() is adequately protected.
Here's a patch that explicitly handles the atomic_t case.

Dave McCracken

======================================================================
Dave McCracken IBM Linux Base Kernel Team 1-512-838-3059
dmccr@us.ibm.com T/L 678-3059

[-- Attachment #2: objfix-2.5.63-1.diff --]
[-- Type: text/plain, Size: 738 bytes --]

--- 2.5.63-objrmap/include/linux/mm.h 2003-02-27 15:58:34.000000000 -0600
+++ 2.5.63-objfix/include/linux/mm.h 2003-02-28 14:21:56.000000000 -0600
@@ -363,10 +363,16 @@
* Return true if this page is mapped into pagetables. Subtle: test pte.direct
* rather than pte.chain. Because sometimes pte.direct is 64-bit, and .chain
* is only 32-bit.
+ *
+ * If the page is an object-mapped page, we need to do an atomic read of
+ * pte.mapcount instead, since atomic values may not be zero in the upper bits.
*/
static inline int page_mapped(struct page *page)
{
- return page->pte.direct != 0;
+ if (PageAnon(page))
+ return page->pte.direct != 0;
+ else
+ return atomic_read(&page->pte.mapcount) != 0;
}

/*