WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-api

[Xen-API] [PATCH 2 of 2] CA-43021: hook in 'sparse_dd' for improved VM.c

To: xen-api@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-API] [PATCH 2 of 2] CA-43021: hook in 'sparse_dd' for improved VM.copy performance
From: David Scott <dave.scott@xxxxxxxxxxxxx>
Date: Fri, 23 Jul 2010 18:23:47 +0100
Delivery-date: Fri, 23 Jul 2010 10:38:04 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <patchbomb.1279905825@ely>
List-help: <mailto:xen-api-request@lists.xensource.com?subject=help>
List-id: Discussion of API issues surrounding Xen <xen-api.lists.xensource.com>
List-post: <mailto:xen-api@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-api>, <mailto:xen-api-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-api>, <mailto:xen-api-request@lists.xensource.com?subject=unsubscribe>
References: <patchbomb.1279905825@ely>
Sender: xen-api-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mercurial-patchbomb/1.4.3
# 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(-)


Attachment: sm_fs_ops.patch
Description: Text Data

_______________________________________________
xen-api mailing list
xen-api@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/mailman/listinfo/xen-api
<Prev in Thread] Current Thread [Next in Thread>