eta name='generator' content='cgit v1.2.2'/>
aboutsummaryrefslogblamecommitdiffstats
path: root/fs/super.c
blob: ab3d672db0deae0a84a01bc1938cd967cc27e79f (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
















                                                                
                                                                



                                                                               

                         

                         

                           

                                                                             
                        
                              
                             
                             
                     

 




                                                     
                                                           



                                                                           
                                                                     
 
                                                                               
                                                        

                




                                           













                                                                           
                                            
      
                                                     
                                                
                                               
                                             
                                                 
                                         
                                       
                                                                     





                                                                 















                                                                         
                               
                                            
                                                   
                                                                                   

                                                      


                                                         

                                            
                                          












                                                       


                                
                            
                            
                            





                             
                                                               
   
                                        
 
                             
                                           
                                  
         








                                                                        
                                      







                              
                                                                              

                                    

                                                                              

                                                                          

                                                                         
   
                                                   

                                                
                                                
                                       
                               




                                                                          

                                   

                                       


         
                                       

   
                                                                              

                                    


                                                                              
   
                                            
 


                                                      


         
                                

   









                                                                             
                                                                
 

                                                


                             

                              
                                
                                 

                               


                 
  
















                                                                








                                                                              



                                                                               


                                                   
                                                      
 
 

                                             
                                    
                              
                                          
 


                                                       
 


                                           
                                                 


                                                                               
                 
                              


                                                                      
                                        


















                                                                 
                                



                            





                                                                         

                                                       
                                                 
                                         
                         
                                                   



                                                                  

                                   


                                      
                                      







                                                
                                       





















                                                      







                                                                     





                                                         
                                          
 
                            
                                                        

                                                 
                                                          

                                              
 
                                                 

                                                          
                                               
 
                                            


                                               

                 

                               


                              
   








                                                                       
                                          

                            
                                                        










                                                 


                                       
         

                               



                              






                                                                             
                                                        
 

                               

                            
 
                            

                                                        

                                                 

                                         
                                              
                                                 
                                          


                                               
                                                 
                                            

                                        






                              






                                                                           
                                        







                                                               
        

                                                        

                                                 





                                                               



                              
 
                                             
 
                               
 
                            

                                                        

                                                 

                                        
                                              
                                                 
                                          


                                               
                                                 
                                            

                                        





                              
   










                                                                           
                       



                                        
                   

                                                               
      
 


                                    
                            
 
                                                                       
 

                                                                    
                         

                                          
                                                



                                      
                                                                
                           


                                                                           
 









                                                                              


                 
                                                          
 
                                          

                            
                                                        

                                                 

                                      
                                          

                                                                             

                                                           
                                                              
                 
                                        
                                    


                                       
         

                               
                              
                    




                                               






                                                      






                                                          
                                   
                                                                 
                                                                    






                                                     
                                                           

                                     
                                                                             

                                            








                                                         
                                                  

                                                



                                               
                                          










                                            
                                           

                                         




                                       








                                              










                                                            

                                                                         




                                                              
                                    





                                                                      
                                                    
                                            




                                         
                                

 
                        
 
                   



                                                            





                                                                     







                                                             
                                                           
                                                    
                                                             


                                  
                                               

                      


                                    
                                                           
                         
                                      





                                                                       





                                                       
                                                                 
                                               
                      
                             


                                                       
                                                   

                                        
                 
 

                                                        



                                                                     

                                       
                                       
                                         


                                      
                                              
                                 
                                                                     
                                                      
                                                                       
                            
                                                   
                                   
                 

                                        
                                   

         
                               
 


                           
                               
      



                              


                                               
                                  
 
                              

                                   
                                           
                                            


                                
      
 
                                                            
                              
                                                             




                                                                          
                                   


                           
                                                               
                    
                                           
                                      

                                
                               
 

                           




                                                         
                                                             
                              
                                                             





                                                                
                                   

                                   
                                                                       
                            
                                                   
                                              

                                        

                                                 
         



                               

                                                                                
 
                            
                               
                             
                            
 
                                                              
                                          
                             
                                 
 
                                                             
                          
                                              

         



                                                    
         


                            
                                                        
                               
 
                                                           

                            
 



                                                                               
                             
           

                                                                       
 
                                
                              
                    
       

                                    

                              
    
                              

 
   

                                                                          





















































































                                                                                
/*
 *  linux/fs/super.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 *
 *  super.c contains code to handle: - mount structures
 *                                   - super-block tables
 *                                   - filesystem drivers list
 *                                   - mount system call
 *                                   - umount system call
 *                                   - ustat system call
 *
 * GK 2/5/95  -  Changed to support mounting the root fs via NFS
 *
 *  Added kerneld support: Jacques Gelinas and Bjorn Ekwall
 *  Added change_root: Werner Almesberger & Hans Lermen, Feb '96
 *  Added options to /proc/mounts:
 *    Torbjörn Lindh (torbjorn.lindh@gopta.se), April 14, 1996.
 *  Added devfs support: Richard Gooch <rgooch@atnf.csiro.au>, 13-JAN-1998
 *  Heavily rewritten for 'one fs - one tree' dcache architecture. AV, Mar 2000
 */

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/acct.h>
#include <linux/blkdev.h>
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/writeback.h>		/* for the emergency remount stuff */
#include <linux/idr.h>
#include <linux/mutex.h>
#include <linux/backing-dev.h>
#include <linux/rculist_bl.h>
#include <linux/cleancache.h>
#include "internal.h"


LIST_HEAD(super_blocks);
DEFINE_SPINLOCK(sb_lock);

/**
 *	alloc_super	-	create new superblock
 *	@type:	filesystem type superblock should belong to
 *
 *	Allocates and initializes a new &struct super_block.  alloc_super()
 *	returns a pointer new superblock or %NULL if allocation had failed.
 */
static struct super_block *alloc_super(struct file_system_type *type)
{
	struct super_block *s = kzalloc(sizeof(struct super_block),  GFP_USER);
	static const struct super_operations default_op;

	if (s) {
		if (security_sb_alloc(s)) {
			kfree(s);
			s = NULL;
			goto out;
		}
#ifdef CONFIG_SMP
		s->s_files = alloc_percpu(struct list_head);
		if (!s->s_files) {
			security_sb_free(s);
			kfree(s);
			s = NULL;
			goto out;
		} else {
			int i;

			for_each_possible_cpu(i)
				INIT_LIST_HEAD(per_cpu_ptr(s->s_files, i));
		}
#else
		INIT_LIST_HEAD(&s->s_files);
#endif
		s->s_bdi = &default_backing_dev_info;
		INIT_LIST_HEAD(&s->s_instances);
		INIT_HLIST_BL_HEAD(&s->s_anon);
		INIT_LIST_HEAD(&s->s_inodes);
		INIT_LIST_HEAD(&s->s_dentry_lru);
		init_rwsem(&s->s_umount);
		mutex_init(&s->s_lock);
		lockdep_set_class(&s->s_umount, &type->s_umount_key);
		/*
		 * The locking rules for s_lock are up to the
		 * filesystem. For example ext3fs has different
		 * lock ordering than usbfs:
		 */
		lockdep_set_class(&s->s_lock, &type->s_lock_key);
		/*
		 * sget() can have s_umount recursion.
		 *
		 * When it cannot find a suitable sb, it allocates a new
		 * one (this one), and tries again to find a suitable old
		 * one.
		 *
		 * In case that succeeds, it will acquire the s_umount
		 * lock of the old one. Since these are clearly distrinct
		 * locks, and this object isn't exposed yet, there's no
		 * risk of deadlocks.
		 *
		 * Annotate this by putting this lock in a different
		 * subclass.
		 */
		down_write_nested(&s->s_umount, SINGLE_DEPTH_NESTING);
		s->s_count = 1;
		atomic_set(&s->s_active, 1);
		mutex_init(&s->s_vfs_rename_mutex);
		lockdep_set_class(&s->s_vfs_rename_mutex, &type->s_vfs_rename_key);
		mutex_init(&s->s_dquot.dqio_mutex);
		mutex_init(&s->s_dquot.dqonoff_mutex);
		init_rwsem(&s->s_dquot.dqptr_sem);
		init_waitqueue_head(&s->s_wait_unfrozen);
		s->s_maxbytes = MAX_NON_LFS;
		s->s_op = &default_op;
		s->s_time_gran = 1000000000;
		s->cleancache_poolid = -1;
	}
out:
	return s;
}

/**
 *	destroy_super	-	frees a superblock
 *	@s: superblock to free
 *
 *	Frees a superblock.
 */
static inline void destroy_super(struct super_block *s)
{
#ifdef CONFIG_SMP
	free_percpu(s->s_files);
#endif
	security_sb_free(s);
	kfree(s->s_subtype);
	kfree(s->s_options);
	kfree(s);
}

/* Superblock refcounting  */

/*
 * Drop a superblock's refcount.  The caller must hold sb_lock.
 */
void __put_super(struct super_block *sb)
{
	if (!--sb->s_count) {
		list_del_init(&sb->s_list);
		destroy_super(sb);
	}
}

/**
 *	put_super	-	drop a temporary reference to superblock
 *	@sb: superblock in question
 *
 *	Drops a temporary reference, frees superblock if there's no
 *	references left.
 */
void put_super(struct super_block *sb)
{
	spin_lock(&sb_lock);
	__put_super(sb);
	spin_unlock(&sb_lock);
}


/**
 *	deactivate_locked_super	-	drop an active reference to superblock
 *	@s: superblock to deactivate
 *
 *	Drops an active reference to superblock, converting it into a temprory
 *	one if there is no other active references left.  In that case we
 *	tell fs driver to shut it down and drop the temporary reference we
 *	had just acquired.
 *
 *	Caller holds exclusive lock on superblock; that lock is released.
 */
void deactivate_locked_super(struct super_block *s)
{
	struct file_system_type *fs = s->s_type;
	if (atomic_dec_and_test(&s->s_active)) {
		cleancache_flush_fs(s);
		fs->kill_sb(s);
		/*
		 * We need to call rcu_barrier so all the delayed rcu free
		 * inodes are flushed before we release the fs module.
		 */
		rcu_barrier();
		put_filesystem(fs);
		put_super(s);
	} else {
		up_write(&s->s_umount);
	}
}

EXPORT_SYMBOL(deactivate_locked_super);

/**
 *	deactivate_super	-	drop an active reference to superblock
 *	@s: superblock to deactivate
 *
 *	Variant of deactivate_locked_super(), except that superblock is *not*
 *	locked by caller.  If we are going to drop the final active reference,
 *	lock will be acquired prior to that.
 */
void deactivate_super(struct super_block *s)
{
        if (!atomic_add_unless(&s->s_active, -1, 1)) {
		down_write(&s->s_umount);
		deactivate_locked_super(s);
	}
}

EXPORT_SYMBOL(deactivate_super);

/**
 *	grab_super - acquire an active reference
 *	@s: reference we are trying to make active
 *
 *	Tries to acquire an active reference.  grab_super() is used when we
 * 	had just found a superblock in super_blocks or fs_type->fs_supers
 *	and want to turn it into a full-blown active reference.  grab_super()
 *	is called with sb_lock held and drops it.  Returns 1 in case of
 *	success, 0 if we had failed (superblock contents was already dead or
 *	dying when grab_super() had been called).
 */
static int grab_super(struct super_block *s) __releases(sb_lock)
{
	if (atomic_inc_not_zero(&s->s_active)) {
		spin_unlock(&sb_lock);
		return 1;
	}
	/* it's going away */
	s->s_count++;
	spin_unlock(&sb_lock);
	/* wait for it to die */
	down_write(&s->s_umount);
	up_write(&s->s_umount);
	put_super(s);
	return 0;
}

/*
 * Superblock locking.  We really ought to get rid of these two.
 */
void lock_super(struct super_block * sb)
{
	get_fs_excl();
	mutex_lock(&sb->s_lock);
}

void unlock_super(struct super_block * sb)
{
	put_fs_excl();
	mutex_unlock(&sb->s_lock);
}

EXPORT_SYMBOL(lock_super);
EXPORT_SYMBOL(unlock_super);

/**
 *	generic_shutdown_super	-	common helper for ->kill_sb()
 *	@sb: superblock to kill
 *
 *	generic_shutdown_super() does all fs-independent work on superblock
 *	shutdown.  Typical ->kill_sb() should pick all fs-specific objects
 *	that need destruction out of superblock, call generic_shutdown_super()
 *	and release aforementioned objects.  Note: dentries and inodes _are_
 *	taken care of and do not need specific handling.
 *
 *	Upon calling this function, the filesystem may no longer alter or
 *	rearrange the set of dentries belonging to this super_block, nor may it
 *	change the attachments of dentries to inodes.
 */
void generic_shutdown_super(struct super_block *sb)
{
	const struct super_operations *sop = sb->s_op;


	if (sb->s_root) {
		shrink_dcache_for_umount(sb);
		sync_filesystem(sb);
		get_fs_excl();
		sb->s_flags &= ~MS_ACTIVE;

		fsnotify_unmount_inodes(&sb->s_inodes);

		evict_inodes(sb);

		if (sop->put_super)
			sop->put_super(sb);

		if (!list_empty(&sb->s_inodes)) {
			printk("VFS: Busy inodes after unmount of %s. "
			   "Self-destruct in 5 seconds.  Have a nice day...\n",
			   sb->s_id);
		}
		put_fs_excl();
	}
	spin_lock(&sb_lock);
	/* should be initialized for __put_super_and_need_restart() */
	list_del_init(&sb->s_instances);
	spin_unlock(&sb_lock);
	up_write(&sb->s_umount);
}

EXPORT_SYMBOL(generic_shutdown_super);

/**
 *	sget	-	find or create a superblock
 *	@type:	filesystem type superblock should belong to
 *	@test:	comparison callback
 *	@set:	setup callback
 *	@data:	argument to each of them