diff options
Diffstat (limited to 'fs/inode.c')
| -rw-r--r-- | fs/inode.c | 31 | 
1 files changed, 23 insertions, 8 deletions
diff --git a/fs/inode.c b/fs/inode.c index da85e56378f..0647d80accf 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -295,6 +295,20 @@ static void destroy_inode(struct inode *inode)  		call_rcu(&inode->i_rcu, i_callback);  } +void address_space_init_once(struct address_space *mapping) +{ +	memset(mapping, 0, sizeof(*mapping)); +	INIT_RADIX_TREE(&mapping->page_tree, GFP_ATOMIC); +	spin_lock_init(&mapping->tree_lock); +	spin_lock_init(&mapping->i_mmap_lock); +	INIT_LIST_HEAD(&mapping->private_list); +	spin_lock_init(&mapping->private_lock); +	INIT_RAW_PRIO_TREE_ROOT(&mapping->i_mmap); +	INIT_LIST_HEAD(&mapping->i_mmap_nonlinear); +	mutex_init(&mapping->unmap_mutex); +} +EXPORT_SYMBOL(address_space_init_once); +  /*   * These are initializations that only need to be done   * once, because the fields are idempotent across use @@ -308,13 +322,7 @@ void inode_init_once(struct inode *inode)  	INIT_LIST_HEAD(&inode->i_devices);  	INIT_LIST_HEAD(&inode->i_wb_list);  	INIT_LIST_HEAD(&inode->i_lru); -	INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC); -	spin_lock_init(&inode->i_data.tree_lock); -	spin_lock_init(&inode->i_data.i_mmap_lock); -	INIT_LIST_HEAD(&inode->i_data.private_list); -	spin_lock_init(&inode->i_data.private_lock); -	INIT_RAW_PRIO_TREE_ROOT(&inode->i_data.i_mmap); -	INIT_LIST_HEAD(&inode->i_data.i_mmap_nonlinear); +	address_space_init_once(&inode->i_data);  	i_size_ordered_init(inode);  #ifdef CONFIG_FSNOTIFY  	INIT_HLIST_HEAD(&inode->i_fsnotify_marks); @@ -540,11 +548,14 @@ void evict_inodes(struct super_block *sb)  /**   * invalidate_inodes	- attempt to free all inodes on a superblock   * @sb:		superblock to operate on + * @kill_dirty: flag to guide handling of dirty inodes   *   * Attempts to free all inodes for a given superblock.  If there were any   * busy inodes return a non-zero value, else zero. + * If @kill_dirty is set, discard dirty inodes too, otherwise treat + * them as busy.   */ -int invalidate_inodes(struct super_block *sb) +int invalidate_inodes(struct super_block *sb, bool kill_dirty)  {  	int busy = 0;  	struct inode *inode, *next; @@ -556,6 +567,10 @@ int invalidate_inodes(struct super_block *sb)  	list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) {  		if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE))  			continue; +		if (inode->i_state & I_DIRTY && !kill_dirty) { +			busy = 1; +			continue; +		}  		if (atomic_read(&inode->i_count)) {  			busy = 1;  			continue;  |