@@ -306,37 +306,86 @@ let send_one ofd (__context : Context.t) rpc session_id progress refresh_session
306306 | Ok (Some (driver, path)) when driver = " vhd" || driver = " qcow2"
307307 -> (
308308 try
309- (* Read backing file headers, then only read and write
310- allocated clusters from the bitmap *)
311- let cluster_size, cluster_list =
312- match driver with
313- | "vhd" ->
314- Vhd_tool_wrapper. parse_header path
315- | "qcow2" ->
316- Qcow_tool_wrapper. parse_header path
317- | _ ->
318- failwith (Printf. sprintf " %s: unreachable" __FUNCTION__)
319- in
320- let set =
321- get_allocated_chunks_from_clusters cluster_size cluster_list
322- in
323- (* First and last chunks are always written - it's a limitation
324- of the XVA format *)
325309 let last_chunk =
326310 Int64. ((to_int size - to_int chunk_size + 1 ) / to_int chunk_size)
327311 in
328- let set = set |> ChunkSet. add 0 |> ChunkSet. add last_chunk in
329- ChunkSet. iter
330- (fun this_chunk_no ->
331- let offset = Int64. (mul (of_int this_chunk_no) chunk_size) in
332- let _ =
333- write_chunk this_chunk_no offset
334- ~write_check: (fun _ _ -> true )
335- ~seek: true ~timeout_workaround: false
336- in
337- ()
338- )
339- set
312+ if ! Xapi_globs. vhd_legacy_blocks_format then
313+ (* Read backing file headers, then only read and write
314+ allocated clusters from the bitmap *)
315+ let cluster_size, cluster_list =
316+ match driver with
317+ | "vhd" ->
318+ Vhd_tool_wrapper. parse_header path
319+ | "qcow2" ->
320+ Qcow_tool_wrapper. parse_header path
321+ | _ ->
322+ failwith (Printf. sprintf " %s: unreachable" __FUNCTION__)
323+ in
324+ let set =
325+ get_allocated_chunks_from_clusters cluster_size cluster_list
326+ in
327+ (* First and last chunks are always written - it's a limitation
328+ of the XVA format *)
329+ let set = set |> ChunkSet. add 0 |> ChunkSet. add last_chunk in
330+ ChunkSet. iter
331+ (fun this_chunk_no ->
332+ let offset =
333+ Int64. (mul (of_int this_chunk_no) chunk_size)
334+ in
335+ let _ =
336+ write_chunk this_chunk_no offset
337+ ~write_check: (fun _ _ -> true )
338+ ~seek: true ~timeout_workaround: false
339+ in
340+ ()
341+ )
342+ set
343+ else
344+ let cluster_size, cluster_list =
345+ match driver with
346+ | "vhd" ->
347+ Vhd_tool_wrapper. parse_header_interval path
348+ | "qcow2" ->
349+ Qcow_tool_wrapper. parse_header_interval path
350+ | _ ->
351+ failwith (Printf. sprintf " %s: unreachable" __FUNCTION__)
352+ in
353+ let process_chunk chunk_no ~force =
354+ if force || (chunk_no <> 0 && chunk_no <> last_chunk) then
355+ let offset = Int64. (mul (of_int chunk_no) chunk_size) in
356+ let _ =
357+ write_chunk chunk_no offset
358+ ~write_check: (fun _ _ -> true )
359+ ~seek: true ~timeout_workaround: false
360+ in
361+ ()
362+ in
363+
364+ process_chunk 0 ~force: true ;
365+
366+ let chunk_size = Int64. to_int chunk_size in
367+ let chunks_in_cluster =
368+ (cluster_size + chunk_size - 1 ) / chunk_size
369+ in
370+ (* Iterate over allocated intervals, copying every cluster inside *)
371+ List. iter
372+ (fun (cluster_no_left , cluster_no_right ) ->
373+ let calc_chunk cluster =
374+ let cluster_offset = cluster * cluster_size in
375+ let chunk_no = cluster_offset / chunk_size in
376+ chunk_no
377+ in
378+ let left_chunk_no = calc_chunk cluster_no_left in
379+ let right_chunk_no =
380+ calc_chunk cluster_no_right + chunks_in_cluster - 1
381+ in
382+ for i = left_chunk_no to right_chunk_no do
383+ process_chunk i ~force: false
384+ done
385+ )
386+ cluster_list ;
387+
388+ process_chunk last_chunk ~force: true
340389 with e ->
341390 debug " %s: Falling back to reading the whole raw disk after %s"
342391 __FUNCTION__ (Printexc. to_string e) ;
0 commit comments