@@ -891,8 +891,10 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
891
891
struct ATTR_LIST_ENTRY * le , * le_b ;
892
892
struct mft_inode * mi , * mi_b ;
893
893
CLST hint , svcn , to_alloc , evcn1 , next_svcn , asize , end , vcn0 , alen ;
894
+ CLST alloc , evcn ;
894
895
unsigned fr ;
895
- u64 total_size ;
896
+ u64 total_size , total_size0 ;
897
+ int step = 0 ;
896
898
897
899
if (new )
898
900
* new = false;
@@ -932,7 +934,12 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
932
934
933
935
asize = le64_to_cpu (attr_b -> nres .alloc_size ) >> cluster_bits ;
934
936
if (vcn >= asize ) {
935
- err = - EINVAL ;
937
+ if (new ) {
938
+ err = - EINVAL ;
939
+ } else {
940
+ * len = 1 ;
941
+ * lcn = SPARSE_LCN ;
942
+ }
936
943
goto out ;
937
944
}
938
945
@@ -1036,10 +1043,12 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
1036
1043
if (err )
1037
1044
goto out ;
1038
1045
* new = true;
1046
+ step = 1 ;
1039
1047
1040
1048
end = vcn + alen ;
1041
- total_size = le64_to_cpu (attr_b -> nres .total_size ) +
1042
- ((u64 )alen << cluster_bits );
1049
+ /* Save 'total_size0' to restore if error. */
1050
+ total_size0 = le64_to_cpu (attr_b -> nres .total_size );
1051
+ total_size = total_size0 + ((u64 )alen << cluster_bits );
1043
1052
1044
1053
if (vcn != vcn0 ) {
1045
1054
if (!run_lookup_entry (run , vcn0 , lcn , len , NULL )) {
@@ -1081,7 +1090,7 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
1081
1090
if (!ni -> attr_list .size ) {
1082
1091
err = ni_create_attr_list (ni );
1083
1092
if (err )
1084
- goto out ;
1093
+ goto undo1 ;
1085
1094
/* Layout of records is changed. */
1086
1095
le_b = NULL ;
1087
1096
attr_b = ni_find_attr (ni , NULL , & le_b , ATTR_DATA , NULL ,
@@ -1098,67 +1107,83 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
1098
1107
}
1099
1108
}
1100
1109
1110
+ /*
1111
+ * The code below may require additional cluster (to extend attribute list)
1112
+ * and / or one MFT record
1113
+ * It is too complex to undo operations if -ENOSPC occurs deep inside
1114
+ * in 'ni_insert_nonresident'.
1115
+ * Return in advance -ENOSPC here if there are no free cluster and no free MFT.
1116
+ */
1117
+ if (!ntfs_check_for_free_space (sbi , 1 , 1 )) {
1118
+ /* Undo step 1. */
1119
+ err = - ENOSPC ;
1120
+ goto undo1 ;
1121
+ }
1122
+
1123
+ step = 2 ;
1101
1124
svcn = evcn1 ;
1102
1125
1103
1126
/* Estimate next attribute. */
1104
1127
attr = ni_find_attr (ni , attr , & le , ATTR_DATA , NULL , 0 , & svcn , & mi );
1105
1128
1106
- if (attr ) {
1107
- CLST alloc = bytes_to_cluster (
1108
- sbi , le64_to_cpu (attr_b -> nres .alloc_size ));
1109
- CLST evcn = le64_to_cpu (attr -> nres .evcn );
1110
-
1111
- if (end < next_svcn )
1112
- end = next_svcn ;
1113
- while (end > evcn ) {
1114
- /* Remove segment [svcn : evcn). */
1115
- mi_remove_attr (NULL , mi , attr );
1116
-
1117
- if (!al_remove_le (ni , le )) {
1118
- err = - EINVAL ;
1119
- goto out ;
1120
- }
1129
+ if (!attr ) {
1130
+ /* Insert new attribute segment. */
1131
+ goto ins_ext ;
1132
+ }
1121
1133
1122
- if (evcn + 1 >= alloc ) {
1123
- /* Last attribute segment. */
1124
- evcn1 = evcn + 1 ;
1125
- goto ins_ext ;
1126
- }
1134
+ /* Try to update existed attribute segment. */
1135
+ alloc = bytes_to_cluster (sbi , le64_to_cpu (attr_b -> nres .alloc_size ));
1136
+ evcn = le64_to_cpu (attr -> nres .evcn );
1127
1137
1128
- if (ni_load_mi (ni , le , & mi )) {
1129
- attr = NULL ;
1130
- goto out ;
1131
- }
1138
+ if (end < next_svcn )
1139
+ end = next_svcn ;
1140
+ while (end > evcn ) {
1141
+ /* Remove segment [svcn : evcn). */
1142
+ mi_remove_attr (NULL , mi , attr );
1132
1143
1133
- attr = mi_find_attr (mi , NULL , ATTR_DATA , NULL , 0 ,
1134
- & le -> id );
1135
- if (!attr ) {
1136
- err = - EINVAL ;
1137
- goto out ;
1138
- }
1139
- svcn = le64_to_cpu (attr -> nres .svcn );
1140
- evcn = le64_to_cpu (attr -> nres .evcn );
1144
+ if (!al_remove_le (ni , le )) {
1145
+ err = - EINVAL ;
1146
+ goto out ;
1141
1147
}
1142
1148
1143
- if (end < svcn )
1144
- end = svcn ;
1149
+ if (evcn + 1 >= alloc ) {
1150
+ /* Last attribute segment. */
1151
+ evcn1 = evcn + 1 ;
1152
+ goto ins_ext ;
1153
+ }
1145
1154
1146
- err = attr_load_runs ( attr , ni , run , & end );
1147
- if ( err )
1155
+ if ( ni_load_mi ( ni , le , & mi )) {
1156
+ attr = NULL ;
1148
1157
goto out ;
1158
+ }
1149
1159
1150
- evcn1 = evcn + 1 ;
1151
- attr -> nres .svcn = cpu_to_le64 (next_svcn );
1152
- err = mi_pack_runs (mi , attr , run , evcn1 - next_svcn );
1153
- if (err )
1160
+ attr = mi_find_attr (mi , NULL , ATTR_DATA , NULL , 0 , & le -> id );
1161
+ if (!attr ) {
1162
+ err = - EINVAL ;
1154
1163
goto out ;
1164
+ }
1165
+ svcn = le64_to_cpu (attr -> nres .svcn );
1166
+ evcn = le64_to_cpu (attr -> nres .evcn );
1167
+ }
1155
1168
1156
- le -> vcn = cpu_to_le64 (next_svcn );
1157
- ni -> attr_list .dirty = true;
1158
- mi -> dirty = true;
1169
+ if (end < svcn )
1170
+ end = svcn ;
1171
+
1172
+ err = attr_load_runs (attr , ni , run , & end );
1173
+ if (err )
1174
+ goto out ;
1175
+
1176
+ evcn1 = evcn + 1 ;
1177
+ attr -> nres .svcn = cpu_to_le64 (next_svcn );
1178
+ err = mi_pack_runs (mi , attr , run , evcn1 - next_svcn );
1179
+ if (err )
1180
+ goto out ;
1181
+
1182
+ le -> vcn = cpu_to_le64 (next_svcn );
1183
+ ni -> attr_list .dirty = true;
1184
+ mi -> dirty = true;
1185
+ next_svcn = le64_to_cpu (attr -> nres .evcn ) + 1 ;
1159
1186
1160
- next_svcn = le64_to_cpu (attr -> nres .evcn ) + 1 ;
1161
- }
1162
1187
ins_ext :
1163
1188
if (evcn1 > next_svcn ) {
1164
1189
err = ni_insert_nonresident (ni , ATTR_DATA , NULL , 0 , run ,
@@ -1170,10 +1195,26 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
1170
1195
ok :
1171
1196
run_truncate_around (run , vcn );
1172
1197
out :
1198
+ if (err && step > 1 ) {
1199
+ /* Too complex to restore. */
1200
+ _ntfs_bad_inode (& ni -> vfs_inode );
1201
+ }
1173
1202
up_write (& ni -> file .run_lock );
1174
1203
ni_unlock (ni );
1175
1204
1176
1205
return err ;
1206
+
1207
+ undo1 :
1208
+ /* Undo step1. */
1209
+ attr_b -> nres .total_size = cpu_to_le64 (total_size0 );
1210
+ inode_set_bytes (& ni -> vfs_inode , total_size0 );
1211
+
1212
+ if (run_deallocate_ex (sbi , run , vcn , alen , NULL , false) ||
1213
+ !run_add_entry (run , vcn , SPARSE_LCN , alen , false) ||
1214
+ mi_pack_runs (mi , attr , run , max (end , evcn1 ) - svcn )) {
1215
+ _ntfs_bad_inode (& ni -> vfs_inode );
1216
+ }
1217
+ goto out ;
1177
1218
}
1178
1219
1179
1220
int attr_data_read_resident (struct ntfs_inode * ni , struct page * page )
0 commit comments