diff options
| -rw-r--r-- | drivers/video/fb_defio.c | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 24843fdd5395..59df132cc375 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c | |||
| @@ -74,6 +74,7 @@ static int fb_deferred_io_mkwrite(struct vm_area_struct *vma, | |||
| 74 | { | 74 | { |
| 75 | struct fb_info *info = vma->vm_private_data; | 75 | struct fb_info *info = vma->vm_private_data; |
| 76 | struct fb_deferred_io *fbdefio = info->fbdefio; | 76 | struct fb_deferred_io *fbdefio = info->fbdefio; |
| 77 | struct page *cur; | ||
| 77 | 78 | ||
| 78 | /* this is a callback we get when userspace first tries to | 79 | /* this is a callback we get when userspace first tries to |
| 79 | write to the page. we schedule a workqueue. that workqueue | 80 | write to the page. we schedule a workqueue. that workqueue |
| @@ -83,7 +84,24 @@ static int fb_deferred_io_mkwrite(struct vm_area_struct *vma, | |||
| 83 | 84 | ||
| 84 | /* protect against the workqueue changing the page list */ | 85 | /* protect against the workqueue changing the page list */ |
| 85 | mutex_lock(&fbdefio->lock); | 86 | mutex_lock(&fbdefio->lock); |
| 86 | list_add(&page->lru, &fbdefio->pagelist); | 87 | |
| 88 | /* we loop through the pagelist before adding in order | ||
| 89 | to keep the pagelist sorted */ | ||
| 90 | list_for_each_entry(cur, &fbdefio->pagelist, lru) { | ||
| 91 | /* this check is to catch the case where a new | ||
| 92 | process could start writing to the same page | ||
| 93 | through a new pte. this new access can cause the | ||
| 94 | mkwrite even when the original ps's pte is marked | ||
| 95 | writable */ | ||
| 96 | if (unlikely(cur == page)) | ||
| 97 | goto page_already_added; | ||
| 98 | else if (cur->index > page->index) | ||
| 99 | break; | ||
| 100 | } | ||
| 101 | |||
| 102 | list_add_tail(&page->lru, &cur->lru); | ||
| 103 | |||
| 104 | page_already_added: | ||
| 87 | mutex_unlock(&fbdefio->lock); | 105 | mutex_unlock(&fbdefio->lock); |
| 88 | 106 | ||
| 89 | /* come back after delay to process the deferred IO */ | 107 | /* come back after delay to process the deferred IO */ |
