diff options
Diffstat (limited to 'drivers/video/fb_defio.c')
-rw-r--r-- | drivers/video/fb_defio.c | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 137100ea8ad7..6b93ef93cb12 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c | |||
@@ -100,6 +100,16 @@ static int fb_deferred_io_mkwrite(struct vm_area_struct *vma, | |||
100 | /* protect against the workqueue changing the page list */ | 100 | /* protect against the workqueue changing the page list */ |
101 | mutex_lock(&fbdefio->lock); | 101 | mutex_lock(&fbdefio->lock); |
102 | 102 | ||
103 | /* | ||
104 | * We want the page to remain locked from ->page_mkwrite until | ||
105 | * the PTE is marked dirty to avoid page_mkclean() being called | ||
106 | * before the PTE is updated, which would leave the page ignored | ||
107 | * by defio. | ||
108 | * Do this by locking the page here and informing the caller | ||
109 | * about it with VM_FAULT_LOCKED. | ||
110 | */ | ||
111 | lock_page(page); | ||
112 | |||
103 | /* we loop through the pagelist before adding in order | 113 | /* we loop through the pagelist before adding in order |
104 | to keep the pagelist sorted */ | 114 | to keep the pagelist sorted */ |
105 | list_for_each_entry(cur, &fbdefio->pagelist, lru) { | 115 | list_for_each_entry(cur, &fbdefio->pagelist, lru) { |
@@ -121,7 +131,7 @@ page_already_added: | |||
121 | 131 | ||
122 | /* come back after delay to process the deferred IO */ | 132 | /* come back after delay to process the deferred IO */ |
123 | schedule_delayed_work(&info->deferred_work, fbdefio->delay); | 133 | schedule_delayed_work(&info->deferred_work, fbdefio->delay); |
124 | return 0; | 134 | return VM_FAULT_LOCKED; |
125 | } | 135 | } |
126 | 136 | ||
127 | static const struct vm_operations_struct fb_deferred_io_vm_ops = { | 137 | static const struct vm_operations_struct fb_deferred_io_vm_ops = { |