* [ZVC 1/4] Fix potential use of out of range page in kmem_getpages.
@ 2006-06-27 17:45 Christoph Lameter
2006-06-27 17:45 ` [ZVC 2/4] highmem.c: Use page after it may have been freed Christoph Lameter
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Christoph Lameter @ 2006-06-27 17:45 UTC (permalink / raw)
To: akpm; +Cc: Nick Piggin, Pekka Enberg, Christoph Lameter, linux-kernel
ZVC: Fix potential use of out of range page in kmem_getpages.
We use page_zone(page) following several page increments in kmem_getpages().
Which page in a zone we use really does not matter. However, we may reach an
invalid page and then oops.
So move the counter decrement before we increment page.
Signed-off-by: Christoph Lameter <clameter@sgi.com>
Index: linux-2.6.17-mm3/mm/slab.c
===================================================================
--- linux-2.6.17-mm3.orig/mm/slab.c 2006-06-27 09:40:25.620599382 -0700
+++ linux-2.6.17-mm3/mm/slab.c 2006-06-27 09:40:32.330144958 -0700
@@ -1539,12 +1539,12 @@ static void kmem_freepages(struct kmem_c
struct page *page = virt_to_page(addr);
const unsigned long nr_freed = i;
+ sub_zone_page_state(page_zone(page), NR_SLAB, nr_freed);
while (i--) {
BUG_ON(!PageSlab(page));
__ClearPageSlab(page);
page++;
}
- sub_zone_page_state(page_zone(page), NR_SLAB, nr_freed);
if (current->reclaim_state)
current->reclaim_state->reclaimed_slab += nr_freed;
free_pages((unsigned long)addr, cachep->gfporder);
^ permalink raw reply [flat|nested] 5+ messages in thread
* [ZVC 2/4] highmem.c: Use page after it may have been freed
2006-06-27 17:45 [ZVC 1/4] Fix potential use of out of range page in kmem_getpages Christoph Lameter
@ 2006-06-27 17:45 ` Christoph Lameter
2006-06-27 17:46 ` [ZVC 3/4] Include vmstat.h in mm.h and not in page-flags.h Christoph Lameter
2006-06-27 17:46 ` [ZVC 4/4] Inline counters for single processor configurations Christoph Lameter
2 siblings, 0 replies; 5+ messages in thread
From: Christoph Lameter @ 2006-06-27 17:45 UTC (permalink / raw)
To: akpm; +Cc: Nick Piggin, Pekka Enberg, Christoph Lameter, linux-kernel
ZVC: highmem.c: Use page after it may have been freed
This is not really a problem since the zone of a page does not
change after it has been freed but its cleaner to use the
page as a reference before it has been freed.
Move the dec_zone_page_state before the free.
Signed-off-by: Christoph Lameter <clameter@sgi.com>
Index: linux-2.6.17-mm3/mm/highmem.c
===================================================================
--- linux-2.6.17-mm3.orig/mm/highmem.c 2006-06-27 09:40:25.586421810 -0700
+++ linux-2.6.17-mm3/mm/highmem.c 2006-06-27 09:42:19.342074956 -0700
@@ -315,8 +315,8 @@ static void bounce_end_io(struct bio *bi
if (bvec->bv_page == org_vec->bv_page)
continue;
- mempool_free(bvec->bv_page, pool);
dec_zone_page_state(bvec->bv_page, NR_BOUNCE);
+ mempool_free(bvec->bv_page, pool);
}
bio_endio(bio_orig, bio_orig->bi_size, err);
^ permalink raw reply [flat|nested] 5+ messages in thread
* [ZVC 3/4] Include vmstat.h in mm.h and not in page-flags.h
2006-06-27 17:45 [ZVC 1/4] Fix potential use of out of range page in kmem_getpages Christoph Lameter
2006-06-27 17:45 ` [ZVC 2/4] highmem.c: Use page after it may have been freed Christoph Lameter
@ 2006-06-27 17:46 ` Christoph Lameter
2006-06-27 17:46 ` [ZVC 4/4] Inline counters for single processor configurations Christoph Lameter
2 siblings, 0 replies; 5+ messages in thread
From: Christoph Lameter @ 2006-06-27 17:46 UTC (permalink / raw)
To: akpm; +Cc: Nick Piggin, Pekka Enberg, Christoph Lameter, linux-kernel
Move include of vmstat.h into mm.h
Some inline functions in vmstat.h need inline definitions from mm.h
So do the same as we already to for page-flags: Include vmstat.h in
mm.h where it fits in.
Signed-off-by: Christoph Lameter <clameter@sgi.com>
Index: linux-2.6.17-mm3/include/linux/mm.h
===================================================================
--- linux-2.6.17-mm3.orig/include/linux/mm.h 2006-06-27 09:40:23.405892736 -0700
+++ linux-2.6.17-mm3/include/linux/mm.h 2006-06-27 10:29:56.424844789 -0700
@@ -4,7 +4,6 @@
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/capability.h>
-#include <linux/vmstat.h>
#ifdef __KERNEL__
@@ -524,6 +523,11 @@ static inline void set_page_links(struct
set_page_section(page, pfn_to_section_nr(pfn));
}
+/*
+ * Some inline functions in vmstat.h depend on page_zone()
+ */
+#include <linux/vmstat.h>
+
#ifndef CONFIG_DISCONTIGMEM
/* The array of struct pages - for discontigmem use pgdat->lmem_map */
extern struct page *mem_map;
Index: linux-2.6.17-mm3/include/linux/page-flags.h
===================================================================
--- linux-2.6.17-mm3.orig/include/linux/page-flags.h 2006-06-27 09:40:23.561156562 -0700
+++ linux-2.6.17-mm3/include/linux/page-flags.h 2006-06-27 10:27:36.956934646 -0700
@@ -6,7 +6,6 @@
#define PAGE_FLAGS_H
#include <linux/types.h>
-#include <linux/vmstat.h>
/*
* Various page->flags bits:
^ permalink raw reply [flat|nested] 5+ messages in thread
* [ZVC 4/4] Inline counters for single processor configurations
2006-06-27 17:45 [ZVC 1/4] Fix potential use of out of range page in kmem_getpages Christoph Lameter
2006-06-27 17:45 ` [ZVC 2/4] highmem.c: Use page after it may have been freed Christoph Lameter
2006-06-27 17:46 ` [ZVC 3/4] Include vmstat.h in mm.h and not in page-flags.h Christoph Lameter
@ 2006-06-27 17:46 ` Christoph Lameter
2006-06-27 18:05 ` Christoph Lameter
2 siblings, 1 reply; 5+ messages in thread
From: Christoph Lameter @ 2006-06-27 17:46 UTC (permalink / raw)
To: akpm; +Cc: Nick Piggin, Pekka Enberg, Christoph Lameter, linux-kernel
ZVC: inline counters handling on single processor systems.
Since we always use atomic operations to update counters on single
processor systems we do no need to distinguish between the case
when we have disabled interrupts or when we did not.
Each update is then only two atomic adds. Code size shrinks if we
switch to inlining instead of providing explicit functions in vmstat.c.
Inline ZVC counters:
-rw-r--r-- 1 root root 1865626 Jun 27 03:06 vmlinuz-2.6.17-mm3
Function calls:
-rw-r--r-- 1 root root 1865792 Jun 27 03:21 /boot/vmlinuz-2.6.17-mm3
Move zone_page_state() and single processor functions from vmstat.c
into vmstat.h. Remove all interrupt disable/enable for single processor.
Signed-off-by: Christoph Lameter <clameter@sgi.com>
Index: linux-2.6.17-mm3/include/linux/vmstat.h
===================================================================
--- linux-2.6.17-mm3.orig/include/linux/vmstat.h 2006-06-27 09:40:24.327710670 -0700
+++ linux-2.6.17-mm3/include/linux/vmstat.h 2006-06-27 10:36:46.363304430 -0700
@@ -84,6 +84,13 @@ extern void vm_events_fold_cpu(int cpu);
*/
extern atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
+static inline void zone_page_state_add(long x, struct zone *zone,
+ enum zone_stat_item item)
+{
+ atomic_long_add(x, &zone->vm_stat[item]);
+ atomic_long_add(x, &vm_stat[item]);
+}
+
static inline unsigned long global_page_state(enum zone_stat_item item)
{
long x = atomic_long_read(&vm_stat[item]);
@@ -138,19 +145,11 @@ extern void zone_statistics(struct zonel
#endif /* CONFIG_NUMA */
-void __mod_zone_page_state(struct zone *, enum zone_stat_item item, int);
-void __inc_zone_page_state(struct page *, enum zone_stat_item);
-void __dec_zone_page_state(struct page *, enum zone_stat_item);
-
#define __add_zone_page_state(__z, __i, __d) \
__mod_zone_page_state(__z, __i, __d)
#define __sub_zone_page_state(__z, __i, __d) \
__mod_zone_page_state(__z, __i,-(__d))
-void mod_zone_page_state(struct zone *, enum zone_stat_item, int);
-void inc_zone_page_state(struct page *, enum zone_stat_item);
-void dec_zone_page_state(struct page *, enum zone_stat_item);
-
#define add_zone_page_state(__z, __i, __d) mod_zone_page_state(__z, __i, __d)
#define sub_zone_page_state(__z, __i, __d) mod_zone_page_state(__z, __i, -(__d))
@@ -159,12 +158,50 @@ static inline void zap_zone_vm_stats(str
memset(zone->vm_stat, 0, sizeof(zone->vm_stat));
}
+#ifdef CONFIG_SMP
+void __mod_zone_page_state(struct zone *, enum zone_stat_item item, int);
+void __inc_zone_page_state(struct page *, enum zone_stat_item);
+void __dec_zone_page_state(struct page *, enum zone_stat_item);
+
+void mod_zone_page_state(struct zone *, enum zone_stat_item, int);
+void inc_zone_page_state(struct page *, enum zone_stat_item);
+void dec_zone_page_state(struct page *, enum zone_stat_item);
+
extern void inc_zone_state(struct zone *, enum zone_stat_item);
-#ifdef CONFIG_SMP
void refresh_cpu_vm_stats(int);
void refresh_vm_stats(void);
-#else
+
+#else /* CONFIG_SMP */
+
+/*
+ * We do not maintain differentials in a single processor configuration.
+ * The functions directly modify the zone and global counters.
+ */
+static inline void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
+ int delta)
+{
+ zone_page_state_add(delta, zone, item);
+}
+
+static inline void __inc_zone_page_state(struct page *page, enum zone_stat_item item)
+{
+ zone_page_state_add(1, page_zone(page), item);
+}
+
+static inline void __dec_zone_page_state(struct page *page, enum zone_stat_item item)
+{
+ zone_page_state_add(-1, page_zone(page), item);
+}
+
+/*
+ * We only use atomic operations to update counters. So there is no need to
+ * disable interrupts.
+ */
+#define inc_zone_page_state __inc_zone_page_state
+#define dec_zone_page_state __dec_zone_page_state
+#define mod_zone_page_state __mod_zone_page_state
+
static inline void refresh_cpu_vm_stats(int cpu) { }
static inline void refresh_vm_stats(void) { }
#endif
Index: linux-2.6.17-mm3/mm/vmstat.c
===================================================================
--- linux-2.6.17-mm3.orig/mm/vmstat.c 2006-06-27 09:40:25.632317407 -0700
+++ linux-2.6.17-mm3/mm/vmstat.c 2006-06-27 10:36:46.364280932 -0700
@@ -110,13 +110,6 @@ void vm_events_fold_cpu(int cpu)
*/
atomic_long_t vm_stat[NR_VM_ZONE_STAT_ITEMS];
-static inline void zone_page_state_add(long x, struct zone *zone,
- enum zone_stat_item item)
-{
- atomic_long_add(x, &zone->vm_stat[item]);
- atomic_long_add(x, &vm_stat[item]);
-}
-
#ifdef CONFIG_SMP
#define STAT_THRESHOLD 32
@@ -303,62 +296,6 @@ void refresh_vm_stats(void)
}
EXPORT_SYMBOL(refresh_vm_stats);
-#else /* CONFIG_SMP */
-
-/*
- * We do not maintain differentials in a single processor configuration.
- * The functions directly modify the zone and global counters.
- */
-
-void __mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
- int delta)
-{
- zone_page_state_add(delta, zone, item);
-}
-EXPORT_SYMBOL(__mod_zone_page_state);
-
-void mod_zone_page_state(struct zone *zone, enum zone_stat_item item,
- int delta)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- zone_page_state_add(delta, zone, item);
- local_irq_restore(flags);
-}
-EXPORT_SYMBOL(mod_zone_page_state);
-
-void __inc_zone_page_state(struct page *page, enum zone_stat_item item)
-{
- zone_page_state_add(1, page_zone(page), item);
-}
-EXPORT_SYMBOL(__inc_zone_page_state);
-
-void __dec_zone_page_state(struct page *page, enum zone_stat_item item)
-{
- zone_page_state_add(-1, page_zone(page), item);
-}
-EXPORT_SYMBOL(__dec_zone_page_state);
-
-void inc_zone_page_state(struct page *page, enum zone_stat_item item)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- zone_page_state_add(1, page_zone(page), item);
- local_irq_restore(flags);
-}
-EXPORT_SYMBOL(inc_zone_page_state);
-
-void dec_zone_page_state(struct page *page, enum zone_stat_item item)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- zone_page_state_add( -1, page_zone(page), item);
- local_irq_restore(flags);
-}
-EXPORT_SYMBOL(dec_zone_page_state);
#endif
#ifdef CONFIG_NUMA
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [ZVC 4/4] Inline counters for single processor configurations
2006-06-27 17:46 ` [ZVC 4/4] Inline counters for single processor configurations Christoph Lameter
@ 2006-06-27 18:05 ` Christoph Lameter
0 siblings, 0 replies; 5+ messages in thread
From: Christoph Lameter @ 2006-06-27 18:05 UTC (permalink / raw)
To: akpm; +Cc: Nick Piggin, Pekka Enberg, linux-kernel
Hmmm.. i386/x86_64 do not convert the adds to incs like ia64. Therefore
one can decrease memory usage even further by using atomic_inc/dec
explicitly.
Index: linux-2.6.17-mm3/include/linux/vmstat.h
===================================================================
--- linux-2.6.17-mm3.orig/include/linux/vmstat.h 2006-06-27 03:53:05.000000000 -0700
+++ linux-2.6.17-mm3/include/linux/vmstat.h 2006-06-27 03:54:16.000000000 -0700
@@ -186,12 +186,14 @@
static inline void __inc_zone_page_state(struct page *page, enum zone_stat_item item)
{
- zone_page_state_add(1, page_zone(page), item);
+ atomic_long_inc(&page_zone(page)->vm_stat[item]);
+ atomic_long_inc(&vm_stat[item]);
}
static inline void __dec_zone_page_state(struct page *page, enum zone_stat_item item)
{
- zone_page_state_add(-1, page_zone(page), item);
+ atomic_long_dec(&page_zone(page)->vm_stat[item]);
+ atomic_long_dec(&vm_stat[item]);
}
/*
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2006-06-27 18:05 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-06-27 17:45 [ZVC 1/4] Fix potential use of out of range page in kmem_getpages Christoph Lameter
2006-06-27 17:45 ` [ZVC 2/4] highmem.c: Use page after it may have been freed Christoph Lameter
2006-06-27 17:46 ` [ZVC 3/4] Include vmstat.h in mm.h and not in page-flags.h Christoph Lameter
2006-06-27 17:46 ` [ZVC 4/4] Inline counters for single processor configurations Christoph Lameter
2006-06-27 18:05 ` Christoph Lameter
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®