Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fbdev: bugfix for multiprocess defio

This patch is a bugfix for how defio handles multiple processes manipulating
the same framebuffer.

Thanks to Bernard Blackham for identifying this bug.

It occurs when two applications mmap the same framebuffer and concurrently
write to the same page. Normally, this doesn't occur since only a single
process mmaps the framebuffer. The symptom of the bug is that the mapping
applications will hang. The cause is that defio incorrectly tries to add the
same page twice to the pagelist. The solution I have is to walk the pagelist
and check for a duplicate before adding. Since I needed to walk the pagelist,
I now also keep the pagelist in sorted order.

Signed-off-by: Jaya Kumar <jayakumar.lkml@gmail.com>
Cc: Bernard Blackham <bernard@largestprime.net>
Cc: <stable@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Jaya Kumar and committed by
Linus Torvalds
f31ad92f 4fc89e39

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