All of lore.kernel.org
 help / color / mirror / Atom feed
From: Robert Richter <robert.richter@amd.com>
To: Will Deacon <will.deacon@arm.com>
Cc: Matt Fleming <matt@console-pimps.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	Paul Mundt <lethal@linux-sh.org>,
	Russell King <linux@arm.linux.org.uk>,
	"linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>,
	"linux-sh@vger.kernel.org" <linux-sh@vger.kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@elte.hu>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Arnaldo Carvalho de Melo <acme@redhat.com>,
	"linux-arch@vger.kernel.org" <linux-arch@vger.kernel.org>
Subject: Re: [PATCH 1/4] oprofile: Handle initialisation failure more gracefully
Date: Fri, 27 Aug 2010 18:38:39 +0200	[thread overview]
Message-ID: <20100827163839.GR22783@erda.amd.com> (raw)
In-Reply-To: <1282922125.22128.5.camel@e102144-lin.cambridge.arm.com>

On 27.08.10 11:15:25, Will Deacon wrote:

> > > The current implementation is not entirely safe in the case that
> > > oprofile_arch_init() fails. We need to make sure that we always call
> > > exit_driverfs() if we've called init_driverfs(). Also, avoid a potential
> > > double free when freeing 'counter_config', e.g. don't free
> > > 'counter_config' in both oprofile_arch_init() and oprofile_arch_exit().

I am not sure if it is worth the memory handling code, we could
alternativly implement fixed size arrays with MAX_COUNTERS. This would
eas it a lot. But, this code will become generic, so we can stick with
this implementation.

But, cpu varables should be used, maybe with a later patch.

> > The root cause that makes this check necessary is that
> > oprofile_arch_exit() is called though oprofile_arch_init() failed. We
> > should better fix this instead. I have to admit we will then have to
> > check all architectural implementations.
> > 
> 
> I took a look through all of the oprofile_arch_{init,exit} functions
> and it looks like only ARM needs fixing. Nobody else does any allocation
> here [well, until Matt's unified version comes into play].

Great, many thanks.

> How about something like this? This removes the exit call
> from the init code and sets pointers to NULL after they have been
> freed. We still have to do some checking so that we don't try to
> release a NULL perf event:
> 
> diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c
> index 0691176..12253eb 100644
> --- a/arch/arm/oprofile/common.c
> +++ b/arch/arm/oprofile/common.c
> @@ -275,10 +275,12 @@ out:
>  	return ret;
>  }
>  
> -static void  exit_driverfs(void)
> +static void __exit exit_driverfs(void)
>  {
> -	platform_device_unregister(oprofile_pdev);
> -	platform_driver_unregister(&oprofile_driver);
> +	if (!IS_ERR_OR_NULL(oprofile_pdev)) {

This check is obsolete here as we do not call oprofile_arch_exit() on
failure.

> +		platform_device_unregister(oprofile_pdev);
> +		platform_driver_unregister(&oprofile_driver);
> +	}
>  }
>  #else
>  static int __init init_driverfs(void) { return 0; }
> @@ -365,6 +367,7 @@ int __init oprofile_arch_init(struct
> oprofile_operations *ops)
>  	ret = init_driverfs();
>  	if (ret) {
>  		kfree(counter_config);
> +		counter_config = NULL;

Dito, obsolete now.

>  		return ret;
>  	}
>  
> @@ -374,8 +377,10 @@ int __init oprofile_arch_init(struct
> oprofile_operations *ops)
>  		if (!perf_events[cpu]) {
>  			pr_info("oprofile: failed to allocate %d perf events "
>  					"for cpu %d\n", perf_num_counters, cpu);
> -			while (--cpu >= 0)
> +			while (--cpu >= 0) {
>  				kfree(perf_events[cpu]);
> +				perf_events[cpu] = NULL;
> +			}

counter_config must be freed here.

>  			return -ENOMEM;
>  		}
>  	}
> @@ -396,25 +401,27 @@ int __init oprofile_arch_init(struct
> oprofile_operations *ops)
>  	return ret;
>  }
>  
> -void oprofile_arch_exit(void)
> +void __exit oprofile_arch_exit(void)
>  {
>  	int cpu, id;
>  	struct perf_event *event;
>  
> -	if (*perf_events) {
> -		exit_driverfs();
> -		for_each_possible_cpu(cpu) {
> -			for (id = 0; id < perf_num_counters; ++id) {
> -				event = perf_events[cpu][id];
> -				if (event != NULL)
> -					perf_event_release_kernel(event);
> -			}
> -			kfree(perf_events[cpu]);
> +	exit_driverfs();

If we shutdown all this in reverse order, this should be after the
loop.

> +
> +	for_each_possible_cpu(cpu) {
> +		if (!perf_events[cpu])
> +			continue;

Should be never NULL, the check can be removed.

> +
> +		for (id = 0; id < perf_num_counters; ++id) {
> +			event = perf_events[cpu][id];
> +			if (event != NULL)

	if (event)
		...

> +				perf_event_release_kernel(event);
>  		}
> +
> +		kfree(perf_events[cpu]);
>  	}
>  
> -	if (counter_config)
> -		kfree(counter_config);
> +	kfree(counter_config);
>  }
>  #else
>  int __init oprofile_arch_init(struct oprofile_operations *ops)
> @@ -422,5 +429,5 @@ int __init oprofile_arch_init(struct
> oprofile_operations *ops)
>  	pr_info("oprofile: hardware counters not available\n");
>  	return -ENODEV;
>  }
> -void oprofile_arch_exit(void) {}
> +void __exit oprofile_arch_exit(void) {}
>  #endif /* CONFIG_HW_PERF_EVENTS */
> diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c
> index b336cd9..3094af0 100644
> --- a/drivers/oprofile/oprof.c
> +++ b/drivers/oprofile/oprof.c
> @@ -257,15 +257,11 @@ static int __init oprofile_init(void)
>  		printk(KERN_INFO "oprofile: using timer interrupt.\n");
>  		err = oprofile_timer_init(&oprofile_ops);
>  		if (err)
> -			goto out_arch;
> +			goto out;

A 'return err;' here would remove the goto. I would preffer this.

Thanks,

-Robert

>  	}
>  	err = oprofilefs_register();
> -	if (err)
> -		goto out_arch;
> -	return 0;
>  
> -out_arch:
> -	oprofile_arch_exit();
> +out:
>  	return err;
>  }
>  
> 
> Thanks,
> 
> Will
> 
> 

-- 
Advanced Micro Devices, Inc.
Operating System Research Center

WARNING: multiple messages have this Message-ID (diff)
From: Robert Richter <robert.richter@amd.com>
To: Will Deacon <will.deacon@arm.com>
Cc: Matt Fleming <matt@console-pimps.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	Paul Mundt <lethal@linux-sh.org>,
	Russell King <linux@arm.linux.org.uk>,
	"linux-arm-kernel@lists.infradead.org"
	<linux-arm-kernel@lists.infradead.org>,
	"linux-sh@vger.kernel.org" <linux-sh@vger.kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Ingo Molnar <mingo@elte.hu>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Arnaldo Carvalho de Melo <acme@redhat.com>,
	"linux-arch@vger.kernel.org" <linux-arch@vger.kernel.org>
Subject: Re: [PATCH 1/4] oprofile: Handle initialisation failure more
Date: Fri, 27 Aug 2010 16:38:39 +0000	[thread overview]
Message-ID: <20100827163839.GR22783@erda.amd.com> (raw)
In-Reply-To: <1282922125.22128.5.camel@e102144-lin.cambridge.arm.com>

On 27.08.10 11:15:25, Will Deacon wrote:

> > > The current implementation is not entirely safe in the case that
> > > oprofile_arch_init() fails. We need to make sure that we always call
> > > exit_driverfs() if we've called init_driverfs(). Also, avoid a potential
> > > double free when freeing 'counter_config', e.g. don't free
> > > 'counter_config' in both oprofile_arch_init() and oprofile_arch_exit().

I am not sure if it is worth the memory handling code, we could
alternativly implement fixed size arrays with MAX_COUNTERS. This would
eas it a lot. But, this code will become generic, so we can stick with
this implementation.

But, cpu varables should be used, maybe with a later patch.

> > The root cause that makes this check necessary is that
> > oprofile_arch_exit() is called though oprofile_arch_init() failed. We
> > should better fix this instead. I have to admit we will then have to
> > check all architectural implementations.
> > 
> 
> I took a look through all of the oprofile_arch_{init,exit} functions
> and it looks like only ARM needs fixing. Nobody else does any allocation
> here [well, until Matt's unified version comes into play].

Great, many thanks.

> How about something like this? This removes the exit call
> from the init code and sets pointers to NULL after they have been
> freed. We still have to do some checking so that we don't try to
> release a NULL perf event:
> 
> diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c
> index 0691176..12253eb 100644
> --- a/arch/arm/oprofile/common.c
> +++ b/arch/arm/oprofile/common.c
> @@ -275,10 +275,12 @@ out:
>  	return ret;
>  }
>  
> -static void  exit_driverfs(void)
> +static void __exit exit_driverfs(void)
>  {
> -	platform_device_unregister(oprofile_pdev);
> -	platform_driver_unregister(&oprofile_driver);
> +	if (!IS_ERR_OR_NULL(oprofile_pdev)) {

This check is obsolete here as we do not call oprofile_arch_exit() on
failure.

> +		platform_device_unregister(oprofile_pdev);
> +		platform_driver_unregister(&oprofile_driver);
> +	}
>  }
>  #else
>  static int __init init_driverfs(void) { return 0; }
> @@ -365,6 +367,7 @@ int __init oprofile_arch_init(struct
> oprofile_operations *ops)
>  	ret = init_driverfs();
>  	if (ret) {
>  		kfree(counter_config);
> +		counter_config = NULL;

Dito, obsolete now.

>  		return ret;
>  	}
>  
> @@ -374,8 +377,10 @@ int __init oprofile_arch_init(struct
> oprofile_operations *ops)
>  		if (!perf_events[cpu]) {
>  			pr_info("oprofile: failed to allocate %d perf events "
>  					"for cpu %d\n", perf_num_counters, cpu);
> -			while (--cpu >= 0)
> +			while (--cpu >= 0) {
>  				kfree(perf_events[cpu]);
> +				perf_events[cpu] = NULL;
> +			}

counter_config must be freed here.

>  			return -ENOMEM;
>  		}
>  	}
> @@ -396,25 +401,27 @@ int __init oprofile_arch_init(struct
> oprofile_operations *ops)
>  	return ret;
>  }
>  
> -void oprofile_arch_exit(void)
> +void __exit oprofile_arch_exit(void)
>  {
>  	int cpu, id;
>  	struct perf_event *event;
>  
> -	if (*perf_events) {
> -		exit_driverfs();
> -		for_each_possible_cpu(cpu) {
> -			for (id = 0; id < perf_num_counters; ++id) {
> -				event = perf_events[cpu][id];
> -				if (event != NULL)
> -					perf_event_release_kernel(event);
> -			}
> -			kfree(perf_events[cpu]);
> +	exit_driverfs();

If we shutdown all this in reverse order, this should be after the
loop.

> +
> +	for_each_possible_cpu(cpu) {
> +		if (!perf_events[cpu])
> +			continue;

Should be never NULL, the check can be removed.

> +
> +		for (id = 0; id < perf_num_counters; ++id) {
> +			event = perf_events[cpu][id];
> +			if (event != NULL)

	if (event)
		...

> +				perf_event_release_kernel(event);
>  		}
> +
> +		kfree(perf_events[cpu]);
>  	}
>  
> -	if (counter_config)
> -		kfree(counter_config);
> +	kfree(counter_config);
>  }
>  #else
>  int __init oprofile_arch_init(struct oprofile_operations *ops)
> @@ -422,5 +429,5 @@ int __init oprofile_arch_init(struct
> oprofile_operations *ops)
>  	pr_info("oprofile: hardware counters not available\n");
>  	return -ENODEV;
>  }
> -void oprofile_arch_exit(void) {}
> +void __exit oprofile_arch_exit(void) {}
>  #endif /* CONFIG_HW_PERF_EVENTS */
> diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c
> index b336cd9..3094af0 100644
> --- a/drivers/oprofile/oprof.c
> +++ b/drivers/oprofile/oprof.c
> @@ -257,15 +257,11 @@ static int __init oprofile_init(void)
>  		printk(KERN_INFO "oprofile: using timer interrupt.\n");
>  		err = oprofile_timer_init(&oprofile_ops);
>  		if (err)
> -			goto out_arch;
> +			goto out;

A 'return err;' here would remove the goto. I would preffer this.

Thanks,

-Robert

>  	}
>  	err = oprofilefs_register();
> -	if (err)
> -		goto out_arch;
> -	return 0;
>  
> -out_arch:
> -	oprofile_arch_exit();
> +out:
>  	return err;
>  }
>  
> 
> Thanks,
> 
> Will
> 
> 

-- 
Advanced Micro Devices, Inc.
Operating System Research Center


WARNING: multiple messages have this Message-ID (diff)
From: robert.richter@amd.com (Robert Richter)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 1/4] oprofile: Handle initialisation failure more gracefully
Date: Fri, 27 Aug 2010 18:38:39 +0200	[thread overview]
Message-ID: <20100827163839.GR22783@erda.amd.com> (raw)
In-Reply-To: <1282922125.22128.5.camel@e102144-lin.cambridge.arm.com>

On 27.08.10 11:15:25, Will Deacon wrote:

> > > The current implementation is not entirely safe in the case that
> > > oprofile_arch_init() fails. We need to make sure that we always call
> > > exit_driverfs() if we've called init_driverfs(). Also, avoid a potential
> > > double free when freeing 'counter_config', e.g. don't free
> > > 'counter_config' in both oprofile_arch_init() and oprofile_arch_exit().

I am not sure if it is worth the memory handling code, we could
alternativly implement fixed size arrays with MAX_COUNTERS. This would
eas it a lot. But, this code will become generic, so we can stick with
this implementation.

But, cpu varables should be used, maybe with a later patch.

> > The root cause that makes this check necessary is that
> > oprofile_arch_exit() is called though oprofile_arch_init() failed. We
> > should better fix this instead. I have to admit we will then have to
> > check all architectural implementations.
> > 
> 
> I took a look through all of the oprofile_arch_{init,exit} functions
> and it looks like only ARM needs fixing. Nobody else does any allocation
> here [well, until Matt's unified version comes into play].

Great, many thanks.

> How about something like this? This removes the exit call
> from the init code and sets pointers to NULL after they have been
> freed. We still have to do some checking so that we don't try to
> release a NULL perf event:
> 
> diff --git a/arch/arm/oprofile/common.c b/arch/arm/oprofile/common.c
> index 0691176..12253eb 100644
> --- a/arch/arm/oprofile/common.c
> +++ b/arch/arm/oprofile/common.c
> @@ -275,10 +275,12 @@ out:
>  	return ret;
>  }
>  
> -static void  exit_driverfs(void)
> +static void __exit exit_driverfs(void)
>  {
> -	platform_device_unregister(oprofile_pdev);
> -	platform_driver_unregister(&oprofile_driver);
> +	if (!IS_ERR_OR_NULL(oprofile_pdev)) {

This check is obsolete here as we do not call oprofile_arch_exit() on
failure.

> +		platform_device_unregister(oprofile_pdev);
> +		platform_driver_unregister(&oprofile_driver);
> +	}
>  }
>  #else
>  static int __init init_driverfs(void) { return 0; }
> @@ -365,6 +367,7 @@ int __init oprofile_arch_init(struct
> oprofile_operations *ops)
>  	ret = init_driverfs();
>  	if (ret) {
>  		kfree(counter_config);
> +		counter_config = NULL;

Dito, obsolete now.

>  		return ret;
>  	}
>  
> @@ -374,8 +377,10 @@ int __init oprofile_arch_init(struct
> oprofile_operations *ops)
>  		if (!perf_events[cpu]) {
>  			pr_info("oprofile: failed to allocate %d perf events "
>  					"for cpu %d\n", perf_num_counters, cpu);
> -			while (--cpu >= 0)
> +			while (--cpu >= 0) {
>  				kfree(perf_events[cpu]);
> +				perf_events[cpu] = NULL;
> +			}

counter_config must be freed here.

>  			return -ENOMEM;
>  		}
>  	}
> @@ -396,25 +401,27 @@ int __init oprofile_arch_init(struct
> oprofile_operations *ops)
>  	return ret;
>  }
>  
> -void oprofile_arch_exit(void)
> +void __exit oprofile_arch_exit(void)
>  {
>  	int cpu, id;
>  	struct perf_event *event;
>  
> -	if (*perf_events) {
> -		exit_driverfs();
> -		for_each_possible_cpu(cpu) {
> -			for (id = 0; id < perf_num_counters; ++id) {
> -				event = perf_events[cpu][id];
> -				if (event != NULL)
> -					perf_event_release_kernel(event);
> -			}
> -			kfree(perf_events[cpu]);
> +	exit_driverfs();

If we shutdown all this in reverse order, this should be after the
loop.

> +
> +	for_each_possible_cpu(cpu) {
> +		if (!perf_events[cpu])
> +			continue;

Should be never NULL, the check can be removed.

> +
> +		for (id = 0; id < perf_num_counters; ++id) {
> +			event = perf_events[cpu][id];
> +			if (event != NULL)

	if (event)
		...

> +				perf_event_release_kernel(event);
>  		}
> +
> +		kfree(perf_events[cpu]);
>  	}
>  
> -	if (counter_config)
> -		kfree(counter_config);
> +	kfree(counter_config);
>  }
>  #else
>  int __init oprofile_arch_init(struct oprofile_operations *ops)
> @@ -422,5 +429,5 @@ int __init oprofile_arch_init(struct
> oprofile_operations *ops)
>  	pr_info("oprofile: hardware counters not available\n");
>  	return -ENODEV;
>  }
> -void oprofile_arch_exit(void) {}
> +void __exit oprofile_arch_exit(void) {}
>  #endif /* CONFIG_HW_PERF_EVENTS */
> diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c
> index b336cd9..3094af0 100644
> --- a/drivers/oprofile/oprof.c
> +++ b/drivers/oprofile/oprof.c
> @@ -257,15 +257,11 @@ static int __init oprofile_init(void)
>  		printk(KERN_INFO "oprofile: using timer interrupt.\n");
>  		err = oprofile_timer_init(&oprofile_ops);
>  		if (err)
> -			goto out_arch;
> +			goto out;

A 'return err;' here would remove the goto. I would preffer this.

Thanks,

-Robert

>  	}
>  	err = oprofilefs_register();
> -	if (err)
> -		goto out_arch;
> -	return 0;
>  
> -out_arch:
> -	oprofile_arch_exit();
> +out:
>  	return err;
>  }
>  
> 
> Thanks,
> 
> Will
> 
> 

-- 
Advanced Micro Devices, Inc.
Operating System Research Center

  reply	other threads:[~2010-08-27 16:41 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-08-26 19:09 [PATCH V2 0/4] Generalise ARM perf-events backend for oprofile Matt Fleming
2010-08-26 19:09 ` Matt Fleming
2010-08-26 19:09 ` Matt Fleming
2010-08-26 19:09 ` [PATCH 1/4] oprofile: Handle initialisation failure more gracefully Matt Fleming
2010-08-26 19:09   ` Matt Fleming
2010-08-26 19:09   ` Matt Fleming
2010-08-27 12:43   ` Robert Richter
2010-08-27 12:43     ` Robert Richter
2010-08-27 12:43     ` [PATCH 1/4] oprofile: Handle initialisation failure more Robert Richter
2010-08-27 15:15     ` [PATCH 1/4] oprofile: Handle initialisation failure more gracefully Will Deacon
2010-08-27 15:15       ` Will Deacon
2010-08-27 15:15       ` [PATCH 1/4] oprofile: Handle initialisation failure more Will Deacon
2010-08-27 16:38       ` Robert Richter [this message]
2010-08-27 16:38         ` [PATCH 1/4] oprofile: Handle initialisation failure more gracefully Robert Richter
2010-08-27 16:38         ` [PATCH 1/4] oprofile: Handle initialisation failure more Robert Richter
2010-08-27 18:06         ` [PATCH 1/4] oprofile: Handle initialisation failure more gracefully Will Deacon
2010-08-27 18:06           ` Will Deacon
2010-08-27 18:06           ` [PATCH 1/4] oprofile: Handle initialisation failure more Will Deacon
2010-08-27 19:47           ` [PATCH 1/4] oprofile: Handle initialisation failure more gracefully Robert Richter
2010-08-27 19:47             ` Robert Richter
2010-08-27 19:47             ` [PATCH 1/4] oprofile: Handle initialisation failure more Robert Richter
2010-08-26 19:09 ` [PATCH 2/4] sh: Accessor functions for the sh_pmu state Matt Fleming
2010-08-26 19:09   ` Matt Fleming
2010-08-26 19:09   ` Matt Fleming
2010-08-27 13:43   ` Robert Richter
2010-08-27 13:43     ` Robert Richter
2010-08-27 13:43     ` Robert Richter
2010-08-27 19:17     ` Matt Fleming
2010-08-27 19:17       ` Matt Fleming
2010-08-27 19:17       ` Matt Fleming
2010-08-30 12:41       ` Robert Richter
2010-08-30 12:41         ` Robert Richter
2010-08-30 12:41         ` Robert Richter
2010-08-26 19:09 ` [PATCH V2 3/4] oprofile: Abstract the perf-events backend Matt Fleming
2010-08-26 19:09   ` Matt Fleming
2010-08-26 19:09   ` Matt Fleming
2010-08-26 19:09   ` Matt Fleming
2010-08-27 10:41   ` Will Deacon
2010-08-27 10:41     ` Will Deacon
2010-08-27 10:41     ` Will Deacon
2010-08-27 12:44     ` Matt Fleming
2010-08-27 12:44       ` Matt Fleming
2010-08-27 12:44       ` Matt Fleming
2010-08-27 12:59   ` Robert Richter
2010-08-27 12:59     ` Robert Richter
2010-08-27 12:59     ` Robert Richter
2010-08-27 14:31   ` Robert Richter
2010-08-27 14:31     ` Robert Richter
2010-08-27 14:31     ` Robert Richter
2010-08-26 19:09 ` [PATCH V2 4/4] sh: Use the perf-events backend for oprofile Matt Fleming
2010-08-26 19:09   ` Matt Fleming
2010-08-26 19:09   ` Matt Fleming
2010-08-26 19:09   ` Matt Fleming
2010-08-27 14:59   ` Robert Richter
2010-08-27 14:59     ` Robert Richter
2010-08-27 14:59     ` Robert Richter
2010-08-27 20:19     ` Matt Fleming
2010-08-27 20:19       ` Matt Fleming
2010-08-27 20:19       ` Matt Fleming
2010-08-31 11:28       ` Robert Richter
2010-08-31 11:28         ` Robert Richter
2010-08-31 11:28         ` Robert Richter
2010-08-31 12:23         ` Matt Fleming
2010-08-31 12:23           ` Matt Fleming
2010-08-31 12:23           ` Matt Fleming
2010-08-31 13:26           ` Robert Richter
2010-08-31 13:26             ` Robert Richter
2010-08-31 13:26             ` Robert Richter
2010-08-31 11:05 ` [PATCH V2 0/4] Generalise ARM " Robert Richter
2010-08-31 11:05   ` Robert Richter
2010-08-31 11:05   ` Robert Richter
2010-08-31 11:25   ` Matt Fleming
2010-08-31 11:25     ` Matt Fleming
2010-08-31 11:25     ` Matt Fleming

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20100827163839.GR22783@erda.amd.com \
    --to=robert.richter@amd.com \
    --cc=acme@redhat.com \
    --cc=fweisbec@gmail.com \
    --cc=lethal@linux-sh.org \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sh@vger.kernel.org \
    --cc=linux@arm.linux.org.uk \
    --cc=matt@console-pimps.org \
    --cc=mingo@elte.hu \
    --cc=peterz@infradead.org \
    --cc=will.deacon@arm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.