diff options
author | Christoph Hellwig <hch@lst.de> | 2016-06-20 20:02:23 -0400 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2016-06-20 20:02:23 -0400 |
commit | 3c2bdc912a1cc050db7e858aabe564cb382c9c30 (patch) | |
tree | 61eb71132006f1cb787838feebab310016c5d9bf | |
parent | bdb0d04fa66d8d02219ca7c027adf810dd75e9e4 (diff) |
xfs: kill xfs_zero_remaining_bytes
Instead punch the whole first, and the use the our zeroing helper
to punch out the edge blocks.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
-rw-r--r-- | fs/xfs/xfs_bmap_util.c | 133 |
1 files changed, 14 insertions, 119 deletions
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index e36664fc5715..569f03ddd41c 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c | |||
@@ -1089,101 +1089,6 @@ error1: /* Just cancel transaction */ | |||
1089 | return error; | 1089 | return error; |
1090 | } | 1090 | } |
1091 | 1091 | ||
1092 | /* | ||
1093 | * Zero file bytes between startoff and endoff inclusive. | ||
1094 | * The iolock is held exclusive and no blocks are buffered. | ||
1095 | * | ||
1096 | * This function is used by xfs_free_file_space() to zero | ||
1097 | * partial blocks when the range to free is not block aligned. | ||
1098 | * When unreserving space with boundaries that are not block | ||
1099 | * aligned we round up the start and round down the end | ||
1100 | * boundaries and then use this function to zero the parts of | ||
1101 | * the blocks that got dropped during the rounding. | ||
1102 | */ | ||
1103 | STATIC int | ||
1104 | xfs_zero_remaining_bytes( | ||
1105 | xfs_inode_t *ip, | ||
1106 | xfs_off_t startoff, | ||
1107 | xfs_off_t endoff) | ||
1108 | { | ||
1109 | xfs_bmbt_irec_t imap; | ||
1110 | xfs_fileoff_t offset_fsb; | ||
1111 | xfs_off_t lastoffset; | ||
1112 | xfs_off_t offset; | ||
1113 | xfs_buf_t *bp; | ||
1114 | xfs_mount_t *mp = ip->i_mount; | ||
1115 | int nimap; | ||
1116 | int error = 0; | ||
1117 | |||
1118 | /* | ||
1119 | * Avoid doing I/O beyond eof - it's not necessary | ||
1120 | * since nothing can read beyond eof. The space will | ||
1121 | * be zeroed when the file is extended anyway. | ||
1122 | */ | ||
1123 | if (startoff >= XFS_ISIZE(ip)) | ||
1124 | return 0; | ||
1125 | |||
1126 | if (endoff > XFS_ISIZE(ip)) | ||
1127 | endoff = XFS_ISIZE(ip); | ||
1128 | |||
1129 | for (offset = startoff; offset <= endoff; offset = lastoffset + 1) { | ||
1130 | uint lock_mode; | ||
1131 | |||
1132 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | ||
1133 | nimap = 1; | ||
1134 | |||
1135 | lock_mode = xfs_ilock_data_map_shared(ip); | ||
1136 | error = xfs_bmapi_read(ip, offset_fsb, 1, &imap, &nimap, 0); | ||
1137 | xfs_iunlock(ip, lock_mode); | ||
1138 | |||
1139 | if (error || nimap < 1) | ||
1140 | break; | ||
1141 | ASSERT(imap.br_blockcount >= 1); | ||
1142 | ASSERT(imap.br_startoff == offset_fsb); | ||
1143 | ASSERT(imap.br_startblock != DELAYSTARTBLOCK); | ||
1144 | |||
1145 | if (imap.br_startblock == HOLESTARTBLOCK || | ||
1146 | imap.br_state == XFS_EXT_UNWRITTEN) { | ||
1147 | /* skip the entire extent */ | ||
1148 | lastoffset = XFS_FSB_TO_B(mp, imap.br_startoff + | ||
1149 | imap.br_blockcount) - 1; | ||
1150 | continue; | ||
1151 | } | ||
1152 | |||
1153 | lastoffset = XFS_FSB_TO_B(mp, imap.br_startoff + 1) - 1; | ||
1154 | if (lastoffset > endoff) | ||
1155 | lastoffset = endoff; | ||
1156 | |||
1157 | /* DAX can just zero the backing device directly */ | ||
1158 | if (IS_DAX(VFS_I(ip))) { | ||
1159 | error = dax_zero_page_range(VFS_I(ip), offset, | ||
1160 | lastoffset - offset + 1, | ||
1161 | xfs_get_blocks_direct); | ||
1162 | if (error) | ||
1163 | return error; | ||
1164 | continue; | ||
1165 | } | ||
1166 | |||
1167 | error = xfs_buf_read_uncached(XFS_IS_REALTIME_INODE(ip) ? | ||
1168 | mp->m_rtdev_targp : mp->m_ddev_targp, | ||
1169 | xfs_fsb_to_db(ip, imap.br_startblock), | ||
1170 | BTOBB(mp->m_sb.sb_blocksize), | ||
1171 | 0, &bp, NULL); | ||
1172 | if (error) | ||
1173 | return error; | ||
1174 | |||
1175 | memset(bp->b_addr + | ||
1176 | (offset - XFS_FSB_TO_B(mp, imap.br_startoff)), | ||
1177 | 0, lastoffset - offset + 1); | ||
1178 | |||
1179 | error = xfs_bwrite(bp); | ||
1180 | xfs_buf_relse(bp); | ||
1181 | if (error) | ||
1182 | return error; | ||
1183 | } | ||
1184 | return error; | ||
1185 | } | ||
1186 | |||
1187 | static int | 1092 | static int |
1188 | xfs_unmap_extent( | 1093 | xfs_unmap_extent( |
1189 | struct xfs_inode *ip, | 1094 | struct xfs_inode *ip, |
@@ -1309,7 +1214,7 @@ xfs_free_file_space( | |||
1309 | struct xfs_mount *mp = ip->i_mount; | 1214 | struct xfs_mount *mp = ip->i_mount; |
1310 | xfs_fileoff_t startoffset_fsb; | 1215 | xfs_fileoff_t startoffset_fsb; |
1311 | xfs_fileoff_t endoffset_fsb; | 1216 | xfs_fileoff_t endoffset_fsb; |
1312 | int done, error; | 1217 | int done = 0, error; |
1313 | 1218 | ||
1314 | trace_xfs_free_file_space(ip); | 1219 | trace_xfs_free_file_space(ip); |
1315 | 1220 | ||
@@ -1341,31 +1246,21 @@ xfs_free_file_space( | |||
1341 | return error; | 1246 | return error; |
1342 | } | 1247 | } |
1343 | 1248 | ||
1344 | if ((done = (endoffset_fsb <= startoffset_fsb))) | 1249 | if (endoffset_fsb > startoffset_fsb) { |
1345 | /* | 1250 | while (!done) { |
1346 | * One contiguous piece to clear | 1251 | error = xfs_unmap_extent(ip, startoffset_fsb, |
1347 | */ | 1252 | endoffset_fsb - startoffset_fsb, &done); |
1348 | error = xfs_zero_remaining_bytes(ip, offset, offset + len - 1); | 1253 | if (error) |
1349 | else { | 1254 | return error; |
1350 | /* | 1255 | } |
1351 | * Some full blocks, possibly two pieces to clear | ||
1352 | */ | ||
1353 | if (offset < XFS_FSB_TO_B(mp, startoffset_fsb)) | ||
1354 | error = xfs_zero_remaining_bytes(ip, offset, | ||
1355 | XFS_FSB_TO_B(mp, startoffset_fsb) - 1); | ||
1356 | if (!error && | ||
1357 | XFS_FSB_TO_B(mp, endoffset_fsb) < offset + len) | ||
1358 | error = xfs_zero_remaining_bytes(ip, | ||
1359 | XFS_FSB_TO_B(mp, endoffset_fsb), | ||
1360 | offset + len - 1); | ||
1361 | } | ||
1362 | |||
1363 | while (!error && !done) { | ||
1364 | error = xfs_unmap_extent(ip, startoffset_fsb, | ||
1365 | endoffset_fsb - startoffset_fsb, &done); | ||
1366 | } | 1256 | } |
1367 | 1257 | ||
1368 | return error; | 1258 | /* |
1259 | * Now that we've unmap all full blocks we'll have to zero out any | ||
1260 | * partial block at the beginning and/or end. xfs_zero_range is | ||
1261 | * smart enough to skip any holes, including those we just created. | ||
1262 | */ | ||
1263 | return xfs_zero_range(ip, offset, len, NULL); | ||
1369 | } | 1264 | } |
1370 | 1265 | ||
1371 | /* | 1266 | /* |