aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2010-10-23 13:07:20 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2010-10-25 21:26:14 -0400
commit99a38919241fd051b8d93b2e4d0c05ef0556d795 (patch)
tree6d42602c4663645412e3c11dc31211a28b285594 /fs
parent4d4eb36679adbdd75495e1bbfe7ac40e4ae41dea (diff)
fs: fix buffer invalidation in invalidate_list
We must not call invalidate_inode_buffers in invalidate_list unless the inode can be reclaimed. If we remove the buffer association of a busy inode fsync won't find the buffers anymore. As invalidate_inode_buffers is called from various others sources than umount this actually does matter in practice. While at it change the loop to a more natural form and remove the WARN_ON for I_NEW, wich we already tested a few lines above. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/inode.c16
1 files changed, 7 insertions, 9 deletions
diff --git a/fs/inode.c b/fs/inode.c
index 2cd2e48f7a20..4bedac32154f 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -28,7 +28,6 @@
28/* 28/*
29 * This is needed for the following functions: 29 * This is needed for the following functions:
30 * - inode_has_buffers 30 * - inode_has_buffers
31 * - invalidate_inode_buffers
32 * - invalidate_bdev 31 * - invalidate_bdev
33 * 32 *
34 * FIXME: remove all knowledge of the buffer layer from this file 33 * FIXME: remove all knowledge of the buffer layer from this file
@@ -503,16 +502,15 @@ static int invalidate_list(struct list_head *head, struct list_head *dispose)
503 inode = list_entry(tmp, struct inode, i_sb_list); 502 inode = list_entry(tmp, struct inode, i_sb_list);
504 if (inode->i_state & I_NEW) 503 if (inode->i_state & I_NEW)
505 continue; 504 continue;
506 invalidate_inode_buffers(inode); 505 if (atomic_read(&inode->i_count)) {
507 if (!atomic_read(&inode->i_count)) { 506 busy = 1;
508 list_move(&inode->i_list, dispose);
509 WARN_ON(inode->i_state & I_NEW);
510 inode->i_state |= I_FREEING;
511 if (!(inode->i_state & (I_DIRTY | I_SYNC)))
512 percpu_counter_dec(&nr_inodes_unused);
513 continue; 507 continue;
514 } 508 }
515 busy = 1; 509
510 list_move(&inode->i_list, dispose);
511 inode->i_state |= I_FREEING;
512 if (!(inode->i_state & (I_DIRTY | I_SYNC)))
513 percpu_counter_dec(&nr_inodes_unused);
516 } 514 }
517 return busy; 515 return busy;
518} 516}