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>
This commit is contained in:
parent
4d4eb36679
commit
99a3891924
16
fs/inode.c
16
fs/inode.c
@ -28,7 +28,6 @@
|
||||
/*
|
||||
* This is needed for the following functions:
|
||||
* - inode_has_buffers
|
||||
* - invalidate_inode_buffers
|
||||
* - invalidate_bdev
|
||||
*
|
||||
* 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)
|
||||
inode = list_entry(tmp, struct inode, i_sb_list);
|
||||
if (inode->i_state & I_NEW)
|
||||
continue;
|
||||
invalidate_inode_buffers(inode);
|
||||
if (!atomic_read(&inode->i_count)) {
|
||||
list_move(&inode->i_list, dispose);
|
||||
WARN_ON(inode->i_state & I_NEW);
|
||||
inode->i_state |= I_FREEING;
|
||||
if (!(inode->i_state & (I_DIRTY | I_SYNC)))
|
||||
percpu_counter_dec(&nr_inodes_unused);
|
||||
if (atomic_read(&inode->i_count)) {
|
||||
busy = 1;
|
||||
continue;
|
||||
}
|
||||
busy = 1;
|
||||
|
||||
list_move(&inode->i_list, dispose);
|
||||
inode->i_state |= I_FREEING;
|
||||
if (!(inode->i_state & (I_DIRTY | I_SYNC)))
|
||||
percpu_counter_dec(&nr_inodes_unused);
|
||||
}
|
||||
return busy;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user