Skip to content

Commit 5458450

Browse files
committed
CP-7327 nice and ionice config options for sparse_dd.conf
Signed-off-by: Thomas Sanders <[email protected]> (cherry picked from commit 1614b17)
1 parent db93e62 commit 5458450

File tree

2 files changed

+104
-1
lines changed

2 files changed

+104
-1
lines changed

src/sparse_dd.conf

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,25 @@
1010
# user: do what the user asks
1111
# encryption-mode = user
1212

13+
# Priority settings for sparse_dd
14+
15+
# Scheduling priority for the process: "niceness" as in the "nice" and
16+
# "renice" commands. An integer in the range -20 (highest priority)
17+
# to 19 (lowest priority, thus nicest to other processes).
18+
# nice = 19
19+
20+
# IO scheduling class and priority for use with the "ionice" command.
21+
# See "man ionice" for details, but ionice_class can be one of
22+
# 0: none
23+
# 1: real-time
24+
# 2: best-effort
25+
# 3: idle
26+
# ionice_class = 3
27+
# If ionice_class is real-time or best-effort, then ionice_class_data
28+
# can be used to specify priority within the class using an integer
29+
# in the range 0 (highest priority) to 7 (lowest).
30+
# ionice_class_data = 7
31+
1332
# This reads directly from the source VHD file (when possible)
1433
# avoiding a round-trip through tapdisk and the kernel.
1534
# NB it is unsafe to use this if the files are being coalesced.

src/sparse_dd.ml

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ let config_file = "/etc/sparse_dd.conf"
88

99
let vhd_search_path = "/dev/mapper"
1010

11+
let ionice_cmd = "/usr/bin/ionice"
12+
let renice_cmd = "/usr/bin/renice"
13+
1114
type encryption_mode =
1215
| Always
1316
| Never
@@ -23,6 +26,11 @@ let encryption_mode_of_string = function
2326
| x -> failwith (Printf.sprintf "Unknown encryption mode %s. Use always, never or user." x)
2427
let encryption_mode = ref User
2528

29+
(* Niceness: strings that may or may not be valid ints. *)
30+
let nice = ref None
31+
let ionice_class = ref None
32+
let ionice_class_data = ref None
33+
2634
let base = ref None
2735
let src = ref None
2836
let dest = ref None
@@ -38,9 +46,17 @@ let string_opt = function
3846

3947
let machine_readable_progress = ref false
4048

41-
let options = [
49+
let options =
50+
let str_option name var_ref description =
51+
name, Arg.String (fun x -> var_ref := Some x), (fun () -> string_opt !var_ref), description
52+
in
53+
[
4254
"unbuffered", Arg.Bool (fun b -> File.use_unbuffered := b), (fun () -> string_of_bool !File.use_unbuffered), "use unbuffered I/O via O_DIRECT";
4355
"encryption-mode", Arg.String (fun x -> encryption_mode := encryption_mode_of_string x), (fun () -> string_of_encryption_mode !encryption_mode), "how to use encryption";
56+
(* Want to ignore bad values for "nice" etc. so not using Arg.Int *)
57+
str_option "nice" nice "If supplied, the scheduling priority will be set using this value as argument to the 'nice' command.";
58+
str_option "ionice_class" ionice_class "If supplied, the io scheduling class will be set using this value as -c argument to the 'ionice' command.";
59+
str_option "ionice_class_data" ionice_class_data "If supplied, the io scheduling class data will be set using this value as -n argument to the 'ionice' command.";
4460
"experimental-reads-bypass-tapdisk", Arg.Set experimental_reads_bypass_tapdisk, (fun () -> string_of_bool !experimental_reads_bypass_tapdisk), "bypass tapdisk and read directly from the underlying vhd file";
4561
"experimental-writes-bypass-tapdisk", Arg.Set experimental_writes_bypass_tapdisk, (fun () -> string_of_bool !experimental_writes_bypass_tapdisk), "bypass tapdisk and write directly to the underlying vhd file";
4662
"base", Arg.String (fun x -> base := Some x), (fun () -> string_opt !base), "base disk to search for differences from";
@@ -218,6 +234,74 @@ let _ =
218234
let size = !size in
219235
let base = !base in
220236

237+
(* Helper function to bring an int into valid range *)
238+
let clip v min max descr =
239+
if v < min then (
240+
warn "Value %d is too low for %s. Using %d instead." v descr min;
241+
min
242+
) else if v > max then (
243+
warn "Value %d is too high for %s. Using %d instead." v descr max;
244+
max
245+
) else v
246+
in
247+
248+
(
249+
let parse_as_int str_opt int_opt_ref opt_name =
250+
match str_opt with
251+
| None -> ()
252+
| Some str ->
253+
try
254+
int_opt_ref := Some (int_of_string str)
255+
with _ ->
256+
error "Ignoring invalid value for %s: %s" opt_name str
257+
in
258+
259+
(* renice this process if specified *)
260+
let n_ref = ref None in
261+
parse_as_int !nice n_ref "nice";
262+
(match !n_ref with
263+
| None -> ()
264+
| Some n -> (
265+
(* Run command like: renice -n priority -p pid *)
266+
let n = clip n (-20) 19 "nice" in
267+
let pid = string_of_int (Unix.getpid ()) in
268+
let (stdout, stderr) = Forkhelpers.execute_command_get_output renice_cmd ["-n"; string_of_int n; "-p"; pid]
269+
in ()
270+
)
271+
);
272+
273+
(* Possibly run command like: ionice -c class -n classdata -p pid *)
274+
let c_ref = ref None in
275+
let cd_ref = ref None in
276+
parse_as_int !ionice_class c_ref "ionice_class";
277+
parse_as_int !ionice_class_data cd_ref "ionice_class_data";
278+
279+
match !c_ref with
280+
| None -> ()
281+
| Some c ->
282+
let pid = string_of_int (Unix.getpid ()) in
283+
let ionice args =
284+
let (stdout, stderr) = Forkhelpers.execute_command_get_output ionice_cmd args
285+
in ()
286+
in
287+
let class_only c =
288+
ionice ["-c"; string_of_int c; "-p"; pid]
289+
in
290+
let class_and_data c n =
291+
ionice ["-c"; string_of_int c; "-n"; string_of_int n; "-p"; pid]
292+
in
293+
match c with
294+
| 0 | 3 ->
295+
class_only c
296+
| 1 | 2 -> (
297+
match !cd_ref with
298+
| None -> class_only c
299+
| Some n ->
300+
let n = clip n 0 7 "ionice classdata" in
301+
class_and_data c n)
302+
| _ -> error "Cannot use ionice due to invalid class value: %d" c
303+
);
304+
221305
debug "src = %s; dest = %s; base = %s; size = %Ld" src dest (Opt.default "None" base) size;
222306
let src_vhd = vhd_of_device src in
223307
let dest_vhd = vhd_of_device dest in

0 commit comments

Comments
 (0)