page-flags: define PG_locked behavior on compound pages
lock_page() must operate on the whole compound page. It doesn't make much sense to lock part of compound page. Change code to use head page's PG_locked, if tail page is passed. This patch also gets rid of custom helper functions -- __set_page_locked() and __clear_page_locked(). They are replaced with helpers generated by __SETPAGEFLAG/__CLEARPAGEFLAG. Tail pages to these helper would trigger VM_BUG_ON(). SLUB uses PG_locked as a bit spin locked. IIUC, tail pages should never appear there. VM_BUG_ON() is added to make sure that this assumption is correct. [akpm@linux-foundation.org: fix fs/cifs/file.c] Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: Hugh Dickins <hughd@google.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Mel Gorman <mgorman@suse.de> Cc: Rik van Riel <riel@redhat.com> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Christoph Lameter <cl@linux.com> Cc: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Cc: Steve Capper <steve.capper@linaro.org> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Michal Hocko <mhocko@suse.cz> Cc: Jerome Marchand <jmarchan@redhat.com> Cc: Jérôme Glisse <jglisse@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
committed by
Linus Torvalds
parent
95ad97554a
commit
48c935ad88
@@ -433,18 +433,9 @@ extern int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
|
||||
unsigned int flags);
|
||||
extern void unlock_page(struct page *page);
|
||||
|
||||
static inline void __set_page_locked(struct page *page)
|
||||
{
|
||||
__set_bit(PG_locked, &page->flags);
|
||||
}
|
||||
|
||||
static inline void __clear_page_locked(struct page *page)
|
||||
{
|
||||
__clear_bit(PG_locked, &page->flags);
|
||||
}
|
||||
|
||||
static inline int trylock_page(struct page *page)
|
||||
{
|
||||
page = compound_head(page);
|
||||
return (likely(!test_and_set_bit_lock(PG_locked, &page->flags)));
|
||||
}
|
||||
|
||||
@@ -497,9 +488,9 @@ extern int wait_on_page_bit_killable_timeout(struct page *page,
|
||||
|
||||
static inline int wait_on_page_locked_killable(struct page *page)
|
||||
{
|
||||
if (PageLocked(page))
|
||||
return wait_on_page_bit_killable(page, PG_locked);
|
||||
return 0;
|
||||
if (!PageLocked(page))
|
||||
return 0;
|
||||
return wait_on_page_bit_killable(compound_head(page), PG_locked);
|
||||
}
|
||||
|
||||
extern wait_queue_head_t *page_waitqueue(struct page *page);
|
||||
@@ -518,7 +509,7 @@ static inline void wake_up_page(struct page *page, int bit)
|
||||
static inline void wait_on_page_locked(struct page *page)
|
||||
{
|
||||
if (PageLocked(page))
|
||||
wait_on_page_bit(page, PG_locked);
|
||||
wait_on_page_bit(compound_head(page), PG_locked);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -664,17 +655,17 @@ int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask);
|
||||
|
||||
/*
|
||||
* Like add_to_page_cache_locked, but used to add newly allocated pages:
|
||||
* the page is new, so we can just run __set_page_locked() against it.
|
||||
* the page is new, so we can just run __SetPageLocked() against it.
|
||||
*/
|
||||
static inline int add_to_page_cache(struct page *page,
|
||||
struct address_space *mapping, pgoff_t offset, gfp_t gfp_mask)
|
||||
{
|
||||
int error;
|
||||
|
||||
__set_page_locked(page);
|
||||
__SetPageLocked(page);
|
||||
error = add_to_page_cache_locked(page, mapping, offset, gfp_mask);
|
||||
if (unlikely(error))
|
||||
__clear_page_locked(page);
|
||||
__ClearPageLocked(page);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user