Skip to content

Commit beeb881

Browse files
committed
Add /proc/modules parsing
Signed-off-by: Furkan <[email protected]>
1 parent b3d77ec commit beeb881

File tree

3 files changed

+295
-0
lines changed

3 files changed

+295
-0
lines changed

proc_modules.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
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+
"io"
20+
"strconv"
21+
"strings"
22+
23+
"github.com/prometheus/procfs/internal/util"
24+
)
25+
26+
// Module represents a single module info in the kernel.
27+
type Module struct {
28+
// Name is the name of the module.
29+
Name string
30+
// Size is the memory size of the module, in bytes
31+
Size uint64
32+
// Instances is the number of instances of the module are currently loaded.
33+
// A value of zero represents an unloaded module.
34+
Instances uint64
35+
// Dependencies is the list of modules that this module depends on.
36+
Dependencies []string
37+
// State is the state of the module is in: Live, Loading, or Unloading are the only possible values.
38+
State string
39+
// Offset is a memory offset for the loaded module
40+
Offset uint64
41+
// Taints is a list of taints that the module has.
42+
Taints []string
43+
}
44+
45+
// Modules represents a list of Module structs.
46+
type Modules []Module
47+
48+
// Modules parses the metrics from /proc/modules file and returns a slice of
49+
// structs containing the relevant info.
50+
func (fs FS) Modules() ([]Module, error) {
51+
data, err := util.ReadFileNoStat(fs.proc.Path("modules"))
52+
if err != nil {
53+
return nil, err
54+
}
55+
return parseModules(bytes.NewReader(data))
56+
}
57+
58+
// parseModules parses the metrics from /proc/modules file
59+
// and returns a []Module structure.
60+
// - https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/4/html/reference_guide/s2-proc-modules
61+
// - https://unix.stackexchange.com/a/152527/300614
62+
func parseModules(r io.Reader) ([]Module, error) {
63+
var (
64+
scanner = bufio.NewScanner(r)
65+
modules = make([]Module, 0)
66+
)
67+
68+
for scanner.Scan() {
69+
parts := strings.Fields(scanner.Text())
70+
71+
module := Module{
72+
Name: parts[0],
73+
Dependencies: []string{},
74+
State: parts[4],
75+
Taints: []string{},
76+
}
77+
78+
if size, err := strconv.ParseUint(parts[1], 10, 64); err == nil {
79+
module.Size = size
80+
}
81+
82+
if instances, err := strconv.ParseUint(parts[2], 10, 64); err == nil {
83+
module.Instances = instances
84+
}
85+
86+
dependencies := parts[3]
87+
if dependencies != "-" {
88+
module.Dependencies = strings.Split(strings.TrimSuffix(dependencies, ","), ",")
89+
}
90+
91+
if offset, err := strconv.ParseUint(parts[5], 10, 64); err == nil {
92+
module.Offset = offset
93+
}
94+
95+
// Kernel Taint State is available if parts length is greater than 6.
96+
if len(parts) > 6 {
97+
taints := strings.TrimSuffix(strings.TrimPrefix(parts[6], "("), ")")
98+
module.Taints = strings.Split(taints, "")
99+
}
100+
101+
modules = append(modules, module)
102+
}
103+
104+
return modules, scanner.Err()
105+
}

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)