[PATCH] swap 04/13 page_convert_anon -ENOMEM

From: Hugh Dickins (hugh@veritas.com)
Date: Tue Mar 25 2003 - 17:13:59 EST


objrmap page_convert_anon tries to allocate pte_chains, so must allow
for failure (even GFP_KERNEL can fail when OOM-killed); and move its
prototype to join the rest of the rmap.c prototypes in swap.h.

--- swap03/include/linux/rmap-locking.h Sun Mar 23 10:30:14 2003
+++ swap04/include/linux/rmap-locking.h Tue Mar 25 20:43:29 2003
@@ -45,5 +45,3 @@
         if (pte_chain)
                 __pte_chain_free(pte_chain);
 }
-
-void page_convert_anon(struct page *page);
--- swap03/include/linux/swap.h Tue Mar 25 20:43:18 2003
+++ swap04/include/linux/swap.h Tue Mar 25 20:43:29 2003
@@ -175,6 +175,8 @@
 void FASTCALL(page_remove_rmap(struct page *, pte_t *));
 int FASTCALL(try_to_unmap(struct page *));
 
+int page_convert_anon(struct page *);
+
 /* linux/mm/shmem.c */
 extern int shmem_unuse(swp_entry_t entry, struct page *page);
 #else
--- swap03/mm/fremap.c Sun Mar 23 10:30:15 2003
+++ swap04/mm/fremap.c Tue Mar 25 20:43:29 2003
@@ -69,8 +69,10 @@
         pgidx = (addr - vma->vm_start) >> PAGE_SHIFT;
         pgidx += vma->vm_pgoff;
         pgidx >>= PAGE_CACHE_SHIFT - PAGE_SHIFT;
- if (!PageAnon(page) && (page->index != pgidx))
- page_convert_anon(page);
+ if (!PageAnon(page) && (page->index != pgidx)) {
+ if (page_convert_anon(page) < 0)
+ goto err_free;
+ }
 
         pgd = pgd_offset(mm, addr);
         spin_lock(&mm->page_table_lock);
@@ -95,12 +97,10 @@
         if (flush)
                 flush_tlb_page(vma, addr);
 
- spin_unlock(&mm->page_table_lock);
- pte_chain_free(pte_chain);
- return 0;
-
+ err = 0;
 err_unlock:
         spin_unlock(&mm->page_table_lock);
+err_free:
         pte_chain_free(pte_chain);
 err:
         return err;
--- swap03/mm/rmap.c Tue Mar 25 20:42:56 2003
+++ swap04/mm/rmap.c Tue Mar 25 20:43:29 2003
@@ -774,7 +774,7 @@
  * of pte_chain structures to ensure that it can complete without releasing
  * the lock.
  */
-void page_convert_anon(struct page *page)
+int page_convert_anon(struct page *page)
 {
         struct address_space *mapping = page->mapping;
         struct vm_area_struct *vma;
@@ -783,6 +783,7 @@
         pte_addr_t pte_paddr;
         int mapcount;
         int index = 0;
+ int err = 0;
 
         if (PageAnon(page))
                 goto out;
@@ -795,6 +796,15 @@
         if (mapcount > 1) {
                 for (; index < mapcount; index += NRPTE) {
                         ptec = pte_chain_alloc(GFP_KERNEL);
+ if (!ptec) {
+ while (pte_chain) {
+ ptec = pte_chain->next;
+ pte_chain_free(pte_chain);
+ pte_chain = ptec;
+ }
+ err = -ENOMEM;
+ goto out;
+ }
                         ptec->next = pte_chain;
                         pte_chain = ptec;
                 }
@@ -867,7 +877,7 @@
         pte_chain_unlock(page);
         up(&mapping->i_shared_sem);
 out:
- return;
+ return err;
 }
 
 /**

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Mon Mar 31 2003 - 22:00:21 EST