diff options
Diffstat (limited to 'fs/ntfs/runlist.c')
-rw-r--r-- | fs/ntfs/runlist.c | 278 |
1 files changed, 198 insertions, 80 deletions
diff --git a/fs/ntfs/runlist.c b/fs/ntfs/runlist.c index 8438fb1da219..758855b0414e 100644 --- a/fs/ntfs/runlist.c +++ b/fs/ntfs/runlist.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /** | 1 | /** |
2 | * runlist.c - NTFS runlist handling code. Part of the Linux-NTFS project. | 2 | * runlist.c - NTFS runlist handling code. Part of the Linux-NTFS project. |
3 | * | 3 | * |
4 | * Copyright (c) 2001-2004 Anton Altaparmakov | 4 | * Copyright (c) 2001-2005 Anton Altaparmakov |
5 | * Copyright (c) 2002 Richard Russon | 5 | * Copyright (c) 2002 Richard Russon |
6 | * | 6 | * |
7 | * This program/include file is free software; you can redistribute it and/or | 7 | * This program/include file is free software; you can redistribute it and/or |
@@ -59,7 +59,7 @@ static inline void ntfs_rl_mc(runlist_element *dstbase, int dst, | |||
59 | * | 59 | * |
60 | * As the runlists grow, more memory will be required. To prevent the | 60 | * As the runlists grow, more memory will be required. To prevent the |
61 | * kernel having to allocate and reallocate large numbers of small bits of | 61 | * kernel having to allocate and reallocate large numbers of small bits of |
62 | * memory, this function returns and entire page of memory. | 62 | * memory, this function returns an entire page of memory. |
63 | * | 63 | * |
64 | * It is up to the caller to serialize access to the runlist @rl. | 64 | * It is up to the caller to serialize access to the runlist @rl. |
65 | * | 65 | * |
@@ -113,8 +113,11 @@ static inline BOOL ntfs_are_rl_mergeable(runlist_element *dst, | |||
113 | BUG_ON(!dst); | 113 | BUG_ON(!dst); |
114 | BUG_ON(!src); | 114 | BUG_ON(!src); |
115 | 115 | ||
116 | if ((dst->lcn < 0) || (src->lcn < 0)) /* Are we merging holes? */ | 116 | if ((dst->lcn < 0) || (src->lcn < 0)) { /* Are we merging holes? */ |
117 | if (dst->lcn == LCN_HOLE && src->lcn == LCN_HOLE) | ||
118 | return TRUE; | ||
117 | return FALSE; | 119 | return FALSE; |
120 | } | ||
118 | if ((dst->lcn + dst->length) != src->lcn) /* Are the runs contiguous? */ | 121 | if ((dst->lcn + dst->length) != src->lcn) /* Are the runs contiguous? */ |
119 | return FALSE; | 122 | return FALSE; |
120 | if ((dst->vcn + dst->length) != src->vcn) /* Are the runs misaligned? */ | 123 | if ((dst->vcn + dst->length) != src->vcn) /* Are the runs misaligned? */ |
@@ -855,30 +858,42 @@ mpa_err: | |||
855 | if (!attr->data.non_resident.lowest_vcn) { | 858 | if (!attr->data.non_resident.lowest_vcn) { |
856 | VCN max_cluster; | 859 | VCN max_cluster; |
857 | 860 | ||
858 | max_cluster = (sle64_to_cpu( | 861 | max_cluster = ((sle64_to_cpu( |
859 | attr->data.non_resident.allocated_size) + | 862 | attr->data.non_resident.allocated_size) + |
860 | vol->cluster_size - 1) >> | 863 | vol->cluster_size - 1) >> |
861 | vol->cluster_size_bits; | 864 | vol->cluster_size_bits) - 1; |
862 | /* | 865 | /* |
863 | * If there is a difference between the highest_vcn and the | 866 | * A highest_vcn of zero means this is a single extent |
864 | * highest cluster, the runlist is either corrupt or, more | 867 | * attribute so simply terminate the runlist with LCN_ENOENT). |
865 | * likely, there are more extents following this one. | ||
866 | */ | 868 | */ |
867 | if (deltaxcn < --max_cluster) { | 869 | if (deltaxcn) { |
868 | ntfs_debug("More extents to follow; deltaxcn = 0x%llx, " | 870 | /* |
869 | "max_cluster = 0x%llx", | 871 | * If there is a difference between the highest_vcn and |
870 | (unsigned long long)deltaxcn, | 872 | * the highest cluster, the runlist is either corrupt |
871 | (unsigned long long)max_cluster); | 873 | * or, more likely, there are more extents following |
872 | rl[rlpos].vcn = vcn; | 874 | * this one. |
873 | vcn += rl[rlpos].length = max_cluster - deltaxcn; | 875 | */ |
874 | rl[rlpos].lcn = LCN_RL_NOT_MAPPED; | 876 | if (deltaxcn < max_cluster) { |
875 | rlpos++; | 877 | ntfs_debug("More extents to follow; deltaxcn " |
876 | } else if (unlikely(deltaxcn > max_cluster)) { | 878 | "= 0x%llx, max_cluster = " |
877 | ntfs_error(vol->sb, "Corrupt attribute. deltaxcn = " | 879 | "0x%llx", |
878 | "0x%llx, max_cluster = 0x%llx", | 880 | (unsigned long long)deltaxcn, |
879 | (unsigned long long)deltaxcn, | 881 | (unsigned long long) |
880 | (unsigned long long)max_cluster); | 882 | max_cluster); |
881 | goto mpa_err; | 883 | rl[rlpos].vcn = vcn; |
884 | vcn += rl[rlpos].length = max_cluster - | ||
885 | deltaxcn; | ||
886 | rl[rlpos].lcn = LCN_RL_NOT_MAPPED; | ||
887 | rlpos++; | ||
888 | } else if (unlikely(deltaxcn > max_cluster)) { | ||
889 | ntfs_error(vol->sb, "Corrupt attribute. " | ||
890 | "deltaxcn = 0x%llx, " | ||
891 | "max_cluster = 0x%llx", | ||
892 | (unsigned long long)deltaxcn, | ||
893 | (unsigned long long) | ||
894 | max_cluster); | ||
895 | goto mpa_err; | ||
896 | } | ||
882 | } | 897 | } |
883 | rl[rlpos].lcn = LCN_ENOENT; | 898 | rl[rlpos].lcn = LCN_ENOENT; |
884 | } else /* Not the base extent. There may be more extents to follow. */ | 899 | } else /* Not the base extent. There may be more extents to follow. */ |
@@ -918,17 +933,18 @@ err_out: | |||
918 | * | 933 | * |
919 | * It is up to the caller to serialize access to the runlist @rl. | 934 | * It is up to the caller to serialize access to the runlist @rl. |
920 | * | 935 | * |
921 | * Since lcns must be >= 0, we use negative return values with special meaning: | 936 | * Since lcns must be >= 0, we use negative return codes with special meaning: |
922 | * | 937 | * |
923 | * Return value Meaning / Description | 938 | * Return code Meaning / Description |
924 | * ================================================== | 939 | * ================================================== |
925 | * -1 = LCN_HOLE Hole / not allocated on disk. | 940 | * LCN_HOLE Hole / not allocated on disk. |
926 | * -2 = LCN_RL_NOT_MAPPED This is part of the runlist which has not been | 941 | * LCN_RL_NOT_MAPPED This is part of the runlist which has not been |
927 | * inserted into the runlist yet. | 942 | * inserted into the runlist yet. |
928 | * -3 = LCN_ENOENT There is no such vcn in the attribute. | 943 | * LCN_ENOENT There is no such vcn in the attribute. |
929 | * | 944 | * |
930 | * Locking: - The caller must have locked the runlist (for reading or writing). | 945 | * Locking: - The caller must have locked the runlist (for reading or writing). |
931 | * - This function does not touch the lock. | 946 | * - This function does not touch the lock, nor does it modify the |
947 | * runlist. | ||
932 | */ | 948 | */ |
933 | LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn) | 949 | LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn) |
934 | { | 950 | { |
@@ -964,6 +980,39 @@ LCN ntfs_rl_vcn_to_lcn(const runlist_element *rl, const VCN vcn) | |||
964 | return LCN_ENOENT; | 980 | return LCN_ENOENT; |
965 | } | 981 | } |
966 | 982 | ||
983 | #ifdef NTFS_RW | ||
984 | |||
985 | /** | ||
986 | * ntfs_rl_find_vcn_nolock - find a vcn in a runlist | ||
987 | * @rl: runlist to search | ||
988 | * @vcn: vcn to find | ||
989 | * | ||
990 | * Find the virtual cluster number @vcn in the runlist @rl and return the | ||
991 | * address of the runlist element containing the @vcn on success. | ||
992 | * | ||
993 | * Return NULL if @rl is NULL or @vcn is in an unmapped part/out of bounds of | ||
994 | * the runlist. | ||
995 | * | ||
996 | * Locking: The runlist must be locked on entry. | ||
997 | */ | ||
998 | runlist_element *ntfs_rl_find_vcn_nolock(runlist_element *rl, const VCN vcn) | ||
999 | { | ||
1000 | BUG_ON(vcn < 0); | ||
1001 | if (unlikely(!rl || vcn < rl[0].vcn)) | ||
1002 | return NULL; | ||
1003 | while (likely(rl->length)) { | ||
1004 | if (unlikely(vcn < rl[1].vcn)) { | ||
1005 | if (likely(rl->lcn >= LCN_HOLE)) | ||
1006 | return rl; | ||
1007 | return NULL; | ||
1008 | } | ||
1009 | rl++; | ||
1010 | } | ||
1011 | if (likely(rl->lcn == LCN_ENOENT)) | ||
1012 | return rl; | ||
1013 | return NULL; | ||
1014 | } | ||
1015 | |||
967 | /** | 1016 | /** |
968 | * ntfs_get_nr_significant_bytes - get number of bytes needed to store a number | 1017 | * ntfs_get_nr_significant_bytes - get number of bytes needed to store a number |
969 | * @n: number for which to get the number of bytes for | 1018 | * @n: number for which to get the number of bytes for |
@@ -999,10 +1048,17 @@ static inline int ntfs_get_nr_significant_bytes(const s64 n) | |||
999 | * 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 |
1000 | * @vol: ntfs volume (needed for the ntfs version) | 1049 | * @vol: ntfs volume (needed for the ntfs version) |
1001 | * @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 |
1002 | * @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 | ||
1003 | * | 1053 | * |
1004 | * 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 |
1005 | * 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 | * | ||
1006 | * 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 |
1007 | * building the mapping pairs array. | 1063 | * building the mapping pairs array. |
1008 | * | 1064 | * |
@@ -1018,34 +1074,50 @@ static inline int ntfs_get_nr_significant_bytes(const s64 n) | |||
1018 | * remains locked throughout, and is left locked upon return. | 1074 | * remains locked throughout, and is left locked upon return. |
1019 | */ | 1075 | */ |
1020 | int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol, | 1076 | int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol, |
1021 | const runlist_element *rl, const VCN start_vcn) | 1077 | const runlist_element *rl, const VCN first_vcn, |
1078 | const VCN last_vcn) | ||
1022 | { | 1079 | { |
1023 | LCN prev_lcn; | 1080 | LCN prev_lcn; |
1024 | int rls; | 1081 | int rls; |
1082 | BOOL the_end = FALSE; | ||
1025 | 1083 | ||
1026 | 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); | ||
1027 | if (!rl) { | 1087 | if (!rl) { |
1028 | BUG_ON(start_vcn); | 1088 | BUG_ON(first_vcn); |
1089 | BUG_ON(last_vcn > 0); | ||
1029 | return 1; | 1090 | return 1; |
1030 | } | 1091 | } |
1031 | /* Skip to runlist element containing @start_vcn. */ | 1092 | /* Skip to runlist element containing @first_vcn. */ |
1032 | while (rl->length && start_vcn >= rl[1].vcn) | 1093 | while (rl->length && first_vcn >= rl[1].vcn) |
1033 | rl++; | 1094 | rl++; |
1034 | 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)) | ||
1035 | return -EINVAL; | 1097 | return -EINVAL; |
1036 | prev_lcn = 0; | 1098 | prev_lcn = 0; |
1037 | /* Always need the termining zero byte. */ | 1099 | /* Always need the termining zero byte. */ |
1038 | rls = 1; | 1100 | rls = 1; |
1039 | /* Do the first partial run if present. */ | 1101 | /* Do the first partial run if present. */ |
1040 | if (start_vcn > rl->vcn) { | 1102 | if (first_vcn > rl->vcn) { |
1041 | s64 delta; | 1103 | s64 delta, length = rl->length; |
1042 | 1104 | ||
1043 | /* We know rl->length != 0 already. */ | 1105 | /* We know rl->length != 0 already. */ |
1044 | if (rl->length < 0 || rl->lcn < LCN_HOLE) | 1106 | if (unlikely(length < 0 || rl->lcn < LCN_HOLE)) |
1045 | goto err_out; | 1107 | goto err_out; |
1046 | 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; | ||
1047 | /* Header byte + length. */ | 1119 | /* Header byte + length. */ |
1048 | rls += 1 + ntfs_get_nr_significant_bytes(rl->length - delta); | 1120 | rls += 1 + ntfs_get_nr_significant_bytes(length - delta); |
1049 | /* | 1121 | /* |
1050 | * If the logical cluster number (lcn) denotes a hole and we | 1122 | * If the logical cluster number (lcn) denotes a hole and we |
1051 | * 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 |
@@ -1053,9 +1125,9 @@ int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol, | |||
1053 | * 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 |
1054 | * 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). |
1055 | */ | 1127 | */ |
1056 | if (rl->lcn >= 0 || vol->major_ver < 3) { | 1128 | if (likely(rl->lcn >= 0 || vol->major_ver < 3)) { |
1057 | prev_lcn = rl->lcn; | 1129 | prev_lcn = rl->lcn; |
1058 | if (rl->lcn >= 0) | 1130 | if (likely(rl->lcn >= 0)) |
1059 | prev_lcn += delta; | 1131 | prev_lcn += delta; |
1060 | /* Change in lcn. */ | 1132 | /* Change in lcn. */ |
1061 | rls += ntfs_get_nr_significant_bytes(prev_lcn); | 1133 | rls += ntfs_get_nr_significant_bytes(prev_lcn); |
@@ -1064,11 +1136,23 @@ int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol, | |||
1064 | rl++; | 1136 | rl++; |
1065 | } | 1137 | } |
1066 | /* Do the full runs. */ | 1138 | /* Do the full runs. */ |
1067 | for (; rl->length; rl++) { | 1139 | for (; rl->length && !the_end; rl++) { |
1068 | if (rl->length < 0 || rl->lcn < LCN_HOLE) | 1140 | s64 length = rl->length; |
1141 | |||
1142 | if (unlikely(length < 0 || rl->lcn < LCN_HOLE)) | ||
1069 | 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 | } | ||
1070 | /* Header byte + length. */ | 1154 | /* Header byte + length. */ |
1071 | rls += 1 + ntfs_get_nr_significant_bytes(rl->length); | 1155 | rls += 1 + ntfs_get_nr_significant_bytes(length); |
1072 | /* | 1156 | /* |
1073 | * If the logical cluster number (lcn) denotes a hole and we | 1157 | * If the logical cluster number (lcn) denotes a hole and we |
1074 | * 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 |
@@ -1076,7 +1160,7 @@ int ntfs_get_size_for_mapping_pairs(const ntfs_volume *vol, | |||
1076 | * 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 |
1077 | * 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). |
1078 | */ | 1162 | */ |
1079 | if (rl->lcn >= 0 || vol->major_ver < 3) { | 1163 | if (likely(rl->lcn >= 0 || vol->major_ver < 3)) { |
1080 | /* Change in lcn. */ | 1164 | /* Change in lcn. */ |
1081 | rls += ntfs_get_nr_significant_bytes(rl->lcn - | 1165 | rls += ntfs_get_nr_significant_bytes(rl->lcn - |
1082 | prev_lcn); | 1166 | prev_lcn); |
@@ -1119,7 +1203,7 @@ static inline int ntfs_write_significant_bytes(s8 *dst, const s8 *dst_max, | |||
1119 | 1203 | ||
1120 | i = 0; | 1204 | i = 0; |
1121 | do { | 1205 | do { |
1122 | if (dst > dst_max) | 1206 | if (unlikely(dst > dst_max)) |
1123 | goto err_out; | 1207 | goto err_out; |
1124 | *dst++ = l & 0xffll; | 1208 | *dst++ = l & 0xffll; |
1125 | l >>= 8; | 1209 | l >>= 8; |
@@ -1128,12 +1212,12 @@ static inline int ntfs_write_significant_bytes(s8 *dst, const s8 *dst_max, | |||
1128 | j = (n >> 8 * (i - 1)) & 0xff; | 1212 | j = (n >> 8 * (i - 1)) & 0xff; |
1129 | /* If the sign bit is wrong, we need an extra byte. */ | 1213 | /* If the sign bit is wrong, we need an extra byte. */ |
1130 | if (n < 0 && j >= 0) { | 1214 | if (n < 0 && j >= 0) { |
1131 | if (dst > dst_max) | 1215 | if (unlikely(dst > dst_max)) |
1132 | goto err_out; | 1216 | goto err_out; |
1133 | i++; | 1217 | i++; |
1134 | *dst = (s8)-1; | 1218 | *dst = (s8)-1; |
1135 | } else if (n > 0 && j < 0) { | 1219 | } else if (n > 0 && j < 0) { |
1136 | if (dst > dst_max) | 1220 | if (unlikely(dst > dst_max)) |
1137 | goto err_out; | 1221 | goto err_out; |
1138 | i++; | 1222 | i++; |
1139 | *dst = (s8)0; | 1223 | *dst = (s8)0; |
@@ -1149,13 +1233,18 @@ err_out: | |||
1149 | * @dst: destination buffer to which to write the mapping pairs array | 1233 | * @dst: destination buffer to which to write the mapping pairs array |
1150 | * @dst_len: size of destination buffer @dst in bytes | 1234 | * @dst_len: size of destination buffer @dst in bytes |
1151 | * @rl: locked runlist for which to build the mapping pairs array | 1235 | * @rl: locked runlist for which to build the mapping pairs array |
1152 | * @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 | ||
1153 | * @stop_vcn: first vcn outside destination buffer on success or -ENOSPC | 1238 | * @stop_vcn: first vcn outside destination buffer on success or -ENOSPC |
1154 | * | 1239 | * |
1155 | * 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 |
1156 | * @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. |
1157 | * 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 |
1158 | * 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. | ||
1159 | * | 1248 | * |
1160 | * 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. |
1161 | * | 1250 | * |
@@ -1164,7 +1253,7 @@ err_out: | |||
1164 | * 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 |
1165 | * 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 |
1166 | * 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 |
1167 | * continued with @start_vcn set to *@stop_vcn. | 1256 | * continued with @first_vcn set to *@stop_vcn. |
1168 | * | 1257 | * |
1169 | * 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 |
1170 | * defined: | 1259 | * defined: |
@@ -1178,27 +1267,32 @@ err_out: | |||
1178 | */ | 1267 | */ |
1179 | int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst, | 1268 | int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst, |
1180 | const int dst_len, const runlist_element *rl, | 1269 | const int dst_len, const runlist_element *rl, |
1181 | const VCN start_vcn, VCN *const stop_vcn) | 1270 | const VCN first_vcn, const VCN last_vcn, VCN *const stop_vcn) |
1182 | { | 1271 | { |
1183 | LCN prev_lcn; | 1272 | LCN prev_lcn; |
1184 | s8 *dst_max, *dst_next; | 1273 | s8 *dst_max, *dst_next; |
1185 | int err = -ENOSPC; | 1274 | int err = -ENOSPC; |
1275 | BOOL the_end = FALSE; | ||
1186 | s8 len_len, lcn_len; | 1276 | s8 len_len, lcn_len; |
1187 | 1277 | ||
1188 | 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); | ||
1189 | BUG_ON(dst_len < 1); | 1281 | BUG_ON(dst_len < 1); |
1190 | if (!rl) { | 1282 | if (!rl) { |
1191 | BUG_ON(start_vcn); | 1283 | BUG_ON(first_vcn); |
1284 | BUG_ON(last_vcn > 0); | ||
1192 | if (stop_vcn) | 1285 | if (stop_vcn) |
1193 | *stop_vcn = 0; | 1286 | *stop_vcn = 0; |
1194 | /* Terminator byte. */ | 1287 | /* Terminator byte. */ |
1195 | *dst = 0; | 1288 | *dst = 0; |
1196 | return 0; | 1289 | return 0; |
1197 | } | 1290 | } |
1198 | /* Skip to runlist element containing @start_vcn. */ | 1291 | /* Skip to runlist element containing @first_vcn. */ |
1199 | while (rl->length && start_vcn >= rl[1].vcn) | 1292 | while (rl->length && first_vcn >= rl[1].vcn) |
1200 | rl++; | 1293 | rl++; |
1201 | 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)) | ||
1202 | return -EINVAL; | 1296 | return -EINVAL; |
1203 | /* | 1297 | /* |
1204 | * @dst_max is used for bounds checking in | 1298 | * @dst_max is used for bounds checking in |
@@ -1207,17 +1301,27 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst, | |||
1207 | dst_max = dst + dst_len - 1; | 1301 | dst_max = dst + dst_len - 1; |
1208 | prev_lcn = 0; | 1302 | prev_lcn = 0; |
1209 | /* Do the first partial run if present. */ | 1303 | /* Do the first partial run if present. */ |
1210 | if (start_vcn > rl->vcn) { | 1304 | if (first_vcn > rl->vcn) { |
1211 | s64 delta; | 1305 | s64 delta, length = rl->length; |
1212 | 1306 | ||
1213 | /* We know rl->length != 0 already. */ | 1307 | /* We know rl->length != 0 already. */ |
1214 | if (rl->length < 0 || rl->lcn < LCN_HOLE) | 1308 | if (unlikely(length < 0 || rl->lcn < LCN_HOLE)) |
1215 | goto err_out; | 1309 | goto err_out; |
1216 | 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; | ||
1217 | /* Write length. */ | 1321 | /* Write length. */ |
1218 | len_len = ntfs_write_significant_bytes(dst + 1, dst_max, | 1322 | len_len = ntfs_write_significant_bytes(dst + 1, dst_max, |
1219 | rl->length - delta); | 1323 | length - delta); |
1220 | if (len_len < 0) | 1324 | if (unlikely(len_len < 0)) |
1221 | goto size_err; | 1325 | goto size_err; |
1222 | /* | 1326 | /* |
1223 | * If the logical cluster number (lcn) denotes a hole and we | 1327 | * If the logical cluster number (lcn) denotes a hole and we |
@@ -1228,19 +1332,19 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst, | |||
1228 | * 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 |
1229 | * change until someone tells us otherwise... (AIA) | 1333 | * change until someone tells us otherwise... (AIA) |
1230 | */ | 1334 | */ |
1231 | if (rl->lcn >= 0 || vol->major_ver < 3) { | 1335 | if (likely(rl->lcn >= 0 || vol->major_ver < 3)) { |
1232 | prev_lcn = rl->lcn; | 1336 | prev_lcn = rl->lcn; |
1233 | if (rl->lcn >= 0) | 1337 | if (likely(rl->lcn >= 0)) |
1234 | prev_lcn += delta; | 1338 | prev_lcn += delta; |
1235 | /* Write change in lcn. */ | 1339 | /* Write change in lcn. */ |
1236 | lcn_len = ntfs_write_significant_bytes(dst + 1 + | 1340 | lcn_len = ntfs_write_significant_bytes(dst + 1 + |
1237 | len_len, dst_max, prev_lcn); | 1341 | len_len, dst_max, prev_lcn); |
1238 | if (lcn_len < 0) | 1342 | if (unlikely(lcn_len < 0)) |
1239 | goto size_err; | 1343 | goto size_err; |
1240 | } else | 1344 | } else |
1241 | lcn_len = 0; | 1345 | lcn_len = 0; |
1242 | dst_next = dst + len_len + lcn_len + 1; | 1346 | dst_next = dst + len_len + lcn_len + 1; |
1243 | if (dst_next > dst_max) | 1347 | if (unlikely(dst_next > dst_max)) |
1244 | goto size_err; | 1348 | goto size_err; |
1245 | /* Update header byte. */ | 1349 | /* Update header byte. */ |
1246 | *dst = lcn_len << 4 | len_len; | 1350 | *dst = lcn_len << 4 | len_len; |
@@ -1250,13 +1354,25 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst, | |||
1250 | rl++; | 1354 | rl++; |
1251 | } | 1355 | } |
1252 | /* Do the full runs. */ | 1356 | /* Do the full runs. */ |
1253 | for (; rl->length; rl++) { | 1357 | for (; rl->length && !the_end; rl++) { |
1254 | if (rl->length < 0 || rl->lcn < LCN_HOLE) | 1358 | s64 length = rl->length; |
1359 | |||
1360 | if (unlikely(length < 0 || rl->lcn < LCN_HOLE)) | ||
1255 | 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 | } | ||
1256 | /* Write length. */ | 1372 | /* Write length. */ |
1257 | len_len = ntfs_write_significant_bytes(dst + 1, dst_max, | 1373 | len_len = ntfs_write_significant_bytes(dst + 1, dst_max, |
1258 | rl->length); | 1374 | length); |
1259 | if (len_len < 0) | 1375 | if (unlikely(len_len < 0)) |
1260 | goto size_err; | 1376 | goto size_err; |
1261 | /* | 1377 | /* |
1262 | * If the logical cluster number (lcn) denotes a hole and we | 1378 | * If the logical cluster number (lcn) denotes a hole and we |
@@ -1267,17 +1383,17 @@ int ntfs_mapping_pairs_build(const ntfs_volume *vol, s8 *dst, | |||
1267 | * 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 |
1268 | * change until someone tells us otherwise... (AIA) | 1384 | * change until someone tells us otherwise... (AIA) |
1269 | */ | 1385 | */ |
1270 | if (rl->lcn >= 0 || vol->major_ver < 3) { | 1386 | if (likely(rl->lcn >= 0 || vol->major_ver < 3)) { |
1271 | /* Write change in lcn. */ | 1387 | /* Write change in lcn. */ |
1272 | lcn_len = ntfs_write_significant_bytes(dst + 1 + | 1388 | lcn_len = ntfs_write_significant_bytes(dst + 1 + |
1273 | len_len, dst_max, rl->lcn - prev_lcn); | 1389 | len_len, dst_max, rl->lcn - prev_lcn); |
1274 | if (lcn_len < 0) | 1390 | if (unlikely(lcn_len < 0)) |
1275 | goto size_err; | 1391 | goto size_err; |
1276 | prev_lcn = rl->lcn; | 1392 | prev_lcn = rl->lcn; |
1277 | } else | 1393 | } else |
1278 | lcn_len = 0; | 1394 | lcn_len = 0; |
1279 | dst_next = dst + len_len + lcn_len + 1; | 1395 | dst_next = dst + len_len + lcn_len + 1; |
1280 | if (dst_next > dst_max) | 1396 | if (unlikely(dst_next > dst_max)) |
1281 | goto size_err; | 1397 | goto size_err; |
1282 | /* Update header byte. */ | 1398 | /* Update header byte. */ |
1283 | *dst = lcn_len << 4 | len_len; | 1399 | *dst = lcn_len << 4 | len_len; |
@@ -1436,3 +1552,5 @@ int ntfs_rl_truncate_nolock(const ntfs_volume *vol, runlist *const runlist, | |||
1436 | ntfs_debug("Done."); | 1552 | ntfs_debug("Done."); |
1437 | return 0; | 1553 | return 0; |
1438 | } | 1554 | } |
1555 | |||
1556 | #endif /* NTFS_RW */ | ||