diff options
Diffstat (limited to 'fs/proc/task_mmu.c')
| -rw-r--r-- | fs/proc/task_mmu.c | 319 | 
1 files changed, 139 insertions, 180 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index dfd73a4616ce..5ea1d64cb0b4 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -247,7 +247,6 @@ static int proc_map_release(struct inode *inode, struct file *file)  	if (priv->mm)  		mmdrop(priv->mm); -	kfree(priv->rollup);  	return seq_release_private(inode, file);  } @@ -294,7 +293,7 @@ static void show_vma_header_prefix(struct seq_file *m,  }  static void -show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) +show_map_vma(struct seq_file *m, struct vm_area_struct *vma)  {  	struct mm_struct *mm = vma->vm_mm;  	struct file *file = vma->vm_file; @@ -357,35 +356,18 @@ done:  	seq_putc(m, '\n');  } -static int show_map(struct seq_file *m, void *v, int is_pid) +static int show_map(struct seq_file *m, void *v)  { -	show_map_vma(m, v, is_pid); +	show_map_vma(m, v);  	m_cache_vma(m, v);  	return 0;  } -static int show_pid_map(struct seq_file *m, void *v) -{ -	return show_map(m, v, 1); -} - -static int show_tid_map(struct seq_file *m, void *v) -{ -	return show_map(m, v, 0); -} -  static const struct seq_operations proc_pid_maps_op = {  	.start	= m_start,  	.next	= m_next,  	.stop	= m_stop, -	.show	= show_pid_map -}; - -static const struct seq_operations proc_tid_maps_op = { -	.start	= m_start, -	.next	= m_next, -	.stop	= m_stop, -	.show	= show_tid_map +	.show	= show_map  };  static int pid_maps_open(struct inode *inode, struct file *file) @@ -393,11 +375,6 @@ static int pid_maps_open(struct inode *inode, struct file *file)  	return do_maps_open(inode, file, &proc_pid_maps_op);  } -static int tid_maps_open(struct inode *inode, struct file *file) -{ -	return do_maps_open(inode, file, &proc_tid_maps_op); -} -  const struct file_operations proc_pid_maps_operations = {  	.open		= pid_maps_open,  	.read		= seq_read, @@ -405,13 +382,6 @@ const struct file_operations proc_pid_maps_operations = {  	.release	= proc_map_release,  }; -const struct file_operations proc_tid_maps_operations = { -	.open		= tid_maps_open, -	.read		= seq_read, -	.llseek		= seq_lseek, -	.release	= proc_map_release, -}; -  /*   * Proportional Set Size(PSS): my share of RSS.   * @@ -433,7 +403,6 @@ const struct file_operations proc_tid_maps_operations = {  #ifdef CONFIG_PROC_PAGE_MONITOR  struct mem_size_stats { -	bool first;  	unsigned long resident;  	unsigned long shared_clean;  	unsigned long shared_dirty; @@ -447,7 +416,6 @@ struct mem_size_stats {  	unsigned long swap;  	unsigned long shared_hugetlb;  	unsigned long private_hugetlb; -	unsigned long first_vma_start;  	u64 pss;  	u64 pss_locked;  	u64 swap_pss; @@ -731,14 +699,9 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask,  }  #endif /* HUGETLB_PAGE */ -#define SEQ_PUT_DEC(str, val) \ -		seq_put_decimal_ull_width(m, str, (val) >> 10, 8) -static int show_smap(struct seq_file *m, void *v, int is_pid) +static void smap_gather_stats(struct vm_area_struct *vma, +			     struct mem_size_stats *mss)  { -	struct proc_maps_private *priv = m->private; -	struct vm_area_struct *vma = v; -	struct mem_size_stats mss_stack; -	struct mem_size_stats *mss;  	struct mm_walk smaps_walk = {  		.pmd_entry = smaps_pte_range,  #ifdef CONFIG_HUGETLB_PAGE @@ -746,23 +709,6 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)  #endif  		.mm = vma->vm_mm,  	}; -	int ret = 0; -	bool rollup_mode; -	bool last_vma; - -	if (priv->rollup) { -		rollup_mode = true; -		mss = priv->rollup; -		if (mss->first) { -			mss->first_vma_start = vma->vm_start; -			mss->first = false; -		} -		last_vma = !m_next_vma(priv, vma); -	} else { -		rollup_mode = false; -		memset(&mss_stack, 0, sizeof(mss_stack)); -		mss = &mss_stack; -	}  	smaps_walk.private = mss; @@ -794,79 +740,116 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)  	walk_page_vma(vma, &smaps_walk);  	if (vma->vm_flags & VM_LOCKED)  		mss->pss_locked += mss->pss; +} -	if (!rollup_mode) { -		show_map_vma(m, vma, is_pid); -	} else if (last_vma) { -		show_vma_header_prefix( -			m, mss->first_vma_start, vma->vm_end, 0, 0, 0, 0); -		seq_pad(m, ' '); -		seq_puts(m, "[rollup]\n"); -	} else { -		ret = SEQ_SKIP; -	} - -	if (!rollup_mode) { -		SEQ_PUT_DEC("Size:           ", vma->vm_end - 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"); -	} +#define SEQ_PUT_DEC(str, val) \ +		seq_put_decimal_ull_width(m, str, (val) >> 10, 8) -	if (!rollup_mode || last_vma) { -		SEQ_PUT_DEC("Rss:            ", mss->resident); -		SEQ_PUT_DEC(" kB\nPss:            ", mss->pss >> PSS_SHIFT); -		SEQ_PUT_DEC(" kB\nShared_Clean:   ", mss->shared_clean); -		SEQ_PUT_DEC(" kB\nShared_Dirty:   ", mss->shared_dirty); -		SEQ_PUT_DEC(" kB\nPrivate_Clean:  ", mss->private_clean); -		SEQ_PUT_DEC(" kB\nPrivate_Dirty:  ", mss->private_dirty); -		SEQ_PUT_DEC(" kB\nReferenced:     ", mss->referenced); -		SEQ_PUT_DEC(" kB\nAnonymous:      ", mss->anonymous); -		SEQ_PUT_DEC(" kB\nLazyFree:       ", mss->lazyfree); -		SEQ_PUT_DEC(" kB\nAnonHugePages:  ", mss->anonymous_thp); -		SEQ_PUT_DEC(" kB\nShmemPmdMapped: ", mss->shmem_thp); -		SEQ_PUT_DEC(" kB\nShared_Hugetlb: ", mss->shared_hugetlb); -		seq_put_decimal_ull_width(m, " kB\nPrivate_Hugetlb: ", -					  mss->private_hugetlb >> 10, 7); -		SEQ_PUT_DEC(" kB\nSwap:           ", mss->swap); -		SEQ_PUT_DEC(" kB\nSwapPss:        ", -						mss->swap_pss >> PSS_SHIFT); -		SEQ_PUT_DEC(" kB\nLocked:         ", -						mss->pss_locked >> PSS_SHIFT); -		seq_puts(m, " kB\n"); -	} -	if (!rollup_mode) { -		if (arch_pkeys_enabled()) -			seq_printf(m, "ProtectionKey:  %8u\n", vma_pkey(vma)); -		show_smap_vma_flags(m, vma); -	} -	m_cache_vma(m, vma); -	return ret; +/* Show the contents common for smaps and smaps_rollup */ +static void __show_smap(struct seq_file *m, const struct mem_size_stats *mss) +{ +	SEQ_PUT_DEC("Rss:            ", mss->resident); +	SEQ_PUT_DEC(" kB\nPss:            ", mss->pss >> PSS_SHIFT); +	SEQ_PUT_DEC(" kB\nShared_Clean:   ", mss->shared_clean); +	SEQ_PUT_DEC(" kB\nShared_Dirty:   ", mss->shared_dirty); +	SEQ_PUT_DEC(" kB\nPrivate_Clean:  ", mss->private_clean); +	SEQ_PUT_DEC(" kB\nPrivate_Dirty:  ", mss->private_dirty); +	SEQ_PUT_DEC(" kB\nReferenced:     ", mss->referenced); +	SEQ_PUT_DEC(" kB\nAnonymous:      ", mss->anonymous); +	SEQ_PUT_DEC(" kB\nLazyFree:       ", mss->lazyfree); +	SEQ_PUT_DEC(" kB\nAnonHugePages:  ", mss->anonymous_thp); +	SEQ_PUT_DEC(" kB\nShmemPmdMapped: ", mss->shmem_thp); +	SEQ_PUT_DEC(" kB\nShared_Hugetlb: ", mss->shared_hugetlb); +	seq_put_decimal_ull_width(m, " kB\nPrivate_Hugetlb: ", +				  mss->private_hugetlb >> 10, 7); +	SEQ_PUT_DEC(" kB\nSwap:           ", mss->swap); +	SEQ_PUT_DEC(" kB\nSwapPss:        ", +					mss->swap_pss >> PSS_SHIFT); +	SEQ_PUT_DEC(" kB\nLocked:         ", +					mss->pss_locked >> PSS_SHIFT); +	seq_puts(m, " kB\n");  } -#undef SEQ_PUT_DEC -static int show_pid_smap(struct seq_file *m, void *v) +static int show_smap(struct seq_file *m, void *v)  { -	return show_smap(m, v, 1); +	struct vm_area_struct *vma = v; +	struct mem_size_stats mss; + +	memset(&mss, 0, sizeof(mss)); + +	smap_gather_stats(vma, &mss); + +	show_map_vma(m, vma); + +	SEQ_PUT_DEC("Size:           ", vma->vm_end - 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"); + +	__show_smap(m, &mss); + +	if (arch_pkeys_enabled()) +		seq_printf(m, "ProtectionKey:  %8u\n", vma_pkey(vma)); +	show_smap_vma_flags(m, vma); + +	m_cache_vma(m, vma); + +	return 0;  } -static int show_tid_smap(struct seq_file *m, void *v) +static int show_smaps_rollup(struct seq_file *m, void *v)  { -	return show_smap(m, v, 0); +	struct proc_maps_private *priv = m->private; +	struct mem_size_stats mss; +	struct mm_struct *mm; +	struct vm_area_struct *vma; +	unsigned long last_vma_end = 0; +	int ret = 0; + +	priv->task = get_proc_task(priv->inode); +	if (!priv->task) +		return -ESRCH; + +	mm = priv->mm; +	if (!mm || !mmget_not_zero(mm)) { +		ret = -ESRCH; +		goto out_put_task; +	} + +	memset(&mss, 0, sizeof(mss)); + +	down_read(&mm->mmap_sem); +	hold_task_mempolicy(priv); + +	for (vma = priv->mm->mmap; vma; vma = vma->vm_next) { +		smap_gather_stats(vma, &mss); +		last_vma_end = vma->vm_end; +	} + +	show_vma_header_prefix(m, priv->mm->mmap->vm_start, +			       last_vma_end, 0, 0, 0, 0); +	seq_pad(m, ' '); +	seq_puts(m, "[rollup]\n"); + +	__show_smap(m, &mss); + +	release_task_mempolicy(priv); +	up_read(&mm->mmap_sem); +	mmput(mm); + +out_put_task: +	put_task_struct(priv->task); +	priv->task = NULL; + +	return ret;  } +#undef SEQ_PUT_DEC  static const struct seq_operations proc_pid_smaps_op = {  	.start	= m_start,  	.next	= m_next,  	.stop	= m_stop, -	.show	= show_pid_smap -}; - -static const struct seq_operations proc_tid_smaps_op = { -	.start	= m_start, -	.next	= m_next, -	.stop	= m_stop, -	.show	= show_tid_smap +	.show	= show_smap  };  static int pid_smaps_open(struct inode *inode, struct file *file) @@ -874,28 +857,45 @@ static int pid_smaps_open(struct inode *inode, struct file *file)  	return do_maps_open(inode, file, &proc_pid_smaps_op);  } -static int pid_smaps_rollup_open(struct inode *inode, struct file *file) +static int smaps_rollup_open(struct inode *inode, struct file *file)  { -	struct seq_file *seq; +	int ret;  	struct proc_maps_private *priv; -	int ret = do_maps_open(inode, file, &proc_pid_smaps_op); - -	if (ret < 0) -		return ret; -	seq = file->private_data; -	priv = seq->private; -	priv->rollup = kzalloc(sizeof(*priv->rollup), GFP_KERNEL); -	if (!priv->rollup) { -		proc_map_release(inode, file); + +	priv = kzalloc(sizeof(*priv), GFP_KERNEL_ACCOUNT); +	if (!priv)  		return -ENOMEM; + +	ret = single_open(file, show_smaps_rollup, priv); +	if (ret) +		goto out_free; + +	priv->inode = inode; +	priv->mm = proc_mem_open(inode, PTRACE_MODE_READ); +	if (IS_ERR(priv->mm)) { +		ret = PTR_ERR(priv->mm); + +		single_release(inode, file); +		goto out_free;  	} -	priv->rollup->first = true; +  	return 0; + +out_free: +	kfree(priv); +	return ret;  } -static int tid_smaps_open(struct inode *inode, struct file *file) +static int smaps_rollup_release(struct inode *inode, struct file *file)  { -	return do_maps_open(inode, file, &proc_tid_smaps_op); +	struct seq_file *seq = file->private_data; +	struct proc_maps_private *priv = seq->private; + +	if (priv->mm) +		mmdrop(priv->mm); + +	kfree(priv); +	return single_release(inode, file);  }  const struct file_operations proc_pid_smaps_operations = { @@ -906,17 +906,10 @@ const struct file_operations proc_pid_smaps_operations = {  };  const struct file_operations proc_pid_smaps_rollup_operations = { -	.open		= pid_smaps_rollup_open, +	.open		= smaps_rollup_open,  	.read		= seq_read,  	.llseek		= seq_lseek, -	.release	= proc_map_release, -}; - -const struct file_operations proc_tid_smaps_operations = { -	.open		= tid_smaps_open, -	.read		= seq_read, -	.llseek		= seq_lseek, -	.release	= proc_map_release, +	.release	= smaps_rollup_release,  };  enum clear_refs_types { @@ -1728,7 +1721,7 @@ static int gather_hugetlb_stats(pte_t *pte, unsigned long hmask,  /*   * Display pages allocated per node and memory policy via /proc.   */ -static int show_numa_map(struct seq_file *m, void *v, int is_pid) +static int show_numa_map(struct seq_file *m, void *v)  {  	struct numa_maps_private *numa_priv = m->private;  	struct proc_maps_private *proc_priv = &numa_priv->proc_maps; @@ -1812,45 +1805,17 @@ out:  	return 0;  } -static int show_pid_numa_map(struct seq_file *m, void *v) -{ -	return show_numa_map(m, v, 1); -} - -static int show_tid_numa_map(struct seq_file *m, void *v) -{ -	return show_numa_map(m, v, 0); -} -  static const struct seq_operations proc_pid_numa_maps_op = {  	.start  = m_start,  	.next   = m_next,  	.stop   = m_stop, -	.show   = show_pid_numa_map, +	.show   = show_numa_map,  }; -static const struct seq_operations proc_tid_numa_maps_op = { -	.start  = m_start, -	.next   = m_next, -	.stop   = m_stop, -	.show   = show_tid_numa_map, -}; - -static int numa_maps_open(struct inode *inode, struct file *file, -			  const struct seq_operations *ops) -{ -	return proc_maps_open(inode, file, ops, -				sizeof(struct numa_maps_private)); -} -  static int pid_numa_maps_open(struct inode *inode, struct file *file)  { -	return numa_maps_open(inode, file, &proc_pid_numa_maps_op); -} - -static int tid_numa_maps_open(struct inode *inode, struct file *file) -{ -	return numa_maps_open(inode, file, &proc_tid_numa_maps_op); +	return proc_maps_open(inode, file, &proc_pid_numa_maps_op, +				sizeof(struct numa_maps_private));  }  const struct file_operations proc_pid_numa_maps_operations = { @@ -1860,10 +1825,4 @@ const struct file_operations proc_pid_numa_maps_operations = {  	.release	= proc_map_release,  }; -const struct file_operations proc_tid_numa_maps_operations = { -	.open		= tid_numa_maps_open, -	.read		= seq_read, -	.llseek		= seq_lseek, -	.release	= proc_map_release, -};  #endif /* CONFIG_NUMA */  |