diff options
author | Hugh Dickins <hugh.dickins@tiscali.co.uk> | 2009-09-21 20:03:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-22 10:17:40 -0400 |
commit | f3e8fccd06d27773186a0094371daf2d84c79469 (patch) | |
tree | 46e652e6ac3588a26c6d3e38ea10274eb3fc2ea8 /fs | |
parent | 1c3aff1ceec2cc86810e2690e67873ff0c505862 (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.c | 44 | ||||
-rw-r--r-- | fs/binfmt_elf_fdpic.c | 56 |
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 | ||
1287 | static void fill_elf_header(struct elfhdr *elf, int segs, | 1284 | static 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 | ||
1332 | static inline void fill_elf_fdpic_header(struct elfhdr *elf, int segs) | 1329 | static 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 | 1544 | out: | |
1561 | return 0; | 1545 | return err; |
1562 | |||
1563 | end_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; |