diff options
author | Dmitry Monakhov <dmonakhov@openvz.org> | 2010-05-07 11:35:44 +0200 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2010-05-17 13:00:41 +0200 |
commit | 5547e8aac6f71505d621a612de2fca0dd988b439 (patch) | |
tree | 36bb4a62fe5773c5acd43c9e72dca1c2f32b1bff | |
parent | writeback: fix WB_SYNC_NONE writeback from umount (diff) | |
download | linux-5547e8aac6f71505d621a612de2fca0dd988b439.tar.xz linux-5547e8aac6f71505d621a612de2fca0dd988b439.zip |
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>
-rw-r--r-- | fs/fs-writeback.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 67db89786e7d..0f629571234f 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -460,11 +460,9 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) BUG_ON(inode->i_state & I_SYNC); - /* Set I_SYNC, reset I_DIRTY */ - dirty = inode->i_state & I_DIRTY; + /* Set I_SYNC, reset I_DIRTY_PAGES */ inode->i_state |= I_SYNC; - inode->i_state &= ~I_DIRTY; - + inode->i_state &= ~I_DIRTY_PAGES; spin_unlock(&inode_lock); ret = do_writepages(mapping, wbc); @@ -480,6 +478,15 @@ writeback_single_inode(struct inode *inode, struct writeback_control *wbc) 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 */ if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { int err = write_inode(inode, wbc); |