diff options
Diffstat (limited to 'mm/nommu.c')
-rw-r--r-- | mm/nommu.c | 50 |
1 files changed, 19 insertions, 31 deletions
diff --git a/mm/nommu.c b/mm/nommu.c index bd1808e194a7..b51eadf6d952 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
@@ -722,11 +722,11 @@ static void add_vma_to_mm(struct mm_struct *mm, struct vm_area_struct *vma) | |||
722 | if (vma->vm_file) { | 722 | if (vma->vm_file) { |
723 | mapping = vma->vm_file->f_mapping; | 723 | mapping = vma->vm_file->f_mapping; |
724 | 724 | ||
725 | mutex_lock(&mapping->i_mmap_mutex); | 725 | i_mmap_lock_write(mapping); |
726 | flush_dcache_mmap_lock(mapping); | 726 | flush_dcache_mmap_lock(mapping); |
727 | vma_interval_tree_insert(vma, &mapping->i_mmap); | 727 | vma_interval_tree_insert(vma, &mapping->i_mmap); |
728 | flush_dcache_mmap_unlock(mapping); | 728 | flush_dcache_mmap_unlock(mapping); |
729 | mutex_unlock(&mapping->i_mmap_mutex); | 729 | i_mmap_unlock_write(mapping); |
730 | } | 730 | } |
731 | 731 | ||
732 | /* add the VMA to the tree */ | 732 | /* add the VMA to the tree */ |
@@ -795,11 +795,11 @@ static void delete_vma_from_mm(struct vm_area_struct *vma) | |||
795 | if (vma->vm_file) { | 795 | if (vma->vm_file) { |
796 | mapping = vma->vm_file->f_mapping; | 796 | mapping = vma->vm_file->f_mapping; |
797 | 797 | ||
798 | mutex_lock(&mapping->i_mmap_mutex); | 798 | i_mmap_lock_write(mapping); |
799 | flush_dcache_mmap_lock(mapping); | 799 | flush_dcache_mmap_lock(mapping); |
800 | vma_interval_tree_remove(vma, &mapping->i_mmap); | 800 | vma_interval_tree_remove(vma, &mapping->i_mmap); |
801 | flush_dcache_mmap_unlock(mapping); | 801 | flush_dcache_mmap_unlock(mapping); |
802 | mutex_unlock(&mapping->i_mmap_mutex); | 802 | i_mmap_unlock_write(mapping); |
803 | } | 803 | } |
804 | 804 | ||
805 | /* remove from the MM's tree and list */ | 805 | /* remove from the MM's tree and list */ |
@@ -1149,8 +1149,7 @@ static int do_mmap_private(struct vm_area_struct *vma, | |||
1149 | unsigned long len, | 1149 | unsigned long len, |
1150 | unsigned long capabilities) | 1150 | unsigned long capabilities) |
1151 | { | 1151 | { |
1152 | struct page *pages; | 1152 | unsigned long total, point; |
1153 | unsigned long total, point, n; | ||
1154 | void *base; | 1153 | void *base; |
1155 | int ret, order; | 1154 | int ret, order; |
1156 | 1155 | ||
@@ -1182,33 +1181,23 @@ static int do_mmap_private(struct vm_area_struct *vma, | |||
1182 | order = get_order(len); | 1181 | order = get_order(len); |
1183 | kdebug("alloc order %d for %lx", order, len); | 1182 | kdebug("alloc order %d for %lx", order, len); |
1184 | 1183 | ||
1185 | pages = alloc_pages(GFP_KERNEL, order); | ||
1186 | if (!pages) | ||
1187 | goto enomem; | ||
1188 | |||
1189 | total = 1 << order; | 1184 | total = 1 << order; |
1190 | atomic_long_add(total, &mmap_pages_allocated); | ||
1191 | |||
1192 | point = len >> PAGE_SHIFT; | 1185 | point = len >> PAGE_SHIFT; |
1193 | 1186 | ||
1194 | /* we allocated a power-of-2 sized page set, so we may want to trim off | 1187 | /* we don't want to allocate a power-of-2 sized page set */ |
1195 | * the excess */ | ||
1196 | if (sysctl_nr_trim_pages && total - point >= sysctl_nr_trim_pages) { | 1188 | if (sysctl_nr_trim_pages && total - point >= sysctl_nr_trim_pages) { |
1197 | while (total > point) { | 1189 | total = point; |
1198 | order = ilog2(total - point); | 1190 | kdebug("try to alloc exact %lu pages", total); |
1199 | n = 1 << order; | 1191 | base = alloc_pages_exact(len, GFP_KERNEL); |
1200 | kdebug("shave %lu/%lu @%lu", n, total - point, total); | 1192 | } else { |
1201 | atomic_long_sub(n, &mmap_pages_allocated); | 1193 | base = (void *)__get_free_pages(GFP_KERNEL, order); |
1202 | total -= n; | ||
1203 | set_page_refcounted(pages + total); | ||
1204 | __free_pages(pages + total, order); | ||
1205 | } | ||
1206 | } | 1194 | } |
1207 | 1195 | ||
1208 | for (point = 1; point < total; point++) | 1196 | if (!base) |
1209 | set_page_refcounted(&pages[point]); | 1197 | goto enomem; |
1198 | |||
1199 | atomic_long_add(total, &mmap_pages_allocated); | ||
1210 | 1200 | ||
1211 | base = page_address(pages); | ||
1212 | region->vm_flags = vma->vm_flags |= VM_MAPPED_COPY; | 1201 | region->vm_flags = vma->vm_flags |= VM_MAPPED_COPY; |
1213 | region->vm_start = (unsigned long) base; | 1202 | region->vm_start = (unsigned long) base; |
1214 | region->vm_end = region->vm_start + len; | 1203 | region->vm_end = region->vm_start + len; |
@@ -2094,14 +2083,14 @@ int nommu_shrink_inode_mappings(struct inode *inode, size_t size, | |||
2094 | high = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; | 2083 | high = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; |
2095 | 2084 | ||
2096 | down_write(&nommu_region_sem); | 2085 | down_write(&nommu_region_sem); |
2097 | mutex_lock(&inode->i_mapping->i_mmap_mutex); | 2086 | i_mmap_lock_read(inode->i_mapping); |
2098 | 2087 | ||
2099 | /* search for VMAs that fall within the dead zone */ | 2088 | /* search for VMAs that fall within the dead zone */ |
2100 | vma_interval_tree_foreach(vma, &inode->i_mapping->i_mmap, low, high) { | 2089 | vma_interval_tree_foreach(vma, &inode->i_mapping->i_mmap, low, high) { |
2101 | /* found one - only interested if it's shared out of the page | 2090 | /* found one - only interested if it's shared out of the page |
2102 | * cache */ | 2091 | * cache */ |
2103 | if (vma->vm_flags & VM_SHARED) { | 2092 | if (vma->vm_flags & VM_SHARED) { |
2104 | mutex_unlock(&inode->i_mapping->i_mmap_mutex); | 2093 | i_mmap_unlock_read(inode->i_mapping); |
2105 | up_write(&nommu_region_sem); | 2094 | up_write(&nommu_region_sem); |
2106 | return -ETXTBSY; /* not quite true, but near enough */ | 2095 | return -ETXTBSY; /* not quite true, but near enough */ |
2107 | } | 2096 | } |
@@ -2113,8 +2102,7 @@ int nommu_shrink_inode_mappings(struct inode *inode, size_t size, | |||
2113 | * we don't check for any regions that start beyond the EOF as there | 2102 | * we don't check for any regions that start beyond the EOF as there |
2114 | * shouldn't be any | 2103 | * shouldn't be any |
2115 | */ | 2104 | */ |
2116 | vma_interval_tree_foreach(vma, &inode->i_mapping->i_mmap, | 2105 | vma_interval_tree_foreach(vma, &inode->i_mapping->i_mmap, 0, ULONG_MAX) { |
2117 | 0, ULONG_MAX) { | ||
2118 | if (!(vma->vm_flags & VM_SHARED)) | 2106 | if (!(vma->vm_flags & VM_SHARED)) |
2119 | continue; | 2107 | continue; |
2120 | 2108 | ||
@@ -2129,7 +2117,7 @@ int nommu_shrink_inode_mappings(struct inode *inode, size_t size, | |||
2129 | } | 2117 | } |
2130 | } | 2118 | } |
2131 | 2119 | ||
2132 | mutex_unlock(&inode->i_mapping->i_mmap_mutex); | 2120 | i_mmap_unlock_read(inode->i_mapping); |
2133 | up_write(&nommu_region_sem); | 2121 | up_write(&nommu_region_sem); |
2134 | return 0; | 2122 | return 0; |
2135 | } | 2123 | } |