lkml.org 
[lkml]   [2010]   [Jul]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    SubjectRe: [RFC] Tight check of pfn_valid on sparsemem
    From
    On Tue, Jul 13, 2010 at 1:23 PM, KAMEZAWA Hiroyuki
    <kamezawa.hiroyu@jp.fujitsu.com> wrote:
    > On Tue, 13 Jul 2010 13:11:14 +0900
    > Minchan Kim <minchan.kim@gmail.com> wrote:
    >
    >> On Tue, Jul 13, 2010 at 12:19 PM, KAMEZAWA Hiroyuki
    >> <kamezawa.hiroyu@jp.fujitsu.com> wrote:
    >> > On Tue, 13 Jul 2010 00:53:48 +0900
    >> > Minchan Kim <minchan.kim@gmail.com> wrote:
    >> >
    >> >> Kukjin, Could you test below patch?
    >> >> I don't have any sparsemem system. Sorry.
    >> >>
    >> >> -- CUT DOWN HERE --
    >> >>
    >> >> Kukjin reported oops happen while he change min_free_kbytes
    >> >> http://www.spinics.net/lists/arm-kernel/msg92894.html
    >> >> It happen by memory map on sparsemem.
    >> >>
    >> >> The system has a memory map following as.
    >> >>      section 0             section 1              section 2
    >> >> 0x20000000-0x25000000, 0x40000000-0x50000000, 0x50000000-0x58000000
    >> >> SECTION_SIZE_BITS 28(256M)
    >> >>
    >> >> It means section 0 is an incompletely filled section.
    >> >> Nontheless, current pfn_valid of sparsemem checks pfn loosely.
    >> >>
    >> >> It checks only mem_section's validation.
    >> >> So in above case, pfn on 0x25000000 can pass pfn_valid's validation check.
    >> >> It's not what we want.
    >> >>
    >> >> The Following patch adds check valid pfn range check on pfn_valid of sparsemem.
    >> >>
    >> >> Signed-off-by: Minchan Kim <minchan.kim@gmail.com>
    >> >> Reported-by: Kukjin Kim <kgene.kim@samsung.com>
    >> >>
    >> >> P.S)
    >> >> It is just RFC. If we agree with this, I will make the patch on mmotm.
    >> >>
    >> >> --
    >> >>
    >> >> diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
    >> >> index b4d109e..6c2147a 100644
    >> >> --- a/include/linux/mmzone.h
    >> >> +++ b/include/linux/mmzone.h
    >> >> @@ -979,6 +979,8 @@ struct mem_section {
    >> >>         struct page_cgroup *page_cgroup;
    >> >>         unsigned long pad;
    >> >>  #endif
    >> >> +       unsigned long start_pfn;
    >> >> +       unsigned long end_pfn;
    >> >>  };
    >> >>
    >> >
    >> > I have 2 concerns.
    >> >  1. This makes mem_section twice. Wasting too much memory and not good for cache.
    >> >    But yes, you can put this under some CONFIG which has small number of mem_section[].
    >> >
    >>
    >> I think memory usage isn't a big deal. but for cache, we can move
    >> fields into just after section_mem_map.
    >>
    > I don't think so. This addtional field can eat up the amount of memory you saved
    > by unmap.

    Agree.

    >
    >> >  2. This can't be help for a case where a section has multiple small holes.
    >>
    >> I agree. But this(not punched hole but not filled section problem)
    >> isn't such case. But it would be better to handle it altogether. :)
    >>
    >> >
    >> > Then, my proposal for HOLES_IN_MEMMAP sparsemem is below.
    >> > ==
    >> > Some architectures unmap memmap[] for memory holes even with SPARSEMEM.
    >> > To handle that, pfn_valid() should check there are really memmap or not.
    >> > For that purpose, __get_user() can be used.
    >>
    >> Look at free_unused_memmap. We don't unmap pte of hole memmap.
    >> Is __get_use effective, still?
    >>
    > __get_user() works with TLB and page table, the vaddr is really mapped or not.
    > If you got SEGV, __get_user() returns -EFAULT. It works per page granule.

    I mean following as.
    For example, there is a struct page in on 0x20000000.

    int pfn_valid_mapped(unsigned long pfn)
    {
    struct page *page = pfn_to_page(pfn); /* hole page is 0x2000000 */
    char *lastbyte = (char *)(page+1)-1; /* lastbyte is 0x2000001f */
    char byte;

    /* We pass this test since free_unused_memmap doesn't unmap pte */
    if(__get_user(byte, page) != 0)
    return 0;
    /*
    * (0x20000000 & PAGE_MASK) == (0x2000001f & PAGE_MASK)
    * So, return 1, it is wrong result.
    */
    if ((((unsigned long)page) & PAGE_MASK) ==
    (((unsigned long)lastbyte) & PAGE_MASK))
    return 1;
    return (__get_user(byte,lastbyte) == 0);
    }

    Am I missing something?


    --
    Kind regards,
    Minchan Kim
    --
    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: 2010-07-13 08:07    [W:0.030 / U:118.160 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site