| From hch@infradead.org Tue Nov 22 13:31:23 2011 |
| From: Christoph Hellwig <hch@infradead.org> |
| Date: Sat, 19 Nov 2011 13:13:38 -0500 |
| Subject: xfs: fix xfs_mark_inode_dirty during umount |
| To: stable@vger.kernel.org |
| Cc: xfs@oss.sgi.com, Alex Elder <aelder@sgi.com> |
| Message-ID: <20111119181543.605305176@bombadil.infradead.org> |
| |
| From: Christoph Hellwig <hch@infradead.org> |
| |
| commit 866e4ed77448a0c311e1b055eb72ea05423fd799 upstream. |
| |
| During umount we do not add a dirty inode to the lru and wait for it to |
| become clean first, but force writeback of data and metadata with |
| I_WILL_FREE set. Currently there is no way for XFS to detect that the |
| inode has been redirtied for metadata operations, as we skip the |
| mark_inode_dirty call during teardown. Fix this by setting i_update_core |
| nanually in that case, so that the inode gets flushed during inode reclaim. |
| |
| Alternatively we could enable calling mark_inode_dirty for inodes in |
| I_WILL_FREE state, and let the VFS dirty tracking handle this. I decided |
| against this as we will get better I/O patterns from reclaim compared to |
| the synchronous writeout in write_inode_now, and always marking the inode |
| dirty in some way from xfs_mark_inode_dirty is a better safetly net in |
| either case. |
| |
| Signed-off-by: Christoph Hellwig <hch@lst.de> |
| Reviewed-by: Dave Chinner <dchinner@redhat.com> |
| Signed-off-by: Alex Elder <aelder@sgi.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| --- |
| fs/xfs/linux-2.6/xfs_iops.c | 14 +++++++++++--- |
| 1 file changed, 11 insertions(+), 3 deletions(-) |
| |
| --- a/fs/xfs/linux-2.6/xfs_iops.c |
| +++ b/fs/xfs/linux-2.6/xfs_iops.c |
| @@ -69,9 +69,8 @@ xfs_synchronize_times( |
| } |
| |
| /* |
| - * If the linux inode is valid, mark it dirty. |
| - * Used when committing a dirty inode into a transaction so that |
| - * the inode will get written back by the linux code |
| + * If the linux inode is valid, mark it dirty, else mark the dirty state |
| + * in the XFS inode to make sure we pick it up when reclaiming the inode. |
| */ |
| void |
| xfs_mark_inode_dirty_sync( |
| @@ -81,6 +80,10 @@ xfs_mark_inode_dirty_sync( |
| |
| if (!(inode->i_state & (I_WILL_FREE|I_FREEING))) |
| mark_inode_dirty_sync(inode); |
| + else { |
| + barrier(); |
| + ip->i_update_core = 1; |
| + } |
| } |
| |
| void |
| @@ -91,6 +94,11 @@ xfs_mark_inode_dirty( |
| |
| if (!(inode->i_state & (I_WILL_FREE|I_FREEING))) |
| mark_inode_dirty(inode); |
| + else { |
| + barrier(); |
| + ip->i_update_core = 1; |
| + } |
| + |
| } |
| |
| /* |