Some ideas for memory.c pieces. Just junk like the earlier patches.

---
 mm/memory.c |  108 ++++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 66 insertions(+), 42 deletions(-)

Index: linux-2.6.21-rc7/mm/memory.c
===================================================================
--- linux-2.6.21-rc7.orig/mm/memory.c   2007-04-20 10:55:49.000000000 -0700
+++ linux-2.6.21-rc7/mm/memory.c        2007-04-20 10:56:13.000000000 -0700
@@ -368,6 +368,12 @@ static inline int is_cow_mapping(unsigne
 /*
  * This function gets the "struct page" associated with a pte.
  *
+ * NOTE! For compound pages it may get to a tail page (maybe we
+ * only deal with a portion of a compound page after all). This
+ * means that the result of vm_normal_page may not directly be
+ * used to manipulate the page state. Use compound_head() if
+ * operations (like getting a ref count) are necessary.
+ *
  * NOTE! Some mappings do not have "struct pages". A raw PFN mapping
  * will have each page table entry just pointing to a raw page frame
  * number, and as far as the VM layer is concerned, those do not have
@@ -480,9 +486,11 @@ copy_one_pte(struct mm_struct *dst_mm, s
 
        page = vm_normal_page(vma, addr, pte);
        if (page) {
-               get_page(page);
-               page_dup_rmap(page);
-               rss[!!PageAnon(page)]++;
+               struct page *head_page = compound_head(page);
+
+               get_page(head_page);
+               page_dup_rmap(head_page);
+               rss[!!PageAnon(head_page)]++;
        }
 
 out_set_pte:
@@ -642,8 +650,14 @@ static unsigned long zap_pte_range(struc
 
                if (pte_present(ptent)) {
                        struct page *page;
+                       struct page *head_page;
 
                        page = vm_normal_page(vma, addr, ptent);
+                       if (page)
+                               head_page = compound_head(page);
+                       else
+                               head_page = NULL;
+
                        if (unlikely(details) && page) {
                                /*
                                 * unmap_shared_mapping_pages() wants to
@@ -651,15 +665,15 @@ static unsigned long zap_pte_range(struc
                                 * unmap shared but keep private pages.
                                 */
                                if (details->check_mapping &&
-                                   details->check_mapping != page->mapping)
+                                   details->check_mapping != 
head_page->mapping)
                                        continue;
                                /*
                                 * Each page->index must be checked when
                                 * invalidating or truncating nonlinear.
                                 */
                                if (details->nonlinear_vma &&
-                                   (page->index < details->first_index ||
-                                    page->index > details->last_index))
+                                   (head_page->index < details->first_index ||
+                                    head_page->index > details->last_index))
                                        continue;
                        }
                        ptent = ptep_get_and_clear_full(mm, addr, pte,
@@ -668,21 +682,24 @@ static unsigned long zap_pte_range(struc
                        if (unlikely(!page))
                                continue;
                        if (unlikely(details) && details->nonlinear_vma
-                           && linear_page_index(details->nonlinear_vma,
-                                               addr) != page->index)
+                           && linear_page_index_mapping(details->nonlinear_vma,
+                                               addr, compound_order(head_page))
+                                                       != head_page->index)
                                set_pte_at(mm, addr, pte,
-                                          pgoff_to_pte(page->index));
-                       if (PageAnon(page))
+                                          pgoff_to_pte(
+                                               (head_page->index << 
compound_page(order))
+                                                       + page - head_page));
+                       if (PageAnon(head_page))
                                anon_rss--;
                        else {
                                if (pte_dirty(ptent))
-                                       set_page_dirty(page);
+                                       set_page_dirty(head_page);
                                if (pte_young(ptent))
-                                       SetPageReferenced(page);
+                                       SetPageReferenced(head_page);
                                file_rss--;
                        }
-                       page_remove_rmap(page, vma);
-                       tlb_remove_page(tlb, page);
+                       page_remove_rmap(head_page, vma);
+                       tlb_remove_page(tlb, head_page);
                        continue;
                }
                /*
@@ -899,6 +916,10 @@ unsigned long zap_page_range(struct vm_a
 
 /*
  * Do a quick page-table lookup for a single page.
+ *
+ * Note: This function may return a pointer to a tail page. However,
+ * any operations like getting a page reference and touching it will
+ * have to be performed on the head page.
  */
 struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
                        unsigned int flags)
@@ -949,13 +970,14 @@ struct page *follow_page(struct vm_area_
        if (unlikely(!page))
                goto unlock;
 
+       head_page = compound_head(page);
        if (flags & FOLL_GET)
-               get_page(page);
+               get_page(head_page);
        if (flags & FOLL_TOUCH) {
                if ((flags & FOLL_WRITE) &&
-                   !pte_dirty(pte) && !PageDirty(page))
-                       set_page_dirty(page);
-               mark_page_accessed(page);
+                   !pte_dirty(pte) && !PageDirty(head_page))
+                       set_page_dirty(head_page);
+               mark_page_accessed(head_page);
        }
 unlock:
        pte_unmap_unlock(ptep, ptl);
@@ -1537,6 +1559,7 @@ static int do_wp_page(struct mm_struct *
                spinlock_t *ptl, pte_t orig_pte)
 {
        struct page *old_page, *new_page;
+       struct page *old_page_head, *new_page_head;
        pte_t entry;
        int reuse = 0, ret = VM_FAULT_MINOR;
        struct page *dirty_page = NULL;
@@ -1545,14 +1568,15 @@ static int do_wp_page(struct mm_struct *
        if (!old_page)
                goto gotten;
 
+       old_page_head = compound_head(old_page);
        /*
         * Take out anonymous pages first, anonymous shared vmas are
         * not dirty accountable.
         */
-       if (PageAnon(old_page)) {
-               if (!TestSetPageLocked(old_page)) {
-                       reuse = can_share_swap_page(old_page);
-                       unlock_page(old_page);
+       if (PageAnon(old_page_head)) {
+               if (!TestSetPageLocked(old_page_head)) {
+                       reuse = can_share_swap_page(old_page_head);
+                       unlock_page(old_page_head);
                }
        } else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
                                        (VM_WRITE|VM_SHARED))) {
@@ -1570,10 +1594,10 @@ static int do_wp_page(struct mm_struct *
                         * We do this without the lock held, so that it can
                         * sleep if it needs to.
                         */
-                       page_cache_get(old_page);
+                       page_cache_get(old_page_head);
                        pte_unmap_unlock(page_table, ptl);
 
-                       if (vma->vm_ops->page_mkwrite(vma, old_page) < 0)
+                       if (vma->vm_ops->page_mkwrite(vma, old_page_head) < 0)
                                goto unwritable_page;
 
                        /*
@@ -1584,11 +1608,11 @@ static int do_wp_page(struct mm_struct *
                         */
                        page_table = pte_offset_map_lock(mm, pmd, address,
                                                         &ptl);
-                       page_cache_release(old_page);
+                       page_cache_release(old_page_head);
                        if (!pte_same(*page_table, orig_pte))
                                goto unlock;
                }
-               dirty_page = old_page;
+               dirty_page = old_page_head;
                get_page(dirty_page);
                reuse = 1;
        }
@@ -1607,7 +1631,7 @@ static int do_wp_page(struct mm_struct *
        /*
         * Ok, we need to copy. Oh, well..
         */
-       page_cache_get(old_page);
+       page_cache_get(old_page_head);
 gotten:
        pte_unmap_unlock(page_table, ptl);
 
@@ -1630,8 +1654,8 @@ gotten:
        page_table = pte_offset_map_lock(mm, pmd, address, &ptl);
        if (likely(pte_same(*page_table, orig_pte))) {
                if (old_page) {
-                       page_remove_rmap(old_page, vma);
-                       if (!PageAnon(old_page)) {
+                       page_remove_rmap(old_page_head, vma);
+                       if (!PageAnon(old_page_head)) {
                                dec_mm_counter(mm, file_rss);
                                inc_mm_counter(mm, anon_rss);
                        }
@@ -1654,13 +1678,13 @@ gotten:
                page_add_new_anon_rmap(new_page, vma, address);
 
                /* Free the old page.. */
-               new_page = old_page;
+               new_page = old_page_head;
                ret |= VM_FAULT_WRITE;
        }
        if (new_page)
                page_cache_release(new_page);
        if (old_page)
-               page_cache_release(old_page);
+               page_cache_release(old_page_head);
 unlock:
        pte_unmap_unlock(page_table, ptl);
        if (dirty_page) {
@@ -1669,8 +1693,8 @@ unlock:
        }
        return ret;
 oom:
-       if (old_page)
-               page_cache_release(old_page);
+       if (old_page_head)
+               page_cache_release(old_page_head);
        return VM_FAULT_OOM;
 
 unwritable_page:
@@ -2243,7 +2267,7 @@ retry:
                        if (!page)
                                goto oom;
                        copy_user_highpage(page, new_page, address, vma);
-                       page_cache_release(new_page);
+                       page_cache_release(compound_head(new_page));
                        new_page = page;
                        anon = 1;
 
@@ -2254,7 +2278,7 @@ retry:
                        if (vma->vm_ops->page_mkwrite &&
                            vma->vm_ops->page_mkwrite(vma, new_page) < 0
                            ) {
-                               page_cache_release(new_page);
+                               page_cache_release(compound_head(new_page));
                                return VM_FAULT_SIGBUS;
                        }
                }
@@ -2268,7 +2292,7 @@ retry:
         */
        if (mapping && unlikely(sequence != mapping->truncate_count)) {
                pte_unmap_unlock(page_table, ptl);
-               page_cache_release(new_page);
+               page_cache_release(compound_head(new_page));
                cond_resched();
                sequence = mapping->truncate_count;
                smp_rmb();
@@ -2298,15 +2322,15 @@ retry:
                        page_add_new_anon_rmap(new_page, vma, address);
                } else {
                        inc_mm_counter(mm, file_rss);
-                       page_add_file_rmap(new_page);
+                       page_add_file_rmap(compound_head(new_page));
                        if (write_access) {
-                               dirty_page = new_page;
+                               dirty_page = compound_head(new_page);
                                get_page(dirty_page);
                        }
                }
        } else {
                /* One of our sibling threads was faster, back out. */
-               page_cache_release(new_page);
+               page_cache_release(compound_head(new_page));
                goto unlock;
        }
 
@@ -2321,7 +2345,7 @@ unlock:
        }
        return ret;
 oom:
-       page_cache_release(new_page);
+       page_cache_release(compound_head(new_page));
        return VM_FAULT_OOM;
 }
 
@@ -2720,13 +2744,13 @@ int access_process_vm(struct task_struct
                if (write) {
                        copy_to_user_page(vma, page, addr,
                                          maddr + offset, buf, bytes);
-                       set_page_dirty_lock(page);
+                       set_page_dirty_lock(compound_head(page));
                } else {
                        copy_from_user_page(vma, page, addr,
                                            buf, maddr + offset, bytes);
                }
                kunmap(page);
-               page_cache_release(page);
+               page_cache_release(compound_head(page));
                len -= bytes;
                buf += bytes;
                addr += bytes;

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

Reply via email to