Skip to content

Commit 394bc48

Browse files
committed
Add /proc/modules parsing
Signed-off-by: Furkan <furkan.turkal@trendyol.com>
1 parent b3d77ec commit 394bc48

File tree

3 files changed

+299
-0
lines changed

3 files changed

+299
-0
lines changed

proc_modules.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Copyright 2018 The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package procfs
15+
16+
import (
17+
"bufio"
18+
"bytes"
19+
"fmt"
20+
"io"
21+
"strconv"
22+
"strings"
23+
24+
"github.com/prometheus/procfs/internal/util"
25+
)
26+
27+
// Module represents a single module info in the kernel.
28+
type Module struct {
29+
// Name is the name of the module.
30+
Name string
31+
// Size is the memory size of the module, in bytes
32+
Size uint64
33+
// Instances is the number of instances of the module are currently loaded.
34+
// A value of zero represents an unloaded module.
35+
Instances uint64
36+
// Dependencies is the list of modules that this module depends on.
37+
Dependencies []string
38+
// State is the state of the module is in: Live, Loading, or Unloading are the only possible values.
39+
State string
40+
// Offset is a memory offset for the loaded module
41+
Offset uint64
42+
// Taints is a list of taints that the module has.
43+
Taints []string
44+
}
45+
46+
// Modules represents a list of Module structs.
47+
type Modules []Module
48+
49+
// Modules parses the metrics from /proc/modules file and returns a slice of
50+
// structs containing the relevant info.
51+
func (fs FS) Modules() ([]Module, error) {
52+
data, err := util.ReadFileNoStat(fs.proc.Path("modules"))
53+
if err != nil {
54+
return nil, err
55+
}
56+
return parseModules(bytes.NewReader(data))
57+
}
58+
59+
// parseModules parses the metrics from /proc/modules file
60+
// and returns a []Module structure.
61+
// - https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/4/html/reference_guide/s2-proc-modules
62+
// - https://unix.stackexchange.com/a/152527/300614
63+
func parseModules(r io.Reader) ([]Module, error) {
64+
var (
65+
scanner = bufio.NewScanner(r)
66+
modules = make([]Module, 0)
67+
)
68+
69+
for scanner.Scan() {
70+
parts := strings.Fields(scanner.Text())
71+
if len(parts) < 6 {
72+
return nil, fmt.Errorf("not enough fields in modules (expected at least 6 fields but got %d): %s", len(parts), parts)
73+
}
74+
75+
module := Module{
76+
Name: parts[0],
77+
Dependencies: []string{},
78+
State: parts[4],
79+
Taints: []string{},
80+
}
81+
82+
if size, err := strconv.ParseUint(parts[1], 10, 64); err == nil {
83+
module.Size = size
84+
}
85+
86+
if instances, err := strconv.ParseUint(parts[2], 10, 64); err == nil {
87+
module.Instances = instances
88+
}
89+
90+
dependencies := parts[3]
91+
if dependencies != "-" {
92+
module.Dependencies = strings.Split(strings.TrimSuffix(dependencies, ","), ",")
93+
}
94+
95+
if offset, err := strconv.ParseUint(parts[5], 10, 64); err == nil {
96+
module.Offset = offset
97+
}
98+
99+
// Kernel Taint State is available if parts length is greater than 6.
100+
if len(parts) > 6 {
101+
taints := strings.TrimSuffix(strings.TrimPrefix(parts[6], "("), ")")
102+
module.Taints = strings.Split(taints, "")
103+
}
104+
105+
modules = append(modules, module)
106+
}
107+
108+
return modules, scanner.Err()
109+
}

proc_modules_test.go

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Copyright 2020 The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
package procfs
15+
16+
import (
17+
"reflect"
18+
"testing"
19+
)
20+
21+
func TestProcInterrupts(t *testing.T) {
22+
fs := getProcFixtures(t)
23+
24+
modules, err := fs.Modules()
25+
if err != nil {
26+
t.Fatal(err)
27+
}
28+
29+
if want, have := 89, len(modules); want != have {
30+
t.Errorf("want length %d, have %d", want, have)
31+
}
32+
33+
for _, test := range []struct {
34+
name string
35+
index int
36+
want Module
37+
}{
38+
{
39+
name: "no dependencies and taints",
40+
index: 0,
41+
want: Module{
42+
Name: "nft_counter",
43+
Size: 16384,
44+
Instances: 4,
45+
Dependencies: []string{},
46+
State: "Live",
47+
Offset: 0,
48+
Taints: []string{},
49+
},
50+
},
51+
{
52+
name: "have dependencies with no taints",
53+
index: 11,
54+
want: Module{
55+
Name: "nf_tables",
56+
Size: 245760,
57+
Instances: 19,
58+
Dependencies: []string{"nft_counter", "nft_chain_nat", "nft_compat"},
59+
State: "Live",
60+
Offset: 0,
61+
Taints: []string{},
62+
},
63+
},
64+
{
65+
name: "have multiple taints with multiple dependencies",
66+
index: 83,
67+
want: Module{
68+
Name: "drm",
69+
Size: 622592,
70+
Instances: 3,
71+
Dependencies: []string{"virtio_gpu", "drm_kms_helper"},
72+
State: "Live",
73+
Offset: 0,
74+
Taints: []string{"P", "O", "E"},
75+
},
76+
},
77+
{
78+
name: "have single taint with single dependency",
79+
index: 88,
80+
want: Module{
81+
Name: "failover",
82+
Size: 16384,
83+
Instances: 1,
84+
Dependencies: []string{"net_failover"},
85+
State: "Live",
86+
Offset: 0,
87+
Taints: []string{"P"},
88+
},
89+
},
90+
} {
91+
t.Run(test.name, func(t *testing.T) {
92+
if want, have := test.want, modules[test.index]; !reflect.DeepEqual(want, have) {
93+
t.Errorf("want %v, have %v", want, have)
94+
}
95+
})
96+
}
97+
}

testdata/fixtures.ttar

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,6 +2258,99 @@ DirectMap4k: 91136 kB
22582258
DirectMap2M: 16039936 kB
22592259
Mode: 664
22602260
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2261+
Path: fixtures/proc/modules
2262+
Lines: 89
2263+
nft_counter 16384 4 - Live 0xffffffffc0c77000
2264+
nft_chain_nat 16384 2 - Live 0xffffffffc0c72000
2265+
nft_compat 20480 8 - Live 0xffffffffc0c6c000
2266+
xt_tcpudp 20480 4 - Live 0xffffffffc0c66000
2267+
xt_nat 16384 4 - Live 0xffffffffc0c61000
2268+
xt_multiport 20480 0 - Live 0xffffffffc0c5b000
2269+
xt_mark 16384 0 - Live 0xffffffffc0c56000
2270+
xt_conntrack 16384 0 - Live 0xffffffffc0c42000
2271+
xt_comment 16384 0 - Live 0xffffffffc0c3d000
2272+
xt_addrtype 16384 0 - Live 0xffffffffc0c51000
2273+
xt_MASQUERADE 20480 0 - Live 0xffffffffc0c4b000
2274+
nf_tables 245760 19 nft_counter,nft_chain_nat,nft_compat, Live 0xffffffffc0c00000
2275+
nfnetlink 20480 2 nft_compat,nf_tables, Live 0xffffffffc0bfa000
2276+
ip6table_filter 16384 0 - Live 0xffffffffc0b8b000
2277+
iptable_filter 16384 0 - Live 0xffffffffc0bde000
2278+
ip6table_nat 16384 0 - Live 0xffffffffc0bd9000
2279+
iptable_nat 16384 0 - Live 0xffffffffc0bf5000
2280+
nf_nat 49152 5 nft_chain_nat,xt_nat,xt_MASQUERADE,ip6table_nat,iptable_nat, Live 0xffffffffc0be8000
2281+
nf_conntrack 172032 4 xt_nat,xt_conntrack,xt_MASQUERADE,nf_nat, Live 0xffffffffc0bae000
2282+
nf_defrag_ipv6 24576 1 nf_conntrack, Live 0xffffffffc0ba3000
2283+
nf_defrag_ipv4 16384 1 nf_conntrack, Live 0xffffffffc0b9e000
2284+
ip6_tables 32768 2 ip6table_filter,ip6table_nat, Live 0xffffffffc0b82000
2285+
veth 32768 0 - Live 0xffffffffc0b95000
2286+
bridge 307200 0 - Live 0xffffffffc0b36000
2287+
stp 16384 1 bridge, Live 0xffffffffc0b2f000
2288+
llc 16384 2 bridge,stp, Live 0xffffffffc0b26000
2289+
tap 28672 0 - Live 0xffffffffc0b1b000
2290+
binfmt_misc 24576 1 - Live 0xffffffffc0ad6000
2291+
overlay 151552 0 - Live 0xffffffffc0ab0000
2292+
isofs 53248 1 - Live 0xffffffffc09d0000
2293+
nls_iso8859_1 16384 1 - Live 0xffffffffc097f000
2294+
input_leds 16384 0 - Live 0xffffffffc099d000
2295+
serio_raw 20480 0 - Live 0xffffffffc098b000
2296+
virtio_input 20480 0 - Live 0xffffffffc0979000
2297+
dm_multipath 40960 0 - Live 0xffffffffc093f000
2298+
sch_fq_codel 20480 3 - Live 0xffffffffc0939000
2299+
scsi_dh_rdac 20480 0 - Live 0xffffffffc0930000
2300+
scsi_dh_emc 16384 0 - Live 0xffffffffc0928000
2301+
scsi_dh_alua 20480 0 - Live 0xffffffffc0917000
2302+
ipmi_devintf 20480 0 - Live 0xffffffffc091e000
2303+
ipmi_msghandler 122880 1 ipmi_devintf, Live 0xffffffffc08f8000
2304+
msr 16384 0 - Live 0xffffffffc08f0000
2305+
efi_pstore 16384 0 - Live 0xffffffffc08eb000
2306+
virtio_rng 16384 0 - Live 0xffffffffc0581000
2307+
ip_tables 32768 2 iptable_filter,iptable_nat, Live 0xffffffffc0743000
2308+
x_tables 53248 15 nft_compat,xt_tcpudp,xt_nat,xt_multiport,xt_mark,xt_conntrack,xt_comment,xt_addrtype,xt_MASQUERADE,ip6table_filter,iptable_filter,ip6table_nat,iptable_nat,ip6_tables,ip_tables, Live 0xffffffffc0735000
2309+
autofs4 49152 2 - Live 0xffffffffc0728000
2310+
btrfs 1552384 0 - Live 0xffffffffc0761000
2311+
blake2b_generic 20480 0 - Live 0xffffffffc06d3000
2312+
zstd_compress 229376 1 btrfs, Live 0xffffffffc06ef000
2313+
raid10 69632 0 - Live 0xffffffffc06dd000
2314+
raid456 163840 0 - Live 0xffffffffc06aa000
2315+
async_raid6_recov 24576 1 raid456, Live 0xffffffffc06a3000
2316+
async_memcpy 20480 2 raid456,async_raid6_recov, Live 0xffffffffc069d000
2317+
async_pq 24576 2 raid456,async_raid6_recov, Live 0xffffffffc0696000
2318+
async_xor 20480 3 raid456,async_raid6_recov,async_pq, Live 0xffffffffc0690000
2319+
async_tx 20480 5 raid456,async_raid6_recov,async_memcpy,async_pq,async_xor, Live 0xffffffffc068a000
2320+
xor 24576 2 btrfs,async_xor, Live 0xffffffffc0593000
2321+
raid6_pq 122880 4 btrfs,raid456,async_raid6_recov,async_pq, Live 0xffffffffc066b000
2322+
libcrc32c 16384 5 nf_tables,nf_nat,nf_conntrack,btrfs,raid456, Live 0xffffffffc0556000
2323+
raid1 49152 0 - Live 0xffffffffc0610000
2324+
raid0 24576 0 - Live 0xffffffffc0517000
2325+
multipath 20480 0 - Live 0xffffffffc0501000
2326+
linear 20480 0 - Live 0xffffffffc045b000
2327+
virtio_gpu 69632 0 - Live 0xffffffffc05a0000
2328+
virtio_dma_buf 16384 1 virtio_gpu, Live 0xffffffffc0536000
2329+
crct10dif_pclmul 16384 1 - Live 0xffffffffc050e000
2330+
drm_kms_helper 311296 3 virtio_gpu, Live 0xffffffffc061e000
2331+
crc32_pclmul 16384 0 - Live 0xffffffffc0527000
2332+
syscopyarea 16384 1 drm_kms_helper, Live 0xffffffffc0520000
2333+
sysfillrect 20480 1 drm_kms_helper, Live 0xffffffffc0508000
2334+
ghash_clmulni_intel 16384 0 - Live 0xffffffffc0456000
2335+
sysimgblt 16384 1 drm_kms_helper, Live 0xffffffffc04fc000
2336+
fb_sys_fops 16384 1 drm_kms_helper, Live 0xffffffffc0425000
2337+
cec 61440 1 drm_kms_helper, Live 0xffffffffc0751000
2338+
rc_core 65536 1 cec, Live 0xffffffffc0540000
2339+
aesni_intel 376832 0 - Live 0xffffffffc05b3000
2340+
crypto_simd 16384 1 aesni_intel, Live 0xffffffffc059b000
2341+
ahci 45056 1 - Live 0xffffffffc0587000
2342+
virtio_net 61440 0 - Live 0xffffffffc0571000
2343+
xhci_pci 24576 0 - Live 0xffffffffc0562000
2344+
net_failover 20480 1 virtio_net, Live 0xffffffffc055c000
2345+
cryptd 24576 2 ghash_clmulni_intel,crypto_simd, Live 0xffffffffc052c000
2346+
drm 622592 3 virtio_gpu,drm_kms_helper, Live 0xffffffffc0463000 (POE)
2347+
psmouse 176128 0 - Live 0xffffffffc042a000
2348+
libahci 45056 1 ahci, Live 0xffffffffc0419000
2349+
virtio_blk 20480 2 - Live 0xffffffffc040f000
2350+
xhci_pci_renesas 20480 1 xhci_pci, Live 0xffffffffc0407000
2351+
failover 16384 1 net_failover, Live 0xffffffffc03ff000 (P)
2352+
Mode: 644
2353+
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22612354
Directory: fixtures/proc/net
22622355
Mode: 755
22632356
# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

0 commit comments

Comments
 (0)