From 813c630e9c4b4ac6d5fd95a2dcf558ad93cb197f Mon Sep 17 00:00:00 2001 From: Nico Vinzens Date: Wed, 17 Oct 2018 13:46:49 +0200 Subject: [PATCH 1/3] replace self/mounts with self/mountinfo --- disk/disk_linux.go | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/disk/disk_linux.go b/disk/disk_linux.go index 1b10a38..e474726 100644 --- a/disk/disk_linux.go +++ b/disk/disk_linux.go @@ -8,13 +8,13 @@ import ( "context" "fmt" "io/ioutil" + "os" "path/filepath" "strconv" "strings" - "golang.org/x/sys/unix" - "github.com/shirou/gopsutil/internal/common" + "golang.org/x/sys/unix" ) const ( @@ -224,7 +224,7 @@ func Partitions(all bool) ([]PartitionStat, error) { } func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) { - filename := common.HostProc("self/mounts") + filename := common.HostProc("self/mountinfo") lines, err := common.ReadLines(filename) if err != nil { return nil, err @@ -238,18 +238,47 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro ret := make([]PartitionStat, 0, len(lines)) for _, line := range lines { + // a line of self/mountinfo has the following structure: + // 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue + // (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) fields := strings.Fields(line) + + mountOpts := fields[5] + mountPoint := fields[4] + blockDeviceID := fields[2] + var device string + var fstype string + + // field (7) is optional and can include multiple lines, + // so to find the disk and the fstype we need to loop for the separator "-" + for i, field := range fields[6:] { + if field == "-" { + device = fields[6+i+2] + fstype = fields[6+i+1] + } + } + d := PartitionStat{ - Device: fields[0], - Mountpoint: fields[1], - Fstype: fields[2], - Opts: fields[3], + Device: device, + Mountpoint: mountPoint, + Fstype: fstype, + Opts: mountOpts, } if all == false { if d.Device == "none" || !common.StringsHas(fs, d.Fstype) { continue } } + // /dev/root is not the real device name + // so we get the real device name from its major/minor number + if d.Device == "/dev/root" { + link := "/sys/dev/block/" + blockDeviceID + devpath, err := os.Readlink(link) + if err != nil { + return nil, err + } + d.Device = strings.Replace(d.Device, "root", filepath.Base(devpath), 1) + } ret = append(ret, d) } From 23dfe986213d242ba4f6b4ba9f70e9fa5ceac364 Mon Sep 17 00:00:00 2001 From: Nico Vinzens Date: Wed, 17 Oct 2018 14:45:40 +0200 Subject: [PATCH 2/3] use HostSys to construct device path --- disk/disk_linux.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/disk/disk_linux.go b/disk/disk_linux.go index e474726..dd62f88 100644 --- a/disk/disk_linux.go +++ b/disk/disk_linux.go @@ -272,8 +272,7 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro // /dev/root is not the real device name // so we get the real device name from its major/minor number if d.Device == "/dev/root" { - link := "/sys/dev/block/" + blockDeviceID - devpath, err := os.Readlink(link) + devpath, err := os.Readlink(common.HostSys("/dev/block/" + blockDeviceID)) if err != nil { return nil, err } From 1079f31626f71e07cdec83836d8dfd8b3f2a1571 Mon Sep 17 00:00:00 2001 From: Nico Vinzens Date: Thu, 18 Oct 2018 09:34:06 +0200 Subject: [PATCH 3/3] change the way we handle the mountinfo lines --- disk/disk_linux.go | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/disk/disk_linux.go b/disk/disk_linux.go index dd62f88..a511ac4 100644 --- a/disk/disk_linux.go +++ b/disk/disk_linux.go @@ -241,23 +241,22 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro // a line of self/mountinfo has the following structure: // 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue // (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) - fields := strings.Fields(line) - mountOpts := fields[5] - mountPoint := fields[4] - blockDeviceID := fields[2] - var device string - var fstype string - - // field (7) is optional and can include multiple lines, - // so to find the disk and the fstype we need to loop for the separator "-" - for i, field := range fields[6:] { - if field == "-" { - device = fields[6+i+2] - fstype = fields[6+i+1] - } + // split the mountinfo line by the separator hyphen + parts := strings.Split(line, " - ") + if len(parts) != 2 { + return nil, fmt.Errorf("found invalid mountinfo line in file %s: %s ", filename, line) } + fields := strings.Fields(parts[0]) + blockDeviceID := fields[2] + mountPoint := fields[4] + mountOpts := fields[5] + + fields = strings.Fields(parts[1]) + fstype := fields[0] + device := fields[1] + d := PartitionStat{ Device: device, Mountpoint: mountPoint,