diff options
author | Christoph Lameter <clameter@sgi.com> | 2007-02-10 04:43:01 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-11 13:51:17 -0500 |
commit | c878538598d1e7ab41ecc0de8894e34e2fdef630 (patch) | |
tree | d22e73fddef75521e287c3e7754a1d3224c348d9 /include | |
parent | c3704ceb4ad055b489b143f4e37c57d128908012 (diff) |
[PATCH] Use ZVC for inactive and active counts
The determination of the dirty ratio to determine writeback behavior is
currently based on the number of total pages on the system.
However, not all pages in the system may be dirtied. Thus the ratio is always
too low and can never reach 100%. The ratio may be particularly skewed if
large hugepage allocations, slab allocations or device driver buffers make
large sections of memory not available anymore. In that case we may get into
a situation in which f.e. the background writeback ratio of 40% cannot be
reached anymore which leads to undesired writeback behavior.
This patchset fixes that issue by determining the ratio based on the actual
pages that may potentially be dirty. These are the pages on the active and
the inactive list plus free pages.
The problem with those counts has so far been that it is expensive to
calculate these because counts from multiple nodes and multiple zones will
have to be summed up. This patchset makes these counters ZVC counters. This
means that a current sum per zone, per node and for the whole system is always
available via global variables and not expensive anymore to calculate.
The patchset results in some other good side effects:
- Removal of the various functions that sum up free, active and inactive
page counts
- Cleanup of the functions that display information via the proc filesystem.
This patch:
The use of a ZVC for nr_inactive and nr_active allows a simplification of some
counter operations. More ZVC functionality is used for sums etc in the
following patches.
[akpm@osdl.org: UP build fix]
Signed-off-by: Christoph Lameter <clameter@sgi.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/mm_inline.h | 13 | ||||
-rw-r--r-- | include/linux/mmzone.h | 4 | ||||
-rw-r--r-- | include/linux/vmstat.h | 9 |
3 files changed, 17 insertions, 9 deletions
diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h index 3b6723dfaff3..895bc4e93039 100644 --- a/include/linux/mm_inline.h +++ b/include/linux/mm_inline.h | |||
@@ -1,30 +1,29 @@ | |||
1 | |||
2 | static inline void | 1 | static inline void |
3 | add_page_to_active_list(struct zone *zone, struct page *page) | 2 | add_page_to_active_list(struct zone *zone, struct page *page) |
4 | { | 3 | { |
5 | list_add(&page->lru, &zone->active_list); | 4 | list_add(&page->lru, &zone->active_list); |
6 | zone->nr_active++; | 5 | __inc_zone_state(zone, NR_ACTIVE); |
7 | } | 6 | } |
8 | 7 | ||
9 | static inline void | 8 | static inline void |
10 | add_page_to_inactive_list(struct zone *zone, struct page *page) | 9 | add_page_to_inactive_list(struct zone *zone, struct page *page) |
11 | { | 10 | { |
12 | list_add(&page->lru, &zone->inactive_list); | 11 | list_add(&page->lru, &zone->inactive_list); |
13 | zone->nr_inactive++; | 12 | __inc_zone_state(zone, NR_INACTIVE); |
14 | } | 13 | } |
15 | 14 | ||
16 | static inline void | 15 | static inline void |
17 | del_page_from_active_list(struct zone *zone, struct page *page) | 16 | del_page_from_active_list(struct zone *zone, struct page *page) |
18 | { | 17 | { |
19 | list_del(&page->lru); | 18 | list_del(&page->lru); |
20 | zone->nr_active--; | 19 | __dec_zone_state(zone, NR_ACTIVE); |
21 | } | 20 | } |
22 | 21 | ||
23 | static inline void | 22 | static inline void |
24 | del_page_from_inactive_list(struct zone *zone, struct page *page) | 23 | del_page_from_inactive_list(struct zone *zone, struct page *page) |
25 | { | 24 | { |
26 | list_del(&page->lru); | 25 | list_del(&page->lru); |
27 | zone->nr_inactive--; | 26 | __dec_zone_state(zone, NR_INACTIVE); |
28 | } | 27 | } |
29 | 28 | ||
30 | static inline void | 29 | static inline void |
@@ -33,9 +32,9 @@ del_page_from_lru(struct zone *zone, struct page *page) | |||
33 | list_del(&page->lru); | 32 | list_del(&page->lru); |
34 | if (PageActive(page)) { | 33 | if (PageActive(page)) { |
35 | __ClearPageActive(page); | 34 | __ClearPageActive(page); |
36 | zone->nr_active--; | 35 | __dec_zone_state(zone, NR_ACTIVE); |
37 | } else { | 36 | } else { |
38 | zone->nr_inactive--; | 37 | __dec_zone_state(zone, NR_INACTIVE); |
39 | } | 38 | } |
40 | } | 39 | } |
41 | 40 | ||
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index b262f47961fb..9137d1b9735c 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
@@ -47,6 +47,8 @@ struct zone_padding { | |||
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | enum zone_stat_item { | 49 | enum zone_stat_item { |
50 | NR_INACTIVE, | ||
51 | NR_ACTIVE, | ||
50 | NR_ANON_PAGES, /* Mapped anonymous pages */ | 52 | NR_ANON_PAGES, /* Mapped anonymous pages */ |
51 | NR_FILE_MAPPED, /* pagecache pages mapped into pagetables. | 53 | NR_FILE_MAPPED, /* pagecache pages mapped into pagetables. |
52 | only modified from process context */ | 54 | only modified from process context */ |
@@ -197,8 +199,6 @@ struct zone { | |||
197 | struct list_head inactive_list; | 199 | struct list_head inactive_list; |
198 | unsigned long nr_scan_active; | 200 | unsigned long nr_scan_active; |
199 | unsigned long nr_scan_inactive; | 201 | unsigned long nr_scan_inactive; |
200 | unsigned long nr_active; | ||
201 | unsigned long nr_inactive; | ||
202 | unsigned long pages_scanned; /* since last reclaim */ | 202 | unsigned long pages_scanned; /* since last reclaim */ |
203 | int all_unreclaimable; /* All pages pinned */ | 203 | int all_unreclaimable; /* All pages pinned */ |
204 | 204 | ||
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h index 5e9803ed17fc..c8d55bcc09b9 100644 --- a/include/linux/vmstat.h +++ b/include/linux/vmstat.h | |||
@@ -186,6 +186,9 @@ void inc_zone_page_state(struct page *, enum zone_stat_item); | |||
186 | void dec_zone_page_state(struct page *, enum zone_stat_item); | 186 | void dec_zone_page_state(struct page *, enum zone_stat_item); |
187 | 187 | ||
188 | extern void inc_zone_state(struct zone *, enum zone_stat_item); | 188 | extern void inc_zone_state(struct zone *, enum zone_stat_item); |
189 | extern void __inc_zone_state(struct zone *, enum zone_stat_item); | ||
190 | extern void dec_zone_state(struct zone *, enum zone_stat_item); | ||
191 | extern void __dec_zone_state(struct zone *, enum zone_stat_item); | ||
189 | 192 | ||
190 | void refresh_cpu_vm_stats(int); | 193 | void refresh_cpu_vm_stats(int); |
191 | void refresh_vm_stats(void); | 194 | void refresh_vm_stats(void); |
@@ -214,6 +217,12 @@ static inline void __inc_zone_page_state(struct page *page, | |||
214 | __inc_zone_state(page_zone(page), item); | 217 | __inc_zone_state(page_zone(page), item); |
215 | } | 218 | } |
216 | 219 | ||
220 | static inline void __dec_zone_state(struct zone *zone, enum zone_stat_item item) | ||
221 | { | ||
222 | atomic_long_dec(&zone->vm_stat[item]); | ||
223 | atomic_long_dec(&vm_stat[item]); | ||
224 | } | ||
225 | |||
217 | static inline void __dec_zone_page_state(struct page *page, | 226 | static inline void __dec_zone_page_state(struct page *page, |
218 | enum zone_stat_item item) | 227 | enum zone_stat_item item) |
219 | { | 228 | { |