Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1332080 > unrolled thread
| Started by | "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> |
|---|---|
| First post | 2016-02-11 15:40 +0100 |
| Last post | 2016-02-11 15:40 +0100 |
| Articles | 5 — 2 participants |
Back to article view | Back to linux.kernel
[PATCHv2 00/28] huge tmpfs implementation using compound pages "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2016-02-11 15:40 +0100
[PATCHv2 02/28] rmap: introduce rmap_walk_locked() "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2016-02-11 15:40 +0100
Re: [PATCHv2 02/28] rmap: introduce rmap_walk_locked() Andi Kleen <andi@firstfloor.org> - 2016-02-11 20:00 +0100
Re: [PATCHv2 02/28] rmap: introduce rmap_walk_locked() "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2016-02-16 10:40 +0100
[PATCHv2 11/28] mm, rmap: account file thp pages "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2016-02-11 15:40 +0100
| From | "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> |
|---|---|
| Date | 2016-02-11 15:40 +0100 |
| Subject | [PATCHv2 00/28] huge tmpfs implementation using compound pages |
| Message-ID | <r10pQ-1zg-3@gated-at.bofh.it> |
Here is my implementation of huge pages support in tmpfs/shmem. It's more or less complete. I'm comfortable enough with this to run my workstation. And it hasn't crashed so far. :) The main difference with Hugh's approach[1] is that I continue with compound pages, where Hugh invents new way couple pages: team pages. I believe THP refcounting rework made team pages unnecessary: compound page are flexible enough to serve needs of page cache. Many ideas and some patches were stolen from Hugh's patchset. Having this patchset around was very helpful. I will continue with code validation. I would expect mlock require some more attention. Please, review and test the code. Git tree: git://git.kernel.org/pub/scm/linux/kernel/git/kas/linux.git hugetmpfs/v2 == Patchset overview == [01/28] I've posted the patch last night. I stepped on the bug during my testing of huge tmpfs, but I think DAX has the same problem, so it should be applied now. [02-05/28] These patches also where posted separately. They simplify split_huge_page() code with speed trade off. I'm not sure if they should go upstream, but they make my life easier for now. Patches were slightly adjust to handle file pages too. [06-11/28] Rework fault path and rmap to handle file pmd. Unlike DAX with vm_ops->pmd_fault, we don't need to ask filesystem twice -- first for huge page and then for small. If ->fault happend to return huge page and VMA is suitable for mapping it as huge, we would do so. [12-20/28] Various preparation of THP core for file pages. [21-25/28] Various preparation of MM core for file pages. [26-28/28] And finally, bring huge pages into tmpfs/shmem. Two of three patches came from Hugh's patchset. :) [1] http://lkml.kernel.org/g/alpine.LSU.2.11.1502201941340.14414@eggly.anvils Hugh Dickins (2): shmem: prepare huge=N mount option and /proc/sys/vm/shmem_huge shmem: get_unmapped_area align huge page Kirill A. Shutemov (26): thp, dax: do not try to withdraw pgtable from non-anon VMA rmap: introduce rmap_walk_locked() rmap: extend try_to_unmap() to be usable by split_huge_page() mm: make remove_migration_ptes() beyond mm/migration.c thp: rewrite freeze_page()/unfreeze_page() with generic rmap walkers mm: do not pass mm_struct into handle_mm_fault mm: introduce fault_env mm: postpone page table allocation until do_set_pte() rmap: support file thp mm: introduce do_set_pmd() mm, rmap: account file thp pages thp, vmstats: add counters for huge file pages thp: support file pages in zap_huge_pmd() thp: handle file pages in split_huge_pmd() thp: handle file COW faults thp: handle file pages in mremap() thp: skip file huge pmd on copy_huge_pmd() thp: prepare change_huge_pmd() for file thp thp: run vma_adjust_trans_huge() outside i_mmap_rwsem thp: file pages support for split_huge_page() vmscan: split file huge pages before paging them out page-flags: relax policy for PG_mappedtodisk and PG_reclaim radix-tree: implement radix_tree_maybe_preload_order() filemap: prepare find and delete operations for huge pages truncate: handle file thp shmem: add huge pages support Documentation/filesystems/Locking | 10 +- arch/alpha/mm/fault.c | 2 +- arch/arc/mm/fault.c | 2 +- arch/arm/mm/fault.c | 2 +- arch/arm64/mm/fault.c | 2 +- arch/avr32/mm/fault.c | 2 +- arch/cris/mm/fault.c | 2 +- arch/frv/mm/fault.c | 2 +- arch/hexagon/mm/vm_fault.c | 2 +- arch/ia64/mm/fault.c | 2 +- arch/m32r/mm/fault.c | 2 +- arch/m68k/mm/fault.c | 2 +- arch/metag/mm/fault.c | 2 +- arch/microblaze/mm/fault.c | 2 +- arch/mips/mm/fault.c | 2 +- arch/mn10300/mm/fault.c | 2 +- arch/nios2/mm/fault.c | 2 +- arch/openrisc/mm/fault.c | 2 +- arch/parisc/mm/fault.c | 2 +- arch/powerpc/mm/copro_fault.c | 2 +- arch/powerpc/mm/fault.c | 2 +- arch/s390/mm/fault.c | 2 +- arch/score/mm/fault.c | 2 +- arch/sh/mm/fault.c | 2 +- arch/sparc/mm/fault_32.c | 4 +- arch/sparc/mm/fault_64.c | 2 +- arch/tile/mm/fault.c | 2 +- arch/um/kernel/trap.c | 2 +- arch/unicore32/mm/fault.c | 2 +- arch/x86/mm/fault.c | 2 +- arch/xtensa/mm/fault.c | 2 +- drivers/base/node.c | 10 +- drivers/char/mem.c | 24 ++ drivers/iommu/amd_iommu_v2.c | 2 +- drivers/iommu/intel-svm.c | 2 +- fs/proc/meminfo.c | 5 +- fs/userfaultfd.c | 22 +- include/linux/huge_mm.h | 29 +- include/linux/mm.h | 33 +- include/linux/mmzone.h | 3 +- include/linux/page-flags.h | 6 +- include/linux/radix-tree.h | 1 + include/linux/rmap.h | 8 +- include/linux/shmem_fs.h | 18 +- include/linux/userfaultfd_k.h | 8 +- include/linux/vm_event_item.h | 7 + ipc/shm.c | 6 +- kernel/sysctl.c | 12 + lib/radix-tree.c | 70 +++- mm/filemap.c | 220 +++++++---- mm/gup.c | 7 +- mm/huge_memory.c | 714 ++++++++++++++-------------------- mm/internal.h | 20 +- mm/ksm.c | 3 +- mm/memory.c | 796 +++++++++++++++++++++----------------- mm/mempolicy.c | 4 +- mm/migrate.c | 17 +- mm/mmap.c | 20 +- mm/mremap.c | 22 +- mm/nommu.c | 3 +- mm/page-writeback.c | 1 + mm/rmap.c | 125 ++++-- mm/shmem.c | 493 +++++++++++++++++++---- mm/swap.c | 2 + mm/truncate.c | 22 +- mm/util.c | 6 + mm/vmscan.c | 15 +- mm/vmstat.c | 3 + 68 files changed, 1727 insertions(+), 1104 deletions(-) -- 2.7.0
[toc] | [next] | [standalone]
| From | "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> |
|---|---|
| Date | 2016-02-11 15:40 +0100 |
| Subject | [PATCHv2 02/28] rmap: introduce rmap_walk_locked() |
| Message-ID | <r10zy-1Ec-59@gated-at.bofh.it> |
| In reply to | #1332080 |
rmap_walk_locked() is the same as rmap_walk(), but caller takes care
about relevant rmap lock.
It's preparation to switch THP splitting from custom rmap walk in
freeze_page()/unfreeze_page() to generic one.
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
---
include/linux/rmap.h | 1 +
mm/rmap.c | 41 ++++++++++++++++++++++++++++++++---------
2 files changed, 33 insertions(+), 9 deletions(-)
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index a07f42bedda3..a5875e9b4a27 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -266,6 +266,7 @@ struct rmap_walk_control {
};
int rmap_walk(struct page *page, struct rmap_walk_control *rwc);
+int rmap_walk_locked(struct page *page, struct rmap_walk_control *rwc);
#else /* !CONFIG_MMU */
diff --git a/mm/rmap.c b/mm/rmap.c
index 02f0bfc3c80a..30b739ce0ffa 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1715,14 +1715,21 @@ static struct anon_vma *rmap_walk_anon_lock(struct page *page,
* vm_flags for that VMA. That should be OK, because that vma shouldn't be
* LOCKED.
*/
-static int rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc)
+static int rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc,
+ bool locked)
{
struct anon_vma *anon_vma;
pgoff_t pgoff;
struct anon_vma_chain *avc;
int ret = SWAP_AGAIN;
- anon_vma = rmap_walk_anon_lock(page, rwc);
+ if (locked) {
+ anon_vma = page_anon_vma(page);
+ /* anon_vma disappear under us? */
+ VM_BUG_ON_PAGE(!anon_vma, page);
+ } else {
+ anon_vma = rmap_walk_anon_lock(page, rwc);
+ }
if (!anon_vma)
return ret;
@@ -1742,7 +1749,9 @@ static int rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc)
if (rwc->done && rwc->done(page))
break;
}
- anon_vma_unlock_read(anon_vma);
+
+ if (!locked)
+ anon_vma_unlock_read(anon_vma);
return ret;
}
@@ -1759,9 +1768,10 @@ static int rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc)
* vm_flags for that VMA. That should be OK, because that vma shouldn't be
* LOCKED.
*/
-static int rmap_walk_file(struct page *page, struct rmap_walk_control *rwc)
+static int rmap_walk_file(struct page *page, struct rmap_walk_control *rwc,
+ bool locked)
{
- struct address_space *mapping = page->mapping;
+ struct address_space *mapping = page_mapping(page);
pgoff_t pgoff;
struct vm_area_struct *vma;
int ret = SWAP_AGAIN;
@@ -1778,7 +1788,8 @@ static int rmap_walk_file(struct page *page, struct rmap_walk_control *rwc)
return ret;
pgoff = page_to_pgoff(page);
- i_mmap_lock_read(mapping);
+ if (!locked)
+ i_mmap_lock_read(mapping);
vma_interval_tree_foreach(vma, &mapping->i_mmap, pgoff, pgoff) {
unsigned long address = vma_address(page, vma);
@@ -1795,7 +1806,8 @@ static int rmap_walk_file(struct page *page, struct rmap_walk_control *rwc)
}
done:
- i_mmap_unlock_read(mapping);
+ if (!locked)
+ i_mmap_unlock_read(mapping);
return ret;
}
@@ -1804,9 +1816,20 @@ int rmap_walk(struct page *page, struct rmap_walk_control *rwc)
if (unlikely(PageKsm(page)))
return rmap_walk_ksm(page, rwc);
else if (PageAnon(page))
- return rmap_walk_anon(page, rwc);
+ return rmap_walk_anon(page, rwc, false);
+ else
+ return rmap_walk_file(page, rwc, false);
+}
+
+/* Like rmap_walk, but caller holds relevant rmap lock */
+int rmap_walk_locked(struct page *page, struct rmap_walk_control *rwc)
+{
+ /* no ksm support for now */
+ VM_BUG_ON_PAGE(PageKsm(page), page);
+ if (PageAnon(page))
+ return rmap_walk_anon(page, rwc, true);
else
- return rmap_walk_file(page, rwc);
+ return rmap_walk_file(page, rwc, true);
}
#ifdef CONFIG_HUGETLB_PAGE
--
2.7.0
[toc] | [prev] | [next] | [standalone]
| From | Andi Kleen <andi@firstfloor.org> |
|---|---|
| Date | 2016-02-11 20:00 +0100 |
| Subject | Re: [PATCHv2 02/28] rmap: introduce rmap_walk_locked() |
| Message-ID | <r14D8-4iJ-11@gated-at.bofh.it> |
| In reply to | #1332091 |
"Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> writes: > rmap_walk_locked() is the same as rmap_walk(), but caller takes care > about relevant rmap lock. > > It's preparation to switch THP splitting from custom rmap walk in > freeze_page()/unfreeze_page() to generic one. Would be better to move all locking into the callers, with an appropiate helper for users who don't want to deal with it. Conditional locking based on flags is always tricky. -Andi -- ak@linux.intel.com -- Speaking for myself only
[toc] | [prev] | [next] | [standalone]
| From | "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> |
|---|---|
| Date | 2016-02-16 10:40 +0100 |
| Subject | Re: [PATCHv2 02/28] rmap: introduce rmap_walk_locked() |
| Message-ID | <r2KgW-611-7@gated-at.bofh.it> |
| In reply to | #1332317 |
On Thu, Feb 11, 2016 at 10:52:08AM -0800, Andi Kleen wrote: > "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> writes: > > > rmap_walk_locked() is the same as rmap_walk(), but caller takes care > > about relevant rmap lock. > > > > It's preparation to switch THP splitting from custom rmap walk in > > freeze_page()/unfreeze_page() to generic one. > > Would be better to move all locking into the callers, with an > appropiate helper for users who don't want to deal with it. > Conditional locking based on flags is always tricky. Hm. That's kinda tricky for rmap_walk_ksm().. -- Kirill A. Shutemov
[toc] | [prev] | [next] | [standalone]
| From | "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> |
|---|---|
| Date | 2016-02-11 15:40 +0100 |
| Subject | [PATCHv2 11/28] mm, rmap: account file thp pages |
| Message-ID | <r10zz-1Ec-71@gated-at.bofh.it> |
| In reply to | #1332080 |
Let's add FileHugePages field into meminfo.
NR_ANON_TRANSPARENT_HUGEPAGES is renames to NR_ANON_THPS.
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
---
drivers/base/node.c | 10 ++++++----
fs/proc/meminfo.c | 5 +++--
include/linux/mmzone.h | 3 ++-
mm/huge_memory.c | 2 +-
mm/rmap.c | 12 ++++++------
mm/vmstat.c | 1 +
6 files changed, 19 insertions(+), 14 deletions(-)
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 560751bad294..57b6c1ed0330 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -113,6 +113,7 @@ static ssize_t node_read_meminfo(struct device *dev,
"Node %d SUnreclaim: %8lu kB\n"
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
"Node %d AnonHugePages: %8lu kB\n"
+ "Node %d FileHugePages: %8lu kB\n"
#endif
,
nid, K(node_page_state(nid, NR_FILE_DIRTY)),
@@ -131,10 +132,11 @@ static ssize_t node_read_meminfo(struct device *dev,
node_page_state(nid, NR_SLAB_UNRECLAIMABLE)),
nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE)),
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
- nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE))
- , nid,
- K(node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) *
- HPAGE_PMD_NR));
+ nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE)),
+ nid, K(node_page_state(nid, NR_ANON_THPS) *
+ HPAGE_PMD_NR),
+ nid, K(node_page_state(nid, NR_FILE_THP_MAPPED) *
+ HPAGE_PMD_NR));
#else
nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE)));
#endif
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
index df4661abadc4..df07256c71a7 100644
--- a/fs/proc/meminfo.c
+++ b/fs/proc/meminfo.c
@@ -134,6 +134,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
#endif
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
"AnonHugePages: %8lu kB\n"
+ "FileHugePages: %8lu kB\n"
#endif
#ifdef CONFIG_CMA
"CmaTotal: %8lu kB\n"
@@ -191,8 +192,8 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
, atomic_long_read(&num_poisoned_pages) << (PAGE_SHIFT - 10)
#endif
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
- , K(global_page_state(NR_ANON_TRANSPARENT_HUGEPAGES) *
- HPAGE_PMD_NR)
+ , K(global_page_state(NR_ANON_THPS) * HPAGE_PMD_NR)
+ , K(global_page_state(NR_FILE_THP_MAPPED) * HPAGE_PMD_NR)
#endif
#ifdef CONFIG_CMA
, K(totalcma_pages)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 03cbdd906f55..a29a87ab05a4 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -158,7 +158,8 @@ enum zone_stat_item {
WORKINGSET_REFAULT,
WORKINGSET_ACTIVATE,
WORKINGSET_NODERECLAIM,
- NR_ANON_TRANSPARENT_HUGEPAGES,
+ NR_ANON_THPS,
+ NR_FILE_THP_MAPPED,
NR_FREE_CMA_PAGES,
NR_VM_ZONE_STAT_ITEMS };
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 9d614cee994f..732bda42ca80 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -2946,7 +2946,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd,
if (atomic_add_negative(-1, compound_mapcount_ptr(page))) {
/* Last compound_mapcount is gone. */
- __dec_zone_page_state(page, NR_ANON_TRANSPARENT_HUGEPAGES);
+ __dec_zone_page_state(page, NR_ANON_THPS);
if (TestClearPageDoubleMap(page)) {
/* No need in mapcount reference anymore */
for (i = 0; i < HPAGE_PMD_NR; i++)
diff --git a/mm/rmap.c b/mm/rmap.c
index b550bf637ce3..765e001836dc 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1227,10 +1227,8 @@ void do_page_add_anon_rmap(struct page *page,
* pte lock(a spinlock) is held, which implies preemption
* disabled.
*/
- if (compound) {
- __inc_zone_page_state(page,
- NR_ANON_TRANSPARENT_HUGEPAGES);
- }
+ if (compound)
+ __inc_zone_page_state(page, NR_ANON_THPS);
__mod_zone_page_state(page_zone(page), NR_ANON_PAGES, nr);
}
if (unlikely(PageKsm(page)))
@@ -1268,7 +1266,7 @@ void page_add_new_anon_rmap(struct page *page,
VM_BUG_ON_PAGE(!PageTransHuge(page), page);
/* increment count (starts at -1) */
atomic_set(compound_mapcount_ptr(page), 0);
- __inc_zone_page_state(page, NR_ANON_TRANSPARENT_HUGEPAGES);
+ __inc_zone_page_state(page, NR_ANON_THPS);
} else {
/* Anon THP always mapped first with PMD */
VM_BUG_ON_PAGE(PageTransCompound(page), page);
@@ -1298,6 +1296,7 @@ void page_add_file_rmap(struct page *page, bool compound)
}
if (!atomic_inc_and_test(compound_mapcount_ptr(page)))
goto out;
+ __inc_zone_page_state(page, NR_FILE_THP_MAPPED);
} else {
if (!atomic_inc_and_test(&page->_mapcount))
goto out;
@@ -1330,6 +1329,7 @@ static void page_remove_file_rmap(struct page *page, bool compound)
}
if (!atomic_add_negative(-1, compound_mapcount_ptr(page)))
goto out;
+ __dec_zone_page_state(page, NR_FILE_THP_MAPPED);
} else {
if (!atomic_add_negative(-1, &page->_mapcount))
goto out;
@@ -1363,7 +1363,7 @@ static void page_remove_anon_compound_rmap(struct page *page)
if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
return;
- __dec_zone_page_state(page, NR_ANON_TRANSPARENT_HUGEPAGES);
+ __dec_zone_page_state(page, NR_ANON_THPS);
if (TestClearPageDoubleMap(page)) {
/*
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 05c6ba2534fe..801e6b18fb94 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -762,6 +762,7 @@ const char * const vmstat_text[] = {
"workingset_activate",
"workingset_nodereclaim",
"nr_anon_transparent_hugepages",
+ "nr_file_transparent_hugepages",
"nr_free_cma",
/* enum writeback_stat_item counters */
--
2.7.0
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web