Skip to content

rrdp: discard stats #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion ocaml/xcp-rrdd/bin/read-blktap-stats/read_blktap_stats.ml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ let () =
Printf.printf "write_sectors = %Ld\n" (get_stats_write_sectors s) ;
Printf.printf "write_total_ticks = %Ld\n" (get_stats_write_total_ticks s) ;
Printf.printf "io_errors = %Ld\n" (get_stats_io_errors s) ;
Printf.printf "flags = %Ld\n" (get_stats_flags s)
Printf.printf "flags = %Ld\n" (get_stats_flags s) ;
Printf.printf "discard_reqs_submitted = %Ld\n"
(get_stats_discard_reqs_submitted s) ;
Printf.printf "discard_reqs_completed = %Ld\n"
(get_stats_discard_reqs_completed s) ;
Printf.printf "discard_sectors = %Ld\n" (get_stats_discard_sectors s) ;
Printf.printf "discard_total_ticks = %Ld\n"
(get_stats_discard_total_ticks s)
| _ ->
usage ()
72 changes: 71 additions & 1 deletion ocaml/xcp-rrdd/bin/rrdp-iostat/rrdp_iostat.ml
Original file line number Diff line number Diff line change
Expand Up @@ -590,12 +590,16 @@ module Stats_value = struct
type t = {
rd_bytes: int64
; wr_bytes: int64
; ds_bytes: int64
; rd_avg_usecs: int64
; wr_avg_usecs: int64
; ds_avg_usecs: int64
; io_throughput_read_mb: float
; io_throughput_write_mb: float
; io_throughput_discard_mb: float
; iops_read: int64
; iops_write: int64
; iops_discard: int64
; iowait: float
; inflight: int64
}
Expand All @@ -604,12 +608,16 @@ module Stats_value = struct
{
rd_bytes= 0L
; wr_bytes= 0L
; ds_bytes= 0L
; rd_avg_usecs= 0L
; wr_avg_usecs= 0L
; ds_avg_usecs= 0L
; io_throughput_read_mb= 0.
; io_throughput_write_mb= 0.
; io_throughput_discard_mb= 0.
; iops_read= 0L
; iops_write= 0L
; iops_discard= 0L
; iowait= 0.
; inflight= 0L
}
Expand All @@ -632,6 +640,7 @@ module Stats_value = struct
{
rd_bytes= stats_diff_get 13
; wr_bytes= stats_diff_get 14
; ds_bytes= 0L
; rd_avg_usecs=
( if stats_diff_get 0 > 0L then
Int64.div (stats_diff_get 3) (stats_diff_get 0)
Expand All @@ -644,10 +653,13 @@ module Stats_value = struct
else
0L
)
; ds_avg_usecs= 0L
; io_throughput_read_mb= to_float (stats_diff_get 13) /. 1048576.
; io_throughput_write_mb= to_float (stats_diff_get 14) /. 1048576.
; io_throughput_discard_mb= 0.
; iops_read= stats_diff_get 0
; iops_write= stats_diff_get 4
; iops_discard= 0L
; iowait= to_float (stats_diff_get 10) /. 1000.
; inflight= stats_get 8
}
Expand Down Expand Up @@ -686,12 +698,16 @@ module Stats_value = struct
{
rd_bytes= Int64.mul (get_stats_read_sectors s3) 512L
; wr_bytes= Int64.mul (get_stats_write_sectors s3) 512L
; ds_bytes= Int64.mul (get_stats_discard_sectors s3) 512L
; rd_avg_usecs=
avg_reqs_completed_last_five_secs get_stats_read_reqs_completed
get_stats_read_total_ticks
; wr_avg_usecs=
avg_reqs_completed_last_five_secs get_stats_write_reqs_completed
get_stats_write_total_ticks
; ds_avg_usecs=
avg_reqs_completed_last_five_secs get_stats_discard_reqs_completed
get_stats_discard_total_ticks
; io_throughput_read_mb=
to_float
(get_stats_read_sectors s3 -- opt get_stats_read_sectors last_s3)
Expand All @@ -702,12 +718,22 @@ module Stats_value = struct
(get_stats_write_sectors s3 -- opt get_stats_write_sectors last_s3)
*. 512.
/. 1048576.
; io_throughput_discard_mb=
to_float
(get_stats_discard_sectors s3
-- opt get_stats_discard_sectors last_s3
)
*. 512.
/. 1048576.
; iops_read=
get_stats_read_reqs_completed s3
-- opt get_stats_read_reqs_completed last_s3
; iops_write=
get_stats_write_reqs_completed s3
-- opt get_stats_write_reqs_completed last_s3
; iops_discard=
get_stats_discard_reqs_completed s3
-- opt get_stats_discard_reqs_completed last_s3
; iowait=
to_float
(get_stats_read_total_ticks s3
Expand Down Expand Up @@ -736,12 +762,17 @@ module Stats_value = struct
; rd_avg_usecs= acc.rd_avg_usecs ++ v.rd_avg_usecs
; wr_bytes= acc.wr_bytes ++ v.wr_bytes
; wr_avg_usecs= acc.wr_avg_usecs ++ v.wr_avg_usecs
; ds_bytes= acc.ds_bytes ++ v.ds_bytes
; ds_avg_usecs= acc.ds_avg_usecs ++ v.ds_avg_usecs
; io_throughput_read_mb=
acc.io_throughput_read_mb +. v.io_throughput_read_mb
; io_throughput_write_mb=
acc.io_throughput_write_mb +. v.io_throughput_write_mb
; io_throughput_discard_mb=
acc.io_throughput_discard_mb +. v.io_throughput_discard_mb
; iops_read= acc.iops_read ++ v.iops_read
; iops_write= acc.iops_write ++ v.iops_write
; iops_discard= acc.iops_discard ++ v.iops_discard
; iowait= acc.iowait +. v.iowait
; inflight= acc.inflight ++ v.inflight
}
Expand All @@ -763,6 +794,12 @@ module Stats_value = struct
~value:(Rrd.VT_Int64 value.wr_bytes) ~ty:Rrd.Derive ~units:"B/s"
~min:0.0 ()
)
; ( owner
, ds_make ~name:(key_format "discard")
~description:("Discards from device " ^ name ^ ", in B/s")
~value:(Rrd.VT_Int64 value.ds_bytes) ~ty:Rrd.Derive ~units:"B/s"
~min:0.0 ()
)
; ( owner
, ds_make
~name:(key_format "read_latency")
Expand All @@ -778,6 +815,14 @@ module Stats_value = struct
~value:(Rrd.VT_Int64 value.wr_avg_usecs) ~ty:Rrd.Gauge ~units:"μs"
~min:0.0 ()
)
; ( owner
, ds_make
~name:(key_format "discard_latency")
~description:
("Discard latency from device " ^ name ^ ", in microseconds")
~value:(Rrd.VT_Int64 value.ds_avg_usecs) ~ty:Rrd.Gauge ~units:"μs"
~min:0.0 ()
)
; ( owner
, ds_make
~name:(key_format "io_throughput_read")
Expand All @@ -792,6 +837,13 @@ module Stats_value = struct
~value:(Rrd.VT_Float value.io_throughput_write_mb) ~ty:Rrd.Absolute
~units:"MiB/s" ~min:0. ()
)
; ( owner
, ds_make
~name:(key_format "io_throughput_discard")
~description:("Data discard to the " ^ name ^ ", in MiB/s")
~value:(Rrd.VT_Float value.io_throughput_discard_mb) ~ty:Rrd.Absolute
~units:"MiB/s" ~min:0. ()
)
; ( owner
, ds_make
~name:(key_format "io_throughput_total")
Expand All @@ -814,10 +866,22 @@ module Stats_value = struct
~value:(Rrd.VT_Int64 value.iops_write) ~ty:Rrd.Absolute
~units:"requests/s" ~min:0. ()
)
; ( owner
, ds_make
~name:(key_format "iops_discard")
~description:"Discard requests per second"
~value:(Rrd.VT_Int64 value.iops_discard) ~ty:Rrd.Absolute
~units:"requests/s" ~min:0. ()
)
; ( owner
, ds_make ~name:(key_format "iops_total")
~description:"I/O Requests per second"
~value:(Rrd.VT_Int64 (Int64.add value.iops_read value.iops_write))
~value:
(Rrd.VT_Int64
(Int64.add value.iops_read
(Int64.add value.iops_write value.iops_discard)
)
)
~ty:Rrd.Absolute ~units:"requests/s" ~min:0. ()
)
; ( owner
Expand Down Expand Up @@ -855,15 +919,19 @@ module Iostats_value = struct
let s3_usecs =
get_stats_read_total_ticks s3
++ get_stats_write_total_ticks s3
++ get_stats_discard_total_ticks s3
-- (opt get_stats_read_total_ticks last_s3
++ opt get_stats_write_total_ticks last_s3
++ opt get_stats_discard_total_ticks last_s3
)
in
let s3_count =
get_stats_read_reqs_completed s3
++ get_stats_write_reqs_completed s3
++ get_stats_discard_reqs_completed s3
-- (opt get_stats_read_reqs_completed last_s3
++ opt get_stats_write_reqs_completed last_s3
++ opt get_stats_discard_reqs_completed last_s3
)
in
let s3_latency_average =
Expand All @@ -874,8 +942,10 @@ module Iostats_value = struct
to_float
(get_stats_read_total_ticks s3
++ get_stats_write_total_ticks s3
++ get_stats_discard_total_ticks s3
-- (opt get_stats_read_total_ticks last_s3
++ opt get_stats_write_total_ticks last_s3
++ opt get_stats_discard_total_ticks last_s3
)
)
/. 1000_000.0
Expand Down
61 changes: 58 additions & 3 deletions ocaml/xcp-rrdd/lib/blktap/lib/blktap3_stats.ml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,28 @@ type stats = {
}
[@@little_endian]]

[%%cstruct
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't need a V2 I think. You can put it in the stats struct and just have wrappers that checks version when accessing these specific fields.

Copy link

@gthvn1 gthvn1 Mar 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But as discussed the problem is now we are not able to know the size of v1 vs the size of v2 that is used by "copy"... So it looks like a v2 is needed. To avoid generating unneeded function you can do something like:

type stats_v2 = {
    _version: uint32_t
  ; _pad: uint32_t
  ; _oo_reqs: uint64_t
  ; _read_reqs_submitted: uint64_t
  ; _read_reqs_completed: uint64_t
  ; _read_sectors: uint64_t
  ; _read_total_ticks: uint64_t
  ; _write_reqs_submitted: uint64_t
  ; _write_reqs_completed: uint64_t
  ; _write_sectors: uint64_t
  ; _write_total_ticks: uint64_t
  ; _io_errors: uint64_t
  ; _flags: uint64_t
  ; discard_reqs_submitted: uint64_t
  ; discard_reqs_completed: uint64_t
  ; discard_sectors: uint64_t
  ; discard_total_ticks: uint64_t
}
[@@little_endian]]

Not sure if it is the correct approach but you will have both sizes and new successors accessors to V2 fields...

type stats_v2 = {
_v1_version: uint32_t
; _v1_pad: uint32_t
; _v1_oo_reqs: uint64_t
; _v1_read_reqs_submitted: uint64_t
; _v1_read_reqs_completed: uint64_t
; _v1_read_sectors: uint64_t
; _v1_read_total_ticks: uint64_t
; _v1_write_reqs_submitted: uint64_t
; _v1_write_reqs_completed: uint64_t
; _v1_write_sectors: uint64_t
; _v1_write_total_ticks: uint64_t
; _v1_io_errors: uint64_t
; _v1_flags: uint64_t
; discard_reqs_submitted: uint64_t
; discard_reqs_completed: uint64_t
; discard_sectors: uint64_t
; discard_total_ticks: uint64_t
}
[@@little_endian]]

let of_file f =
let fd = Unix.(openfile f [O_RDONLY] 0o000) in
try
Expand All @@ -51,6 +73,39 @@ let of_file f =

let copy : t -> t =
fun t ->
let t' = Cstruct.create_unsafe sizeof_stats in
Cstruct.blit t 0 t' 0 sizeof_stats ;
t'
let size =
if get_stats_version t >= 2l then
sizeof_stats_v2
else
sizeof_stats
in
let t' = Cstruct.create_unsafe size in
Cstruct.blit t 0 t' 0 size ; t'

let get_stats_discard_reqs_submitted : t -> Cstruct.uint64 =
fun t ->
if get_stats_version t >= 2l then
get_stats_v2_discard_reqs_submitted t
else
0L

let get_stats_discard_reqs_completed : t -> Cstruct.uint64 =
fun t ->
if get_stats_version t >= 2l then
get_stats_v2_discard_reqs_completed t
else
0L

let get_stats_discard_sectors : t -> Cstruct.uint64 =
fun t ->
if get_stats_version t >= 2l then
get_stats_v2_discard_sectors t
else
0L

let get_stats_discard_total_ticks : t -> Cstruct.uint64 =
fun t ->
if get_stats_version t >= 2l then
get_stats_v2_discard_total_ticks t
else
0L
8 changes: 8 additions & 0 deletions ocaml/xcp-rrdd/lib/blktap/lib/blktap3_stats.mli
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ val get_stats_io_errors : t -> Cstruct.uint64

val get_stats_flags : t -> Cstruct.uint64

val get_stats_discard_reqs_submitted : t -> Cstruct.uint64

val get_stats_discard_reqs_completed : t -> Cstruct.uint64

val get_stats_discard_sectors : t -> Cstruct.uint64

val get_stats_discard_total_ticks : t -> Cstruct.uint64

val of_file : string -> t

val copy : t -> t
Loading