Clean up and make try_to_free_buffers() not race with dirty pages
This is preparatory work in our continuing saga on some hard-to-trigger
file corruption with shared writable mmap() after the dirty page
tracking changes (commit d08b3851da etc)
were merged.
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
			
			
This commit is contained in:
		
							
								
								
									
										18
									
								
								fs/buffer.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								fs/buffer.c
									
									
									
									
									
								
							| @@ -2834,7 +2834,7 @@ int try_to_free_buffers(struct page *page) | ||||
| 	int ret = 0; | ||||
|  | ||||
| 	BUG_ON(!PageLocked(page)); | ||||
| 	if (PageWriteback(page)) | ||||
| 	if (PageDirty(page) || PageWriteback(page)) | ||||
| 		return 0; | ||||
|  | ||||
| 	if (mapping == NULL) {		/* can this still happen? */ | ||||
| @@ -2845,22 +2845,6 @@ int try_to_free_buffers(struct page *page) | ||||
| 	spin_lock(&mapping->private_lock); | ||||
| 	ret = drop_buffers(page, &buffers_to_free); | ||||
| 	spin_unlock(&mapping->private_lock); | ||||
| 	if (ret) { | ||||
| 		/* | ||||
| 		 * If the filesystem writes its buffers by hand (eg ext3) | ||||
| 		 * then we can have clean buffers against a dirty page.  We | ||||
| 		 * clean the page here; otherwise later reattachment of buffers | ||||
| 		 * could encounter a non-uptodate page, which is unresolvable. | ||||
| 		 * This only applies in the rare case where try_to_free_buffers | ||||
| 		 * succeeds but the page is not freed. | ||||
| 		 * | ||||
| 		 * Also, during truncate, discard_buffer will have marked all | ||||
| 		 * the page's buffers clean.  We discover that here and clean | ||||
| 		 * the page also. | ||||
| 		 */ | ||||
| 		if (test_clear_page_dirty(page)) | ||||
| 			task_io_account_cancelled_write(PAGE_CACHE_SIZE); | ||||
| 	} | ||||
| out: | ||||
| 	if (buffers_to_free) { | ||||
| 		struct buffer_head *bh = buffers_to_free; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user