public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Fix blktrace unaligned memory access
@ 2009-07-10  7:53 Jens Axboe
  2009-07-10  9:07 ` Li Zefan
  0 siblings, 1 reply; 6+ messages in thread
From: Jens Axboe @ 2009-07-10  7:53 UTC (permalink / raw)
  To: Linux Kernel; +Cc: lizf, Alan.Brunelle, Ingo Molnar

Hi,

It seems that relay_reserve() (or the ring_buffer_event_data(), that one
still needs some love) can return unaligned memory, there's no way
around that when you have pdu lengths that aren't a nice size. This can
cause unaligned access warnings on platforms that care about alignment.

This is an RFC, perhaps we can fix this in some other way. This one takes
the simple approach, use an on-stack copy and memcpy() that to the
destination.

diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
index 39af8af..9aba4ec 100644
--- a/kernel/trace/blktrace.c
+++ b/kernel/trace/blktrace.c
@@ -62,7 +62,7 @@ static void blk_unregister_tracepoints(void);
 static void trace_note(struct blk_trace *bt, pid_t pid, int action,
 		       const void *data, size_t len)
 {
-	struct blk_io_trace *t;
+	struct blk_io_trace *ptr, __t, *t = &__t;
 	struct ring_buffer_event *event = NULL;
 	int pc = 0;
 	int cpu = smp_processor_id();
@@ -75,15 +75,15 @@ static void trace_note(struct blk_trace *bt, pid_t pid, int action,
 						  0, pc);
 		if (!event)
 			return;
-		t = ring_buffer_event_data(event);
+		ptr = t = ring_buffer_event_data(event);
 		goto record_it;
 	}
 
 	if (!bt->rchan)
 		return;
 
-	t = relay_reserve(bt->rchan, sizeof(*t) + len);
-	if (t) {
+	ptr = relay_reserve(bt->rchan, sizeof(*t) + len);
+	if (ptr) {
 		t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION;
 		t->time = ktime_to_ns(ktime_get());
 record_it:
@@ -92,7 +92,9 @@ record_it:
 		t->pid = pid;
 		t->cpu = cpu;
 		t->pdu_len = len;
-		memcpy((void *) t + sizeof(*t), data, len);
+		if (t == &__t)
+			memcpy(ptr, t, sizeof(*t));
+		memcpy((void *) ptr + sizeof(*ptr), data, len);
 
 		if (blk_tracer)
 			trace_buffer_unlock_commit(blk_tr, event, 0, pc);
@@ -178,7 +180,7 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
 {
 	struct task_struct *tsk = current;
 	struct ring_buffer_event *event = NULL;
-	struct blk_io_trace *t;
+	struct blk_io_trace *ptr, __t, *t = &__t;
 	unsigned long flags = 0;
 	unsigned long *sequence;
 	pid_t pid;
@@ -209,7 +211,7 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
 						  0, pc);
 		if (!event)
 			return;
-		t = ring_buffer_event_data(event);
+		ptr = t = ring_buffer_event_data(event);
 		goto record_it;
 	}
 
@@ -223,8 +225,8 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
 	if (unlikely(tsk->btrace_seq != blktrace_seq))
 		trace_note_tsk(bt, tsk);
 
-	t = relay_reserve(bt->rchan, sizeof(*t) + pdu_len);
-	if (t) {
+	ptr = relay_reserve(bt->rchan, sizeof(*ptr) + pdu_len);
+	if (ptr) {
 		sequence = per_cpu_ptr(bt->sequence, cpu);
 
 		t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION;
@@ -247,8 +249,10 @@ record_it:
 		t->error = error;
 		t->pdu_len = pdu_len;
 
+		if (t == &__t)
+			memcpy(ptr, t, sizeof(*t));
 		if (pdu_len)
-			memcpy((void *) t + sizeof(*t), pdu_data, pdu_len);
+			memcpy((void *) ptr + sizeof(*ptr), pdu_data, pdu_len);
 
 		if (blk_tracer) {
 			trace_buffer_unlock_commit(blk_tr, event, 0, pc);

-- 
Jens Axboe


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] Fix blktrace unaligned memory access
  2009-07-10  7:53 [PATCH] Fix blktrace unaligned memory access Jens Axboe
@ 2009-07-10  9:07 ` Li Zefan
  2009-07-10  9:13   ` Jens Axboe
  0 siblings, 1 reply; 6+ messages in thread
From: Li Zefan @ 2009-07-10  9:07 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Linux Kernel, Alan.Brunelle, Ingo Molnar, Steven Rostedt,
	Frederic Weisbecker

Jens Axboe wrote:
> Hi,
> 
> It seems that relay_reserve() (or the ring_buffer_event_data(), that one
> still needs some love) can return unaligned memory, there's no way
> around that when you have pdu lengths that aren't a nice size. This can
> cause unaligned access warnings on platforms that care about alignment.
> 

Seems relay_reserve() does nothing for alignment..On the other hand,
ring_buffer_event_data() returns a ptr which is 32bit-aligned, but
this still means it can cause unaligned accesses on 64bits arch, while
I think it's fixable in ring buffer, it's certainly not an easy job.

> This is an RFC, perhaps we can fix this in some other way. This one takes
> the simple approach, use an on-stack copy and memcpy() that to the
> destination.
> 

or get_unaligned() ?

> diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c
> index 39af8af..9aba4ec 100644
> --- a/kernel/trace/blktrace.c
> +++ b/kernel/trace/blktrace.c
> @@ -62,7 +62,7 @@ static void blk_unregister_tracepoints(void);
>  static void trace_note(struct blk_trace *bt, pid_t pid, int action,
>  		       const void *data, size_t len)
>  {
> -	struct blk_io_trace *t;
> +	struct blk_io_trace *ptr, __t, *t = &__t;
>  	struct ring_buffer_event *event = NULL;
>  	int pc = 0;
>  	int cpu = smp_processor_id();
> @@ -75,15 +75,15 @@ static void trace_note(struct blk_trace *bt, pid_t pid, int action,
>  						  0, pc);
>  		if (!event)
>  			return;
> -		t = ring_buffer_event_data(event);
> +		ptr = t = ring_buffer_event_data(event);
>  		goto record_it;
>  	}
>  
>  	if (!bt->rchan)
>  		return;
>  
> -	t = relay_reserve(bt->rchan, sizeof(*t) + len);
> -	if (t) {
> +	ptr = relay_reserve(bt->rchan, sizeof(*t) + len);
> +	if (ptr) {
>  		t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION;
>  		t->time = ktime_to_ns(ktime_get());
>  record_it:
> @@ -92,7 +92,9 @@ record_it:
>  		t->pid = pid;
>  		t->cpu = cpu;
>  		t->pdu_len = len;
> -		memcpy((void *) t + sizeof(*t), data, len);
> +		if (t == &__t)
> +			memcpy(ptr, t, sizeof(*t));
> +		memcpy((void *) ptr + sizeof(*ptr), data, len);
>  
>  		if (blk_tracer)
>  			trace_buffer_unlock_commit(blk_tr, event, 0, pc);
> @@ -178,7 +180,7 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
>  {
>  	struct task_struct *tsk = current;
>  	struct ring_buffer_event *event = NULL;
> -	struct blk_io_trace *t;
> +	struct blk_io_trace *ptr, __t, *t = &__t;
>  	unsigned long flags = 0;
>  	unsigned long *sequence;
>  	pid_t pid;
> @@ -209,7 +211,7 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
>  						  0, pc);
>  		if (!event)
>  			return;
> -		t = ring_buffer_event_data(event);
> +		ptr = t = ring_buffer_event_data(event);
>  		goto record_it;
>  	}
>  
> @@ -223,8 +225,8 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
>  	if (unlikely(tsk->btrace_seq != blktrace_seq))
>  		trace_note_tsk(bt, tsk);
>  
> -	t = relay_reserve(bt->rchan, sizeof(*t) + pdu_len);
> -	if (t) {
> +	ptr = relay_reserve(bt->rchan, sizeof(*ptr) + pdu_len);
> +	if (ptr) {
>  		sequence = per_cpu_ptr(bt->sequence, cpu);
>  
>  		t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION;
> @@ -247,8 +249,10 @@ record_it:
>  		t->error = error;
>  		t->pdu_len = pdu_len;
>  
> +		if (t == &__t)
> +			memcpy(ptr, t, sizeof(*t));
>  		if (pdu_len)
> -			memcpy((void *) t + sizeof(*t), pdu_data, pdu_len);
> +			memcpy((void *) ptr + sizeof(*ptr), pdu_data, pdu_len);
>  
>  		if (blk_tracer) {
>  			trace_buffer_unlock_commit(blk_tr, event, 0, pc);
> 


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Fix blktrace unaligned memory access
  2009-07-10  9:07 ` Li Zefan
@ 2009-07-10  9:13   ` Jens Axboe
  2009-07-10  9:30     ` Li Zefan
  0 siblings, 1 reply; 6+ messages in thread
From: Jens Axboe @ 2009-07-10  9:13 UTC (permalink / raw)
  To: Li Zefan
  Cc: Linux Kernel, Alan.Brunelle, Ingo Molnar, Steven Rostedt,
	Frederic Weisbecker

On Fri, Jul 10 2009, Li Zefan wrote:
> Jens Axboe wrote:
> > Hi,
> > 
> > It seems that relay_reserve() (or the ring_buffer_event_data(), that one
> > still needs some love) can return unaligned memory, there's no way
> > around that when you have pdu lengths that aren't a nice size. This can
> > cause unaligned access warnings on platforms that care about alignment.
> > 
> 
> Seems relay_reserve() does nothing for alignment..On the other hand,
> ring_buffer_event_data() returns a ptr which is 32bit-aligned, but
> this still means it can cause unaligned accesses on 64bits arch, while
> I think it's fixable in ring buffer, it's certainly not an easy job.

Right, it's a bit nasty...

> > This is an RFC, perhaps we can fix this in some other way. This one takes
> > the simple approach, use an on-stack copy and memcpy() that to the
> > destination.
> > 
> 
> or get_unaligned() ?

put_unaligned(), you mean? The big question is then which is faster, using
put_unaligned() or doing the memcpy() of the structure...

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Fix blktrace unaligned memory access
  2009-07-10  9:13   ` Jens Axboe
@ 2009-07-10  9:30     ` Li Zefan
  2009-07-10  9:36       ` Jens Axboe
  0 siblings, 1 reply; 6+ messages in thread
From: Li Zefan @ 2009-07-10  9:30 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Linux Kernel, Alan.Brunelle, Ingo Molnar, Steven Rostedt,
	Frederic Weisbecker

Jens Axboe wrote:
> On Fri, Jul 10 2009, Li Zefan wrote:
>> Jens Axboe wrote:
>>> Hi,
>>>
>>> It seems that relay_reserve() (or the ring_buffer_event_data(), that one
>>> still needs some love) can return unaligned memory, there's no way
>>> around that when you have pdu lengths that aren't a nice size. This can
>>> cause unaligned access warnings on platforms that care about alignment.
>>>
>> Seems relay_reserve() does nothing for alignment..On the other hand,
>> ring_buffer_event_data() returns a ptr which is 32bit-aligned, but
>> this still means it can cause unaligned accesses on 64bits arch, while
>> I think it's fixable in ring buffer, it's certainly not an easy job.
> 
> Right, it's a bit nasty...
> 

Lai Jiangshan noticed this issue long ago and had some ideas in mind
how to fix ring buffer, but never try it out for it will probably be
frustrating..

>>> This is an RFC, perhaps we can fix this in some other way. This one takes
>>> the simple approach, use an on-stack copy and memcpy() that to the
>>> destination.
>>>
>> or get_unaligned() ?
> 
> put_unaligned(), you mean? The big question is then which is faster, using
> put_unaligned() or doing the memcpy() of the structure...
> 

Ah, I meant put_unaligned().

I think the patch you posted can be a workaround at least for now, and
can be improved by detecting HAVE_EFFICIENT_UNALIGNED_ACCESS


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Fix blktrace unaligned memory access
  2009-07-10  9:30     ` Li Zefan
@ 2009-07-10  9:36       ` Jens Axboe
  2009-07-14 17:35         ` Steven Rostedt
  0 siblings, 1 reply; 6+ messages in thread
From: Jens Axboe @ 2009-07-10  9:36 UTC (permalink / raw)
  To: Li Zefan
  Cc: Linux Kernel, Alan.Brunelle, Ingo Molnar, Steven Rostedt,
	Frederic Weisbecker

On Fri, Jul 10 2009, Li Zefan wrote:
> Jens Axboe wrote:
> > On Fri, Jul 10 2009, Li Zefan wrote:
> >> Jens Axboe wrote:
> >>> Hi,
> >>>
> >>> It seems that relay_reserve() (or the ring_buffer_event_data(), that one
> >>> still needs some love) can return unaligned memory, there's no way
> >>> around that when you have pdu lengths that aren't a nice size. This can
> >>> cause unaligned access warnings on platforms that care about alignment.
> >>>
> >> Seems relay_reserve() does nothing for alignment..On the other hand,
> >> ring_buffer_event_data() returns a ptr which is 32bit-aligned, but
> >> this still means it can cause unaligned accesses on 64bits arch, while
> >> I think it's fixable in ring buffer, it's certainly not an easy job.
> > 
> > Right, it's a bit nasty...
> > 
> 
> Lai Jiangshan noticed this issue long ago and had some ideas in mind
> how to fix ring buffer, but never try it out for it will probably be
> frustrating..
> 
> >>> This is an RFC, perhaps we can fix this in some other way. This one takes
> >>> the simple approach, use an on-stack copy and memcpy() that to the
> >>> destination.
> >>>
> >> or get_unaligned() ?
> > 
> > put_unaligned(), you mean? The big question is then which is faster, using
> > put_unaligned() or doing the memcpy() of the structure...
> > 
> 
> Ah, I meant put_unaligned().
> 
> I think the patch you posted can be a workaround at least for now, and
> can be improved by detecting HAVE_EFFICIENT_UNALIGNED_ACCESS

We either do one or the other, I don't want to clutter the code with
both methods implemented and some ifdef checking and deciding. I'll
check the unaligned put here on x86/ppc/sparc and then decide which one
is faster.

-- 
Jens Axboe


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Fix blktrace unaligned memory access
  2009-07-10  9:36       ` Jens Axboe
@ 2009-07-14 17:35         ` Steven Rostedt
  0 siblings, 0 replies; 6+ messages in thread
From: Steven Rostedt @ 2009-07-14 17:35 UTC (permalink / raw)
  To: Jens Axboe
  Cc: Li Zefan, Linux Kernel, Alan.Brunelle, Ingo Molnar,
	Frederic Weisbecker



On Fri, 10 Jul 2009, Jens Axboe wrote:

> On Fri, Jul 10 2009, Li Zefan wrote:
> > Jens Axboe wrote:
> > > On Fri, Jul 10 2009, Li Zefan wrote:
> > >> Jens Axboe wrote:
> > >>> Hi,
> > >>>
> > >>> It seems that relay_reserve() (or the ring_buffer_event_data(), that one
> > >>> still needs some love) can return unaligned memory, there's no way
> > >>> around that when you have pdu lengths that aren't a nice size. This can
> > >>> cause unaligned access warnings on platforms that care about alignment.
> > >>>
> > >> Seems relay_reserve() does nothing for alignment..On the other hand,
> > >> ring_buffer_event_data() returns a ptr which is 32bit-aligned, but
> > >> this still means it can cause unaligned accesses on 64bits arch, while
> > >> I think it's fixable in ring buffer, it's certainly not an easy job.

Correct, this is only needed if the data is bigger than 32 bits.


> > > 
> > > Right, it's a bit nasty...
> > > 
> > 
> > Lai Jiangshan noticed this issue long ago and had some ideas in mind
> > how to fix ring buffer, but never try it out for it will probably be
> > frustrating..

Perhaps we can make an attribute for the ring buffer itself that would 
allow the user to give an alignment. Would anything ever need a bigger 
than 64bit (8 byte) alignment? We can set a flag that says, make all 
entries 8 bytes aligned.

-- Steve


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2009-07-14 17:35 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-07-10  7:53 [PATCH] Fix blktrace unaligned memory access Jens Axboe
2009-07-10  9:07 ` Li Zefan
2009-07-10  9:13   ` Jens Axboe
2009-07-10  9:30     ` Li Zefan
2009-07-10  9:36       ` Jens Axboe
2009-07-14 17:35         ` Steven Rostedt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox