Skip to content
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

collector/zfs: Prevent procfs integer underflow #2961

Open
wants to merge 2 commits 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions collector/fixtures/e2e-64k-page-output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3741,6 +3741,9 @@ node_zfs_arc_l2_writes_lock_retry 0
# HELP node_zfs_arc_l2_writes_sent kstat.zfs.misc.arcstats.l2_writes_sent
# TYPE node_zfs_arc_l2_writes_sent untyped
node_zfs_arc_l2_writes_sent 0
# HELP node_zfs_arc_memory_available_bytes kstat.zfs.misc.arcstats.memory_available_bytes
# TYPE node_zfs_arc_memory_available_bytes untyped
node_zfs_arc_memory_available_bytes -9.223372036854776e+17
# HELP node_zfs_arc_memory_direct_count kstat.zfs.misc.arcstats.memory_direct_count
# TYPE node_zfs_arc_memory_direct_count untyped
node_zfs_arc_memory_direct_count 542
Expand Down
3 changes: 3 additions & 0 deletions collector/fixtures/e2e-output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3763,6 +3763,9 @@ node_zfs_arc_l2_writes_lock_retry 0
# HELP node_zfs_arc_l2_writes_sent kstat.zfs.misc.arcstats.l2_writes_sent
# TYPE node_zfs_arc_l2_writes_sent untyped
node_zfs_arc_l2_writes_sent 0
# HELP node_zfs_arc_memory_available_bytes kstat.zfs.misc.arcstats.memory_available_bytes
# TYPE node_zfs_arc_memory_available_bytes untyped
node_zfs_arc_memory_available_bytes -9.223372036854776e+17
# HELP node_zfs_arc_memory_direct_count kstat.zfs.misc.arcstats.memory_direct_count
# TYPE node_zfs_arc_memory_direct_count untyped
node_zfs_arc_memory_direct_count 542
Expand Down
143 changes: 72 additions & 71 deletions collector/fixtures/proc/spl/kstat/zfs/arcstats
Original file line number Diff line number Diff line change
@@ -1,93 +1,94 @@
6 1 0x01 91 4368 5266997922 97951858082072
name type data
hits 4 8772612
misses 4 604635
anon_evictable_data 4 0
anon_evictable_metadata 4 0
anon_size 4 1917440
arc_loaned_bytes 4 0
arc_meta_limit 4 6275982336
arc_meta_max 4 449286096
arc_meta_min 4 16777216
arc_meta_used 4 308103632
arc_need_free 4 0
arc_no_grow 4 0
arc_prune 4 0
arc_sys_free 4 261496832
arc_tempreserve 4 0
c 4 1643208777
c_max 4 8367976448
c_min 4 33554432
data_size 4 1295836160
deleted 4 60403
demand_data_hits 4 7221032
demand_data_misses 4 73300
demand_metadata_hits 4 1464353
demand_metadata_misses 4 498170
prefetch_data_hits 4 3615
prefetch_data_misses 4 17094
prefetch_metadata_hits 4 83612
prefetch_metadata_misses 4 16071
mru_hits 4 855535
mru_ghost_hits 4 21100
mfu_hits 4 7829854
mfu_ghost_hits 4 821
deleted 4 60403
mutex_miss 4 2
evict_skip 4 2265729
evict_not_enough 4 680
duplicate_buffers 4 0
duplicate_buffers_size 4 0
duplicate_reads 4 0
evict_l2_cached 4 0
evict_l2_eligible 4 8992514560
evict_l2_ineligible 4 992552448
evict_l2_skip 4 0
evict_not_enough 4 680
evict_skip 4 2265729
hash_chain_max 4 3
hash_chains 4 412
hash_collisions 4 50564
hash_elements 4 42359
hash_elements_max 4 88245
hash_collisions 4 50564
hash_chains 4 412
hash_chain_max 4 3
p 4 516395305
c 4 1643208777
c_min 4 33554432
c_max 4 8367976448
size 4 1603939792
hdr_size 4 16361080
data_size 4 1295836160
metadata_size 4 175298560
other_size 4 116443992
anon_size 4 1917440
anon_evictable_data 4 0
anon_evictable_metadata 4 0
mru_size 4 402593792
mru_evictable_data 4 278091264
mru_evictable_metadata 4 18606592
mru_ghost_size 4 999728128
mru_ghost_evictable_data 4 883765248
mru_ghost_evictable_metadata 4 115962880
mfu_size 4 1066623488
mfu_evictable_data 4 1017613824
mfu_evictable_metadata 4 9163776
mfu_ghost_size 4 104936448
mfu_ghost_evictable_data 4 96731136
mfu_ghost_evictable_metadata 4 8205312
hits 4 8772612
l2_abort_lowmem 4 0
l2_asize 4 0
l2_cdata_free_on_write 4 0
l2_cksum_bad 4 0
l2_compress_failures 4 0
l2_compress_successes 4 0
l2_compress_zeros 4 0
l2_evict_l1cached 4 0
l2_evict_lock_retry 4 0
l2_evict_reading 4 0
l2_feeds 4 0
l2_free_on_write 4 0
l2_hdr_size 4 0
l2_hits 4 0
l2_io_error 4 0
l2_misses 4 0
l2_feeds 4 0
l2_rw_clash 4 0
l2_read_bytes 4 0
l2_rw_clash 4 0
l2_size 4 0
l2_write_bytes 4 0
l2_writes_sent 4 0
l2_writes_done 4 0
l2_writes_error 4 0
l2_writes_lock_retry 4 0
l2_evict_lock_retry 4 0
l2_evict_reading 4 0
l2_evict_l1cached 4 0
l2_free_on_write 4 0
l2_cdata_free_on_write 4 0
l2_abort_lowmem 4 0
l2_cksum_bad 4 0
l2_io_error 4 0
l2_size 4 0
l2_asize 4 0
l2_hdr_size 4 0
l2_compress_successes 4 0
l2_compress_zeros 4 0
l2_compress_failures 4 0
memory_throttle_count 4 0
duplicate_buffers 4 0
duplicate_buffers_size 4 0
duplicate_reads 4 0
l2_writes_sent 4 0
memory_available_bytes 3 -922337203685477580
memory_direct_count 4 542
memory_indirect_count 4 3006
arc_no_grow 4 0
arc_tempreserve 4 0
arc_loaned_bytes 4 0
arc_prune 4 0
arc_meta_used 4 308103632
arc_meta_limit 4 6275982336
arc_meta_max 4 449286096
arc_meta_min 4 16777216
arc_need_free 4 0
arc_sys_free 4 261496832
memory_throttle_count 4 0
metadata_size 4 175298560
mfu_evictable_data 4 1017613824
mfu_evictable_metadata 4 9163776
mfu_ghost_evictable_data 4 96731136
mfu_ghost_evictable_metadata 4 8205312
mfu_ghost_hits 4 821
mfu_ghost_size 4 104936448
mfu_hits 4 7829854
mfu_size 4 1066623488
misses 4 604635
mru_evictable_data 4 278091264
mru_evictable_metadata 4 18606592
mru_ghost_evictable_data 4 883765248
mru_ghost_evictable_metadata 4 115962880
mru_ghost_hits 4 21100
mru_ghost_size 4 999728128
mru_hits 4 855535
mru_size 4 402593792
mutex_miss 4 2
other_size 4 116443992
p 4 516395305
prefetch_data_hits 4 3615
prefetch_data_misses 4 17094
prefetch_metadata_hits 4 83612
prefetch_metadata_misses 4 16071
size 4 1603939792
4 changes: 2 additions & 2 deletions collector/zfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func (s zfsSysctl) metricName() string {
return strings.Replace(parts[len(parts)-1], "-", "_", -1)
}

func (c *zfsCollector) constSysctlMetric(subsystem string, sysctl zfsSysctl, value uint64) prometheus.Metric {
func (c *zfsCollector) constSysctlMetric(subsystem string, sysctl zfsSysctl, value float64) prometheus.Metric {
metricName := sysctl.metricName()

return prometheus.MustNewConstMetric(
Expand All @@ -106,7 +106,7 @@ func (c *zfsCollector) constSysctlMetric(subsystem string, sysctl zfsSysctl, val
nil,
),
prometheus.UntypedValue,
float64(value),
value,
)
}

Expand Down
26 changes: 20 additions & 6 deletions collector/zfs_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,15 @@ func (c *zfsCollector) updateZfsStats(subsystem string, ch chan<- prometheus.Met
}
defer file.Close()

return c.parseProcfsFile(file, c.linuxPathMap[subsystem], func(s zfsSysctl, v uint64) {
ch <- c.constSysctlMetric(subsystem, s, v)
return c.parseProcfsFile(file, c.linuxPathMap[subsystem], func(s zfsSysctl, v interface{}) {
var valueAsFloat64 float64
switch value := v.(type) {
case int64:
valueAsFloat64 = float64(value)
case uint64:
valueAsFloat64 = float64(value)
}
ch <- c.constSysctlMetric(subsystem, s, valueAsFloat64)
})
}

Expand Down Expand Up @@ -144,7 +151,7 @@ func (c *zfsCollector) updatePoolStats(ch chan<- prometheus.Metric) error {
return nil
}

func (c *zfsCollector) parseProcfsFile(reader io.Reader, fmtExt string, handler func(zfsSysctl, uint64)) error {
func (c *zfsCollector) parseProcfsFile(reader io.Reader, fmtExt string, handler func(zfsSysctl, interface{})) error {
scanner := bufio.NewScanner(reader)

parseLine := false
Expand All @@ -163,11 +170,18 @@ func (c *zfsCollector) parseProcfsFile(reader io.Reader, fmtExt string, handler

// kstat data type (column 2) should be KSTAT_DATA_UINT64, otherwise ignore
// TODO: when other KSTAT_DATA_* types arrive, much of this will need to be restructured
if parts[1] == kstatDataUint64 || parts[1] == kstatDataInt64 {
key := fmt.Sprintf("kstat.zfs.misc.%s.%s", fmtExt, parts[0])
key := fmt.Sprintf("kstat.zfs.misc.%s.%s", fmtExt, parts[0])
switch parts[1] {
case kstatDataUint64:
value, err := strconv.ParseUint(parts[2], 10, 64)
if err != nil {
return fmt.Errorf("could not parse expected integer value for %q", key)
return fmt.Errorf("could not parse expected unsigned integer value for %q: %w", key, err)
}
handler(zfsSysctl(key), value)
case kstatDataInt64:
value, err := strconv.ParseInt(parts[2], 10, 64)
if err != nil {
return fmt.Errorf("could not parse expected signed integer value for %q: %w", key, err)
}
handler(zfsSysctl(key), value)
}
Expand Down