X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=lib%2Fdiskimage.mli;h=3f59bad39180e7c318df87f849ddf22037dfe04f;hb=70ecd5f92e887185fd3e09f603e4c5e1a06ef4f4;hp=e3a85b605ffe797a57d5dce17a3b2603db4581f4;hpb=8634421d865fb745cc6ce742f6e43d306a071bac;p=virt-df.git diff --git a/lib/diskimage.mli b/lib/diskimage.mli index e3a85b6..3f59bad 100644 --- a/lib/diskimage.mli +++ b/lib/diskimage.mli @@ -28,44 +28,7 @@ ]} *) -(** - {2 Machine/device model} - - The "machine/device model" that we currently understand looks - like this: - -{v -machines - | - \--- host partitions / disk image files - || - guest block devices - | - +--> guest partitions (eg. using MBR) - | | - \-(1)->+--- filesystems (eg. ext3) - | - \--- PVs for LVM - ||| - VGs and LVs -v} - - (1) Filesystems and PVs may also appear directly on guest - block devices. - - Partition schemes (eg. MBR) and filesystems register themselves - with this main module and they are queried first to get an idea - of the physical devices, partitions and filesystems potentially - available to the guest. - - Volume management schemes (eg. LVM2) register themselves here - and are called later with "spare" physical devices and partitions - to see if they contain LVM data. If this results in additional - logical volumes then these are checked for filesystems. - - Swap space is considered to be a dumb filesystem for the purposes - of this discussion. -*) +(** {2 Device class and specialized subclasses} *) class virtual device : object @@ -77,14 +40,28 @@ class virtual device : 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 close : unit -> unit - (** Close the device. This must be called to fully free up - any resources used by the device. *) - method virtual read : int64 -> int -> string - (** [read offset len] reads len bytes starting at offset. *) + method read : int64 -> int -> 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 + map each block in the request. *) method read_bitstring : int64 -> int -> Bitmatch.bitstring (** [read_bitstring] is the same as [read] but returns a pa_bitmatch-style bitstring. *) + method virtual blocksize : int + (** [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 + mapped down to any underlying device(s). + + Returns [[]] (empty list) if there is no underlying + device for this block. Otherwise returns a list of + [(device, byte-offset)] locations where this block is mapped. + + Normally the returned list has length 1, but in cases + such as mirroring you can have the same block mapped + to several underlying devices. *) end (** A virtual (or physical!) device, encapsulating any translation @@ -95,27 +72,35 @@ class virtual device : Note this very rare use of OOP in OCaml! *) -class block_device : string -> +class block_device : string -> int -> object method name : string method size : int64 - method close : unit -> unit method read : int64 -> int -> string method read_bitstring : int64 -> int -> Bitmatch.bitstring + method blocksize : int + method mapblock : int64 -> (device * int64) list + method close : unit -> unit + (** Close the device, freeing up the file descriptor. *) end - (** A concrete device which just direct-maps a file or /dev device. *) + (** A concrete device which just direct-maps a file or /dev device. + + Create the device with [new block_device filename blocksize] + where [filename] is the path to the file or device and + [blocksize] is the blocksize of the device. *) -class offset_device : string -> int64 -> int64 -> device -> +class offset_device : string -> int64 -> int64 -> int -> device -> object method name : string method size : int64 - method close : unit -> unit method read : int64 -> int -> string method read_bitstring : int64 -> int -> Bitmatch.bitstring + method blocksize : int + method mapblock : int64 -> (device * int64) list end (** A concrete device which maps a linear part of an underlying device. - [new offset_device name start size dev] creates a new + [new offset_device name start size blocksize dev] creates a new device which maps bytes from [start] to [start+size-1] of the underlying device [dev] (ie. in this device they appear as bytes [0] to [size-1]). @@ -123,9 +108,61 @@ class offset_device : string -> int64 -> int64 -> device -> Useful for things like partitions. *) +class blocksize_overlay : int -> 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 + end + (** Change the blocksize of an existing device. *) + val null_device : device (** The null device. Any attempt to read generates an error. *) +(** + {2 Structures used to describe machines, disks, partitions and filesystems} + + {3 Machine/device model} + + The "machine/device model" that we currently understand looks + like this: + +{v +machines + | + \--- host partitions / disk image files + || + guest block devices + | + +--> guest partitions (eg. using MBR) + | | + \-(1)->+--- filesystems (eg. ext3) + | + \--- PVs for LVM + ||| + VGs and LVs +v} + + (1) Filesystems and PVs may also appear directly on guest + block devices. + + Partition schemes (eg. MBR) and filesystems register themselves + with this main module and they are queried first to get an idea + of the physical devices, partitions and filesystems potentially + available to the guest. + + Volume management schemes (eg. LVM2) register themselves here + and are called later with "spare" physical devices and partitions + to see if they contain LVM data. If this results in additional + logical volumes then these are checked for filesystems. + + Swap space is considered to be a dumb filesystem for the purposes + of this discussion. +*) + type machine = { m_name : string; (** Machine name. *) m_disks : disk list; (** Machine disks. *) @@ -136,7 +173,7 @@ type machine = { and disk = { d_name : string; (** Device name (eg "hda") *) - d_dev : device; (** Disk device. *) + d_dev : block_device; (** Disk device. *) d_content : disk_content; (** What's on it. *) } (** A single physical disk image. *) @@ -169,7 +206,8 @@ and partition_content = and filesystem = { fs_plugin_id : fs_plugin_id; (** Filesystem type. *) - fs_block_size : int64; (** Block size (bytes). *) + fs_dev : device; (** Device containing the filesystem. *) + fs_blocksize : int; (** Block size (bytes). *) fs_blocks_total : int64; (** Total blocks. *) fs_is_swap : bool; (** If swap, following not valid. *) fs_blocks_reserved : int64; (** Blocks reserved for super-user. *) @@ -180,7 +218,7 @@ and filesystem = { fs_inodes_avail : int64; (** Inodes free (available). *) fs_inodes_used : int64; (** Inodes in use. *) } - (** A filesystem. *) + (** A filesystem, with superblock contents. *) and pv = { lvm_plugin_id : lvm_plugin_id; (** The LVM plug-in which detected @@ -219,7 +257,7 @@ val open_machine : string -> (string * string) list -> machine val close_machine : machine -> unit (** This is a convenience function which calls the [dev#close] - method on any open devices owned by the machine. This just + method on any open {!block_device}s owned by the machine. This just has the effect of closing any file descriptors which are opened by these devices. *) @@ -229,6 +267,8 @@ val scan_machine : machine -> machine identifying all partitions, filesystems, physical and logical volumes that are known to this library. + This scans down to the level of the filesystem superblocks. + Returns an updated {!machine} structure with the scan results. *)