Restructure library for dealing with block mappings.
[virt-df.git] / lib / diskimage_lvm2.ml
index e14c14e..0f00e1f 100644 (file)
@@ -51,39 +51,34 @@ class linear_map_device name extent_size segments =
     List.fold_left max 0L
       (List.map (fun (_, end_extent, _, _) -> end_extent) segments) in
   let size = size_in_extents *^ extent_size in
-object
+object (self)
   inherit device
   method name = name
   method size = size
 
-  (* Read method checks which segment the request lies inside and
-   * maps it to the underlying device.  If there is no mapping then
-   * we have to return an error.
-   *
-   * The request must lie inside a single extent, otherwise this is
-   * also an error (XXX - should lift this restriction, however default
-   * extent size is 4 MB so we probably won't hit this very often).
+  (* The natural blocksize for LVM devices is the extent size.
+   * NB. Throws a runtime exception if the extent size is bigger
+   * than an int (only likely to matter on 32 bit).
    *)
-  method read offset len =
-    let offset_in_extents = offset /^ extent_size in
-
-    (* Check we don't cross an extent boundary. *)
-    if (offset +^ Int64.of_int (len-1)) /^ extent_size <> offset_in_extents
-    then invalid_arg "linear_map_device: request crosses extent boundary";
+  method blocksize = Int64.to_int extent_size
 
-    if offset_in_extents < 0L || offset_in_extents >= size_in_extents then
+  (* Map block (extent) i to the underlying device. *)
+  method mapblock i =
+    if i < 0L || i >= size_in_extents then
       invalid_arg "linear_map_device: read outside device";
 
     let rec loop = function
       | [] ->
-         invalid_arg "linear_map_device: offset not mapped"
+         []
       | (start_extent, end_extent, dev, pvoffset) :: rest ->
-         if start_extent <= offset_in_extents &&
-            offset_in_extents < end_extent
-         then dev#read (offset +^ pvoffset *^ extent_size) len
-         else loop rest
+         if start_extent <= i && i < end_extent then
+           [dev, (pvoffset +^ i) *^ extent_size]
+         else
+           loop rest
     in
     loop segments
+
+  (* NB. Use the superclass #read method. *)
 end
 
 (*----------------------------------------------------------------------*)
@@ -302,7 +297,13 @@ let rec list devs =
                let pe_start = pe_start *^ sector_size64 in
                let pe_count = get_int64 "pe_count" meta in
                let pe_count = pe_count *^ extent_size in
-               let pvdev = new offset_device pvuuid pe_start pe_count dev in
+               let pvdev =
+                 new offset_device
+                   pvuuid (* name *)
+                   pe_start pe_count (* start, size in bytes *)
+                   (* don't really have a natural block size ... *)
+                   (Int64.to_int extent_size)
+                   dev (* underlying device *) in
 
                Some (pvname, pvdev)
            | _ ->