diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/Makefile | 2 | ||||
-rw-r--r-- | mm/debug.c | 1 | ||||
-rw-r--r-- | mm/filemap.c | 119 | ||||
-rw-r--r-- | mm/internal.h | 10 | ||||
-rw-r--r-- | mm/memory.c | 19 | ||||
-rw-r--r-- | mm/page-writeback.c | 3 | ||||
-rw-r--r-- | mm/vmscan.c | 7 | ||||
-rw-r--r-- | mm/vmstat.c | 4 |
8 files changed, 143 insertions, 22 deletions
diff --git a/mm/Makefile b/mm/Makefile index 98c4eaeabdcb..98d28edd36a5 100644 --- a/mm/Makefile +++ b/mm/Makefile | |||
@@ -56,7 +56,7 @@ obj-$(CONFIG_KASAN) += kasan/ | |||
56 | obj-$(CONFIG_FAILSLAB) += failslab.o | 56 | obj-$(CONFIG_FAILSLAB) += failslab.o |
57 | obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o | 57 | obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o |
58 | obj-$(CONFIG_MEMTEST) += memtest.o | 58 | obj-$(CONFIG_MEMTEST) += memtest.o |
59 | obj-$(CONFIG_MIGRATION) += migrate.o | 59 | obj-$(CONFIG_MIGRATION) += migrate.o replication.o |
60 | obj-$(CONFIG_QUICKLIST) += quicklist.o | 60 | obj-$(CONFIG_QUICKLIST) += quicklist.o |
61 | obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += huge_memory.o | 61 | obj-$(CONFIG_TRANSPARENT_HUGEPAGE) += huge_memory.o |
62 | obj-$(CONFIG_PAGE_COUNTER) += page_counter.o | 62 | obj-$(CONFIG_PAGE_COUNTER) += page_counter.o |
diff --git a/mm/debug.c b/mm/debug.c index 3eb3ac2fcee7..dbc3ea81dde7 100644 --- a/mm/debug.c +++ b/mm/debug.c | |||
@@ -36,6 +36,7 @@ static const struct trace_print_flags pageflag_names[] = { | |||
36 | {1UL << PG_reclaim, "reclaim" }, | 36 | {1UL << PG_reclaim, "reclaim" }, |
37 | {1UL << PG_swapbacked, "swapbacked" }, | 37 | {1UL << PG_swapbacked, "swapbacked" }, |
38 | {1UL << PG_unevictable, "unevictable" }, | 38 | {1UL << PG_unevictable, "unevictable" }, |
39 | {1UL << PG_replicated, "replicated" }, | ||
39 | #ifdef CONFIG_MMU | 40 | #ifdef CONFIG_MMU |
40 | {1UL << PG_mlocked, "mlocked" }, | 41 | {1UL << PG_mlocked, "mlocked" }, |
41 | #endif | 42 | #endif |
diff --git a/mm/filemap.c b/mm/filemap.c index 8ea609718839..93853e337f07 100644 --- a/mm/filemap.c +++ b/mm/filemap.c | |||
@@ -973,13 +973,21 @@ repeat: | |||
973 | page = NULL; | 973 | page = NULL; |
974 | pagep = radix_tree_lookup_slot(&mapping->page_tree, offset); | 974 | pagep = radix_tree_lookup_slot(&mapping->page_tree, offset); |
975 | if (pagep) { | 975 | if (pagep) { |
976 | void *pdesc; | 976 | page = radix_tree_deref_slot(pagep); |
977 | pdesc = radix_tree_deref_slot(pagep); | ||
978 | if (pdesc) | ||
979 | page = (struct page*)pdesc; | ||
980 | //page = radix_tree_deref_slot(pagep); | ||
981 | if (unlikely(!page)) | 977 | if (unlikely(!page)) |
982 | goto out; | 978 | goto out; |
979 | if (is_pcache_desc(page)) { | ||
980 | struct pcache_desc *pcd; | ||
981 | printk(KERN_INFO "PCACHE_DESC\n"); | ||
982 | pcd = ptr_to_pcache_desc(page); | ||
983 | page = pcd->master; | ||
984 | page_cache_get_speculative(page); | ||
985 | |||
986 | unreplicate_pcache(mapping, page->index, 0); | ||
987 | |||
988 | goto out; | ||
989 | } | ||
990 | |||
983 | if (radix_tree_exception(page)) { | 991 | if (radix_tree_exception(page)) { |
984 | if (radix_tree_deref_retry(page)) | 992 | if (radix_tree_deref_retry(page)) |
985 | goto repeat; | 993 | goto repeat; |
@@ -1178,6 +1186,20 @@ repeat: | |||
1178 | page = radix_tree_deref_slot(slot); | 1186 | page = radix_tree_deref_slot(slot); |
1179 | if (unlikely(!page)) | 1187 | if (unlikely(!page)) |
1180 | continue; | 1188 | continue; |
1189 | |||
1190 | if (is_pcache_desc(page)) { | ||
1191 | struct pcache_desc *pcd; | ||
1192 | printk(KERN_INFO "PCACHE_DESC\n"); | ||
1193 | |||
1194 | pcd = ptr_to_pcache_desc(page); | ||
1195 | page = pcd->master; | ||
1196 | page_cache_get_speculative(page); | ||
1197 | |||
1198 | unreplicate_pcache(mapping, page->index, 0); | ||
1199 | |||
1200 | goto export; | ||
1201 | } | ||
1202 | |||
1181 | if (radix_tree_exception(page)) { | 1203 | if (radix_tree_exception(page)) { |
1182 | if (radix_tree_deref_retry(page)) | 1204 | if (radix_tree_deref_retry(page)) |
1183 | goto restart; | 1205 | goto restart; |
@@ -1241,6 +1263,20 @@ repeat: | |||
1241 | if (unlikely(!page)) | 1263 | if (unlikely(!page)) |
1242 | continue; | 1264 | continue; |
1243 | 1265 | ||
1266 | if (is_pcache_desc(page)) { | ||
1267 | struct pcache_desc *pcd; | ||
1268 | |||
1269 | printk(KERN_INFO "PCACHE_DESC\n"); | ||
1270 | |||
1271 | pcd = ptr_to_pcache_desc(page); | ||
1272 | page = pcd->master; | ||
1273 | page_cache_get_speculative(page); | ||
1274 | |||
1275 | unreplicate_pcache(mapping, page->index, 0); | ||
1276 | |||
1277 | goto export; | ||
1278 | } | ||
1279 | |||
1244 | if (radix_tree_exception(page)) { | 1280 | if (radix_tree_exception(page)) { |
1245 | if (radix_tree_deref_retry(page)) { | 1281 | if (radix_tree_deref_retry(page)) { |
1246 | /* | 1282 | /* |
@@ -1268,6 +1304,7 @@ repeat: | |||
1268 | goto repeat; | 1304 | goto repeat; |
1269 | } | 1305 | } |
1270 | 1306 | ||
1307 | export: | ||
1271 | pages[ret] = page; | 1308 | pages[ret] = page; |
1272 | if (++ret == nr_pages) | 1309 | if (++ret == nr_pages) |
1273 | break; | 1310 | break; |
@@ -1309,6 +1346,20 @@ repeat: | |||
1309 | if (unlikely(!page)) | 1346 | if (unlikely(!page)) |
1310 | break; | 1347 | break; |
1311 | 1348 | ||
1349 | if (is_pcache_desc(page)) { | ||
1350 | struct pcache_desc *pcd; | ||
1351 | |||
1352 | printk(KERN_INFO "PCACHE_DESC\n"); | ||
1353 | |||
1354 | pcd = ptr_to_pcache_desc(page); | ||
1355 | page = pcd->master; | ||
1356 | page_cache_get_speculative(page); | ||
1357 | |||
1358 | unreplicate_pcache(mapping, page->index, 0); | ||
1359 | |||
1360 | goto export; | ||
1361 | } | ||
1362 | |||
1312 | if (radix_tree_exception(page)) { | 1363 | if (radix_tree_exception(page)) { |
1313 | if (radix_tree_deref_retry(page)) { | 1364 | if (radix_tree_deref_retry(page)) { |
1314 | /* | 1365 | /* |
@@ -1334,7 +1385,7 @@ repeat: | |||
1334 | page_cache_release(page); | 1385 | page_cache_release(page); |
1335 | goto repeat; | 1386 | goto repeat; |
1336 | } | 1387 | } |
1337 | 1388 | export: | |
1338 | /* | 1389 | /* |
1339 | * must check mapping and index after taking the ref. | 1390 | * must check mapping and index after taking the ref. |
1340 | * otherwise we can get both false positives and false | 1391 | * otherwise we can get both false positives and false |
@@ -1385,6 +1436,20 @@ repeat: | |||
1385 | if (unlikely(!page)) | 1436 | if (unlikely(!page)) |
1386 | continue; | 1437 | continue; |
1387 | 1438 | ||
1439 | if (is_pcache_desc(page)) { | ||
1440 | struct pcache_desc *pcd; | ||
1441 | |||
1442 | printk(KERN_INFO "PCACHE_DESC BUG!!!!!!!!!!\n"); | ||
1443 | |||
1444 | pcd = ptr_to_pcache_desc(page); | ||
1445 | page = pcd->master; | ||
1446 | page_cache_get_speculative(page); | ||
1447 | |||
1448 | unreplicate_pcache(mapping, page->index, 0); | ||
1449 | |||
1450 | goto export; | ||
1451 | } | ||
1452 | |||
1388 | if (radix_tree_exception(page)) { | 1453 | if (radix_tree_exception(page)) { |
1389 | if (radix_tree_deref_retry(page)) { | 1454 | if (radix_tree_deref_retry(page)) { |
1390 | /* | 1455 | /* |
@@ -1416,7 +1481,7 @@ repeat: | |||
1416 | page_cache_release(page); | 1481 | page_cache_release(page); |
1417 | goto repeat; | 1482 | goto repeat; |
1418 | } | 1483 | } |
1419 | 1484 | export: | |
1420 | pages[ret] = page; | 1485 | pages[ret] = page; |
1421 | if (++ret == nr_pages) | 1486 | if (++ret == nr_pages) |
1422 | break; | 1487 | break; |
@@ -1492,7 +1557,11 @@ static ssize_t do_generic_file_read(struct file *filp, loff_t *ppos, | |||
1492 | 1557 | ||
1493 | cond_resched(); | 1558 | cond_resched(); |
1494 | find_page: | 1559 | find_page: |
1495 | page = find_get_page(mapping, index); | 1560 | if (is_realtime(current)) |
1561 | page = find_get_page_readonly(mapping, index); | ||
1562 | else | ||
1563 | page = find_get_page(mapping, index); | ||
1564 | |||
1496 | if (!page) { | 1565 | if (!page) { |
1497 | page_cache_sync_readahead(mapping, | 1566 | page_cache_sync_readahead(mapping, |
1498 | ra, filp, | 1567 | ra, filp, |
@@ -1644,7 +1713,8 @@ readpage: | |||
1644 | unlock_page(page); | 1713 | unlock_page(page); |
1645 | } | 1714 | } |
1646 | 1715 | ||
1647 | goto page_ok; | 1716 | page_cache_release(page); |
1717 | goto find_page; | ||
1648 | 1718 | ||
1649 | readpage_error: | 1719 | readpage_error: |
1650 | /* UHHUH! A synchronous read error occurred. Report it */ | 1720 | /* UHHUH! A synchronous read error occurred. Report it */ |
@@ -1888,9 +1958,11 @@ int filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
1888 | /* | 1958 | /* |
1889 | * Do we have something in the page cache already? | 1959 | * Do we have something in the page cache already? |
1890 | */ | 1960 | */ |
1891 | if (is_realtime(current)) | 1961 | if ((vmf->flags & FAULT_FLAG_WRITE) || !is_realtime(current)) |
1892 | printk("FILEMAP_FAULT %ld\n", vma->vm_start); | 1962 | page = find_get_page(mapping, offset); |
1893 | page = find_get_page(mapping, offset); | 1963 | else |
1964 | page = find_get_page_readonly(mapping, offset); | ||
1965 | |||
1894 | if (likely(page) && !(vmf->flags & FAULT_FLAG_TRIED)) { | 1966 | if (likely(page) && !(vmf->flags & FAULT_FLAG_TRIED)) { |
1895 | /* | 1967 | /* |
1896 | * We found the page, so try async readahead before | 1968 | * We found the page, so try async readahead before |
@@ -1904,7 +1976,10 @@ if (is_realtime(current)) | |||
1904 | mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT); | 1976 | mem_cgroup_count_vm_event(vma->vm_mm, PGMAJFAULT); |
1905 | ret = VM_FAULT_MAJOR; | 1977 | ret = VM_FAULT_MAJOR; |
1906 | retry_find: | 1978 | retry_find: |
1907 | page = find_get_page(mapping, offset); | 1979 | if ((vmf->flags & FAULT_FLAG_WRITE) || !is_realtime(current)) |
1980 | page = find_get_page(mapping, offset); | ||
1981 | else | ||
1982 | page = find_get_page_readonly(mapping, offset); | ||
1908 | if (!page) | 1983 | if (!page) |
1909 | goto no_cached_page; | 1984 | goto no_cached_page; |
1910 | } | 1985 | } |
@@ -2012,6 +2087,22 @@ repeat: | |||
2012 | page = radix_tree_deref_slot(slot); | 2087 | page = radix_tree_deref_slot(slot); |
2013 | if (unlikely(!page)) | 2088 | if (unlikely(!page)) |
2014 | goto next; | 2089 | goto next; |
2090 | |||
2091 | if (is_pcache_desc(page)) { | ||
2092 | struct pcache_desc *pcd; | ||
2093 | |||
2094 | printk(KERN_INFO "PCACHE_DESC FILE_MAP_PAGES\n"); | ||
2095 | |||
2096 | pcd = ptr_to_pcache_desc(page); | ||
2097 | page = pcd->master; | ||
2098 | if (!page_cache_get_speculative(page)) | ||
2099 | goto repeat; | ||
2100 | |||
2101 | //unreplicate_pcache(mapping, page->index, 0); | ||
2102 | |||
2103 | goto export; | ||
2104 | } | ||
2105 | |||
2015 | if (radix_tree_exception(page)) { | 2106 | if (radix_tree_exception(page)) { |
2016 | if (radix_tree_deref_retry(page)) | 2107 | if (radix_tree_deref_retry(page)) |
2017 | break; | 2108 | break; |
@@ -2027,7 +2118,7 @@ repeat: | |||
2027 | page_cache_release(page); | 2118 | page_cache_release(page); |
2028 | goto repeat; | 2119 | goto repeat; |
2029 | } | 2120 | } |
2030 | 2121 | export: | |
2031 | if (!PageUptodate(page) || | 2122 | if (!PageUptodate(page) || |
2032 | PageReadahead(page) || | 2123 | PageReadahead(page) || |
2033 | PageHWPoison(page)) | 2124 | PageHWPoison(page)) |
diff --git a/mm/internal.h b/mm/internal.h index a25e359a4039..ccc349b59d00 100644 --- a/mm/internal.h +++ b/mm/internal.h | |||
@@ -433,4 +433,14 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone, | |||
433 | #define ALLOC_CMA 0x80 /* allow allocations from CMA areas */ | 433 | #define ALLOC_CMA 0x80 /* allow allocations from CMA areas */ |
434 | #define ALLOC_FAIR 0x100 /* fair zone allocation */ | 434 | #define ALLOC_FAIR 0x100 /* fair zone allocation */ |
435 | 435 | ||
436 | extern int reclaim_replicated_page(struct address_space *mapping, | ||
437 | struct page *page); | ||
438 | extern struct page *find_get_page_readonly(struct address_space *mapping, | ||
439 | unsigned long offset); | ||
440 | extern int is_pcache_desc(void *ptr); | ||
441 | extern struct pcache_desc *ptr_to_pcache_desc(void *ptr); | ||
442 | extern void *pcache_desc_to_ptr(struct pcache_desc *pcd); | ||
443 | extern void unreplicate_pcache(struct address_space *mapping, unsigned long offset, int locked); | ||
444 | int page_write_fault_retry(struct page *page); | ||
445 | |||
436 | #endif /* __MM_INTERNAL_H */ | 446 | #endif /* __MM_INTERNAL_H */ |
diff --git a/mm/memory.c b/mm/memory.c index 22e037e3364e..1fc358bec6d5 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -2231,15 +2231,24 @@ static int wp_page_shared(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2231 | * read-only shared pages can get COWed by | 2231 | * read-only shared pages can get COWed by |
2232 | * get_user_pages(.write=1, .force=1). | 2232 | * get_user_pages(.write=1, .force=1). |
2233 | */ | 2233 | */ |
2234 | if (vma->vm_ops && vma->vm_ops->page_mkwrite) { | 2234 | // if (vma->vm_ops && vma->vm_ops->page_mkwrite) { |
2235 | { | ||
2235 | int tmp; | 2236 | int tmp; |
2236 | 2237 | ||
2237 | pte_unmap_unlock(page_table, ptl); | 2238 | pte_unmap_unlock(page_table, ptl); |
2238 | tmp = do_page_mkwrite(vma, old_page, address); | 2239 | |
2239 | if (unlikely(!tmp || (tmp & | 2240 | if (page_write_fault_retry(old_page)) { |
2240 | (VM_FAULT_ERROR | VM_FAULT_NOPAGE)))) { | ||
2241 | page_cache_release(old_page); | 2241 | page_cache_release(old_page); |
2242 | return tmp; | 2242 | return 0; |
2243 | } | ||
2244 | |||
2245 | if (vma->vm_ops && vma->vm_ops->page_mkwrite) { | ||
2246 | tmp = do_page_mkwrite(vma, old_page, address); | ||
2247 | if (unlikely(!tmp || (tmp & | ||
2248 | (VM_FAULT_ERROR | VM_FAULT_NOPAGE)))) { | ||
2249 | page_cache_release(old_page); | ||
2250 | return tmp; | ||
2251 | } | ||
2243 | } | 2252 | } |
2244 | /* | 2253 | /* |
2245 | * Since we dropped the lock we need to revalidate | 2254 | * Since we dropped the lock we need to revalidate |
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 7e39ffceb566..161af608b7e2 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -2287,7 +2287,8 @@ int clear_page_dirty_for_io(struct page *page) | |||
2287 | 2287 | ||
2288 | BUG_ON(!PageLocked(page)); | 2288 | BUG_ON(!PageLocked(page)); |
2289 | 2289 | ||
2290 | if (mapping && mapping_cap_account_dirty(mapping)) { | 2290 | //if (mapping && mapping_cap_account_dirty(mapping)) { |
2291 | if (mapping) { | ||
2291 | /* | 2292 | /* |
2292 | * Yes, Virginia, this is indeed insane. | 2293 | * Yes, Virginia, this is indeed insane. |
2293 | * | 2294 | * |
diff --git a/mm/vmscan.c b/mm/vmscan.c index 5e8eadd71bac..b9b6bef90169 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -582,6 +582,7 @@ static int __remove_mapping(struct address_space *mapping, struct page *page, | |||
582 | BUG_ON(!PageLocked(page)); | 582 | BUG_ON(!PageLocked(page)); |
583 | BUG_ON(mapping != page_mapping(page)); | 583 | BUG_ON(mapping != page_mapping(page)); |
584 | 584 | ||
585 | again: | ||
585 | spin_lock_irq(&mapping->tree_lock); | 586 | spin_lock_irq(&mapping->tree_lock); |
586 | /* | 587 | /* |
587 | * The non racy check for a busy page. | 588 | * The non racy check for a busy page. |
@@ -640,7 +641,11 @@ static int __remove_mapping(struct address_space *mapping, struct page *page, | |||
640 | if (reclaimed && page_is_file_cache(page) && | 641 | if (reclaimed && page_is_file_cache(page) && |
641 | !mapping_exiting(mapping)) | 642 | !mapping_exiting(mapping)) |
642 | shadow = workingset_eviction(mapping, page); | 643 | shadow = workingset_eviction(mapping, page); |
643 | __delete_from_page_cache(page, shadow); | 644 | if (PageReplicated(page)) { |
645 | if (reclaim_replicated_page(mapping, page)) | ||
646 | goto again; | ||
647 | } else | ||
648 | __delete_from_page_cache(page, shadow); | ||
644 | spin_unlock_irq(&mapping->tree_lock); | 649 | spin_unlock_irq(&mapping->tree_lock); |
645 | 650 | ||
646 | if (freepage != NULL) | 651 | if (freepage != NULL) |
diff --git a/mm/vmstat.c b/mm/vmstat.c index 4f5cd974e11a..6af8ea00cbef 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
@@ -708,6 +708,7 @@ const char * const vmstat_text[] = { | |||
708 | "nr_anon_pages", | 708 | "nr_anon_pages", |
709 | "nr_mapped", | 709 | "nr_mapped", |
710 | "nr_file_pages", | 710 | "nr_file_pages", |
711 | "nr_repl_pages", | ||
711 | "nr_dirty", | 712 | "nr_dirty", |
712 | "nr_writeback", | 713 | "nr_writeback", |
713 | "nr_slab_reclaimable", | 714 | "nr_slab_reclaimable", |
@@ -760,6 +761,9 @@ const char * const vmstat_text[] = { | |||
760 | "pgfault", | 761 | "pgfault", |
761 | "pgmajfault", | 762 | "pgmajfault", |
762 | 763 | ||
764 | "pgreplicated", | ||
765 | "pgreplicazap", | ||
766 | |||
763 | TEXTS_FOR_ZONES("pgrefill") | 767 | TEXTS_FOR_ZONES("pgrefill") |
764 | TEXTS_FOR_ZONES("pgsteal_kswapd") | 768 | TEXTS_FOR_ZONES("pgsteal_kswapd") |
765 | TEXTS_FOR_ZONES("pgsteal_direct") | 769 | TEXTS_FOR_ZONES("pgsteal_direct") |