Skip to content

Commit bec8b6e

Browse files
committed
Merge branch 'akpm' (patches from Andrew)
Merge misc fixes from Andrew Morton: "11 fixes" MM fixes and one xz decompressor fix. * emailed patches from Andrew Morton <[email protected]>: mm/debug.c: PageAnon() is true for PageKsm() pages mm/debug.c: __dump_page() prints an extra line mm/page_io.c: do not free shared swap slots mm/memory_hotplug: fix try_offline_node() mm,thp: recheck each page before collapsing file THP mm: slub: really fix slab walking for init_on_free mm: hugetlb: switch to css_tryget() in hugetlb_cgroup_charge_cgroup() mm: memcg: switch to css_tryget() in get_mem_cgroup_from_mm() lib/xz: fix XZ_DYNALLOC to avoid useless memory reallocations mm: fix trying to reclaim unevictable lru page when calling madvise_pageout mm: mempolicy: fix the wrong return value and potential pages leak of mbind
2 parents 6c9594b + 6855ac4 commit bec8b6e

File tree

12 files changed

+133
-86
lines changed

12 files changed

+133
-86
lines changed

drivers/base/memory.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,3 +872,39 @@ int walk_memory_blocks(unsigned long start, unsigned long size,
872872
}
873873
return ret;
874874
}
875+
876+
struct for_each_memory_block_cb_data {
877+
walk_memory_blocks_func_t func;
878+
void *arg;
879+
};
880+
881+
static int for_each_memory_block_cb(struct device *dev, void *data)
882+
{
883+
struct memory_block *mem = to_memory_block(dev);
884+
struct for_each_memory_block_cb_data *cb_data = data;
885+
886+
return cb_data->func(mem, cb_data->arg);
887+
}
888+
889+
/**
890+
* for_each_memory_block - walk through all present memory blocks
891+
*
892+
* @arg: argument passed to func
893+
* @func: callback for each memory block walked
894+
*
895+
* This function walks through all present memory blocks, calling func on
896+
* each memory block.
897+
*
898+
* In case func() returns an error, walking is aborted and the error is
899+
* returned.
900+
*/
901+
int for_each_memory_block(void *arg, walk_memory_blocks_func_t func)
902+
{
903+
struct for_each_memory_block_cb_data cb_data = {
904+
.func = func,
905+
.arg = arg,
906+
};
907+
908+
return bus_for_each_dev(&memory_subsys, NULL, &cb_data,
909+
for_each_memory_block_cb);
910+
}

include/linux/memory.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ extern struct memory_block *find_memory_block(struct mem_section *);
119119
typedef int (*walk_memory_blocks_func_t)(struct memory_block *, void *);
120120
extern int walk_memory_blocks(unsigned long start, unsigned long size,
121121
void *arg, walk_memory_blocks_func_t func);
122+
extern int for_each_memory_block(void *arg, walk_memory_blocks_func_t func);
122123
#define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION<<PAGE_SHIFT)
123124
#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
124125

lib/xz/xz_dec_lzma2.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,6 +1146,7 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s, uint8_t props)
11461146

11471147
if (DEC_IS_DYNALLOC(s->dict.mode)) {
11481148
if (s->dict.allocated < s->dict.size) {
1149+
s->dict.allocated = s->dict.size;
11491150
vfree(s->dict.buf);
11501151
s->dict.buf = vmalloc(s->dict.size);
11511152
if (s->dict.buf == NULL) {

mm/debug.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -67,28 +67,31 @@ void __dump_page(struct page *page, const char *reason)
6767
*/
6868
mapcount = PageSlab(page) ? 0 : page_mapcount(page);
6969

70-
pr_warn("page:%px refcount:%d mapcount:%d mapping:%px index:%#lx",
71-
page, page_ref_count(page), mapcount,
72-
page->mapping, page_to_pgoff(page));
7370
if (PageCompound(page))
74-
pr_cont(" compound_mapcount: %d", compound_mapcount(page));
75-
pr_cont("\n");
76-
if (PageAnon(page))
77-
pr_warn("anon ");
78-
else if (PageKsm(page))
79-
pr_warn("ksm ");
71+
pr_warn("page:%px refcount:%d mapcount:%d mapping:%px "
72+
"index:%#lx compound_mapcount: %d\n",
73+
page, page_ref_count(page), mapcount,
74+
page->mapping, page_to_pgoff(page),
75+
compound_mapcount(page));
76+
else
77+
pr_warn("page:%px refcount:%d mapcount:%d mapping:%px index:%#lx\n",
78+
page, page_ref_count(page), mapcount,
79+
page->mapping, page_to_pgoff(page));
80+
if (PageKsm(page))
81+
pr_warn("ksm flags: %#lx(%pGp)\n", page->flags, &page->flags);
82+
else if (PageAnon(page))
83+
pr_warn("anon flags: %#lx(%pGp)\n", page->flags, &page->flags);
8084
else if (mapping) {
81-
pr_warn("%ps ", mapping->a_ops);
8285
if (mapping->host && mapping->host->i_dentry.first) {
8386
struct dentry *dentry;
8487
dentry = container_of(mapping->host->i_dentry.first, struct dentry, d_u.d_alias);
85-
pr_warn("name:\"%pd\" ", dentry);
86-
}
88+
pr_warn("%ps name:\"%pd\"\n", mapping->a_ops, dentry);
89+
} else
90+
pr_warn("%ps\n", mapping->a_ops);
91+
pr_warn("flags: %#lx(%pGp)\n", page->flags, &page->flags);
8792
}
8893
BUILD_BUG_ON(ARRAY_SIZE(pageflag_names) != __NR_PAGEFLAGS + 1);
8994

90-
pr_warn("flags: %#lx(%pGp)\n", page->flags, &page->flags);
91-
9295
hex_only:
9396
print_hex_dump(KERN_WARNING, "raw: ", DUMP_PREFIX_NONE, 32,
9497
sizeof(unsigned long), page,

mm/hugetlb_cgroup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ int hugetlb_cgroup_charge_cgroup(int idx, unsigned long nr_pages,
196196
again:
197197
rcu_read_lock();
198198
h_cg = hugetlb_cgroup_from_task(current);
199-
if (!css_tryget_online(&h_cg->css)) {
199+
if (!css_tryget(&h_cg->css)) {
200200
rcu_read_unlock();
201201
goto again;
202202
}

mm/khugepaged.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,17 +1602,6 @@ static void collapse_file(struct mm_struct *mm,
16021602
result = SCAN_FAIL;
16031603
goto xa_unlocked;
16041604
}
1605-
} else if (!PageUptodate(page)) {
1606-
xas_unlock_irq(&xas);
1607-
wait_on_page_locked(page);
1608-
if (!trylock_page(page)) {
1609-
result = SCAN_PAGE_LOCK;
1610-
goto xa_unlocked;
1611-
}
1612-
get_page(page);
1613-
} else if (PageDirty(page)) {
1614-
result = SCAN_FAIL;
1615-
goto xa_locked;
16161605
} else if (trylock_page(page)) {
16171606
get_page(page);
16181607
xas_unlock_irq(&xas);
@@ -1627,7 +1616,12 @@ static void collapse_file(struct mm_struct *mm,
16271616
* without racing with truncate.
16281617
*/
16291618
VM_BUG_ON_PAGE(!PageLocked(page), page);
1630-
VM_BUG_ON_PAGE(!PageUptodate(page), page);
1619+
1620+
/* make sure the page is up to date */
1621+
if (unlikely(!PageUptodate(page))) {
1622+
result = SCAN_FAIL;
1623+
goto out_unlock;
1624+
}
16311625

16321626
/*
16331627
* If file was truncated then extended, or hole-punched, before
@@ -1643,6 +1637,16 @@ static void collapse_file(struct mm_struct *mm,
16431637
goto out_unlock;
16441638
}
16451639

1640+
if (!is_shmem && PageDirty(page)) {
1641+
/*
1642+
* khugepaged only works on read-only fd, so this
1643+
* page is dirty because it hasn't been flushed
1644+
* since first write.
1645+
*/
1646+
result = SCAN_FAIL;
1647+
goto out_unlock;
1648+
}
1649+
16461650
if (isolate_lru_page(page)) {
16471651
result = SCAN_DEL_PAGE_LRU;
16481652
goto out_unlock;

mm/madvise.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,12 @@ static int madvise_cold_or_pageout_pte_range(pmd_t *pmd,
363363
ClearPageReferenced(page);
364364
test_and_clear_page_young(page);
365365
if (pageout) {
366-
if (!isolate_lru_page(page))
367-
list_add(&page->lru, &page_list);
366+
if (!isolate_lru_page(page)) {
367+
if (PageUnevictable(page))
368+
putback_lru_page(page);
369+
else
370+
list_add(&page->lru, &page_list);
371+
}
368372
} else
369373
deactivate_page(page);
370374
huge_unlock:
@@ -441,8 +445,12 @@ static int madvise_cold_or_pageout_pte_range(pmd_t *pmd,
441445
ClearPageReferenced(page);
442446
test_and_clear_page_young(page);
443447
if (pageout) {
444-
if (!isolate_lru_page(page))
445-
list_add(&page->lru, &page_list);
448+
if (!isolate_lru_page(page)) {
449+
if (PageUnevictable(page))
450+
putback_lru_page(page);
451+
else
452+
list_add(&page->lru, &page_list);
453+
}
446454
} else
447455
deactivate_page(page);
448456
}

mm/memcontrol.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -960,7 +960,7 @@ struct mem_cgroup *get_mem_cgroup_from_mm(struct mm_struct *mm)
960960
if (unlikely(!memcg))
961961
memcg = root_mem_cgroup;
962962
}
963-
} while (!css_tryget_online(&memcg->css));
963+
} while (!css_tryget(&memcg->css));
964964
rcu_read_unlock();
965965
return memcg;
966966
}

mm/memory_hotplug.c

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,6 +1646,18 @@ static int check_cpu_on_node(pg_data_t *pgdat)
16461646
return 0;
16471647
}
16481648

1649+
static int check_no_memblock_for_node_cb(struct memory_block *mem, void *arg)
1650+
{
1651+
int nid = *(int *)arg;
1652+
1653+
/*
1654+
* If a memory block belongs to multiple nodes, the stored nid is not
1655+
* reliable. However, such blocks are always online (e.g., cannot get
1656+
* offlined) and, therefore, are still spanned by the node.
1657+
*/
1658+
return mem->nid == nid ? -EEXIST : 0;
1659+
}
1660+
16491661
/**
16501662
* try_offline_node
16511663
* @nid: the node ID
@@ -1658,25 +1670,24 @@ static int check_cpu_on_node(pg_data_t *pgdat)
16581670
void try_offline_node(int nid)
16591671
{
16601672
pg_data_t *pgdat = NODE_DATA(nid);
1661-
unsigned long start_pfn = pgdat->node_start_pfn;
1662-
unsigned long end_pfn = start_pfn + pgdat->node_spanned_pages;
1663-
unsigned long pfn;
1664-
1665-
for (pfn = start_pfn; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
1666-
unsigned long section_nr = pfn_to_section_nr(pfn);
1667-
1668-
if (!present_section_nr(section_nr))
1669-
continue;
1673+
int rc;
16701674

1671-
if (pfn_to_nid(pfn) != nid)
1672-
continue;
1675+
/*
1676+
* If the node still spans pages (especially ZONE_DEVICE), don't
1677+
* offline it. A node spans memory after move_pfn_range_to_zone(),
1678+
* e.g., after the memory block was onlined.
1679+
*/
1680+
if (pgdat->node_spanned_pages)
1681+
return;
16731682

1674-
/*
1675-
* some memory sections of this node are not removed, and we
1676-
* can't offline node now.
1677-
*/
1683+
/*
1684+
* Especially offline memory blocks might not be spanned by the
1685+
* node. They will get spanned by the node once they get onlined.
1686+
* However, they link to the node in sysfs and can get onlined later.
1687+
*/
1688+
rc = for_each_memory_block(&nid, check_no_memblock_for_node_cb);
1689+
if (rc)
16781690
return;
1679-
}
16801691

16811692
if (check_cpu_on_node(pgdat))
16821693
return;

mm/mempolicy.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,9 @@ static const struct mm_walk_ops queue_pages_walk_ops = {
672672
* 1 - there is unmovable page, but MPOL_MF_MOVE* & MPOL_MF_STRICT were
673673
* specified.
674674
* 0 - queue pages successfully or no misplaced page.
675-
* -EIO - there is misplaced page and only MPOL_MF_STRICT was specified.
675+
* errno - i.e. misplaced pages with MPOL_MF_STRICT specified (-EIO) or
676+
* memory range specified by nodemask and maxnode points outside
677+
* your accessible address space (-EFAULT)
676678
*/
677679
static int
678680
queue_pages_range(struct mm_struct *mm, unsigned long start, unsigned long end,
@@ -1286,7 +1288,7 @@ static long do_mbind(unsigned long start, unsigned long len,
12861288
flags | MPOL_MF_INVERT, &pagelist);
12871289

12881290
if (ret < 0) {
1289-
err = -EIO;
1291+
err = ret;
12901292
goto up_out;
12911293
}
12921294

@@ -1305,10 +1307,12 @@ static long do_mbind(unsigned long start, unsigned long len,
13051307

13061308
if ((ret > 0) || (nr_failed && (flags & MPOL_MF_STRICT)))
13071309
err = -EIO;
1308-
} else
1309-
putback_movable_pages(&pagelist);
1310-
1310+
} else {
13111311
up_out:
1312+
if (!list_empty(&pagelist))
1313+
putback_movable_pages(&pagelist);
1314+
}
1315+
13121316
up_write(&mm->mmap_sem);
13131317
mpol_out:
13141318
mpol_put(new);

0 commit comments

Comments
 (0)