/usr/

2008-patch-series'>litmus2008-patch-series The LITMUS^RT kernel.Bjoern Brandenburg
aboutsummaryrefslogblamecommitdiffstats
path: root/mm/filemap.c
blob: 045b31c37653d133394146c8b49db671ea016591 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11










                                                               



                           
                          
                      
                             








                              
                              



                           
                         
                                                              
                             
                                                           

                     
  

                                                                   
                                                            
 
















                                                                      
                                                    
                                                                      

                                                             
  
             



                                                               
                                                                     




                                                                       

                                                                        
  
             









                                                     
                                                                      
  
                                 
                                                  


                                                                 
                                                                   







                                                                         



                                                                    




                                                                       
                                                          







                                                            
                                                   

                                                      
                                  











                                                                         





                                                      
                                  
 
                                           
                                       
                                             
                                             






                                      
                                                                       

          














                                                                        
                                                                             


                                                                    








                                                                   





                                                          
   
                                                                               

                                                      
                                                                
                                            
  


                                                                  
                                                                            
                                                                           


                                                                              

                                                                           



                                        
                                        

                                     











                                                                     
                                                                            







                                                          
                                                                         
                                           


                                                                            
                                        
 



                                              








                                                                        
   



                                                                        
  

                                                                    
   

                                                                             
 

                                                       


                            
 
                                  


                               




























                                                                               


                                       
                                                                     
                                                


                                                                    







                                                    
                                                               




                                                         
                    

                               











                                                                          
         
                   
 
                                      
 





                                                                  




                                                                              


                                                               
                    

                               



                                                                       

                                                                   


                                           
         
                   
 
                                            
 
   
                                                                




                                        
                                                                           

                                                                            
                                                                              
                                               
 




                                                          
                                                                     

                         
 
                                                              
                         



                                        
                                                   
                                                                             
                                     
                                           
                                                                   

                                                                      
                                                             

                                             
                                                             
                                                             

                                                 
                                         
              
                                                     
    

                     
                                        

                                                                           
                                                               
 

















                                                                               

                   
                                         
 
                  
                                          


                                                 
                                                         
         
                                   
 
                                  

      





                                           





















                                                                        
                                                    









                                                                              
                                                                       

                                                  














                                                                      
                                     






                                                                              

                                                                               
   
                                   
 


                                                  



                                      


                                                    


                                          





                                              




                                         


                                                                            
  
                                                                             



                                                                             
                                   







                                                                              
                                           





                                                                           
                                        
 



                                                                           


                                                                            
                                          





                                                                              




                                                

                                                                         
   
                                                                         
 
                     

                          























                                                                       

                    

                             
   
                                                         

                                        





                                                                         
                                                                          


                          
       
                                              
                   





                                                         
                 
                                                 
         

                    



                                                       


                                            












                                                                             
                                              
 
                          



                                              


                                                    







                                                                              




                                                 
                 
         

                    






















                                                                        



























                                                                          
 



                                  


                   
















                                                                            


















                                                                          
 
                                                                  

                              










                                                             

                        

                          
 
                                     
 







                                                             
                                                                         
                                                                     





                                                                            
































                                                                          
 

                                                   
 

                   
                                  
 




                                                                             
                                                                         







                                                                         
                                                                    

                                                          

                   
                                       



                                         
                                                                         
                                                                            




                                         

                                      

















                                                                            
                          

 
   
                                                   




                                     
                                                    
                                                                      


                                                                   
   

                                                                 
 
                                                        
                                            
                                               



                                                                   
                                 
                  
 
                                          

                                                         


                                                                                   

                                  
                                  
                             

                                      
                               

                                                     
                            
                                                          
                                                 





                                                                   
                                                           
                                                       
                                                                   
                 



                                                                               
                                                





                                                                              
        

























                                                                               








                                                                        

                                                                        
                   
                                                                 
















                                                                                
                                     







                                                          


                                                 
 
                           
                                                                  















                                                                           




                                                          
                                            
                 

                                          


                                                         


                                                            
                                                                          





                                                                 
                                                                    

                                                    



                                          












                                                                         



                                                      
                 
                                                            

                                                                   
                                                 




                                               



                              


                                          
 
                                                             
                            
 






































                                                                          






































                                                                                
   
                                                          


                                               
                                     
  



                                                   

                                                                  




                                          
                                     

                  


                                                                             


                                                                   
                            




                                              



                                                  

                                                                            



                                                                              

                                                     



                                                    
                 

         

                                             
 










                                                                         
                 

                                   



                      

                                     

                                                              
                                             



                                                                     
                                                             


                 
                                                              








                                                                        

                                                                               






                                                                      






                                                                 

                 




                                                                               


                                                                            
                                                             


                                                        
                
 









                                                                               
 
                                         
 


                                            



                             















                                                              

                                                                           

                                                                    












                                                             


                           

                                                    



                                                                




















                                                                         

                                                                       

 
   
                                                            

                                                               
  
                                                                 





                                                                              
                                                                   

                  
                                         


                                                        
                                    
                          
                     
                    
 
                                                                              
                           
                                       
 
          

                                                          

                                              
                  

                                                                   
                   

                                                                     
 




                                                         
                 






                                                              



                                            
          

                                                                           
           
                                          

                                       



                                                     
                                                                              
                                       
                                  
                                         
                                       

         
                                                          
                         
                                     
 




                                                                  
                                              














                                                                    

                                    

                  





                                                                  
                             
                                                     




                                          


                                                  
                                
 
                                                                          
                                            
                               


                             
                                                         
                                        











                                                                      
                                          

                 























                                                                               
                                                                    
                                              
                                                                   

                                           
 
                          



                                             
                                                            






                                                                              
                                                                   

                                            





                                                 


                    
                                                                     
                                              
                                                                   


                                           




                          
                                                                    
                         
                            















                                         
                                    
         
    


                                 






















                                                                                           

                                     



































                                                                                        












                                                                            
                                              


                                                                   
                                                                                      
 


                               




                                  
                                             


                                              











                                                                             
                                                                    
                            
 

                 
                                  
 
                                                         






                                                
                                       
 
                                                    


                                                            
 





                                                        
 
                     
 
                                
 
                                                          

                                                                           
                                    





                                                           
                                                                   




                               
                                   
                              




                             
                                                                            
                                                                                 












                                                                       
                                                                             








                                                                              
                                              
















                                                                       
                                                                    







                                                                              
                                       
 
                                                       
 

                                 

                                       
                                  



                                                 

                                                                        
                                                                       
                   
                                                                      
                                 
 


                                                               










                                                   
                                
 









                                                                         
 
                                                            

                                                            
 
                                          











                                                                   
                                         

  

                                                 
                                                           





                                                                                         
                                                   



                               





















                                                                         
















                                                                           







                                                                       
                   










                                                   


                              




                                    





                                                                           
                                                                
                                                                       







                                                                          
 

                                                                              


                                   








                                                                      

                                  



                                                                             

                                                        
 
                                                                                  






                                                                               
                                                              



                                                                      






                                                                          
                                 
                 
















                                                                             







                                                                          
    



                                         



                                                                           

                                                                       


                          


                                       




                                              
                                                                            

                            

                                                                           







                                         
                                           
 






                                                                      






                                                                             






























                                                                              
                                                                             



                                                                


                                                     




                                                                                
                                         







                                                                            
                                            












                                                                               















                                                                        



                                                        
                                                      
 
                                  

                                     

         



                                           




















                                                                               

                                          
                                                         


                                                             




                                


                                                                          
















                                                                               
                                     


                         
                               


                                                                   




                                                                             







                                                                          













                                                                               
 





                                                                             
                                                                                  














                                                                              



                                         

                                        










                                                                         

                                                                           

                                          
                                                    
                    


                                    
                                    
                                                                          
                                      
 
                                             

                            
                                                         
                                       





                                      









                                                                             


                                                                              
                                                                           
                                                                                
  














                                                                   
/*
 *	linux/mm/filemap.c
 *
 * Copyright (C) 1994-1999  Linus Torvalds
 */

/*
 * This file handles the generic file mmap semantics used by
 * most "normal" filesystems (but you don't /have/ to use this:
 * the NFS filesystem used to do this differently, for example)
 */
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/compiler.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/aio.h>
#include <linux/capability.h>
#include <linux/kernel_stat.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/mman.h>
#include <linux/pagemap.h>
#include <linux/file.h>
#include <linux/uio.h>
#include <linux/hash.h>
#include <linux/writeback.h>
#include <linux/backing-dev.h>
#include <linux/pagevec.h>
#include <linux/blkdev.h>
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/cpuset.h>
#include <linux/hardirq.h> /* for BUG_ON(!in_atomic()) only */
#include <linux/memcontrol.h>
#include <linux/mm_inline.h> /* for page_is_file_cache() */
#include "internal.h"

/*
 * FIXME: remove all knowledge of the buffer layer from the core VM
 */
#include <linux/buffer_head.h> /* for try_to_free_buffers */

#include <asm/mman.h>

/*
 * Shared mappings implemented 30.11.1994. It's not fully working yet,
 * though.
 *
 * Shared mappings now work. 15.8.1995  Bruno.
 *
 * finished 'unifying' the page and buffer cache and SMP-threaded the
 * page-cache, 21.05.1999, Ingo Molnar <mingo@redhat.com>
 *
 * SMP-threaded pagemap-LRU 1999, Andrea Arcangeli <andrea@suse.de>
 */

/*
 * Lock ordering:
 *
 *  ->i_mmap_lock		(truncate_pagecache)
 *    ->private_lock		(__free_pte->__set_page_dirty_buffers)
 *      ->swap_lock		(exclusive_swap_page, others)
 *        ->mapping->tree_lock
 *
 *  ->i_mutex
 *    ->i_mmap_lock		(truncate->unmap_mapping_range)
 *
 *  ->mmap_sem
 *    ->i_mmap_lock
 *      ->page_table_lock or pte_lock	(various, mainly in memory.c)
 *        ->mapping->tree_lock	(arch-dependent flush_dcache_mmap_lock)
 *
 *  ->mmap_sem
 *    ->lock_page		(access_process_vm)
 *
 *  ->i_mutex			(generic_file_buffered_write)
 *    ->mmap_sem		(fault_in_pages_readable->do_page_fault)
 *
 *  ->i_mutex
 *    ->i_alloc_sem             (various)
 *
 *  ->inode_lock
 *    ->sb_lock			(fs/fs-writeback.c)
 *    ->mapping->tree_lock	(__sync_single_inode)
 *
 *  ->i_mmap_lock
 *    ->anon_vma.lock		(vma_adjust)
 *
 *  ->anon_vma.lock
 *    ->page_table_lock or pte_lock	(anon_vma_prepare and various)
 *
 *  ->page_table_lock or pte_lock
 *    ->swap_lock		(try_to_unmap_one)
 *    ->private_lock		(try_to_unmap_one)
 *    ->tree_lock		(try_to_unmap_one)
 *    ->zone.lru_lock		(follow_page->mark_page_accessed)
 *    ->zone.lru_lock		(check_pte_range->isolate_lru_page)
 *    ->private_lock		(page_remove_rmap->set_page_dirty)
 *    ->tree_lock		(page_remove_rmap->set_page_dirty)
 *    ->inode_lock		(page_remove_rmap->set_page_dirty)
 *    ->inode_lock		(zap_pte_range->set_page_dirty)
 *    ->private_lock		(zap_pte_range->__set_page_dirty_buffers)
 *
 *  ->task->proc_lock
 *    ->dcache_lock		(proc_pid_lookup)
 *
 *  (code doesn't rely on that order, so you could switch it around)
 *  ->tasklist_lock             (memory_failure, collect_procs_ao)
 *    ->i_mmap_lock
 */

/*
 * Remove a page from the page cache and free it. Caller has to make
 * sure the page is locked and that nobody else uses it - or that usage
 * is safe.  The caller must hold the mapping's tree_lock.
 */
void __remove_from_page_cache(struct page *page)
{
	struct address_space *mapping = page->mapping;

	radix_tree_delete(&mapping->page_tree, page->index);
	page->mapping = NULL;
	mapping->nrpages--;
	__dec_zone_page_state(page, NR_FILE_PAGES);
	if (PageSwapBacked(page))
		__dec_zone_page_state(page, NR_SHMEM);
	BUG_ON(page_mapped(page));

	/*
	 * Some filesystems seem to re-dirty the page even after
	 * the VM has canceled the dirty bit (eg ext3 journaling).
	 *
	 * Fix it up by doing a final dirty accounting check after
	 * having removed the page entirely.
	 */
	if (PageDirty(page) && mapping_cap_account_dirty(mapping)) {
		dec_zone_page_state(page, NR_FILE_DIRTY);
		dec_bdi_stat(mapping->backing_dev_info, BDI_RECLAIMABLE);
	}
}

void remove_from_page_cache(struct page *page)
{
	struct address_space *mapping = page->mapping;

	BUG_ON(!PageLocked(page));

	spin_lock_irq(&mapping->tree_lock);
	__remove_from_page_cache(page);
	spin_unlock_irq(&mapping->tree_lock);
	mem_cgroup_uncharge_cache_page(page);
}

static int sync_page(void *word)
{
	struct address_space *mapping;
	struct page *page;

	page = container_of((unsigned long *)word, struct page, flags);

	/*
	 * page_mapping() is being called without PG_locked held.
	 * Some knowledge of the state and use of the page is used to
	 * reduce the requirements down to a memory barrier.
	 * The danger here is of a stale page_mapping() return value
	 * indicating a struct address_space different from the one it's
	 * associated with when it is associated with one.
	 * After smp_mb(), it's either the correct page_mapping() for
	 * the page, or an old page_mapping() and the page's own
	 * page_mapping() has gone NULL.
	 * The ->sync_page() address_space operation must tolerate
	 * page_mapping() going NULL. By an amazing coincidence,
	 * this comes about because none of the users of the page
	 * in the ->sync_page() methods make essential use of the
	 * page_mapping(), merely passing the page down to the backing
	 * device's unplug functions when it's non-NULL, which in turn
	 * ignore it for all cases but swap, where only page_private(page) is
	 * of interest. When page_mapping() does go NULL, the entire
	 * call stack gracefully ignores the page and returns.
	 * -- wli
	 */
	smp_mb();
	mapping = page_mapping(page);
	if (mapping && mapping->a_ops && mapping->a_ops->sync_page)
		mapping->a_ops->sync_page(page);
	io_schedule();
	return 0;
}

static int sync_page_killable(void *word)
{
	sync_page(word);
	return fatal_signal_pending(current) ? -EINTR : 0;
}

/**
 * __filemap_fdatawrite_range - start writeback on mapping dirty pages in range
 * @mapping:	address space structure to write
 * @start:	offset in bytes where the range starts
 * @end:	offset in bytes where the range ends (inclusive)
 * @sync_mode:	enable synchronous operation
 *
 * Start writeback against all of a mapping's dirty pages that lie
 * within the byte offsets <start, end> inclusive.
 *
 * If sync_mode is WB_SYNC_ALL then this is a "data integrity" operation, as
 * opposed to a regular memory cleansing writeback.  The difference between
 * these two operations is that if a dirty page/buffer is encountered, it must
 * be waited upon, and not just skipped over.
 */
int __filemap_fdatawrite_range(struct address_space *mapping, loff_t start,
				loff_t end, int sync_mode)
{
	int ret;
	struct writeback_control wbc = {
		.sync_mode = sync_mode,
		.nr_to_write = LONG_MAX,
		.range_start = start,
		.range_end = end,
	};

	if (!mapping_cap_writeback_dirty(mapping))
		return 0;

	ret = do_writepages(mapping, &wbc);
	return ret;
}

static inline int __filemap_fdatawrite(struct address_space *mapping,
	int sync_mode)
{
	return __filemap_fdatawrite_range(mapping, 0, LLONG_MAX, sync_mode);
}

int filemap_fdatawrite(struct address_space *mapping)
{
	return __filemap_fdatawrite(mapping, WB_SYNC_ALL);
}
EXPORT_SYMBOL(filemap_fdatawrite);

int filemap_fdatawrite_range(struct address_space *mapping, loff_t start,
				loff_t end)
{
	return __filemap_fdatawrite_range(mapping, start, end, WB_SYNC_ALL);
}
EXPORT_SYMBOL(filemap_fdatawrite_range);

/**
 * filemap_flush - mostly a non-blocking flush
 * @mapping:	target address_space
 *
 * This is a mostly non-blocking flush.  Not suitable for data-integrity
 * purposes - I/O may not be started against all dirty pages.
 */
int filemap_flush(struct address_space *mapping)
{
	return __filemap_fdatawrite(mapping, WB_SYNC_NONE);
}
EXPORT_SYMBOL(filemap_flush);

/**
 * filemap_fdatawait_range - wait for writeback to complete
 * @mapping:		address space structure to wait for
 * @start_byte:		offset in bytes where the range starts
 * @end_byte:		offset in bytes where the range ends (inclusive)
 *
 * Walk the list of under-writeback pages of the given address space
 * in the given range and wait for all of them.
 */
int filemap_fdatawait_range(struct address_space *mapping, loff_t start_byte,
			    loff_t end_byte)
{
	pgoff_t index = start_byte >> PAGE_CACHE_SHIFT;
	pgoff_t end = end_byte >> PAGE_CACHE_SHIFT;
	struct pagevec pvec;
	int nr_pages;
	int ret = 0;