cpumask: use percpu allocations instead of arrays in kernel/trace/ring_buffer.c

Instead of allocating an nr_cpu_ids array, most places should be using
percpu_alloc().  This doesn't waste space if cpu numbers aren't
contiguous.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
 kernel/trace/ring_buffer.c |   68 +++++++++++++++++++++------------------------
 1 file changed, 33 insertions(+), 35 deletions(-)

diff -r 1aa3a65f9ac6 kernel/trace/ring_buffer.c
--- a/kernel/trace/ring_buffer.c	Fri Nov 07 23:07:03 2008 +1100
+++ b/kernel/trace/ring_buffer.c	Fri Nov 07 23:08:27 2008 +1100
@@ -170,13 +170,12 @@ struct ring_buffer {
 	unsigned long			size;
 	unsigned			pages;
 	unsigned			flags;
-	int				cpus;
 	cpumask_t			cpumask;
 	atomic_t			record_disabled;
 
 	struct mutex			mutex;
 
-	struct ring_buffer_per_cpu	**buffers;
+	struct ring_buffer_per_cpu	**buffers_pcpu;
 };
 
 struct ring_buffer_iter {
@@ -357,7 +356,6 @@ struct ring_buffer *ring_buffer_alloc(un
 struct ring_buffer *ring_buffer_alloc(unsigned long size, unsigned flags)
 {
 	struct ring_buffer *buffer;
-	int bsize;
 	int cpu;
 
 	/* Paranoid! Optimizes out when all is well */
@@ -379,18 +377,15 @@ struct ring_buffer *ring_buffer_alloc(un
 		buffer->pages++;
 
 	buffer->cpumask = cpu_possible_map;
-	buffer->cpus = nr_cpu_ids;
 
-	bsize = sizeof(void *) * nr_cpu_ids;
-	buffer->buffers = kzalloc(ALIGN(bsize, cache_line_size()),
-				  GFP_KERNEL);
-	if (!buffer->buffers)
+	buffer->buffers_pcpu = alloc_percpu(struct ring_buffer_per_cpu);
+	if (!buffer->buffers_pcpu)
 		goto fail_free_buffer;
 
 	for_each_buffer_cpu(buffer, cpu) {
-		buffer->buffers[cpu] =
+		*per_cpu_ptr(buffer->buffers_pcpu, cpu) =
 			rb_allocate_cpu_buffer(buffer, cpu);
-		if (!buffer->buffers[cpu])
+		if (!*per_cpu_ptr(buffer->buffers_pcpu, cpu))
 			goto fail_free_buffers;
 	}
 
@@ -400,10 +395,11 @@ struct ring_buffer *ring_buffer_alloc(un
 
  fail_free_buffers:
 	for_each_buffer_cpu(buffer, cpu) {
-		if (buffer->buffers[cpu])
-			rb_free_cpu_buffer(buffer->buffers[cpu]);
+		if (*per_cpu_ptr(buffer->buffers_pcpu, cpu))
+			rb_free_cpu_buffer(*per_cpu_ptr(buffer->buffers_pcpu,
+						        cpu));
 	}
-	kfree(buffer->buffers);
+	free_percpu(buffer->buffers_pcpu);
 
  fail_free_buffer:
 	kfree(buffer);
@@ -420,7 +416,7 @@ ring_buffer_free(struct ring_buffer *buf
 	int cpu;
 
 	for_each_buffer_cpu(buffer, cpu)
-		rb_free_cpu_buffer(buffer->buffers[cpu]);
+		rb_free_cpu_buffer(*per_cpu_ptr(buffer->buffers_pcpu, cpu));
 
 	kfree(buffer);
 }
@@ -526,7 +522,7 @@ int ring_buffer_resize(struct ring_buffe
 		rm_pages = buffer->pages - nr_pages;
 
 		for_each_buffer_cpu(buffer, cpu) {
-			cpu_buffer = buffer->buffers[cpu];
+			cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 			rb_remove_pages(cpu_buffer, rm_pages);
 		}
 		goto out;
@@ -559,7 +555,7 @@ int ring_buffer_resize(struct ring_buffe
 	}
 
 	for_each_buffer_cpu(buffer, cpu) {
-		cpu_buffer = buffer->buffers[cpu];
+		cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 		rb_insert_pages(cpu_buffer, &pages, new_pages);
 	}
 
@@ -1145,7 +1141,7 @@ ring_buffer_lock_reserve(struct ring_buf
 	if (!cpu_isset(cpu, buffer->cpumask))
 		goto out;
 
-	cpu_buffer = buffer->buffers[cpu];
+	cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 
 	if (atomic_read(&cpu_buffer->record_disabled))
 		goto out;
@@ -1207,7 +1203,7 @@ int ring_buffer_unlock_commit(struct rin
 	struct ring_buffer_per_cpu *cpu_buffer;
 	int cpu = raw_smp_processor_id();
 
-	cpu_buffer = buffer->buffers[cpu];
+	cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 
 	rb_commit(cpu_buffer, event);
 
@@ -1260,7 +1256,7 @@ int ring_buffer_write(struct ring_buffer
 	if (!cpu_isset(cpu, buffer->cpumask))
 		goto out;
 
-	cpu_buffer = buffer->buffers[cpu];
+	cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 
 	if (atomic_read(&cpu_buffer->record_disabled))
 		goto out;
@@ -1342,7 +1338,7 @@ void ring_buffer_record_disable_cpu(stru
 	if (!cpu_isset(cpu, buffer->cpumask))
 		return;
 
-	cpu_buffer = buffer->buffers[cpu];
+	cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 	atomic_inc(&cpu_buffer->record_disabled);
 }
 
@@ -1361,7 +1357,7 @@ void ring_buffer_record_enable_cpu(struc
 	if (!cpu_isset(cpu, buffer->cpumask))
 		return;
 
-	cpu_buffer = buffer->buffers[cpu];
+	cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 	atomic_dec(&cpu_buffer->record_disabled);
 }
 
@@ -1377,7 +1373,7 @@ unsigned long ring_buffer_entries_cpu(st
 	if (!cpu_isset(cpu, buffer->cpumask))
 		return 0;
 
-	cpu_buffer = buffer->buffers[cpu];
+	cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 	return cpu_buffer->entries;
 }
 
@@ -1393,7 +1389,7 @@ unsigned long ring_buffer_overrun_cpu(st
 	if (!cpu_isset(cpu, buffer->cpumask))
 		return 0;
 
-	cpu_buffer = buffer->buffers[cpu];
+	cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 	return cpu_buffer->overrun;
 }
 
@@ -1412,7 +1408,7 @@ unsigned long ring_buffer_entries(struct
 
 	/* if you care about this being correct, lock the buffer */
 	for_each_buffer_cpu(buffer, cpu) {
-		cpu_buffer = buffer->buffers[cpu];
+		cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 		entries += cpu_buffer->entries;
 	}
 
@@ -1434,7 +1430,7 @@ unsigned long ring_buffer_overruns(struc
 
 	/* if you care about this being correct, lock the buffer */
 	for_each_buffer_cpu(buffer, cpu) {
-		cpu_buffer = buffer->buffers[cpu];
+		cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 		overruns += cpu_buffer->overrun;
 	}
 
@@ -1698,7 +1694,7 @@ ring_buffer_peek(struct ring_buffer *buf
 	if (!cpu_isset(cpu, buffer->cpumask))
 		return NULL;
 
-	cpu_buffer = buffer->buffers[cpu];
+	cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 
  again:
 	/*
@@ -1841,7 +1837,7 @@ ring_buffer_consume(struct ring_buffer *
 	if (!event)
 		return NULL;
 
-	cpu_buffer = buffer->buffers[cpu];
+	cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 	rb_advance_reader(cpu_buffer);
 
 	return event;
@@ -1873,7 +1869,7 @@ ring_buffer_read_start(struct ring_buffe
 	if (!iter)
 		return NULL;
 
-	cpu_buffer = buffer->buffers[cpu];
+	cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 
 	iter->cpu_buffer = cpu_buffer;
 
@@ -1962,11 +1958,13 @@ rb_reset_cpu(struct ring_buffer_per_cpu 
  */
 void ring_buffer_reset_cpu(struct ring_buffer *buffer, int cpu)
 {
-	struct ring_buffer_per_cpu *cpu_buffer = buffer->buffers[cpu];
+	struct ring_buffer_per_cpu *cpu_buffer;
 	unsigned long flags;
 
 	if (!cpu_isset(cpu, buffer->cpumask))
 		return;
+
+	cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 
 	spin_lock_irqsave(&cpu_buffer->lock, flags);
 
@@ -1998,7 +1996,7 @@ int ring_buffer_empty(struct ring_buffer
 
 	/* yes this is racy, but if you don't like the race, lock the buffer */
 	for_each_buffer_cpu(buffer, cpu) {
-		cpu_buffer = buffer->buffers[cpu];
+		cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 		if (!rb_per_cpu_empty(cpu_buffer))
 			return 0;
 	}
@@ -2017,7 +2015,7 @@ int ring_buffer_empty_cpu(struct ring_bu
 	if (!cpu_isset(cpu, buffer->cpumask))
 		return 1;
 
-	cpu_buffer = buffer->buffers[cpu];
+	cpu_buffer = *per_cpu_ptr(buffer->buffers_pcpu, cpu);
 	return rb_per_cpu_empty(cpu_buffer);
 }
 
@@ -2046,8 +2044,8 @@ int ring_buffer_swap_cpu(struct ring_buf
 	    buffer_a->pages != buffer_b->pages)
 		return -EINVAL;
 
-	cpu_buffer_a = buffer_a->buffers[cpu];
-	cpu_buffer_b = buffer_b->buffers[cpu];
+	cpu_buffer_a = *per_cpu_ptr(buffer_a->buffers_pcpu, cpu);
+	cpu_buffer_b = *per_cpu_ptr(buffer_b->buffers_pcpu, cpu);
 
 	/*
 	 * We can't do a synchronize_sched here because this
@@ -2058,8 +2056,8 @@ int ring_buffer_swap_cpu(struct ring_buf
 	atomic_inc(&cpu_buffer_a->record_disabled);
 	atomic_inc(&cpu_buffer_b->record_disabled);
 
-	buffer_a->buffers[cpu] = cpu_buffer_b;
-	buffer_b->buffers[cpu] = cpu_buffer_a;
+	*per_cpu_ptr(buffer_a->buffers_pcpu, cpu) = cpu_buffer_b;
+	*per_cpu_ptr(buffer_b->buffers_pcpu, cpu) = cpu_buffer_a;
 
 	cpu_buffer_b->buffer = buffer_a;
 	cpu_buffer_a->buffer = buffer_b;
