aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2009-09-18 16:05:44 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2009-09-24 07:47:25 -0400
commit22fe404218156328a27e66349b1175cd0baa4990 (patch)
treef03f8eb0b346a6950815212a5fa86c6b7e65bd16
parentaf0d9ae811d11de8a01d6bc922c5e062be01bd7f (diff)
vfs: split generic_forget_inode() so that hugetlbfs does not have to copy it
Hugetlbfs needs to do special things instead of truncate_inode_pages(). Currently, it copied generic_forget_inode() except for truncate_inode_pages() call which is asking for trouble (the code there isn't trivial). So create a separate function generic_detach_inode() which does all the list magic done in generic_forget_inode() and call it from hugetlbfs_forget_inode(). Signed-off-by: Jan Kara <jack@suse.cz> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/hugetlbfs/inode.c33
-rw-r--r--fs/inode.c21
-rw-r--r--include/linux/fs.h1
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
381static void hugetlbfs_forget_inode(struct inode *inode) __releases(inode_lock) 381static 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
415static void hugetlbfs_drop_inode(struct inode *inode) 390static 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}
1242EXPORT_SYMBOL(generic_delete_inode); 1242EXPORT_SYMBOL(generic_delete_inode);
1243 1243
1244static 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 */
1253int 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}
1283EXPORT_SYMBOL_GPL(generic_detach_inode);
1284
1285static 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);
2156extern int inode_needs_sync(struct inode *inode); 2156extern int inode_needs_sync(struct inode *inode);
2157extern void generic_delete_inode(struct inode *inode); 2157extern void generic_delete_inode(struct inode *inode);
2158extern void generic_drop_inode(struct inode *inode); 2158extern void generic_drop_inode(struct inode *inode);
2159extern int generic_detach_inode(struct inode *inode);
2159 2160
2160extern struct inode *ilookup5_nowait(struct super_block *sb, 2161extern 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 *),