Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 83102
b: refs/heads/master
c: 0ed361d
h: refs/heads/master
v: v3
  • Loading branch information
Nick Piggin authored and Linus Torvalds committed Feb 5, 2008
1 parent d0c338e commit fce90b5
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 14 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 62e1c55300f306e06478f460a7eefba085206e0b
refs/heads/master: 0ed361dec36945f3116ee1338638ada9a8920905
4 changes: 0 additions & 4 deletions trunk/include/linux/highmem.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,6 @@ static inline void clear_user_highpage(struct page *page, unsigned long vaddr)
void *addr = kmap_atomic(page, KM_USER0);
clear_user_page(addr, vaddr, page);
kunmap_atomic(addr, KM_USER0);
/* Make sure this page is cleared on other CPU's too before using it */
smp_wmb();
}

#ifndef __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
Expand Down Expand Up @@ -172,8 +170,6 @@ static inline void copy_user_highpage(struct page *to, struct page *from,
copy_user_page(vto, vfrom, vaddr, to);
kunmap_atomic(vfrom, KM_USER0);
kunmap_atomic(vto, KM_USER1);
/* Make sure this page is cleared on other CPU's too before using it */
smp_wmb();
}

#endif
Expand Down
42 changes: 39 additions & 3 deletions trunk/include/linux/page-flags.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,16 +131,52 @@
#define ClearPageReferenced(page) clear_bit(PG_referenced, &(page)->flags)
#define TestClearPageReferenced(page) test_and_clear_bit(PG_referenced, &(page)->flags)

#define PageUptodate(page) test_bit(PG_uptodate, &(page)->flags)
static inline int PageUptodate(struct page *page)
{
int ret = test_bit(PG_uptodate, &(page)->flags);

/*
* Must ensure that the data we read out of the page is loaded
* _after_ we've loaded page->flags to check for PageUptodate.
* We can skip the barrier if the page is not uptodate, because
* we wouldn't be reading anything from it.
*
* See SetPageUptodate() for the other side of the story.
*/
if (ret)
smp_rmb();

return ret;
}

static inline void __SetPageUptodate(struct page *page)
{
smp_wmb();
__set_bit(PG_uptodate, &(page)->flags);
#ifdef CONFIG_S390
page_clear_dirty(page);
#endif
}

static inline void SetPageUptodate(struct page *page)
{
#ifdef CONFIG_S390
if (!test_and_set_bit(PG_uptodate, &page->flags))
page_clear_dirty(page);
}
#else
#define SetPageUptodate(page) set_bit(PG_uptodate, &(page)->flags)
/*
* Memory barrier must be issued before setting the PG_uptodate bit,
* so that all previous stores issued in order to bring the page
* uptodate are actually visible before PageUptodate becomes true.
*
* s390 doesn't need an explicit smp_wmb here because the test and
* set bit already provides full barriers.
*/
smp_wmb();
set_bit(PG_uptodate, &(page)->flags);
#endif
}

#define ClearPageUptodate(page) clear_bit(PG_uptodate, &(page)->flags)

#define PageDirty(page) test_bit(PG_dirty, &(page)->flags)
Expand Down
2 changes: 2 additions & 0 deletions trunk/mm/hugetlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,7 @@ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,

spin_unlock(&mm->page_table_lock);
copy_huge_page(new_page, old_page, address, vma);
__SetPageUptodate(new_page);
spin_lock(&mm->page_table_lock);

ptep = huge_pte_offset(mm, address & HPAGE_MASK);
Expand Down Expand Up @@ -858,6 +859,7 @@ static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma,
goto out;
}
clear_huge_page(page, address);
__SetPageUptodate(page);

if (vma->vm_flags & VM_SHARED) {
int err;
Expand Down
9 changes: 5 additions & 4 deletions trunk/mm/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -1518,10 +1518,8 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo
memset(kaddr, 0, PAGE_SIZE);
kunmap_atomic(kaddr, KM_USER0);
flush_dcache_page(dst);
return;

}
copy_user_highpage(dst, src, va, vma);
} else
copy_user_highpage(dst, src, va, vma);
}

/*
Expand Down Expand Up @@ -1630,6 +1628,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
if (!new_page)
goto oom;
cow_user_page(new_page, old_page, address, vma);
__SetPageUptodate(new_page);

/*
* Re-check the pte - we dropped the lock
Expand Down Expand Up @@ -2102,6 +2101,7 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
page = alloc_zeroed_user_highpage_movable(vma, address);
if (!page)
goto oom;
__SetPageUptodate(page);

entry = mk_pte(page, vma->vm_page_prot);
entry = maybe_mkwrite(pte_mkdirty(entry), vma);
Expand Down Expand Up @@ -2202,6 +2202,7 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma,
goto out;
}
copy_user_highpage(page, vmf.page, address, vma);
__SetPageUptodate(page);
} else {
/*
* If the page will be shareable, see if the backing
Expand Down
2 changes: 1 addition & 1 deletion trunk/mm/page_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ int swap_readpage(struct file *file, struct page *page)
int ret = 0;

BUG_ON(!PageLocked(page));
ClearPageUptodate(page);
BUG_ON(PageUptodate(page));
bio = get_swap_bio(GFP_KERNEL, page_private(page), page,
end_swap_bio_read);
if (bio == NULL) {
Expand Down
2 changes: 1 addition & 1 deletion trunk/mm/swap_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ int add_to_swap(struct page * page, gfp_t gfp_mask)
int err;

BUG_ON(!PageLocked(page));
BUG_ON(!PageUptodate(page));

for (;;) {
entry = get_swap_page();
Expand All @@ -147,7 +148,6 @@ int add_to_swap(struct page * page, gfp_t gfp_mask)

switch (err) {
case 0: /* Success */
SetPageUptodate(page);
SetPageDirty(page);
return 1;
case -EEXIST:
Expand Down

0 comments on commit fce90b5

Please sign in to comment.