Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Kernel v2.4.22 /mm/vmalloc.c

Filename:/mm/vmalloc.c
Lines Added:57
Lines Deleted:10
Also changed in: (Previous) 2.4.22-rc4  2.4.22-rc3  2.4.22-rc2-ac3  2.4.22-rc2-ac2  2.4.22-rc2-ac1  2.4.22-rc1-ac1 
(Following) 2.4.22-ac1  2.4.22-ac2  2.4.22-ac3  2.4.22-ac4  2.4.26-pre2  2.4.26-pre3 

Location
[  2.4.22
  [  mm
     o  vmalloc.c

Patch

diff -urN linux-2.4.21/mm/vmalloc.c linux-2.4.22/mm/vmalloc.c
--- linux-2.4.21/mm/vmalloc.c   2003-06-13 07:51:39.000000000 -0700
+++ linux-2.4.22/mm/vmalloc.c   2003-08-25 04:44:44.000000000 -0700
@@ -93,7 +93,8 @@
 }
 
 static inline int alloc_area_pte (pte_t * pte, unsigned long address,
-         unsigned long size, int gfp_mask, pgprot_t prot)
+         unsigned long size, int gfp_mask,
+         pgprot_t prot, struct page ***pages)
 {
    unsigned long end;
 
@@ -103,9 +104,20 @@
       end = PMD_SIZE;
    do {
       struct page * page;
-      spin_unlock(&init_mm.page_table_lock);
-      page = alloc_page(gfp_mask);
-      spin_lock(&init_mm.page_table_lock);
+
+      if (!pages) {
+         spin_unlock(&init_mm.page_table_lock);
+         page = alloc_page(gfp_mask);
+         spin_lock(&init_mm.page_table_lock);
+      } else {
+         page = (**pages);
+         (*pages)++;
+
+         /* Add a reference to the page so we can free later */
+         if (page)
+            atomic_inc(&page->count);
+
+      }
       if (!pte_none(*pte))
          printk(KERN_ERR "alloc_area_pte: page already exists\n");
       if (!page)
@@ -117,7 +129,9 @@
    return 0;
 }
 
-static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, int gfp_mask, pgprot_t prot)
+static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address,
+         unsigned long size, int gfp_mask,
+         pgprot_t prot, struct page ***pages)
 {
    unsigned long end;
 
@@ -129,7 +143,8 @@
       pte_t * pte = pte_alloc(&init_mm, pmd, address);
       if (!pte)
          return -ENOMEM;
-      if (alloc_area_pte(pte, address, end - address, gfp_mask, prot))
+      if (alloc_area_pte(pte, address, end - address,
+               gfp_mask, prot, pages))
          return -ENOMEM;
       address = (address + PMD_SIZE) & PMD_MASK;
       pmd++;
@@ -137,8 +152,11 @@
    return 0;
 }
 
-inline int vmalloc_area_pages (unsigned long address, unsigned long size,
-                               int gfp_mask, pgprot_t prot)
+static inline int __vmalloc_area_pages (unsigned long address,
+               unsigned long size,
+               int gfp_mask,
+               pgprot_t prot,
+               struct page ***pages)
 {
    pgd_t * dir;
    unsigned long end = address + size;
@@ -155,7 +173,7 @@
          break;
 
       ret = -ENOMEM;
-      if (alloc_area_pmd(pmd, address, end - address, gfp_mask, prot))
+      if (alloc_area_pmd(pmd, address, end - address, gfp_mask, prot, pages))
          break;
 
       address = (address + PGDIR_SIZE) & PGDIR_MASK;
@@ -168,6 +186,12 @@
    return ret;
 }
 
+int vmalloc_area_pages(unsigned long address, unsigned long size,
+             int gfp_mask, pgprot_t prot)
+{
+   return __vmalloc_area_pages(address, size, gfp_mask, prot, NULL);
+}
+
 struct vm_struct * get_vm_area(unsigned long size, unsigned long flags)
 {
    unsigned long addr, next;
@@ -246,7 +270,30 @@
    if (!area)
       return NULL;
    addr = area->addr;
-   if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, gfp_mask, prot)) {
+   if (__vmalloc_area_pages(VMALLOC_VMADDR(addr), size, gfp_mask,
+             prot, NULL)) {
+      vfree(addr);
+      return NULL;
+   }
+   return addr;
+}
+
+void * vmap(struct page **pages, int count,
+       unsigned long flags, pgprot_t prot)
+{
+   void * addr;
+   struct vm_struct *area;
+   unsigned long size = count << PAGE_SHIFT;
+
+   if (!size || size > (max_mapnr << PAGE_SHIFT))
+      return NULL;
+   area = get_vm_area(size, flags);
+   if (!area) {
+      return NULL;
+   }
+   addr = area->addr;
+   if (__vmalloc_area_pages(VMALLOC_VMADDR(addr), size, 0,
+             prot, &pages)) {
       vfree(addr);
       return NULL;
    }


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.