X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=lib%2Fdiskimage_lvm2.ml;h=0a9b74a962b702de9b9d1ab7a6d60a699fa26f51;hb=554b96246db7b4db7972a0aa50eb33d4d6039ab6;hp=143f32bf8361aac445016610bf5800119d6d4a59;hpb=de49d4605c37574f38b55b400db310f368640c94;p=virt-df.git diff --git a/lib/diskimage_lvm2.ml b/lib/diskimage_lvm2.ml index 143f32b..0a9b74a 100644 --- a/lib/diskimage_lvm2.ml +++ b/lib/diskimage_lvm2.ml @@ -23,16 +23,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 +105,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_dev = dev } + { pv_cb = callbacks (); pv_uuid = uuid; pv_dev = dev } with exn -> if !debug then prerr_endline (Printexc.to_string exn); raise Not_found @@ -120,8 +123,6 @@ 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 *) @@ -131,7 +132,7 @@ and read_pv_label dev = "LABELONE" : 64 : string; (* "LABELONE" *) _ : 128 : bitstring; (* Seems to contain something. *) "LVM2 001" : 64 : string; (* "LVM2 001" *) - uuid : 256 : string; (* UUID *) + uuid : 256 : string; (* PV UUID *) endsect : (sector_size_int-64)*8 : bitstring;(* to end of second sector *) (* sectors 2-7 *) @@ -147,56 +148,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 +202,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 +214,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 +302,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 +416,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 +447,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