1 From f83a275dbc5ca1721143698e844243fcadfabf6a Mon Sep 17 00:00:00 2001
2 From: Mel Gorman <mel@csn.ul.ie>
3 Date: Thu, 28 May 2009 14:34:40 -0700
4 Subject: mm: account for MAP_SHARED mappings using VM_MAYSHARE and not VM_SHARED in hugetlbfs
6 From: Mel Gorman <mel@csn.ul.ie>
8 commit f83a275dbc5ca1721143698e844243fcadfabf6a upstream.
10 Addresses http://bugzilla.kernel.org/show_bug.cgi?id=13302
12 hugetlbfs reserves huge pages but does not fault them at mmap() time to
13 ensure that future faults succeed. The reservation behaviour differs
14 depending on whether the mapping was mapped MAP_SHARED or MAP_PRIVATE.
15 For MAP_SHARED mappings, hugepages are reserved when mmap() is first
16 called and are tracked based on information associated with the inode.
17 Other processes mapping MAP_SHARED use the same reservation. MAP_PRIVATE
18 track the reservations based on the VMA created as part of the mmap()
19 operation. Each process mapping MAP_PRIVATE must make its own
22 hugetlbfs currently checks if a VMA is MAP_SHARED with the VM_SHARED flag
23 and not VM_MAYSHARE. For file-backed mappings, such as hugetlbfs,
24 VM_SHARED is set only if the mapping is MAP_SHARED and the file was opened
25 read-write. If a shared memory mapping was mapped shared-read-write for
26 populating of data and mapped shared-read-only by other processes, then
27 hugetlbfs would account for the mapping as if it was MAP_PRIVATE. This
28 causes processes to fail to map the file MAP_SHARED even though it should
29 succeed as the reservation is there.
31 This patch alters mm/hugetlb.c and replaces VM_SHARED with VM_MAYSHARE
32 when the intent of the code was to check whether the VMA was mapped
33 MAP_SHARED or MAP_PRIVATE.
35 Signed-off-by: Mel Gorman <mel@csn.ul.ie>
36 Cc: Hugh Dickins <hugh.dickins@tiscali.co.uk>
37 Cc: Ingo Molnar <mingo@elte.hu>
38 Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
39 Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
40 Cc: <starlight@binnacle.cx>
41 Cc: Eric B Munson <ebmunson@us.ibm.com>
42 Cc: Adam Litke <agl@us.ibm.com>
43 Cc: Andy Whitcroft <apw@canonical.com>
44 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
45 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
46 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
49 mm/hugetlb.c | 26 +++++++++++++-------------
50 1 file changed, 13 insertions(+), 13 deletions(-)
54 @@ -286,7 +286,7 @@ void resv_map_release(struct kref *ref)
55 static struct resv_map *vma_resv_map(struct vm_area_struct *vma)
57 VM_BUG_ON(!is_vm_hugetlb_page(vma));
58 - if (!(vma->vm_flags & VM_SHARED))
59 + if (!(vma->vm_flags & VM_MAYSHARE))
60 return (struct resv_map *)(get_vma_private_data(vma) &
63 @@ -295,7 +295,7 @@ static struct resv_map *vma_resv_map(str
64 static void set_vma_resv_map(struct vm_area_struct *vma, struct resv_map *map)
66 VM_BUG_ON(!is_vm_hugetlb_page(vma));
67 - VM_BUG_ON(vma->vm_flags & VM_SHARED);
68 + VM_BUG_ON(vma->vm_flags & VM_MAYSHARE);
70 set_vma_private_data(vma, (get_vma_private_data(vma) &
71 HPAGE_RESV_MASK) | (unsigned long)map);
72 @@ -304,7 +304,7 @@ static void set_vma_resv_map(struct vm_a
73 static void set_vma_resv_flags(struct vm_area_struct *vma, unsigned long flags)
75 VM_BUG_ON(!is_vm_hugetlb_page(vma));
76 - VM_BUG_ON(vma->vm_flags & VM_SHARED);
77 + VM_BUG_ON(vma->vm_flags & VM_MAYSHARE);
79 set_vma_private_data(vma, get_vma_private_data(vma) | flags);
81 @@ -323,7 +323,7 @@ static void decrement_hugepage_resv_vma(
82 if (vma->vm_flags & VM_NORESERVE)
85 - if (vma->vm_flags & VM_SHARED) {
86 + if (vma->vm_flags & VM_MAYSHARE) {
87 /* Shared mappings always use reserves */
89 } else if (is_vma_resv_set(vma, HPAGE_RESV_OWNER)) {
90 @@ -339,14 +339,14 @@ static void decrement_hugepage_resv_vma(
91 void reset_vma_resv_huge_pages(struct vm_area_struct *vma)
93 VM_BUG_ON(!is_vm_hugetlb_page(vma));
94 - if (!(vma->vm_flags & VM_SHARED))
95 + if (!(vma->vm_flags & VM_MAYSHARE))
96 vma->vm_private_data = (void *)0;
99 /* Returns true if the VMA has associated reserve pages */
100 static int vma_has_reserves(struct vm_area_struct *vma)
102 - if (vma->vm_flags & VM_SHARED)
103 + if (vma->vm_flags & VM_MAYSHARE)
105 if (is_vma_resv_set(vma, HPAGE_RESV_OWNER))
107 @@ -890,7 +890,7 @@ static int vma_needs_reservation(struct
108 struct address_space *mapping = vma->vm_file->f_mapping;
109 struct inode *inode = mapping->host;
111 - if (vma->vm_flags & VM_SHARED) {
112 + if (vma->vm_flags & VM_MAYSHARE) {
113 pgoff_t idx = vma_hugecache_offset(h, vma, addr);
114 return region_chg(&inode->i_mapping->private_list,
116 @@ -915,7 +915,7 @@ static void vma_commit_reservation(struc
117 struct address_space *mapping = vma->vm_file->f_mapping;
118 struct inode *inode = mapping->host;
120 - if (vma->vm_flags & VM_SHARED) {
121 + if (vma->vm_flags & VM_MAYSHARE) {
122 pgoff_t idx = vma_hugecache_offset(h, vma, addr);
123 region_add(&inode->i_mapping->private_list, idx, idx + 1);
125 @@ -1862,7 +1862,7 @@ retry_avoidcopy:
126 * at the time of fork() could consume its reserves on COW instead
127 * of the full address range.
129 - if (!(vma->vm_flags & VM_SHARED) &&
130 + if (!(vma->vm_flags & VM_MAYSHARE) &&
131 is_vma_resv_set(vma, HPAGE_RESV_OWNER) &&
132 old_page != pagecache_page)
134 @@ -1969,7 +1969,7 @@ retry:
135 clear_huge_page(page, address, huge_page_size(h));
136 __SetPageUptodate(page);
138 - if (vma->vm_flags & VM_SHARED) {
139 + if (vma->vm_flags & VM_MAYSHARE) {
141 struct inode *inode = mapping->host;
143 @@ -2073,7 +2073,7 @@ int hugetlb_fault(struct mm_struct *mm,
147 - if (!(vma->vm_flags & VM_SHARED))
148 + if (!(vma->vm_flags & VM_MAYSHARE))
149 pagecache_page = hugetlbfs_pagecache_page(h,
152 @@ -2223,7 +2223,7 @@ int hugetlb_reserve_pages(struct inode *
153 * to reserve the full area even if read-only as mprotect() may be
154 * called to make the mapping read-write. Assume !vma is a shm mapping
156 - if (!vma || vma->vm_flags & VM_SHARED)
157 + if (!vma || vma->vm_flags & VM_MAYSHARE)
158 chg = region_chg(&inode->i_mapping->private_list, from, to);
160 struct resv_map *resv_map = resv_map_alloc();
161 @@ -2246,7 +2246,7 @@ int hugetlb_reserve_pages(struct inode *
162 hugetlb_put_quota(inode->i_mapping, chg);
165 - if (!vma || vma->vm_flags & VM_SHARED)
166 + if (!vma || vma->vm_flags & VM_MAYSHARE)
167 region_add(&inode->i_mapping->private_list, from, to);