mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 08:38:45 +02:00 
			
		
		
		
	split invalidate_inodes()
Pull removal of fsnotify marks into generic_shutdown_super(). Split umount-time work into a new function - evict_inodes(). Make sure that invalidate_inodes() will be able to cope with I_FREEING once we change locking in iput(). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									9843b76aae
								
							
						
					
					
						commit
						63997e98a3
					
				
					 4 changed files with 51 additions and 6 deletions
				
			
		
							
								
								
									
										46
									
								
								fs/inode.c
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								fs/inode.c
									
									
									
									
									
								
							|  | @ -477,6 +477,49 @@ static void dispose_list(struct list_head *head) | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * evict_inodes	- evict all evictable inodes for a superblock | ||||
|  * @sb:		superblock to operate on | ||||
|  * | ||||
|  * Make sure that no inodes with zero refcount are retained.  This is | ||||
|  * called by superblock shutdown after having MS_ACTIVE flag removed, | ||||
|  * so any inode reaching zero refcount during or after that call will | ||||
|  * be immediately evicted. | ||||
|  */ | ||||
| void evict_inodes(struct super_block *sb) | ||||
| { | ||||
| 	struct inode *inode, *next; | ||||
| 	LIST_HEAD(dispose); | ||||
| 
 | ||||
| 	down_write(&iprune_sem); | ||||
| 
 | ||||
| 	spin_lock(&inode_lock); | ||||
| 	list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { | ||||
| 		if (atomic_read(&inode->i_count)) | ||||
| 			continue; | ||||
| 
 | ||||
| 		if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) { | ||||
| 			WARN_ON(1); | ||||
| 			continue; | ||||
| 		} | ||||
| 
 | ||||
| 		inode->i_state |= I_FREEING; | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Move the inode off the IO lists and LRU once I_FREEING is | ||||
| 		 * set so that it won't get moved back on there if it is dirty. | ||||
| 		 */ | ||||
| 		list_move(&inode->i_lru, &dispose); | ||||
| 		list_del_init(&inode->i_wb_list); | ||||
| 		if (!(inode->i_state & (I_DIRTY | I_SYNC))) | ||||
| 			percpu_counter_dec(&nr_inodes_unused); | ||||
| 	} | ||||
| 	spin_unlock(&inode_lock); | ||||
| 
 | ||||
| 	dispose_list(&dispose); | ||||
| 	up_write(&iprune_sem); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
|  * invalidate_inodes	- attempt to free all inodes on a superblock | ||||
|  * @sb:		superblock to operate on | ||||
|  | @ -493,9 +536,8 @@ int invalidate_inodes(struct super_block *sb) | |||
| 	down_write(&iprune_sem); | ||||
| 
 | ||||
| 	spin_lock(&inode_lock); | ||||
| 	fsnotify_unmount_inodes(&sb->s_inodes); | ||||
| 	list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) { | ||||
| 		if (inode->i_state & I_NEW) | ||||
| 		if (inode->i_state & (I_NEW | I_FREEING | I_WILL_FREE)) | ||||
| 			continue; | ||||
| 		if (atomic_read(&inode->i_count)) { | ||||
| 			busy = 1; | ||||
|  |  | |||
|  | @ -106,4 +106,5 @@ extern void release_open_intent(struct nameidata *); | |||
|  * inode.c | ||||
|  */ | ||||
| extern int get_nr_dirty_inodes(void); | ||||
| extern int evict_inodes(struct super_block *); | ||||
| extern int invalidate_inodes(struct super_block *); | ||||
|  |  | |||
|  | @ -240,6 +240,7 @@ void fsnotify_unmount_inodes(struct list_head *list) | |||
| { | ||||
| 	struct inode *inode, *next_i, *need_iput = NULL; | ||||
| 
 | ||||
| 	spin_lock(&inode_lock); | ||||
| 	list_for_each_entry_safe(inode, next_i, list, i_sb_list) { | ||||
| 		struct inode *need_iput_tmp; | ||||
| 
 | ||||
|  | @ -297,4 +298,5 @@ void fsnotify_unmount_inodes(struct list_head *list) | |||
| 
 | ||||
| 		spin_lock(&inode_lock); | ||||
| 	} | ||||
| 	spin_unlock(&inode_lock); | ||||
| } | ||||
|  |  | |||
|  | @ -273,14 +273,14 @@ void generic_shutdown_super(struct super_block *sb) | |||
| 		get_fs_excl(); | ||||
| 		sb->s_flags &= ~MS_ACTIVE; | ||||
| 
 | ||||
| 		/* bad name - it should be evict_inodes() */ | ||||
| 		invalidate_inodes(sb); | ||||
| 		fsnotify_unmount_inodes(&sb->s_inodes); | ||||
| 
 | ||||
| 		evict_inodes(sb); | ||||
| 
 | ||||
| 		if (sop->put_super) | ||||
| 			sop->put_super(sb); | ||||
| 
 | ||||
| 		/* Forget any remaining inodes */ | ||||
| 		if (invalidate_inodes(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); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Al Viro
						Al Viro