2323#include <linux/rmap.h>
2424#include <linux/pagemap.h>
2525
26+ /*
27+ * struct fb_deferred_io_state
28+ */
29+
30+ struct fb_deferred_io_state {
31+ struct kref ref ;
32+
33+ struct mutex lock ; /* mutex that protects the pageref list */
34+ /* fields protected by lock */
35+ struct fb_info * info ;
36+ };
37+
38+ static struct fb_deferred_io_state * fb_deferred_io_state_alloc (void )
39+ {
40+ struct fb_deferred_io_state * fbdefio_state ;
41+
42+ fbdefio_state = kzalloc (sizeof (* fbdefio_state ), GFP_KERNEL );
43+ if (!fbdefio_state )
44+ return NULL ;
45+
46+ kref_init (& fbdefio_state -> ref );
47+ mutex_init (& fbdefio_state -> lock );
48+
49+ return fbdefio_state ;
50+ }
51+
52+ static void fb_deferred_io_state_release (struct fb_deferred_io_state * fbdefio_state )
53+ {
54+ mutex_destroy (& fbdefio_state -> lock );
55+
56+ kfree (fbdefio_state );
57+ }
58+
59+ static void fb_deferred_io_state_get (struct fb_deferred_io_state * fbdefio_state )
60+ {
61+ kref_get (& fbdefio_state -> ref );
62+ }
63+
64+ static void __fb_deferred_io_state_release (struct kref * ref )
65+ {
66+ struct fb_deferred_io_state * fbdefio_state =
67+ container_of (ref , struct fb_deferred_io_state , ref );
68+
69+ fb_deferred_io_state_release (fbdefio_state );
70+ }
71+
72+ static void fb_deferred_io_state_put (struct fb_deferred_io_state * fbdefio_state )
73+ {
74+ kref_put (& fbdefio_state -> ref , __fb_deferred_io_state_release );
75+ }
76+
77+ /*
78+ * struct vm_operations_struct
79+ */
80+
81+ static void fb_deferred_io_vm_open (struct vm_area_struct * vma )
82+ {
83+ struct fb_deferred_io_state * fbdefio_state = vma -> vm_private_data ;
84+
85+ fb_deferred_io_state_get (fbdefio_state );
86+ }
87+
88+ static void fb_deferred_io_vm_close (struct vm_area_struct * vma )
89+ {
90+ struct fb_deferred_io_state * fbdefio_state = vma -> vm_private_data ;
91+
92+ fb_deferred_io_state_put (fbdefio_state );
93+ }
94+
2695static struct page * fb_deferred_io_page (struct fb_info * info , unsigned long offs )
2796{
2897 void * screen_base = (void __force * ) info -> screen_base ;
@@ -93,17 +162,31 @@ static void fb_deferred_io_pageref_put(struct fb_deferred_io_pageref *pageref,
93162/* this is to find and return the vmalloc-ed fb pages */
94163static vm_fault_t fb_deferred_io_fault (struct vm_fault * vmf )
95164{
165+ struct fb_info * info ;
96166 unsigned long offset ;
97167 struct page * page ;
98- struct fb_info * info = vmf -> vma -> vm_private_data ;
168+ vm_fault_t ret ;
169+ struct fb_deferred_io_state * fbdefio_state = vmf -> vma -> vm_private_data ;
170+
171+ mutex_lock (& fbdefio_state -> lock );
172+
173+ info = fbdefio_state -> info ;
174+ if (!info ) {
175+ ret = VM_FAULT_SIGBUS ; /* our device is gone */
176+ goto err_mutex_unlock ;
177+ }
99178
100179 offset = vmf -> pgoff << PAGE_SHIFT ;
101- if (offset >= info -> fix .smem_len )
102- return VM_FAULT_SIGBUS ;
180+ if (offset >= info -> fix .smem_len ) {
181+ ret = VM_FAULT_SIGBUS ;
182+ goto err_mutex_unlock ;
183+ }
103184
104185 page = fb_deferred_io_page (info , offset );
105- if (!page )
106- return VM_FAULT_SIGBUS ;
186+ if (!page ) {
187+ ret = VM_FAULT_SIGBUS ;
188+ goto err_mutex_unlock ;
189+ }
107190
108191 get_page (page );
109192
@@ -115,8 +198,15 @@ static vm_fault_t fb_deferred_io_fault(struct vm_fault *vmf)
115198 BUG_ON (!page -> mapping );
116199 page -> index = vmf -> pgoff ; /* for page_mkclean() */
117200
201+ mutex_unlock (& fbdefio_state -> lock );
202+
118203 vmf -> page = page ;
204+
119205 return 0 ;
206+
207+ err_mutex_unlock :
208+ mutex_unlock (& fbdefio_state -> lock );
209+ return ret ;
120210}
121211
122212int fb_deferred_io_fsync (struct file * file , loff_t start , loff_t end , int datasync )
@@ -143,15 +233,24 @@ EXPORT_SYMBOL_GPL(fb_deferred_io_fsync);
143233 * Adds a page to the dirty list. Call this from struct
144234 * vm_operations_struct.page_mkwrite.
145235 */
146- static vm_fault_t fb_deferred_io_track_page (struct fb_info * info , unsigned long offset ,
147- struct page * page )
236+ static vm_fault_t fb_deferred_io_track_page (struct fb_deferred_io_state * fbdefio_state ,
237+ unsigned long offset , struct page * page )
148238{
149- struct fb_deferred_io * fbdefio = info -> fbdefio ;
239+ struct fb_info * info ;
240+ struct fb_deferred_io * fbdefio ;
150241 struct fb_deferred_io_pageref * pageref ;
151242 vm_fault_t ret ;
152243
153244 /* protect against the workqueue changing the page list */
154- mutex_lock (& fbdefio -> lock );
245+ mutex_lock (& fbdefio_state -> lock );
246+
247+ info = fbdefio_state -> info ;
248+ if (!info ) {
249+ ret = VM_FAULT_SIGBUS ; /* our device is gone */
250+ goto err_mutex_unlock ;
251+ }
252+
253+ fbdefio = info -> fbdefio ;
155254
156255 pageref = fb_deferred_io_pageref_get (info , offset , page );
157256 if (WARN_ON_ONCE (!pageref )) {
@@ -169,50 +268,38 @@ static vm_fault_t fb_deferred_io_track_page(struct fb_info *info, unsigned long
169268 */
170269 lock_page (pageref -> page );
171270
172- mutex_unlock (& fbdefio -> lock );
271+ mutex_unlock (& fbdefio_state -> lock );
173272
174273 /* come back after delay to process the deferred IO */
175274 schedule_delayed_work (& info -> deferred_work , fbdefio -> delay );
176275 return VM_FAULT_LOCKED ;
177276
178277err_mutex_unlock :
179- mutex_unlock (& fbdefio -> lock );
278+ mutex_unlock (& fbdefio_state -> lock );
180279 return ret ;
181280}
182281
183- /*
184- * fb_deferred_io_page_mkwrite - Mark a page as written for deferred I/O
185- * @fb_info: The fbdev info structure
186- * @vmf: The VM fault
187- *
188- * This is a callback we get when userspace first tries to
189- * write to the page. We schedule a workqueue. That workqueue
190- * will eventually mkclean the touched pages and execute the
191- * deferred framebuffer IO. Then if userspace touches a page
192- * again, we repeat the same scheme.
193- *
194- * Returns:
195- * VM_FAULT_LOCKED on success, or a VM_FAULT error otherwise.
196- */
197- static vm_fault_t fb_deferred_io_page_mkwrite (struct fb_info * info , struct vm_fault * vmf )
282+ static vm_fault_t fb_deferred_io_page_mkwrite (struct fb_deferred_io_state * fbdefio_state ,
283+ struct vm_fault * vmf )
198284{
199285 unsigned long offset = vmf -> pgoff << PAGE_SHIFT ;
200286 struct page * page = vmf -> page ;
201287
202288 file_update_time (vmf -> vma -> vm_file );
203289
204- return fb_deferred_io_track_page (info , offset , page );
290+ return fb_deferred_io_track_page (fbdefio_state , offset , page );
205291}
206292
207- /* vm_ops->page_mkwrite handler */
208293static vm_fault_t fb_deferred_io_mkwrite (struct vm_fault * vmf )
209294{
210- struct fb_info * info = vmf -> vma -> vm_private_data ;
295+ struct fb_deferred_io_state * fbdefio_state = vmf -> vma -> vm_private_data ;
211296
212- return fb_deferred_io_page_mkwrite (info , vmf );
297+ return fb_deferred_io_page_mkwrite (fbdefio_state , vmf );
213298}
214299
215300static const struct vm_operations_struct fb_deferred_io_vm_ops = {
301+ .open = fb_deferred_io_vm_open ,
302+ .close = fb_deferred_io_vm_close ,
216303 .fault = fb_deferred_io_fault ,
217304 .page_mkwrite = fb_deferred_io_mkwrite ,
218305};
@@ -227,7 +314,10 @@ int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma)
227314 vm_flags_set (vma , VM_DONTEXPAND | VM_DONTDUMP );
228315 if (!(info -> flags & FBINFO_VIRTFB ))
229316 vm_flags_set (vma , VM_IO );
230- vma -> vm_private_data = info ;
317+ vma -> vm_private_data = info -> fbdefio_state ;
318+
319+ fb_deferred_io_state_get (info -> fbdefio_state ); /* released in vma->vm_ops->close() */
320+
231321 return 0 ;
232322}
233323EXPORT_SYMBOL_GPL (fb_deferred_io_mmap );
@@ -238,9 +328,10 @@ static void fb_deferred_io_work(struct work_struct *work)
238328 struct fb_info * info = container_of (work , struct fb_info , deferred_work .work );
239329 struct fb_deferred_io_pageref * pageref , * next ;
240330 struct fb_deferred_io * fbdefio = info -> fbdefio ;
331+ struct fb_deferred_io_state * fbdefio_state = info -> fbdefio_state ;
241332
242333 /* here we mkclean the pages, then do all deferred IO */
243- mutex_lock (& fbdefio -> lock );
334+ mutex_lock (& fbdefio_state -> lock );
244335 list_for_each_entry (pageref , & fbdefio -> pagereflist , list ) {
245336 struct page * cur = pageref -> page ;
246337 lock_page (cur );
@@ -255,12 +346,13 @@ static void fb_deferred_io_work(struct work_struct *work)
255346 list_for_each_entry_safe (pageref , next , & fbdefio -> pagereflist , list )
256347 fb_deferred_io_pageref_put (pageref , info );
257348
258- mutex_unlock (& fbdefio -> lock );
349+ mutex_unlock (& fbdefio_state -> lock );
259350}
260351
261352int fb_deferred_io_init (struct fb_info * info )
262353{
263354 struct fb_deferred_io * fbdefio = info -> fbdefio ;
355+ struct fb_deferred_io_state * fbdefio_state ;
264356 struct fb_deferred_io_pageref * pagerefs ;
265357 unsigned long npagerefs , i ;
266358 int ret ;
@@ -270,7 +362,11 @@ int fb_deferred_io_init(struct fb_info *info)
270362 if (WARN_ON (!info -> fix .smem_len ))
271363 return - EINVAL ;
272364
273- mutex_init (& fbdefio -> lock );
365+ fbdefio_state = fb_deferred_io_state_alloc ();
366+ if (!fbdefio_state )
367+ return - ENOMEM ;
368+ fbdefio_state -> info = info ;
369+
274370 INIT_DELAYED_WORK (& info -> deferred_work , fb_deferred_io_work );
275371 INIT_LIST_HEAD (& fbdefio -> pagereflist );
276372 if (fbdefio -> delay == 0 ) /* set a default of 1 s */
@@ -289,10 +385,12 @@ int fb_deferred_io_init(struct fb_info *info)
289385 info -> npagerefs = npagerefs ;
290386 info -> pagerefs = pagerefs ;
291387
388+ info -> fbdefio_state = fbdefio_state ;
389+
292390 return 0 ;
293391
294392err :
295- mutex_destroy ( & fbdefio -> lock );
393+ fb_deferred_io_state_release ( fbdefio_state );
296394 return ret ;
297395}
298396EXPORT_SYMBOL_GPL (fb_deferred_io_init );
@@ -333,11 +431,18 @@ EXPORT_SYMBOL_GPL(fb_deferred_io_release);
333431
334432void fb_deferred_io_cleanup (struct fb_info * info )
335433{
336- struct fb_deferred_io * fbdefio = info -> fbdefio ;
434+ struct fb_deferred_io_state * fbdefio_state = info -> fbdefio_state ;
337435
338436 fb_deferred_io_lastclose (info );
339437
438+ info -> fbdefio_state = NULL ;
439+
440+ mutex_lock (& fbdefio_state -> lock );
441+ fbdefio_state -> info = NULL ;
442+ mutex_unlock (& fbdefio_state -> lock );
443+
444+ fb_deferred_io_state_put (fbdefio_state );
445+
340446 kvfree (info -> pagerefs );
341- mutex_destroy (& fbdefio -> lock );
342447}
343448EXPORT_SYMBOL_GPL (fb_deferred_io_cleanup );
0 commit comments