diff options
author | David S. Miller <davem@davemloft.net> | 2010-04-13 03:28:45 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-04-13 03:28:45 -0400 |
commit | 9343af084c7e8911897b0883042ee690cee3aaef (patch) | |
tree | 6211a4bdc84690bec6530d27a3abb19f5e8bb8f3 /fs/proc | |
parent | e182c77cc291456eed127b1472952ddb59a81a9d (diff) | |
parent | 0d0fb0f9c5fddef4a10242fe3337f00f528a3099 (diff) |
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Conflicts:
lib/Kconfig.debug
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/array.c | 1 | ||||
-rw-r--r-- | fs/proc/base.c | 1 | ||||
-rw-r--r-- | fs/proc/generic.c | 1 | ||||
-rw-r--r-- | fs/proc/inode.c | 1 | ||||
-rw-r--r-- | fs/proc/kcore.c | 1 | ||||
-rw-r--r-- | fs/proc/nommu.c | 1 | ||||
-rw-r--r-- | fs/proc/proc_devtree.c | 1 | ||||
-rw-r--r-- | fs/proc/proc_net.c | 1 | ||||
-rw-r--r-- | fs/proc/stat.c | 1 | ||||
-rw-r--r-- | fs/proc/task_mmu.c | 115 | ||||
-rw-r--r-- | fs/proc/task_nommu.c | 1 | ||||
-rw-r--r-- | fs/proc/vmcore.c | 1 |
12 files changed, 54 insertions, 72 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c index aa8637b81028..e51f2ec2c5e5 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
@@ -68,7 +68,6 @@ | |||
68 | #include <linux/hugetlb.h> | 68 | #include <linux/hugetlb.h> |
69 | #include <linux/pagemap.h> | 69 | #include <linux/pagemap.h> |
70 | #include <linux/swap.h> | 70 | #include <linux/swap.h> |
71 | #include <linux/slab.h> | ||
72 | #include <linux/smp.h> | 71 | #include <linux/smp.h> |
73 | #include <linux/signal.h> | 72 | #include <linux/signal.h> |
74 | #include <linux/highmem.h> | 73 | #include <linux/highmem.h> |
diff --git a/fs/proc/base.c b/fs/proc/base.c index b1f6e62773d3..7621db800a74 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -81,6 +81,7 @@ | |||
81 | #include <linux/elf.h> | 81 | #include <linux/elf.h> |
82 | #include <linux/pid_namespace.h> | 82 | #include <linux/pid_namespace.h> |
83 | #include <linux/fs_struct.h> | 83 | #include <linux/fs_struct.h> |
84 | #include <linux/slab.h> | ||
84 | #include "internal.h" | 85 | #include "internal.h" |
85 | 86 | ||
86 | /* NOTE: | 87 | /* NOTE: |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 08f4d71dacd7..43c127490606 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/proc_fs.h> | 13 | #include <linux/proc_fs.h> |
14 | #include <linux/stat.h> | 14 | #include <linux/stat.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/slab.h> | ||
16 | #include <linux/mount.h> | 17 | #include <linux/mount.h> |
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/idr.h> | 19 | #include <linux/idr.h> |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 445a02bcaab3..d35b23238fb1 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/smp_lock.h> | 19 | #include <linux/smp_lock.h> |
20 | #include <linux/sysctl.h> | 20 | #include <linux/sysctl.h> |
21 | #include <linux/slab.h> | ||
21 | 22 | ||
22 | #include <asm/system.h> | 23 | #include <asm/system.h> |
23 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index b442dac8f5f9..19979a2ce272 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/highmem.h> | 19 | #include <linux/highmem.h> |
20 | #include <linux/bootmem.h> | 20 | #include <linux/bootmem.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/slab.h> | ||
22 | #include <asm/uaccess.h> | 23 | #include <asm/uaccess.h> |
23 | #include <asm/io.h> | 24 | #include <asm/io.h> |
24 | #include <linux/list.h> | 25 | #include <linux/list.h> |
diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c index 9fe7d7ebe115..b1822dde55c2 100644 --- a/fs/proc/nommu.c +++ b/fs/proc/nommu.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/mmzone.h> | 21 | #include <linux/mmzone.h> |
22 | #include <linux/pagemap.h> | 22 | #include <linux/pagemap.h> |
23 | #include <linux/swap.h> | 23 | #include <linux/swap.h> |
24 | #include <linux/slab.h> | ||
25 | #include <linux/smp.h> | 24 | #include <linux/smp.h> |
26 | #include <linux/seq_file.h> | 25 | #include <linux/seq_file.h> |
27 | #include <linux/hugetlb.h> | 26 | #include <linux/hugetlb.h> |
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c index f8650dce74fb..ce94801f48ca 100644 --- a/fs/proc/proc_devtree.c +++ b/fs/proc/proc_devtree.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/string.h> | 12 | #include <linux/string.h> |
13 | #include <linux/of.h> | 13 | #include <linux/of.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/slab.h> | ||
15 | #include <asm/prom.h> | 16 | #include <asm/prom.h> |
16 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
17 | #include "internal.h" | 18 | #include "internal.h" |
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c index 04d1270f1c38..9020ac15baaa 100644 --- a/fs/proc/proc_net.c +++ b/fs/proc/proc_net.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/time.h> | 14 | #include <linux/time.h> |
15 | #include <linux/proc_fs.h> | 15 | #include <linux/proc_fs.h> |
16 | #include <linux/stat.h> | 16 | #include <linux/stat.h> |
17 | #include <linux/slab.h> | ||
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
diff --git a/fs/proc/stat.c b/fs/proc/stat.c index b9b7aad2003d..bf31b03fc275 100644 --- a/fs/proc/stat.c +++ b/fs/proc/stat.c | |||
@@ -1,6 +1,5 @@ | |||
1 | #include <linux/cpumask.h> | 1 | #include <linux/cpumask.h> |
2 | #include <linux/fs.h> | 2 | #include <linux/fs.h> |
3 | #include <linux/gfp.h> | ||
4 | #include <linux/init.h> | 3 | #include <linux/init.h> |
5 | #include <linux/interrupt.h> | 4 | #include <linux/interrupt.h> |
6 | #include <linux/kernel_stat.h> | 5 | #include <linux/kernel_stat.h> |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 183f8ff5f400..070553427dd5 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/seq_file.h> | 4 | #include <linux/seq_file.h> |
5 | #include <linux/highmem.h> | 5 | #include <linux/highmem.h> |
6 | #include <linux/ptrace.h> | 6 | #include <linux/ptrace.h> |
7 | #include <linux/slab.h> | ||
7 | #include <linux/pagemap.h> | 8 | #include <linux/pagemap.h> |
8 | #include <linux/mempolicy.h> | 9 | #include <linux/mempolicy.h> |
9 | #include <linux/swap.h> | 10 | #include <linux/swap.h> |
@@ -406,6 +407,7 @@ static int show_smap(struct seq_file *m, void *v) | |||
406 | 407 | ||
407 | memset(&mss, 0, sizeof mss); | 408 | memset(&mss, 0, sizeof mss); |
408 | mss.vma = vma; | 409 | mss.vma = vma; |
410 | /* mmap_sem is held in m_start */ | ||
409 | if (vma->vm_mm && !is_vm_hugetlb_page(vma)) | 411 | if (vma->vm_mm && !is_vm_hugetlb_page(vma)) |
410 | walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk); | 412 | walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk); |
411 | 413 | ||
@@ -552,7 +554,8 @@ const struct file_operations proc_clear_refs_operations = { | |||
552 | }; | 554 | }; |
553 | 555 | ||
554 | struct pagemapread { | 556 | struct pagemapread { |
555 | u64 __user *out, *end; | 557 | int pos, len; |
558 | u64 *buffer; | ||
556 | }; | 559 | }; |
557 | 560 | ||
558 | #define PM_ENTRY_BYTES sizeof(u64) | 561 | #define PM_ENTRY_BYTES sizeof(u64) |
@@ -575,10 +578,8 @@ struct pagemapread { | |||
575 | static int add_to_pagemap(unsigned long addr, u64 pfn, | 578 | static int add_to_pagemap(unsigned long addr, u64 pfn, |
576 | struct pagemapread *pm) | 579 | struct pagemapread *pm) |
577 | { | 580 | { |
578 | if (put_user(pfn, pm->out)) | 581 | pm->buffer[pm->pos++] = pfn; |
579 | return -EFAULT; | 582 | if (pm->pos >= pm->len) |
580 | pm->out++; | ||
581 | if (pm->out >= pm->end) | ||
582 | return PM_END_OF_BUFFER; | 583 | return PM_END_OF_BUFFER; |
583 | return 0; | 584 | return 0; |
584 | } | 585 | } |
@@ -661,31 +662,18 @@ static u64 huge_pte_to_pagemap_entry(pte_t pte, int offset) | |||
661 | return pme; | 662 | return pme; |
662 | } | 663 | } |
663 | 664 | ||
664 | static int pagemap_hugetlb_range(pte_t *pte, unsigned long addr, | 665 | /* This function walks within one hugetlb entry in the single call */ |
665 | unsigned long end, struct mm_walk *walk) | 666 | static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask, |
667 | unsigned long addr, unsigned long end, | ||
668 | struct mm_walk *walk) | ||
666 | { | 669 | { |
667 | struct vm_area_struct *vma; | ||
668 | struct pagemapread *pm = walk->private; | 670 | struct pagemapread *pm = walk->private; |
669 | struct hstate *hs = NULL; | ||
670 | int err = 0; | 671 | int err = 0; |
672 | u64 pfn; | ||
671 | 673 | ||
672 | vma = find_vma(walk->mm, addr); | ||
673 | if (vma) | ||
674 | hs = hstate_vma(vma); | ||
675 | for (; addr != end; addr += PAGE_SIZE) { | 674 | for (; addr != end; addr += PAGE_SIZE) { |
676 | u64 pfn = PM_NOT_PRESENT; | 675 | int offset = (addr & ~hmask) >> PAGE_SHIFT; |
677 | 676 | pfn = huge_pte_to_pagemap_entry(*pte, offset); | |
678 | if (vma && (addr >= vma->vm_end)) { | ||
679 | vma = find_vma(walk->mm, addr); | ||
680 | if (vma) | ||
681 | hs = hstate_vma(vma); | ||
682 | } | ||
683 | |||
684 | if (vma && (vma->vm_start <= addr) && is_vm_hugetlb_page(vma)) { | ||
685 | /* calculate pfn of the "raw" page in the hugepage. */ | ||
686 | int offset = (addr & ~huge_page_mask(hs)) >> PAGE_SHIFT; | ||
687 | pfn = huge_pte_to_pagemap_entry(*pte, offset); | ||
688 | } | ||
689 | err = add_to_pagemap(addr, pfn, pm); | 677 | err = add_to_pagemap(addr, pfn, pm); |
690 | if (err) | 678 | if (err) |
691 | return err; | 679 | return err; |
@@ -720,21 +708,20 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long addr, | |||
720 | * determine which areas of memory are actually mapped and llseek to | 708 | * determine which areas of memory are actually mapped and llseek to |
721 | * skip over unmapped regions. | 709 | * skip over unmapped regions. |
722 | */ | 710 | */ |
711 | #define PAGEMAP_WALK_SIZE (PMD_SIZE) | ||
723 | static ssize_t pagemap_read(struct file *file, char __user *buf, | 712 | static ssize_t pagemap_read(struct file *file, char __user *buf, |
724 | size_t count, loff_t *ppos) | 713 | size_t count, loff_t *ppos) |
725 | { | 714 | { |
726 | struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); | 715 | struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); |
727 | struct page **pages, *page; | ||
728 | unsigned long uaddr, uend; | ||
729 | struct mm_struct *mm; | 716 | struct mm_struct *mm; |
730 | struct pagemapread pm; | 717 | struct pagemapread pm; |
731 | int pagecount; | ||
732 | int ret = -ESRCH; | 718 | int ret = -ESRCH; |
733 | struct mm_walk pagemap_walk = {}; | 719 | struct mm_walk pagemap_walk = {}; |
734 | unsigned long src; | 720 | unsigned long src; |
735 | unsigned long svpfn; | 721 | unsigned long svpfn; |
736 | unsigned long start_vaddr; | 722 | unsigned long start_vaddr; |
737 | unsigned long end_vaddr; | 723 | unsigned long end_vaddr; |
724 | int copied = 0; | ||
738 | 725 | ||
739 | if (!task) | 726 | if (!task) |
740 | goto out; | 727 | goto out; |
@@ -757,35 +744,12 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, | |||
757 | if (!mm) | 744 | if (!mm) |
758 | goto out_task; | 745 | goto out_task; |
759 | 746 | ||
760 | 747 | pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); | |
761 | uaddr = (unsigned long)buf & PAGE_MASK; | 748 | pm.buffer = kmalloc(pm.len, GFP_TEMPORARY); |
762 | uend = (unsigned long)(buf + count); | ||
763 | pagecount = (PAGE_ALIGN(uend) - uaddr) / PAGE_SIZE; | ||
764 | ret = 0; | ||
765 | if (pagecount == 0) | ||
766 | goto out_mm; | ||
767 | pages = kcalloc(pagecount, sizeof(struct page *), GFP_KERNEL); | ||
768 | ret = -ENOMEM; | 749 | ret = -ENOMEM; |
769 | if (!pages) | 750 | if (!pm.buffer) |
770 | goto out_mm; | 751 | goto out_mm; |
771 | 752 | ||
772 | down_read(¤t->mm->mmap_sem); | ||
773 | ret = get_user_pages(current, current->mm, uaddr, pagecount, | ||
774 | 1, 0, pages, NULL); | ||
775 | up_read(¤t->mm->mmap_sem); | ||
776 | |||
777 | if (ret < 0) | ||
778 | goto out_free; | ||
779 | |||
780 | if (ret != pagecount) { | ||
781 | pagecount = ret; | ||
782 | ret = -EFAULT; | ||
783 | goto out_pages; | ||
784 | } | ||
785 | |||
786 | pm.out = (u64 __user *)buf; | ||
787 | pm.end = (u64 __user *)(buf + count); | ||
788 | |||
789 | pagemap_walk.pmd_entry = pagemap_pte_range; | 753 | pagemap_walk.pmd_entry = pagemap_pte_range; |
790 | pagemap_walk.pte_hole = pagemap_pte_hole; | 754 | pagemap_walk.pte_hole = pagemap_pte_hole; |
791 | pagemap_walk.hugetlb_entry = pagemap_hugetlb_range; | 755 | pagemap_walk.hugetlb_entry = pagemap_hugetlb_range; |
@@ -807,23 +771,36 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, | |||
807 | * user buffer is tracked in "pm", and the walk | 771 | * user buffer is tracked in "pm", and the walk |
808 | * will stop when we hit the end of the buffer. | 772 | * will stop when we hit the end of the buffer. |
809 | */ | 773 | */ |
810 | ret = walk_page_range(start_vaddr, end_vaddr, &pagemap_walk); | 774 | ret = 0; |
811 | if (ret == PM_END_OF_BUFFER) | 775 | while (count && (start_vaddr < end_vaddr)) { |
812 | ret = 0; | 776 | int len; |
813 | /* don't need mmap_sem for these, but this looks cleaner */ | 777 | unsigned long end; |
814 | *ppos += (char __user *)pm.out - buf; | 778 | |
815 | if (!ret) | 779 | pm.pos = 0; |
816 | ret = (char __user *)pm.out - buf; | 780 | end = start_vaddr + PAGEMAP_WALK_SIZE; |
817 | 781 | /* overflow ? */ | |
818 | out_pages: | 782 | if (end < start_vaddr || end > end_vaddr) |
819 | for (; pagecount; pagecount--) { | 783 | end = end_vaddr; |
820 | page = pages[pagecount-1]; | 784 | down_read(&mm->mmap_sem); |
821 | if (!PageReserved(page)) | 785 | ret = walk_page_range(start_vaddr, end, &pagemap_walk); |
822 | SetPageDirty(page); | 786 | up_read(&mm->mmap_sem); |
823 | page_cache_release(page); | 787 | start_vaddr = end; |
788 | |||
789 | len = min(count, PM_ENTRY_BYTES * pm.pos); | ||
790 | if (copy_to_user(buf, pm.buffer, len)) { | ||
791 | ret = -EFAULT; | ||
792 | goto out_free; | ||
793 | } | ||
794 | copied += len; | ||
795 | buf += len; | ||
796 | count -= len; | ||
824 | } | 797 | } |
798 | *ppos += copied; | ||
799 | if (!ret || ret == PM_END_OF_BUFFER) | ||
800 | ret = copied; | ||
801 | |||
825 | out_free: | 802 | out_free: |
826 | kfree(pages); | 803 | kfree(pm.buffer); |
827 | out_mm: | 804 | out_mm: |
828 | mmput(mm); | 805 | mmput(mm); |
829 | out_task: | 806 | out_task: |
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index 5d9fd64ef81a..46d4b5d72bd3 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/fs_struct.h> | 5 | #include <linux/fs_struct.h> |
6 | #include <linux/mount.h> | 6 | #include <linux/mount.h> |
7 | #include <linux/ptrace.h> | 7 | #include <linux/ptrace.h> |
8 | #include <linux/slab.h> | ||
8 | #include <linux/seq_file.h> | 9 | #include <linux/seq_file.h> |
9 | #include "internal.h" | 10 | #include "internal.h" |
10 | 11 | ||
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 0872afa58d39..9fbc99ec799a 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/user.h> | 12 | #include <linux/user.h> |
13 | #include <linux/elf.h> | 13 | #include <linux/elf.h> |
14 | #include <linux/elfcore.h> | 14 | #include <linux/elfcore.h> |
15 | #include <linux/slab.h> | ||
15 | #include <linux/highmem.h> | 16 | #include <linux/highmem.h> |
16 | #include <linux/bootmem.h> | 17 | #include <linux/bootmem.h> |
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |