diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/proc/task_mmu.c | 62 | 
1 files changed, 62 insertions, 0 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 3e636d864d5..e2c925fa782 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -134,6 +134,56 @@ static void release_task_mempolicy(struct proc_maps_private *priv)  }  #endif +static void seq_print_vma_name(struct seq_file *m, struct vm_area_struct *vma) +{ +	const char __user *name = vma_get_anon_name(vma); +	struct mm_struct *mm = vma->vm_mm; + +	unsigned long page_start_vaddr; +	unsigned long page_offset; +	unsigned long num_pages; +	unsigned long max_len = NAME_MAX; +	int i; + +	page_start_vaddr = (unsigned long)name & PAGE_MASK; +	page_offset = (unsigned long)name - page_start_vaddr; +	num_pages = DIV_ROUND_UP(page_offset + max_len, PAGE_SIZE); + +	seq_puts(m, "[anon:"); + +	for (i = 0; i < num_pages; i++) { +		int len; +		int write_len; +		const char *kaddr; +		long pages_pinned; +		struct page *page; + +		pages_pinned = get_user_pages(current, mm, page_start_vaddr, +				1, 0, 0, &page, NULL); +		if (pages_pinned < 1) { +			seq_puts(m, "<fault>]"); +			return; +		} + +		kaddr = (const char *)kmap(page); +		len = min(max_len, PAGE_SIZE - page_offset); +		write_len = strnlen(kaddr + page_offset, len); +		seq_write(m, kaddr + page_offset, write_len); +		kunmap(page); +		put_page(page); + +		/* if strnlen hit a null terminator then we're done */ +		if (write_len != len) +			break; + +		max_len -= len; +		page_offset = 0; +		page_start_vaddr += PAGE_SIZE; +	} + +	seq_putc(m, ']'); +} +  static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma)  {  	if (vma && vma != priv->tail_vma) { @@ -335,6 +385,12 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)  				pad_len_spaces(m, len);  				seq_printf(m, "[stack:%d]", tid);  			} +			goto done; +		} + +		if (vma_get_anon_name(vma)) { +			pad_len_spaces(m, len); +			seq_print_vma_name(m, vma);  		}  	} @@ -634,6 +690,12 @@ static int show_smap(struct seq_file *m, void *v, int is_pid)  	show_smap_vma_flags(m, vma); +	if (vma_get_anon_name(vma)) { +		seq_puts(m, "Name:           "); +		seq_print_vma_name(m, vma); +		seq_putc(m, '\n'); +	} +  	if (m->count < m->size)  /* vma is copied successfully */  		m->version = (vma != get_gate_vma(task->mm))  			? vma->vm_start : 0;  |