diff options
| author | Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> | 2014-07-23 17:00:01 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-07-23 18:10:54 -0400 |
| commit | a0f7a756c2f7543585657cdeeefdfcc11b567293 (patch) | |
| tree | 05ddd356f6aa17f826a1923d8601dd3c78f7fbbc /include/linux | |
| parent | aed8adb7688d5744cb484226820163af31d2499a (diff) | |
mm/rmap.c: fix pgoff calculation to handle hugepage correctly
I triggered VM_BUG_ON() in vma_address() when I tried to migrate an
anonymous hugepage with mbind() in the kernel v3.16-rc3. This is
because pgoff's calculation in rmap_walk_anon() fails to consider
compound_order() only to have an incorrect value.
This patch introduces page_to_pgoff(), which gets the page's offset in
PAGE_CACHE_SIZE.
Kirill pointed out that page cache tree should natively handle
hugepages, and in order to make hugetlbfs fit it, page->index of
hugetlbfs page should be in PAGE_CACHE_SIZE. This is beyond this patch,
but page_to_pgoff() contains the point to be fixed in a single function.
Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Hillf Danton <dhillf@gmail.com>
Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/pagemap.h | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 0a97b583ee8d..e1474ae18c88 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h | |||
| @@ -399,6 +399,18 @@ static inline struct page *read_mapping_page(struct address_space *mapping, | |||
| 399 | } | 399 | } |
| 400 | 400 | ||
| 401 | /* | 401 | /* |
| 402 | * Get the offset in PAGE_SIZE. | ||
| 403 | * (TODO: hugepage should have ->index in PAGE_SIZE) | ||
| 404 | */ | ||
| 405 | static inline pgoff_t page_to_pgoff(struct page *page) | ||
| 406 | { | ||
| 407 | if (unlikely(PageHeadHuge(page))) | ||
| 408 | return page->index << compound_order(page); | ||
| 409 | else | ||
| 410 | return page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); | ||
| 411 | } | ||
| 412 | |||
| 413 | /* | ||
| 402 | * Return byte-offset into filesystem object for page. | 414 | * Return byte-offset into filesystem object for page. |
| 403 | */ | 415 | */ |
| 404 | static inline loff_t page_offset(struct page *page) | 416 | static inline loff_t page_offset(struct page *page) |
