@@ -1055,8 +1055,8 @@ int run_unpack_ex(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
1055
1055
{
1056
1056
int ret , err ;
1057
1057
CLST next_vcn , lcn , len ;
1058
- size_t index ;
1059
- bool ok ;
1058
+ size_t index , done ;
1059
+ bool ok , zone ;
1060
1060
struct wnd_bitmap * wnd ;
1061
1061
1062
1062
ret = run_unpack (run , sbi , ino , svcn , evcn , vcn , run_buf , run_buf_size );
@@ -1087,23 +1087,43 @@ int run_unpack_ex(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
1087
1087
continue ;
1088
1088
1089
1089
down_read_nested (& wnd -> rw_lock , BITMAP_MUTEX_CLUSTERS );
1090
+ zone = max (wnd -> zone_bit , lcn ) < min (wnd -> zone_end , lcn + len );
1090
1091
/* Check for free blocks. */
1091
- ok = wnd_is_used (wnd , lcn , len );
1092
+ ok = ! zone && wnd_is_used (wnd , lcn , len );
1092
1093
up_read (& wnd -> rw_lock );
1093
1094
if (ok )
1094
1095
continue ;
1095
1096
1096
1097
/* Looks like volume is corrupted. */
1097
1098
ntfs_set_state (sbi , NTFS_DIRTY_ERROR );
1098
1099
1099
- if (down_write_trylock (& wnd -> rw_lock )) {
1100
- /* Mark all zero bits as used in range [lcn, lcn+len). */
1101
- size_t done ;
1102
- err = wnd_set_used_safe (wnd , lcn , len , & done );
1103
- up_write (& wnd -> rw_lock );
1104
- if (err )
1105
- return err ;
1100
+ if (!down_write_trylock (& wnd -> rw_lock ))
1101
+ continue ;
1102
+
1103
+ if (zone ) {
1104
+ /*
1105
+ * Range [lcn, lcn + len) intersects with zone.
1106
+ * To avoid complex with zone just turn it off.
1107
+ */
1108
+ wnd_zone_set (wnd , 0 , 0 );
1109
+ }
1110
+
1111
+ /* Mark all zero bits as used in range [lcn, lcn+len). */
1112
+ err = wnd_set_used_safe (wnd , lcn , len , & done );
1113
+ if (zone ) {
1114
+ /* Restore zone. Lock mft run. */
1115
+ struct rw_semaphore * lock ;
1116
+ lock = is_mounted (sbi ) ? & sbi -> mft .ni -> file .run_lock :
1117
+ NULL ;
1118
+ if (lock )
1119
+ down_read (lock );
1120
+ ntfs_refresh_zone (sbi );
1121
+ if (lock )
1122
+ up_read (lock );
1106
1123
}
1124
+ up_write (& wnd -> rw_lock );
1125
+ if (err )
1126
+ return err ;
1107
1127
}
1108
1128
1109
1129
return ret ;
0 commit comments