diff options
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r-- | mm/vmscan.c | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index f713e9f6ac73..548e023c193b 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/cpuset.h> | 33 | #include <linux/cpuset.h> |
34 | #include <linux/notifier.h> | 34 | #include <linux/notifier.h> |
35 | #include <linux/rwsem.h> | 35 | #include <linux/rwsem.h> |
36 | #include <linux/delay.h> | ||
36 | 37 | ||
37 | #include <asm/tlbflush.h> | 38 | #include <asm/tlbflush.h> |
38 | #include <asm/div64.h> | 39 | #include <asm/div64.h> |
@@ -1784,11 +1785,13 @@ unsigned long shrink_all_memory(unsigned long nr_pages) | |||
1784 | pg_data_t *pgdat; | 1785 | pg_data_t *pgdat; |
1785 | unsigned long nr_to_free = nr_pages; | 1786 | unsigned long nr_to_free = nr_pages; |
1786 | unsigned long ret = 0; | 1787 | unsigned long ret = 0; |
1788 | unsigned retry = 2; | ||
1787 | struct reclaim_state reclaim_state = { | 1789 | struct reclaim_state reclaim_state = { |
1788 | .reclaimed_slab = 0, | 1790 | .reclaimed_slab = 0, |
1789 | }; | 1791 | }; |
1790 | 1792 | ||
1791 | current->reclaim_state = &reclaim_state; | 1793 | current->reclaim_state = &reclaim_state; |
1794 | repeat: | ||
1792 | for_each_pgdat(pgdat) { | 1795 | for_each_pgdat(pgdat) { |
1793 | unsigned long freed; | 1796 | unsigned long freed; |
1794 | 1797 | ||
@@ -1798,6 +1801,10 @@ unsigned long shrink_all_memory(unsigned long nr_pages) | |||
1798 | if ((long)nr_to_free <= 0) | 1801 | if ((long)nr_to_free <= 0) |
1799 | break; | 1802 | break; |
1800 | } | 1803 | } |
1804 | if (retry-- && ret < nr_pages) { | ||
1805 | blk_congestion_wait(WRITE, HZ/5); | ||
1806 | goto repeat; | ||
1807 | } | ||
1801 | current->reclaim_state = NULL; | 1808 | current->reclaim_state = NULL; |
1802 | return ret; | 1809 | return ret; |
1803 | } | 1810 | } |