lkml.org 
[lkml]   [2005]   [Jan]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectRe: "kernel BUG at mm/rmap.c:474!" error on 2.6.9
    On Tue, 11 Jan 2005, Daniel Fenert wrote:
    > What could be the real cause of such messages? (I assume that it was not
    > really apache or php fault (httpd and php shown in logs below)).

    We still do not know; we'd very much like to know.

    It would not be the fault of any userspace program
    (unless they corrupt via /dev/mem or something like that).

    It may be a core kernel problem, but I've searched repeatedly and
    failed. It may be a driver problem e.g. GregKH's incident suggested
    a problem in DRM, and Andrea has pointed to a worrying ioctl there
    (looks like it could ClearPageReserved too early): I've been halfway
    through following that up for a few weeks now. Are you using DRM?
    (but the hallmarks in your case are different.)

    It can be caused by somewhere freeing a page it no longer holds;
    but in that case we'd usually expect to see the Bad page state
    error coming from free_pages_check rather than prep_new_page,
    and to be followed by the rmap.c BUG rather than following it.

    It could easily be caused by bad memory bitflipping in a page table
    (but in general, we'd expect to be hearing of swap_free errors,
    or random corruption, if that were generally the case - I think).
    Please give memtest86 a good run to rule out that possibility.

    If memtest86 is satifisfied, would you mind running with the patch
    below (against 2.6.9, suitable for i386 or x86_64, but not suitable
    for the various architectures which use PG_arch_1)? To give us more
    debug info - it's unlikely to solve the mystery on it's own, but I
    hope it might help us to look in the right direction. And send me
    any "Bad rmap" and "Bad page state" log entries you find (but
    perhaps this was a one-off, and nothing more will appear).

    Thanks,
    Hugh

    > Kernel 2.6.9, SATA drive on intel chipset (ICH5), processor is P4 with HT,
    > 1GB of memory. Glibc 2.3.2, gcc version 3.3.4.

    > Jan 11 10:00:44 sh kernel: kernel BUG at mm/rmap.c:474!
    > Jan 11 10:00:44 sh kernel: EIP is at page_remove_rmap+0x3f/0x53
    > Jan 11 10:00:44 sh kernel: eax: ffffffff ebx: 00000000 ecx: c17b4580 edx: c17b4580
    > Jan 11 10:00:44 sh kernel: esi: de3dd27c edi: c17b4580 ebp: 00000020 esp: ce236e84
    > Jan 11 10:01:01 sh kernel: Bad page state at prep_new_page (in process 'php', page c17b4580)
    > Jan 11 10:01:01 sh kernel: flags:0x40000114 mapping:00000000 mapcount:-1 count:0

    --- 2.6.9/include/linux/rmap.h 2004-10-18 22:55:54.000000000 +0100
    +++ linux/include/linux/rmap.h 2005-01-11 13:16:39.000000000 +0000
    @@ -71,7 +71,7 @@ void __anon_vma_link(struct vm_area_stru
    */
    void page_add_anon_rmap(struct page *, struct vm_area_struct *, unsigned long);
    void page_add_file_rmap(struct page *);
    -void page_remove_rmap(struct page *);
    +void page_remove_rmap(struct page *, struct vm_area_struct *, unsigned long);

    /**
    * page_dup_rmap - duplicate pte mapping to a page
    --- 2.6.9/mm/fremap.c 2004-10-18 22:55:54.000000000 +0100
    +++ linux/mm/fremap.c 2005-01-11 13:16:39.000000000 +0000
    @@ -36,7 +36,7 @@ static inline void zap_pte(struct mm_str
    if (!PageReserved(page)) {
    if (pte_dirty(pte))
    set_page_dirty(page);
    - page_remove_rmap(page);
    + page_remove_rmap(page, vma, addr);
    page_cache_release(page);
    mm->rss--;
    }
    --- 2.6.9/mm/memory.c 2004-10-18 22:56:29.000000000 +0100
    +++ linux/mm/memory.c 2005-01-11 13:16:39.000000000 +0000
    @@ -356,6 +356,7 @@ nomem:
    }

    static void zap_pte_range(struct mmu_gather *tlb,
    + struct vm_area_struct *vma,
    pmd_t *pmd, unsigned long address,
    unsigned long size, struct zap_details *details)
    {
    @@ -419,7 +420,7 @@ static void zap_pte_range(struct mmu_gat
    if (pte_young(pte) && !PageAnon(page))
    mark_page_accessed(page);
    tlb->freed++;
    - page_remove_rmap(page);
    + page_remove_rmap(page, vma, address+offset);
    tlb_remove_page(tlb, page);
    continue;
    }
    @@ -437,6 +438,7 @@ static void zap_pte_range(struct mmu_gat
    }

    static void zap_pmd_range(struct mmu_gather *tlb,
    + struct vm_area_struct *vma,
    pgd_t * dir, unsigned long address,
    unsigned long size, struct zap_details *details)
    {
    @@ -455,7 +457,7 @@ static void zap_pmd_range(struct mmu_gat
    if (end > ((address + PGDIR_SIZE) & PGDIR_MASK))
    end = ((address + PGDIR_SIZE) & PGDIR_MASK);
    do {
    - zap_pte_range(tlb, pmd, address, end - address, details);
    + zap_pte_range(tlb, vma, pmd, address, end - address, details);
    address = (address + PMD_SIZE) & PMD_MASK;
    pmd++;
    } while (address && (address < end));
    @@ -471,7 +473,7 @@ static void unmap_page_range(struct mmu_
    dir = pgd_offset(vma->vm_mm, address);
    tlb_start_vma(tlb, vma);
    do {
    - zap_pmd_range(tlb, dir, address, end - address, details);
    + zap_pmd_range(tlb, vma, dir, address, end - address, details);
    address = (address + PGDIR_SIZE) & PGDIR_MASK;
    dir++;
    } while (address && (address < end));
    @@ -1098,7 +1100,7 @@ static int do_wp_page(struct mm_struct *
    if (PageReserved(old_page))
    ++mm->rss;
    else
    - page_remove_rmap(old_page);
    + page_remove_rmap(old_page, vma, address);
    break_cow(vma, new_page, address, page_table);
    lru_cache_add_active(new_page);
    page_add_anon_rmap(new_page, vma, address);
    --- 2.6.9/mm/rmap.c 2004-10-18 22:57:03.000000000 +0100
    +++ linux/mm/rmap.c 2005-01-11 13:20:28.000000000 +0000
    @@ -453,8 +453,12 @@ void page_add_anon_rmap(struct page *pag
    void page_add_file_rmap(struct page *page)
    {
    BUG_ON(PageAnon(page));
    - if (!pfn_valid(page_to_pfn(page)) || PageReserved(page))
    + if (!pfn_valid(page_to_pfn(page)))
    return;
    + if (PageReserved(page)) {
    + set_bit(PG_arch_1, &page->flags);
    + return;
    + }

    if (atomic_inc_and_test(&page->_mapcount))
    inc_page_state(nr_mapped);
    @@ -466,12 +470,36 @@ void page_add_file_rmap(struct page *pag
    *
    * Caller needs to hold the mm->page_table_lock.
    */
    -void page_remove_rmap(struct page *page)
    +void page_remove_rmap(struct page *page,
    + struct vm_area_struct *vma, unsigned long address)
    {
    + struct address_space *mapping = NULL;
    + unsigned long index;
    +
    BUG_ON(PageReserved(page));

    + index = (address - vma->vm_start) >> PAGE_SHIFT;
    + index += vma->vm_pgoff;
    +
    + if (PageAnon(page))
    + mapping = (void *) vma->anon_vma + PAGE_MAPPING_ANON;
    + else if (!(vma->vm_flags & (VM_IO|VM_RESERVED)))
    + mapping = vma->vm_file? vma->vm_file->f_mapping: (void *)(-1);
    +
    + if (page_mapcount(page) <= 0 || page_count(page) <= 0 ||
    + (mapping && (mapping != page->mapping || index != page->index)) ||
    + test_bit(PG_arch_1, &page->flags)) {
    + printk("Bad rmap in %s: page %p flags %lx "
    + "count %d mapcount %d addr %lx vm_flags %lx\n",
    + current->comm, page, (unsigned long)page->flags,
    + page_count(page), page_mapcount(page), address,
    + vma->vm_flags);
    + printk("\tpage mapping %p index %lx vma mapping %p index %lx\n",
    + page->mapping, page->index, mapping, index);
    + get_page(page);
    + return;
    + }
    if (atomic_add_negative(-1, &page->_mapcount)) {
    - BUG_ON(page_mapcount(page) < 0);
    /*
    * It would be tidy to reset the PageAnon mapping here,
    * but that might overwrite a racing page_add_anon_rmap
    @@ -581,7 +609,7 @@ static int try_to_unmap_one(struct page
    }

    mm->rss--;
    - page_remove_rmap(page);
    + page_remove_rmap(page, vma, address);
    page_cache_release(page);

    out_unmap:
    @@ -678,7 +706,7 @@ static void try_to_unmap_cluster(unsigne
    if (pte_dirty(pteval))
    set_page_dirty(page);

    - page_remove_rmap(page);
    + page_remove_rmap(page, vma, address);
    page_cache_release(page);
    mm->rss--;
    (*mapcount)--;
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2005-03-22 14:09    [W:0.031 / U:60.976 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site