diff options
author | David Chinner <dgc@sgi.com> | 2007-06-18 02:49:58 -0400 |
---|---|---|
committer | Tim Shimmin <tes@chook.melbourne.sgi.com> | 2007-07-14 01:32:49 -0400 |
commit | effd120edb7609069cca9f3d1cb4bfae464b2f85 (patch) | |
tree | 3183077b16d0af765bce44a4a3df5e6d37f78fc8 /fs/xfs/linux-2.6 | |
parent | 45c34141126a89da07197d5b89c04c6847f1171a (diff) |
[XFS] Map unwritten extents correctly for I/o completion processing
If we have multiple unwritten extents within a single page, we fail to
tell the I/o completion construction handlers we need a new handle for the
second and subsequent blocks in the page. While we still issue the I/O
correctly, we do not have the correct ranges recorded in the ioend
structures and hence when we go to convert the unwritten extents we screw
it up.
Make sure we start a new ioend every time the mapping changes so that we
convert the correct ranges on I/O completion.
SGI-PV: 964647
SGI-Modid: xfs-linux-melb:xfs-kern:28797a
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Tim Shimmin <tes@sgi.com>
Diffstat (limited to 'fs/xfs/linux-2.6')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_aops.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index c097e4e69768..fd4105d662e0 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -1010,6 +1010,8 @@ xfs_page_state_convert( | |||
1010 | if (buffer_unwritten(bh) || buffer_delay(bh) || | 1010 | if (buffer_unwritten(bh) || buffer_delay(bh) || |
1011 | ((buffer_uptodate(bh) || PageUptodate(page)) && | 1011 | ((buffer_uptodate(bh) || PageUptodate(page)) && |
1012 | !buffer_mapped(bh) && (unmapped || startio))) { | 1012 | !buffer_mapped(bh) && (unmapped || startio))) { |
1013 | int new_ioend = 0; | ||
1014 | |||
1013 | /* | 1015 | /* |
1014 | * Make sure we don't use a read-only iomap | 1016 | * Make sure we don't use a read-only iomap |
1015 | */ | 1017 | */ |
@@ -1028,6 +1030,15 @@ xfs_page_state_convert( | |||
1028 | } | 1030 | } |
1029 | 1031 | ||
1030 | if (!iomap_valid) { | 1032 | if (!iomap_valid) { |
1033 | /* | ||
1034 | * if we didn't have a valid mapping then we | ||
1035 | * need to ensure that we put the new mapping | ||
1036 | * in a new ioend structure. This needs to be | ||
1037 | * done to ensure that the ioends correctly | ||
1038 | * reflect the block mappings at io completion | ||
1039 | * for unwritten extent conversion. | ||
1040 | */ | ||
1041 | new_ioend = 1; | ||
1031 | if (type == IOMAP_NEW) { | 1042 | if (type == IOMAP_NEW) { |
1032 | size = xfs_probe_cluster(inode, | 1043 | size = xfs_probe_cluster(inode, |
1033 | page, bh, head, 0); | 1044 | page, bh, head, 0); |
@@ -1047,7 +1058,7 @@ xfs_page_state_convert( | |||
1047 | if (startio) { | 1058 | if (startio) { |
1048 | xfs_add_to_ioend(inode, bh, offset, | 1059 | xfs_add_to_ioend(inode, bh, offset, |
1049 | type, &ioend, | 1060 | type, &ioend, |
1050 | !iomap_valid); | 1061 | new_ioend); |
1051 | } else { | 1062 | } else { |
1052 | set_buffer_dirty(bh); | 1063 | set_buffer_dirty(bh); |
1053 | unlock_buffer(bh); | 1064 | unlock_buffer(bh); |