On Wed, Nov 03, 2010 at 04:27:40PM +0100, Andrea Arcangeli wrote: > From: Andrea Arcangeli <aarcange@xxxxxxxxxx> > > Add a new compound_lock() needed to serialize put_page against > __split_huge_page_refcount(). > Does it only apply to a compound page? If I pass in a PageTail, what happens? Could do with a beefier description on why it's needed but maybe it's obvious later. > Signed-off-by: Andrea Arcangeli <aarcange@xxxxxxxxxx> > Acked-by: Rik van Riel <riel@xxxxxxxxxx> > --- > > diff --git a/include/linux/mm.h b/include/linux/mm.h > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -14,6 +14,7 @@ > #include <linux/mm_types.h> > #include <linux/range.h> > #include <linux/pfn.h> > +#include <linux/bit_spinlock.h> > > struct mempolicy; > struct anon_vma; > @@ -302,6 +303,40 @@ static inline int is_vmalloc_or_module_a > } > #endif > > +static inline void compound_lock(struct page *page) > +{ > +#ifdef CONFIG_TRANSPARENT_HUGEPAGE > + bit_spin_lock(PG_compound_lock, &page->flags); > +#endif > +} > + > +static inline void compound_unlock(struct page *page) > +{ > +#ifdef CONFIG_TRANSPARENT_HUGEPAGE > + bit_spin_unlock(PG_compound_lock, &page->flags); > +#endif > +} > + > +static inline void compound_lock_irqsave(struct page *page, > + unsigned long *flagsp) > +{ > +#ifdef CONFIG_TRANSPARENT_HUGEPAGE > + unsigned long flags; > + local_irq_save(flags); > + compound_lock(page); > + *flagsp = flags; > +#endif > +} > + The pattern for spinlock irqsave passes in unsigned long, not unsigned long *. It'd be nice if they matched. > +static inline void compound_unlock_irqrestore(struct page *page, > + unsigned long flags) > +{ > +#ifdef CONFIG_TRANSPARENT_HUGEPAGE > + compound_unlock(page); > + local_irq_restore(flags); > +#endif > +} > + > static inline struct page *compound_head(struct page *page) > { > if (unlikely(PageTail(page))) > diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h > --- a/include/linux/page-flags.h > +++ b/include/linux/page-flags.h > @@ -108,6 +108,9 @@ enum pageflags { > #ifdef CONFIG_MEMORY_FAILURE > PG_hwpoison, /* hardware poisoned page. Don't touch */ > #endif > +#ifdef CONFIG_TRANSPARENT_HUGEPAGE > + PG_compound_lock, > +#endif > __NR_PAGEFLAGS, > > /* Filesystems */ > @@ -397,6 +400,12 @@ static inline void __ClearPageTail(struc > #define __PG_MLOCKED 0 > #endif > > +#ifdef CONFIG_TRANSPARENT_HUGEPAGE > +#define __PG_COMPOUND_LOCK (1 << PG_compound_lock) > +#else > +#define __PG_COMPOUND_LOCK 0 > +#endif > + > /* > * Flags checked when a page is freed. Pages being freed should not have > * these flags set. It they are, there is a problem. > @@ -406,7 +415,8 @@ static inline void __ClearPageTail(struc > 1 << PG_private | 1 << PG_private_2 | \ > 1 << PG_buddy | 1 << PG_writeback | 1 << PG_reserved | \ > 1 << PG_slab | 1 << PG_swapcache | 1 << PG_active | \ > - 1 << PG_unevictable | __PG_MLOCKED | __PG_HWPOISON) > + 1 << PG_unevictable | __PG_MLOCKED | __PG_HWPOISON | \ > + __PG_COMPOUND_LOCK) > > /* > * Flags checked when a page is prepped for return by the page allocator. > -- Mel Gorman Part-time Phd Student Linux Technology Center University of Limerick IBM Dublin Software Lab -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxxx For more info on Linux MM, see: http://www.linux-mm.org/ . Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/ Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>