aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorHugh Dickins <hugh.dickins@tiscali.co.uk>2009-09-21 20:03:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-22 10:17:40 -0400
commitf3e8fccd06d27773186a0094371daf2d84c79469 (patch)
tree46e652e6ac3588a26c6d3e38ea10274eb3fc2ea8 /fs
parent1c3aff1ceec2cc86810e2690e67873ff0c505862 (diff)
mm: add get_dump_page
In preparation for the next patch, add a simple get_dump_page(addr) interface for the CONFIG_ELF_CORE dumpers to use, instead of calling get_user_pages() directly. They're not interested in errors: they just want to use holes as much as possible, to save space and make sure that the data is aligned where the headers said it would be. Oh, and don't use that horrid DUMP_SEEK(off) macro! Signed-off-by: Hugh Dickins <hugh.dickins@tiscali.co.uk> Acked-by: Rik van Riel <riel@redhat.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Nick Piggin <npiggin@suse.de> Cc: Mel Gorman <mel@csn.ul.ie> Cc: Minchan Kim <minchan.kim@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/binfmt_elf.c44
-rw-r--r--fs/binfmt_elf_fdpic.c56
2 files changed, 33 insertions, 67 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 7c1e65d54872..442d94fe255c 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1280,9 +1280,6 @@ static int writenote(struct memelfnote *men, struct file *file,
1280#define DUMP_WRITE(addr, nr) \ 1280#define DUMP_WRITE(addr, nr) \
1281 if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \ 1281 if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
1282 goto end_coredump; 1282 goto end_coredump;
1283#define DUMP_SEEK(off) \
1284 if (!dump_seek(file, (off))) \
1285 goto end_coredump;
1286 1283
1287static void fill_elf_header(struct elfhdr *elf, int segs, 1284static void fill_elf_header(struct elfhdr *elf, int segs,
1288 u16 machine, u32 flags, u8 osabi) 1285 u16 machine, u32 flags, u8 osabi)
@@ -2016,7 +2013,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un
2016 goto end_coredump; 2013 goto end_coredump;
2017 2014
2018 /* Align to page */ 2015 /* Align to page */
2019 DUMP_SEEK(dataoff - foffset); 2016 if (!dump_seek(file, dataoff - foffset))
2017 goto end_coredump;
2020 2018
2021 for (vma = first_vma(current, gate_vma); vma != NULL; 2019 for (vma = first_vma(current, gate_vma); vma != NULL;
2022 vma = next_vma(vma, gate_vma)) { 2020 vma = next_vma(vma, gate_vma)) {
@@ -2027,33 +2025,19 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file, un
2027 2025
2028 for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) { 2026 for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) {
2029 struct page *page; 2027 struct page *page;
2030 struct vm_area_struct *tmp_vma; 2028 int stop;
2031 2029
2032 if (get_user_pages(current, current->mm, addr, 1, 0, 1, 2030 page = get_dump_page(addr);
2033 &page, &tmp_vma) <= 0) { 2031 if (page) {
2034 DUMP_SEEK(PAGE_SIZE); 2032 void *kaddr = kmap(page);
2035 } else { 2033 stop = ((size += PAGE_SIZE) > limit) ||
2036 if (page == ZERO_PAGE(0)) { 2034 !dump_write(file, kaddr, PAGE_SIZE);
2037 if (!dump_seek(file, PAGE_SIZE)) { 2035 kunmap(page);
2038 page_cache_release(page);
2039 goto end_coredump;
2040 }
2041 } else {
2042 void *kaddr;
2043 flush_cache_page(tmp_vma, addr,
2044 page_to_pfn(page));
2045 kaddr = kmap(page);
2046 if ((size += PAGE_SIZE) > limit ||
2047 !dump_write(file, kaddr,
2048 PAGE_SIZE)) {
2049 kunmap(page);
2050 page_cache_release(page);
2051 goto end_coredump;
2052 }
2053 kunmap(page);
2054 }
2055 page_cache_release(page); 2036 page_cache_release(page);
2056 } 2037 } else
2038 stop = !dump_seek(file, PAGE_SIZE);
2039 if (stop)
2040 goto end_coredump;
2057 } 2041 }
2058 } 2042 }
2059 2043
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 20fbeced472b..76285471073e 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -1325,9 +1325,6 @@ static int writenote(struct memelfnote *men, struct file *file)
1325#define DUMP_WRITE(addr, nr) \ 1325#define DUMP_WRITE(addr, nr) \
1326 if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \ 1326 if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
1327 goto end_coredump; 1327 goto end_coredump;
1328#define DUMP_SEEK(off) \
1329 if (!dump_seek(file, (off))) \
1330 goto end_coredump;
1331 1328
1332static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs) 1329static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs)
1333{ 1330{
@@ -1518,6 +1515,7 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size,
1518 unsigned long *limit, unsigned long mm_flags) 1515 unsigned long *limit, unsigned long mm_flags)
1519{ 1516{
1520 struct vm_area_struct *vma; 1517 struct vm_area_struct *vma;
1518 int err = 0;
1521 1519
1522 for (vma = current->mm->mmap; vma; vma = vma->vm_next) { 1520 for (vma = current->mm->mmap; vma; vma = vma->vm_next) {
1523 unsigned long addr; 1521 unsigned long addr;
@@ -1525,43 +1523,26 @@ static int elf_fdpic_dump_segments(struct file *file, size_t *size,
1525 if (!maydump(vma, mm_flags)) 1523 if (!maydump(vma, mm_flags))
1526 continue; 1524 continue;
1527 1525
1528 for (addr = vma->vm_start; 1526 for (addr = vma->vm_start; addr < vma->vm_end;
1529 addr < vma->vm_end; 1527 addr += PAGE_SIZE) {
1530 addr += PAGE_SIZE 1528 struct page *page = get_dump_page(addr);
1531 ) { 1529 if (page) {
1532 struct vm_area_struct *vma; 1530 void *kaddr = kmap(page);
1533 struct page *page; 1531 *size += PAGE_SIZE;
1534 1532 if (*size > *limit)
1535 if (get_user_pages(current, current->mm, addr, 1, 0, 1, 1533 err = -EFBIG;
1536 &page, &vma) <= 0) { 1534 else if (!dump_write(file, kaddr, PAGE_SIZE))
1537 DUMP_SEEK(file->f_pos + PAGE_SIZE); 1535 err = -EIO;
1538 }
1539 else if (page == ZERO_PAGE(0)) {
1540 page_cache_release(page);
1541 DUMP_SEEK(file->f_pos + PAGE_SIZE);
1542 }
1543 else {
1544 void *kaddr;
1545
1546 flush_cache_page(vma, addr, page_to_pfn(page));
1547 kaddr = kmap(page);
1548 if ((*size += PAGE_SIZE) > *limit ||
1549 !dump_write(file, kaddr, PAGE_SIZE)
1550 ) {
1551 kunmap(page);
1552 page_cache_release(page);
1553 return -EIO;
1554 }
1555 kunmap(page); 1536 kunmap(page);
1556 page_cache_release(page); 1537 page_cache_release(page);
1557 } 1538 } else if (!dump_seek(file, file->f_pos + PAGE_SIZE))
1539 err = -EFBIG;
1540 if (err)
1541 goto out;
1558 } 1542 }
1559 } 1543 }
1560 1544out:
1561 return 0; 1545 return err;
1562
1563end_coredump:
1564 return -EFBIG;
1565} 1546}
1566#endif 1547#endif
1567 1548
@@ -1802,7 +1783,8 @@ static int elf_fdpic_core_dump(long signr, struct pt_regs *regs,
1802 goto end_coredump; 1783 goto end_coredump;
1803 } 1784 }
1804 1785
1805 DUMP_SEEK(dataoff); 1786 if (!dump_seek(file, dataoff))
1787 goto end_coredump;
1806 1788
1807 if (elf_fdpic_dump_segments(file, &size, &limit, mm_flags) < 0) 1789 if (elf_fdpic_dump_segments(file, &size, &limit, mm_flags) < 0)
1808 goto end_coredump; 1790 goto end_coredump;