Skip to content

Commit 9b1369a

Browse files
committed
Merge pull request #131 from djs55/dump
lvcreate: support `-a n` and `-a y`
2 parents 80d095c + a60e266 commit 9b1369a

File tree

2 files changed

+114
-29
lines changed

2 files changed

+114
-29
lines changed

xenvm/lvcreate.ml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ open Lwt
55

66

77
(* lvcreate -n <name> vgname -l <size_in_percent> -L <size_in_mb> --addtag tag *)
8-
let lvcreate copts lv_name real_size percent_size tags vg_name =
8+
let lvcreate copts lv_name real_size percent_size tags vg_name action =
99
let open Xenvm_common in
1010
let info = Lwt_main.run (
1111
get_vg_info_t copts vg_name >>= fun info ->
@@ -35,7 +35,10 @@ let lvcreate copts lv_name real_size percent_size tags vg_name =
3535
| e -> fail e
3636
) >>= fun () ->
3737
return info) in
38-
match info with | Some i -> Lvchange.lvchange_activate copts vg_name lv_name (Some i.local_device) false | None -> ()
38+
match action with
39+
| Some Xenvm_common.Activate ->
40+
(match info with | Some i -> Lvchange.lvchange_activate copts vg_name lv_name (Some i.local_device) false | None -> ())
41+
| _ -> ()
3942

4043
let lv_name_arg =
4144
let doc = "Gives the name of the LV to be created. This must be unique within the volume group. " in
@@ -55,7 +58,7 @@ let lvcreate_cmd =
5558
`S "DESCRIPTION";
5659
`P "lvcreate creates a new logical volume in a volume group by allocating logical extents from the free physical extent pool of that volume group. If there are not enough free physical extents then the volume group can be extended with other physical volumes or by reducing existing logical volumes of this volume group in size."
5760
] in
58-
Term.(pure lvcreate $ Xenvm_common.copts_t $ lv_name_arg $ Xenvm_common.real_size_arg $ Xenvm_common.percent_size_arg $ tags_arg $ vg_name_arg),
61+
Term.(pure lvcreate $ Xenvm_common.copts_t $ lv_name_arg $ Xenvm_common.real_size_arg $ Xenvm_common.percent_size_arg $ tags_arg $ vg_name_arg $ Xenvm_common.action_arg),
5962
Term.info "lvcreate" ~sdocs:"COMMON OPTIONS" ~doc ~man
6063

6164

xenvm/xenvm.ml

Lines changed: 108 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,30 @@ let format config name filenames =
7979
return () in
8080
Lwt_main.run t
8181

82+
let dump config filenames =
83+
let t =
84+
let module Vg_IO = Vg.Make(Log)(Block)(Time)(Clock) in
85+
let open Xenvm_interface in
86+
Lwt_list.map_s
87+
(fun filename ->
88+
Block.connect filename
89+
>>= function
90+
| `Error _ -> fail (Failure (Printf.sprintf "Failed to open %s" filename))
91+
| `Ok x -> return x
92+
) filenames
93+
>>= fun blocks ->
94+
Vg_IO.connect blocks `RO
95+
>>|= fun vg ->
96+
let md = Vg_IO.metadata_of vg in
97+
let buf = Cstruct.create (64 * 1024 * 1024) in
98+
let next = Vg.marshal md buf in
99+
let buf = Cstruct.(sub buf 0 ((len buf) - (len next))) in
100+
let txt = Cstruct.to_string buf in
101+
output_string Pervasives.stdout txt;
102+
output_string Pervasives.stdout "\n";
103+
return () in
104+
Lwt_main.run t
105+
82106
let host_create copts (vg_name,_) host =
83107
let t =
84108
get_vg_info_t copts vg_name >>= fun info ->
@@ -140,37 +164,79 @@ let shutdown copts (vg_name,_) =
140164
lwt_while (fun () -> is_alive pid) (fun () -> Lwt_unix.sleep 1.0)
141165
in Lwt_main.run t
142166

143-
let benchmark copts (vg_name,_) =
167+
let benchmark copts (vg_name,_) volumes threads =
144168
let t =
145169
let creation_host = Unix.gethostname () in
146170
get_vg_info_t copts vg_name >>= fun info ->
147171
set_uri copts info;
148172
let mib = Int64.mul 1048576L 4L in
149-
let number = 1000 in
150-
let start = Unix.gettimeofday () in
151-
let rec fori test_name acc f = function
152-
| 0 -> return acc
153-
| n ->
154-
f n
155-
>>= fun () ->
156-
( if ((n * 100) / number) <> (((n + 1) * 100) / number)
157-
then stderr "%s %d %% complete\n%!" test_name (100 - (n * 100) / number)
158-
else return () ) >>= fun () ->
159-
fori test_name ((number - n, Unix.gettimeofday () -. start) :: acc) f (n - 1) in
160-
fori "Creating volumes" [] (fun i -> Client.create ~name:(Printf.sprintf "test-lv-%d" i) ~size:mib ~creation_host ~creation_time:(Unix.gettimeofday () |> Int64.of_float) ~tags:[]) number
161-
>>= fun creates ->
162-
let time = Unix.gettimeofday () -. start in
173+
174+
let start = ref (Unix.gettimeofday ()) in
175+
let n_pending = ref volumes in
176+
let m = Lwt_mutex.create () in
177+
let n_complete = ref 0 in
178+
let times = ref [] in
179+
let on_complete () =
180+
incr n_complete;
181+
let n = !n_complete in
182+
times := (n, Unix.gettimeofday () -. !start) :: !times;
183+
if ((n * 100) / volumes) <> (((n + 1) * 100) / volumes)
184+
then stderr "%d %% complete" ((n * 100) / volumes)
185+
else return () in
186+
let rec worker f =
187+
Lwt_mutex.with_lock m
188+
(fun () ->
189+
if !n_pending > 0 then begin
190+
decr n_pending;
191+
return (Some (volumes - !n_pending))
192+
end else return None)
193+
>>= function
194+
| Some n ->
195+
f n
196+
>>= fun () ->
197+
on_complete ()
198+
>>= fun () ->
199+
worker f
200+
| None ->
201+
return () in
202+
203+
let create n =
204+
Client.create ~name:(Printf.sprintf "test-lv-%d" n) ~size:mib ~creation_host ~creation_time:(Unix.gettimeofday () |> Int64.of_float) ~tags:[] in
205+
let destroy n =
206+
Client.remove ~name:(Printf.sprintf "test-lv-%d" n) in
207+
208+
let rec mkints = function
209+
| 0 -> []
210+
| n -> n :: (mkints (n - 1)) in
211+
let creators = List.map (fun _ -> worker create) (mkints threads) in
212+
Lwt.join creators
213+
>>= fun () ->
214+
163215
let oc = open_out "benchmark.dat" in
164-
List.iter (fun (n, t) -> Printf.fprintf oc "%d %f\n" n t) (List.rev creates);
165-
Printf.fprintf oc "# %d creates in %.1f s\n" number time;
166-
Printf.fprintf oc "# Average %.1f /sec\n" (float_of_int number /. time);
167-
let start = Unix.gettimeofday () in
168-
fori "Removing volumes" [] (fun i -> Client.remove ~name:(Printf.sprintf "test-lv-%d" i)) number
169-
>>= fun destroys ->
170-
let time = Unix.gettimeofday () -. start in
171-
List.iter (fun (n, t) -> Printf.fprintf oc "%d %f\n" (number + n) t) (List.rev destroys);
172-
Printf.fprintf oc "# %d destroys in %.1f s\n" number time;
173-
Printf.fprintf oc "# Average %.1f /sec\n" (float_of_int number /. time);
216+
let time = Unix.gettimeofday () -. !start in
217+
List.iter (fun (n, t) -> Printf.fprintf oc "%d %f\n" n t) (List.rev !times);
218+
Printf.fprintf oc "# %d creates in %.1f s\n" volumes time;
219+
Printf.fprintf oc "# Average %.1f /sec\n" (float_of_int volumes /. time);
220+
221+
start := Unix.gettimeofday ();
222+
n_pending := volumes;
223+
n_complete := 0;
224+
times := [];
225+
226+
let destroyers = List.map (fun _ -> worker destroy) (mkints threads) in
227+
Lwt.join destroyers
228+
>>= fun () ->
229+
let time = Unix.gettimeofday () -. !start in
230+
List.iter (fun (n, t) -> Printf.fprintf oc "%d %f\n" (volumes + n) t) (List.rev !times);
231+
Printf.fprintf oc "# %d destroys in %.1f s\n" volumes time;
232+
Printf.fprintf oc "# Average %.1f /sec\n" (float_of_int volumes /. time);
233+
close_out oc;
234+
let oc = open_out "benchmark.gp" in
235+
Printf.fprintf oc "set xlabel \"LV number\"\n";
236+
Printf.fprintf oc "set ylabel \"Time/seconds\"\n";
237+
Printf.fprintf oc "set title \"Creating and then destroying %d LVs\"\n" volumes;
238+
Printf.fprintf oc "plot \"benchmark.dat\" with points\n";
239+
close_out oc;
174240
return () in
175241
Lwt_main.run t
176242

@@ -213,6 +279,15 @@ let size =
213279
let doc = "Size of the LV in megs" in
214280
Arg.(value & opt int64 4L & info ["size"] ~docv:"SIZE" ~doc)
215281

282+
let dump_cmd =
283+
let doc = "Dump the metadata in LVM format to stdout" in
284+
let man = [
285+
`S "DESCRIPTION";
286+
`P "Prints the volume group metadata to stdout in LVM format. Note this will not include any updates which are still pending in the redo-log."
287+
] in
288+
Term.(pure dump $ copts_t $ filenames),
289+
Term.info "dump" ~sdocs:copts_sect ~doc ~man
290+
216291
let format_cmd =
217292
let doc = "Format the specified file as a VG" in
218293
let man = [
@@ -285,7 +360,13 @@ let benchmark_cmd =
285360
`S "DESCRIPTION";
286361
`P "Perform some microbenchmarks and print the results.";
287362
] in
288-
Term.(pure benchmark $ copts_t $ name_arg),
363+
let volumes_arg =
364+
let doc = "The number of logical volumes which should be created then destroyed." in
365+
Arg.(value & opt int 10000 & info [ "volumes"; "v" ] ~docv:"VOLUMES" ~doc) in
366+
let threads_arg =
367+
let doc = "The number of concurrent worker threads which should create then destroy the volumes." in
368+
Arg.(value & opt int 1 & info [ "threads"; "t" ] ~docv:"THREADS" ~doc) in
369+
Term.(pure benchmark $ copts_t $ name_arg $ volumes_arg $ threads_arg),
289370
Term.info "benchmark" ~sdocs:copts_sect ~doc ~man
290371

291372
let default_cmd =
@@ -295,6 +376,7 @@ let cmds = [
295376
Lvresize.lvresize_cmd;
296377
Lvresize.lvextend_cmd;
297378
format_cmd;
379+
dump_cmd;
298380
shutdown_cmd; host_create_cmd; host_destroy_cmd;
299381
host_list_cmd;
300382
host_connect_cmd; host_disconnect_cmd; benchmark_cmd;

0 commit comments

Comments
 (0)