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 9cab3f2d58..3b5f1c521d 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; |
