linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] dma-contiguous: two bug fixes for dma_{alloc,free}_contiguous()
@ 2019-07-25 23:39 Nicolin Chen
  2019-07-25 23:39 ` [PATCH 1/2] dma-contiguous: do not overwrite align in dma_alloc_contiguous() Nicolin Chen
  2019-07-25 23:39 ` [PATCH 2/2] dma-contiguous: page-align the size in dma_free_contiguous() Nicolin Chen
  0 siblings, 2 replies; 6+ messages in thread
From: Nicolin Chen @ 2019-07-25 23:39 UTC (permalink / raw)
  To: dafna.hirschfeld, hch, m.szyprowski, robin.murphy; +Cc: iommu, linux-kernel

There are two obvious bugs in these two functions. So having
two patches to fix them.

Nicolin Chen (2):
  dma-contiguous: do not overwrite align in dma_alloc_contiguous()
  dma-contiguous: page-align the size in dma_free_contiguous()

 kernel/dma/contiguous.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

-- 
2.17.1


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

* [PATCH 1/2] dma-contiguous: do not overwrite align in dma_alloc_contiguous()
  2019-07-25 23:39 [PATCH 0/2] dma-contiguous: two bug fixes for dma_{alloc,free}_contiguous() Nicolin Chen
@ 2019-07-25 23:39 ` Nicolin Chen
  2019-07-26  6:28   ` Christoph Hellwig
  2019-07-25 23:39 ` [PATCH 2/2] dma-contiguous: page-align the size in dma_free_contiguous() Nicolin Chen
  1 sibling, 1 reply; 6+ messages in thread
From: Nicolin Chen @ 2019-07-25 23:39 UTC (permalink / raw)
  To: dafna.hirschfeld, hch, m.szyprowski, robin.murphy; +Cc: iommu, linux-kernel

The dma_alloc_contiguous() limits align at CONFIG_CMA_ALIGNMENT for
cma_alloc() however it does not restore it for the fallback routine.
This will result in a size mismatch between the allocation and free
when running in the fallback routines, if the align is larger than
CONFIG_CMA_ALIGNMENT.

This patch adds a cma_align to take care of cma_alloc() and prevent
the align from being overwritten.

Fixes: fdaeec198ada ("dma-contiguous: add dma_{alloc,free}_contiguous() helpers")
Reported-by: Dafna Hirschfeld <dafna.hirschfeld@collabora.com>
Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com>
---
 kernel/dma/contiguous.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
index bfc0c17f2a3d..fa8cd0f0512e 100644
--- a/kernel/dma/contiguous.c
+++ b/kernel/dma/contiguous.c
@@ -233,6 +233,7 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
 	int node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
 	size_t count = PAGE_ALIGN(size) >> PAGE_SHIFT;
 	size_t align = get_order(PAGE_ALIGN(size));
+	size_t cma_align = CONFIG_CMA_ALIGNMENT;
 	struct page *page = NULL;
 	struct cma *cma = NULL;
 
@@ -241,11 +242,11 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
 	else if (count > 1)
 		cma = dma_contiguous_default_area;
 
+	cma_align = min_t(size_t, align, cma_align);
+
 	/* CMA can be used only in the context which permits sleeping */
-	if (cma && gfpflags_allow_blocking(gfp)) {
-		align = min_t(size_t, align, CONFIG_CMA_ALIGNMENT);
-		page = cma_alloc(cma, count, align, gfp & __GFP_NOWARN);
-	}
+	if (cma && gfpflags_allow_blocking(gfp))
+		page = cma_alloc(cma, count, cma_align, gfp & __GFP_NOWARN);
 
 	/* Fallback allocation of normal pages */
 	if (!page)
-- 
2.17.1


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

* [PATCH 2/2] dma-contiguous: page-align the size in dma_free_contiguous()
  2019-07-25 23:39 [PATCH 0/2] dma-contiguous: two bug fixes for dma_{alloc,free}_contiguous() Nicolin Chen
  2019-07-25 23:39 ` [PATCH 1/2] dma-contiguous: do not overwrite align in dma_alloc_contiguous() Nicolin Chen
@ 2019-07-25 23:39 ` Nicolin Chen
  2019-07-26  6:30   ` Christoph Hellwig
  1 sibling, 1 reply; 6+ messages in thread
From: Nicolin Chen @ 2019-07-25 23:39 UTC (permalink / raw)
  To: dafna.hirschfeld, hch, m.szyprowski, robin.murphy; +Cc: iommu, linux-kernel

According to the original dma_direct_alloc_pages() code:
{
	unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;

	if (!dma_release_from_contiguous(dev, page, count))
		__free_pages(page, get_order(size));
}

The count parameter for dma_release_from_contiguous() was page
aligned before the right-shifting operation, while the new API
dma_free_contiguous() forgets to have PAGE_ALIGN() at the size.

So this patch simply adds it to prevent any corner case.

Fixes: fdaeec198ada ("dma-contiguous: add dma_{alloc,free}_contiguous() helpers")
Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com>
---
 kernel/dma/contiguous.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
index fa8cd0f0512e..5735a9166866 100644
--- a/kernel/dma/contiguous.c
+++ b/kernel/dma/contiguous.c
@@ -267,7 +267,8 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
  */
 void dma_free_contiguous(struct device *dev, struct page *page, size_t size)
 {
-	if (!cma_release(dev_get_cma_area(dev), page, size >> PAGE_SHIFT))
+	if (!cma_release(dev_get_cma_area(dev), page,
+			 PAGE_ALIGN(size) >> PAGE_SHIFT))
 		__free_pages(page, get_order(size));
 }
 
-- 
2.17.1


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

* Re: [PATCH 1/2] dma-contiguous: do not overwrite align in dma_alloc_contiguous()
  2019-07-25 23:39 ` [PATCH 1/2] dma-contiguous: do not overwrite align in dma_alloc_contiguous() Nicolin Chen
@ 2019-07-26  6:28   ` Christoph Hellwig
  2019-07-26 19:22     ` Nicolin Chen
  0 siblings, 1 reply; 6+ messages in thread
From: Christoph Hellwig @ 2019-07-26  6:28 UTC (permalink / raw)
  To: Nicolin Chen
  Cc: dafna.hirschfeld, hch, m.szyprowski, robin.murphy, iommu, linux-kernel

On Thu, Jul 25, 2019 at 04:39:58PM -0700, Nicolin Chen wrote:
> The dma_alloc_contiguous() limits align at CONFIG_CMA_ALIGNMENT for
> cma_alloc() however it does not restore it for the fallback routine.
> This will result in a size mismatch between the allocation and free
> when running in the fallback routines, if the align is larger than
> CONFIG_CMA_ALIGNMENT.
> 
> This patch adds a cma_align to take care of cma_alloc() and prevent
> the align from being overwritten.
> 
> Fixes: fdaeec198ada ("dma-contiguous: add dma_{alloc,free}_contiguous() helpers")
> Reported-by: Dafna Hirschfeld <dafna.hirschfeld@collabora.com>
> Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com>
> ---
>  kernel/dma/contiguous.c | 9 +++++----
>  1 file changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
> index bfc0c17f2a3d..fa8cd0f0512e 100644
> --- a/kernel/dma/contiguous.c
> +++ b/kernel/dma/contiguous.c
> @@ -233,6 +233,7 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
>  	int node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
>  	size_t count = PAGE_ALIGN(size) >> PAGE_SHIFT;
>  	size_t align = get_order(PAGE_ALIGN(size));
> +	size_t cma_align = CONFIG_CMA_ALIGNMENT;
>  	struct page *page = NULL;
>  	struct cma *cma = NULL;
>  
> @@ -241,11 +242,11 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
>  	else if (count > 1)
>  		cma = dma_contiguous_default_area;
>  
> +	cma_align = min_t(size_t, align, cma_align);
> +
>  	/* CMA can be used only in the context which permits sleeping */
> -	if (cma && gfpflags_allow_blocking(gfp)) {
> -		align = min_t(size_t, align, CONFIG_CMA_ALIGNMENT);
> -		page = cma_alloc(cma, count, align, gfp & __GFP_NOWARN);
> -	}
> +	if (cma && gfpflags_allow_blocking(gfp))
> +		page = cma_alloc(cma, count, cma_align, gfp & __GFP_NOWARN);

Shouldn't cma_align be confined to the block guarded by
"if (cma && gfpflags_allow_blocking(gfp))" so that we can optimize it
away for configurations that do not support CMA?

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

* Re: [PATCH 2/2] dma-contiguous: page-align the size in dma_free_contiguous()
  2019-07-25 23:39 ` [PATCH 2/2] dma-contiguous: page-align the size in dma_free_contiguous() Nicolin Chen
@ 2019-07-26  6:30   ` Christoph Hellwig
  0 siblings, 0 replies; 6+ messages in thread
From: Christoph Hellwig @ 2019-07-26  6:30 UTC (permalink / raw)
  To: Nicolin Chen
  Cc: dafna.hirschfeld, hch, m.szyprowski, robin.murphy, iommu, linux-kernel

On Thu, Jul 25, 2019 at 04:39:59PM -0700, Nicolin Chen wrote:
> According to the original dma_direct_alloc_pages() code:
> {
> 	unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
> 
> 	if (!dma_release_from_contiguous(dev, page, count))
> 		__free_pages(page, get_order(size));
> }
> 
> The count parameter for dma_release_from_contiguous() was page
> aligned before the right-shifting operation, while the new API
> dma_free_contiguous() forgets to have PAGE_ALIGN() at the size.
> 
> So this patch simply adds it to prevent any corner case.
> 
> Fixes: fdaeec198ada ("dma-contiguous: add dma_{alloc,free}_contiguous() helpers")
> Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com>

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

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

* Re: [PATCH 1/2] dma-contiguous: do not overwrite align in dma_alloc_contiguous()
  2019-07-26  6:28   ` Christoph Hellwig
@ 2019-07-26 19:22     ` Nicolin Chen
  0 siblings, 0 replies; 6+ messages in thread
From: Nicolin Chen @ 2019-07-26 19:22 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: dafna.hirschfeld, m.szyprowski, robin.murphy, iommu, linux-kernel

On Fri, Jul 26, 2019 at 08:28:49AM +0200, Christoph Hellwig wrote:
> On Thu, Jul 25, 2019 at 04:39:58PM -0700, Nicolin Chen wrote:
> > The dma_alloc_contiguous() limits align at CONFIG_CMA_ALIGNMENT for
> > cma_alloc() however it does not restore it for the fallback routine.
> > This will result in a size mismatch between the allocation and free
> > when running in the fallback routines, if the align is larger than
> > CONFIG_CMA_ALIGNMENT.
> > 
> > This patch adds a cma_align to take care of cma_alloc() and prevent
> > the align from being overwritten.
> > 
> > Fixes: fdaeec198ada ("dma-contiguous: add dma_{alloc,free}_contiguous() helpers")
> > Reported-by: Dafna Hirschfeld <dafna.hirschfeld@collabora.com>
> > Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com>
> > ---
> >  kernel/dma/contiguous.c | 9 +++++----
> >  1 file changed, 5 insertions(+), 4 deletions(-)
> > 
> > diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
> > index bfc0c17f2a3d..fa8cd0f0512e 100644
> > --- a/kernel/dma/contiguous.c
> > +++ b/kernel/dma/contiguous.c
> > @@ -233,6 +233,7 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
> >  	int node = dev ? dev_to_node(dev) : NUMA_NO_NODE;
> >  	size_t count = PAGE_ALIGN(size) >> PAGE_SHIFT;
> >  	size_t align = get_order(PAGE_ALIGN(size));
> > +	size_t cma_align = CONFIG_CMA_ALIGNMENT;
> >  	struct page *page = NULL;
> >  	struct cma *cma = NULL;
> >  
> > @@ -241,11 +242,11 @@ struct page *dma_alloc_contiguous(struct device *dev, size_t size, gfp_t gfp)
> >  	else if (count > 1)
> >  		cma = dma_contiguous_default_area;
> >  
> > +	cma_align = min_t(size_t, align, cma_align);
> > +
> >  	/* CMA can be used only in the context which permits sleeping */
> > -	if (cma && gfpflags_allow_blocking(gfp)) {
> > -		align = min_t(size_t, align, CONFIG_CMA_ALIGNMENT);
> > -		page = cma_alloc(cma, count, align, gfp & __GFP_NOWARN);
> > -	}
> > +	if (cma && gfpflags_allow_blocking(gfp))
> > +		page = cma_alloc(cma, count, cma_align, gfp & __GFP_NOWARN);
> 
> Shouldn't cma_align be confined to the block guarded by
> "if (cma && gfpflags_allow_blocking(gfp))" so that we can optimize it
> away for configurations that do not support CMA?

Had my local 1st version doing just like that but then wanted to
simplify the statement within that if-condition so redid in this
way. Will change it back as you suggested. Thanks

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

end of thread, other threads:[~2019-07-26 19:21 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-25 23:39 [PATCH 0/2] dma-contiguous: two bug fixes for dma_{alloc,free}_contiguous() Nicolin Chen
2019-07-25 23:39 ` [PATCH 1/2] dma-contiguous: do not overwrite align in dma_alloc_contiguous() Nicolin Chen
2019-07-26  6:28   ` Christoph Hellwig
2019-07-26 19:22     ` Nicolin Chen
2019-07-25 23:39 ` [PATCH 2/2] dma-contiguous: page-align the size in dma_free_contiguous() Nicolin Chen
2019-07-26  6:30   ` Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).