diff options
-rw-r--r-- | fs/fs-writeback.c | 29 |
1 files changed, 22 insertions, 7 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index ef9bef118342..2d609a5fbfea 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -479,12 +479,28 @@ __writeback_single_inode(struct inode *inode, struct writeback_control *wbc) | |||
479 | * write_inode() | 479 | * write_inode() |
480 | */ | 480 | */ |
481 | spin_lock(&inode->i_lock); | 481 | spin_lock(&inode->i_lock); |
482 | /* Clear I_DIRTY_PAGES if we've written out all dirty pages */ | 482 | |
483 | if (!mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) | ||
484 | inode->i_state &= ~I_DIRTY_PAGES; | ||
485 | dirty = inode->i_state & I_DIRTY; | 483 | dirty = inode->i_state & I_DIRTY; |
486 | inode->i_state &= ~(I_DIRTY_SYNC | I_DIRTY_DATASYNC); | 484 | inode->i_state &= ~I_DIRTY; |
485 | |||
486 | /* | ||
487 | * Paired with smp_mb() in __mark_inode_dirty(). This allows | ||
488 | * __mark_inode_dirty() to test i_state without grabbing i_lock - | ||
489 | * either they see the I_DIRTY bits cleared or we see the dirtied | ||
490 | * inode. | ||
491 | * | ||
492 | * I_DIRTY_PAGES is always cleared together above even if @mapping | ||
493 | * still has dirty pages. The flag is reinstated after smp_mb() if | ||
494 | * necessary. This guarantees that either __mark_inode_dirty() | ||
495 | * sees clear I_DIRTY_PAGES or we see PAGECACHE_TAG_DIRTY. | ||
496 | */ | ||
497 | smp_mb(); | ||
498 | |||
499 | if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) | ||
500 | inode->i_state |= I_DIRTY_PAGES; | ||
501 | |||
487 | spin_unlock(&inode->i_lock); | 502 | spin_unlock(&inode->i_lock); |
503 | |||
488 | /* Don't write the inode if only I_DIRTY_PAGES was set */ | 504 | /* Don't write the inode if only I_DIRTY_PAGES was set */ |
489 | if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { | 505 | if (dirty & (I_DIRTY_SYNC | I_DIRTY_DATASYNC)) { |
490 | int err = write_inode(inode, wbc); | 506 | int err = write_inode(inode, wbc); |
@@ -1148,12 +1164,11 @@ void __mark_inode_dirty(struct inode *inode, int flags) | |||
1148 | } | 1164 | } |
1149 | 1165 | ||
1150 | /* | 1166 | /* |
1151 | * make sure that changes are seen by all cpus before we test i_state | 1167 | * Paired with smp_mb() in __writeback_single_inode() for the |
1152 | * -- mikulas | 1168 | * following lockless i_state test. See there for details. |
1153 | */ | 1169 | */ |
1154 | smp_mb(); | 1170 | smp_mb(); |
1155 | 1171 | ||
1156 | /* avoid the locking if we can */ | ||
1157 | if ((inode->i_state & flags) == flags) | 1172 | if ((inode->i_state & flags) == flags) |
1158 | return; | 1173 | return; |
1159 | 1174 | ||