aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorDave Kleikamp <shaggy@austin.ibm.com>2005-08-04 16:56:15 -0400
committerDave Kleikamp <shaggy@austin.ibm.com>2005-08-04 16:56:15 -0400
commita5c96cab8f3c4ca9b2177dceb5de5a0edb31418e (patch)
tree45692a1b3d770f721f4586ad81c206f1b8509b75 /mm
parent30db1ae8640d3527ca7ac8df4bcbf14ccc6ae9cd (diff)
parent1c5ad84516ae7ea4ec868436a910a6bd8d20215a (diff)
Merge with /home/shaggy/git/linus-clean/
Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
Diffstat (limited to 'mm')
-rw-r--r--mm/memory.c48
-rw-r--r--mm/mempolicy.c2
-rw-r--r--mm/mremap.c2
-rw-r--r--mm/page_alloc.c21
4 files changed, 41 insertions, 32 deletions
diff --git a/mm/memory.c b/mm/memory.c
index 6fe77acbc1..e046b7e4b5 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -913,9 +913,13 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
913 pud = pud_offset(pgd, pg); 913 pud = pud_offset(pgd, pg);
914 BUG_ON(pud_none(*pud)); 914 BUG_ON(pud_none(*pud));
915 pmd = pmd_offset(pud, pg); 915 pmd = pmd_offset(pud, pg);
916 BUG_ON(pmd_none(*pmd)); 916 if (pmd_none(*pmd))
917 return i ? : -EFAULT;
917 pte = pte_offset_map(pmd, pg); 918 pte = pte_offset_map(pmd, pg);
918 BUG_ON(pte_none(*pte)); 919 if (pte_none(*pte)) {
920 pte_unmap(pte);
921 return i ? : -EFAULT;
922 }
919 if (pages) { 923 if (pages) {
920 pages[i] = pte_page(*pte); 924 pages[i] = pte_page(*pte);
921 get_page(pages[i]); 925 get_page(pages[i]);
@@ -940,11 +944,13 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
940 } 944 }
941 spin_lock(&mm->page_table_lock); 945 spin_lock(&mm->page_table_lock);
942 do { 946 do {
947 int write_access = write;
943 struct page *page; 948 struct page *page;
944 int lookup_write = write;
945 949
946 cond_resched_lock(&mm->page_table_lock); 950 cond_resched_lock(&mm->page_table_lock);
947 while (!(page = follow_page(mm, start, lookup_write))) { 951 while (!(page = follow_page(mm, start, write_access))) {
952 int ret;
953
948 /* 954 /*
949 * Shortcut for anonymous pages. We don't want 955 * Shortcut for anonymous pages. We don't want
950 * to force the creation of pages tables for 956 * to force the creation of pages tables for
@@ -952,13 +958,23 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
952 * nobody touched so far. This is important 958 * nobody touched so far. This is important
953 * for doing a core dump for these mappings. 959 * for doing a core dump for these mappings.
954 */ 960 */
955 if (!lookup_write && 961 if (!write && untouched_anonymous_page(mm,vma,start)) {
956 untouched_anonymous_page(mm,vma,start)) {
957 page = ZERO_PAGE(start); 962 page = ZERO_PAGE(start);
958 break; 963 break;
959 } 964 }
960 spin_unlock(&mm->page_table_lock); 965 spin_unlock(&mm->page_table_lock);
961 switch (handle_mm_fault(mm,vma,start,write)) { 966 ret = __handle_mm_fault(mm, vma, start, write_access);
967
968 /*
969 * The VM_FAULT_WRITE bit tells us that do_wp_page has
970 * broken COW when necessary, even if maybe_mkwrite
971 * decided not to set pte_write. We can thus safely do
972 * subsequent page lookups as if they were reads.
973 */
974 if (ret & VM_FAULT_WRITE)
975 write_access = 0;
976
977 switch (ret & ~VM_FAULT_WRITE) {
962 case VM_FAULT_MINOR: 978 case VM_FAULT_MINOR:
963 tsk->min_flt++; 979 tsk->min_flt++;
964 break; 980 break;
@@ -972,14 +988,6 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
972 default: 988 default:
973 BUG(); 989 BUG();
974 } 990 }
975 /*
976 * Now that we have performed a write fault
977 * and surely no longer have a shared page we
978 * shouldn't write, we shouldn't ignore an
979 * unwritable page in the page table if
980 * we are forcing write access.
981 */
982 lookup_write = write && !force;
983 spin_lock(&mm->page_table_lock); 991 spin_lock(&mm->page_table_lock);
984 } 992 }
985 if (pages) { 993 if (pages) {
@@ -1229,6 +1237,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
1229 struct page *old_page, *new_page; 1237 struct page *old_page, *new_page;
1230 unsigned long pfn = pte_pfn(pte); 1238 unsigned long pfn = pte_pfn(pte);
1231 pte_t entry; 1239 pte_t entry;
1240 int ret;
1232 1241
1233 if (unlikely(!pfn_valid(pfn))) { 1242 if (unlikely(!pfn_valid(pfn))) {
1234 /* 1243 /*
@@ -1256,7 +1265,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
1256 lazy_mmu_prot_update(entry); 1265 lazy_mmu_prot_update(entry);
1257 pte_unmap(page_table); 1266 pte_unmap(page_table);
1258 spin_unlock(&mm->page_table_lock); 1267 spin_unlock(&mm->page_table_lock);
1259 return VM_FAULT_MINOR; 1268 return VM_FAULT_MINOR|VM_FAULT_WRITE;
1260 } 1269 }
1261 } 1270 }
1262 pte_unmap(page_table); 1271 pte_unmap(page_table);
@@ -1283,6 +1292,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
1283 /* 1292 /*
1284 * Re-check the pte - we dropped the lock 1293 * Re-check the pte - we dropped the lock
1285 */ 1294 */
1295 ret = VM_FAULT_MINOR;
1286 spin_lock(&mm->page_table_lock); 1296 spin_lock(&mm->page_table_lock);
1287 page_table = pte_offset_map(pmd, address); 1297 page_table = pte_offset_map(pmd, address);
1288 if (likely(pte_same(*page_table, pte))) { 1298 if (likely(pte_same(*page_table, pte))) {
@@ -1299,12 +1309,13 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
1299 1309
1300 /* Free the old page.. */ 1310 /* Free the old page.. */
1301 new_page = old_page; 1311 new_page = old_page;
1312 ret |= VM_FAULT_WRITE;
1302 } 1313 }
1303 pte_unmap(page_table); 1314 pte_unmap(page_table);
1304 page_cache_release(new_page); 1315 page_cache_release(new_page);
1305 page_cache_release(old_page); 1316 page_cache_release(old_page);
1306 spin_unlock(&mm->page_table_lock); 1317 spin_unlock(&mm->page_table_lock);
1307 return VM_FAULT_MINOR; 1318 return ret;
1308 1319
1309no_new_page: 1320no_new_page:
1310 page_cache_release(old_page); 1321 page_cache_release(old_page);
@@ -1996,7 +2007,6 @@ static inline int handle_pte_fault(struct mm_struct *mm,
1996 if (write_access) { 2007 if (write_access) {
1997 if (!pte_write(entry)) 2008 if (!pte_write(entry))
1998 return do_wp_page(mm, vma, address, pte, pmd, entry); 2009 return do_wp_page(mm, vma, address, pte, pmd, entry);
1999
2000 entry = pte_mkdirty(entry); 2010 entry = pte_mkdirty(entry);
2001 } 2011 }
2002 entry = pte_mkyoung(entry); 2012 entry = pte_mkyoung(entry);
@@ -2011,7 +2021,7 @@ static inline int handle_pte_fault(struct mm_struct *mm,
2011/* 2021/*
2012 * By the time we get here, we already hold the mm semaphore 2022 * By the time we get here, we already hold the mm semaphore
2013 */ 2023 */
2014int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma, 2024int __handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma,
2015 unsigned long address, int write_access) 2025 unsigned long address, int write_access)
2016{ 2026{
2017 pgd_t *pgd; 2027 pgd_t *pgd;
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 1694845526..b4eababc81 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -443,7 +443,7 @@ asmlinkage long sys_set_mempolicy(int mode, unsigned long __user *nmask,
443 struct mempolicy *new; 443 struct mempolicy *new;
444 DECLARE_BITMAP(nodes, MAX_NUMNODES); 444 DECLARE_BITMAP(nodes, MAX_NUMNODES);
445 445
446 if (mode > MPOL_MAX) 446 if (mode < 0 || mode > MPOL_MAX)
447 return -EINVAL; 447 return -EINVAL;
448 err = get_nodes(nodes, nmask, maxnode, mode); 448 err = get_nodes(nodes, nmask, maxnode, mode);
449 if (err) 449 if (err)
diff --git a/mm/mremap.c b/mm/mremap.c
index ec7238a78f..fc45dc9a61 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -229,6 +229,7 @@ static unsigned long move_vma(struct vm_area_struct *vma,
229 * since do_munmap() will decrement it by old_len == new_len 229 * since do_munmap() will decrement it by old_len == new_len
230 */ 230 */
231 mm->total_vm += new_len >> PAGE_SHIFT; 231 mm->total_vm += new_len >> PAGE_SHIFT;
232 __vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT);
232 233
233 if (do_munmap(mm, old_addr, old_len) < 0) { 234 if (do_munmap(mm, old_addr, old_len) < 0) {
234 /* OOM: unable to split vma, just get accounts right */ 235 /* OOM: unable to split vma, just get accounts right */
@@ -243,7 +244,6 @@ static unsigned long move_vma(struct vm_area_struct *vma,
243 vma->vm_next->vm_flags |= VM_ACCOUNT; 244 vma->vm_next->vm_flags |= VM_ACCOUNT;
244 } 245 }
245 246
246 __vm_stat_account(mm, vma->vm_flags, vma->vm_file, new_len>>PAGE_SHIFT);
247 if (vm_flags & VM_LOCKED) { 247 if (vm_flags & VM_LOCKED) {
248 mm->locked_vm += new_len >> PAGE_SHIFT; 248 mm->locked_vm += new_len >> PAGE_SHIFT;
249 if (new_len > old_len) 249 if (new_len > old_len)
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 42bccfb846..8d08837119 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1061,20 +1061,19 @@ unsigned int nr_free_pages_pgdat(pg_data_t *pgdat)
1061 1061
1062static unsigned int nr_free_zone_pages(int offset) 1062static unsigned int nr_free_zone_pages(int offset)
1063{ 1063{
1064 pg_data_t *pgdat; 1064 /* Just pick one node, since fallback list is circular */
1065 pg_data_t *pgdat = NODE_DATA(numa_node_id());
1065 unsigned int sum = 0; 1066 unsigned int sum = 0;
1066 1067
1067 for_each_pgdat(pgdat) { 1068 struct zonelist *zonelist = pgdat->node_zonelists + offset;
1068 struct zonelist *zonelist = pgdat->node_zonelists + offset; 1069 struct zone **zonep = zonelist->zones;
1069 struct zone **zonep = zonelist->zones; 1070 struct zone *zone;
1070 struct zone *zone;
1071 1071
1072 for (zone = *zonep++; zone; zone = *zonep++) { 1072 for (zone = *zonep++; zone; zone = *zonep++) {
1073 unsigned long size = zone->present_pages; 1073 unsigned long size = zone->present_pages;
1074 unsigned long high = zone->pages_high; 1074 unsigned long high = zone->pages_high;
1075 if (size > high) 1075 if (size > high)
1076 sum += size - high; 1076 sum += size - high;
1077 }
1078 } 1077 }
1079 1078
1080 return sum; 1079 return sum;