|
|
|
|
|
|
|
|
|
|
xen-api
[Xen-API] [PATCH 2 of 2] CA-43021: hook in 'sparse_dd' for improved VM.c
# HG changeset patch
# User David Scott <dave.scott@xxxxxxxxxxxxx>
# Date 1279905520 -3600
# Node ID 3bf70773971b9906e4d7355049b2cf7a88a13b23
# Parent 2580868fdc435e5c729f98bd707d018dafd3dc2a
CA-43021: hook in 'sparse_dd' for improved VM.copy performance
On local LVHD, VM.copies of freshly installed guests are much quicker:
Guest Previous VM.copy time New VM.copy time Speedup
----------------------------------------------------------------
Debian Lenny 2:11 1:18 40%
Windows 7 14:18 7:57 44%
Signed-off-by: David Scott <dave.scott@xxxxxxxxxxxxx>
diff -r 2580868fdc43 -r 3bf70773971b ocaml/xapi/sm_fs_ops.ml
--- a/ocaml/xapi/sm_fs_ops.ml Fri Jul 23 18:18:39 2010 +0100
+++ b/ocaml/xapi/sm_fs_ops.ml Fri Jul 23 18:18:40 2010 +0100
@@ -138,59 +138,48 @@
raise e
)
-exception Cancelled
-exception NonZero
-
-(* dd with sparseness check *)
-let sparse_dd refresh_session ~__context sparse ifd ofd size bs =
- let round v = int_of_float (v *. 50.0) in
- let update =
- let oldvalue = ref (-1.0) in
- fun value ->
- if round value <> round !oldvalue then begin
- TaskHelper.exn_if_cancelling ~__context;
- TaskHelper.operate_on_db_task ~__context
- (fun self ->
- Db.Task.set_progress ~__context ~self ~value);
- end;
- oldvalue := value
- in
-
- let buf = String.create bs in
-
- let allzero s n =
- try
- for i=0 to n-1 do
- if s.[i] <> '\000' then raise NonZero
- done;
- true
- with NonZero -> false
- in
-
- let rec do_block offset =
- refresh_session ();
-
- update ((Int64.to_float offset) /. (Int64.to_float size));
- let remaining = Int64.sub size offset in
- if remaining=0L
- then () (* EOF *)
- else
- begin
- let this_chunk = Int64.to_int (min remaining (Int64.of_int bs)) in
- Unixext.really_read ifd buf 0 this_chunk;
- begin
- if sparse && (allzero buf this_chunk)
- then
- ignore(Unix.LargeFile.lseek ofd (Int64.of_int this_chunk)
Unix.SEEK_CUR)
- else
- let n = Unix.write ofd buf 0 this_chunk in
- (if n<this_chunk then failwith "Error!")
- end;
- do_block (Int64.add offset (Int64.of_int this_chunk))
- end
- in
- do_block 0L;
- update 1.0
+(** Use the new external sparse_dd program *)
+let sparse_dd_new ~__context prezeroed infile outfile size =
+ let pipe_read, pipe_write = Unix.pipe () in
+ let to_close = ref [ pipe_read; pipe_write ] in
+ let close x = if List.mem x !to_close then (Unix.close x; to_close :=
List.filter (fun y -> y <> x) !to_close) in
+ finally
+ (fun () ->
+ match Forkhelpers.with_logfile_fd "sparse_dd"
+ (fun log_fd ->
+ let pid = Forkhelpers.safe_close_and_exec None
(Some pipe_write) (Some log_fd) []
+ "/opt/xensource/libexec/sparse_dd"
+ ([ "-machine"; "-src"; infile; "-dest";
outfile; "-size"; Int64.to_string size ] @
+ (if prezeroed then [ "-prezeroed" ] else [])) in
+ close pipe_write;
+ (* Read Progress: output from the binary *)
+ let buf = String.create 128 in
+ let finished = ref false in
+ while not (!finished) do
+ let n = Unix.read pipe_read buf 0
(String.length buf) in
+ if n = 0 then finished := true else
debug "sparse_dd: %s" (String.sub buf 0 n);
+ try
+ Scanf.sscanf (String.sub buf 0
n) "Progress: %d"
+ (fun progress ->
+
TaskHelper.exn_if_cancelling ~__context;
+
TaskHelper.operate_on_db_task ~__context
+ (fun self ->
Db.Task.set_progress ~__context ~self ~value:(float_of_int progress /. 100.))
+ )
+ with _ -> ()
+ done;
+ match Forkhelpers.waitpid pid with
+ | (_, Unix.WEXITED 0) -> ()
+ | (_, Unix.WEXITED n) -> error "sparse_dd exit:
%d" n; failwith "sparse_dd"
+ ) with
+ | Forkhelpers.Success _ -> ()
+ | Forkhelpers.Failure (log, exn) ->
+ error "Failure from sparse_dd: %s" log;
+ raise exn
+ )
+ (fun () ->
+ close pipe_read;
+ close pipe_write)
+
(* SCTX-286: thin provisioning is thrown away over VDI.copy,
VM.import(VM.export).
Return true if the newly created vdi must have zeroes written into it;
default to false
@@ -226,38 +215,18 @@
let copy_vdi ~__context vdi_src vdi_dst =
TaskHelper.set_cancellable ~__context;
Helpers.call_api_functions ~__context (fun rpc session_id ->
- let refresh_session = Xapi_session.consider_touching_session rpc session_id
in
(* Use the sparse copy unless we must write zeroes into the new VDI *)
let sparse = not (must_write_zeroes_into_new_vdi ~__context vdi_dst) in
let size = Db.VDI.get_virtual_size ~__context ~self:vdi_src in
- let blocksize = 1024*1024 in
-
- debug "Sm_fs_ops.copy_vdi: copying %Ld in blocks of %d%s preserving
sparseness" size blocksize (if sparse then "" else " NOT");
-
- let dd = sparse_dd refresh_session ~__context sparse in
with_block_attached_device __context rpc session_id vdi_src `RO
(fun device_src ->
with_block_attached_device __context rpc session_id vdi_dst `RW
(fun device_dst ->
- let ifd=Unix.openfile device_src [Unix.O_RDONLY] 0o600
- and ofd=Unix.openfile device_dst [Unix.O_WRONLY; Unix.O_SYNC] 0o600
in
- finally
- (fun () ->
- try
- dd ifd ofd size blocksize;
- with
- | Unix.Unix_error(Unix.EIO, _, _) ->
- raise (Api_errors.Server_error (Api_errors.vdi_io_error,
["Device I/O error"]))
- | e ->
- debug "Caught exception %s" (ExnHelper.string_of_exn e);
- log_backtrace ())
- (fun () ->
- Unix.close ifd;
- Unix.close ofd)
+ sparse_dd_new ~__context sparse device_src device_dst size;
)
)
)
ocaml/xapi/sm_fs_ops.ml | 117 +++++++++++++++++------------------------------
1 files changed, 43 insertions(+), 74 deletions(-)
sm_fs_ops.patch
Description: Text Data
_______________________________________________
xen-api mailing list
xen-api@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-api
|
|
|
|
|