Skip to contentSkip to conversation

mm/sparse.c: Check the return value of sparse_index_alloc().

PATCH In review WANG Cong 4 participants 12 messages Nov 15, 2007 – Nov 29, 2007

Subsystems (3)
lore
Share & tools
lore

WANG Cong

author
#0 lore raw

PATCH 1/1 mm/sparse.c: Check the return value of sparse_index_alloc().

Since sparse_index_alloc() can return NULL on memory allocation failure, we must deal with the failure condition when calling it.

Cc Christoph Lameter <[email protected]>
Cc Rik van Riel <[email protected]>

---

Makefile +0 -0
mm/sparse.c +2 -0
index e06f514..d245e59 100644
@@ -83,6 +83,8 @@ static int __meminit sparse_index_init(unsigned long section_nr, int nid)
 		return -EEXIST;
 
 	section = sparse_index_alloc(nid);
+	if (!section)
+		return -ENOMEM;
 	/*
 	 * This lock keeps two different sections from
 	 * reallocating for the same index

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#1 lore raw
Quoted 16 lines · On Thu, 15 Nov 2007 21:54:28 +0800 WANG Cong <[email protected]> wrote:

Since sparse_index_alloc() can return NULL on memory allocation failure, we must deal with the failure condition when calling it.

Cc Christoph Lameter <[email protected]>
Cc Rik van Riel <[email protected]>

---

Makefile +0 -0
mm/sparse.c +0 -0
index e06f514..d245e59 100644

mm/sparse.c static int __meminit sparse_index_init(unsigned long section_nr, int nid) · line 90

Quoted 8 lines
mm/sparse.c +2 -0
@@ -83,6 +83,8 @@ static int __meminit sparse_index_init(unsigned long section_nr, int nid)
 		return -EEXIST;
 
 	section = sparse_index_alloc(nid);
+	if (!section)
+		return -ENOMEM;
 	/*
 	 * This lock keeps two different sections from
 	 * reallocating for the same index

Sure, but both callers of sparse_index_init() ignore its return value anyway.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#2 lore raw
In reply to WANG Cong
Quoted 15 lines · WANG Cong

Since sparse_index_alloc() can return NULL on memory allocation failure, we must deal with the failure condition when calling it.

Cc Christoph Lameter <[email protected]>
Cc Rik van Riel <[email protected]>

---

Makefile +0 -0
mm/sparse.c +0 -0
index e06f514..d245e59 100644

mm/sparse.c static int __meminit sparse_index_init(unsigned long section_nr, int nid) · line 90

Quoted 8 lines
mm/sparse.c +2 -0
@@ -83,6 +83,8 @@ static int __meminit sparse_index_init(unsigned long section_nr, int nid)
 		return -EEXIST;
 
 	section = sparse_index_alloc(nid);
+	if (!section)
+		return -ENOMEM;
 	/*
 	 * This lock keeps two different sections from
 	 * reallocating for the same index

Oddly enough, sparse_add_one_section() doesn't seem to like to check its allocations. The usemap is checked, but not freed on error. If you want to fix this up, I think it needs a little more love than just two lines.

Do you want to try to add some actual error handling to sparse_add_one_section()?

-- Dave

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#3 lore raw
Quoted 18 lines · Dave Hansen
Quoted 17 lines · WANG Cong

Since sparse_index_alloc() can return NULL on memory allocation failure, we must deal with the failure condition when calling it.

Cc Christoph Lameter <[email protected]>
Cc Rik van Riel <[email protected]>

---

Makefile +0 -0
mm/sparse.c +0 -0
index e06f514..d245e59 100644
@@ -83,6 +83,8 @@ static int __meminit sparse_index_init(unsigned long section_nr, int nid)
 		return -EEXIST;
 
Quoted 11 lines

mm/sparse.c static int __meminit sparse_index_init(unsigned long section_nr, int nid) · line 90

Quoted 6 lines
mm/sparse.c +2 -0
 	section = sparse_index_alloc(nid);
+	if (!section)
+		return -ENOMEM;
 	/*
 	 * This lock keeps two different sections from
 	 * reallocating for the same index

Oddly enough, sparse_add_one_section() doesn't seem to like to check its allocations. The usemap is checked, but not freed on error. If you want to fix this up, I think it needs a little more love than just two lines.

Er, right. I missed this point.

Quoted 3 lines

Do you want to try to add some actual error handling to sparse_add_one_section()?

Yes, I will have a try. And memory_present() also doesn't check it. More patches around this will come up soon. Since Andrew has included the above patch, so I won't remake it with others together.

Andrew, is this OK for you?

Thanks.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#4 lore raw

PATCH 1/1 mm/sparse.c: Improve the error handling for sparse_add_one_section()

In reply to Dave Hansen

Improve the error handling for mm/sparse.c::sparse_add_one_section(). And I see no reason to check 'usemap' until holding the 'pgdat_resize_lock'. If someone knows, please let me know.

Note! This patch is _not_ tested yet, since it seems that I can't configure sparse memory for i386 box. Sorry for this. ;( I hope someone can help me to test it.

Cc Christoph Lameter <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Rik van Riel <[email protected]>
---
 mm/sparse.c |   17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)
mm/sparse.c +10 -7
Index: linux-2.6/mm/sparse.c
===================================================================
@@ -391,9 +391,17 @@ int sparse_add_one_section(struct zone *
 	 * no locking for this, because it does its own
 	 * plus, it does a kmalloc
 	 */
-	sparse_index_init(section_nr, pgdat->node_id);
+	ret = sparse_index_init(section_nr, pgdat->node_id);
+	if (ret < 0)
+		return ret;
 	memmap = kmalloc_section_memmap(section_nr, pgdat->node_id, nr_pages);
+	if (!memmap)
+		return -ENOMEM;
 	usemap = __kmalloc_section_usemap();
+	if (!usemap) {
+		__kfree_section_memmap(memmap, nr_pages);
+		return -ENOMEM;
+	}
 
 	pgdat_resize_lock(pgdat, &flags);
 
@@ -403,18 +411,13 @@ int sparse_add_one_section(struct zone *
 		goto out;
 	}
 
-	if (!usemap) {
-		ret = -ENOMEM;
-		goto out;
-	}
 	ms->section_mem_map |= SECTION_MARKED_PRESENT;
 
 	ret = sparse_init_one_section(ms, section_nr, memmap, usemap);
 
 out:
 	pgdat_resize_unlock(pgdat, &flags);
-	if (ret <= 0)
-		__kfree_section_memmap(memmap, nr_pages);
+
 	return ret;
 }
 #endif

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#5 lore raw

Re: [Patch] mm/sparse.c: Improve the error handling for sparse_add_one_section()

Hi, Cong-san.

mm/sparse.c int sparse_add_one_section(struct zone * · line 423

Quoted 12 lines
mm/sparse.c +1 -2
 	ms->section_mem_map |= SECTION_MARKED_PRESENT;
 
 	ret = sparse_init_one_section(ms, section_nr, memmap, usemap);
 
 out:
 	pgdat_resize_unlock(pgdat, &flags);
-	if (ret <= 0)
-		__kfree_section_memmap(memmap, nr_pages);
+
 	return ret;
 }
 #endif

Hmm. When sparse_init_one_section() returns error, memmap and usemap should be free.

Thanks for your fixing.

Signature · 8 lines
Yasunori Goto 


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
author
#6 lore raw

PATCH 1/1 (Resend) mm/sparse.c: Improve the error handling for sparse_add_one_section()

Quoted 6 lines · Yasunori Goto

Hi, Cong-san.

Quoted 4 lines
(quoted diff) +0 -0
 	ms->section_mem_map |= SECTION_MARKED_PRESENT;
 
 	ret = sparse_init_one_section(ms, section_nr, memmap, usemap);
Quoted 11 lines

Review

Quoted 8 lines

out:

(quoted diff) +1 -2
 	pgdat_resize_unlock(pgdat, &flags);
-	if (ret <= 0)
-		__kfree_section_memmap(memmap, nr_pages);
+
 	return ret;
 }
 #endif

Hmm. When sparse_init_one_section() returns error, memmap and usemap should be free.

Hi, Yasunori.

Thanks for your comments. Is the following one fine for you?

---

mm/sparse.c +10 -6
Index: linux-2.6/mm/sparse.c
===================================================================
@@ -391,9 +391,17 @@ int sparse_add_one_section(struct zone *
 	 * no locking for this, because it does its own
 	 * plus, it does a kmalloc
 	 */
-	sparse_index_init(section_nr, pgdat->node_id);
+	ret = sparse_index_init(section_nr, pgdat->node_id);
+	if (ret < 0)
+		return ret;
 	memmap = kmalloc_section_memmap(section_nr, pgdat->node_id, nr_pages);
+	if (!memmap)
+		return -ENOMEM;
 	usemap = __kmalloc_section_usemap();
+	if (!usemap) {
+		__kfree_section_memmap(memmap, nr_pages);
+		return -ENOMEM;
+	}
 
 	pgdat_resize_lock(pgdat, &flags);
 
@@ -403,10 +411,6 @@ int sparse_add_one_section(struct zone *
 		goto out;
 	}
 
-	if (!usemap) {
-		ret = -ENOMEM;
-		goto out;
-	}
 	ms->section_mem_map |= SECTION_MARKED_PRESENT;
 
 	ret = sparse_init_one_section(ms, section_nr, memmap, usemap);
@@ -414,7 +418,7 @@ int sparse_add_one_section(struct zone *
 out:
 	pgdat_resize_unlock(pgdat, &flags);
 	if (ret <= 0)
-		__kfree_section_memmap(memmap, nr_pages);
+		kfree(usemap);
 	return ret;
 }
 #endif

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#7 lore raw

Re: [Patch](Resend) mm/sparse.c: Improve the error handling for sparse_add_one_section()

mm/sparse.c int sparse_add_one_section(struct zone * · line 424

Quoted 11 lines
mm/sparse.c +1 -1
 	ret = sparse_init_one_section(ms, section_nr, memmap, usemap);
@@ -414,7 +418,7 @@ int sparse_add_one_section(struct zone *
 out:
 	pgdat_resize_unlock(pgdat, &flags);
 	if (ret <= 0)
-		__kfree_section_memmap(memmap, nr_pages);
+		kfree(usemap);
 	return ret;
 }
 #endif

I guess you think __kfree_section_memmap() is not necessary due to no implementation. But, it is still available when CONFIG_SPARSEMEM_VMEMMAP is off. So, it should not be removed.

Bye.

Signature · 8 lines
Yasunori Goto 


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#8 lore raw

Re: [Patch](Resend) mm/sparse.c: Improve the error handling for sparse_add_one_section()

In reply to WANG Cong

mm/sparse.c int sparse_add_one_section(struct zone * · line 424

Quoted 10 lines · WANG Cong
mm/sparse.c +1 -1
@@ -414,7 +418,7 @@ int sparse_add_one_section(struct zone *
 out:
        pgdat_resize_unlock(pgdat, &flags);
        if (ret <= 0)
-               __kfree_section_memmap(memmap, nr_pages);
+               kfree(usemap);
        return ret;
 }
 #endif 

Why did you get rid of the memmap free here? A bad return from sparse_init_one_section() indicates that we didn't use the memmap, so it will leak otherwise.

-- Dave

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#9 lore raw

Re: [Patch](Resend) mm/sparse.c: Improve the error handling for sparse_add_one_section()

Quoted 15 lines · Dave Hansen

Review int sparse_add_one_section(struct zone * · line 424

Quoted 10 lines · WANG Cong
(quoted diff) +1 -1
@@ -414,7 +418,7 @@ int sparse_add_one_section(struct zone *
 out:
        pgdat_resize_unlock(pgdat, &flags);
        if (ret <= 0)
-               __kfree_section_memmap(memmap, nr_pages);
+               kfree(usemap);
        return ret;
 }
 #endif 

Why did you get rid of the memmap free here? A bad return from sparse_init_one_section() indicates that we didn't use the memmap, so it will leak otherwise.

Sorry, I was confused by the recursion. This one should be OK.

Thanks.

Improve the error handling for mm/sparse.c::sparse_add_one_section(). And I see no reason to check 'usemap' until holding the 'pgdat_resize_lock'.

Cc Christoph Lameter <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Rik van Riel <[email protected]>
Cc Yasunori Goto <[email protected]>
Cc Andy Whitcroft <[email protected]>

---

mm/sparse.c +12 -6
Index: linux-2.6/mm/sparse.c
===================================================================
@@ -391,9 +391,17 @@ int sparse_add_one_section(struct zone *
 	 * no locking for this, because it does its own
 	 * plus, it does a kmalloc
 	 */
-	sparse_index_init(section_nr, pgdat->node_id);
+	ret = sparse_index_init(section_nr, pgdat->node_id);
+	if (ret < 0)
+		return ret;
 	memmap = kmalloc_section_memmap(section_nr, pgdat->node_id, nr_pages);
+	if (!memmap)
+		return -ENOMEM;
 	usemap = __kmalloc_section_usemap();
+	if (!usemap) {
+		__kfree_section_memmap(memmap, nr_pages);
+		return -ENOMEM;
+	}
 
 	pgdat_resize_lock(pgdat, &flags);
 
@@ -403,18 +411,16 @@ int sparse_add_one_section(struct zone *
 		goto out;
 	}
 
-	if (!usemap) {
-		ret = -ENOMEM;
-		goto out;
-	}
 	ms->section_mem_map |= SECTION_MARKED_PRESENT;
 
 	ret = sparse_init_one_section(ms, section_nr, memmap, usemap);
 
 out:
 	pgdat_resize_unlock(pgdat, &flags);
-	if (ret <= 0)
+	if (ret <= 0) {
+		kfree(usemap);
 		__kfree_section_memmap(memmap, nr_pages);
+	}
 	return ret;
 }
 #endif

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

Acked-by
#10 lore raw

Re: [Patch](Resend) mm/sparse.c: Improve the error handling for sparse_add_one_section()

Looks good to me.

Thanks.

Quoted 79 lines · Dave Hansen
Quoted 15 lines · WANG Cong

mm/sparse.c int sparse_add_one_section(struct zone * · line 424

Quoted 10 lines
mm/sparse.c +1 -1
@@ -414,7 +418,7 @@ int sparse_add_one_section(struct zone *
 out:
        pgdat_resize_unlock(pgdat, &flags);
        if (ret <= 0)
-               __kfree_section_memmap(memmap, nr_pages);
+               kfree(usemap);
        return ret;
 }
 #endif 

Why did you get rid of the memmap free here? A bad return from sparse_init_one_section() indicates that we didn't use the memmap, so it will leak otherwise.

Sorry, I was confused by the recursion. This one should be OK.

Thanks.

Improve the error handling for mm/sparse.c::sparse_add_one_section(). And I see no reason to check 'usemap' until holding the 'pgdat_resize_lock'.

Cc Christoph Lameter <[email protected]>
Cc Dave Hansen <[email protected]>
Cc Rik van Riel <[email protected]>
Cc Yasunori Goto <[email protected]>
Cc Andy Whitcroft <[email protected]>

---
Index: linux-2.6/mm/sparse.c
===================================================================

mm/sparse.c +12 -6
@@ -391,9 +391,17 @@ int sparse_add_one_section(struct zone *
 	 * no locking for this, because it does its own
 	 * plus, it does a kmalloc
 	 */
-	sparse_index_init(section_nr, pgdat->node_id);
+	ret = sparse_index_init(section_nr, pgdat->node_id);
+	if (ret < 0)
+		return ret;
 	memmap = kmalloc_section_memmap(section_nr, pgdat->node_id, nr_pages);
+	if (!memmap)
+		return -ENOMEM;
 	usemap = __kmalloc_section_usemap();
+	if (!usemap) {
+		__kfree_section_memmap(memmap, nr_pages);
+		return -ENOMEM;
+	}
 
 	pgdat_resize_lock(pgdat, &flags);
 
@@ -403,18 +411,16 @@ int sparse_add_one_section(struct zone *
 		goto out;
 	}
 
-	if (!usemap) {
-		ret = -ENOMEM;
-		goto out;
-	}
 	ms->section_mem_map |= SECTION_MARKED_PRESENT;
 
 	ret = sparse_init_one_section(ms, section_nr, memmap, usemap);
 
 out:
 	pgdat_resize_unlock(pgdat, &flags);
-	if (ret <= 0)
+	if (ret <= 0) {
+		kfree(usemap);
 		__kfree_section_memmap(memmap, nr_pages);
+	}
 	return ret;
 }
 #endif
Signature · 8 lines
Yasunori Goto 


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>