Merge branch 'akpm' (Andrew's incoming - part two)
Says Andrew: "60 patches. That's good enough for -rc1 I guess. I have quite a lot of detritus to be rechecked, work through maintainers, etc. - most of the remains of MM - rtc - various misc - cgroups - memcg - cpusets - procfs - ipc - rapidio - sysctl - pps - w1 - drivers/misc - aio" * akpm: (60 commits) memcg: replace ss->id_lock with a rwlock aio: allocate kiocbs in batches drivers/misc/vmw_balloon.c: fix typo in code comment drivers/misc/vmw_balloon.c: determine page allocation flag can_sleep outside loop w1: disable irqs in critical section drivers/w1/w1_int.c: multiple masters used same init_name drivers/power/ds2780_battery.c: fix deadlock upon insertion and removal drivers/power/ds2780_battery.c: add a nolock function to w1 interface drivers/power/ds2780_battery.c: create central point for calling w1 interface w1: ds2760 and ds2780, use ida for id and ida_simple_get() to get it pps gpio client: add missing dependency pps: new client driver using GPIO pps: default echo function include/linux/dma-mapping.h: add dma_zalloc_coherent() sysctl: make CONFIG_SYSCTL_SYSCALL default to n sysctl: add support for poll() RapidIO: documentation update drivers/net/rionet.c: fix ethernet address macros for LE platforms RapidIO: fix potential null deref in rio_setup_device() RapidIO: add mport driver for Tsi721 bridge ...
This commit is contained in:
@@ -990,7 +990,7 @@ struct page *follow_trans_huge_pmd(struct mm_struct *mm,
|
||||
page += (addr & ~HPAGE_PMD_MASK) >> PAGE_SHIFT;
|
||||
VM_BUG_ON(!PageCompound(page));
|
||||
if (flags & FOLL_GET)
|
||||
get_page(page);
|
||||
get_page_foll(page);
|
||||
|
||||
out:
|
||||
return page;
|
||||
@@ -1202,6 +1202,7 @@ static void __split_huge_page_refcount(struct page *page)
|
||||
unsigned long head_index = page->index;
|
||||
struct zone *zone = page_zone(page);
|
||||
int zonestat;
|
||||
int tail_count = 0;
|
||||
|
||||
/* prevent PageLRU to go away from under us, and freeze lru stats */
|
||||
spin_lock_irq(&zone->lru_lock);
|
||||
@@ -1210,11 +1211,27 @@ static void __split_huge_page_refcount(struct page *page)
|
||||
for (i = 1; i < HPAGE_PMD_NR; i++) {
|
||||
struct page *page_tail = page + i;
|
||||
|
||||
/* tail_page->_count cannot change */
|
||||
atomic_sub(atomic_read(&page_tail->_count), &page->_count);
|
||||
BUG_ON(page_count(page) <= 0);
|
||||
atomic_add(page_mapcount(page) + 1, &page_tail->_count);
|
||||
BUG_ON(atomic_read(&page_tail->_count) <= 0);
|
||||
/* tail_page->_mapcount cannot change */
|
||||
BUG_ON(page_mapcount(page_tail) < 0);
|
||||
tail_count += page_mapcount(page_tail);
|
||||
/* check for overflow */
|
||||
BUG_ON(tail_count < 0);
|
||||
BUG_ON(atomic_read(&page_tail->_count) != 0);
|
||||
/*
|
||||
* tail_page->_count is zero and not changing from
|
||||
* under us. But get_page_unless_zero() may be running
|
||||
* from under us on the tail_page. If we used
|
||||
* atomic_set() below instead of atomic_add(), we
|
||||
* would then run atomic_set() concurrently with
|
||||
* get_page_unless_zero(), and atomic_set() is
|
||||
* implemented in C not using locked ops. spin_unlock
|
||||
* on x86 sometime uses locked ops because of PPro
|
||||
* errata 66, 92, so unless somebody can guarantee
|
||||
* atomic_set() here would be safe on all archs (and
|
||||
* not only on x86), it's safer to use atomic_add().
|
||||
*/
|
||||
atomic_add(page_mapcount(page) + page_mapcount(page_tail) + 1,
|
||||
&page_tail->_count);
|
||||
|
||||
/* after clearing PageTail the gup refcount can be released */
|
||||
smp_mb();
|
||||
@@ -1232,10 +1249,7 @@ static void __split_huge_page_refcount(struct page *page)
|
||||
(1L << PG_uptodate)));
|
||||
page_tail->flags |= (1L << PG_dirty);
|
||||
|
||||
/*
|
||||
* 1) clear PageTail before overwriting first_page
|
||||
* 2) clear PageTail before clearing PageHead for VM_BUG_ON
|
||||
*/
|
||||
/* clear PageTail before overwriting first_page */
|
||||
smp_wmb();
|
||||
|
||||
/*
|
||||
@@ -1252,7 +1266,6 @@ static void __split_huge_page_refcount(struct page *page)
|
||||
* status is achieved setting a reserved bit in the
|
||||
* pmd, not by clearing the present bit.
|
||||
*/
|
||||
BUG_ON(page_mapcount(page_tail));
|
||||
page_tail->_mapcount = page->_mapcount;
|
||||
|
||||
BUG_ON(page_tail->mapping);
|
||||
@@ -1269,6 +1282,8 @@ static void __split_huge_page_refcount(struct page *page)
|
||||
|
||||
lru_add_page_tail(zone, page, page_tail);
|
||||
}
|
||||
atomic_sub(tail_count, &page->_count);
|
||||
BUG_ON(atomic_read(&page->_count) <= 0);
|
||||
|
||||
__dec_zone_page_state(page, NR_ANON_TRANSPARENT_HUGEPAGES);
|
||||
__mod_zone_page_state(zone, NR_ANON_PAGES, HPAGE_PMD_NR);
|
||||
|
@@ -37,6 +37,52 @@ static inline void __put_page(struct page *page)
|
||||
atomic_dec(&page->_count);
|
||||
}
|
||||
|
||||
static inline void __get_page_tail_foll(struct page *page,
|
||||
bool get_page_head)
|
||||
{
|
||||
/*
|
||||
* If we're getting a tail page, the elevated page->_count is
|
||||
* required only in the head page and we will elevate the head
|
||||
* page->_count and tail page->_mapcount.
|
||||
*
|
||||
* We elevate page_tail->_mapcount for tail pages to force
|
||||
* page_tail->_count to be zero at all times to avoid getting
|
||||
* false positives from get_page_unless_zero() with
|
||||
* speculative page access (like in
|
||||
* page_cache_get_speculative()) on tail pages.
|
||||
*/
|
||||
VM_BUG_ON(atomic_read(&page->first_page->_count) <= 0);
|
||||
VM_BUG_ON(atomic_read(&page->_count) != 0);
|
||||
VM_BUG_ON(page_mapcount(page) < 0);
|
||||
if (get_page_head)
|
||||
atomic_inc(&page->first_page->_count);
|
||||
atomic_inc(&page->_mapcount);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is meant to be called as the FOLL_GET operation of
|
||||
* follow_page() and it must be called while holding the proper PT
|
||||
* lock while the pte (or pmd_trans_huge) is still mapping the page.
|
||||
*/
|
||||
static inline void get_page_foll(struct page *page)
|
||||
{
|
||||
if (unlikely(PageTail(page)))
|
||||
/*
|
||||
* This is safe only because
|
||||
* __split_huge_page_refcount() can't run under
|
||||
* get_page_foll() because we hold the proper PT lock.
|
||||
*/
|
||||
__get_page_tail_foll(page, true);
|
||||
else {
|
||||
/*
|
||||
* Getting a normal page or the head of a compound page
|
||||
* requires to already have an elevated page->_count.
|
||||
*/
|
||||
VM_BUG_ON(atomic_read(&page->_count) <= 0);
|
||||
atomic_inc(&page->_count);
|
||||
}
|
||||
}
|
||||
|
||||
extern unsigned long highest_memmap_pfn;
|
||||
|
||||
/*
|
||||
|
1008
mm/memcontrol.c
1008
mm/memcontrol.c
File diff suppressed because it is too large
Load Diff
@@ -1503,7 +1503,7 @@ split_fallthrough:
|
||||
}
|
||||
|
||||
if (flags & FOLL_GET)
|
||||
get_page(page);
|
||||
get_page_foll(page);
|
||||
if (flags & FOLL_TOUCH) {
|
||||
if ((flags & FOLL_WRITE) &&
|
||||
!pte_dirty(pte) && !PageDirty(page))
|
||||
|
@@ -133,10 +133,13 @@ struct page *lookup_cgroup_page(struct page_cgroup *pc)
|
||||
static void *__meminit alloc_page_cgroup(size_t size, int nid)
|
||||
{
|
||||
void *addr = NULL;
|
||||
gfp_t flags = GFP_KERNEL | __GFP_NOWARN;
|
||||
|
||||
addr = alloc_pages_exact_nid(nid, size, GFP_KERNEL | __GFP_NOWARN);
|
||||
if (addr)
|
||||
addr = alloc_pages_exact_nid(nid, size, flags);
|
||||
if (addr) {
|
||||
kmemleak_alloc(addr, size, 1, flags);
|
||||
return addr;
|
||||
}
|
||||
|
||||
if (node_state(nid, N_HIGH_MEMORY))
|
||||
addr = vmalloc_node(size, nid);
|
||||
@@ -357,7 +360,7 @@ struct swap_cgroup_ctrl {
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
struct swap_cgroup_ctrl swap_cgroup_ctrl[MAX_SWAPFILES];
|
||||
static struct swap_cgroup_ctrl swap_cgroup_ctrl[MAX_SWAPFILES];
|
||||
|
||||
struct swap_cgroup {
|
||||
unsigned short id;
|
||||
|
83
mm/swap.c
83
mm/swap.c
@@ -78,39 +78,22 @@ static void put_compound_page(struct page *page)
|
||||
{
|
||||
if (unlikely(PageTail(page))) {
|
||||
/* __split_huge_page_refcount can run under us */
|
||||
struct page *page_head = page->first_page;
|
||||
smp_rmb();
|
||||
/*
|
||||
* If PageTail is still set after smp_rmb() we can be sure
|
||||
* that the page->first_page we read wasn't a dangling pointer.
|
||||
* See __split_huge_page_refcount() smp_wmb().
|
||||
*/
|
||||
if (likely(PageTail(page) && get_page_unless_zero(page_head))) {
|
||||
struct page *page_head = compound_trans_head(page);
|
||||
|
||||
if (likely(page != page_head &&
|
||||
get_page_unless_zero(page_head))) {
|
||||
unsigned long flags;
|
||||
/*
|
||||
* Verify that our page_head wasn't converted
|
||||
* to a a regular page before we got a
|
||||
* reference on it.
|
||||
* page_head wasn't a dangling pointer but it
|
||||
* may not be a head page anymore by the time
|
||||
* we obtain the lock. That is ok as long as it
|
||||
* can't be freed from under us.
|
||||
*/
|
||||
if (unlikely(!PageHead(page_head))) {
|
||||
/* PageHead is cleared after PageTail */
|
||||
smp_rmb();
|
||||
VM_BUG_ON(PageTail(page));
|
||||
goto out_put_head;
|
||||
}
|
||||
/*
|
||||
* Only run compound_lock on a valid PageHead,
|
||||
* after having it pinned with
|
||||
* get_page_unless_zero() above.
|
||||
*/
|
||||
smp_mb();
|
||||
/* page_head wasn't a dangling pointer */
|
||||
flags = compound_lock_irqsave(page_head);
|
||||
if (unlikely(!PageTail(page))) {
|
||||
/* __split_huge_page_refcount run before us */
|
||||
compound_unlock_irqrestore(page_head, flags);
|
||||
VM_BUG_ON(PageHead(page_head));
|
||||
out_put_head:
|
||||
if (put_page_testzero(page_head))
|
||||
__put_single_page(page_head);
|
||||
out_put_single:
|
||||
@@ -121,16 +104,17 @@ static void put_compound_page(struct page *page)
|
||||
VM_BUG_ON(page_head != page->first_page);
|
||||
/*
|
||||
* We can release the refcount taken by
|
||||
* get_page_unless_zero now that
|
||||
* split_huge_page_refcount is blocked on the
|
||||
* compound_lock.
|
||||
* get_page_unless_zero() now that
|
||||
* __split_huge_page_refcount() is blocked on
|
||||
* the compound_lock.
|
||||
*/
|
||||
if (put_page_testzero(page_head))
|
||||
VM_BUG_ON(1);
|
||||
/* __split_huge_page_refcount will wait now */
|
||||
VM_BUG_ON(atomic_read(&page->_count) <= 0);
|
||||
atomic_dec(&page->_count);
|
||||
VM_BUG_ON(page_mapcount(page) <= 0);
|
||||
atomic_dec(&page->_mapcount);
|
||||
VM_BUG_ON(atomic_read(&page_head->_count) <= 0);
|
||||
VM_BUG_ON(atomic_read(&page->_count) != 0);
|
||||
compound_unlock_irqrestore(page_head, flags);
|
||||
if (put_page_testzero(page_head)) {
|
||||
if (PageHead(page_head))
|
||||
@@ -160,6 +144,45 @@ void put_page(struct page *page)
|
||||
}
|
||||
EXPORT_SYMBOL(put_page);
|
||||
|
||||
/*
|
||||
* This function is exported but must not be called by anything other
|
||||
* than get_page(). It implements the slow path of get_page().
|
||||
*/
|
||||
bool __get_page_tail(struct page *page)
|
||||
{
|
||||
/*
|
||||
* This takes care of get_page() if run on a tail page
|
||||
* returned by one of the get_user_pages/follow_page variants.
|
||||
* get_user_pages/follow_page itself doesn't need the compound
|
||||
* lock because it runs __get_page_tail_foll() under the
|
||||
* proper PT lock that already serializes against
|
||||
* split_huge_page().
|
||||
*/
|
||||
unsigned long flags;
|
||||
bool got = false;
|
||||
struct page *page_head = compound_trans_head(page);
|
||||
|
||||
if (likely(page != page_head && get_page_unless_zero(page_head))) {
|
||||
/*
|
||||
* page_head wasn't a dangling pointer but it
|
||||
* may not be a head page anymore by the time
|
||||
* we obtain the lock. That is ok as long as it
|
||||
* can't be freed from under us.
|
||||
*/
|
||||
flags = compound_lock_irqsave(page_head);
|
||||
/* here __split_huge_page_refcount won't run anymore */
|
||||
if (likely(PageTail(page))) {
|
||||
__get_page_tail_foll(page, false);
|
||||
got = true;
|
||||
}
|
||||
compound_unlock_irqrestore(page_head, flags);
|
||||
if (unlikely(!got))
|
||||
put_page(page_head);
|
||||
}
|
||||
return got;
|
||||
}
|
||||
EXPORT_SYMBOL(__get_page_tail);
|
||||
|
||||
/**
|
||||
* put_pages_list() - release a list of pages
|
||||
* @pages: list of pages threaded on page->lru
|
||||
|
@@ -1767,7 +1767,7 @@ static int inactive_anon_is_low(struct zone *zone, struct scan_control *sc)
|
||||
if (scanning_global_lru(sc))
|
||||
low = inactive_anon_is_low_global(zone);
|
||||
else
|
||||
low = mem_cgroup_inactive_anon_is_low(sc->mem_cgroup);
|
||||
low = mem_cgroup_inactive_anon_is_low(sc->mem_cgroup, zone);
|
||||
return low;
|
||||
}
|
||||
#else
|
||||
@@ -1810,7 +1810,7 @@ static int inactive_file_is_low(struct zone *zone, struct scan_control *sc)
|
||||
if (scanning_global_lru(sc))
|
||||
low = inactive_file_is_low_global(zone);
|
||||
else
|
||||
low = mem_cgroup_inactive_file_is_low(sc->mem_cgroup);
|
||||
low = mem_cgroup_inactive_file_is_low(sc->mem_cgroup, zone);
|
||||
return low;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user