diff options
| -rw-r--r-- | fs/hugetlbfs/inode.c | 33 | ||||
| -rw-r--r-- | fs/inode.c | 21 | ||||
| -rw-r--r-- | include/linux/fs.h | 1 |
3 files changed, 24 insertions, 31 deletions
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index eba6d552d9c9..478a169a262d 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
| @@ -380,36 +380,11 @@ static void hugetlbfs_delete_inode(struct inode *inode) | |||
| 380 | 380 | ||
| 381 | static void hugetlbfs_forget_inode(struct inode *inode) __releases(inode_lock) | 381 | static void hugetlbfs_forget_inode(struct inode *inode) __releases(inode_lock) |
| 382 | { | 382 | { |
| 383 | struct super_block *sb = inode->i_sb; | 383 | if (generic_detach_inode(inode)) { |
| 384 | 384 | truncate_hugepages(inode, 0); | |
| 385 | if (!hlist_unhashed(&inode->i_hash)) { | 385 | clear_inode(inode); |
| 386 | if (!(inode->i_state & (I_DIRTY|I_SYNC))) | 386 | destroy_inode(inode); |
| 387 | list_move(&inode->i_list, &inode_unused); | ||
| 388 | inodes_stat.nr_unused++; | ||
| 389 | if (!sb || (sb->s_flags & MS_ACTIVE)) { | ||
| 390 | spin_unlock(&inode_lock); | ||
| 391 | return; | ||
| 392 | } | ||
| 393 | inode->i_state |= I_WILL_FREE; | ||
| 394 | spin_unlock(&inode_lock); | ||
| 395 | /* | ||
| 396 | * write_inode_now is a noop as we set BDI_CAP_NO_WRITEBACK | ||
| 397 | * in our backing_dev_info. | ||
| 398 | */ | ||
| 399 | write_inode_now(inode, 1); | ||
| 400 | spin_lock(&inode_lock); | ||
| 401 | inode->i_state &= ~I_WILL_FREE; | ||
| 402 | inodes_stat.nr_unused--; | ||
| 403 | hlist_del_init(&inode->i_hash); | ||
| 404 | } | 387 | } |
| 405 | list_del_init(&inode->i_list); | ||
| 406 | list_del_init(&inode->i_sb_list); | ||
| 407 | inode->i_state |= I_FREEING; | ||
| 408 | inodes_stat.nr_inodes--; | ||
| 409 | spin_unlock(&inode_lock); | ||
| 410 | truncate_hugepages(inode, 0); | ||
| 411 | clear_inode(inode); | ||
| 412 | destroy_inode(inode); | ||
| 413 | } | 388 | } |
| 414 | 389 | ||
| 415 | static void hugetlbfs_drop_inode(struct inode *inode) | 390 | static void hugetlbfs_drop_inode(struct inode *inode) |
diff --git a/fs/inode.c b/fs/inode.c index 07d775ea6161..fa506d539653 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -1241,7 +1241,16 @@ void generic_delete_inode(struct inode *inode) | |||
| 1241 | } | 1241 | } |
| 1242 | EXPORT_SYMBOL(generic_delete_inode); | 1242 | EXPORT_SYMBOL(generic_delete_inode); |
| 1243 | 1243 | ||
| 1244 | static void generic_forget_inode(struct inode *inode) | 1244 | /** |
| 1245 | * generic_detach_inode - remove inode from inode lists | ||
| 1246 | * @inode: inode to remove | ||
| 1247 | * | ||
| 1248 | * Remove inode from inode lists, write it if it's dirty. This is just an | ||
| 1249 | * internal VFS helper exported for hugetlbfs. Do not use! | ||
| 1250 | * | ||
| 1251 | * Returns 1 if inode should be completely destroyed. | ||
| 1252 | */ | ||
| 1253 | int generic_detach_inode(struct inode *inode) | ||
| 1245 | { | 1254 | { |
| 1246 | struct super_block *sb = inode->i_sb; | 1255 | struct super_block *sb = inode->i_sb; |
| 1247 | 1256 | ||
| @@ -1251,7 +1260,7 @@ static void generic_forget_inode(struct inode *inode) | |||
| 1251 | inodes_stat.nr_unused++; | 1260 | inodes_stat.nr_unused++; |
| 1252 | if (sb->s_flags & MS_ACTIVE) { | 1261 | if (sb->s_flags & MS_ACTIVE) { |
| 1253 | spin_unlock(&inode_lock); | 1262 | spin_unlock(&inode_lock); |
| 1254 | return; | 1263 | return 0; |
| 1255 | } | 1264 | } |
| 1256 | WARN_ON(inode->i_state & I_NEW); | 1265 | WARN_ON(inode->i_state & I_NEW); |
| 1257 | inode->i_state |= I_WILL_FREE; | 1266 | inode->i_state |= I_WILL_FREE; |
| @@ -1269,6 +1278,14 @@ static void generic_forget_inode(struct inode *inode) | |||
| 1269 | inode->i_state |= I_FREEING; | 1278 | inode->i_state |= I_FREEING; |
| 1270 | inodes_stat.nr_inodes--; | 1279 | inodes_stat.nr_inodes--; |
| 1271 | spin_unlock(&inode_lock); | 1280 | spin_unlock(&inode_lock); |
| 1281 | return 1; | ||
| 1282 | } | ||
| 1283 | EXPORT_SYMBOL_GPL(generic_detach_inode); | ||
| 1284 | |||
| 1285 | static void generic_forget_inode(struct inode *inode) | ||
| 1286 | { | ||
| 1287 | if (!generic_detach_inode(inode)) | ||
| 1288 | return; | ||
| 1272 | if (inode->i_data.nrpages) | 1289 | if (inode->i_data.nrpages) |
| 1273 | truncate_inode_pages(&inode->i_data, 0); | 1290 | truncate_inode_pages(&inode->i_data, 0); |
| 1274 | clear_inode(inode); | 1291 | clear_inode(inode); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 51803528b095..955e34615cb7 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -2156,6 +2156,7 @@ extern ino_t iunique(struct super_block *, ino_t); | |||
| 2156 | extern int inode_needs_sync(struct inode *inode); | 2156 | extern int inode_needs_sync(struct inode *inode); |
| 2157 | extern void generic_delete_inode(struct inode *inode); | 2157 | extern void generic_delete_inode(struct inode *inode); |
| 2158 | extern void generic_drop_inode(struct inode *inode); | 2158 | extern void generic_drop_inode(struct inode *inode); |
| 2159 | extern int generic_detach_inode(struct inode *inode); | ||
| 2159 | 2160 | ||
| 2160 | extern struct inode *ilookup5_nowait(struct super_block *sb, | 2161 | extern struct inode *ilookup5_nowait(struct super_block *sb, |
| 2161 | unsigned long hashval, int (*test)(struct inode *, void *), | 2162 | unsigned long hashval, int (*test)(struct inode *, void *), |
