Skip to contentSkip to conversation

media: atomisp: Fixed error handling path

PATCH Superseded Souptick Joarder 2 participants 4 messages Sep 27, 2020 – Sep 29, 2020

Subsystems (4)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 media: atomisp: Fixed error handling path

Inside alloc_user_pages() based on flag value either pin_user_pages() or get_user_pages_fast() will be called. However, these API might fail.

But free_user_pages() called in error handling path doesn't bother about return value and will try to unpin bo->pgnr pages, which is incorrect.

Fix this by passing the page_nr to free_user_pages(). If page_nr > 0 pages will be unpinned based on bo->mem_type. This will also take care of non error handling path.

Fixes 14a638ab96c5 ("media: atomisp: use pin_user_pages() for memory

allocation")

Cc John Hubbard <[email protected]>
Cc Ira Weiny <[email protected]>
Cc Dan Carpenter <[email protected]>
---
 drivers/staging/media/atomisp/pci/hmm/hmm_bo.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c +8 -5
index f13af23..0168f98 100644
@@ -857,16 +857,17 @@ static void free_private_pages(struct hmm_buffer_object *bo,
 	kfree(bo->page_obj);
 }
 
-static void free_user_pages(struct hmm_buffer_object *bo)
+static void free_user_pages(struct hmm_buffer_object *bo,
+			    unsigned int page_nr)
 {
 	int i;
 
 	hmm_mem_stat.usr_size -= bo->pgnr;
 
 	if (bo->mem_type == HMM_BO_MEM_TYPE_PFN) {
-		unpin_user_pages(bo->pages, bo->pgnr);
+		unpin_user_pages(bo->pages, page_nr);
 	} else {
-		for (i = 0; i < bo->pgnr; i++)
+		for (i = 0; i < page_nr; i++)
 			put_page(bo->pages[i]);
 	}
 	kfree(bo->pages);
@@ -942,6 +943,8 @@ static int alloc_user_pages(struct hmm_buffer_object *bo,
 		dev_err(atomisp_dev,
 			"get_user_pages err: bo->pgnr = %d, pgnr actually pinned = %d.\n",
 			bo->pgnr, page_nr);
+		if (page_nr < 0)
+			page_nr = 0;
 		goto out_of_mem;
 	}
 
@@ -954,7 +957,7 @@ static int alloc_user_pages(struct hmm_buffer_object *bo,
 
 out_of_mem:
 
-	free_user_pages(bo);
+	free_user_pages(bo, page_nr);
 
 	return -ENOMEM;
 }
@@ -1037,7 +1040,7 @@ void hmm_bo_free_pages(struct hmm_buffer_object *bo)
 	if (bo->type == HMM_BO_PRIVATE)
 		free_private_pages(bo, &dynamic_pool, &reserved_pool);
 	else if (bo->type == HMM_BO_USER)
-		free_user_pages(bo);
+		free_user_pages(bo, bo->pgnr);
 	else
 		dev_err(atomisp_dev, "invalid buffer type.\n");
 	mutex_unlock(&bo->mutex);
Signature · 1 line
1.9.1
#1 lore raw
Quoted 26 lines · Souptick Joarder

Inside alloc_user_pages() based on flag value either pin_user_pages() or get_user_pages_fast() will be called. However, these API might fail.

But free_user_pages() called in error handling path doesn't bother about return value and will try to unpin bo->pgnr pages, which is incorrect.

Fix this by passing the page_nr to free_user_pages(). If page_nr > 0 pages will be unpinned based on bo->mem_type. This will also take care of non error handling path.

Fixes 14a638ab96c5 ("media: atomisp: use pin_user_pages() for memory

allocation")

Cc John Hubbard <[email protected]>
Cc Ira Weiny <[email protected]>
Cc Dan Carpenter <[email protected]>
---
 drivers/staging/media/atomisp/pci/hmm/hmm_bo.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c +0 -0
index f13af23..0168f98 100644

drivers/staging/media/atomisp/pci/hmm/hmm_bo.c static void free_private_pages(struct hmm_buffer_object *bo, · line 865

Quoted 10 lines
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c +2 -1
@@ -857,16 +857,17 @@ static void free_private_pages(struct hmm_buffer_object *bo,
 	kfree(bo->page_obj);
 }
 
-static void free_user_pages(struct hmm_buffer_object *bo)
+static void free_user_pages(struct hmm_buffer_object *bo,
+			    unsigned int page_nr)
 {
 	int i;
 
 	hmm_mem_stat.usr_size -= bo->pgnr;
                              ^^^^^^^^^^^

This is still a problem. It needs to be hmm_mem_stat.usr_size -= page_nr.

regards,
dan carpenter

Quoted 10 lines
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c +2 -2
 	if (bo->mem_type == HMM_BO_MEM_TYPE_PFN) {
-		unpin_user_pages(bo->pages, bo->pgnr);
+		unpin_user_pages(bo->pages, page_nr);
 	} else {
-		for (i = 0; i < bo->pgnr; i++)
+		for (i = 0; i < page_nr; i++)
 			put_page(bo->pages[i]);
 	}
 	kfree(bo->pages);
#2 lore raw

Hi Dan,

Quoted 37 lines · Dan Carpenter
Quoted 35 lines · Souptick Joarder

Inside alloc_user_pages() based on flag value either pin_user_pages() or get_user_pages_fast() will be called. However, these API might fail.

But free_user_pages() called in error handling path doesn't bother about return value and will try to unpin bo->pgnr pages, which is incorrect.

Fix this by passing the page_nr to free_user_pages(). If page_nr > 0 pages will be unpinned based on bo->mem_type. This will also take care of non error handling path.

Fixes 14a638ab96c5 ("media: atomisp: use pin_user_pages() for memory

allocation")

Cc John Hubbard <[email protected]>
Cc Ira Weiny <[email protected]>
Cc Dan Carpenter <[email protected]>
---
 drivers/staging/media/atomisp/pci/hmm/hmm_bo.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c +2 -1
index f13af23..0168f98 100644
@@ -857,16 +857,17 @@ static void free_private_pages(struct hmm_buffer_object *bo,
      kfree(bo->page_obj);
 }
 
-static void free_user_pages(struct hmm_buffer_object *bo)
+static void free_user_pages(struct hmm_buffer_object *bo,
+                         unsigned int page_nr)
 {
      int i;
 
Quoted 3 lines

drivers/staging/media/atomisp/pci/hmm/hmm_bo.c static void free_private_pages(struct hmm_buffer_object *bo, · line 865

Quoted 1 line
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c +0 -0
      hmm_mem_stat.usr_size -= bo->pgnr;
                              ^^^^^^^^^^^

This is still a problem. It needs to be hmm_mem_stat.usr_size -= page_nr.

In failure path, it is hmm_mem_stat.usr_size += bo->pgnr.
I think, hmm_mem_stat.usr_size -= bo->pgnr is correct as per existing code. Do you think that needs to be changed ?

Quoted 15 lines

regards,
dan carpenter

Quoted 10 lines
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c +2 -2
      if (bo->mem_type == HMM_BO_MEM_TYPE_PFN) {
-             unpin_user_pages(bo->pages, bo->pgnr);
+             unpin_user_pages(bo->pages, page_nr);
      } else {
-             for (i = 0; i < bo->pgnr; i++)
+             for (i = 0; i < page_nr; i++)
                      put_page(bo->pages[i]);
      }
      kfree(bo->pages);
Reviewed-by
#3 lore raw
Quoted 41 lines · Souptick Joarder

Hi Dan,

Quoted 37 lines · Dan Carpenter
Quoted 35 lines · Souptick Joarder

Inside alloc_user_pages() based on flag value either pin_user_pages() or get_user_pages_fast() will be called. However, these API might fail.

But free_user_pages() called in error handling path doesn't bother about return value and will try to unpin bo->pgnr pages, which is incorrect.

Fix this by passing the page_nr to free_user_pages(). If page_nr > 0 pages will be unpinned based on bo->mem_type. This will also take care of non error handling path.

Fixes 14a638ab96c5 ("media: atomisp: use pin_user_pages() for memory

allocation")

Cc John Hubbard <[email protected]>
Cc Ira Weiny <[email protected]>
Cc Dan Carpenter <[email protected]>
---
 drivers/staging/media/atomisp/pci/hmm/hmm_bo.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c +2 -1
index f13af23..0168f98 100644
@@ -857,16 +857,17 @@ static void free_private_pages(struct hmm_buffer_object *bo,
      kfree(bo->page_obj);
 }
 
-static void free_user_pages(struct hmm_buffer_object *bo)
+static void free_user_pages(struct hmm_buffer_object *bo,
+                         unsigned int page_nr)
 {
      int i;
 
Quoted 8 lines
Quoted 3 lines

drivers/staging/media/atomisp/pci/hmm/hmm_bo.c static void free_private_pages(struct hmm_buffer_object *bo, · line 865

Quoted 1 line
drivers/staging/media/atomisp/pci/hmm/hmm_bo.c +0 -0
      hmm_mem_stat.usr_size -= bo->pgnr;
                              ^^^^^^^^^^^

This is still a problem. It needs to be hmm_mem_stat.usr_size -= page_nr.

In failure path, it is hmm_mem_stat.usr_size += bo->pgnr.
I think, hmm_mem_stat.usr_size -= bo->pgnr is correct as per existing code. Do you think that needs to be changed ?

Yeah. Crud. I'm sorry. You had it right.

regards,
dan carpenter