aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ntfs/runlist.c
diff options
context:
space:
mode:
authorAnton Altaparmakov <aia21@cantab.net>2005-06-25 12:15:36 -0400
committerAnton Altaparmakov <aia21@cantab.net>2005-06-25 12:15:36 -0400
commitfa3be92317c4ae34edcf5274e8bbeff181e20b7a (patch)
tree84ae4ace6c891aa95b804950283e1f8f3e46c730 /fs/ntfs/runlist.c
parent1d58b27b8d77ecb816cfa8f846b78c845675eb89 (diff)
NTFS: Add an extra parameter @last_vcn to ntfs_get_size_for_mapping_pairs()
and ntfs_mapping_pairs_build() to allow the runlist encoding to be partial which is desirable when filling holes in sparse attributes. Update all callers. Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
Diffstat (limited to 'fs/ntfs/runlist.c')
-rw-r--r--fs/ntfs/runlist.c167
1 files changed, 117 insertions, 50 deletions
diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c
index 396d767c2cab..758855b0414e 100644
--- a/fs/ntfs/runlist.c
+++ b/fs/ntfs/runlist.c
@@ -1048,10 +1048,17 @@ static inline int ntfs_get_nr_significant_bytes(const s64 n)
1048 * ntfs_get_size_for_mapping_pairs - get bytes needed for mapping pairs array 1048 * ntfs_get_size_for_mapping_pairs - get bytes needed for mapping pairs array
1049 * @vol: ntfs volume (needed for the ntfs version) 1049 * @vol: ntfs volume (needed for the ntfs version)
1050 * @rl: locked runlist to determine the size of the mapping pairs of 1050 * @rl: locked runlist to determine the size of the mapping pairs of
1051 * @start_vcn: vcn at which to start the mapping pairs array 1051 * @first_vcn: first vcn which to include in the mapping pairs array
1052 * @last_vcn: last vcn which to include in the mapping pairs array
1052 * 1053 *
1053 * Walk the locked runlist @rl and calculate the size in bytes of the mapping 1054 * Walk the locked runlist @rl and calculate the size in bytes of the mapping
1054 * pairs array corresponding to the runlist @rl, starting at vcn @start_vcn. 1055 * pairs array corresponding to the runlist @rl, starting at vcn @first_vcn and
1056 * finishing with vcn @last_vcn.
1057 *
1058 * A @last_vcn of -1 means end of runlist and in that case the size of the
1059 * mapping pairs array corresponding to the runlist starting at vcn @first_vcn
1060 * and finishing at the end of the runlist is determined.
1061 *
1055 * This for example allows us to allocate a buffer of the right size when 1062 * This for example allows us to allocate a buffer of the right size when
1056 * building the mapping pairs array. 1063 * building the mapping pairs array.
1057 * 1064 *
@@ -1067,34 +1074,50 @@ static inline int ntfs_get_nr_significant_bytes(const s64 n)
1067 * remains locked throughout, and is left locked upon return. 1074 * remains locked throughout, and is left locked upon return.
1068 */ 1075 */
1069int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol, 1076int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
1070 const runlist_element *rl, const VCN start_vcn) 1077 const runlist_element *rl, const VCN first_vcn,
1078 const VCN last_vcn)
1071{ 1079{
1072 LCN prev_lcn; 1080 LCN prev_lcn;
1073 int rls; 1081 int rls;
1082 BOOL the_end = FALSE;
1074 1083
1075 BUG_ON(start_vcn < 0); 1084 BUG_ON(first_vcn < 0);
1085 BUG_ON(last_vcn < -1);
1086 BUG_ON(last_vcn >= 0 && first_vcn > last_vcn);
1076 if (!rl) { 1087 if (!rl) {
1077 BUG_ON(start_vcn); 1088 BUG_ON(first_vcn);
1089 BUG_ON(last_vcn > 0);
1078 return 1; 1090 return 1;
1079 } 1091 }
1080 /* Skip to runlist element containing @start_vcn. */ 1092 /* Skip to runlist element containing @first_vcn. */
1081 while (rl->length && start_vcn >= rl[1].vcn) 1093 while (rl->length && first_vcn >= rl[1].vcn)
1082 rl++; 1094 rl++;
1083 if ((!rl->length && start_vcn > rl->vcn) || start_vcn < rl->vcn) 1095 if (unlikely((!rl->length && first_vcn > rl->vcn) ||
1096 first_vcn < rl->vcn))
1084 return -EINVAL; 1097 return -EINVAL;
1085 prev_lcn = 0; 1098 prev_lcn = 0;
1086 /* Always need the termining zero byte. */ 1099 /* Always need the termining zero byte. */
1087 rls = 1; 1100 rls = 1;
1088 /* Do the first partial run if present. */ 1101 /* Do the first partial run if present. */
1089 if (start_vcn > rl->vcn) { 1102 if (first_vcn > rl->vcn) {
1090 s64 delta; 1103 s64 delta, length = rl->length;
1091 1104
1092 /* We know rl->length != 0 already. */ 1105 /* We know rl->length != 0 already. */
1093 if (rl->length < 0 || rl->lcn < LCN_HOLE) 1106 if (unlikely(length < 0 || rl->lcn < LCN_HOLE))
1094 goto err_out; 1107 goto err_out;
1095 delta = start_vcn - rl->vcn; 1108 /*
1109 * If @stop_vcn is given and finishes inside this run, cap the
1110 * run length.
1111 */
1112 if (unlikely(last_vcn >= 0 && rl[1].vcn > last_vcn)) {
1113 s64 s1 = last_vcn + 1;
1114 if (unlikely(rl[1].vcn > s1))
1115 length = s1 - rl->vcn;
1116 the_end = TRUE;
1117 }
1118 delta = first_vcn - rl->vcn;
1096 /* Header byte + length. */ 1119 /* Header byte + length. */
1097 rls += 1 + ntfs_get_nr_significant_bytes(rl->length - delta); 1120 rls += 1 + ntfs_get_nr_significant_bytes(length - delta);
1098 /* 1121 /*
1099 * If the logical cluster number (lcn) denotes a hole and we 1122 * If the logical cluster number (lcn) denotes a hole and we
1100 * are on NTFS 3.0+, we don't store it at all, i.e. we need 1123 * are on NTFS 3.0+, we don't store it at all, i.e. we need
@@ -1102,9 +1125,9 @@ int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
1102 * Note: this assumes that on NTFS 1.2-, holes are stored with 1125 * Note: this assumes that on NTFS 1.2-, holes are stored with
1103 * an lcn of -1 and not a delta_lcn of -1 (unless both are -1). 1126 * an lcn of -1 and not a delta_lcn of -1 (unless both are -1).
1104 */ 1127 */
1105 if (rl->lcn >= 0 || vol->major_ver < 3) { 1128 if (likely(rl->lcn >= 0 || vol->major_ver < 3)) {
1106 prev_lcn = rl->lcn; 1129 prev_lcn = rl->lcn;
1107 if (rl->lcn >= 0) 1130 if (likely(rl->lcn >= 0))
1108 prev_lcn += delta; 1131 prev_lcn += delta;
1109 /* Change in lcn. */ 1132 /* Change in lcn. */
1110 rls += ntfs_get_nr_significant_bytes(prev_lcn); 1133 rls += ntfs_get_nr_significant_bytes(prev_lcn);
@@ -1113,11 +1136,23 @@ int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
1113 rl++; 1136 rl++;
1114 } 1137 }
1115 /* Do the full runs. */ 1138 /* Do the full runs. */
1116 for (; rl->length; rl++) { 1139 for (; rl->length && !the_end; rl++) {
1117 if (rl->length < 0 || rl->lcn < LCN_HOLE) 1140 s64 length = rl->length;
1141
1142 if (unlikely(length < 0 || rl->lcn < LCN_HOLE))
1118 goto err_out; 1143 goto err_out;
1144 /*
1145 * If @stop_vcn is given and finishes inside this run, cap the
1146 * run length.
1147 */
1148 if (unlikely(last_vcn >= 0 && rl[1].vcn > last_vcn)) {
1149 s64 s1 = last_vcn + 1;
1150 if (unlikely(rl[1].vcn > s1))
1151 length = s1 - rl->vcn;
1152 the_end = TRUE;
1153 }
1119 /* Header byte + length. */ 1154 /* Header byte + length. */
1120 rls += 1 + ntfs_get_nr_significant_bytes(rl->length); 1155 rls += 1 + ntfs_get_nr_significant_bytes(length);
1121 /* 1156 /*
1122 * If the logical cluster number (lcn) denotes a hole and we 1157 * If the logical cluster number (lcn) denotes a hole and we
1123 * are on NTFS 3.0+, we don't store it at all, i.e. we need 1158 * are on NTFS 3.0+, we don't store it at all, i.e. we need
@@ -1125,7 +1160,7 @@ int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol,
1125 * Note: this assumes that on NTFS 1.2-, holes are stored with 1160 * Note: this assumes that on NTFS 1.2-, holes are stored with
1126 * an lcn of -1 and not a delta_lcn of -1 (unless both are -1). 1161 * an lcn of -1 and not a delta_lcn of -1 (unless both are -1).
1127 */ 1162 */
1128 if (rl->lcn >= 0 || vol->major_ver < 3) { 1163 if (likely(rl->lcn >= 0 || vol->major_ver < 3)) {
1129 /* Change in lcn. */ 1164 /* Change in lcn. */
1130 rls += ntfs_get_nr_significant_bytes(rl->lcn - 1165 rls += ntfs_get_nr_significant_bytes(rl->lcn -
1131 prev_lcn); 1166 prev_lcn);
@@ -1168,7 +1203,7 @@ static inline int ntfs_write_significant_bytes(s8 *dst, const s8 *dst_max,
1168 1203
1169 i = 0; 1204 i = 0;
1170 do { 1205 do {
1171 if (dst > dst_max) 1206 if (unlikely(dst > dst_max))
1172 goto err_out; 1207 goto err_out;
1173 *dst++ = l & 0xffll; 1208 *dst++ = l & 0xffll;
1174 l >>= 8; 1209 l >>= 8;
@@ -1177,12 +1212,12 @@ static inline int ntfs_write_significant_bytes(s8 *dst, const s8 *dst_max,
1177 j = (n >> 8 * (i - 1)) & 0xff; 1212 j = (n >> 8 * (i - 1)) & 0xff;
1178 /* If the sign bit is wrong, we need an extra byte. */ 1213 /* If the sign bit is wrong, we need an extra byte. */
1179 if (n < 0 && j >= 0) { 1214 if (n < 0 && j >= 0) {
1180 if (dst > dst_max) 1215 if (unlikely(dst > dst_max))
1181 goto err_out; 1216 goto err_out;
1182 i++; 1217 i++;
1183 *dst = (s8)-1; 1218 *dst = (s8)-1;
1184 } else if (n > 0 && j < 0) { 1219 } else if (n > 0 && j < 0) {
1185 if (dst > dst_max) 1220 if (unlikely(dst > dst_max))
1186 goto err_out; 1221 goto err_out;
1187 i++; 1222 i++;
1188 *dst = (s8)0; 1223 *dst = (s8)0;
@@ -1198,13 +1233,18 @@ err_out:
1198 * @dst: destination buffer to which to write the mapping pairs array 1233 * @dst: destination buffer to which to write the mapping pairs array
1199 * @dst_len: size of destination buffer @dst in bytes 1234 * @dst_len: size of destination buffer @dst in bytes
1200 * @rl: locked runlist for which to build the mapping pairs array 1235 * @rl: locked runlist for which to build the mapping pairs array
1201 * @start_vcn: vcn at which to start the mapping pairs array 1236 * @first_vcn: first vcn which to include in the mapping pairs array
1237 * @last_vcn: last vcn which to include in the mapping pairs array
1202 * @stop_vcn: first vcn outside destination buffer on success or -ENOSPC 1238 * @stop_vcn: first vcn outside destination buffer on success or -ENOSPC
1203 * 1239 *
1204 * Create the mapping pairs array from the locked runlist @rl, starting at vcn 1240 * Create the mapping pairs array from the locked runlist @rl, starting at vcn
1205 * @start_vcn and save the array in @dst. @dst_len is the size of @dst in 1241 * @first_vcn and finishing with vcn @last_vcn and save the array in @dst.
1206 * bytes and it should be at least equal to the value obtained by calling 1242 * @dst_len is the size of @dst in bytes and it should be at least equal to the
1207 * ntfs_get_size_for_mapping_pairs(). 1243 * value obtained by calling ntfs_get_size_for_mapping_pairs().
1244 *
1245 * A @last_vcn of -1 means end of runlist and in that case the mapping pairs
1246 * array corresponding to the runlist starting at vcn @first_vcn and finishing
1247 * at the end of the runlist is created.
1208 * 1248 *
1209 * If @rl is NULL, just write a single terminator byte to @dst. 1249 * If @rl is NULL, just write a single terminator byte to @dst.
1210 * 1250 *
@@ -1213,7 +1253,7 @@ err_out:
1213 * been filled with all the mapping pairs that will fit, thus it can be treated 1253 * been filled with all the mapping pairs that will fit, thus it can be treated
1214 * as partial success, in that a new attribute extent needs to be created or 1254 * as partial success, in that a new attribute extent needs to be created or
1215 * the next extent has to be used and the mapping pairs build has to be 1255 * the next extent has to be used and the mapping pairs build has to be
1216 * continued with @start_vcn set to *@stop_vcn. 1256 * continued with @first_vcn set to *@stop_vcn.
1217 * 1257 *
1218 * Return 0 on success and -errno on error. The following error codes are 1258 * Return 0 on success and -errno on error. The following error codes are
1219 * defined: 1259 * defined:
@@ -1227,27 +1267,32 @@ err_out:
1227 */ 1267 */
1228int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst, 1268int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
1229 const int dst_len, const runlist_element *rl, 1269 const int dst_len, const runlist_element *rl,
1230 const VCN start_vcn, VCN *const stop_vcn) 1270 const VCN first_vcn, const VCN last_vcn, VCN *const stop_vcn)
1231{ 1271{
1232 LCN prev_lcn; 1272 LCN prev_lcn;
1233 s8 *dst_max, *dst_next; 1273 s8 *dst_max, *dst_next;
1234 int err = -ENOSPC; 1274 int err = -ENOSPC;
1275 BOOL the_end = FALSE;
1235 s8 len_len, lcn_len; 1276 s8 len_len, lcn_len;
1236 1277
1237 BUG_ON(start_vcn < 0); 1278 BUG_ON(first_vcn < 0);
1279 BUG_ON(last_vcn < -1);
1280 BUG_ON(last_vcn >= 0 && first_vcn > last_vcn);
1238 BUG_ON(dst_len < 1); 1281 BUG_ON(dst_len < 1);
1239 if (!rl) { 1282 if (!rl) {
1240 BUG_ON(start_vcn); 1283 BUG_ON(first_vcn);
1284 BUG_ON(last_vcn > 0);
1241 if (stop_vcn) 1285 if (stop_vcn)
1242 *stop_vcn = 0; 1286 *stop_vcn = 0;
1243 /* Terminator byte. */ 1287 /* Terminator byte. */
1244 *dst = 0; 1288 *dst = 0;
1245 return 0; 1289 return 0;
1246 } 1290 }
1247 /* Skip to runlist element containing @start_vcn. */ 1291 /* Skip to runlist element containing @first_vcn. */
1248 while (rl->length && start_vcn >= rl[1].vcn) 1292 while (rl->length && first_vcn >= rl[1].vcn)
1249 rl++; 1293 rl++;
1250 if ((!rl->length && start_vcn > rl->vcn) || start_vcn < rl->vcn) 1294 if (unlikely((!rl->length && first_vcn > rl->vcn) ||
1295 first_vcn < rl->vcn))
1251 return -EINVAL; 1296 return -EINVAL;
1252 /* 1297 /*
1253 * @dst_max is used for bounds checking in 1298 * @dst_max is used for bounds checking in
@@ -1256,17 +1301,27 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
1256 dst_max = dst + dst_len - 1; 1301 dst_max = dst + dst_len - 1;
1257 prev_lcn = 0; 1302 prev_lcn = 0;
1258 /* Do the first partial run if present. */ 1303 /* Do the first partial run if present. */
1259 if (start_vcn > rl->vcn) { 1304 if (first_vcn > rl->vcn) {
1260 s64 delta; 1305 s64 delta, length = rl->length;
1261 1306
1262 /* We know rl->length != 0 already. */ 1307 /* We know rl->length != 0 already. */
1263 if (rl->length < 0 || rl->lcn < LCN_HOLE) 1308 if (unlikely(length < 0 || rl->lcn < LCN_HOLE))
1264 goto err_out; 1309 goto err_out;
1265 delta = start_vcn - rl->vcn; 1310 /*
1311 * If @stop_vcn is given and finishes inside this run, cap the
1312 * run length.
1313 */
1314 if (unlikely(last_vcn >= 0 && rl[1].vcn > last_vcn)) {
1315 s64 s1 = last_vcn + 1;
1316 if (unlikely(rl[1].vcn > s1))
1317 length = s1 - rl->vcn;
1318 the_end = TRUE;
1319 }
1320 delta = first_vcn - rl->vcn;
1266 /* Write length. */ 1321 /* Write length. */
1267 len_len = ntfs_write_significant_bytes(dst + 1, dst_max, 1322 len_len = ntfs_write_significant_bytes(dst + 1, dst_max,
1268 rl->length - delta); 1323 length - delta);
1269 if (len_len < 0) 1324 if (unlikely(len_len < 0))
1270 goto size_err; 1325 goto size_err;
1271 /* 1326 /*
1272 * If the logical cluster number (lcn) denotes a hole and we 1327 * If the logical cluster number (lcn) denotes a hole and we
@@ -1277,19 +1332,19 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
1277 * case on NT4. - We assume that we just need to write the lcn 1332 * case on NT4. - We assume that we just need to write the lcn
1278 * change until someone tells us otherwise... (AIA) 1333 * change until someone tells us otherwise... (AIA)
1279 */ 1334 */
1280 if (rl->lcn >= 0 || vol->major_ver < 3) { 1335 if (likely(rl->lcn >= 0 || vol->major_ver < 3)) {
1281 prev_lcn = rl->lcn; 1336 prev_lcn = rl->lcn;
1282 if (rl->lcn >= 0) 1337 if (likely(rl->lcn >= 0))
1283 prev_lcn += delta; 1338 prev_lcn += delta;
1284 /* Write change in lcn. */ 1339 /* Write change in lcn. */
1285 lcn_len = ntfs_write_significant_bytes(dst + 1 + 1340 lcn_len = ntfs_write_significant_bytes(dst + 1 +
1286 len_len, dst_max, prev_lcn); 1341 len_len, dst_max, prev_lcn);
1287 if (lcn_len < 0) 1342 if (unlikely(lcn_len < 0))
1288 goto size_err; 1343 goto size_err;
1289 } else 1344 } else
1290 lcn_len = 0; 1345 lcn_len = 0;
1291 dst_next = dst + len_len + lcn_len + 1; 1346 dst_next = dst + len_len + lcn_len + 1;
1292 if (dst_next > dst_max) 1347 if (unlikely(dst_next > dst_max))
1293 goto size_err; 1348 goto size_err;
1294 /* Update header byte. */ 1349 /* Update header byte. */
1295 *dst = lcn_len << 4 | len_len; 1350 *dst = lcn_len << 4 | len_len;
@@ -1299,13 +1354,25 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
1299 rl++; 1354 rl++;
1300 } 1355 }
1301 /* Do the full runs. */ 1356 /* Do the full runs. */
1302 for (; rl->length; rl++) { 1357 for (; rl->length && !the_end; rl++) {
1303 if (rl->length < 0 || rl->lcn < LCN_HOLE) 1358 s64 length = rl->length;
1359
1360 if (unlikely(length < 0 || rl->lcn < LCN_HOLE))
1304 goto err_out; 1361 goto err_out;
1362 /*
1363 * If @stop_vcn is given and finishes inside this run, cap the
1364 * run length.
1365 */
1366 if (unlikely(last_vcn >= 0 && rl[1].vcn > last_vcn)) {
1367 s64 s1 = last_vcn + 1;
1368 if (unlikely(rl[1].vcn > s1))
1369 length = s1 - rl->vcn;
1370 the_end = TRUE;
1371 }
1305 /* Write length. */ 1372 /* Write length. */
1306 len_len = ntfs_write_significant_bytes(dst + 1, dst_max, 1373 len_len = ntfs_write_significant_bytes(dst + 1, dst_max,
1307 rl->length); 1374 length);
1308 if (len_len < 0) 1375 if (unlikely(len_len < 0))
1309 goto size_err; 1376 goto size_err;
1310 /* 1377 /*
1311 * If the logical cluster number (lcn) denotes a hole and we 1378 * If the logical cluster number (lcn) denotes a hole and we
@@ -1316,17 +1383,17 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst,
1316 * case on NT4. - We assume that we just need to write the lcn 1383 * case on NT4. - We assume that we just need to write the lcn
1317 * change until someone tells us otherwise... (AIA) 1384 * change until someone tells us otherwise... (AIA)
1318 */ 1385 */
1319 if (rl->lcn >= 0 || vol->major_ver < 3) { 1386 if (likely(rl->lcn >= 0 || vol->major_ver < 3)) {
1320 /* Write change in lcn. */ 1387 /* Write change in lcn. */
1321 lcn_len = ntfs_write_significant_bytes(dst + 1 + 1388 lcn_len = ntfs_write_significant_bytes(dst + 1 +
1322 len_len, dst_max, rl->lcn - prev_lcn); 1389 len_len, dst_max, rl->lcn - prev_lcn);
1323 if (lcn_len < 0) 1390 if (unlikely(lcn_len < 0))
1324 goto size_err; 1391 goto size_err;
1325 prev_lcn = rl->lcn; 1392 prev_lcn = rl->lcn;
1326 } else 1393 } else
1327 lcn_len = 0; 1394 lcn_len = 0;
1328 dst_next = dst + len_len + lcn_len + 1; 1395 dst_next = dst + len_len + lcn_len + 1;
1329 if (dst_next > dst_max) 1396 if (unlikely(dst_next > dst_max))
1330 goto size_err; 1397 goto size_err;
1331 /* Update header byte. */ 1398 /* Update header byte. */
1332 *dst = lcn_len << 4 | len_len; 1399 *dst = lcn_len << 4 | len_len;