]> xenbits.xensource.com Git - xcp/xen-api-libs.git/commitdiff
A few bits and pieces to support the vhd daemon
authorJon Ludlam <Jonathan.Ludlam@eu.citrix.com>
Mon, 21 Dec 2009 18:10:58 +0000 (18:10 +0000)
committerJon Ludlam <Jonathan.Ludlam@eu.citrix.com>
Mon, 21 Dec 2009 18:10:58 +0000 (18:10 +0000)
 * Introduce a dereferencing type to camldm so that PVs can be referenced by ID rather than by device name. This is useful for passing a device-mapper table between hosts where the physical device for a particular PV is different.
 * Implement device-mapper reload/suspend/resume so that a table can be changed without tearing down the device
 * A few more helper functions for stdext

Signed-off-by: Jon Ludlam <Jonathan.Ludlam@eu.citrix.com>
camldm/camldm.ml
camldm/camldm.mli
camldm/camldm_stubs.c
stdext/listext.ml
stdext/listext.mli
stdext/unixext.ml
stdext/unixext.mli
stdext/unixext_stubs.c

index 2fe4169ba7f16e4c9f19472d679a2e376d29fc01..9ebe4496d5edf43424f45748438a8ed25b8019cc 100644 (file)
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
  *)
+
+type devty = 
+    | Dereferenced of string (* e.g. PV id *)
+    | Real of string (* device *)
+       
 type dev = {
-  device : string;
+  device : devty;
   offset : int64;
 }
-
+    
 type stripety = {
-  chunk_size : int64;
+  chunk_size : int64;  (* In sectors - must be a power of 2 and at least as large as the system's PAGE_SIZE *)
   dests : dev array;
 }
 
@@ -27,7 +32,7 @@ type mapty =
 
 type mapping = {
   start : int64;
-  len : int64;
+  len : int64; 
   map : mapty;
 }
 
@@ -45,33 +50,82 @@ type status = {
 }
 
 external _create : string -> (int64 * int64 * string * string) array -> unit = "camldm_create"
+external _reload : string -> (int64 * int64 * string * string) array -> unit = "camldm_reload"
 external _table : string -> status = "camldm_table"
 external _mknods : string -> unit = "camldm_mknods"
 external _remove : string -> unit = "camldm_remove"
+external _suspend : string -> unit = "camldm_suspend"
+external _resume : string -> unit = "camldm_resume"
 external _mknod : string -> int -> int -> int -> unit = "camldm_mknod"
 
 (* Helper to convert from our type to the string*string 
  * type expected by libdevmapper *)
-let convert_mapty m =
+let resolve_device dev deref_table =
+  match dev with
+    | Real d -> d
+    | Dereferenced d -> List.assoc d deref_table
+
+let convert_mapty m deref_table =
   let array_concat sep a = String.concat sep (Array.to_list a) in
   match m with
     | Linear dev -> 
-       "linear",Printf.sprintf "%s %Ld" dev.device dev.offset
+       "linear",Printf.sprintf "%s %Ld" (resolve_device dev.device deref_table) dev.offset
     | Striped st ->
        "striped",
        Printf.sprintf "%d %Ld %s" (Array.length st.dests) st.chunk_size 
          (array_concat " " 
              (Array.map (fun dev -> 
-               Printf.sprintf "%s %Ld" dev.device dev.offset) st.dests))
+               Printf.sprintf "%s %Ld" (resolve_device dev.device deref_table) dev.offset) st.dests))
 
-let create dev map =
-  let newmap = Array.map (fun m ->
-    let (ty,params) = convert_mapty m.map in
-    (m.start, m.len, ty, params)) map in
-  _create dev newmap
+exception CreateError of (int64 * int64 * string * string) array
+exception ReloadError of (int64 * int64 * string * string) array
+let _writemap dev map =
+  let oc = open_out (Printf.sprintf "/tmp/%s.map" dev) in
+  Printf.fprintf oc "%s" (String.concat " " (Array.to_list (Array.map (fun (start,len,ty,params) -> Printf.sprintf "(start: %Ld len: %Ld ty: %s params: %s)" start len ty params) map)));
+  close_out oc
+    
+let _getmap map dereference_table =  
+  Array.map (fun m ->
+    let (ty,params) = convert_mapty m.map dereference_table in
+    (m.start, m.len, ty, params)) map 
+    
+let create dev map ?(dereference_table=[]) =
+  let newmap = _getmap map dereference_table in
+  try 
+    _writemap dev newmap;
+    _create dev newmap
+  with e ->
+    raise (CreateError newmap)
+      
+let reload dev map ?(dereference_table=[]) =
+  let newmap = _getmap map dereference_table in
+  try 
+    _writemap dev newmap;
+    _reload dev newmap
+  with e ->
+    raise (ReloadError newmap)
 
+let get_sector_pos_of map sector ~dereference_table =
+  match map.map with 
+    | Linear l -> (resolve_device l.device dereference_table, Int64.add l.offset sector)
+    | Striped s ->
+       (* Untested *)
+       let ndevs = Int64.of_int (Array.length s.dests) in
+       let chunk_num = Int64.div sector s.chunk_size in
+       let offset_in_chunk = Int64.rem sector s.chunk_size in
+       let dev_num = Int64.to_int (Int64.rem chunk_num ndevs) in
+       let dev_off = Int64.div chunk_num ndevs in
+       let device = s.dests.(dev_num) in
+       let offset_from_start = Int64.add (Int64.mul dev_off s.chunk_size) offset_in_chunk in   
+       let total_offset = Int64.add offset_from_start device.offset in
+       (resolve_device device.device dereference_table, total_offset)
+      
 let remove = _remove
 let table = _table
 let mknods = _mknods
 let mknod = _mknod
+let suspend = _suspend
+let resume = _resume 
+let to_string (m : mapping array) = Marshal.to_string m []
+let of_string s = (Marshal.from_string s 0 : mapping array)
index 6c24d56a5269db114cdff9a1b31b45a3169ab4fe..f08896034fd1e911e0882bd510f369726b1a8648 100644 (file)
@@ -11,7 +11,9 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU Lesser General Public License for more details.
  *)
-type dev = { device : string; offset : int64; }
+
+type devty = | Dereferenced of string | Real of string
+type dev = { device : devty; offset : int64; }
 type stripety = { chunk_size : int64; dests : dev array; }
 type mapty = Linear of dev | Striped of stripety
 type mapping = { start : int64; len : int64; map : mapty; }
@@ -27,9 +29,19 @@ type status = {
   read_only : bool;
   targets : (int64 * int64 * string * string) list;
 }
-val convert_mapty : mapty -> string * string
-val create : string -> mapping array -> unit
+
+exception CreateError of (int64 * int64 * string * string) array
+exception ReloadError of (int64 * int64 * string * string) array
+
+val convert_mapty : mapty -> (string * string) list -> string * string
+val create : string -> mapping array -> ?dereference_table : (string * string) list -> unit
+val reload : string -> mapping array -> ?dereference_table : (string * string) list -> unit
+val suspend : string -> unit
+val resume : string -> unit
 val remove : string -> unit
 val table : string -> status
 val mknods : string -> unit
 val mknod : string -> int -> int -> int -> unit
+val get_sector_pos_of : mapping -> int64 -> dereference_table:(string * string) list -> string * int64
+val to_string : mapping array -> string
+val of_string : string -> mapping array
index 168b0b8cb0d467b6bc6ace202740d27f2fd5f73f..e49120abeb172bc89e032e417c26df33b9bc47f3 100644 (file)
@@ -67,6 +67,46 @@ void camldm_create(value name, value map)
   CAMLreturn0;  
 }
 
+void camldm_reload(value name, value map) 
+{
+  CAMLparam2(name,map);
+
+  struct dm_task *dmt;
+  int i;
+  uint64_t start, size;
+  char *ty,*params;
+
+  if(!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
+    caml_failwith("Failed to create task!");
+
+  if(!dm_task_set_name(dmt, String_val(name))) 
+    goto out;
+
+  for(i=0; i<Wosize_val(map); i++) {
+    start=Int64_val(Field(Field(map,i),0));
+    size=Int64_val(Field(Field(map,i),1));
+    ty=String_val(Field(Field(map,i),2));
+    params=String_val(Field(Field(map,i),3));
+
+    printf("%" PRIu64 " %" PRIu64 " %s %s\n", start, size, ty, params);
+
+    if(!dm_task_add_target(dmt, start, size, ty, params))
+      goto out;
+  }
+  
+  if(!dm_task_run(dmt))
+    goto out;
+
+  goto win;
+
+ out:
+  dm_task_destroy(dmt);
+  caml_failwith("Failed!");
+
+ win:
+  CAMLreturn0;  
+}
+
 
 void camldm_mknods(value dev)
 {
@@ -177,6 +217,20 @@ void camldm_remove(value device)
   CAMLreturn0;
 }
 
+void camldm_suspend(value device)
+{
+  CAMLparam1(device);
+  _simple(DM_DEVICE_SUSPEND,String_val(device));
+  CAMLreturn0;
+}
+
+void camldm_resume(value device)
+{
+  CAMLparam1(device);
+  _simple(DM_DEVICE_RESUME,String_val(device));
+  CAMLreturn0;
+}
+
 void camldm_mknod(value path, value mode, value major, value minor)
 {
   CAMLparam4(path, mode, major, minor);
index 7c59e828205772793e6d5cc21b2de76a6c9cec30..dcdb5a9e97569e88ef34f9b5312b6cf8ba9c4c84 100644 (file)
@@ -22,6 +22,7 @@ let subset s1 s2 = List.fold_left (&&) true (List.map (fun s->List.mem s s2) s1)
 let set_equiv s1 s2 = (subset s1 s2) && (subset s2 s1)
 
 let iteri f list = ignore (fold_left (fun i x -> f i x; i+1) 0 list)
+let iteri_right f list = ignore (fold_right (fun x i -> f i x; i+1) list 0)
 
 let rec inv_assoc k = function
        | [] -> raise Not_found
index 64c81a073ef07618a8c46be5f7a6e689f90d42bc..335dea41f21dd2e28346d6e17536b43f1b7e0a81 100644 (file)
@@ -77,6 +77,8 @@ module List :
 
     val iteri : (int -> 'a -> unit) -> 'a list -> unit
 
+    val iteri_right : (int -> 'a -> unit) -> 'a list -> unit
+
     (** Map the given function over a list in reverse order. *)
     val rev_mapi : (int -> 'a -> 'b) -> 'a list -> 'b list
 
index b80287d75327be53dc2bac963f43228cc0384416..1e6c2744ec922f09473103679e808d9277c06a88 100644 (file)
@@ -460,6 +460,7 @@ let double_fork f =
 external set_tcp_nodelay : Unix.file_descr -> bool -> unit = "stub_unixext_set_tcp_nodelay"
 
 external fsync : Unix.file_descr -> unit = "stub_unixext_fsync"
+external blkgetsize64 : Unix.file_descr -> int64 = "stub_unixext_blkgetsize64"
 
 external get_max_fd : unit -> int = "stub_unixext_get_max_fd"
 
@@ -541,6 +542,18 @@ module Fdset = struct
        let select_wo w t = _select_wo w t
 end
 
+let wait_for_path path delay timeout =
+  let rec inner ttl =
+    if ttl=0 then failwith "No path!";
+    try 
+      ignore(Unix.stat path)
+    with _ ->
+      delay 0.5;
+      inner (ttl - 1)
+  in
+  inner (timeout * 2)
+       
+
 let _ = Callback.register_exception "unixext.unix_error" (Unix_error (0))
 
 (* HTTP helpers *)
index 4be933e4b51f43857f93fcd56a97de48781a6017..a07aff67df8f1bbf59a3bce6ff369af3ba825e7d 100644 (file)
@@ -83,6 +83,8 @@ external set_tcp_nodelay : Unix.file_descr -> bool -> unit
   = "stub_unixext_set_tcp_nodelay"
 external fsync : Unix.file_descr -> unit = "stub_unixext_fsync"
 external get_max_fd : unit -> int = "stub_unixext_get_max_fd"
+external blkgetsize64 : Unix.file_descr -> int64 = "stub_unixext_blkgetsize64"
+
 val int_of_file_descr : Unix.file_descr -> int
 val file_descr_of_int : int -> Unix.file_descr
 val close_all_fds_except : Unix.file_descr list -> unit
@@ -106,6 +108,8 @@ module Fdset : sig
        val select_wo : t -> float -> t
 end
 
+val wait_for_path : string -> (float -> unit) -> int -> unit
+
 (** Download a file via an HTTP GET *)
 val http_get: open_tcp:(server:string -> (in_channel * out_channel)) -> uri:string -> filename:string -> server:string -> unit
 (** Upload a file via an HTTP PUT *)
index 1600537d0404518aa475e26fd882d7f84e6b9ef0..ba744a766263535be18401f58598f5a4d735b8b1 100644 (file)
@@ -20,6 +20,8 @@
 #include <string.h>
 #include <unistd.h> /* needed for _SC_OPEN_MAX */
 #include <stdio.h> /* snprintf */
+#include <sys/ioctl.h>
+#include <linux/fs.h> 
 
 #include <caml/mlvalues.h>
 #include <caml/memory.h>
@@ -59,6 +61,16 @@ CAMLprim value stub_unixext_fsync (value fd)
        CAMLreturn(Val_unit);
 }
        
+CAMLprim value stub_unixext_blkgetsize64(value fd)
+{
+  CAMLparam1(fd);
+  uint64_t size;
+  int c_fd = Int_val(fd);
+  if(ioctl(c_fd,BLKGETSIZE64,&size)) {
+    failwith_errno();
+  }
+  CAMLreturn(caml_copy_int64(size));
+}
 
 CAMLprim value stub_unixext_get_max_fd (value unit)
 {