aboutsummaryrefslogtreecommitdiffstats
path: root/mm/msync.c
diff options
context:
space:
mode:
authorHugh Dickins <hugh@veritas.com>2005-10-29 21:15:53 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-10-30 00:40:36 -0400
commit0c942a4539c09adf09097315cc174aefd0eeedf7 (patch)
treeb9b7d5093ca0a130ef2221f8932fabcf4291f6a6 /mm/msync.c
parente040f218bb49a6965a5b77edce05fe47a62dda39 (diff)
[PATCH] mm: msync_pte_range progress
Use latency breaking in msync_pte_range like that in copy_pte_range, instead of the ugly CONFIG_PREEMPT filemap_msync alternatives. Signed-off-by: Hugh Dickins <hugh@veritas.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm/msync.c')
-rw-r--r--mm/msync.c38
1 files changed, 14 insertions, 24 deletions
diff --git a/mm/msync.c b/mm/msync.c
index 9cab3f2d5863..3b5f1c521d4b 100644
--- a/mm/msync.c
+++ b/mm/msync.c
@@ -26,12 +26,21 @@ static void msync_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
26 unsigned long addr, unsigned long end) 26 unsigned long addr, unsigned long end)
27{ 27{
28 pte_t *pte; 28 pte_t *pte;
29 int progress = 0;
29 30
31again:
30 pte = pte_offset_map(pmd, addr); 32 pte = pte_offset_map(pmd, addr);
31 do { 33 do {
32 unsigned long pfn; 34 unsigned long pfn;
33 struct page *page; 35 struct page *page;
34 36
37 if (progress >= 64) {
38 progress = 0;
39 if (need_resched() ||
40 need_lockbreak(&vma->vm_mm->page_table_lock))
41 break;
42 }
43 progress++;
35 if (!pte_present(*pte)) 44 if (!pte_present(*pte))
36 continue; 45 continue;
37 if (!pte_maybe_dirty(*pte)) 46 if (!pte_maybe_dirty(*pte))
@@ -46,8 +55,12 @@ static void msync_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
46 if (ptep_clear_flush_dirty(vma, addr, pte) || 55 if (ptep_clear_flush_dirty(vma, addr, pte) ||
47 page_test_and_clear_dirty(page)) 56 page_test_and_clear_dirty(page))
48 set_page_dirty(page); 57 set_page_dirty(page);
58 progress += 3;
49 } while (pte++, addr += PAGE_SIZE, addr != end); 59 } while (pte++, addr += PAGE_SIZE, addr != end);
50 pte_unmap(pte - 1); 60 pte_unmap(pte - 1);
61 cond_resched_lock(&vma->vm_mm->page_table_lock);
62 if (addr != end)
63 goto again;
51} 64}
52 65
53static inline void msync_pmd_range(struct vm_area_struct *vma, pud_t *pud, 66static inline void msync_pmd_range(struct vm_area_struct *vma, pud_t *pud,
@@ -106,29 +119,6 @@ static void msync_page_range(struct vm_area_struct *vma,
106 spin_unlock(&mm->page_table_lock); 119 spin_unlock(&mm->page_table_lock);
107} 120}
108 121
109#ifdef CONFIG_PREEMPT
110static inline void filemap_msync(struct vm_area_struct *vma,
111 unsigned long addr, unsigned long end)
112{
113 const size_t chunk = 64 * 1024; /* bytes */
114 unsigned long next;
115
116 do {
117 next = addr + chunk;
118 if (next > end || next < addr)
119 next = end;
120 msync_page_range(vma, addr, next);
121 cond_resched();
122 } while (addr = next, addr != end);
123}
124#else
125static inline void filemap_msync(struct vm_area_struct *vma,
126 unsigned long addr, unsigned long end)
127{
128 msync_page_range(vma, addr, end);
129}
130#endif
131
132/* 122/*
133 * MS_SYNC syncs the entire file - including mappings. 123 * MS_SYNC syncs the entire file - including mappings.
134 * 124 *
@@ -150,7 +140,7 @@ static int msync_interval(struct vm_area_struct *vma,
150 return -EBUSY; 140 return -EBUSY;
151 141
152 if (file && (vma->vm_flags & VM_SHARED)) { 142 if (file && (vma->vm_flags & VM_SHARED)) {
153 filemap_msync(vma, addr, end); 143 msync_page_range(vma, addr, end);
154 144
155 if (flags & MS_SYNC) { 145 if (flags & MS_SYNC) {
156 struct address_space *mapping = file->f_mapping; 146 struct address_space *mapping = file->f_mapping;