diff options
Diffstat (limited to 'fs/xfs/xfs_iomap.c')
-rw-r--r-- | fs/xfs/xfs_iomap.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 41662fb14e87..288ee5b840d7 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
@@ -630,6 +630,11 @@ retry: | |||
630 | goto out_unlock; | 630 | goto out_unlock; |
631 | } | 631 | } |
632 | 632 | ||
633 | /* | ||
634 | * Flag newly allocated delalloc blocks with IOMAP_F_NEW so we punch | ||
635 | * them out if the write happens to fail. | ||
636 | */ | ||
637 | iomap->flags = IOMAP_F_NEW; | ||
633 | trace_xfs_iomap_alloc(ip, offset, count, 0, &got); | 638 | trace_xfs_iomap_alloc(ip, offset, count, 0, &got); |
634 | done: | 639 | done: |
635 | if (isnullstartblock(got.br_startblock)) | 640 | if (isnullstartblock(got.br_startblock)) |
@@ -1071,16 +1076,22 @@ xfs_file_iomap_end_delalloc( | |||
1071 | struct xfs_inode *ip, | 1076 | struct xfs_inode *ip, |
1072 | loff_t offset, | 1077 | loff_t offset, |
1073 | loff_t length, | 1078 | loff_t length, |
1074 | ssize_t written) | 1079 | ssize_t written, |
1080 | struct iomap *iomap) | ||
1075 | { | 1081 | { |
1076 | struct xfs_mount *mp = ip->i_mount; | 1082 | struct xfs_mount *mp = ip->i_mount; |
1077 | xfs_fileoff_t start_fsb; | 1083 | xfs_fileoff_t start_fsb; |
1078 | xfs_fileoff_t end_fsb; | 1084 | xfs_fileoff_t end_fsb; |
1079 | int error = 0; | 1085 | int error = 0; |
1080 | 1086 | ||
1081 | /* behave as if the write failed if drop writes is enabled */ | 1087 | /* |
1082 | if (xfs_mp_drop_writes(mp)) | 1088 | * Behave as if the write failed if drop writes is enabled. Set the NEW |
1089 | * flag to force delalloc cleanup. | ||
1090 | */ | ||
1091 | if (xfs_mp_drop_writes(mp)) { | ||
1092 | iomap->flags |= IOMAP_F_NEW; | ||
1083 | written = 0; | 1093 | written = 0; |
1094 | } | ||
1084 | 1095 | ||
1085 | /* | 1096 | /* |
1086 | * start_fsb refers to the first unused block after a short write. If | 1097 | * start_fsb refers to the first unused block after a short write. If |
@@ -1094,14 +1105,14 @@ xfs_file_iomap_end_delalloc( | |||
1094 | end_fsb = XFS_B_TO_FSB(mp, offset + length); | 1105 | end_fsb = XFS_B_TO_FSB(mp, offset + length); |
1095 | 1106 | ||
1096 | /* | 1107 | /* |
1097 | * Trim back delalloc blocks if we didn't manage to write the whole | 1108 | * Trim delalloc blocks if they were allocated by this write and we |
1098 | * range reserved. | 1109 | * didn't manage to write the whole range. |
1099 | * | 1110 | * |
1100 | * We don't need to care about racing delalloc as we hold i_mutex | 1111 | * We don't need to care about racing delalloc as we hold i_mutex |
1101 | * across the reserve/allocate/unreserve calls. If there are delalloc | 1112 | * across the reserve/allocate/unreserve calls. If there are delalloc |
1102 | * blocks in the range, they are ours. | 1113 | * blocks in the range, they are ours. |
1103 | */ | 1114 | */ |
1104 | if (start_fsb < end_fsb) { | 1115 | if ((iomap->flags & IOMAP_F_NEW) && start_fsb < end_fsb) { |
1105 | truncate_pagecache_range(VFS_I(ip), XFS_FSB_TO_B(mp, start_fsb), | 1116 | truncate_pagecache_range(VFS_I(ip), XFS_FSB_TO_B(mp, start_fsb), |
1106 | XFS_FSB_TO_B(mp, end_fsb) - 1); | 1117 | XFS_FSB_TO_B(mp, end_fsb) - 1); |
1107 | 1118 | ||
@@ -1131,7 +1142,7 @@ xfs_file_iomap_end( | |||
1131 | { | 1142 | { |
1132 | if ((flags & IOMAP_WRITE) && iomap->type == IOMAP_DELALLOC) | 1143 | if ((flags & IOMAP_WRITE) && iomap->type == IOMAP_DELALLOC) |
1133 | return xfs_file_iomap_end_delalloc(XFS_I(inode), offset, | 1144 | return xfs_file_iomap_end_delalloc(XFS_I(inode), offset, |
1134 | length, written); | 1145 | length, written, iomap); |
1135 | return 0; | 1146 | return 0; |
1136 | } | 1147 | } |
1137 | 1148 | ||