diff options
author | OGAWA Hirofumi <hirofumi@mail.parknet.co.jp> | 2013-12-03 20:15:54 +0900 |
---|---|---|
committer | Daniel Phillips <daniel@tux3.org> | 2013-12-03 20:15:54 +0900 |
commit | f0cadb5f5f15c5c159eabead0a79af995e59033e (patch) | |
tree | 0b414c77abbe6c33c34e42e62f14014073bf5b14 | |
parent | ecbf36f4028a510a1ecc0392f1cd142967132431 (diff) | |
download | linux-tux3-f0cadb5f5f15c5c159eabead0a79af995e59033e.tar.gz |
tux3: Remove unnecesarry I_DIRTY in tux3_clear_dirty_inode_nolock()
If tux3_clear_dirty_inode_nolock() was called for frontend delta,
inode should has I_DIRTY already. Otherwise, by following race, delta
dirty and I_DIRTY become inconsistent state.
cpu0 cpu1
__tux3_mark_inode_dirty()
tux3_dirty_inode()
mark delta0 dirty
tux3_clear_dirty_inode_nolock()
clear I_DIRTY and delta0
__mark_inode_dirty()
mark I_DIRTY
Therefore, tux3_clear_dirty_inode_nolock() should be called only for
backend delta, i.e. inode should be marked as I_DIRTY. So, this patch
removes unnecessary "inode->i_state |= I_DIRTY".
Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
-rw-r--r-- | fs/tux3/writeback.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/fs/tux3/writeback.c b/fs/tux3/writeback.c index b7b2eb49c8a989..02d4173d9c4372 100644 --- a/fs/tux3/writeback.c +++ b/fs/tux3/writeback.c @@ -221,7 +221,23 @@ static inline void tux3_inode_wb_list_del(struct inode *inode) #endif } -/* Clear dirty flags for delta (caller must hold inode->i_lock/tuxnode->lock) */ +/* + * Clear dirty flags for delta (caller must hold inode->i_lock/tuxnode->lock). + * + * Note: This can race with *_mark_inode_dirty(). + * + * cpu0 cpu1 + * __tux3_mark_inode_dirty() + * tux3_dirty_inode() + * mark delta dirty + * tux3_clear_dirty_inode_nolock() + * clear core dirty and delta + * __mark_inode_dirty() + * mark core dirty + * + * For this race, we can't use this to clear dirty for frontend delta + * (exception is the points which has no race like umount). + */ static void tux3_clear_dirty_inode_nolock(struct inode *inode, unsigned delta, int frontend) { @@ -248,10 +264,8 @@ static void tux3_clear_dirty_inode_nolock(struct inode *inode, unsigned delta, spin_unlock(&sb->dirty_inodes_lock); } - /* Update inode state */ - if (tuxnode->flags & ~NON_DIRTY_FLAGS) - inode->i_state |= I_DIRTY; - else { + /* Update state if inode isn't dirty anymore */ + if (!(tuxnode->flags & ~NON_DIRTY_FLAGS)) { inode->i_state &= ~I_DIRTY; tux3_inode_wb_list_del(inode); } @@ -270,7 +284,10 @@ static void __tux3_clear_dirty_inode(struct inode *inode, unsigned delta) tux3_inode_wb_unlock(inode); } -/* Clear dirty flags for frontend delta */ +/* + * Clear dirty flags for frontend delta. + * Note: see comment of tux3_clear_dirty_inode_nolock) + */ void tux3_clear_dirty_inode(struct inode *inode) { struct tux3_inode *tuxnode = tux_inode(inode); |