Added private_data_functions.
[virt-df.git] / lib / diskimage_lvm2.ml
index ea127cb..2c2fa60 100644 (file)
 open Printf
 open ExtList
 
-open Diskimage_utils
+open Diskimage_impl
 open Diskimage_lvm2_metadata
 
 open Int63.Operators
 
-let plugin_id = "LVM2"
+let id = "LVM2"
 
 let sector_size_int = 512
 let sector_size = ~^sector_size_int
@@ -64,33 +64,50 @@ object (self)
    *)
   method blocksize = extent_size
 
-  (* Map block (extent) i to the underlying device. *)
-  method mapblock i =
+  method private map i =
     if i < ~^0 || i >= size_in_extents then
       invalid_arg "linear_map_device: read outside device";
 
     let rec loop = function
       | [] ->
-         []
+         None
       | (start_extent, end_extent, dev, pvoffset) :: rest ->
-         if start_extent <= i && i < end_extent then
-           [dev, (pvoffset +^ i) *^ extent_size]
-         else
+         if start_extent <= i && i < end_extent then (
+           let dev_offset = (pvoffset +^ i) *^ extent_size in
+           Some (start_extent, end_extent, dev, dev_offset, pvoffset)
+         ) else
            loop rest
     in
     loop segments
 
+  (* Map block (extent) i to the underlying device. *)
+  method map_block i =
+    match self#map i with
+    | Some (_, _, dev, dev_offset, _) -> [dev, dev_offset]
+    | None -> []
+
+  (* Continguous span. *)
+  method contiguous offset =
+    let offset_in_extents = offset /^ extent_size in
+
+    (* Get the segment that this offset lies in. *)
+    match self#map offset_in_extents with
+    | Some (_, end_extent, dev, dev_offset, _) ->
+       (* Contiguous bytes up to the end of this extent. *)
+       end_extent *^ extent_size -^ offset
+    | None -> ~^0
+
   (* NB. Use the superclass #read method. *)
 end
 
 (*----------------------------------------------------------------------*)
 (* Probe to see if it's an LVM2 PV. *)
-let rec probe lvm_plugin_id dev =
+let rec probe dev =
   try
     let uuid, _ = read_pv_label dev in
     if !debug then
       eprintf "LVM2 detected PV UUID %s\n%!" uuid;
-    { lvm_plugin_id = lvm_plugin_id; pv_uuid = uuid }
+    { pv_cb = callbacks; pv_uuid = uuid; pv_dev = dev }
   with exn ->
     if !debug then prerr_endline (Printexc.to_string exn);
     raise Not_found
@@ -164,15 +181,17 @@ and read_metadata dev offset len =
  * (as devices) and return them.  Note that we don't try to detect
  * what is on these LVs - that will be done in the main code.
  *)
-let rec list devs =
+and list_lvs pvs =
   (* Read the UUID and metadata (again) from each device to end up with
    * an assoc list of PVs, keyed on the UUID.
+   *
+   * XXX We've already read this - we should save it in the pv struct.
    *)
   let pvs = List.map (
-    fun dev ->
+    fun { pv_dev = dev } ->
       let uuid, metadata = read_pv_label dev in
       (uuid, (metadata, dev))
-  ) devs in
+  ) pvs in
 
   (* Parse the metadata using the external lexer/parser. *)
   let pvs = List.map (
@@ -430,3 +449,18 @@ let rec list devs =
 
   (* Return the list of LV devices. *)
   lvs
+
+(* XXX We don't currently have enough information in the PV
+ * structure to determine quickly which blocks are used.  Need
+ * to store the parsed metadata in the structure ...
+ *)
+and offset_is_free _ _ = false
+
+and callbacks = {
+  lvm_cb_name = id;
+  lvm_cb_list_lvs = list_lvs;
+  lvm_cb_offset_is_free = offset_is_free;
+}
+
+(* Register the plugin. *)
+let () = register_plugin ~lvm:probe id