| From jejb@kernel.org Tue Sep 2 17:09:21 2008 |
| From: Ian Campbell <ijc@hellion.org.uk> |
| Date: Wed, 20 Aug 2008 22:50:11 GMT |
| Subject: fbdefio: add set_page_dirty handler to deferred IO FB |
| To: jejb@kernel.org, stable@kernel.org |
| Message-ID: <200808202250.m7KMoAHT016246@hera.kernel.org> |
| |
| From: Ian Campbell <ijc@hellion.org.uk> |
| |
| commit d847471d063663b9f36927d265c66a270c0cfaab upstream |
| |
| Fixes kernel BUG at lib/radix-tree.c:473. |
| |
| Previously the handler was incidentally provided by tmpfs but this was |
| removed with: |
| |
| commit 14fcc23fdc78e9d32372553ccf21758a9bd56fa1 |
| Author: Hugh Dickins <hugh@veritas.com> |
| Date: Mon Jul 28 15:46:19 2008 -0700 |
| |
| tmpfs: fix kernel BUG in shmem_delete_inode |
| |
| relying on this behaviour was incorrect in any case and the BUG also |
| appeared when the device node was on an ext3 filesystem. |
| |
| v2: override a_ops at open() time rather than mmap() time to minimise |
| races per AKPM's concerns. |
| |
| Signed-off-by: Ian Campbell <ijc@hellion.org.uk> |
| Cc: Jaya Kumar <jayakumar.lkml@gmail.com> |
| Cc: Nick Piggin <npiggin@suse.de> |
| Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> |
| Cc: Hugh Dickins <hugh@veritas.com> |
| Cc: Johannes Weiner <hannes@saeurebad.de> |
| Cc: Jeremy Fitzhardinge <jeremy@goop.org> |
| Cc: Kel Modderman <kel@otaku42.de> |
| Cc: Markus Armbruster <armbru@redhat.com> |
| Cc: Krzysztof Helt <krzysztof.h1@poczta.fm> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/video/fb_defio.c | 19 +++++++++++++++++++ |
| drivers/video/fbmem.c | 4 ++++ |
| include/linux/fb.h | 3 +++ |
| 3 files changed, 26 insertions(+) |
| |
| --- a/drivers/video/fb_defio.c |
| +++ b/drivers/video/fb_defio.c |
| @@ -114,6 +114,17 @@ static struct vm_operations_struct fb_de |
| .page_mkwrite = fb_deferred_io_mkwrite, |
| }; |
| |
| +static int fb_deferred_io_set_page_dirty(struct page *page) |
| +{ |
| + if (!PageDirty(page)) |
| + SetPageDirty(page); |
| + return 0; |
| +} |
| + |
| +static const struct address_space_operations fb_deferred_io_aops = { |
| + .set_page_dirty = fb_deferred_io_set_page_dirty, |
| +}; |
| + |
| static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma) |
| { |
| vma->vm_ops = &fb_deferred_io_vm_ops; |
| @@ -163,6 +174,14 @@ void fb_deferred_io_init(struct fb_info |
| } |
| EXPORT_SYMBOL_GPL(fb_deferred_io_init); |
| |
| +void fb_deferred_io_open(struct fb_info *info, |
| + struct inode *inode, |
| + struct file *file) |
| +{ |
| + file->f_mapping->a_ops = &fb_deferred_io_aops; |
| +} |
| +EXPORT_SYMBOL_GPL(fb_deferred_io_open); |
| + |
| void fb_deferred_io_cleanup(struct fb_info *info) |
| { |
| void *screen_base = (void __force *) info->screen_base; |
| --- a/drivers/video/fbmem.c |
| +++ b/drivers/video/fbmem.c |
| @@ -1315,6 +1315,10 @@ fb_open(struct inode *inode, struct file |
| if (res) |
| module_put(info->fbops->owner); |
| } |
| +#ifdef CONFIG_FB_DEFERRED_IO |
| + if (info->fbdefio) |
| + fb_deferred_io_open(info, inode, file); |
| +#endif |
| return res; |
| } |
| |
| --- a/include/linux/fb.h |
| +++ b/include/linux/fb.h |
| @@ -966,6 +966,9 @@ static inline void __fb_pad_aligned_buff |
| |
| /* drivers/video/fb_defio.c */ |
| extern void fb_deferred_io_init(struct fb_info *info); |
| +extern void fb_deferred_io_open(struct fb_info *info, |
| + struct inode *inode, |
| + struct file *file); |
| extern void fb_deferred_io_cleanup(struct fb_info *info); |
| extern int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, |
| int datasync); |