Add .gitignore file for git.
[virt-df.git] / lib / diskimage.mli
index 09d791e..ee95453 100644 (file)
@@ -2,20 +2,21 @@
 (* (C) Copyright 2007-2008 Richard W.M. Jones, Red Hat Inc.
    http://libvirt.org/
 
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
-   (at your option) any later version.
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version,
+   with the OCaml linking exception described in ../COPYING.LIB.
 
-   This program is distributed in the hope that it will be useful,
+   This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
 
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *)
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
+*)
 
 (**
    {2 Examples}
@@ -34,25 +35,27 @@ class virtual device :
   object
     method virtual name : string
       (** Return some printable name for the device. *)
-    method virtual size : int64
+
+    method virtual size : Int63.t
       (** Return the size of the device in bytes.
 
          Note: For some types of devices, the device may have
          "holes", alignment requirements, etc. so this method doesn't
          imply that every byte from [0..size-1] is readable. *)
-    method read : int64 -> int -> string
+    method read : Int63.t -> Int63.t -> string
       (** [read offset len] reads len bytes starting at offset.
 
          Note: A default implementation is provided for [read],
-         but it is fairly inefficient because it uses {!mapblock} to
+         but it is fairly inefficient because it uses {!map_block} to
          map each block in the request. *)
-    method read_bitstring : int64 -> int -> Bitmatch.bitstring
+    method read_bitstring : Int63.t -> Int63.t -> Bitstring.bitstring
       (** [read_bitstring] is the same as [read] but returns
-         a pa_bitmatch-style bitstring. *)
-    method virtual blocksize : int
+         a pa_bitstring-style bitstring. *)
+
+    method virtual blocksize : Int63.t
       (** [blocksize] returns the natural block size of the device. *)
-    method virtual mapblock : int64 -> (device * int64) list
-      (** [mapblock] describes how a block in this device is
+    method virtual map_block : Int63.t -> (device * Int63.t) list
+      (** [map_block] describes how a block in this device is
          mapped down to any underlying device(s).
 
          Returns [[]] (empty list) if there is no underlying
@@ -62,24 +65,36 @@ class virtual device :
          Normally the returned list has length 1, but in cases
          such as mirroring you can have the same block mapped
          to several underlying devices. *)
+
+    method virtual contiguous : Int63.t -> Int63.t
+      (** [contiguous offset] returns the number of contiguous
+         {i bytes} starting at byte [offset] on this device,
+         before (eg.) end of device or some discontinuity in
+         the mapping table occurs.
+
+         This method and {!map_block} allow callers to determine how
+         high level blocks map to low level disk images efficiently
+         (complex striping and interleaving patterns can make the
+         process much less efficient however). *)
   end
   (**
      A virtual (or physical!) device, encapsulating any translation
      that has to be done to access the device.  eg. For partitions
      there is a simple offset, but for LVM you may need complicated
      table lookups.
-    
+     
      Note this very rare use of OOP in OCaml!
   *)
 
-class block_device : string -> int ->
+class block_device : string -> Int63.t ->
   object
     method name : string
-    method size : int64
-    method read : int64 -> int -> string
-    method read_bitstring : int64 -> int -> Bitmatch.bitstring
-    method blocksize : int
-    method mapblock : int64 -> (device * int64) list
+    method size : Int63.t
+    method read : Int63.t -> Int63.t -> string
+    method read_bitstring : Int63.t -> Int63.t -> Bitstring.bitstring
+    method blocksize : Int63.t
+    method map_block : Int63.t -> (device * Int63.t) list
+    method contiguous : Int63.t -> Int63.t
     method close : unit -> unit
       (** Close the device, freeing up the file descriptor. *)
   end
@@ -89,14 +104,15 @@ class block_device : string -> int ->
        where [filename] is the path to the file or device and
        [blocksize] is the blocksize of the device. *)
 
-class offset_device : string -> int64 -> int64 -> int -> device ->
+class offset_device : string -> Int63.t -> Int63.t -> Int63.t -> device ->
   object
     method name : string
-    method size : int64
-    method read : int64 -> int -> string
-    method read_bitstring : int64 -> int -> Bitmatch.bitstring
-    method blocksize : int
-    method mapblock : int64 -> (device * int64) list
+    method size : Int63.t
+    method read : Int63.t -> Int63.t -> string
+    method read_bitstring : Int63.t -> Int63.t -> Bitstring.bitstring
+    method blocksize : Int63.t
+    method map_block : Int63.t -> (device * Int63.t) list
+    method contiguous : Int63.t -> Int63.t
   end
     (** A concrete device which maps a linear part of an underlying device.
 
@@ -108,6 +124,18 @@ class offset_device : string -> int64 -> int64 -> int -> device ->
        Useful for things like partitions.
     *)
 
+class blocksize_overlay : Int63.t -> device ->
+  object
+    method name : string
+    method size : Int63.t
+    method read : Int63.t -> Int63.t -> string
+    method read_bitstring : Int63.t -> Int63.t -> Bitstring.bitstring
+    method blocksize : Int63.t
+    method contiguous : Int63.t -> Int63.t
+    method map_block : Int63.t -> (device * Int63.t) list
+  end
+    (** Change the blocksize of an existing device. *)
+
 val null_device : device
     (** The null device.  Any attempt to read generates an error. *)
 
@@ -175,7 +203,8 @@ and disk_content =
     ]
 
 and partitions = {
-  parts_plugin_id : parts_plugin_id;   (** Partitioning scheme. *)
+  parts_cb : partitioner_callbacks;    (** Partitioning scheme. *)
+  parts_dev : device;                  (** Partitions (whole) device. *)
   parts : partition list;              (** Partitions. *)
 }
 and partition = {
@@ -194,24 +223,25 @@ and partition_content =
     ]
 
 and filesystem = {
+  fs_cb : filesystem_callbacks;                (** Filesystem type. *)
   fs_dev : device;                     (** Device containing the filesystem. *)
-  fs_plugin_id : fs_plugin_id;         (** Filesystem type. *)
-  fs_block_size : int64;               (** Block size (bytes). *)
-  fs_blocks_total : int64;             (** Total blocks. *)
+  fs_blocksize : Int63.t;              (** Block size (bytes). *)
+  fs_blocks_total : Int63.t;           (** Total blocks. *)
   fs_is_swap : bool;                   (** If swap, following not valid. *)
-  fs_blocks_reserved : int64;          (** Blocks reserved for super-user. *)
-  fs_blocks_avail : int64;             (** Blocks free (available). *)
-  fs_blocks_used : int64;              (** Blocks in use. *)
-  fs_inodes_total : int64;             (** Total inodes. *)
-  fs_inodes_reserved : int64;          (** Inodes reserved for super-user. *)
-  fs_inodes_avail : int64;             (** Inodes free (available). *)
-  fs_inodes_used : int64;              (** Inodes in use. *)
+  fs_blocks_reserved : Int63.t;                (** Blocks reserved for super-user. *)
+  fs_blocks_avail : Int63.t;           (** Blocks free (available). *)
+  fs_blocks_used : Int63.t;            (** Blocks in use. *)
+  fs_inodes_total : Int63.t;           (** Total inodes. *)
+  fs_inodes_reserved : Int63.t;                (** Inodes reserved for super-user. *)
+  fs_inodes_avail : Int63.t;           (** Inodes free (available). *)
+  fs_inodes_used : Int63.t;            (** Inodes in use. *)
 }
     (** A filesystem, with superblock contents. *)
 
 and pv = {
-  lvm_plugin_id : lvm_plugin_id;        (** The LVM plug-in which detected
+  pv_cb : lvm_callbacks;               (** The LVM plug-in which detected
                                            this. *)
+  pv_dev : device;                     (** Device covering whole PV. *)
   pv_uuid : string;                    (** UUID. *)
 }
 and lv = {
@@ -219,17 +249,18 @@ and lv = {
 }
     (** Physical and logical volumes as used by LVM plug-ins. *)
 
-and parts_plugin_id
-and fs_plugin_id
-and lvm_plugin_id
-  (** Opaque IDs used to refer to the plug-ins. *)
+and partitioner_callbacks
+and filesystem_callbacks
+and lvm_callbacks
+
+(** {2 Functions} *)
 
-val name_of_parts : parts_plugin_id -> string
-val name_of_filesystem : fs_plugin_id -> string
-val name_of_lvm : lvm_plugin_id -> string
-  (** Convert plug-in IDs to printable strings. *)
+val name_of_filesystem : filesystem -> string
+  (** [name_of_filesystem fs] returns a printable name for
+      the filesystem.
+  *)
 
-(** {2 Scanning functions} *)
+(** {3 Create 'machine'} *)
 
 val open_machine : string -> (string * string) list -> machine
   (** [open_machine m_name devs]
@@ -244,6 +275,11 @@ val open_machine : string -> (string * string) list -> machine
       LV filesystems in the returned structure.
   *)
 
+val open_machine_from_devices : string -> (string * block_device) list ->
+  machine
+  (** This is the same as {!open_machine} except that instead
+      of passing a path you should pass a {!block_device} object. *)
+
 val close_machine : machine -> unit
   (** This is a convenience function which calls the [dev#close]
       method on any open {!block_device}s owned by the machine.  This just
@@ -251,6 +287,8 @@ val close_machine : machine -> unit
       opened by these devices.
   *)
 
+(** {3 Scanning for filesystems} *)
+
 val scan_machine : machine -> machine
   (** This does a complete scan of all devices owned by a machine,
       identifying all partitions, filesystems, physical and logical
@@ -261,6 +299,54 @@ val scan_machine : machine -> machine
       Returns an updated {!machine} structure with the scan results.
   *)
 
+(** {3 Create ownership tables} *)
+
+type ownership
+
+val create_ownership : machine -> ownership
+  (** This creates the ownership tables (mapping disk blocks to the
+      ultimate filesystem, etc., which owns each one).
+  *)
+
+type owner =
+    [ `Filesystem of filesystem
+    | `Partitions of partitions
+    | `PhysicalVolume of pv ]
+
+val get_owners_lookup : machine -> ownership -> block_device ->
+  (Int63.t -> (owner * Int63.t) list)
+  (** [get_owners_lookup machine disk] returns a specialized
+      function for looking up owners (filesystems, etc.)
+      which reside on block device [disk].
+
+      [disk] must be a block device of the machine.
+
+      The specialized lookup function that is returned
+      can be called as [lookup offset] to look up the
+      owners of byte offset [offset].
+
+      Returns a list of [(owner, owner_offset)] where [owner]
+      is the filesystem, etc., and [owner_offset] is the byte
+      offset relative to the owner.
+
+      It is common for there to be multiple owners: for example
+      in the case where a filesystem is created on a partition,
+      both the filesystem ([`Filesystem fs]) and
+      partition scheme ([`Partitions parts]) will be returned.
+
+      The specialized function is efficient.  {!create_ownership}
+      creates a tree structure which allows ownership to be determined
+      in just a few steps. *)
+
+val offset_is_free : (owner * Int63.t) list -> bool
+  (** [offset_is_free owners] tests if the offset is free (unused).
+
+      If an offset is free, then it may be discarded without
+      changing the semantics of the disk image.  In normal cases
+      this extends to the end of the current block, but blocksize
+      will differ for each owner, so what this really means is
+      tricky in practice. *)
+
 (** {2 Debugging} *)
 
 val debug : bool ref