fbdev/defio: Early-out if page is already enlisted
Return early if a page is already in the list of dirty pages for deferred I/O. This can be detected if the page's list head is not empty. Keep the list head initialized while the page is not enlisted to make this work reliably. v2: * update comment and fix spelling (Sam) Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220211094640.21632-2-tzimmermann@suse.de
This commit is contained in:
parent
21d26b3972
commit
105a940416
@ -59,6 +59,7 @@ static vm_fault_t fb_deferred_io_fault(struct vm_fault *vmf)
|
|||||||
printk(KERN_ERR "no mapping available\n");
|
printk(KERN_ERR "no mapping available\n");
|
||||||
|
|
||||||
BUG_ON(!page->mapping);
|
BUG_ON(!page->mapping);
|
||||||
|
INIT_LIST_HEAD(&page->lru);
|
||||||
page->index = vmf->pgoff;
|
page->index = vmf->pgoff;
|
||||||
|
|
||||||
vmf->page = page;
|
vmf->page = page;
|
||||||
@ -122,17 +123,24 @@ static vm_fault_t fb_deferred_io_mkwrite(struct vm_fault *vmf)
|
|||||||
*/
|
*/
|
||||||
lock_page(page);
|
lock_page(page);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This check is to catch the case where a new process could start
|
||||||
|
* writing to the same page through a new PTE. This new access
|
||||||
|
* can cause a call to .page_mkwrite even if the original process'
|
||||||
|
* PTE is marked writable.
|
||||||
|
*
|
||||||
|
* TODO: The lru field is owned by the page cache; hence the name.
|
||||||
|
* We dequeue in fb_deferred_io_work() after flushing the
|
||||||
|
* page's content into video memory. Instead of lru, fbdefio
|
||||||
|
* should have it's own field.
|
||||||
|
*/
|
||||||
|
if (!list_empty(&page->lru))
|
||||||
|
goto page_already_added;
|
||||||
|
|
||||||
/* we loop through the pagelist before adding in order
|
/* we loop through the pagelist before adding in order
|
||||||
to keep the pagelist sorted */
|
to keep the pagelist sorted */
|
||||||
list_for_each_entry(cur, &fbdefio->pagelist, lru) {
|
list_for_each_entry(cur, &fbdefio->pagelist, lru) {
|
||||||
/* this check is to catch the case where a new
|
if (cur->index > page->index)
|
||||||
process could start writing to the same page
|
|
||||||
through a new pte. this new access can cause the
|
|
||||||
mkwrite even when the original ps's pte is marked
|
|
||||||
writable */
|
|
||||||
if (unlikely(cur == page))
|
|
||||||
goto page_already_added;
|
|
||||||
else if (cur->index > page->index)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +202,7 @@ static void fb_deferred_io_work(struct work_struct *work)
|
|||||||
|
|
||||||
/* clear the list */
|
/* clear the list */
|
||||||
list_for_each_safe(node, next, &fbdefio->pagelist) {
|
list_for_each_safe(node, next, &fbdefio->pagelist) {
|
||||||
list_del(node);
|
list_del_init(node);
|
||||||
}
|
}
|
||||||
mutex_unlock(&fbdefio->lock);
|
mutex_unlock(&fbdefio->lock);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user