@@ -891,8 +891,10 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
891891 struct ATTR_LIST_ENTRY * le , * le_b ;
892892 struct mft_inode * mi , * mi_b ;
893893 CLST hint , svcn , to_alloc , evcn1 , next_svcn , asize , end , vcn0 , alen ;
894+ CLST alloc , evcn ;
894895 unsigned fr ;
895- u64 total_size ;
896+ u64 total_size , total_size0 ;
897+ int step = 0 ;
896898
897899 if (new )
898900 * new = false;
@@ -932,7 +934,12 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
932934
933935 asize = le64_to_cpu (attr_b -> nres .alloc_size ) >> cluster_bits ;
934936 if (vcn >= asize ) {
935- err = - EINVAL ;
937+ if (new ) {
938+ err = - EINVAL ;
939+ } else {
940+ * len = 1 ;
941+ * lcn = SPARSE_LCN ;
942+ }
936943 goto out ;
937944 }
938945
@@ -1036,10 +1043,12 @@ int attr_data_get_block(struct ntfs_inode *ni, CLST vcn, CLST clen, CLST *lcn,
10361043 if (err )
10371044 goto out ;
10381045 * new = true;
1046+ step = 1 ;
10391047
10401048 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 );
10431052
10441053 if (vcn != vcn0 ) {
10451054 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,
10811090 if (!ni -> attr_list .size ) {
10821091 err = ni_create_attr_list (ni );
10831092 if (err )
1084- goto out ;
1093+ goto undo1 ;
10851094 /* Layout of records is changed. */
10861095 le_b = NULL ;
10871096 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,
10981107 }
10991108 }
11001109
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 ;
11011124 svcn = evcn1 ;
11021125
11031126 /* Estimate next attribute. */
11041127 attr = ni_find_attr (ni , attr , & le , ATTR_DATA , NULL , 0 , & svcn , & mi );
11051128
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+ }
11211133
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 );
11271137
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 );
11321143
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 ;
11411147 }
11421148
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+ }
11451154
1146- err = attr_load_runs ( attr , ni , run , & end );
1147- if ( err )
1155+ if ( ni_load_mi ( ni , le , & mi )) {
1156+ attr = NULL ;
11481157 goto out ;
1158+ }
11491159
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 ;
11541163 goto out ;
1164+ }
1165+ svcn = le64_to_cpu (attr -> nres .svcn );
1166+ evcn = le64_to_cpu (attr -> nres .evcn );
1167+ }
11551168
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 ;
11591186
1160- next_svcn = le64_to_cpu (attr -> nres .evcn ) + 1 ;
1161- }
11621187ins_ext :
11631188 if (evcn1 > next_svcn ) {
11641189 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,
11701195ok :
11711196 run_truncate_around (run , vcn );
11721197out :
1198+ if (err && step > 1 ) {
1199+ /* Too complex to restore. */
1200+ _ntfs_bad_inode (& ni -> vfs_inode );
1201+ }
11731202 up_write (& ni -> file .run_lock );
11741203 ni_unlock (ni );
11751204
11761205 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 ;
11771218}
11781219
11791220int attr_data_read_resident (struct ntfs_inode * ni , struct page * page )
0 commit comments