diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 1afd67def3c1..fa54b36c8aeb 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -367,7 +367,7 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma) } start = vma->vm_start; - end = vma->vm_end; + end = VMA_PAD_START(vma); show_vma_header_prefix(m, start, end, flags, pgoff, dev, ino); /* @@ -420,13 +420,12 @@ done: static int show_map(struct seq_file *m, void *v) { - struct vm_area_struct *pad_vma = get_pad_vma(v); - struct vm_area_struct *vma = get_data_vma(v); + struct vm_area_struct *vma = v; if (vma_pages(vma)) show_map_vma(m, vma); - show_map_pad_vma(vma, pad_vma, m, show_map_vma, false); + show_map_pad_vma(vma, m, show_map_vma, false); m_cache_vma(m, v); return 0; @@ -813,6 +812,8 @@ static const struct mm_walk_ops smaps_shmem_walk_ops = { static void smap_gather_stats(struct vm_area_struct *vma, struct mem_size_stats *mss) { + unsigned long end = VMA_PAD_START(vma); + #ifdef CONFIG_SHMEM /* In case of smaps_rollup, reset the value from previous vma */ mss->check_shmem_swap = false; @@ -829,18 +830,27 @@ static void smap_gather_stats(struct vm_area_struct *vma, */ unsigned long shmem_swapped = shmem_swap_usage(vma); - if (!shmem_swapped || (vma->vm_flags & VM_SHARED) || - !(vma->vm_flags & VM_WRITE)) { + if ((!shmem_swapped || (vma->vm_flags & VM_SHARED) || + !(vma->vm_flags & VM_WRITE)) && + /* + * Only if we don't have padding can we use the fast path + * shmem_inode_info->swapped for shmem_swapped. + * + * Else we'll walk the page table to calculate + * shmem_swapped, (excluding the padding region). + */ + end == vma->vm_end) { mss->swap += shmem_swapped; } else { mss->check_shmem_swap = true; - walk_page_vma(vma, &smaps_shmem_walk_ops, mss); + walk_page_range(vma->vm_mm, vma->vm_start, end, + &smaps_shmem_walk_ops, mss); return; } } #endif /* mmap_sem is held in m_start */ - walk_page_vma(vma, &smaps_walk_ops, mss); + walk_page_range(vma->vm_mm, vma->vm_start, end, &smaps_walk_ops, mss); } #define SEQ_PUT_DEC(str, val) \ @@ -901,7 +911,7 @@ static void show_smap_vma(struct seq_file *m, void *v) seq_putc(m, '\n'); } - SEQ_PUT_DEC("Size: ", vma->vm_end - vma->vm_start); + SEQ_PUT_DEC("Size: ", VMA_PAD_START(vma) - vma->vm_start); SEQ_PUT_DEC(" kB\nKernelPageSize: ", vma_kernel_pagesize(vma)); SEQ_PUT_DEC(" kB\nMMUPageSize: ", vma_mmu_pagesize(vma)); seq_puts(m, " kB\n"); @@ -918,13 +928,12 @@ static void show_smap_vma(struct seq_file *m, void *v) static int show_smap(struct seq_file *m, void *v) { - struct vm_area_struct *pad_vma = get_pad_vma(v); - struct vm_area_struct *vma = get_data_vma(v); + struct vm_area_struct *vma = v; if (vma_pages(vma)) show_smap_vma(m, vma); - show_map_pad_vma(vma, pad_vma, m, show_smap_vma, true); + show_map_pad_vma(vma, m, show_smap_vma, true); m_cache_vma(m, v); return 0; diff --git a/include/linux/pgsize_migration.h b/include/linux/pgsize_migration.h index 48672dbc84e9..359c1807ff1d 100644 --- a/include/linux/pgsize_migration.h +++ b/include/linux/pgsize_migration.h @@ -26,12 +26,7 @@ extern unsigned long vma_pad_pages(struct vm_area_struct *vma); extern void madvise_vma_pad_pages(struct vm_area_struct *vma, unsigned long start, unsigned long end); -extern struct vm_area_struct *get_pad_vma(struct vm_area_struct *vma); - -extern struct vm_area_struct *get_data_vma(struct vm_area_struct *vma); - extern void show_map_pad_vma(struct vm_area_struct *vma, - struct vm_area_struct *pad, struct seq_file *m, void *func, bool smaps); extern void split_pad_vma(struct vm_area_struct *vma, struct vm_area_struct *new, @@ -57,18 +52,7 @@ static inline void madvise_vma_pad_pages(struct vm_area_struct *vma, { } -static inline struct vm_area_struct *get_pad_vma(struct vm_area_struct *vma) -{ - return NULL; -} - -static inline struct vm_area_struct *get_data_vma(struct vm_area_struct *vma) -{ - return vma; -} - static inline void show_map_pad_vma(struct vm_area_struct *vma, - struct vm_area_struct *pad, struct seq_file *m, void *func, bool smaps) { } diff --git a/mm/pgsize_migration.c b/mm/pgsize_migration.c index ad9e638ab3b6..f80a40faa605 100644 --- a/mm/pgsize_migration.c +++ b/mm/pgsize_migration.c @@ -258,10 +258,10 @@ static const struct vm_operations_struct pad_vma_ops = { }; /* - * Returns a new VMA representing the padding in @vma, if no padding - * in @vma returns NULL. + * Returns a new VMA representing the padding in @vma; + * returns NULL if no padding in @vma or allocation failed. */ -struct vm_area_struct *get_pad_vma(struct vm_area_struct *vma) +static struct vm_area_struct *get_pad_vma(struct vm_area_struct *vma) { struct vm_area_struct *pad; @@ -269,6 +269,10 @@ struct vm_area_struct *get_pad_vma(struct vm_area_struct *vma) return NULL; pad = kzalloc(sizeof(struct vm_area_struct), GFP_KERNEL); + if (!pad) { + pr_warn("Page size migration: Failed to allocate padding VMA"); + return NULL; + } *pad = *vma; @@ -290,34 +294,14 @@ struct vm_area_struct *get_pad_vma(struct vm_area_struct *vma) return pad; } -/* - * Returns a new VMA exclusing the padding from @vma; if no padding in - * @vma returns @vma. - */ -struct vm_area_struct *get_data_vma(struct vm_area_struct *vma) -{ - struct vm_area_struct *data; - - if (!is_pgsize_migration_enabled() || !(vma->vm_flags & VM_PAD_MASK)) - return vma; - - data = kzalloc(sizeof(struct vm_area_struct), GFP_KERNEL); - - *data = *vma; - - /* Adjust the end to the start of the padding section */ - data->vm_end = VMA_PAD_START(data); - - return data; -} - /* * Calls the show_pad_vma_fn on the @pad VMA, and frees the copies of @vma * and @pad. */ -void show_map_pad_vma(struct vm_area_struct *vma, struct vm_area_struct *pad, - struct seq_file *m, void *func, bool smaps) +void show_map_pad_vma(struct vm_area_struct *vma, struct seq_file *m, + void *func, bool smaps) { + struct vm_area_struct *pad = get_pad_vma(vma); if (!pad) return; @@ -333,13 +317,21 @@ void show_map_pad_vma(struct vm_area_struct *vma, struct vm_area_struct *pad, */ BUG_ON(!vma); + /* The pad VMA should be anonymous. */ + BUG_ON(pad->vm_file); + + /* The pad VMA should be PROT_NONE. */ + BUG_ON(pad->vm_flags & (VM_READ|VM_WRITE|VM_EXEC)); + + /* The pad VMA itself cannot have padding; infinite recursion */ + BUG_ON(pad->vm_flags & VM_PAD_MASK); + if (smaps) ((show_pad_smaps_fn)func)(m, pad); else ((show_pad_maps_fn)func)(m, pad); kfree(pad); - kfree(vma); } /*