diff options
author | Ian Campbell <ijc@hellion.org.uk> | 2008-08-20 17:09:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-20 18:40:32 -0400 |
commit | d847471d063663b9f36927d265c66a270c0cfaab (patch) | |
tree | c58124be633945a548a1a16c1191ccfeb9ef3ea5 | |
parent | b42f931737bea8ca3982449d63ec46410d13e891 (diff) |
fbdefio: add set_page_dirty handler to deferred IO FB
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>
Cc: <stable@kernel.org> [14fcc23fd is in 2.6.25.14 and 2.6.26.1]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | drivers/video/fb_defio.c | 19 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 4 | ||||
-rw-r--r-- | include/linux/fb.h | 3 |
3 files changed, 26 insertions, 0 deletions
diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 59df132cc375..4835bdc4e9f1 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c | |||
@@ -114,6 +114,17 @@ static struct vm_operations_struct fb_deferred_io_vm_ops = { | |||
114 | .page_mkwrite = fb_deferred_io_mkwrite, | 114 | .page_mkwrite = fb_deferred_io_mkwrite, |
115 | }; | 115 | }; |
116 | 116 | ||
117 | static int fb_deferred_io_set_page_dirty(struct page *page) | ||
118 | { | ||
119 | if (!PageDirty(page)) | ||
120 | SetPageDirty(page); | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static const struct address_space_operations fb_deferred_io_aops = { | ||
125 | .set_page_dirty = fb_deferred_io_set_page_dirty, | ||
126 | }; | ||
127 | |||
117 | static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma) | 128 | static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma) |
118 | { | 129 | { |
119 | vma->vm_ops = &fb_deferred_io_vm_ops; | 130 | vma->vm_ops = &fb_deferred_io_vm_ops; |
@@ -163,6 +174,14 @@ void fb_deferred_io_init(struct fb_info *info) | |||
163 | } | 174 | } |
164 | EXPORT_SYMBOL_GPL(fb_deferred_io_init); | 175 | EXPORT_SYMBOL_GPL(fb_deferred_io_init); |
165 | 176 | ||
177 | void fb_deferred_io_open(struct fb_info *info, | ||
178 | struct inode *inode, | ||
179 | struct file *file) | ||
180 | { | ||
181 | file->f_mapping->a_ops = &fb_deferred_io_aops; | ||
182 | } | ||
183 | EXPORT_SYMBOL_GPL(fb_deferred_io_open); | ||
184 | |||
166 | void fb_deferred_io_cleanup(struct fb_info *info) | 185 | void fb_deferred_io_cleanup(struct fb_info *info) |
167 | { | 186 | { |
168 | void *screen_base = (void __force *) info->screen_base; | 187 | void *screen_base = (void __force *) info->screen_base; |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 6b487801eeae..98843c2ecf73 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -1344,6 +1344,10 @@ fb_open(struct inode *inode, struct file *file) | |||
1344 | if (res) | 1344 | if (res) |
1345 | module_put(info->fbops->owner); | 1345 | module_put(info->fbops->owner); |
1346 | } | 1346 | } |
1347 | #ifdef CONFIG_FB_DEFERRED_IO | ||
1348 | if (info->fbdefio) | ||
1349 | fb_deferred_io_open(info, inode, file); | ||
1350 | #endif | ||
1347 | out: | 1351 | out: |
1348 | unlock_kernel(); | 1352 | unlock_kernel(); |
1349 | return res; | 1353 | return res; |
diff --git a/include/linux/fb.h b/include/linux/fb.h index 3b8870e32afd..531ccd5f5960 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h | |||
@@ -976,6 +976,9 @@ static inline void __fb_pad_aligned_buffer(u8 *dst, u32 d_pitch, | |||
976 | 976 | ||
977 | /* drivers/video/fb_defio.c */ | 977 | /* drivers/video/fb_defio.c */ |
978 | extern void fb_deferred_io_init(struct fb_info *info); | 978 | extern void fb_deferred_io_init(struct fb_info *info); |
979 | extern void fb_deferred_io_open(struct fb_info *info, | ||
980 | struct inode *inode, | ||
981 | struct file *file); | ||
979 | extern void fb_deferred_io_cleanup(struct fb_info *info); | 982 | extern void fb_deferred_io_cleanup(struct fb_info *info); |
980 | extern int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, | 983 | extern int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, |
981 | int datasync); | 984 | int datasync); |