MCPcopy Create free account
hub / github.com/prometheus/procfs / parseMDStat

Function parseMDStat

mdstat.go:103–225  ·  view source on GitHub ↗

parseMDStat parses data from mdstat file (/proc/mdstat) and returns a slice of structs containing the relevant info.

(mdStatData []byte)

Source from the content-addressed store, hash-verified

101// parseMDStat parses data from mdstat file (/proc/mdstat) and returns a slice of
102// structs containing the relevant info.
103func parseMDStat(mdStatData []byte) ([]MDStat, error) {
104 // TODO:
105 // - parse global hotspares from the "unused devices" line.
106 mdStats := []MDStat{}
107 lines := strings.Split(string(mdStatData), "\n")
108 knownRaidTypes := make(map[string]bool)
109
110 for i, line := range lines {
111 if strings.TrimSpace(line) == "" || line[0] == ' ' ||
112 strings.HasPrefix(line, "unused") {
113 continue
114 }
115 // Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10]
116 if len(knownRaidTypes) == 0 && strings.HasPrefix(line, personalitiesPrefix) {
117 personalities := strings.Fields(line[len(personalitiesPrefix):])
118 for _, word := range personalities {
119 word := word[1 : len(word)-1]
120 knownRaidTypes[word] = true
121 }
122 continue
123 }
124
125 deviceFields := strings.Fields(line)
126 if len(deviceFields) < 3 {
127 return nil, fmt.Errorf("%w: Expected 3+ lines, got %q", ErrFileParse, line)
128 }
129 mdName := deviceFields[0] // mdx
130 state := deviceFields[2] // active, inactive, broken
131
132 mdType := "unknown" // raid1, raid5, etc.
133 var deviceStartIndex int
134 if len(deviceFields) > 3 { // mdType may be in the 3rd or 4th field
135 if isRaidType(deviceFields[3], knownRaidTypes) {
136 mdType = deviceFields[3]
137 deviceStartIndex = 4
138 } else if len(deviceFields) > 4 && isRaidType(deviceFields[4], knownRaidTypes) {
139 // if the 3rd field is (...), the 4th field is the mdType
140 mdType = deviceFields[4]
141 deviceStartIndex = 5
142 }
143 }
144
145 if len(lines) <= i+3 {
146 return nil, fmt.Errorf("%w: Too few lines for md device: %q", ErrFileParse, mdName)
147 }
148
149 // Failed (Faulty) disks have the suffix (F) & Spare disks have the suffix (S).
150 fail := int64(strings.Count(line, "(F)"))
151 spare := int64(strings.Count(line, "(S)"))
152 active, total, down, size, err := evalStatusLine(lines[i], lines[i+1])
153
154 if err != nil {
155 return nil, fmt.Errorf("%w: Cannot parse md device lines: %v: %w", ErrFileParse, active, err)
156 }
157
158 syncLineIdx := i + 2
159 if strings.Contains(lines[i+2], "bitmap") { // skip bitmap line
160 syncLineIdx++

Callers 2

TestInvalidMdstatFunction · 0.85
MDStatMethod · 0.85

Calls 4

isRaidTypeFunction · 0.85
evalStatusLineFunction · 0.85
evalRecoveryLineFunction · 0.85
evalComponentDevicesFunction · 0.85

Tested by 1

TestInvalidMdstatFunction · 0.68

Used in the wild real call sites across dependent graphs

searching dependent graphs…