Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 2718

kernel-2.6.18-194.11.1.el5.src.rpm

From: Doug Ledford <dledford@redhat.com>
Date: Thu, 16 Jul 2009 14:10:09 -0400
Subject: [openib] mthca: fix over sized kmalloc usage
Message-id: 27677386-CB00-4315-BB5C-9B0EBC2CEF72@redhat.com
O-Subject: [Patch RHEL5.4] mthca: fix over sized kmalloc usage
Bugzilla: 508902
RH-Acked-by: Jay Fenlason <fenlason@redhat.com>

This is for bz508902.  Don't try to kmalloc > 128K allocations, use
__get_free_pages instead.  Patch provided by reporter, reviewed, built
locally, and tested by me.

commit a7f18a776785aecb5eb9967aef6f0f603b698ba0
Author: Doug Ledford <dledford@redhat.com>
Date:   Thu Jul 16 12:47:55 2009 -0400

    [mthca] Fix attempts to use kmalloc on overly large allocations

    Signed-off-by: Doug Ledford <dledford@redhat.com>

diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index d606edf..312e18d 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -152,8 +152,11 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
 		goto err_out;
 
 	for (i = 0; i <= buddy->max_order; ++i) {
-		s = BITS_TO_LONGS(1 << (buddy->max_order - i));
-		buddy->bits[i] = kmalloc(s * sizeof (long), GFP_KERNEL);
+		s = BITS_TO_LONGS(1 << (buddy->max_order - i)) * sizeof(long);
+		if(s > PAGE_SIZE)
+			buddy->bits[i] = (unsigned long *)__get_free_pages(GFP_KERNEL, get_order(s));
+		else 
+			buddy->bits[i] = kmalloc(s, GFP_KERNEL);
 		if (!buddy->bits[i])
 			goto err_out_free;
 		bitmap_zero(buddy->bits[i],
@@ -166,9 +169,13 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
 	return 0;
 
 err_out_free:
-	for (i = 0; i <= buddy->max_order; ++i)
-		kfree(buddy->bits[i]);
-
+	for (i = 0; i <= buddy->max_order; ++i){
+		s = BITS_TO_LONGS(1 << (buddy->max_order - i)) * sizeof(long);
+		if(s > PAGE_SIZE)
+			free_pages((unsigned long)buddy->bits[i], get_order(s));
+		else
+			kfree(buddy->bits[i]);
+	}
 err_out:
 	kfree(buddy->bits);
 	kfree(buddy->num_free);
@@ -178,10 +185,15 @@ err_out:
 
 static void mthca_buddy_cleanup(struct mthca_buddy *buddy)
 {
-	int i;
+	int i, s;
 
-	for (i = 0; i <= buddy->max_order; ++i)
-		kfree(buddy->bits[i]);
+	for (i = 0; i <= buddy->max_order; ++i){
+		s = BITS_TO_LONGS(1 << (buddy->max_order - i)) * sizeof(long);
+		if(s > PAGE_SIZE)
+			free_pages((unsigned long)buddy->bits[i], get_order(s));
+		else
+			kfree(buddy->bits[i]);
+	}
 
 	kfree(buddy->bits);
 	kfree(buddy->num_free);