writeback: Update dirty flags in two steps

Filesystems with delalloc support may dirty inode during writepages.
As result inode will have dirty metadata flags even after write_inode.
In fact we have two dedicated functions for proper data and metadata
writeback. It is reasonable to separate flags updates in two stages.

https://bugzilla.kernel.org/show_bug.cgi?id=15906

Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
This commit is contained in:
Dmitry Monakhov 2010-05-07 13:35:44 +04:00 committed by Jens Axboe
parent e913fc825d
commit 5547e8aac6

View file

@ -460,11 +460,9 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
BUG_ON(inode->i_state & I_SYNC); BUG_ON(inode->i_state & I_SYNC);
/* Set I_SYNC, reset I_DIRTY */ /* Set I_SYNC, reset I_DIRTY_PAGES */
dirty = inode->i_state & I_DIRTY;
inode->i_state |= I_SYNC; inode->i_state |= I_SYNC;
inode->i_state &= ~I_DIRTY; inode->i_state &= ~I_DIRTY_PAGES;
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
ret = do_writepages(mapping, wbc); ret = do_writepages(mapping, wbc);
@ -480,6 +478,15 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc)
ret = err; ret = err;
} }
/*
* Some filesystems may redirty the inode during the writeback
* due to delalloc, clear dirty metadata flags right before
* write_inode()
*/
spin_lock(&inode_lock);
dirty = inode->i_state & I_DIRTY;
inode->i_state &= ~(I_DIRTY_SYNC | I_DIRTY_DATASYNC);
spin_unlock(&inode_lock);
/* Don't write the inode if only I_DIRTY_PAGES was set */ /* Don't write the inode if only I_DIRTY_PAGES was set */
if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) {
int err = write_inode(inode, wbc); int err = write_inode(inode, wbc);