1717package collector
1818
1919import (
20- "bufio "
20+ "bytes "
2121 "errors"
2222 "fmt"
23- "io"
2423 "log/slog"
2524 "os"
2625 "slices"
@@ -182,9 +181,9 @@ func stuckMountWatcher(mountPoint string, success chan struct{}, logger *slog.Lo
182181
183182func mountPointDetails (logger * slog.Logger ) ([]filesystemLabels , error ) {
184183 fs , err := procfs .NewFS (* procPath )
185- if err != nil {
186- return nil , fmt .Errorf ("failed to open procfs: %w" , err )
187- }
184+ if err != nil {
185+ return nil , fmt .Errorf ("failed to open procfs: %w" , err )
186+ }
188187 mountInfo , err := fs .GetProcMounts (1 )
189188 if errors .Is (err , os .ErrNotExist ) {
190189 // Fallback to `/proc/self/mountinfo` if `/proc/1/mountinfo` is missing due hidepid.
@@ -195,48 +194,37 @@ func mountPointDetails(logger *slog.Logger) ([]filesystemLabels, error) {
195194 return nil , err
196195 }
197196
198- return parseFilesystemLabels (file )
197+ return parseFilesystemLabels (mountInfo )
199198}
200199
201200func parseFilesystemLabels (mountInfo []* procfs.MountInfo ) ([]filesystemLabels , error ) {
202201 var filesystems []filesystemLabels
203202
204- for mount in range mountInfo {
205- parts := strings .Fields (scanner .Text ())
206-
207- if len (parts ) < 11 {
208- return nil , fmt .Errorf ("malformed mount point information: %q" , scanner .Text ())
209- }
210-
203+ for _ , mount := range mountInfo {
211204 major , minor := 0 , 0
212- _ , err := fmt .Sscanf (parts [ 2 ] , "%d:%d" , & major , & minor )
205+ _ , err := fmt .Sscanf (mount . MajorMinorVer , "%d:%d" , & major , & minor )
213206 if err != nil {
214- return nil , fmt .Errorf ("malformed mount point information: %q" , scanner .Text ())
215- }
216-
217- m := 5
218- for parts [m + 1 ] != "-" {
219- m ++
207+ return nil , fmt .Errorf ("malformed mount point MajorMinorVer: %q" , mount .MajorMinorVer )
220208 }
221209
222210 // Ensure we handle the translation of \040 and \011
223211 // as per fstab(5).
224- parts [ 4 ] = strings .ReplaceAll (parts [ 4 ] , "\\ 040" , " " )
225- parts [ 4 ] = strings .ReplaceAll (parts [ 4 ] , "\\ 011" , "\t " )
212+ mount . MountPoint = strings .ReplaceAll (mount . MountPoint , "\\ 040" , " " )
213+ mount . MountPoint = strings .ReplaceAll (mount . MountPoint , "\\ 011" , "\t " )
226214
227215 filesystems = append (filesystems , filesystemLabels {
228- device : parts [ m + 3 ] ,
229- mountPoint : rootfsStripPrefix (parts [ 4 ] ),
230- fsType : parts [ m + 2 ] ,
231- mountOptions : parts [ 5 ] ,
232- superOptions : parts [ 10 ] ,
216+ device : mount . Source ,
217+ mountPoint : rootfsStripPrefix (mount . MountPoint ),
218+ fsType : mount . FSType ,
219+ mountOptions : mountOptionsString ( mount . Options ) ,
220+ superOptions : mountOptionsString ( mount . SuperOptions ) ,
233221 major : strconv .Itoa (major ),
234222 minor : strconv .Itoa (minor ),
235223 deviceError : "" ,
236224 })
237225 }
238226
239- return filesystems , scanner . Err ()
227+ return filesystems , nil
240228}
241229
242230// see https://github.com/prometheus/node_exporter/issues/3157#issuecomment-2422761187
@@ -248,3 +236,15 @@ func isFilesystemReadOnly(labels filesystemLabels) bool {
248236
249237 return false
250238}
239+
240+ func mountOptionsString (m map [string ]string ) string {
241+ b := new (bytes.Buffer )
242+ for key , value := range m {
243+ if value == "" {
244+ fmt .Fprintf (b , "%s" , key )
245+ } else {
246+ fmt .Fprintf (b , "%s=%s" , key , value )
247+ }
248+ }
249+ return b .String ()
250+ }
0 commit comments