/sound/

0879091e33cd65fd60418d006ad9'>root/fs/eventpoll.c
blob: 7bcfff900f058cd9d98278c1fa13ed2b0202eccc (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
  

                                                             









                                                                        









                         




                           




                            
                        
                              
                         
                        

                     
                         

                           
                         
                          
 



                                                       
                     

                         








                                                                




                                                                         

                                                                   
                                                                






                                                                     








                                                                    


                                                                 
                                                                 

                                                               

   
                                              
                                                              
 

                                                         
 

                                                            

                                      

                                                                          


                          
           

  

                                                                         
   
                         
                               
                     
                  


  

                                                                     
   

                                         



                        

                                                             

                                                                           

               





                                                                                



                                                                                 





                                                                    











                                                                     


                                                                                
                                                        
                                       
 

                                                                                 


  
                                                                        
                                                                     


                  
                                                  
                        

          



                                                                      
           
                         









                                                 
                                                             
                           


                                                                                
                                                                      


                               
 


                                                                   

                                                            





                                                   







                                                                            
                            










                                                                        





                                          





                                                                    
  

                                                             
                                                           
                                           

  
                                                                          
   
                             
 


                                                             




                                                                        

                                                 
                                                  

                                                       
                                                  
 








                                                                               



                         

                                
 
                                  
         

                                                     
                                                           
                                       
                                                         
                                        
                                            
          
           


                          





                                                   
 
                                                             






                                                        
                          






                                                              





                                                   




                                                                    
                                                       
                                                               




                                                                
                                                                




                                                                            
                                         
 
                                   

 
                                                
                                                             
 

                                                 

 
   












                                                                              









                                                                           
                               


                                                                      
   

                                                                        
                                                  
 
                                  
                            


                                                             
 
                                                
 




                                                                             
                                                    
                                        
                                                                            



                                                                               

                                        


                 
                                                         
                        
                              

                                        
                                                     
 

                                                   

                                                   
                                                
                               
           




                                                     
























                                                                           

















                                                                        

                                                                        

                                                               














                                                                      

                                 
                                                           


                                                                                

 











                                                                 
  


                                                                           
   
                                                                            
 

                                                  
 

                                                                            
 
                                      
                                          
                                                
         

 































                                                                              







                                                                             
                                                           
                                           





                                                                        
                                                                    



                                  
                          


                                                          
                                                    
           


                                                   









                                                                       
                                                





















                                                                                
                                                   
                                                                   
                                              
                 











                                                                             
                           


                                        

                                                                              







                                                     

                                       







                                                   





                                                                    
  
                                                                       
                                                                


                                                              

                                          

          





                                                                                  
           
                                        
 
                                                                  
                                 
                                   
                                   
 
                                      
 



                                                 
 
                                                        







                                                                               
 
                                                  
 
                 

 
                                         
 

                            
 

                                                                 
                                                 
 


                                                                               
                                                                       

                                                                             
                                                

                             

          
                                                                        
           



                                                                 
                               
         

          

                                                                                    
                                                                              
                                                                            

                                                                           
           
                             
                                                    

                                                        
                               
         
                               
 
                               
                                
                           
                                         
                  
 
 


                                                                       
 
               
                            
 
                 

 






                                                                                

                                                                            

                                 
                      
 
                                     
 
                                                           
                                           
                                                   
                      




                                                                                
                                                          
                                                     
                 




                 







                                                                             

                                                                             



                                                                     

 

                                                                          
                      
                                                  







                                                                        
 


                                               






                                                                           
                                                                                
 
                                               

 






















                                                                          

                                                                


                                         
                                               

                                            

  
  


                                                                               
   
                                              
 
                             
                                  

          
                                                                
                                                                            
                                                                               
                                                                              
                                                                              
                                                                          
                                                                        
                                                                                
                                       

                                                                            
           
                             
                                                                        
                             
                                               
                                   
                                       
         
                               

 
                                           
 


                                 
 
                                  



                                              
 
                                  
                             



                                            
                                      
                        
 
                  
 
                 



                       

 
  


                                                                      



                                                                              



                                         
                                   

                                                        
                                                   




                                            



                                   
 


                    
  
                                                               
                                                                   
                         
   
                                                                                   
 



                                                     
 







                                                                           
                                                
         
 
                                            
 






                                                                                   


                                








                                                                            
                                                                           
                                                                                  
                                                                                





                                                        







                                                                        


                                
 
                                                                    
                                           
                                                           
                                          
         
 




                                                                              
                                        


                                             
           
                                                 
 

                                                   
                                                 


                 







                                                                             
                                                      

                                 
                                                                                 





                                                                        
                

                                                              
         

 








                                                                      
                                                         








                                              

 
















                                                                               



                                                        



















                                                                            


                                                                              




















                                                                                
                          














                                                                             




                                                                             









                                                                              


                                                      
                                 







                                                                  


                                          
                               
                                        



                 

                                                                          
 

                                                         
                                        







                                                                      

 


                                  
                                                                     
                                                                


                                      
                          


                             

                                                                  
                               
                                                             
                               

                                                 

                                      

                                      
                                         
                            
                       
                                    




                                                        
                                                
         







                                                                        


                                                                         
           
                                             





                                                                              
                        
                           
                                      

                                                                                 
                                  
                                                            
                                    
 



                                                                          

                                  

                                                           
                                               

                                      


                                                                                   
                                                                             
                                                                        
                                                           
                                      


                                                                    
                                                



                                                     
                                                 
 
                                                  
 

                                                   
                                                 
 

                 

                                  
                                   



                                      
                 



                                                                              


                                                                                 
           
                                            
                                        
                                             
                                                 
 
                                                        

                           
                                        
 


                     

                                                                      
                                                                          




                                                                                         


                                     

          


                                                                       
           
                                                                   
                                                             
                                              
                                               
                                                     
                                               

                                              

          



















                                                                         


                                                                             
                                         
 
          
                                                                         
                                
           
                                      
                                         

                                                                   
                                              


                                                                            
                                                        

                                                             
                 
                                           
         
 

                                                   
                                                 
 
                 

 

                                                                            
 

                                                
                             

                                          
                                 


                                     
 
          


                                                                              
           


                                                                     
 








                                                                                






                                                        
                                             
 
                                                 
 
                  



                                                                              

                              
                                                                   

                                                                         
                                                      
                                                                     
                         
                                   
                                 







                                                                              
                                                                                 





                                                                                
                                                      


                         


                        
 

                                                                           

                                        
 

                                   
 
                                                                            

 










                                                               
















                                                                                


                                                                           
                                           
                            
                       
                          


                                    

                                                                     



                                                            



                                                                            
                              

                                                    
         
 
             
                                            
 
                                       





                                                                             
                                                           







                                                                                    
                                                                 





                                                      
                                                                 
                                                                                   

                                              
                                                            
                 
                                                    


                                                
             
                                                    
                                         
 
                                                 






                                                                            
                                                                         
                                  



                   



















                                                                               
                                     


                            
                                                    

                                                        


                                                                 


                                                                 
                                                                               

                                                                          

                                       











                                                                              



















                                                                               



                                                             
                                                                     



















                                                                            

 
  
                                     
   
                                          
 
                      
                                    
                          
 


                                                          

                                   
          
                                                                   
           
                              

                             

                                                                            
                                                       
           





                                                                     
                                                               



                                      
                        
                             





                          
                     

 
                                        
 
                      


                                    

 


                                                                  
                                            
   

                                                       

                  
                           
                        


                                
                                     
 




                                                                     
                       

                        


                                                         

                       



                                                          
                                 

                                    
                                             

                                                   
 





                                                                                  
                                                        





                                                                              
                                  
 


                                                                              



                                                                            
          





                                                                                
           
                                       
                                  

















                                                                           
                         

                 
 




                                                                            
                                       





                                                         
                                                                              

                                        

                                                 














                                                          

                                        
                               

               
                       

                                       
                  
           
                 
             







                                                                              

                                                                           
 

                    

                             




                                                                   

                                                                                     

                                                            


                              





                                                                     
                                   





                                                                              
                                  




                                                        
                 


                     



                                                                              


                                                                               












                                                                               

                                               












                                                                              
                                                 
                                              
                      
                                                       




                     




















                                                                               

                                               















                                                                              
                                                       





                   

                                      


                          



                                                                                
                             
                                     
 





                                                                         
                                                                                   



                                                                                
 





                                                                         

                                                                             
                                                                  


                                                                         
                                                                          
 
                 
 
                            
/*
 *  fs/eventpoll.c (Efficient event retrieval implementation)
 *  Copyright (C) 2001,...,2009	 Davide Libenzi
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  Davide Libenzi <davidel@xmailserver.org>
 *
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/hash.h>
#include <linux/spinlock.h>
#include <linux/syscalls.h>
#include <linux/rbtree.h>
#include <linux/wait.h>
#include <linux/eventpoll.h>
#include <linux/mount.h>
#include <linux/bitops.h>
#include <linux/mutex.h>
#include <linux/anon_inodes.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/mman.h>
#include <linux/atomic.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/compat.h>
#include <linux/rculist.h>

/*
 * LOCKING:
 * There are three level of locking required by epoll :
 *
 * 1) epmutex (mutex)
 * 2) ep->mtx (mutex)
 * 3) ep->lock (spinlock)
 *
 * The acquire order is the one listed above, from 1 to 3.
 * We need a spinlock (ep->lock) because we manipulate objects
 * from inside the poll callback, that might be triggered from
 * a wake_up() that in turn might be called from IRQ context.
 * So we can't sleep inside the poll callback and hence we need
 * a spinlock. During the event transfer loop (from kernel to
 * user space) we could end up sleeping due a copy_to_user(), so
 * we need a lock that will allow us to sleep. This lock is a
 * mutex (ep->mtx). It is acquired during the event transfer loop,
 * during epoll_ctl(EPOLL_CTL_DEL) and during eventpoll_release_file().
 * Then we also need a global mutex to serialize eventpoll_release_file()
 * and ep_free().
 * This mutex is acquired by ep_free() during the epoll file
 * cleanup path and it is also acquired by eventpoll_release_file()
 * if a file has been pushed inside an epoll set and it is then
 * close()d without a previous call to epoll_ctl(EPOLL_CTL_DEL).
 * It is also acquired when inserting an epoll fd onto another epoll
 * fd. We do this so that we walk the epoll tree and ensure that this
 * insertion does not create a cycle of epoll file descriptors, which
 * could lead to deadlock. We need a global mutex to prevent two
 * simultaneous inserts (A into B and B into A) from racing and
 * constructing a cycle without either insert observing that it is
 * going to.
 * It is necessary to acquire multiple "ep->mtx"es at once in the
 * case when one epoll fd is added to another. In this case, we
 * always acquire the locks in the order of nesting (i.e. after
 * epoll_ctl(e1, EPOLL_CTL_ADD, e2), e1->mtx will always be acquired
 * before e2->mtx). Since we disallow cycles of epoll file
 * descriptors, this ensures that the mutexes are well-ordered. In
 * order to communicate this nesting to lockdep, when walking a tree
 * of epoll file descriptors, we use the current recursion depth as
 * the lockdep subkey.
 * It is possible to drop the "ep->mtx" and to use the global
 * mutex "epmutex" (together with "ep->lock") to have it working,
 * but having "ep->mtx" will make the interface more scalable.
 * Events that require holding "epmutex" are very rare, while for
 * normal operations the epoll private "ep->mtx" will guarantee
 * a better scalability.
 */

/* Epoll private bits inside the event mask */
#define EP_PRIVATE_BITS (EPOLLWAKEUP | EPOLLONESHOT | EPOLLET)

/* Maximum number of nesting allowed inside epoll sets */
#define EP_MAX_NESTS 4

#define EP_MAX_EVENTS (INT_MAX / sizeof(struct epoll_event))

#define EP_UNACTIVE_PTR ((void *) -1L)

#define EP_ITEM_COST (sizeof(struct epitem) + sizeof(struct eppoll_entry))

struct epoll_filefd {
	struct file *file;
	int fd;
} __packed;

/*
 * Structure used to track possible nested calls, for too deep recursions
 * and loop cycles.
 */
struct nested_call_node {
	struct list_head llink;
	void *cookie;
	void *ctx;
};

/*
 * This structure is used as collector for nested calls, to check for
 * maximum recursion dept and loop cycles.
 */
struct nested_calls {
	struct list_head tasks_call_list;
	spinlock_t lock;
};

/*
 * Each file descriptor added to the eventpoll interface will
 * have an entry of this type linked to the "rbr" RB tree.
 * Avoid increasing the size of this struct, there can be many thousands
 * of these on a server and we do not want this to take another cache line.
 */
struct epitem {
	union {
		/* RB tree node links this structure to the eventpoll RB tree */
		struct rb_node rbn;
		/* Used to free the struct epitem */
		struct rcu_head rcu;
	};

	/* List header used to link this structure to the eventpoll ready list */
	struct list_head rdllink;

	/*
	 * Works together "struct eventpoll"->ovflist in keeping the
	 * single linked chain of items.
	 */
	struct epitem *next;

	/* The file descriptor information this item refers to */
	struct epoll_filefd ffd;

	/* Number of active wait queue attached to poll operations */
	int nwait;

	/* List containing poll wait queues */
	struct list_head pwqlist;

	/* The "container" of this item */
	struct eventpoll *ep;

	/* List header used to link this item to the "struct file" items list */
	struct list_head fllink;

	/* wakeup_source used when EPOLLWAKEUP is set */
	struct wakeup_source __rcu *ws;

	/* The structure that describe the interested events and the source fd */
	struct epoll_event event;
};

/*
 * This structure is stored inside the "private_data" member of the file
 * structure and represents the main data structure for the eventpoll
 * interface.
 */
struct eventpoll {
	/* Protect the access to this structure */
	spinlock_t lock;

	/*
	 * This mutex is used to ensure that files are not removed
	 * while epoll is using them. This is held during the event
	 * collection loop, the file cleanup path, the epoll file exit
	 * code and the ctl operations.
	 */
	struct mutex mtx;

	/* Wait queue used by sys_epoll_wait() */
	wait_queue_head_t wq;

	/* Wait queue used by file->poll() */
	wait_queue_head_t poll_wait;

	/* List of ready file descriptors */
	struct list_head rdllist;

	/* RB tree root used to store monitored fd structs */
	struct rb_root rbr;

	/*