Skip to content

Commit 7a6d626

Browse files
committed
feat: Go implement lsmod and rmmod
Signed-off-by: Fred Rolland <frolland@nvidia.com>
1 parent fab58e0 commit 7a6d626

File tree

2 files changed

+443
-18
lines changed

2 files changed

+443
-18
lines changed

entrypoint/internal/utils/host/host.go

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package host
1919
import (
2020
"context"
2121
"fmt"
22+
"strconv"
2223
"strings"
2324

2425
"github.com/Mellanox/doca-driver-build/entrypoint/internal/utils/cmd"
@@ -100,13 +101,76 @@ type LoadedModule struct {
100101

101102
// LsMod is the default implementation of the host.Interface.
102103
func (h *host) LsMod(ctx context.Context) (map[string]LoadedModule, error) {
103-
// TODO: add implementation
104-
//nolint:nilnil
105-
return nil, nil
104+
// Execute lsmod command
105+
stdout, stderr, err := h.cmd.RunCommand(ctx, "lsmod")
106+
if err != nil {
107+
return nil, fmt.Errorf("failed to execute lsmod command: %w, stderr: %s", err, stderr)
108+
}
109+
110+
// Parse the output
111+
modules := make(map[string]LoadedModule)
112+
lines := strings.Split(strings.TrimSpace(stdout), "\n")
113+
114+
// Skip the header line
115+
for i, line := range lines {
116+
if i == 0 {
117+
continue // Skip header line "Module Size Used by"
118+
}
119+
120+
line = strings.TrimSpace(line)
121+
if line == "" {
122+
continue
123+
}
124+
125+
// Parse each line: module_name size ref_count [dependent_modules]
126+
fields := strings.Fields(line)
127+
if len(fields) < 3 {
128+
continue // Skip malformed lines
129+
}
130+
131+
moduleName := fields[0]
132+
refCountStr := fields[2]
133+
134+
// Parse reference count
135+
refCount, err := strconv.Atoi(refCountStr)
136+
if err != nil {
137+
// If we can't parse the ref count, set it to 0
138+
refCount = 0
139+
}
140+
141+
// Parse dependent modules (everything after the ref count)
142+
var usedBy []string
143+
if len(fields) > 3 {
144+
// Join all fields after ref count and split by comma
145+
dependentStr := strings.Join(fields[3:], " ")
146+
if dependentStr != "-" {
147+
// Split by comma and clean up each module name
148+
dependentModules := strings.Split(dependentStr, ",")
149+
for _, dep := range dependentModules {
150+
dep = strings.TrimSpace(dep)
151+
if dep != "" {
152+
usedBy = append(usedBy, dep)
153+
}
154+
}
155+
}
156+
}
157+
158+
modules[moduleName] = LoadedModule{
159+
Name: moduleName,
160+
RefCount: refCount,
161+
UsedBy: usedBy,
162+
}
163+
}
164+
165+
return modules, nil
106166
}
107167

108168
// RmMod is the default implementation of the host.Interface.
109169
func (h *host) RmMod(ctx context.Context, module string) error {
110-
// TODO: add implementation
170+
// Execute rmmod command to unload the kernel module
171+
_, stderr, err := h.cmd.RunCommand(ctx, "rmmod", module)
172+
if err != nil {
173+
return fmt.Errorf("failed to unload kernel module %s: %w, stderr: %s", module, err, stderr)
174+
}
111175
return nil
112176
}

0 commit comments

Comments
 (0)