@@ -1055,8 +1055,8 @@ int run_unpack_ex(struct runs_tree *run, struct ntfs_sb_info *sbi, CLST ino,
10551055{
10561056 int ret , err ;
10571057 CLST next_vcn , lcn , len ;
1058- size_t index ;
1059- bool ok ;
1058+ size_t index , done ;
1059+ bool ok , zone ;
10601060 struct wnd_bitmap * wnd ;
10611061
10621062 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,
10871087 continue ;
10881088
10891089 down_read_nested (& wnd -> rw_lock , BITMAP_MUTEX_CLUSTERS );
1090+ zone = max (wnd -> zone_bit , lcn ) < min (wnd -> zone_end , lcn + len );
10901091 /* Check for free blocks. */
1091- ok = wnd_is_used (wnd , lcn , len );
1092+ ok = ! zone && wnd_is_used (wnd , lcn , len );
10921093 up_read (& wnd -> rw_lock );
10931094 if (ok )
10941095 continue ;
10951096
10961097 /* Looks like volume is corrupted. */
10971098 ntfs_set_state (sbi , NTFS_DIRTY_ERROR );
10981099
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 );
11061123 }
1124+ up_write (& wnd -> rw_lock );
1125+ if (err )
1126+ return err ;
11071127 }
11081128
11091129 return ret ;
0 commit comments