Re: [patch 1/1] alloc_pages(): permit get_zeroed_page(GFP_ATOMIC) from interrupt context

Andrew Morton
2007-08-27T21:04:40Z

On Mon, 27 Aug 2007 14:00:04 -0700 (PDT)
Christoph Lameter <clameter@sgi.com> wrote:

> On Mon, 27 Aug 2007, Andrew Morton wrote:
>
> > > > I think it makes sense to permit a non-BUGging get_zeroed_page(GFP_ATOMIC)
> > > > from interrupt context.
> > >
> > > AFAIK this works now. GFP_ATOMIC does not set __GFP_HIGHMEM and thus the
> > > check
> > >
> > > VM_BUG_ON((gfp_flags & __GFP_HIGHMEM) && in_interrupt());
> > >
> > > does not trigger
> >
> > The crash happens in
> >
> > clear_highpage
> > ->kmap_atomic
> > ->kmap_atomic_prot
> > ->BUG_ON(!pte_none(*(kmap_pte-idx)));
> >
> > ie: this CPU held a kmap slot when the interrupt happened.
>
> I guess I do not get what the problem is then. AFAIK: You cannot get there
> if you do a get_zeroed_page(GFP_ATOMIC). We should have bugged in
> get_zeroed_page() before we even got to clear_highpage.
>

: static inline void prep_zero_page(struct page *page, int order, gfp_t gfp_flags)
: {
: int i;
:
: VM_BUG_ON((gfp_flags & (__GFP_WAIT | __GFP_HIGHMEM)) == __GFP_HIGHMEM);

__GFP_HIGHMEM is not set.

: /*
: * clear_highpage() will use KM_USER0, so it's a bug to use __GFP_ZERO
: * and __GFP_HIGHMEM from hard or soft interrupt context.
: */
: VM_BUG_ON((gfp_flags & __GFP_HIGHMEM) && in_interrupt());

__GFP_HIGHMEM is not set

: for (i = 0; i < (1 << order); i++)
: clear_highpage(page + i);

kmap_atomic() goes boom.

: }