patch-2.4.22 linux-2.4.22/mm/vmalloc.c
Next file: linux-2.4.22/net/802/llc_sendpdu.c
Previous file: linux-2.4.22/mm/swapfile.c
Back to the patch index
Back to the overall index
- Lines: 123
- Date:
2003-08-25 04:44:44.000000000 -0700
- Orig file:
linux-2.4.21/mm/vmalloc.c
- Orig date:
2003-06-13 07:51:39.000000000 -0700
diff -urN linux-2.4.21/mm/vmalloc.c linux-2.4.22/mm/vmalloc.c
@@ -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;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)