X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=lib%2Fdiskimage_lvm2.ml;h=7e58cc9c3f73edb13cbc8ce750c16e1b1589313c;hb=ce220c62fccd46bb3fd79b863142fe6579ba40da;hp=4432e90e845d4f3d2a19eac9d6c99c7594e7a9f3;hpb=e1e5cfb926e886b8fc3126429d045b8ba305fe50;p=virt-df.git diff --git a/lib/diskimage_lvm2.ml b/lib/diskimage_lvm2.ml index 4432e90..7e58cc9 100644 --- a/lib/diskimage_lvm2.ml +++ b/lib/diskimage_lvm2.ml @@ -3,19 +3,20 @@ (C) Copyright 2007 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 Support for LVM2 PVs. *) @@ -23,16 +24,19 @@ 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 +(*let attach_private_data, get_private_data = + private_data_functions (fun {lvm_cb = {lvm_cb_uq = u}} -> u)*) + (*----------------------------------------------------------------------*) (* Block device which can do linear maps, same as the kernel dm-linear.c *) class linear_map_device name extent_size segments = @@ -102,12 +106,12 @@ 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 + 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 @@ -120,22 +124,20 @@ and read_pv_label dev = *) let bits = dev#read_bitstring ~^0 (~^9 *^ sector_size) in - (*Bitmatch.hexdump_bitstring stdout bits;*) - bitmatch bits with | { (* sector 0 *) - sector0 : sector_size_int*8 : bitstring; + _ : sector_size_int*8 : bitstring; (* sector 1 *) "LABELONE" : 64 : string; (* "LABELONE" *) _ : 128 : bitstring; (* Seems to contain something. *) "LVM2 001" : 64 : string; (* "LVM2 001" *) - uuid : 256 : string; (* UUID *) - endsect : (sector_size_int-64)*8 : bitstring;(* to end of second sector *) + uuid : 256 : string; (* PV UUID *) + _ : (sector_size_int-64)*8 : bitstring;(* to end of second sector *) (* sectors 2-7 *) - sectors234567 : sector_size_int*8 * 6 : bitstring; + _ : sector_size_int*8 * 6 : bitstring; (* sector 8 *) _ : 320 : bitstring; (* start of sector 8 *) @@ -147,56 +149,53 @@ and read_pv_label dev = (* Metadata offset is relative to end of PV label. *) let metadata_offset = Int63.of_int32 metadata_offset +^ ~^0x1000 in (* Metadata length appears to include the trailing \000 which - * we don't want. + * we don't want, so subtract 1 to get the true length. *) let metadata_length = Int63.of_int32 metadata_length -^ ~^1 in - let metadata = read_metadata dev metadata_offset metadata_length in + (* Check the metadata offset and length are sensible. *) + if metadata_offset <= ~^0x1200 || metadata_offset >= dev#size + || metadata_length <= ~^0 + || metadata_offset +^ metadata_length >= dev#size then + invalid_arg "LVM2: read_metadata: bad metadata offset or length"; - uuid, metadata + uuid, metadata_offset, metadata_length | { _ } -> invalid_arg (sprintf "LVM2: read_pv_label: %s: not an LVM2 physical volume" dev#name) -and read_metadata dev offset len = - if !debug then - eprintf "metadata: offset %s len %s bytes\n%!" - (Int63.to_string offset) (Int63.to_string len); - - (* Check the offset and length are sensible. *) - if offset <= ~^0x1200 || offset >= dev#size - || len <= ~^0 || offset +^ len >= dev#size then - invalid_arg "LVM2: read_metadata: bad metadata offset or length"; - - (* If it is outside the disk boundaries, this will throw an exception, - * otherwise it will read and return the metadata string. - *) - dev#read offset len - (*----------------------------------------------------------------------*) (* We are passed a list of devices which we previously identified * as PVs belonging to us. From these produce a list of all LVs * (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 = - (* Read the UUID and metadata (again) from each device to end up with - * an assoc list of PVs, keyed on the UUID. +and list_lvs pvs = + (* Read the PV label (again) for each PV, and this time also + * read out the metadata, which is a big block of text. *) - let pvs = List.map ( - fun dev -> - let uuid, metadata = read_pv_label dev in + let pvsmap = List.map ( + fun { pv_dev = dev } -> + let uuid, metadata_offset, metadata_length = read_pv_label dev in + let metadata = dev#read metadata_offset metadata_length in + + if !debug then + eprintf "list_lvs: metadata for PV %s (offset %s len %s):\n%s\n%!" + dev#name + (Int63.to_string metadata_offset) (Int63.to_string metadata_length) + metadata; + (uuid, (metadata, dev)) - ) devs in + ) pvs in (* Parse the metadata using the external lexer/parser. *) - let pvs = List.map ( + let pvsmap = List.map ( fun (uuid, (metadata, dev)) -> uuid, (Diskimage_lvm2_lexer.parse_lvm2_metadata_from_string metadata, dev) - ) pvs in + ) pvsmap in (* Print the parsed metadata. *) if !debug then @@ -204,7 +203,7 @@ let rec list devs = fun (uuid, (metadata, dev)) -> eprintf "metadata for PV UUID %s on %s:\n" uuid dev#name; output_metadata stderr metadata - ) pvs; + ) pvsmap; (* Scan for volume groups. The first entry in the metadata * appears to be the volume group name. This gives us a @@ -216,7 +215,7 @@ let rec list devs = | pvuuid, (((vgname, Metadata vgmeta) :: _), dev) -> Some (vgname, (pvuuid, vgmeta)) | _ -> None - ) pvs in + ) pvsmap in let cmp ((a:string),_) ((b:string),_) = compare a b in let vgnames = List.sort ~cmp vgnames in @@ -304,7 +303,7 @@ let rec list devs = let pvuuid = canonical_uuid pvuuid in (* Get the underlying physical device. *) - let _, dev = List.assoc pvuuid pvs in + let _, dev = List.assoc pvuuid pvsmap in (* Construct a PV device. *) let pe_start = get_int63 "pe_start" meta in @@ -418,10 +417,12 @@ let rec list devs = flush stderr ); +(* List.iter (fun pv -> attach_private_data pv vgs) pvs; *) + (* Finally we can set up devices for the LVs. *) let lvs = List.map ( - fun (vgname, (pvuuid, vgmeta, pvdevs, extent_size, lvs)) -> + fun (vgname, (pvuuids, vgmeta, pvdevs, extent_size, lvs)) -> try List.map ( fun (lvname, segments) -> @@ -447,3 +448,20 @@ let rec list devs = (* Return the list of LV devices. *) lvs + +(* XXX We need to reparse the metadata in a different way in + * order to calculate this. Need to generalize metadata handling. + *) +and offset_is_free _ _ = false + +and callbacks = + let i = ref 0 in + fun () -> { + lvm_cb_uq = (incr i; !i); + 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