Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 310546
b: refs/heads/master
c: 0142ef6
h: refs/heads/master
v: v3
  • Loading branch information
Hugh Dickins authored and Linus Torvalds committed Jun 7, 2012
1 parent d30a3ae commit fd79296
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 27 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: 513335f964a17bd99a699b939391eb111aa5f65b
refs/heads/master: 0142ef6cdca5f9784eb0762ac50fe378d98d71d4
3 changes: 1 addition & 2 deletions trunk/arch/parisc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ KBUILD_DEFCONFIG := default_defconfig

NM = sh $(srctree)/arch/parisc/nm
CHECKFLAGS += -D__hppa__=1
LIBGCC = $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)

MACHINE := $(shell uname -m)
ifeq ($(MACHINE),parisc*)
Expand Down Expand Up @@ -80,7 +79,7 @@ kernel-y := mm/ kernel/ math-emu/
kernel-$(CONFIG_HPUX) += hpux/

core-y += $(addprefix arch/parisc/, $(kernel-y))
libs-y += arch/parisc/lib/ $(LIBGCC)
libs-y += arch/parisc/lib/ `$(CC) -print-libgcc-file-name`

drivers-$(CONFIG_OPROFILE) += arch/parisc/oprofile/

Expand Down
1 change: 0 additions & 1 deletion trunk/arch/parisc/include/asm/Kbuild
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
include include/asm-generic/Kbuild.asm

header-y += pdc.h
generic-y += word-at-a-time.h
2 changes: 0 additions & 2 deletions trunk/arch/parisc/include/asm/bug.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#ifndef _PARISC_BUG_H
#define _PARISC_BUG_H

#include <linux/kernel.h> /* for BUGFLAG_TAINT */

/*
* Tell the user there is some problem.
* The offending file and line are encoded in the __bug_table section.
Expand Down
5 changes: 5 additions & 0 deletions trunk/arch/tile/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,11 @@ extern void smp_nap(void);
/* Enable interrupts racelessly and nap forever: helper for cpu_idle(). */
extern void _cpu_idle(void);

/* Switch boot idle thread to a freshly-allocated stack and free old stack. */
extern void cpu_idle_on_new_stack(struct thread_info *old_ti,
unsigned long new_sp,
unsigned long new_ss10);

#else /* __ASSEMBLY__ */

/*
Expand Down
14 changes: 14 additions & 0 deletions trunk/arch/tile/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,20 @@ STD_ENTRY(KBacktraceIterator_init_current)
jrp lr /* keep backtracer happy */
STD_ENDPROC(KBacktraceIterator_init_current)

/*
* Reset our stack to r1/r2 (sp and ksp0+cpu respectively), then
* free the old stack (passed in r0) and re-invoke cpu_idle().
* We update sp and ksp0 simultaneously to avoid backtracer warnings.
*/
STD_ENTRY(cpu_idle_on_new_stack)
{
move sp, r1
mtspr SPR_SYSTEM_SAVE_K_0, r2
}
jal free_thread_info
j cpu_idle
STD_ENDPROC(cpu_idle_on_new_stack)

/* Loop forever on a nap during SMP boot. */
STD_ENTRY(smp_nap)
nap
Expand Down
1 change: 0 additions & 1 deletion trunk/arch/tile/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
#include <linux/smp.h>
#include <linux/timex.h>
#include <linux/hugetlb.h>
#include <linux/start_kernel.h>
#include <asm/setup.h>
#include <asm/sections.h>
#include <asm/cacheflush.h>
Expand Down
57 changes: 37 additions & 20 deletions trunk/mm/shmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -683,10 +683,21 @@ static int shmem_unuse_inode(struct shmem_inode_info *info,
mutex_lock(&shmem_swaplist_mutex);
/*
* We needed to drop mutex to make that restrictive page
* allocation; but the inode might already be freed by now,
* and we cannot refer to inode or mapping or info to check.
* However, we do hold page lock on the PageSwapCache page,
* so can check if that still has our reference remaining.
* allocation, but the inode might have been freed while we
* dropped it: although a racing shmem_evict_inode() cannot
* complete without emptying the radix_tree, our page lock
* on this swapcache page is not enough to prevent that -
* free_swap_and_cache() of our swap entry will only
* trylock_page(), removing swap from radix_tree whatever.
*
* We must not proceed to shmem_add_to_page_cache() if the
* inode has been freed, but of course we cannot rely on
* inode or mapping or info to check that. However, we can
* safely check if our swap entry is still in use (and here
* it can't have got reused for another page): if it's still
* in use, then the inode cannot have been freed yet, and we
* can safely proceed (if it's no longer in use, that tells
* nothing about the inode, but we don't need to unuse swap).
*/
if (!page_swapcount(*pagep))
error = -ENOENT;
Expand Down Expand Up @@ -730,9 +741,9 @@ int shmem_unuse(swp_entry_t swap, struct page *page)

/*
* There's a faint possibility that swap page was replaced before
* caller locked it: it will come back later with the right page.
* caller locked it: caller will come back later with the right page.
*/
if (unlikely(!PageSwapCache(page)))
if (unlikely(!PageSwapCache(page) || page_private(page) != swap.val))
goto out;

/*
Expand Down Expand Up @@ -995,21 +1006,15 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp,
newpage = shmem_alloc_page(gfp, info, index);
if (!newpage)
return -ENOMEM;
VM_BUG_ON(shmem_should_replace_page(newpage, gfp));

*pagep = newpage;
page_cache_get(newpage);
copy_highpage(newpage, oldpage);
flush_dcache_page(newpage);

VM_BUG_ON(!PageLocked(oldpage));
__set_page_locked(newpage);
VM_BUG_ON(!PageUptodate(oldpage));
SetPageUptodate(newpage);
VM_BUG_ON(!PageSwapBacked(oldpage));
SetPageSwapBacked(newpage);
VM_BUG_ON(!swap_index);
set_page_private(newpage, swap_index);
VM_BUG_ON(!PageSwapCache(oldpage));
SetPageSwapCache(newpage);

/*
Expand All @@ -1019,21 +1024,32 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp,
spin_lock_irq(&swap_mapping->tree_lock);
error = shmem_radix_tree_replace(swap_mapping, swap_index, oldpage,
newpage);
__inc_zone_page_state(newpage, NR_FILE_PAGES);
__dec_zone_page_state(oldpage, NR_FILE_PAGES);
if (!error) {
__inc_zone_page_state(newpage, NR_FILE_PAGES);
__dec_zone_page_state(oldpage, NR_FILE_PAGES);
}
spin_unlock_irq(&swap_mapping->tree_lock);
BUG_ON(error);

mem_cgroup_replace_page_cache(oldpage, newpage);
lru_cache_add_anon(newpage);
if (unlikely(error)) {
/*
* Is this possible? I think not, now that our callers check
* both PageSwapCache and page_private after getting page lock;
* but be defensive. Reverse old to newpage for clear and free.
*/
oldpage = newpage;
} else {
mem_cgroup_replace_page_cache(oldpage, newpage);
lru_cache_add_anon(newpage);
*pagep = newpage;
}

ClearPageSwapCache(oldpage);
set_page_private(oldpage, 0);

unlock_page(oldpage);
page_cache_release(oldpage);
page_cache_release(oldpage);
return 0;
return error;
}

/*
Expand Down Expand Up @@ -1107,7 +1123,8 @@ static int shmem_getpage_gfp(struct inode *inode, pgoff_t index,

/* We have to do this with page locked to prevent races */
lock_page(page);
if (!PageSwapCache(page) || page->mapping) {
if (!PageSwapCache(page) || page_private(page) != swap.val ||
page->mapping) {
error = -EEXIST; /* try again */
goto failed;
}
Expand Down

0 comments on commit fd79296

Please sign in to comment.