diff options
-rw-r--r-- | include/linux/hugetlb.h | 2 | ||||
-rw-r--r-- | mm/hugetlb.c | 27 |
2 files changed, 20 insertions, 9 deletions
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 35afca1692fb..1222fb07a746 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h | |||
@@ -333,6 +333,8 @@ struct huge_bootmem_page { | |||
333 | struct page *alloc_huge_page_node(struct hstate *h, int nid); | 333 | struct page *alloc_huge_page_node(struct hstate *h, int nid); |
334 | struct page *alloc_huge_page_noerr(struct vm_area_struct *vma, | 334 | struct page *alloc_huge_page_noerr(struct vm_area_struct *vma, |
335 | unsigned long addr, int avoid_reserve); | 335 | unsigned long addr, int avoid_reserve); |
336 | int huge_add_to_page_cache(struct page *page, struct address_space *mapping, | ||
337 | pgoff_t idx); | ||
336 | 338 | ||
337 | /* arch callback */ | 339 | /* arch callback */ |
338 | int __init alloc_bootmem_huge_page(struct hstate *h); | 340 | int __init alloc_bootmem_huge_page(struct hstate *h); |
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 114ad6ce7030..d45eacc5653e 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -3375,6 +3375,23 @@ static bool hugetlbfs_pagecache_present(struct hstate *h, | |||
3375 | return page != NULL; | 3375 | return page != NULL; |
3376 | } | 3376 | } |
3377 | 3377 | ||
3378 | int huge_add_to_page_cache(struct page *page, struct address_space *mapping, | ||
3379 | pgoff_t idx) | ||
3380 | { | ||
3381 | struct inode *inode = mapping->host; | ||
3382 | struct hstate *h = hstate_inode(inode); | ||
3383 | int err = add_to_page_cache(page, mapping, idx, GFP_KERNEL); | ||
3384 | |||
3385 | if (err) | ||
3386 | return err; | ||
3387 | ClearPagePrivate(page); | ||
3388 | |||
3389 | spin_lock(&inode->i_lock); | ||
3390 | inode->i_blocks += blocks_per_huge_page(h); | ||
3391 | spin_unlock(&inode->i_lock); | ||
3392 | return 0; | ||
3393 | } | ||
3394 | |||
3378 | static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma, | 3395 | static int hugetlb_no_page(struct mm_struct *mm, struct vm_area_struct *vma, |
3379 | struct address_space *mapping, pgoff_t idx, | 3396 | struct address_space *mapping, pgoff_t idx, |
3380 | unsigned long address, pte_t *ptep, unsigned int flags) | 3397 | unsigned long address, pte_t *ptep, unsigned int flags) |
@@ -3422,21 +3439,13 @@ retry: | |||
3422 | set_page_huge_active(page); | 3439 | set_page_huge_active(page); |
3423 | 3440 | ||
3424 | if (vma->vm_flags & VM_MAYSHARE) { | 3441 | if (vma->vm_flags & VM_MAYSHARE) { |
3425 | int err; | 3442 | int err = huge_add_to_page_cache(page, mapping, idx); |
3426 | struct inode *inode = mapping->host; | ||
3427 | |||
3428 | err = add_to_page_cache(page, mapping, idx, GFP_KERNEL); | ||
3429 | if (err) { | 3443 | if (err) { |
3430 | put_page(page); | 3444 | put_page(page); |
3431 | if (err == -EEXIST) | 3445 | if (err == -EEXIST) |
3432 | goto retry; | 3446 | goto retry; |
3433 | goto out; | 3447 | goto out; |
3434 | } | 3448 | } |
3435 | ClearPagePrivate(page); | ||
3436 | |||
3437 | spin_lock(&inode->i_lock); | ||
3438 | inode->i_blocks += blocks_per_huge_page(h); | ||
3439 | spin_unlock(&inode->i_lock); | ||
3440 | } else { | 3449 | } else { |
3441 | lock_page(page); | 3450 | lock_page(page); |
3442 | if (unlikely(anon_vma_prepare(vma))) { | 3451 | if (unlikely(anon_vma_prepare(vma))) { |