aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2016-06-20 20:02:23 -0400
committerDave Chinner <david@fromorbit.com>2016-06-20 20:02:23 -0400
commit3c2bdc912a1cc050db7e858aabe564cb382c9c30 (patch)
tree61eb71132006f1cb787838feebab310016c5d9bf
parentbdb0d04fa66d8d02219ca7c027adf810dd75e9e4 (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.c133
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 */
1103STATIC int
1104xfs_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
1187static int 1092static int
1188xfs_unmap_extent( 1093xfs_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/*