diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/backing-dev.c | 219 | ||||
-rw-r--r-- | mm/hugetlb.c | 6 | ||||
-rw-r--r-- | mm/memcontrol.c | 179 | ||||
-rw-r--r-- | mm/migrate.c | 9 | ||||
-rw-r--r-- | mm/mmap.c | 24 | ||||
-rw-r--r-- | mm/nommu.c | 23 | ||||
-rw-r--r-- | mm/page-writeback.c | 77 | ||||
-rw-r--r-- | mm/page_alloc.c | 47 | ||||
-rw-r--r-- | mm/readahead.c | 8 | ||||
-rw-r--r-- | mm/shmem.c | 2 | ||||
-rw-r--r-- | mm/slab.c | 14 | ||||
-rw-r--r-- | mm/slub.c | 5 | ||||
-rw-r--r-- | mm/sparse.c | 19 | ||||
-rw-r--r-- | mm/swap_state.c | 2 | ||||
-rw-r--r-- | mm/swapfile.c | 6 | ||||
-rw-r--r-- | mm/vmalloc.c | 2 | ||||
-rw-r--r-- | mm/vmscan.c | 11 | ||||
-rw-r--r-- | mm/vmstat.c | 5 |
18 files changed, 504 insertions, 154 deletions
diff --git a/mm/backing-dev.c b/mm/backing-dev.c index e8644b1e5527..7c4f9e097095 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c | |||
@@ -4,12 +4,229 @@ | |||
4 | #include <linux/fs.h> | 4 | #include <linux/fs.h> |
5 | #include <linux/sched.h> | 5 | #include <linux/sched.h> |
6 | #include <linux/module.h> | 6 | #include <linux/module.h> |
7 | #include <linux/writeback.h> | ||
8 | #include <linux/device.h> | ||
9 | |||
10 | |||
11 | static struct class *bdi_class; | ||
12 | |||
13 | #ifdef CONFIG_DEBUG_FS | ||
14 | #include <linux/debugfs.h> | ||
15 | #include <linux/seq_file.h> | ||
16 | |||
17 | static struct dentry *bdi_debug_root; | ||
18 | |||
19 | static void bdi_debug_init(void) | ||
20 | { | ||
21 | bdi_debug_root = debugfs_create_dir("bdi", NULL); | ||
22 | } | ||
23 | |||
24 | static int bdi_debug_stats_show(struct seq_file *m, void *v) | ||
25 | { | ||
26 | struct backing_dev_info *bdi = m->private; | ||
27 | long background_thresh; | ||
28 | long dirty_thresh; | ||
29 | long bdi_thresh; | ||
30 | |||
31 | get_dirty_limits(&background_thresh, &dirty_thresh, &bdi_thresh, bdi); | ||
32 | |||
33 | #define K(x) ((x) << (PAGE_SHIFT - 10)) | ||
34 | seq_printf(m, | ||
35 | "BdiWriteback: %8lu kB\n" | ||
36 | "BdiReclaimable: %8lu kB\n" | ||
37 | "BdiDirtyThresh: %8lu kB\n" | ||
38 | "DirtyThresh: %8lu kB\n" | ||
39 | "BackgroundThresh: %8lu kB\n", | ||
40 | (unsigned long) K(bdi_stat(bdi, BDI_WRITEBACK)), | ||
41 | (unsigned long) K(bdi_stat(bdi, BDI_RECLAIMABLE)), | ||
42 | K(bdi_thresh), | ||
43 | K(dirty_thresh), | ||
44 | K(background_thresh)); | ||
45 | #undef K | ||
46 | |||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | static int bdi_debug_stats_open(struct inode *inode, struct file *file) | ||
51 | { | ||
52 | return single_open(file, bdi_debug_stats_show, inode->i_private); | ||
53 | } | ||
54 | |||
55 | static const struct file_operations bdi_debug_stats_fops = { | ||
56 | .open = bdi_debug_stats_open, | ||
57 | .read = seq_read, | ||
58 | .llseek = seq_lseek, | ||
59 | .release = single_release, | ||
60 | }; | ||
61 | |||
62 | static void bdi_debug_register(struct backing_dev_info *bdi, const char *name) | ||
63 | { | ||
64 | bdi->debug_dir = debugfs_create_dir(name, bdi_debug_root); | ||
65 | bdi->debug_stats = debugfs_create_file("stats", 0444, bdi->debug_dir, | ||
66 | bdi, &bdi_debug_stats_fops); | ||
67 | } | ||
68 | |||
69 | static void bdi_debug_unregister(struct backing_dev_info *bdi) | ||
70 | { | ||
71 | debugfs_remove(bdi->debug_stats); | ||
72 | debugfs_remove(bdi->debug_dir); | ||
73 | } | ||
74 | #else | ||
75 | static inline void bdi_debug_init(void) | ||
76 | { | ||
77 | } | ||
78 | static inline void bdi_debug_register(struct backing_dev_info *bdi, | ||
79 | const char *name) | ||
80 | { | ||
81 | } | ||
82 | static inline void bdi_debug_unregister(struct backing_dev_info *bdi) | ||
83 | { | ||
84 | } | ||
85 | #endif | ||
86 | |||
87 | static ssize_t read_ahead_kb_store(struct device *dev, | ||
88 | struct device_attribute *attr, | ||
89 | const char *buf, size_t count) | ||
90 | { | ||
91 | struct backing_dev_info *bdi = dev_get_drvdata(dev); | ||
92 | char *end; | ||
93 | unsigned long read_ahead_kb; | ||
94 | ssize_t ret = -EINVAL; | ||
95 | |||
96 | read_ahead_kb = simple_strtoul(buf, &end, 10); | ||
97 | if (*buf && (end[0] == '\0' || (end[0] == '\n' && end[1] == '\0'))) { | ||
98 | bdi->ra_pages = read_ahead_kb >> (PAGE_SHIFT - 10); | ||
99 | ret = count; | ||
100 | } | ||
101 | return ret; | ||
102 | } | ||
103 | |||
104 | #define K(pages) ((pages) << (PAGE_SHIFT - 10)) | ||
105 | |||
106 | #define BDI_SHOW(name, expr) \ | ||
107 | static ssize_t name##_show(struct device *dev, \ | ||
108 | struct device_attribute *attr, char *page) \ | ||
109 | { \ | ||
110 | struct backing_dev_info *bdi = dev_get_drvdata(dev); \ | ||
111 | \ | ||
112 | return snprintf(page, PAGE_SIZE-1, "%lld\n", (long long)expr); \ | ||
113 | } | ||
114 | |||
115 | BDI_SHOW(read_ahead_kb, K(bdi->ra_pages)) | ||
116 | |||
117 | static ssize_t min_ratio_store(struct device *dev, | ||
118 | struct device_attribute *attr, const char *buf, size_t count) | ||
119 | { | ||
120 | struct backing_dev_info *bdi = dev_get_drvdata(dev); | ||
121 | char *end; | ||
122 | unsigned int ratio; | ||
123 | ssize_t ret = -EINVAL; | ||
124 | |||
125 | ratio = simple_strtoul(buf, &end, 10); | ||
126 | if (*buf && (end[0] == '\0' || (end[0] == '\n' && end[1] == '\0'))) { | ||
127 | ret = bdi_set_min_ratio(bdi, ratio); | ||
128 | if (!ret) | ||
129 | ret = count; | ||
130 | } | ||
131 | return ret; | ||
132 | } | ||
133 | BDI_SHOW(min_ratio, bdi->min_ratio) | ||
134 | |||
135 | static ssize_t max_ratio_store(struct device *dev, | ||
136 | struct device_attribute *attr, const char *buf, size_t count) | ||
137 | { | ||
138 | struct backing_dev_info *bdi = dev_get_drvdata(dev); | ||
139 | char *end; | ||
140 | unsigned int ratio; | ||
141 | ssize_t ret = -EINVAL; | ||
142 | |||
143 | ratio = simple_strtoul(buf, &end, 10); | ||
144 | if (*buf && (end[0] == '\0' || (end[0] == '\n' && end[1] == '\0'))) { | ||
145 | ret = bdi_set_max_ratio(bdi, ratio); | ||
146 | if (!ret) | ||
147 | ret = count; | ||
148 | } | ||
149 | return ret; | ||
150 | } | ||
151 | BDI_SHOW(max_ratio, bdi->max_ratio) | ||
152 | |||
153 | #define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store) | ||
154 | |||
155 | static struct device_attribute bdi_dev_attrs[] = { | ||
156 | __ATTR_RW(read_ahead_kb), | ||
157 | __ATTR_RW(min_ratio), | ||
158 | __ATTR_RW(max_ratio), | ||
159 | __ATTR_NULL, | ||
160 | }; | ||
161 | |||
162 | static __init int bdi_class_init(void) | ||
163 | { | ||
164 | bdi_class = class_create(THIS_MODULE, "bdi"); | ||
165 | bdi_class->dev_attrs = bdi_dev_attrs; | ||
166 | bdi_debug_init(); | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | postcore_initcall(bdi_class_init); | ||
171 | |||
172 | int bdi_register(struct backing_dev_info *bdi, struct device *parent, | ||
173 | const char *fmt, ...) | ||
174 | { | ||
175 | char *name; | ||
176 | va_list args; | ||
177 | int ret = 0; | ||
178 | struct device *dev; | ||
179 | |||
180 | va_start(args, fmt); | ||
181 | name = kvasprintf(GFP_KERNEL, fmt, args); | ||
182 | va_end(args); | ||
183 | |||
184 | if (!name) | ||
185 | return -ENOMEM; | ||
186 | |||
187 | dev = device_create(bdi_class, parent, MKDEV(0, 0), name); | ||
188 | if (IS_ERR(dev)) { | ||
189 | ret = PTR_ERR(dev); | ||
190 | goto exit; | ||
191 | } | ||
192 | |||
193 | bdi->dev = dev; | ||
194 | dev_set_drvdata(bdi->dev, bdi); | ||
195 | bdi_debug_register(bdi, name); | ||
196 | |||
197 | exit: | ||
198 | kfree(name); | ||
199 | return ret; | ||
200 | } | ||
201 | EXPORT_SYMBOL(bdi_register); | ||
202 | |||
203 | int bdi_register_dev(struct backing_dev_info *bdi, dev_t dev) | ||
204 | { | ||
205 | return bdi_register(bdi, NULL, "%u:%u", MAJOR(dev), MINOR(dev)); | ||
206 | } | ||
207 | EXPORT_SYMBOL(bdi_register_dev); | ||
208 | |||
209 | void bdi_unregister(struct backing_dev_info *bdi) | ||
210 | { | ||
211 | if (bdi->dev) { | ||
212 | bdi_debug_unregister(bdi); | ||
213 | device_unregister(bdi->dev); | ||
214 | bdi->dev = NULL; | ||
215 | } | ||
216 | } | ||
217 | EXPORT_SYMBOL(bdi_unregister); | ||
7 | 218 | ||
8 | int bdi_init(struct backing_dev_info *bdi) | 219 | int bdi_init(struct backing_dev_info *bdi) |
9 | { | 220 | { |
10 | int i; | 221 | int i; |
11 | int err; | 222 | int err; |
12 | 223 | ||
224 | bdi->dev = NULL; | ||
225 | |||
226 | bdi->min_ratio = 0; | ||
227 | bdi->max_ratio = 100; | ||
228 | bdi->max_prop_frac = PROP_FRAC_BASE; | ||
229 | |||
13 | for (i = 0; i < NR_BDI_STAT_ITEMS; i++) { | 230 | for (i = 0; i < NR_BDI_STAT_ITEMS; i++) { |
14 | err = percpu_counter_init_irq(&bdi->bdi_stat[i], 0); | 231 | err = percpu_counter_init_irq(&bdi->bdi_stat[i], 0); |
15 | if (err) | 232 | if (err) |
@@ -33,6 +250,8 @@ void bdi_destroy(struct backing_dev_info *bdi) | |||
33 | { | 250 | { |
34 | int i; | 251 | int i; |
35 | 252 | ||
253 | bdi_unregister(bdi); | ||
254 | |||
36 | for (i = 0; i < NR_BDI_STAT_ITEMS; i++) | 255 | for (i = 0; i < NR_BDI_STAT_ITEMS; i++) |
37 | percpu_counter_destroy(&bdi->bdi_stat[i]); | 256 | percpu_counter_destroy(&bdi->bdi_stat[i]); |
38 | 257 | ||
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 2c37c67ed8c9..bbf953eeb58b 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -199,7 +199,8 @@ static struct page *alloc_fresh_huge_page_node(int nid) | |||
199 | struct page *page; | 199 | struct page *page; |
200 | 200 | ||
201 | page = alloc_pages_node(nid, | 201 | page = alloc_pages_node(nid, |
202 | htlb_alloc_mask|__GFP_COMP|__GFP_THISNODE|__GFP_NOWARN, | 202 | htlb_alloc_mask|__GFP_COMP|__GFP_THISNODE| |
203 | __GFP_REPEAT|__GFP_NOWARN, | ||
203 | HUGETLB_PAGE_ORDER); | 204 | HUGETLB_PAGE_ORDER); |
204 | if (page) { | 205 | if (page) { |
205 | if (arch_prepare_hugepage(page)) { | 206 | if (arch_prepare_hugepage(page)) { |
@@ -294,7 +295,8 @@ static struct page *alloc_buddy_huge_page(struct vm_area_struct *vma, | |||
294 | } | 295 | } |
295 | spin_unlock(&hugetlb_lock); | 296 | spin_unlock(&hugetlb_lock); |
296 | 297 | ||
297 | page = alloc_pages(htlb_alloc_mask|__GFP_COMP|__GFP_NOWARN, | 298 | page = alloc_pages(htlb_alloc_mask|__GFP_COMP| |
299 | __GFP_REPEAT|__GFP_NOWARN, | ||
298 | HUGETLB_PAGE_ORDER); | 300 | HUGETLB_PAGE_ORDER); |
299 | 301 | ||
300 | spin_lock(&hugetlb_lock); | 302 | spin_lock(&hugetlb_lock); |
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 2e0bfc93484b..33add96cd5fb 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c | |||
@@ -26,15 +26,18 @@ | |||
26 | #include <linux/backing-dev.h> | 26 | #include <linux/backing-dev.h> |
27 | #include <linux/bit_spinlock.h> | 27 | #include <linux/bit_spinlock.h> |
28 | #include <linux/rcupdate.h> | 28 | #include <linux/rcupdate.h> |
29 | #include <linux/slab.h> | ||
29 | #include <linux/swap.h> | 30 | #include <linux/swap.h> |
30 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
31 | #include <linux/fs.h> | 32 | #include <linux/fs.h> |
32 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
34 | #include <linux/vmalloc.h> | ||
33 | 35 | ||
34 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
35 | 37 | ||
36 | struct cgroup_subsys mem_cgroup_subsys; | 38 | struct cgroup_subsys mem_cgroup_subsys; |
37 | static const int MEM_CGROUP_RECLAIM_RETRIES = 5; | 39 | static const int MEM_CGROUP_RECLAIM_RETRIES = 5; |
40 | static struct kmem_cache *page_cgroup_cache; | ||
38 | 41 | ||
39 | /* | 42 | /* |
40 | * Statistics for memory cgroup. | 43 | * Statistics for memory cgroup. |
@@ -236,26 +239,12 @@ static struct mem_cgroup *mem_cgroup_from_cont(struct cgroup *cont) | |||
236 | css); | 239 | css); |
237 | } | 240 | } |
238 | 241 | ||
239 | static struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p) | 242 | struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p) |
240 | { | 243 | { |
241 | return container_of(task_subsys_state(p, mem_cgroup_subsys_id), | 244 | return container_of(task_subsys_state(p, mem_cgroup_subsys_id), |
242 | struct mem_cgroup, css); | 245 | struct mem_cgroup, css); |
243 | } | 246 | } |
244 | 247 | ||
245 | void mm_init_cgroup(struct mm_struct *mm, struct task_struct *p) | ||
246 | { | ||
247 | struct mem_cgroup *mem; | ||
248 | |||
249 | mem = mem_cgroup_from_task(p); | ||
250 | css_get(&mem->css); | ||
251 | mm->mem_cgroup = mem; | ||
252 | } | ||
253 | |||
254 | void mm_free_cgroup(struct mm_struct *mm) | ||
255 | { | ||
256 | css_put(&mm->mem_cgroup->css); | ||
257 | } | ||
258 | |||
259 | static inline int page_cgroup_locked(struct page *page) | 248 | static inline int page_cgroup_locked(struct page *page) |
260 | { | 249 | { |
261 | return bit_spin_is_locked(PAGE_CGROUP_LOCK_BIT, &page->page_cgroup); | 250 | return bit_spin_is_locked(PAGE_CGROUP_LOCK_BIT, &page->page_cgroup); |
@@ -287,10 +276,10 @@ static void unlock_page_cgroup(struct page *page) | |||
287 | bit_spin_unlock(PAGE_CGROUP_LOCK_BIT, &page->page_cgroup); | 276 | bit_spin_unlock(PAGE_CGROUP_LOCK_BIT, &page->page_cgroup); |
288 | } | 277 | } |
289 | 278 | ||
290 | static void __mem_cgroup_remove_list(struct page_cgroup *pc) | 279 | static void __mem_cgroup_remove_list(struct mem_cgroup_per_zone *mz, |
280 | struct page_cgroup *pc) | ||
291 | { | 281 | { |
292 | int from = pc->flags & PAGE_CGROUP_FLAG_ACTIVE; | 282 | int from = pc->flags & PAGE_CGROUP_FLAG_ACTIVE; |
293 | struct mem_cgroup_per_zone *mz = page_cgroup_zoneinfo(pc); | ||
294 | 283 | ||
295 | if (from) | 284 | if (from) |
296 | MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_ACTIVE) -= 1; | 285 | MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_ACTIVE) -= 1; |
@@ -301,10 +290,10 @@ static void __mem_cgroup_remove_list(struct page_cgroup *pc) | |||
301 | list_del_init(&pc->lru); | 290 | list_del_init(&pc->lru); |
302 | } | 291 | } |
303 | 292 | ||
304 | static void __mem_cgroup_add_list(struct page_cgroup *pc) | 293 | static void __mem_cgroup_add_list(struct mem_cgroup_per_zone *mz, |
294 | struct page_cgroup *pc) | ||
305 | { | 295 | { |
306 | int to = pc->flags & PAGE_CGROUP_FLAG_ACTIVE; | 296 | int to = pc->flags & PAGE_CGROUP_FLAG_ACTIVE; |
307 | struct mem_cgroup_per_zone *mz = page_cgroup_zoneinfo(pc); | ||
308 | 297 | ||
309 | if (!to) { | 298 | if (!to) { |
310 | MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_INACTIVE) += 1; | 299 | MEM_CGROUP_ZSTAT(mz, MEM_CGROUP_ZSTAT_INACTIVE) += 1; |
@@ -476,6 +465,7 @@ unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan, | |||
476 | int zid = zone_idx(z); | 465 | int zid = zone_idx(z); |
477 | struct mem_cgroup_per_zone *mz; | 466 | struct mem_cgroup_per_zone *mz; |
478 | 467 | ||
468 | BUG_ON(!mem_cont); | ||
479 | mz = mem_cgroup_zoneinfo(mem_cont, nid, zid); | 469 | mz = mem_cgroup_zoneinfo(mem_cont, nid, zid); |
480 | if (active) | 470 | if (active) |
481 | src = &mz->active_list; | 471 | src = &mz->active_list; |
@@ -560,7 +550,7 @@ retry: | |||
560 | } | 550 | } |
561 | unlock_page_cgroup(page); | 551 | unlock_page_cgroup(page); |
562 | 552 | ||
563 | pc = kzalloc(sizeof(struct page_cgroup), gfp_mask); | 553 | pc = kmem_cache_zalloc(page_cgroup_cache, gfp_mask); |
564 | if (pc == NULL) | 554 | if (pc == NULL) |
565 | goto err; | 555 | goto err; |
566 | 556 | ||
@@ -574,7 +564,7 @@ retry: | |||
574 | mm = &init_mm; | 564 | mm = &init_mm; |
575 | 565 | ||
576 | rcu_read_lock(); | 566 | rcu_read_lock(); |
577 | mem = rcu_dereference(mm->mem_cgroup); | 567 | mem = mem_cgroup_from_task(rcu_dereference(mm->owner)); |
578 | /* | 568 | /* |
579 | * For every charge from the cgroup, increment reference count | 569 | * For every charge from the cgroup, increment reference count |
580 | */ | 570 | */ |
@@ -602,7 +592,6 @@ retry: | |||
602 | mem_cgroup_out_of_memory(mem, gfp_mask); | 592 | mem_cgroup_out_of_memory(mem, gfp_mask); |
603 | goto out; | 593 | goto out; |
604 | } | 594 | } |
605 | congestion_wait(WRITE, HZ/10); | ||
606 | } | 595 | } |
607 | 596 | ||
608 | pc->ref_cnt = 1; | 597 | pc->ref_cnt = 1; |
@@ -610,7 +599,7 @@ retry: | |||
610 | pc->page = page; | 599 | pc->page = page; |
611 | pc->flags = PAGE_CGROUP_FLAG_ACTIVE; | 600 | pc->flags = PAGE_CGROUP_FLAG_ACTIVE; |
612 | if (ctype == MEM_CGROUP_CHARGE_TYPE_CACHE) | 601 | if (ctype == MEM_CGROUP_CHARGE_TYPE_CACHE) |
613 | pc->flags |= PAGE_CGROUP_FLAG_CACHE; | 602 | pc->flags = PAGE_CGROUP_FLAG_CACHE; |
614 | 603 | ||
615 | lock_page_cgroup(page); | 604 | lock_page_cgroup(page); |
616 | if (page_get_page_cgroup(page)) { | 605 | if (page_get_page_cgroup(page)) { |
@@ -622,14 +611,14 @@ retry: | |||
622 | */ | 611 | */ |
623 | res_counter_uncharge(&mem->res, PAGE_SIZE); | 612 | res_counter_uncharge(&mem->res, PAGE_SIZE); |
624 | css_put(&mem->css); | 613 | css_put(&mem->css); |
625 | kfree(pc); | 614 | kmem_cache_free(page_cgroup_cache, pc); |
626 | goto retry; | 615 | goto retry; |
627 | } | 616 | } |
628 | page_assign_page_cgroup(page, pc); | 617 | page_assign_page_cgroup(page, pc); |
629 | 618 | ||
630 | mz = page_cgroup_zoneinfo(pc); | 619 | mz = page_cgroup_zoneinfo(pc); |
631 | spin_lock_irqsave(&mz->lru_lock, flags); | 620 | spin_lock_irqsave(&mz->lru_lock, flags); |
632 | __mem_cgroup_add_list(pc); | 621 | __mem_cgroup_add_list(mz, pc); |
633 | spin_unlock_irqrestore(&mz->lru_lock, flags); | 622 | spin_unlock_irqrestore(&mz->lru_lock, flags); |
634 | 623 | ||
635 | unlock_page_cgroup(page); | 624 | unlock_page_cgroup(page); |
@@ -637,7 +626,7 @@ done: | |||
637 | return 0; | 626 | return 0; |
638 | out: | 627 | out: |
639 | css_put(&mem->css); | 628 | css_put(&mem->css); |
640 | kfree(pc); | 629 | kmem_cache_free(page_cgroup_cache, pc); |
641 | err: | 630 | err: |
642 | return -ENOMEM; | 631 | return -ENOMEM; |
643 | } | 632 | } |
@@ -685,7 +674,7 @@ void mem_cgroup_uncharge_page(struct page *page) | |||
685 | if (--(pc->ref_cnt) == 0) { | 674 | if (--(pc->ref_cnt) == 0) { |
686 | mz = page_cgroup_zoneinfo(pc); | 675 | mz = page_cgroup_zoneinfo(pc); |
687 | spin_lock_irqsave(&mz->lru_lock, flags); | 676 | spin_lock_irqsave(&mz->lru_lock, flags); |
688 | __mem_cgroup_remove_list(pc); | 677 | __mem_cgroup_remove_list(mz, pc); |
689 | spin_unlock_irqrestore(&mz->lru_lock, flags); | 678 | spin_unlock_irqrestore(&mz->lru_lock, flags); |
690 | 679 | ||
691 | page_assign_page_cgroup(page, NULL); | 680 | page_assign_page_cgroup(page, NULL); |
@@ -695,7 +684,7 @@ void mem_cgroup_uncharge_page(struct page *page) | |||
695 | res_counter_uncharge(&mem->res, PAGE_SIZE); | 684 | res_counter_uncharge(&mem->res, PAGE_SIZE); |
696 | css_put(&mem->css); | 685 | css_put(&mem->css); |
697 | 686 | ||
698 | kfree(pc); | 687 | kmem_cache_free(page_cgroup_cache, pc); |
699 | return; | 688 | return; |
700 | } | 689 | } |
701 | 690 | ||
@@ -747,7 +736,7 @@ void mem_cgroup_page_migration(struct page *page, struct page *newpage) | |||
747 | 736 | ||
748 | mz = page_cgroup_zoneinfo(pc); | 737 | mz = page_cgroup_zoneinfo(pc); |
749 | spin_lock_irqsave(&mz->lru_lock, flags); | 738 | spin_lock_irqsave(&mz->lru_lock, flags); |
750 | __mem_cgroup_remove_list(pc); | 739 | __mem_cgroup_remove_list(mz, pc); |
751 | spin_unlock_irqrestore(&mz->lru_lock, flags); | 740 | spin_unlock_irqrestore(&mz->lru_lock, flags); |
752 | 741 | ||
753 | page_assign_page_cgroup(page, NULL); | 742 | page_assign_page_cgroup(page, NULL); |
@@ -759,7 +748,7 @@ void mem_cgroup_page_migration(struct page *page, struct page *newpage) | |||
759 | 748 | ||
760 | mz = page_cgroup_zoneinfo(pc); | 749 | mz = page_cgroup_zoneinfo(pc); |
761 | spin_lock_irqsave(&mz->lru_lock, flags); | 750 | spin_lock_irqsave(&mz->lru_lock, flags); |
762 | __mem_cgroup_add_list(pc); | 751 | __mem_cgroup_add_list(mz, pc); |
763 | spin_unlock_irqrestore(&mz->lru_lock, flags); | 752 | spin_unlock_irqrestore(&mz->lru_lock, flags); |
764 | 753 | ||
765 | unlock_page_cgroup(newpage); | 754 | unlock_page_cgroup(newpage); |
@@ -853,13 +842,10 @@ static int mem_cgroup_write_strategy(char *buf, unsigned long long *tmp) | |||
853 | return 0; | 842 | return 0; |
854 | } | 843 | } |
855 | 844 | ||
856 | static ssize_t mem_cgroup_read(struct cgroup *cont, | 845 | static u64 mem_cgroup_read(struct cgroup *cont, struct cftype *cft) |
857 | struct cftype *cft, struct file *file, | ||
858 | char __user *userbuf, size_t nbytes, loff_t *ppos) | ||
859 | { | 846 | { |
860 | return res_counter_read(&mem_cgroup_from_cont(cont)->res, | 847 | return res_counter_read_u64(&mem_cgroup_from_cont(cont)->res, |
861 | cft->private, userbuf, nbytes, ppos, | 848 | cft->private); |
862 | NULL); | ||
863 | } | 849 | } |
864 | 850 | ||
865 | static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft, | 851 | static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft, |
@@ -871,27 +857,25 @@ static ssize_t mem_cgroup_write(struct cgroup *cont, struct cftype *cft, | |||
871 | mem_cgroup_write_strategy); | 857 | mem_cgroup_write_strategy); |
872 | } | 858 | } |
873 | 859 | ||
874 | static ssize_t mem_force_empty_write(struct cgroup *cont, | 860 | static int mem_cgroup_reset(struct cgroup *cont, unsigned int event) |
875 | struct cftype *cft, struct file *file, | ||
876 | const char __user *userbuf, | ||
877 | size_t nbytes, loff_t *ppos) | ||
878 | { | 861 | { |
879 | struct mem_cgroup *mem = mem_cgroup_from_cont(cont); | 862 | struct mem_cgroup *mem; |
880 | int ret = mem_cgroup_force_empty(mem); | 863 | |
881 | if (!ret) | 864 | mem = mem_cgroup_from_cont(cont); |
882 | ret = nbytes; | 865 | switch (event) { |
883 | return ret; | 866 | case RES_MAX_USAGE: |
867 | res_counter_reset_max(&mem->res); | ||
868 | break; | ||
869 | case RES_FAILCNT: | ||
870 | res_counter_reset_failcnt(&mem->res); | ||
871 | break; | ||
872 | } | ||
873 | return 0; | ||
884 | } | 874 | } |
885 | 875 | ||
886 | /* | 876 | static int mem_force_empty_write(struct cgroup *cont, unsigned int event) |
887 | * Note: This should be removed if cgroup supports write-only file. | ||
888 | */ | ||
889 | static ssize_t mem_force_empty_read(struct cgroup *cont, | ||
890 | struct cftype *cft, | ||
891 | struct file *file, char __user *userbuf, | ||
892 | size_t nbytes, loff_t *ppos) | ||
893 | { | 877 | { |
894 | return -EINVAL; | 878 | return mem_cgroup_force_empty(mem_cgroup_from_cont(cont)); |
895 | } | 879 | } |
896 | 880 | ||
897 | static const struct mem_cgroup_stat_desc { | 881 | static const struct mem_cgroup_stat_desc { |
@@ -902,9 +886,9 @@ static const struct mem_cgroup_stat_desc { | |||
902 | [MEM_CGROUP_STAT_RSS] = { "rss", PAGE_SIZE, }, | 886 | [MEM_CGROUP_STAT_RSS] = { "rss", PAGE_SIZE, }, |
903 | }; | 887 | }; |
904 | 888 | ||
905 | static int mem_control_stat_show(struct seq_file *m, void *arg) | 889 | static int mem_control_stat_show(struct cgroup *cont, struct cftype *cft, |
890 | struct cgroup_map_cb *cb) | ||
906 | { | 891 | { |
907 | struct cgroup *cont = m->private; | ||
908 | struct mem_cgroup *mem_cont = mem_cgroup_from_cont(cont); | 892 | struct mem_cgroup *mem_cont = mem_cgroup_from_cont(cont); |
909 | struct mem_cgroup_stat *stat = &mem_cont->stat; | 893 | struct mem_cgroup_stat *stat = &mem_cont->stat; |
910 | int i; | 894 | int i; |
@@ -914,8 +898,7 @@ static int mem_control_stat_show(struct seq_file *m, void *arg) | |||
914 | 898 | ||
915 | val = mem_cgroup_read_stat(stat, i); | 899 | val = mem_cgroup_read_stat(stat, i); |
916 | val *= mem_cgroup_stat_desc[i].unit; | 900 | val *= mem_cgroup_stat_desc[i].unit; |
917 | seq_printf(m, "%s %lld\n", mem_cgroup_stat_desc[i].msg, | 901 | cb->fill(cb, mem_cgroup_stat_desc[i].msg, val); |
918 | (long long)val); | ||
919 | } | 902 | } |
920 | /* showing # of active pages */ | 903 | /* showing # of active pages */ |
921 | { | 904 | { |
@@ -925,52 +908,43 @@ static int mem_control_stat_show(struct seq_file *m, void *arg) | |||
925 | MEM_CGROUP_ZSTAT_INACTIVE); | 908 | MEM_CGROUP_ZSTAT_INACTIVE); |
926 | active = mem_cgroup_get_all_zonestat(mem_cont, | 909 | active = mem_cgroup_get_all_zonestat(mem_cont, |
927 | MEM_CGROUP_ZSTAT_ACTIVE); | 910 | MEM_CGROUP_ZSTAT_ACTIVE); |
928 | seq_printf(m, "active %ld\n", (active) * PAGE_SIZE); | 911 | cb->fill(cb, "active", (active) * PAGE_SIZE); |
929 | seq_printf(m, "inactive %ld\n", (inactive) * PAGE_SIZE); | 912 | cb->fill(cb, "inactive", (inactive) * PAGE_SIZE); |
930 | } | 913 | } |
931 | return 0; | 914 | return 0; |
932 | } | 915 | } |
933 | 916 | ||
934 | static const struct file_operations mem_control_stat_file_operations = { | ||
935 | .read = seq_read, | ||
936 | .llseek = seq_lseek, | ||
937 | .release = single_release, | ||
938 | }; | ||
939 | |||
940 | static int mem_control_stat_open(struct inode *unused, struct file *file) | ||
941 | { | ||
942 | /* XXX __d_cont */ | ||
943 | struct cgroup *cont = file->f_dentry->d_parent->d_fsdata; | ||
944 | |||
945 | file->f_op = &mem_control_stat_file_operations; | ||
946 | return single_open(file, mem_control_stat_show, cont); | ||
947 | } | ||
948 | |||
949 | static struct cftype mem_cgroup_files[] = { | 917 | static struct cftype mem_cgroup_files[] = { |
950 | { | 918 | { |
951 | .name = "usage_in_bytes", | 919 | .name = "usage_in_bytes", |
952 | .private = RES_USAGE, | 920 | .private = RES_USAGE, |
953 | .read = mem_cgroup_read, | 921 | .read_u64 = mem_cgroup_read, |
922 | }, | ||
923 | { | ||
924 | .name = "max_usage_in_bytes", | ||
925 | .private = RES_MAX_USAGE, | ||
926 | .trigger = mem_cgroup_reset, | ||
927 | .read_u64 = mem_cgroup_read, | ||
954 | }, | 928 | }, |
955 | { | 929 | { |
956 | .name = "limit_in_bytes", | 930 | .name = "limit_in_bytes", |
957 | .private = RES_LIMIT, | 931 | .private = RES_LIMIT, |
958 | .write = mem_cgroup_write, | 932 | .write = mem_cgroup_write, |
959 | .read = mem_cgroup_read, | 933 | .read_u64 = mem_cgroup_read, |
960 | }, | 934 | }, |
961 | { | 935 | { |
962 | .name = "failcnt", | 936 | .name = "failcnt", |
963 | .private = RES_FAILCNT, | 937 | .private = RES_FAILCNT, |
964 | .read = mem_cgroup_read, | 938 | .trigger = mem_cgroup_reset, |
939 | .read_u64 = mem_cgroup_read, | ||
965 | }, | 940 | }, |
966 | { | 941 | { |
967 | .name = "force_empty", | 942 | .name = "force_empty", |
968 | .write = mem_force_empty_write, | 943 | .trigger = mem_force_empty_write, |
969 | .read = mem_force_empty_read, | ||
970 | }, | 944 | }, |
971 | { | 945 | { |
972 | .name = "stat", | 946 | .name = "stat", |
973 | .open = mem_control_stat_open, | 947 | .read_map = mem_control_stat_show, |
974 | }, | 948 | }, |
975 | }; | 949 | }; |
976 | 950 | ||
@@ -1010,6 +984,29 @@ static void free_mem_cgroup_per_zone_info(struct mem_cgroup *mem, int node) | |||
1010 | kfree(mem->info.nodeinfo[node]); | 984 | kfree(mem->info.nodeinfo[node]); |
1011 | } | 985 | } |
1012 | 986 | ||
987 | static struct mem_cgroup *mem_cgroup_alloc(void) | ||
988 | { | ||
989 | struct mem_cgroup *mem; | ||
990 | |||
991 | if (sizeof(*mem) < PAGE_SIZE) | ||
992 | mem = kmalloc(sizeof(*mem), GFP_KERNEL); | ||
993 | else | ||
994 | mem = vmalloc(sizeof(*mem)); | ||
995 | |||
996 | if (mem) | ||
997 | memset(mem, 0, sizeof(*mem)); | ||
998 | return mem; | ||
999 | } | ||
1000 | |||
1001 | static void mem_cgroup_free(struct mem_cgroup *mem) | ||
1002 | { | ||
1003 | if (sizeof(*mem) < PAGE_SIZE) | ||
1004 | kfree(mem); | ||
1005 | else | ||
1006 | vfree(mem); | ||
1007 | } | ||
1008 | |||
1009 | |||
1013 | static struct cgroup_subsys_state * | 1010 | static struct cgroup_subsys_state * |
1014 | mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) | 1011 | mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) |
1015 | { | 1012 | { |
@@ -1018,17 +1015,15 @@ mem_cgroup_create(struct cgroup_subsys *ss, struct cgroup *cont) | |||
1018 | 1015 | ||
1019 | if (unlikely((cont->parent) == NULL)) { | 1016 | if (unlikely((cont->parent) == NULL)) { |
1020 | mem = &init_mem_cgroup; | 1017 | mem = &init_mem_cgroup; |
1021 | init_mm.mem_cgroup = mem; | 1018 | page_cgroup_cache = KMEM_CACHE(page_cgroup, SLAB_PANIC); |
1022 | } else | 1019 | } else { |
1023 | mem = kzalloc(sizeof(struct mem_cgroup), GFP_KERNEL); | 1020 | mem = mem_cgroup_alloc(); |
1024 | 1021 | if (!mem) | |
1025 | if (mem == NULL) | 1022 | return ERR_PTR(-ENOMEM); |
1026 | return ERR_PTR(-ENOMEM); | 1023 | } |
1027 | 1024 | ||
1028 | res_counter_init(&mem->res); | 1025 | res_counter_init(&mem->res); |
1029 | 1026 | ||
1030 | memset(&mem->info, 0, sizeof(mem->info)); | ||
1031 | |||
1032 | for_each_node_state(node, N_POSSIBLE) | 1027 | for_each_node_state(node, N_POSSIBLE) |
1033 | if (alloc_mem_cgroup_per_zone_info(mem, node)) | 1028 | if (alloc_mem_cgroup_per_zone_info(mem, node)) |
1034 | goto free_out; | 1029 | goto free_out; |
@@ -1038,7 +1033,7 @@ free_out: | |||
1038 | for_each_node_state(node, N_POSSIBLE) | 1033 | for_each_node_state(node, N_POSSIBLE) |
1039 | free_mem_cgroup_per_zone_info(mem, node); | 1034 | free_mem_cgroup_per_zone_info(mem, node); |
1040 | if (cont->parent != NULL) | 1035 | if (cont->parent != NULL) |
1041 | kfree(mem); | 1036 | mem_cgroup_free(mem); |
1042 | return ERR_PTR(-ENOMEM); | 1037 | return ERR_PTR(-ENOMEM); |
1043 | } | 1038 | } |
1044 | 1039 | ||
@@ -1058,7 +1053,7 @@ static void mem_cgroup_destroy(struct cgroup_subsys *ss, | |||
1058 | for_each_node_state(node, N_POSSIBLE) | 1053 | for_each_node_state(node, N_POSSIBLE) |
1059 | free_mem_cgroup_per_zone_info(mem, node); | 1054 | free_mem_cgroup_per_zone_info(mem, node); |
1060 | 1055 | ||
1061 | kfree(mem_cgroup_from_cont(cont)); | 1056 | mem_cgroup_free(mem_cgroup_from_cont(cont)); |
1062 | } | 1057 | } |
1063 | 1058 | ||
1064 | static int mem_cgroup_populate(struct cgroup_subsys *ss, | 1059 | static int mem_cgroup_populate(struct cgroup_subsys *ss, |
@@ -1098,10 +1093,6 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss, | |||
1098 | if (!thread_group_leader(p)) | 1093 | if (!thread_group_leader(p)) |
1099 | goto out; | 1094 | goto out; |
1100 | 1095 | ||
1101 | css_get(&mem->css); | ||
1102 | rcu_assign_pointer(mm->mem_cgroup, mem); | ||
1103 | css_put(&old_mem->css); | ||
1104 | |||
1105 | out: | 1096 | out: |
1106 | mmput(mm); | 1097 | mmput(mm); |
1107 | } | 1098 | } |
diff --git a/mm/migrate.c b/mm/migrate.c index 4e0eccca5e26..449d77d409f5 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -383,7 +383,14 @@ static void migrate_page_copy(struct page *newpage, struct page *page) | |||
383 | 383 | ||
384 | if (PageDirty(page)) { | 384 | if (PageDirty(page)) { |
385 | clear_page_dirty_for_io(page); | 385 | clear_page_dirty_for_io(page); |
386 | set_page_dirty(newpage); | 386 | /* |
387 | * Want to mark the page and the radix tree as dirty, and | ||
388 | * redo the accounting that clear_page_dirty_for_io undid, | ||
389 | * but we can't use set_page_dirty because that function | ||
390 | * is actually a signal that all of the page has become dirty. | ||
391 | * Wheras only part of our page may be dirty. | ||
392 | */ | ||
393 | __set_page_dirty_nobuffers(newpage); | ||
387 | } | 394 | } |
388 | 395 | ||
389 | #ifdef CONFIG_SWAP | 396 | #ifdef CONFIG_SWAP |
@@ -230,8 +230,11 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) | |||
230 | might_sleep(); | 230 | might_sleep(); |
231 | if (vma->vm_ops && vma->vm_ops->close) | 231 | if (vma->vm_ops && vma->vm_ops->close) |
232 | vma->vm_ops->close(vma); | 232 | vma->vm_ops->close(vma); |
233 | if (vma->vm_file) | 233 | if (vma->vm_file) { |
234 | fput(vma->vm_file); | 234 | fput(vma->vm_file); |
235 | if (vma->vm_flags & VM_EXECUTABLE) | ||
236 | removed_exe_file_vma(vma->vm_mm); | ||
237 | } | ||
235 | mpol_put(vma_policy(vma)); | 238 | mpol_put(vma_policy(vma)); |
236 | kmem_cache_free(vm_area_cachep, vma); | 239 | kmem_cache_free(vm_area_cachep, vma); |
237 | return next; | 240 | return next; |
@@ -623,8 +626,11 @@ again: remove_next = 1 + (end > next->vm_end); | |||
623 | spin_unlock(&mapping->i_mmap_lock); | 626 | spin_unlock(&mapping->i_mmap_lock); |
624 | 627 | ||
625 | if (remove_next) { | 628 | if (remove_next) { |
626 | if (file) | 629 | if (file) { |
627 | fput(file); | 630 | fput(file); |
631 | if (next->vm_flags & VM_EXECUTABLE) | ||
632 | removed_exe_file_vma(mm); | ||
633 | } | ||
628 | mm->map_count--; | 634 | mm->map_count--; |
629 | mpol_put(vma_policy(next)); | 635 | mpol_put(vma_policy(next)); |
630 | kmem_cache_free(vm_area_cachep, next); | 636 | kmem_cache_free(vm_area_cachep, next); |
@@ -1154,6 +1160,8 @@ munmap_back: | |||
1154 | error = file->f_op->mmap(file, vma); | 1160 | error = file->f_op->mmap(file, vma); |
1155 | if (error) | 1161 | if (error) |
1156 | goto unmap_and_free_vma; | 1162 | goto unmap_and_free_vma; |
1163 | if (vm_flags & VM_EXECUTABLE) | ||
1164 | added_exe_file_vma(mm); | ||
1157 | } else if (vm_flags & VM_SHARED) { | 1165 | } else if (vm_flags & VM_SHARED) { |
1158 | error = shmem_zero_setup(vma); | 1166 | error = shmem_zero_setup(vma); |
1159 | if (error) | 1167 | if (error) |
@@ -1185,6 +1193,8 @@ munmap_back: | |||
1185 | mpol_put(vma_policy(vma)); | 1193 | mpol_put(vma_policy(vma)); |
1186 | kmem_cache_free(vm_area_cachep, vma); | 1194 | kmem_cache_free(vm_area_cachep, vma); |
1187 | fput(file); | 1195 | fput(file); |
1196 | if (vm_flags & VM_EXECUTABLE) | ||
1197 | removed_exe_file_vma(mm); | ||
1188 | } else { | 1198 | } else { |
1189 | vma_link(mm, vma, prev, rb_link, rb_parent); | 1199 | vma_link(mm, vma, prev, rb_link, rb_parent); |
1190 | file = vma->vm_file; | 1200 | file = vma->vm_file; |
@@ -1817,8 +1827,11 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, | |||
1817 | } | 1827 | } |
1818 | vma_set_policy(new, pol); | 1828 | vma_set_policy(new, pol); |
1819 | 1829 | ||
1820 | if (new->vm_file) | 1830 | if (new->vm_file) { |
1821 | get_file(new->vm_file); | 1831 | get_file(new->vm_file); |
1832 | if (vma->vm_flags & VM_EXECUTABLE) | ||
1833 | added_exe_file_vma(mm); | ||
1834 | } | ||
1822 | 1835 | ||
1823 | if (new->vm_ops && new->vm_ops->open) | 1836 | if (new->vm_ops && new->vm_ops->open) |
1824 | new->vm_ops->open(new); | 1837 | new->vm_ops->open(new); |
@@ -2135,8 +2148,11 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, | |||
2135 | new_vma->vm_start = addr; | 2148 | new_vma->vm_start = addr; |
2136 | new_vma->vm_end = addr + len; | 2149 | new_vma->vm_end = addr + len; |
2137 | new_vma->vm_pgoff = pgoff; | 2150 | new_vma->vm_pgoff = pgoff; |
2138 | if (new_vma->vm_file) | 2151 | if (new_vma->vm_file) { |
2139 | get_file(new_vma->vm_file); | 2152 | get_file(new_vma->vm_file); |
2153 | if (vma->vm_flags & VM_EXECUTABLE) | ||
2154 | added_exe_file_vma(mm); | ||
2155 | } | ||
2140 | if (new_vma->vm_ops && new_vma->vm_ops->open) | 2156 | if (new_vma->vm_ops && new_vma->vm_ops->open) |
2141 | new_vma->vm_ops->open(new_vma); | 2157 | new_vma->vm_ops->open(new_vma); |
2142 | vma_link(mm, new_vma, prev, rb_link, rb_parent); | 2158 | vma_link(mm, new_vma, prev, rb_link, rb_parent); |
diff --git a/mm/nommu.c b/mm/nommu.c index 1d32fe89d57b..ef8c62cec697 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
@@ -966,8 +966,13 @@ unsigned long do_mmap_pgoff(struct file *file, | |||
966 | 966 | ||
967 | INIT_LIST_HEAD(&vma->anon_vma_node); | 967 | INIT_LIST_HEAD(&vma->anon_vma_node); |
968 | atomic_set(&vma->vm_usage, 1); | 968 | atomic_set(&vma->vm_usage, 1); |
969 | if (file) | 969 | if (file) { |
970 | get_file(file); | 970 | get_file(file); |
971 | if (vm_flags & VM_EXECUTABLE) { | ||
972 | added_exe_file_vma(current->mm); | ||
973 | vma->vm_mm = current->mm; | ||
974 | } | ||
975 | } | ||
971 | vma->vm_file = file; | 976 | vma->vm_file = file; |
972 | vma->vm_flags = vm_flags; | 977 | vma->vm_flags = vm_flags; |
973 | vma->vm_start = addr; | 978 | vma->vm_start = addr; |
@@ -1022,8 +1027,11 @@ unsigned long do_mmap_pgoff(struct file *file, | |||
1022 | up_write(&nommu_vma_sem); | 1027 | up_write(&nommu_vma_sem); |
1023 | kfree(vml); | 1028 | kfree(vml); |
1024 | if (vma) { | 1029 | if (vma) { |
1025 | if (vma->vm_file) | 1030 | if (vma->vm_file) { |
1026 | fput(vma->vm_file); | 1031 | fput(vma->vm_file); |
1032 | if (vma->vm_flags & VM_EXECUTABLE) | ||
1033 | removed_exe_file_vma(vma->vm_mm); | ||
1034 | } | ||
1027 | kfree(vma); | 1035 | kfree(vma); |
1028 | } | 1036 | } |
1029 | return ret; | 1037 | return ret; |
@@ -1053,7 +1061,7 @@ EXPORT_SYMBOL(do_mmap_pgoff); | |||
1053 | /* | 1061 | /* |
1054 | * handle mapping disposal for uClinux | 1062 | * handle mapping disposal for uClinux |
1055 | */ | 1063 | */ |
1056 | static void put_vma(struct vm_area_struct *vma) | 1064 | static void put_vma(struct mm_struct *mm, struct vm_area_struct *vma) |
1057 | { | 1065 | { |
1058 | if (vma) { | 1066 | if (vma) { |
1059 | down_write(&nommu_vma_sem); | 1067 | down_write(&nommu_vma_sem); |
@@ -1075,8 +1083,11 @@ static void put_vma(struct vm_area_struct *vma) | |||
1075 | realalloc -= kobjsize(vma); | 1083 | realalloc -= kobjsize(vma); |
1076 | askedalloc -= sizeof(*vma); | 1084 | askedalloc -= sizeof(*vma); |
1077 | 1085 | ||
1078 | if (vma->vm_file) | 1086 | if (vma->vm_file) { |
1079 | fput(vma->vm_file); | 1087 | fput(vma->vm_file); |
1088 | if (vma->vm_flags & VM_EXECUTABLE) | ||
1089 | removed_exe_file_vma(mm); | ||
1090 | } | ||
1080 | kfree(vma); | 1091 | kfree(vma); |
1081 | } | 1092 | } |
1082 | 1093 | ||
@@ -1113,7 +1124,7 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len) | |||
1113 | found: | 1124 | found: |
1114 | vml = *parent; | 1125 | vml = *parent; |
1115 | 1126 | ||
1116 | put_vma(vml->vma); | 1127 | put_vma(mm, vml->vma); |
1117 | 1128 | ||
1118 | *parent = vml->next; | 1129 | *parent = vml->next; |
1119 | realalloc -= kobjsize(vml); | 1130 | realalloc -= kobjsize(vml); |
@@ -1158,7 +1169,7 @@ void exit_mmap(struct mm_struct * mm) | |||
1158 | 1169 | ||
1159 | while ((tmp = mm->context.vmlist)) { | 1170 | while ((tmp = mm->context.vmlist)) { |
1160 | mm->context.vmlist = tmp->next; | 1171 | mm->context.vmlist = tmp->next; |
1161 | put_vma(tmp->vma); | 1172 | put_vma(mm, tmp->vma); |
1162 | 1173 | ||
1163 | realalloc -= kobjsize(tmp); | 1174 | realalloc -= kobjsize(tmp); |
1164 | askedalloc -= sizeof(*tmp); | 1175 | askedalloc -= sizeof(*tmp); |
diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 5e00f1772c20..789b6adbef37 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c | |||
@@ -164,9 +164,20 @@ int dirty_ratio_handler(struct ctl_table *table, int write, | |||
164 | */ | 164 | */ |
165 | static inline void __bdi_writeout_inc(struct backing_dev_info *bdi) | 165 | static inline void __bdi_writeout_inc(struct backing_dev_info *bdi) |
166 | { | 166 | { |
167 | __prop_inc_percpu(&vm_completions, &bdi->completions); | 167 | __prop_inc_percpu_max(&vm_completions, &bdi->completions, |
168 | bdi->max_prop_frac); | ||
168 | } | 169 | } |
169 | 170 | ||
171 | void bdi_writeout_inc(struct backing_dev_info *bdi) | ||
172 | { | ||
173 | unsigned long flags; | ||
174 | |||
175 | local_irq_save(flags); | ||
176 | __bdi_writeout_inc(bdi); | ||
177 | local_irq_restore(flags); | ||
178 | } | ||
179 | EXPORT_SYMBOL_GPL(bdi_writeout_inc); | ||
180 | |||
170 | static inline void task_dirty_inc(struct task_struct *tsk) | 181 | static inline void task_dirty_inc(struct task_struct *tsk) |
171 | { | 182 | { |
172 | prop_inc_single(&vm_dirties, &tsk->dirties); | 183 | prop_inc_single(&vm_dirties, &tsk->dirties); |
@@ -200,7 +211,8 @@ clip_bdi_dirty_limit(struct backing_dev_info *bdi, long dirty, long *pbdi_dirty) | |||
200 | avail_dirty = dirty - | 211 | avail_dirty = dirty - |
201 | (global_page_state(NR_FILE_DIRTY) + | 212 | (global_page_state(NR_FILE_DIRTY) + |
202 | global_page_state(NR_WRITEBACK) + | 213 | global_page_state(NR_WRITEBACK) + |
203 | global_page_state(NR_UNSTABLE_NFS)); | 214 | global_page_state(NR_UNSTABLE_NFS) + |
215 | global_page_state(NR_WRITEBACK_TEMP)); | ||
204 | 216 | ||
205 | if (avail_dirty < 0) | 217 | if (avail_dirty < 0) |
206 | avail_dirty = 0; | 218 | avail_dirty = 0; |
@@ -243,6 +255,55 @@ static void task_dirty_limit(struct task_struct *tsk, long *pdirty) | |||
243 | } | 255 | } |
244 | 256 | ||
245 | /* | 257 | /* |
258 | * | ||
259 | */ | ||
260 | static DEFINE_SPINLOCK(bdi_lock); | ||
261 | static unsigned int bdi_min_ratio; | ||
262 | |||
263 | int bdi_set_min_ratio(struct backing_dev_info *bdi, unsigned int min_ratio) | ||
264 | { | ||
265 | int ret = 0; | ||
266 | unsigned long flags; | ||
267 | |||
268 | spin_lock_irqsave(&bdi_lock, flags); | ||
269 | if (min_ratio > bdi->max_ratio) { | ||
270 | ret = -EINVAL; | ||
271 | } else { | ||
272 | min_ratio -= bdi->min_ratio; | ||
273 | if (bdi_min_ratio + min_ratio < 100) { | ||
274 | bdi_min_ratio += min_ratio; | ||
275 | bdi->min_ratio += min_ratio; | ||
276 | } else { | ||
277 | ret = -EINVAL; | ||
278 | } | ||
279 | } | ||
280 | spin_unlock_irqrestore(&bdi_lock, flags); | ||
281 | |||
282 | return ret; | ||
283 | } | ||
284 | |||
285 | int bdi_set_max_ratio(struct backing_dev_info *bdi, unsigned max_ratio) | ||
286 | { | ||
287 | unsigned long flags; | ||
288 | int ret = 0; | ||
289 | |||
290 | if (max_ratio > 100) | ||
291 | return -EINVAL; | ||
292 | |||
293 | spin_lock_irqsave(&bdi_lock, flags); | ||
294 | if (bdi->min_ratio > max_ratio) { | ||
295 | ret = -EINVAL; | ||
296 | } else { | ||
297 | bdi->max_ratio = max_ratio; | ||
298 | bdi->max_prop_frac = (PROP_FRAC_BASE * max_ratio) / 100; | ||
299 | } | ||
300 | spin_unlock_irqrestore(&bdi_lock, flags); | ||
301 | |||
302 | return ret; | ||
303 | } | ||
304 | EXPORT_SYMBOL(bdi_set_max_ratio); | ||
305 | |||
306 | /* | ||
246 | * Work out the current dirty-memory clamping and background writeout | 307 | * Work out the current dirty-memory clamping and background writeout |
247 | * thresholds. | 308 | * thresholds. |
248 | * | 309 | * |
@@ -300,7 +361,7 @@ static unsigned long determine_dirtyable_memory(void) | |||
300 | return x + 1; /* Ensure that we never return 0 */ | 361 | return x + 1; /* Ensure that we never return 0 */ |
301 | } | 362 | } |
302 | 363 | ||
303 | static void | 364 | void |
304 | get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty, | 365 | get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty, |
305 | struct backing_dev_info *bdi) | 366 | struct backing_dev_info *bdi) |
306 | { | 367 | { |
@@ -330,7 +391,7 @@ get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty, | |||
330 | *pdirty = dirty; | 391 | *pdirty = dirty; |
331 | 392 | ||
332 | if (bdi) { | 393 | if (bdi) { |
333 | u64 bdi_dirty = dirty; | 394 | u64 bdi_dirty; |
334 | long numerator, denominator; | 395 | long numerator, denominator; |
335 | 396 | ||
336 | /* | 397 | /* |
@@ -338,8 +399,12 @@ get_dirty_limits(long *pbackground, long *pdirty, long *pbdi_dirty, | |||
338 | */ | 399 | */ |
339 | bdi_writeout_fraction(bdi, &numerator, &denominator); | 400 | bdi_writeout_fraction(bdi, &numerator, &denominator); |
340 | 401 | ||
402 | bdi_dirty = (dirty * (100 - bdi_min_ratio)) / 100; | ||
341 | bdi_dirty *= numerator; | 403 | bdi_dirty *= numerator; |
342 | do_div(bdi_dirty, denominator); | 404 | do_div(bdi_dirty, denominator); |
405 | bdi_dirty += (dirty * bdi->min_ratio) / 100; | ||
406 | if (bdi_dirty > (dirty * bdi->max_ratio) / 100) | ||
407 | bdi_dirty = dirty * bdi->max_ratio / 100; | ||
343 | 408 | ||
344 | *pbdi_dirty = bdi_dirty; | 409 | *pbdi_dirty = bdi_dirty; |
345 | clip_bdi_dirty_limit(bdi, dirty, pbdi_dirty); | 410 | clip_bdi_dirty_limit(bdi, dirty, pbdi_dirty); |
@@ -1192,7 +1257,7 @@ int test_clear_page_writeback(struct page *page) | |||
1192 | radix_tree_tag_clear(&mapping->page_tree, | 1257 | radix_tree_tag_clear(&mapping->page_tree, |
1193 | page_index(page), | 1258 | page_index(page), |
1194 | PAGECACHE_TAG_WRITEBACK); | 1259 | PAGECACHE_TAG_WRITEBACK); |
1195 | if (bdi_cap_writeback_dirty(bdi)) { | 1260 | if (bdi_cap_account_writeback(bdi)) { |
1196 | __dec_bdi_stat(bdi, BDI_WRITEBACK); | 1261 | __dec_bdi_stat(bdi, BDI_WRITEBACK); |
1197 | __bdi_writeout_inc(bdi); | 1262 | __bdi_writeout_inc(bdi); |
1198 | } | 1263 | } |
@@ -1221,7 +1286,7 @@ int test_set_page_writeback(struct page *page) | |||
1221 | radix_tree_tag_set(&mapping->page_tree, | 1286 | radix_tree_tag_set(&mapping->page_tree, |
1222 | page_index(page), | 1287 | page_index(page), |
1223 | PAGECACHE_TAG_WRITEBACK); | 1288 | PAGECACHE_TAG_WRITEBACK); |
1224 | if (bdi_cap_writeback_dirty(bdi)) | 1289 | if (bdi_cap_account_writeback(bdi)) |
1225 | __inc_bdi_stat(bdi, BDI_WRITEBACK); | 1290 | __inc_bdi_stat(bdi, BDI_WRITEBACK); |
1226 | } | 1291 | } |
1227 | if (!PageDirty(page)) | 1292 | if (!PageDirty(page)) |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index d1cf4f05dcda..bdd5c432c426 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/fault-inject.h> | 45 | #include <linux/fault-inject.h> |
46 | #include <linux/page-isolation.h> | 46 | #include <linux/page-isolation.h> |
47 | #include <linux/memcontrol.h> | 47 | #include <linux/memcontrol.h> |
48 | #include <linux/debugobjects.h> | ||
48 | 49 | ||
49 | #include <asm/tlbflush.h> | 50 | #include <asm/tlbflush.h> |
50 | #include <asm/div64.h> | 51 | #include <asm/div64.h> |
@@ -532,8 +533,11 @@ static void __free_pages_ok(struct page *page, unsigned int order) | |||
532 | if (reserved) | 533 | if (reserved) |
533 | return; | 534 | return; |
534 | 535 | ||
535 | if (!PageHighMem(page)) | 536 | if (!PageHighMem(page)) { |
536 | debug_check_no_locks_freed(page_address(page),PAGE_SIZE<<order); | 537 | debug_check_no_locks_freed(page_address(page),PAGE_SIZE<<order); |
538 | debug_check_no_obj_freed(page_address(page), | ||
539 | PAGE_SIZE << order); | ||
540 | } | ||
537 | arch_free_page(page, order); | 541 | arch_free_page(page, order); |
538 | kernel_map_pages(page, 1 << order, 0); | 542 | kernel_map_pages(page, 1 << order, 0); |
539 | 543 | ||
@@ -995,8 +999,10 @@ static void free_hot_cold_page(struct page *page, int cold) | |||
995 | if (free_pages_check(page)) | 999 | if (free_pages_check(page)) |
996 | return; | 1000 | return; |
997 | 1001 | ||
998 | if (!PageHighMem(page)) | 1002 | if (!PageHighMem(page)) { |
999 | debug_check_no_locks_freed(page_address(page), PAGE_SIZE); | 1003 | debug_check_no_locks_freed(page_address(page), PAGE_SIZE); |
1004 | debug_check_no_obj_freed(page_address(page), PAGE_SIZE); | ||
1005 | } | ||
1000 | arch_free_page(page, 0); | 1006 | arch_free_page(page, 0); |
1001 | kernel_map_pages(page, 1, 0); | 1007 | kernel_map_pages(page, 1, 0); |
1002 | 1008 | ||
@@ -1461,7 +1467,8 @@ __alloc_pages_internal(gfp_t gfp_mask, unsigned int order, | |||
1461 | struct task_struct *p = current; | 1467 | struct task_struct *p = current; |
1462 | int do_retry; | 1468 | int do_retry; |
1463 | int alloc_flags; | 1469 | int alloc_flags; |
1464 | int did_some_progress; | 1470 | unsigned long did_some_progress; |
1471 | unsigned long pages_reclaimed = 0; | ||
1465 | 1472 | ||
1466 | might_sleep_if(wait); | 1473 | might_sleep_if(wait); |
1467 | 1474 | ||
@@ -1611,14 +1618,26 @@ nofail_alloc: | |||
1611 | * Don't let big-order allocations loop unless the caller explicitly | 1618 | * Don't let big-order allocations loop unless the caller explicitly |
1612 | * requests that. Wait for some write requests to complete then retry. | 1619 | * requests that. Wait for some write requests to complete then retry. |
1613 | * | 1620 | * |
1614 | * In this implementation, __GFP_REPEAT means __GFP_NOFAIL for order | 1621 | * In this implementation, order <= PAGE_ALLOC_COSTLY_ORDER |
1615 | * <= 3, but that may not be true in other implementations. | 1622 | * means __GFP_NOFAIL, but that may not be true in other |
1623 | * implementations. | ||
1624 | * | ||
1625 | * For order > PAGE_ALLOC_COSTLY_ORDER, if __GFP_REPEAT is | ||
1626 | * specified, then we retry until we no longer reclaim any pages | ||
1627 | * (above), or we've reclaimed an order of pages at least as | ||
1628 | * large as the allocation's order. In both cases, if the | ||
1629 | * allocation still fails, we stop retrying. | ||
1616 | */ | 1630 | */ |
1631 | pages_reclaimed += did_some_progress; | ||
1617 | do_retry = 0; | 1632 | do_retry = 0; |
1618 | if (!(gfp_mask & __GFP_NORETRY)) { | 1633 | if (!(gfp_mask & __GFP_NORETRY)) { |
1619 | if ((order <= PAGE_ALLOC_COSTLY_ORDER) || | 1634 | if (order <= PAGE_ALLOC_COSTLY_ORDER) { |
1620 | (gfp_mask & __GFP_REPEAT)) | ||
1621 | do_retry = 1; | 1635 | do_retry = 1; |
1636 | } else { | ||
1637 | if (gfp_mask & __GFP_REPEAT && | ||
1638 | pages_reclaimed < (1 << order)) | ||
1639 | do_retry = 1; | ||
1640 | } | ||
1622 | if (gfp_mask & __GFP_NOFAIL) | 1641 | if (gfp_mask & __GFP_NOFAIL) |
1623 | do_retry = 1; | 1642 | do_retry = 1; |
1624 | } | 1643 | } |
@@ -2524,7 +2543,9 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, | |||
2524 | struct page *page; | 2543 | struct page *page; |
2525 | unsigned long end_pfn = start_pfn + size; | 2544 | unsigned long end_pfn = start_pfn + size; |
2526 | unsigned long pfn; | 2545 | unsigned long pfn; |
2546 | struct zone *z; | ||
2527 | 2547 | ||
2548 | z = &NODE_DATA(nid)->node_zones[zone]; | ||
2528 | for (pfn = start_pfn; pfn < end_pfn; pfn++) { | 2549 | for (pfn = start_pfn; pfn < end_pfn; pfn++) { |
2529 | /* | 2550 | /* |
2530 | * There can be holes in boot-time mem_map[]s | 2551 | * There can be holes in boot-time mem_map[]s |
@@ -2542,7 +2563,6 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, | |||
2542 | init_page_count(page); | 2563 | init_page_count(page); |
2543 | reset_page_mapcount(page); | 2564 | reset_page_mapcount(page); |
2544 | SetPageReserved(page); | 2565 | SetPageReserved(page); |
2545 | |||
2546 | /* | 2566 | /* |
2547 | * Mark the block movable so that blocks are reserved for | 2567 | * Mark the block movable so that blocks are reserved for |
2548 | * movable at startup. This will force kernel allocations | 2568 | * movable at startup. This will force kernel allocations |
@@ -2551,8 +2571,15 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone, | |||
2551 | * kernel allocations are made. Later some blocks near | 2571 | * kernel allocations are made. Later some blocks near |
2552 | * the start are marked MIGRATE_RESERVE by | 2572 | * the start are marked MIGRATE_RESERVE by |
2553 | * setup_zone_migrate_reserve() | 2573 | * setup_zone_migrate_reserve() |
2574 | * | ||
2575 | * bitmap is created for zone's valid pfn range. but memmap | ||
2576 | * can be created for invalid pages (for alignment) | ||
2577 | * check here not to call set_pageblock_migratetype() against | ||
2578 | * pfn out of zone. | ||
2554 | */ | 2579 | */ |
2555 | if ((pfn & (pageblock_nr_pages-1))) | 2580 | if ((z->zone_start_pfn <= pfn) |
2581 | && (pfn < z->zone_start_pfn + z->spanned_pages) | ||
2582 | && !(pfn & (pageblock_nr_pages - 1))) | ||
2556 | set_pageblock_migratetype(page, MIGRATE_MOVABLE); | 2583 | set_pageblock_migratetype(page, MIGRATE_MOVABLE); |
2557 | 2584 | ||
2558 | INIT_LIST_HEAD(&page->lru); | 2585 | INIT_LIST_HEAD(&page->lru); |
@@ -4464,6 +4491,8 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags, | |||
4464 | pfn = page_to_pfn(page); | 4491 | pfn = page_to_pfn(page); |
4465 | bitmap = get_pageblock_bitmap(zone, pfn); | 4492 | bitmap = get_pageblock_bitmap(zone, pfn); |
4466 | bitidx = pfn_to_bitidx(zone, pfn); | 4493 | bitidx = pfn_to_bitidx(zone, pfn); |
4494 | VM_BUG_ON(pfn < zone->zone_start_pfn); | ||
4495 | VM_BUG_ON(pfn >= zone->zone_start_pfn + zone->spanned_pages); | ||
4467 | 4496 | ||
4468 | for (; start_bitidx <= end_bitidx; start_bitidx++, value <<= 1) | 4497 | for (; start_bitidx <= end_bitidx; start_bitidx++, value <<= 1) |
4469 | if (flags & value) | 4498 | if (flags & value) |
diff --git a/mm/readahead.c b/mm/readahead.c index 8762e8988972..d8723a5f6496 100644 --- a/mm/readahead.c +++ b/mm/readahead.c | |||
@@ -235,7 +235,13 @@ unsigned long max_sane_readahead(unsigned long nr) | |||
235 | 235 | ||
236 | static int __init readahead_init(void) | 236 | static int __init readahead_init(void) |
237 | { | 237 | { |
238 | return bdi_init(&default_backing_dev_info); | 238 | int err; |
239 | |||
240 | err = bdi_init(&default_backing_dev_info); | ||
241 | if (!err) | ||
242 | bdi_register(&default_backing_dev_info, NULL, "default"); | ||
243 | |||
244 | return err; | ||
239 | } | 245 | } |
240 | subsys_initcall(readahead_init); | 246 | subsys_initcall(readahead_init); |
241 | 247 | ||
diff --git a/mm/shmem.c b/mm/shmem.c index e6d9298aa22a..e2a6ae1a44e9 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -201,7 +201,7 @@ static struct vm_operations_struct shmem_vm_ops; | |||
201 | 201 | ||
202 | static struct backing_dev_info shmem_backing_dev_info __read_mostly = { | 202 | static struct backing_dev_info shmem_backing_dev_info __read_mostly = { |
203 | .ra_pages = 0, /* No readahead */ | 203 | .ra_pages = 0, /* No readahead */ |
204 | .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, | 204 | .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, |
205 | .unplug_io_fn = default_unplug_io_fn, | 205 | .unplug_io_fn = default_unplug_io_fn, |
206 | }; | 206 | }; |
207 | 207 | ||
@@ -110,6 +110,7 @@ | |||
110 | #include <linux/fault-inject.h> | 110 | #include <linux/fault-inject.h> |
111 | #include <linux/rtmutex.h> | 111 | #include <linux/rtmutex.h> |
112 | #include <linux/reciprocal_div.h> | 112 | #include <linux/reciprocal_div.h> |
113 | #include <linux/debugobjects.h> | ||
113 | 114 | ||
114 | #include <asm/cacheflush.h> | 115 | #include <asm/cacheflush.h> |
115 | #include <asm/tlbflush.h> | 116 | #include <asm/tlbflush.h> |
@@ -174,12 +175,14 @@ | |||
174 | SLAB_CACHE_DMA | \ | 175 | SLAB_CACHE_DMA | \ |
175 | SLAB_STORE_USER | \ | 176 | SLAB_STORE_USER | \ |
176 | SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \ | 177 | SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \ |
177 | SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD) | 178 | SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \ |
179 | SLAB_DEBUG_OBJECTS) | ||
178 | #else | 180 | #else |
179 | # define CREATE_MASK (SLAB_HWCACHE_ALIGN | \ | 181 | # define CREATE_MASK (SLAB_HWCACHE_ALIGN | \ |
180 | SLAB_CACHE_DMA | \ | 182 | SLAB_CACHE_DMA | \ |
181 | SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \ | 183 | SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \ |
182 | SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD) | 184 | SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \ |
185 | SLAB_DEBUG_OBJECTS) | ||
183 | #endif | 186 | #endif |
184 | 187 | ||
185 | /* | 188 | /* |
@@ -858,7 +861,7 @@ static void cache_estimate(unsigned long gfporder, size_t buffer_size, | |||
858 | *left_over = slab_size - nr_objs*buffer_size - mgmt_size; | 861 | *left_over = slab_size - nr_objs*buffer_size - mgmt_size; |
859 | } | 862 | } |
860 | 863 | ||
861 | #define slab_error(cachep, msg) __slab_error(__FUNCTION__, cachep, msg) | 864 | #define slab_error(cachep, msg) __slab_error(__func__, cachep, msg) |
862 | 865 | ||
863 | static void __slab_error(const char *function, struct kmem_cache *cachep, | 866 | static void __slab_error(const char *function, struct kmem_cache *cachep, |
864 | char *msg) | 867 | char *msg) |
@@ -2153,7 +2156,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, | |||
2153 | */ | 2156 | */ |
2154 | if (!name || in_interrupt() || (size < BYTES_PER_WORD) || | 2157 | if (!name || in_interrupt() || (size < BYTES_PER_WORD) || |
2155 | size > KMALLOC_MAX_SIZE) { | 2158 | size > KMALLOC_MAX_SIZE) { |
2156 | printk(KERN_ERR "%s: Early error in slab %s\n", __FUNCTION__, | 2159 | printk(KERN_ERR "%s: Early error in slab %s\n", __func__, |
2157 | name); | 2160 | name); |
2158 | BUG(); | 2161 | BUG(); |
2159 | } | 2162 | } |
@@ -3760,6 +3763,8 @@ void kmem_cache_free(struct kmem_cache *cachep, void *objp) | |||
3760 | 3763 | ||
3761 | local_irq_save(flags); | 3764 | local_irq_save(flags); |
3762 | debug_check_no_locks_freed(objp, obj_size(cachep)); | 3765 | debug_check_no_locks_freed(objp, obj_size(cachep)); |
3766 | if (!(cachep->flags & SLAB_DEBUG_OBJECTS)) | ||
3767 | debug_check_no_obj_freed(objp, obj_size(cachep)); | ||
3763 | __cache_free(cachep, objp); | 3768 | __cache_free(cachep, objp); |
3764 | local_irq_restore(flags); | 3769 | local_irq_restore(flags); |
3765 | } | 3770 | } |
@@ -3785,6 +3790,7 @@ void kfree(const void *objp) | |||
3785 | kfree_debugcheck(objp); | 3790 | kfree_debugcheck(objp); |
3786 | c = virt_to_cache(objp); | 3791 | c = virt_to_cache(objp); |
3787 | debug_check_no_locks_freed(objp, obj_size(c)); | 3792 | debug_check_no_locks_freed(objp, obj_size(c)); |
3793 | debug_check_no_obj_freed(objp, obj_size(c)); | ||
3788 | __cache_free(c, (void *)objp); | 3794 | __cache_free(c, (void *)objp); |
3789 | local_irq_restore(flags); | 3795 | local_irq_restore(flags); |
3790 | } | 3796 | } |
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/cpuset.h> | 19 | #include <linux/cpuset.h> |
20 | #include <linux/mempolicy.h> | 20 | #include <linux/mempolicy.h> |
21 | #include <linux/ctype.h> | 21 | #include <linux/ctype.h> |
22 | #include <linux/debugobjects.h> | ||
22 | #include <linux/kallsyms.h> | 23 | #include <linux/kallsyms.h> |
23 | #include <linux/memory.h> | 24 | #include <linux/memory.h> |
24 | 25 | ||
@@ -1747,6 +1748,8 @@ static __always_inline void slab_free(struct kmem_cache *s, | |||
1747 | local_irq_save(flags); | 1748 | local_irq_save(flags); |
1748 | c = get_cpu_slab(s, smp_processor_id()); | 1749 | c = get_cpu_slab(s, smp_processor_id()); |
1749 | debug_check_no_locks_freed(object, c->objsize); | 1750 | debug_check_no_locks_freed(object, c->objsize); |
1751 | if (!(s->flags & SLAB_DEBUG_OBJECTS)) | ||
1752 | debug_check_no_obj_freed(object, s->objsize); | ||
1750 | if (likely(page == c->page && c->node >= 0)) { | 1753 | if (likely(page == c->page && c->node >= 0)) { |
1751 | object[c->offset] = c->freelist; | 1754 | object[c->offset] = c->freelist; |
1752 | c->freelist = object; | 1755 | c->freelist = object; |
@@ -2978,7 +2981,7 @@ void __init kmem_cache_init(void) | |||
2978 | kmalloc_caches[0].refcount = -1; | 2981 | kmalloc_caches[0].refcount = -1; |
2979 | caches++; | 2982 | caches++; |
2980 | 2983 | ||
2981 | hotplug_memory_notifier(slab_memory_callback, 1); | 2984 | hotplug_memory_notifier(slab_memory_callback, SLAB_CALLBACK_PRI); |
2982 | #endif | 2985 | #endif |
2983 | 2986 | ||
2984 | /* Able to allocate the per node structures */ | 2987 | /* Able to allocate the per node structures */ |
diff --git a/mm/sparse.c b/mm/sparse.c index dff71f173ae9..36511c7b5e2c 100644 --- a/mm/sparse.c +++ b/mm/sparse.c | |||
@@ -250,29 +250,18 @@ static unsigned long *__kmalloc_section_usemap(void) | |||
250 | 250 | ||
251 | static unsigned long *__init sparse_early_usemap_alloc(unsigned long pnum) | 251 | static unsigned long *__init sparse_early_usemap_alloc(unsigned long pnum) |
252 | { | 252 | { |
253 | unsigned long *usemap, section_nr; | 253 | unsigned long *usemap; |
254 | struct mem_section *ms = __nr_to_section(pnum); | 254 | struct mem_section *ms = __nr_to_section(pnum); |
255 | int nid = sparse_early_nid(ms); | 255 | int nid = sparse_early_nid(ms); |
256 | struct pglist_data *pgdat = NODE_DATA(nid); | ||
257 | 256 | ||
258 | /* | 257 | usemap = alloc_bootmem_node(NODE_DATA(nid), usemap_size()); |
259 | * Usemap's page can't be freed until freeing other sections | ||
260 | * which use it. And, Pgdat has same feature. | ||
261 | * If section A has pgdat and section B has usemap for other | ||
262 | * sections (includes section A), both sections can't be removed, | ||
263 | * because there is the dependency each other. | ||
264 | * To solve above issue, this collects all usemap on the same section | ||
265 | * which has pgdat. | ||
266 | */ | ||
267 | section_nr = pfn_to_section_nr(__pa(pgdat) >> PAGE_SHIFT); | ||
268 | usemap = alloc_bootmem_section(usemap_size(), section_nr); | ||
269 | if (usemap) | 258 | if (usemap) |
270 | return usemap; | 259 | return usemap; |
271 | 260 | ||
272 | /* Stupid: suppress gcc warning for SPARSEMEM && !NUMA */ | 261 | /* Stupid: suppress gcc warning for SPARSEMEM && !NUMA */ |
273 | nid = 0; | 262 | nid = 0; |
274 | 263 | ||
275 | printk(KERN_WARNING "%s: allocation failed\n", __FUNCTION__); | 264 | printk(KERN_WARNING "%s: allocation failed\n", __func__); |
276 | return NULL; | 265 | return NULL; |
277 | } | 266 | } |
278 | 267 | ||
@@ -302,7 +291,7 @@ struct page __init *sparse_early_mem_map_alloc(unsigned long pnum) | |||
302 | return map; | 291 | return map; |
303 | 292 | ||
304 | printk(KERN_ERR "%s: sparsemem memory map backing failed " | 293 | printk(KERN_ERR "%s: sparsemem memory map backing failed " |
305 | "some memory will not be available.\n", __FUNCTION__); | 294 | "some memory will not be available.\n", __func__); |
306 | ms->section_mem_map = 0; | 295 | ms->section_mem_map = 0; |
307 | return NULL; | 296 | return NULL; |
308 | } | 297 | } |
diff --git a/mm/swap_state.c b/mm/swap_state.c index 50757ee3f9f3..d8aadaf2a0ba 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c | |||
@@ -33,7 +33,7 @@ static const struct address_space_operations swap_aops = { | |||
33 | }; | 33 | }; |
34 | 34 | ||
35 | static struct backing_dev_info swap_backing_dev_info = { | 35 | static struct backing_dev_info swap_backing_dev_info = { |
36 | .capabilities = BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK, | 36 | .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK, |
37 | .unplug_io_fn = swap_unplug_io_fn, | 37 | .unplug_io_fn = swap_unplug_io_fn, |
38 | }; | 38 | }; |
39 | 39 | ||
diff --git a/mm/swapfile.c b/mm/swapfile.c index 67051be7083a..bd1bb5920306 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -1426,11 +1426,7 @@ static const struct file_operations proc_swaps_operations = { | |||
1426 | 1426 | ||
1427 | static int __init procswaps_init(void) | 1427 | static int __init procswaps_init(void) |
1428 | { | 1428 | { |
1429 | struct proc_dir_entry *entry; | 1429 | proc_create("swaps", 0, NULL, &proc_swaps_operations); |
1430 | |||
1431 | entry = create_proc_entry("swaps", 0, NULL); | ||
1432 | if (entry) | ||
1433 | entry->proc_fops = &proc_swaps_operations; | ||
1434 | return 0; | 1430 | return 0; |
1435 | } | 1431 | } |
1436 | __initcall(procswaps_init); | 1432 | __initcall(procswaps_init); |
diff --git a/mm/vmalloc.c b/mm/vmalloc.c index e33e0ae69ad1..2a39cf128aba 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/seq_file.h> | 17 | #include <linux/seq_file.h> |
18 | #include <linux/debugobjects.h> | ||
18 | #include <linux/vmalloc.h> | 19 | #include <linux/vmalloc.h> |
19 | #include <linux/kallsyms.h> | 20 | #include <linux/kallsyms.h> |
20 | 21 | ||
@@ -394,6 +395,7 @@ static void __vunmap(const void *addr, int deallocate_pages) | |||
394 | } | 395 | } |
395 | 396 | ||
396 | debug_check_no_locks_freed(addr, area->size); | 397 | debug_check_no_locks_freed(addr, area->size); |
398 | debug_check_no_obj_freed(addr, area->size); | ||
397 | 399 | ||
398 | if (deallocate_pages) { | 400 | if (deallocate_pages) { |
399 | int i; | 401 | int i; |
diff --git a/mm/vmscan.c b/mm/vmscan.c index eceac9f9032f..9a29901ad3b3 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -191,7 +191,7 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask, | |||
191 | shrinker->nr += delta; | 191 | shrinker->nr += delta; |
192 | if (shrinker->nr < 0) { | 192 | if (shrinker->nr < 0) { |
193 | printk(KERN_ERR "%s: nr=%ld\n", | 193 | printk(KERN_ERR "%s: nr=%ld\n", |
194 | __FUNCTION__, shrinker->nr); | 194 | __func__, shrinker->nr); |
195 | shrinker->nr = max_pass; | 195 | shrinker->nr = max_pass; |
196 | } | 196 | } |
197 | 197 | ||
@@ -339,7 +339,7 @@ static pageout_t pageout(struct page *page, struct address_space *mapping, | |||
339 | if (PagePrivate(page)) { | 339 | if (PagePrivate(page)) { |
340 | if (try_to_free_buffers(page)) { | 340 | if (try_to_free_buffers(page)) { |
341 | ClearPageDirty(page); | 341 | ClearPageDirty(page); |
342 | printk("%s: orphaned page\n", __FUNCTION__); | 342 | printk("%s: orphaned page\n", __func__); |
343 | return PAGE_CLEAN; | 343 | return PAGE_CLEAN; |
344 | } | 344 | } |
345 | } | 345 | } |
@@ -1299,6 +1299,9 @@ static unsigned long shrink_zones(int priority, struct zonelist *zonelist, | |||
1299 | * hope that some of these pages can be written. But if the allocating task | 1299 | * hope that some of these pages can be written. But if the allocating task |
1300 | * holds filesystem locks which prevent writeout this might not work, and the | 1300 | * holds filesystem locks which prevent writeout this might not work, and the |
1301 | * allocation attempt will fail. | 1301 | * allocation attempt will fail. |
1302 | * | ||
1303 | * returns: 0, if no pages reclaimed | ||
1304 | * else, the number of pages reclaimed | ||
1302 | */ | 1305 | */ |
1303 | static unsigned long do_try_to_free_pages(struct zonelist *zonelist, | 1306 | static unsigned long do_try_to_free_pages(struct zonelist *zonelist, |
1304 | struct scan_control *sc) | 1307 | struct scan_control *sc) |
@@ -1347,7 +1350,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, | |||
1347 | } | 1350 | } |
1348 | total_scanned += sc->nr_scanned; | 1351 | total_scanned += sc->nr_scanned; |
1349 | if (nr_reclaimed >= sc->swap_cluster_max) { | 1352 | if (nr_reclaimed >= sc->swap_cluster_max) { |
1350 | ret = 1; | 1353 | ret = nr_reclaimed; |
1351 | goto out; | 1354 | goto out; |
1352 | } | 1355 | } |
1353 | 1356 | ||
@@ -1370,7 +1373,7 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, | |||
1370 | } | 1373 | } |
1371 | /* top priority shrink_caches still had more to do? don't OOM, then */ | 1374 | /* top priority shrink_caches still had more to do? don't OOM, then */ |
1372 | if (!sc->all_unreclaimable && scan_global_lru(sc)) | 1375 | if (!sc->all_unreclaimable && scan_global_lru(sc)) |
1373 | ret = 1; | 1376 | ret = nr_reclaimed; |
1374 | out: | 1377 | out: |
1375 | /* | 1378 | /* |
1376 | * Now that we've scanned all the zones at this priority level, note | 1379 | * Now that we've scanned all the zones at this priority level, note |
diff --git a/mm/vmstat.c b/mm/vmstat.c index ec6035eda933..1a32130b958c 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
@@ -548,6 +548,10 @@ static int pagetypeinfo_show(struct seq_file *m, void *arg) | |||
548 | { | 548 | { |
549 | pg_data_t *pgdat = (pg_data_t *)arg; | 549 | pg_data_t *pgdat = (pg_data_t *)arg; |
550 | 550 | ||
551 | /* check memoryless node */ | ||
552 | if (!node_state(pgdat->node_id, N_HIGH_MEMORY)) | ||
553 | return 0; | ||
554 | |||
551 | seq_printf(m, "Page block order: %d\n", pageblock_order); | 555 | seq_printf(m, "Page block order: %d\n", pageblock_order); |
552 | seq_printf(m, "Pages per block: %lu\n", pageblock_nr_pages); | 556 | seq_printf(m, "Pages per block: %lu\n", pageblock_nr_pages); |
553 | seq_putc(m, '\n'); | 557 | seq_putc(m, '\n'); |
@@ -608,6 +612,7 @@ static const char * const vmstat_text[] = { | |||
608 | "nr_unstable", | 612 | "nr_unstable", |
609 | "nr_bounce", | 613 | "nr_bounce", |
610 | "nr_vmscan_write", | 614 | "nr_vmscan_write", |
615 | "nr_writeback_temp", | ||
611 | 616 | ||
612 | #ifdef CONFIG_NUMA | 617 | #ifdef CONFIG_NUMA |
613 | "numa_hit", | 618 | "numa_hit", |