diff options
author | Hugh Dickins <hugh@veritas.com> | 2005-10-29 21:15:53 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-10-30 00:40:36 -0400 |
commit | 0c942a4539c09adf09097315cc174aefd0eeedf7 (patch) | |
tree | b9b7d5093ca0a130ef2221f8932fabcf4291f6a6 | |
parent | e040f218bb49a6965a5b77edce05fe47a62dda39 (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>
-rw-r--r-- | mm/msync.c | 38 |
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 | ||
31 | again: | ||
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 | ||
53 | static inline void msync_pmd_range(struct vm_area_struct *vma, pud_t *pud, | 66 | static 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 | ||
110 | static 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 | ||
125 | static 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; |