diff options
Diffstat (limited to 'fs/proc/task_mmu.c')
| -rw-r--r-- | fs/proc/task_mmu.c | 210 | 
1 files changed, 169 insertions, 41 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index c7e3a163295..9694cc28351 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -209,16 +209,20 @@ static int do_maps_open(struct inode *inode, struct file *file,  	return ret;  } -static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) +static void +show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)  {  	struct mm_struct *mm = vma->vm_mm;  	struct file *file = vma->vm_file; +	struct proc_maps_private *priv = m->private; +	struct task_struct *task = priv->task;  	vm_flags_t flags = vma->vm_flags;  	unsigned long ino = 0;  	unsigned long long pgoff = 0;  	unsigned long start, end;  	dev_t dev = 0;  	int len; +	const char *name = NULL;  	if (file) {  		struct inode *inode = vma->vm_file->f_path.dentry->d_inode; @@ -252,36 +256,57 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)  	if (file) {  		pad_len_spaces(m, len);  		seq_path(m, &file->f_path, "\n"); -	} else { -		const char *name = arch_vma_name(vma); -		if (!name) { -			if (mm) { -				if (vma->vm_start <= mm->brk && -						vma->vm_end >= mm->start_brk) { -					name = "[heap]"; -				} else if (vma->vm_start <= mm->start_stack && -					   vma->vm_end >= mm->start_stack) { -					name = "[stack]"; -				} +		goto done; +	} + +	name = arch_vma_name(vma); +	if (!name) { +		pid_t tid; + +		if (!mm) { +			name = "[vdso]"; +			goto done; +		} + +		if (vma->vm_start <= mm->brk && +		    vma->vm_end >= mm->start_brk) { +			name = "[heap]"; +			goto done; +		} + +		tid = vm_is_stack(task, vma, is_pid); + +		if (tid != 0) { +			/* +			 * Thread stack in /proc/PID/task/TID/maps or +			 * the main process stack. +			 */ +			if (!is_pid || (vma->vm_start <= mm->start_stack && +			    vma->vm_end >= mm->start_stack)) { +				name = "[stack]";  			} else { -				name = "[vdso]"; +				/* Thread stack in /proc/PID/maps */ +				pad_len_spaces(m, len); +				seq_printf(m, "[stack:%d]", tid);  			}  		} -		if (name) { -			pad_len_spaces(m, len); -			seq_puts(m, name); -		} +	} + +done: +	if (name) { +		pad_len_spaces(m, len); +		seq_puts(m, name);  	}  	seq_putc(m, '\n');  } -static int show_map(struct seq_file *m, void *v) +static int show_map(struct seq_file *m, void *v, int is_pid)  {  	struct vm_area_struct *vma = v;  	struct proc_maps_private *priv = m->private;  	struct task_struct *task = priv->task; -	show_map_vma(m, vma); +	show_map_vma(m, vma, is_pid);  	if (m->count < m->size)  /* vma is copied successfully */  		m->version = (vma != get_gate_vma(task->mm)) @@ -289,20 +314,49 @@ static int show_map(struct seq_file *m, void *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_map +	.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  }; -static int maps_open(struct inode *inode, struct file *file) +static int pid_maps_open(struct inode *inode, struct file *file)  {  	return do_maps_open(inode, file, &proc_pid_maps_op);  } -const struct file_operations proc_maps_operations = { -	.open		= maps_open, +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, +	.llseek		= seq_lseek, +	.release	= seq_release_private, +}; + +const struct file_operations proc_tid_maps_operations = { +	.open		= tid_maps_open,  	.read		= seq_read,  	.llseek		= seq_lseek,  	.release	= seq_release_private, @@ -416,7 +470,7 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,  	return 0;  } -static int show_smap(struct seq_file *m, void *v) +static int show_smap(struct seq_file *m, void *v, int is_pid)  {  	struct proc_maps_private *priv = m->private;  	struct task_struct *task = priv->task; @@ -434,7 +488,7 @@ static int show_smap(struct seq_file *m, void *v)  	if (vma->vm_mm && !is_vm_hugetlb_page(vma))  		walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk); -	show_map_vma(m, vma); +	show_map_vma(m, vma, is_pid);  	seq_printf(m,  		   "Size:           %8lu kB\n" @@ -473,20 +527,49 @@ static int show_smap(struct seq_file *m, void *v)  	return 0;  } +static int show_pid_smap(struct seq_file *m, void *v) +{ +	return show_smap(m, v, 1); +} + +static int show_tid_smap(struct seq_file *m, void *v) +{ +	return show_smap(m, v, 0); +} +  static const struct seq_operations proc_pid_smaps_op = {  	.start	= m_start,  	.next	= m_next,  	.stop	= m_stop, -	.show	= show_smap +	.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  }; -static int smaps_open(struct inode *inode, struct file *file) +static int pid_smaps_open(struct inode *inode, struct file *file)  {  	return do_maps_open(inode, file, &proc_pid_smaps_op);  } -const struct file_operations proc_smaps_operations = { -	.open		= smaps_open, +static int tid_smaps_open(struct inode *inode, struct file *file) +{ +	return do_maps_open(inode, file, &proc_tid_smaps_op); +} + +const struct file_operations proc_pid_smaps_operations = { +	.open		= pid_smaps_open, +	.read		= seq_read, +	.llseek		= seq_lseek, +	.release	= seq_release_private, +}; + +const struct file_operations proc_tid_smaps_operations = { +	.open		= tid_smaps_open,  	.read		= seq_read,  	.llseek		= seq_lseek,  	.release	= seq_release_private, @@ -1039,7 +1122,7 @@ static int gather_hugetbl_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) +static int show_numa_map(struct seq_file *m, void *v, int is_pid)  {  	struct numa_maps_private *numa_priv = m->private;  	struct proc_maps_private *proc_priv = &numa_priv->proc_maps; @@ -1076,9 +1159,19 @@ static int show_numa_map(struct seq_file *m, void *v)  		seq_path(m, &file->f_path, "\n\t= ");  	} else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {  		seq_printf(m, " heap"); -	} else if (vma->vm_start <= mm->start_stack && -			vma->vm_end >= mm->start_stack) { -		seq_printf(m, " stack"); +	} else { +		pid_t tid = vm_is_stack(proc_priv->task, vma, is_pid); +		if (tid != 0) { +			/* +			 * Thread stack in /proc/PID/task/TID/maps or +			 * the main process stack. +			 */ +			if (!is_pid || (vma->vm_start <= mm->start_stack && +			    vma->vm_end >= mm->start_stack)) +				seq_printf(m, " stack"); +			else +				seq_printf(m, " stack:%d", tid); +		}  	}  	if (is_vm_hugetlb_page(vma)) @@ -1121,21 +1214,39 @@ 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_numa_map, +	.start  = m_start, +	.next   = m_next, +	.stop   = m_stop, +	.show   = show_pid_numa_map,  }; -static int numa_maps_open(struct inode *inode, struct file *file) +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)  {  	struct numa_maps_private *priv;  	int ret = -ENOMEM;  	priv = kzalloc(sizeof(*priv), GFP_KERNEL);  	if (priv) {  		priv->proc_maps.pid = proc_pid(inode); -		ret = seq_open(file, &proc_pid_numa_maps_op); +		ret = seq_open(file, ops);  		if (!ret) {  			struct seq_file *m = file->private_data;  			m->private = priv; @@ -1146,8 +1257,25 @@ static int numa_maps_open(struct inode *inode, struct file *file)  	return ret;  } -const struct file_operations proc_numa_maps_operations = { -	.open		= numa_maps_open, +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); +} + +const struct file_operations proc_pid_numa_maps_operations = { +	.open		= pid_numa_maps_open, +	.read		= seq_read, +	.llseek		= seq_lseek, +	.release	= seq_release_private, +}; + +const struct file_operations proc_tid_numa_maps_operations = { +	.open		= tid_numa_maps_open,  	.read		= seq_read,  	.llseek		= seq_lseek,  	.release	= seq_release_private,  |