From 47610d0d2b0e8bccc0595e413f232c24bdd56260 Mon Sep 17 00:00:00 2001 From: Ben Kochie Date: Thu, 19 Mar 2020 19:51:20 +0100 Subject: [PATCH] Update procfs library (#1640) Bump procfs to latest release. Fixes: https://github.com/prometheus/node_exporter/issues/1625 Fixes: https://github.com/prometheus/node_exporter/issues/1634 Signed-off-by: Ben Kochie --- go.mod | 2 +- go.sum | 5 +- .../prometheus/procfs/.golangci.yml | 4 +- .../prometheus/procfs/Makefile.common | 20 +- .../prometheus/procfs/bcache/bcache.go | 2 +- .../prometheus/procfs/bcache/get.go | 25 ++- .../prometheus/procfs/fixtures.ttar | 42 +++- vendor/github.com/prometheus/procfs/go.mod | 1 + vendor/github.com/prometheus/procfs/go.sum | 2 + .../github.com/prometheus/procfs/mountinfo.go | 12 +- .../prometheus/procfs/net_softnet.go | 14 +- .../prometheus/procfs/proc_fdinfo.go | 32 ++- .../github.com/prometheus/procfs/proc_maps.go | 208 ++++++++++++++++++ .../prometheus/procfs/proc_status.go | 32 +-- .../procfs/sysfs/class_infiniband.go | 4 +- .../prometheus/procfs/sysfs/net_class.go | 2 +- vendor/modules.txt | 2 +- 17 files changed, 345 insertions(+), 64 deletions(-) create mode 100644 vendor/github.com/prometheus/procfs/proc_maps.go diff --git a/go.mod b/go.mod index d8f9a4e6..f67a6b29 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/prometheus/client_golang v1.4.1 github.com/prometheus/client_model v0.2.0 github.com/prometheus/common v0.9.1 - github.com/prometheus/procfs v0.0.10 + github.com/prometheus/procfs v0.0.11 github.com/siebenmann/go-kstat v0.0.0-20160321171754-d34789b79745 github.com/soundcloud/go-runit v0.0.0-20150630195641-06ad41a06c4a go.uber.org/atomic v1.5.1 // indirect diff --git a/go.sum b/go.sum index b161752e..b5b43a00 100644 --- a/go.sum +++ b/go.sum @@ -275,8 +275,8 @@ github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.0.10 h1:QJQN3jYQhkamO4mhfUWqdDH2asK7ONOI9MTWjyAxNKM= -github.com/prometheus/procfs v0.0.10/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.0.11 h1:DhHlBtkHWPYi8O2y31JkK0TF+DGM+51OopZjH/Ia5qI= +github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -405,6 +405,7 @@ golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867 h1:JoRuNIf+rpHl+VhScRQQvzbHed86tKkqwPMV34T8myw= diff --git a/vendor/github.com/prometheus/procfs/.golangci.yml b/vendor/github.com/prometheus/procfs/.golangci.yml index 7c4ce1fa..0aa09eda 100644 --- a/vendor/github.com/prometheus/procfs/.golangci.yml +++ b/vendor/github.com/prometheus/procfs/.golangci.yml @@ -1,4 +1,4 @@ +--- linters: enable: - - staticcheck - - govet + - golint diff --git a/vendor/github.com/prometheus/procfs/Makefile.common b/vendor/github.com/prometheus/procfs/Makefile.common index 066866ea..b978dfc5 100644 --- a/vendor/github.com/prometheus/procfs/Makefile.common +++ b/vendor/github.com/prometheus/procfs/Makefile.common @@ -69,6 +69,15 @@ else GO_BUILD_PLATFORM ?= $(GOHOSTOS)-$(GOHOSTARCH) endif +GOTEST := $(GO) test +GOTEST_DIR := +ifneq ($(CIRCLE_JOB),) +ifneq ($(shell which gotestsum),) + GOTEST_DIR := test-results + GOTEST := gotestsum --junitfile $(GOTEST_DIR)/unit-tests.xml -- +endif +endif + PROMU_VERSION ?= 0.5.0 PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz @@ -142,14 +151,17 @@ else endif .PHONY: common-test-short -common-test-short: +common-test-short: $(GOTEST_DIR) @echo ">> running short tests" - GO111MODULE=$(GO111MODULE) $(GO) test -short $(GOOPTS) $(pkgs) + GO111MODULE=$(GO111MODULE) $(GOTEST) -short $(GOOPTS) $(pkgs) .PHONY: common-test -common-test: +common-test: $(GOTEST_DIR) @echo ">> running all tests" - GO111MODULE=$(GO111MODULE) $(GO) test $(test-flags) $(GOOPTS) $(pkgs) + GO111MODULE=$(GO111MODULE) $(GOTEST) $(test-flags) $(GOOPTS) $(pkgs) + +$(GOTEST_DIR): + @mkdir -p $@ .PHONY: common-format common-format: diff --git a/vendor/github.com/prometheus/procfs/bcache/bcache.go b/vendor/github.com/prometheus/procfs/bcache/bcache.go index 1db178ce..df724eda 100644 --- a/vendor/github.com/prometheus/procfs/bcache/bcache.go +++ b/vendor/github.com/prometheus/procfs/bcache/bcache.go @@ -29,7 +29,7 @@ type Stats struct { } // BcacheStats contains statistics tied to a bcache ID. -type BcacheStats struct { +type BcacheStats struct { // nolint:golint AverageKeySize uint64 BtreeCacheSize uint64 CacheAvailablePercent uint64 diff --git a/vendor/github.com/prometheus/procfs/bcache/get.go b/vendor/github.com/prometheus/procfs/bcache/get.go index a8896bd9..67fcf8b1 100644 --- a/vendor/github.com/prometheus/procfs/bcache/get.go +++ b/vendor/github.com/prometheus/procfs/bcache/get.go @@ -51,8 +51,21 @@ func NewFS(mountPoint string) (FS, error) { return FS{&fs}, nil } -// Stats retrieves bcache runtime statistics for each bcache. +// Stats is a wrapper around stats() +// It returns full available statistics func (fs FS) Stats() ([]*Stats, error) { + return fs.stats(true) +} + +// StatsWithoutPriority is a wrapper around stats(). +// It ignores priority_stats file, because it is expensive to read. +func (fs FS) StatsWithoutPriority() ([]*Stats, error) { + return fs.stats(false) +} + +// stats() retrieves bcache runtime statistics for each bcache. +// priorityStats flag controls if we need to read priority_stats. +func (fs FS) stats(priorityStats bool) ([]*Stats, error) { matches, err := filepath.Glob(fs.sys.Path("fs/bcache/*-*")) if err != nil { return nil, err @@ -64,7 +77,7 @@ func (fs FS) Stats() ([]*Stats, error) { name := filepath.Base(uuidPath) // stats - s, err := GetStats(uuidPath) + s, err := GetStats(uuidPath, priorityStats) if err != nil { return nil, err } @@ -251,7 +264,7 @@ func (p *parser) getPriorityStats() PriorityStats { } // GetStats collects from sysfs files data tied to one bcache ID. -func GetStats(uuidPath string) (*Stats, error) { +func GetStats(uuidPath string, priorityStats bool) (*Stats, error) { var bs Stats par := parser{uuidPath: uuidPath} @@ -370,8 +383,10 @@ func GetStats(uuidPath string) (*Stats, error) { cs.MetadataWritten = par.readValue("metadata_written") cs.Written = par.readValue("written") - ps := par.getPriorityStats() - cs.Priority = ps + if priorityStats { + ps := par.getPriorityStats() + cs.Priority = ps + } } if par.err != nil { diff --git a/vendor/github.com/prometheus/procfs/fixtures.ttar b/vendor/github.com/prometheus/procfs/fixtures.ttar index a21ccade..45a73215 100644 --- a/vendor/github.com/prometheus/procfs/fixtures.ttar +++ b/vendor/github.com/prometheus/procfs/fixtures.ttar @@ -289,6 +289,19 @@ Max realtime priority 0 0 Max realtime timeout unlimited unlimited us Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/proc/26232/maps +Lines: 9 +55680ae1e000-55680ae20000 r--p 00000000 fd:01 47316994 /bin/cat +55680ae29000-55680ae2a000 rwxs 0000a000 fd:01 47316994 /bin/cat +55680bed6000-55680bef7000 rw-p 00000000 00:00 0 [heap] +7fdf964fc000-7fdf973f2000 r--p 00000000 fd:01 17432624 /usr/lib/locale/locale-archive +7fdf973f2000-7fdf97417000 r--p 00000000 fd:01 60571062 /lib/x86_64-linux-gnu/libc-2.29.so +7ffe9215c000-7ffe9217f000 rw-p 00000000 00:00 0 [stack] +7ffe921da000-7ffe921dd000 r--p 00000000 00:00 0 [vvar] +7ffe921dd000-7ffe921de000 r-xp 00000000 00:00 0 [vdso] +ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall] +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26232/root SymlinkTo: /does/not/exist # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -317,6 +330,17 @@ Lines: 8 || || Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Directory: fixtures/proc/26234 +Mode: 755 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/proc/26234/maps +Lines: 4 +08048000-08089000 r-xp 00000000 03:01 104219 /bin/tcsh +08089000-0808c000 rw-p 00041000 03:01 104219 /bin/tcsh +0808c000-08146000 rwxp 00000000 00:00 0 +40000000-40015000 r-xp 00000000 03:01 61874 /lib/ld-2.3.2.so +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/584 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1527,11 +1551,6 @@ blocksize : 16 min keysize : 16 max keysize : 32 -Mode: 444 -# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Path: fixtures/proc/loadavg -Lines: 1 -0.02 0.04 0.05 1/497 11947 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/diskstats @@ -1620,6 +1639,11 @@ xpc 399724544 92823103 86219234 debug 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/proc/loadavg +Lines: 1 +0.02 0.04 0.05 1/497 11947 +Mode: 444 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/mdstat Lines: 56 Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] @@ -1827,8 +1851,14 @@ FRAG6: inuse 0 memory 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/softnet_stat -Lines: 1 +Lines: 2 00015c73 00020e76 F0000769 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 +01663fb2 00000000 000109a4 00000000 00000000 00000000 00000000 00000000 00000000 +Mode: 644 +# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +Path: fixtures/proc/net/softnet_stat.broken +Lines: 1 +00015c73 00020e76 F0000769 00000000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/udp diff --git a/vendor/github.com/prometheus/procfs/go.mod b/vendor/github.com/prometheus/procfs/go.mod index 0e04e5d1..ded48253 100644 --- a/vendor/github.com/prometheus/procfs/go.mod +++ b/vendor/github.com/prometheus/procfs/go.mod @@ -5,4 +5,5 @@ go 1.12 require ( github.com/google/go-cmp v0.3.1 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e + golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e ) diff --git a/vendor/github.com/prometheus/procfs/go.sum b/vendor/github.com/prometheus/procfs/go.sum index 33b824b0..54b5f330 100644 --- a/vendor/github.com/prometheus/procfs/go.sum +++ b/vendor/github.com/prometheus/procfs/go.sum @@ -2,3 +2,5 @@ github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e h1:LwyF2AFISC9nVbS6MgzsaQNSUsRXI49GS+YQ5KX/QH0= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/prometheus/procfs/mountinfo.go b/vendor/github.com/prometheus/procfs/mountinfo.go index bb01bb5a..94711361 100644 --- a/vendor/github.com/prometheus/procfs/mountinfo.go +++ b/vendor/github.com/prometheus/procfs/mountinfo.go @@ -29,10 +29,10 @@ import ( // is described in the following man page. // http://man7.org/linux/man-pages/man5/proc.5.html type MountInfo struct { - // Unique Id for the mount - MountId int - // The Id of the parent mount - ParentId int + // Unique ID for the mount + MountID int + // The ID of the parent mount + ParentID int // The value of `st_dev` for the files on this FS MajorMinorVer string // The pathname of the directory in the FS that forms @@ -96,11 +96,11 @@ func parseMountInfoString(mountString string) (*MountInfo, error) { SuperOptions: mountOptionsParser(mountInfo[mountInfoLength-1]), } - mount.MountId, err = strconv.Atoi(mountInfo[0]) + mount.MountID, err = strconv.Atoi(mountInfo[0]) if err != nil { return nil, fmt.Errorf("failed to parse mount ID") } - mount.ParentId, err = strconv.Atoi(mountInfo[1]) + mount.ParentID, err = strconv.Atoi(mountInfo[1]) if err != nil { return nil, fmt.Errorf("failed to parse parent ID") } diff --git a/vendor/github.com/prometheus/procfs/net_softnet.go b/vendor/github.com/prometheus/procfs/net_softnet.go index 2a65cf19..db5debdf 100644 --- a/vendor/github.com/prometheus/procfs/net_softnet.go +++ b/vendor/github.com/prometheus/procfs/net_softnet.go @@ -25,7 +25,9 @@ import ( ) // For the proc file format details, -// see https://elixir.bootlin.com/linux/v4.17/source/net/core/net-procfs.c#L162 +// See: +// * Linux 2.6.23 https://elixir.bootlin.com/linux/v2.6.23/source/net/core/dev.c#L2343 +// * Linux 4.17 https://elixir.bootlin.com/linux/v4.17/source/net/core/net-procfs.c#L162 // and https://elixir.bootlin.com/linux/v4.17/source/include/linux/netdevice.h#L2810. // SoftnetStat contains a single row of data from /proc/net/softnet_stat @@ -38,9 +40,11 @@ type SoftnetStat struct { TimeSqueezed uint32 } +var softNetProcFile = "net/softnet_stat" + // NetSoftnetStat reads data from /proc/net/softnet_stat. func (fs FS) NetSoftnetStat() ([]SoftnetStat, error) { - b, err := util.ReadFileNoStat(fs.proc.Path("net/softnet_stat")) + b, err := util.ReadFileNoStat(fs.proc.Path(softNetProcFile)) if err != nil { return nil, err } @@ -54,7 +58,7 @@ func (fs FS) NetSoftnetStat() ([]SoftnetStat, error) { } func parseSoftnet(r io.Reader) ([]SoftnetStat, error) { - const expectedColumns = 11 + const minColumns = 9 s := bufio.NewScanner(r) @@ -63,8 +67,8 @@ func parseSoftnet(r io.Reader) ([]SoftnetStat, error) { columns := strings.Fields(s.Text()) width := len(columns) - if width != 11 { - return nil, fmt.Errorf("%d columns were detected, but %d were expected", width, expectedColumns) + if width < minColumns { + return nil, fmt.Errorf("%d columns were detected, but at least %d were expected", width, minColumns) } // We only parse the first three columns at the moment. diff --git a/vendor/github.com/prometheus/procfs/proc_fdinfo.go b/vendor/github.com/prometheus/procfs/proc_fdinfo.go index 4e7597f8..0c9c4028 100644 --- a/vendor/github.com/prometheus/procfs/proc_fdinfo.go +++ b/vendor/github.com/prometheus/procfs/proc_fdinfo.go @@ -16,6 +16,7 @@ package procfs import ( "bufio" "bytes" + "errors" "regexp" "github.com/prometheus/procfs/internal/util" @@ -23,10 +24,11 @@ import ( // Regexp variables var ( - rPos = regexp.MustCompile(`^pos:\s+(\d+)$`) - rFlags = regexp.MustCompile(`^flags:\s+(\d+)$`) - rMntID = regexp.MustCompile(`^mnt_id:\s+(\d+)$`) - rInotify = regexp.MustCompile(`^inotify`) + rPos = regexp.MustCompile(`^pos:\s+(\d+)$`) + rFlags = regexp.MustCompile(`^flags:\s+(\d+)$`) + rMntID = regexp.MustCompile(`^mnt_id:\s+(\d+)$`) + rInotify = regexp.MustCompile(`^inotify`) + rInotifyParts = regexp.MustCompile(`^inotify\s+wd:([0-9a-f]+)\s+ino:([0-9a-f]+)\s+sdev:([0-9a-f]+)(?:\s+mask:([0-9a-f]+))?`) ) // ProcFDInfo contains represents file descriptor information. @@ -96,15 +98,21 @@ type InotifyInfo struct { // InotifyInfo constructor. Only available on kernel 3.8+. func parseInotifyInfo(line string) (*InotifyInfo, error) { - r := regexp.MustCompile(`^inotify\s+wd:([0-9a-f]+)\s+ino:([0-9a-f]+)\s+sdev:([0-9a-f]+)\s+mask:([0-9a-f]+)`) - m := r.FindStringSubmatch(line) - i := &InotifyInfo{ - WD: m[1], - Ino: m[2], - Sdev: m[3], - Mask: m[4], + m := rInotifyParts.FindStringSubmatch(line) + if len(m) >= 4 { + var mask string + if len(m) == 5 { + mask = m[4] + } + i := &InotifyInfo{ + WD: m[1], + Ino: m[2], + Sdev: m[3], + Mask: mask, + } + return i, nil } - return i, nil + return nil, errors.New("invalid inode entry: " + line) } // ProcFDInfos represents a list of ProcFDInfo structs. diff --git a/vendor/github.com/prometheus/procfs/proc_maps.go b/vendor/github.com/prometheus/procfs/proc_maps.go new file mode 100644 index 00000000..28d5c6eb --- /dev/null +++ b/vendor/github.com/prometheus/procfs/proc_maps.go @@ -0,0 +1,208 @@ +// Copyright 2019 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// +build !windows + +package procfs + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" + + "golang.org/x/sys/unix" +) + +type ProcMapPermissions struct { + // mapping has the [R]ead flag set + Read bool + // mapping has the [W]rite flag set + Write bool + // mapping has the [X]ecutable flag set + Execute bool + // mapping has the [S]hared flag set + Shared bool + // mapping is marked as [P]rivate (copy on write) + Private bool +} + +// ProcMap contains the process memory-mappings of the process, +// read from /proc/[pid]/maps +type ProcMap struct { + // The start address of current mapping. + StartAddr uintptr + // The end address of the current mapping + EndAddr uintptr + // The permissions for this mapping + Perms *ProcMapPermissions + // The current offset into the file/fd (e.g., shared libs) + Offset int64 + // Device owner of this mapping (major:minor) in Mkdev format. + Dev uint64 + // The inode of the device above + Inode uint64 + // The file or psuedofile (or empty==anonymous) + Pathname string +} + +// parseDevice parses the device token of a line and converts it to a dev_t +// (mkdev) like structure. +func parseDevice(s string) (uint64, error) { + toks := strings.Split(s, ":") + if len(toks) < 2 { + return 0, fmt.Errorf("unexpected number of fields") + } + + major, err := strconv.ParseUint(toks[0], 16, 0) + if err != nil { + return 0, err + } + + minor, err := strconv.ParseUint(toks[1], 16, 0) + if err != nil { + return 0, err + } + + return unix.Mkdev(uint32(major), uint32(minor)), nil +} + +// parseAddress just converts a hex-string to a uintptr +func parseAddress(s string) (uintptr, error) { + a, err := strconv.ParseUint(s, 16, 0) + if err != nil { + return 0, err + } + + return uintptr(a), nil +} + +// parseAddresses parses the start-end address +func parseAddresses(s string) (uintptr, uintptr, error) { + toks := strings.Split(s, "-") + if len(toks) < 2 { + return 0, 0, fmt.Errorf("invalid address") + } + + saddr, err := parseAddress(toks[0]) + if err != nil { + return 0, 0, err + } + + eaddr, err := parseAddress(toks[1]) + if err != nil { + return 0, 0, err + } + + return saddr, eaddr, nil +} + +// parsePermissions parses a token and returns any that are set. +func parsePermissions(s string) (*ProcMapPermissions, error) { + if len(s) < 4 { + return nil, fmt.Errorf("invalid permissions token") + } + + perms := ProcMapPermissions{} + for _, ch := range s { + switch ch { + case 'r': + perms.Read = true + case 'w': + perms.Write = true + case 'x': + perms.Execute = true + case 'p': + perms.Private = true + case 's': + perms.Shared = true + } + } + + return &perms, nil +} + +// parseProcMap will attempt to parse a single line within a proc/[pid]/maps +// buffer. +func parseProcMap(text string) (*ProcMap, error) { + fields := strings.Fields(text) + if len(fields) < 5 { + return nil, fmt.Errorf("truncated procmap entry") + } + + saddr, eaddr, err := parseAddresses(fields[0]) + if err != nil { + return nil, err + } + + perms, err := parsePermissions(fields[1]) + if err != nil { + return nil, err + } + + offset, err := strconv.ParseInt(fields[2], 16, 0) + if err != nil { + return nil, err + } + + device, err := parseDevice(fields[3]) + if err != nil { + return nil, err + } + + inode, err := strconv.ParseUint(fields[4], 10, 0) + if err != nil { + return nil, err + } + + pathname := "" + + if len(fields) >= 5 { + pathname = strings.Join(fields[5:], " ") + } + + return &ProcMap{ + StartAddr: saddr, + EndAddr: eaddr, + Perms: perms, + Offset: offset, + Dev: device, + Inode: inode, + Pathname: pathname, + }, nil +} + +// ProcMaps reads from /proc/[pid]/maps to get the memory-mappings of the +// process. +func (p Proc) ProcMaps() ([]*ProcMap, error) { + file, err := os.Open(p.path("maps")) + if err != nil { + return nil, err + } + defer file.Close() + + maps := []*ProcMap{} + scan := bufio.NewScanner(file) + + for scan.Scan() { + m, err := parseProcMap(scan.Text()) + if err != nil { + return nil, err + } + + maps = append(maps, m) + } + + return maps, nil +} diff --git a/vendor/github.com/prometheus/procfs/proc_status.go b/vendor/github.com/prometheus/procfs/proc_status.go index 17b45167..c58346d9 100644 --- a/vendor/github.com/prometheus/procfs/proc_status.go +++ b/vendor/github.com/prometheus/procfs/proc_status.go @@ -33,37 +33,37 @@ type ProcStatus struct { TGID int // Peak virtual memory size. - VmPeak uint64 + VmPeak uint64 // nolint:golint // Virtual memory size. - VmSize uint64 + VmSize uint64 // nolint:golint // Locked memory size. - VmLck uint64 + VmLck uint64 // nolint:golint // Pinned memory size. - VmPin uint64 + VmPin uint64 // nolint:golint // Peak resident set size. - VmHWM uint64 + VmHWM uint64 // nolint:golint // Resident set size (sum of RssAnnon RssFile and RssShmem). - VmRSS uint64 + VmRSS uint64 // nolint:golint // Size of resident anonymous memory. - RssAnon uint64 + RssAnon uint64 // nolint:golint // Size of resident file mappings. - RssFile uint64 + RssFile uint64 // nolint:golint // Size of resident shared memory. - RssShmem uint64 + RssShmem uint64 // nolint:golint // Size of data segments. - VmData uint64 + VmData uint64 // nolint:golint // Size of stack segments. - VmStk uint64 + VmStk uint64 // nolint:golint // Size of text segments. - VmExe uint64 + VmExe uint64 // nolint:golint // Shared library code size. - VmLib uint64 + VmLib uint64 // nolint:golint // Page table entries size. - VmPTE uint64 + VmPTE uint64 // nolint:golint // Size of second-level page tables. - VmPMD uint64 + VmPMD uint64 // nolint:golint // Swapped-out virtual memory size by anonymous private. - VmSwap uint64 + VmSwap uint64 // nolint:golint // Size of hugetlb memory portions HugetlbPages uint64 diff --git a/vendor/github.com/prometheus/procfs/sysfs/class_infiniband.go b/vendor/github.com/prometheus/procfs/sysfs/class_infiniband.go index 0eab1eb1..be900fa9 100644 --- a/vendor/github.com/prometheus/procfs/sysfs/class_infiniband.go +++ b/vendor/github.com/prometheus/procfs/sysfs/class_infiniband.go @@ -251,7 +251,7 @@ func parseInfiniBandCounters(portPath string) (*InfiniBandCounters, error) { name := filepath.Join(path, f.Name()) value, err := util.SysReadFile(name) if err != nil { - if os.IsNotExist(err) || err.Error() == "operation not supported" || err.Error() == "invalid argument" { + if os.IsNotExist(err) || os.IsPermission(err) || err.Error() == "operation not supported" || err.Error() == "invalid argument" { continue } return nil, fmt.Errorf("failed to read file %q: %v", name, err) @@ -334,7 +334,7 @@ func parseInfiniBandCounters(portPath string) (*InfiniBandCounters, error) { name := filepath.Join(path, f.Name()) value, err := util.SysReadFile(name) if err != nil { - if os.IsNotExist(err) || err.Error() == "operation not supported" || err.Error() == "invalid argument" { + if os.IsNotExist(err) || os.IsPermission(err) || err.Error() == "operation not supported" || err.Error() == "invalid argument" { continue } return nil, fmt.Errorf("failed to read file %q: %v", name, err) diff --git a/vendor/github.com/prometheus/procfs/sysfs/net_class.go b/vendor/github.com/prometheus/procfs/sysfs/net_class.go index 9aa6b57f..8f649877 100644 --- a/vendor/github.com/prometheus/procfs/sysfs/net_class.go +++ b/vendor/github.com/prometheus/procfs/sysfs/net_class.go @@ -119,7 +119,7 @@ func (nc NetClass) parseNetClassIface(devicePath string) (*NetClassIface, error) name := filepath.Join(devicePath, f.Name()) value, err := util.SysReadFile(name) if err != nil { - if os.IsNotExist(err) || err.Error() == "operation not supported" || err.Error() == "invalid argument" { + if os.IsNotExist(err) || os.IsPermission(err) || err.Error() == "operation not supported" || err.Error() == "invalid argument" { continue } return nil, fmt.Errorf("failed to read file %q: %v", name, err) diff --git a/vendor/modules.txt b/vendor/modules.txt index 9b77b1a8..033b85a3 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -59,7 +59,7 @@ github.com/prometheus/common/model github.com/prometheus/common/promlog github.com/prometheus/common/promlog/flag github.com/prometheus/common/version -# github.com/prometheus/procfs v0.0.10 +# github.com/prometheus/procfs v0.0.11 github.com/prometheus/procfs github.com/prometheus/procfs/bcache github.com/prometheus/procfs/btrfs