aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>2013-12-03 20:15:54 +0900
committerDaniel Phillips <daniel@tux3.org>2013-12-03 20:15:54 +0900
commitf0cadb5f5f15c5c159eabead0a79af995e59033e (patch)
tree0b414c77abbe6c33c34e42e62f14014073bf5b14
parentecbf36f4028a510a1ecc0392f1cd142967132431 (diff)
downloadlinux-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.c29
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);