[PATCH] mm: cma: Retry from the beginning of cma area if all blocks are busy

johannes at johannesthoma.com johannes at johannesthoma.com
Fri Jan 6 11:16:11 EST 2017


From: Johannes Thoma <johannes at johannesthoma.com>

When the size of the requested block is close to the total size of
the contigous memory, cma_alloc fails early when no more free
memory blocks are found by bitmap_find_next_zero_area_off and the
memory areas tested are temporarily busy.

This patch introduces a little extra loop that causes cma_alloc to
rescan from the beginning when all checked memory areas are busy.

We ran into this problem when a GPU driver tried to allocate cma memory
on a busy system, but failed because the memory area was busy.

Signed-off-by: Johannes Thoma <johannes at johannesthoma.com>
---
 mm/cma.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/mm/cma.c b/mm/cma.c
index c960459..35d68c8 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -368,6 +368,7 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align)
 	unsigned long pfn = -1;
 	unsigned long start = 0;
 	unsigned long bitmap_maxno, bitmap_no, bitmap_count;
+	int retries = 10;
 	struct page *page = NULL;
 	int ret;
 
@@ -390,10 +391,21 @@ struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align)
 
 	for (;;) {
 		mutex_lock(&cma->lock);
+scan_again:
 		bitmap_no = bitmap_find_next_zero_area_off(cma->bitmap,
 				bitmap_maxno, start, bitmap_count, mask,
 				offset);
 		if (bitmap_no >= bitmap_maxno) {
+			/*
+			 * Restart from the beginning if all areas were busy.
+			 * This handles false failures when count is close
+			 * to overall CMA size and the checked areas were
+			 * busy temporarily.
+			 */
+			if (start != 0 && retries--) {
+				start = 0;
+				goto scan_again;
+			}
 			mutex_unlock(&cma->lock);
 			break;
 		}
-- 
2.8.0-rc4




More information about the Kernelnewbies mailing list