pax_global_header00006660000000000000000000000064146100275470014520gustar00rootroot0000000000000052 comment=6bec248f1af7b94f7b57c4b2cefd7c2a8b80e40a golang-github-prometheus-procfs-0.14.0/000077500000000000000000000000001461002754700200145ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/.circleci/000077500000000000000000000000001461002754700216475ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/.circleci/config.yml000066400000000000000000000021031461002754700236330ustar00rootroot00000000000000--- version: 2.1 jobs: lint: docker: - image: cimg/go:1.22 steps: - checkout - run: make check_license - run: ./scripts/check_build_tags.sh - run: make fixtures - run: make update_fixtures - run: make style - run: git diff --exit-code test: parameters: go_version: type: string os: type: string run_test: type: boolean default: true docker: - image: cimg/go:<< parameters.go_version >> environment: GOOS: "<< parameters.os >>" steps: - checkout - run: make lint - when: condition: << parameters.run_test >> steps: - run: make test workflows: version: 2 procfs: jobs: - lint - test: name: test-linux os: linux matrix: parameters: go_version: - "1.21" - "1.22" - test: name: test-windows os: windows run_test: false matrix: parameters: go_version: - "1.21" - "1.22" golang-github-prometheus-procfs-0.14.0/.github/000077500000000000000000000000001461002754700213545ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/.github/dependabot.yml000066400000000000000000000001561461002754700242060ustar00rootroot00000000000000version: 2 updates: - package-ecosystem: "gomod" directory: "/" schedule: interval: "monthly" golang-github-prometheus-procfs-0.14.0/.github/workflows/000077500000000000000000000000001461002754700234115ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/.github/workflows/golangci-lint.yml000066400000000000000000000023131461002754700266620ustar00rootroot00000000000000--- # This action is synced from https://github.com/prometheus/prometheus name: golangci-lint on: push: paths: - "go.sum" - "go.mod" - "**.go" - "scripts/errcheck_excludes.txt" - ".github/workflows/golangci-lint.yml" - ".golangci.yml" pull_request: permissions: # added using https://github.com/step-security/secure-repo contents: read jobs: golangci: permissions: contents: read # for actions/checkout to fetch code pull-requests: read # for golangci/golangci-lint-action to fetch pull requests name: lint runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - name: install Go uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0 with: go-version: 1.22.x - name: Install snmp_exporter/generator dependencies run: sudo apt-get update && sudo apt-get -y install libsnmp-dev if: github.repository == 'prometheus/snmp_exporter' - name: Lint uses: golangci/golangci-lint-action@3cfe3a4abbb849e10058ce4af15d205b6da42804 # v4.0.0 with: version: v1.56.2 golang-github-prometheus-procfs-0.14.0/.gitignore000066400000000000000000000000361461002754700220030ustar00rootroot00000000000000/testdata/fixtures/ /fixtures golang-github-prometheus-procfs-0.14.0/.golangci.yml000066400000000000000000000002631461002754700224010ustar00rootroot00000000000000--- linters: enable: - godot - misspell - revive linter-settings: godot: capital: true exclude: # Ignore "See: URL" - 'See:' misspell: locale: US golang-github-prometheus-procfs-0.14.0/CODE_OF_CONDUCT.md000066400000000000000000000002301461002754700226060ustar00rootroot00000000000000# Prometheus Community Code of Conduct Prometheus follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/main/code-of-conduct.md). golang-github-prometheus-procfs-0.14.0/CONTRIBUTING.md000066400000000000000000000150341461002754700222500ustar00rootroot00000000000000# Contributing Prometheus uses GitHub to manage reviews of pull requests. * If you are a new contributor see: [Steps to Contribute](#steps-to-contribute) * If you have a trivial fix or improvement, go ahead and create a pull request, addressing (with `@...`) a suitable maintainer of this repository (see [MAINTAINERS.md](MAINTAINERS.md)) in the description of the pull request. * If you plan to do something more involved, first discuss your ideas on our [mailing list](https://groups.google.com/forum/?fromgroups#!forum/prometheus-developers). This will avoid unnecessary work and surely give you and us a good deal of inspiration. Also please see our [non-goals issue](https://github.com/prometheus/docs/issues/149) on areas that the Prometheus community doesn't plan to work on. * Relevant coding style guidelines are the [Go Code Review Comments](https://code.google.com/p/go-wiki/wiki/CodeReviewComments) and the _Formatting and style_ section of Peter Bourgon's [Go: Best Practices for Production Environments](https://peter.bourgon.org/go-in-production/#formatting-and-style). * Be sure to sign off on the [DCO](https://github.com/probot/dco#how-it-works) ## Steps to Contribute Should you wish to work on an issue, please claim it first by commenting on the GitHub issue that you want to work on it. This is to prevent duplicated efforts from contributors on the same issue. Please check the [`help-wanted`](https://github.com/prometheus/procfs/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22) label to find issues that are good for getting started. If you have questions about one of the issues, with or without the tag, please comment on them and one of the maintainers will clarify it. For a quicker response, contact us over [IRC](https://prometheus.io/community). For quickly compiling and testing your changes do: ``` make test # Make sure all the tests pass before you commit and push :) ``` We use [`golangci-lint`](https://github.com/golangci/golangci-lint) for linting the code. If it reports an issue and you think that the warning needs to be disregarded or is a false-positive, you can add a special comment `//nolint:linter1[,linter2,...]` before the offending line. Use this sparingly though, fixing the code to comply with the linter's recommendation is in general the preferred course of action. ## Pull Request Checklist * Branch from the master branch and, if needed, rebase to the current master branch before submitting your pull request. If it doesn't merge cleanly with master you may be asked to rebase your changes. * Commits should be as small as possible, while ensuring that each commit is correct independently (i.e., each commit should compile and pass tests). * If your patch is not getting reviewed or you need a specific person to review it, you can @-reply a reviewer asking for a review in the pull request or a comment, or you can ask for a review on IRC channel [#prometheus](https://webchat.freenode.net/?channels=#prometheus) on irc.freenode.net (for the easiest start, [join via Riot](https://riot.im/app/#/room/#prometheus:matrix.org)). * Add tests relevant to the fixed bug or new feature. ## Dependency management The Prometheus project uses [Go modules](https://golang.org/cmd/go/#hdr-Modules__module_versions__and_more) to manage dependencies on external packages. This requires a working Go environment with version 1.12 or greater installed. All dependencies are vendored in the `vendor/` directory. To add or update a new dependency, use the `go get` command: ```bash # Pick the latest tagged release. go get example.com/some/module/pkg # Pick a specific version. go get example.com/some/module/pkg@vX.Y.Z ``` Tidy up the `go.mod` and `go.sum` files and copy the new/updated dependency to the `vendor/` directory: ```bash # The GO111MODULE variable can be omitted when the code isn't located in GOPATH. GO111MODULE=on go mod tidy GO111MODULE=on go mod vendor ``` You have to commit the changes to `go.mod`, `go.sum` and the `vendor/` directory before submitting the pull request. ## API Implementation Guidelines ### Naming and Documentation Public functions and structs should normally be named according to the file(s) being read and parsed. For example, the `fs.BuddyInfo()` function reads the file `/proc/buddyinfo`. In addition, the godoc for each public function should contain the path to the file(s) being read and a URL of the linux kernel documentation describing the file(s). ### Reading vs. Parsing Most functionality in this library consists of reading files and then parsing the text into structured data. In most cases reading and parsing should be separated into different functions/methods with a public `fs.Thing()` method and a private `parseThing(r Reader)` function. This provides a logical separation and allows parsing to be tested directly without the need to read from the filesystem. Using a `Reader` argument is preferred over other data types such as `string` or `*File` because it provides the most flexibility regarding the data source. When a set of files in a directory needs to be parsed, then a `path` string parameter to the parse function can be used instead. ### /proc and /sys filesystem I/O The `proc` and `sys` filesystems are pseudo file systems and work a bit differently from standard disk I/O. Many of the files are changing continuously and the data being read can in some cases change between subsequent reads in the same file. Also, most of the files are relatively small (less than a few KBs), and system calls to the `stat` function will often return the wrong size. Therefore, for most files it's recommended to read the full file in a single operation using an internal utility function called `util.ReadFileNoStat`. This function is similar to `os.ReadFile`, but it avoids the system call to `stat` to get the current size of the file. Note that parsing the file's contents can still be performed one line at a time. This is done by first reading the full file, and then using a scanner on the `[]byte` or `string` containing the data. ``` data, err := util.ReadFileNoStat("/proc/cpuinfo") if err != nil { return err } reader := bytes.NewReader(data) scanner := bufio.NewScanner(reader) ``` The `/sys` filesystem contains many very small files which contain only a single numeric or text value. These files can be read using an internal function called `util.SysReadFile` which is similar to `os.ReadFile` but does not bother to check the size of the file before reading. ``` data, err := util.SysReadFile("/sys/class/power_supply/BAT0/capacity") ``` golang-github-prometheus-procfs-0.14.0/LICENSE000066400000000000000000000261351461002754700210300ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] 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. golang-github-prometheus-procfs-0.14.0/MAINTAINERS.md000066400000000000000000000002201461002754700221020ustar00rootroot00000000000000* Johannes 'fish' Ziemke @discordianfish * Paul Gier @pgier * Ben Kochie @SuperQ golang-github-prometheus-procfs-0.14.0/Makefile000066400000000000000000000016551461002754700214630ustar00rootroot00000000000000# Copyright 2018 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. include Makefile.common %/.unpacked: %.ttar @echo ">> extracting fixtures $*" ./ttar -C $(dir $*) -x -f $*.ttar touch $@ fixtures: testdata/fixtures/.unpacked update_fixtures: rm -vf testdata/fixtures/.unpacked ./ttar -c -f testdata/fixtures.ttar -C testdata/ fixtures/ .PHONY: build build: .PHONY: test test: testdata/fixtures/.unpacked common-test golang-github-prometheus-procfs-0.14.0/Makefile.common000066400000000000000000000217151461002754700227510ustar00rootroot00000000000000# Copyright 2018 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. # A common Makefile that includes rules to be reused in different prometheus projects. # !!! Open PRs only against the prometheus/prometheus/Makefile.common repository! # Example usage : # Create the main Makefile in the root project directory. # include Makefile.common # customTarget: # @echo ">> Running customTarget" # # Ensure GOBIN is not set during build so that promu is installed to the correct path unexport GOBIN GO ?= go GOFMT ?= $(GO)fmt FIRST_GOPATH := $(firstword $(subst :, ,$(shell $(GO) env GOPATH))) GOOPTS ?= GOHOSTOS ?= $(shell $(GO) env GOHOSTOS) GOHOSTARCH ?= $(shell $(GO) env GOHOSTARCH) GO_VERSION ?= $(shell $(GO) version) GO_VERSION_NUMBER ?= $(word 3, $(GO_VERSION)) PRE_GO_111 ?= $(shell echo $(GO_VERSION_NUMBER) | grep -E 'go1\.(10|[0-9])\.') PROMU := $(FIRST_GOPATH)/bin/promu pkgs = ./... ifeq (arm, $(GOHOSTARCH)) GOHOSTARM ?= $(shell GOARM= $(GO) env GOARM) GO_BUILD_PLATFORM ?= $(GOHOSTOS)-$(GOHOSTARCH)v$(GOHOSTARM) else GO_BUILD_PLATFORM ?= $(GOHOSTOS)-$(GOHOSTARCH) endif GOTEST := $(GO) test GOTEST_DIR := ifneq ($(CIRCLE_JOB),) ifneq ($(shell command -v gotestsum 2> /dev/null),) GOTEST_DIR := test-results GOTEST := gotestsum --junitfile $(GOTEST_DIR)/unit-tests.xml -- endif endif PROMU_VERSION ?= 0.15.0 PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz SKIP_GOLANGCI_LINT := GOLANGCI_LINT := GOLANGCI_LINT_OPTS ?= GOLANGCI_LINT_VERSION ?= v1.56.2 # golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64. # windows isn't included here because of the path separator being different. ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin)) ifeq ($(GOHOSTARCH),$(filter $(GOHOSTARCH),amd64 i386 arm64)) # If we're in CI and there is an Actions file, that means the linter # is being run in Actions, so we don't need to run it here. ifneq (,$(SKIP_GOLANGCI_LINT)) GOLANGCI_LINT := else ifeq (,$(CIRCLE_JOB)) GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint else ifeq (,$(wildcard .github/workflows/golangci-lint.yml)) GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint endif endif endif PREFIX ?= $(shell pwd) BIN_DIR ?= $(shell pwd) DOCKER_IMAGE_TAG ?= $(subst /,-,$(shell git rev-parse --abbrev-ref HEAD)) DOCKERFILE_PATH ?= ./Dockerfile DOCKERBUILD_CONTEXT ?= ./ DOCKER_REPO ?= prom DOCKER_ARCHS ?= amd64 BUILD_DOCKER_ARCHS = $(addprefix common-docker-,$(DOCKER_ARCHS)) PUBLISH_DOCKER_ARCHS = $(addprefix common-docker-publish-,$(DOCKER_ARCHS)) TAG_DOCKER_ARCHS = $(addprefix common-docker-tag-latest-,$(DOCKER_ARCHS)) SANITIZED_DOCKER_IMAGE_TAG := $(subst +,-,$(DOCKER_IMAGE_TAG)) ifeq ($(GOHOSTARCH),amd64) ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux freebsd darwin windows)) # Only supported on amd64 test-flags := -race endif endif # This rule is used to forward a target like "build" to "common-build". This # allows a new "build" target to be defined in a Makefile which includes this # one and override "common-build" without override warnings. %: common-% ; .PHONY: common-all common-all: precheck style check_license lint yamllint unused build test .PHONY: common-style common-style: @echo ">> checking code style" @fmtRes=$$($(GOFMT) -d $$(find . -path ./vendor -prune -o -name '*.go' -print)); \ if [ -n "$${fmtRes}" ]; then \ echo "gofmt checking failed!"; echo "$${fmtRes}"; echo; \ echo "Please ensure you are using $$($(GO) version) for formatting code."; \ exit 1; \ fi .PHONY: common-check_license common-check_license: @echo ">> checking license header" @licRes=$$(for file in $$(find . -type f -iname '*.go' ! -path './vendor/*') ; do \ awk 'NR<=3' $$file | grep -Eq "(Copyright|generated|GENERATED)" || echo $$file; \ done); \ if [ -n "$${licRes}" ]; then \ echo "license header checking failed:"; echo "$${licRes}"; \ exit 1; \ fi .PHONY: common-deps common-deps: @echo ">> getting dependencies" $(GO) mod download .PHONY: update-go-deps update-go-deps: @echo ">> updating Go dependencies" @for m in $$($(GO) list -mod=readonly -m -f '{{ if and (not .Indirect) (not .Main)}}{{.Path}}{{end}}' all); do \ $(GO) get -d $$m; \ done $(GO) mod tidy .PHONY: common-test-short common-test-short: $(GOTEST_DIR) @echo ">> running short tests" $(GOTEST) -short $(GOOPTS) $(pkgs) .PHONY: common-test common-test: $(GOTEST_DIR) @echo ">> running all tests" $(GOTEST) $(test-flags) $(GOOPTS) $(pkgs) $(GOTEST_DIR): @mkdir -p $@ .PHONY: common-format common-format: @echo ">> formatting code" $(GO) fmt $(pkgs) .PHONY: common-vet common-vet: @echo ">> vetting code" $(GO) vet $(GOOPTS) $(pkgs) .PHONY: common-lint common-lint: $(GOLANGCI_LINT) ifdef GOLANGCI_LINT @echo ">> running golangci-lint" $(GOLANGCI_LINT) run $(GOLANGCI_LINT_OPTS) $(pkgs) endif .PHONY: common-lint-fix common-lint-fix: $(GOLANGCI_LINT) ifdef GOLANGCI_LINT @echo ">> running golangci-lint fix" $(GOLANGCI_LINT) run --fix $(GOLANGCI_LINT_OPTS) $(pkgs) endif .PHONY: common-yamllint common-yamllint: @echo ">> running yamllint on all YAML files in the repository" ifeq (, $(shell command -v yamllint 2> /dev/null)) @echo "yamllint not installed so skipping" else yamllint . endif # For backward-compatibility. .PHONY: common-staticcheck common-staticcheck: lint .PHONY: common-unused common-unused: @echo ">> running check for unused/missing packages in go.mod" $(GO) mod tidy @git diff --exit-code -- go.sum go.mod .PHONY: common-build common-build: promu @echo ">> building binaries" $(PROMU) build --prefix $(PREFIX) $(PROMU_BINARIES) .PHONY: common-tarball common-tarball: promu @echo ">> building release tarball" $(PROMU) tarball --prefix $(PREFIX) $(BIN_DIR) .PHONY: common-docker-repo-name common-docker-repo-name: @echo "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)" .PHONY: common-docker $(BUILD_DOCKER_ARCHS) common-docker: $(BUILD_DOCKER_ARCHS) $(BUILD_DOCKER_ARCHS): common-docker-%: docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" \ -f $(DOCKERFILE_PATH) \ --build-arg ARCH="$*" \ --build-arg OS="linux" \ $(DOCKERBUILD_CONTEXT) .PHONY: common-docker-publish $(PUBLISH_DOCKER_ARCHS) common-docker-publish: $(PUBLISH_DOCKER_ARCHS) $(PUBLISH_DOCKER_ARCHS): common-docker-publish-%: docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" DOCKER_MAJOR_VERSION_TAG = $(firstword $(subst ., ,$(shell cat VERSION))) .PHONY: common-docker-tag-latest $(TAG_DOCKER_ARCHS) common-docker-tag-latest: $(TAG_DOCKER_ARCHS) $(TAG_DOCKER_ARCHS): common-docker-tag-latest-%: docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest" docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)" .PHONY: common-docker-manifest common-docker-manifest: DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)" $(foreach ARCH,$(DOCKER_ARCHS),$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$(ARCH):$(SANITIZED_DOCKER_IMAGE_TAG)) DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)" .PHONY: promu promu: $(PROMU) $(PROMU): $(eval PROMU_TMP := $(shell mktemp -d)) curl -s -L $(PROMU_URL) | tar -xvzf - -C $(PROMU_TMP) mkdir -p $(FIRST_GOPATH)/bin cp $(PROMU_TMP)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM)/promu $(FIRST_GOPATH)/bin/promu rm -r $(PROMU_TMP) .PHONY: proto proto: @echo ">> generating code from proto files" @./scripts/genproto.sh ifdef GOLANGCI_LINT $(GOLANGCI_LINT): mkdir -p $(FIRST_GOPATH)/bin curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/$(GOLANGCI_LINT_VERSION)/install.sh \ | sed -e '/install -d/d' \ | sh -s -- -b $(FIRST_GOPATH)/bin $(GOLANGCI_LINT_VERSION) endif .PHONY: precheck precheck:: define PRECHECK_COMMAND_template = precheck:: $(1)_precheck PRECHECK_COMMAND_$(1) ?= $(1) $$(strip $$(PRECHECK_OPTIONS_$(1))) .PHONY: $(1)_precheck $(1)_precheck: @if ! $$(PRECHECK_COMMAND_$(1)) 1>/dev/null 2>&1; then \ echo "Execution of '$$(PRECHECK_COMMAND_$(1))' command failed. Is $(1) installed?"; \ exit 1; \ fi endef golang-github-prometheus-procfs-0.14.0/NOTICE000066400000000000000000000003551461002754700207230ustar00rootroot00000000000000procfs provides functions to retrieve system, kernel and process metrics from the pseudo-filesystem proc. Copyright 2014-2015 The Prometheus Authors This product includes software developed at SoundCloud Ltd. (http://soundcloud.com/). golang-github-prometheus-procfs-0.14.0/README.md000066400000000000000000000054221461002754700212760ustar00rootroot00000000000000# procfs This package provides functions to retrieve system, kernel, and process metrics from the pseudo-filesystems /proc and /sys. *WARNING*: This package is a work in progress. Its API may still break in backwards-incompatible ways without warnings. Use it at your own risk. [![Go Reference](https://pkg.go.dev/badge/github.com/prometheus/procfs.svg)](https://pkg.go.dev/github.com/prometheus/procfs) [![CircleCI](https://circleci.com/gh/prometheus/procfs/tree/master.svg?style=svg)](https://circleci.com/gh/prometheus/procfs/tree/master) [![Go Report Card](https://goreportcard.com/badge/github.com/prometheus/procfs)](https://goreportcard.com/report/github.com/prometheus/procfs) ## Usage The procfs library is organized by packages based on whether the gathered data is coming from /proc, /sys, or both. Each package contains an `FS` type which represents the path to either /proc, /sys, or both. For example, cpu statistics are gathered from `/proc/stat` and are available via the root procfs package. First, the proc filesystem mount point is initialized, and then the stat information is read. ```go fs, err := procfs.NewFS("/proc") stats, err := fs.Stat() ``` Some sub-packages such as `blockdevice`, require access to both the proc and sys filesystems. ```go fs, err := blockdevice.NewFS("/proc", "/sys") stats, err := fs.ProcDiskstats() ``` ## Package Organization The packages in this project are organized according to (1) whether the data comes from the `/proc` or `/sys` filesystem and (2) the type of information being retrieved. For example, most process information can be gathered from the functions in the root `procfs` package. Information about block devices such as disk drives is available in the `blockdevices` sub-package. ## Building and Testing The procfs library is intended to be built as part of another application, so there are no distributable binaries. However, most of the API includes unit tests which can be run with `make test`. ### Updating Test Fixtures The procfs library includes a set of test fixtures which include many example files from the `/proc` and `/sys` filesystems. These fixtures are included as a [ttar](https://github.com/ideaship/ttar) file which is extracted automatically during testing. To add/update the test fixtures, first ensure the `fixtures` directory is up to date by removing the existing directory and then extracting the ttar file using `make fixtures/.unpacked` or just `make test`. ```bash rm -rf testdata/fixtures make test ``` Next, make the required changes to the extracted files in the `fixtures` directory. When the changes are complete, run `make update_fixtures` to create a new `fixtures.ttar` file based on the updated `fixtures` directory. And finally, verify the changes using `git diff testdata/fixtures.ttar`. golang-github-prometheus-procfs-0.14.0/SECURITY.md000066400000000000000000000002541461002754700216060ustar00rootroot00000000000000# Reporting a security issue The Prometheus security policy, including how to report vulnerabilities, can be found here: golang-github-prometheus-procfs-0.14.0/arp.go000066400000000000000000000057031461002754700211320ustar00rootroot00000000000000// 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. package procfs import ( "fmt" "net" "os" "strconv" "strings" ) // Learned from include/uapi/linux/if_arp.h. const ( // completed entry (ha valid). ATFComplete = 0x02 // permanent entry. ATFPermanent = 0x04 // Publish entry. ATFPublish = 0x08 // Has requested trailers. ATFUseTrailers = 0x10 // Obsoleted: Want to use a netmask (only for proxy entries). ATFNetmask = 0x20 // Don't answer this addresses. ATFDontPublish = 0x40 ) // ARPEntry contains a single row of the columnar data represented in // /proc/net/arp. type ARPEntry struct { // IP address IPAddr net.IP // MAC address HWAddr net.HardwareAddr // Name of the device Device string // Flags Flags byte } // GatherARPEntries retrieves all the ARP entries, parse the relevant columns, // and then return a slice of ARPEntry's. func (fs FS) GatherARPEntries() ([]ARPEntry, error) { data, err := os.ReadFile(fs.proc.Path("net/arp")) if err != nil { return nil, fmt.Errorf("%w: error reading arp %s: %w", ErrFileRead, fs.proc.Path("net/arp"), err) } return parseARPEntries(data) } func parseARPEntries(data []byte) ([]ARPEntry, error) { lines := strings.Split(string(data), "\n") entries := make([]ARPEntry, 0) var err error const ( expectedDataWidth = 6 expectedHeaderWidth = 9 ) for _, line := range lines { columns := strings.Fields(line) width := len(columns) if width == expectedHeaderWidth || width == 0 { continue } else if width == expectedDataWidth { entry, err := parseARPEntry(columns) if err != nil { return []ARPEntry{}, fmt.Errorf("%w: Failed to parse ARP entry: %v: %w", ErrFileParse, entry, err) } entries = append(entries, entry) } else { return []ARPEntry{}, fmt.Errorf("%w: %d columns found, but expected %d: %w", ErrFileParse, width, expectedDataWidth, err) } } return entries, err } func parseARPEntry(columns []string) (ARPEntry, error) { entry := ARPEntry{Device: columns[5]} ip := net.ParseIP(columns[0]) entry.IPAddr = ip if mac, err := net.ParseMAC(columns[3]); err == nil { entry.HWAddr = mac } else { return ARPEntry{}, err } if flags, err := strconv.ParseUint(columns[2], 0, 8); err == nil { entry.Flags = byte(flags) } else { return ARPEntry{}, err } return entry, nil } // IsComplete returns true if ARP entry is marked with complete flag. func (entry *ARPEntry) IsComplete() bool { return entry.Flags&ATFComplete != 0 } golang-github-prometheus-procfs-0.14.0/arp_test.go000066400000000000000000000035071461002754700221710ustar00rootroot00000000000000// 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. package procfs import ( "net" "testing" ) func TestARP(t *testing.T) { fs, err := NewFS(procTestFixtures) if err != nil { t.Fatal(err) } arpFile, err := fs.GatherARPEntries() if err != nil { t.Fatal(err) } if want, got := "192.168.224.1", arpFile[0].IPAddr.String(); want != got { t.Errorf("want 192.168.224.1, got %s", got) } if want, got := "00:50:56:c0:00:08", arpFile[0].HWAddr.String(); want != got { t.Errorf("want %s, got %s", want, got) } if want, got := "ens33", arpFile[0].Device; want != got { t.Errorf("want ens33, got %s", got) } if want, got := true, arpFile[0].IsComplete(); want != got { t.Errorf("want %t, got %t", want, got) } if want, got := "192.168.224.2", arpFile[1].IPAddr.String(); want != got { t.Errorf("want 192.168.224.2, got %s", got) } if want, got := make(net.HardwareAddr, 6).String(), arpFile[1].HWAddr.String(); want != got { t.Errorf("expected empty MAC, got %s", got) } if want, got := "ens33", arpFile[1].Device; want != got { t.Errorf("want %s, got %s", want, got) } if want, got := byte(0x0), arpFile[1].Flags; want != got { t.Errorf("want %b, got %b", want, got) } if want, got := false, arpFile[1].IsComplete(); want != got { t.Errorf("want %t, got %t", want, got) } } golang-github-prometheus-procfs-0.14.0/bcache/000077500000000000000000000000001461002754700212215ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/bcache/bcache.go000066400000000000000000000055731461002754700227670ustar00rootroot00000000000000// Copyright 2017 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. // Package bcache provides access to statistics exposed by the bcache (Linux // block cache). package bcache // Stats contains bcache runtime statistics, parsed from /sys/fs/bcache/. // // The names and meanings of each statistic were taken from bcache.txt and // files in drivers/md/bcache in the Linux kernel source. Counters are uint64 // (in-kernel counters are mostly unsigned long). type Stats struct { // The name of the bcache used to source these statistics. Name string Bcache BcacheStats Bdevs []BdevStats Caches []CacheStats } // BcacheStats contains statistics tied to a bcache ID. type BcacheStats struct { // nolint:revive AverageKeySize uint64 BtreeCacheSize uint64 CacheAvailablePercent uint64 Congested uint64 RootUsagePercent uint64 TreeDepth uint64 Internal InternalStats FiveMin PeriodStats Total PeriodStats } // BdevStats contains statistics for one backing device. type BdevStats struct { Name string DirtyData uint64 FiveMin PeriodStats Total PeriodStats WritebackRateDebug WritebackRateDebugStats } // CacheStats contains statistics for one cache device. type CacheStats struct { Name string IOErrors uint64 MetadataWritten uint64 Written uint64 Priority PriorityStats } // PriorityStats contains statistics from the priority_stats file. type PriorityStats struct { UnusedPercent uint64 MetadataPercent uint64 } // InternalStats contains internal bcache statistics. type InternalStats struct { ActiveJournalEntries uint64 BtreeNodes uint64 BtreeReadAverageDurationNanoSeconds uint64 CacheReadRaces uint64 } // PeriodStats contains statistics for a time period (5 min or total). type PeriodStats struct { Bypassed uint64 CacheBypassHits uint64 CacheBypassMisses uint64 CacheHits uint64 CacheMissCollisions uint64 CacheMisses uint64 CacheReadaheads uint64 } // WritebackRateDebugStats contains bcache writeback statistics. type WritebackRateDebugStats struct { Rate uint64 Dirty uint64 Target uint64 Proportional int64 Integral int64 Change int64 NextIO int64 } golang-github-prometheus-procfs-0.14.0/bcache/get.go000066400000000000000000000324641461002754700223400ustar00rootroot00000000000000// Copyright 2017 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. package bcache import ( "bufio" "fmt" "os" "path" "path/filepath" "strconv" "strings" "github.com/prometheus/procfs/internal/fs" ) // FS represents the pseudo-filesystem proc, which provides an interface to // kernel data structures. type FS struct { sys *fs.FS } // NewDefaultFS returns a new Bcache using the default sys fs mount point. It will error // if the mount point can't be read. func NewDefaultFS() (FS, error) { return NewFS(fs.DefaultSysMountPoint) } // NewFS returns a new Bcache using the given sys fs mount point. It will error // if the mount point can't be read. func NewFS(mountPoint string) (FS, error) { if strings.TrimSpace(mountPoint) == "" { mountPoint = fs.DefaultSysMountPoint } fs, err := fs.NewFS(mountPoint) if err != nil { return FS{}, err } return FS{&fs}, nil } // 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 } stats := make([]*Stats, 0, len(matches)) for _, uuidPath := range matches { // "*-*" in glob above indicates the name of the bcache. name := filepath.Base(uuidPath) // stats s, err := GetStats(uuidPath, priorityStats) if err != nil { return nil, err } s.Name = name stats = append(stats, s) } return stats, nil } // ParsePseudoFloat parses the peculiar format produced by bcache's bch_hprint. func parsePseudoFloat(str string) (float64, error) { ss := strings.Split(str, ".") intPart, err := strconv.ParseFloat(ss[0], 64) if err != nil { return 0, err } if len(ss) == 1 { // Pure integers are fine. return intPart, nil } fracPart, err := strconv.ParseFloat(ss[1], 64) if err != nil { return 0, err } // fracPart is a number between 0 and 1023 divided by 100; it is off // by a small amount. Unexpected bumps in time lines may occur because // for bch_hprint .1 != .10 and .10 > .9 (at least up to Linux // v4.12-rc3). // Restore the proper order: fracPart = fracPart / 10.24 return intPart + fracPart, nil } // Dehumanize converts a human-readable byte slice into a uint64. func dehumanize(hbytes []byte) (uint64, error) { ll := len(hbytes) if ll == 0 { return 0, fmt.Errorf("zero-length reply") } lastByte := hbytes[ll-1] mul := float64(1) var ( mant float64 err error ) // If lastByte is beyond the range of ASCII digits, it must be a // multiplier. if lastByte > 57 { // Remove multiplier from slice. hbytes = hbytes[:len(hbytes)-1] const ( _ = 1 << (10 * iota) KiB MiB GiB TiB PiB EiB ZiB YiB ) multipliers := map[rune]float64{ // Source for conversion rules: // linux-kernel/drivers/md/bcache/util.c:bch_hprint() 'k': KiB, 'M': MiB, 'G': GiB, 'T': TiB, 'P': PiB, 'E': EiB, 'Z': ZiB, 'Y': YiB, } mul = multipliers[rune(lastByte)] mant, err = parsePseudoFloat(string(hbytes)) if err != nil { return 0, err } } else { // Not humanized by bch_hprint mant, err = strconv.ParseFloat(string(hbytes), 64) if err != nil { return 0, err } } res := uint64(mant * mul) return res, nil } func dehumanizeSigned(str string) (int64, error) { value, err := dehumanize([]byte(strings.TrimPrefix(str, "-"))) if err != nil { return 0, err } if strings.HasPrefix(str, "-") { return int64(-value), nil } return int64(value), nil } type parser struct { uuidPath string subDir string currentDir string err error } func (p *parser) setSubDir(pathElements ...string) { p.subDir = path.Join(pathElements...) p.currentDir = path.Join(p.uuidPath, p.subDir) } // readValues reads a number of numerical values into an uint64 slice. // Non-existing files are ignored. func (p *parser) readValue(fileName string) uint64 { if p.err != nil { return 0 } path := path.Join(p.currentDir, fileName) byt, err := os.ReadFile(path) if err != nil { if !os.IsNotExist(err) { p.err = fmt.Errorf("failed to read: %s", path) } return 0 } // Remove trailing newline. byt = byt[:len(byt)-1] res, err := dehumanize(byt) p.err = err return res } // ParsePriorityStats parses lines from the priority_stats file. func parsePriorityStats(line string, ps *PriorityStats) error { var ( value uint64 err error ) switch { case strings.HasPrefix(line, "Unused:"): fields := strings.Fields(line) rawValue := fields[len(fields)-1] valueStr := strings.TrimSuffix(rawValue, "%") value, err = strconv.ParseUint(valueStr, 10, 64) if err != nil { return err } ps.UnusedPercent = value case strings.HasPrefix(line, "Metadata:"): fields := strings.Fields(line) rawValue := fields[len(fields)-1] valueStr := strings.TrimSuffix(rawValue, "%") value, err = strconv.ParseUint(valueStr, 10, 64) if err != nil { return err } ps.MetadataPercent = value } return nil } // ParseWritebackRateDebug parses lines from the writeback_rate_debug file. func parseWritebackRateDebug(line string, wrd *WritebackRateDebugStats) error { switch { case strings.HasPrefix(line, "rate:"): fields := strings.Fields(line) rawValue := fields[len(fields)-1] valueStr := strings.TrimSuffix(rawValue, "/sec") value, err := dehumanize([]byte(valueStr)) if err != nil { return err } wrd.Rate = value case strings.HasPrefix(line, "dirty:"): fields := strings.Fields(line) valueStr := fields[len(fields)-1] value, err := dehumanize([]byte(valueStr)) if err != nil { return err } wrd.Dirty = value case strings.HasPrefix(line, "target:"): fields := strings.Fields(line) valueStr := fields[len(fields)-1] value, err := dehumanize([]byte(valueStr)) if err != nil { return err } wrd.Target = value case strings.HasPrefix(line, "proportional:"): fields := strings.Fields(line) valueStr := fields[len(fields)-1] value, err := dehumanizeSigned(valueStr) if err != nil { return err } wrd.Proportional = value case strings.HasPrefix(line, "integral:"): fields := strings.Fields(line) valueStr := fields[len(fields)-1] value, err := dehumanizeSigned(valueStr) if err != nil { return err } wrd.Integral = value case strings.HasPrefix(line, "change:"): fields := strings.Fields(line) rawValue := fields[len(fields)-1] valueStr := strings.TrimSuffix(rawValue, "/sec") value, err := dehumanizeSigned(valueStr) if err != nil { return err } wrd.Change = value case strings.HasPrefix(line, "next io:"): fields := strings.Fields(line) rawValue := fields[len(fields)-1] valueStr := strings.TrimSuffix(rawValue, "ms") value, err := strconv.ParseInt(valueStr, 10, 64) if err != nil { return err } wrd.NextIO = value } return nil } func (p *parser) getPriorityStats() PriorityStats { var res PriorityStats if p.err != nil { return res } path := path.Join(p.currentDir, "priority_stats") file, err := os.Open(path) if err != nil { p.err = fmt.Errorf("failed to read: %s", path) return res } defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan() { err = parsePriorityStats(scanner.Text(), &res) if err != nil { p.err = fmt.Errorf("failed to parse path %q: %w", path, err) return res } } if err := scanner.Err(); err != nil { p.err = fmt.Errorf("failed to parse path %q: %w", path, err) return res } return res } func (p *parser) getWritebackRateDebug() WritebackRateDebugStats { var res WritebackRateDebugStats if p.err != nil { return res } path := path.Join(p.currentDir, "writeback_rate_debug") file, err := os.Open(path) if err != nil { p.err = fmt.Errorf("failed to read: %s", path) return res } defer file.Close() scanner := bufio.NewScanner(file) for scanner.Scan() { err = parseWritebackRateDebug(scanner.Text(), &res) if err != nil { p.err = fmt.Errorf("failed to parse path %q: %w", path, err) return res } } if err := scanner.Err(); err != nil { p.err = fmt.Errorf("failed to parse path %q: %w", path, err) return res } return res } // GetStats collects from sysfs files data tied to one bcache ID. func GetStats(uuidPath string, priorityStats bool) (*Stats, error) { var bs Stats par := parser{uuidPath: uuidPath} // bcache stats // dir par.setSubDir("") bs.Bcache.AverageKeySize = par.readValue("average_key_size") bs.Bcache.BtreeCacheSize = par.readValue("btree_cache_size") bs.Bcache.CacheAvailablePercent = par.readValue("cache_available_percent") bs.Bcache.Congested = par.readValue("congested") bs.Bcache.RootUsagePercent = par.readValue("root_usage_percent") bs.Bcache.TreeDepth = par.readValue("tree_depth") // bcache stats (internal) // dir /internal par.setSubDir("internal") bs.Bcache.Internal.ActiveJournalEntries = par.readValue("active_journal_entries") bs.Bcache.Internal.BtreeNodes = par.readValue("btree_nodes") bs.Bcache.Internal.BtreeReadAverageDurationNanoSeconds = par.readValue("btree_read_average_duration_us") bs.Bcache.Internal.CacheReadRaces = par.readValue("cache_read_races") // bcache stats (period) // dir /stats_five_minute par.setSubDir("stats_five_minute") bs.Bcache.FiveMin.Bypassed = par.readValue("bypassed") bs.Bcache.FiveMin.CacheHits = par.readValue("cache_hits") bs.Bcache.FiveMin.Bypassed = par.readValue("bypassed") bs.Bcache.FiveMin.CacheBypassHits = par.readValue("cache_bypass_hits") bs.Bcache.FiveMin.CacheBypassMisses = par.readValue("cache_bypass_misses") bs.Bcache.FiveMin.CacheHits = par.readValue("cache_hits") bs.Bcache.FiveMin.CacheMissCollisions = par.readValue("cache_miss_collisions") bs.Bcache.FiveMin.CacheMisses = par.readValue("cache_misses") bs.Bcache.FiveMin.CacheReadaheads = par.readValue("cache_readaheads") // dir /stats_total par.setSubDir("stats_total") bs.Bcache.Total.Bypassed = par.readValue("bypassed") bs.Bcache.Total.CacheHits = par.readValue("cache_hits") bs.Bcache.Total.Bypassed = par.readValue("bypassed") bs.Bcache.Total.CacheBypassHits = par.readValue("cache_bypass_hits") bs.Bcache.Total.CacheBypassMisses = par.readValue("cache_bypass_misses") bs.Bcache.Total.CacheHits = par.readValue("cache_hits") bs.Bcache.Total.CacheMissCollisions = par.readValue("cache_miss_collisions") bs.Bcache.Total.CacheMisses = par.readValue("cache_misses") bs.Bcache.Total.CacheReadaheads = par.readValue("cache_readaheads") if par.err != nil { return nil, par.err } // bdev stats reg := path.Join(uuidPath, "bdev[0-9]*") bdevDirs, err := filepath.Glob(reg) if err != nil { return nil, err } bs.Bdevs = make([]BdevStats, len(bdevDirs)) for ii, bdevDir := range bdevDirs { var bds = &bs.Bdevs[ii] bds.Name = filepath.Base(bdevDir) par.setSubDir(bds.Name) bds.DirtyData = par.readValue("dirty_data") wrd := par.getWritebackRateDebug() bds.WritebackRateDebug = wrd // dir //stats_five_minute par.setSubDir(bds.Name, "stats_five_minute") bds.FiveMin.Bypassed = par.readValue("bypassed") bds.FiveMin.CacheBypassHits = par.readValue("cache_bypass_hits") bds.FiveMin.CacheBypassMisses = par.readValue("cache_bypass_misses") bds.FiveMin.CacheHits = par.readValue("cache_hits") bds.FiveMin.CacheMissCollisions = par.readValue("cache_miss_collisions") bds.FiveMin.CacheMisses = par.readValue("cache_misses") bds.FiveMin.CacheReadaheads = par.readValue("cache_readaheads") // dir //stats_total par.setSubDir(bds.Name, "stats_total") bds.Total.Bypassed = par.readValue("bypassed") bds.Total.CacheBypassHits = par.readValue("cache_bypass_hits") bds.Total.CacheBypassMisses = par.readValue("cache_bypass_misses") bds.Total.CacheHits = par.readValue("cache_hits") bds.Total.CacheMissCollisions = par.readValue("cache_miss_collisions") bds.Total.CacheMisses = par.readValue("cache_misses") bds.Total.CacheReadaheads = par.readValue("cache_readaheads") } if par.err != nil { return nil, par.err } // cache stats reg = path.Join(uuidPath, "cache[0-9]*") cacheDirs, err := filepath.Glob(reg) if err != nil { return nil, err } bs.Caches = make([]CacheStats, len(cacheDirs)) for ii, cacheDir := range cacheDirs { var cs = &bs.Caches[ii] cs.Name = filepath.Base(cacheDir) // dir is / par.setSubDir(cs.Name) cs.IOErrors = par.readValue("io_errors") cs.MetadataWritten = par.readValue("metadata_written") cs.Written = par.readValue("written") if priorityStats { ps := par.getPriorityStats() cs.Priority = ps } } if par.err != nil { return nil, par.err } return &bs, nil } golang-github-prometheus-procfs-0.14.0/bcache/get_test.go000066400000000000000000000126001461002754700233650ustar00rootroot00000000000000// Copyright 2017 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. package bcache import ( "math" "testing" ) func TestFSBcacheStats(t *testing.T) { bcache, err := NewFS("testdata/fixtures/sys") if err != nil { t.Fatalf("failed to access bcache fs: %v", err) } stats, err := bcache.Stats() if err != nil { t.Fatalf("failed to parse bcache stats: %v", err) } tests := []struct { name string bdevs int caches int }{ { name: "deaddd54-c735-46d5-868e-f331c5fd7c74", bdevs: 1, caches: 1, }, } const expect = 1 if l := len(stats); l != expect { t.Fatalf("unexpected number of bcache stats: %d", l) } if l := len(tests); l != expect { t.Fatalf("unexpected number of tests: %d", l) } for i, tt := range tests { if want, got := tt.name, stats[i].Name; want != got { t.Errorf("unexpected stats name:\nwant: %q\nhave: %q", want, got) } if want, got := tt.bdevs, len(stats[i].Bdevs); want != got { t.Errorf("unexpected value allocated:\nwant: %d\nhave: %d", want, got) } if want, got := tt.caches, len(stats[i].Caches); want != got { t.Errorf("unexpected value allocated:\nwant: %d\nhave: %d", want, got) } } } func TestDehumanizeTests(t *testing.T) { dehumanizeTests := []struct { in []byte out uint64 invalid bool }{ { in: []byte("542k"), out: 555008, }, { in: []byte("322M"), out: 337641472, }, { in: []byte("1.1k"), out: 1124, }, { in: []byte("1.9k"), out: 1924, }, { in: []byte("1.10k"), out: 2024, }, { in: []byte(""), out: 0, invalid: true, }, } for _, tst := range dehumanizeTests { got, err := dehumanize(tst.in) if tst.invalid && err == nil { t.Error("expected an error, but none occurred") } if !tst.invalid && err != nil { t.Errorf("unexpected error: %v", err) } if got != tst.out { t.Errorf("dehumanize: '%s', want %d, got %d", tst.in, tst.out, got) } } } func TestParsePseudoFloatTests(t *testing.T) { parsePseudoFloatTests := []struct { in string out float64 }{ { in: "1.1", out: float64(1.097656), }, { in: "1.9", out: float64(1.878906), }, { in: "1.10", out: float64(1.976562), }, } for _, tst := range parsePseudoFloatTests { got, err := parsePseudoFloat(tst.in) if err != nil || math.Abs(got-tst.out) > 0.0001 { t.Errorf("parsePseudoFloat: %s, want %f, got %f", tst.in, tst.out, got) } } } func TestPriorityStats(t *testing.T) { var want = PriorityStats{ UnusedPercent: 99, MetadataPercent: 5, } var ( in string gotErr error got PriorityStats ) in = "Metadata: 5%" gotErr = parsePriorityStats(in, &got) if gotErr != nil || got.MetadataPercent != want.MetadataPercent { t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.MetadataPercent, got.MetadataPercent) } in = "Unused: 99%" gotErr = parsePriorityStats(in, &got) if gotErr != nil || got.UnusedPercent != want.UnusedPercent { t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.UnusedPercent, got.UnusedPercent) } } func TestWritebackRateDebug(t *testing.T) { var want = WritebackRateDebugStats{ Rate: 1765376, Dirty: 21789409280, Target: 21894266880, Proportional: -1124, Integral: -257624, Change: 2648, NextIO: -150773, } var ( in string gotErr error got WritebackRateDebugStats ) in = "rate: 1.7M/sec" gotErr = parseWritebackRateDebug(in, &got) if gotErr != nil || got.Rate != want.Rate { t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.Rate, got.Rate) } in = "dirty: 20.3G" gotErr = parseWritebackRateDebug(in, &got) if gotErr != nil || got.Dirty != want.Dirty { t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.Dirty, got.Dirty) } in = "target: 20.4G" gotErr = parseWritebackRateDebug(in, &got) if gotErr != nil || got.Target != want.Target { t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.Target, got.Target) } in = "proportional: -1.1k" gotErr = parseWritebackRateDebug(in, &got) if gotErr != nil || got.Proportional != want.Proportional { t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.Proportional, got.Proportional) } in = "integral: -251.6k" gotErr = parseWritebackRateDebug(in, &got) if gotErr != nil || got.Integral != want.Integral { t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.Integral, got.Integral) } in = "change: 2.6k/sec" gotErr = parseWritebackRateDebug(in, &got) if gotErr != nil || got.Change != want.Change { t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.Change, got.Change) } in = "next io: -150773ms" gotErr = parseWritebackRateDebug(in, &got) if gotErr != nil || got.NextIO != want.NextIO { t.Errorf("parsePriorityStats: '%s', want %d, got %d", in, want.NextIO, got.NextIO) } } golang-github-prometheus-procfs-0.14.0/bcache/testdata/000077500000000000000000000000001461002754700230325ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/bcache/testdata/fixtures000077700000000000000000000000001461002754700306542../../testdata/fixturesustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/blockdevice/000077500000000000000000000000001461002754700222665ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/blockdevice/stats.go000066400000000000000000000425531461002754700237640ustar00rootroot00000000000000// Copyright 2018 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. package blockdevice import ( "bufio" "errors" "fmt" "io" "os" "strings" "github.com/prometheus/procfs/internal/fs" "github.com/prometheus/procfs/internal/util" ) // Info contains identifying information for a block device such as a disk drive. type Info struct { MajorNumber uint32 MinorNumber uint32 DeviceName string } // IOStats models the iostats data described in the kernel documentation. // - https://www.kernel.org/doc/Documentation/iostats.txt, // - https://www.kernel.org/doc/Documentation/block/stat.txt // - https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats type IOStats struct { // ReadIOs is the number of reads completed successfully. ReadIOs uint64 // ReadMerges is the number of reads merged. Reads and writes // which are adjacent to each other may be merged for efficiency. ReadMerges uint64 // ReadSectors is the total number of sectors read successfully. ReadSectors uint64 // ReadTicks is the total number of milliseconds spent by all reads. ReadTicks uint64 // WriteIOs is the total number of writes completed successfully. WriteIOs uint64 // WriteMerges is the number of reads merged. WriteMerges uint64 // WriteSectors is the total number of sectors written successfully. WriteSectors uint64 // WriteTicks is the total number of milliseconds spent by all writes. WriteTicks uint64 // IOsInProgress is number of I/Os currently in progress. IOsInProgress uint64 // IOsTotalTicks is the number of milliseconds spent doing I/Os. // This field increases so long as IosInProgress is nonzero. IOsTotalTicks uint64 // WeightedIOTicks is the weighted number of milliseconds spent doing I/Os. // This can also be used to estimate average queue wait time for requests. WeightedIOTicks uint64 // DiscardIOs is the total number of discards completed successfully. DiscardIOs uint64 // DiscardMerges is the number of discards merged. DiscardMerges uint64 // DiscardSectors is the total number of sectors discarded successfully. DiscardSectors uint64 // DiscardTicks is the total number of milliseconds spent by all discards. DiscardTicks uint64 // FlushRequestsCompleted is the total number of flush request completed successfully. FlushRequestsCompleted uint64 // TimeSpentFlushing is the total number of milliseconds spent flushing. TimeSpentFlushing uint64 } // Diskstats combines the device Info and IOStats. type Diskstats struct { Info IOStats // IoStatsCount contains the number of io stats read. For kernel versions 5.5+, // there should be 20 fields read. For kernel versions 4.18+, // there should be 18 fields read. For earlier kernel versions this // will be 14 because the discard values are not available. IoStatsCount int } // BlockQueueStats models the queue files that are located in the sysfs tree for each block device // and described in the kernel documentation: // https://www.kernel.org/doc/Documentation/block/queue-sysfs.txt // https://www.kernel.org/doc/html/latest/block/queue-sysfs.html type BlockQueueStats struct { // AddRandom is the status of a disk entropy (1 is on, 0 is off). AddRandom uint64 // Dax indicates whether the device supports Direct Access (DAX) (1 is on, 0 is off). DAX uint64 // DiscardGranularity is the size of internal allocation of the device in bytes, 0 means device // does not support the discard functionality. DiscardGranularity uint64 // DiscardMaxHWBytes is the hardware maximum number of bytes that can be discarded in a single operation, // 0 means device does not support the discard functionality. DiscardMaxHWBytes uint64 // DiscardMaxBytes is the software maximum number of bytes that can be discarded in a single operation. DiscardMaxBytes uint64 // HWSectorSize is the sector size of the device, in bytes. HWSectorSize uint64 // IOPoll indicates if polling is enabled (1 is on, 0 is off). IOPoll uint64 // IOPollDelay indicates how polling will be performed, -1 for classic polling, 0 for hybrid polling, // with greater than 0 the kernel will put process issuing IO to sleep for this amount of time in // microseconds before entering classic polling. IOPollDelay int64 // IOTimeout is the request timeout in milliseconds. IOTimeout uint64 // IOStats indicates if iostats accounting is used for the disk (1 is on, 0 is off). IOStats uint64 // LogicalBlockSize is the logical block size of the device, in bytes. LogicalBlockSize uint64 // MaxHWSectorsKB is the maximum number of kilobytes supported in a single data transfer. MaxHWSectorsKB uint64 // MaxIntegritySegments is the max limit of integrity segments as set by block layer which a hardware controller // can handle. MaxIntegritySegments uint64 // MaxSectorsKB is the maximum number of kilobytes that the block layer will allow for a filesystem request. MaxSectorsKB uint64 // MaxSegments is the number of segments on the device. MaxSegments uint64 // MaxSegmentsSize is the maximum segment size of the device. MaxSegmentSize uint64 // MinimumIOSize is the smallest preferred IO size reported by the device. MinimumIOSize uint64 // NoMerges shows the lookup logic involved with IO merging requests in the block layer. 0 all merges are // enabled, 1 only simple one hit merges are tried, 2 no merge algorithms will be tried. NoMerges uint64 // NRRequests is the number of how many requests may be allocated in the block layer for read or write requests. NRRequests uint64 // OptimalIOSize is the optimal IO size reported by the device. OptimalIOSize uint64 // PhysicalBlockSize is the physical block size of device, in bytes. PhysicalBlockSize uint64 // ReadAHeadKB is the maximum number of kilobytes to read-ahead for filesystems on this block device. ReadAHeadKB uint64 // Rotational indicates if the device is of rotational type or non-rotational type. Rotational uint64 // RQAffinity indicates affinity policy of device, if 1 the block layer will migrate request completions to the // cpu “group†that originally submitted the request, if 2 forces the completion to run on the requesting cpu. RQAffinity uint64 // SchedulerList contains list of available schedulers for this block device. SchedulerList []string // SchedulerCurrent is the current scheduler for this block device. SchedulerCurrent string // WriteCache shows the type of cache for block device, "write back" or "write through". WriteCache string // WriteSameMaxBytes is the number of bytes the device can write in a single write-same command. // A value of ‘0’ means write-same is not supported by this device. WriteSameMaxBytes uint64 // WBTLatUSec is the target minimum read latency, 0 means feature is disables. WBTLatUSec int64 // ThrottleSampleTime is the time window that blk-throttle samples data, in millisecond. Optional // exists only if CONFIG_BLK_DEV_THROTTLING_LOW is enabled. ThrottleSampleTime *uint64 // Zoned indicates if the device is a zoned block device and the zone model of the device if it is indeed zoned. // Possible values are: none, host-aware, host-managed for zoned block devices. Zoned string // NRZones indicates the total number of zones of the device, always zero for regular block devices. NRZones uint64 // ChunksSectors for RAID is the size in 512B sectors of the RAID volume stripe segment, // for zoned host device is the size in 512B sectors. ChunkSectors uint64 // FUA indicates whether the device supports Force Unit Access for write requests. FUA uint64 // MaxDiscardSegments is the maximum number of DMA entries in a discard request. MaxDiscardSegments uint64 // WriteZeroesMaxBytes the maximum number of bytes that can be zeroed at once. // The value 0 means that REQ_OP_WRITE_ZEROES is not supported. WriteZeroesMaxBytes uint64 } // DeviceMapperInfo models the devicemapper files that are located in the sysfs tree for each block device // and described in the kernel documentation: // https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-block-dm type DeviceMapperInfo struct { // Name is the string containing mapped device name. Name string // RqBasedSeqIOMergeDeadline determines how long (in microseconds) a request that is a reasonable merge // candidate can be queued on the request queue. RqBasedSeqIOMergeDeadline uint64 // Suspended indicates if the device is suspended (1 is on, 0 is off). Suspended uint64 // UseBlkMQ indicates if the device is using the request-based blk-mq I/O path mode (1 is on, 0 is off). UseBlkMQ uint64 // UUID is the DM-UUID string or empty string if DM-UUID is not set. UUID string } // UnderlyingDevices models the list of devices that this device is built from. type UnderlyingDeviceInfo struct { // DeviceNames is the list of devices names DeviceNames []string } const ( procDiskstatsPath = "diskstats" procDiskstatsFormat = "%d %d %s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d" sysBlockPath = "block" sysBlockStatFormat = "%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d" sysBlockQueue = "queue" sysBlockDM = "dm" sysUnderlyingDev = "slaves" ) // FS represents the pseudo-filesystems proc and sys, which provides an // interface to kernel data structures. type FS struct { proc *fs.FS sys *fs.FS } // NewDefaultFS returns a new blockdevice fs using the default mountPoints for proc and sys. // It will error if either of these mount points can't be read. func NewDefaultFS() (FS, error) { return NewFS(fs.DefaultProcMountPoint, fs.DefaultSysMountPoint) } // NewFS returns a new blockdevice fs using the given mountPoints for proc and sys. // It will error if either of these mount points can't be read. func NewFS(procMountPoint string, sysMountPoint string) (FS, error) { if strings.TrimSpace(procMountPoint) == "" { procMountPoint = fs.DefaultProcMountPoint } procfs, err := fs.NewFS(procMountPoint) if err != nil { return FS{}, err } if strings.TrimSpace(sysMountPoint) == "" { sysMountPoint = fs.DefaultSysMountPoint } sysfs, err := fs.NewFS(sysMountPoint) if err != nil { return FS{}, err } return FS{&procfs, &sysfs}, nil } // ProcDiskstats reads the diskstats file and returns // an array of Diskstats (one per line/device). func (fs FS) ProcDiskstats() ([]Diskstats, error) { file, err := os.Open(fs.proc.Path(procDiskstatsPath)) if err != nil { return nil, err } defer file.Close() return parseProcDiskstats(file) } func parseProcDiskstats(r io.Reader) ([]Diskstats, error) { var ( diskstats []Diskstats scanner = bufio.NewScanner(r) err error ) for scanner.Scan() { d := &Diskstats{} d.IoStatsCount, err = fmt.Sscanf(scanner.Text(), procDiskstatsFormat, &d.MajorNumber, &d.MinorNumber, &d.DeviceName, &d.ReadIOs, &d.ReadMerges, &d.ReadSectors, &d.ReadTicks, &d.WriteIOs, &d.WriteMerges, &d.WriteSectors, &d.WriteTicks, &d.IOsInProgress, &d.IOsTotalTicks, &d.WeightedIOTicks, &d.DiscardIOs, &d.DiscardMerges, &d.DiscardSectors, &d.DiscardTicks, &d.FlushRequestsCompleted, &d.TimeSpentFlushing, ) // The io.EOF error can be safely ignored because it just means we read fewer than // the full 20 fields. if err != nil && !errors.Is(err, io.EOF) { return diskstats, err } if d.IoStatsCount >= 14 { diskstats = append(diskstats, *d) } } return diskstats, scanner.Err() } // SysBlockDevices lists the device names from /sys/block/. func (fs FS) SysBlockDevices() ([]string, error) { deviceDirs, err := os.ReadDir(fs.sys.Path(sysBlockPath)) if err != nil { return nil, err } devices := []string{} for _, deviceDir := range deviceDirs { devices = append(devices, deviceDir.Name()) } return devices, nil } // SysBlockDeviceStat returns stats for the block device read from /sys/block//stat. // The number of stats read will be 15 if the discard stats are available (kernel 4.18+) // and 11 if they are not available. func (fs FS) SysBlockDeviceStat(device string) (IOStats, int, error) { bytes, err := os.ReadFile(fs.sys.Path(sysBlockPath, device, "stat")) if err != nil { return IOStats{}, 0, err } return parseSysBlockDeviceStat(bytes) } func parseSysBlockDeviceStat(data []byte) (IOStats, int, error) { stat := IOStats{} count, err := fmt.Sscanf(strings.TrimSpace(string(data)), sysBlockStatFormat, &stat.ReadIOs, &stat.ReadMerges, &stat.ReadSectors, &stat.ReadTicks, &stat.WriteIOs, &stat.WriteMerges, &stat.WriteSectors, &stat.WriteTicks, &stat.IOsInProgress, &stat.IOsTotalTicks, &stat.WeightedIOTicks, &stat.DiscardIOs, &stat.DiscardMerges, &stat.DiscardSectors, &stat.DiscardTicks, &stat.FlushRequestsCompleted, &stat.TimeSpentFlushing, ) // An io.EOF error is ignored because it just means we read fewer than the full 15 fields. if errors.Is(err, io.EOF) { return stat, count, nil } return stat, count, err } // SysBlockDeviceQueueStats returns stats for /sys/block/xxx/queue where xxx is a device name. func (fs FS) SysBlockDeviceQueueStats(device string) (BlockQueueStats, error) { stat := BlockQueueStats{} // Files with uint64 fields for file, p := range map[string]*uint64{ "add_random": &stat.AddRandom, "dax": &stat.DAX, "discard_granularity": &stat.DiscardGranularity, "discard_max_hw_bytes": &stat.DiscardMaxHWBytes, "discard_max_bytes": &stat.DiscardMaxBytes, "hw_sector_size": &stat.HWSectorSize, "io_poll": &stat.IOPoll, "io_timeout": &stat.IOTimeout, "iostats": &stat.IOStats, "logical_block_size": &stat.LogicalBlockSize, "max_hw_sectors_kb": &stat.MaxHWSectorsKB, "max_integrity_segments": &stat.MaxIntegritySegments, "max_sectors_kb": &stat.MaxSectorsKB, "max_segments": &stat.MaxSegments, "max_segment_size": &stat.MaxSegmentSize, "minimum_io_size": &stat.MinimumIOSize, "nomerges": &stat.NoMerges, "nr_requests": &stat.NRRequests, "optimal_io_size": &stat.OptimalIOSize, "physical_block_size": &stat.PhysicalBlockSize, "read_ahead_kb": &stat.ReadAHeadKB, "rotational": &stat.Rotational, "rq_affinity": &stat.RQAffinity, "write_same_max_bytes": &stat.WriteSameMaxBytes, "nr_zones": &stat.NRZones, "chunk_sectors": &stat.ChunkSectors, "fua": &stat.FUA, "max_discard_segments": &stat.MaxDiscardSegments, "write_zeroes_max_bytes": &stat.WriteZeroesMaxBytes, } { val, err := util.ReadUintFromFile(fs.sys.Path(sysBlockPath, device, sysBlockQueue, file)) if err != nil { return BlockQueueStats{}, err } *p = val } // Files with int64 fields for file, p := range map[string]*int64{ "io_poll_delay": &stat.IOPollDelay, "wbt_lat_usec": &stat.WBTLatUSec, } { val, err := util.ReadIntFromFile(fs.sys.Path(sysBlockPath, device, sysBlockQueue, file)) if err != nil { return BlockQueueStats{}, err } *p = val } // Files with string fields for file, p := range map[string]*string{ "write_cache": &stat.WriteCache, "zoned": &stat.Zoned, } { val, err := util.SysReadFile(fs.sys.Path(sysBlockPath, device, sysBlockQueue, file)) if err != nil { return BlockQueueStats{}, err } *p = val } scheduler, err := util.SysReadFile(fs.sys.Path(sysBlockPath, device, sysBlockQueue, "scheduler")) if err != nil { return BlockQueueStats{}, err } var schedulers []string xs := strings.Split(scheduler, " ") for _, s := range xs { if strings.HasPrefix(s, "[") && strings.HasSuffix(s, "]") { s = s[1 : len(s)-1] stat.SchedulerCurrent = s } schedulers = append(schedulers, s) } stat.SchedulerList = schedulers // optional throttleSampleTime, err := util.ReadUintFromFile(fs.sys.Path(sysBlockPath, device, sysBlockQueue, "throttle_sample_time")) if err == nil { stat.ThrottleSampleTime = &throttleSampleTime } return stat, nil } func (fs FS) SysBlockDeviceMapperInfo(device string) (DeviceMapperInfo, error) { info := DeviceMapperInfo{} // Files with uint64 fields for file, p := range map[string]*uint64{ "rq_based_seq_io_merge_deadline": &info.RqBasedSeqIOMergeDeadline, "suspended": &info.Suspended, "use_blk_mq": &info.UseBlkMQ, } { val, err := util.ReadUintFromFile(fs.sys.Path(sysBlockPath, device, sysBlockDM, file)) if err != nil { return DeviceMapperInfo{}, err } *p = val } // Files with string fields for file, p := range map[string]*string{ "name": &info.Name, "uuid": &info.UUID, } { val, err := util.SysReadFile(fs.sys.Path(sysBlockPath, device, sysBlockDM, file)) if err != nil { return DeviceMapperInfo{}, err } *p = val } return info, nil } func (fs FS) SysBlockDeviceUnderlyingDevices(device string) (UnderlyingDeviceInfo, error) { underlyingDir, err := os.Open(fs.sys.Path(sysBlockPath, device, sysUnderlyingDev)) if err != nil { return UnderlyingDeviceInfo{}, err } underlying, err := underlyingDir.Readdirnames(0) if err != nil { return UnderlyingDeviceInfo{}, err } return UnderlyingDeviceInfo{DeviceNames: underlying}, nil } golang-github-prometheus-procfs-0.14.0/blockdevice/stats_test.go000066400000000000000000000160311461002754700250130ustar00rootroot00000000000000// Copyright 2018 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. package blockdevice import ( "os" "reflect" "testing" ) const ( failMsgFormat = "%v, expected %v, actual %v" procfsFixtures = "testdata/fixtures/proc" sysfsFixtures = "testdata/fixtures/sys" ) func TestDiskstats(t *testing.T) { blockdevice, err := NewFS(procfsFixtures, sysfsFixtures) if err != nil { t.Fatalf("failed to access blockdevice fs: %v", err) } diskstats, err := blockdevice.ProcDiskstats() if err != nil { t.Fatal(err) } expectedNumOfDevices := 52 if len(diskstats) != expectedNumOfDevices { t.Errorf(failMsgFormat, "Incorrect number of devices", expectedNumOfDevices, len(diskstats)) } if diskstats[0].DeviceName != "ram0" { t.Errorf(failMsgFormat, "Incorrect device name", "ram0", diskstats[0].DeviceName) } if diskstats[1].IoStatsCount != 14 { t.Errorf(failMsgFormat, "Incorrect number of stats read", 14, diskstats[0].IoStatsCount) } if diskstats[24].WriteIOs != 28444756 { t.Errorf(failMsgFormat, "Incorrect writes completed", 28444756, diskstats[24].WriteIOs) } if diskstats[48].DiscardTicks != 11130 { t.Errorf(failMsgFormat, "Incorrect discard time", 11130, diskstats[48].DiscardTicks) } if diskstats[48].IoStatsCount != 18 { t.Errorf(failMsgFormat, "Incorrect number of stats read", 18, diskstats[48].IoStatsCount) } if diskstats[49].IoStatsCount != 20 { t.Errorf(failMsgFormat, "Incorrect number of stats read", 20, diskstats[50].IoStatsCount) } if diskstats[49].FlushRequestsCompleted != 127 { t.Errorf(failMsgFormat, "Incorrect number of flash requests completed", 127, diskstats[50].FlushRequestsCompleted) } if diskstats[49].TimeSpentFlushing != 182 { t.Errorf(failMsgFormat, "Incorrect time spend flushing", 182, diskstats[50].TimeSpentFlushing) } } func TestBlockDevice(t *testing.T) { blockdevice, err := NewFS("testdata/fixtures/proc", "testdata/fixtures/sys") if err != nil { t.Fatalf("failed to access blockdevice fs: %v", err) } devices, err := blockdevice.SysBlockDevices() if err != nil { t.Fatal(err) } expectedNumOfDevices := 8 if len(devices) != expectedNumOfDevices { t.Fatalf(failMsgFormat, "Incorrect number of devices", expectedNumOfDevices, len(devices)) } if devices[0] != "dm-0" { t.Errorf(failMsgFormat, "Incorrect device name", "dm-0", devices[0]) } device0stats, count, err := blockdevice.SysBlockDeviceStat(devices[0]) if err != nil { t.Fatal(err) } if count != 11 { t.Errorf(failMsgFormat, "Incorrect number of stats read", 11, count) } if device0stats.ReadIOs != 6447303 { t.Errorf(failMsgFormat, "Incorrect read I/Os", 6447303, device0stats.ReadIOs) } if device0stats.WeightedIOTicks != 6088971 { t.Errorf(failMsgFormat, "Incorrect time in queue", 6088971, device0stats.WeightedIOTicks) } device7stats, count, err := blockdevice.SysBlockDeviceStat(devices[7]) if count != 15 { t.Errorf(failMsgFormat, "Incorrect number of stats read", 15, count) } if err != nil { t.Fatal(err) } if device7stats.WriteSectors != 286915323 { t.Errorf(failMsgFormat, "Incorrect write merges", 286915323, device7stats.WriteSectors) } if device7stats.DiscardTicks != 12 { t.Errorf(failMsgFormat, "Incorrect discard ticks", 12, device7stats.DiscardTicks) } blockQueueStatExpected := BlockQueueStats{ AddRandom: 1, DAX: 0, DiscardGranularity: 0, DiscardMaxHWBytes: 0, DiscardMaxBytes: 0, HWSectorSize: 512, IOPoll: 0, IOPollDelay: -1, IOTimeout: 30000, IOStats: 1, LogicalBlockSize: 512, MaxHWSectorsKB: 32767, MaxIntegritySegments: 0, MaxSectorsKB: 1280, MaxSegments: 168, MaxSegmentSize: 65536, MinimumIOSize: 512, NoMerges: 0, NRRequests: 64, OptimalIOSize: 0, PhysicalBlockSize: 512, ReadAHeadKB: 128, Rotational: 1, RQAffinity: 1, SchedulerList: []string{"mq-deadline", "kyber", "bfq", "none"}, SchedulerCurrent: "bfq", WriteCache: "write back", WriteSameMaxBytes: 0, WBTLatUSec: 75000, ThrottleSampleTime: nil, Zoned: "none", NRZones: 0, ChunkSectors: 0, FUA: 0, MaxDiscardSegments: 1, WriteZeroesMaxBytes: 0, } blockQueueStat, err := blockdevice.SysBlockDeviceQueueStats(devices[7]) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(blockQueueStat, blockQueueStatExpected) { t.Errorf("Incorrect BlockQueueStat, expected: \n%+v, got: \n%+v", blockQueueStatExpected, blockQueueStat) } } func TestBlockDmInfo(t *testing.T) { blockdevice, err := NewFS("testdata/fixtures/proc", "testdata/fixtures/sys") if err != nil { t.Fatalf("failed to access blockdevice fs: %v", err) } devices, err := blockdevice.SysBlockDevices() if err != nil { t.Fatal(err) } dm0Info, err := blockdevice.SysBlockDeviceMapperInfo(devices[0]) if err != nil { t.Fatal(err) } dm0InfoExpected := DeviceMapperInfo{ Name: "vg0--lv_root", RqBasedSeqIOMergeDeadline: 0, Suspended: 0, UseBlkMQ: 0, UUID: "LVM-3zSHSR5Nbf4j7g6auAAefWY2CMaX01theZYEvQyecVsm2WtX3iY5q51qq5dWWOq7", } if !reflect.DeepEqual(dm0Info, dm0InfoExpected) { t.Errorf("Incorrect BlockQueueStat, expected: \n%+v, got: \n%+v", dm0InfoExpected, dm0Info) } dm1Info, err := blockdevice.SysBlockDeviceMapperInfo(devices[1]) if err != nil { if _, ok := err.(*os.PathError); ok { // Fail the test if there's an error other than PathError. if !os.IsNotExist(err) { t.Fatal(err) } } else { t.Fatal(err) } } else { t.Fatal("SysBlockDeviceMapperInfo on sda was supposed to fail.") } dm1InfoExpected := DeviceMapperInfo{} if !reflect.DeepEqual(dm1Info, dm1InfoExpected) { t.Errorf("Incorrect BlockQueueStat, expected: \n%+v, got: \n%+v", dm0InfoExpected, dm0Info) } } func TestSysBlockDeviceUnderlyingDevices(t *testing.T) { blockdevice, err := NewFS("testdata/fixtures/proc", "testdata/fixtures/sys") if err != nil { t.Fatalf("failed to access blockdevice fs: %v", err) } devices, err := blockdevice.SysBlockDevices() if err != nil { t.Fatal(err) } underlying0, err := blockdevice.SysBlockDeviceUnderlyingDevices(devices[0]) if err != nil { t.Fatal(err) } underlying0Expected := UnderlyingDeviceInfo{ DeviceNames: []string{"sda"}, } if !reflect.DeepEqual(underlying0, underlying0Expected) { t.Errorf("Incorrect BlockQueueStat, expected: \n%+v, got: \n%+v", underlying0Expected, underlying0) } } golang-github-prometheus-procfs-0.14.0/blockdevice/testdata/000077500000000000000000000000001461002754700240775ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/blockdevice/testdata/fixtures000077700000000000000000000000001461002754700317212../../testdata/fixturesustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/btrfs/000077500000000000000000000000001461002754700211345ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/btrfs/btrfs.go000066400000000000000000000044641461002754700226130ustar00rootroot00000000000000// 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. // Package btrfs provides access to statistics exposed by Btrfs filesystems. package btrfs // Stats contains statistics for a single Btrfs filesystem. // See Linux fs/btrfs/sysfs.c for more information. type Stats struct { UUID, Label string Allocation Allocation Devices map[string]*Device Features []string CloneAlignment uint64 NodeSize uint64 QuotaOverride uint64 SectorSize uint64 CommitStats CommitStats } // Allocation contains allocation statistics for data, metadata and system data. type Allocation struct { GlobalRsvReserved, GlobalRsvSize uint64 Data, Metadata, System *AllocationStats } // AllocationStats contains allocation statistics for a data type. type AllocationStats struct { // Usage statistics DiskUsedBytes uint64 DiskTotalBytes uint64 MayUseBytes uint64 PinnedBytes uint64 TotalPinnedBytes uint64 ReadOnlyBytes uint64 ReservedBytes uint64 UsedBytes uint64 TotalBytes uint64 // Flags marking filesystem state // See Linux fs/btrfs/ctree.h for more information. Flags uint64 // Additional disk usage statistics depending on the disk layout. // At least one of these will exist and not be nil. Layouts map[string]*LayoutUsage } // LayoutUsage contains additional usage statistics for a disk layout. type LayoutUsage struct { UsedBytes, TotalBytes uint64 Ratio float64 } // Device contains information about a device that is part of a Btrfs filesystem. type Device struct { Size uint64 } // Number of commits and various time related statistics. // See Linux fs/btrfs/sysfs.c with 6.x version. type CommitStats struct { Commits uint64 LastCommitMs uint64 MaxCommitMs uint64 TotalCommitMs uint64 } golang-github-prometheus-procfs-0.14.0/btrfs/get.go000066400000000000000000000174771461002754700222620ustar00rootroot00000000000000// 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. package btrfs import ( "bufio" "fmt" "os" "path" "path/filepath" "strconv" "strings" "github.com/prometheus/procfs/internal/fs" "github.com/prometheus/procfs/internal/util" ) // SectorSize contains the Linux sector size. // > Linux always considers sectors to be 512 bytes long independently // > of the devices real block size. const SectorSize = 512 // FS represents the pseudo-filesystem sys, which provides an interface to // kernel data structures. type FS struct { sys *fs.FS } // NewDefaultFS returns a new Bcache using the default sys fs mount point. It will error // if the mount point can't be read. func NewDefaultFS() (FS, error) { return NewFS(fs.DefaultSysMountPoint) } // NewFS returns a new Btrfs filesystem using the given sys fs mount point. It will error // if the mount point can't be read. func NewFS(mountPoint string) (FS, error) { if strings.TrimSpace(mountPoint) == "" { mountPoint = fs.DefaultSysMountPoint } sys, err := fs.NewFS(mountPoint) if err != nil { return FS{}, err } return FS{&sys}, nil } // Stats retrieves Btrfs filesystem runtime statistics for each mounted Btrfs filesystem. func (fs FS) Stats() ([]*Stats, error) { matches, err := filepath.Glob(fs.sys.Path("fs/btrfs/*-*")) if err != nil { return nil, err } stats := make([]*Stats, 0, len(matches)) for _, uuidPath := range matches { s, err := GetStats(uuidPath) if err != nil { return nil, err } // Set the UUID from the path when it could not be retrieved from the filesystem. if s.UUID == "" { s.UUID = filepath.Base(uuidPath) } stats = append(stats, s) } return stats, nil } // GetStats collects all Btrfs statistics from sysfs. func GetStats(uuidPath string) (*Stats, error) { r := &reader{path: uuidPath} s := r.readFilesystemStats() if r.err != nil { return nil, r.err } return s, nil } type reader struct { path string err error devCount int } // readFile reads a file relative to the path of the reader. // Non-existing files are ignored. func (r *reader) readFile(n string) string { b, err := util.SysReadFile(path.Join(r.path, n)) if err != nil && !os.IsNotExist(err) { r.err = err } return strings.TrimSpace(string(b)) } // readValues reads a number of numerical values into an uint64 slice. func (r *reader) readValue(n string) (v uint64) { // Read value from file s := r.readFile(n) if r.err != nil { return } // Convert number v, _ = strconv.ParseUint(s, 10, 64) return } // listFiles returns a list of files for a directory of the reader. func (r *reader) listFiles(p string) []string { files, err := os.ReadDir(path.Join(r.path, p)) if err != nil { r.err = err return nil } names := make([]string, len(files)) for i, f := range files { names[i] = f.Name() } return names } // readAllocationStats reads Btrfs allocation data for the current path. func (r *reader) readAllocationStats(d string) (a *AllocationStats) { // Create a reader for this subdirectory sr := &reader{path: path.Join(r.path, d), devCount: r.devCount} // Get the stats a = &AllocationStats{ // Read basic allocation stats MayUseBytes: sr.readValue("bytes_may_use"), PinnedBytes: sr.readValue("bytes_pinned"), ReadOnlyBytes: sr.readValue("bytes_readonly"), ReservedBytes: sr.readValue("bytes_reserved"), UsedBytes: sr.readValue("bytes_used"), DiskUsedBytes: sr.readValue("disk_used"), DiskTotalBytes: sr.readValue("disk_total"), Flags: sr.readValue("flags"), TotalBytes: sr.readValue("total_bytes"), TotalPinnedBytes: sr.readValue("total_bytes_pinned"), Layouts: sr.readLayouts(), } // Pass any error back r.err = sr.err return } // readLayouts reads all Btrfs layout statistics for the current path. func (r *reader) readLayouts() map[string]*LayoutUsage { files, err := os.ReadDir(r.path) if err != nil { r.err = err return nil } m := make(map[string]*LayoutUsage) for _, f := range files { if f.IsDir() { m[f.Name()] = r.readLayout(f.Name()) } } return m } // readLayout reads the Btrfs layout statistics for an allocation layout. func (r *reader) readLayout(p string) (l *LayoutUsage) { l = new(LayoutUsage) l.TotalBytes = r.readValue(path.Join(p, "total_bytes")) l.UsedBytes = r.readValue(path.Join(p, "used_bytes")) l.Ratio = r.calcRatio(p) return } // calcRatio returns the calculated ratio for a layout mode. func (r *reader) calcRatio(p string) float64 { switch p { case "single", "raid0": return 1 case "dup", "raid1", "raid10": return 2 case "raid5": return float64(r.devCount) / (float64(r.devCount) - 1) case "raid6": return float64(r.devCount) / (float64(r.devCount) - 2) default: return 0 } } // readDeviceInfo returns the information for all devices associated with this filesystem. func (r *reader) readDeviceInfo(d string) map[string]*Device { devs := r.listFiles(d) info := make(map[string]*Device, len(devs)) for _, n := range devs { info[n] = &Device{ Size: SectorSize * r.readValue("devices/"+n+"/size"), } } return info } // readFilesystemStats reads Btrfs statistics for a filesystem. func (r *reader) readFilesystemStats() (s *Stats) { // First get disk info, and add it to reader devices := r.readDeviceInfo("devices") r.devCount = len(devices) s = &Stats{ // Read basic filesystem information Label: r.readFile("label"), UUID: r.readFile("metadata_uuid"), Features: r.listFiles("features"), CloneAlignment: r.readValue("clone_alignment"), NodeSize: r.readValue("nodesize"), QuotaOverride: r.readValue("quota_override"), SectorSize: r.readValue("sectorsize"), // Device info Devices: devices, // Read allocation data Allocation: Allocation{ GlobalRsvReserved: r.readValue("allocation/global_rsv_reserved"), GlobalRsvSize: r.readValue("allocation/global_rsv_size"), Data: r.readAllocationStats("allocation/data"), Metadata: r.readAllocationStats("allocation/metadata"), System: r.readAllocationStats("allocation/system"), }, // Read commit stats data CommitStats: r.readCommitStats("commit_stats"), } return } // readCommitStats returns the commit_stats information for commit stats metrics. func (r *reader) readCommitStats(p string) CommitStats { stats := CommitStats{} f, err := os.Open(path.Join(r.path, p)) if err != nil { // if commit_stats not found. maybe btrfs version < 6.0 if !os.IsNotExist(err) { r.err = err } return stats } defer f.Close() scanner := bufio.NewScanner(f) for scanner.Scan() { line := scanner.Text() parts := strings.Fields(scanner.Text()) // require if len(parts) != 2 { r.err = fmt.Errorf("invalid commit_stats line %q", line) return stats } value, err := strconv.ParseUint(parts[1], 10, 64) if err != nil { r.err = fmt.Errorf("error parsing commit_stats line: %w", err) return stats } switch metricName := parts[0]; metricName { case "commits": stats.Commits = value case "last_commit_ms": stats.LastCommitMs = value case "max_commit_ms": stats.MaxCommitMs = value case "total_commit_ms": stats.TotalCommitMs = value default: continue } } if err := scanner.Err(); err != nil { r.err = fmt.Errorf("error scanning commit_stats file: %w", err) return stats } return stats } golang-github-prometheus-procfs-0.14.0/btrfs/get_test.go000066400000000000000000000104331461002754700233020ustar00rootroot00000000000000// 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. package btrfs import "testing" type testVector struct { uuid, label string devices, features int data, meta, system alloc commitstats commit } type alloc struct { layout string size uint64 ratio float64 } type commit struct { commits uint64 lastCommitMs uint64 maxCommitMs uint64 totalCommitMs uint64 } func TestFSBtrfsStats(t *testing.T) { btrfs, err := NewFS("testdata/fixtures/sys") if err != nil { t.Fatalf("failed to access Btrfs filesystem: %v", err) } stats, err := btrfs.Stats() if err != nil { t.Fatalf("failed to parse Btrfs stats: %v", err) } tests := []testVector{ { uuid: "0abb23a9-579b-43e6-ad30-227ef47fcb9d", label: "fixture", devices: 2, features: 4, data: alloc{"raid0", 2147483648, 1}, meta: alloc{"raid1", 1073741824, 2}, system: alloc{"raid1", 8388608, 2}, commitstats: commit{258051, 1000, 51462, 47836090}, }, { uuid: "7f07c59f-6136-449c-ab87-e1cf2328731b", label: "", devices: 4, features: 5, data: alloc{"raid5", 644087808, 4. / 3.}, meta: alloc{"raid6", 429391872, 4. / 2.}, system: alloc{"raid6", 16777216, 4. / 2.}, commitstats: commit{0, 0, 0, 0}, }, } if l := len(stats); l != len(tests) { t.Fatalf("unexpected number of btrfs stats: %d", l) } for i, tt := range tests { if want, got := tt.uuid, stats[i].UUID; want != got { t.Errorf("fs %q unexpected stats name:\nwant: %q\nhave: %q", tt.uuid, want, got) } if want, got := tt.devices, len(stats[i].Devices); want != got { t.Errorf("fs %q unexpected number of devices:\nwant: %d\nhave: %d", tt.uuid, want, got) } if want, got := tt.features, len(stats[i].Features); want != got { t.Errorf("fs %q unexpected number of features:\nwant: %d\nhave: %d", tt.uuid, want, got) } if want, got := tt.data.size, stats[i].Allocation.Data.TotalBytes; want != got { t.Errorf("fs %q unexpected data size:\nwant: %d\nhave: %d", tt.uuid, want, got) } if want, got := tt.meta.size, stats[i].Allocation.Metadata.TotalBytes; want != got { t.Errorf("fs %q unexpected metadata size:\nwant: %d\nhave: %d", tt.uuid, want, got) } if want, got := tt.system.size, stats[i].Allocation.System.TotalBytes; want != got { t.Errorf("fs %q unexpected system size:\nwant: %d\nhave: %d", tt.uuid, want, got) } if want, got := tt.data.ratio, stats[i].Allocation.Data.Layouts[tt.data.layout].Ratio; want != got { t.Errorf("fs %q unexpected data ratio:\nwant: %f\nhave: %f", tt.uuid, want, got) } if want, got := tt.meta.ratio, stats[i].Allocation.Metadata.Layouts[tt.meta.layout].Ratio; want != got { t.Errorf("fs %q unexpected metadata ratio:\nwant: %f\nhave: %f", tt.uuid, want, got) } if want, got := tt.system.ratio, stats[i].Allocation.System.Layouts[tt.system.layout].Ratio; want != got { t.Errorf("fs %q unexpected system ratio:\nwant: %f\nhave: %f", tt.uuid, want, got) } if want, got := tt.commitstats.commits, stats[i].CommitStats.Commits; want != got { t.Errorf("fs %q unexpected commit stats commits:\nwant: %d\nhave: %d", tt.uuid, want, got) } if want, got := tt.commitstats.lastCommitMs, stats[i].CommitStats.LastCommitMs; want != got { t.Errorf("fs %q unexpected commit stats last_commit_ms:\nwant: %d\nhave: %d", tt.uuid, want, got) } if want, got := tt.commitstats.maxCommitMs, stats[i].CommitStats.MaxCommitMs; want != got { t.Errorf("fs %q unexpected commit stats max_commit_ms:\nwant: %d\nhave: %d", tt.uuid, want, got) } if want, got := tt.commitstats.totalCommitMs, stats[i].CommitStats.TotalCommitMs; want != got { t.Errorf("fs %q unexpected commit stats total_commit_ms:\nwant: %d\nhave: %d", tt.uuid, want, got) } } } golang-github-prometheus-procfs-0.14.0/btrfs/testdata/000077500000000000000000000000001461002754700227455ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/btrfs/testdata/fixtures000077700000000000000000000000001461002754700305672../../testdata/fixturesustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/buddyinfo.go000066400000000000000000000043611461002754700223320ustar00rootroot00000000000000// Copyright 2017 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. package procfs import ( "bufio" "fmt" "io" "os" "strconv" "strings" ) // A BuddyInfo is the details parsed from /proc/buddyinfo. // The data is comprised of an array of free fragments of each size. // The sizes are 2^n*PAGE_SIZE, where n is the array index. type BuddyInfo struct { Node string Zone string Sizes []float64 } // BuddyInfo reads the buddyinfo statistics from the specified `proc` filesystem. func (fs FS) BuddyInfo() ([]BuddyInfo, error) { file, err := os.Open(fs.proc.Path("buddyinfo")) if err != nil { return nil, err } defer file.Close() return parseBuddyInfo(file) } func parseBuddyInfo(r io.Reader) ([]BuddyInfo, error) { var ( buddyInfo = []BuddyInfo{} scanner = bufio.NewScanner(r) bucketCount = -1 ) for scanner.Scan() { var err error line := scanner.Text() parts := strings.Fields(line) if len(parts) < 4 { return nil, fmt.Errorf("%w: Invalid number of fields, found: %v", ErrFileParse, parts) } node := strings.TrimRight(parts[1], ",") zone := strings.TrimRight(parts[3], ",") arraySize := len(parts[4:]) if bucketCount == -1 { bucketCount = arraySize } else { if bucketCount != arraySize { return nil, fmt.Errorf("%w: mismatch in number of buddyinfo buckets, previous count %d, new count %d", ErrFileParse, bucketCount, arraySize) } } sizes := make([]float64, arraySize) for i := 0; i < arraySize; i++ { sizes[i], err = strconv.ParseFloat(parts[i+4], 64) if err != nil { return nil, fmt.Errorf("%w: Invalid valid in buddyinfo: %f: %w", ErrFileParse, sizes[i], err) } } buddyInfo = append(buddyInfo, BuddyInfo{node, zone, sizes}) } return buddyInfo, scanner.Err() } golang-github-prometheus-procfs-0.14.0/buddyinfo_test.go000066400000000000000000000046761461002754700234020ustar00rootroot00000000000000// Copyright 2017 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. package procfs import ( "strings" "testing" ) func TestBuddyInfo(t *testing.T) { buddyInfo, err := getProcFixtures(t).BuddyInfo() if err != nil { t.Fatal(err) } if want, got := "DMA", buddyInfo[0].Zone; want != got { t.Errorf("want Node 0, Zone %s, got %s", want, got) } if want, got := "Normal", buddyInfo[2].Zone; want != got { t.Errorf("want Node 0, Zone %s, got %s", want, got) } if want, got := 4381.0, buddyInfo[2].Sizes[0]; want != got { t.Errorf("want Node 0, Zone Normal %f, got %f", want, got) } if want, got := 572.0, buddyInfo[1].Sizes[1]; want != got { t.Errorf("want Node 0, Zone DMA32 %f, got %f", want, got) } } func TestParseBuddyInfoShort(t *testing.T) { testdata := `Node 0, zone Node 0, zone Node 0, zone ` reader := strings.NewReader(testdata) _, err := parseBuddyInfo(reader) if err == nil { t.Fatalf("expected error, but none occurred") } if want, got := "Error Parsing File: Invalid number of fields, found: [Node 0, zone]", err.Error(); want != got { t.Fatalf("Error Parsing File: Invalid number of fields, found: [Node %q, %q]", want, got) } } func TestParseBuddyInfoSizeMismatch(t *testing.T) { testdata := `Node 0, zone DMA 1 0 1 0 2 1 1 0 1 1 3 Node 0, zone DMA32 759 572 791 475 194 45 12 0 0 0 0 0 Node 0, zone Normal 4381 1093 185 1530 567 102 4 0 0 0 ` reader := strings.NewReader(testdata) _, err := parseBuddyInfo(reader) if err == nil { t.Fatalf("expected error, but none occurred") } if want, got := "Error Parsing File: mismatch in number of buddyinfo buckets, previous count 11, new count 12", err.Error(); !strings.HasPrefix(got, want) { t.Fatalf("Error Parsing File: mismatch in number of buddyinfo buckets, previous count %q, new count %q", want, got) } } golang-github-prometheus-procfs-0.14.0/cmdline.go000066400000000000000000000016231461002754700217600ustar00rootroot00000000000000// Copyright 2021 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. package procfs import ( "strings" "github.com/prometheus/procfs/internal/util" ) // CmdLine returns the command line of the kernel. func (fs FS) CmdLine() ([]string, error) { data, err := util.ReadFileNoStat(fs.proc.Path("cmdline")) if err != nil { return nil, err } return strings.Fields(string(data)), nil } golang-github-prometheus-procfs-0.14.0/cmdline_test.go000066400000000000000000000021651461002754700230210ustar00rootroot00000000000000// Copyright 2021 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. //go:build linux // +build linux package procfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestCmdline(t *testing.T) { fs, err := NewFS(procTestFixtures) if err != nil { t.Fatal(err) } got, err := fs.CmdLine() if err != nil { t.Fatal(err) } want := []string{ "BOOT_IMAGE=/vmlinuz-5.11.0-22-generic", "root=UUID=456a0345-450d-4f7b-b7c9-43e3241d99ad", "ro", "quiet", "splash", "vt.handoff=7", } if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected CmdLine (-want +got):\n%s", diff) } } golang-github-prometheus-procfs-0.14.0/cpuinfo.go000066400000000000000000000323771461002754700220220ustar00rootroot00000000000000// 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. //go:build linux // +build linux package procfs import ( "bufio" "bytes" "errors" "fmt" "regexp" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // CPUInfo contains general information about a system CPU found in /proc/cpuinfo. type CPUInfo struct { Processor uint VendorID string CPUFamily string Model string ModelName string Stepping string Microcode string CPUMHz float64 CacheSize string PhysicalID string Siblings uint CoreID string CPUCores uint APICID string InitialAPICID string FPU string FPUException string CPUIDLevel uint WP string Flags []string Bugs []string BogoMips float64 CLFlushSize uint CacheAlignment uint AddressSizes string PowerManagement string } var ( cpuinfoClockRegexp = regexp.MustCompile(`([\d.]+)`) cpuinfoS390XProcessorRegexp = regexp.MustCompile(`^processor\s+(\d+):.*`) ) // CPUInfo returns information about current system CPUs. // See https://www.kernel.org/doc/Documentation/filesystems/proc.txt func (fs FS) CPUInfo() ([]CPUInfo, error) { data, err := util.ReadFileNoStat(fs.proc.Path("cpuinfo")) if err != nil { return nil, err } return parseCPUInfo(data) } func parseCPUInfoX86(info []byte) ([]CPUInfo, error) { scanner := bufio.NewScanner(bytes.NewReader(info)) // find the first "processor" line firstLine := firstNonEmptyLine(scanner) if !strings.HasPrefix(firstLine, "processor") || !strings.Contains(firstLine, ":") { return nil, fmt.Errorf("%w: Cannot parse line: %q", ErrFileParse, firstLine) } field := strings.SplitN(firstLine, ": ", 2) v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } firstcpu := CPUInfo{Processor: uint(v)} cpuinfo := []CPUInfo{firstcpu} i := 0 for scanner.Scan() { line := scanner.Text() if !strings.Contains(line, ":") { continue } field := strings.SplitN(line, ": ", 2) switch strings.TrimSpace(field[0]) { case "processor": cpuinfo = append(cpuinfo, CPUInfo{}) // start of the next processor i++ v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } cpuinfo[i].Processor = uint(v) case "vendor", "vendor_id": cpuinfo[i].VendorID = field[1] case "cpu family": cpuinfo[i].CPUFamily = field[1] case "model": cpuinfo[i].Model = field[1] case "model name": cpuinfo[i].ModelName = field[1] case "stepping": cpuinfo[i].Stepping = field[1] case "microcode": cpuinfo[i].Microcode = field[1] case "cpu MHz": v, err := strconv.ParseFloat(field[1], 64) if err != nil { return nil, err } cpuinfo[i].CPUMHz = v case "cache size": cpuinfo[i].CacheSize = field[1] case "physical id": cpuinfo[i].PhysicalID = field[1] case "siblings": v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } cpuinfo[i].Siblings = uint(v) case "core id": cpuinfo[i].CoreID = field[1] case "cpu cores": v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } cpuinfo[i].CPUCores = uint(v) case "apicid": cpuinfo[i].APICID = field[1] case "initial apicid": cpuinfo[i].InitialAPICID = field[1] case "fpu": cpuinfo[i].FPU = field[1] case "fpu_exception": cpuinfo[i].FPUException = field[1] case "cpuid level": v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } cpuinfo[i].CPUIDLevel = uint(v) case "wp": cpuinfo[i].WP = field[1] case "flags": cpuinfo[i].Flags = strings.Fields(field[1]) case "bugs": cpuinfo[i].Bugs = strings.Fields(field[1]) case "bogomips": v, err := strconv.ParseFloat(field[1], 64) if err != nil { return nil, err } cpuinfo[i].BogoMips = v case "clflush size": v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } cpuinfo[i].CLFlushSize = uint(v) case "cache_alignment": v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } cpuinfo[i].CacheAlignment = uint(v) case "address sizes": cpuinfo[i].AddressSizes = field[1] case "power management": cpuinfo[i].PowerManagement = field[1] } } return cpuinfo, nil } func parseCPUInfoARM(info []byte) ([]CPUInfo, error) { scanner := bufio.NewScanner(bytes.NewReader(info)) firstLine := firstNonEmptyLine(scanner) match, err := regexp.MatchString("^[Pp]rocessor", firstLine) if !match || !strings.Contains(firstLine, ":") { return nil, fmt.Errorf("%w: Cannot parse line: %q: %w", ErrFileParse, firstLine, err) } field := strings.SplitN(firstLine, ": ", 2) cpuinfo := []CPUInfo{} featuresLine := "" commonCPUInfo := CPUInfo{} i := 0 if strings.TrimSpace(field[0]) == "Processor" { commonCPUInfo = CPUInfo{ModelName: field[1]} i = -1 } else { v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } firstcpu := CPUInfo{Processor: uint(v)} cpuinfo = []CPUInfo{firstcpu} } for scanner.Scan() { line := scanner.Text() if !strings.Contains(line, ":") { continue } field := strings.SplitN(line, ": ", 2) switch strings.TrimSpace(field[0]) { case "processor": cpuinfo = append(cpuinfo, commonCPUInfo) // start of the next processor i++ v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } cpuinfo[i].Processor = uint(v) case "BogoMIPS": if i == -1 { cpuinfo = append(cpuinfo, commonCPUInfo) // There is only one processor i++ cpuinfo[i].Processor = 0 } v, err := strconv.ParseFloat(field[1], 64) if err != nil { return nil, err } cpuinfo[i].BogoMips = v case "Features": featuresLine = line case "model name": cpuinfo[i].ModelName = field[1] } } fields := strings.SplitN(featuresLine, ": ", 2) for i := range cpuinfo { cpuinfo[i].Flags = strings.Fields(fields[1]) } return cpuinfo, nil } func parseCPUInfoS390X(info []byte) ([]CPUInfo, error) { scanner := bufio.NewScanner(bytes.NewReader(info)) firstLine := firstNonEmptyLine(scanner) if !strings.HasPrefix(firstLine, "vendor_id") || !strings.Contains(firstLine, ":") { return nil, fmt.Errorf("%w: Cannot parse line: %q", ErrFileParse, firstLine) } field := strings.SplitN(firstLine, ": ", 2) cpuinfo := []CPUInfo{} commonCPUInfo := CPUInfo{VendorID: field[1]} for scanner.Scan() { line := scanner.Text() if !strings.Contains(line, ":") { continue } field := strings.SplitN(line, ": ", 2) switch strings.TrimSpace(field[0]) { case "bogomips per cpu": v, err := strconv.ParseFloat(field[1], 64) if err != nil { return nil, err } commonCPUInfo.BogoMips = v case "features": commonCPUInfo.Flags = strings.Fields(field[1]) } if strings.HasPrefix(line, "processor") { match := cpuinfoS390XProcessorRegexp.FindStringSubmatch(line) if len(match) < 2 { return nil, fmt.Errorf("%w: %q", ErrFileParse, firstLine) } cpu := commonCPUInfo v, err := strconv.ParseUint(match[1], 0, 32) if err != nil { return nil, err } cpu.Processor = uint(v) cpuinfo = append(cpuinfo, cpu) } if strings.HasPrefix(line, "cpu number") { break } } i := 0 for scanner.Scan() { line := scanner.Text() if !strings.Contains(line, ":") { continue } field := strings.SplitN(line, ": ", 2) switch strings.TrimSpace(field[0]) { case "cpu number": i++ case "cpu MHz dynamic": clock := cpuinfoClockRegexp.FindString(strings.TrimSpace(field[1])) v, err := strconv.ParseFloat(clock, 64) if err != nil { return nil, err } cpuinfo[i].CPUMHz = v case "physical id": cpuinfo[i].PhysicalID = field[1] case "core id": cpuinfo[i].CoreID = field[1] case "cpu cores": v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } cpuinfo[i].CPUCores = uint(v) case "siblings": v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } cpuinfo[i].Siblings = uint(v) } } return cpuinfo, nil } func parseCPUInfoMips(info []byte) ([]CPUInfo, error) { scanner := bufio.NewScanner(bytes.NewReader(info)) // find the first "processor" line firstLine := firstNonEmptyLine(scanner) if !strings.HasPrefix(firstLine, "system type") || !strings.Contains(firstLine, ":") { return nil, fmt.Errorf("%w: %q", ErrFileParse, firstLine) } field := strings.SplitN(firstLine, ": ", 2) cpuinfo := []CPUInfo{} systemType := field[1] i := 0 for scanner.Scan() { line := scanner.Text() if !strings.Contains(line, ":") { continue } field := strings.SplitN(line, ": ", 2) switch strings.TrimSpace(field[0]) { case "processor": v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } i = int(v) cpuinfo = append(cpuinfo, CPUInfo{}) // start of the next processor cpuinfo[i].Processor = uint(v) cpuinfo[i].VendorID = systemType case "cpu model": cpuinfo[i].ModelName = field[1] case "BogoMIPS": v, err := strconv.ParseFloat(field[1], 64) if err != nil { return nil, err } cpuinfo[i].BogoMips = v } } return cpuinfo, nil } func parseCPUInfoLoong(info []byte) ([]CPUInfo, error) { scanner := bufio.NewScanner(bytes.NewReader(info)) // find the first "processor" line firstLine := firstNonEmptyLine(scanner) if !strings.HasPrefix(firstLine, "system type") || !strings.Contains(firstLine, ":") { return nil, fmt.Errorf("%w: %q", ErrFileParse, firstLine) } field := strings.SplitN(firstLine, ": ", 2) cpuinfo := []CPUInfo{} systemType := field[1] i := 0 for scanner.Scan() { line := scanner.Text() if !strings.Contains(line, ":") { continue } field := strings.SplitN(line, ": ", 2) switch strings.TrimSpace(field[0]) { case "processor": v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } i = int(v) cpuinfo = append(cpuinfo, CPUInfo{}) // start of the next processor cpuinfo[i].Processor = uint(v) cpuinfo[i].VendorID = systemType case "CPU Family": cpuinfo[i].CPUFamily = field[1] case "Model Name": cpuinfo[i].ModelName = field[1] } } return cpuinfo, nil } func parseCPUInfoPPC(info []byte) ([]CPUInfo, error) { scanner := bufio.NewScanner(bytes.NewReader(info)) firstLine := firstNonEmptyLine(scanner) if !strings.HasPrefix(firstLine, "processor") || !strings.Contains(firstLine, ":") { return nil, fmt.Errorf("%w: %q", ErrFileParse, firstLine) } field := strings.SplitN(firstLine, ": ", 2) v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } firstcpu := CPUInfo{Processor: uint(v)} cpuinfo := []CPUInfo{firstcpu} i := 0 for scanner.Scan() { line := scanner.Text() if !strings.Contains(line, ":") { continue } field := strings.SplitN(line, ": ", 2) switch strings.TrimSpace(field[0]) { case "processor": cpuinfo = append(cpuinfo, CPUInfo{}) // start of the next processor i++ v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } cpuinfo[i].Processor = uint(v) case "cpu": cpuinfo[i].VendorID = field[1] case "clock": clock := cpuinfoClockRegexp.FindString(strings.TrimSpace(field[1])) v, err := strconv.ParseFloat(clock, 64) if err != nil { return nil, err } cpuinfo[i].CPUMHz = v } } return cpuinfo, nil } func parseCPUInfoRISCV(info []byte) ([]CPUInfo, error) { scanner := bufio.NewScanner(bytes.NewReader(info)) firstLine := firstNonEmptyLine(scanner) if !strings.HasPrefix(firstLine, "processor") || !strings.Contains(firstLine, ":") { return nil, fmt.Errorf("%w: %q", ErrFileParse, firstLine) } field := strings.SplitN(firstLine, ": ", 2) v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } firstcpu := CPUInfo{Processor: uint(v)} cpuinfo := []CPUInfo{firstcpu} i := 0 for scanner.Scan() { line := scanner.Text() if !strings.Contains(line, ":") { continue } field := strings.SplitN(line, ": ", 2) switch strings.TrimSpace(field[0]) { case "processor": v, err := strconv.ParseUint(field[1], 0, 32) if err != nil { return nil, err } i = int(v) cpuinfo = append(cpuinfo, CPUInfo{}) // start of the next processor cpuinfo[i].Processor = uint(v) case "hart": cpuinfo[i].CoreID = field[1] case "isa": cpuinfo[i].ModelName = field[1] } } return cpuinfo, nil } func parseCPUInfoDummy(_ []byte) ([]CPUInfo, error) { // nolint:unused,deadcode return nil, errors.New("not implemented") } // firstNonEmptyLine advances the scanner to the first non-empty line // and returns the contents of that line. func firstNonEmptyLine(scanner *bufio.Scanner) string { for scanner.Scan() { line := scanner.Text() if strings.TrimSpace(line) != "" { return line } } return "" } golang-github-prometheus-procfs-0.14.0/cpuinfo_armx.go000066400000000000000000000013141461002754700230340ustar00rootroot00000000000000// Copyright 2020 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. //go:build linux && (arm || arm64) // +build linux // +build arm arm64 package procfs var parseCPUInfo = parseCPUInfoARM golang-github-prometheus-procfs-0.14.0/cpuinfo_loong64.go000066400000000000000000000012501461002754700233540ustar00rootroot00000000000000// Copyright 2022 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. //go:build linux // +build linux package procfs var parseCPUInfo = parseCPUInfoLoong golang-github-prometheus-procfs-0.14.0/cpuinfo_mipsx.go000066400000000000000000000013671461002754700232350ustar00rootroot00000000000000// Copyright 2020 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. //go:build linux && (mips || mipsle || mips64 || mips64le) // +build linux // +build mips mipsle mips64 mips64le package procfs var parseCPUInfo = parseCPUInfoMips golang-github-prometheus-procfs-0.14.0/cpuinfo_others.go000066400000000000000000000016211461002754700233720ustar00rootroot00000000000000// Copyright 2020 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. //go:build linux && !386 && !amd64 && !arm && !arm64 && !loong64 && !mips && !mips64 && !mips64le && !mipsle && !ppc64 && !ppc64le && !riscv64 && !s390x // +build linux,!386,!amd64,!arm,!arm64,!loong64,!mips,!mips64,!mips64le,!mipsle,!ppc64,!ppc64le,!riscv64,!s390x package procfs var parseCPUInfo = parseCPUInfoDummy golang-github-prometheus-procfs-0.14.0/cpuinfo_ppcx.go000066400000000000000000000013241461002754700230400ustar00rootroot00000000000000// Copyright 2020 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. //go:build linux && (ppc64 || ppc64le) // +build linux // +build ppc64 ppc64le package procfs var parseCPUInfo = parseCPUInfoPPC golang-github-prometheus-procfs-0.14.0/cpuinfo_riscvx.go000066400000000000000000000013261461002754700234060ustar00rootroot00000000000000// Copyright 2020 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. //go:build linux && (riscv || riscv64) // +build linux // +build riscv riscv64 package procfs var parseCPUInfo = parseCPUInfoRISCV golang-github-prometheus-procfs-0.14.0/cpuinfo_s390x.go000066400000000000000000000012501461002754700227520ustar00rootroot00000000000000// Copyright 2020 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. //go:build linux // +build linux package procfs var parseCPUInfo = parseCPUInfoS390X golang-github-prometheus-procfs-0.14.0/cpuinfo_test.go000066400000000000000000000334171461002754700230550ustar00rootroot00000000000000// 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. //go:build linux // +build linux package procfs import "testing" const ( cpuinfoArm7Legacy = ` Processor : ARMv7 Processor rev 5 (v7l) processor : 0 BogoMIPS : 2400.00 processor : 1 BogoMIPS : 2400.00 Features : swp half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpv4 idiva idivt CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xc07 CPU revision : 5 Hardware : sun8i Revision : 0000 Serial : 5400503583203c3c040e` cpuinfoArm7LegacyV1 = ` Processor : ARMv6-compatible processor rev 5 (v6l) BogoMIPS : 791.34 Features : swp half thumb fastmult vfp edsp java CPU implementer : 0x41 CPU architecture: 6TEJ CPU variant : 0x1 CPU part : 0xb36 CPU revision : 5 Hardware : IMAPX200 Revision : 0000 Serial : 0000000000000000` cpuinfoArm7 = ` processor : 0 model name : ARMv7 Processor rev 3 (v7l) BogoMIPS : 108.00 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xd08 CPU revision : 3 processor : 1 model name : ARMv7 Processor rev 3 (v7l) BogoMIPS : 108.00 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xd08 CPU revision : 3 processor : 2 model name : ARMv7 Processor rev 3 (v7l) BogoMIPS : 108.00 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xd08 CPU revision : 3 processor : 3 model name : ARMv7 Processor rev 3 (v7l) BogoMIPS : 108.00 Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32 CPU implementer : 0x41 CPU architecture: 7 CPU variant : 0x0 CPU part : 0xd08 CPU revision : 3 Hardware : BCM2835 Revision : c03111 ` cpuinfoS390x = ` vendor_id : IBM/S390 # processors : 4 bogomips per cpu: 3033.00 max thread id : 0 features : esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs te vx sie facilities : 0 1 2 3 4 6 7 8 9 10 12 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 30 31 32 33 34 35 36 37 40 41 42 43 44 45 46 47 48 49 50 51 52 53 55 57 73 74 75 76 77 80 81 82 128 129 131 cache0 : level=1 type=Data scope=Private size=128K line_size=256 associativity=8 cache1 : level=1 type=Instruction scope=Private size=96K line_size=256 associativity=6 cache2 : level=2 type=Data scope=Private size=2048K line_size=256 associativity=8 cache3 : level=2 type=Instruction scope=Private size=2048K line_size=256 associativity=8 cache4 : level=3 type=Unified scope=Shared size=65536K line_size=256 associativity=16 cache5 : level=4 type=Unified scope=Shared size=491520K line_size=256 associativity=30 processor 0: version = FF, identification = 2733E8, machine = 2964 processor 1: version = FF, identification = 2733E8, machine = 2964 processor 2: version = FF, identification = 2733E8, machine = 2964 processor 3: version = FF, identification = 2733E8, machine = 2964 cpu number : 0 physical id : 2 core id : 0 siblings : 8 cpu cores : 4 cpu MHz dynamic : 5000 cpu MHz static : 5000 cpu number : 1 physical id : 2 core id : 0 siblings : 8 cpu cores : 4 cpu MHz dynamic : 5000 cpu MHz static : 5000 cpu number : 2 physical id : 2 core id : 1 siblings : 8 cpu cores : 4 cpu MHz dynamic : 5000 cpu MHz static : 5000 cpu number : 3 physical id : 2 core id : 1 siblings : 8 cpu cores : 4 cpu MHz dynamic : 5000 cpu MHz static : 5000 ` cpuinfoMips = ` system type : UBNT_E100 machine : Unknown processor : 0 cpu model : Cavium Octeon+ V0.1 BogoMIPS : 1000.00 wait instruction : yes microsecond timers : yes tlb_entries : 64 extra interrupt vector : yes hardware watchpoint : yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb] isa : mips1 mips2 mips3 mips4 mips5 mips64r2 ASEs implemented : shadow register sets : 1 kscratch registers : 0 core : 0 VCED exceptions : not available VCEI exceptions : not available processor : 1 cpu model : Cavium Octeon+ V0.1 BogoMIPS : 1000.00 wait instruction : yes microsecond timers : yes tlb_entries : 64 extra interrupt vector : yes hardware watchpoint : yes, count: 2, address/irw mask: [0x0ffc, 0x0ffb] isa : mips1 mips2 mips3 mips4 mips5 mips64r2 ASEs implemented : shadow register sets : 1 kscratch registers : 0 core : 1 VCED exceptions : not available VCEI exceptions : not available ` cpuinfoPpc64 = ` processor : 0 cpu : POWER7 (architected), altivec supported clock : 3000.000000MHz revision : 2.1 (pvr 003f 0201) processor : 1 cpu : POWER7 (architected), altivec supported clock : 3000.000000MHz revision : 2.1 (pvr 003f 0201) processor : 2 cpu : POWER7 (architected), altivec supported clock : 3000.000000MHz revision : 2.1 (pvr 003f 0201) processor : 3 cpu : POWER7 (architected), altivec supported clock : 3000.000000MHz revision : 2.1 (pvr 003f 0201) processor : 4 cpu : POWER7 (architected), altivec supported clock : 3000.000000MHz revision : 2.1 (pvr 003f 0201) processor : 5 cpu : POWER7 (architected), altivec supported clock : 3000.000000MHz revision : 2.1 (pvr 003f 0201) timebase : 512000000 platform : pSeries model : IBM,8233-E8B machine : CHRP IBM,8233-E8B ` cpuinfoRiscv64 = ` processor : 0 hart : 0 isa : rv64imafdcsu mmu : sv48 processor : 1 hart : 1 isa : rv64imafdcsu mmu : sv48 ` cpuinfoLoong64 = ` system type : generic-loongson-machine processor : 0 package : 0 core : 0 CPU Family : Loongson-64bit Model Name : Loongson-3A5000 CPU Revision : 0x10 FPU Revision : 0x00 CPU MHz : 2500.00 BogoMIPS : 5000.00 TLB Entries : 2112 Address Sizes : 48 bits physical, 48 bits virtual ISA : loongarch32 loongarch64 Features : cpucfg lam ual fpu complex crypto lvz Hardware Watchpoint : yes, iwatch count: 0, dwatch count: 0 processor : 1 package : 0 core : 1 CPU Family : Loongson-64bit Model Name : Loongson-3A5000 CPU Revision : 0x10 FPU Revision : 0x00 CPU MHz : 2500.00 BogoMIPS : 5000.00 TLB Entries : 2112 Address Sizes : 48 bits physical, 48 bits virtual ISA : loongarch32 loongarch64 Features : cpucfg lam ual fpu complex crypto lvz Hardware Watchpoint : yes, iwatch count: 0, dwatch count: 0 processor : 2 package : 0 core : 2 CPU Family : Loongson-64bit Model Name : Loongson-3A5000 CPU Revision : 0x10 FPU Revision : 0x00 CPU MHz : 2500.00 BogoMIPS : 5000.00 TLB Entries : 2112 Address Sizes : 48 bits physical, 48 bits virtual ISA : loongarch32 loongarch64 Features : cpucfg lam ual fpu complex crypto lvz Hardware Watchpoint : yes, iwatch count: 0, dwatch count: 0 processor : 3 package : 0 core : 3 CPU Family : Loongson-64bit Model Name : Loongson-3A5000 CPU Revision : 0x10 FPU Revision : 0x00 CPU MHz : 2500.00 BogoMIPS : 5000.00 TLB Entries : 2112 Address Sizes : 48 bits physical, 48 bits virtual ISA : loongarch32 loongarch64 Features : cpucfg lam ual fpu complex crypto lvz Hardware Watchpoint : yes, iwatch count: 0, dwatch count: 0 ` ) func TestCPUInfoX86(t *testing.T) { parseCPUInfo = parseCPUInfoX86 cpuinfo, err := getProcFixtures(t).CPUInfo() if err != nil { t.Fatal(err) } if cpuinfo == nil { t.Fatal("cpuinfo is nil") } if want, have := 8, len(cpuinfo); want != have { t.Errorf("want number of processors %v, have %v", want, have) } if want, have := uint(7), cpuinfo[7].Processor; want != have { t.Errorf("want processor %v, have %v", want, have) } if want, have := "GenuineIntel", cpuinfo[0].VendorID; want != have { t.Errorf("want vendor %v, have %v", want, have) } if want, have := "6", cpuinfo[1].CPUFamily; want != have { t.Errorf("want family %v, have %v", want, have) } if want, have := "142", cpuinfo[2].Model; want != have { t.Errorf("want model %v, have %v", want, have) } if want, have := "Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz", cpuinfo[3].ModelName; want != have { t.Errorf("want model %v, have %v", want, have) } if want, have := uint(8), cpuinfo[4].Siblings; want != have { t.Errorf("want siblings %v, have %v", want, have) } if want, have := "1", cpuinfo[5].CoreID; want != have { t.Errorf("want core id %v, have %v", want, have) } if want, have := uint(4), cpuinfo[6].CPUCores; want != have { t.Errorf("want cpu cores %v, have %v", want, have) } if want, have := "vme", cpuinfo[7].Flags[1]; want != have { t.Errorf("want flag %v, have %v", want, have) } } func TestCPUInfoParseARMLegacy(t *testing.T) { cpuinfo, err := parseCPUInfoARM([]byte(cpuinfoArm7Legacy)) if err != nil || cpuinfo == nil { t.Fatalf("unable to parse arm cpu info: %v", err) } if want, have := 2, len(cpuinfo); want != have { t.Errorf("want number of processors %v, have %v", want, have) } if want, have := "ARMv7 Processor rev 5 (v7l)", cpuinfo[0].ModelName; want != have { t.Errorf("want vendor %v, have %v", want, have) } if want, have := "thumb", cpuinfo[1].Flags[2]; want != have { t.Errorf("want flag %v, have %v", want, have) } } func TestCPUInfoParseARMLegacyV1(t *testing.T) { cpuinfo, err := parseCPUInfoARM([]byte(cpuinfoArm7LegacyV1)) if err != nil || cpuinfo == nil { t.Fatalf("unable to parse arm cpu info: %v", err) } if want, have := 1, len(cpuinfo); want != have { t.Errorf("want number of processors %v, have %v", want, have) } if want, have := "ARMv6-compatible processor rev 5 (v6l)", cpuinfo[0].ModelName; want != have { t.Errorf("want vendor %v, have %v", want, have) } if want, have := "thumb", cpuinfo[0].Flags[2]; want != have { t.Errorf("want flag %v, have %v", want, have) } } func TestCPUInfoParseARM(t *testing.T) { cpuinfo, err := parseCPUInfoARM([]byte(cpuinfoArm7)) if err != nil || cpuinfo == nil { t.Fatalf("unable to parse arm cpu info: %v", err) } if want, have := 4, len(cpuinfo); want != have { t.Errorf("want number of processors %v, have %v", want, have) } if want, have := "ARMv7 Processor rev 3 (v7l)", cpuinfo[0].ModelName; want != have { t.Errorf("want vendor %v, have %v", want, have) } if want, have := "thumb", cpuinfo[1].Flags[1]; want != have { t.Errorf("want flag %v, have %v", want, have) } } func TestCPUInfoParseS390X(t *testing.T) { cpuinfo, err := parseCPUInfoS390X([]byte(cpuinfoS390x)) if err != nil || cpuinfo == nil { t.Fatalf("unable to parse s390x cpu info: %v", err) } if want, have := 4, len(cpuinfo); want != have { t.Errorf("want number of processors %v, have %v", want, have) } if want, have := "IBM/S390", cpuinfo[0].VendorID; want != have { t.Errorf("want vendor %v, have %v", want, have) } if want, have := "ldisp", cpuinfo[1].Flags[4]; want != have { t.Errorf("want flag %v, have %v", want, have) } if want, have := 5000.0, cpuinfo[2].CPUMHz; want != have { t.Errorf("want cpu MHz %v, have %v", want, have) } if want, have := uint(8), cpuinfo[3].Siblings; want != have { t.Errorf("want siblings %v, have %v", want, have) } if want, have := "1", cpuinfo[3].CoreID; want != have { t.Errorf("want core id %v, have %v", want, have) } if want, have := uint(4), cpuinfo[2].CPUCores; want != have { t.Errorf("want cpu cores %v, have %v", want, have) } if want, have := "2", cpuinfo[2].PhysicalID; want != have { t.Errorf("want physical id %v, have %v", want, have) } } func TestCPUInfoParseMips(t *testing.T) { cpuinfo, err := parseCPUInfoMips([]byte(cpuinfoMips)) if err != nil || cpuinfo == nil { t.Fatalf("unable to parse mips cpu info: %v", err) } if want, have := 2, len(cpuinfo); want != have { t.Errorf("want number of processors %v, have %v", want, have) } if want, have := 1000.00, cpuinfo[0].BogoMips; want != have { t.Errorf("want BogoMIPS %v, have %v", want, have) } if want, have := "Cavium Octeon+ V0.1", cpuinfo[1].ModelName; want != have { t.Errorf("want ModelName '%v', have '%v'", want, have) } } func TestCPUInfoParsePPC(t *testing.T) { cpuinfo, err := parseCPUInfoPPC([]byte(cpuinfoPpc64)) if err != nil || cpuinfo == nil { t.Fatalf("unable to parse ppc cpu info: %v", err) } if want, have := 6, len(cpuinfo); want != have { t.Errorf("want number of processors %v, have %v", want, have) } if want, have := 3000.00, cpuinfo[2].CPUMHz; want != have { t.Errorf("want cpu mhz %v, have %v", want, have) } } func TestCPUInfoParseRISCV64(t *testing.T) { cpuinfo, err := parseCPUInfoRISCV([]byte(cpuinfoRiscv64)) if err != nil || cpuinfo == nil { t.Fatalf("unable to parse ppc cpu info: %v", err) } if want, have := 2, len(cpuinfo); want != have { t.Errorf("want number of processors %v, have %v", want, have) } if want, have := "1", cpuinfo[1].CoreID; want != have { t.Errorf("want CoreId %v, have %v", want, have) } if want, have := "rv64imafdcsu", cpuinfo[1].ModelName; want != have { t.Errorf("want ModelName %v, have %v", want, have) } } func TestCPUInfoParseLoong64(t *testing.T) { cpuinfo, err := parseCPUInfoLoong([]byte(cpuinfoLoong64)) if err != nil || cpuinfo == nil { t.Fatalf("unable to parse loong cpu info: %v", err) } if want, have := 4, len(cpuinfo); want != have { t.Errorf("want number of processors %v, have %v", want, have) } if want, have := "Loongson-64bit", cpuinfo[1].CPUFamily; want != have { t.Errorf("want CPUFamily '%v', have '%v'", want, have) } } golang-github-prometheus-procfs-0.14.0/cpuinfo_x86.go000066400000000000000000000013141461002754700225120ustar00rootroot00000000000000// Copyright 2020 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. //go:build linux && (386 || amd64) // +build linux // +build 386 amd64 package procfs var parseCPUInfo = parseCPUInfoX86 golang-github-prometheus-procfs-0.14.0/crypto.go000066400000000000000000000070021461002754700216620ustar00rootroot00000000000000// 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. package procfs import ( "bufio" "bytes" "fmt" "io" "strings" "github.com/prometheus/procfs/internal/util" ) // Crypto holds info parsed from /proc/crypto. type Crypto struct { Alignmask *uint64 Async bool Blocksize *uint64 Chunksize *uint64 Ctxsize *uint64 Digestsize *uint64 Driver string Geniv string Internal string Ivsize *uint64 Maxauthsize *uint64 MaxKeysize *uint64 MinKeysize *uint64 Module string Name string Priority *int64 Refcnt *int64 Seedsize *uint64 Selftest string Type string Walksize *uint64 } // Crypto parses an crypto-file (/proc/crypto) and returns a slice of // structs containing the relevant info. More information available here: // https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html func (fs FS) Crypto() ([]Crypto, error) { path := fs.proc.Path("crypto") b, err := util.ReadFileNoStat(path) if err != nil { return nil, fmt.Errorf("%w: Cannot read file %v: %w", ErrFileRead, b, err) } crypto, err := parseCrypto(bytes.NewReader(b)) if err != nil { return nil, fmt.Errorf("%w: Cannot parse %v: %w", ErrFileParse, crypto, err) } return crypto, nil } // parseCrypto parses a /proc/crypto stream into Crypto elements. func parseCrypto(r io.Reader) ([]Crypto, error) { var out []Crypto s := bufio.NewScanner(r) for s.Scan() { text := s.Text() switch { case strings.HasPrefix(text, "name"): // Each crypto element begins with its name. out = append(out, Crypto{}) case text == "": continue } kv := strings.Split(text, ":") if len(kv) != 2 { return nil, fmt.Errorf("%w: Cannot parse line: %q", ErrFileParse, text) } k := strings.TrimSpace(kv[0]) v := strings.TrimSpace(kv[1]) // Parse the key/value pair into the currently focused element. c := &out[len(out)-1] if err := c.parseKV(k, v); err != nil { return nil, err } } if err := s.Err(); err != nil { return nil, err } return out, nil } // parseKV parses a key/value pair into the appropriate field of c. func (c *Crypto) parseKV(k, v string) error { vp := util.NewValueParser(v) switch k { case "async": // Interpret literal yes as true. c.Async = v == "yes" case "blocksize": c.Blocksize = vp.PUInt64() case "chunksize": c.Chunksize = vp.PUInt64() case "digestsize": c.Digestsize = vp.PUInt64() case "driver": c.Driver = v case "geniv": c.Geniv = v case "internal": c.Internal = v case "ivsize": c.Ivsize = vp.PUInt64() case "maxauthsize": c.Maxauthsize = vp.PUInt64() case "max keysize": c.MaxKeysize = vp.PUInt64() case "min keysize": c.MinKeysize = vp.PUInt64() case "module": c.Module = v case "name": c.Name = v case "priority": c.Priority = vp.PInt64() case "refcnt": c.Refcnt = vp.PInt64() case "seedsize": c.Seedsize = vp.PUInt64() case "selftest": c.Selftest = v case "type": c.Type = v case "walksize": c.Walksize = vp.PUInt64() } return vp.Err() } golang-github-prometheus-procfs-0.14.0/crypto_test.go000066400000000000000000000061771461002754700227350ustar00rootroot00000000000000// 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. package procfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestFS_Crypto(t *testing.T) { fs := getProcFixtures(t) crypto, err := fs.Crypto() if err != nil { t.Fatalf("parsing of reference-file failed entirely: %s", err) } refs := []Crypto{ { Name: "ccm(aes)", Driver: "ccm_base(ctr(aes-aesni),cbcmac(aes-aesni))", Module: "ccm", Priority: newint64(300), Refcnt: newint64(4), Selftest: "passed", Internal: "no", Type: "aead", Async: false, Blocksize: newuint64(1), Ivsize: newuint64(16), Maxauthsize: newuint64(16), Geniv: "", }, { Name: "cbcmac(aes)", Driver: "cbcmac(aes-aesni)", Module: "ccm", Priority: newint64(300), Refcnt: newint64(7), Selftest: "passed", Internal: "no", Type: "shash", Blocksize: newuint64(1), Digestsize: newuint64(16), }, { Name: "ecdh", Driver: "ecdh-generic", Module: "ecdh_generic", Priority: newint64(100), Refcnt: newint64(1), Selftest: "passed", Internal: "no", Type: "kpp", Async: true, }, { Name: "ecb(arc4)", Driver: "ecb(arc4)-generic", Module: "arc4", Priority: newint64(100), Refcnt: newint64(1), Selftest: "passed", Internal: "no", Type: "skcipher", Async: false, Blocksize: newuint64(1), MinKeysize: newuint64(1), MaxKeysize: newuint64(256), Ivsize: newuint64(0), Chunksize: newuint64(1), Walksize: newuint64(1), }, { Name: "arc4", Driver: "arc4-generic", Module: "arc4", Priority: newint64(0), Refcnt: newint64(3), Selftest: "passed", Internal: "no", Type: "cipher", Blocksize: newuint64(1), MinKeysize: newuint64(1), MaxKeysize: newuint64(256), }, { Name: "crct10dif", Driver: "crct10dif-pclmul", Module: "crct10dif_pclmul", Priority: newint64(200), Refcnt: newint64(2), Selftest: "passed", Internal: "no", Type: "shash", Blocksize: newuint64(1), Digestsize: newuint64(2), }, } if want, have := len(refs), len(crypto); want > have { t.Errorf("want at least %d parsed crypto-entries, have %d", want, have) } for index, ref := range refs { want, got := ref, crypto[index] if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected crypto entry (-want +got):\n%s", diff) } } } func newint64(i int64) *int64 { return &i } func newuint64(i uint64) *uint64 { return &i } golang-github-prometheus-procfs-0.14.0/doc.go000066400000000000000000000024021461002754700211060ustar00rootroot00000000000000// Copyright 2014 Prometheus Team // 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. // Package procfs provides functions to retrieve system, kernel and process // metrics from the pseudo-filesystem proc. // // Example: // // package main // // import ( // "fmt" // "log" // // "github.com/prometheus/procfs" // ) // // func main() { // p, err := procfs.Self() // if err != nil { // log.Fatalf("could not get process: %s", err) // } // // stat, err := p.Stat() // if err != nil { // log.Fatalf("could not get process stat: %s", err) // } // // fmt.Printf("command: %s\n", stat.Comm) // fmt.Printf("cpu time: %fs\n", stat.CPUTime()) // fmt.Printf("vsize: %dB\n", stat.VirtualMemory()) // fmt.Printf("rss: %dB\n", stat.ResidentMemory()) // } package procfs golang-github-prometheus-procfs-0.14.0/fs.go000066400000000000000000000027761461002754700207670ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "github.com/prometheus/procfs/internal/fs" ) // FS represents the pseudo-filesystem sys, which provides an interface to // kernel data structures. type FS struct { proc fs.FS isReal bool } // DefaultMountPoint is the common mount point of the proc filesystem. const DefaultMountPoint = fs.DefaultProcMountPoint // NewDefaultFS returns a new proc FS mounted under the default proc mountPoint. // It will error if the mount point directory can't be read or is a file. func NewDefaultFS() (FS, error) { return NewFS(DefaultMountPoint) } // NewFS returns a new proc FS mounted under the given proc mountPoint. It will error // if the mount point directory can't be read or is a file. func NewFS(mountPoint string) (FS, error) { fs, err := fs.NewFS(mountPoint) if err != nil { return FS{}, err } isReal, err := isRealProc(mountPoint) if err != nil { return FS{}, err } return FS{fs, isReal}, nil } golang-github-prometheus-procfs-0.14.0/fs_statfs_notype.go000066400000000000000000000015111461002754700237330ustar00rootroot00000000000000// Copyright 2018 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. //go:build !freebsd && !linux // +build !freebsd,!linux package procfs // isRealProc returns true on architectures that don't have a Type argument // in their Statfs_t struct func isRealProc(mountPoint string) (bool, error) { return true, nil } golang-github-prometheus-procfs-0.14.0/fs_statfs_type.go000066400000000000000000000020601461002754700233760ustar00rootroot00000000000000// Copyright 2018 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. //go:build freebsd || linux // +build freebsd linux package procfs import ( "syscall" ) // isRealProc determines whether supplied mountpoint is really a proc filesystem. func isRealProc(mountPoint string) (bool, error) { stat := syscall.Statfs_t{} err := syscall.Statfs(mountPoint, &stat) if err != nil { return false, err } // 0x9fa0 is PROC_SUPER_MAGIC: https://elixir.bootlin.com/linux/v6.1/source/include/uapi/linux/magic.h#L87 return stat.Type == 0x9fa0, nil } golang-github-prometheus-procfs-0.14.0/fs_test.go000066400000000000000000000022211461002754700220070ustar00rootroot00000000000000// Copyright 2018 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. package procfs import "testing" const ( procTestFixtures = "testdata/fixtures/proc" ) func TestNewFS(t *testing.T) { if _, err := NewFS("foobar"); err == nil { t.Error("want NewFS to fail for non-existing mount point") } if _, err := NewFS("procfs.go"); err == nil { t.Error("want NewFS to fail if mount point is not a directory") } getProcFixtures(t) } func getProcFixtures(t *testing.T) FS { fs, err := NewFS(procTestFixtures) if err != nil { t.Fatalf("Creating pseudo fs from getProcFixtures failed at fixtures/proc with error: %s", err) } return fs } golang-github-prometheus-procfs-0.14.0/fscache.go000066400000000000000000000367201461002754700217470ustar00rootroot00000000000000// 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. package procfs import ( "bufio" "bytes" "fmt" "io" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // Fscacheinfo represents fscache statistics. type Fscacheinfo struct { // Number of index cookies allocated IndexCookiesAllocated uint64 // data storage cookies allocated DataStorageCookiesAllocated uint64 // Number of special cookies allocated SpecialCookiesAllocated uint64 // Number of objects allocated ObjectsAllocated uint64 // Number of object allocation failures ObjectAllocationsFailure uint64 // Number of objects that reached the available state ObjectsAvailable uint64 // Number of objects that reached the dead state ObjectsDead uint64 // Number of objects that didn't have a coherency check ObjectsWithoutCoherencyCheck uint64 // Number of objects that passed a coherency check ObjectsWithCoherencyCheck uint64 // Number of objects that needed a coherency data update ObjectsNeedCoherencyCheckUpdate uint64 // Number of objects that were declared obsolete ObjectsDeclaredObsolete uint64 // Number of pages marked as being cached PagesMarkedAsBeingCached uint64 // Number of uncache page requests seen UncachePagesRequestSeen uint64 // Number of acquire cookie requests seen AcquireCookiesRequestSeen uint64 // Number of acq reqs given a NULL parent AcquireRequestsWithNullParent uint64 // Number of acq reqs rejected due to no cache available AcquireRequestsRejectedNoCacheAvailable uint64 // Number of acq reqs succeeded AcquireRequestsSucceeded uint64 // Number of acq reqs rejected due to error AcquireRequestsRejectedDueToError uint64 // Number of acq reqs failed on ENOMEM AcquireRequestsFailedDueToEnomem uint64 // Number of lookup calls made on cache backends LookupsNumber uint64 // Number of negative lookups made LookupsNegative uint64 // Number of positive lookups made LookupsPositive uint64 // Number of objects created by lookup ObjectsCreatedByLookup uint64 // Number of lookups timed out and requeued LookupsTimedOutAndRequed uint64 InvalidationsNumber uint64 InvalidationsRunning uint64 // Number of update cookie requests seen UpdateCookieRequestSeen uint64 // Number of upd reqs given a NULL parent UpdateRequestsWithNullParent uint64 // Number of upd reqs granted CPU time UpdateRequestsRunning uint64 // Number of relinquish cookie requests seen RelinquishCookiesRequestSeen uint64 // Number of rlq reqs given a NULL parent RelinquishCookiesWithNullParent uint64 // Number of rlq reqs waited on completion of creation RelinquishRequestsWaitingCompleteCreation uint64 // Relinqs rtr RelinquishRetries uint64 // Number of attribute changed requests seen AttributeChangedRequestsSeen uint64 // Number of attr changed requests queued AttributeChangedRequestsQueued uint64 // Number of attr changed rejected -ENOBUFS AttributeChangedRejectDueToEnobufs uint64 // Number of attr changed failed -ENOMEM AttributeChangedFailedDueToEnomem uint64 // Number of attr changed ops given CPU time AttributeChangedOps uint64 // Number of allocation requests seen AllocationRequestsSeen uint64 // Number of successful alloc reqs AllocationOkRequests uint64 // Number of alloc reqs that waited on lookup completion AllocationWaitingOnLookup uint64 // Number of alloc reqs rejected -ENOBUFS AllocationsRejectedDueToEnobufs uint64 // Number of alloc reqs aborted -ERESTARTSYS AllocationsAbortedDueToErestartsys uint64 // Number of alloc reqs submitted AllocationOperationsSubmitted uint64 // Number of alloc reqs waited for CPU time AllocationsWaitedForCPU uint64 // Number of alloc reqs aborted due to object death AllocationsAbortedDueToObjectDeath uint64 // Number of retrieval (read) requests seen RetrievalsReadRequests uint64 // Number of successful retr reqs RetrievalsOk uint64 // Number of retr reqs that waited on lookup completion RetrievalsWaitingLookupCompletion uint64 // Number of retr reqs returned -ENODATA RetrievalsReturnedEnodata uint64 // Number of retr reqs rejected -ENOBUFS RetrievalsRejectedDueToEnobufs uint64 // Number of retr reqs aborted -ERESTARTSYS RetrievalsAbortedDueToErestartsys uint64 // Number of retr reqs failed -ENOMEM RetrievalsFailedDueToEnomem uint64 // Number of retr reqs submitted RetrievalsRequests uint64 // Number of retr reqs waited for CPU time RetrievalsWaitingCPU uint64 // Number of retr reqs aborted due to object death RetrievalsAbortedDueToObjectDeath uint64 // Number of storage (write) requests seen StoreWriteRequests uint64 // Number of successful store reqs StoreSuccessfulRequests uint64 // Number of store reqs on a page already pending storage StoreRequestsOnPendingStorage uint64 // Number of store reqs rejected -ENOBUFS StoreRequestsRejectedDueToEnobufs uint64 // Number of store reqs failed -ENOMEM StoreRequestsFailedDueToEnomem uint64 // Number of store reqs submitted StoreRequestsSubmitted uint64 // Number of store reqs granted CPU time StoreRequestsRunning uint64 // Number of pages given store req processing time StorePagesWithRequestsProcessing uint64 // Number of store reqs deleted from tracking tree StoreRequestsDeleted uint64 // Number of store reqs over store limit StoreRequestsOverStoreLimit uint64 // Number of release reqs against pages with no pending store ReleaseRequestsAgainstPagesWithNoPendingStorage uint64 // Number of release reqs against pages stored by time lock granted ReleaseRequestsAgainstPagesStoredByTimeLockGranted uint64 // Number of release reqs ignored due to in-progress store ReleaseRequestsIgnoredDueToInProgressStore uint64 // Number of page stores cancelled due to release req PageStoresCancelledByReleaseRequests uint64 VmscanWaiting uint64 // Number of times async ops added to pending queues OpsPending uint64 // Number of times async ops given CPU time OpsRunning uint64 // Number of times async ops queued for processing OpsEnqueued uint64 // Number of async ops cancelled OpsCancelled uint64 // Number of async ops rejected due to object lookup/create failure OpsRejected uint64 // Number of async ops initialised OpsInitialised uint64 // Number of async ops queued for deferred release OpsDeferred uint64 // Number of async ops released (should equal ini=N when idle) OpsReleased uint64 // Number of deferred-release async ops garbage collected OpsGarbageCollected uint64 // Number of in-progress alloc_object() cache ops CacheopAllocationsinProgress uint64 // Number of in-progress lookup_object() cache ops CacheopLookupObjectInProgress uint64 // Number of in-progress lookup_complete() cache ops CacheopLookupCompleteInPorgress uint64 // Number of in-progress grab_object() cache ops CacheopGrabObjectInProgress uint64 CacheopInvalidations uint64 // Number of in-progress update_object() cache ops CacheopUpdateObjectInProgress uint64 // Number of in-progress drop_object() cache ops CacheopDropObjectInProgress uint64 // Number of in-progress put_object() cache ops CacheopPutObjectInProgress uint64 // Number of in-progress attr_changed() cache ops CacheopAttributeChangeInProgress uint64 // Number of in-progress sync_cache() cache ops CacheopSyncCacheInProgress uint64 // Number of in-progress read_or_alloc_page() cache ops CacheopReadOrAllocPageInProgress uint64 // Number of in-progress read_or_alloc_pages() cache ops CacheopReadOrAllocPagesInProgress uint64 // Number of in-progress allocate_page() cache ops CacheopAllocatePageInProgress uint64 // Number of in-progress allocate_pages() cache ops CacheopAllocatePagesInProgress uint64 // Number of in-progress write_page() cache ops CacheopWritePagesInProgress uint64 // Number of in-progress uncache_page() cache ops CacheopUncachePagesInProgress uint64 // Number of in-progress dissociate_pages() cache ops CacheopDissociatePagesInProgress uint64 // Number of object lookups/creations rejected due to lack of space CacheevLookupsAndCreationsRejectedLackSpace uint64 // Number of stale objects deleted CacheevStaleObjectsDeleted uint64 // Number of objects retired when relinquished CacheevRetiredWhenReliquished uint64 // Number of objects culled CacheevObjectsCulled uint64 } // Fscacheinfo returns information about current fscache statistics. // See https://www.kernel.org/doc/Documentation/filesystems/caching/fscache.txt func (fs FS) Fscacheinfo() (Fscacheinfo, error) { b, err := util.ReadFileNoStat(fs.proc.Path("fs/fscache/stats")) if err != nil { return Fscacheinfo{}, err } m, err := parseFscacheinfo(bytes.NewReader(b)) if err != nil { return Fscacheinfo{}, fmt.Errorf("%w: Cannot parse %v: %w", ErrFileParse, m, err) } return *m, nil } func setFSCacheFields(fields []string, setFields ...*uint64) error { var err error if len(fields) < len(setFields) { return fmt.Errorf("%w: Expected %d, but got %d: %w", ErrFileParse, len(setFields), len(fields), err) } for i := range setFields { *setFields[i], err = strconv.ParseUint(strings.Split(fields[i], "=")[1], 0, 64) if err != nil { return err } } return nil } func parseFscacheinfo(r io.Reader) (*Fscacheinfo, error) { var m Fscacheinfo s := bufio.NewScanner(r) for s.Scan() { fields := strings.Fields(s.Text()) if len(fields) < 2 { return nil, fmt.Errorf("%w: malformed Fscacheinfo line: %q", ErrFileParse, s.Text()) } switch fields[0] { case "Cookies:": err := setFSCacheFields(fields[1:], &m.IndexCookiesAllocated, &m.DataStorageCookiesAllocated, &m.SpecialCookiesAllocated) if err != nil { return &m, err } case "Objects:": err := setFSCacheFields(fields[1:], &m.ObjectsAllocated, &m.ObjectAllocationsFailure, &m.ObjectsAvailable, &m.ObjectsDead) if err != nil { return &m, err } case "ChkAux": err := setFSCacheFields(fields[2:], &m.ObjectsWithoutCoherencyCheck, &m.ObjectsWithCoherencyCheck, &m.ObjectsNeedCoherencyCheckUpdate, &m.ObjectsDeclaredObsolete) if err != nil { return &m, err } case "Pages": err := setFSCacheFields(fields[2:], &m.PagesMarkedAsBeingCached, &m.UncachePagesRequestSeen) if err != nil { return &m, err } case "Acquire:": err := setFSCacheFields(fields[1:], &m.AcquireCookiesRequestSeen, &m.AcquireRequestsWithNullParent, &m.AcquireRequestsRejectedNoCacheAvailable, &m.AcquireRequestsSucceeded, &m.AcquireRequestsRejectedDueToError, &m.AcquireRequestsFailedDueToEnomem) if err != nil { return &m, err } case "Lookups:": err := setFSCacheFields(fields[1:], &m.LookupsNumber, &m.LookupsNegative, &m.LookupsPositive, &m.ObjectsCreatedByLookup, &m.LookupsTimedOutAndRequed) if err != nil { return &m, err } case "Invals": err := setFSCacheFields(fields[2:], &m.InvalidationsNumber, &m.InvalidationsRunning) if err != nil { return &m, err } case "Updates:": err := setFSCacheFields(fields[1:], &m.UpdateCookieRequestSeen, &m.UpdateRequestsWithNullParent, &m.UpdateRequestsRunning) if err != nil { return &m, err } case "Relinqs:": err := setFSCacheFields(fields[1:], &m.RelinquishCookiesRequestSeen, &m.RelinquishCookiesWithNullParent, &m.RelinquishRequestsWaitingCompleteCreation, &m.RelinquishRetries) if err != nil { return &m, err } case "AttrChg:": err := setFSCacheFields(fields[1:], &m.AttributeChangedRequestsSeen, &m.AttributeChangedRequestsQueued, &m.AttributeChangedRejectDueToEnobufs, &m.AttributeChangedFailedDueToEnomem, &m.AttributeChangedOps) if err != nil { return &m, err } case "Allocs": if strings.Split(fields[2], "=")[0] == "n" { err := setFSCacheFields(fields[2:], &m.AllocationRequestsSeen, &m.AllocationOkRequests, &m.AllocationWaitingOnLookup, &m.AllocationsRejectedDueToEnobufs, &m.AllocationsAbortedDueToErestartsys) if err != nil { return &m, err } } else { err := setFSCacheFields(fields[2:], &m.AllocationOperationsSubmitted, &m.AllocationsWaitedForCPU, &m.AllocationsAbortedDueToObjectDeath) if err != nil { return &m, err } } case "Retrvls:": if strings.Split(fields[1], "=")[0] == "n" { err := setFSCacheFields(fields[1:], &m.RetrievalsReadRequests, &m.RetrievalsOk, &m.RetrievalsWaitingLookupCompletion, &m.RetrievalsReturnedEnodata, &m.RetrievalsRejectedDueToEnobufs, &m.RetrievalsAbortedDueToErestartsys, &m.RetrievalsFailedDueToEnomem) if err != nil { return &m, err } } else { err := setFSCacheFields(fields[1:], &m.RetrievalsRequests, &m.RetrievalsWaitingCPU, &m.RetrievalsAbortedDueToObjectDeath) if err != nil { return &m, err } } case "Stores": if strings.Split(fields[2], "=")[0] == "n" { err := setFSCacheFields(fields[2:], &m.StoreWriteRequests, &m.StoreSuccessfulRequests, &m.StoreRequestsOnPendingStorage, &m.StoreRequestsRejectedDueToEnobufs, &m.StoreRequestsFailedDueToEnomem) if err != nil { return &m, err } } else { err := setFSCacheFields(fields[2:], &m.StoreRequestsSubmitted, &m.StoreRequestsRunning, &m.StorePagesWithRequestsProcessing, &m.StoreRequestsDeleted, &m.StoreRequestsOverStoreLimit) if err != nil { return &m, err } } case "VmScan": err := setFSCacheFields(fields[2:], &m.ReleaseRequestsAgainstPagesWithNoPendingStorage, &m.ReleaseRequestsAgainstPagesStoredByTimeLockGranted, &m.ReleaseRequestsIgnoredDueToInProgressStore, &m.PageStoresCancelledByReleaseRequests, &m.VmscanWaiting) if err != nil { return &m, err } case "Ops": if strings.Split(fields[2], "=")[0] == "pend" { err := setFSCacheFields(fields[2:], &m.OpsPending, &m.OpsRunning, &m.OpsEnqueued, &m.OpsCancelled, &m.OpsRejected) if err != nil { return &m, err } } else { err := setFSCacheFields(fields[2:], &m.OpsInitialised, &m.OpsDeferred, &m.OpsReleased, &m.OpsGarbageCollected) if err != nil { return &m, err } } case "CacheOp:": if strings.Split(fields[1], "=")[0] == "alo" { err := setFSCacheFields(fields[1:], &m.CacheopAllocationsinProgress, &m.CacheopLookupObjectInProgress, &m.CacheopLookupCompleteInPorgress, &m.CacheopGrabObjectInProgress) if err != nil { return &m, err } } else if strings.Split(fields[1], "=")[0] == "inv" { err := setFSCacheFields(fields[1:], &m.CacheopInvalidations, &m.CacheopUpdateObjectInProgress, &m.CacheopDropObjectInProgress, &m.CacheopPutObjectInProgress, &m.CacheopAttributeChangeInProgress, &m.CacheopSyncCacheInProgress) if err != nil { return &m, err } } else { err := setFSCacheFields(fields[1:], &m.CacheopReadOrAllocPageInProgress, &m.CacheopReadOrAllocPagesInProgress, &m.CacheopAllocatePageInProgress, &m.CacheopAllocatePagesInProgress, &m.CacheopWritePagesInProgress, &m.CacheopUncachePagesInProgress, &m.CacheopDissociatePagesInProgress) if err != nil { return &m, err } } case "CacheEv:": err := setFSCacheFields(fields[1:], &m.CacheevLookupsAndCreationsRejectedLackSpace, &m.CacheevStaleObjectsDeleted, &m.CacheevRetiredWhenReliquished, &m.CacheevObjectsCulled) if err != nil { return &m, err } } } return &m, nil } golang-github-prometheus-procfs-0.14.0/fscache_test.go000066400000000000000000000153311461002754700230010ustar00rootroot00000000000000// 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. package procfs import ( "reflect" "testing" ) func TestFscacheinfo(t *testing.T) { expected := Fscacheinfo{ IndexCookiesAllocated: 3, DataStorageCookiesAllocated: 67877, SpecialCookiesAllocated: 0, ObjectsAllocated: 67473, ObjectAllocationsFailure: 0, ObjectsAvailable: 67473, ObjectsDead: 388, ObjectsWithoutCoherencyCheck: 12, ObjectsWithCoherencyCheck: 33, ObjectsNeedCoherencyCheckUpdate: 44, ObjectsDeclaredObsolete: 55, PagesMarkedAsBeingCached: 547164, UncachePagesRequestSeen: 364577, AcquireCookiesRequestSeen: 67880, AcquireRequestsWithNullParent: 98, AcquireRequestsRejectedNoCacheAvailable: 25, AcquireRequestsSucceeded: 67780, AcquireRequestsRejectedDueToError: 39, AcquireRequestsFailedDueToEnomem: 26, LookupsNumber: 67473, LookupsNegative: 67470, LookupsPositive: 58, ObjectsCreatedByLookup: 67473, LookupsTimedOutAndRequed: 85, InvalidationsNumber: 14, InvalidationsRunning: 13, UpdateCookieRequestSeen: 7, UpdateRequestsWithNullParent: 3, UpdateRequestsRunning: 8, RelinquishCookiesRequestSeen: 394, RelinquishCookiesWithNullParent: 1, RelinquishRequestsWaitingCompleteCreation: 2, RelinquishRetries: 3, AttributeChangedRequestsSeen: 6, AttributeChangedRequestsQueued: 5, AttributeChangedRejectDueToEnobufs: 4, AttributeChangedFailedDueToEnomem: 3, AttributeChangedOps: 2, AllocationRequestsSeen: 20, AllocationOkRequests: 19, AllocationWaitingOnLookup: 18, AllocationsRejectedDueToEnobufs: 17, AllocationsAbortedDueToErestartsys: 16, AllocationOperationsSubmitted: 15, AllocationsWaitedForCPU: 14, AllocationsAbortedDueToObjectDeath: 13, RetrievalsReadRequests: 151959, RetrievalsOk: 82823, RetrievalsWaitingLookupCompletion: 23467, RetrievalsReturnedEnodata: 69136, RetrievalsRejectedDueToEnobufs: 15, RetrievalsAbortedDueToErestartsys: 69, RetrievalsFailedDueToEnomem: 43, RetrievalsRequests: 151959, RetrievalsWaitingCPU: 42747, RetrievalsAbortedDueToObjectDeath: 44, StoreWriteRequests: 225565, StoreSuccessfulRequests: 225565, StoreRequestsOnPendingStorage: 12, StoreRequestsRejectedDueToEnobufs: 13, StoreRequestsFailedDueToEnomem: 14, StoreRequestsSubmitted: 69156, StoreRequestsRunning: 294721, StorePagesWithRequestsProcessing: 225565, StoreRequestsDeleted: 225565, StoreRequestsOverStoreLimit: 43, ReleaseRequestsAgainstPagesWithNoPendingStorage: 364512, ReleaseRequestsAgainstPagesStoredByTimeLockGranted: 2, ReleaseRequestsIgnoredDueToInProgressStore: 43, PageStoresCancelledByReleaseRequests: 12, VmscanWaiting: 66, OpsPending: 42753, OpsRunning: 221129, OpsEnqueued: 628798, OpsCancelled: 11, OpsRejected: 88, OpsInitialised: 377538, OpsDeferred: 27, OpsReleased: 377538, OpsGarbageCollected: 37, CacheopAllocationsinProgress: 1, CacheopLookupObjectInProgress: 2, CacheopLookupCompleteInPorgress: 3, CacheopGrabObjectInProgress: 4, CacheopInvalidations: 5, CacheopUpdateObjectInProgress: 6, CacheopDropObjectInProgress: 7, CacheopPutObjectInProgress: 8, CacheopAttributeChangeInProgress: 9, CacheopSyncCacheInProgress: 10, CacheopReadOrAllocPageInProgress: 11, CacheopReadOrAllocPagesInProgress: 12, CacheopAllocatePageInProgress: 13, CacheopAllocatePagesInProgress: 14, CacheopWritePagesInProgress: 15, CacheopUncachePagesInProgress: 16, CacheopDissociatePagesInProgress: 17, CacheevLookupsAndCreationsRejectedLackSpace: 18, CacheevStaleObjectsDeleted: 19, CacheevRetiredWhenReliquished: 20, CacheevObjectsCulled: 21, } have, err := getProcFixtures(t).Fscacheinfo() if err != nil { t.Fatal(err) } if !reflect.DeepEqual(have, expected) { t.Logf("have: %+v", have) t.Logf("expected: %+v", expected) t.Errorf("structs are not equal") } } golang-github-prometheus-procfs-0.14.0/go.mod000066400000000000000000000002171461002754700211220ustar00rootroot00000000000000module github.com/prometheus/procfs go 1.21 require ( github.com/google/go-cmp v0.6.0 golang.org/x/sync v0.7.0 golang.org/x/sys v0.19.0 ) golang-github-prometheus-procfs-0.14.0/go.sum000066400000000000000000000007311461002754700211500ustar00rootroot00000000000000github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang-github-prometheus-procfs-0.14.0/internal/000077500000000000000000000000001461002754700216305ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/internal/fs/000077500000000000000000000000001461002754700222405ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/internal/fs/fs.go000066400000000000000000000033141461002754700232000ustar00rootroot00000000000000// 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. package fs import ( "fmt" "os" "path/filepath" ) const ( // DefaultProcMountPoint is the common mount point of the proc filesystem. DefaultProcMountPoint = "/proc" // DefaultSysMountPoint is the common mount point of the sys filesystem. DefaultSysMountPoint = "/sys" // DefaultConfigfsMountPoint is the common mount point of the configfs. DefaultConfigfsMountPoint = "/sys/kernel/config" ) // FS represents a pseudo-filesystem, normally /proc or /sys, which provides an // interface to kernel data structures. type FS string // NewFS returns a new FS mounted under the given mountPoint. It will error // if the mount point can't be read. func NewFS(mountPoint string) (FS, error) { info, err := os.Stat(mountPoint) if err != nil { return "", fmt.Errorf("could not read %q: %w", mountPoint, err) } if !info.IsDir() { return "", fmt.Errorf("mount point %q is not a directory", mountPoint) } return FS(mountPoint), nil } // Path appends the given path elements to the filesystem path, adding separators // as necessary. func (fs FS) Path(p ...string) string { return filepath.Join(append([]string{string(fs)}, p...)...) } golang-github-prometheus-procfs-0.14.0/internal/fs/fs_test.go000066400000000000000000000020241461002754700242340ustar00rootroot00000000000000// 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. package fs import "testing" const ( sysTestFixtures = "testdata/fixtures/sys" ) func TestNewFS(t *testing.T) { if _, err := NewFS("foobar"); err == nil { t.Error("want NewFS to fail for non-existing mount point") } if _, err := NewFS("doc.go"); err == nil { t.Error("want NewFS to fail if mount point is not a directory") } if _, err := NewFS(sysTestFixtures); err != nil { t.Error("want NewFS to succeed if mount point exists") } } golang-github-prometheus-procfs-0.14.0/internal/fs/testdata/000077500000000000000000000000001461002754700240515ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/internal/fs/testdata/fixtures000077700000000000000000000000001461002754700321062../../../testdata/fixturesustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/internal/util/000077500000000000000000000000001461002754700226055ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/internal/util/parse.go000066400000000000000000000050541461002754700242520ustar00rootroot00000000000000// Copyright 2018 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. package util import ( "os" "strconv" "strings" ) // ParseUint32s parses a slice of strings into a slice of uint32s. func ParseUint32s(ss []string) ([]uint32, error) { us := make([]uint32, 0, len(ss)) for _, s := range ss { u, err := strconv.ParseUint(s, 10, 32) if err != nil { return nil, err } us = append(us, uint32(u)) } return us, nil } // ParseUint64s parses a slice of strings into a slice of uint64s. func ParseUint64s(ss []string) ([]uint64, error) { us := make([]uint64, 0, len(ss)) for _, s := range ss { u, err := strconv.ParseUint(s, 10, 64) if err != nil { return nil, err } us = append(us, u) } return us, nil } // ParsePInt64s parses a slice of strings into a slice of int64 pointers. func ParsePInt64s(ss []string) ([]*int64, error) { us := make([]*int64, 0, len(ss)) for _, s := range ss { u, err := strconv.ParseInt(s, 10, 64) if err != nil { return nil, err } us = append(us, &u) } return us, nil } // Parses a uint64 from given hex in string. func ParseHexUint64s(ss []string) ([]*uint64, error) { us := make([]*uint64, 0, len(ss)) for _, s := range ss { u, err := strconv.ParseUint(s, 16, 64) if err != nil { return nil, err } us = append(us, &u) } return us, nil } // ReadUintFromFile reads a file and attempts to parse a uint64 from it. func ReadUintFromFile(path string) (uint64, error) { data, err := os.ReadFile(path) if err != nil { return 0, err } return strconv.ParseUint(strings.TrimSpace(string(data)), 10, 64) } // ReadIntFromFile reads a file and attempts to parse a int64 from it. func ReadIntFromFile(path string) (int64, error) { data, err := os.ReadFile(path) if err != nil { return 0, err } return strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64) } // ParseBool parses a string into a boolean pointer. func ParseBool(b string) *bool { var truth bool switch b { case "enabled": truth = true case "disabled": truth = false default: return nil } return &truth } golang-github-prometheus-procfs-0.14.0/internal/util/readfile.go000066400000000000000000000022541461002754700247120ustar00rootroot00000000000000// 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. package util import ( "io" "os" ) // ReadFileNoStat uses io.ReadAll to read contents of entire file. // This is similar to os.ReadFile but without the call to os.Stat, because // many files in /proc and /sys report incorrect file sizes (either 0 or 4096). // Reads a max file size of 1024kB. For files larger than this, a scanner // should be used. func ReadFileNoStat(filename string) ([]byte, error) { const maxBufferSize = 1024 * 1024 f, err := os.Open(filename) if err != nil { return nil, err } defer f.Close() reader := io.LimitReader(f, maxBufferSize) return io.ReadAll(reader) } golang-github-prometheus-procfs-0.14.0/internal/util/sysreadfile.go000066400000000000000000000027611461002754700254540ustar00rootroot00000000000000// Copyright 2018 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. //go:build (linux || darwin) && !appengine // +build linux darwin // +build !appengine package util import ( "bytes" "os" "syscall" ) // SysReadFile is a simplified os.ReadFile that invokes syscall.Read directly. // https://github.com/prometheus/node_exporter/pull/728/files // // Note that this function will not read files larger than 128 bytes. func SysReadFile(file string) (string, error) { f, err := os.Open(file) if err != nil { return "", err } defer f.Close() // On some machines, hwmon drivers are broken and return EAGAIN. This causes // Go's os.ReadFile implementation to poll forever. // // Since we either want to read data or bail immediately, do the simplest // possible read using syscall directly. const sysFileBufferSize = 128 b := make([]byte, sysFileBufferSize) n, err := syscall.Read(int(f.Fd()), b) if err != nil { return "", err } return string(bytes.TrimSpace(b[:n])), nil } golang-github-prometheus-procfs-0.14.0/internal/util/sysreadfile_compat.go000066400000000000000000000017231461002754700270140ustar00rootroot00000000000000// 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. //go:build (linux && appengine) || (!linux && !darwin) // +build linux,appengine !linux,!darwin package util import ( "fmt" ) // SysReadFile is here implemented as a noop for builds that do not support // the read syscall. For example Windows, or Linux on Google App Engine. func SysReadFile(file string) (string, error) { return "", fmt.Errorf("not supported on this platform") } golang-github-prometheus-procfs-0.14.0/internal/util/valueparser.go000066400000000000000000000046141461002754700254720ustar00rootroot00000000000000// 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. package util import ( "strconv" ) // TODO(mdlayher): util packages are an anti-pattern and this should be moved // somewhere else that is more focused in the future. // A ValueParser enables parsing a single string into a variety of data types // in a concise and safe way. The Err method must be invoked after invoking // any other methods to ensure a value was successfully parsed. type ValueParser struct { v string err error } // NewValueParser creates a ValueParser using the input string. func NewValueParser(v string) *ValueParser { return &ValueParser{v: v} } // Int interprets the underlying value as an int and returns that value. func (vp *ValueParser) Int() int { return int(vp.int64()) } // PInt64 interprets the underlying value as an int64 and returns a pointer to // that value. func (vp *ValueParser) PInt64() *int64 { if vp.err != nil { return nil } v := vp.int64() return &v } // int64 interprets the underlying value as an int64 and returns that value. // TODO: export if/when necessary. func (vp *ValueParser) int64() int64 { if vp.err != nil { return 0 } // A base value of zero makes ParseInt infer the correct base using the // string's prefix, if any. const base = 0 v, err := strconv.ParseInt(vp.v, base, 64) if err != nil { vp.err = err return 0 } return v } // PUInt64 interprets the underlying value as an uint64 and returns a pointer to // that value. func (vp *ValueParser) PUInt64() *uint64 { if vp.err != nil { return nil } // A base value of zero makes ParseInt infer the correct base using the // string's prefix, if any. const base = 0 v, err := strconv.ParseUint(vp.v, base, 64) if err != nil { vp.err = err return nil } return &v } // Err returns the last error, if any, encountered by the ValueParser. func (vp *ValueParser) Err() error { return vp.err } golang-github-prometheus-procfs-0.14.0/internal/util/valueparser_test.go000066400000000000000000000060751461002754700265340ustar00rootroot00000000000000// 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. package util_test import ( "testing" "github.com/google/go-cmp/cmp" "github.com/prometheus/procfs/internal/util" ) func TestValueParser(t *testing.T) { tests := []struct { name string v string ok bool fn func(t *testing.T, vp *util.ValueParser) }{ { name: "ok Int", v: "10", ok: true, fn: func(t *testing.T, vp *util.ValueParser) { want := 10 got := vp.Int() if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected integer (-want +got):\n%s", diff) } }, }, { name: "bad PInt64", v: "hello", fn: func(_ *testing.T, vp *util.ValueParser) { _ = vp.PInt64() }, }, { name: "bad hex PInt64", v: "0xhello", fn: func(_ *testing.T, vp *util.ValueParser) { _ = vp.PInt64() }, }, { name: "ok PInt64", v: "1", ok: true, fn: func(t *testing.T, vp *util.ValueParser) { want := int64(1) got := vp.PInt64() if diff := cmp.Diff(&want, got); diff != "" { t.Fatalf("unexpected integer (-want +got):\n%s", diff) } }, }, { name: "ok hex PInt64", v: "0xff", ok: true, fn: func(t *testing.T, vp *util.ValueParser) { want := int64(255) got := vp.PInt64() if diff := cmp.Diff(&want, got); diff != "" { t.Fatalf("unexpected integer (-want +got):\n%s", diff) } }, }, { name: "bad PUInt64", v: "-42", fn: func(_ *testing.T, vp *util.ValueParser) { _ = vp.PUInt64() }, }, { name: "bad hex PUInt64", v: "0xhello", fn: func(_ *testing.T, vp *util.ValueParser) { _ = vp.PUInt64() }, }, { name: "ok PUInt64", v: "1", ok: true, fn: func(t *testing.T, vp *util.ValueParser) { want := uint64(1) got := vp.PUInt64() if diff := cmp.Diff(&want, got); diff != "" { t.Fatalf("unexpected integer (-want +got):\n%s", diff) } }, }, { name: "ok hex PUInt64", v: "0xff", ok: true, fn: func(t *testing.T, vp *util.ValueParser) { want := uint64(255) got := vp.PUInt64() if diff := cmp.Diff(&want, got); diff != "" { t.Fatalf("unexpected integer (-want +got):\n%s", diff) } }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { vp := util.NewValueParser(tt.v) tt.fn(t, vp) err := vp.Err() if err != nil { if tt.ok { t.Fatalf("unexpected error: %v", err) } t.Logf("OK err: %v", err) return } if !tt.ok { t.Fatal("expected an error, but none occurred") } }) } } golang-github-prometheus-procfs-0.14.0/ipvs.go000066400000000000000000000137451461002754700213360ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "bufio" "bytes" "encoding/hex" "errors" "fmt" "io" "net" "os" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // IPVSStats holds IPVS statistics, as exposed by the kernel in `/proc/net/ip_vs_stats`. type IPVSStats struct { // Total count of connections. Connections uint64 // Total incoming packages processed. IncomingPackets uint64 // Total outgoing packages processed. OutgoingPackets uint64 // Total incoming traffic. IncomingBytes uint64 // Total outgoing traffic. OutgoingBytes uint64 } // IPVSBackendStatus holds current metrics of one virtual / real address pair. type IPVSBackendStatus struct { // The local (virtual) IP address. LocalAddress net.IP // The remote (real) IP address. RemoteAddress net.IP // The local (virtual) port. LocalPort uint16 // The remote (real) port. RemotePort uint16 // The local firewall mark LocalMark string // The transport protocol (TCP, UDP). Proto string // The current number of active connections for this virtual/real address pair. ActiveConn uint64 // The current number of inactive connections for this virtual/real address pair. InactConn uint64 // The current weight of this virtual/real address pair. Weight uint64 } // IPVSStats reads the IPVS statistics from the specified `proc` filesystem. func (fs FS) IPVSStats() (IPVSStats, error) { data, err := util.ReadFileNoStat(fs.proc.Path("net/ip_vs_stats")) if err != nil { return IPVSStats{}, err } return parseIPVSStats(bytes.NewReader(data)) } // parseIPVSStats performs the actual parsing of `ip_vs_stats`. func parseIPVSStats(r io.Reader) (IPVSStats, error) { var ( statContent []byte statLines []string statFields []string stats IPVSStats ) statContent, err := io.ReadAll(r) if err != nil { return IPVSStats{}, err } statLines = strings.SplitN(string(statContent), "\n", 4) if len(statLines) != 4 { return IPVSStats{}, errors.New("ip_vs_stats corrupt: too short") } statFields = strings.Fields(statLines[2]) if len(statFields) != 5 { return IPVSStats{}, errors.New("ip_vs_stats corrupt: unexpected number of fields") } stats.Connections, err = strconv.ParseUint(statFields[0], 16, 64) if err != nil { return IPVSStats{}, err } stats.IncomingPackets, err = strconv.ParseUint(statFields[1], 16, 64) if err != nil { return IPVSStats{}, err } stats.OutgoingPackets, err = strconv.ParseUint(statFields[2], 16, 64) if err != nil { return IPVSStats{}, err } stats.IncomingBytes, err = strconv.ParseUint(statFields[3], 16, 64) if err != nil { return IPVSStats{}, err } stats.OutgoingBytes, err = strconv.ParseUint(statFields[4], 16, 64) if err != nil { return IPVSStats{}, err } return stats, nil } // IPVSBackendStatus reads and returns the status of all (virtual,real) server pairs from the specified `proc` filesystem. func (fs FS) IPVSBackendStatus() ([]IPVSBackendStatus, error) { file, err := os.Open(fs.proc.Path("net/ip_vs")) if err != nil { return nil, err } defer file.Close() return parseIPVSBackendStatus(file) } func parseIPVSBackendStatus(file io.Reader) ([]IPVSBackendStatus, error) { var ( status []IPVSBackendStatus scanner = bufio.NewScanner(file) proto string localMark string localAddress net.IP localPort uint16 err error ) for scanner.Scan() { fields := strings.Fields(scanner.Text()) if len(fields) == 0 { continue } switch { case fields[0] == "IP" || fields[0] == "Prot" || fields[1] == "RemoteAddress:Port": continue case fields[0] == "TCP" || fields[0] == "UDP": if len(fields) < 2 { continue } proto = fields[0] localMark = "" localAddress, localPort, err = parseIPPort(fields[1]) if err != nil { return nil, err } case fields[0] == "FWM": if len(fields) < 2 { continue } proto = fields[0] localMark = fields[1] localAddress = nil localPort = 0 case fields[0] == "->": if len(fields) < 6 { continue } remoteAddress, remotePort, err := parseIPPort(fields[1]) if err != nil { return nil, err } weight, err := strconv.ParseUint(fields[3], 10, 64) if err != nil { return nil, err } activeConn, err := strconv.ParseUint(fields[4], 10, 64) if err != nil { return nil, err } inactConn, err := strconv.ParseUint(fields[5], 10, 64) if err != nil { return nil, err } status = append(status, IPVSBackendStatus{ LocalAddress: localAddress, LocalPort: localPort, LocalMark: localMark, RemoteAddress: remoteAddress, RemotePort: remotePort, Proto: proto, Weight: weight, ActiveConn: activeConn, InactConn: inactConn, }) } } return status, nil } func parseIPPort(s string) (net.IP, uint16, error) { var ( ip net.IP err error ) switch len(s) { case 13: ip, err = hex.DecodeString(s[0:8]) if err != nil { return nil, 0, err } case 46: ip = net.ParseIP(s[1:40]) if ip == nil { return nil, 0, fmt.Errorf("%w: Invalid IPv6 addr %s: %w", ErrFileParse, s[1:40], err) } default: return nil, 0, fmt.Errorf("%w: Unexpected IP:Port %s: %w", ErrFileParse, s, err) } portString := s[len(s)-4:] if len(portString) != 4 { return nil, 0, fmt.Errorf("%w: Unexpected port string format %s: %w", ErrFileParse, portString, err) } port, err := strconv.ParseUint(portString, 16, 16) if err != nil { return nil, 0, err } return ip, uint16(port), nil } golang-github-prometheus-procfs-0.14.0/ipvs_test.go000066400000000000000000000151021461002754700223620ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "net" "testing" ) var ( expectedIPVSStats = IPVSStats{ Connections: 23765872, IncomingPackets: 3811989221, OutgoingPackets: 0, IncomingBytes: 89991519156915, OutgoingBytes: 0, } expectedIPVSBackendStatuses = []IPVSBackendStatus{ { LocalAddress: net.ParseIP("192.168.0.22"), LocalPort: 3306, RemoteAddress: net.ParseIP("192.168.82.22"), RemotePort: 3306, Proto: "TCP", Weight: 100, ActiveConn: 248, InactConn: 2, }, { LocalAddress: net.ParseIP("192.168.0.22"), LocalPort: 3306, RemoteAddress: net.ParseIP("192.168.83.24"), RemotePort: 3306, Proto: "TCP", Weight: 100, ActiveConn: 248, InactConn: 2, }, { LocalAddress: net.ParseIP("192.168.0.22"), LocalPort: 3306, RemoteAddress: net.ParseIP("192.168.83.21"), RemotePort: 3306, Proto: "TCP", Weight: 100, ActiveConn: 248, InactConn: 1, }, { LocalAddress: net.ParseIP("192.168.0.57"), LocalPort: 3306, RemoteAddress: net.ParseIP("192.168.84.22"), RemotePort: 3306, Proto: "TCP", Weight: 0, ActiveConn: 0, InactConn: 0, }, { LocalAddress: net.ParseIP("192.168.0.57"), LocalPort: 3306, RemoteAddress: net.ParseIP("192.168.82.21"), RemotePort: 3306, Proto: "TCP", Weight: 100, ActiveConn: 1499, InactConn: 0, }, { LocalAddress: net.ParseIP("192.168.0.57"), LocalPort: 3306, RemoteAddress: net.ParseIP("192.168.50.21"), RemotePort: 3306, Proto: "TCP", Weight: 100, ActiveConn: 1498, InactConn: 0, }, { LocalAddress: net.ParseIP("192.168.0.55"), LocalPort: 3306, RemoteAddress: net.ParseIP("192.168.50.26"), RemotePort: 3306, Proto: "TCP", Weight: 0, ActiveConn: 0, InactConn: 0, }, { LocalAddress: net.ParseIP("192.168.0.55"), LocalPort: 3306, RemoteAddress: net.ParseIP("192.168.49.32"), RemotePort: 3306, Proto: "TCP", Weight: 100, ActiveConn: 0, InactConn: 0, }, { LocalAddress: net.ParseIP("2620::1"), LocalPort: 80, RemoteAddress: net.ParseIP("2620::2"), RemotePort: 80, Proto: "TCP", Weight: 1, ActiveConn: 0, InactConn: 0, }, { LocalAddress: net.ParseIP("2620::1"), LocalPort: 80, RemoteAddress: net.ParseIP("2620::3"), RemotePort: 80, Proto: "TCP", Weight: 1, ActiveConn: 0, InactConn: 0, }, { LocalAddress: net.ParseIP("2620::1"), LocalPort: 80, RemoteAddress: net.ParseIP("2620::4"), RemotePort: 80, Proto: "TCP", Weight: 1, ActiveConn: 1, InactConn: 1, }, { LocalMark: "10001000", RemoteAddress: net.ParseIP("192.168.50.26"), RemotePort: 3306, Proto: "FWM", Weight: 0, ActiveConn: 0, InactConn: 1, }, { LocalMark: "10001000", RemoteAddress: net.ParseIP("192.168.50.21"), RemotePort: 3306, Proto: "FWM", Weight: 0, ActiveConn: 0, InactConn: 2, }, } ) func TestIPVSStats(t *testing.T) { fs, err := NewFS(procTestFixtures) if err != nil { t.Fatal(err) } stats, err := fs.IPVSStats() if err != nil { t.Fatal(err) } if stats != expectedIPVSStats { t.Errorf("want %+v, have %+v", expectedIPVSStats, stats) } } func TestParseIPPort(t *testing.T) { ip := net.ParseIP("192.168.0.22") port := uint16(3306) gotIP, gotPort, err := parseIPPort("C0A80016:0CEA") if err != nil { t.Fatal(err) } if !(gotIP.Equal(ip) && port == gotPort) { t.Errorf("want %s:%d, have %s:%d", ip, port, gotIP, gotPort) } } func TestParseIPPortInvalid(t *testing.T) { testcases := []string{ "", "C0A80016", "C0A800:1234", "FOOBARBA:1234", "C0A80016:0CEA:1234", } for _, s := range testcases { ip, port, err := parseIPPort(s) if ip != nil || port != uint16(0) || err == nil { t.Errorf("Expected error for input %s, have ip = %s, port = %v, err = %v", s, ip, port, err) } } } func TestParseIPPortIPv6(t *testing.T) { ip := net.ParseIP("dead:beef::1") port := uint16(8080) gotIP, gotPort, err := parseIPPort("[DEAD:BEEF:0000:0000:0000:0000:0000:0001]:1F90") if err != nil { t.Fatal(err) } if !(gotIP.Equal(ip) && port == gotPort) { t.Errorf("want %s:%d, have %s:%d", ip, port, gotIP, gotPort) } } func TestIPVSBackendStatus(t *testing.T) { backendStats, err := getProcFixtures(t).IPVSBackendStatus() if err != nil { t.Fatal(err) } if want, have := len(expectedIPVSBackendStatuses), len(backendStats); want != have { t.Fatalf("want %d backend statuses, have %d", want, have) } for idx, expect := range expectedIPVSBackendStatuses { if !backendStats[idx].LocalAddress.Equal(expect.LocalAddress) { t.Errorf("want LocalAddress %s, have %s", expect.LocalAddress, backendStats[idx].LocalAddress) } if backendStats[idx].LocalPort != expect.LocalPort { t.Errorf("want LocalPort %d, have %d", expect.LocalPort, backendStats[idx].LocalPort) } if !backendStats[idx].RemoteAddress.Equal(expect.RemoteAddress) { t.Errorf("want RemoteAddress %s, have %s", expect.RemoteAddress, backendStats[idx].RemoteAddress) } if backendStats[idx].RemotePort != expect.RemotePort { t.Errorf("want RemotePort %d, have %d", expect.RemotePort, backendStats[idx].RemotePort) } if backendStats[idx].Proto != expect.Proto { t.Errorf("want Proto %s, have %s", expect.Proto, backendStats[idx].Proto) } if backendStats[idx].Weight != expect.Weight { t.Errorf("want Weight %d, have %d", expect.Weight, backendStats[idx].Weight) } if backendStats[idx].ActiveConn != expect.ActiveConn { t.Errorf("want ActiveConn %d, have %d", expect.ActiveConn, backendStats[idx].ActiveConn) } if backendStats[idx].InactConn != expect.InactConn { t.Errorf("want InactConn %d, have %d", expect.InactConn, backendStats[idx].InactConn) } } } golang-github-prometheus-procfs-0.14.0/iscsi/000077500000000000000000000000001461002754700211265ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/iscsi/get.go000066400000000000000000000174661461002754700222520ustar00rootroot00000000000000// 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. package iscsi import ( "errors" "fmt" "os" "path/filepath" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // GetStats is the main iscsi status information func for // building the path and prepare info for enable iscsi. func GetStats(iqnPath string) (*Stats, error) { var istats Stats istats.Name = filepath.Base(iqnPath) istats.RootPath = filepath.Dir(iqnPath) matches, err := filepath.Glob(filepath.Join(iqnPath, "tpgt*")) if err != nil { return nil, fmt.Errorf("iscsi: GetStats: get TPGT path error %w", err) } istats.Tpgt = make([]TPGT, len(matches)) for i, tpgtPath := range matches { istats.Tpgt[i].Name = filepath.Base(tpgtPath) istats.Tpgt[i].TpgtPath = tpgtPath istats.Tpgt[i].IsEnable, _ = isPathEnable(tpgtPath) if istats.Tpgt[i].IsEnable { matchesLunsPath, _ := filepath.Glob(filepath.Join(tpgtPath, "lun/lun*")) for _, lunPath := range matchesLunsPath { lun, err := getLunLinkTarget(lunPath) if err == nil { istats.Tpgt[i].Luns = append(istats.Tpgt[i].Luns, lun) } } } } return &istats, nil } // isPathEnable checks if the file "enable" contain enable message. func isPathEnable(path string) (bool, error) { enableReadout, err := os.ReadFile(filepath.Join(path, "enable")) if err != nil { return false, fmt.Errorf("iscsi: isPathEnable ReadFile error %w", err) } isEnable, err := strconv.ParseBool(strings.TrimSpace(string(enableReadout))) if err != nil { return false, fmt.Errorf("iscsi: isPathEnable ParseBool error %w", err) } return isEnable, nil } func getLunLinkTarget(lunPath string) (lunObject LUN, err error) { lunObject.Name = filepath.Base(lunPath) lunObject.LunPath = lunPath files, err := os.ReadDir(lunPath) if err != nil { return lunObject, fmt.Errorf("getLunLinkTarget: ReadDir path %q: %w", lunPath, err) } for _, file := range files { fileInfo, _ := os.Lstat(filepath.Join(lunPath, file.Name())) if fileInfo.Mode()&os.ModeSymlink != 0 { target, err := os.Readlink(filepath.Join(lunPath, fileInfo.Name())) if err != nil { return lunObject, fmt.Errorf("getLunLinkTarget: Readlink: %w", err) } targetPath, objectName := filepath.Split(target) _, typeWithNumber := filepath.Split(filepath.Clean(targetPath)) underscore := strings.LastIndex(typeWithNumber, "_") if underscore != -1 { lunObject.Backstore = typeWithNumber[:underscore] lunObject.TypeNumber = typeWithNumber[underscore+1:] } lunObject.ObjectName = objectName return lunObject, nil } } return lunObject, errors.New("iscsi: getLunLinkTarget: Lun Link does not exist") } // ReadWriteOPS read and return the stat of read and write in megabytes, // and total commands that send to the target. func ReadWriteOPS(iqnPath string, tpgt string, lun string) (readmb uint64, writemb uint64, iops uint64, err error) { readmbPath := filepath.Join(iqnPath, tpgt, "lun", lun, "statistics/scsi_tgt_port/read_mbytes") readmb, err = util.ReadUintFromFile(readmbPath) if err != nil { return 0, 0, 0, fmt.Errorf("iscsi: ReadWriteOPS: read_mbytes error file %q: %w", readmbPath, err) } writembPath := filepath.Join(iqnPath, tpgt, "lun", lun, "statistics/scsi_tgt_port/write_mbytes") writemb, err = util.ReadUintFromFile(writembPath) if err != nil { return 0, 0, 0, fmt.Errorf("iscsi: ReadWriteOPS: write_mbytes error file %q: %w", writembPath, err) } iopsPath := filepath.Join(iqnPath, tpgt, "lun", lun, "statistics/scsi_tgt_port/in_cmds") iops, err = util.ReadUintFromFile(iopsPath) if err != nil { return 0, 0, 0, fmt.Errorf("iscsi: ReadWriteOPS: in_cmds error file %q: %w", iopsPath, err) } return readmb, writemb, iops, nil } // GetFileioUdev is getting the actual info to build up // the FILEIO data and match with the enable target. func (fs FS) GetFileioUdev(fileioNumber string, objectName string) (*FILEIO, error) { fileio := FILEIO{ Name: "fileio_" + fileioNumber, Fnumber: fileioNumber, ObjectName: objectName, } udevPath := fs.configfs.Path(targetCore, fileio.Name, fileio.ObjectName, "udev_path") if _, err := os.Stat(udevPath); os.IsNotExist(err) { return nil, fmt.Errorf("iscsi: GetFileioUdev: fileio_%s is missing file name", fileio.Fnumber) } filename, err := os.ReadFile(udevPath) if err != nil { return nil, fmt.Errorf("iscsi: GetFileioUdev: Cannot read filename from udev link %q", udevPath) } fileio.Filename = strings.TrimSpace(string(filename)) return &fileio, nil } // GetIblockUdev is getting the actual info to build up // the IBLOCK data and match with the enable target. func (fs FS) GetIblockUdev(iblockNumber string, objectName string) (*IBLOCK, error) { iblock := IBLOCK{ Name: "iblock_" + iblockNumber, Bnumber: iblockNumber, ObjectName: objectName, } udevPath := fs.configfs.Path(targetCore, iblock.Name, iblock.ObjectName, "udev_path") if _, err := os.Stat(udevPath); os.IsNotExist(err) { return nil, fmt.Errorf("iscsi: GetIBlockUdev: iblock_%s is missing file name", iblock.Bnumber) } filename, err := os.ReadFile(udevPath) if err != nil { return nil, fmt.Errorf("iscsi: GetIBlockUdev: Cannot read iblock from udev link %q", udevPath) } iblock.Iblock = strings.TrimSpace(string(filename)) return &iblock, nil } // GetRBDMatch is getting the actual info to build up // the RBD data and match with the enable target. func (fs FS) GetRBDMatch(rbdNumber string, poolImage string) (*RBD, error) { rbd := RBD{ Name: "rbd_" + rbdNumber, Rnumber: rbdNumber, } systemRbds, err := filepath.Glob(fs.sysfs.Path(devicePath, "[0-9]*")) if err != nil { return nil, fmt.Errorf("iscsi: GetRBDMatch: Cannot find any rbd block") } for systemRbdNumber, systemRbdPath := range systemRbds { var systemPool, systemImage string systemPoolPath := filepath.Join(systemRbdPath, "pool") if _, err := os.Stat(systemPoolPath); os.IsNotExist(err) { continue } bSystemPool, err := os.ReadFile(systemPoolPath) if err != nil { continue } systemPool = strings.TrimSpace(string(bSystemPool)) systemImagePath := filepath.Join(systemRbdPath, "name") if _, err := os.Stat(systemImagePath); os.IsNotExist(err) { continue } bSystemImage, err := os.ReadFile(systemImagePath) if err != nil { continue } systemImage = strings.TrimSpace(string(bSystemImage)) if strings.Compare(strconv.FormatInt(int64(systemRbdNumber), 10), rbdNumber) == 0 && matchPoolImage(systemPool, systemImage, poolImage) { rbd.Pool = systemPool rbd.Image = systemImage return &rbd, nil } } return nil, nil } // GetRDMCPPath is getting the actual info to build up RDMCP data. func (fs FS) GetRDMCPPath(rdmcpNumber string, objectName string) (*RDMCP, error) { rdmcp := RDMCP{ Name: "rd_mcp_" + rdmcpNumber, ObjectName: objectName, } rdmcpPath := fs.configfs.Path(targetCore, rdmcp.Name, rdmcp.ObjectName) if _, err := os.Stat(rdmcpPath); os.IsNotExist(err) { return nil, fmt.Errorf("iscsi: GetRDMCPPath %q does not exist", rdmcpPath) } isEnable, err := isPathEnable(rdmcpPath) if err != nil { return nil, fmt.Errorf("iscsi: GetRDMCPPath: error %w", err) } if isEnable { return &rdmcp, nil } return nil, nil } func matchPoolImage(pool string, image string, matchPoolImage string) (isEqual bool) { var poolImage = fmt.Sprintf("%s-%s", pool, image) return strings.Compare(poolImage, matchPoolImage) == 0 } golang-github-prometheus-procfs-0.14.0/iscsi/get_test.go000066400000000000000000000157171461002754700233060ustar00rootroot00000000000000// 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. package iscsi_test import ( "reflect" "testing" "github.com/prometheus/procfs/iscsi" ) func TestGetStats(t *testing.T) { tests := []struct { stat *iscsi.Stats }{ { stat: &iscsi.Stats{ Name: "iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0", Tpgt: []iscsi.TPGT{ { Name: "tpgt_1", TpgtPath: "testdata/fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1", IsEnable: true, Luns: []iscsi.LUN{ { Name: "lun_0", LunPath: "testdata/fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.8888bbbbddd0/tpgt_1/lun/lun_0", Backstore: "rd_mcp", ObjectName: "ramdisk_lio_1G", TypeNumber: "119", }, }, }, }, RootPath: "testdata/fixtures/sys/kernel/config/target/iscsi", }, }, { stat: &iscsi.Stats{ Name: "iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab", Tpgt: []iscsi.TPGT{ { Name: "tpgt_1", TpgtPath: "testdata/fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1", IsEnable: true, Luns: []iscsi.LUN{ { Name: "lun_0", LunPath: "testdata/fixtures/sys/kernel/config/target/iscsi/iqn.2003-01.org.linux-iscsi.osd1.x8664:sn.abcd1abcd2ab/tpgt_1/lun/lun_0", Backstore: "iblock", ObjectName: "block_lio_rbd1", TypeNumber: "0", }, }, }, }, RootPath: "testdata/fixtures/sys/kernel/config/target/iscsi", }, }, { stat: &iscsi.Stats{ Name: "iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0", Tpgt: []iscsi.TPGT{ { Name: "tpgt_1", TpgtPath: "testdata/fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1", IsEnable: true, Luns: []iscsi.LUN{ { Name: "lun_0", LunPath: "testdata/fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:dev.rbd0/tpgt_1/lun/lun_0", Backstore: "fileio", ObjectName: "file_lio_1G", TypeNumber: "1", }, }, }, }, RootPath: "testdata/fixtures/sys/kernel/config/target/iscsi", }, }, { stat: &iscsi.Stats{ Name: "iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo", Tpgt: []iscsi.TPGT{ { Name: "tpgt_1", TpgtPath: "testdata/fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1", IsEnable: true, Luns: []iscsi.LUN{ { Name: "lun_0", LunPath: "testdata/fixtures/sys/kernel/config/target/iscsi/iqn.2016-11.org.linux-iscsi.igw.x86:sn.ramdemo/tpgt_1/lun/lun_0", Backstore: "rbd", ObjectName: "iscsi-images-demo", TypeNumber: "0", }, }, }, }, RootPath: "testdata/fixtures/sys/kernel/config/target/iscsi", }, }, } readTests := []struct { read uint64 write uint64 iops uint64 }{ {10325, 40325, 204950}, {20095, 71235, 104950}, {10195, 30195, 301950}, {1504, 4733, 1234}, } sysconfigfs, err := iscsi.NewFS("testdata/fixtures/sys", "testdata/fixtures/sys/kernel/config") if err != nil { t.Fatalf("failed to access xfs fs: %v", err) } sysfsStat, err := sysconfigfs.ISCSIStats() statSize := len(sysfsStat) if statSize != 4 { t.Errorf("fixtures size does not match %d", statSize) } if err != nil { t.Errorf("unexpected test fixtures") } for i, stat := range sysfsStat { want, have := tests[i].stat, stat if !reflect.DeepEqual(want, have) { t.Errorf("unexpected iSCSI stats:\nwant:\n%v\nhave:\n%v", want, have) } else { readMB, writeMB, iops, err := iscsi.ReadWriteOPS(stat.RootPath+"/"+stat.Name, stat.Tpgt[0].Name, stat.Tpgt[0].Luns[0].Name) if err != nil { t.Errorf("unexpected iSCSI ReadWriteOPS path %s %s %s", stat.Name, stat.Tpgt[0].Name, stat.Tpgt[0].Luns[0].Name) t.Errorf("%v", err) } if !reflect.DeepEqual(readTests[i].read, readMB) { t.Errorf("unexpected iSCSI read data :\nwant:\n%v\nhave:\n%v", readTests[i].read, readMB) } if !reflect.DeepEqual(readTests[i].write, writeMB) { t.Errorf("unexpected iSCSI write data :\nwant:\n%v\nhave:\n%v", readTests[i].write, writeMB) } if !reflect.DeepEqual(readTests[i].iops, iops) { t.Errorf("unexpected iSCSI iops data :\nwant:\n%v\nhave:\n%v", readTests[i].iops, iops) } if stat.Tpgt[0].Luns[0].Backstore == "rd_mcp" { haveRdmcp, err := sysconfigfs.GetRDMCPPath("119", "ramdisk_lio_1G") if err != nil { t.Errorf("fail rdmcp error %v", err) } // Name ObjectName wantRdmcp := &iscsi.RDMCP{"rd_mcp_" + stat.Tpgt[0].Luns[0].TypeNumber, stat.Tpgt[0].Luns[0].ObjectName} if !reflect.DeepEqual(wantRdmcp, haveRdmcp) { t.Errorf("unexpected rdmcp data :\nwant:\n%v\nhave:\n%v", wantRdmcp, haveRdmcp) } } else if stat.Tpgt[0].Luns[0].Backstore == "iblock" { haveIblock, err := sysconfigfs.GetIblockUdev("0", "block_lio_rbd1") if err != nil { t.Errorf("fail iblock error %v", err) } // Name Bnumber ObjectName Iblock wantIblock := &iscsi.IBLOCK{"iblock_" + stat.Tpgt[0].Luns[0].TypeNumber, stat.Tpgt[0].Luns[0].TypeNumber, stat.Tpgt[0].Luns[0].ObjectName, "/dev/rbd1"} if !reflect.DeepEqual(wantIblock, haveIblock) { t.Errorf("unexpected iblock data :\nwant:\n%v\nhave:\n%v", wantIblock, haveIblock) } } else if stat.Tpgt[0].Luns[0].Backstore == "fileio" { haveFileIO, err := sysconfigfs.GetFileioUdev("1", "file_lio_1G") if err != nil { t.Errorf("fail fileio error %v", err) } // Name, Fnumber, ObjectName, Filename wantFileIO := &iscsi.FILEIO{"fileio_" + stat.Tpgt[0].Luns[0].TypeNumber, stat.Tpgt[0].Luns[0].TypeNumber, "file_lio_1G", "/home/iscsi/file_back_1G"} if !reflect.DeepEqual(wantFileIO, haveFileIO) { t.Errorf("unexpected fileio data :\nwant:\n%v\nhave:\n%v", wantFileIO, haveFileIO) } } else if stat.Tpgt[0].Luns[0].Backstore == "rbd" { haveRBD, err := sysconfigfs.GetRBDMatch("0", "iscsi-images-demo") if err != nil { t.Errorf("fail rbd error %v", err) } // Name, Rnumber, Pool, Image wantRBD := &iscsi.RBD{"rbd_" + stat.Tpgt[0].Luns[0].TypeNumber, stat.Tpgt[0].Luns[0].TypeNumber, "iscsi-images", "demo"} if !reflect.DeepEqual(wantRBD, haveRBD) { t.Errorf("unexpected fileio data :\nwant:\n%v\nhave:\n%v", wantRBD, haveRBD) } } } } } golang-github-prometheus-procfs-0.14.0/iscsi/iscsi.go000066400000000000000000000102011461002754700225610ustar00rootroot00000000000000// 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. package iscsi import ( "path/filepath" "strings" "github.com/prometheus/procfs/internal/fs" ) // iscsi target started with /sys/kernel/config/target/iscsi/iqn* // configfs + target/iscsi/iqn* // iqnGlob is representing all the possible IQN. const iqnGlob = "target/iscsi/iqn*" // targetCore static path /sys/kernel/config/target/core for node_exporter // reading runtime status. const targetCore = "target/core" // devicePath static path /sys/devices/rbd/[0-9]* for rbd devices to // read at runtime status. const devicePath = "devices/rbd" // FS represents the pseudo-filesystem configfs, which provides an interface to // iscsi kernel data structures in sysfs as /sys and configfs as /sys/kernel/config. type FS struct { sysfs *fs.FS configfs *fs.FS } // NewFS returns a new configfs mounted under the given mount point. It will // error and return empty FS if the mount point can't be read. For the ease of // use, an empty string parameter configfsMountPoint will call internal fs for // the default sys path as /sys/kernel/config. func NewFS(sysfsPath string, configfsMountPoint string) (FS, error) { if strings.TrimSpace(sysfsPath) == "" { sysfsPath = fs.DefaultSysMountPoint } sysfs, err := fs.NewFS(sysfsPath) if err != nil { return FS{}, err } if strings.TrimSpace(configfsMountPoint) == "" { configfsMountPoint = fs.DefaultConfigfsMountPoint } configfs, err := fs.NewFS(configfsMountPoint) if err != nil { return FS{}, err } return FS{&sysfs, &configfs}, nil } // Path is a helper function to get configfs path. func (fs FS) Path(p ...string) string { return fs.configfs.Path(p...) } // ISCSIStats getting iscsi runtime information. func (fs FS) ISCSIStats() ([]*Stats, error) { matches, err := filepath.Glob(fs.configfs.Path(iqnGlob)) if err != nil { return nil, err } stats := make([]*Stats, 0, len(matches)) for _, iqnPath := range matches { // stats s, err := GetStats(iqnPath) if err != nil { return nil, err } stats = append(stats, s) } return stats, nil } // TPGT struct for sys target portal group tag info. type TPGT struct { Name string // name of the tpgt group TpgtPath string // file path of tpgt IsEnable bool // is the tpgt enable Luns []LUN // the Luns that tpgt has } // LUN struct for sys logical unit number info. type LUN struct { Name string // name of the lun LunPath string // file path of the lun Backstore string // backstore of the lun ObjectName string // place holder for object TypeNumber string // place holder for number of the device } // FILEIO struct for backstore info. type FILEIO struct { Name string // name of the fileio Fnumber string // number related to the backstore ObjectName string // place holder for object in iscsi object Filename string // link to the actual file being export } // IBLOCK struct for backstore info. type IBLOCK struct { Name string // name of the iblock Bnumber string // number related to the backstore ObjectName string // place holder for object in iscsi object Iblock string // link to the actual block being export } // RBD struct for backstore info. type RBD struct { Name string // name of the rbd Rnumber string // number related to the backstore Pool string // place holder for the rbd pool Image string // place holder for the rbd image } // RDMCP struct for backstore info. type RDMCP struct { Name string // name of the rdm_cp ObjectName string // place holder for object name } // Stats struct for all targets info. type Stats struct { Name string Tpgt []TPGT RootPath string } golang-github-prometheus-procfs-0.14.0/iscsi/testdata/000077500000000000000000000000001461002754700227375ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/iscsi/testdata/fixtures000077700000000000000000000000001461002754700305612../../testdata/fixturesustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/kernel_random.go000066400000000000000000000041441461002754700231660ustar00rootroot00000000000000// Copyright 2020 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. //go:build !windows // +build !windows package procfs import ( "os" "github.com/prometheus/procfs/internal/util" ) // KernelRandom contains information about to the kernel's random number generator. type KernelRandom struct { // EntropyAvaliable gives the available entropy, in bits. EntropyAvaliable *uint64 // PoolSize gives the size of the entropy pool, in bits. PoolSize *uint64 // URandomMinReseedSeconds is the number of seconds after which the DRNG will be reseeded. URandomMinReseedSeconds *uint64 // WriteWakeupThreshold the number of bits of entropy below which we wake up processes // that do a select(2) or poll(2) for write access to /dev/random. WriteWakeupThreshold *uint64 // ReadWakeupThreshold is the number of bits of entropy required for waking up processes that sleep // waiting for entropy from /dev/random. ReadWakeupThreshold *uint64 } // KernelRandom returns values from /proc/sys/kernel/random. func (fs FS) KernelRandom() (KernelRandom, error) { random := KernelRandom{} for file, p := range map[string]**uint64{ "entropy_avail": &random.EntropyAvaliable, "poolsize": &random.PoolSize, "urandom_min_reseed_secs": &random.URandomMinReseedSeconds, "write_wakeup_threshold": &random.WriteWakeupThreshold, "read_wakeup_threshold": &random.ReadWakeupThreshold, } { val, err := util.ReadUintFromFile(fs.proc.Path("sys", "kernel", "random", file)) if os.IsNotExist(err) { continue } if err != nil { return random, err } *p = &val } return random, nil } golang-github-prometheus-procfs-0.14.0/kernel_random_test.go000066400000000000000000000031311461002754700242200ustar00rootroot00000000000000// Copyright 2020 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. //go:build !windows // +build !windows package procfs import ( "testing" ) const procfsFixtures = "testdata/fixtures/proc" func TestKernelRandom(t *testing.T) { fs, err := NewFS(procfsFixtures) if err != nil { t.Fatalf("failed to access %s: %v", procfsFixtures, err) } random, err := fs.KernelRandom() if err != nil { t.Fatalf("failed to collect %s/sys/kernel/random: %v", procfsFixtures, err) } if *random.EntropyAvaliable != 3943 { t.Errorf("entropy_avail, want %d got %d", 3943, *random.EntropyAvaliable) } if *random.PoolSize != 4096 { t.Errorf("poolsize, want %d got %d", 4096, *random.PoolSize) } if *random.URandomMinReseedSeconds != 60 { t.Errorf("urandom_min_reseed_secs, want %d got %d", 60, *random.URandomMinReseedSeconds) } if *random.WriteWakeupThreshold != 3072 { t.Errorf("write_wakeup_threshold, want %d got %d", 3072, *random.WriteWakeupThreshold) } if random.ReadWakeupThreshold != nil { t.Errorf("read_wakeup_threshold, want %v got %d", nil, *random.ReadWakeupThreshold) } } golang-github-prometheus-procfs-0.14.0/loadavg.go000066400000000000000000000031371461002754700217640ustar00rootroot00000000000000// 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. package procfs import ( "fmt" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // LoadAvg represents an entry in /proc/loadavg. type LoadAvg struct { Load1 float64 Load5 float64 Load15 float64 } // LoadAvg returns loadavg from /proc. func (fs FS) LoadAvg() (*LoadAvg, error) { path := fs.proc.Path("loadavg") data, err := util.ReadFileNoStat(path) if err != nil { return nil, err } return parseLoad(data) } // Parse /proc loadavg and return 1m, 5m and 15m. func parseLoad(loadavgBytes []byte) (*LoadAvg, error) { loads := make([]float64, 3) parts := strings.Fields(string(loadavgBytes)) if len(parts) < 3 { return nil, fmt.Errorf("%w: Malformed line %q", ErrFileParse, string(loadavgBytes)) } var err error for i, load := range parts[0:3] { loads[i], err = strconv.ParseFloat(load, 64) if err != nil { return nil, fmt.Errorf("%w: Cannot parse load: %f: %w", ErrFileParse, loads[i], err) } } return &LoadAvg{ Load1: loads[0], Load5: loads[1], Load15: loads[2], }, nil } golang-github-prometheus-procfs-0.14.0/loadavg_test.go000066400000000000000000000042231461002754700230200ustar00rootroot00000000000000// 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. package procfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestLoadAvg(t *testing.T) { fs, err := NewFS(procTestFixtures) if err != nil { t.Fatalf("failed to open procfs: %v", err) } loadavg, err := fs.LoadAvg() if err != nil { t.Fatalf("failed to get loadavg: %v", err) } if diff := cmp.Diff(0.02, loadavg.Load1); diff != "" { t.Fatalf("unexpected LoadAvg Per a minute:\n%s", diff) } if diff := cmp.Diff(0.04, loadavg.Load5); diff != "" { t.Fatalf("unexpected LoadAvg Per five minutes:\n%s", diff) } if diff := cmp.Diff(0.05, loadavg.Load15); diff != "" { t.Fatalf("unexpected LoadAvg Per fifteen minutes:\n%s", diff) } } func Test_parseLoad(t *testing.T) { tests := []struct { name string s string ok bool loadavg *LoadAvg }{ { name: "empty", ok: false, }, { name: "not enough fields", s: `0.00 0.03`, ok: false, }, { name: "invalid line", s: `malformed line`, ok: false, }, { name: "valid line", s: `0.00 0.03 0.05 1/502 33634`, ok: true, loadavg: &LoadAvg{Load1: 0, Load5: 0.03, Load15: 0.05}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { loadavg, err := parseLoad([]byte(tt.s)) if err != nil { if tt.ok { t.Fatalf("failed to parse loadavg: %v", err) } t.Logf("OK error: %v", err) return } if !tt.ok { t.Fatal("expected an error, but none occurred") } if diff := cmp.Diff(tt.loadavg, loadavg); diff != "" { t.Errorf("unexpected loadavg(-want +got):\n%s", diff) } }) } } golang-github-prometheus-procfs-0.14.0/mdstat.go000066400000000000000000000214321461002754700216410ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "fmt" "os" "regexp" "strconv" "strings" ) var ( statusLineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[([U_]+)\]`) recoveryLineBlocksRE = regexp.MustCompile(`\((\d+)/\d+\)`) recoveryLinePctRE = regexp.MustCompile(`= (.+)%`) recoveryLineFinishRE = regexp.MustCompile(`finish=(.+)min`) recoveryLineSpeedRE = regexp.MustCompile(`speed=(.+)[A-Z]`) componentDeviceRE = regexp.MustCompile(`(.*)\[\d+\]`) ) // MDStat holds info parsed from /proc/mdstat. type MDStat struct { // Name of the device. Name string // activity-state of the device. ActivityState string // Number of active disks. DisksActive int64 // Total number of disks the device requires. DisksTotal int64 // Number of failed disks. DisksFailed int64 // Number of "down" disks. (the _ indicator in the status line) DisksDown int64 // Spare disks in the device. DisksSpare int64 // Number of blocks the device holds. BlocksTotal int64 // Number of blocks on the device that are in sync. BlocksSynced int64 // progress percentage of current sync BlocksSyncedPct float64 // estimated finishing time for current sync (in minutes) BlocksSyncedFinishTime float64 // current sync speed (in Kilobytes/sec) BlocksSyncedSpeed float64 // Name of md component devices Devices []string } // MDStat parses an mdstat-file (/proc/mdstat) and returns a slice of // structs containing the relevant info. More information available here: // https://raid.wiki.kernel.org/index.php/Mdstat func (fs FS) MDStat() ([]MDStat, error) { data, err := os.ReadFile(fs.proc.Path("mdstat")) if err != nil { return nil, err } mdstat, err := parseMDStat(data) if err != nil { return nil, fmt.Errorf("%w: Cannot parse %v: %w", ErrFileParse, fs.proc.Path("mdstat"), err) } return mdstat, nil } // parseMDStat parses data from mdstat file (/proc/mdstat) and returns a slice of // structs containing the relevant info. func parseMDStat(mdStatData []byte) ([]MDStat, error) { mdStats := []MDStat{} lines := strings.Split(string(mdStatData), "\n") for i, line := range lines { if strings.TrimSpace(line) == "" || line[0] == ' ' || strings.HasPrefix(line, "Personalities") || strings.HasPrefix(line, "unused") { continue } deviceFields := strings.Fields(line) if len(deviceFields) < 3 { return nil, fmt.Errorf("%w: Expected 3+ lines, got %q", ErrFileParse, line) } mdName := deviceFields[0] // mdx state := deviceFields[2] // active or inactive if len(lines) <= i+3 { return nil, fmt.Errorf("%w: Too few lines for md device: %q", ErrFileParse, mdName) } // Failed disks have the suffix (F) & Spare disks have the suffix (S). fail := int64(strings.Count(line, "(F)")) spare := int64(strings.Count(line, "(S)")) active, total, down, size, err := evalStatusLine(lines[i], lines[i+1]) if err != nil { return nil, fmt.Errorf("%w: Cannot parse md device lines: %v: %w", ErrFileParse, active, err) } syncLineIdx := i + 2 if strings.Contains(lines[i+2], "bitmap") { // skip bitmap line syncLineIdx++ } // If device is syncing at the moment, get the number of currently // synced bytes, otherwise that number equals the size of the device. syncedBlocks := size speed := float64(0) finish := float64(0) pct := float64(0) recovering := strings.Contains(lines[syncLineIdx], "recovery") resyncing := strings.Contains(lines[syncLineIdx], "resync") checking := strings.Contains(lines[syncLineIdx], "check") // Append recovery and resyncing state info. if recovering || resyncing || checking { if recovering { state = "recovering" } else if checking { state = "checking" } else { state = "resyncing" } // Handle case when resync=PENDING or resync=DELAYED. if strings.Contains(lines[syncLineIdx], "PENDING") || strings.Contains(lines[syncLineIdx], "DELAYED") { syncedBlocks = 0 } else { syncedBlocks, pct, finish, speed, err = evalRecoveryLine(lines[syncLineIdx]) if err != nil { return nil, fmt.Errorf("%w: Cannot parse sync line in md device: %q: %w", ErrFileParse, mdName, err) } } } mdStats = append(mdStats, MDStat{ Name: mdName, ActivityState: state, DisksActive: active, DisksFailed: fail, DisksDown: down, DisksSpare: spare, DisksTotal: total, BlocksTotal: size, BlocksSynced: syncedBlocks, BlocksSyncedPct: pct, BlocksSyncedFinishTime: finish, BlocksSyncedSpeed: speed, Devices: evalComponentDevices(deviceFields), }) } return mdStats, nil } func evalStatusLine(deviceLine, statusLine string) (active, total, down, size int64, err error) { statusFields := strings.Fields(statusLine) if len(statusFields) < 1 { return 0, 0, 0, 0, fmt.Errorf("%w: Unexpected statusline %q: %w", ErrFileParse, statusLine, err) } sizeStr := statusFields[0] size, err = strconv.ParseInt(sizeStr, 10, 64) if err != nil { return 0, 0, 0, 0, fmt.Errorf("%w: Unexpected statusline %q: %w", ErrFileParse, statusLine, err) } if strings.Contains(deviceLine, "raid0") || strings.Contains(deviceLine, "linear") { // In the device deviceLine, only disks have a number associated with them in []. total = int64(strings.Count(deviceLine, "[")) return total, total, 0, size, nil } if strings.Contains(deviceLine, "inactive") { return 0, 0, 0, size, nil } matches := statusLineRE.FindStringSubmatch(statusLine) if len(matches) != 5 { return 0, 0, 0, 0, fmt.Errorf("%w: Could not fild all substring matches %s: %w", ErrFileParse, statusLine, err) } total, err = strconv.ParseInt(matches[2], 10, 64) if err != nil { return 0, 0, 0, 0, fmt.Errorf("%w: Unexpected statusline %q: %w", ErrFileParse, statusLine, err) } active, err = strconv.ParseInt(matches[3], 10, 64) if err != nil { return 0, 0, 0, 0, fmt.Errorf("%w: Unexpected active %d: %w", ErrFileParse, active, err) } down = int64(strings.Count(matches[4], "_")) return active, total, down, size, nil } func evalRecoveryLine(recoveryLine string) (syncedBlocks int64, pct float64, finish float64, speed float64, err error) { matches := recoveryLineBlocksRE.FindStringSubmatch(recoveryLine) if len(matches) != 2 { return 0, 0, 0, 0, fmt.Errorf("%w: Unexpected recoveryLine %s: %w", ErrFileParse, recoveryLine, err) } syncedBlocks, err = strconv.ParseInt(matches[1], 10, 64) if err != nil { return 0, 0, 0, 0, fmt.Errorf("%w: Unexpected parsing of recoveryLine %q: %w", ErrFileParse, recoveryLine, err) } // Get percentage complete matches = recoveryLinePctRE.FindStringSubmatch(recoveryLine) if len(matches) != 2 { return syncedBlocks, 0, 0, 0, fmt.Errorf("%w: Unexpected recoveryLine matching percentage %s", ErrFileParse, recoveryLine) } pct, err = strconv.ParseFloat(strings.TrimSpace(matches[1]), 64) if err != nil { return syncedBlocks, 0, 0, 0, fmt.Errorf("%w: Error parsing float from recoveryLine %q", ErrFileParse, recoveryLine) } // Get time expected left to complete matches = recoveryLineFinishRE.FindStringSubmatch(recoveryLine) if len(matches) != 2 { return syncedBlocks, pct, 0, 0, fmt.Errorf("%w: Unexpected recoveryLine matching est. finish time: %s", ErrFileParse, recoveryLine) } finish, err = strconv.ParseFloat(matches[1], 64) if err != nil { return syncedBlocks, pct, 0, 0, fmt.Errorf("%w: Unable to parse float from recoveryLine: %q", ErrFileParse, recoveryLine) } // Get recovery speed matches = recoveryLineSpeedRE.FindStringSubmatch(recoveryLine) if len(matches) != 2 { return syncedBlocks, pct, finish, 0, fmt.Errorf("%w: Unexpected recoveryLine value: %s", ErrFileParse, recoveryLine) } speed, err = strconv.ParseFloat(matches[1], 64) if err != nil { return syncedBlocks, pct, finish, 0, fmt.Errorf("%w: Error parsing float from recoveryLine: %q: %w", ErrFileParse, recoveryLine, err) } return syncedBlocks, pct, finish, speed, nil } func evalComponentDevices(deviceFields []string) []string { mdComponentDevices := make([]string, 0) if len(deviceFields) > 3 { for _, field := range deviceFields[4:] { match := componentDeviceRE.FindStringSubmatch(field) if match == nil { continue } mdComponentDevices = append(mdComponentDevices, match[1]) } } return mdComponentDevices } golang-github-prometheus-procfs-0.14.0/mdstat_test.go000066400000000000000000000145761461002754700227130ustar00rootroot00000000000000// Copyright 2018 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. package procfs import "testing" import "github.com/google/go-cmp/cmp" func TestFS_MDStat(t *testing.T) { fs := getProcFixtures(t) mdStats, err := fs.MDStat() if err != nil { t.Fatalf("parsing of reference-file failed entirely: %s", err) } refs := map[string]MDStat{ "md127": {Name: "md127", ActivityState: "active", DisksActive: 2, DisksTotal: 2, DisksFailed: 0, DisksDown: 0, DisksSpare: 0, BlocksTotal: 312319552, BlocksSynced: 312319552, BlocksSyncedPct: 0, BlocksSyncedFinishTime: 0, BlocksSyncedSpeed: 0, Devices: []string{"sdi2", "sdj2"}}, "md0": {Name: "md0", ActivityState: "active", DisksActive: 2, DisksTotal: 2, DisksFailed: 0, DisksDown: 0, DisksSpare: 0, BlocksTotal: 248896, BlocksSynced: 248896, BlocksSyncedPct: 0, BlocksSyncedFinishTime: 0, BlocksSyncedSpeed: 0, Devices: []string{"sdi1", "sdj1"}}, "md4": {Name: "md4", ActivityState: "inactive", DisksActive: 0, DisksTotal: 0, DisksFailed: 1, DisksDown: 0, DisksSpare: 1, BlocksTotal: 4883648, BlocksSynced: 4883648, BlocksSyncedPct: 0, BlocksSyncedFinishTime: 0, BlocksSyncedSpeed: 0, Devices: []string{"sda3", "sdb3"}}, "md6": {Name: "md6", ActivityState: "recovering", DisksActive: 1, DisksTotal: 2, DisksFailed: 1, DisksDown: 1, DisksSpare: 1, BlocksTotal: 195310144, BlocksSynced: 16775552, BlocksSyncedPct: 8.5, BlocksSyncedFinishTime: 17, BlocksSyncedSpeed: 259783, Devices: []string{"sdb2", "sdc", "sda2"}}, "md3": {Name: "md3", ActivityState: "active", DisksActive: 8, DisksTotal: 8, DisksFailed: 0, DisksDown: 0, DisksSpare: 2, BlocksTotal: 5853468288, BlocksSynced: 5853468288, BlocksSyncedPct: 0, BlocksSyncedFinishTime: 0, BlocksSyncedSpeed: 0, Devices: []string{"sda1", "sdh1", "sdg1", "sdf1", "sde1", "sdd1", "sdc1", "sdb1", "sdd1", "sdd2"}}, "md8": {Name: "md8", ActivityState: "resyncing", DisksActive: 2, DisksTotal: 2, DisksFailed: 0, DisksDown: 0, DisksSpare: 2, BlocksTotal: 195310144, BlocksSynced: 16775552, BlocksSyncedPct: 8.5, BlocksSyncedFinishTime: 17, BlocksSyncedSpeed: 259783, Devices: []string{"sdb1", "sda1", "sdc", "sde"}}, "md7": {Name: "md7", ActivityState: "active", DisksActive: 3, DisksTotal: 4, DisksFailed: 1, DisksDown: 1, DisksSpare: 0, BlocksTotal: 7813735424, BlocksSynced: 7813735424, BlocksSyncedPct: 0, BlocksSyncedFinishTime: 0, BlocksSyncedSpeed: 0, Devices: []string{"sdb1", "sde1", "sdd1", "sdc1"}}, "md9": {Name: "md9", ActivityState: "resyncing", DisksActive: 4, DisksTotal: 4, DisksSpare: 1, DisksDown: 0, DisksFailed: 2, BlocksTotal: 523968, BlocksSynced: 0, BlocksSyncedPct: 0, BlocksSyncedFinishTime: 0, BlocksSyncedSpeed: 0, Devices: []string{"sdc2", "sdd2", "sdb2", "sda2", "sde", "sdf", "sdg"}}, "md10": {Name: "md10", ActivityState: "active", DisksActive: 2, DisksTotal: 2, DisksFailed: 0, DisksDown: 0, DisksSpare: 0, BlocksTotal: 314159265, BlocksSynced: 314159265, BlocksSyncedPct: 0, BlocksSyncedFinishTime: 0, BlocksSyncedSpeed: 0, Devices: []string{"sda1", "sdb1"}}, "md11": {Name: "md11", ActivityState: "resyncing", DisksActive: 2, DisksTotal: 2, DisksFailed: 1, DisksDown: 0, DisksSpare: 2, BlocksTotal: 4190208, BlocksSynced: 0, BlocksSyncedPct: 0, BlocksSyncedFinishTime: 0, BlocksSyncedSpeed: 0, Devices: []string{"sdb2", "sdc2", "sdc3", "hda", "ssdc2"}}, "md12": {Name: "md12", ActivityState: "active", DisksActive: 2, DisksTotal: 2, DisksSpare: 0, DisksDown: 0, DisksFailed: 0, BlocksTotal: 3886394368, BlocksSynced: 3886394368, BlocksSyncedPct: 0, BlocksSyncedFinishTime: 0, BlocksSyncedSpeed: 0, Devices: []string{"sdc2", "sdd2"}}, "md120": {Name: "md120", ActivityState: "active", DisksActive: 2, DisksTotal: 2, DisksFailed: 0, DisksDown: 0, DisksSpare: 0, BlocksTotal: 2095104, BlocksSynced: 2095104, BlocksSyncedPct: 0, BlocksSyncedFinishTime: 0, BlocksSyncedSpeed: 0, Devices: []string{"sda1", "sdb1"}}, "md126": {Name: "md126", ActivityState: "active", DisksActive: 2, DisksTotal: 2, DisksFailed: 0, DisksDown: 0, DisksSpare: 0, BlocksTotal: 1855870976, BlocksSynced: 1855870976, BlocksSyncedPct: 0, BlocksSyncedFinishTime: 0, BlocksSyncedSpeed: 0, Devices: []string{"sdb", "sdc"}}, "md219": {Name: "md219", ActivityState: "inactive", DisksTotal: 0, DisksFailed: 0, DisksActive: 0, DisksDown: 0, DisksSpare: 3, BlocksTotal: 7932, BlocksSynced: 7932, BlocksSyncedPct: 0, BlocksSyncedFinishTime: 0, BlocksSyncedSpeed: 0, Devices: []string{"sdc", "sda"}}, "md00": {Name: "md00", ActivityState: "active", DisksActive: 1, DisksTotal: 1, DisksFailed: 0, DisksDown: 0, DisksSpare: 0, BlocksTotal: 4186624, BlocksSynced: 4186624, BlocksSyncedPct: 0, BlocksSyncedFinishTime: 0, BlocksSyncedSpeed: 0, Devices: []string{"xvdb"}}, "md101": {Name: "md101", ActivityState: "active", DisksActive: 3, DisksTotal: 3, DisksFailed: 0, DisksDown: 0, DisksSpare: 0, BlocksTotal: 322560, BlocksSynced: 322560, BlocksSyncedPct: 0, BlocksSyncedFinishTime: 0, BlocksSyncedSpeed: 0, Devices: []string{"sdb", "sdd", "sdc"}}, "md201": {Name: "md201", ActivityState: "checking", DisksActive: 2, DisksTotal: 2, DisksFailed: 0, DisksDown: 0, DisksSpare: 0, BlocksTotal: 1993728, BlocksSynced: 114176, BlocksSyncedPct: 5.7, BlocksSyncedFinishTime: 0.2, BlocksSyncedSpeed: 114176, Devices: []string{"sda3", "sdb3"}}, } if want, have := len(refs), len(mdStats); want != have { t.Errorf("want %d parsed md-devices, have %d", want, have) } for _, md := range mdStats { if want, have := refs[md.Name], md; !cmp.Equal(want, have) { t.Errorf("%s: want %v, have %v", md.Name, want, have) } } } func TestInvalidMdstat(t *testing.T) { invalidMount := [][]byte{[]byte(` Personalities : [invalid] md3 : invalid 314159265 blocks 64k chunks unused devices: `), []byte(` md12 : active raid0 sdc2[0] sdd2[1] 3886394368 blocks super 1.2 512k chunks `)} for _, invalid := range invalidMount { _, err := parseMDStat(invalid) if err == nil { t.Fatalf("parsing of invalid reference file did not find any errors") } } } golang-github-prometheus-procfs-0.14.0/meminfo.go000066400000000000000000000272241461002754700220040ustar00rootroot00000000000000// 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. package procfs import ( "bufio" "bytes" "fmt" "io" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // Meminfo represents memory statistics. type Meminfo struct { // Total usable ram (i.e. physical ram minus a few reserved // bits and the kernel binary code) MemTotal *uint64 // The sum of LowFree+HighFree MemFree *uint64 // An estimate of how much memory is available for starting // new applications, without swapping. Calculated from // MemFree, SReclaimable, the size of the file LRU lists, and // the low watermarks in each zone. The estimate takes into // account that the system needs some page cache to function // well, and that not all reclaimable slab will be // reclaimable, due to items being in use. The impact of those // factors will vary from system to system. MemAvailable *uint64 // Relatively temporary storage for raw disk blocks shouldn't // get tremendously large (20MB or so) Buffers *uint64 Cached *uint64 // Memory that once was swapped out, is swapped back in but // still also is in the swapfile (if memory is needed it // doesn't need to be swapped out AGAIN because it is already // in the swapfile. This saves I/O) SwapCached *uint64 // Memory that has been used more recently and usually not // reclaimed unless absolutely necessary. Active *uint64 // Memory which has been less recently used. It is more // eligible to be reclaimed for other purposes Inactive *uint64 ActiveAnon *uint64 InactiveAnon *uint64 ActiveFile *uint64 InactiveFile *uint64 Unevictable *uint64 Mlocked *uint64 // total amount of swap space available SwapTotal *uint64 // Memory which has been evicted from RAM, and is temporarily // on the disk SwapFree *uint64 // Memory which is waiting to get written back to the disk Dirty *uint64 // Memory which is actively being written back to the disk Writeback *uint64 // Non-file backed pages mapped into userspace page tables AnonPages *uint64 // files which have been mapped, such as libraries Mapped *uint64 Shmem *uint64 // in-kernel data structures cache Slab *uint64 // Part of Slab, that might be reclaimed, such as caches SReclaimable *uint64 // Part of Slab, that cannot be reclaimed on memory pressure SUnreclaim *uint64 KernelStack *uint64 // amount of memory dedicated to the lowest level of page // tables. PageTables *uint64 // NFS pages sent to the server, but not yet committed to // stable storage NFSUnstable *uint64 // Memory used for block device "bounce buffers" Bounce *uint64 // Memory used by FUSE for temporary writeback buffers WritebackTmp *uint64 // Based on the overcommit ratio ('vm.overcommit_ratio'), // this is the total amount of memory currently available to // be allocated on the system. This limit is only adhered to // if strict overcommit accounting is enabled (mode 2 in // 'vm.overcommit_memory'). // The CommitLimit is calculated with the following formula: // CommitLimit = ([total RAM pages] - [total huge TLB pages]) * // overcommit_ratio / 100 + [total swap pages] // For example, on a system with 1G of physical RAM and 7G // of swap with a `vm.overcommit_ratio` of 30 it would // yield a CommitLimit of 7.3G. // For more details, see the memory overcommit documentation // in vm/overcommit-accounting. CommitLimit *uint64 // The amount of memory presently allocated on the system. // The committed memory is a sum of all of the memory which // has been allocated by processes, even if it has not been // "used" by them as of yet. A process which malloc()'s 1G // of memory, but only touches 300M of it will show up as // using 1G. This 1G is memory which has been "committed" to // by the VM and can be used at any time by the allocating // application. With strict overcommit enabled on the system // (mode 2 in 'vm.overcommit_memory'),allocations which would // exceed the CommitLimit (detailed above) will not be permitted. // This is useful if one needs to guarantee that processes will // not fail due to lack of memory once that memory has been // successfully allocated. CommittedAS *uint64 // total size of vmalloc memory area VmallocTotal *uint64 // amount of vmalloc area which is used VmallocUsed *uint64 // largest contiguous block of vmalloc area which is free VmallocChunk *uint64 Percpu *uint64 HardwareCorrupted *uint64 AnonHugePages *uint64 ShmemHugePages *uint64 ShmemPmdMapped *uint64 CmaTotal *uint64 CmaFree *uint64 HugePagesTotal *uint64 HugePagesFree *uint64 HugePagesRsvd *uint64 HugePagesSurp *uint64 Hugepagesize *uint64 DirectMap4k *uint64 DirectMap2M *uint64 DirectMap1G *uint64 // The struct fields below are the byte-normalized counterparts to the // existing struct fields. Values are normalized using the optional // unit field in the meminfo line. MemTotalBytes *uint64 MemFreeBytes *uint64 MemAvailableBytes *uint64 BuffersBytes *uint64 CachedBytes *uint64 SwapCachedBytes *uint64 ActiveBytes *uint64 InactiveBytes *uint64 ActiveAnonBytes *uint64 InactiveAnonBytes *uint64 ActiveFileBytes *uint64 InactiveFileBytes *uint64 UnevictableBytes *uint64 MlockedBytes *uint64 SwapTotalBytes *uint64 SwapFreeBytes *uint64 DirtyBytes *uint64 WritebackBytes *uint64 AnonPagesBytes *uint64 MappedBytes *uint64 ShmemBytes *uint64 SlabBytes *uint64 SReclaimableBytes *uint64 SUnreclaimBytes *uint64 KernelStackBytes *uint64 PageTablesBytes *uint64 NFSUnstableBytes *uint64 BounceBytes *uint64 WritebackTmpBytes *uint64 CommitLimitBytes *uint64 CommittedASBytes *uint64 VmallocTotalBytes *uint64 VmallocUsedBytes *uint64 VmallocChunkBytes *uint64 PercpuBytes *uint64 HardwareCorruptedBytes *uint64 AnonHugePagesBytes *uint64 ShmemHugePagesBytes *uint64 ShmemPmdMappedBytes *uint64 CmaTotalBytes *uint64 CmaFreeBytes *uint64 HugepagesizeBytes *uint64 DirectMap4kBytes *uint64 DirectMap2MBytes *uint64 DirectMap1GBytes *uint64 } // Meminfo returns an information about current kernel/system memory statistics. // See https://www.kernel.org/doc/Documentation/filesystems/proc.txt func (fs FS) Meminfo() (Meminfo, error) { b, err := util.ReadFileNoStat(fs.proc.Path("meminfo")) if err != nil { return Meminfo{}, err } m, err := parseMemInfo(bytes.NewReader(b)) if err != nil { return Meminfo{}, fmt.Errorf("%w: %w", ErrFileParse, err) } return *m, nil } func parseMemInfo(r io.Reader) (*Meminfo, error) { var m Meminfo s := bufio.NewScanner(r) for s.Scan() { fields := strings.Fields(s.Text()) var val, valBytes uint64 val, err := strconv.ParseUint(fields[1], 0, 64) if err != nil { return nil, err } switch len(fields) { case 2: // No unit present, use the parsed the value as bytes directly. valBytes = val case 3: // Unit present in optional 3rd field, convert it to // bytes. The only unit supported within the Linux // kernel is `kB`. if fields[2] != "kB" { return nil, fmt.Errorf("%w: Unsupported unit in optional 3rd field %q", ErrFileParse, fields[2]) } valBytes = 1024 * val default: return nil, fmt.Errorf("%w: Malformed line %q", ErrFileParse, s.Text()) } switch fields[0] { case "MemTotal:": m.MemTotal = &val m.MemTotalBytes = &valBytes case "MemFree:": m.MemFree = &val m.MemFreeBytes = &valBytes case "MemAvailable:": m.MemAvailable = &val m.MemAvailableBytes = &valBytes case "Buffers:": m.Buffers = &val m.BuffersBytes = &valBytes case "Cached:": m.Cached = &val m.CachedBytes = &valBytes case "SwapCached:": m.SwapCached = &val m.SwapCachedBytes = &valBytes case "Active:": m.Active = &val m.ActiveBytes = &valBytes case "Inactive:": m.Inactive = &val m.InactiveBytes = &valBytes case "Active(anon):": m.ActiveAnon = &val m.ActiveAnonBytes = &valBytes case "Inactive(anon):": m.InactiveAnon = &val m.InactiveAnonBytes = &valBytes case "Active(file):": m.ActiveFile = &val m.ActiveFileBytes = &valBytes case "Inactive(file):": m.InactiveFile = &val m.InactiveFileBytes = &valBytes case "Unevictable:": m.Unevictable = &val m.UnevictableBytes = &valBytes case "Mlocked:": m.Mlocked = &val m.MlockedBytes = &valBytes case "SwapTotal:": m.SwapTotal = &val m.SwapTotalBytes = &valBytes case "SwapFree:": m.SwapFree = &val m.SwapFreeBytes = &valBytes case "Dirty:": m.Dirty = &val m.DirtyBytes = &valBytes case "Writeback:": m.Writeback = &val m.WritebackBytes = &valBytes case "AnonPages:": m.AnonPages = &val m.AnonPagesBytes = &valBytes case "Mapped:": m.Mapped = &val m.MappedBytes = &valBytes case "Shmem:": m.Shmem = &val m.ShmemBytes = &valBytes case "Slab:": m.Slab = &val m.SlabBytes = &valBytes case "SReclaimable:": m.SReclaimable = &val m.SReclaimableBytes = &valBytes case "SUnreclaim:": m.SUnreclaim = &val m.SUnreclaimBytes = &valBytes case "KernelStack:": m.KernelStack = &val m.KernelStackBytes = &valBytes case "PageTables:": m.PageTables = &val m.PageTablesBytes = &valBytes case "NFS_Unstable:": m.NFSUnstable = &val m.NFSUnstableBytes = &valBytes case "Bounce:": m.Bounce = &val m.BounceBytes = &valBytes case "WritebackTmp:": m.WritebackTmp = &val m.WritebackTmpBytes = &valBytes case "CommitLimit:": m.CommitLimit = &val m.CommitLimitBytes = &valBytes case "Committed_AS:": m.CommittedAS = &val m.CommittedASBytes = &valBytes case "VmallocTotal:": m.VmallocTotal = &val m.VmallocTotalBytes = &valBytes case "VmallocUsed:": m.VmallocUsed = &val m.VmallocUsedBytes = &valBytes case "VmallocChunk:": m.VmallocChunk = &val m.VmallocChunkBytes = &valBytes case "Percpu:": m.Percpu = &val m.PercpuBytes = &valBytes case "HardwareCorrupted:": m.HardwareCorrupted = &val m.HardwareCorruptedBytes = &valBytes case "AnonHugePages:": m.AnonHugePages = &val m.AnonHugePagesBytes = &valBytes case "ShmemHugePages:": m.ShmemHugePages = &val m.ShmemHugePagesBytes = &valBytes case "ShmemPmdMapped:": m.ShmemPmdMapped = &val m.ShmemPmdMappedBytes = &valBytes case "CmaTotal:": m.CmaTotal = &val m.CmaTotalBytes = &valBytes case "CmaFree:": m.CmaFree = &val m.CmaFreeBytes = &valBytes case "HugePages_Total:": m.HugePagesTotal = &val case "HugePages_Free:": m.HugePagesFree = &val case "HugePages_Rsvd:": m.HugePagesRsvd = &val case "HugePages_Surp:": m.HugePagesSurp = &val case "Hugepagesize:": m.Hugepagesize = &val m.HugepagesizeBytes = &valBytes case "DirectMap4k:": m.DirectMap4k = &val m.DirectMap4kBytes = &valBytes case "DirectMap2M:": m.DirectMap2M = &val m.DirectMap2MBytes = &valBytes case "DirectMap1G:": m.DirectMap1G = &val m.DirectMap1GBytes = &valBytes } } return &m, nil } golang-github-prometheus-procfs-0.14.0/meminfo_test.go000066400000000000000000000104321461002754700230340ustar00rootroot00000000000000// 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. package procfs import ( "reflect" "testing" ) func TestMeminfo(t *testing.T) { expected := Meminfo{ MemTotal: newuint64(15666184), MemFree: newuint64(440324), Buffers: newuint64(1020128), Cached: newuint64(12007640), SwapCached: newuint64(0), Active: newuint64(6761276), Inactive: newuint64(6532708), ActiveAnon: newuint64(267256), InactiveAnon: newuint64(268), ActiveFile: newuint64(6494020), InactiveFile: newuint64(6532440), Unevictable: newuint64(0), Mlocked: newuint64(0), SwapTotal: newuint64(0), SwapFree: newuint64(0), Dirty: newuint64(768), Writeback: newuint64(0), AnonPages: newuint64(266216), Mapped: newuint64(44204), Shmem: newuint64(1308), Slab: newuint64(1807264), SReclaimable: newuint64(1738124), SUnreclaim: newuint64(69140), KernelStack: newuint64(1616), PageTables: newuint64(5288), NFSUnstable: newuint64(0), Bounce: newuint64(0), WritebackTmp: newuint64(0), CommitLimit: newuint64(7833092), CommittedAS: newuint64(530844), VmallocTotal: newuint64(34359738367), VmallocUsed: newuint64(36596), VmallocChunk: newuint64(34359637840), Percpu: newuint64(26176), HardwareCorrupted: newuint64(0), AnonHugePages: newuint64(12288), HugePagesTotal: newuint64(0), HugePagesFree: newuint64(0), HugePagesRsvd: newuint64(0), HugePagesSurp: newuint64(0), Hugepagesize: newuint64(2048), DirectMap4k: newuint64(91136), DirectMap2M: newuint64(16039936), MemTotalBytes: newuint64(16042172416), MemFreeBytes: newuint64(450891776), BuffersBytes: newuint64(1044611072), CachedBytes: newuint64(12295823360), SwapCachedBytes: newuint64(0), ActiveBytes: newuint64(6923546624), InactiveBytes: newuint64(6689492992), ActiveAnonBytes: newuint64(273670144), InactiveAnonBytes: newuint64(274432), ActiveFileBytes: newuint64(6649876480), InactiveFileBytes: newuint64(6689218560), UnevictableBytes: newuint64(0), MlockedBytes: newuint64(0), SwapTotalBytes: newuint64(0), SwapFreeBytes: newuint64(0), DirtyBytes: newuint64(786432), WritebackBytes: newuint64(0), AnonPagesBytes: newuint64(272605184), MappedBytes: newuint64(45264896), ShmemBytes: newuint64(1339392), SlabBytes: newuint64(1850638336), SReclaimableBytes: newuint64(1779838976), SUnreclaimBytes: newuint64(70799360), KernelStackBytes: newuint64(1654784), PageTablesBytes: newuint64(5414912), NFSUnstableBytes: newuint64(0), BounceBytes: newuint64(0), WritebackTmpBytes: newuint64(0), CommitLimitBytes: newuint64(8021086208), CommittedASBytes: newuint64(543584256), VmallocTotalBytes: newuint64(35184372087808), VmallocUsedBytes: newuint64(37474304), VmallocChunkBytes: newuint64(35184269148160), PercpuBytes: newuint64(26804224), HardwareCorruptedBytes: newuint64(0), AnonHugePagesBytes: newuint64(12582912), HugepagesizeBytes: newuint64(2097152), DirectMap4kBytes: newuint64(93323264), DirectMap2MBytes: newuint64(16424894464), } have, err := getProcFixtures(t).Meminfo() if err != nil { t.Fatal(err) } if !reflect.DeepEqual(have, expected) { t.Logf("have: %+v", have) t.Logf("expected: %+v", expected) t.Errorf("structs are not equal") } } golang-github-prometheus-procfs-0.14.0/mountinfo.go000066400000000000000000000124771461002754700223740ustar00rootroot00000000000000// 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. package procfs import ( "bufio" "bytes" "fmt" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // A MountInfo is a type that describes the details, options // for each mount, parsed from /proc/self/mountinfo. // The fields described in each entry of /proc/self/mountinfo // 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 // The value of `st_dev` for the files on this FS MajorMinorVer string // The pathname of the directory in the FS that forms // the root for this mount Root string // The pathname of the mount point relative to the root MountPoint string // Mount options Options map[string]string // Zero or more optional fields OptionalFields map[string]string // The Filesystem type FSType string // FS specific information or "none" Source string // Superblock options SuperOptions map[string]string } // Reads each line of the mountinfo file, and returns a list of formatted MountInfo structs. func parseMountInfo(info []byte) ([]*MountInfo, error) { mounts := []*MountInfo{} scanner := bufio.NewScanner(bytes.NewReader(info)) for scanner.Scan() { mountString := scanner.Text() parsedMounts, err := parseMountInfoString(mountString) if err != nil { return nil, err } mounts = append(mounts, parsedMounts) } err := scanner.Err() return mounts, err } // Parses a mountinfo file line, and converts it to a MountInfo struct. // An important check here is to see if the hyphen separator, as if it does not exist, // it means that the line is malformed. func parseMountInfoString(mountString string) (*MountInfo, error) { var err error mountInfo := strings.Split(mountString, " ") mountInfoLength := len(mountInfo) if mountInfoLength < 10 { return nil, fmt.Errorf("%w: Too few fields in mount string: %s", ErrFileParse, mountString) } if mountInfo[mountInfoLength-4] != "-" { return nil, fmt.Errorf("%w: couldn't find separator in expected field: %s", ErrFileParse, mountInfo[mountInfoLength-4]) } mount := &MountInfo{ MajorMinorVer: mountInfo[2], Root: mountInfo[3], MountPoint: mountInfo[4], Options: mountOptionsParser(mountInfo[5]), OptionalFields: nil, FSType: mountInfo[mountInfoLength-3], Source: mountInfo[mountInfoLength-2], SuperOptions: mountOptionsParser(mountInfo[mountInfoLength-1]), } mount.MountID, err = strconv.Atoi(mountInfo[0]) if err != nil { return nil, fmt.Errorf("%w: mount ID: %q", ErrFileParse, mount.MountID) } mount.ParentID, err = strconv.Atoi(mountInfo[1]) if err != nil { return nil, fmt.Errorf("%w: parent ID: %q", ErrFileParse, mount.ParentID) } // Has optional fields, which is a space separated list of values. // Example: shared:2 master:7 if mountInfo[6] != "" { mount.OptionalFields, err = mountOptionsParseOptionalFields(mountInfo[6 : mountInfoLength-4]) if err != nil { return nil, fmt.Errorf("%w: %w", ErrFileParse, err) } } return mount, nil } // mountOptionsIsValidField checks a string against a valid list of optional fields keys. func mountOptionsIsValidField(s string) bool { switch s { case "shared", "master", "propagate_from", "unbindable": return true } return false } // mountOptionsParseOptionalFields parses a list of optional fields strings into a double map of strings. func mountOptionsParseOptionalFields(o []string) (map[string]string, error) { optionalFields := make(map[string]string) for _, field := range o { optionSplit := strings.SplitN(field, ":", 2) value := "" if len(optionSplit) == 2 { value = optionSplit[1] } if mountOptionsIsValidField(optionSplit[0]) { optionalFields[optionSplit[0]] = value } } return optionalFields, nil } // mountOptionsParser parses the mount options, superblock options. func mountOptionsParser(mountOptions string) map[string]string { opts := make(map[string]string) options := strings.Split(mountOptions, ",") for _, opt := range options { splitOption := strings.Split(opt, "=") if len(splitOption) < 2 { key := splitOption[0] opts[key] = "" } else { key, value := splitOption[0], splitOption[1] opts[key] = value } } return opts } // GetMounts retrieves mountinfo information from `/proc/self/mountinfo`. func GetMounts() ([]*MountInfo, error) { data, err := util.ReadFileNoStat("/proc/self/mountinfo") if err != nil { return nil, err } return parseMountInfo(data) } // GetProcMounts retrieves mountinfo information from a processes' `/proc//mountinfo`. func GetProcMounts(pid int) ([]*MountInfo, error) { data, err := util.ReadFileNoStat(fmt.Sprintf("/proc/%d/mountinfo", pid)) if err != nil { return nil, err } return parseMountInfo(data) } golang-github-prometheus-procfs-0.14.0/mountinfo_test.go000066400000000000000000000155641461002754700234330ustar00rootroot00000000000000// 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. package procfs import ( "reflect" "testing" ) func TestMountInfo(t *testing.T) { tests := []struct { name string s string mount *MountInfo invalid bool }{ { name: "Regular sysfs mounted at /sys", s: "16 21 0:16 / /sys rw,nosuid,nodev,noexec,relatime shared:7 - sysfs sysfs rw", invalid: false, mount: &MountInfo{ MountID: 16, ParentID: 21, MajorMinorVer: "0:16", Root: "/", MountPoint: "/sys", Options: map[string]string{"rw": "", "nosuid": "", "nodev": "", "noexec": "", "relatime": ""}, OptionalFields: map[string]string{"shared": "7"}, FSType: "sysfs", Source: "sysfs", SuperOptions: map[string]string{"rw": ""}, }, }, { name: "Not enough information", s: "hello", invalid: true, }, { name: "Tmpfs mounted at /run", s: "225 20 0:39 / /run/user/112 rw,nosuid,nodev,relatime shared:177 - tmpfs tmpfs rw,size=405096k,mode=700,uid=112,gid=116", mount: &MountInfo{ MountID: 225, ParentID: 20, MajorMinorVer: "0:39", Root: "/", MountPoint: "/run/user/112", Options: map[string]string{"rw": "", "nosuid": "", "nodev": "", "relatime": ""}, OptionalFields: map[string]string{"shared": "177"}, FSType: "tmpfs", Source: "tmpfs", SuperOptions: map[string]string{"rw": "", "size": "405096k", "mode": "700", "uid": "112", "gid": "116"}, }, invalid: false, }, { name: "Tmpfs mounted at /run, but no optional values", s: "225 20 0:39 / /run/user/112 rw,nosuid,nodev,relatime - tmpfs tmpfs rw,size=405096k,mode=700,uid=112,gid=116", mount: &MountInfo{ MountID: 225, ParentID: 20, MajorMinorVer: "0:39", Root: "/", MountPoint: "/run/user/112", Options: map[string]string{"rw": "", "nosuid": "", "nodev": "", "relatime": ""}, OptionalFields: nil, FSType: "tmpfs", Source: "tmpfs", SuperOptions: map[string]string{"rw": "", "size": "405096k", "mode": "700", "uid": "112", "gid": "116"}, }, invalid: false, }, { name: "Tmpfs mounted at /run, with multiple optional values", s: "225 20 0:39 / /run/user/112 rw,nosuid,nodev,relatime shared:177 master:8 - tmpfs tmpfs rw,size=405096k,mode=700,uid=112,gid=116", mount: &MountInfo{ MountID: 225, ParentID: 20, MajorMinorVer: "0:39", Root: "/", MountPoint: "/run/user/112", Options: map[string]string{"rw": "", "nosuid": "", "nodev": "", "relatime": ""}, OptionalFields: map[string]string{"shared": "177", "master": "8"}, FSType: "tmpfs", Source: "tmpfs", SuperOptions: map[string]string{"rw": "", "size": "405096k", "mode": "700", "uid": "112", "gid": "116"}, }, invalid: false, }, { name: "Tmpfs mounted at /run, with a mixture of valid and invalid optional values", s: "225 20 0:39 / /run/user/112 rw,nosuid,nodev,relatime shared:177 master:8 foo:bar - tmpfs tmpfs rw,size=405096k,mode=700,uid=112,gid=116", mount: &MountInfo{ MountID: 225, ParentID: 20, MajorMinorVer: "0:39", Root: "/", MountPoint: "/run/user/112", Options: map[string]string{"rw": "", "nosuid": "", "nodev": "", "relatime": ""}, OptionalFields: map[string]string{"shared": "177", "master": "8"}, FSType: "tmpfs", Source: "tmpfs", SuperOptions: map[string]string{"rw": "", "size": "405096k", "mode": "700", "uid": "112", "gid": "116"}, }, invalid: false, }, { name: "CIFS mounted at /with/a-hyphen", s: "454 29 0:87 / /with/a-hyphen rw,relatime shared:255 - cifs //remote-storage/Path rw,vers=3.1.1,cache=strict,username=user,uid=1000,forceuid,gid=0,noforcegid,addr=127.0.0.1,file_mode=0755,dir_mode=0755,soft,nounix,serverino,mapposix,echo_interval=60,actimeo=1", mount: &MountInfo{ MountID: 454, ParentID: 29, MajorMinorVer: "0:87", Root: "/", MountPoint: "/with/a-hyphen", Options: map[string]string{"rw": "", "relatime": ""}, OptionalFields: map[string]string{"shared": "255"}, FSType: "cifs", Source: "//remote-storage/Path", SuperOptions: map[string]string{"rw": "", "vers": "3.1.1", "cache": "strict", "username": "user", "uid": "1000", "forceuid": "", "gid": "0", "noforcegid": "", "addr": "127.0.0.1", "file_mode": "0755", "dir_mode": "0755", "soft": "", "nounix": "", "serverino": "", "mapposix": "", "echo_interval": "60", "actimeo": "1"}, }, invalid: false, }, { name: "Docker overlay with 10 fields (no optional fields)", s: "137 45 253:2 /lib/docker/overlay2 /var/lib/docker/overlay2 rw,relatime - ext4 /dev/mapper/vg0-lv_var rw,data=ordered", mount: &MountInfo{ MountID: 137, ParentID: 45, MajorMinorVer: "253:2", Root: "/lib/docker/overlay2", MountPoint: "/var/lib/docker/overlay2", Options: map[string]string{"rw": "", "relatime": ""}, OptionalFields: map[string]string{}, FSType: "ext4", Source: "/dev/mapper/vg0-lv_var", SuperOptions: map[string]string{"rw": "", "data": "ordered"}, }, }, { name: "bind chroot bind mount with 10 fields (no optional fields)", s: "157 47 253:2 /etc/named /var/named/chroot/etc/named rw,relatime - ext4 /dev/mapper/vg0-lv_root rw,data=ordered", mount: &MountInfo{ MountID: 157, ParentID: 47, MajorMinorVer: "253:2", Root: "/etc/named", MountPoint: "/var/named/chroot/etc/named", Options: map[string]string{"rw": "", "relatime": ""}, OptionalFields: map[string]string{}, FSType: "ext4", Source: "/dev/mapper/vg0-lv_root", SuperOptions: map[string]string{"rw": "", "data": "ordered"}, }, }, } for i, test := range tests { t.Logf("[%02d] test %q", i, test.name) mount, err := parseMountInfoString(test.s) if test.invalid && err == nil { t.Error("expected an error, but none occurred") } if !test.invalid && err != nil { t.Errorf("unexpected error: %v", err) } if want, have := test.mount, mount; !reflect.DeepEqual(want, have) { t.Errorf("mounts:\nwant:\n%+v\nhave:\n%+v", want, have) } } } golang-github-prometheus-procfs-0.14.0/mountstats.go000066400000000000000000000521101461002754700225630ustar00rootroot00000000000000// Copyright 2018 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. package procfs // While implementing parsing of /proc/[pid]/mountstats, this blog was used // heavily as a reference: // https://utcc.utoronto.ca/~cks/space/blog/linux/NFSMountstatsIndex // // Special thanks to Chris Siebenmann for all of his posts explaining the // various statistics available for NFS. import ( "bufio" "fmt" "io" "strconv" "strings" "time" ) // Constants shared between multiple functions. const ( deviceEntryLen = 8 fieldBytesLen = 8 fieldEventsLen = 27 statVersion10 = "1.0" statVersion11 = "1.1" fieldTransport10TCPLen = 10 fieldTransport10UDPLen = 7 fieldTransport11TCPLen = 13 fieldTransport11UDPLen = 10 // kernel version >= 4.14 MaxLen // See: https://elixir.bootlin.com/linux/v6.4.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L393 fieldTransport11RDMAMaxLen = 28 // kernel version <= 4.2 MinLen // See: https://elixir.bootlin.com/linux/v4.2.8/source/net/sunrpc/xprtrdma/xprt_rdma.h#L331 fieldTransport11RDMAMinLen = 20 ) // A Mount is a device mount parsed from /proc/[pid]/mountstats. type Mount struct { // Name of the device. Device string // The mount point of the device. Mount string // The filesystem type used by the device. Type string // If available additional statistics related to this Mount. // Use a type assertion to determine if additional statistics are available. Stats MountStats } // A MountStats is a type which contains detailed statistics for a specific // type of Mount. type MountStats interface { mountStats() } // A MountStatsNFS is a MountStats implementation for NFSv3 and v4 mounts. type MountStatsNFS struct { // The version of statistics provided. StatVersion string // The mount options of the NFS mount. Opts map[string]string // The age of the NFS mount. Age time.Duration // Statistics related to byte counters for various operations. Bytes NFSBytesStats // Statistics related to various NFS event occurrences. Events NFSEventsStats // Statistics broken down by filesystem operation. Operations []NFSOperationStats // Statistics about the NFS RPC transport. Transport NFSTransportStats } // mountStats implements MountStats. func (m MountStatsNFS) mountStats() {} // A NFSBytesStats contains statistics about the number of bytes read and written // by an NFS client to and from an NFS server. type NFSBytesStats struct { // Number of bytes read using the read() syscall. Read uint64 // Number of bytes written using the write() syscall. Write uint64 // Number of bytes read using the read() syscall in O_DIRECT mode. DirectRead uint64 // Number of bytes written using the write() syscall in O_DIRECT mode. DirectWrite uint64 // Number of bytes read from the NFS server, in total. ReadTotal uint64 // Number of bytes written to the NFS server, in total. WriteTotal uint64 // Number of pages read directly via mmap()'d files. ReadPages uint64 // Number of pages written directly via mmap()'d files. WritePages uint64 } // A NFSEventsStats contains statistics about NFS event occurrences. type NFSEventsStats struct { // Number of times cached inode attributes are re-validated from the server. InodeRevalidate uint64 // Number of times cached dentry nodes are re-validated from the server. DnodeRevalidate uint64 // Number of times an inode cache is cleared. DataInvalidate uint64 // Number of times cached inode attributes are invalidated. AttributeInvalidate uint64 // Number of times files or directories have been open()'d. VFSOpen uint64 // Number of times a directory lookup has occurred. VFSLookup uint64 // Number of times permissions have been checked. VFSAccess uint64 // Number of updates (and potential writes) to pages. VFSUpdatePage uint64 // Number of pages read directly via mmap()'d files. VFSReadPage uint64 // Number of times a group of pages have been read. VFSReadPages uint64 // Number of pages written directly via mmap()'d files. VFSWritePage uint64 // Number of times a group of pages have been written. VFSWritePages uint64 // Number of times directory entries have been read with getdents(). VFSGetdents uint64 // Number of times attributes have been set on inodes. VFSSetattr uint64 // Number of pending writes that have been forcefully flushed to the server. VFSFlush uint64 // Number of times fsync() has been called on directories and files. VFSFsync uint64 // Number of times locking has been attempted on a file. VFSLock uint64 // Number of times files have been closed and released. VFSFileRelease uint64 // Unknown. Possibly unused. CongestionWait uint64 // Number of times files have been truncated. Truncation uint64 // Number of times a file has been grown due to writes beyond its existing end. WriteExtension uint64 // Number of times a file was removed while still open by another process. SillyRename uint64 // Number of times the NFS server gave less data than expected while reading. ShortRead uint64 // Number of times the NFS server wrote less data than expected while writing. ShortWrite uint64 // Number of times the NFS server indicated EJUKEBOX; retrieving data from // offline storage. JukeboxDelay uint64 // Number of NFS v4.1+ pNFS reads. PNFSRead uint64 // Number of NFS v4.1+ pNFS writes. PNFSWrite uint64 } // A NFSOperationStats contains statistics for a single operation. type NFSOperationStats struct { // The name of the operation. Operation string // Number of requests performed for this operation. Requests uint64 // Number of times an actual RPC request has been transmitted for this operation. Transmissions uint64 // Number of times a request has had a major timeout. MajorTimeouts uint64 // Number of bytes sent for this operation, including RPC headers and payload. BytesSent uint64 // Number of bytes received for this operation, including RPC headers and payload. BytesReceived uint64 // Duration all requests spent queued for transmission before they were sent. CumulativeQueueMilliseconds uint64 // Duration it took to get a reply back after the request was transmitted. CumulativeTotalResponseMilliseconds uint64 // Duration from when a request was enqueued to when it was completely handled. CumulativeTotalRequestMilliseconds uint64 // The count of operations that complete with tk_status < 0. These statuses usually indicate error conditions. Errors uint64 } // A NFSTransportStats contains statistics for the NFS mount RPC requests and // responses. type NFSTransportStats struct { // The transport protocol used for the NFS mount. Protocol string // The local port used for the NFS mount. Port uint64 // Number of times the client has had to establish a connection from scratch // to the NFS server. Bind uint64 // Number of times the client has made a TCP connection to the NFS server. Connect uint64 // Duration (in jiffies, a kernel internal unit of time) the NFS mount has // spent waiting for connections to the server to be established. ConnectIdleTime uint64 // Duration since the NFS mount last saw any RPC traffic. IdleTimeSeconds uint64 // Number of RPC requests for this mount sent to the NFS server. Sends uint64 // Number of RPC responses for this mount received from the NFS server. Receives uint64 // Number of times the NFS server sent a response with a transaction ID // unknown to this client. BadTransactionIDs uint64 // A running counter, incremented on each request as the current difference // ebetween sends and receives. CumulativeActiveRequests uint64 // A running counter, incremented on each request by the current backlog // queue size. CumulativeBacklog uint64 // Stats below only available with stat version 1.1. // Maximum number of simultaneously active RPC requests ever used. MaximumRPCSlotsUsed uint64 // A running counter, incremented on each request as the current size of the // sending queue. CumulativeSendingQueue uint64 // A running counter, incremented on each request as the current size of the // pending queue. CumulativePendingQueue uint64 // Stats below only available with stat version 1.1. // Transport over RDMA // accessed when sending a call ReadChunkCount uint64 WriteChunkCount uint64 ReplyChunkCount uint64 TotalRdmaRequest uint64 // rarely accessed error counters PullupCopyCount uint64 HardwayRegisterCount uint64 FailedMarshalCount uint64 BadReplyCount uint64 MrsRecovered uint64 MrsOrphaned uint64 MrsAllocated uint64 EmptySendctxQ uint64 // accessed when receiving a reply TotalRdmaReply uint64 FixupCopyCount uint64 ReplyWaitsForSend uint64 LocalInvNeeded uint64 NomsgCallCount uint64 BcallCount uint64 } // parseMountStats parses a /proc/[pid]/mountstats file and returns a slice // of Mount structures containing detailed information about each mount. // If available, statistics for each mount are parsed as well. func parseMountStats(r io.Reader) ([]*Mount, error) { const ( device = "device" statVersionPrefix = "statvers=" nfs3Type = "nfs" nfs4Type = "nfs4" ) var mounts []*Mount s := bufio.NewScanner(r) for s.Scan() { // Only look for device entries in this function ss := strings.Fields(string(s.Bytes())) if len(ss) == 0 || ss[0] != device { continue } m, err := parseMount(ss) if err != nil { return nil, err } // Does this mount also possess statistics information? if len(ss) > deviceEntryLen { // Only NFSv3 and v4 are supported for parsing statistics if m.Type != nfs3Type && m.Type != nfs4Type { return nil, fmt.Errorf("%w: Cannot parse MountStats for %q", ErrFileParse, m.Type) } statVersion := strings.TrimPrefix(ss[8], statVersionPrefix) stats, err := parseMountStatsNFS(s, statVersion) if err != nil { return nil, err } m.Stats = stats } mounts = append(mounts, m) } return mounts, s.Err() } // parseMount parses an entry in /proc/[pid]/mountstats in the format: // // device [device] mounted on [mount] with fstype [type] func parseMount(ss []string) (*Mount, error) { if len(ss) < deviceEntryLen { return nil, fmt.Errorf("%w: Invalid device %q", ErrFileParse, ss) } // Check for specific words appearing at specific indices to ensure // the format is consistent with what we expect format := []struct { i int s string }{ {i: 0, s: "device"}, {i: 2, s: "mounted"}, {i: 3, s: "on"}, {i: 5, s: "with"}, {i: 6, s: "fstype"}, } for _, f := range format { if ss[f.i] != f.s { return nil, fmt.Errorf("%w: Invalid device %q", ErrFileParse, ss) } } return &Mount{ Device: ss[1], Mount: ss[4], Type: ss[7], }, nil } // parseMountStatsNFS parses a MountStatsNFS by scanning additional information // related to NFS statistics. func parseMountStatsNFS(s *bufio.Scanner, statVersion string) (*MountStatsNFS, error) { // Field indicators for parsing specific types of data const ( fieldOpts = "opts:" fieldAge = "age:" fieldBytes = "bytes:" fieldEvents = "events:" fieldPerOpStats = "per-op" fieldTransport = "xprt:" ) stats := &MountStatsNFS{ StatVersion: statVersion, } for s.Scan() { ss := strings.Fields(string(s.Bytes())) if len(ss) == 0 { break } switch ss[0] { case fieldOpts: if len(ss) < 2 { return nil, fmt.Errorf("%w: Incomplete information for NFS stats: %v", ErrFileParse, ss) } if stats.Opts == nil { stats.Opts = map[string]string{} } for _, opt := range strings.Split(ss[1], ",") { split := strings.Split(opt, "=") if len(split) == 2 { stats.Opts[split[0]] = split[1] } else { stats.Opts[opt] = "" } } case fieldAge: if len(ss) < 2 { return nil, fmt.Errorf("%w: Incomplete information for NFS stats: %v", ErrFileParse, ss) } // Age integer is in seconds d, err := time.ParseDuration(ss[1] + "s") if err != nil { return nil, err } stats.Age = d case fieldBytes: if len(ss) < 2 { return nil, fmt.Errorf("%w: Incomplete information for NFS stats: %v", ErrFileParse, ss) } bstats, err := parseNFSBytesStats(ss[1:]) if err != nil { return nil, err } stats.Bytes = *bstats case fieldEvents: if len(ss) < 2 { return nil, fmt.Errorf("%w: Incomplete information for NFS events: %v", ErrFileParse, ss) } estats, err := parseNFSEventsStats(ss[1:]) if err != nil { return nil, err } stats.Events = *estats case fieldTransport: if len(ss) < 3 { return nil, fmt.Errorf("%w: Incomplete information for NFS transport stats: %v", ErrFileParse, ss) } tstats, err := parseNFSTransportStats(ss[1:], statVersion) if err != nil { return nil, err } stats.Transport = *tstats } // When encountering "per-operation statistics", we must break this // loop and parse them separately to ensure we can terminate parsing // before reaching another device entry; hence why this 'if' statement // is not just another switch case if ss[0] == fieldPerOpStats { break } } if err := s.Err(); err != nil { return nil, err } // NFS per-operation stats appear last before the next device entry perOpStats, err := parseNFSOperationStats(s) if err != nil { return nil, err } stats.Operations = perOpStats return stats, nil } // parseNFSBytesStats parses a NFSBytesStats line using an input set of // integer fields. func parseNFSBytesStats(ss []string) (*NFSBytesStats, error) { if len(ss) != fieldBytesLen { return nil, fmt.Errorf("%w: Invalid NFS bytes stats: %v", ErrFileParse, ss) } ns := make([]uint64, 0, fieldBytesLen) for _, s := range ss { n, err := strconv.ParseUint(s, 10, 64) if err != nil { return nil, err } ns = append(ns, n) } return &NFSBytesStats{ Read: ns[0], Write: ns[1], DirectRead: ns[2], DirectWrite: ns[3], ReadTotal: ns[4], WriteTotal: ns[5], ReadPages: ns[6], WritePages: ns[7], }, nil } // parseNFSEventsStats parses a NFSEventsStats line using an input set of // integer fields. func parseNFSEventsStats(ss []string) (*NFSEventsStats, error) { if len(ss) != fieldEventsLen { return nil, fmt.Errorf("%w: invalid NFS events stats: %v", ErrFileParse, ss) } ns := make([]uint64, 0, fieldEventsLen) for _, s := range ss { n, err := strconv.ParseUint(s, 10, 64) if err != nil { return nil, err } ns = append(ns, n) } return &NFSEventsStats{ InodeRevalidate: ns[0], DnodeRevalidate: ns[1], DataInvalidate: ns[2], AttributeInvalidate: ns[3], VFSOpen: ns[4], VFSLookup: ns[5], VFSAccess: ns[6], VFSUpdatePage: ns[7], VFSReadPage: ns[8], VFSReadPages: ns[9], VFSWritePage: ns[10], VFSWritePages: ns[11], VFSGetdents: ns[12], VFSSetattr: ns[13], VFSFlush: ns[14], VFSFsync: ns[15], VFSLock: ns[16], VFSFileRelease: ns[17], CongestionWait: ns[18], Truncation: ns[19], WriteExtension: ns[20], SillyRename: ns[21], ShortRead: ns[22], ShortWrite: ns[23], JukeboxDelay: ns[24], PNFSRead: ns[25], PNFSWrite: ns[26], }, nil } // parseNFSOperationStats parses a slice of NFSOperationStats by scanning // additional information about per-operation statistics until an empty // line is reached. func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) { const ( // Minimum number of expected fields in each per-operation statistics set minFields = 9 ) var ops []NFSOperationStats for s.Scan() { ss := strings.Fields(string(s.Bytes())) if len(ss) == 0 { // Must break when reading a blank line after per-operation stats to // enable top-level function to parse the next device entry break } if len(ss) < minFields { return nil, fmt.Errorf("%w: invalid NFS per-operations stats: %v", ErrFileParse, ss) } // Skip string operation name for integers ns := make([]uint64, 0, minFields-1) for _, st := range ss[1:] { n, err := strconv.ParseUint(st, 10, 64) if err != nil { return nil, err } ns = append(ns, n) } opStats := NFSOperationStats{ Operation: strings.TrimSuffix(ss[0], ":"), Requests: ns[0], Transmissions: ns[1], MajorTimeouts: ns[2], BytesSent: ns[3], BytesReceived: ns[4], CumulativeQueueMilliseconds: ns[5], CumulativeTotalResponseMilliseconds: ns[6], CumulativeTotalRequestMilliseconds: ns[7], } if len(ns) > 8 { opStats.Errors = ns[8] } ops = append(ops, opStats) } return ops, s.Err() } // parseNFSTransportStats parses a NFSTransportStats line using an input set of // integer fields matched to a specific stats version. func parseNFSTransportStats(ss []string, statVersion string) (*NFSTransportStats, error) { // Extract the protocol field. It is the only string value in the line protocol := ss[0] ss = ss[1:] switch statVersion { case statVersion10: var expectedLength int if protocol == "tcp" { expectedLength = fieldTransport10TCPLen } else if protocol == "udp" { expectedLength = fieldTransport10UDPLen } else { return nil, fmt.Errorf("%w: Invalid NFS protocol \"%s\" in stats 1.0 statement: %v", ErrFileParse, protocol, ss) } if len(ss) != expectedLength { return nil, fmt.Errorf("%w: Invalid NFS transport stats 1.0 statement: %v", ErrFileParse, ss) } case statVersion11: var expectedLength int if protocol == "tcp" { expectedLength = fieldTransport11TCPLen } else if protocol == "udp" { expectedLength = fieldTransport11UDPLen } else if protocol == "rdma" { expectedLength = fieldTransport11RDMAMinLen } else { return nil, fmt.Errorf("%w: invalid NFS protocol \"%s\" in stats 1.1 statement: %v", ErrFileParse, protocol, ss) } if (len(ss) != expectedLength && (protocol == "tcp" || protocol == "udp")) || (protocol == "rdma" && len(ss) < expectedLength) { return nil, fmt.Errorf("%w: invalid NFS transport stats 1.1 statement: %v, protocol: %v", ErrFileParse, ss, protocol) } default: return nil, fmt.Errorf("%w: Unrecognized NFS transport stats version: %q, protocol: %v", ErrFileParse, statVersion, protocol) } // Allocate enough for v1.1 stats since zero value for v1.1 stats will be okay // in a v1.0 response. Since the stat length is bigger for TCP stats, we use // the TCP length here. // // Note: slice length must be set to length of v1.1 stats to avoid a panic when // only v1.0 stats are present. // See: https://github.com/prometheus/node_exporter/issues/571. // // Note: NFS Over RDMA slice length is fieldTransport11RDMAMaxLen ns := make([]uint64, fieldTransport11RDMAMaxLen+3) for i, s := range ss { n, err := strconv.ParseUint(s, 10, 64) if err != nil { return nil, err } ns[i] = n } // The fields differ depending on the transport protocol (TCP or UDP) // From https://utcc.utoronto.ca/%7Ecks/space/blog/linux/NFSMountstatsXprt // // For the udp RPC transport there is no connection count, connect idle time, // or idle time (fields #3, #4, and #5); all other fields are the same. So // we set them to 0 here. if protocol == "udp" { ns = append(ns[:2], append(make([]uint64, 3), ns[2:]...)...) } else if protocol == "tcp" { ns = append(ns[:fieldTransport11TCPLen], make([]uint64, fieldTransport11RDMAMaxLen-fieldTransport11TCPLen+3)...) } else if protocol == "rdma" { ns = append(ns[:fieldTransport10TCPLen], append(make([]uint64, 3), ns[fieldTransport10TCPLen:]...)...) } return &NFSTransportStats{ // NFS xprt over tcp or udp Protocol: protocol, Port: ns[0], Bind: ns[1], Connect: ns[2], ConnectIdleTime: ns[3], IdleTimeSeconds: ns[4], Sends: ns[5], Receives: ns[6], BadTransactionIDs: ns[7], CumulativeActiveRequests: ns[8], CumulativeBacklog: ns[9], // NFS xprt over tcp or udp // And statVersion 1.1 MaximumRPCSlotsUsed: ns[10], CumulativeSendingQueue: ns[11], CumulativePendingQueue: ns[12], // NFS xprt over rdma // And stat Version 1.1 ReadChunkCount: ns[13], WriteChunkCount: ns[14], ReplyChunkCount: ns[15], TotalRdmaRequest: ns[16], PullupCopyCount: ns[17], HardwayRegisterCount: ns[18], FailedMarshalCount: ns[19], BadReplyCount: ns[20], MrsRecovered: ns[21], MrsOrphaned: ns[22], MrsAllocated: ns[23], EmptySendctxQ: ns[24], TotalRdmaReply: ns[25], FixupCopyCount: ns[26], ReplyWaitsForSend: ns[27], LocalInvNeeded: ns[28], NomsgCallCount: ns[29], BcallCount: ns[30], }, nil } golang-github-prometheus-procfs-0.14.0/mountstats_test.go000066400000000000000000000640261461002754700236330ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "fmt" "reflect" "strings" "testing" "time" ) func TestMountStats(t *testing.T) { tests := []struct { name string s string mounts []*Mount invalid bool }{ { name: "no devices", s: `hello`, }, { name: "device has too few fields", s: `device foo`, invalid: true, }, { name: "device incorrect format", s: `device rootfs BAD on / with fstype rootfs`, invalid: true, }, { name: "device incorrect format", s: `device rootfs mounted BAD / with fstype rootfs`, invalid: true, }, { name: "device incorrect format", s: `device rootfs mounted on / BAD fstype rootfs`, invalid: true, }, { name: "device incorrect format", s: `device rootfs mounted on / with BAD rootfs`, invalid: true, }, { name: "device rootfs cannot have stats", s: `device rootfs mounted on / with fstype rootfs stats`, invalid: true, }, { name: "NFSv4 device with too little info", s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nopts:", invalid: true, }, { name: "NFSv4 device with bad bytes", s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nbytes: 0", invalid: true, }, { name: "NFSv4 device with bad events", s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nevents: 0", invalid: true, }, { name: "NFSv4 device with bad per-op stats", s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nper-op statistics\nFOO 0", invalid: true, }, { name: "NFSv4 device with bad transport stats", s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nxprt: tcp", invalid: true, }, { name: "NFSv4 device with bad transport version", s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=foo\nxprt: tcp 0", invalid: true, }, { name: "NFSv4 device with bad transport stats version 1.0", s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.0\nxprt: tcp 0 0 0 0 0 0 0 0 0 0 0 0 0", invalid: true, }, { name: "NFSv4 device with bad transport stats version 1.1", s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nxprt: tcp 0 0 0 0 0 0 0 0 0 0", invalid: true, }, { name: "NFSv3 device with bad transport protocol", s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nxprt: tcpx 0 0 0 0 0 0 0 0 0 0", invalid: true, }, { name: "NFSv3 device using TCP with transport stats version 1.0 OK", s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs statvers=1.0\nxprt: tcp 1 2 3 4 5 6 7 8 9 10", mounts: []*Mount{{ Device: "192.168.1.1:/srv", Mount: "/mnt/nfs", Type: "nfs", Stats: &MountStatsNFS{ StatVersion: "1.0", Transport: NFSTransportStats{ Protocol: "tcp", Port: 1, Bind: 2, Connect: 3, ConnectIdleTime: 4, IdleTimeSeconds: 5, Sends: 6, Receives: 7, BadTransactionIDs: 8, CumulativeActiveRequests: 9, CumulativeBacklog: 10, MaximumRPCSlotsUsed: 0, // these three are not CumulativeSendingQueue: 0, // present in statvers=1.0 CumulativePendingQueue: 0, // }, }, }}, }, { name: "NFSv3 device using UDP with transport stats version 1.0 OK", s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs statvers=1.0\nxprt: udp 1 2 3 4 5 6 7", mounts: []*Mount{{ Device: "192.168.1.1:/srv", Mount: "/mnt/nfs", Type: "nfs", Stats: &MountStatsNFS{ StatVersion: "1.0", Transport: NFSTransportStats{ Protocol: "udp", Port: 1, Bind: 2, Connect: 0, ConnectIdleTime: 0, IdleTimeSeconds: 0, Sends: 3, Receives: 4, BadTransactionIDs: 5, CumulativeActiveRequests: 6, CumulativeBacklog: 7, MaximumRPCSlotsUsed: 0, // these three are not CumulativeSendingQueue: 0, // present in statvers=1.0 CumulativePendingQueue: 0, // }, }, }}, }, { name: "NFSv3 device using TCP with transport stats version 1.1 OK", s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs statvers=1.1\nxprt: tcp 1 2 3 4 5 6 7 8 9 10 11 12 13", mounts: []*Mount{{ Device: "192.168.1.1:/srv", Mount: "/mnt/nfs", Type: "nfs", Stats: &MountStatsNFS{ StatVersion: "1.1", Transport: NFSTransportStats{ Protocol: "tcp", Port: 1, Bind: 2, Connect: 3, ConnectIdleTime: 4, IdleTimeSeconds: 5, Sends: 6, Receives: 7, BadTransactionIDs: 8, CumulativeActiveRequests: 9, CumulativeBacklog: 10, MaximumRPCSlotsUsed: 11, CumulativeSendingQueue: 12, CumulativePendingQueue: 13, }, }, }}, }, { name: "NFSv3 device using UDP with transport stats version 1.1 OK", s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs statvers=1.1\nxprt: udp 1 2 3 4 5 6 7 8 9 10", mounts: []*Mount{{ Device: "192.168.1.1:/srv", Mount: "/mnt/nfs", Type: "nfs", Stats: &MountStatsNFS{ StatVersion: "1.1", Transport: NFSTransportStats{ Protocol: "udp", Port: 1, Bind: 2, Connect: 0, // these three are not ConnectIdleTime: 0, // present for UDP IdleTimeSeconds: 0, // Sends: 3, Receives: 4, BadTransactionIDs: 5, CumulativeActiveRequests: 6, CumulativeBacklog: 7, MaximumRPCSlotsUsed: 8, CumulativeSendingQueue: 9, CumulativePendingQueue: 10, }, }, }}, }, { name: "NFSv3 device with mountaddr OK", s: "device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs statvers=1.1\nopts: rw,vers=3,mountaddr=192.168.1.1,proto=udp\n", mounts: []*Mount{{ Device: "192.168.1.1:/srv", Mount: "/mnt/nfs", Type: "nfs", Stats: &MountStatsNFS{ StatVersion: "1.1", Opts: map[string]string{"rw": "", "vers": "3", "mountaddr": "192.168.1.1", "proto": "udp"}, }, }}, }, { name: "device rootfs OK", s: `device rootfs mounted on / with fstype rootfs`, mounts: []*Mount{{ Device: "rootfs", Mount: "/", Type: "rootfs", }}, }, { name: "NFSv3 device with minimal stats OK", s: `device 192.168.1.1:/srv mounted on /mnt/nfs with fstype nfs statvers=1.1`, mounts: []*Mount{{ Device: "192.168.1.1:/srv", Mount: "/mnt/nfs", Type: "nfs", Stats: &MountStatsNFS{ StatVersion: "1.1", }, }}, }, { name: "NFS4.1 device with multiline impl_id OK", s: "device 192.168.0.1:/srv mounted on /mnt/nfs with fstype nfs4 statvers=1.1\nopts: rw,vers=4.1,rsize=131072,wsize=131072,namlen=255,acregmin=3,acregmax=60,acdirmin=30,acdirmax=60,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.0.2,fsc,local_lock=none\nage: 1234567\nimpl_id: name='FreeBSD 11.2-STABLE #0 r325575+c9231c7d6bd(HEAD): Mon Nov 18 22:46:47 UTC 2019\nuser@host:/path/to/something'\n,domain='something.org',date='1293840000,0'", mounts: []*Mount{{ Device: "192.168.0.1:/srv", Mount: "/mnt/nfs", Type: "nfs4", Stats: &MountStatsNFS{ StatVersion: "1.1", Opts: map[string]string{"rw": "", "vers": "4.1", "rsize": "131072", "wsize": "131072", "namlen": "255", "acregmin": "3", "acregmax": "60", "acdirmin": "30", "acdirmax": "60", "fsc": "", "hard": "", "proto": "tcp", "timeo": "600", "retrans": "2", "sec": "sys", "clientaddr": "192.168.0.2", "local_lock": "none", }, Age: 1234567 * time.Second, }, }}, }, { name: "fixtures/proc OK", mounts: []*Mount{ { Device: "rootfs", Mount: "/", Type: "rootfs", }, { Device: "sysfs", Mount: "/sys", Type: "sysfs", }, { Device: "proc", Mount: "/proc", Type: "proc", }, { Device: "/dev/sda1", Mount: "/", Type: "ext4", }, { Device: "192.168.1.1:/srv/test", Mount: "/mnt/nfs/test", Type: "nfs4", Stats: &MountStatsNFS{ StatVersion: "1.1", Opts: map[string]string{"rw": "", "vers": "4.0", "rsize": "1048576", "wsize": "1048576", "namlen": "255", "acregmin": "3", "acregmax": "60", "acdirmin": "30", "acdirmax": "60", "hard": "", "proto": "tcp", "port": "0", "timeo": "600", "retrans": "2", "sec": "sys", "mountaddr": "192.168.1.1", "clientaddr": "192.168.1.5", "local_lock": "none", }, Age: 13968 * time.Second, Bytes: NFSBytesStats{ Read: 1207640230, ReadTotal: 1210214218, ReadPages: 295483, }, Events: NFSEventsStats{ InodeRevalidate: 52, DnodeRevalidate: 226, VFSOpen: 1, VFSLookup: 13, VFSAccess: 398, VFSReadPages: 331, VFSWritePages: 47, VFSFlush: 77, VFSFileRelease: 77, }, Operations: []NFSOperationStats{ { Operation: "NULL", }, { Operation: "READ", Requests: 1298, Transmissions: 1298, BytesSent: 207680, BytesReceived: 1210292152, CumulativeQueueMilliseconds: 6, CumulativeTotalResponseMilliseconds: 79386, CumulativeTotalRequestMilliseconds: 79407, }, { Operation: "WRITE", }, { Operation: "ACCESS", Requests: 2927395007, Transmissions: 2927394995, BytesSent: 526931094212, BytesReceived: 362996810236, CumulativeQueueMilliseconds: 18446743919241604546, CumulativeTotalResponseMilliseconds: 1667369447, CumulativeTotalRequestMilliseconds: 1953587717, }, }, Transport: NFSTransportStats{ Protocol: "tcp", Port: 832, Connect: 1, IdleTimeSeconds: 11, Sends: 6428, Receives: 6428, CumulativeActiveRequests: 12154, MaximumRPCSlotsUsed: 24, CumulativeSendingQueue: 26, CumulativePendingQueue: 5726, }, }, }, }, }, { name: "NFS xprt over rdma proto", s: `device : mounted on with fstype nfs statvers=1.1 opts: ro,vers=3,rsize=1048576,wsize=1048576,namlen=255,acregmin=120,acregmax=120,acdirmin=120,acdirmax=120,hard,nocto,forcerdirplus,proto=rdma,nconnect=16,port=20049,timeo=600,retrans=2,sec=sys,mountaddr=172.16.40.20,mountvers=3,mountport=0,mountproto=tcp,local_lock=none age: 1270876 caps: caps=0xf,wtmult=4096,dtsize=131072,bsize=0,namlen=255 sec: flavor=1,pseudoflavor=1 events: 512052 36601115 0 68 1498583 16514 38815015 0 41584 2654459933 0 0 0 0 1527715 0 0 1498575 0 0 0 0 0 0 0 0 0 bytes: 3104202770327296 0 0 0 2013200952170479 0 491504202537 0 RPC iostats version: 1.1 p/v: 100003/3 (nfs) xprt: rdma 0 0 5808 62 0 494490723 494490687 36 10032963746 1282789 107150285 1226637531 2673889 135120843409861 135119397156505 266368832 75716996 0 7853 0 0 0 0 119328 1336431717 0 96 per-op statistics NULL: 16 16 0 640 384 320 11 331 0 `, mounts: []*Mount{{ Device: ":", Mount: "", Type: "nfs", Stats: &MountStatsNFS{ StatVersion: "1.1", Opts: map[string]string{"acdirmax": "120", "acdirmin": "120", "acregmax": "120", "acregmin": "120", "forcerdirplus": "", "hard": "", "local_lock": "none", "mountaddr": "172.16.40.20", "mountport": "0", "mountproto": "tcp", "mountvers": "3", "namlen": "255", "nconnect": "16", "nocto": "", "port": "20049", "proto": "rdma", "retrans": "2", "ro": "", "rsize": "1048576", "sec": "sys", "timeo": "600", "vers": "3", "wsize": "1048576"}, Age: 1270876 * time.Second, Bytes: NFSBytesStats{ Read: 3104202770327296, ReadTotal: 2013200952170479, ReadPages: 491504202537, }, Events: NFSEventsStats{ InodeRevalidate: 512052, DnodeRevalidate: 36601115, AttributeInvalidate: 68, VFSOpen: 1498583, VFSLookup: 16514, VFSAccess: 38815015, VFSReadPage: 41584, VFSReadPages: 2654459933, VFSFlush: 1527715, VFSFileRelease: 1498575, }, Operations: []NFSOperationStats{ { Operation: "NULL", Requests: 16, Transmissions: 16, MajorTimeouts: 0, BytesSent: 640, BytesReceived: 384, CumulativeQueueMilliseconds: 320, CumulativeTotalResponseMilliseconds: 11, CumulativeTotalRequestMilliseconds: 331, Errors: 0, }, }, Transport: NFSTransportStats{ Protocol: "rdma", Port: 0, Bind: 0, Connect: 5808, ConnectIdleTime: 62, IdleTimeSeconds: 0, Sends: 494490723, Receives: 494490687, BadTransactionIDs: 36, CumulativeActiveRequests: 10032963746, CumulativeBacklog: 1282789, MaximumRPCSlotsUsed: 0, CumulativeSendingQueue: 0, CumulativePendingQueue: 0, ReadChunkCount: 107150285, WriteChunkCount: 1226637531, ReplyChunkCount: 2673889, TotalRdmaRequest: 135120843409861, PullupCopyCount: 135119397156505, HardwayRegisterCount: 266368832, FailedMarshalCount: 75716996, BadReplyCount: 0, MrsRecovered: 7853, MrsOrphaned: 0, MrsAllocated: 0, EmptySendctxQ: 0, TotalRdmaReply: 0, FixupCopyCount: 119328, ReplyWaitsForSend: 1336431717, LocalInvNeeded: 0, NomsgCallCount: 96, BcallCount: 0, }, }, }}, }, } for i, tt := range tests { t.Logf("[%02d] test %q", i, tt.name) var mounts []*Mount var err error if tt.s != "" { mounts, err = parseMountStats(strings.NewReader(tt.s)) } else { proc, e := getProcFixtures(t).Proc(26231) if e != nil { t.Fatalf("failed to create proc: %v", err) } mounts, err = proc.MountStats() } if tt.invalid && err == nil { t.Error("expected an error, but none occurred") } if !tt.invalid && err != nil { t.Errorf("unexpected error: %v", err) } if want, have := tt.mounts, mounts; !reflect.DeepEqual(want, have) { t.Errorf("mounts:\nwant:\n%v\nhave:\n%v", mountsStr(want), mountsStr(have)) } } } func mountsStr(mounts []*Mount) string { var out string for i, m := range mounts { out += fmt.Sprintf("[%d] %q on %q (%q)", i, m.Device, m.Mount, m.Type) stats, ok := m.Stats.(*MountStatsNFS) if !ok { out += "\n" continue } out += fmt.Sprintf("\n\t- opts: %s", stats.Opts) out += fmt.Sprintf("\n\t- v%s, age: %s", stats.StatVersion, stats.Age) out += fmt.Sprintf("\n\t- bytes: %v", stats.Bytes) out += fmt.Sprintf("\n\t- events: %v", stats.Events) out += fmt.Sprintf("\n\t- transport: %v", stats.Transport) out += "\n\t- per-operation stats:" for _, o := range stats.Operations { out += fmt.Sprintf("\n\t\t- %v", o) } out += "\n" } return out } func TestMountStatsExtendedOperationStats(t *testing.T) { r := strings.NewReader(extendedOpsExampleMountstats) _, err := parseMountStats(r) if err != nil { t.Errorf("failed to parse mount stats with extended per-op statistics: %v", err) } } const ( extendedOpsExampleMountstats = ` device fs.example.com:/volume4/apps/home-automation/node-red-data mounted on /var/lib/kubelet/pods/1c2215a7-0d92-4df5-83ce-a807bcc2f8c8/volumes/kubernetes.io~nfs/home-automation--node-red-data--pv0001 with fstype nfs4 statvers=1.1 opts: rw,vers=4.1,rsize=131072,wsize=131072,namlen=255,acregmin=3,acregmax=60,acdirmin=30,acdirmax=60,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.1.191,local_lock=none age: 83520 impl_id: name='',domain='',date='0,0' caps: caps=0x3fff7,wtmult=512,dtsize=32768,bsize=0,namlen=255 nfsv4: bm0=0xfdffafff,bm1=0xf9be3e,bm2=0x800,acl=0x0,sessions,pnfs=not configured,lease_time=90,lease_expired=0 sec: flavor=1,pseudoflavor=1 events: 52472 472680 16671 57552 2104 9565 749555 9568641 168 24103 1 267134 3350 20097 116581 18214 43757 111141 0 28 9563845 34 0 0 0 0 0 bytes: 2021340783 39056395530 0 0 1788561151 39087991255 442605 9557343 RPC iostats version: 1.1 p/v: 100003/4 (nfs) xprt: tcp 940 0 2 0 1 938505 938504 0 12756069 0 32 254729 10823602 per-op statistics NULL: 1 1 0 44 24 0 0 0 0 READ: 34096 34096 0 7103096 1792122744 2272 464840 467945 0 WRITE: 322308 322308 0 39161277084 56725504 401718334 10139998 411864389 0 COMMIT: 12541 12541 0 2709896 1304264 342 7179 7819 0 OPEN: 12637 12637 0 3923256 4659940 871 57185 58251 394 OPEN_CONFIRM: 0 0 0 0 0 0 0 0 0 OPEN_NOATTR: 98741 98741 0 25656212 31630800 3366 77710 82693 0 OPEN_DOWNGRADE: 0 0 0 0 0 0 0 0 0 CLOSE: 87075 87075 0 18778608 15308496 2026 49131 52399 116 SETATTR: 24576 24576 0 5825876 6522260 643 34384 35650 0 FSINFO: 1 1 0 168 152 0 0 0 0 RENEW: 0 0 0 0 0 0 0 0 0 SETCLIENTID: 0 0 0 0 0 0 0 0 0 SETCLIENTID_CONFIRM: 0 0 0 0 0 0 0 0 0 LOCK: 22512 22512 0 5417628 2521312 1088 17407 18794 2 LOCKT: 0 0 0 0 0 0 0 0 0 LOCKU: 21247 21247 0 4589352 2379664 315 8409 9003 0 ACCESS: 1466 1466 0 298160 246288 22 1394 1492 0 GETATTR: 52480 52480 0 10015464 12694076 2930 30069 34502 0 LOOKUP: 11727 11727 0 2518200 2886376 272 16935 17662 3546 LOOKUP_ROOT: 0 0 0 0 0 0 0 0 0 REMOVE: 833 833 0 172236 95268 15 4566 4617 68 RENAME: 11431 11431 0 3150708 1737512 211 52649 53091 0 LINK: 1 1 0 288 292 0 0 0 0 SYMLINK: 0 0 0 0 0 0 0 0 0 CREATE: 77 77 0 18292 23496 0 363 371 11 PATHCONF: 1 1 0 164 116 0 0 0 0 STATFS: 7420 7420 0 1394960 1187200 144 4672 4975 0 READLINK: 4 4 0 704 488 0 1 1 0 READDIR: 1353 1353 0 304024 2902928 11 4326 4411 0 SERVER_CAPS: 9 9 0 1548 1476 0 3 3 0 DELEGRETURN: 232 232 0 48896 37120 811 300 1115 0 GETACL: 0 0 0 0 0 0 0 0 0 SETACL: 0 0 0 0 0 0 0 0 0 FS_LOCATIONS: 0 0 0 0 0 0 0 0 0 RELEASE_LOCKOWNER: 0 0 0 0 0 0 0 0 0 SECINFO: 0 0 0 0 0 0 0 0 0 FSID_PRESENT: 0 0 0 0 0 0 0 0 0 EXCHANGE_ID: 2 2 0 464 200 0 0 0 0 CREATE_SESSION: 1 1 0 192 124 0 0 0 0 DESTROY_SESSION: 0 0 0 0 0 0 0 0 0 SEQUENCE: 0 0 0 0 0 0 0 0 0 GET_LEASE_TIME: 0 0 0 0 0 0 0 0 0 RECLAIM_COMPLETE: 1 1 0 124 88 0 81 81 0 LAYOUTGET: 0 0 0 0 0 0 0 0 0 GETDEVICEINFO: 0 0 0 0 0 0 0 0 0 LAYOUTCOMMIT: 0 0 0 0 0 0 0 0 0 LAYOUTRETURN: 0 0 0 0 0 0 0 0 0 SECINFO_NO_NAME: 0 0 0 0 0 0 0 0 0 TEST_STATEID: 0 0 0 0 0 0 0 0 0 FREE_STATEID: 10413 10413 0 1416168 916344 147 3518 3871 10413 GETDEVICELIST: 0 0 0 0 0 0 0 0 0 BIND_CONN_TO_SESSION: 0 0 0 0 0 0 0 0 0 DESTROY_CLIENTID: 0 0 0 0 0 0 0 0 0 SEEK: 0 0 0 0 0 0 0 0 0 ALLOCATE: 0 0 0 0 0 0 0 0 0 DEALLOCATE: 0 0 0 0 0 0 0 0 0 LAYOUTSTATS: 0 0 0 0 0 0 0 0 0 CLONE: 0 0 0 0 0 0 0 0 0 COPY: 0 0 0 0 0 0 0 0 0 OFFLOAD_CANCEL: 0 0 0 0 0 0 0 0 0 LOOKUPP: 0 0 0 0 0 0 0 0 0 LAYOUTERROR: 0 0 0 0 0 0 0 0 0 ` extendedRDMAExampleALLMountstats = `device : mounted on with fstype nfs statvers=1.1 opts: ro,vers=3,rsize=1048576,wsize=1048576,namlen=255,acregmin=120,acregmax=120,acdirmin=120,acdirmax=120,hard,nocto,forcerdirplus,proto=rdma,nconnect=16,port=20049,timeo=600,retrans=2,sec=sys,mountaddr=172.16.40.20,mountvers=3,mountport=0,mountproto=tcp,local_lock=none age: 1270876 caps: caps=0xf,wtmult=4096,dtsize=131072,bsize=0,namlen=255 sec: flavor=1,pseudoflavor=1 events: 512052 36601115 0 68 1498583 16514 38815015 0 41584 2654459933 0 0 0 0 1527715 0 0 1498575 0 0 0 0 0 0 0 0 0 bytes: 3104202770327296 0 0 0 2013200952170479 0 491504202537 0 RPC iostats version: 1.1 p/v: 100003/3 (nfs) xprt: rdma 0 0 5808 62 0 494490723 494490687 36 10032963746 1282789 107150285 1226637531 2673889 135120843409861 135119397156505 266368832 75716996 0 7853 0 0 0 0 119328 1336431717 0 96 xprt: rdma 0 0 14094 145 0 492392334 492392307 27 7078693624 2509627 105561370 1280878332 2659446 142218924010291 142217463504063 276368040 94761838 0 7610 0 0 0 0 207977 1389069860 0 103 xprt: rdma 0 0 16107 156 0 522755125 522755092 33 9119562599 1147699 109077860 1491898147 2566003 167152062826463 167149287506014 284931680 83011025 0 6229 0 0 0 0 221408 1603518232 0 82 xprt: rdma 0 0 7808 82 0 441542046 441542010 36 7226132207 2519174 111096004 955223347 2676765 105741904708009 105740125663595 275613584 80373159 0 8893 0 0 0 0 149479 1068962768 0 76 xprt: rdma 0 0 15018 167 0 508091827 508091764 63 19817677255 36702583 108265928 1258185459 2438516 138247436686102 138246196289594 270162080 74962306 0 13328 0 0 0 0 268433 1368837472 0 66 xprt: rdma 0 0 14321 149 0 530246310 530246275 35 9723190432 2392024 111099700 1494204555 2589805 166691166581904 166689567426908 289995492 85067377 0 8010 0 0 0 0 214511 1607864447 0 100 xprt: rdma 0 0 7863 84 0 459019689 459019642 47 11809253102 1716688 111825219 1032758664 2564226 114416685286438 114414936423706 290494252 73702102 0 6927 0 0 0 0 134453 1147121864 0 79 xprt: rdma 0 0 7702 84 3 497598986 497598931 55 11816221496 3924722 106922130 1382063307 2506108 153967067193941 153965665472218 286222584 84094006 0 5875 0 0 0 0 127347 1491469045 0 66 xprt: rdma 0 0 18341 202 0 477721151 477721073 78 15204400959 40562626 106645745 1291616653 3091375 144533696686651 144529688231163 278135800 73821525 0 6795 0 0 0 0 251097 1401327563 0 64 xprt: rdma 0 0 8228 90 4 453155092 453155063 29 7884786894 1591225 112197590 1026006338 2742688 114591819605673 114590175821191 275541944 85857259 0 7487 0 0 0 0 143044 1140917892 0 76 xprt: rdma 0 0 7843 83 0 446480377 446480324 53 12267986428 2958997 111971246 963162784 2693433 107176282309753 107174637802555 290269096 101100410 0 7825 0 0 0 0 141735 1077797328 0 83 xprt: rdma 0 0 7582 86 0 423315608 423315567 41 10197484604 2076993 109207538 785978455 2650354 86090211449474 86088475571312 279912524 87676008 0 7491 0 0 0 0 137533 897807641 0 101 xprt: rdma 0 0 7767 84 0 482538465 482538424 41 8935200479 1344778 112200583 1192341640 2644896 132860698423762 132858881459050 273354060 75337030 0 5941 0 0 0 0 127842 1307164736 0 97 xprt: rdma 0 0 14526 148 2 537745063 537745007 56 20756072620 3970332320 109539564 1363647371 2503250 148793734936250 148791264145401 291888720 90344151 0 7471 0 0 0 0 211057 1475661285 0 82 xprt: rdma 0 0 14300 151 0 495357347 495357316 31 8703101643 1451809 112315311 1303804607 2620502 145680743007170 145678880292235 288046696 98018259 0 7241 0 0 0 0 209396 1418712657 0 139 xprt: rdma 0 0 7700 82 0 466611083 466611050 33 8540498291 4082864 114740300 1059770596 2523155 117376668239921 117375375683167 260927576 78437075 0 6691 0 0 0 0 130878 1177008175 1 76 per-op statistics NULL: 16 16 0 640 384 320 11 331 0 GETATTR: 512052 512052 0 79823516 57349824 107131 612667 751847 0 SETATTR: 0 0 0 0 0 0 0 0 0 LOOKUP: 16713 16713 0 3040536 3706344 560 17488 20232 346 ACCESS: 211705 211705 0 33860920 25404600 37059 229754 283822 0 READLINK: 0 0 0 0 0 0 0 0 0 READ: 2654501510 2654501510 0 445911966900 2013540728551504 6347457114 31407021389 37927280438 0 WRITE: 0 0 0 0 0 0 0 0 0 CREATE: 0 0 0 0 0 0 0 0 0 MKDIR: 0 0 0 0 0 0 0 0 0 SYMLINK: 0 0 0 0 0 0 0 0 0 MKNOD: 0 0 0 0 0 0 0 0 0 REMOVE: 0 0 0 0 0 0 0 0 0 RMDIR: 0 0 0 0 0 0 0 0 0 RENAME: 0 0 0 0 0 0 0 0 0 LINK: 0 0 0 0 0 0 0 0 0 READDIR: 0 0 0 0 0 0 0 0 0 READDIRPLUS: 0 0 0 0 0 0 0 0 0 FSSTAT: 56356 56356 0 6243572 9467808 82068 74356 159001 0 FSINFO: 2 2 0 184 328 0 0 0 0 PATHCONF: 1 1 0 92 140 0 0 0 0 COMMIT: 0 0 0 0 0 0 0 0 0 ` ) func TestMountStatsExtendedRDMAStats(t *testing.T) { r := strings.NewReader(extendedRDMAExampleALLMountstats) _, err := parseMountStats(r) if err != nil { t.Errorf("failed to parse mount stats with extended RDMA statistics: %v", err) } } golang-github-prometheus-procfs-0.14.0/net_conntrackstat.go000066400000000000000000000065241461002754700240760ustar00rootroot00000000000000// Copyright 2020 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. package procfs import ( "bufio" "bytes" "fmt" "io" "strings" "github.com/prometheus/procfs/internal/util" ) // A ConntrackStatEntry represents one line from net/stat/nf_conntrack // and contains netfilter conntrack statistics at one CPU core. type ConntrackStatEntry struct { Entries uint64 Searched uint64 Found uint64 New uint64 Invalid uint64 Ignore uint64 Delete uint64 DeleteList uint64 Insert uint64 InsertFailed uint64 Drop uint64 EarlyDrop uint64 SearchRestart uint64 } // ConntrackStat retrieves netfilter's conntrack statistics, split by CPU cores. func (fs FS) ConntrackStat() ([]ConntrackStatEntry, error) { return readConntrackStat(fs.proc.Path("net", "stat", "nf_conntrack")) } // Parses a slice of ConntrackStatEntries from the given filepath. func readConntrackStat(path string) ([]ConntrackStatEntry, error) { // This file is small and can be read with one syscall. b, err := util.ReadFileNoStat(path) if err != nil { // Do not wrap this error so the caller can detect os.IsNotExist and // similar conditions. return nil, err } stat, err := parseConntrackStat(bytes.NewReader(b)) if err != nil { return nil, fmt.Errorf("%w: Cannot read file: %v: %w", ErrFileRead, path, err) } return stat, nil } // Reads the contents of a conntrack statistics file and parses a slice of ConntrackStatEntries. func parseConntrackStat(r io.Reader) ([]ConntrackStatEntry, error) { var entries []ConntrackStatEntry scanner := bufio.NewScanner(r) scanner.Scan() for scanner.Scan() { fields := strings.Fields(scanner.Text()) conntrackEntry, err := parseConntrackStatEntry(fields) if err != nil { return nil, err } entries = append(entries, *conntrackEntry) } return entries, nil } // Parses a ConntrackStatEntry from given array of fields. func parseConntrackStatEntry(fields []string) (*ConntrackStatEntry, error) { entries, err := util.ParseHexUint64s(fields) if err != nil { return nil, fmt.Errorf("%w: Cannot parse entry: %d: %w", ErrFileParse, entries, err) } numEntries := len(entries) if numEntries < 16 || numEntries > 17 { return nil, fmt.Errorf("%w: invalid conntrackstat entry, invalid number of fields: %d", ErrFileParse, numEntries) } stats := &ConntrackStatEntry{ Entries: *entries[0], Searched: *entries[1], Found: *entries[2], New: *entries[3], Invalid: *entries[4], Ignore: *entries[5], Delete: *entries[6], DeleteList: *entries[7], Insert: *entries[8], InsertFailed: *entries[9], Drop: *entries[10], EarlyDrop: *entries[11], } // Ignore missing search_restart on Linux < 2.6.35. if numEntries == 17 { stats.SearchRestart = *entries[16] } return stats, nil } golang-github-prometheus-procfs-0.14.0/net_conntrackstat_test.go000066400000000000000000000070031461002754700251260ustar00rootroot00000000000000// Copyright 2020 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. package procfs import ( "bytes" "reflect" "testing" ) func TestParseConntrackStat(t *testing.T) { var nfConntrackStat = []byte(`entries searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete search_restart 00000021 00000000 00000000 00000000 00000003 0000588a 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000021 00000000 00000000 00000000 00000002 000056a4 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000002 00000021 00000000 00000000 00000000 00000001 000058d4 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001 00000021 00000000 00000000 00000000 0000002f 00005688 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000004 `) r := bytes.NewReader(nfConntrackStat) have, err := parseConntrackStat(r) if err != nil { t.Fatal(err) } want := []ConntrackStatEntry{ ConntrackStatEntry{ Entries: 33, Found: 0, Invalid: 3, Ignore: 22666, Insert: 0, InsertFailed: 0, Drop: 0, EarlyDrop: 0, SearchRestart: 0, }, ConntrackStatEntry{ Entries: 33, Found: 0, Invalid: 2, Ignore: 22180, Insert: 0, InsertFailed: 0, Drop: 0, EarlyDrop: 0, SearchRestart: 2, }, ConntrackStatEntry{ Entries: 33, Found: 0, Invalid: 1, Ignore: 22740, Insert: 0, InsertFailed: 0, Drop: 0, EarlyDrop: 0, SearchRestart: 1, }, ConntrackStatEntry{ Entries: 33, Found: 0, Invalid: 47, Ignore: 22152, Insert: 0, InsertFailed: 0, Drop: 0, EarlyDrop: 0, SearchRestart: 4, }, } if !reflect.DeepEqual(want, have) { t.Errorf("want %v, have %v", want, have) } } func TestParseOldConntrackStat(t *testing.T) { var nfConntrackStat = []byte(`entries searched found new invalid ignore delete delete_list insert insert_failed drop early_drop icmp_error expect_new expect_create expect_delete 0000002b 0003159f 02e6786a 00142562 0001bf93 00e1a051 00142537 000b8fe0 000b900b 00000000 00000000 00000000 0001b46a 00000000 00000000 00000000 `) r := bytes.NewReader(nfConntrackStat) have, err := parseConntrackStat(r) if err != nil { t.Fatal(err) } want := []ConntrackStatEntry{ ConntrackStatEntry{ Entries: 43, Searched: 202143, Found: 48658538, New: 1320290, Invalid: 114579, Ignore: 14786641, Delete: 1320247, DeleteList: 757728, Insert: 757771, InsertFailed: 0, Drop: 0, EarlyDrop: 0, SearchRestart: 0, }, } if !reflect.DeepEqual(want, have) { t.Errorf("want %v, have %v", want, have) } } golang-github-prometheus-procfs-0.14.0/net_dev.go000066400000000000000000000145531461002754700217770ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "bufio" "errors" "os" "sort" "strconv" "strings" ) // NetDevLine is single line parsed from /proc/net/dev or /proc/[pid]/net/dev. type NetDevLine struct { Name string `json:"name"` // The name of the interface. RxBytes uint64 `json:"rx_bytes"` // Cumulative count of bytes received. RxPackets uint64 `json:"rx_packets"` // Cumulative count of packets received. RxErrors uint64 `json:"rx_errors"` // Cumulative count of receive errors encountered. RxDropped uint64 `json:"rx_dropped"` // Cumulative count of packets dropped while receiving. RxFIFO uint64 `json:"rx_fifo"` // Cumulative count of FIFO buffer errors. RxFrame uint64 `json:"rx_frame"` // Cumulative count of packet framing errors. RxCompressed uint64 `json:"rx_compressed"` // Cumulative count of compressed packets received by the device driver. RxMulticast uint64 `json:"rx_multicast"` // Cumulative count of multicast frames received by the device driver. TxBytes uint64 `json:"tx_bytes"` // Cumulative count of bytes transmitted. TxPackets uint64 `json:"tx_packets"` // Cumulative count of packets transmitted. TxErrors uint64 `json:"tx_errors"` // Cumulative count of transmit errors encountered. TxDropped uint64 `json:"tx_dropped"` // Cumulative count of packets dropped while transmitting. TxFIFO uint64 `json:"tx_fifo"` // Cumulative count of FIFO buffer errors. TxCollisions uint64 `json:"tx_collisions"` // Cumulative count of collisions detected on the interface. TxCarrier uint64 `json:"tx_carrier"` // Cumulative count of carrier losses detected by the device driver. TxCompressed uint64 `json:"tx_compressed"` // Cumulative count of compressed packets transmitted by the device driver. } // NetDev is parsed from /proc/net/dev or /proc/[pid]/net/dev. The map keys // are interface names. type NetDev map[string]NetDevLine // NetDev returns kernel/system statistics read from /proc/net/dev. func (fs FS) NetDev() (NetDev, error) { return newNetDev(fs.proc.Path("net/dev")) } // NetDev returns kernel/system statistics read from /proc/[pid]/net/dev. func (p Proc) NetDev() (NetDev, error) { return newNetDev(p.path("net/dev")) } // newNetDev creates a new NetDev from the contents of the given file. func newNetDev(file string) (NetDev, error) { f, err := os.Open(file) if err != nil { return NetDev{}, err } defer f.Close() netDev := NetDev{} s := bufio.NewScanner(f) for n := 0; s.Scan(); n++ { // Skip the 2 header lines. if n < 2 { continue } line, err := netDev.parseLine(s.Text()) if err != nil { return netDev, err } netDev[line.Name] = *line } return netDev, s.Err() } // parseLine parses a single line from the /proc/net/dev file. Header lines // must be filtered prior to calling this method. func (netDev NetDev) parseLine(rawLine string) (*NetDevLine, error) { idx := strings.LastIndex(rawLine, ":") if idx == -1 { return nil, errors.New("invalid net/dev line, missing colon") } fields := strings.Fields(strings.TrimSpace(rawLine[idx+1:])) var err error line := &NetDevLine{} // Interface Name line.Name = strings.TrimSpace(rawLine[:idx]) if line.Name == "" { return nil, errors.New("invalid net/dev line, empty interface name") } // RX line.RxBytes, err = strconv.ParseUint(fields[0], 10, 64) if err != nil { return nil, err } line.RxPackets, err = strconv.ParseUint(fields[1], 10, 64) if err != nil { return nil, err } line.RxErrors, err = strconv.ParseUint(fields[2], 10, 64) if err != nil { return nil, err } line.RxDropped, err = strconv.ParseUint(fields[3], 10, 64) if err != nil { return nil, err } line.RxFIFO, err = strconv.ParseUint(fields[4], 10, 64) if err != nil { return nil, err } line.RxFrame, err = strconv.ParseUint(fields[5], 10, 64) if err != nil { return nil, err } line.RxCompressed, err = strconv.ParseUint(fields[6], 10, 64) if err != nil { return nil, err } line.RxMulticast, err = strconv.ParseUint(fields[7], 10, 64) if err != nil { return nil, err } // TX line.TxBytes, err = strconv.ParseUint(fields[8], 10, 64) if err != nil { return nil, err } line.TxPackets, err = strconv.ParseUint(fields[9], 10, 64) if err != nil { return nil, err } line.TxErrors, err = strconv.ParseUint(fields[10], 10, 64) if err != nil { return nil, err } line.TxDropped, err = strconv.ParseUint(fields[11], 10, 64) if err != nil { return nil, err } line.TxFIFO, err = strconv.ParseUint(fields[12], 10, 64) if err != nil { return nil, err } line.TxCollisions, err = strconv.ParseUint(fields[13], 10, 64) if err != nil { return nil, err } line.TxCarrier, err = strconv.ParseUint(fields[14], 10, 64) if err != nil { return nil, err } line.TxCompressed, err = strconv.ParseUint(fields[15], 10, 64) if err != nil { return nil, err } return line, nil } // Total aggregates the values across interfaces and returns a new NetDevLine. // The Name field will be a sorted comma separated list of interface names. func (netDev NetDev) Total() NetDevLine { total := NetDevLine{} names := make([]string, 0, len(netDev)) for _, ifc := range netDev { names = append(names, ifc.Name) total.RxBytes += ifc.RxBytes total.RxPackets += ifc.RxPackets total.RxErrors += ifc.RxErrors total.RxDropped += ifc.RxDropped total.RxFIFO += ifc.RxFIFO total.RxFrame += ifc.RxFrame total.RxCompressed += ifc.RxCompressed total.RxMulticast += ifc.RxMulticast total.TxBytes += ifc.TxBytes total.TxPackets += ifc.TxPackets total.TxErrors += ifc.TxErrors total.TxDropped += ifc.TxDropped total.TxFIFO += ifc.TxFIFO total.TxCollisions += ifc.TxCollisions total.TxCarrier += ifc.TxCarrier total.TxCompressed += ifc.TxCompressed } sort.Strings(names) total.Name = strings.Join(names, ", ") return total } golang-github-prometheus-procfs-0.14.0/net_dev_test.go000066400000000000000000000050701461002754700230300ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "fmt" "testing" ) func TestNetDevParseLine(t *testing.T) { tc := []string{"eth0", "eth0:1"} for i := range tc { rawLine := fmt.Sprintf(` %v: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16`, tc[i]) have, err := NetDev{}.parseLine(rawLine) if err != nil { t.Fatal(err) } want := NetDevLine{tc[i], 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} if want != *have { t.Errorf("want %v, have %v", want, have) } } } func TestNetDev(t *testing.T) { fs, err := NewFS(procTestFixtures) if err != nil { t.Fatal(err) } netDev, err := fs.NetDev() if err != nil { t.Fatal(err) } lines := map[string]NetDevLine{ "vethf345468": {Name: "vethf345468", RxBytes: 648, RxPackets: 8, TxBytes: 438, TxPackets: 5}, "lo": {Name: "lo", RxBytes: 1664039048, RxPackets: 1566805, TxBytes: 1664039048, TxPackets: 1566805}, "docker0": {Name: "docker0", RxBytes: 2568, RxPackets: 38, TxBytes: 438, TxPackets: 5}, "eth0": {Name: "eth0", RxBytes: 874354587, RxPackets: 1036395, TxBytes: 563352563, TxPackets: 732147}, } if want, have := len(lines), len(netDev); want != have { t.Errorf("want %d parsed net/dev lines, have %d", want, have) } for _, line := range netDev { if want, have := lines[line.Name], line; want != have { t.Errorf("%s: want %v, have %v", line.Name, want, have) } } } func TestProcNetDev(t *testing.T) { p, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } netDev, err := p.NetDev() if err != nil { t.Fatal(err) } lines := map[string]NetDevLine{ "lo": {Name: "lo"}, "eth0": {Name: "eth0", RxBytes: 438, RxPackets: 5, TxBytes: 648, TxPackets: 8}, } if want, have := len(lines), len(netDev); want != have { t.Errorf("want %d parsed net/dev lines, have %d", want, have) } for _, line := range netDev { if want, have := lines[line.Name], line; want != have { t.Errorf("%s: want %v, have %v", line.Name, want, have) } } } golang-github-prometheus-procfs-0.14.0/net_ip_socket.go000066400000000000000000000172021461002754700231730ustar00rootroot00000000000000// Copyright 2020 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. package procfs import ( "bufio" "encoding/hex" "fmt" "io" "net" "os" "strconv" "strings" ) const ( // readLimit is used by io.LimitReader while reading the content of the // /proc/net/udp{,6} files. The number of lines inside such a file is dynamic // as each line represents a single used socket. // In theory, the number of available sockets is 65535 (2^16 - 1) per IP. // With e.g. 150 Byte per line and the maximum number of 65535, // the reader needs to handle 150 Byte * 65535 =~ 10 MB for a single IP. readLimit = 4294967296 // Byte -> 4 GiB ) // This contains generic data structures for both udp and tcp sockets. type ( // NetIPSocket represents the contents of /proc/net/{t,u}dp{,6} file without the header. NetIPSocket []*netIPSocketLine // NetIPSocketSummary provides already computed values like the total queue lengths or // the total number of used sockets. In contrast to NetIPSocket it does not collect // the parsed lines into a slice. NetIPSocketSummary struct { // TxQueueLength shows the total queue length of all parsed tx_queue lengths. TxQueueLength uint64 // RxQueueLength shows the total queue length of all parsed rx_queue lengths. RxQueueLength uint64 // UsedSockets shows the total number of parsed lines representing the // number of used sockets. UsedSockets uint64 // Drops shows the total number of dropped packets of all UPD sockets. Drops *uint64 } // netIPSocketLine represents the fields parsed from a single line // in /proc/net/{t,u}dp{,6}. Fields which are not used by IPSocket are skipped. // Drops is non-nil for udp{,6}, but nil for tcp{,6}. // For the proc file format details, see https://linux.die.net/man/5/proc. netIPSocketLine struct { Sl uint64 LocalAddr net.IP LocalPort uint64 RemAddr net.IP RemPort uint64 St uint64 TxQueue uint64 RxQueue uint64 UID uint64 Inode uint64 Drops *uint64 } ) func newNetIPSocket(file string) (NetIPSocket, error) { f, err := os.Open(file) if err != nil { return nil, err } defer f.Close() var netIPSocket NetIPSocket isUDP := strings.Contains(file, "udp") lr := io.LimitReader(f, readLimit) s := bufio.NewScanner(lr) s.Scan() // skip first line with headers for s.Scan() { fields := strings.Fields(s.Text()) line, err := parseNetIPSocketLine(fields, isUDP) if err != nil { return nil, err } netIPSocket = append(netIPSocket, line) } if err := s.Err(); err != nil { return nil, err } return netIPSocket, nil } // newNetIPSocketSummary creates a new NetIPSocket{,6} from the contents of the given file. func newNetIPSocketSummary(file string) (*NetIPSocketSummary, error) { f, err := os.Open(file) if err != nil { return nil, err } defer f.Close() var netIPSocketSummary NetIPSocketSummary var udpPacketDrops uint64 isUDP := strings.Contains(file, "udp") lr := io.LimitReader(f, readLimit) s := bufio.NewScanner(lr) s.Scan() // skip first line with headers for s.Scan() { fields := strings.Fields(s.Text()) line, err := parseNetIPSocketLine(fields, isUDP) if err != nil { return nil, err } netIPSocketSummary.TxQueueLength += line.TxQueue netIPSocketSummary.RxQueueLength += line.RxQueue netIPSocketSummary.UsedSockets++ if isUDP { udpPacketDrops += *line.Drops netIPSocketSummary.Drops = &udpPacketDrops } } if err := s.Err(); err != nil { return nil, err } return &netIPSocketSummary, nil } // the /proc/net/{t,u}dp{,6} files are network byte order for ipv4 and for ipv6 the address is four words consisting of four bytes each. In each of those four words the four bytes are written in reverse order. func parseIP(hexIP string) (net.IP, error) { var byteIP []byte byteIP, err := hex.DecodeString(hexIP) if err != nil { return nil, fmt.Errorf("%w: Cannot parse socket field in %q: %w", ErrFileParse, hexIP, err) } switch len(byteIP) { case 4: return net.IP{byteIP[3], byteIP[2], byteIP[1], byteIP[0]}, nil case 16: i := net.IP{ byteIP[3], byteIP[2], byteIP[1], byteIP[0], byteIP[7], byteIP[6], byteIP[5], byteIP[4], byteIP[11], byteIP[10], byteIP[9], byteIP[8], byteIP[15], byteIP[14], byteIP[13], byteIP[12], } return i, nil default: return nil, fmt.Errorf("%w: Unable to parse IP %s: %v", ErrFileParse, hexIP, nil) } } // parseNetIPSocketLine parses a single line, represented by a list of fields. func parseNetIPSocketLine(fields []string, isUDP bool) (*netIPSocketLine, error) { line := &netIPSocketLine{} if len(fields) < 10 { return nil, fmt.Errorf( "%w: Less than 10 columns found %q", ErrFileParse, strings.Join(fields, " "), ) } var err error // parse error // sl s := strings.Split(fields[0], ":") if len(s) != 2 { return nil, fmt.Errorf("%w: Unable to parse sl field in line %q", ErrFileParse, fields[0]) } if line.Sl, err = strconv.ParseUint(s[0], 0, 64); err != nil { return nil, fmt.Errorf("%w: Unable to parse sl field in %q: %w", ErrFileParse, line.Sl, err) } // local_address l := strings.Split(fields[1], ":") if len(l) != 2 { return nil, fmt.Errorf("%w: Unable to parse local_address field in %q", ErrFileParse, fields[1]) } if line.LocalAddr, err = parseIP(l[0]); err != nil { return nil, err } if line.LocalPort, err = strconv.ParseUint(l[1], 16, 64); err != nil { return nil, fmt.Errorf("%w: Unable to parse local_address port value line %q: %w", ErrFileParse, line.LocalPort, err) } // remote_address r := strings.Split(fields[2], ":") if len(r) != 2 { return nil, fmt.Errorf("%w: Unable to parse rem_address field in %q", ErrFileParse, fields[1]) } if line.RemAddr, err = parseIP(r[0]); err != nil { return nil, err } if line.RemPort, err = strconv.ParseUint(r[1], 16, 64); err != nil { return nil, fmt.Errorf("%w: Cannot parse rem_address port value in %q: %w", ErrFileParse, line.RemPort, err) } // st if line.St, err = strconv.ParseUint(fields[3], 16, 64); err != nil { return nil, fmt.Errorf("%w: Cannot parse st value in %q: %w", ErrFileParse, line.St, err) } // tx_queue and rx_queue q := strings.Split(fields[4], ":") if len(q) != 2 { return nil, fmt.Errorf( "%w: Missing colon for tx/rx queues in socket line %q", ErrFileParse, fields[4], ) } if line.TxQueue, err = strconv.ParseUint(q[0], 16, 64); err != nil { return nil, fmt.Errorf("%w: Cannot parse tx_queue value in %q: %w", ErrFileParse, line.TxQueue, err) } if line.RxQueue, err = strconv.ParseUint(q[1], 16, 64); err != nil { return nil, fmt.Errorf("%w: Cannot parse trx_queue value in %q: %w", ErrFileParse, line.RxQueue, err) } // uid if line.UID, err = strconv.ParseUint(fields[7], 0, 64); err != nil { return nil, fmt.Errorf("%w: Cannot parse UID value in %q: %w", ErrFileParse, line.UID, err) } // inode if line.Inode, err = strconv.ParseUint(fields[9], 0, 64); err != nil { return nil, fmt.Errorf("%w: Cannot parse inode value in %q: %w", ErrFileParse, line.Inode, err) } // drops if isUDP { drops, err := strconv.ParseUint(fields[12], 0, 64) if err != nil { return nil, fmt.Errorf("%w: Cannot parse drops value in %q: %w", ErrFileParse, drops, err) } line.Drops = &drops } return line, nil } golang-github-prometheus-procfs-0.14.0/net_ip_socket_test.go000066400000000000000000000077001461002754700242340ustar00rootroot00000000000000// Copyright 2020 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. package procfs import ( "net" "reflect" "testing" ) func Test_parseNetIPSocketLine(t *testing.T) { tests := []struct { fields []string name string want *netIPSocketLine wantErr bool isUDP bool }{ { name: "reading valid lines, no issue should happened", fields: []string{"11:", "00000000:0000", "00000000:0000", "0A", "00000017:0000002A", "0:0", "0", "1000", "0", "39309"}, want: &netIPSocketLine{ Sl: 11, LocalAddr: net.IP{0, 0, 0, 0}, LocalPort: 0, RemAddr: net.IP{0, 0, 0, 0}, RemPort: 0, St: 10, TxQueue: 23, RxQueue: 42, UID: 1000, Inode: 39309, }, }, { name: "error case - invalid line - number of fields/columns < 10", fields: []string{"1:", "00000000:0000", "00000000:0000", "07", "0:0", "0", "0"}, want: nil, wantErr: true, }, { name: "error case - parse sl - not a valid uint", fields: []string{"a:", "00000000:0000", "00000000:0000", "07", "00000000:00000001", "0:0", "0", "0", "0", "39309"}, want: nil, wantErr: true, }, { name: "error case - parse local_address - not a valid hex", fields: []string{"1:", "0000000O:0000", "00000000:0000", "07", "00000000:00000001", "0:0", "0", "0", "0", "39309"}, want: nil, wantErr: true, }, { name: "error case - parse rem_address - not a valid hex", fields: []string{"1:", "00000000:0000", "0000000O:0000", "07", "00000000:00000001", "0:0", "0", "0", "0", "39309"}, want: nil, wantErr: true, }, { name: "error case - cannot parse line - missing colon", fields: []string{"1:", "00000000:0000", "00000000:0000", "07", "0000000000000001", "0:0", "0", "0", "0", "39309"}, want: nil, wantErr: true, }, { name: "error case - parse tx_queue - not a valid hex", fields: []string{"1:", "00000000:0000", "00000000:0000", "07", "DEADCODE:00000001", "0:0", "0", "0", "0", "39309"}, want: nil, wantErr: true, }, { name: "error case - parse rx_queue - not a valid hex", fields: []string{"1:", "00000000:0000", "00000000:0000", "07", "00000000:FEEDCODE", "0:0", "0", "0", "0", "39309"}, want: nil, wantErr: true, }, { name: "error case - parse UID - not a valid uint", fields: []string{"1:", "00000000:0000", "00000000:0000", "07", "00000000:00000001", "0:0", "0", "-10", "0", "39309"}, want: nil, wantErr: true, }, { name: "error case - parse Inode - not a valid uint", fields: []string{"1:", "00000000:0000", "00000000:0000", "07", "00000000:00000001", "0:0", "0", "-10", "0", "-39309"}, want: nil, wantErr: true, }, { name: "error case - parse Drops - not a valid uint", fields: []string{"1:", "00000000:0000", "00000000:0000", "07", "00000000:00000001", "0:0", "0", "10", "0", "39309", "2", "000000009bd60d72", "-5"}, want: nil, wantErr: true, isUDP: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := parseNetIPSocketLine(tt.fields, tt.isUDP) if (err != nil) != tt.wantErr { t.Errorf("parseNetIPSocketLine() error = %v, wantErr %v", err, tt.wantErr) return } if tt.want == nil && got != nil { t.Errorf("parseNetIPSocketLine() = %v, want %v", got, tt.want) } if !reflect.DeepEqual(got, tt.want) { t.Errorf("parseNetIPSocketLine() = %#v, want %#v", got, tt.want) } }) } } golang-github-prometheus-procfs-0.14.0/net_protocols.go000066400000000000000000000126251461002754700232430ustar00rootroot00000000000000// Copyright 2020 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. package procfs import ( "bufio" "bytes" "fmt" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // NetProtocolStats stores the contents from /proc/net/protocols. type NetProtocolStats map[string]NetProtocolStatLine // NetProtocolStatLine contains a single line parsed from /proc/net/protocols. We // only care about the first six columns as the rest are not likely to change // and only serve to provide a set of capabilities for each protocol. type NetProtocolStatLine struct { Name string // 0 The name of the protocol Size uint64 // 1 The size, in bytes, of a given protocol structure. e.g. sizeof(struct tcp_sock) or sizeof(struct unix_sock) Sockets int64 // 2 Number of sockets in use by this protocol Memory int64 // 3 Number of 4KB pages allocated by all sockets of this protocol Pressure int // 4 This is either yes, no, or NI (not implemented). For the sake of simplicity we treat NI as not experiencing memory pressure. MaxHeader uint64 // 5 Protocol specific max header size Slab bool // 6 Indicates whether or not memory is allocated from the SLAB ModuleName string // 7 The name of the module that implemented this protocol or "kernel" if not from a module Capabilities NetProtocolCapabilities } // NetProtocolCapabilities contains a list of capabilities for each protocol. type NetProtocolCapabilities struct { Close bool // 8 Connect bool // 9 Disconnect bool // 10 Accept bool // 11 IoCtl bool // 12 Init bool // 13 Destroy bool // 14 Shutdown bool // 15 SetSockOpt bool // 16 GetSockOpt bool // 17 SendMsg bool // 18 RecvMsg bool // 19 SendPage bool // 20 Bind bool // 21 BacklogRcv bool // 22 Hash bool // 23 UnHash bool // 24 GetPort bool // 25 EnterMemoryPressure bool // 26 } // NetProtocols reads stats from /proc/net/protocols and returns a map of // PortocolStatLine entries. As of this writing no official Linux Documentation // exists, however the source is fairly self-explanatory and the format seems // stable since its introduction in 2.6.12-rc2 // Linux 2.6.12-rc2 - https://elixir.bootlin.com/linux/v2.6.12-rc2/source/net/core/sock.c#L1452 // Linux 5.10 - https://elixir.bootlin.com/linux/v5.10.4/source/net/core/sock.c#L3586 func (fs FS) NetProtocols() (NetProtocolStats, error) { data, err := util.ReadFileNoStat(fs.proc.Path("net/protocols")) if err != nil { return NetProtocolStats{}, err } return parseNetProtocols(bufio.NewScanner(bytes.NewReader(data))) } func parseNetProtocols(s *bufio.Scanner) (NetProtocolStats, error) { nps := NetProtocolStats{} // Skip the header line s.Scan() for s.Scan() { line, err := nps.parseLine(s.Text()) if err != nil { return NetProtocolStats{}, err } nps[line.Name] = *line } return nps, nil } func (ps NetProtocolStats) parseLine(rawLine string) (*NetProtocolStatLine, error) { line := &NetProtocolStatLine{Capabilities: NetProtocolCapabilities{}} var err error const enabled = "yes" const disabled = "no" fields := strings.Fields(rawLine) line.Name = fields[0] line.Size, err = strconv.ParseUint(fields[1], 10, 64) if err != nil { return nil, err } line.Sockets, err = strconv.ParseInt(fields[2], 10, 64) if err != nil { return nil, err } line.Memory, err = strconv.ParseInt(fields[3], 10, 64) if err != nil { return nil, err } if fields[4] == enabled { line.Pressure = 1 } else if fields[4] == disabled { line.Pressure = 0 } else { line.Pressure = -1 } line.MaxHeader, err = strconv.ParseUint(fields[5], 10, 64) if err != nil { return nil, err } if fields[6] == enabled { line.Slab = true } else if fields[6] == disabled { line.Slab = false } else { return nil, fmt.Errorf("%w: capability for protocol: %s", ErrFileParse, line.Name) } line.ModuleName = fields[7] err = line.Capabilities.parseCapabilities(fields[8:]) if err != nil { return nil, err } return line, nil } func (pc *NetProtocolCapabilities) parseCapabilities(capabilities []string) error { // The capabilities are all bools so we can loop over to map them capabilityFields := [...]*bool{ &pc.Close, &pc.Connect, &pc.Disconnect, &pc.Accept, &pc.IoCtl, &pc.Init, &pc.Destroy, &pc.Shutdown, &pc.SetSockOpt, &pc.GetSockOpt, &pc.SendMsg, &pc.RecvMsg, &pc.SendPage, &pc.Bind, &pc.BacklogRcv, &pc.Hash, &pc.UnHash, &pc.GetPort, &pc.EnterMemoryPressure, } for i := 0; i < len(capabilities); i++ { if capabilities[i] == "y" { *capabilityFields[i] = true } else if capabilities[i] == "n" { *capabilityFields[i] = false } else { return fmt.Errorf("%w: capability block for protocol: position %d", ErrFileParse, i) } } return nil } golang-github-prometheus-procfs-0.14.0/net_protocols_test.go000066400000000000000000000115571461002754700243050ustar00rootroot00000000000000// Copyright 2020 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. package procfs import ( "strings" "testing" ) func TestParseCapabilities(t *testing.T) { rawStr := "y y y y y y y y y y y y y n y y y y y\n" have := NetProtocolCapabilities{} err := have.parseCapabilities(strings.Fields(rawStr)) if err != nil { t.Fatal(err) } want := NetProtocolCapabilities{true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, true, true, true, true} if want != have { t.Errorf("want %+v\nhave %+v\n", want, have) } } func TestProtocolsParseLine(t *testing.T) { rawStr := "TCP 1984 93064 1225378 no 320 yes kernel y y y y y y y y y y y y y n y y y y y\n" protocols := NetProtocolStats{} have, err := protocols.parseLine(rawStr) if err != nil { t.Fatal(err) } want := NetProtocolStatLine{"TCP", 1984, 93064, 1225378, 0, 320, true, "kernel", NetProtocolCapabilities{true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, true, true, true, true}} if want != *have { t.Errorf("want %+v\nhave %+v\n", want, have) } } func TestProtocolsParseProtocols(t *testing.T) { fs, err := NewFS(procTestFixtures) if err != nil { t.Fatal(err) } protocolStats, err := fs.NetProtocols() if err != nil { t.Fatal(err) } lines := map[string]NetProtocolStatLine{ "PACKET": {"PACKET", 1344, 2, -1, -1, 0, false, "kernel", NetProtocolCapabilities{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}}, "PINGv6": {"PINGv6", 1112, 0, -1, -1, 0, true, "kernel", NetProtocolCapabilities{true, true, true, false, false, true, false, false, true, true, true, true, false, true, true, true, true, true, false}}, "RAWv6": {"RAWv6", 1112, 1, -1, -1, 0, true, "kernel", NetProtocolCapabilities{true, true, true, false, true, true, true, false, true, true, true, true, false, true, true, true, true, false, false}}, "UDPLITEv6": {"UDPLITEv6", 1216, 0, 57, -1, 0, true, "kernel", NetProtocolCapabilities{true, true, true, false, true, true, true, false, true, true, true, true, false, false, false, true, true, true, false}}, "UDPv6": {"UDPv6", 1216, 10, 57, -1, 0, true, "kernel", NetProtocolCapabilities{true, true, true, false, true, true, true, false, true, true, true, true, false, false, false, true, true, true, false}}, "TCPv6": {"TCPv6", 2144, 1937, 1225378, 0, 320, true, "kernel", NetProtocolCapabilities{true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, true, true, true, true}}, "UNIX": {"UNIX", 1024, 120, -1, -1, 0, true, "kernel", NetProtocolCapabilities{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}}, "UDP-Lite": {"UDP-Lite", 1024, 0, 57, -1, 0, true, "kernel", NetProtocolCapabilities{true, true, true, false, true, true, true, false, true, true, true, true, true, false, false, true, true, true, false}}, "PING": {"PING", 904, 0, -1, -1, 0, true, "kernel", NetProtocolCapabilities{true, true, true, false, false, true, false, false, true, true, true, true, false, true, true, true, true, true, false}}, "RAW": {"RAW", 912, 0, -1, -1, 0, true, "kernel", NetProtocolCapabilities{true, true, true, false, true, true, true, false, true, true, true, true, false, true, true, true, true, false, false}}, "UDP": {"UDP", 1024, 73, 57, -1, 0, true, "kernel", NetProtocolCapabilities{true, true, true, false, true, true, true, false, true, true, true, true, true, false, false, true, true, true, false}}, "TCP": {"TCP", 1984, 93064, 1225378, 1, 320, true, "kernel", NetProtocolCapabilities{true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, true, true, true, true}}, "NETLINK": {"NETLINK", 1040, 16, -1, -1, 0, false, "kernel", NetProtocolCapabilities{false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false}}, } if want, have := len(lines), len(protocolStats); want != have { t.Errorf("want %d parsed net/protocols lines, have %d", want, have) } for _, line := range protocolStats { if want, have := lines[line.Name], line; want != have { t.Errorf("%s: want %v, have %v", line.Name, want, have) } } } golang-github-prometheus-procfs-0.14.0/net_route.go000066400000000000000000000066561461002754700223640ustar00rootroot00000000000000// Copyright 2023 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. package procfs import ( "bufio" "bytes" "fmt" "io" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) const ( blackholeRepresentation string = "*" blackholeIfaceName string = "blackhole" routeLineColumns int = 11 ) // A NetRouteLine represents one line from net/route. type NetRouteLine struct { Iface string Destination uint32 Gateway uint32 Flags uint32 RefCnt uint32 Use uint32 Metric uint32 Mask uint32 MTU uint32 Window uint32 IRTT uint32 } func (fs FS) NetRoute() ([]NetRouteLine, error) { return readNetRoute(fs.proc.Path("net", "route")) } func readNetRoute(path string) ([]NetRouteLine, error) { b, err := util.ReadFileNoStat(path) if err != nil { return nil, err } routelines, err := parseNetRoute(bytes.NewReader(b)) if err != nil { return nil, fmt.Errorf("failed to read net route from %s: %w", path, err) } return routelines, nil } func parseNetRoute(r io.Reader) ([]NetRouteLine, error) { var routelines []NetRouteLine scanner := bufio.NewScanner(r) scanner.Scan() for scanner.Scan() { fields := strings.Fields(scanner.Text()) routeline, err := parseNetRouteLine(fields) if err != nil { return nil, err } routelines = append(routelines, *routeline) } return routelines, nil } func parseNetRouteLine(fields []string) (*NetRouteLine, error) { if len(fields) != routeLineColumns { return nil, fmt.Errorf("invalid routeline, num of digits: %d", len(fields)) } iface := fields[0] if iface == blackholeRepresentation { iface = blackholeIfaceName } destination, err := strconv.ParseUint(fields[1], 16, 32) if err != nil { return nil, err } gateway, err := strconv.ParseUint(fields[2], 16, 32) if err != nil { return nil, err } flags, err := strconv.ParseUint(fields[3], 10, 32) if err != nil { return nil, err } refcnt, err := strconv.ParseUint(fields[4], 10, 32) if err != nil { return nil, err } use, err := strconv.ParseUint(fields[5], 10, 32) if err != nil { return nil, err } metric, err := strconv.ParseUint(fields[6], 10, 32) if err != nil { return nil, err } mask, err := strconv.ParseUint(fields[7], 16, 32) if err != nil { return nil, err } mtu, err := strconv.ParseUint(fields[8], 10, 32) if err != nil { return nil, err } window, err := strconv.ParseUint(fields[9], 10, 32) if err != nil { return nil, err } irtt, err := strconv.ParseUint(fields[10], 10, 32) if err != nil { return nil, err } routeline := &NetRouteLine{ Iface: iface, Destination: uint32(destination), Gateway: uint32(gateway), Flags: uint32(flags), RefCnt: uint32(refcnt), Use: uint32(use), Metric: uint32(metric), Mask: uint32(mask), MTU: uint32(mtu), Window: uint32(window), IRTT: uint32(irtt), } return routeline, nil } golang-github-prometheus-procfs-0.14.0/net_route_test.go000066400000000000000000000031771461002754700234160ustar00rootroot00000000000000// Copyright 2023 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. package procfs import ( "bytes" "reflect" "testing" ) func TestParseNetRoute(t *testing.T) { var netRoute = []byte(`Iface Destination Gateway Flags RefCnt Use Metric Mask MTU Window IRTT eno16780032 00000000 9503A8C0 0003 0 0 100 00000000 0 0 0 eno16780032 0000A8C0 00000000 0001 0 0 100 0000FFFF 0 0 0`) r := bytes.NewReader(netRoute) parsed, _ := parseNetRoute(r) want := []NetRouteLine{ { Iface: "eno16780032", Destination: 0, Gateway: 2500044992, Flags: 3, RefCnt: 0, Use: 0, Metric: 100, Mask: 0, MTU: 0, Window: 0, IRTT: 0, }, { Iface: "eno16780032", Destination: 43200, Gateway: 0, Flags: 1, RefCnt: 0, Use: 0, Metric: 100, Mask: 65535, MTU: 0, Window: 0, IRTT: 0, }, } if !reflect.DeepEqual(want, parsed) { t.Errorf("want %v, parsed %v", want, parsed) } } golang-github-prometheus-procfs-0.14.0/net_sockstat.go000066400000000000000000000105771461002754700230560ustar00rootroot00000000000000// 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. package procfs import ( "bufio" "bytes" "fmt" "io" "strings" "github.com/prometheus/procfs/internal/util" ) // A NetSockstat contains the output of /proc/net/sockstat{,6} for IPv4 or IPv6, // respectively. type NetSockstat struct { // Used is non-nil for IPv4 sockstat results, but nil for IPv6. Used *int Protocols []NetSockstatProtocol } // A NetSockstatProtocol contains statistics about a given socket protocol. // Pointer fields indicate that the value may or may not be present on any // given protocol. type NetSockstatProtocol struct { Protocol string InUse int Orphan *int TW *int Alloc *int Mem *int Memory *int } // NetSockstat retrieves IPv4 socket statistics. func (fs FS) NetSockstat() (*NetSockstat, error) { return readSockstat(fs.proc.Path("net", "sockstat")) } // NetSockstat6 retrieves IPv6 socket statistics. // // If IPv6 is disabled on this kernel, the returned error can be checked with // os.IsNotExist. func (fs FS) NetSockstat6() (*NetSockstat, error) { return readSockstat(fs.proc.Path("net", "sockstat6")) } // readSockstat opens and parses a NetSockstat from the input file. func readSockstat(name string) (*NetSockstat, error) { // This file is small and can be read with one syscall. b, err := util.ReadFileNoStat(name) if err != nil { // Do not wrap this error so the caller can detect os.IsNotExist and // similar conditions. return nil, err } stat, err := parseSockstat(bytes.NewReader(b)) if err != nil { return nil, fmt.Errorf("%w: sockstats from %q: %w", ErrFileRead, name, err) } return stat, nil } // parseSockstat reads the contents of a sockstat file and parses a NetSockstat. func parseSockstat(r io.Reader) (*NetSockstat, error) { var stat NetSockstat s := bufio.NewScanner(r) for s.Scan() { // Expect a minimum of a protocol and one key/value pair. fields := strings.Split(s.Text(), " ") if len(fields) < 3 { return nil, fmt.Errorf("%w: Malformed sockstat line: %q", ErrFileParse, s.Text()) } // The remaining fields are key/value pairs. kvs, err := parseSockstatKVs(fields[1:]) if err != nil { return nil, fmt.Errorf("%w: sockstat key/value pairs from %q: %w", ErrFileParse, s.Text(), err) } // The first field is the protocol. We must trim its colon suffix. proto := strings.TrimSuffix(fields[0], ":") switch proto { case "sockets": // Special case: IPv4 has a sockets "used" key/value pair that we // embed at the top level of the structure. used := kvs["used"] stat.Used = &used default: // Parse all other lines as individual protocols. nsp := parseSockstatProtocol(kvs) nsp.Protocol = proto stat.Protocols = append(stat.Protocols, nsp) } } if err := s.Err(); err != nil { return nil, err } return &stat, nil } // parseSockstatKVs parses a string slice into a map of key/value pairs. func parseSockstatKVs(kvs []string) (map[string]int, error) { if len(kvs)%2 != 0 { return nil, fmt.Errorf("%w:: Odd number of fields in key/value pairs %q", ErrFileParse, kvs) } // Iterate two values at a time to gather key/value pairs. out := make(map[string]int, len(kvs)/2) for i := 0; i < len(kvs); i += 2 { vp := util.NewValueParser(kvs[i+1]) out[kvs[i]] = vp.Int() if err := vp.Err(); err != nil { return nil, err } } return out, nil } // parseSockstatProtocol parses a NetSockstatProtocol from the input kvs map. func parseSockstatProtocol(kvs map[string]int) NetSockstatProtocol { var nsp NetSockstatProtocol for k, v := range kvs { // Capture the range variable to ensure we get unique pointers for // each of the optional fields. v := v switch k { case "inuse": nsp.InUse = v case "orphan": nsp.Orphan = &v case "tw": nsp.TW = &v case "alloc": nsp.Alloc = &v case "mem": nsp.Mem = &v case "memory": nsp.Memory = &v } } return nsp } golang-github-prometheus-procfs-0.14.0/net_sockstat_test.go000066400000000000000000000112021461002754700240770ustar00rootroot00000000000000// 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. package procfs import ( "os" "strings" "testing" "github.com/google/go-cmp/cmp" ) // The majority of test cases are covered in Test_parseSockstat. The top level // tests just check the basics for integration test purposes. func TestNetSockstat(t *testing.T) { fs, err := NewFS(procTestFixtures) if err != nil { t.Fatalf("failed to open procfs: %v", err) } stat, err := fs.NetSockstat() if err != nil { t.Fatalf("failed to get sockstat: %v", err) } // IPv4 stats should include Used. if stat.Used == nil { t.Fatalf("IPv4 sockstat used value was nil") } if diff := cmp.Diff(1602, *stat.Used); diff != "" { t.Fatalf("unexpected IPv4 used sockets (-want +got):\n%s", diff) } // TCP occurs first; do a basic sanity check. if diff := cmp.Diff("TCP", stat.Protocols[0].Protocol); diff != "" { t.Fatalf("unexpected socket protocol (-want +got):\n%s", diff) } if diff := cmp.Diff(35, stat.Protocols[0].InUse); diff != "" { t.Fatalf("unexpected number of TCP sockets (-want +got):\n%s", diff) } } func TestNetSockstat6(t *testing.T) { fs, err := NewFS(procTestFixtures) if err != nil { t.Fatalf("failed to open procfs: %v", err) } stat, err := fs.NetSockstat6() if err != nil { t.Fatalf("failed to get sockstat: %v", err) } // IPv6 stats should not include Used. if stat.Used != nil { t.Fatalf("IPv6 sockstat used value was not nil") } // TCP6 occurs first; do a basic sanity check. if diff := cmp.Diff("TCP6", stat.Protocols[0].Protocol); diff != "" { t.Fatalf("unexpected socket protocol (-want +got):\n%s", diff) } if diff := cmp.Diff(17, stat.Protocols[0].InUse); diff != "" { t.Fatalf("unexpected number of TCP sockets (-want +got):\n%s", diff) } } func Test_readSockstatIsNotExist(t *testing.T) { // On a machine with IPv6 disabled for example, we want to ensure that // readSockstat returns an error that is compatible with os.IsNotExist. // // We can use a synthetic file path here to verify this behavior. _, err := readSockstat("/does/not/exist") if err == nil || !os.IsNotExist(err) { t.Fatalf("error is not compatible with os.IsNotExist: %#v", err) } } func Test_parseSockstat(t *testing.T) { tests := []struct { name string s string ok bool stat *NetSockstat }{ { name: "empty", ok: true, stat: &NetSockstat{}, }, { name: "bad line", s: ` sockets: used `, }, { name: "bad key/value pairs", s: ` TCP: inuse 32 orphan `, }, { name: "IPv4", s: ` sockets: used 1591 TCP: inuse 32 orphan 0 tw 0 alloc 58 mem 13 UDP: inuse 8 mem 115 UDPLITE: inuse 0 RAW: inuse 0 FRAG: inuse 0 memory 0 `, ok: true, stat: &NetSockstat{ Used: intp(1591), Protocols: []NetSockstatProtocol{ { Protocol: "TCP", InUse: 32, Orphan: intp(0), TW: intp(0), Alloc: intp(58), Mem: intp(13), }, { Protocol: "UDP", InUse: 8, Mem: intp(115), }, { Protocol: "UDPLITE", }, { Protocol: "RAW", }, { Protocol: "FRAG", Memory: intp(0), }, }, }, }, { name: "IPv6", s: ` TCP6: inuse 24 UDP6: inuse 9 UDPLITE6: inuse 0 RAW6: inuse 1 FRAG6: inuse 0 memory 0 `, ok: true, stat: &NetSockstat{ Protocols: []NetSockstatProtocol{ { Protocol: "TCP6", InUse: 24, }, { Protocol: "UDP6", InUse: 9, }, { Protocol: "UDPLITE6", }, { Protocol: "RAW6", InUse: 1, }, { Protocol: "FRAG6", Memory: intp(0), }, }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { stat, err := parseSockstat(strings.NewReader(strings.TrimSpace(tt.s))) if err != nil { if tt.ok { t.Fatalf("failed to parse sockstats: %v", err) } t.Logf("OK error: %v", err) return } if !tt.ok { t.Fatal("expected an error, but none occurred") } if diff := cmp.Diff(tt.stat, stat); diff != "" { t.Errorf("unexpected sockstats (-want +got):\n%s", diff) } }) } } func intp(i int) *int { return &i } golang-github-prometheus-procfs-0.14.0/net_softnet.go000066400000000000000000000101171461002754700226730ustar00rootroot00000000000000// 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. package procfs import ( "bufio" "bytes" "fmt" "io" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // For the proc file format details, // See: // * Linux 2.6.23 https://elixir.bootlin.com/linux/v2.6.23/source/net/core/dev.c#L2343 // * Linux 2.6.39 https://elixir.bootlin.com/linux/v2.6.39/source/net/core/dev.c#L4086 // * Linux 4.18 https://elixir.bootlin.com/linux/v4.18/source/net/core/net-procfs.c#L162 // * Linux 5.14 https://elixir.bootlin.com/linux/v5.14/source/net/core/net-procfs.c#L169 // SoftnetStat contains a single row of data from /proc/net/softnet_stat. type SoftnetStat struct { // Number of processed packets. Processed uint32 // Number of dropped packets. Dropped uint32 // Number of times processing packets ran out of quota. TimeSqueezed uint32 // Number of collision occur while obtaining device lock while transmitting. CPUCollision uint32 // Number of times cpu woken up received_rps. ReceivedRps uint32 // number of times flow limit has been reached. FlowLimitCount uint32 // Softnet backlog status. SoftnetBacklogLen uint32 // CPU id owning this softnet_data. Index uint32 // softnet_data's Width. Width int } 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(softNetProcFile)) if err != nil { return nil, err } entries, err := parseSoftnet(bytes.NewReader(b)) if err != nil { return nil, fmt.Errorf("%w: /proc/net/softnet_stat: %w", ErrFileParse, err) } return entries, nil } func parseSoftnet(r io.Reader) ([]SoftnetStat, error) { const minColumns = 9 s := bufio.NewScanner(r) var stats []SoftnetStat cpuIndex := 0 for s.Scan() { columns := strings.Fields(s.Text()) width := len(columns) softnetStat := SoftnetStat{} if width < minColumns { return nil, fmt.Errorf("%w: detected %d columns, but expected at least %d", ErrFileParse, width, minColumns) } // Linux 2.6.23 https://elixir.bootlin.com/linux/v2.6.23/source/net/core/dev.c#L2347 if width >= minColumns { us, err := parseHexUint32s(columns[0:9]) if err != nil { return nil, err } softnetStat.Processed = us[0] softnetStat.Dropped = us[1] softnetStat.TimeSqueezed = us[2] softnetStat.CPUCollision = us[8] } // Linux 2.6.39 https://elixir.bootlin.com/linux/v2.6.39/source/net/core/dev.c#L4086 if width >= 10 { us, err := parseHexUint32s(columns[9:10]) if err != nil { return nil, err } softnetStat.ReceivedRps = us[0] } // Linux 4.18 https://elixir.bootlin.com/linux/v4.18/source/net/core/net-procfs.c#L162 if width >= 11 { us, err := parseHexUint32s(columns[10:11]) if err != nil { return nil, err } softnetStat.FlowLimitCount = us[0] } // Linux 5.14 https://elixir.bootlin.com/linux/v5.14/source/net/core/net-procfs.c#L169 if width >= 13 { us, err := parseHexUint32s(columns[11:13]) if err != nil { return nil, err } softnetStat.SoftnetBacklogLen = us[0] softnetStat.Index = us[1] } else { // For older kernels, create the Index based on the scan line number. softnetStat.Index = uint32(cpuIndex) } softnetStat.Width = width stats = append(stats, softnetStat) cpuIndex++ } return stats, nil } func parseHexUint32s(ss []string) ([]uint32, error) { us := make([]uint32, 0, len(ss)) for _, s := range ss { u, err := strconv.ParseUint(s, 16, 32) if err != nil { return nil, err } us = append(us, uint32(u)) } return us, nil } golang-github-prometheus-procfs-0.14.0/net_softnet_test.go000066400000000000000000000046411461002754700237370ustar00rootroot00000000000000// 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. package procfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestNetSoftnet(t *testing.T) { fs, err := NewFS(procTestFixtures) if err != nil { t.Fatal(err) } want := []SoftnetStat{ { Processed: 0x00358fe3, Dropped: 0x00006283, TimeSqueezed: 0x00000000, CPUCollision: 0x00000000, ReceivedRps: 0x000855fc, FlowLimitCount: 0x00000076, SoftnetBacklogLen: 0x00000000, Index: 0x00000000, Width: 13, }, { Processed: 0x00953d1a, Dropped: 0x00000446, TimeSqueezed: 0x000000b1, CPUCollision: 0x00000000, ReceivedRps: 0x008eeb9a, FlowLimitCount: 0x0000002b, SoftnetBacklogLen: 0x000000dc, Index: 0x00000001, Width: 13, }, { Processed: 0x00015c73, Dropped: 0x00020e76, TimeSqueezed: 0xf0000769, CPUCollision: 0x00000004, ReceivedRps: 0x00000003, FlowLimitCount: 0x00000002, Index: 0x00000002, Width: 11, }, { Processed: 0x01663fb2, Dropped: 0x00000000, TimeSqueezed: 0x0109a4, CPUCollision: 0x00020e76, Index: 0x00000003, Width: 9, }, { Processed: 0x00008e78, Dropped: 0x00000001, TimeSqueezed: 0x00000011, CPUCollision: 0x00000020, ReceivedRps: 0x00000010, Index: 0x00000004, Width: 10, }, } got, err := fs.NetSoftnetStat() if err != nil { t.Fatal(err) } if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected softnet stats(-want +got):\n%s", diff) } } func TestBadSoftnet(t *testing.T) { softNetProcFile = "net/softnet_stat.broken" fs, err := NewFS(procTestFixtures) if err != nil { t.Fatal(err) } _, err = fs.NetSoftnetStat() if err == nil { t.Fatal("expected error, got nil") } } golang-github-prometheus-procfs-0.14.0/net_tcp.go000066400000000000000000000042111461002754700217750ustar00rootroot00000000000000// Copyright 2020 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. package procfs type ( // NetTCP represents the contents of /proc/net/tcp{,6} file without the header. NetTCP []*netIPSocketLine // NetTCPSummary provides already computed values like the total queue lengths or // the total number of used sockets. In contrast to NetTCP it does not collect // the parsed lines into a slice. NetTCPSummary NetIPSocketSummary ) // NetTCP returns the IPv4 kernel/networking statistics for TCP datagrams // read from /proc/net/tcp. func (fs FS) NetTCP() (NetTCP, error) { return newNetTCP(fs.proc.Path("net/tcp")) } // NetTCP6 returns the IPv6 kernel/networking statistics for TCP datagrams // read from /proc/net/tcp6. func (fs FS) NetTCP6() (NetTCP, error) { return newNetTCP(fs.proc.Path("net/tcp6")) } // NetTCPSummary returns already computed statistics like the total queue lengths // for TCP datagrams read from /proc/net/tcp. func (fs FS) NetTCPSummary() (*NetTCPSummary, error) { return newNetTCPSummary(fs.proc.Path("net/tcp")) } // NetTCP6Summary returns already computed statistics like the total queue lengths // for TCP datagrams read from /proc/net/tcp6. func (fs FS) NetTCP6Summary() (*NetTCPSummary, error) { return newNetTCPSummary(fs.proc.Path("net/tcp6")) } // newNetTCP creates a new NetTCP{,6} from the contents of the given file. func newNetTCP(file string) (NetTCP, error) { n, err := newNetIPSocket(file) n1 := NetTCP(n) return n1, err } func newNetTCPSummary(file string) (*NetTCPSummary, error) { n, err := newNetIPSocketSummary(file) if n == nil { return nil, err } n1 := NetTCPSummary(*n) return &n1, err } golang-github-prometheus-procfs-0.14.0/net_tcp_test.go000066400000000000000000000102561461002754700230420ustar00rootroot00000000000000// Copyright 2020 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. package procfs import ( "net" "reflect" "testing" ) func Test_newNetTCP(t *testing.T) { tests := []struct { name string file string want NetTCP wantErr bool }{ { name: "tcp file found, no error should come up", file: "testdata/fixtures/proc/net/tcp", want: []*netIPSocketLine{ { Sl: 0, LocalAddr: net.IP{10, 0, 0, 5}, LocalPort: 22, RemAddr: net.IP{0, 0, 0, 0}, RemPort: 0, St: 10, TxQueue: 0, RxQueue: 1, UID: 0, Inode: 2740, }, { Sl: 1, LocalAddr: net.IP{0, 0, 0, 0}, LocalPort: 22, RemAddr: net.IP{0, 0, 0, 0}, RemPort: 0, St: 10, TxQueue: 1, RxQueue: 0, UID: 0, Inode: 2740, }, { Sl: 2, LocalAddr: net.IP{0, 0, 0, 0}, LocalPort: 22, RemAddr: net.IP{0, 0, 0, 0}, RemPort: 0, St: 10, TxQueue: 1, RxQueue: 1, UID: 0, Inode: 2740, }, }, wantErr: false, }, { name: "tcp6 file found, no error should come up", file: "testdata/fixtures/proc/net/tcp6", want: []*netIPSocketLine{ { Sl: 1315, LocalAddr: net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, LocalPort: 5355, RemAddr: net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, RemPort: 0, St: 7, TxQueue: 0, RxQueue: 0, UID: 981, Inode: 21040, }, { Sl: 6073, LocalAddr: net.IP{254, 128, 0, 0, 0, 0, 0, 0, 86, 225, 173, 255, 254, 124, 102, 9}, LocalPort: 51073, RemAddr: net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, RemPort: 0, St: 7, TxQueue: 0, RxQueue: 0, UID: 1000, Inode: 11337031, }, }, wantErr: false, }, { name: "error case - file not found", file: "somewhere over the rainbow", want: nil, wantErr: true, }, { name: "error case - parse error", file: "testdata/fixtures/proc/net/tcp_broken", want: nil, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := newNetTCP(tt.file) if (err != nil) != tt.wantErr { t.Errorf("newNetTCP() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { t.Errorf("newNetTCP() = %v, want %v", got, tt.want) } }) } } func Test_newNetTCPSummary(t *testing.T) { tests := []struct { name string file string want *NetTCPSummary wantErr bool }{ { name: "tcp file found, no error should come up", file: "testdata/fixtures/proc/net/tcp", want: &NetTCPSummary{TxQueueLength: 2, RxQueueLength: 2, UsedSockets: 3}, wantErr: false, }, { name: "tcp6 file found, no error should come up", file: "testdata/fixtures/proc/net/tcp6", want: &NetTCPSummary{TxQueueLength: 0, RxQueueLength: 0, UsedSockets: 2}, wantErr: false, }, { name: "error case - file not found", file: "somewhere over the rainbow", want: nil, wantErr: true, }, { name: "error case - parse error", file: "testdata/fixtures/proc/net/tcp_broken", want: nil, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := newNetTCPSummary(tt.file) if (err != nil) != tt.wantErr { t.Errorf("newNetTCPSummary() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { t.Errorf("newNetTCPSummary() = %v, want %v", got, tt.want) } }) } } golang-github-prometheus-procfs-0.14.0/net_tls_stat.go000066400000000000000000000065511461002754700230550ustar00rootroot00000000000000// Copyright 2023 Prometheus Team // 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. package procfs import ( "bufio" "fmt" "os" "strconv" "strings" ) // TLSStat struct represents data in /proc/net/tls_stat. // See https://docs.kernel.org/networking/tls.html#statistics type TLSStat struct { // number of TX sessions currently installed where host handles cryptography TLSCurrTxSw int // number of RX sessions currently installed where host handles cryptography TLSCurrRxSw int // number of TX sessions currently installed where NIC handles cryptography TLSCurrTxDevice int // number of RX sessions currently installed where NIC handles cryptography TLSCurrRxDevice int //number of TX sessions opened with host cryptography TLSTxSw int //number of RX sessions opened with host cryptography TLSRxSw int // number of TX sessions opened with NIC cryptography TLSTxDevice int // number of RX sessions opened with NIC cryptography TLSRxDevice int // record decryption failed (e.g. due to incorrect authentication tag) TLSDecryptError int // number of RX resyncs sent to NICs handling cryptography TLSRxDeviceResync int // number of RX records which had to be re-decrypted due to TLS_RX_EXPECT_NO_PAD mis-prediction. Note that this counter will also increment for non-data records. TLSDecryptRetry int // number of data RX records which had to be re-decrypted due to TLS_RX_EXPECT_NO_PAD mis-prediction. TLSRxNoPadViolation int } // NewTLSStat reads the tls_stat statistics. func NewTLSStat() (TLSStat, error) { fs, err := NewFS(DefaultMountPoint) if err != nil { return TLSStat{}, err } return fs.NewTLSStat() } // NewTLSStat reads the tls_stat statistics. func (fs FS) NewTLSStat() (TLSStat, error) { file, err := os.Open(fs.proc.Path("net/tls_stat")) if err != nil { return TLSStat{}, err } defer file.Close() var ( tlsstat = TLSStat{} s = bufio.NewScanner(file) ) for s.Scan() { fields := strings.Fields(s.Text()) if len(fields) != 2 { return TLSStat{}, fmt.Errorf("%w: %q line %q", ErrFileParse, file.Name(), s.Text()) } name := fields[0] value, err := strconv.Atoi(fields[1]) if err != nil { return TLSStat{}, err } switch name { case "TlsCurrTxSw": tlsstat.TLSCurrTxSw = value case "TlsCurrRxSw": tlsstat.TLSCurrRxSw = value case "TlsCurrTxDevice": tlsstat.TLSCurrTxDevice = value case "TlsCurrRxDevice": tlsstat.TLSCurrRxDevice = value case "TlsTxSw": tlsstat.TLSTxSw = value case "TlsRxSw": tlsstat.TLSRxSw = value case "TlsTxDevice": tlsstat.TLSTxDevice = value case "TlsRxDevice": tlsstat.TLSRxDevice = value case "TlsDecryptError": tlsstat.TLSDecryptError = value case "TlsRxDeviceResync": tlsstat.TLSRxDeviceResync = value case "TlsDecryptRetry": tlsstat.TLSDecryptRetry = value case "TlsRxNoPadViolation": tlsstat.TLSRxNoPadViolation = value } } return tlsstat, s.Err() } golang-github-prometheus-procfs-0.14.0/net_tls_stat_test.go000066400000000000000000000032561461002754700241130ustar00rootroot00000000000000// Copyright 2023 Prometheus Team // 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. package procfs import ( "testing" ) func TestTLSStat(t *testing.T) { tlsStats, err := getProcFixtures(t).NewTLSStat() if err != nil { t.Fatal(err) } for _, test := range []struct { name string want int got int }{ {name: "TLSCurrTxSw", want: 5, got: tlsStats.TLSCurrTxSw}, {name: "TLSCurrRxSw", want: 5, got: tlsStats.TLSCurrRxSw}, {name: "TLSCurrTxDevice", want: 0, got: tlsStats.TLSCurrTxDevice}, {name: "TLSCurrRxDevice", want: 0, got: tlsStats.TLSCurrRxDevice}, {name: "TLSTxSw", want: 8711, got: tlsStats.TLSTxSw}, {name: "TLSTxSw", want: 8711, got: tlsStats.TLSRxSw}, {name: "TLSTxDevice", want: 0, got: tlsStats.TLSTxDevice}, {name: "TLSRxDevice", want: 0, got: tlsStats.TLSRxDevice}, {name: "TLSDecryptError", want: 13, got: tlsStats.TLSDecryptError}, {name: "TLSRxDeviceResync", want: 0, got: tlsStats.TLSRxDeviceResync}, {name: "TLSDecryptRetry", want: 0, got: tlsStats.TLSDecryptRetry}, {name: "TLSRxNoPadViolation", want: 0, got: tlsStats.TLSRxNoPadViolation}, } { if test.want != test.got { t.Errorf("Want %s %d, have %d", test.name, test.want, test.got) } } } golang-github-prometheus-procfs-0.14.0/net_udp.go000066400000000000000000000042111461002754700217770ustar00rootroot00000000000000// Copyright 2020 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. package procfs type ( // NetUDP represents the contents of /proc/net/udp{,6} file without the header. NetUDP []*netIPSocketLine // NetUDPSummary provides already computed values like the total queue lengths or // the total number of used sockets. In contrast to NetUDP it does not collect // the parsed lines into a slice. NetUDPSummary NetIPSocketSummary ) // NetUDP returns the IPv4 kernel/networking statistics for UDP datagrams // read from /proc/net/udp. func (fs FS) NetUDP() (NetUDP, error) { return newNetUDP(fs.proc.Path("net/udp")) } // NetUDP6 returns the IPv6 kernel/networking statistics for UDP datagrams // read from /proc/net/udp6. func (fs FS) NetUDP6() (NetUDP, error) { return newNetUDP(fs.proc.Path("net/udp6")) } // NetUDPSummary returns already computed statistics like the total queue lengths // for UDP datagrams read from /proc/net/udp. func (fs FS) NetUDPSummary() (*NetUDPSummary, error) { return newNetUDPSummary(fs.proc.Path("net/udp")) } // NetUDP6Summary returns already computed statistics like the total queue lengths // for UDP datagrams read from /proc/net/udp6. func (fs FS) NetUDP6Summary() (*NetUDPSummary, error) { return newNetUDPSummary(fs.proc.Path("net/udp6")) } // newNetUDP creates a new NetUDP{,6} from the contents of the given file. func newNetUDP(file string) (NetUDP, error) { n, err := newNetIPSocket(file) n1 := NetUDP(n) return n1, err } func newNetUDPSummary(file string) (*NetUDPSummary, error) { n, err := newNetIPSocketSummary(file) if n == nil { return nil, err } n1 := NetUDPSummary(*n) return &n1, err } golang-github-prometheus-procfs-0.14.0/net_udp_test.go000066400000000000000000000110731461002754700230420ustar00rootroot00000000000000// Copyright 2020 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. package procfs import ( "net" "reflect" "testing" ) func Test_newNetUDP(t *testing.T) { tests := []struct { name string file string want NetUDP wantErr bool }{ { name: "udp file found, no error should come up", file: "testdata/fixtures/proc/net/udp", want: []*netIPSocketLine{ &netIPSocketLine{ Sl: 0, LocalAddr: net.IP{10, 0, 0, 5}, LocalPort: 22, RemAddr: net.IP{0, 0, 0, 0}, RemPort: 0, St: 10, TxQueue: 0, RxQueue: 1, UID: 0, Inode: 2740, Drops: intToU64(100), }, &netIPSocketLine{ Sl: 1, LocalAddr: net.IP{0, 0, 0, 0}, LocalPort: 22, RemAddr: net.IP{0, 0, 0, 0}, RemPort: 0, St: 10, TxQueue: 1, RxQueue: 0, UID: 0, Inode: 2740, Drops: intToU64(100), }, &netIPSocketLine{ Sl: 2, LocalAddr: net.IP{0, 0, 0, 0}, LocalPort: 22, RemAddr: net.IP{0, 0, 0, 0}, RemPort: 0, St: 10, TxQueue: 1, RxQueue: 1, UID: 0, Inode: 2740, Drops: intToU64(100), }, }, wantErr: false, }, { name: "udp6 file found, no error should come up", file: "testdata/fixtures/proc/net/udp6", want: []*netIPSocketLine{ &netIPSocketLine{ Sl: 1315, LocalAddr: net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, LocalPort: 5355, RemAddr: net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, RemPort: 0, St: 7, TxQueue: 0, RxQueue: 0, UID: 981, Inode: 21040, Drops: intToU64(0), }, &netIPSocketLine{ Sl: 6073, LocalAddr: net.IP{254, 128, 0, 0, 0, 0, 0, 0, 86, 225, 173, 255, 254, 124, 102, 9}, LocalPort: 51073, RemAddr: net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, RemPort: 0, St: 7, TxQueue: 0, RxQueue: 0, UID: 1000, Inode: 11337031, Drops: intToU64(0), }, }, wantErr: false, }, { name: "error case - file not found", file: "somewhere over the rainbow", want: nil, wantErr: true, }, { name: "error case - parse error", file: "testdata/fixtures/proc/net/udp_broken", want: nil, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := newNetUDP(tt.file) if (err != nil) != tt.wantErr { t.Errorf("newNetUDP() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { t.Errorf("newNetUDP() = %v, want %v", got, tt.want) } }) } } func Test_newNetUDPSummary(t *testing.T) { tests := []struct { name string file string want *NetUDPSummary wantErr bool }{ { name: "udp file found, no error should come up", file: "testdata/fixtures/proc/net/udp", want: &NetUDPSummary{TxQueueLength: 2, RxQueueLength: 2, UsedSockets: 3, Drops: intToU64(300)}, wantErr: false, }, { name: "udp6 file found, no error should come up", file: "testdata/fixtures/proc/net/udp6", want: &NetUDPSummary{TxQueueLength: 0, RxQueueLength: 0, UsedSockets: 2, Drops: intToU64(0)}, wantErr: false, }, { name: "error case - file not found", file: "somewhere over the rainbow", want: nil, wantErr: true, }, { name: "error case - parse error", file: "testdata/fixtures/proc/net/udp_broken", want: nil, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := newNetUDPSummary(tt.file) if (err != nil) != tt.wantErr { t.Errorf("newNetUDPSummary() error = %v, wantErr %v", err, tt.wantErr) return } if !reflect.DeepEqual(got, tt.want) { t.Errorf("newNetUDPSummary() = %v, want %v", got, tt.want) } }) } } // intToU64 convert int to uint64 and return it pointer. func intToU64(i int) *uint64 { cast := uint64(i) return &cast } golang-github-prometheus-procfs-0.14.0/net_unix.go000066400000000000000000000140341461002754700221760ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "bufio" "fmt" "io" "os" "strconv" "strings" ) // For the proc file format details, // see https://elixir.bootlin.com/linux/v4.17/source/net/unix/af_unix.c#L2815 // and https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/net.h#L48. // Constants for the various /proc/net/unix enumerations. // TODO: match against x/sys/unix or similar? const ( netUnixTypeStream = 1 netUnixTypeDgram = 2 netUnixTypeSeqpacket = 5 netUnixFlagDefault = 0 netUnixFlagListen = 1 << 16 netUnixStateUnconnected = 1 netUnixStateConnecting = 2 netUnixStateConnected = 3 netUnixStateDisconnected = 4 ) // NetUNIXType is the type of the type field. type NetUNIXType uint64 // NetUNIXFlags is the type of the flags field. type NetUNIXFlags uint64 // NetUNIXState is the type of the state field. type NetUNIXState uint64 // NetUNIXLine represents a line of /proc/net/unix. type NetUNIXLine struct { KernelPtr string RefCount uint64 Protocol uint64 Flags NetUNIXFlags Type NetUNIXType State NetUNIXState Inode uint64 Path string } // NetUNIX holds the data read from /proc/net/unix. type NetUNIX struct { Rows []*NetUNIXLine } // NetUNIX returns data read from /proc/net/unix. func (fs FS) NetUNIX() (*NetUNIX, error) { return readNetUNIX(fs.proc.Path("net/unix")) } // readNetUNIX reads data in /proc/net/unix format from the specified file. func readNetUNIX(file string) (*NetUNIX, error) { // This file could be quite large and a streaming read is desirable versus // reading the entire contents at once. f, err := os.Open(file) if err != nil { return nil, err } defer f.Close() return parseNetUNIX(f) } // parseNetUNIX creates a NetUnix structure from the incoming stream. func parseNetUNIX(r io.Reader) (*NetUNIX, error) { // Begin scanning by checking for the existence of Inode. s := bufio.NewScanner(r) s.Scan() // From the man page of proc(5), it does not contain an Inode field, // but in actually it exists. This code works for both cases. hasInode := strings.Contains(s.Text(), "Inode") // Expect a minimum number of fields, but Inode and Path are optional: // Num RefCount Protocol Flags Type St Inode Path minFields := 6 if hasInode { minFields++ } var nu NetUNIX for s.Scan() { line := s.Text() item, err := nu.parseLine(line, hasInode, minFields) if err != nil { return nil, fmt.Errorf("%w: /proc/net/unix encountered data %q: %w", ErrFileParse, line, err) } nu.Rows = append(nu.Rows, item) } if err := s.Err(); err != nil { return nil, fmt.Errorf("%w: /proc/net/unix encountered data: %w", ErrFileParse, err) } return &nu, nil } func (u *NetUNIX) parseLine(line string, hasInode bool, min int) (*NetUNIXLine, error) { fields := strings.Fields(line) l := len(fields) if l < min { return nil, fmt.Errorf("%w: expected at least %d fields but got %d", ErrFileParse, min, l) } // Field offsets are as follows: // Num RefCount Protocol Flags Type St Inode Path kernelPtr := strings.TrimSuffix(fields[0], ":") users, err := u.parseUsers(fields[1]) if err != nil { return nil, fmt.Errorf("%w: ref count %q: %w", ErrFileParse, fields[1], err) } flags, err := u.parseFlags(fields[3]) if err != nil { return nil, fmt.Errorf("%w: Unable to parse flags %q: %w", ErrFileParse, fields[3], err) } typ, err := u.parseType(fields[4]) if err != nil { return nil, fmt.Errorf("%w: Failed to parse type %q: %w", ErrFileParse, fields[4], err) } state, err := u.parseState(fields[5]) if err != nil { return nil, fmt.Errorf("%w: Failed to parse state %q: %w", ErrFileParse, fields[5], err) } var inode uint64 if hasInode { inode, err = u.parseInode(fields[6]) if err != nil { return nil, fmt.Errorf("%w failed to parse inode %q: %w", ErrFileParse, fields[6], err) } } n := &NetUNIXLine{ KernelPtr: kernelPtr, RefCount: users, Type: typ, Flags: flags, State: state, Inode: inode, } // Path field is optional. if l > min { // Path occurs at either index 6 or 7 depending on whether inode is // already present. pathIdx := 7 if !hasInode { pathIdx-- } n.Path = fields[pathIdx] } return n, nil } func (u NetUNIX) parseUsers(s string) (uint64, error) { return strconv.ParseUint(s, 16, 32) } func (u NetUNIX) parseType(s string) (NetUNIXType, error) { typ, err := strconv.ParseUint(s, 16, 16) if err != nil { return 0, err } return NetUNIXType(typ), nil } func (u NetUNIX) parseFlags(s string) (NetUNIXFlags, error) { flags, err := strconv.ParseUint(s, 16, 32) if err != nil { return 0, err } return NetUNIXFlags(flags), nil } func (u NetUNIX) parseState(s string) (NetUNIXState, error) { st, err := strconv.ParseInt(s, 16, 8) if err != nil { return 0, err } return NetUNIXState(st), nil } func (u NetUNIX) parseInode(s string) (uint64, error) { return strconv.ParseUint(s, 10, 64) } func (t NetUNIXType) String() string { switch t { case netUnixTypeStream: return "stream" case netUnixTypeDgram: return "dgram" case netUnixTypeSeqpacket: return "seqpacket" } return "unknown" } func (f NetUNIXFlags) String() string { switch f { case netUnixFlagListen: return "listen" default: return "default" } } func (s NetUNIXState) String() string { switch s { case netUnixStateUnconnected: return "unconnected" case netUnixStateConnecting: return "connecting" case netUnixStateConnected: return "connected" case netUnixStateDisconnected: return "disconnected" } return "unknown" } golang-github-prometheus-procfs-0.14.0/net_unix_test.go000066400000000000000000000074661461002754700232500ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "testing" "github.com/google/go-cmp/cmp" ) // Whether or not to run tests with inode fixtures. const ( checkInode = true noCheckInode = false ) func TestNetUnix(t *testing.T) { fs, err := NewFS(procTestFixtures) if err != nil { t.Fatalf("failed to open procfs: %v", err) } got, err := fs.NetUNIX() if err != nil { t.Fatalf("failed to get UNIX socket data: %v", err) } testNetUNIX(t, checkInode, got) } func TestNetUnixNoInode(t *testing.T) { fs, err := NewFS(procTestFixtures) if err != nil { t.Fatalf("failed to open procfs: %v", err) } got, err := readNetUNIX(fs.proc.Path("net/unix_without_inode")) if err != nil { t.Fatalf("failed to read UNIX socket data: %v", err) } testNetUNIX(t, noCheckInode, got) } func testNetUNIX(t *testing.T, testInode bool, got *NetUNIX) { t.Helper() // First verify that the input data matches a prepopulated structure. want := []*NetUNIXLine{ { KernelPtr: "0000000000000000", RefCount: 2, Flags: 1 << 16, Type: 1, State: 1, Inode: 3442596, Path: "/var/run/postgresql/.s.PGSQL.5432", }, { KernelPtr: "0000000000000000", RefCount: 10, Flags: 1 << 16, Type: 5, State: 1, Inode: 10061, Path: "/run/udev/control", }, { KernelPtr: "0000000000000000", RefCount: 7, Flags: 0, Type: 2, State: 1, Inode: 12392, Path: "/dev/log", }, { KernelPtr: "0000000000000000", RefCount: 3, Flags: 0, Type: 1, State: 3, Inode: 4787297, Path: "/var/run/postgresql/.s.PGSQL.5432", }, { KernelPtr: "0000000000000000", RefCount: 3, Flags: 0, Type: 1, State: 3, Inode: 5091797, }, } // Enable the fixtures to be used for multiple tests by clearing the inode // field when appropriate. if !testInode { for i := 0; i < len(want); i++ { want[i].Inode = 0 } } if diff := cmp.Diff(want, got.Rows); diff != "" { t.Fatalf("unexpected /proc/net/unix data (-want +got):\n%s", diff) } // Now test the field enumerations and ensure they match up correctly // with the constants used to generate readable strings. wantFlags := []NetUNIXFlags{ netUnixFlagListen, netUnixFlagListen, netUnixFlagDefault, netUnixFlagDefault, netUnixFlagDefault, } wantType := []NetUNIXType{ netUnixTypeStream, netUnixTypeSeqpacket, netUnixTypeDgram, netUnixTypeStream, netUnixTypeStream, } wantState := []NetUNIXState{ netUnixStateUnconnected, netUnixStateUnconnected, netUnixStateUnconnected, netUnixStateConnected, netUnixStateConnected, } var ( gotFlags []NetUNIXFlags gotType []NetUNIXType gotState []NetUNIXState ) for _, r := range got.Rows { gotFlags = append(gotFlags, r.Flags) gotType = append(gotType, r.Type) gotState = append(gotState, r.State) } if diff := cmp.Diff(wantFlags, gotFlags); diff != "" { t.Fatalf("unexpected /proc/net/unix flags (-want +got):\n%s", diff) } if diff := cmp.Diff(wantType, gotType); diff != "" { t.Fatalf("unexpected /proc/net/unix types (-want +got):\n%s", diff) } if diff := cmp.Diff(wantState, gotState); diff != "" { t.Fatalf("unexpected /proc/net/unix states (-want +got):\n%s", diff) } } golang-github-prometheus-procfs-0.14.0/net_wireless.go000066400000000000000000000121431461002754700230470ustar00rootroot00000000000000// Copyright 2023 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. package procfs import ( "bufio" "bytes" "fmt" "io" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // Wireless models the content of /proc/net/wireless. type Wireless struct { Name string // Status is the current 4-digit hex value status of the interface. Status uint64 // QualityLink is the link quality. QualityLink int // QualityLevel is the signal gain (dBm). QualityLevel int // QualityNoise is the signal noise baseline (dBm). QualityNoise int // DiscardedNwid is the number of discarded packets with wrong nwid/essid. DiscardedNwid int // DiscardedCrypt is the number of discarded packets with wrong code/decode (WEP). DiscardedCrypt int // DiscardedFrag is the number of discarded packets that can't perform MAC reassembly. DiscardedFrag int // DiscardedRetry is the number of discarded packets that reached max MAC retries. DiscardedRetry int // DiscardedMisc is the number of discarded packets for other reasons. DiscardedMisc int // MissedBeacon is the number of missed beacons/superframe. MissedBeacon int } // Wireless returns kernel wireless statistics. func (fs FS) Wireless() ([]*Wireless, error) { b, err := util.ReadFileNoStat(fs.proc.Path("net/wireless")) if err != nil { return nil, err } m, err := parseWireless(bytes.NewReader(b)) if err != nil { return nil, fmt.Errorf("%w: wireless: %w", ErrFileParse, err) } return m, nil } // parseWireless parses the contents of /proc/net/wireless. /* Inter-| sta-| Quality | Discarded packets | Missed | WE face | tus | link level noise | nwid crypt frag retry misc | beacon | 22 eth1: 0000 5. -256. -10. 0 1 0 3 0 0 eth2: 0000 5. -256. -20. 0 2 0 4 0 0 */ func parseWireless(r io.Reader) ([]*Wireless, error) { var ( interfaces []*Wireless scanner = bufio.NewScanner(r) ) for n := 0; scanner.Scan(); n++ { // Skip the 2 header lines. if n < 2 { continue } line := scanner.Text() parts := strings.Split(line, ":") if len(parts) != 2 { return nil, fmt.Errorf("%w: expected 2 parts after splitting line by ':', got %d for line %q", ErrFileParse, len(parts), line) } name := strings.TrimSpace(parts[0]) stats := strings.Fields(parts[1]) if len(stats) < 10 { return nil, fmt.Errorf("%w: invalid number of fields in line %d, expected 10+, got %d: %q", ErrFileParse, n, len(stats), line) } status, err := strconv.ParseUint(stats[0], 16, 16) if err != nil { return nil, fmt.Errorf("%w: invalid status in line %d: %q", ErrFileParse, n, line) } qlink, err := strconv.Atoi(strings.TrimSuffix(stats[1], ".")) if err != nil { return nil, fmt.Errorf("%w: parse Quality:link as integer %q: %w", ErrFileParse, qlink, err) } qlevel, err := strconv.Atoi(strings.TrimSuffix(stats[2], ".")) if err != nil { return nil, fmt.Errorf("%w: Quality:level as integer %q: %w", ErrFileParse, qlevel, err) } qnoise, err := strconv.Atoi(strings.TrimSuffix(stats[3], ".")) if err != nil { return nil, fmt.Errorf("%w: Quality:noise as integer %q: %w", ErrFileParse, qnoise, err) } dnwid, err := strconv.Atoi(stats[4]) if err != nil { return nil, fmt.Errorf("%w: Discarded:nwid as integer %q: %w", ErrFileParse, dnwid, err) } dcrypt, err := strconv.Atoi(stats[5]) if err != nil { return nil, fmt.Errorf("%w: Discarded:crypt as integer %q: %w", ErrFileParse, dcrypt, err) } dfrag, err := strconv.Atoi(stats[6]) if err != nil { return nil, fmt.Errorf("%w: Discarded:frag as integer %q: %w", ErrFileParse, dfrag, err) } dretry, err := strconv.Atoi(stats[7]) if err != nil { return nil, fmt.Errorf("%w: Discarded:retry as integer %q: %w", ErrFileParse, dretry, err) } dmisc, err := strconv.Atoi(stats[8]) if err != nil { return nil, fmt.Errorf("%w: Discarded:misc as integer %q: %w", ErrFileParse, dmisc, err) } mbeacon, err := strconv.Atoi(stats[9]) if err != nil { return nil, fmt.Errorf("%w: Missed:beacon as integer %q: %w", ErrFileParse, mbeacon, err) } w := &Wireless{ Name: name, Status: status, QualityLink: qlink, QualityLevel: qlevel, QualityNoise: qnoise, DiscardedNwid: dnwid, DiscardedCrypt: dcrypt, DiscardedFrag: dfrag, DiscardedRetry: dretry, DiscardedMisc: dmisc, MissedBeacon: mbeacon, } interfaces = append(interfaces, w) } if err := scanner.Err(); err != nil { return nil, fmt.Errorf("%w: Failed to scan /proc/net/wireless: %w", ErrFileRead, err) } return interfaces, nil } golang-github-prometheus-procfs-0.14.0/net_wireless_test.go000066400000000000000000000032201461002754700241020ustar00rootroot00000000000000// Copyright 2023 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. package procfs import ( "reflect" "testing" ) func TestWireless(t *testing.T) { fs, err := NewFS(procTestFixtures) if err != nil { t.Fatalf("failed to open procfs: %v", err) } got, err := fs.Wireless() if err != nil { t.Fatal(err) } expected := []*Wireless{ { Name: "wlan0", Status: 1, QualityLink: 2, QualityLevel: 3, QualityNoise: 4, DiscardedNwid: 5, DiscardedCrypt: 6, DiscardedFrag: 7, DiscardedRetry: 8, DiscardedMisc: 9, MissedBeacon: 10, }, { Name: "wlan1", Status: 16, QualityLink: 9, QualityLevel: 8, QualityNoise: 7, DiscardedNwid: 6, DiscardedCrypt: 5, DiscardedFrag: 4, DiscardedRetry: 3, DiscardedMisc: 2, MissedBeacon: 1, }, } if len(got) != len(expected) { t.Fatalf("unexpected number of interfaces parsed %d, expected %d", len(got), len(expected)) } for i, iface := range got { if !reflect.DeepEqual(iface, expected[i]) { t.Errorf("unexpected interface got %+v, expected %+v", iface, expected[i]) } } } golang-github-prometheus-procfs-0.14.0/net_xfrm.go000066400000000000000000000116041461002754700221670ustar00rootroot00000000000000// Copyright 2017 Prometheus Team // 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. package procfs import ( "bufio" "fmt" "os" "strconv" "strings" ) // XfrmStat models the contents of /proc/net/xfrm_stat. type XfrmStat struct { // All errors which are not matched by other XfrmInError int // No buffer is left XfrmInBufferError int // Header Error XfrmInHdrError int // No state found // i.e. either inbound SPI, address, or IPSEC protocol at SA is wrong XfrmInNoStates int // Transformation protocol specific error // e.g. SA Key is wrong XfrmInStateProtoError int // Transformation mode specific error XfrmInStateModeError int // Sequence error // e.g. sequence number is out of window XfrmInStateSeqError int // State is expired XfrmInStateExpired int // State has mismatch option // e.g. UDP encapsulation type is mismatched XfrmInStateMismatch int // State is invalid XfrmInStateInvalid int // No matching template for states // e.g. Inbound SAs are correct but SP rule is wrong XfrmInTmplMismatch int // No policy is found for states // e.g. Inbound SAs are correct but no SP is found XfrmInNoPols int // Policy discards XfrmInPolBlock int // Policy error XfrmInPolError int // All errors which are not matched by others XfrmOutError int // Bundle generation error XfrmOutBundleGenError int // Bundle check error XfrmOutBundleCheckError int // No state was found XfrmOutNoStates int // Transformation protocol specific error XfrmOutStateProtoError int // Transportation mode specific error XfrmOutStateModeError int // Sequence error // i.e sequence number overflow XfrmOutStateSeqError int // State is expired XfrmOutStateExpired int // Policy discads XfrmOutPolBlock int // Policy is dead XfrmOutPolDead int // Policy Error XfrmOutPolError int // Forward routing of a packet is not allowed XfrmFwdHdrError int // State is invalid, perhaps expired XfrmOutStateInvalid int // State hasn’t been fully acquired before use XfrmAcquireError int } // NewXfrmStat reads the xfrm_stat statistics. func NewXfrmStat() (XfrmStat, error) { fs, err := NewFS(DefaultMountPoint) if err != nil { return XfrmStat{}, err } return fs.NewXfrmStat() } // NewXfrmStat reads the xfrm_stat statistics from the 'proc' filesystem. func (fs FS) NewXfrmStat() (XfrmStat, error) { file, err := os.Open(fs.proc.Path("net/xfrm_stat")) if err != nil { return XfrmStat{}, err } defer file.Close() var ( x = XfrmStat{} s = bufio.NewScanner(file) ) for s.Scan() { fields := strings.Fields(s.Text()) if len(fields) != 2 { return XfrmStat{}, fmt.Errorf("%w: %q line %q", ErrFileParse, file.Name(), s.Text()) } name := fields[0] value, err := strconv.Atoi(fields[1]) if err != nil { return XfrmStat{}, err } switch name { case "XfrmInError": x.XfrmInError = value case "XfrmInBufferError": x.XfrmInBufferError = value case "XfrmInHdrError": x.XfrmInHdrError = value case "XfrmInNoStates": x.XfrmInNoStates = value case "XfrmInStateProtoError": x.XfrmInStateProtoError = value case "XfrmInStateModeError": x.XfrmInStateModeError = value case "XfrmInStateSeqError": x.XfrmInStateSeqError = value case "XfrmInStateExpired": x.XfrmInStateExpired = value case "XfrmInStateInvalid": x.XfrmInStateInvalid = value case "XfrmInTmplMismatch": x.XfrmInTmplMismatch = value case "XfrmInNoPols": x.XfrmInNoPols = value case "XfrmInPolBlock": x.XfrmInPolBlock = value case "XfrmInPolError": x.XfrmInPolError = value case "XfrmOutError": x.XfrmOutError = value case "XfrmInStateMismatch": x.XfrmInStateMismatch = value case "XfrmOutBundleGenError": x.XfrmOutBundleGenError = value case "XfrmOutBundleCheckError": x.XfrmOutBundleCheckError = value case "XfrmOutNoStates": x.XfrmOutNoStates = value case "XfrmOutStateProtoError": x.XfrmOutStateProtoError = value case "XfrmOutStateModeError": x.XfrmOutStateModeError = value case "XfrmOutStateSeqError": x.XfrmOutStateSeqError = value case "XfrmOutStateExpired": x.XfrmOutStateExpired = value case "XfrmOutPolBlock": x.XfrmOutPolBlock = value case "XfrmOutPolDead": x.XfrmOutPolDead = value case "XfrmOutPolError": x.XfrmOutPolError = value case "XfrmFwdHdrError": x.XfrmFwdHdrError = value case "XfrmOutStateInvalid": x.XfrmOutStateInvalid = value case "XfrmAcquireError": x.XfrmAcquireError = value } } return x, s.Err() } golang-github-prometheus-procfs-0.14.0/net_xfrm_test.go000066400000000000000000000062251461002754700232310ustar00rootroot00000000000000// Copyright 2017 Prometheus Team // 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. package procfs import ( "testing" ) func TestXfrmStats(t *testing.T) { xfrmStats, err := getProcFixtures(t).NewXfrmStat() if err != nil { t.Fatal(err) } for _, test := range []struct { name string want int got int }{ {name: "XfrmInError", want: 1, got: xfrmStats.XfrmInError}, {name: "XfrmInBufferError", want: 2, got: xfrmStats.XfrmInBufferError}, {name: "XfrmInHdrError", want: 4, got: xfrmStats.XfrmInHdrError}, {name: "XfrmInNoStates", want: 3, got: xfrmStats.XfrmInNoStates}, {name: "XfrmInStateProtoError", want: 40, got: xfrmStats.XfrmInStateProtoError}, {name: "XfrmInStateModeError", want: 100, got: xfrmStats.XfrmInStateModeError}, {name: "XfrmInStateSeqError", want: 6000, got: xfrmStats.XfrmInStateSeqError}, {name: "XfrmInStateExpired", want: 4, got: xfrmStats.XfrmInStateExpired}, {name: "XfrmInStateMismatch", want: 23451, got: xfrmStats.XfrmInStateMismatch}, {name: "XfrmInStateInvalid", want: 55555, got: xfrmStats.XfrmInStateInvalid}, {name: "XfrmInTmplMismatch", want: 51, got: xfrmStats.XfrmInTmplMismatch}, {name: "XfrmInNoPols", want: 65432, got: xfrmStats.XfrmInNoPols}, {name: "XfrmInPolBlock", want: 100, got: xfrmStats.XfrmInPolBlock}, {name: "XfrmInPolError", want: 10000, got: xfrmStats.XfrmInPolError}, {name: "XfrmOutError", want: 1000000, got: xfrmStats.XfrmOutError}, {name: "XfrmOutBundleGenError", want: 43321, got: xfrmStats.XfrmOutBundleGenError}, {name: "XfrmOutBundleCheckError", want: 555, got: xfrmStats.XfrmOutBundleCheckError}, {name: "XfrmOutNoStates", want: 869, got: xfrmStats.XfrmOutNoStates}, {name: "XfrmOutStateProtoError", want: 4542, got: xfrmStats.XfrmOutStateProtoError}, {name: "XfrmOutStateModeError", want: 4, got: xfrmStats.XfrmOutStateModeError}, {name: "XfrmOutStateSeqError", want: 543, got: xfrmStats.XfrmOutStateSeqError}, {name: "XfrmOutStateExpired", want: 565, got: xfrmStats.XfrmOutStateExpired}, {name: "XfrmOutPolBlock", want: 43456, got: xfrmStats.XfrmOutPolBlock}, {name: "XfrmOutPolDead", want: 7656, got: xfrmStats.XfrmOutPolDead}, {name: "XfrmOutPolError", want: 1454, got: xfrmStats.XfrmOutPolError}, {name: "XfrmFwdHdrError", want: 6654, got: xfrmStats.XfrmFwdHdrError}, {name: "XfrmOutStateInvaliad", want: 28765, got: xfrmStats.XfrmOutStateInvalid}, {name: "XfrmAcquireError", want: 24532, got: xfrmStats.XfrmAcquireError}, {name: "XfrmInStateInvalid", want: 55555, got: xfrmStats.XfrmInStateInvalid}, {name: "XfrmOutError", want: 1000000, got: xfrmStats.XfrmOutError}, } { if test.want != test.got { t.Errorf("Want %s %d, have %d", test.name, test.want, test.got) } } } golang-github-prometheus-procfs-0.14.0/netstat.go000066400000000000000000000041171461002754700220300ustar00rootroot00000000000000// Copyright 2020 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. package procfs import ( "bufio" "os" "path/filepath" "strconv" "strings" ) // NetStat contains statistics for all the counters from one file. type NetStat struct { Stats map[string][]uint64 Filename string } // NetStat retrieves stats from `/proc/net/stat/`. func (fs FS) NetStat() ([]NetStat, error) { statFiles, err := filepath.Glob(fs.proc.Path("net/stat/*")) if err != nil { return nil, err } var netStatsTotal []NetStat for _, filePath := range statFiles { procNetstat, err := parseNetstat(filePath) if err != nil { return nil, err } procNetstat.Filename = filepath.Base(filePath) netStatsTotal = append(netStatsTotal, procNetstat) } return netStatsTotal, nil } // parseNetstat parses the metrics from `/proc/net/stat/` file // and returns a NetStat structure. func parseNetstat(filePath string) (NetStat, error) { netStat := NetStat{ Stats: make(map[string][]uint64), } file, err := os.Open(filePath) if err != nil { return netStat, err } defer file.Close() scanner := bufio.NewScanner(file) scanner.Scan() // First string is always a header for stats var headers []string headers = append(headers, strings.Fields(scanner.Text())...) // Other strings represent per-CPU counters for scanner.Scan() { for num, counter := range strings.Fields(scanner.Text()) { value, err := strconv.ParseUint(counter, 16, 64) if err != nil { return NetStat{}, err } netStat.Stats[headers[num]] = append(netStat.Stats[headers[num]], value) } } return netStat, nil } golang-github-prometheus-procfs-0.14.0/netstat_test.go000066400000000000000000000076511461002754700230750ustar00rootroot00000000000000// Copyright 2020 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. package procfs import ( "testing" ) func TestNetStat(t *testing.T) { const ( filesCount = 2 CPUsCount = 2 arpCacheMetricsCount = 13 ndiscCacheMetricsCount = 13 ) fs, err := NewFS(procTestFixtures) if err != nil { t.Fatalf("failed to open procfs: %v", err) } netStats, err := fs.NetStat() if err != nil { t.Fatalf("NetStat() error: %s", err) } if len(netStats) != filesCount { t.Fatalf("unexpected number of files parsed %d, expected %d", len(netStats), filesCount) } expectedStats := [2]NetStat{ { Filename: "arp_cache", Stats: make(map[string][]uint64), }, { Filename: "ndisc_cache", Stats: make(map[string][]uint64), }, } for _, expected := range expectedStats { if expected.Filename == "arp_cache" { expected.Stats["entries"] = []uint64{20, 20} expected.Stats["allocs"] = []uint64{1, 13} expected.Stats["destroys"] = []uint64{2, 14} expected.Stats["hash_grows"] = []uint64{3, 15} expected.Stats["lookups"] = []uint64{4, 16} expected.Stats["hits"] = []uint64{5, 17} expected.Stats["res_failed"] = []uint64{6, 18} expected.Stats["rcv_probes_mcast"] = []uint64{7, 19} expected.Stats["rcv_probes_ucast"] = []uint64{8, 20} expected.Stats["periodic_gc_runs"] = []uint64{9, 21} expected.Stats["forced_gc_runs"] = []uint64{10, 22} expected.Stats["unresolved_discards"] = []uint64{11, 23} expected.Stats["table_fulls"] = []uint64{12, 24} } if expected.Filename == "ndisc_cache" { expected.Stats["entries"] = []uint64{36, 36} expected.Stats["allocs"] = []uint64{240, 252} expected.Stats["destroys"] = []uint64{241, 253} expected.Stats["hash_grows"] = []uint64{242, 254} expected.Stats["lookups"] = []uint64{243, 255} expected.Stats["hits"] = []uint64{244, 256} expected.Stats["res_failed"] = []uint64{245, 257} expected.Stats["rcv_probes_mcast"] = []uint64{246, 258} expected.Stats["rcv_probes_ucast"] = []uint64{247, 259} expected.Stats["periodic_gc_runs"] = []uint64{248, 260} expected.Stats["forced_gc_runs"] = []uint64{249, 261} expected.Stats["unresolved_discards"] = []uint64{250, 262} expected.Stats["table_fulls"] = []uint64{251, 263} } } for _, netStatFile := range netStats { if netStatFile.Filename == "arp_cache" && len(netStatFile.Stats) != arpCacheMetricsCount { t.Fatalf("unexpected arp_cache metrics count %d, expected %d", len(netStatFile.Stats), arpCacheMetricsCount) } if netStatFile.Filename == "ndisc_cache" && len(netStatFile.Stats) != ndiscCacheMetricsCount { t.Fatalf("unexpected ndisc_cache metrics count %d, expected %d", len(netStatFile.Stats), ndiscCacheMetricsCount) } for _, expected := range expectedStats { for header, stats := range netStatFile.Stats { if header == "" { t.Fatalf("Found empty metric name") } if len(stats) != CPUsCount { t.Fatalf("NetStat() parsed %d lines with metrics, expected %d", len(stats), CPUsCount) } if netStatFile.Filename == expected.Filename { if expected.Stats[header] == nil { t.Fatalf("unexpected metric header: %s", header) } for cpu, value := range netStatFile.Stats[header] { if expected.Stats[header][cpu] != value { t.Fatalf("unexpected value for %s for cpu %d in %s: %d, expected %d", header, cpu, netStatFile.Filename, value, expected.Stats[header][cpu]) } } } } } } } golang-github-prometheus-procfs-0.14.0/nfs/000077500000000000000000000000001461002754700206025ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/nfs/nfs.go000066400000000000000000000176651461002754700217360ustar00rootroot00000000000000// Copyright 2018 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. // Package nfs implements parsing of /proc/net/rpc/nfsd. // Fields are documented in https://www.svennd.be/nfsd-stats-explained-procnetrpcnfsd/ package nfs import ( "os" "strings" "github.com/prometheus/procfs/internal/fs" ) // ReplyCache models the "rc" line. type ReplyCache struct { Hits uint64 Misses uint64 NoCache uint64 } // FileHandles models the "fh" line. type FileHandles struct { Stale uint64 TotalLookups uint64 AnonLookups uint64 DirNoCache uint64 NoDirNoCache uint64 } // InputOutput models the "io" line. type InputOutput struct { Read uint64 Write uint64 } // Threads models the "th" line. type Threads struct { Threads uint64 FullCnt uint64 } // ReadAheadCache models the "ra" line. type ReadAheadCache struct { CacheSize uint64 CacheHistogram []uint64 NotFound uint64 } // Network models the "net" line. type Network struct { NetCount uint64 UDPCount uint64 TCPCount uint64 TCPConnect uint64 } // ClientRPC models the nfs "rpc" line. type ClientRPC struct { RPCCount uint64 Retransmissions uint64 AuthRefreshes uint64 } // ServerRPC models the nfsd "rpc" line. type ServerRPC struct { RPCCount uint64 BadCnt uint64 BadFmt uint64 BadAuth uint64 BadcInt uint64 } // V2Stats models the "proc2" line. type V2Stats struct { Null uint64 GetAttr uint64 SetAttr uint64 Root uint64 Lookup uint64 ReadLink uint64 Read uint64 WrCache uint64 Write uint64 Create uint64 Remove uint64 Rename uint64 Link uint64 SymLink uint64 MkDir uint64 RmDir uint64 ReadDir uint64 FsStat uint64 } // V3Stats models the "proc3" line. type V3Stats struct { Null uint64 GetAttr uint64 SetAttr uint64 Lookup uint64 Access uint64 ReadLink uint64 Read uint64 Write uint64 Create uint64 MkDir uint64 SymLink uint64 MkNod uint64 Remove uint64 RmDir uint64 Rename uint64 Link uint64 ReadDir uint64 ReadDirPlus uint64 FsStat uint64 FsInfo uint64 PathConf uint64 Commit uint64 } // ClientV4Stats models the nfs "proc4" line. type ClientV4Stats struct { Null uint64 Read uint64 Write uint64 Commit uint64 Open uint64 OpenConfirm uint64 OpenNoattr uint64 OpenDowngrade uint64 Close uint64 Setattr uint64 FsInfo uint64 Renew uint64 SetClientID uint64 SetClientIDConfirm uint64 Lock uint64 Lockt uint64 Locku uint64 Access uint64 Getattr uint64 Lookup uint64 LookupRoot uint64 Remove uint64 Rename uint64 Link uint64 Symlink uint64 Create uint64 Pathconf uint64 StatFs uint64 ReadLink uint64 ReadDir uint64 ServerCaps uint64 DelegReturn uint64 GetACL uint64 SetACL uint64 FsLocations uint64 ReleaseLockowner uint64 Secinfo uint64 FsidPresent uint64 ExchangeID uint64 CreateSession uint64 DestroySession uint64 Sequence uint64 GetLeaseTime uint64 ReclaimComplete uint64 LayoutGet uint64 GetDeviceInfo uint64 LayoutCommit uint64 LayoutReturn uint64 SecinfoNoName uint64 TestStateID uint64 FreeStateID uint64 GetDeviceList uint64 BindConnToSession uint64 DestroyClientID uint64 Seek uint64 Allocate uint64 DeAllocate uint64 LayoutStats uint64 Clone uint64 } // ServerV4Stats models the nfsd "proc4" line. type ServerV4Stats struct { Null uint64 Compound uint64 } // V4Ops models the "proc4ops" line: NFSv4 operations // Variable list. // See: // - v4.0 https://tools.ietf.org/html/rfc3010 (38/39 operations) // - nfs == v2.5.x 38 field : https://elixir.bootlin.com/linux/v2.5.75/source/include/linux/nfs4.h#L52 // - nfs >= v2.6.x 39 field : https://elixir.bootlin.com/linux/v2.6.39.4/source/include/linux/nfs4.h#L233 // // - v4.1 https://tools.ietf.org/html/rfc5661 (58 operations) // - v4.2 https://tools.ietf.org/html/draft-ietf-nfsv4-minorversion2-41 (71 operations) // //nolint:godot type V4Ops struct { //Values uint64 // Variable depending on v4.x sub-version. TODO: Will this always at least include the fields in this struct? Op0Unused uint64 Op1Unused uint64 Op2Future uint64 Access uint64 Close uint64 Commit uint64 Create uint64 DelegPurge uint64 DelegReturn uint64 GetAttr uint64 GetFH uint64 Link uint64 Lock uint64 Lockt uint64 Locku uint64 Lookup uint64 LookupRoot uint64 Nverify uint64 Open uint64 OpenAttr uint64 OpenConfirm uint64 OpenDgrd uint64 PutFH uint64 PutPubFH uint64 PutRootFH uint64 Read uint64 ReadDir uint64 ReadLink uint64 Remove uint64 Rename uint64 Renew uint64 RestoreFH uint64 SaveFH uint64 SecInfo uint64 SetAttr uint64 SetClientID uint64 SetClientIDConfirm uint64 Verify uint64 Write uint64 RelLockOwner uint64 } // ClientRPCStats models all stats from /proc/net/rpc/nfs. type ClientRPCStats struct { Network Network ClientRPC ClientRPC V2Stats V2Stats V3Stats V3Stats ClientV4Stats ClientV4Stats } // ServerRPCStats models all stats from /proc/net/rpc/nfsd. type ServerRPCStats struct { ReplyCache ReplyCache FileHandles FileHandles InputOutput InputOutput Threads Threads ReadAheadCache ReadAheadCache Network Network ServerRPC ServerRPC V2Stats V2Stats V3Stats V3Stats ServerV4Stats ServerV4Stats V4Ops V4Ops WdelegGetattr uint64 } // FS represents the pseudo-filesystem proc, which provides an interface to // kernel data structures. type FS struct { proc *fs.FS } // NewDefaultFS returns a new FS mounted under the default mountPoint. It will error // if the mount point can't be read. func NewDefaultFS() (FS, error) { return NewFS(fs.DefaultProcMountPoint) } // NewFS returns a new FS mounted under the given mountPoint. It will error // if the mount point can't be read. func NewFS(mountPoint string) (FS, error) { if strings.TrimSpace(mountPoint) == "" { mountPoint = fs.DefaultProcMountPoint } fs, err := fs.NewFS(mountPoint) if err != nil { return FS{}, err } return FS{&fs}, nil } // ClientRPCStats retrieves NFS client RPC statistics // from proc/net/rpc/nfs. func (fs FS) ClientRPCStats() (*ClientRPCStats, error) { f, err := os.Open(fs.proc.Path("net/rpc/nfs")) if err != nil { return nil, err } defer f.Close() return ParseClientRPCStats(f) } // ServerRPCStats retrieves NFS daemon RPC statistics // from proc/net/rpc/nfsd. func (fs FS) ServerRPCStats() (*ServerRPCStats, error) { f, err := os.Open(fs.proc.Path("net/rpc/nfsd")) if err != nil { return nil, err } defer f.Close() return ParseServerRPCStats(f) } golang-github-prometheus-procfs-0.14.0/nfs/parse.go000066400000000000000000000170271461002754700222520ustar00rootroot00000000000000// Copyright 2018 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. package nfs import ( "fmt" ) func parseReplyCache(v []uint64) (ReplyCache, error) { if len(v) != 3 { return ReplyCache{}, fmt.Errorf("invalid ReplyCache line %q", v) } return ReplyCache{ Hits: v[0], Misses: v[1], NoCache: v[2], }, nil } func parseFileHandles(v []uint64) (FileHandles, error) { if len(v) != 5 { return FileHandles{}, fmt.Errorf("invalid FileHandles, line %q", v) } return FileHandles{ Stale: v[0], TotalLookups: v[1], AnonLookups: v[2], DirNoCache: v[3], NoDirNoCache: v[4], }, nil } func parseInputOutput(v []uint64) (InputOutput, error) { if len(v) != 2 { return InputOutput{}, fmt.Errorf("invalid InputOutput line %q", v) } return InputOutput{ Read: v[0], Write: v[1], }, nil } func parseThreads(v []uint64) (Threads, error) { if len(v) != 2 { return Threads{}, fmt.Errorf("invalid Threads line %q", v) } return Threads{ Threads: v[0], FullCnt: v[1], }, nil } func parseReadAheadCache(v []uint64) (ReadAheadCache, error) { if len(v) != 12 { return ReadAheadCache{}, fmt.Errorf("invalid ReadAheadCache line %q", v) } return ReadAheadCache{ CacheSize: v[0], CacheHistogram: v[1:11], NotFound: v[11], }, nil } func parseNetwork(v []uint64) (Network, error) { if len(v) != 4 { return Network{}, fmt.Errorf("invalid Network line %q", v) } return Network{ NetCount: v[0], UDPCount: v[1], TCPCount: v[2], TCPConnect: v[3], }, nil } func parseServerRPC(v []uint64) (ServerRPC, error) { if len(v) != 5 { return ServerRPC{}, fmt.Errorf("invalid RPC line %q", v) } return ServerRPC{ RPCCount: v[0], BadCnt: v[1], BadFmt: v[2], BadAuth: v[3], BadcInt: v[4], }, nil } func parseClientRPC(v []uint64) (ClientRPC, error) { if len(v) != 3 { return ClientRPC{}, fmt.Errorf("invalid RPC line %q", v) } return ClientRPC{ RPCCount: v[0], Retransmissions: v[1], AuthRefreshes: v[2], }, nil } func parseV2Stats(v []uint64) (V2Stats, error) { values := int(v[0]) if len(v[1:]) != values || values < 18 { return V2Stats{}, fmt.Errorf("invalid V2Stats line %q", v) } return V2Stats{ Null: v[1], GetAttr: v[2], SetAttr: v[3], Root: v[4], Lookup: v[5], ReadLink: v[6], Read: v[7], WrCache: v[8], Write: v[9], Create: v[10], Remove: v[11], Rename: v[12], Link: v[13], SymLink: v[14], MkDir: v[15], RmDir: v[16], ReadDir: v[17], FsStat: v[18], }, nil } func parseV3Stats(v []uint64) (V3Stats, error) { values := int(v[0]) if len(v[1:]) != values || values < 22 { return V3Stats{}, fmt.Errorf("invalid V3Stats line %q", v) } return V3Stats{ Null: v[1], GetAttr: v[2], SetAttr: v[3], Lookup: v[4], Access: v[5], ReadLink: v[6], Read: v[7], Write: v[8], Create: v[9], MkDir: v[10], SymLink: v[11], MkNod: v[12], Remove: v[13], RmDir: v[14], Rename: v[15], Link: v[16], ReadDir: v[17], ReadDirPlus: v[18], FsStat: v[19], FsInfo: v[20], PathConf: v[21], Commit: v[22], }, nil } func parseClientV4Stats(v []uint64) (ClientV4Stats, error) { values := int(v[0]) if len(v[1:]) != values { return ClientV4Stats{}, fmt.Errorf("invalid ClientV4Stats line %q", v) } // This function currently supports mapping 59 NFS v4 client stats. Older // kernels may emit fewer stats, so we must detect this and pad out the // values to match the expected slice size. if values < 59 { newValues := make([]uint64, 60) copy(newValues, v) v = newValues } return ClientV4Stats{ Null: v[1], Read: v[2], Write: v[3], Commit: v[4], Open: v[5], OpenConfirm: v[6], OpenNoattr: v[7], OpenDowngrade: v[8], Close: v[9], Setattr: v[10], FsInfo: v[11], Renew: v[12], SetClientID: v[13], SetClientIDConfirm: v[14], Lock: v[15], Lockt: v[16], Locku: v[17], Access: v[18], Getattr: v[19], Lookup: v[20], LookupRoot: v[21], Remove: v[22], Rename: v[23], Link: v[24], Symlink: v[25], Create: v[26], Pathconf: v[27], StatFs: v[28], ReadLink: v[29], ReadDir: v[30], ServerCaps: v[31], DelegReturn: v[32], GetACL: v[33], SetACL: v[34], FsLocations: v[35], ReleaseLockowner: v[36], Secinfo: v[37], FsidPresent: v[38], ExchangeID: v[39], CreateSession: v[40], DestroySession: v[41], Sequence: v[42], GetLeaseTime: v[43], ReclaimComplete: v[44], LayoutGet: v[45], GetDeviceInfo: v[46], LayoutCommit: v[47], LayoutReturn: v[48], SecinfoNoName: v[49], TestStateID: v[50], FreeStateID: v[51], GetDeviceList: v[52], BindConnToSession: v[53], DestroyClientID: v[54], Seek: v[55], Allocate: v[56], DeAllocate: v[57], LayoutStats: v[58], Clone: v[59], }, nil } func parseServerV4Stats(v []uint64) (ServerV4Stats, error) { values := int(v[0]) if len(v[1:]) != values || values != 2 { return ServerV4Stats{}, fmt.Errorf("invalid V4Stats line %q", v) } return ServerV4Stats{ Null: v[1], Compound: v[2], }, nil } func parseV4Ops(v []uint64) (V4Ops, error) { values := int(v[0]) if len(v[1:]) != values || values < 39 { return V4Ops{}, fmt.Errorf("invalid V4Ops line %q", v) } // nfs v2.5.x 39field and >=v2.6.x 40 field; v40 := uint64(0) if values > 39 { v40 = v[40] } stats := V4Ops{ Op0Unused: v[1], Op1Unused: v[2], Op2Future: v[3], Access: v[4], Close: v[5], Commit: v[6], Create: v[7], DelegPurge: v[8], DelegReturn: v[9], GetAttr: v[10], GetFH: v[11], Link: v[12], Lock: v[13], Lockt: v[14], Locku: v[15], Lookup: v[16], LookupRoot: v[17], Nverify: v[18], Open: v[19], OpenAttr: v[20], OpenConfirm: v[21], OpenDgrd: v[22], PutFH: v[23], PutPubFH: v[24], PutRootFH: v[25], Read: v[26], ReadDir: v[27], ReadLink: v[28], Remove: v[29], Rename: v[30], Renew: v[31], RestoreFH: v[32], SaveFH: v[33], SecInfo: v[34], SetAttr: v[35], SetClientID: v[36], SetClientIDConfirm: v[37], Verify: v[38], Write: v[39], RelLockOwner: v40, } return stats, nil } golang-github-prometheus-procfs-0.14.0/nfs/parse_nfs.go000066400000000000000000000035631461002754700231200ustar00rootroot00000000000000// Copyright 2018 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. package nfs import ( "bufio" "fmt" "io" "strings" "github.com/prometheus/procfs/internal/util" ) // ParseClientRPCStats returns stats read from /proc/net/rpc/nfs. func ParseClientRPCStats(r io.Reader) (*ClientRPCStats, error) { stats := &ClientRPCStats{} scanner := bufio.NewScanner(r) for scanner.Scan() { line := scanner.Text() parts := strings.Fields(scanner.Text()) // require at least if len(parts) < 2 { return nil, fmt.Errorf("invalid NFS metric line %q", line) } values, err := util.ParseUint64s(parts[1:]) if err != nil { return nil, fmt.Errorf("error parsing NFS metric line: %w", err) } switch metricLine := parts[0]; metricLine { case "net": stats.Network, err = parseNetwork(values) case "rpc": stats.ClientRPC, err = parseClientRPC(values) case "proc2": stats.V2Stats, err = parseV2Stats(values) case "proc3": stats.V3Stats, err = parseV3Stats(values) case "proc4": stats.ClientV4Stats, err = parseClientV4Stats(values) default: return nil, fmt.Errorf("unknown NFS metric line %q", metricLine) } if err != nil { return nil, fmt.Errorf("errors parsing NFS metric line: %w", err) } } if err := scanner.Err(); err != nil { return nil, fmt.Errorf("error scanning NFS file: %w", err) } return stats, nil } golang-github-prometheus-procfs-0.14.0/nfs/parse_nfs_test.go000066400000000000000000000175641461002754700241650ustar00rootroot00000000000000// Copyright 2018 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. package nfs_test import ( "reflect" "strings" "testing" "github.com/prometheus/procfs/nfs" ) func TestNewNFSClientRPCStats(t *testing.T) { tests := []struct { name string content string stats *nfs.ClientRPCStats invalid bool }{ { name: "invalid file", content: "invalid", invalid: true, }, { name: "good old kernel version file", content: `net 70 70 69 45 rpc 1218785755 374636 1218815394 proc2 18 16 57 74 52 71 73 45 86 0 52 83 61 17 53 50 23 70 82 proc3 22 0 1061909262 48906 4077635 117661341 5 29391916 2570425 2993289 590 0 0 7815 15 1130 0 3983 92385 13332 2 1 23729 proc4 48 98 51 54 83 85 23 24 1 28 73 68 83 12 84 39 68 59 58 88 29 74 69 96 21 84 15 53 86 54 66 56 97 36 49 32 85 81 11 58 32 67 13 28 35 90 1 26 1337 `, stats: &nfs.ClientRPCStats{ Network: nfs.Network{ NetCount: 70, UDPCount: 70, TCPCount: 69, TCPConnect: 45, }, ClientRPC: nfs.ClientRPC{ RPCCount: 1218785755, Retransmissions: 374636, AuthRefreshes: 1218815394, }, V2Stats: nfs.V2Stats{ Null: 16, GetAttr: 57, SetAttr: 74, Root: 52, Lookup: 71, ReadLink: 73, Read: 45, WrCache: 86, Write: 0, Create: 52, Remove: 83, Rename: 61, Link: 17, SymLink: 53, MkDir: 50, RmDir: 23, ReadDir: 70, FsStat: 82, }, V3Stats: nfs.V3Stats{ Null: 0, GetAttr: 1061909262, SetAttr: 48906, Lookup: 4077635, Access: 117661341, ReadLink: 5, Read: 29391916, Write: 2570425, Create: 2993289, MkDir: 590, SymLink: 0, MkNod: 0, Remove: 7815, RmDir: 15, Rename: 1130, Link: 0, ReadDir: 3983, ReadDirPlus: 92385, FsStat: 13332, FsInfo: 2, PathConf: 1, Commit: 23729}, ClientV4Stats: nfs.ClientV4Stats{ Null: 98, Read: 51, Write: 54, Commit: 83, Open: 85, OpenConfirm: 23, OpenNoattr: 24, OpenDowngrade: 1, Close: 28, Setattr: 73, FsInfo: 68, Renew: 83, SetClientID: 12, SetClientIDConfirm: 84, Lock: 39, Lockt: 68, Locku: 59, Access: 58, Getattr: 88, Lookup: 29, LookupRoot: 74, Remove: 69, Rename: 96, Link: 21, Symlink: 84, Create: 15, Pathconf: 53, StatFs: 86, ReadLink: 54, ReadDir: 66, ServerCaps: 56, DelegReturn: 97, GetACL: 36, SetACL: 49, FsLocations: 32, ReleaseLockowner: 85, Secinfo: 81, FsidPresent: 11, ExchangeID: 58, CreateSession: 32, DestroySession: 67, Sequence: 13, GetLeaseTime: 28, ReclaimComplete: 35, LayoutGet: 90, GetDeviceInfo: 1, LayoutCommit: 26, LayoutReturn: 1337, SecinfoNoName: 0, TestStateID: 0, FreeStateID: 0, GetDeviceList: 0, BindConnToSession: 0, DestroyClientID: 0, Seek: 0, Allocate: 0, DeAllocate: 0, LayoutStats: 0, Clone: 0, }, }, }, { name: "good file", content: `net 18628 0 18628 6 rpc 4329785 0 4338291 proc2 18 2 69 0 0 4410 0 0 0 0 0 0 0 0 0 0 0 99 2 proc3 22 1 4084749 29200 94754 32580 186 47747 7981 8639 0 6356 0 6962 0 7958 0 0 241 4 4 2 39 proc4 61 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 `, stats: &nfs.ClientRPCStats{ Network: nfs.Network{ NetCount: 18628, UDPCount: 0, TCPCount: 18628, TCPConnect: 6, }, ClientRPC: nfs.ClientRPC{ RPCCount: 4329785, Retransmissions: 0, AuthRefreshes: 4338291, }, V2Stats: nfs.V2Stats{ Null: 2, GetAttr: 69, SetAttr: 0, Root: 0, Lookup: 4410, ReadLink: 0, Read: 0, WrCache: 0, Write: 0, Create: 0, Remove: 0, Rename: 0, Link: 0, SymLink: 0, MkDir: 0, RmDir: 0, ReadDir: 99, FsStat: 2, }, V3Stats: nfs.V3Stats{ Null: 1, GetAttr: 4084749, SetAttr: 29200, Lookup: 94754, Access: 32580, ReadLink: 186, Read: 47747, Write: 7981, Create: 8639, MkDir: 0, SymLink: 6356, MkNod: 0, Remove: 6962, RmDir: 0, Rename: 7958, Link: 0, ReadDir: 0, ReadDirPlus: 241, FsStat: 4, FsInfo: 4, PathConf: 2, Commit: 39, }, ClientV4Stats: nfs.ClientV4Stats{ Null: 1, Read: 0, Write: 0, Commit: 0, Open: 0, OpenConfirm: 0, OpenNoattr: 0, OpenDowngrade: 0, Close: 0, Setattr: 0, FsInfo: 0, Renew: 0, SetClientID: 1, SetClientIDConfirm: 1, Lock: 0, Lockt: 0, Locku: 0, Access: 0, Getattr: 0, Lookup: 0, LookupRoot: 0, Remove: 2, Rename: 0, Link: 0, Symlink: 0, Create: 0, Pathconf: 0, StatFs: 0, ReadLink: 0, ReadDir: 0, ServerCaps: 0, DelegReturn: 0, GetACL: 0, SetACL: 0, FsLocations: 0, ReleaseLockowner: 0, Secinfo: 0, FsidPresent: 0, ExchangeID: 0, CreateSession: 0, DestroySession: 0, Sequence: 0, GetLeaseTime: 0, ReclaimComplete: 0, LayoutGet: 0, GetDeviceInfo: 0, LayoutCommit: 0, LayoutReturn: 0, SecinfoNoName: 0, TestStateID: 0, FreeStateID: 0, GetDeviceList: 0, BindConnToSession: 0, DestroyClientID: 0, Seek: 0, Allocate: 0, DeAllocate: 0, LayoutStats: 0, Clone: 0, }, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { stats, err := nfs.ParseClientRPCStats(strings.NewReader(tt.content)) if tt.invalid && err == nil { t.Fatal("expected an error, but none occurred") } if !tt.invalid && err != nil { t.Fatalf("unexpected error: %v", err) } if want, have := tt.stats, stats; !reflect.DeepEqual(want, have) { t.Fatalf("unexpected NFS stats:\nwant:\n%v\nhave:\n%v", want, have) } }) } } golang-github-prometheus-procfs-0.14.0/nfs/parse_nfsd.go000066400000000000000000000050431461002754700232570ustar00rootroot00000000000000// Copyright 2018 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. package nfs import ( "bufio" "fmt" "io" "strings" "github.com/prometheus/procfs/internal/util" ) // ParseServerRPCStats returns stats read from /proc/net/rpc/nfsd. func ParseServerRPCStats(r io.Reader) (*ServerRPCStats, error) { stats := &ServerRPCStats{} scanner := bufio.NewScanner(r) for scanner.Scan() { line := scanner.Text() parts := strings.Fields(scanner.Text()) // require at least if len(parts) < 2 { return nil, fmt.Errorf("invalid NFSd metric line %q", line) } label := parts[0] var values []uint64 var err error if label == "th" { if len(parts) < 3 { return nil, fmt.Errorf("invalid NFSd th metric line %q", line) } values, err = util.ParseUint64s(parts[1:3]) } else { values, err = util.ParseUint64s(parts[1:]) } if err != nil { return nil, fmt.Errorf("error parsing NFSd metric line: %w", err) } switch metricLine := parts[0]; metricLine { case "rc": stats.ReplyCache, err = parseReplyCache(values) case "fh": stats.FileHandles, err = parseFileHandles(values) case "io": stats.InputOutput, err = parseInputOutput(values) case "th": stats.Threads, err = parseThreads(values) case "ra": stats.ReadAheadCache, err = parseReadAheadCache(values) case "net": stats.Network, err = parseNetwork(values) case "rpc": stats.ServerRPC, err = parseServerRPC(values) case "proc2": stats.V2Stats, err = parseV2Stats(values) case "proc3": stats.V3Stats, err = parseV3Stats(values) case "proc4": stats.ServerV4Stats, err = parseServerV4Stats(values) case "proc4ops": stats.V4Ops, err = parseV4Ops(values) case "wdeleg_getattr": stats.WdelegGetattr = values[0] default: return nil, fmt.Errorf("unknown NFSd metric line %q", metricLine) } if err != nil { return nil, fmt.Errorf("errors parsing NFSd metric line: %w", err) } } if err := scanner.Err(); err != nil { return nil, fmt.Errorf("error scanning NFSd file: %w", err) } return stats, nil } golang-github-prometheus-procfs-0.14.0/nfs/parse_nfsd_test.go000066400000000000000000000373541461002754700243300ustar00rootroot00000000000000// Copyright 2018 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. package nfs_test import ( "reflect" "strings" "testing" "github.com/prometheus/procfs/nfs" ) func TestNewNFSdServerRPCStats(t *testing.T) { tests := []struct { name string content string stats *nfs.ServerRPCStats invalid bool }{ { name: "invalid file", content: "invalid", invalid: true, }, { name: "good file, proc4ops 72", content: `rc 0 6 18622 fh 0 0 0 0 0 io 157286400 0 th 8 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 ra 32 0 0 0 0 0 0 0 0 0 0 0 net 18628 0 18628 6 rpc 18628 0 0 0 0 proc2 18 2 69 0 0 4410 0 0 0 0 0 0 0 0 0 0 0 99 2 proc3 22 2 112 0 2719 111 0 0 0 0 0 0 0 0 0 0 0 27 216 0 2 1 0 proc4 2 2 10853 proc4ops 72 0 0 0 1098 2 0 0 0 0 8179 5896 0 0 0 0 5900 0 0 2 0 2 0 9609 0 2 150 1272 0 0 0 1236 0 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 wdeleg_getattr 16 `, stats: &nfs.ServerRPCStats{ ReplyCache: nfs.ReplyCache{ Hits: 0, Misses: 6, NoCache: 18622, }, FileHandles: nfs.FileHandles{ Stale: 0, TotalLookups: 0, AnonLookups: 0, DirNoCache: 0, NoDirNoCache: 0, }, InputOutput: nfs.InputOutput{ Read: 157286400, Write: 0, }, Threads: nfs.Threads{ Threads: 8, FullCnt: 0, }, ReadAheadCache: nfs.ReadAheadCache{ CacheSize: 32, CacheHistogram: []uint64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, NotFound: 0, }, Network: nfs.Network{ NetCount: 18628, UDPCount: 0, TCPCount: 18628, TCPConnect: 6, }, ServerRPC: nfs.ServerRPC{ RPCCount: 18628, BadCnt: 0, BadFmt: 0, BadAuth: 0, BadcInt: 0, }, V2Stats: nfs.V2Stats{ Null: 2, GetAttr: 69, SetAttr: 0, Root: 0, Lookup: 4410, ReadLink: 0, Read: 0, WrCache: 0, Write: 0, Create: 0, Remove: 0, Rename: 0, Link: 0, SymLink: 0, MkDir: 0, RmDir: 0, ReadDir: 99, FsStat: 2, }, V3Stats: nfs.V3Stats{ Null: 2, GetAttr: 112, SetAttr: 0, Lookup: 2719, Access: 111, ReadLink: 0, Read: 0, Write: 0, Create: 0, MkDir: 0, SymLink: 0, MkNod: 0, Remove: 0, RmDir: 0, Rename: 0, Link: 0, ReadDir: 27, ReadDirPlus: 216, FsStat: 0, FsInfo: 2, PathConf: 1, Commit: 0, }, ServerV4Stats: nfs.ServerV4Stats{ Null: 2, Compound: 10853, }, V4Ops: nfs.V4Ops{ Op0Unused: 0, Op1Unused: 0, Op2Future: 0, Access: 1098, Close: 2, Commit: 0, Create: 0, DelegPurge: 0, DelegReturn: 0, GetAttr: 8179, GetFH: 5896, Link: 0, Lock: 0, Lockt: 0, Locku: 0, Lookup: 5900, LookupRoot: 0, Nverify: 0, Open: 2, OpenAttr: 0, OpenConfirm: 2, OpenDgrd: 0, PutFH: 9609, PutPubFH: 0, PutRootFH: 2, Read: 150, ReadDir: 1272, ReadLink: 0, Remove: 0, Rename: 0, Renew: 1236, RestoreFH: 0, SaveFH: 0, SecInfo: 0, SetAttr: 0, SetClientID: 3, SetClientIDConfirm: 3, Verify: 0, Write: 0, RelLockOwner: 0, }, WdelegGetattr: 16, }, }, { name: "good file, proc4ops 40", content: `rc 0 25020854 19157796 fh 276 0 0 0 0 io 899844043 2470085989 th 1024 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 ra 2048 4250593 118232 55926 31504 20253 13815 9875 7028 5546 3991 171551 net 44179842 1 44179026 3092 rpc 44177753 0 0 0 0 proc2 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 proc3 22 747 7259760 1383711 1570520 3464939 8436 4688207 21668847 1173194 6457 2127 172 213538 1253 556401 14950 1101 56245 90790 742 367 1989658 proc4 2 0 0 proc4ops 40 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 wdeleg_getattr 9`, stats: &nfs.ServerRPCStats{ ReplyCache: nfs.ReplyCache{ Hits: 0, Misses: 25020854, NoCache: 19157796, }, FileHandles: nfs.FileHandles{ Stale: 276, TotalLookups: 0, AnonLookups: 0, DirNoCache: 0, NoDirNoCache: 0, }, InputOutput: nfs.InputOutput{ Read: 899844043, Write: 2470085989, }, Threads: nfs.Threads{ Threads: 1024, FullCnt: 0, }, ReadAheadCache: nfs.ReadAheadCache{ CacheSize: 2048, CacheHistogram: []uint64{4250593, 118232, 55926, 31504, 20253, 13815, 9875, 7028, 5546, 3991}, NotFound: 171551, }, Network: nfs.Network{ NetCount: 44179842, UDPCount: 1, TCPCount: 44179026, TCPConnect: 3092, }, ServerRPC: nfs.ServerRPC{ RPCCount: 44177753, BadCnt: 0, BadFmt: 0, BadAuth: 0, BadcInt: 0, }, V2Stats: nfs.V2Stats{ Null: 0, GetAttr: 0, SetAttr: 0, Root: 0, Lookup: 0, ReadLink: 0, Read: 0, WrCache: 0, Write: 0, Create: 0, Remove: 0, Rename: 0, Link: 0, SymLink: 0, MkDir: 0, RmDir: 0, ReadDir: 0, FsStat: 0, }, V3Stats: nfs.V3Stats{ Null: 747, GetAttr: 7259760, SetAttr: 1383711, Lookup: 1570520, Access: 3464939, ReadLink: 8436, Read: 4688207, Write: 21668847, Create: 1173194, MkDir: 6457, SymLink: 2127, MkNod: 172, Remove: 213538, RmDir: 1253, Rename: 556401, Link: 14950, ReadDir: 1101, ReadDirPlus: 56245, FsStat: 90790, FsInfo: 742, PathConf: 367, Commit: 1989658, }, ServerV4Stats: nfs.ServerV4Stats{ Null: 0, Compound: 0, }, V4Ops: nfs.V4Ops{ Op0Unused: 0, Op1Unused: 0, Op2Future: 0, Access: 0, Close: 0, Commit: 0, Create: 0, DelegPurge: 0, DelegReturn: 0, GetAttr: 0, GetFH: 0, Link: 0, Lock: 0, Lockt: 0, Locku: 0, Lookup: 0, LookupRoot: 0, Nverify: 0, Open: 0, OpenAttr: 0, OpenConfirm: 0, OpenDgrd: 0, PutFH: 0, PutPubFH: 0, PutRootFH: 0, Read: 0, ReadDir: 0, ReadLink: 0, Remove: 0, Rename: 0, Renew: 0, RestoreFH: 0, SaveFH: 0, SecInfo: 0, SetAttr: 0, SetClientID: 0, SetClientIDConfirm: 0, Verify: 0, Write: 0, RelLockOwner: 0, }, WdelegGetattr: 9, }, }, { name: "good file, proc4ops 59", content: `rc 0 268 742119 fh 0 0 0 0 0 io 2476981939 0 th 8 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 ra 32 30104 0 0 0 0 0 0 0 0 0 71174 net 742701 314 742393 10103960 rpc 742406 310 310 0 0 proc2 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 proc3 22 105 71158 0 175642 184711 17103 101277 0 0 0 0 0 0 0 0 0 0 8916 102 202 0 0 proc4 2 101 182991 proc4ops 59 0 0 0 18112 8341 0 0 0 3239 71595 11834 0 0 0 0 107097 0 0 8344 0 5100 0 181968 0 235 5735 4406 0 0 0 652 8342 8344 0 0 134 134 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 wdeleg_getattr 10`, stats: &nfs.ServerRPCStats{ ReplyCache: nfs.ReplyCache{ Hits: 0, Misses: 268, NoCache: 742119, }, FileHandles: nfs.FileHandles{ Stale: 0, TotalLookups: 0, AnonLookups: 0, DirNoCache: 0, NoDirNoCache: 0, }, InputOutput: nfs.InputOutput{ Read: 2476981939, Write: 0, }, Threads: nfs.Threads{ Threads: 8, FullCnt: 0, }, ReadAheadCache: nfs.ReadAheadCache{ CacheSize: 32, CacheHistogram: []uint64{30104, 0, 0, 0, 0, 0, 0, 0, 0, 0}, NotFound: 71174, }, Network: nfs.Network{ NetCount: 742701, UDPCount: 314, TCPCount: 742393, TCPConnect: 10103960, }, ServerRPC: nfs.ServerRPC{ RPCCount: 742406, BadCnt: 310, BadFmt: 310, BadAuth: 0, BadcInt: 0, }, V2Stats: nfs.V2Stats{ Null: 0, GetAttr: 0, SetAttr: 0, Root: 0, Lookup: 0, ReadLink: 0, Read: 0, WrCache: 0, Write: 0, Create: 0, Remove: 0, Rename: 0, Link: 0, SymLink: 0, MkDir: 0, RmDir: 0, ReadDir: 0, FsStat: 0, }, V3Stats: nfs.V3Stats{ Null: 105, GetAttr: 71158, SetAttr: 0, Lookup: 175642, Access: 184711, ReadLink: 17103, Read: 101277, Write: 0, Create: 0, MkDir: 0, SymLink: 0, MkNod: 0, Remove: 0, RmDir: 0, Rename: 0, Link: 0, ReadDir: 0, ReadDirPlus: 8916, FsStat: 102, FsInfo: 202, PathConf: 0, Commit: 0, }, ServerV4Stats: nfs.ServerV4Stats{ Null: 101, Compound: 182991, }, V4Ops: nfs.V4Ops{ Op0Unused: 0, Op1Unused: 0, Op2Future: 0, Access: 18112, Close: 8341, Commit: 0, Create: 0, DelegPurge: 0, DelegReturn: 3239, GetAttr: 71595, GetFH: 11834, Link: 0, Lock: 0, Lockt: 0, Locku: 0, Lookup: 107097, LookupRoot: 0, Nverify: 0, Open: 8344, OpenAttr: 0, OpenConfirm: 5100, OpenDgrd: 0, PutFH: 181968, PutPubFH: 0, PutRootFH: 235, Read: 5735, ReadDir: 4406, ReadLink: 0, Remove: 0, Rename: 0, Renew: 652, RestoreFH: 8342, SaveFH: 8344, SecInfo: 0, SetAttr: 0, SetClientID: 134, SetClientIDConfirm: 134, Verify: 0, Write: 0, RelLockOwner: 0, }, WdelegGetattr: 10, }, }, { name: "good file, proc4ops 39", content: `rc 0 25020854 19157796 fh 276 0 0 0 0 io 899844043 2470085989 th 1024 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 ra 2048 4250593 118232 55926 31504 20253 13815 9875 7028 5546 3991 171551 net 44179842 1 44179026 3092 rpc 44177753 0 0 0 0 proc2 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 proc3 22 747 7259760 1383711 1570520 3464939 8436 4688207 21668847 1173194 6457 2127 172 213538 1253 556401 14950 1101 56245 90790 742 367 1989658 proc4 2 0 0 proc4ops 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 39 wdeleg_getattr 765432`, stats: &nfs.ServerRPCStats{ ReplyCache: nfs.ReplyCache{ Hits: 0, Misses: 25020854, NoCache: 19157796, }, FileHandles: nfs.FileHandles{ Stale: 276, TotalLookups: 0, AnonLookups: 0, DirNoCache: 0, NoDirNoCache: 0, }, InputOutput: nfs.InputOutput{ Read: 899844043, Write: 2470085989, }, Threads: nfs.Threads{ Threads: 1024, FullCnt: 0, }, ReadAheadCache: nfs.ReadAheadCache{ CacheSize: 2048, CacheHistogram: []uint64{4250593, 118232, 55926, 31504, 20253, 13815, 9875, 7028, 5546, 3991}, NotFound: 171551, }, Network: nfs.Network{ NetCount: 44179842, UDPCount: 1, TCPCount: 44179026, TCPConnect: 3092, }, ServerRPC: nfs.ServerRPC{ RPCCount: 44177753, BadCnt: 0, BadFmt: 0, BadAuth: 0, BadcInt: 0, }, V2Stats: nfs.V2Stats{ Null: 0, GetAttr: 0, SetAttr: 0, Root: 0, Lookup: 0, ReadLink: 0, Read: 0, WrCache: 0, Write: 0, Create: 0, Remove: 0, Rename: 0, Link: 0, SymLink: 0, MkDir: 0, RmDir: 0, ReadDir: 0, FsStat: 0, }, V3Stats: nfs.V3Stats{ Null: 747, GetAttr: 7259760, SetAttr: 1383711, Lookup: 1570520, Access: 3464939, ReadLink: 8436, Read: 4688207, Write: 21668847, Create: 1173194, MkDir: 6457, SymLink: 2127, MkNod: 172, Remove: 213538, RmDir: 1253, Rename: 556401, Link: 14950, ReadDir: 1101, ReadDirPlus: 56245, FsStat: 90790, FsInfo: 742, PathConf: 367, Commit: 1989658, }, ServerV4Stats: nfs.ServerV4Stats{ Null: 0, Compound: 0, }, V4Ops: nfs.V4Ops{ Op0Unused: 0, Op1Unused: 0, Op2Future: 0, Access: 0, Close: 0, Commit: 0, Create: 0, DelegPurge: 0, DelegReturn: 0, GetAttr: 0, GetFH: 0, Link: 0, Lock: 0, Lockt: 0, Locku: 0, Lookup: 0, LookupRoot: 0, Nverify: 0, Open: 0, OpenAttr: 0, OpenConfirm: 0, OpenDgrd: 0, PutFH: 0, PutPubFH: 0, PutRootFH: 0, Read: 0, ReadDir: 0, ReadLink: 0, Remove: 0, Rename: 0, Renew: 0, RestoreFH: 0, SaveFH: 0, SecInfo: 0, SetAttr: 0, SetClientID: 0, SetClientIDConfirm: 0, Verify: 0, Write: 39, RelLockOwner: 0, }, WdelegGetattr: 765432, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { stats, err := nfs.ParseServerRPCStats(strings.NewReader(tt.content)) if tt.invalid && err == nil { t.Fatal("expected an error, but none occurred") } if !tt.invalid && err != nil { t.Fatalf("unexpected error: %v", err) } if want, have := tt.stats, stats; !reflect.DeepEqual(want, have) { t.Fatalf("unexpected NFS stats:\nwant:\n%v\nhave:\n%v", want, have) } }) } } golang-github-prometheus-procfs-0.14.0/proc.go000066400000000000000000000173701461002754700213160ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "bytes" "errors" "fmt" "io" "os" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // Proc provides information about a running process. type Proc struct { // The process ID. PID int fs FS } // Procs represents a list of Proc structs. type Procs []Proc var ( ErrFileParse = errors.New("Error Parsing File") ErrFileRead = errors.New("Error Reading File") ErrMountPoint = errors.New("Error Accessing Mount point") ) func (p Procs) Len() int { return len(p) } func (p Procs) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p Procs) Less(i, j int) bool { return p[i].PID < p[j].PID } // Self returns a process for the current process read via /proc/self. func Self() (Proc, error) { fs, err := NewFS(DefaultMountPoint) if err != nil || errors.Unwrap(err) == ErrMountPoint { return Proc{}, err } return fs.Self() } // NewProc returns a process for the given pid under /proc. func NewProc(pid int) (Proc, error) { fs, err := NewFS(DefaultMountPoint) if err != nil { return Proc{}, err } return fs.Proc(pid) } // AllProcs returns a list of all currently available processes under /proc. func AllProcs() (Procs, error) { fs, err := NewFS(DefaultMountPoint) if err != nil { return Procs{}, err } return fs.AllProcs() } // Self returns a process for the current process. func (fs FS) Self() (Proc, error) { p, err := os.Readlink(fs.proc.Path("self")) if err != nil { return Proc{}, err } pid, err := strconv.Atoi(strings.Replace(p, string(fs.proc), "", -1)) if err != nil { return Proc{}, err } return fs.Proc(pid) } // NewProc returns a process for the given pid. // // Deprecated: Use fs.Proc() instead. func (fs FS) NewProc(pid int) (Proc, error) { return fs.Proc(pid) } // Proc returns a process for the given pid. func (fs FS) Proc(pid int) (Proc, error) { if _, err := os.Stat(fs.proc.Path(strconv.Itoa(pid))); err != nil { return Proc{}, err } return Proc{PID: pid, fs: fs}, nil } // AllProcs returns a list of all currently available processes. func (fs FS) AllProcs() (Procs, error) { d, err := os.Open(fs.proc.Path()) if err != nil { return Procs{}, err } defer d.Close() names, err := d.Readdirnames(-1) if err != nil { return Procs{}, fmt.Errorf("%w: Cannot read file: %v: %w", ErrFileRead, names, err) } p := Procs{} for _, n := range names { pid, err := strconv.ParseInt(n, 10, 64) if err != nil { continue } p = append(p, Proc{PID: int(pid), fs: fs}) } return p, nil } // CmdLine returns the command line of a process. func (p Proc) CmdLine() ([]string, error) { data, err := util.ReadFileNoStat(p.path("cmdline")) if err != nil { return nil, err } if len(data) < 1 { return []string{}, nil } return strings.Split(string(bytes.TrimRight(data, string("\x00"))), string(byte(0))), nil } // Wchan returns the wchan (wait channel) of a process. func (p Proc) Wchan() (string, error) { f, err := os.Open(p.path("wchan")) if err != nil { return "", err } defer f.Close() data, err := io.ReadAll(f) if err != nil { return "", err } wchan := string(data) if wchan == "" || wchan == "0" { return "", nil } return wchan, nil } // Comm returns the command name of a process. func (p Proc) Comm() (string, error) { data, err := util.ReadFileNoStat(p.path("comm")) if err != nil { return "", err } return strings.TrimSpace(string(data)), nil } // Executable returns the absolute path of the executable command of a process. func (p Proc) Executable() (string, error) { exe, err := os.Readlink(p.path("exe")) if os.IsNotExist(err) { return "", nil } return exe, err } // Cwd returns the absolute path to the current working directory of the process. func (p Proc) Cwd() (string, error) { wd, err := os.Readlink(p.path("cwd")) if os.IsNotExist(err) { return "", nil } return wd, err } // RootDir returns the absolute path to the process's root directory (as set by chroot). func (p Proc) RootDir() (string, error) { rdir, err := os.Readlink(p.path("root")) if os.IsNotExist(err) { return "", nil } return rdir, err } // FileDescriptors returns the currently open file descriptors of a process. func (p Proc) FileDescriptors() ([]uintptr, error) { names, err := p.fileDescriptors() if err != nil { return nil, err } fds := make([]uintptr, len(names)) for i, n := range names { fd, err := strconv.ParseInt(n, 10, 32) if err != nil { return nil, fmt.Errorf("%w: Cannot parse line: %v: %w", ErrFileParse, i, err) } fds[i] = uintptr(fd) } return fds, nil } // FileDescriptorTargets returns the targets of all file descriptors of a process. // If a file descriptor is not a symlink to a file (like a socket), that value will be the empty string. func (p Proc) FileDescriptorTargets() ([]string, error) { names, err := p.fileDescriptors() if err != nil { return nil, err } targets := make([]string, len(names)) for i, name := range names { target, err := os.Readlink(p.path("fd", name)) if err == nil { targets[i] = target } } return targets, nil } // FileDescriptorsLen returns the number of currently open file descriptors of // a process. func (p Proc) FileDescriptorsLen() (int, error) { // Use fast path if available (Linux v6.2): https://github.com/torvalds/linux/commit/f1f1f2569901 if p.fs.isReal { stat, err := os.Stat(p.path("fd")) if err != nil { return 0, err } size := stat.Size() if size > 0 { return int(size), nil } } fds, err := p.fileDescriptors() if err != nil { return 0, err } return len(fds), nil } // MountStats retrieves statistics and configuration for mount points in a // process's namespace. func (p Proc) MountStats() ([]*Mount, error) { f, err := os.Open(p.path("mountstats")) if err != nil { return nil, err } defer f.Close() return parseMountStats(f) } // MountInfo retrieves mount information for mount points in a // process's namespace. // It supplies information missing in `/proc/self/mounts` and // fixes various other problems with that file too. func (p Proc) MountInfo() ([]*MountInfo, error) { data, err := util.ReadFileNoStat(p.path("mountinfo")) if err != nil { return nil, err } return parseMountInfo(data) } func (p Proc) fileDescriptors() ([]string, error) { d, err := os.Open(p.path("fd")) if err != nil { return nil, err } defer d.Close() names, err := d.Readdirnames(-1) if err != nil { return nil, fmt.Errorf("%w: Cannot read file: %v: %w", ErrFileRead, names, err) } return names, nil } func (p Proc) path(pa ...string) string { return p.fs.proc.Path(append([]string{strconv.Itoa(p.PID)}, pa...)...) } // FileDescriptorsInfo retrieves information about all file descriptors of // the process. func (p Proc) FileDescriptorsInfo() (ProcFDInfos, error) { names, err := p.fileDescriptors() if err != nil { return nil, err } var fdinfos ProcFDInfos for _, n := range names { fdinfo, err := p.FDInfo(n) if err != nil { continue } fdinfos = append(fdinfos, *fdinfo) } return fdinfos, nil } // Schedstat returns task scheduling information for the process. func (p Proc) Schedstat() (ProcSchedstat, error) { contents, err := os.ReadFile(p.path("schedstat")) if err != nil { return ProcSchedstat{}, err } return parseProcSchedstat(string(contents)) } golang-github-prometheus-procfs-0.14.0/proc_cgroup.go000066400000000000000000000072311461002754700226700ustar00rootroot00000000000000// Copyright 2020 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. package procfs import ( "bufio" "bytes" "fmt" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // Cgroup models one line from /proc/[pid]/cgroup. Each Cgroup struct describes the placement of a PID inside a // specific control hierarchy. The kernel has two cgroup APIs, v1 and v2. v1 has one hierarchy per available resource // controller, while v2 has one unified hierarchy shared by all controllers. Regardless of v1 or v2, all hierarchies // contain all running processes, so the question answerable with a Cgroup struct is 'where is this process in // this hierarchy' (where==what path on the specific cgroupfs). By prefixing this path with the mount point of // *this specific* hierarchy, you can locate the relevant pseudo-files needed to read/set the data for this PID // in this hierarchy // // Also see http://man7.org/linux/man-pages/man7/cgroups.7.html type Cgroup struct { // HierarchyID that can be matched to a named hierarchy using /proc/cgroups. Cgroups V2 only has one // hierarchy, so HierarchyID is always 0. For cgroups v1 this is a unique ID number HierarchyID int // Controllers using this hierarchy of processes. Controllers are also known as subsystems. For // Cgroups V2 this may be empty, as all active controllers use the same hierarchy Controllers []string // Path of this control group, relative to the mount point of the cgroupfs representing this specific // hierarchy Path string } // parseCgroupString parses each line of the /proc/[pid]/cgroup file // Line format is hierarchyID:[controller1,controller2]:path. func parseCgroupString(cgroupStr string) (*Cgroup, error) { var err error fields := strings.SplitN(cgroupStr, ":", 3) if len(fields) < 3 { return nil, fmt.Errorf("%w: 3+ fields required, found %d fields in cgroup string: %s", ErrFileParse, len(fields), cgroupStr) } cgroup := &Cgroup{ Path: fields[2], Controllers: nil, } cgroup.HierarchyID, err = strconv.Atoi(fields[0]) if err != nil { return nil, fmt.Errorf("%w: hierarchy ID: %q", ErrFileParse, cgroup.HierarchyID) } if fields[1] != "" { ssNames := strings.Split(fields[1], ",") cgroup.Controllers = append(cgroup.Controllers, ssNames...) } return cgroup, nil } // parseCgroups reads each line of the /proc/[pid]/cgroup file. func parseCgroups(data []byte) ([]Cgroup, error) { var cgroups []Cgroup scanner := bufio.NewScanner(bytes.NewReader(data)) for scanner.Scan() { mountString := scanner.Text() parsedMounts, err := parseCgroupString(mountString) if err != nil { return nil, err } cgroups = append(cgroups, *parsedMounts) } err := scanner.Err() return cgroups, err } // Cgroups reads from /proc//cgroups and returns a []*Cgroup struct locating this PID in each process // control hierarchy running on this system. On every system (v1 and v2), all hierarchies contain all processes, // so the len of the returned struct is equal to the number of active hierarchies on this system. func (p Proc) Cgroups() ([]Cgroup, error) { data, err := util.ReadFileNoStat(p.path("cgroup")) if err != nil { return nil, err } return parseCgroups(data) } golang-github-prometheus-procfs-0.14.0/proc_cgroup_test.go000066400000000000000000000045631461002754700237340ustar00rootroot00000000000000// Copyright 2020 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. package procfs import ( "reflect" "testing" ) func TestParseCgroupString(t *testing.T) { tests := []struct { name string s string shouldErr bool cgroup *Cgroup }{ { name: "cgroups-v1 simple line", s: "10:rdma:/", shouldErr: false, cgroup: &Cgroup{ HierarchyID: 10, Controllers: []string{"rdma"}, Path: "/", }, }, { name: "cgroups-v1 multi-hier line", s: "3:cpu,cpuacct:/user.slice/user-1000.slice/session-10.scope", shouldErr: false, cgroup: &Cgroup{ HierarchyID: 3, Controllers: []string{"cpu", "cpuacct"}, Path: "/user.slice/user-1000.slice/session-10.scope", }, }, { name: "cgroup-v2 line", s: "0::/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service", shouldErr: false, cgroup: &Cgroup{ HierarchyID: 0, Controllers: nil, Path: "/user.slice/user-1000.slice/user@1000.service/gnome-terminal-server.service", }, }, { name: "path containing colons", s: "0::/some/long/path:foobar", shouldErr: false, cgroup: &Cgroup{ HierarchyID: 0, Controllers: nil, Path: "/some/long/path:foobar", }, }, { name: "bad hierarchy ID field", s: "a:cpu:/", shouldErr: true, cgroup: nil, }, } for i, test := range tests { t.Logf("[%02d] test %q", i, test.name) cgroup, err := parseCgroupString(test.s) if test.shouldErr && err == nil { t.Errorf("%s: expected an error, but none occurred", test.name) } if !test.shouldErr && err != nil { t.Errorf("%s: unexpected error: %v", test.name, err) } if want, have := test.cgroup, cgroup; !reflect.DeepEqual(want, have) { t.Errorf("cgroup:\nwant:\n%+v\nhave:\n%+v", want, have) } } } golang-github-prometheus-procfs-0.14.0/proc_cgroups.go000066400000000000000000000062541461002754700230570ustar00rootroot00000000000000// Copyright 2021 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. package procfs import ( "bufio" "bytes" "fmt" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // CgroupSummary models one line from /proc/cgroups. // This file contains information about the controllers that are compiled into the kernel. // // Also see http://man7.org/linux/man-pages/man7/cgroups.7.html type CgroupSummary struct { // The name of the controller. controller is also known as subsystem. SubsysName string // The unique ID of the cgroup hierarchy on which this controller is mounted. Hierarchy int // The number of control groups in this hierarchy using this controller. Cgroups int // This field contains the value 1 if this controller is enabled, or 0 if it has been disabled Enabled int } // parseCgroupSummary parses each line of the /proc/cgroup file // Line format is `subsys_name hierarchy num_cgroups enabled`. func parseCgroupSummaryString(CgroupSummaryStr string) (*CgroupSummary, error) { var err error fields := strings.Fields(CgroupSummaryStr) // require at least 4 fields if len(fields) < 4 { return nil, fmt.Errorf("%w: 4+ fields required, found %d fields in cgroup info string: %s", ErrFileParse, len(fields), CgroupSummaryStr) } CgroupSummary := &CgroupSummary{ SubsysName: fields[0], } CgroupSummary.Hierarchy, err = strconv.Atoi(fields[1]) if err != nil { return nil, fmt.Errorf("%w: Unable to parse hierarchy ID from %q", ErrFileParse, fields[1]) } CgroupSummary.Cgroups, err = strconv.Atoi(fields[2]) if err != nil { return nil, fmt.Errorf("%w: Unable to parse Cgroup Num from %q", ErrFileParse, fields[2]) } CgroupSummary.Enabled, err = strconv.Atoi(fields[3]) if err != nil { return nil, fmt.Errorf("%w: Unable to parse Enabled from %q", ErrFileParse, fields[3]) } return CgroupSummary, nil } // parseCgroupSummary reads each line of the /proc/cgroup file. func parseCgroupSummary(data []byte) ([]CgroupSummary, error) { var CgroupSummarys []CgroupSummary scanner := bufio.NewScanner(bytes.NewReader(data)) for scanner.Scan() { CgroupSummaryString := scanner.Text() // ignore comment lines if strings.HasPrefix(CgroupSummaryString, "#") { continue } CgroupSummary, err := parseCgroupSummaryString(CgroupSummaryString) if err != nil { return nil, err } CgroupSummarys = append(CgroupSummarys, *CgroupSummary) } err := scanner.Err() return CgroupSummarys, err } // CgroupSummarys returns information about current /proc/cgroups. func (fs FS) CgroupSummarys() ([]CgroupSummary, error) { data, err := util.ReadFileNoStat(fs.proc.Path("cgroups")) if err != nil { return nil, err } return parseCgroupSummary(data) } golang-github-prometheus-procfs-0.14.0/proc_cgroups_test.go000066400000000000000000000032161461002754700241110ustar00rootroot00000000000000// Copyright 2021 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. package procfs import ( "reflect" "testing" ) func TestParseCgroupSummaryString(t *testing.T) { tests := []struct { name string s string shouldErr bool CgroupSummary *CgroupSummary }{ { name: "cpuset simple line", s: "cpuset 7 148 1", shouldErr: false, CgroupSummary: &CgroupSummary{ SubsysName: "cpuset", Hierarchy: 7, Cgroups: 148, Enabled: 1, }, }, { name: "memory cgroup number mis format", s: "memory 9 ## 1", shouldErr: true, CgroupSummary: nil, }, } for i, test := range tests { t.Logf("[%02d] test %q", i, test.name) CgroupSummary, err := parseCgroupSummaryString(test.s) if test.shouldErr && err == nil { t.Errorf("%s: expected an error, but none occurred", test.name) } if !test.shouldErr && err != nil { t.Errorf("%s: unexpected error: %v", test.name, err) } if want, have := test.CgroupSummary, CgroupSummary; !reflect.DeepEqual(want, have) { t.Errorf("cgroup:\nwant:\n%+v\nhave:\n%+v", want, have) } } } golang-github-prometheus-procfs-0.14.0/proc_environ.go000066400000000000000000000021021461002754700230410ustar00rootroot00000000000000// 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. package procfs import ( "strings" "github.com/prometheus/procfs/internal/util" ) // Environ reads process environments from `/proc//environ`. func (p Proc) Environ() ([]string, error) { environments := make([]string, 0) data, err := util.ReadFileNoStat(p.path("environ")) if err != nil { return environments, err } environments = strings.Split(string(data), "\000") if len(environments) > 0 { environments = environments[:len(environments)-1] } return environments, nil } golang-github-prometheus-procfs-0.14.0/proc_environ_test.go000066400000000000000000000025341461002754700241110ustar00rootroot00000000000000// 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. package procfs import "testing" func TestProcEnviron(t *testing.T) { p, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } environments, err := p.Environ() if err != nil { t.Fatal(err) } expectedEnvironments := []string{ "PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "HOSTNAME=cd24e11f73a5", "TERM=xterm", "GOLANG_VERSION=1.12.5", "GOPATH=/go", "HOME=/root", } if want, have := len(expectedEnvironments), len(environments); want != have { t.Errorf("want %d parsed environments, have %d", want, have) } for i, environment := range environments { if want, have := expectedEnvironments[i], environment; want != have { t.Errorf("%d: want %v, have %v", i, want, have) } } } golang-github-prometheus-procfs-0.14.0/proc_fdinfo.go000066400000000000000000000071761461002754700226460ustar00rootroot00000000000000// 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. package procfs import ( "bufio" "bytes" "fmt" "regexp" "github.com/prometheus/procfs/internal/util" ) var ( rPos = regexp.MustCompile(`^pos:\s+(\d+)$`) rFlags = regexp.MustCompile(`^flags:\s+(\d+)$`) rMntID = regexp.MustCompile(`^mnt_id:\s+(\d+)$`) rIno = regexp.MustCompile(`^ino:\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. type ProcFDInfo struct { // File descriptor FD string // File offset Pos string // File access mode and status flags Flags string // Mount point ID MntID string // Inode number Ino string // List of inotify lines (structured) in the fdinfo file (kernel 3.8+ only) InotifyInfos []InotifyInfo } // FDInfo constructor. On kernels older than 3.8, InotifyInfos will always be empty. func (p Proc) FDInfo(fd string) (*ProcFDInfo, error) { data, err := util.ReadFileNoStat(p.path("fdinfo", fd)) if err != nil { return nil, err } var text, pos, flags, mntid, ino string var inotify []InotifyInfo scanner := bufio.NewScanner(bytes.NewReader(data)) for scanner.Scan() { text = scanner.Text() if rPos.MatchString(text) { pos = rPos.FindStringSubmatch(text)[1] } else if rFlags.MatchString(text) { flags = rFlags.FindStringSubmatch(text)[1] } else if rMntID.MatchString(text) { mntid = rMntID.FindStringSubmatch(text)[1] } else if rIno.MatchString(text) { ino = rIno.FindStringSubmatch(text)[1] } else if rInotify.MatchString(text) { newInotify, err := parseInotifyInfo(text) if err != nil { return nil, err } inotify = append(inotify, *newInotify) } } i := &ProcFDInfo{ FD: fd, Pos: pos, Flags: flags, MntID: mntid, Ino: ino, InotifyInfos: inotify, } return i, nil } // InotifyInfo represents a single inotify line in the fdinfo file. type InotifyInfo struct { // Watch descriptor number WD string // Inode number Ino string // Device ID Sdev string // Mask of events being monitored Mask string } // InotifyInfo constructor. Only available on kernel 3.8+. func parseInotifyInfo(line string) (*InotifyInfo, error) { 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 nil, fmt.Errorf("%w: invalid inode entry: %q", ErrFileParse, line) } // ProcFDInfos represents a list of ProcFDInfo structs. type ProcFDInfos []ProcFDInfo func (p ProcFDInfos) Len() int { return len(p) } func (p ProcFDInfos) Swap(i, j int) { p[i], p[j] = p[j], p[i] } func (p ProcFDInfos) Less(i, j int) bool { return p[i].FD < p[j].FD } // InotifyWatchLen returns the total number of inotify watches. func (p ProcFDInfos) InotifyWatchLen() (int, error) { length := 0 for _, f := range p { length += len(f.InotifyInfos) } return length, nil } golang-github-prometheus-procfs-0.14.0/proc_fdinfo_test.go000066400000000000000000000017351461002754700237000ustar00rootroot00000000000000// 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. package procfs import "testing" func TestInotifyWatchLen(t *testing.T) { p1, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } fdinfos, err := p1.FileDescriptorsInfo() if err != nil { t.Fatal(err) } l, err := fdinfos.InotifyWatchLen() if err != nil { t.Fatal(err) } if want, have := 3, l; want != have { t.Errorf("want length %d, have %d", want, have) } } golang-github-prometheus-procfs-0.14.0/proc_interrupts.go000066400000000000000000000052341461002754700236110ustar00rootroot00000000000000// Copyright 2022 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. package procfs import ( "bufio" "bytes" "errors" "fmt" "io" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // Interrupt represents a single interrupt line. type Interrupt struct { // Info is the type of interrupt. Info string // Devices is the name of the device that is located at that IRQ Devices string // Values is the number of interrupts per CPU. Values []string } // Interrupts models the content of /proc/interrupts. Key is the IRQ number. // - https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/s2-proc-interrupts // - https://raspberrypi.stackexchange.com/questions/105802/explanation-of-proc-interrupts-output type Interrupts map[string]Interrupt // Interrupts creates a new instance from a given Proc instance. func (p Proc) Interrupts() (Interrupts, error) { data, err := util.ReadFileNoStat(p.path("interrupts")) if err != nil { return nil, err } return parseInterrupts(bytes.NewReader(data)) } func parseInterrupts(r io.Reader) (Interrupts, error) { var ( interrupts = Interrupts{} scanner = bufio.NewScanner(r) ) if !scanner.Scan() { return nil, errors.New("interrupts empty") } cpuNum := len(strings.Fields(scanner.Text())) // one header per cpu for scanner.Scan() { parts := strings.Fields(scanner.Text()) if len(parts) == 0 { // skip empty lines continue } if len(parts) < 2 { return nil, fmt.Errorf("%w: Not enough fields in interrupts (expected 2+ fields but got %d): %s", ErrFileParse, len(parts), parts) } intName := parts[0][:len(parts[0])-1] // remove trailing : if len(parts) == 2 { interrupts[intName] = Interrupt{ Info: "", Devices: "", Values: []string{ parts[1], }, } continue } intr := Interrupt{ Values: parts[1 : cpuNum+1], } if _, err := strconv.Atoi(intName); err == nil { // numeral interrupt intr.Info = parts[cpuNum+1] intr.Devices = strings.Join(parts[cpuNum+2:], " ") } else { intr.Info = strings.Join(parts[cpuNum+1:], " ") } interrupts[intName] = intr } return interrupts, scanner.Err() } golang-github-prometheus-procfs-0.14.0/proc_interrupts_test.go000066400000000000000000000042751461002754700246540ustar00rootroot00000000000000// Copyright 2022 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. package procfs import ( "reflect" "testing" ) func TestProcInterrupts(t *testing.T) { p, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } interrupts, err := p.Interrupts() if err != nil { t.Fatal(err) } if want, have := 47, len(interrupts); want != have { t.Errorf("want length %d, have %d", want, have) } for _, test := range []struct { name string irq string want Interrupt }{ { name: "first line", irq: "0", want: Interrupt{ Info: "IO-APIC", Devices: "2-edge timer", Values: []string{"49", "0", "0", "0"}, }, }, { name: "last line", irq: "PIW", want: Interrupt{ Info: "Posted-interrupt wakeup event", Devices: "", Values: []string{"0", "0", "0", "0"}, }, }, { name: "empty devices", irq: "LOC", want: Interrupt{ Info: "Local timer interrupts", Devices: "", Values: []string{"10196", "7429", "8542", "8229"}, }, }, { name: "single value", irq: "ERR", want: Interrupt{ Info: "", Devices: "", Values: []string{"0"}, }, }, } { t.Run(test.name, func(t *testing.T) { if value, ok := interrupts[test.irq]; ok { if value.Info != test.want.Info { t.Errorf("info: want %s, have %s", test.want.Info, value.Info) } if value.Devices != test.want.Devices { t.Errorf("devices: want %s, have %s", test.want.Devices, value.Devices) } if !reflect.DeepEqual(value.Values, test.want.Values) { t.Errorf("values: want %v, have %v", test.want.Values, value.Values) } } else { t.Errorf("IRQ %s not found", test.irq) } }) } } golang-github-prometheus-procfs-0.14.0/proc_io.go000066400000000000000000000031511461002754700217750ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "fmt" "github.com/prometheus/procfs/internal/util" ) // ProcIO models the content of /proc//io. type ProcIO struct { // Chars read. RChar uint64 // Chars written. WChar uint64 // Read syscalls. SyscR uint64 // Write syscalls. SyscW uint64 // Bytes read. ReadBytes uint64 // Bytes written. WriteBytes uint64 // Bytes written, but taking into account truncation. See // Documentation/filesystems/proc.txt in the kernel sources for // detailed explanation. CancelledWriteBytes int64 } // IO creates a new ProcIO instance from a given Proc instance. func (p Proc) IO() (ProcIO, error) { pio := ProcIO{} data, err := util.ReadFileNoStat(p.path("io")) if err != nil { return pio, err } ioFormat := "rchar: %d\nwchar: %d\nsyscr: %d\nsyscw: %d\n" + "read_bytes: %d\nwrite_bytes: %d\n" + "cancelled_write_bytes: %d\n" _, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR, &pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes) return pio, err } golang-github-prometheus-procfs-0.14.0/proc_io_test.go000066400000000000000000000025631461002754700230420ustar00rootroot00000000000000// Copyright 2018 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. package procfs import "testing" func TestProcIO(t *testing.T) { p, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } s, err := p.IO() if err != nil { t.Fatal(err) } for _, test := range []struct { name string want int64 have int64 }{ {name: "RChar", want: 750339, have: int64(s.RChar)}, {name: "WChar", want: 818609, have: int64(s.WChar)}, {name: "SyscR", want: 7405, have: int64(s.SyscR)}, {name: "SyscW", want: 5245, have: int64(s.SyscW)}, {name: "ReadBytes", want: 1024, have: int64(s.ReadBytes)}, {name: "WriteBytes", want: 2048, have: int64(s.WriteBytes)}, {name: "CancelledWriteBytes", want: -1024, have: s.CancelledWriteBytes}, } { if test.want != test.have { t.Errorf("want %s %d, have %d", test.name, test.want, test.have) } } } golang-github-prometheus-procfs-0.14.0/proc_limits.go000066400000000000000000000114771461002754700227010ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "bufio" "fmt" "os" "regexp" "strconv" ) // ProcLimits represents the soft limits for each of the process's resource // limits. For more information see getrlimit(2): // http://man7.org/linux/man-pages/man2/getrlimit.2.html. type ProcLimits struct { // CPU time limit in seconds. CPUTime uint64 // Maximum size of files that the process may create. FileSize uint64 // Maximum size of the process's data segment (initialized data, // uninitialized data, and heap). DataSize uint64 // Maximum size of the process stack in bytes. StackSize uint64 // Maximum size of a core file. CoreFileSize uint64 // Limit of the process's resident set in pages. ResidentSet uint64 // Maximum number of processes that can be created for the real user ID of // the calling process. Processes uint64 // Value one greater than the maximum file descriptor number that can be // opened by this process. OpenFiles uint64 // Maximum number of bytes of memory that may be locked into RAM. LockedMemory uint64 // Maximum size of the process's virtual memory address space in bytes. AddressSpace uint64 // Limit on the combined number of flock(2) locks and fcntl(2) leases that // this process may establish. FileLocks uint64 // Limit of signals that may be queued for the real user ID of the calling // process. PendingSignals uint64 // Limit on the number of bytes that can be allocated for POSIX message // queues for the real user ID of the calling process. MsqqueueSize uint64 // Limit of the nice priority set using setpriority(2) or nice(2). NicePriority uint64 // Limit of the real-time priority set using sched_setscheduler(2) or // sched_setparam(2). RealtimePriority uint64 // Limit (in microseconds) on the amount of CPU time that a process // scheduled under a real-time scheduling policy may consume without making // a blocking system call. RealtimeTimeout uint64 } const ( limitsFields = 4 limitsUnlimited = "unlimited" ) var ( limitsMatch = regexp.MustCompile(`(Max \w+\s{0,1}?\w*\s{0,1}\w*)\s{2,}(\w+)\s+(\w+)`) ) // NewLimits returns the current soft limits of the process. // // Deprecated: Use p.Limits() instead. func (p Proc) NewLimits() (ProcLimits, error) { return p.Limits() } // Limits returns the current soft limits of the process. func (p Proc) Limits() (ProcLimits, error) { f, err := os.Open(p.path("limits")) if err != nil { return ProcLimits{}, err } defer f.Close() var ( l = ProcLimits{} s = bufio.NewScanner(f) ) s.Scan() // Skip limits header for s.Scan() { //fields := limitsMatch.Split(s.Text(), limitsFields) fields := limitsMatch.FindStringSubmatch(s.Text()) if len(fields) != limitsFields { return ProcLimits{}, fmt.Errorf("%w: couldn't parse %q line %q", ErrFileParse, f.Name(), s.Text()) } switch fields[1] { case "Max cpu time": l.CPUTime, err = parseUint(fields[2]) case "Max file size": l.FileSize, err = parseUint(fields[2]) case "Max data size": l.DataSize, err = parseUint(fields[2]) case "Max stack size": l.StackSize, err = parseUint(fields[2]) case "Max core file size": l.CoreFileSize, err = parseUint(fields[2]) case "Max resident set": l.ResidentSet, err = parseUint(fields[2]) case "Max processes": l.Processes, err = parseUint(fields[2]) case "Max open files": l.OpenFiles, err = parseUint(fields[2]) case "Max locked memory": l.LockedMemory, err = parseUint(fields[2]) case "Max address space": l.AddressSpace, err = parseUint(fields[2]) case "Max file locks": l.FileLocks, err = parseUint(fields[2]) case "Max pending signals": l.PendingSignals, err = parseUint(fields[2]) case "Max msgqueue size": l.MsqqueueSize, err = parseUint(fields[2]) case "Max nice priority": l.NicePriority, err = parseUint(fields[2]) case "Max realtime priority": l.RealtimePriority, err = parseUint(fields[2]) case "Max realtime timeout": l.RealtimeTimeout, err = parseUint(fields[2]) } if err != nil { return ProcLimits{}, err } } return l, s.Err() } func parseUint(s string) (uint64, error) { if s == limitsUnlimited { return 18446744073709551615, nil } i, err := strconv.ParseUint(s, 10, 64) if err != nil { return 0, fmt.Errorf("%w: couldn't parse value %q: %w", ErrFileParse, s, err) } return i, nil } golang-github-prometheus-procfs-0.14.0/proc_limits_test.go000066400000000000000000000024201461002754700237240ustar00rootroot00000000000000// Copyright 2018 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. package procfs import "testing" func TestLimits(t *testing.T) { p, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } l, err := p.Limits() if err != nil { t.Fatal(err) } for _, test := range []struct { name string want uint64 have uint64 }{ {name: "cpu time", want: 18446744073709551615, have: l.CPUTime}, {name: "open files", want: 2048, have: l.OpenFiles}, {name: "msgqueue size", want: 819200, have: l.MsqqueueSize}, {name: "nice priority", want: 0, have: l.NicePriority}, {name: "address space", want: 8589934592, have: l.AddressSpace}, } { if test.want != test.have { t.Errorf("want %s %d, have %d", test.name, test.want, test.have) } } } golang-github-prometheus-procfs-0.14.0/proc_maps.go000066400000000000000000000113371461002754700223330ustar00rootroot00000000000000// 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. //go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris) && !js // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris // +build !js package procfs import ( "bufio" "fmt" "os" "strconv" "strings" "golang.org/x/sys/unix" ) // ProcMapPermissions contains permission settings read from `/proc/[pid]/maps`. 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) { i := strings.Index(s, ":") if i == -1 { return 0, fmt.Errorf("%w: expected separator `:` in %s", ErrFileParse, s) } major, err := strconv.ParseUint(s[0:i], 16, 0) if err != nil { return 0, err } minor, err := strconv.ParseUint(s[i+1:], 16, 0) if err != nil { return 0, err } return unix.Mkdev(uint32(major), uint32(minor)), nil } // parseAddress 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) { idx := strings.Index(s, "-") if idx == -1 { return 0, 0, fmt.Errorf("%w: expected separator `-` in %s", ErrFileParse, s) } saddr, err := parseAddress(s[0:idx]) if err != nil { return 0, 0, err } eaddr, err := parseAddress(s[idx+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("%w: invalid permissions token", ErrFileParse) } 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("%w: truncated procmap entry", ErrFileParse) } 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 } golang-github-prometheus-procfs-0.14.0/proc_maps32_test.go000066400000000000000000000045651461002754700235440ustar00rootroot00000000000000// 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. //go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris) && (386 || arm || mips || mipsle) // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris // +build 386 arm mips mipsle package procfs import ( "testing" "github.com/google/go-cmp/cmp" "golang.org/x/sys/unix" ) func TestProcMaps(t *testing.T) { tsts32 := []*ProcMap{ { StartAddr: 0x08048000, EndAddr: 0x08089000, Perms: &ProcMapPermissions{true, false, true, false, true}, Offset: 0, Dev: unix.Mkdev(0x03, 0x01), Inode: 104219, Pathname: "/bin/tcsh", }, { StartAddr: 0x08089000, EndAddr: 0x0808c000, Perms: &ProcMapPermissions{true, true, false, false, true}, Offset: 266240, Dev: unix.Mkdev(0x03, 0x01), Inode: 104219, Pathname: "/bin/tcsh", }, { StartAddr: 0x0808c000, EndAddr: 0x08146000, Perms: &ProcMapPermissions{true, true, true, false, true}, Offset: 0, Dev: unix.Mkdev(0x00, 0x00), Inode: 0, Pathname: "", }, { StartAddr: 0x40000000, EndAddr: 0x40015000, Perms: &ProcMapPermissions{true, false, true, false, true}, Offset: 0, Dev: unix.Mkdev(0x03, 0x01), Inode: 61874, Pathname: "/lib/ld-2.3.2.so", }, } // 32-bit test pid and fixtures tpid := 26234 tsts := tsts32 p, err := getProcFixtures(t).Proc(tpid) if err != nil { t.Fatal(err) } maps, err := p.ProcMaps() if err != nil { t.Fatal(err) } if want, have := len(maps), len(tsts); want > have { t.Errorf("want at least %d parsed proc/map entries, have %d", want, have) } for idx, tst := range tsts { want, got := tst, maps[idx] if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected proc/map entry (-want +got):\n%s", diff) } } } golang-github-prometheus-procfs-0.14.0/proc_maps64_test.go000066400000000000000000000102471461002754700235430ustar00rootroot00000000000000// 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. //go:build (aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris) && !386 && !arm && !mips && !mipsle // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris // +build !386 // +build !arm // +build !mips // +build !mipsle package procfs import ( "testing" "github.com/google/go-cmp/cmp" "golang.org/x/sys/unix" ) func TestProcMaps(t *testing.T) { tsts64 := []*ProcMap{ { StartAddr: 0x55680ae1e000, EndAddr: 0x55680ae20000, Perms: &ProcMapPermissions{true, false, false, false, true}, Offset: 0, Dev: unix.Mkdev(0xfd, 0x01), Inode: 47316994, Pathname: "/bin/cat", }, { StartAddr: 0x55680ae29000, EndAddr: 0x55680ae2a000, Perms: &ProcMapPermissions{true, true, true, true, false}, Offset: 40960, Dev: unix.Mkdev(0xfd, 0x01), Inode: 47316994, Pathname: "/bin/cat", }, { StartAddr: 0x55680bed6000, EndAddr: 0x55680bef7000, Perms: &ProcMapPermissions{true, true, false, false, true}, Offset: 0, Dev: unix.Mkdev(0, 0), Inode: 0, Pathname: "[heap]", }, { StartAddr: 0x7fdf964fc000, EndAddr: 0x7fdf973f2000, Perms: &ProcMapPermissions{true, false, false, false, true}, Offset: 0, Dev: unix.Mkdev(0xfd, 0x01), Inode: 17432624, Pathname: "/usr/lib/locale/locale-archive", }, { StartAddr: 0x7fdf973f2000, EndAddr: 0x7fdf97417000, Perms: &ProcMapPermissions{true, false, false, false, true}, Offset: 0, Dev: unix.Mkdev(0xfd, 0x01), Inode: 60571062, Pathname: "/lib/x86_64-linux-gnu/libc-2.29.so", }, { StartAddr: 0x7ffe9215c000, EndAddr: 0x7ffe9217f000, Perms: &ProcMapPermissions{true, true, false, false, true}, Offset: 0, Dev: 0, Inode: 0, Pathname: "[stack]", }, { StartAddr: 0x7ffe921da000, EndAddr: 0x7ffe921dd000, Perms: &ProcMapPermissions{true, false, false, false, true}, Offset: 0, Dev: 0, Inode: 0, Pathname: "[vvar]", }, { StartAddr: 0x7ffe921dd000, EndAddr: 0x7ffe921de000, Perms: &ProcMapPermissions{true, false, true, false, true}, Offset: 0, Dev: 0, Inode: 0, Pathname: "[vdso]", }, { StartAddr: 0xffffffffff600000, EndAddr: 0xffffffffff601000, Perms: &ProcMapPermissions{false, false, true, false, true}, Offset: 0, Dev: 0, Inode: 0, Pathname: "[vsyscall]", }, } // 64-bit test pid and fixtures tpid := 26232 tsts := tsts64 p, err := getProcFixtures(t).Proc(tpid) if err != nil { t.Fatal(err) } maps, err := p.ProcMaps() if err != nil { t.Fatal(err) } if want, have := len(maps), len(tsts); want > have { t.Errorf("want at least %d parsed proc/map entries, have %d", want, have) } for idx, tst := range tsts { want, got := tst, maps[idx] if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected proc/map entry (-want +got):\n%s", diff) } } } var start, end uintptr func BenchmarkParseAddress(b *testing.B) { b.ReportAllocs() var ( s, e uintptr err error ) for i := 0; i < b.N; i++ { s, e, err = parseAddresses("7f7d7469e000-7f7d746a0000") if err != nil { b.Fatal(err) } } // Prevent the compiler from optimizing away benchmark code. start = s end = e } var device uint64 func BenchmarkParseDevice(b *testing.B) { b.ReportAllocs() var ( d uint64 err error ) for i := 0; i < b.N; i++ { d, err = parseDevice("00:22") if err != nil { b.Fatal(err) } } // Prevent the compiler from optimizing away benchmark code. device = d } golang-github-prometheus-procfs-0.14.0/proc_netstat.go000066400000000000000000000355711461002754700230630ustar00rootroot00000000000000// Copyright 2022 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. package procfs import ( "bufio" "bytes" "fmt" "io" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // ProcNetstat models the content of /proc//net/netstat. type ProcNetstat struct { // The process ID. PID int TcpExt IpExt } type TcpExt struct { // nolint:revive SyncookiesSent *float64 SyncookiesRecv *float64 SyncookiesFailed *float64 EmbryonicRsts *float64 PruneCalled *float64 RcvPruned *float64 OfoPruned *float64 OutOfWindowIcmps *float64 LockDroppedIcmps *float64 ArpFilter *float64 TW *float64 TWRecycled *float64 TWKilled *float64 PAWSActive *float64 PAWSEstab *float64 DelayedACKs *float64 DelayedACKLocked *float64 DelayedACKLost *float64 ListenOverflows *float64 ListenDrops *float64 TCPHPHits *float64 TCPPureAcks *float64 TCPHPAcks *float64 TCPRenoRecovery *float64 TCPSackRecovery *float64 TCPSACKReneging *float64 TCPSACKReorder *float64 TCPRenoReorder *float64 TCPTSReorder *float64 TCPFullUndo *float64 TCPPartialUndo *float64 TCPDSACKUndo *float64 TCPLossUndo *float64 TCPLostRetransmit *float64 TCPRenoFailures *float64 TCPSackFailures *float64 TCPLossFailures *float64 TCPFastRetrans *float64 TCPSlowStartRetrans *float64 TCPTimeouts *float64 TCPLossProbes *float64 TCPLossProbeRecovery *float64 TCPRenoRecoveryFail *float64 TCPSackRecoveryFail *float64 TCPRcvCollapsed *float64 TCPDSACKOldSent *float64 TCPDSACKOfoSent *float64 TCPDSACKRecv *float64 TCPDSACKOfoRecv *float64 TCPAbortOnData *float64 TCPAbortOnClose *float64 TCPAbortOnMemory *float64 TCPAbortOnTimeout *float64 TCPAbortOnLinger *float64 TCPAbortFailed *float64 TCPMemoryPressures *float64 TCPMemoryPressuresChrono *float64 TCPSACKDiscard *float64 TCPDSACKIgnoredOld *float64 TCPDSACKIgnoredNoUndo *float64 TCPSpuriousRTOs *float64 TCPMD5NotFound *float64 TCPMD5Unexpected *float64 TCPMD5Failure *float64 TCPSackShifted *float64 TCPSackMerged *float64 TCPSackShiftFallback *float64 TCPBacklogDrop *float64 PFMemallocDrop *float64 TCPMinTTLDrop *float64 TCPDeferAcceptDrop *float64 IPReversePathFilter *float64 TCPTimeWaitOverflow *float64 TCPReqQFullDoCookies *float64 TCPReqQFullDrop *float64 TCPRetransFail *float64 TCPRcvCoalesce *float64 TCPRcvQDrop *float64 TCPOFOQueue *float64 TCPOFODrop *float64 TCPOFOMerge *float64 TCPChallengeACK *float64 TCPSYNChallenge *float64 TCPFastOpenActive *float64 TCPFastOpenActiveFail *float64 TCPFastOpenPassive *float64 TCPFastOpenPassiveFail *float64 TCPFastOpenListenOverflow *float64 TCPFastOpenCookieReqd *float64 TCPFastOpenBlackhole *float64 TCPSpuriousRtxHostQueues *float64 BusyPollRxPackets *float64 TCPAutoCorking *float64 TCPFromZeroWindowAdv *float64 TCPToZeroWindowAdv *float64 TCPWantZeroWindowAdv *float64 TCPSynRetrans *float64 TCPOrigDataSent *float64 TCPHystartTrainDetect *float64 TCPHystartTrainCwnd *float64 TCPHystartDelayDetect *float64 TCPHystartDelayCwnd *float64 TCPACKSkippedSynRecv *float64 TCPACKSkippedPAWS *float64 TCPACKSkippedSeq *float64 TCPACKSkippedFinWait2 *float64 TCPACKSkippedTimeWait *float64 TCPACKSkippedChallenge *float64 TCPWinProbe *float64 TCPKeepAlive *float64 TCPMTUPFail *float64 TCPMTUPSuccess *float64 TCPWqueueTooBig *float64 } type IpExt struct { // nolint:revive InNoRoutes *float64 InTruncatedPkts *float64 InMcastPkts *float64 OutMcastPkts *float64 InBcastPkts *float64 OutBcastPkts *float64 InOctets *float64 OutOctets *float64 InMcastOctets *float64 OutMcastOctets *float64 InBcastOctets *float64 OutBcastOctets *float64 InCsumErrors *float64 InNoECTPkts *float64 InECT1Pkts *float64 InECT0Pkts *float64 InCEPkts *float64 ReasmOverlaps *float64 } func (p Proc) Netstat() (ProcNetstat, error) { filename := p.path("net/netstat") data, err := util.ReadFileNoStat(filename) if err != nil { return ProcNetstat{PID: p.PID}, err } procNetstat, err := parseProcNetstat(bytes.NewReader(data), filename) procNetstat.PID = p.PID return procNetstat, err } // parseProcNetstat parses the metrics from proc//net/netstat file // and returns a ProcNetstat structure. func parseProcNetstat(r io.Reader, fileName string) (ProcNetstat, error) { var ( scanner = bufio.NewScanner(r) procNetstat = ProcNetstat{} ) for scanner.Scan() { nameParts := strings.Split(scanner.Text(), " ") scanner.Scan() valueParts := strings.Split(scanner.Text(), " ") // Remove trailing :. protocol := strings.TrimSuffix(nameParts[0], ":") if len(nameParts) != len(valueParts) { return procNetstat, fmt.Errorf("%w: mismatch field count mismatch in %s: %s", ErrFileParse, fileName, protocol) } for i := 1; i < len(nameParts); i++ { value, err := strconv.ParseFloat(valueParts[i], 64) if err != nil { return procNetstat, err } key := nameParts[i] switch protocol { case "TcpExt": switch key { case "SyncookiesSent": procNetstat.TcpExt.SyncookiesSent = &value case "SyncookiesRecv": procNetstat.TcpExt.SyncookiesRecv = &value case "SyncookiesFailed": procNetstat.TcpExt.SyncookiesFailed = &value case "EmbryonicRsts": procNetstat.TcpExt.EmbryonicRsts = &value case "PruneCalled": procNetstat.TcpExt.PruneCalled = &value case "RcvPruned": procNetstat.TcpExt.RcvPruned = &value case "OfoPruned": procNetstat.TcpExt.OfoPruned = &value case "OutOfWindowIcmps": procNetstat.TcpExt.OutOfWindowIcmps = &value case "LockDroppedIcmps": procNetstat.TcpExt.LockDroppedIcmps = &value case "ArpFilter": procNetstat.TcpExt.ArpFilter = &value case "TW": procNetstat.TcpExt.TW = &value case "TWRecycled": procNetstat.TcpExt.TWRecycled = &value case "TWKilled": procNetstat.TcpExt.TWKilled = &value case "PAWSActive": procNetstat.TcpExt.PAWSActive = &value case "PAWSEstab": procNetstat.TcpExt.PAWSEstab = &value case "DelayedACKs": procNetstat.TcpExt.DelayedACKs = &value case "DelayedACKLocked": procNetstat.TcpExt.DelayedACKLocked = &value case "DelayedACKLost": procNetstat.TcpExt.DelayedACKLost = &value case "ListenOverflows": procNetstat.TcpExt.ListenOverflows = &value case "ListenDrops": procNetstat.TcpExt.ListenDrops = &value case "TCPHPHits": procNetstat.TcpExt.TCPHPHits = &value case "TCPPureAcks": procNetstat.TcpExt.TCPPureAcks = &value case "TCPHPAcks": procNetstat.TcpExt.TCPHPAcks = &value case "TCPRenoRecovery": procNetstat.TcpExt.TCPRenoRecovery = &value case "TCPSackRecovery": procNetstat.TcpExt.TCPSackRecovery = &value case "TCPSACKReneging": procNetstat.TcpExt.TCPSACKReneging = &value case "TCPSACKReorder": procNetstat.TcpExt.TCPSACKReorder = &value case "TCPRenoReorder": procNetstat.TcpExt.TCPRenoReorder = &value case "TCPTSReorder": procNetstat.TcpExt.TCPTSReorder = &value case "TCPFullUndo": procNetstat.TcpExt.TCPFullUndo = &value case "TCPPartialUndo": procNetstat.TcpExt.TCPPartialUndo = &value case "TCPDSACKUndo": procNetstat.TcpExt.TCPDSACKUndo = &value case "TCPLossUndo": procNetstat.TcpExt.TCPLossUndo = &value case "TCPLostRetransmit": procNetstat.TcpExt.TCPLostRetransmit = &value case "TCPRenoFailures": procNetstat.TcpExt.TCPRenoFailures = &value case "TCPSackFailures": procNetstat.TcpExt.TCPSackFailures = &value case "TCPLossFailures": procNetstat.TcpExt.TCPLossFailures = &value case "TCPFastRetrans": procNetstat.TcpExt.TCPFastRetrans = &value case "TCPSlowStartRetrans": procNetstat.TcpExt.TCPSlowStartRetrans = &value case "TCPTimeouts": procNetstat.TcpExt.TCPTimeouts = &value case "TCPLossProbes": procNetstat.TcpExt.TCPLossProbes = &value case "TCPLossProbeRecovery": procNetstat.TcpExt.TCPLossProbeRecovery = &value case "TCPRenoRecoveryFail": procNetstat.TcpExt.TCPRenoRecoveryFail = &value case "TCPSackRecoveryFail": procNetstat.TcpExt.TCPSackRecoveryFail = &value case "TCPRcvCollapsed": procNetstat.TcpExt.TCPRcvCollapsed = &value case "TCPDSACKOldSent": procNetstat.TcpExt.TCPDSACKOldSent = &value case "TCPDSACKOfoSent": procNetstat.TcpExt.TCPDSACKOfoSent = &value case "TCPDSACKRecv": procNetstat.TcpExt.TCPDSACKRecv = &value case "TCPDSACKOfoRecv": procNetstat.TcpExt.TCPDSACKOfoRecv = &value case "TCPAbortOnData": procNetstat.TcpExt.TCPAbortOnData = &value case "TCPAbortOnClose": procNetstat.TcpExt.TCPAbortOnClose = &value case "TCPDeferAcceptDrop": procNetstat.TcpExt.TCPDeferAcceptDrop = &value case "IPReversePathFilter": procNetstat.TcpExt.IPReversePathFilter = &value case "TCPTimeWaitOverflow": procNetstat.TcpExt.TCPTimeWaitOverflow = &value case "TCPReqQFullDoCookies": procNetstat.TcpExt.TCPReqQFullDoCookies = &value case "TCPReqQFullDrop": procNetstat.TcpExt.TCPReqQFullDrop = &value case "TCPRetransFail": procNetstat.TcpExt.TCPRetransFail = &value case "TCPRcvCoalesce": procNetstat.TcpExt.TCPRcvCoalesce = &value case "TCPRcvQDrop": procNetstat.TcpExt.TCPRcvQDrop = &value case "TCPOFOQueue": procNetstat.TcpExt.TCPOFOQueue = &value case "TCPOFODrop": procNetstat.TcpExt.TCPOFODrop = &value case "TCPOFOMerge": procNetstat.TcpExt.TCPOFOMerge = &value case "TCPChallengeACK": procNetstat.TcpExt.TCPChallengeACK = &value case "TCPSYNChallenge": procNetstat.TcpExt.TCPSYNChallenge = &value case "TCPFastOpenActive": procNetstat.TcpExt.TCPFastOpenActive = &value case "TCPFastOpenActiveFail": procNetstat.TcpExt.TCPFastOpenActiveFail = &value case "TCPFastOpenPassive": procNetstat.TcpExt.TCPFastOpenPassive = &value case "TCPFastOpenPassiveFail": procNetstat.TcpExt.TCPFastOpenPassiveFail = &value case "TCPFastOpenListenOverflow": procNetstat.TcpExt.TCPFastOpenListenOverflow = &value case "TCPFastOpenCookieReqd": procNetstat.TcpExt.TCPFastOpenCookieReqd = &value case "TCPFastOpenBlackhole": procNetstat.TcpExt.TCPFastOpenBlackhole = &value case "TCPSpuriousRtxHostQueues": procNetstat.TcpExt.TCPSpuriousRtxHostQueues = &value case "BusyPollRxPackets": procNetstat.TcpExt.BusyPollRxPackets = &value case "TCPAutoCorking": procNetstat.TcpExt.TCPAutoCorking = &value case "TCPFromZeroWindowAdv": procNetstat.TcpExt.TCPFromZeroWindowAdv = &value case "TCPToZeroWindowAdv": procNetstat.TcpExt.TCPToZeroWindowAdv = &value case "TCPWantZeroWindowAdv": procNetstat.TcpExt.TCPWantZeroWindowAdv = &value case "TCPSynRetrans": procNetstat.TcpExt.TCPSynRetrans = &value case "TCPOrigDataSent": procNetstat.TcpExt.TCPOrigDataSent = &value case "TCPHystartTrainDetect": procNetstat.TcpExt.TCPHystartTrainDetect = &value case "TCPHystartTrainCwnd": procNetstat.TcpExt.TCPHystartTrainCwnd = &value case "TCPHystartDelayDetect": procNetstat.TcpExt.TCPHystartDelayDetect = &value case "TCPHystartDelayCwnd": procNetstat.TcpExt.TCPHystartDelayCwnd = &value case "TCPACKSkippedSynRecv": procNetstat.TcpExt.TCPACKSkippedSynRecv = &value case "TCPACKSkippedPAWS": procNetstat.TcpExt.TCPACKSkippedPAWS = &value case "TCPACKSkippedSeq": procNetstat.TcpExt.TCPACKSkippedSeq = &value case "TCPACKSkippedFinWait2": procNetstat.TcpExt.TCPACKSkippedFinWait2 = &value case "TCPACKSkippedTimeWait": procNetstat.TcpExt.TCPACKSkippedTimeWait = &value case "TCPACKSkippedChallenge": procNetstat.TcpExt.TCPACKSkippedChallenge = &value case "TCPWinProbe": procNetstat.TcpExt.TCPWinProbe = &value case "TCPKeepAlive": procNetstat.TcpExt.TCPKeepAlive = &value case "TCPMTUPFail": procNetstat.TcpExt.TCPMTUPFail = &value case "TCPMTUPSuccess": procNetstat.TcpExt.TCPMTUPSuccess = &value case "TCPWqueueTooBig": procNetstat.TcpExt.TCPWqueueTooBig = &value } case "IpExt": switch key { case "InNoRoutes": procNetstat.IpExt.InNoRoutes = &value case "InTruncatedPkts": procNetstat.IpExt.InTruncatedPkts = &value case "InMcastPkts": procNetstat.IpExt.InMcastPkts = &value case "OutMcastPkts": procNetstat.IpExt.OutMcastPkts = &value case "InBcastPkts": procNetstat.IpExt.InBcastPkts = &value case "OutBcastPkts": procNetstat.IpExt.OutBcastPkts = &value case "InOctets": procNetstat.IpExt.InOctets = &value case "OutOctets": procNetstat.IpExt.OutOctets = &value case "InMcastOctets": procNetstat.IpExt.InMcastOctets = &value case "OutMcastOctets": procNetstat.IpExt.OutMcastOctets = &value case "InBcastOctets": procNetstat.IpExt.InBcastOctets = &value case "OutBcastOctets": procNetstat.IpExt.OutBcastOctets = &value case "InCsumErrors": procNetstat.IpExt.InCsumErrors = &value case "InNoECTPkts": procNetstat.IpExt.InNoECTPkts = &value case "InECT1Pkts": procNetstat.IpExt.InECT1Pkts = &value case "InECT0Pkts": procNetstat.IpExt.InECT0Pkts = &value case "InCEPkts": procNetstat.IpExt.InCEPkts = &value case "ReasmOverlaps": procNetstat.IpExt.ReasmOverlaps = &value } } } } return procNetstat, scanner.Err() } golang-github-prometheus-procfs-0.14.0/proc_netstat_test.go000066400000000000000000000031261461002754700241110ustar00rootroot00000000000000// Copyright 2022 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. package procfs import ( "testing" ) func TestProcNetstat(t *testing.T) { p, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } procNetstat, err := p.Netstat() if err != nil { t.Fatal(err) } for _, test := range []struct { name string want float64 have float64 }{ {name: "pid", want: 26231, have: float64(procNetstat.PID)}, {name: "TcpExt:SyncookiesSent", want: 0, have: *procNetstat.TcpExt.SyncookiesSent}, {name: "TcpExt:EmbryonicRsts", want: 1, have: *procNetstat.TcpExt.EmbryonicRsts}, {name: "TcpExt:TW", want: 83, have: *procNetstat.TcpExt.TW}, {name: "TcpExt:PAWSEstab", want: 3640, have: *procNetstat.TcpExt.PAWSEstab}, {name: "IpExt:InNoRoutes", want: 0, have: *procNetstat.IpExt.InNoRoutes}, {name: "IpExt:InMcastPkts", want: 208, have: *procNetstat.IpExt.InMcastPkts}, {name: "IpExt:OutMcastPkts", want: 214, have: *procNetstat.IpExt.OutMcastPkts}, } { if test.want != test.have { t.Errorf("want %s %f, have %f", test.name, test.want, test.have) } } } golang-github-prometheus-procfs-0.14.0/proc_ns.go000066400000000000000000000036561461002754700220200ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "fmt" "os" "strconv" "strings" ) // Namespace represents a single namespace of a process. type Namespace struct { Type string // Namespace type. Inode uint32 // Inode number of the namespace. If two processes are in the same namespace their inodes will match. } // Namespaces contains all of the namespaces that the process is contained in. type Namespaces map[string]Namespace // Namespaces reads from /proc//ns/* to get the namespaces of which the // process is a member. func (p Proc) Namespaces() (Namespaces, error) { d, err := os.Open(p.path("ns")) if err != nil { return nil, err } defer d.Close() names, err := d.Readdirnames(-1) if err != nil { return nil, fmt.Errorf("%w: failed to read contents of ns dir: %w", ErrFileRead, err) } ns := make(Namespaces, len(names)) for _, name := range names { target, err := os.Readlink(p.path("ns", name)) if err != nil { return nil, err } fields := strings.SplitN(target, ":", 2) if len(fields) != 2 { return nil, fmt.Errorf("%w: namespace type and inode from %q", ErrFileParse, target) } typ := fields[0] inode, err := strconv.ParseUint(strings.Trim(fields[1], "[]"), 10, 32) if err != nil { return nil, fmt.Errorf("%w: inode from %q: %w", ErrFileParse, fields[1], err) } ns[name] = Namespace{typ, uint32(inode)} } return ns, nil } golang-github-prometheus-procfs-0.14.0/proc_ns_test.go000066400000000000000000000023221461002754700230440ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "testing" ) func TestNewNamespaces(t *testing.T) { p, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } namespaces, err := p.Namespaces() if err != nil { t.Fatal(err) } expectedNamespaces := map[string]Namespace{ "mnt": {"mnt", 4026531840}, "net": {"net", 4026531993}, } if want, have := len(expectedNamespaces), len(namespaces); want != have { t.Errorf("want %d parsed namespaces, have %d", want, have) } for _, ns := range namespaces { if want, have := expectedNamespaces[ns.Type], ns; want != have { t.Errorf("%s: want %v, have %v", ns.Type, want, have) } } } golang-github-prometheus-procfs-0.14.0/proc_psi.go000066400000000000000000000064661461002754700221750ustar00rootroot00000000000000// 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. package procfs // The PSI / pressure interface is described at // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/accounting/psi.txt // Each resource (cpu, io, memory, ...) is exposed as a single file. // Each file may contain up to two lines, one for "some" pressure and one for "full" pressure. // Each line contains several averages (over n seconds) and a total in µs. // // Example io pressure file: // > some avg10=0.06 avg60=0.21 avg300=0.99 total=8537362 // > full avg10=0.00 avg60=0.13 avg300=0.96 total=8183134 import ( "bufio" "bytes" "fmt" "io" "strings" "github.com/prometheus/procfs/internal/util" ) const lineFormat = "avg10=%f avg60=%f avg300=%f total=%d" // PSILine is a single line of values as returned by `/proc/pressure/*`. // // The Avg entries are averages over n seconds, as a percentage. // The Total line is in microseconds. type PSILine struct { Avg10 float64 Avg60 float64 Avg300 float64 Total uint64 } // PSIStats represent pressure stall information from /proc/pressure/* // // "Some" indicates the share of time in which at least some tasks are stalled. // "Full" indicates the share of time in which all non-idle tasks are stalled simultaneously. type PSIStats struct { Some *PSILine Full *PSILine } // PSIStatsForResource reads pressure stall information for the specified // resource from /proc/pressure/. At time of writing this can be // either "cpu", "memory" or "io". func (fs FS) PSIStatsForResource(resource string) (PSIStats, error) { data, err := util.ReadFileNoStat(fs.proc.Path(fmt.Sprintf("%s/%s", "pressure", resource))) if err != nil { return PSIStats{}, fmt.Errorf("%w: psi_stats: unavailable for %q: %w", ErrFileRead, resource, err) } return parsePSIStats(bytes.NewReader(data)) } // parsePSIStats parses the specified file for pressure stall information. func parsePSIStats(r io.Reader) (PSIStats, error) { psiStats := PSIStats{} scanner := bufio.NewScanner(r) for scanner.Scan() { l := scanner.Text() prefix := strings.Split(l, " ")[0] switch prefix { case "some": psi := PSILine{} _, err := fmt.Sscanf(l, fmt.Sprintf("some %s", lineFormat), &psi.Avg10, &psi.Avg60, &psi.Avg300, &psi.Total) if err != nil { return PSIStats{}, err } psiStats.Some = &psi case "full": psi := PSILine{} _, err := fmt.Sscanf(l, fmt.Sprintf("full %s", lineFormat), &psi.Avg10, &psi.Avg60, &psi.Avg300, &psi.Total) if err != nil { return PSIStats{}, err } psiStats.Full = &psi default: // If we encounter a line with an unknown prefix, ignore it and move on // Should new measurement types be added in the future we'll simply ignore them instead // of erroring on retrieval continue } } return psiStats, nil } golang-github-prometheus-procfs-0.14.0/proc_psi_test.go000066400000000000000000000076401461002754700232270ustar00rootroot00000000000000// 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. package procfs import ( "strings" "testing" ) func TestPSIStats(t *testing.T) { t.Run("fake", func(t *testing.T) { stats, err := getProcFixtures(t).PSIStatsForResource("fake") if err == nil { t.Fatal("fake resource does not have PSI statistics") } if stats.Some != nil || stats.Full != nil { t.Error("a fake resource cannot have PSILine entries") } }) t.Run("cpu", func(t *testing.T) { stats, err := getProcFixtures(t).PSIStatsForResource("cpu") if err != nil { t.Fatal(err) } if stats.Full != nil { t.Fatal("cpu resource cannot have 'full' stats") } if stats.Some == nil { t.Fatal("cpu resource should not have nil 'some' stats") } testCases := []struct { name string got float64 want float64 }{ {"Avg10", stats.Some.Avg10, 0.1}, {"Avg60", stats.Some.Avg60, 2.0}, {"Avg300", stats.Some.Avg300, 3.85}, {"Total", float64(stats.Some.Total), 15.0}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { if tc.got != tc.want { t.Errorf("got: %f, want: %f", tc.got, tc.want) } }) } }) res := []string{"memory", "io"} for _, resource := range res { t.Run(resource, func(t *testing.T) { stats, err := getProcFixtures(t).PSIStatsForResource(resource) if err != nil { t.Fatal(err) } if stats.Full == nil { t.Fatalf("%s resource must not have nil 'full' stats", resource) } if stats.Some == nil { t.Fatalf("%s resource must not have nil 'some' stats", resource) } testCases := []struct { name string got float64 want float64 }{ {"some/Avg10", stats.Some.Avg10, 0.1}, {"some/Avg60", stats.Some.Avg60, 2.0}, {"some/Avg300", stats.Some.Avg300, 3.85}, {"some/Total", float64(stats.Some.Total), 15.0}, {"full/Avg10", stats.Full.Avg10, 0.2}, {"full/Avg60", stats.Full.Avg60, 3.0}, {"full/Avg300", stats.Full.Avg300, 4.95}, {"full/Total", float64(stats.Full.Total), 25.0}, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { if tc.got != tc.want { t.Errorf("got: %f, want: %f", tc.got, tc.want) } }) } }) } } // TestParsePSIStats tests the edge cases that we won't run into when running TestPSIStats. func TestParsePSIStats(t *testing.T) { t.Run("unknown measurement type", func(t *testing.T) { raw := "nonsense haha test=fake" _, err := parsePSIStats(strings.NewReader(raw)) if err != nil { t.Error("unknown measurement type must be ignored") } }) t.Run("malformed measurement", func(t *testing.T) { t.Run("some", func(t *testing.T) { raw := `some avg10=0.10 avg60=2.00 avg300=3.85 total=oops full avg10=0.20 avg60=3.00 avg300=teddy total=25` stats, err := parsePSIStats(strings.NewReader(raw)) if err == nil { t.Error("a malformed line must result in a parse error") } if stats.Some != nil || stats.Full != nil { t.Error("a parse error must result in a nil PSILine") } }) t.Run("full", func(t *testing.T) { raw := `some avg10=0.10 avg60=2.00 avg300=3.85 total=1 full avg10=0.20 avg60=3.00 avg300=test total=25` stats, err := parsePSIStats(strings.NewReader(raw)) t.Log(err) t.Log(stats) if err == nil { t.Error("a malformed line must result in a parse error") } if stats.Some != nil || stats.Full != nil { t.Error("a parse error must result in a nil PSILine") } }) }) } golang-github-prometheus-procfs-0.14.0/proc_smaps.go000066400000000000000000000075221461002754700225170ustar00rootroot00000000000000// Copyright 2020 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. //go:build !windows // +build !windows package procfs import ( "bufio" "errors" "fmt" "os" "regexp" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) var ( // match the header line before each mapped zone in `/proc/pid/smaps`. procSMapsHeaderLine = regexp.MustCompile(`^[a-f0-9].*$`) ) type ProcSMapsRollup struct { // Amount of the mapping that is currently resident in RAM. Rss uint64 // Process's proportional share of this mapping. Pss uint64 // Size in bytes of clean shared pages. SharedClean uint64 // Size in bytes of dirty shared pages. SharedDirty uint64 // Size in bytes of clean private pages. PrivateClean uint64 // Size in bytes of dirty private pages. PrivateDirty uint64 // Amount of memory currently marked as referenced or accessed. Referenced uint64 // Amount of memory that does not belong to any file. Anonymous uint64 // Amount would-be-anonymous memory currently on swap. Swap uint64 // Process's proportional memory on swap. SwapPss uint64 } // ProcSMapsRollup reads from /proc/[pid]/smaps_rollup to get summed memory information of the // process. // // If smaps_rollup does not exists (require kernel >= 4.15), the content of /proc/pid/smaps will // we read and summed. func (p Proc) ProcSMapsRollup() (ProcSMapsRollup, error) { data, err := util.ReadFileNoStat(p.path("smaps_rollup")) if err != nil && os.IsNotExist(err) { return p.procSMapsRollupManual() } if err != nil { return ProcSMapsRollup{}, err } lines := strings.Split(string(data), "\n") smaps := ProcSMapsRollup{} // skip first line which don't contains information we need lines = lines[1:] for _, line := range lines { if line == "" { continue } if err := smaps.parseLine(line); err != nil { return ProcSMapsRollup{}, err } } return smaps, nil } // Read /proc/pid/smaps and do the roll-up in Go code. func (p Proc) procSMapsRollupManual() (ProcSMapsRollup, error) { file, err := os.Open(p.path("smaps")) if err != nil { return ProcSMapsRollup{}, err } defer file.Close() smaps := ProcSMapsRollup{} scan := bufio.NewScanner(file) for scan.Scan() { line := scan.Text() if procSMapsHeaderLine.MatchString(line) { continue } if err := smaps.parseLine(line); err != nil { return ProcSMapsRollup{}, err } } return smaps, nil } func (s *ProcSMapsRollup) parseLine(line string) error { kv := strings.SplitN(line, ":", 2) if len(kv) != 2 { fmt.Println(line) return errors.New("invalid net/dev line, missing colon") } k := kv[0] if k == "VmFlags" { return nil } v := strings.TrimSpace(kv[1]) v = strings.TrimRight(v, " kB") vKBytes, err := strconv.ParseUint(v, 10, 64) if err != nil { return err } vBytes := vKBytes * 1024 s.addValue(k, vBytes) return nil } func (s *ProcSMapsRollup) addValue(k string, vUintBytes uint64) { switch k { case "Rss": s.Rss += vUintBytes case "Pss": s.Pss += vUintBytes case "Shared_Clean": s.SharedClean += vUintBytes case "Shared_Dirty": s.SharedDirty += vUintBytes case "Private_Clean": s.PrivateClean += vUintBytes case "Private_Dirty": s.PrivateDirty += vUintBytes case "Referenced": s.Referenced += vUintBytes case "Anonymous": s.Anonymous += vUintBytes case "Swap": s.Swap += vUintBytes case "SwapPss": s.SwapPss += vUintBytes } } golang-github-prometheus-procfs-0.14.0/proc_smaps_test.go000066400000000000000000000044671461002754700235630ustar00rootroot00000000000000// Copyright 2020 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. //go:build !windows // +build !windows package procfs import ( "testing" ) func BenchmarkProcSMapsRollup(b *testing.B) { fs, err := NewFS(procTestFixtures) if err != nil { b.Fatalf("Creating pseudo fs from getProcFixtures failed at fixtures/proc with error: %s", err) } p, err := fs.Proc(26231) if err != nil { b.Fatal(err) } b.ResetTimer() for n := 0; n < b.N; n++ { _, _ = p.ProcSMapsRollup() } } func TestProcSmapsRollup(t *testing.T) { p, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } s1, err := p.ProcSMapsRollup() if err != nil { t.Fatal(err) } s2, err := p.procSMapsRollupManual() if err != nil { t.Fatal(err) } cases := []struct { name string smaps ProcSMapsRollup }{ { name: "ProcSMapsRollup", smaps: s1, }, { name: "procSMapsRollupManual", smaps: s2, }, } for _, c := range cases { for _, test := range []struct { name string want uint64 have uint64 }{ {name: "Rss", want: 29948 * 1024, have: c.smaps.Rss}, {name: "Pss", want: 29944 * 1024, have: c.smaps.Pss}, {name: "SharedClean", want: 4 * 1024, have: c.smaps.SharedClean}, {name: "SharedDirty", want: 0 * 1024, have: c.smaps.SharedDirty}, {name: "PrivateClean", want: 15548 * 1024, have: c.smaps.PrivateClean}, {name: "PrivateDirty", want: 14396 * 1024, have: c.smaps.PrivateDirty}, {name: "Referenced", want: 24752 * 1024, have: c.smaps.Referenced}, {name: "Anonymous", want: 20756 * 1024, have: c.smaps.Anonymous}, {name: "Swap", want: 1940 * 1024, have: c.smaps.Swap}, {name: "SwapPss", want: 1940 * 1024, have: c.smaps.SwapPss}, } { if test.want != test.have { t.Errorf("want %s %s %d, have %d", c.name, test.name, test.want, test.have) } } } } golang-github-prometheus-procfs-0.14.0/proc_snmp.go000066400000000000000000000223071461002754700223470ustar00rootroot00000000000000// Copyright 2022 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. package procfs import ( "bufio" "bytes" "fmt" "io" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // ProcSnmp models the content of /proc//net/snmp. type ProcSnmp struct { // The process ID. PID int Ip Icmp IcmpMsg Tcp Udp UdpLite } type Ip struct { // nolint:revive Forwarding *float64 DefaultTTL *float64 InReceives *float64 InHdrErrors *float64 InAddrErrors *float64 ForwDatagrams *float64 InUnknownProtos *float64 InDiscards *float64 InDelivers *float64 OutRequests *float64 OutDiscards *float64 OutNoRoutes *float64 ReasmTimeout *float64 ReasmReqds *float64 ReasmOKs *float64 ReasmFails *float64 FragOKs *float64 FragFails *float64 FragCreates *float64 } type Icmp struct { // nolint:revive InMsgs *float64 InErrors *float64 InCsumErrors *float64 InDestUnreachs *float64 InTimeExcds *float64 InParmProbs *float64 InSrcQuenchs *float64 InRedirects *float64 InEchos *float64 InEchoReps *float64 InTimestamps *float64 InTimestampReps *float64 InAddrMasks *float64 InAddrMaskReps *float64 OutMsgs *float64 OutErrors *float64 OutDestUnreachs *float64 OutTimeExcds *float64 OutParmProbs *float64 OutSrcQuenchs *float64 OutRedirects *float64 OutEchos *float64 OutEchoReps *float64 OutTimestamps *float64 OutTimestampReps *float64 OutAddrMasks *float64 OutAddrMaskReps *float64 } type IcmpMsg struct { InType3 *float64 OutType3 *float64 } type Tcp struct { // nolint:revive RtoAlgorithm *float64 RtoMin *float64 RtoMax *float64 MaxConn *float64 ActiveOpens *float64 PassiveOpens *float64 AttemptFails *float64 EstabResets *float64 CurrEstab *float64 InSegs *float64 OutSegs *float64 RetransSegs *float64 InErrs *float64 OutRsts *float64 InCsumErrors *float64 } type Udp struct { // nolint:revive InDatagrams *float64 NoPorts *float64 InErrors *float64 OutDatagrams *float64 RcvbufErrors *float64 SndbufErrors *float64 InCsumErrors *float64 IgnoredMulti *float64 } type UdpLite struct { // nolint:revive InDatagrams *float64 NoPorts *float64 InErrors *float64 OutDatagrams *float64 RcvbufErrors *float64 SndbufErrors *float64 InCsumErrors *float64 IgnoredMulti *float64 } func (p Proc) Snmp() (ProcSnmp, error) { filename := p.path("net/snmp") data, err := util.ReadFileNoStat(filename) if err != nil { return ProcSnmp{PID: p.PID}, err } procSnmp, err := parseSnmp(bytes.NewReader(data), filename) procSnmp.PID = p.PID return procSnmp, err } // parseSnmp parses the metrics from proc//net/snmp file // and returns a map contains those metrics (e.g. {"Ip": {"Forwarding": 2}}). func parseSnmp(r io.Reader, fileName string) (ProcSnmp, error) { var ( scanner = bufio.NewScanner(r) procSnmp = ProcSnmp{} ) for scanner.Scan() { nameParts := strings.Split(scanner.Text(), " ") scanner.Scan() valueParts := strings.Split(scanner.Text(), " ") // Remove trailing :. protocol := strings.TrimSuffix(nameParts[0], ":") if len(nameParts) != len(valueParts) { return procSnmp, fmt.Errorf("%w: mismatch field count mismatch in %s: %s", ErrFileParse, fileName, protocol) } for i := 1; i < len(nameParts); i++ { value, err := strconv.ParseFloat(valueParts[i], 64) if err != nil { return procSnmp, err } key := nameParts[i] switch protocol { case "Ip": switch key { case "Forwarding": procSnmp.Ip.Forwarding = &value case "DefaultTTL": procSnmp.Ip.DefaultTTL = &value case "InReceives": procSnmp.Ip.InReceives = &value case "InHdrErrors": procSnmp.Ip.InHdrErrors = &value case "InAddrErrors": procSnmp.Ip.InAddrErrors = &value case "ForwDatagrams": procSnmp.Ip.ForwDatagrams = &value case "InUnknownProtos": procSnmp.Ip.InUnknownProtos = &value case "InDiscards": procSnmp.Ip.InDiscards = &value case "InDelivers": procSnmp.Ip.InDelivers = &value case "OutRequests": procSnmp.Ip.OutRequests = &value case "OutDiscards": procSnmp.Ip.OutDiscards = &value case "OutNoRoutes": procSnmp.Ip.OutNoRoutes = &value case "ReasmTimeout": procSnmp.Ip.ReasmTimeout = &value case "ReasmReqds": procSnmp.Ip.ReasmReqds = &value case "ReasmOKs": procSnmp.Ip.ReasmOKs = &value case "ReasmFails": procSnmp.Ip.ReasmFails = &value case "FragOKs": procSnmp.Ip.FragOKs = &value case "FragFails": procSnmp.Ip.FragFails = &value case "FragCreates": procSnmp.Ip.FragCreates = &value } case "Icmp": switch key { case "InMsgs": procSnmp.Icmp.InMsgs = &value case "InErrors": procSnmp.Icmp.InErrors = &value case "InCsumErrors": procSnmp.Icmp.InCsumErrors = &value case "InDestUnreachs": procSnmp.Icmp.InDestUnreachs = &value case "InTimeExcds": procSnmp.Icmp.InTimeExcds = &value case "InParmProbs": procSnmp.Icmp.InParmProbs = &value case "InSrcQuenchs": procSnmp.Icmp.InSrcQuenchs = &value case "InRedirects": procSnmp.Icmp.InRedirects = &value case "InEchos": procSnmp.Icmp.InEchos = &value case "InEchoReps": procSnmp.Icmp.InEchoReps = &value case "InTimestamps": procSnmp.Icmp.InTimestamps = &value case "InTimestampReps": procSnmp.Icmp.InTimestampReps = &value case "InAddrMasks": procSnmp.Icmp.InAddrMasks = &value case "InAddrMaskReps": procSnmp.Icmp.InAddrMaskReps = &value case "OutMsgs": procSnmp.Icmp.OutMsgs = &value case "OutErrors": procSnmp.Icmp.OutErrors = &value case "OutDestUnreachs": procSnmp.Icmp.OutDestUnreachs = &value case "OutTimeExcds": procSnmp.Icmp.OutTimeExcds = &value case "OutParmProbs": procSnmp.Icmp.OutParmProbs = &value case "OutSrcQuenchs": procSnmp.Icmp.OutSrcQuenchs = &value case "OutRedirects": procSnmp.Icmp.OutRedirects = &value case "OutEchos": procSnmp.Icmp.OutEchos = &value case "OutEchoReps": procSnmp.Icmp.OutEchoReps = &value case "OutTimestamps": procSnmp.Icmp.OutTimestamps = &value case "OutTimestampReps": procSnmp.Icmp.OutTimestampReps = &value case "OutAddrMasks": procSnmp.Icmp.OutAddrMasks = &value case "OutAddrMaskReps": procSnmp.Icmp.OutAddrMaskReps = &value } case "IcmpMsg": switch key { case "InType3": procSnmp.IcmpMsg.InType3 = &value case "OutType3": procSnmp.IcmpMsg.OutType3 = &value } case "Tcp": switch key { case "RtoAlgorithm": procSnmp.Tcp.RtoAlgorithm = &value case "RtoMin": procSnmp.Tcp.RtoMin = &value case "RtoMax": procSnmp.Tcp.RtoMax = &value case "MaxConn": procSnmp.Tcp.MaxConn = &value case "ActiveOpens": procSnmp.Tcp.ActiveOpens = &value case "PassiveOpens": procSnmp.Tcp.PassiveOpens = &value case "AttemptFails": procSnmp.Tcp.AttemptFails = &value case "EstabResets": procSnmp.Tcp.EstabResets = &value case "CurrEstab": procSnmp.Tcp.CurrEstab = &value case "InSegs": procSnmp.Tcp.InSegs = &value case "OutSegs": procSnmp.Tcp.OutSegs = &value case "RetransSegs": procSnmp.Tcp.RetransSegs = &value case "InErrs": procSnmp.Tcp.InErrs = &value case "OutRsts": procSnmp.Tcp.OutRsts = &value case "InCsumErrors": procSnmp.Tcp.InCsumErrors = &value } case "Udp": switch key { case "InDatagrams": procSnmp.Udp.InDatagrams = &value case "NoPorts": procSnmp.Udp.NoPorts = &value case "InErrors": procSnmp.Udp.InErrors = &value case "OutDatagrams": procSnmp.Udp.OutDatagrams = &value case "RcvbufErrors": procSnmp.Udp.RcvbufErrors = &value case "SndbufErrors": procSnmp.Udp.SndbufErrors = &value case "InCsumErrors": procSnmp.Udp.InCsumErrors = &value case "IgnoredMulti": procSnmp.Udp.IgnoredMulti = &value } case "UdpLite": switch key { case "InDatagrams": procSnmp.UdpLite.InDatagrams = &value case "NoPorts": procSnmp.UdpLite.NoPorts = &value case "InErrors": procSnmp.UdpLite.InErrors = &value case "OutDatagrams": procSnmp.UdpLite.OutDatagrams = &value case "RcvbufErrors": procSnmp.UdpLite.RcvbufErrors = &value case "SndbufErrors": procSnmp.UdpLite.SndbufErrors = &value case "InCsumErrors": procSnmp.UdpLite.InCsumErrors = &value case "IgnoredMulti": procSnmp.UdpLite.IgnoredMulti = &value } } } } return procSnmp, scanner.Err() } golang-github-prometheus-procfs-0.14.0/proc_snmp6.go000066400000000000000000000260531461002754700224370ustar00rootroot00000000000000// Copyright 2022 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. package procfs import ( "bufio" "bytes" "errors" "io" "os" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // ProcSnmp6 models the content of /proc//net/snmp6. type ProcSnmp6 struct { // The process ID. PID int Ip6 Icmp6 Udp6 UdpLite6 } type Ip6 struct { // nolint:revive InReceives *float64 InHdrErrors *float64 InTooBigErrors *float64 InNoRoutes *float64 InAddrErrors *float64 InUnknownProtos *float64 InTruncatedPkts *float64 InDiscards *float64 InDelivers *float64 OutForwDatagrams *float64 OutRequests *float64 OutDiscards *float64 OutNoRoutes *float64 ReasmTimeout *float64 ReasmReqds *float64 ReasmOKs *float64 ReasmFails *float64 FragOKs *float64 FragFails *float64 FragCreates *float64 InMcastPkts *float64 OutMcastPkts *float64 InOctets *float64 OutOctets *float64 InMcastOctets *float64 OutMcastOctets *float64 InBcastOctets *float64 OutBcastOctets *float64 InNoECTPkts *float64 InECT1Pkts *float64 InECT0Pkts *float64 InCEPkts *float64 } type Icmp6 struct { InMsgs *float64 InErrors *float64 OutMsgs *float64 OutErrors *float64 InCsumErrors *float64 InDestUnreachs *float64 InPktTooBigs *float64 InTimeExcds *float64 InParmProblems *float64 InEchos *float64 InEchoReplies *float64 InGroupMembQueries *float64 InGroupMembResponses *float64 InGroupMembReductions *float64 InRouterSolicits *float64 InRouterAdvertisements *float64 InNeighborSolicits *float64 InNeighborAdvertisements *float64 InRedirects *float64 InMLDv2Reports *float64 OutDestUnreachs *float64 OutPktTooBigs *float64 OutTimeExcds *float64 OutParmProblems *float64 OutEchos *float64 OutEchoReplies *float64 OutGroupMembQueries *float64 OutGroupMembResponses *float64 OutGroupMembReductions *float64 OutRouterSolicits *float64 OutRouterAdvertisements *float64 OutNeighborSolicits *float64 OutNeighborAdvertisements *float64 OutRedirects *float64 OutMLDv2Reports *float64 InType1 *float64 InType134 *float64 InType135 *float64 InType136 *float64 InType143 *float64 OutType133 *float64 OutType135 *float64 OutType136 *float64 OutType143 *float64 } type Udp6 struct { // nolint:revive InDatagrams *float64 NoPorts *float64 InErrors *float64 OutDatagrams *float64 RcvbufErrors *float64 SndbufErrors *float64 InCsumErrors *float64 IgnoredMulti *float64 } type UdpLite6 struct { // nolint:revive InDatagrams *float64 NoPorts *float64 InErrors *float64 OutDatagrams *float64 RcvbufErrors *float64 SndbufErrors *float64 InCsumErrors *float64 } func (p Proc) Snmp6() (ProcSnmp6, error) { filename := p.path("net/snmp6") data, err := util.ReadFileNoStat(filename) if err != nil { // On systems with IPv6 disabled, this file won't exist. // Do nothing. if errors.Is(err, os.ErrNotExist) { return ProcSnmp6{PID: p.PID}, nil } return ProcSnmp6{PID: p.PID}, err } procSnmp6, err := parseSNMP6Stats(bytes.NewReader(data)) procSnmp6.PID = p.PID return procSnmp6, err } // parseSnmp6 parses the metrics from proc//net/snmp6 file // and returns a map contains those metrics. func parseSNMP6Stats(r io.Reader) (ProcSnmp6, error) { var ( scanner = bufio.NewScanner(r) procSnmp6 = ProcSnmp6{} ) for scanner.Scan() { stat := strings.Fields(scanner.Text()) if len(stat) < 2 { continue } // Expect to have "6" in metric name, skip line otherwise if sixIndex := strings.Index(stat[0], "6"); sixIndex != -1 { protocol := stat[0][:sixIndex+1] key := stat[0][sixIndex+1:] value, err := strconv.ParseFloat(stat[1], 64) if err != nil { return procSnmp6, err } switch protocol { case "Ip6": switch key { case "InReceives": procSnmp6.Ip6.InReceives = &value case "InHdrErrors": procSnmp6.Ip6.InHdrErrors = &value case "InTooBigErrors": procSnmp6.Ip6.InTooBigErrors = &value case "InNoRoutes": procSnmp6.Ip6.InNoRoutes = &value case "InAddrErrors": procSnmp6.Ip6.InAddrErrors = &value case "InUnknownProtos": procSnmp6.Ip6.InUnknownProtos = &value case "InTruncatedPkts": procSnmp6.Ip6.InTruncatedPkts = &value case "InDiscards": procSnmp6.Ip6.InDiscards = &value case "InDelivers": procSnmp6.Ip6.InDelivers = &value case "OutForwDatagrams": procSnmp6.Ip6.OutForwDatagrams = &value case "OutRequests": procSnmp6.Ip6.OutRequests = &value case "OutDiscards": procSnmp6.Ip6.OutDiscards = &value case "OutNoRoutes": procSnmp6.Ip6.OutNoRoutes = &value case "ReasmTimeout": procSnmp6.Ip6.ReasmTimeout = &value case "ReasmReqds": procSnmp6.Ip6.ReasmReqds = &value case "ReasmOKs": procSnmp6.Ip6.ReasmOKs = &value case "ReasmFails": procSnmp6.Ip6.ReasmFails = &value case "FragOKs": procSnmp6.Ip6.FragOKs = &value case "FragFails": procSnmp6.Ip6.FragFails = &value case "FragCreates": procSnmp6.Ip6.FragCreates = &value case "InMcastPkts": procSnmp6.Ip6.InMcastPkts = &value case "OutMcastPkts": procSnmp6.Ip6.OutMcastPkts = &value case "InOctets": procSnmp6.Ip6.InOctets = &value case "OutOctets": procSnmp6.Ip6.OutOctets = &value case "InMcastOctets": procSnmp6.Ip6.InMcastOctets = &value case "OutMcastOctets": procSnmp6.Ip6.OutMcastOctets = &value case "InBcastOctets": procSnmp6.Ip6.InBcastOctets = &value case "OutBcastOctets": procSnmp6.Ip6.OutBcastOctets = &value case "InNoECTPkts": procSnmp6.Ip6.InNoECTPkts = &value case "InECT1Pkts": procSnmp6.Ip6.InECT1Pkts = &value case "InECT0Pkts": procSnmp6.Ip6.InECT0Pkts = &value case "InCEPkts": procSnmp6.Ip6.InCEPkts = &value } case "Icmp6": switch key { case "InMsgs": procSnmp6.Icmp6.InMsgs = &value case "InErrors": procSnmp6.Icmp6.InErrors = &value case "OutMsgs": procSnmp6.Icmp6.OutMsgs = &value case "OutErrors": procSnmp6.Icmp6.OutErrors = &value case "InCsumErrors": procSnmp6.Icmp6.InCsumErrors = &value case "InDestUnreachs": procSnmp6.Icmp6.InDestUnreachs = &value case "InPktTooBigs": procSnmp6.Icmp6.InPktTooBigs = &value case "InTimeExcds": procSnmp6.Icmp6.InTimeExcds = &value case "InParmProblems": procSnmp6.Icmp6.InParmProblems = &value case "InEchos": procSnmp6.Icmp6.InEchos = &value case "InEchoReplies": procSnmp6.Icmp6.InEchoReplies = &value case "InGroupMembQueries": procSnmp6.Icmp6.InGroupMembQueries = &value case "InGroupMembResponses": procSnmp6.Icmp6.InGroupMembResponses = &value case "InGroupMembReductions": procSnmp6.Icmp6.InGroupMembReductions = &value case "InRouterSolicits": procSnmp6.Icmp6.InRouterSolicits = &value case "InRouterAdvertisements": procSnmp6.Icmp6.InRouterAdvertisements = &value case "InNeighborSolicits": procSnmp6.Icmp6.InNeighborSolicits = &value case "InNeighborAdvertisements": procSnmp6.Icmp6.InNeighborAdvertisements = &value case "InRedirects": procSnmp6.Icmp6.InRedirects = &value case "InMLDv2Reports": procSnmp6.Icmp6.InMLDv2Reports = &value case "OutDestUnreachs": procSnmp6.Icmp6.OutDestUnreachs = &value case "OutPktTooBigs": procSnmp6.Icmp6.OutPktTooBigs = &value case "OutTimeExcds": procSnmp6.Icmp6.OutTimeExcds = &value case "OutParmProblems": procSnmp6.Icmp6.OutParmProblems = &value case "OutEchos": procSnmp6.Icmp6.OutEchos = &value case "OutEchoReplies": procSnmp6.Icmp6.OutEchoReplies = &value case "OutGroupMembQueries": procSnmp6.Icmp6.OutGroupMembQueries = &value case "OutGroupMembResponses": procSnmp6.Icmp6.OutGroupMembResponses = &value case "OutGroupMembReductions": procSnmp6.Icmp6.OutGroupMembReductions = &value case "OutRouterSolicits": procSnmp6.Icmp6.OutRouterSolicits = &value case "OutRouterAdvertisements": procSnmp6.Icmp6.OutRouterAdvertisements = &value case "OutNeighborSolicits": procSnmp6.Icmp6.OutNeighborSolicits = &value case "OutNeighborAdvertisements": procSnmp6.Icmp6.OutNeighborAdvertisements = &value case "OutRedirects": procSnmp6.Icmp6.OutRedirects = &value case "OutMLDv2Reports": procSnmp6.Icmp6.OutMLDv2Reports = &value case "InType1": procSnmp6.Icmp6.InType1 = &value case "InType134": procSnmp6.Icmp6.InType134 = &value case "InType135": procSnmp6.Icmp6.InType135 = &value case "InType136": procSnmp6.Icmp6.InType136 = &value case "InType143": procSnmp6.Icmp6.InType143 = &value case "OutType133": procSnmp6.Icmp6.OutType133 = &value case "OutType135": procSnmp6.Icmp6.OutType135 = &value case "OutType136": procSnmp6.Icmp6.OutType136 = &value case "OutType143": procSnmp6.Icmp6.OutType143 = &value } case "Udp6": switch key { case "InDatagrams": procSnmp6.Udp6.InDatagrams = &value case "NoPorts": procSnmp6.Udp6.NoPorts = &value case "InErrors": procSnmp6.Udp6.InErrors = &value case "OutDatagrams": procSnmp6.Udp6.OutDatagrams = &value case "RcvbufErrors": procSnmp6.Udp6.RcvbufErrors = &value case "SndbufErrors": procSnmp6.Udp6.SndbufErrors = &value case "InCsumErrors": procSnmp6.Udp6.InCsumErrors = &value case "IgnoredMulti": procSnmp6.Udp6.IgnoredMulti = &value } case "UdpLite6": switch key { case "InDatagrams": procSnmp6.UdpLite6.InDatagrams = &value case "NoPorts": procSnmp6.UdpLite6.NoPorts = &value case "InErrors": procSnmp6.UdpLite6.InErrors = &value case "OutDatagrams": procSnmp6.UdpLite6.OutDatagrams = &value case "RcvbufErrors": procSnmp6.UdpLite6.RcvbufErrors = &value case "SndbufErrors": procSnmp6.UdpLite6.SndbufErrors = &value case "InCsumErrors": procSnmp6.UdpLite6.InCsumErrors = &value } } } } return procSnmp6, scanner.Err() } golang-github-prometheus-procfs-0.14.0/proc_snmp6_test.go000066400000000000000000000030471461002754700234740ustar00rootroot00000000000000// Copyright 2022 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. package procfs import "testing" func TestProcSnmp6(t *testing.T) { p, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } procSnmp6, err := p.Snmp6() if err != nil { t.Fatal(err) } for _, test := range []struct { name string want float64 have float64 }{ {name: "pid", want: 26231, have: float64(procSnmp6.PID)}, {name: "Ip6InReceives", want: 92166, have: *procSnmp6.Ip6.InReceives}, {name: "Ip6InDelivers", want: 92053, have: *procSnmp6.Ip6.InDelivers}, {name: "Ip6OutNoRoutes", want: 169, have: *procSnmp6.Ip6.OutNoRoutes}, {name: "Ip6InOctets", want: 113479132, have: *procSnmp6.Ip6.InOctets}, {name: "Icmp6InMsgs", want: 142, have: *procSnmp6.Icmp6.InMsgs}, {name: "Udp6InDatagrams", want: 2016, have: *procSnmp6.Udp6.InDatagrams}, {name: "UdpLite6InDatagrams", want: 0, have: *procSnmp6.UdpLite6.InDatagrams}, } { if test.want != test.have { t.Errorf("want %s %f, have %f", test.name, test.want, test.have) } } } golang-github-prometheus-procfs-0.14.0/proc_snmp_test.go000066400000000000000000000034351461002754700234070ustar00rootroot00000000000000// Copyright 2022 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. package procfs import "testing" func TestProcSnmp(t *testing.T) { p, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } procSnmp, err := p.Snmp() if err != nil { t.Fatal(err) } for _, test := range []struct { name string want float64 have float64 }{ {name: "pid", want: 26231, have: float64(procSnmp.PID)}, {name: "IP:Forwarding", want: 2, have: *procSnmp.Ip.Forwarding}, {name: "IP:DefaultTTL", want: 64, have: *procSnmp.Ip.DefaultTTL}, {name: "Icmp:InMsgs", want: 45, have: *procSnmp.Icmp.InMsgs}, {name: "IcmpMsg:InType3", want: 45, have: *procSnmp.IcmpMsg.InType3}, {name: "IcmpMsg:OutType3", want: 50, have: *procSnmp.IcmpMsg.OutType3}, {name: "TCP:RtoAlgorithm", want: 1, have: *procSnmp.Tcp.RtoAlgorithm}, {name: "TCP:RtoMin", want: 200, have: *procSnmp.Tcp.RtoMin}, {name: "Udp:InDatagrams", want: 10179, have: *procSnmp.Udp.InDatagrams}, {name: "Udp:NoPorts", want: 50, have: *procSnmp.Udp.NoPorts}, {name: "UdpLite:InDatagrams", want: 0, have: *procSnmp.UdpLite.NoPorts}, {name: "UdpLite:NoPorts", want: 0, have: *procSnmp.UdpLite.NoPorts}, } { if test.want != test.have { t.Errorf("want %s %f, have %f", test.name, test.want, test.have) } } } golang-github-prometheus-procfs-0.14.0/proc_stat.go000066400000000000000000000147621461002754700223530ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "bytes" "fmt" "os" "github.com/prometheus/procfs/internal/util" ) // Originally, this USER_HZ value was dynamically retrieved via a sysconf call // which required cgo. However, that caused a lot of problems regarding // cross-compilation. Alternatives such as running a binary to determine the // value, or trying to derive it in some other way were all problematic. After // much research it was determined that USER_HZ is actually hardcoded to 100 on // all Go-supported platforms as of the time of this writing. This is why we // decided to hardcode it here as well. It is not impossible that there could // be systems with exceptions, but they should be very exotic edge cases, and // in that case, the worst outcome will be two misreported metrics. // // See also the following discussions: // // - https://github.com/prometheus/node_exporter/issues/52 // - https://github.com/prometheus/procfs/pull/2 // - http://stackoverflow.com/questions/17410841/how-does-user-hz-solve-the-jiffy-scaling-issue const userHZ = 100 // ProcStat provides status information about the process, // read from /proc/[pid]/stat. type ProcStat struct { // The process ID. PID int // The filename of the executable. Comm string // The process state. State string // The PID of the parent of this process. PPID int // The process group ID of the process. PGRP int // The session ID of the process. Session int // The controlling terminal of the process. TTY int // The ID of the foreground process group of the controlling terminal of // the process. TPGID int // The kernel flags word of the process. Flags uint // The number of minor faults the process has made which have not required // loading a memory page from disk. MinFlt uint // The number of minor faults that the process's waited-for children have // made. CMinFlt uint // The number of major faults the process has made which have required // loading a memory page from disk. MajFlt uint // The number of major faults that the process's waited-for children have // made. CMajFlt uint // Amount of time that this process has been scheduled in user mode, // measured in clock ticks. UTime uint // Amount of time that this process has been scheduled in kernel mode, // measured in clock ticks. STime uint // Amount of time that this process's waited-for children have been // scheduled in user mode, measured in clock ticks. CUTime int // Amount of time that this process's waited-for children have been // scheduled in kernel mode, measured in clock ticks. CSTime int // For processes running a real-time scheduling policy, this is the negated // scheduling priority, minus one. Priority int // The nice value, a value in the range 19 (low priority) to -20 (high // priority). Nice int // Number of threads in this process. NumThreads int // The time the process started after system boot, the value is expressed // in clock ticks. Starttime uint64 // Virtual memory size in bytes. VSize uint // Resident set size in pages. RSS int // Soft limit in bytes on the rss of the process. RSSLimit uint64 // CPU number last executed on. Processor uint // Real-time scheduling priority, a number in the range 1 to 99 for processes // scheduled under a real-time policy, or 0, for non-real-time processes. RTPriority uint // Scheduling policy. Policy uint // Aggregated block I/O delays, measured in clock ticks (centiseconds). DelayAcctBlkIOTicks uint64 // Guest time of the process (time spent running a virtual CPU for a guest // operating system), measured in clock ticks. GuestTime int // Guest time of the process's children, measured in clock ticks. CGuestTime int proc FS } // NewStat returns the current status information of the process. // // Deprecated: Use p.Stat() instead. func (p Proc) NewStat() (ProcStat, error) { return p.Stat() } // Stat returns the current status information of the process. func (p Proc) Stat() (ProcStat, error) { data, err := util.ReadFileNoStat(p.path("stat")) if err != nil { return ProcStat{}, err } var ( ignoreInt64 int64 ignoreUint64 uint64 s = ProcStat{PID: p.PID, proc: p.fs} l = bytes.Index(data, []byte("(")) r = bytes.LastIndex(data, []byte(")")) ) if l < 0 || r < 0 { return ProcStat{}, fmt.Errorf("%w: unexpected format, couldn't extract comm %q", ErrFileParse, data) } s.Comm = string(data[l+1 : r]) // Check the following resources for the details about the particular stat // fields and their data types: // * https://man7.org/linux/man-pages/man5/proc.5.html // * https://man7.org/linux/man-pages/man3/scanf.3.html _, err = fmt.Fscan( bytes.NewBuffer(data[r+2:]), &s.State, &s.PPID, &s.PGRP, &s.Session, &s.TTY, &s.TPGID, &s.Flags, &s.MinFlt, &s.CMinFlt, &s.MajFlt, &s.CMajFlt, &s.UTime, &s.STime, &s.CUTime, &s.CSTime, &s.Priority, &s.Nice, &s.NumThreads, &ignoreInt64, &s.Starttime, &s.VSize, &s.RSS, &s.RSSLimit, &ignoreUint64, &ignoreUint64, &ignoreUint64, &ignoreUint64, &ignoreUint64, &ignoreUint64, &ignoreUint64, &ignoreUint64, &ignoreUint64, &ignoreUint64, &ignoreUint64, &ignoreUint64, &ignoreInt64, &s.Processor, &s.RTPriority, &s.Policy, &s.DelayAcctBlkIOTicks, &s.GuestTime, &s.CGuestTime, ) if err != nil { return ProcStat{}, err } return s, nil } // VirtualMemory returns the virtual memory size in bytes. func (s ProcStat) VirtualMemory() uint { return s.VSize } // ResidentMemory returns the resident memory size in bytes. func (s ProcStat) ResidentMemory() int { return s.RSS * os.Getpagesize() } // StartTime returns the unix timestamp of the process in seconds. func (s ProcStat) StartTime() (float64, error) { stat, err := s.proc.Stat() if err != nil { return 0, err } return float64(stat.BootTime) + (float64(s.Starttime) / userHZ), nil } // CPUTime returns the total CPU user and system time in seconds. func (s ProcStat) CPUTime() float64 { return float64(s.UTime+s.STime) / userHZ } golang-github-prometheus-procfs-0.14.0/proc_stat_test.go000066400000000000000000000102651461002754700234040ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "math" "os" "testing" ) func TestProcStat(t *testing.T) { p, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } s, err := p.Stat() if err != nil { t.Fatal(err) } // pid stat int fields for _, test := range []struct { name string want int have int }{ {name: "pid", want: 26231, have: s.PID}, {name: "user time", want: 1677, have: int(s.UTime)}, {name: "system time", want: 44, have: int(s.STime)}, {name: "start time", want: 82375, have: int(s.Starttime)}, {name: "virtual memory size", want: 56274944, have: int(s.VSize)}, {name: "resident set size", want: 1981, have: s.RSS}, } { if test.want != test.have { t.Errorf("want %s %d, have %d", test.name, test.want, test.have) } } // pid stat uint64 fields for _, test := range []struct { name string want uint64 have uint64 }{ {name: "RSS Limit", want: 18446744073709551615, have: s.RSSLimit}, {name: "delayacct_blkio_ticks", want: 31, have: s.DelayAcctBlkIOTicks}, } { if test.want != test.have { t.Errorf("want %s %d, have %d", test.name, test.want, test.have) } } // pid stat uint fields for _, test := range []struct { name string want uint have uint }{ {name: "processor", want: 0, have: s.Processor}, {name: "rt_priority", want: 0, have: s.RTPriority}, {name: "policy", want: 0, have: s.Policy}, } { if test.want != test.have { t.Errorf("want %s %d, have %d", test.name, test.want, test.have) } } } func TestProcStatLimits(t *testing.T) { p, err := getProcFixtures(t).Proc(26232) if err != nil { t.Fatal(err) } s, err := p.Stat() if err != nil { t.Errorf("want not error, have %s", err) } // max values of stat int fields for _, test := range []struct { name string want int have int }{ {name: "waited for children user time", want: math.MinInt64, have: s.CUTime}, {name: "waited for children system time", want: math.MaxInt64, have: s.CSTime}, } { if test.want != test.have { t.Errorf("want %s %d, have %d", test.name, test.want, test.have) } } } func TestProcStatComm(t *testing.T) { s1, err := testProcStat(26231) if err != nil { t.Fatal(err) } if want, have := "vim", s1.Comm; want != have { t.Errorf("want comm %s, have %s", want, have) } s2, err := testProcStat(584) if err != nil { t.Fatal(err) } if want, have := "(a b ) ( c d) ", s2.Comm; want != have { t.Errorf("want comm %s, have %s", want, have) } } func TestProcStatVirtualMemory(t *testing.T) { s, err := testProcStat(26231) if err != nil { t.Fatal(err) } if want, have := 56274944, int(s.VirtualMemory()); want != have { t.Errorf("want virtual memory %d, have %d", want, have) } } func TestProcStatResidentMemory(t *testing.T) { s, err := testProcStat(26231) if err != nil { t.Fatal(err) } if want, have := 1981*os.Getpagesize(), s.ResidentMemory(); want != have { t.Errorf("want resident memory %d, have %d", want, have) } } func TestProcStatStartTime(t *testing.T) { s, err := testProcStat(26231) if err != nil { t.Fatal(err) } time, err := s.StartTime() if err != nil { t.Fatal(err) } if want, have := 1418184099.75, time; want != have { t.Errorf("want start time %f, have %f", want, have) } } func TestProcStatCPUTime(t *testing.T) { s, err := testProcStat(26231) if err != nil { t.Fatal(err) } if want, have := 17.21, s.CPUTime(); want != have { t.Errorf("want cpu time %f, have %f", want, have) } } func testProcStat(pid int) (ProcStat, error) { fs, err := NewFS(procTestFixtures) if err != nil { return ProcStat{}, err } p, err := fs.Proc(pid) if err != nil { return ProcStat{}, err } return p.Stat() } golang-github-prometheus-procfs-0.14.0/proc_status.go000066400000000000000000000135001461002754700227100ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "bytes" "math/bits" "sort" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // ProcStatus provides status information about the process, // read from /proc/[pid]/status. type ProcStatus struct { // The process ID. PID int // The process name. Name string // Thread group ID. TGID int // List of Pid namespace. NSpids []uint64 // Peak virtual memory size. VmPeak uint64 // nolint:revive // Virtual memory size. VmSize uint64 // nolint:revive // Locked memory size. VmLck uint64 // nolint:revive // Pinned memory size. VmPin uint64 // nolint:revive // Peak resident set size. VmHWM uint64 // nolint:revive // Resident set size (sum of RssAnnon RssFile and RssShmem). VmRSS uint64 // nolint:revive // Size of resident anonymous memory. RssAnon uint64 // nolint:revive // Size of resident file mappings. RssFile uint64 // nolint:revive // Size of resident shared memory. RssShmem uint64 // nolint:revive // Size of data segments. VmData uint64 // nolint:revive // Size of stack segments. VmStk uint64 // nolint:revive // Size of text segments. VmExe uint64 // nolint:revive // Shared library code size. VmLib uint64 // nolint:revive // Page table entries size. VmPTE uint64 // nolint:revive // Size of second-level page tables. VmPMD uint64 // nolint:revive // Swapped-out virtual memory size by anonymous private. VmSwap uint64 // nolint:revive // Size of hugetlb memory portions HugetlbPages uint64 // Number of voluntary context switches. VoluntaryCtxtSwitches uint64 // Number of involuntary context switches. NonVoluntaryCtxtSwitches uint64 // UIDs of the process (Real, effective, saved set, and filesystem UIDs) UIDs [4]uint64 // GIDs of the process (Real, effective, saved set, and filesystem GIDs) GIDs [4]uint64 // CpusAllowedList: List of cpu cores processes are allowed to run on. CpusAllowedList []uint64 } // NewStatus returns the current status information of the process. func (p Proc) NewStatus() (ProcStatus, error) { data, err := util.ReadFileNoStat(p.path("status")) if err != nil { return ProcStatus{}, err } s := ProcStatus{PID: p.PID} lines := strings.Split(string(data), "\n") for _, line := range lines { if !bytes.Contains([]byte(line), []byte(":")) { continue } kv := strings.SplitN(line, ":", 2) // removes spaces k := strings.TrimSpace(kv[0]) v := strings.TrimSpace(kv[1]) // removes "kB" v = strings.TrimSuffix(v, " kB") // value to int when possible // we can skip error check here, 'cause vKBytes is not used when value is a string vKBytes, _ := strconv.ParseUint(v, 10, 64) // convert kB to B vBytes := vKBytes * 1024 err = s.fillStatus(k, v, vKBytes, vBytes) if err != nil { return ProcStatus{}, err } } return s, nil } func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintBytes uint64) error { switch k { case "Tgid": s.TGID = int(vUint) case "Name": s.Name = vString case "Uid": var err error for i, v := range strings.Split(vString, "\t") { s.UIDs[i], err = strconv.ParseUint(v, 10, bits.UintSize) if err != nil { return err } } case "Gid": var err error for i, v := range strings.Split(vString, "\t") { s.GIDs[i], err = strconv.ParseUint(v, 10, bits.UintSize) if err != nil { return err } } case "NSpid": s.NSpids = calcNSPidsList(vString) case "VmPeak": s.VmPeak = vUintBytes case "VmSize": s.VmSize = vUintBytes case "VmLck": s.VmLck = vUintBytes case "VmPin": s.VmPin = vUintBytes case "VmHWM": s.VmHWM = vUintBytes case "VmRSS": s.VmRSS = vUintBytes case "RssAnon": s.RssAnon = vUintBytes case "RssFile": s.RssFile = vUintBytes case "RssShmem": s.RssShmem = vUintBytes case "VmData": s.VmData = vUintBytes case "VmStk": s.VmStk = vUintBytes case "VmExe": s.VmExe = vUintBytes case "VmLib": s.VmLib = vUintBytes case "VmPTE": s.VmPTE = vUintBytes case "VmPMD": s.VmPMD = vUintBytes case "VmSwap": s.VmSwap = vUintBytes case "HugetlbPages": s.HugetlbPages = vUintBytes case "voluntary_ctxt_switches": s.VoluntaryCtxtSwitches = vUint case "nonvoluntary_ctxt_switches": s.NonVoluntaryCtxtSwitches = vUint case "Cpus_allowed_list": s.CpusAllowedList = calcCpusAllowedList(vString) } return nil } // TotalCtxtSwitches returns the total context switch. func (s ProcStatus) TotalCtxtSwitches() uint64 { return s.VoluntaryCtxtSwitches + s.NonVoluntaryCtxtSwitches } func calcCpusAllowedList(cpuString string) []uint64 { s := strings.Split(cpuString, ",") var g []uint64 for _, cpu := range s { // parse cpu ranges, example: 1-3=[1,2,3] if l := strings.Split(strings.TrimSpace(cpu), "-"); len(l) > 1 { startCPU, _ := strconv.ParseUint(l[0], 10, 64) endCPU, _ := strconv.ParseUint(l[1], 10, 64) for i := startCPU; i <= endCPU; i++ { g = append(g, i) } } else if len(l) == 1 { cpu, _ := strconv.ParseUint(l[0], 10, 64) g = append(g, cpu) } } sort.Slice(g, func(i, j int) bool { return g[i] < g[j] }) return g } func calcNSPidsList(nspidsString string) []uint64 { s := strings.Split(nspidsString, " ") var nspids []uint64 for _, nspid := range s { nspid, _ := strconv.ParseUint(nspid, 10, 64) if nspid == 0 { continue } nspids = append(nspids, nspid) } return nspids } golang-github-prometheus-procfs-0.14.0/proc_status_test.go000066400000000000000000000075621461002754700237620ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "reflect" "testing" ) func TestProcStatus(t *testing.T) { p, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } s, err := p.NewStatus() if err != nil { t.Fatal(err) } for _, test := range []struct { name string want int have int }{ {name: "Pid", want: 26231, have: s.PID}, {name: "Tgid", want: 26231, have: s.TGID}, {name: "NSpid", want: 1, have: int(s.NSpids[0])}, {name: "VmPeak", want: 58472 * 1024, have: int(s.VmPeak)}, {name: "VmSize", want: 58440 * 1024, have: int(s.VmSize)}, {name: "VmLck", want: 0 * 1024, have: int(s.VmLck)}, {name: "VmPin", want: 0 * 1024, have: int(s.VmPin)}, {name: "VmHWM", want: 8028 * 1024, have: int(s.VmHWM)}, {name: "VmRSS", want: 6716 * 1024, have: int(s.VmRSS)}, {name: "RssAnon", want: 2092 * 1024, have: int(s.RssAnon)}, {name: "RssFile", want: 4624 * 1024, have: int(s.RssFile)}, {name: "RssShmem", want: 0 * 1024, have: int(s.RssShmem)}, {name: "VmData", want: 2580 * 1024, have: int(s.VmData)}, {name: "VmStk", want: 136 * 1024, have: int(s.VmStk)}, {name: "VmExe", want: 948 * 1024, have: int(s.VmExe)}, {name: "VmLib", want: 6816 * 1024, have: int(s.VmLib)}, {name: "VmPTE", want: 128 * 1024, have: int(s.VmPTE)}, {name: "VmPMD", want: 12 * 1024, have: int(s.VmPMD)}, {name: "VmSwap", want: 660 * 1024, have: int(s.VmSwap)}, {name: "HugetlbPages", want: 0 * 1024, have: int(s.HugetlbPages)}, {name: "VoluntaryCtxtSwitches", want: 4742839, have: int(s.VoluntaryCtxtSwitches)}, {name: "NonVoluntaryCtxtSwitches", want: 1727500, have: int(s.NonVoluntaryCtxtSwitches)}, {name: "TotalCtxtSwitches", want: 4742839 + 1727500, have: int(s.TotalCtxtSwitches())}, } { if test.want != test.have { t.Errorf("want %s %d, have %d", test.name, test.want, test.have) } } } func TestProcStatusName(t *testing.T) { p, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } s, err := p.NewStatus() if err != nil { t.Fatal(err) } if want, have := "prometheus", s.Name; want != have { t.Errorf("want name %s, have %s", want, have) } } func TestProcStatusNameTrim(t *testing.T) { p, err := getProcFixtures(t).Proc(26235) if err != nil { t.Fatal(err) } s, err := p.NewStatus() if err != nil { t.Fatal(err) } if want, have := "kube-proxy", s.Name; want != have { t.Errorf("want name %s, have %s", want, have) } } func TestProcStatusUIDs(t *testing.T) { p, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } s, err := p.NewStatus() if err != nil { t.Fatal(err) } if want, have := [4]uint64{1000, 1000, 1000, 0}, s.UIDs; want != have { t.Errorf("want uids %v, have %v", want, have) } } func TestProcStatusGIDs(t *testing.T) { p, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } s, err := p.NewStatus() if err != nil { t.Fatal(err) } if want, have := [4]uint64{1001, 1001, 1001, 0}, s.GIDs; want != have { t.Errorf("want gids %v, have %v", want, have) } } func TestCpusAllowedList(t *testing.T) { p, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } s, err := p.NewStatus() if err != nil { t.Fatal(err) } if want, have := []uint64{0, 1, 2, 3, 4, 5, 6, 7}, s.CpusAllowedList; !reflect.DeepEqual(want, have) { t.Errorf("want CpusAllowedList %v, have %v", want, have) } } golang-github-prometheus-procfs-0.14.0/proc_sys.go000066400000000000000000000026111461002754700222040ustar00rootroot00000000000000// Copyright 2022 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. package procfs import ( "fmt" "strings" "github.com/prometheus/procfs/internal/util" ) func sysctlToPath(sysctl string) string { return strings.Replace(sysctl, ".", "/", -1) } func (fs FS) SysctlStrings(sysctl string) ([]string, error) { value, err := util.SysReadFile(fs.proc.Path("sys", sysctlToPath(sysctl))) if err != nil { return nil, err } return strings.Fields(value), nil } func (fs FS) SysctlInts(sysctl string) ([]int, error) { fields, err := fs.SysctlStrings(sysctl) if err != nil { return nil, err } values := make([]int, len(fields)) for i, f := range fields { vp := util.NewValueParser(f) values[i] = vp.Int() if err := vp.Err(); err != nil { return nil, fmt.Errorf("%w: field %d in sysctl %s is not a valid int: %w", ErrFileParse, i, sysctl, err) } } return values, nil } golang-github-prometheus-procfs-0.14.0/proc_sys_test.go000066400000000000000000000043561461002754700232530ustar00rootroot00000000000000// Copyright 2022 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. package procfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestSysctlInts(t *testing.T) { fs := getProcFixtures(t) for _, tc := range []struct { sysctl string want []int }{ {"kernel.random.entropy_avail", []int{3943}}, {"vm.lowmem_reserve_ratio", []int{256, 256, 32, 0, 0}}, } { t.Run(tc.sysctl, func(t *testing.T) { got, err := fs.SysctlInts(tc.sysctl) if err != nil { t.Fatal(err) } if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("unexpected syscall value(-want +got):\n%s", diff) } }) } } func TestSysctlStrings(t *testing.T) { fs := getProcFixtures(t) for _, tc := range []struct { sysctl string want []string }{ {"kernel.seccomp.actions_avail", []string{"kill_process", "kill_thread", "trap", "errno", "trace", "log", "allow"}}, } { t.Run(tc.sysctl, func(t *testing.T) { got, err := fs.SysctlStrings(tc.sysctl) if err != nil { t.Fatal(err) } if diff := cmp.Diff(tc.want, got); diff != "" { t.Fatalf("unexpected syscall value(-want +got):\n%s", diff) } }) } } func TestSysctlIntsError(t *testing.T) { fs := getProcFixtures(t) for _, tc := range []struct { sysctl string want string }{ {"kernel.seccomp.actions_avail", "Error Parsing File: field 0 in sysctl kernel.seccomp.actions_avail is not a valid int: strconv.ParseInt: parsing \"kill_process\": invalid syntax"}, } { t.Run(tc.sysctl, func(t *testing.T) { _, err := fs.SysctlInts(tc.sysctl) if err == nil { t.Fatal("Error Parsing File: expected error") } if diff := cmp.Diff(tc.want, err.Error()); diff != "" { t.Fatalf("unexpected syscall value(-want +got):\n%s", diff) } }) } } golang-github-prometheus-procfs-0.14.0/proc_test.go000066400000000000000000000147431461002754700223560ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "reflect" "sort" "testing" ) func TestSelf(t *testing.T) { fs := getProcFixtures(t) p1, err := fs.Proc(26231) if err != nil { t.Fatal(err) } p2, err := fs.Self() if err != nil { t.Fatal(err) } if !reflect.DeepEqual(p1, p2) { t.Errorf("want process %v, have %v", p1, p2) } } func TestAllProcs(t *testing.T) { procs, err := getProcFixtures(t).AllProcs() if err != nil { t.Fatal(err) } sort.Sort(procs) for i, p := range []*Proc{{PID: 584}, {PID: 26231}} { if want, have := p.PID, procs[i].PID; want != have { t.Errorf("want processes %d, have %d", want, have) } } } func TestCmdLine(t *testing.T) { for _, tt := range []struct { process int want []string }{ {process: 26231, want: []string{"vim", "test.go", "+10"}}, {process: 26232, want: []string{}}, {process: 26233, want: []string{"com.github.uiautomator"}}, } { p1, err := getProcFixtures(t).Proc(tt.process) if err != nil { t.Fatal(err) } c1, err := p1.CmdLine() if err != nil { t.Fatal(err) } if !reflect.DeepEqual(tt.want, c1) { t.Errorf("want cmdline %v, have %v", tt.want, c1) } } } func TestWchan(t *testing.T) { for _, tt := range []struct { process int want string }{ {process: 26231, want: "poll_schedule_timeout"}, {process: 26232, want: ""}, } { p1, err := getProcFixtures(t).Proc(tt.process) if err != nil { t.Fatal(err) } c1, err := p1.Wchan() if err != nil { t.Fatal(err) } if !reflect.DeepEqual(tt.want, c1) { t.Errorf("want wchan %v, have %v", tt.want, c1) } } } func TestComm(t *testing.T) { for _, tt := range []struct { process int want string }{ {process: 26231, want: "vim"}, {process: 26232, want: "ata_sff"}, } { p1, err := getProcFixtures(t).Proc(tt.process) if err != nil { t.Fatal(err) } c1, err := p1.Comm() if err != nil { t.Fatal(err) } if !reflect.DeepEqual(tt.want, c1) { t.Errorf("want comm %v, have %v", tt.want, c1) } } } func TestExecutable(t *testing.T) { for _, tt := range []struct { process int want string }{ {process: 26231, want: "/usr/bin/vim"}, {process: 26232, want: ""}, } { p, err := getProcFixtures(t).Proc(tt.process) if err != nil { t.Fatal(err) } exe, err := p.Executable() if err != nil { t.Fatal(err) } if !reflect.DeepEqual(tt.want, exe) { t.Errorf("want absolute path to exe %v, have %v", tt.want, exe) } } } func TestCwd(t *testing.T) { for _, tt := range []struct { process int want string brokenLink bool }{ {process: 26231, want: "/usr/bin"}, {process: 26232, want: "/does/not/exist", brokenLink: true}, {process: 26233, want: ""}, } { p, err := getProcFixtures(t).Proc(tt.process) if err != nil { t.Fatal(err) } wd, err := p.Cwd() if err != nil { t.Fatal(err) } if !reflect.DeepEqual(tt.want, wd) { if wd == "" && tt.brokenLink { // Allow the result to be empty when can't os.Readlink broken links continue } t.Errorf("want absolute path to cwd %v, have %v", tt.want, wd) } } } func TestRoot(t *testing.T) { for _, tt := range []struct { process int want string brokenLink bool }{ {process: 26231, want: "/"}, {process: 26232, want: "/does/not/exist", brokenLink: true}, {process: 26233, want: ""}, } { p, err := getProcFixtures(t).Proc(tt.process) if err != nil { t.Fatal(err) } rdir, err := p.RootDir() if err != nil { t.Fatal(err) } if !reflect.DeepEqual(tt.want, rdir) { if rdir == "" && tt.brokenLink { // Allow the result to be empty when can't os.Readlink broken links continue } t.Errorf("want absolute path to rootdir %v, have %v", tt.want, rdir) } } } func TestFileDescriptors(t *testing.T) { p1, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } fds, err := p1.FileDescriptors() if err != nil { t.Fatal(err) } sort.Sort(byUintptr(fds)) if want := []uintptr{0, 1, 2, 3, 10}; !reflect.DeepEqual(want, fds) { t.Errorf("want fds %v, have %v", want, fds) } } func TestFileDescriptorTargets(t *testing.T) { p1, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } fds, err := p1.FileDescriptorTargets() if err != nil { t.Fatal(err) } sort.Strings(fds) var want = []string{ "../../symlinktargets/abc", "../../symlinktargets/def", "../../symlinktargets/ghi", "../../symlinktargets/uvw", "../../symlinktargets/xyz", } if !reflect.DeepEqual(want, fds) { t.Errorf("want fds %v, have %v", want, fds) } } func TestFileDescriptorsLen(t *testing.T) { p1, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } l, err := p1.FileDescriptorsLen() if err != nil { t.Fatal(err) } if want, have := 5, l; want != have { t.Errorf("want fds %d, have %d", want, have) } } func TestFileDescriptorsInfo(t *testing.T) { p1, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } fdinfos, err := p1.FileDescriptorsInfo() if err != nil { t.Fatal(err) } sort.Sort(fdinfos) var want = ProcFDInfos{ ProcFDInfo{FD: "0", Pos: "0", Flags: "02004000", MntID: "13", InotifyInfos: []InotifyInfo{ InotifyInfo{WD: "3", Ino: "1", Sdev: "34", Mask: "fce"}, InotifyInfo{WD: "2", Ino: "1300016", Sdev: "fd00002", Mask: "fce"}, InotifyInfo{WD: "1", Ino: "2e0001", Sdev: "fd00000", Mask: "fce"}, }}, ProcFDInfo{FD: "1", Pos: "0", Flags: "02004002", MntID: "13", InotifyInfos: nil}, ProcFDInfo{FD: "10", Pos: "0", Flags: "02004002", MntID: "9", InotifyInfos: nil}, ProcFDInfo{FD: "2", Pos: "0", Flags: "02004002", MntID: "9", InotifyInfos: nil}, ProcFDInfo{FD: "3", Pos: "0", Flags: "02004002", MntID: "9", InotifyInfos: nil}, } if !reflect.DeepEqual(want, fdinfos) { t.Errorf("want fdinfos %+v, have %+v", want, fdinfos) } } type byUintptr []uintptr func (a byUintptr) Len() int { return len(a) } func (a byUintptr) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a byUintptr) Less(i, j int) bool { return a[i] < a[j] } golang-github-prometheus-procfs-0.14.0/schedstat.go000066400000000000000000000060221461002754700223250ustar00rootroot00000000000000// 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. package procfs import ( "bufio" "errors" "os" "regexp" "strconv" ) var ( cpuLineRE = regexp.MustCompile(`cpu(\d+) (\d+) (\d+) (\d+) (\d+) (\d+) (\d+) (\d+) (\d+) (\d+)`) procLineRE = regexp.MustCompile(`(\d+) (\d+) (\d+)`) ) // Schedstat contains scheduler statistics from /proc/schedstat // // See // https://www.kernel.org/doc/Documentation/scheduler/sched-stats.txt // for a detailed description of what these numbers mean. // // Note the current kernel documentation claims some of the time units are in // jiffies when they are actually in nanoseconds since 2.6.23 with the // introduction of CFS. A fix to the documentation is pending. See // https://lore.kernel.org/patchwork/project/lkml/list/?series=403473 type Schedstat struct { CPUs []*SchedstatCPU } // SchedstatCPU contains the values from one "cpu" line. type SchedstatCPU struct { CPUNum string RunningNanoseconds uint64 WaitingNanoseconds uint64 RunTimeslices uint64 } // ProcSchedstat contains the values from `/proc//schedstat`. type ProcSchedstat struct { RunningNanoseconds uint64 WaitingNanoseconds uint64 RunTimeslices uint64 } // Schedstat reads data from `/proc/schedstat`. func (fs FS) Schedstat() (*Schedstat, error) { file, err := os.Open(fs.proc.Path("schedstat")) if err != nil { return nil, err } defer file.Close() stats := &Schedstat{} scanner := bufio.NewScanner(file) for scanner.Scan() { match := cpuLineRE.FindStringSubmatch(scanner.Text()) if match != nil { cpu := &SchedstatCPU{} cpu.CPUNum = match[1] cpu.RunningNanoseconds, err = strconv.ParseUint(match[8], 10, 64) if err != nil { continue } cpu.WaitingNanoseconds, err = strconv.ParseUint(match[9], 10, 64) if err != nil { continue } cpu.RunTimeslices, err = strconv.ParseUint(match[10], 10, 64) if err != nil { continue } stats.CPUs = append(stats.CPUs, cpu) } } return stats, nil } func parseProcSchedstat(contents string) (ProcSchedstat, error) { var ( stats ProcSchedstat err error ) match := procLineRE.FindStringSubmatch(contents) if match != nil { stats.RunningNanoseconds, err = strconv.ParseUint(match[1], 10, 64) if err != nil { return stats, err } stats.WaitingNanoseconds, err = strconv.ParseUint(match[2], 10, 64) if err != nil { return stats, err } stats.RunTimeslices, err = strconv.ParseUint(match[3], 10, 64) return stats, err } return stats, errors.New("could not parse schedstat") } golang-github-prometheus-procfs-0.14.0/schedstat_test.go000066400000000000000000000067331461002754700233750ustar00rootroot00000000000000// 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. package procfs import ( "testing" ) func TestSchedstat(t *testing.T) { stats, err := getProcFixtures(t).Schedstat() if err != nil { t.Fatal(err) } if len(stats.CPUs) != 2 { t.Errorf("expected 2 CPUs, got %v", len(stats.CPUs)) } var cpu *SchedstatCPU for _, cpu = range stats.CPUs { if cpu.CPUNum == "0" { break } } if cpu == nil || cpu.CPUNum != "0" { t.Error("could not find cpu0") } if want, have := uint64(2045936778163039), cpu.RunningNanoseconds; want != have { t.Errorf("want RunningNanoseconds %v, have %v", want, have) } if want, have := uint64(343796328169361), cpu.WaitingNanoseconds; want != have { t.Errorf("want WaitingNanoseconds %v, have %v", want, have) } if want, have := uint64(4767485306), cpu.RunTimeslices; want != have { t.Errorf("want RunTimeslices %v, have %v", want, have) } } func TestProcSchedstat(t *testing.T) { p1, err := getProcFixtures(t).Proc(26231) if err != nil { t.Fatal(err) } schedstat, err := p1.Schedstat() if err != nil { t.Fatal(err) } if want, have := uint64(411605849), schedstat.RunningNanoseconds; want != have { t.Errorf("want RunningNanoseconds %v, have %v", want, have) } if want, have := uint64(93680043), schedstat.WaitingNanoseconds; want != have { t.Errorf("want WaitingNanoseconds %v, have %v", want, have) } if want, have := uint64(79), schedstat.RunTimeslices; want != have { t.Errorf("want RunTimeslices %v, have %v", want, have) } } func TestProcSchedstatErrors(t *testing.T) { p1, err := getProcFixtures(t).Proc(26232) if err != nil { t.Fatal(err) } _, err = p1.Schedstat() if err == nil { t.Error("proc 26232 doesn't have schedstat -- should have gotten an error") } p2, err := getProcFixtures(t).Proc(26233) if err != nil { t.Fatal(err) } _, err = p2.Schedstat() if err == nil { t.Error("proc 26233 has malformed schedstat -- should have gotten an error") } } // schedstat can have a 2nd line: it should be ignored. func TestProcSchedstatMultipleLines(t *testing.T) { schedstat, err := parseProcSchedstat("123 456 789\n10 11\n") if err != nil { t.Fatal(err) } if want, have := uint64(123), schedstat.RunningNanoseconds; want != have { t.Errorf("want RunningNanoseconds %v, have %v", want, have) } if want, have := uint64(456), schedstat.WaitingNanoseconds; want != have { t.Errorf("want WaitingNanoseconds %v, have %v", want, have) } if want, have := uint64(789), schedstat.RunTimeslices; want != have { t.Errorf("want RunTimeslices %v, have %v", want, have) } } func TestProcSchedstatUnparsableInt(t *testing.T) { if _, err := parseProcSchedstat("abc 456 789\n"); err == nil { t.Error("schedstat should have been unparsable\n") } if _, err := parseProcSchedstat("123 abc 789\n"); err == nil { t.Error("schedstat should have been unparsable\n") } if _, err := parseProcSchedstat("123 456 abc\n"); err == nil { t.Error("schedstat should have been unparsable\n") } } golang-github-prometheus-procfs-0.14.0/scripts/000077500000000000000000000000001461002754700215035ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/scripts/check_build_tags.sh000077500000000000000000000003061461002754700253130ustar00rootroot00000000000000#!/usr/bin/env bash fail=0 while read -r f ; do if ! grep -q '+build linux' "$f" ; then echo "missing linux build tag: $f" fail=1 fi done < <(find sysfs -name '*.go') exit "${fail}" golang-github-prometheus-procfs-0.14.0/scripts/check_license.sh000077500000000000000000000016331461002754700246240ustar00rootroot00000000000000#!/bin/sh # # Copyright 2018 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. check_license() { local file="" for file in $(find . -type f -iname '*.go' ! -path './vendor/*'); do head -n3 "${file}" | grep -Eq "(Copyright|generated|GENERATED)" || echo " ${file}" done } licRes=$(check_license) if [ -n "${licRes}" ]; then echo "license header checking failed:" echo "${licRes}" exit 255 fi golang-github-prometheus-procfs-0.14.0/slab.go000066400000000000000000000070251461002754700212700ustar00rootroot00000000000000// Copyright 2020 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. package procfs import ( "bufio" "bytes" "fmt" "regexp" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) var ( slabSpace = regexp.MustCompile(`\s+`) slabVer = regexp.MustCompile(`slabinfo -`) slabHeader = regexp.MustCompile(`# name`) ) // Slab represents a slab pool in the kernel. type Slab struct { Name string ObjActive int64 ObjNum int64 ObjSize int64 ObjPerSlab int64 PagesPerSlab int64 // tunables Limit int64 Batch int64 SharedFactor int64 SlabActive int64 SlabNum int64 SharedAvail int64 } // SlabInfo represents info for all slabs. type SlabInfo struct { Slabs []*Slab } func shouldParseSlab(line string) bool { if slabVer.MatchString(line) { return false } if slabHeader.MatchString(line) { return false } return true } // parseV21SlabEntry is used to parse a line from /proc/slabinfo version 2.1. func parseV21SlabEntry(line string) (*Slab, error) { // First cleanup whitespace. l := slabSpace.ReplaceAllString(line, " ") s := strings.Split(l, " ") if len(s) != 16 { return nil, fmt.Errorf("%w: unable to parse: %q", ErrFileParse, line) } var err error i := &Slab{Name: s[0]} i.ObjActive, err = strconv.ParseInt(s[1], 10, 64) if err != nil { return nil, err } i.ObjNum, err = strconv.ParseInt(s[2], 10, 64) if err != nil { return nil, err } i.ObjSize, err = strconv.ParseInt(s[3], 10, 64) if err != nil { return nil, err } i.ObjPerSlab, err = strconv.ParseInt(s[4], 10, 64) if err != nil { return nil, err } i.PagesPerSlab, err = strconv.ParseInt(s[5], 10, 64) if err != nil { return nil, err } i.Limit, err = strconv.ParseInt(s[8], 10, 64) if err != nil { return nil, err } i.Batch, err = strconv.ParseInt(s[9], 10, 64) if err != nil { return nil, err } i.SharedFactor, err = strconv.ParseInt(s[10], 10, 64) if err != nil { return nil, err } i.SlabActive, err = strconv.ParseInt(s[13], 10, 64) if err != nil { return nil, err } i.SlabNum, err = strconv.ParseInt(s[14], 10, 64) if err != nil { return nil, err } i.SharedAvail, err = strconv.ParseInt(s[15], 10, 64) if err != nil { return nil, err } return i, nil } // parseSlabInfo21 is used to parse a slabinfo 2.1 file. func parseSlabInfo21(r *bytes.Reader) (SlabInfo, error) { scanner := bufio.NewScanner(r) s := SlabInfo{Slabs: []*Slab{}} for scanner.Scan() { line := scanner.Text() if !shouldParseSlab(line) { continue } slab, err := parseV21SlabEntry(line) if err != nil { return s, err } s.Slabs = append(s.Slabs, slab) } return s, nil } // SlabInfo reads data from `/proc/slabinfo`. func (fs FS) SlabInfo() (SlabInfo, error) { // TODO: Consider passing options to allow for parsing different // slabinfo versions. However, slabinfo 2.1 has been stable since // kernel 2.6.10 and later. data, err := util.ReadFileNoStat(fs.proc.Path("slabinfo")) if err != nil { return SlabInfo{}, err } return parseSlabInfo21(bytes.NewReader(data)) } golang-github-prometheus-procfs-0.14.0/slab_test.go000066400000000000000000000045021461002754700223240ustar00rootroot00000000000000// Copyright 2020 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. package procfs import ( "testing" ) func TestSlabInfo(t *testing.T) { slabs, err := getProcFixtures(t).SlabInfo() if err != nil { t.Fatal(err) } if numSlabs := len(slabs.Slabs); numSlabs != 300 { t.Errorf("expected 300 slabs, got %v", numSlabs) } if name := slabs.Slabs[0].Name; name != "pid_3" { t.Errorf("Expected slab name to be 'pid_3', got %v", name) } if objActive := slabs.Slabs[0].ObjActive; objActive != 375 { t.Errorf("Expected slab objects active to be 375, got %v", objActive) } if objNum := slabs.Slabs[0].ObjNum; objNum != 532 { t.Errorf("Expected slab objects number to be 532, got %v", objNum) } if objSize := slabs.Slabs[0].ObjSize; objSize != 576 { t.Errorf("Expected slab objects Size to be 576, got %+v", objSize) } if objPerSlab := slabs.Slabs[0].ObjPerSlab; objPerSlab != 28 { t.Errorf("Expected slab objects per slab to be 28, got %v", objPerSlab) } if pagesPerSlab := slabs.Slabs[0].PagesPerSlab; pagesPerSlab != 4 { t.Errorf("Expected pages per slab to be 4, got %v", pagesPerSlab) } if limit := slabs.Slabs[0].Limit; limit != 0 { t.Errorf("Expected limit to be 0, got %v", limit) } if batch := slabs.Slabs[0].Batch; batch != 0 { t.Errorf("Expected batch to be 0, got %v", batch) } if sharedFactor := slabs.Slabs[0].SharedFactor; sharedFactor != 0 { t.Errorf("Expected shared factor to be 0, got %v", sharedFactor) } if slabActive := slabs.Slabs[0].SlabActive; slabActive != 19 { t.Errorf("Expected slab active to be 19, got %v", slabActive) } if slabNum := slabs.Slabs[0].SlabNum; slabNum != 19 { t.Errorf("Expected slab num to be 19, got %v", slabNum) } if sharedAvail := slabs.Slabs[0].SharedAvail; sharedAvail != 0 { t.Errorf("Expected shared available to be 0, got %v", sharedAvail) } } golang-github-prometheus-procfs-0.14.0/softirqs.go000066400000000000000000000116551461002754700222250ustar00rootroot00000000000000// Copyright 2022 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. package procfs import ( "bufio" "bytes" "fmt" "io" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // Softirqs represents the softirq statistics. type Softirqs struct { Hi []uint64 Timer []uint64 NetTx []uint64 NetRx []uint64 Block []uint64 IRQPoll []uint64 Tasklet []uint64 Sched []uint64 HRTimer []uint64 RCU []uint64 } func (fs FS) Softirqs() (Softirqs, error) { fileName := fs.proc.Path("softirqs") data, err := util.ReadFileNoStat(fileName) if err != nil { return Softirqs{}, err } reader := bytes.NewReader(data) return parseSoftirqs(reader) } func parseSoftirqs(r io.Reader) (Softirqs, error) { var ( softirqs = Softirqs{} scanner = bufio.NewScanner(r) ) if !scanner.Scan() { return Softirqs{}, fmt.Errorf("%w: softirqs empty", ErrFileRead) } for scanner.Scan() { parts := strings.Fields(scanner.Text()) var err error // require at least one cpu if len(parts) < 2 { continue } switch { case parts[0] == "HI:": perCPU := parts[1:] softirqs.Hi = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.Hi[i], err = strconv.ParseUint(count, 10, 64); err != nil { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (HI%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "TIMER:": perCPU := parts[1:] softirqs.Timer = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.Timer[i], err = strconv.ParseUint(count, 10, 64); err != nil { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (TIMER%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "NET_TX:": perCPU := parts[1:] softirqs.NetTx = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.NetTx[i], err = strconv.ParseUint(count, 10, 64); err != nil { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (NET_TX%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "NET_RX:": perCPU := parts[1:] softirqs.NetRx = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.NetRx[i], err = strconv.ParseUint(count, 10, 64); err != nil { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (NET_RX%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "BLOCK:": perCPU := parts[1:] softirqs.Block = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.Block[i], err = strconv.ParseUint(count, 10, 64); err != nil { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (BLOCK%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "IRQ_POLL:": perCPU := parts[1:] softirqs.IRQPoll = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.IRQPoll[i], err = strconv.ParseUint(count, 10, 64); err != nil { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (IRQ_POLL%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "TASKLET:": perCPU := parts[1:] softirqs.Tasklet = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.Tasklet[i], err = strconv.ParseUint(count, 10, 64); err != nil { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (TASKLET%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "SCHED:": perCPU := parts[1:] softirqs.Sched = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.Sched[i], err = strconv.ParseUint(count, 10, 64); err != nil { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (SCHED%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "HRTIMER:": perCPU := parts[1:] softirqs.HRTimer = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.HRTimer[i], err = strconv.ParseUint(count, 10, 64); err != nil { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (HRTIMER%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "RCU:": perCPU := parts[1:] softirqs.RCU = make([]uint64, len(perCPU)) for i, count := range perCPU { if softirqs.RCU[i], err = strconv.ParseUint(count, 10, 64); err != nil { return Softirqs{}, fmt.Errorf("%w: couldn't parse %q (RCU%d): %w", ErrFileParse, count, i, err) } } } } if err := scanner.Err(); err != nil { return Softirqs{}, fmt.Errorf("%w: couldn't parse softirqs: %w", ErrFileParse, err) } return softirqs, scanner.Err() } golang-github-prometheus-procfs-0.14.0/softirqs_test.go000066400000000000000000000040661461002754700232620ustar00rootroot00000000000000// Copyright 2022 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. package procfs import "testing" func TestSoftirqs(t *testing.T) { s, err := getProcFixtures(t).Softirqs() if err != nil { t.Fatal(err) } // hi if want, have := uint64(3), s.Hi[0]; want != have { t.Errorf("want softirq HI count %d, have %d", want, have) } // timer if want, have := uint64(247490), s.Timer[1]; want != have { t.Errorf("want softirq TIMER count %d, have %d", want, have) } // net_tx if want, have := uint64(2419), s.NetTx[0]; want != have { t.Errorf("want softirq NET_TX count %d, have %d", want, have) } // net_rx if want, have := uint64(28694), s.NetRx[1]; want != have { t.Errorf("want softirq NET_RX count %d, have %d", want, have) } // block if want, have := uint64(262755), s.Block[1]; want != have { t.Errorf("want softirq BLOCK count %d, have %d", want, have) } // irq_poll if want, have := uint64(0), s.IRQPoll[0]; want != have { t.Errorf("want softirq IRQ_POLL count %d, have %d", want, have) } // tasklet if want, have := uint64(209), s.Tasklet[0]; want != have { t.Errorf("want softirq TASKLET count %d, have %d", want, have) } // sched if want, have := uint64(2278692), s.Sched[0]; want != have { t.Errorf("want softirq SCHED count %d, have %d", want, have) } // hrtimer if want, have := uint64(1281), s.HRTimer[0]; want != have { t.Errorf("want softirq HRTIMER count %d, have %d", want, have) } // rcu if want, have := uint64(532783), s.RCU[1]; want != have { t.Errorf("want softirq RCU count %d, have %d", want, have) } } golang-github-prometheus-procfs-0.14.0/stat.go000066400000000000000000000172631461002754700213270ustar00rootroot00000000000000// Copyright 2018 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. package procfs import ( "bufio" "bytes" "fmt" "io" "strconv" "strings" "github.com/prometheus/procfs/internal/fs" "github.com/prometheus/procfs/internal/util" ) // CPUStat shows how much time the cpu spend in various stages. type CPUStat struct { User float64 Nice float64 System float64 Idle float64 Iowait float64 IRQ float64 SoftIRQ float64 Steal float64 Guest float64 GuestNice float64 } // SoftIRQStat represent the softirq statistics as exported in the procfs stat file. // A nice introduction can be found at https://0xax.gitbooks.io/linux-insides/content/interrupts/interrupts-9.html // It is possible to get per-cpu stats by reading `/proc/softirqs`. type SoftIRQStat struct { Hi uint64 Timer uint64 NetTx uint64 NetRx uint64 Block uint64 BlockIoPoll uint64 Tasklet uint64 Sched uint64 Hrtimer uint64 Rcu uint64 } // Stat represents kernel/system statistics. type Stat struct { // Boot time in seconds since the Epoch. BootTime uint64 // Summed up cpu statistics. CPUTotal CPUStat // Per-CPU statistics. CPU map[int64]CPUStat // Number of times interrupts were handled, which contains numbered and unnumbered IRQs. IRQTotal uint64 // Number of times a numbered IRQ was triggered. IRQ []uint64 // Number of times a context switch happened. ContextSwitches uint64 // Number of times a process was created. ProcessCreated uint64 // Number of processes currently running. ProcessesRunning uint64 // Number of processes currently blocked (waiting for IO). ProcessesBlocked uint64 // Number of times a softirq was scheduled. SoftIRQTotal uint64 // Detailed softirq statistics. SoftIRQ SoftIRQStat } // Parse a cpu statistics line and returns the CPUStat struct plus the cpu id (or -1 for the overall sum). func parseCPUStat(line string) (CPUStat, int64, error) { cpuStat := CPUStat{} var cpu string count, err := fmt.Sscanf(line, "%s %f %f %f %f %f %f %f %f %f %f", &cpu, &cpuStat.User, &cpuStat.Nice, &cpuStat.System, &cpuStat.Idle, &cpuStat.Iowait, &cpuStat.IRQ, &cpuStat.SoftIRQ, &cpuStat.Steal, &cpuStat.Guest, &cpuStat.GuestNice) if err != nil && err != io.EOF { return CPUStat{}, -1, fmt.Errorf("%w: couldn't parse %q (cpu): %w", ErrFileParse, line, err) } if count == 0 { return CPUStat{}, -1, fmt.Errorf("%w: couldn't parse %q (cpu): 0 elements parsed", ErrFileParse, line) } cpuStat.User /= userHZ cpuStat.Nice /= userHZ cpuStat.System /= userHZ cpuStat.Idle /= userHZ cpuStat.Iowait /= userHZ cpuStat.IRQ /= userHZ cpuStat.SoftIRQ /= userHZ cpuStat.Steal /= userHZ cpuStat.Guest /= userHZ cpuStat.GuestNice /= userHZ if cpu == "cpu" { return cpuStat, -1, nil } cpuID, err := strconv.ParseInt(cpu[3:], 10, 64) if err != nil { return CPUStat{}, -1, fmt.Errorf("%w: couldn't parse %q (cpu/cpuid): %w", ErrFileParse, line, err) } return cpuStat, cpuID, nil } // Parse a softirq line. func parseSoftIRQStat(line string) (SoftIRQStat, uint64, error) { softIRQStat := SoftIRQStat{} var total uint64 var prefix string _, err := fmt.Sscanf(line, "%s %d %d %d %d %d %d %d %d %d %d %d", &prefix, &total, &softIRQStat.Hi, &softIRQStat.Timer, &softIRQStat.NetTx, &softIRQStat.NetRx, &softIRQStat.Block, &softIRQStat.BlockIoPoll, &softIRQStat.Tasklet, &softIRQStat.Sched, &softIRQStat.Hrtimer, &softIRQStat.Rcu) if err != nil { return SoftIRQStat{}, 0, fmt.Errorf("%w: couldn't parse %q (softirq): %w", ErrFileParse, line, err) } return softIRQStat, total, nil } // NewStat returns information about current cpu/process statistics. // See https://www.kernel.org/doc/Documentation/filesystems/proc.txt // // Deprecated: Use fs.Stat() instead. func NewStat() (Stat, error) { fs, err := NewFS(fs.DefaultProcMountPoint) if err != nil { return Stat{}, err } return fs.Stat() } // NewStat returns information about current cpu/process statistics. // See: https://www.kernel.org/doc/Documentation/filesystems/proc.txt // // Deprecated: Use fs.Stat() instead. func (fs FS) NewStat() (Stat, error) { return fs.Stat() } // Stat returns information about current cpu/process statistics. // See: https://www.kernel.org/doc/Documentation/filesystems/proc.txt func (fs FS) Stat() (Stat, error) { fileName := fs.proc.Path("stat") data, err := util.ReadFileNoStat(fileName) if err != nil { return Stat{}, err } procStat, err := parseStat(bytes.NewReader(data), fileName) if err != nil { return Stat{}, err } return procStat, nil } // parseStat parses the metrics from /proc/[pid]/stat. func parseStat(r io.Reader, fileName string) (Stat, error) { var ( scanner = bufio.NewScanner(r) stat = Stat{ CPU: make(map[int64]CPUStat), } err error ) // Increase default scanner buffer to handle very long `intr` lines. buf := make([]byte, 0, 8*1024) scanner.Buffer(buf, 1024*1024) for scanner.Scan() { line := scanner.Text() parts := strings.Fields(scanner.Text()) // require at least if len(parts) < 2 { continue } switch { case parts[0] == "btime": if stat.BootTime, err = strconv.ParseUint(parts[1], 10, 64); err != nil { return Stat{}, fmt.Errorf("%w: couldn't parse %q (btime): %w", ErrFileParse, parts[1], err) } case parts[0] == "intr": if stat.IRQTotal, err = strconv.ParseUint(parts[1], 10, 64); err != nil { return Stat{}, fmt.Errorf("%w: couldn't parse %q (intr): %w", ErrFileParse, parts[1], err) } numberedIRQs := parts[2:] stat.IRQ = make([]uint64, len(numberedIRQs)) for i, count := range numberedIRQs { if stat.IRQ[i], err = strconv.ParseUint(count, 10, 64); err != nil { return Stat{}, fmt.Errorf("%w: couldn't parse %q (intr%d): %w", ErrFileParse, count, i, err) } } case parts[0] == "ctxt": if stat.ContextSwitches, err = strconv.ParseUint(parts[1], 10, 64); err != nil { return Stat{}, fmt.Errorf("%w: couldn't parse %q (ctxt): %w", ErrFileParse, parts[1], err) } case parts[0] == "processes": if stat.ProcessCreated, err = strconv.ParseUint(parts[1], 10, 64); err != nil { return Stat{}, fmt.Errorf("%w: couldn't parse %q (processes): %w", ErrFileParse, parts[1], err) } case parts[0] == "procs_running": if stat.ProcessesRunning, err = strconv.ParseUint(parts[1], 10, 64); err != nil { return Stat{}, fmt.Errorf("%w: couldn't parse %q (procs_running): %w", ErrFileParse, parts[1], err) } case parts[0] == "procs_blocked": if stat.ProcessesBlocked, err = strconv.ParseUint(parts[1], 10, 64); err != nil { return Stat{}, fmt.Errorf("%w: couldn't parse %q (procs_blocked): %w", ErrFileParse, parts[1], err) } case parts[0] == "softirq": softIRQStats, total, err := parseSoftIRQStat(line) if err != nil { return Stat{}, err } stat.SoftIRQTotal = total stat.SoftIRQ = softIRQStats case strings.HasPrefix(parts[0], "cpu"): cpuStat, cpuID, err := parseCPUStat(line) if err != nil { return Stat{}, err } if cpuID == -1 { stat.CPUTotal = cpuStat } else { stat.CPU[cpuID] = cpuStat } } } if err := scanner.Err(); err != nil { return Stat{}, fmt.Errorf("%w: couldn't parse %q: %w", ErrFileParse, fileName, err) } return stat, nil } golang-github-prometheus-procfs-0.14.0/stat_test.go000066400000000000000000000043331461002754700223600ustar00rootroot00000000000000// Copyright 2018 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. package procfs import "testing" func TestStat(t *testing.T) { s, err := getProcFixtures(t).Stat() if err != nil { t.Fatal(err) } // cpu if want, have := float64(301854)/userHZ, s.CPUTotal.User; want != have { t.Errorf("want cpu/user %v, have %v", want, have) } if want, have := float64(31)/userHZ, s.CPU[7].SoftIRQ; want != have { t.Errorf("want cpu7/softirq %v, have %v", want, have) } // intr if want, have := uint64(73777505), s.IRQTotal; want != have { t.Errorf("want irq/total %d, have %d", want, have) } if want, have := uint64(1), s.IRQ[8]; want != have { t.Errorf("want irq8 %d, have %d", want, have) } // ctxt if want, have := uint64(38014093), s.ContextSwitches; want != have { t.Errorf("want context switches (ctxt) %d, have %d", want, have) } // btime if want, have := uint64(1418183276), s.BootTime; want != have { t.Errorf("want boot time (btime) %d, have %d", want, have) } // processes if want, have := uint64(26442), s.ProcessCreated; want != have { t.Errorf("want process created (processes) %d, have %d", want, have) } // procs_running if want, have := uint64(2), s.ProcessesRunning; want != have { t.Errorf("want processes running (procs_running) %d, have %d", want, have) } // procs_blocked if want, have := uint64(1), s.ProcessesBlocked; want != have { t.Errorf("want processes blocked (procs_blocked) %d, have %d", want, have) } // softirq if want, have := uint64(5057579), s.SoftIRQTotal; want != have { t.Errorf("want softirq total %d, have %d", want, have) } if want, have := uint64(508444), s.SoftIRQ.Rcu; want != have { t.Errorf("want softirq RCU %d, have %d", want, have) } } golang-github-prometheus-procfs-0.14.0/swaps.go000066400000000000000000000044141461002754700215030ustar00rootroot00000000000000// 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. package procfs import ( "bufio" "bytes" "fmt" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // Swap represents an entry in /proc/swaps. type Swap struct { Filename string Type string Size int Used int Priority int } // Swaps returns a slice of all configured swap devices on the system. func (fs FS) Swaps() ([]*Swap, error) { data, err := util.ReadFileNoStat(fs.proc.Path("swaps")) if err != nil { return nil, err } return parseSwaps(data) } func parseSwaps(info []byte) ([]*Swap, error) { swaps := []*Swap{} scanner := bufio.NewScanner(bytes.NewReader(info)) scanner.Scan() // ignore header line for scanner.Scan() { swapString := scanner.Text() parsedSwap, err := parseSwapString(swapString) if err != nil { return nil, err } swaps = append(swaps, parsedSwap) } err := scanner.Err() return swaps, err } func parseSwapString(swapString string) (*Swap, error) { var err error swapFields := strings.Fields(swapString) swapLength := len(swapFields) if swapLength < 5 { return nil, fmt.Errorf("%w: too few fields in swap string: %s", ErrFileParse, swapString) } swap := &Swap{ Filename: swapFields[0], Type: swapFields[1], } swap.Size, err = strconv.Atoi(swapFields[2]) if err != nil { return nil, fmt.Errorf("%w: invalid swap size: %s: %w", ErrFileParse, swapFields[2], err) } swap.Used, err = strconv.Atoi(swapFields[3]) if err != nil { return nil, fmt.Errorf("%w: invalid swap used: %s: %w", ErrFileParse, swapFields[3], err) } swap.Priority, err = strconv.Atoi(swapFields[4]) if err != nil { return nil, fmt.Errorf("%w: invalid swap priority: %s: %w", ErrFileParse, swapFields[4], err) } return swap, nil } golang-github-prometheus-procfs-0.14.0/swaps_test.go000066400000000000000000000053531461002754700225450ustar00rootroot00000000000000// 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. package procfs import ( "reflect" "testing" ) func TestSwaps(t *testing.T) { fs, err := NewFS(procTestFixtures) if err != nil { t.Fatalf("failed to open procfs: %v", err) } swaps, err := fs.Swaps() if err != nil { t.Fatalf("failed to get swaps: %v", err) } if len(swaps) != 1 { t.Fatalf("expected 1 swap entry, got %d", len(swaps)) } swap := swaps[0] if swap.Filename != "/dev/dm-2" { t.Errorf("expected swap.Filename /dev/dm-2, got %s", swap.Filename) } if swap.Type != "partition" { t.Errorf("expected swap.Type partition, got %s", swap.Type) } if swap.Size != 131068 { t.Errorf("expected swap.Size 131068, got %d", swap.Size) } if swap.Used != 176 { t.Errorf("expected swap.Used 176, got %d", swap.Used) } if swap.Priority != -2 { t.Errorf("expected swap.Priority -2, got %d", swap.Priority) } } func TestParseSwapString(t *testing.T) { tests := []struct { name string s string swap *Swap invalid bool }{ { name: "device-mapper volume", s: "/dev/dm-2 partition 131068 1024 -2", invalid: false, swap: &Swap{ Filename: "/dev/dm-2", Type: "partition", Size: 131068, Used: 1024, Priority: -2, }, }, { name: "Swap file", s: "/foo file 1048572 0 -3", invalid: false, swap: &Swap{ Filename: "/foo", Type: "file", Size: 1048572, Used: 0, Priority: -3, }, }, { name: "Invalid number", s: "/dev/sda2 partition hello world -2", invalid: true, }, { name: "Not enough fields", s: "/dev/dm-2 partition 131068 1024", invalid: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { swap, err := parseSwapString(tt.s) if tt.invalid && err == nil { t.Error("unexpected success") } if !tt.invalid && err != nil { t.Errorf("unexpected error: %v", err) } if !reflect.DeepEqual(tt.swap, swap) { t.Errorf("swap:\nwant:\n%+v\nhave:\n%+v", tt.swap, swap) } }) } } golang-github-prometheus-procfs-0.14.0/sysfs/000077500000000000000000000000001461002754700211635ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/sysfs/.gitignore000066400000000000000000000000121461002754700231440ustar00rootroot00000000000000fixtures/ golang-github-prometheus-procfs-0.14.0/sysfs/class_cooling_device.go000066400000000000000000000053571461002754700256620ustar00rootroot00000000000000// 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. //go:build linux // +build linux package sysfs import ( "path/filepath" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // ClassCoolingDeviceStats contains info from files in /sys/class/thermal/cooling_device[0-9]* // for a single device. // https://www.kernel.org/doc/Documentation/thermal/sysfs-api.txt type ClassCoolingDeviceStats struct { Name string // The name of the cooling device. Type string // Type of the cooling device(processor/fan/...) MaxState int64 // Maximum cooling state of the cooling device CurState int64 // Current cooling state of the cooling device } func (fs FS) ClassCoolingDeviceStats() ([]ClassCoolingDeviceStats, error) { cds, err := filepath.Glob(fs.sys.Path("class/thermal/cooling_device[0-9]*")) if err != nil { return []ClassCoolingDeviceStats{}, err } var coolingDeviceStats = ClassCoolingDeviceStats{} stats := make([]ClassCoolingDeviceStats, len(cds)) for i, cd := range cds { cdName := strings.TrimPrefix(filepath.Base(cd), "cooling_device") coolingDeviceStats, err = parseCoolingDeviceStats(cd) if err != nil { return []ClassCoolingDeviceStats{}, err } coolingDeviceStats.Name = cdName stats[i] = coolingDeviceStats } return stats, nil } func parseCoolingDeviceStats(cd string) (ClassCoolingDeviceStats, error) { cdType, err := util.SysReadFile(filepath.Join(cd, "type")) if err != nil { return ClassCoolingDeviceStats{}, err } cdMaxStateString, err := util.SysReadFile(filepath.Join(cd, "max_state")) if err != nil { return ClassCoolingDeviceStats{}, err } cdMaxStateInt, err := strconv.ParseInt(cdMaxStateString, 10, 64) if err != nil { return ClassCoolingDeviceStats{}, err } // cur_state can be -1, eg intel powerclamp // https://www.kernel.org/doc/Documentation/thermal/intel_powerclamp.txt cdCurStateString, err := util.SysReadFile(filepath.Join(cd, "cur_state")) if err != nil { return ClassCoolingDeviceStats{}, err } cdCurStateInt, err := strconv.ParseInt(cdCurStateString, 10, 64) if err != nil { return ClassCoolingDeviceStats{}, err } return ClassCoolingDeviceStats{ Type: cdType, MaxState: cdMaxStateInt, CurState: cdCurStateInt, }, nil } golang-github-prometheus-procfs-0.14.0/sysfs/class_cooling_device_test.go000066400000000000000000000024201461002754700267050ustar00rootroot00000000000000// 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. //go:build linux // +build linux package sysfs import ( "reflect" "testing" ) func TestClassCoolingDeviceStats(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } coolingDeviceTest, err := fs.ClassCoolingDeviceStats() if err != nil { t.Fatal(err) } classCoolingDeviceStats := []ClassCoolingDeviceStats{ { Name: "0", Type: "Processor", MaxState: 50, CurState: 0, }, { Name: "1", Type: "intel_powerclamp", MaxState: 27, CurState: -1, }, } if !reflect.DeepEqual(classCoolingDeviceStats, coolingDeviceTest) { t.Errorf("Result not correct: want %v, have %v", classCoolingDeviceStats, coolingDeviceTest) } } golang-github-prometheus-procfs-0.14.0/sysfs/class_dmi.go000066400000000000000000000076601461002754700234610ustar00rootroot00000000000000// Copyright 2021 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. //go:build linux // +build linux package sysfs import ( "fmt" "os" "path/filepath" "github.com/prometheus/procfs/internal/util" ) const dmiClassPath = "class/dmi/id" // DMIClass contains info from files in /sys/class/dmi/id. type DMIClass struct { BiosDate *string // /sys/class/dmi/id/bios_date BiosRelease *string // /sys/class/dmi/id/bios_release BiosVendor *string // /sys/class/dmi/id/bios_vendor BiosVersion *string // /sys/class/dmi/id/bios_version BoardAssetTag *string // /sys/class/dmi/id/board_asset_tag BoardName *string // /sys/class/dmi/id/board_name BoardSerial *string // /sys/class/dmi/id/board_serial BoardVendor *string // /sys/class/dmi/id/board_vendor BoardVersion *string // /sys/class/dmi/id/board_version ChassisAssetTag *string // /sys/class/dmi/id/chassis_asset_tag ChassisSerial *string // /sys/class/dmi/id/chassis_serial ChassisType *string // /sys/class/dmi/id/chassis_type ChassisVendor *string // /sys/class/dmi/id/chassis_vendor ChassisVersion *string // /sys/class/dmi/id/chassis_version ProductFamily *string // /sys/class/dmi/id/product_family ProductName *string // /sys/class/dmi/id/product_name ProductSerial *string // /sys/class/dmi/id/product_serial ProductSKU *string // /sys/class/dmi/id/product_sku ProductUUID *string // /sys/class/dmi/id/product_uuid ProductVersion *string // /sys/class/dmi/id/product_version SystemVendor *string // /sys/class/dmi/id/sys_vendor } // DMIClass returns Desktop Management Interface (DMI) information read from /sys/class/dmi. func (fs FS) DMIClass() (*DMIClass, error) { path := fs.sys.Path(dmiClassPath) files, err := os.ReadDir(path) if err != nil { return nil, fmt.Errorf("failed to read directory %q: %w", path, err) } var dmi DMIClass for _, f := range files { if !f.Type().IsRegular() { continue } name := f.Name() if name == "modalias" || name == "uevent" { continue } filename := filepath.Join(path, name) value, err := util.SysReadFile(filename) if err != nil { if os.IsPermission(err) { // Only root is allowed to read the serial and product_uuid files! continue } return nil, fmt.Errorf("failed to read file %q: %w", filename, err) } switch name { case "bios_date": dmi.BiosDate = &value case "bios_release": dmi.BiosRelease = &value case "bios_vendor": dmi.BiosVendor = &value case "bios_version": dmi.BiosVersion = &value case "board_asset_tag": dmi.BoardAssetTag = &value case "board_name": dmi.BoardName = &value case "board_serial": dmi.BoardSerial = &value case "board_vendor": dmi.BoardVendor = &value case "board_version": dmi.BoardVersion = &value case "chassis_asset_tag": dmi.ChassisAssetTag = &value case "chassis_serial": dmi.ChassisSerial = &value case "chassis_type": dmi.ChassisType = &value case "chassis_vendor": dmi.ChassisVendor = &value case "chassis_version": dmi.ChassisVersion = &value case "product_family": dmi.ProductFamily = &value case "product_name": dmi.ProductName = &value case "product_serial": dmi.ProductSerial = &value case "product_sku": dmi.ProductSKU = &value case "product_uuid": dmi.ProductUUID = &value case "product_version": dmi.ProductVersion = &value case "sys_vendor": dmi.SystemVendor = &value } } return &dmi, nil } golang-github-prometheus-procfs-0.14.0/sysfs/class_dmi_test.go000066400000000000000000000042151461002754700245110ustar00rootroot00000000000000// Copyright 2021 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. //go:build linux // +build linux package sysfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestDMIClass(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } got, err := fs.DMIClass() if err != nil { t.Fatal(err) } empty := "" biosDate := "04/12/2021" biosRelease := "2.2" biosVendor := "Dell Inc." biosVersion := "2.2.4" boardName := "07PXPY" boardSerial := ".7N62AI2.GRTCL6944100GP." boardVendor := "Dell Inc." boardVersion := "A01" chassisSerial := "7N62AI2" chassisType := "23" chassisVendor := "Dell Inc." productFamily := "PowerEdge" productName := "PowerEdge R6515" productSerial := "7N62AI2" productSKU := "SKU=NotProvided;ModelName=PowerEdge R6515" productUUID := "83340ca8-cb49-4474-8c29-d2088ca84dd9" systemVendor := "Dell Inc." want := &DMIClass{ BiosDate: &biosDate, BiosRelease: &biosRelease, BiosVendor: &biosVendor, BiosVersion: &biosVersion, BoardName: &boardName, BoardSerial: &boardSerial, BoardVendor: &boardVendor, BoardVersion: &boardVersion, ChassisAssetTag: &empty, ChassisSerial: &chassisSerial, ChassisType: &chassisType, ChassisVendor: &chassisVendor, ChassisVersion: &empty, ProductFamily: &productFamily, ProductName: &productName, ProductSerial: &productSerial, ProductSKU: &productSKU, ProductUUID: &productUUID, ProductVersion: &empty, SystemVendor: &systemVendor, } if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected DMI class (-want +got):\n%s", diff) } } golang-github-prometheus-procfs-0.14.0/sysfs/class_drm.go000066400000000000000000000015131461002754700234610ustar00rootroot00000000000000// Copyright 2021 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. //go:build linux // +build linux package sysfs import ( "path/filepath" "github.com/prometheus/procfs/internal/util" ) func readDRMCardField(card, field string) (string, error) { return util.SysReadFile(filepath.Join(card, "device", field)) } golang-github-prometheus-procfs-0.14.0/sysfs/class_drm_amdgpu.go000066400000000000000000000104411461002754700250160ustar00rootroot00000000000000// Copyright 2021 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. //go:build linux // +build linux package sysfs import ( "errors" "fmt" "path/filepath" "regexp" "syscall" "github.com/prometheus/procfs/internal/util" ) const ( // Supported device drivers. deviceDriverAMDGPU = "amdgpu" ) // ClassDRMCardAMDGPUStats contains info from files in // /sys/class/drm/card/device for a single amdgpu card. // Not all cards expose all metrics. // https://www.kernel.org/doc/html/latest/gpu/amdgpu.html type ClassDRMCardAMDGPUStats struct { Name string // The card name. GPUBusyPercent uint64 // How busy the GPU is as a percentage. MemoryGTTSize uint64 // The size of the graphics translation table (GTT) block in bytes. MemoryGTTUsed uint64 // The used amount of the graphics translation table (GTT) block in bytes. MemoryVisibleVRAMSize uint64 // The size of visible VRAM in bytes. MemoryVisibleVRAMUsed uint64 // The used amount of visible VRAM in bytes. MemoryVRAMSize uint64 // The size of VRAM in bytes. MemoryVRAMUsed uint64 // The used amount of VRAM in bytes. MemoryVRAMVendor string // The VRAM vendor name. PowerDPMForcePerformanceLevel string // The current power performance level. UniqueID string // The unique ID of the GPU that will persist from machine to machine. } // ClassDRMCardAMDGPUStats returns DRM card metrics for all amdgpu cards. func (fs FS) ClassDRMCardAMDGPUStats() ([]ClassDRMCardAMDGPUStats, error) { cards, err := filepath.Glob(fs.sys.Path("class/drm/card[0-9]")) if err != nil { return nil, err } var stats []ClassDRMCardAMDGPUStats for _, card := range cards { cardStats, err := parseClassDRMAMDGPUCard(card) if err != nil { if errors.Is(err, syscall.ENODATA) { continue } return nil, err } cardStats.Name = filepath.Base(card) stats = append(stats, cardStats) } return stats, nil } func parseClassDRMAMDGPUCard(card string) (ClassDRMCardAMDGPUStats, error) { uevent, err := util.SysReadFile(filepath.Join(card, "device/uevent")) if err != nil { return ClassDRMCardAMDGPUStats{}, err } match, err := regexp.MatchString(fmt.Sprintf("DRIVER=%s", deviceDriverAMDGPU), uevent) if err != nil { return ClassDRMCardAMDGPUStats{}, err } if !match { return ClassDRMCardAMDGPUStats{}, nil } stats := ClassDRMCardAMDGPUStats{Name: card} // Read only specific files for faster data gathering. if v, err := readDRMCardField(card, "gpu_busy_percent"); err == nil { stats.GPUBusyPercent = *util.NewValueParser(v).PUInt64() } if v, err := readDRMCardField(card, "mem_info_gtt_total"); err == nil { stats.MemoryGTTSize = *util.NewValueParser(v).PUInt64() } if v, err := readDRMCardField(card, "mem_info_gtt_used"); err == nil { stats.MemoryGTTUsed = *util.NewValueParser(v).PUInt64() } if v, err := readDRMCardField(card, "mem_info_vis_vram_total"); err == nil { stats.MemoryVisibleVRAMSize = *util.NewValueParser(v).PUInt64() } if v, err := readDRMCardField(card, "mem_info_vis_vram_used"); err == nil { stats.MemoryVisibleVRAMUsed = *util.NewValueParser(v).PUInt64() } if v, err := readDRMCardField(card, "mem_info_vram_total"); err == nil { stats.MemoryVRAMSize = *util.NewValueParser(v).PUInt64() } if v, err := readDRMCardField(card, "mem_info_vram_used"); err == nil { stats.MemoryVRAMUsed = *util.NewValueParser(v).PUInt64() } if v, err := readDRMCardField(card, "mem_info_vram_vendor"); err == nil { stats.MemoryVRAMVendor = v } if v, err := readDRMCardField(card, "power_dpm_force_performance_level"); err == nil { stats.PowerDPMForcePerformanceLevel = v } if v, err := readDRMCardField(card, "unique_id"); err == nil { stats.UniqueID = v } return stats, nil } golang-github-prometheus-procfs-0.14.0/sysfs/class_drm_amdgpu_test.go000066400000000000000000000030471461002754700260610ustar00rootroot00000000000000// Copyright 2021 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. //go:build linux // +build linux package sysfs import ( "reflect" "testing" ) func TestClassDRMCardAMDGPUStats(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } drmTest, err := fs.ClassDRMCardAMDGPUStats() if err != nil { t.Fatal(err) } classDRMCardStats := []ClassDRMCardAMDGPUStats{ { Name: "card0", GPUBusyPercent: 4, MemoryGTTSize: 8573157376, MemoryGTTUsed: 144560128, MemoryVisibleVRAMSize: 8573157376, MemoryVisibleVRAMUsed: 1490378752, MemoryVRAMSize: 8573157376, MemoryVRAMUsed: 1490378752, MemoryVRAMVendor: "samsung", PowerDPMForcePerformanceLevel: "manual", UniqueID: "0123456789abcdef", }, } if !reflect.DeepEqual(classDRMCardStats, drmTest) { t.Errorf("Result not correct: want %v, have %v", classDRMCardStats, drmTest) } } golang-github-prometheus-procfs-0.14.0/sysfs/class_fibrechannel.go000066400000000000000000000203101461002754700253130ustar00rootroot00000000000000// Copyright 2020 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. //go:build linux // +build linux package sysfs import ( "errors" "fmt" "os" "path/filepath" "github.com/prometheus/procfs/internal/util" ) const fibrechannelClassPath = "class/fc_host" type FibreChannelCounters struct { DumpedFrames uint64 // /sys/class/fc_host//statistics/dumped_frames ErrorFrames uint64 // /sys/class/fc_host//statistics/error_frames InvalidCRCCount uint64 // /sys/class/fc_host//statistics/invalid_crc_count RXFrames uint64 // /sys/class/fc_host//statistics/rx_frames RXWords uint64 // /sys/class/fc_host//statistics/rx_words TXFrames uint64 // /sys/class/fc_host//statistics/tx_frames TXWords uint64 // /sys/class/fc_host//statistics/tx_words SecondsSinceLastReset uint64 // /sys/class/fc_host//statistics/seconds_since_last_reset InvalidTXWordCount uint64 // /sys/class/fc_host//statistics/invalid_tx_word_count LinkFailureCount uint64 // /sys/class/fc_host//statistics/link_failure_count LossOfSyncCount uint64 // /sys/class/fc_host//statistics/loss_of_sync_count LossOfSignalCount uint64 // /sys/class/fc_host//statistics/loss_of_signal_count NosCount uint64 // /sys/class/fc_host//statistics/nos_count FCPPacketAborts uint64 // / sys/class/fc_host//statistics/fcp_packet_aborts } type FibreChannelHost struct { Name string // /sys/class/fc_host/ Speed string // /sys/class/fc_host//speed PortState string // /sys/class/fc_host//port_state PortType string // /sys/class/fc_host//port_type SymbolicName string // /sys/class/fc_host//symbolic_name NodeName string // /sys/class/fc_host//node_name PortID string // /sys/class/fc_host//port_id PortName string // /sys/class/fc_host//port_name FabricName string // /sys/class/fc_host//fabric_name DevLossTMO string // /sys/class/fc_host//dev_loss_tmo SupportedClasses string // /sys/class/fc_host//supported_classes SupportedSpeeds string // /sys/class/fc_host//supported_speeds Counters FibreChannelCounters // /sys/class/fc_host//statistics/* } type FibreChannelClass map[string]FibreChannelHost // FibreChannelClass parses everything in /sys/class/fc_host. func (fs FS) FibreChannelClass() (FibreChannelClass, error) { path := fs.sys.Path(fibrechannelClassPath) dirs, err := os.ReadDir(path) if err != nil { return nil, err } fcc := make(FibreChannelClass, len(dirs)) for _, d := range dirs { host, err := fs.parseFibreChannelHost(d.Name()) if err != nil { return nil, err } fcc[host.Name] = *host } return fcc, nil } // Parse a single FC host. func (fs FS) parseFibreChannelHost(name string) (*FibreChannelHost, error) { path := fs.sys.Path(fibrechannelClassPath, name) host := FibreChannelHost{Name: name} for _, f := range [...]string{"speed", "port_state", "port_type", "node_name", "port_id", "port_name", "fabric_name", "dev_loss_tmo", "symbolic_name", "supported_classes", "supported_speeds"} { name := filepath.Join(path, f) value, err := util.SysReadFile(name) if err != nil { // drivers can choose not to expose some attributes to sysfs. // See: https://github.com/prometheus/node_exporter/issues/2919. if os.IsNotExist(err) { continue } return nil, fmt.Errorf("failed to read file %q: %w", name, err) } switch f { case "speed": host.Speed = value case "port_state": host.PortState = value case "port_type": host.PortType = value case "node_name": if len(value) > 2 { value = value[2:] } host.NodeName = value case "port_id": if len(value) > 2 { value = value[2:] } host.PortID = value case "port_name": if len(value) > 2 { value = value[2:] } host.PortName = value case "fabric_name": if len(value) > 2 { value = value[2:] } host.FabricName = value case "dev_loss_tmo": host.DevLossTMO = value case "supported_classes": host.SupportedClasses = value case "supported_speeds": host.SupportedSpeeds = value case "symbolic_name": host.SymbolicName = value } } counters, err := parseFibreChannelStatistics(path) if err != nil { return nil, err } host.Counters = *counters return &host, nil } // parseFibreChannelStatistics parses metrics from a single FC host. func parseFibreChannelStatistics(hostPath string) (*FibreChannelCounters, error) { var counters FibreChannelCounters path := filepath.Join(hostPath, "statistics") files, err := os.ReadDir(path) if err != nil { return nil, err } for _, f := range files { if !f.Type().IsRegular() || f.Name() == "reset_statistics" { continue } name := filepath.Join(path, f.Name()) value, err := util.SysReadFile(name) if err != nil { // there are some write-only files in this directory; we can safely skip over them if os.IsNotExist(err) || err.Error() == "operation not supported" || errors.Is(err, os.ErrInvalid) { continue } return nil, fmt.Errorf("failed to read file %q: %w", name, err) } vp := util.NewValueParser(value) // Below switch was automatically generated. Don't need everything in there yet, so the unwanted bits are commented out. switch f.Name() { case "dumped_frames": counters.DumpedFrames = *vp.PUInt64() case "error_frames": counters.ErrorFrames = *vp.PUInt64() /* case "fc_no_free_exch": counters.FcNoFreeExch = *vp.PUInt64() case "fc_no_free_exch_xid": counters.FcNoFreeExchXid = *vp.PUInt64() case "fc_non_bls_resp": counters.FcNonBlsResp = *vp.PUInt64() case "fc_seq_not_found": counters.FcSeqNotFound = *vp.PUInt64() case "fc_xid_busy": counters.FcXidBusy = *vp.PUInt64() case "fc_xid_not_found": counters.FcXidNotFound = *vp.PUInt64() case "fcp_control_requests": counters.FcpControlRequests = *vp.PUInt64() case "fcp_frame_alloc_failures": counters.FcpFrameAllocFailures = *vp.PUInt64() case "fcp_input_megabytes": counters.FcpInputMegabytes = *vp.PUInt64() case "fcp_input_requests": counters.FcpInputRequests = *vp.PUInt64() case "fcp_output_megabytes": counters.FcpOutputMegabytes = *vp.PUInt64() case "fcp_output_requests": counters.FcpOutputRequests = *vp.PUInt64() */ case "fcp_packet_aborts": counters.FCPPacketAborts = *vp.PUInt64() /* case "fcp_packet_alloc_failures": counters.FcpPacketAllocFailures = *vp.PUInt64() */ case "invalid_tx_word_count": counters.InvalidTXWordCount = *vp.PUInt64() case "invalid_crc_count": counters.InvalidCRCCount = *vp.PUInt64() case "link_failure_count": counters.LinkFailureCount = *vp.PUInt64() /* case "lip_count": counters.LipCount = *vp.PUInt64() */ case "loss_of_signal_count": counters.LossOfSignalCount = *vp.PUInt64() case "loss_of_sync_count": counters.LossOfSyncCount = *vp.PUInt64() case "nos_count": counters.NosCount = *vp.PUInt64() /* case "prim_seq_protocol_err_count": counters.PrimSeqProtocolErrCount = *vp.PUInt64() */ case "rx_frames": counters.RXFrames = *vp.PUInt64() case "rx_words": counters.RXWords = *vp.PUInt64() case "seconds_since_last_reset": counters.SecondsSinceLastReset = *vp.PUInt64() case "tx_frames": counters.TXFrames = *vp.PUInt64() case "tx_words": counters.TXWords = *vp.PUInt64() } if err := vp.Err(); err != nil { return nil, err } } return &counters, nil } golang-github-prometheus-procfs-0.14.0/sysfs/class_fibrechannel_test.go000066400000000000000000000051301461002754700263550ustar00rootroot00000000000000// 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. //go:build linux // +build linux package sysfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestFibreChannelClass(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } got, err := fs.FibreChannelClass() if err != nil { t.Fatal(err) } want := FibreChannelClass{ "host0": FibreChannelHost{ Name: "host0", Speed: "16 Gbit", PortState: "Online", PortType: "Point-To-Point (direct nport connection)", PortName: "1000e0071bce95f2", SymbolicName: "Emulex SN1100E2P FV12.4.270.3 DV12.4.0.0. HN:gotest. OS:Linux", NodeName: "2000e0071bce95f2", PortID: "000002", FabricName: "0", DevLossTMO: "30", SupportedClasses: "Class 3", SupportedSpeeds: "4 Gbit, 8 Gbit, 16 Gbit", Counters: FibreChannelCounters{ DumpedFrames: ^uint64(0), ErrorFrames: 0, InvalidCRCCount: 0x2, RXFrames: 0x3, RXWords: 0x4, TXFrames: 0x5, TXWords: 0x6, SecondsSinceLastReset: 0x7, InvalidTXWordCount: 0x8, LinkFailureCount: 0x9, LossOfSyncCount: 0x10, LossOfSignalCount: 0x11, NosCount: 0x12, FCPPacketAborts: 0x13, }, }, "host1": FibreChannelHost{ Name: "host1", PortState: "Online", Counters: FibreChannelCounters{ DumpedFrames: 0, ErrorFrames: ^uint64(0), InvalidCRCCount: 0x20, RXFrames: 0x30, RXWords: 0x40, TXFrames: 0x50, TXWords: 0x60, SecondsSinceLastReset: 0x70, InvalidTXWordCount: 0x80, LinkFailureCount: 0x90, LossOfSyncCount: 0x100, LossOfSignalCount: 0x110, NosCount: 0x120, FCPPacketAborts: 0x130, }, }, } if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected FibreChannel class (-want +got):\n%s", diff) } } golang-github-prometheus-procfs-0.14.0/sysfs/class_infiniband.go000066400000000000000000000501531461002754700250040ustar00rootroot00000000000000// 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. //go:build linux // +build linux package sysfs import ( "errors" "fmt" "os" "path/filepath" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) const infinibandClassPath = "class/infiniband" // InfiniBandCounters contains counter values from files in // /sys/class/infiniband//ports//counters or // /sys/class/infiniband//ports//counters_ext // for a single port of one InfiniBand device. type InfiniBandCounters struct { LegacyPortMulticastRcvPackets *uint64 // counters_ext/port_multicast_rcv_packets LegacyPortMulticastXmitPackets *uint64 // counters_ext/port_multicast_xmit_packets LegacyPortRcvData64 *uint64 // counters_ext/port_rcv_data_64 LegacyPortRcvPackets64 *uint64 // counters_ext/port_rcv_packets_64 LegacyPortUnicastRcvPackets *uint64 // counters_ext/port_unicast_rcv_packets LegacyPortUnicastXmitPackets *uint64 // counters_ext/port_unicast_xmit_packets LegacyPortXmitData64 *uint64 // counters_ext/port_xmit_data_64 LegacyPortXmitPackets64 *uint64 // counters_ext/port_xmit_packets_64 ExcessiveBufferOverrunErrors *uint64 // counters/excessive_buffer_overrun_errors LinkDowned *uint64 // counters/link_downed LinkErrorRecovery *uint64 // counters/link_error_recovery LocalLinkIntegrityErrors *uint64 // counters/local_link_integrity_errors MulticastRcvPackets *uint64 // counters/multicast_rcv_packets MulticastXmitPackets *uint64 // counters/multicast_xmit_packets PortRcvConstraintErrors *uint64 // counters/port_rcv_constraint_errors PortRcvData *uint64 // counters/port_rcv_data PortRcvDiscards *uint64 // counters/port_rcv_discards PortRcvErrors *uint64 // counters/port_rcv_errors PortRcvPackets *uint64 // counters/port_rcv_packets PortRcvRemotePhysicalErrors *uint64 // counters/port_rcv_remote_physical_errors PortRcvSwitchRelayErrors *uint64 // counters/port_rcv_switch_relay_errors PortXmitConstraintErrors *uint64 // counters/port_xmit_constraint_errors PortXmitData *uint64 // counters/port_xmit_data PortXmitDiscards *uint64 // counters/port_xmit_discards PortXmitPackets *uint64 // counters/port_xmit_packets PortXmitWait *uint64 // counters/port_xmit_wait SymbolError *uint64 // counters/symbol_error UnicastRcvPackets *uint64 // counters/unicast_rcv_packets UnicastXmitPackets *uint64 // counters/unicast_xmit_packets VL15Dropped *uint64 // counters/VL15_dropped } // InfiniBandHwCounters contains counter value from files in // /sys/class/infiniband//ports//hw_counters // for a single port of one InfiniBand device. type InfiniBandHwCounters struct { DuplicateRequest *uint64 // hw_counters/duplicate_request ImpliedNakSeqErr *uint64 // hw_counters/implied_nak_seq_err Lifespan *uint64 // hw_counters/lifespan LocalAckTimeoutErr *uint64 // hw_counters/local_ack_timeout_err NpCnpSent *uint64 // hw_counters/np_cnp_sent NpEcnMarkedRocePackets *uint64 // hw_counters/np_ecn_marked_roce_packets OutOfBuffer *uint64 // hw_counters/out_of_buffer OutOfSequence *uint64 // hw_counters/out_of_sequence PacketSeqErr *uint64 // hw_counters/packet_seq_err ReqCqeError *uint64 // hw_counters/req_cqe_error ReqCqeFlushError *uint64 // hw_counters/req_cqe_flush_error ReqRemoteAccessErrors *uint64 // hw_counters/req_remote_access_errors ReqRemoteInvalidRequest *uint64 // hw_counters/req_remote_invalid_request RespCqeError *uint64 // hw_counters/resp_cqe_error RespCqeFlushError *uint64 // hw_counters/resp_cqe_flush_error RespLocalLengthError *uint64 // hw_counters/resp_local_length_error RespRemoteAccessErrors *uint64 // hw_counters/resp_remote_access_errors RnrNakRetryErr *uint64 // hw_counters/rnr_nak_retry_err RoceAdpRetrans *uint64 // hw_counters/roce_adp_retrans RoceAdpRetransTo *uint64 // hw_counters/roce_adp_retrans_to RoceSlowRestart *uint64 // hw_counters/roce_slow_restart RoceSlowRestartCnps *uint64 // hw_counters/roce_slow_restart_cnps RoceSlowRestartTrans *uint64 // hw_counters/roce_slow_restart_trans RpCnpHandled *uint64 // hw_counters/rp_cnp_handled RpCnpIgnored *uint64 // hw_counters/rp_cnp_ignored RxAtomicRequests *uint64 // hw_counters/rx_atomic_requests RxDctConnect *uint64 // hw_counters/rx_dct_connect RxIcrcEncapsulated *uint64 // hw_counters/rx_icrc_encapsulated RxReadRequests *uint64 // hw_counters/rx_read_requests RxWriteRequests *uint64 // hw_counters/rx_write_requests } // InfiniBandPort contains info from files in // /sys/class/infiniband//ports/ // for a single port of one InfiniBand device. type InfiniBandPort struct { Name string Port uint State string // String representation from /sys/class/infiniband//ports//state StateID uint // ID from /sys/class/infiniband//ports//state PhysState string // String representation from /sys/class/infiniband//ports//phys_state PhysStateID uint // String representation from /sys/class/infiniband//ports//phys_state Rate uint64 // in bytes/second from /sys/class/infiniband//ports//rate Counters InfiniBandCounters HwCounters InfiniBandHwCounters } // InfiniBandDevice contains info from files in /sys/class/infiniband for a // single InfiniBand device. type InfiniBandDevice struct { Name string BoardID string // /sys/class/infiniband//board_id FirmwareVersion string // /sys/class/infiniband//fw_ver HCAType string // /sys/class/infiniband//hca_type Ports map[uint]InfiniBandPort } // InfiniBandClass is a collection of every InfiniBand device in // /sys/class/infiniband. // // The map keys are the names of the InfiniBand devices. type InfiniBandClass map[string]InfiniBandDevice // InfiniBandClass returns info for all InfiniBand devices read from // /sys/class/infiniband. func (fs FS) InfiniBandClass() (InfiniBandClass, error) { path := fs.sys.Path(infinibandClassPath) dirs, err := os.ReadDir(path) if err != nil { return nil, err } ibc := make(InfiniBandClass, len(dirs)) for _, d := range dirs { device, err := fs.parseInfiniBandDevice(d.Name()) if err != nil { return nil, err } ibc[device.Name] = *device } return ibc, nil } // Parse one InfiniBand device. // Refer to https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-infiniband func (fs FS) parseInfiniBandDevice(name string) (*InfiniBandDevice, error) { path := fs.sys.Path(infinibandClassPath, name) device := InfiniBandDevice{Name: name} // fw_ver is exposed by all InfiniBand drivers since kernel version 4.10. value, err := util.SysReadFile(filepath.Join(path, "fw_ver")) if err != nil { return nil, fmt.Errorf("failed to read HCA firmware version: %w", err) } device.FirmwareVersion = value // Not all InfiniBand drivers expose all of these. for _, f := range [...]string{"board_id", "hca_type"} { name := filepath.Join(path, f) value, err := util.SysReadFile(name) if err != nil { if os.IsNotExist(err) { continue } return nil, fmt.Errorf("failed to read file %q: %w", name, err) } switch f { case "board_id": device.BoardID = value case "hca_type": device.HCAType = value } } portsPath := filepath.Join(path, "ports") ports, err := os.ReadDir(portsPath) if err != nil { return nil, fmt.Errorf("failed to list InfiniBand ports at %q: %w", portsPath, err) } device.Ports = make(map[uint]InfiniBandPort, len(ports)) for _, d := range ports { port, err := fs.parseInfiniBandPort(name, d.Name()) if err != nil { return nil, err } device.Ports[port.Port] = *port } return &device, nil } // Parse InfiniBand state. Expected format: ": ". func parseState(s string) (uint, string, error) { parts := strings.Split(s, ":") if len(parts) != 2 { return 0, "", fmt.Errorf("failed to split %s into 'ID: NAME'", s) } name := strings.TrimSpace(parts[1]) value, err := strconv.ParseUint(strings.TrimSpace(parts[0]), 10, 32) if err != nil { return 0, name, fmt.Errorf("failed to convert %s into uint", strings.TrimSpace(parts[0])) } id := uint(value) return id, name, nil } // Parse rate (example: "100 Gb/sec (4X EDR)") and return it as bytes/second. func parseRate(s string) (uint64, error) { parts := strings.SplitAfterN(s, " ", 2) if len(parts) != 2 { return 0, fmt.Errorf("failed to split %q", s) } value, err := strconv.ParseFloat(strings.TrimSpace(parts[0]), 32) if err != nil { return 0, fmt.Errorf("failed to convert %s into uint", strings.TrimSpace(parts[0])) } // Convert Gb/s into bytes/s rate := uint64(value * 125000000) return rate, nil } // parseInfiniBandPort scans predefined files in /sys/class/infiniband//ports/ // directory and gets their contents. func (fs FS) parseInfiniBandPort(name string, port string) (*InfiniBandPort, error) { portNumber, err := strconv.ParseUint(port, 10, 32) if err != nil { return nil, fmt.Errorf("failed to convert %s into uint", port) } ibp := InfiniBandPort{Name: name, Port: uint(portNumber)} portPath := fs.sys.Path(infinibandClassPath, name, "ports", port) content, err := os.ReadFile(filepath.Join(portPath, "state")) if err != nil { return nil, err } id, name, err := parseState(string(content)) if err != nil { return nil, fmt.Errorf("could not parse state file in %q: %w", portPath, err) } ibp.State = name ibp.StateID = id content, err = os.ReadFile(filepath.Join(portPath, "phys_state")) if err != nil { return nil, err } id, name, err = parseState(string(content)) if err != nil { return nil, fmt.Errorf("could not parse phys_state file in %q: %w", portPath, err) } ibp.PhysState = name ibp.PhysStateID = id content, err = os.ReadFile(filepath.Join(portPath, "rate")) if err != nil { return nil, err } ibp.Rate, err = parseRate(string(content)) if err != nil { return nil, fmt.Errorf("could not parse rate file in %q: %w", portPath, err) } // Intel irdma module does not expose /sys/class/infiniband//ports//counters if !strings.HasPrefix(ibp.Name, "irdma") { counters, err := parseInfiniBandCounters(portPath) if err != nil { return nil, err } ibp.Counters = *counters } if strings.HasPrefix(ibp.Name, "irdma") || strings.HasPrefix(ibp.Name, "mlx5_") { hwCounters, err := parseInfiniBandHwCounters(portPath) if err != nil { return nil, err } ibp.HwCounters = *hwCounters } return &ibp, nil } // parseInfiniBandCounters parses the counters exposed under // /sys/class/infiniband//ports//counters, which first appeared in kernel v2.6.12. // Prior to kernel v4.5, 64-bit counters were exposed separately under the "counters_ext" directory. func parseInfiniBandCounters(portPath string) (*InfiniBandCounters, error) { var counters InfiniBandCounters path := filepath.Join(portPath, "counters") files, err := os.ReadDir(path) if err != nil { return nil, err } for _, f := range files { if !f.Type().IsRegular() { continue } name := filepath.Join(path, f.Name()) value, err := util.SysReadFile(name) if err != nil { if os.IsNotExist(err) || os.IsPermission(err) || err.Error() == "operation not supported" || errors.Is(err, os.ErrInvalid) { continue } return nil, fmt.Errorf("failed to read file %q: %w", name, err) } // According to Mellanox, the metrics port_rcv_data, port_xmit_data, // port_rcv_data_64, and port_xmit_data_64 "are divided by 4 unconditionally" // as they represent the amount of data being transmitted and received per lane. // Mellanox cards have 4 lanes per port, so all values must be multiplied by 4 // to get the expected value. vp := util.NewValueParser(value) switch f.Name() { case "excessive_buffer_overrun_errors": counters.ExcessiveBufferOverrunErrors = vp.PUInt64() case "link_downed": counters.LinkDowned = vp.PUInt64() case "link_error_recovery": counters.LinkErrorRecovery = vp.PUInt64() case "local_link_integrity_errors": counters.LocalLinkIntegrityErrors = vp.PUInt64() case "multicast_rcv_packets": counters.MulticastRcvPackets = vp.PUInt64() case "multicast_xmit_packets": counters.MulticastXmitPackets = vp.PUInt64() case "port_rcv_constraint_errors": counters.PortRcvConstraintErrors = vp.PUInt64() case "port_rcv_data": counters.PortRcvData = vp.PUInt64() if counters.PortRcvData != nil { *counters.PortRcvData *= 4 } case "port_rcv_discards": counters.PortRcvDiscards = vp.PUInt64() case "port_rcv_errors": counters.PortRcvErrors = vp.PUInt64() case "port_rcv_packets": counters.PortRcvPackets = vp.PUInt64() case "port_rcv_remote_physical_errors": counters.PortRcvRemotePhysicalErrors = vp.PUInt64() case "port_rcv_switch_relay_errors": counters.PortRcvSwitchRelayErrors = vp.PUInt64() case "port_xmit_constraint_errors": counters.PortXmitConstraintErrors = vp.PUInt64() case "port_xmit_data": counters.PortXmitData = vp.PUInt64() if counters.PortXmitData != nil { *counters.PortXmitData *= 4 } case "port_xmit_discards": counters.PortXmitDiscards = vp.PUInt64() case "port_xmit_packets": counters.PortXmitPackets = vp.PUInt64() case "port_xmit_wait": counters.PortXmitWait = vp.PUInt64() case "symbol_error": counters.SymbolError = vp.PUInt64() case "unicast_rcv_packets": counters.UnicastRcvPackets = vp.PUInt64() case "unicast_xmit_packets": counters.UnicastXmitPackets = vp.PUInt64() case "VL15_dropped": counters.VL15Dropped = vp.PUInt64() } if err := vp.Err(); err != nil { // Ugly workaround for handling https://github.com/prometheus/node_exporter/issues/966 // when counters are `N/A (not available)`. // This was already patched and submitted, see // https://www.spinics.net/lists/linux-rdma/msg68596.html // Remove this as soon as the fix lands in the enterprise distros. if strings.Contains(value, "N/A (no PMA)") { continue } return nil, err } } // Parse pre-kernel-v4.5 64-bit counters. path = filepath.Join(portPath, "counters_ext") files, err = os.ReadDir(path) if err != nil && !os.IsNotExist(err) { return nil, err } for _, f := range files { if !f.Type().IsRegular() { continue } name := filepath.Join(path, f.Name()) value, err := util.SysReadFile(name) if err != nil { if os.IsNotExist(err) || os.IsPermission(err) || err.Error() == "operation not supported" || errors.Is(err, os.ErrInvalid) { continue } return nil, fmt.Errorf("failed to read file %q: %w", name, err) } vp := util.NewValueParser(value) switch f.Name() { case "port_multicast_rcv_packets": counters.LegacyPortMulticastRcvPackets = vp.PUInt64() case "port_multicast_xmit_packets": counters.LegacyPortMulticastXmitPackets = vp.PUInt64() case "port_rcv_data_64": counters.LegacyPortRcvData64 = vp.PUInt64() if counters.LegacyPortRcvData64 != nil { *counters.LegacyPortRcvData64 *= 4 } case "port_rcv_packets_64": counters.LegacyPortRcvPackets64 = vp.PUInt64() case "port_unicast_rcv_packets": counters.LegacyPortUnicastRcvPackets = vp.PUInt64() case "port_unicast_xmit_packets": counters.LegacyPortUnicastXmitPackets = vp.PUInt64() case "port_xmit_data_64": counters.LegacyPortXmitData64 = vp.PUInt64() if counters.LegacyPortXmitData64 != nil { *counters.LegacyPortXmitData64 *= 4 } case "port_xmit_packets_64": counters.LegacyPortXmitPackets64 = vp.PUInt64() } if err := vp.Err(); err != nil { // Ugly workaround for handling https://github.com/prometheus/node_exporter/issues/966 // when counters are `N/A (not available)`. // This was already patched and submitted, see // https://www.spinics.net/lists/linux-rdma/msg68596.html // Remove this as soon as the fix lands in the enterprise distros. if strings.Contains(value, "N/A (no PMA)") { continue } return nil, err } } return &counters, nil } // parseInfiniBandHwCounters parses the optional counters exposed under // /sys/class/infiniband//ports//hw_counters, which first appeared in kernel v4.6. func parseInfiniBandHwCounters(portPath string) (*InfiniBandHwCounters, error) { var hwCounters InfiniBandHwCounters path := filepath.Join(portPath, "hw_counters") files, err := os.ReadDir(path) if err != nil { return nil, err } for _, f := range files { if !f.Type().IsRegular() { continue } name := filepath.Join(path, f.Name()) value, err := util.SysReadFile(name) if err != nil { if os.IsNotExist(err) || os.IsPermission(err) || err.Error() == "operation not supported" || errors.Is(err, os.ErrInvalid) { continue } return nil, fmt.Errorf("failed to read file %q: %w", name, err) } vp := util.NewValueParser(value) switch f.Name() { case "duplicate_request": hwCounters.DuplicateRequest = vp.PUInt64() case "implied_nak_seq_err": hwCounters.ImpliedNakSeqErr = vp.PUInt64() case "lifespan": hwCounters.Lifespan = vp.PUInt64() case "local_ack_timeout_err": hwCounters.LocalAckTimeoutErr = vp.PUInt64() case "np_cnp_sent": hwCounters.NpCnpSent = vp.PUInt64() case "np_ecn_marked_roce_packets": hwCounters.NpEcnMarkedRocePackets = vp.PUInt64() case "out_of_buffer": hwCounters.OutOfBuffer = vp.PUInt64() case "out_of_sequence": hwCounters.OutOfSequence = vp.PUInt64() case "packet_seq_err": hwCounters.PacketSeqErr = vp.PUInt64() case "req_cqe_error": hwCounters.ReqCqeError = vp.PUInt64() case "req_cqe_flush_error": hwCounters.ReqCqeFlushError = vp.PUInt64() case "req_remote_access_errors": hwCounters.ReqRemoteAccessErrors = vp.PUInt64() case "req_remote_invalid_request": hwCounters.ReqRemoteInvalidRequest = vp.PUInt64() case "resp_cqe_error": hwCounters.RespCqeError = vp.PUInt64() case "resp_cqe_flush_error": hwCounters.RespCqeFlushError = vp.PUInt64() case "resp_local_length_error": hwCounters.RespLocalLengthError = vp.PUInt64() case "resp_remote_access_errors": hwCounters.RespRemoteAccessErrors = vp.PUInt64() case "rnr_nak_retry_err": hwCounters.RnrNakRetryErr = vp.PUInt64() case "roce_adp_retrans": hwCounters.RoceAdpRetrans = vp.PUInt64() case "roce_adp_retrans_to": hwCounters.RoceAdpRetransTo = vp.PUInt64() case "roce_slow_restart": hwCounters.RoceSlowRestart = vp.PUInt64() case "roce_slow_restart_cnps": hwCounters.RoceSlowRestartCnps = vp.PUInt64() case "roce_slow_restart_trans": hwCounters.RoceSlowRestartTrans = vp.PUInt64() case "rp_cnp_handled": hwCounters.RpCnpHandled = vp.PUInt64() case "rp_cnp_ignored": hwCounters.RpCnpIgnored = vp.PUInt64() case "rx_atomic_requests": hwCounters.RxAtomicRequests = vp.PUInt64() case "rx_dct_connect": hwCounters.RxDctConnect = vp.PUInt64() case "rx_icrc_encapsulated": hwCounters.RxIcrcEncapsulated = vp.PUInt64() case "rx_read_requests": hwCounters.RxReadRequests = vp.PUInt64() case "rx_write_requests": hwCounters.RxWriteRequests = vp.PUInt64() } if err := vp.Err(); err != nil { // Ugly workaround for handling https://github.com/prometheus/node_exporter/issues/966 // when counters are `N/A (not available)`. // This was already patched and submitted, see // https://www.spinics.net/lists/linux-rdma/msg68596.html // Remove this as soon as the fix lands in the enterprise distros. if strings.Contains(value, "N/A (no PMA)") { continue } return nil, err } } return &hwCounters, nil } golang-github-prometheus-procfs-0.14.0/sysfs/class_infiniband_test.go000066400000000000000000000336541461002754700260520ustar00rootroot00000000000000// 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. //go:build linux // +build linux package sysfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestParseSlowRate(t *testing.T) { tests := []struct { rate string want uint64 }{ { rate: "0 GB/sec", want: 0, }, { rate: "2.5 Gb/sec (1X SDR)", want: 312500000, }, { rate: "500 Gb/sec (4X HDR)", want: 62500000000, }, } for _, tt := range tests { rate, err := parseRate(tt.rate) if err != nil { t.Fatal(err) } if rate != tt.want { t.Errorf("Result for InfiniBand rate not correct: want %v, have %v", tt.want, rate) } } } func TestInfiniBandClass(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } got, err := fs.InfiniBandClass() if err != nil { t.Fatal(err) } var ( hfi1Port1ExcessiveBufferOverrunErrors uint64 hfi1Port1LinkDowned uint64 hfi1Port1LinkErrorRecovery uint64 hfi1Port1LocalLinkIntegrityErrors uint64 hfi1Port1PortRcvConstraintErrors uint64 hfi1Port1PortRcvData uint64 = 1380366808104 hfi1Port1PortRcvErrors uint64 hfi1Port1PortRcvPackets uint64 = 638036947 hfi1Port1PortRcvRemotePhysicalErrors uint64 hfi1Port1PortRcvSwitchRelayErrors uint64 hfi1Port1PortXmitConstraintErrors uint64 hfi1Port1PortXmitData uint64 = 1094233306172 hfi1Port1PortXmitDiscards uint64 hfi1Port1PortXmitPackets uint64 = 568318856 hfi1Port1PortXmitWait uint64 hfi1Port1SymbolError uint64 hfi1Port1VL15Dropped uint64 mlx4Port1ExcessiveBufferOverrunErrors uint64 mlx4Port1LinkDowned uint64 mlx4Port1LinkErrorRecovery uint64 mlx4Port1LocalLinkIntegrityErrors uint64 mlx4Port1PortRcvConstraintErrors uint64 mlx4Port1PortRcvData uint64 = 8884894436 mlx4Port1PortRcvErrors uint64 mlx4Port1PortRcvPackets uint64 = 87169372 mlx4Port1PortRcvRemotePhysicalErrors uint64 mlx4Port1PortRcvSwitchRelayErrors uint64 mlx4Port1PortXmitConstraintErrors uint64 mlx4Port1PortXmitData uint64 = 106036453180 mlx4Port1PortXmitDiscards uint64 mlx4Port1PortXmitPackets uint64 = 85734114 mlx4Port1PortXmitWait uint64 = 3599 mlx4Port1SymbolError uint64 mlx4Port1VL15Dropped uint64 mlx4Port2ExcessiveBufferOverrunErrors uint64 mlx4Port2LinkDowned uint64 mlx4Port2LinkErrorRecovery uint64 mlx4Port2LocalLinkIntegrityErrors uint64 mlx4Port2PortRcvConstraintErrors uint64 mlx4Port2PortRcvData uint64 = 9841747136 mlx4Port2PortRcvErrors uint64 mlx4Port2PortRcvPackets uint64 = 89332064 mlx4Port2PortRcvRemotePhysicalErrors uint64 mlx4Port2PortRcvSwitchRelayErrors uint64 mlx4Port2PortXmitConstraintErrors uint64 mlx4Port2PortXmitData uint64 = 106161427560 mlx4Port2PortXmitDiscards uint64 mlx4Port2PortXmitPackets uint64 = 88622850 mlx4Port2PortXmitWait uint64 = 3846 mlx4Port2SymbolError uint64 mlx4Port2VL15Dropped uint64 mlx5Port1ExcessiveBufferOverrunErrors uint64 mlx5Port1LinkDowned uint64 mlx5Port1LinkErrorRecovery uint64 mlx5Port1LocalLinkIntegrityErrors uint64 mlx5Port1MulticastRcvPackets uint64 mlx5Port1MulticastXmitPackets uint64 mlx5Port1PortRcvConstraintErrors uint64 mlx5Port1PortRcvData uint64 = 72505381512 mlx5Port1PortRcvErrors uint64 mlx5Port1PortRcvPackets uint64 = 541889824 mlx5Port1PortRcvRemotePhysicalErrors uint64 mlx5Port1PortRcvSwitchRelayErrors uint64 mlx5Port1PortXmitConstraintErrors uint64 mlx5Port1PortXmitData uint64 = 11523046035392 mlx5Port1PortXmitDiscards uint64 mlx5Port1PortXmitPackets uint64 = 10907922116 mlx5Port1PortXmitWait uint64 mlx5Port1SymbolError uint64 mlx5Port1UnicastRcvPackets uint64 = 541889824 mlx5Port1UnicastXmitPackets uint64 = 10907922116 mlx5Port1VL15Dropped uint64 mlx5Port1DuplicateRequest uint64 = 41 mlx5Port1ImpliedNakSeqErr uint64 mlx5Port1Lifespan uint64 = 10 mlx5Port1LocalAckTimeoutErr uint64 = 131 mlx5Port1OutOfBuffer uint64 mlx5Port1OutOfSequence uint64 = 1 mlx5Port1PacketSeqErr uint64 = 1 mlx5Port1ReqCqeError uint64 = 3481 mlx5Port1ReqCqeFlushError uint64 = 80 mlx5Port1ReqRemoteAccessErrors uint64 mlx5Port1ReqRemoteInvalidRequest uint64 mlx5Port1RespCqeError uint64 = 8109 mlx5Port1RespCqeFlushError uint64 = 4708 mlx5Port1RespLocalLengthError uint64 mlx5Port1RespRemoteAccessErrors uint64 mlx5Port1RnrNakRetryErr uint64 mlx5Port1RoceAdpRetrans uint64 = 99 mlx5Port1RoceAdpRetransTo uint64 = 4 mlx5Port1RoceSlowRestart uint64 mlx5Port1RoceSlowRestartCnps uint64 = 131 mlx5Port1RoceSlowRestartTrans uint64 mlx5Port1RxAtomicRequests uint64 mlx5Port1RxDctConnect uint64 mlx5Port1RxReadRequests uint64 = 175528982 mlx5Port1RxWriteRequests uint64 = 742114 ) want := InfiniBandClass{ "hfi1_0": InfiniBandDevice{ Name: "hfi1_0", BoardID: "HPE 100Gb 1-port OP101 QSFP28 x16 PCIe Gen3 with Intel Omni-Path Adapter", FirmwareVersion: "1.27.0", HCAType: "", Ports: map[uint]InfiniBandPort{ 1: { Name: "hfi1_0", Port: 1, State: "ACTIVE", StateID: 4, PhysState: "LinkUp", PhysStateID: 5, Rate: 12500000000, Counters: InfiniBandCounters{ ExcessiveBufferOverrunErrors: &hfi1Port1ExcessiveBufferOverrunErrors, LinkDowned: &hfi1Port1LinkDowned, LinkErrorRecovery: &hfi1Port1LinkErrorRecovery, LocalLinkIntegrityErrors: &hfi1Port1LocalLinkIntegrityErrors, PortRcvConstraintErrors: &hfi1Port1PortRcvConstraintErrors, PortRcvData: &hfi1Port1PortRcvData, PortRcvErrors: &hfi1Port1PortRcvErrors, PortRcvPackets: &hfi1Port1PortRcvPackets, PortRcvRemotePhysicalErrors: &hfi1Port1PortRcvRemotePhysicalErrors, PortRcvSwitchRelayErrors: &hfi1Port1PortRcvSwitchRelayErrors, PortXmitConstraintErrors: &hfi1Port1PortXmitConstraintErrors, PortXmitData: &hfi1Port1PortXmitData, PortXmitDiscards: &hfi1Port1PortXmitDiscards, PortXmitPackets: &hfi1Port1PortXmitPackets, PortXmitWait: &hfi1Port1PortXmitWait, SymbolError: &hfi1Port1SymbolError, VL15Dropped: &hfi1Port1VL15Dropped, }, }, }, }, "mlx4_0": InfiniBandDevice{ Name: "mlx4_0", BoardID: "SM_1141000001000", FirmwareVersion: "2.31.5050", HCAType: "MT4099", Ports: map[uint]InfiniBandPort{ 1: { Name: "mlx4_0", Port: 1, State: "ACTIVE", StateID: 4, PhysState: "LinkUp", PhysStateID: 5, Rate: 5000000000, Counters: InfiniBandCounters{ ExcessiveBufferOverrunErrors: &mlx4Port1ExcessiveBufferOverrunErrors, LinkDowned: &mlx4Port1LinkDowned, LinkErrorRecovery: &mlx4Port1LinkErrorRecovery, LocalLinkIntegrityErrors: &mlx4Port1LocalLinkIntegrityErrors, PortRcvConstraintErrors: &mlx4Port1PortRcvConstraintErrors, PortRcvData: &mlx4Port1PortRcvData, PortRcvErrors: &mlx4Port1PortRcvErrors, PortRcvPackets: &mlx4Port1PortRcvPackets, PortRcvRemotePhysicalErrors: &mlx4Port1PortRcvRemotePhysicalErrors, PortRcvSwitchRelayErrors: &mlx4Port1PortRcvSwitchRelayErrors, PortXmitConstraintErrors: &mlx4Port1PortXmitConstraintErrors, PortXmitData: &mlx4Port1PortXmitData, PortXmitDiscards: &mlx4Port1PortXmitDiscards, PortXmitPackets: &mlx4Port1PortXmitPackets, PortXmitWait: &mlx4Port1PortXmitWait, SymbolError: &mlx4Port1SymbolError, VL15Dropped: &mlx4Port1VL15Dropped, }, }, 2: { Name: "mlx4_0", Port: 2, State: "ACTIVE", StateID: 4, PhysState: "LinkUp", PhysStateID: 5, Rate: 5000000000, Counters: InfiniBandCounters{ ExcessiveBufferOverrunErrors: &mlx4Port2ExcessiveBufferOverrunErrors, LinkDowned: &mlx4Port2LinkDowned, LinkErrorRecovery: &mlx4Port2LinkErrorRecovery, LocalLinkIntegrityErrors: &mlx4Port2LocalLinkIntegrityErrors, PortRcvConstraintErrors: &mlx4Port2PortRcvConstraintErrors, PortRcvData: &mlx4Port2PortRcvData, PortRcvErrors: &mlx4Port2PortRcvErrors, PortRcvPackets: &mlx4Port2PortRcvPackets, PortRcvRemotePhysicalErrors: &mlx4Port2PortRcvRemotePhysicalErrors, PortRcvSwitchRelayErrors: &mlx4Port2PortRcvSwitchRelayErrors, PortXmitConstraintErrors: &mlx4Port2PortXmitConstraintErrors, PortXmitData: &mlx4Port2PortXmitData, PortXmitDiscards: &mlx4Port2PortXmitDiscards, PortXmitPackets: &mlx4Port2PortXmitPackets, PortXmitWait: &mlx4Port2PortXmitWait, SymbolError: &mlx4Port2SymbolError, VL15Dropped: &mlx4Port2VL15Dropped, }, }, }, }, "mlx5_0": InfiniBandDevice{ Name: "mlx5_0", BoardID: "SM_2001000001034", FirmwareVersion: "14.28.2006", HCAType: "MT4118", Ports: map[uint]InfiniBandPort{ 1: { Name: "mlx5_0", Port: 1, State: "ACTIVE", StateID: 4, PhysState: "ACTIVE", PhysStateID: 4, Rate: 3125000000, Counters: InfiniBandCounters{ ExcessiveBufferOverrunErrors: &mlx5Port1ExcessiveBufferOverrunErrors, LinkDowned: &mlx5Port1LinkDowned, LinkErrorRecovery: &mlx5Port1LinkErrorRecovery, LocalLinkIntegrityErrors: &mlx5Port1LocalLinkIntegrityErrors, MulticastRcvPackets: &mlx5Port1MulticastRcvPackets, MulticastXmitPackets: &mlx5Port1MulticastXmitPackets, PortRcvConstraintErrors: &mlx5Port1PortRcvConstraintErrors, PortRcvData: &mlx5Port1PortRcvData, PortRcvErrors: &mlx5Port1PortRcvErrors, PortRcvPackets: &mlx5Port1PortRcvPackets, PortRcvRemotePhysicalErrors: &mlx5Port1PortRcvRemotePhysicalErrors, PortRcvSwitchRelayErrors: &mlx5Port1PortRcvSwitchRelayErrors, PortXmitConstraintErrors: &mlx5Port1PortXmitConstraintErrors, PortXmitData: &mlx5Port1PortXmitData, PortXmitDiscards: &mlx5Port1PortXmitDiscards, PortXmitPackets: &mlx5Port1PortXmitPackets, PortXmitWait: &mlx5Port1PortXmitWait, SymbolError: &mlx5Port1SymbolError, UnicastRcvPackets: &mlx5Port1UnicastRcvPackets, UnicastXmitPackets: &mlx5Port1UnicastXmitPackets, VL15Dropped: &mlx5Port1VL15Dropped, }, HwCounters: InfiniBandHwCounters{ DuplicateRequest: &mlx5Port1DuplicateRequest, ImpliedNakSeqErr: &mlx5Port1ImpliedNakSeqErr, Lifespan: &mlx5Port1Lifespan, LocalAckTimeoutErr: &mlx5Port1LocalAckTimeoutErr, OutOfBuffer: &mlx5Port1OutOfBuffer, OutOfSequence: &mlx5Port1OutOfSequence, PacketSeqErr: &mlx5Port1PacketSeqErr, ReqCqeError: &mlx5Port1ReqCqeError, ReqCqeFlushError: &mlx5Port1ReqCqeFlushError, ReqRemoteAccessErrors: &mlx5Port1ReqRemoteAccessErrors, ReqRemoteInvalidRequest: &mlx5Port1ReqRemoteInvalidRequest, RespCqeError: &mlx5Port1RespCqeError, RespCqeFlushError: &mlx5Port1RespCqeFlushError, RespLocalLengthError: &mlx5Port1RespLocalLengthError, RespRemoteAccessErrors: &mlx5Port1RespRemoteAccessErrors, RnrNakRetryErr: &mlx5Port1RnrNakRetryErr, RoceAdpRetrans: &mlx5Port1RoceAdpRetrans, RoceAdpRetransTo: &mlx5Port1RoceAdpRetransTo, RoceSlowRestart: &mlx5Port1RoceSlowRestart, RoceSlowRestartCnps: &mlx5Port1RoceSlowRestartCnps, RoceSlowRestartTrans: &mlx5Port1RoceSlowRestartTrans, RxAtomicRequests: &mlx5Port1RxAtomicRequests, RxDctConnect: &mlx5Port1RxDctConnect, RxReadRequests: &mlx5Port1RxReadRequests, RxWriteRequests: &mlx5Port1RxWriteRequests, }, }, }, }, } if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected InfiniBand class (-want +got):\n%s", diff) } } golang-github-prometheus-procfs-0.14.0/sysfs/class_nvme.go000066400000000000000000000045621461002754700236530ustar00rootroot00000000000000// Copyright 2021 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. //go:build linux // +build linux package sysfs import ( "fmt" "os" "path/filepath" "github.com/prometheus/procfs/internal/util" ) const nvmeClassPath = "class/nvme" // NVMeDevice contains info from files in /sys/class/nvme for a single NVMe device. type NVMeDevice struct { Name string Serial string // /sys/class/nvme//serial Model string // /sys/class/nvme//model State string // /sys/class/nvme//state FirmwareRevision string // /sys/class/nvme//firmware_rev } // NVMeClass is a collection of every NVMe device in /sys/class/nvme. // // The map keys are the names of the NVMe devices. type NVMeClass map[string]NVMeDevice // NVMeClass returns info for all NVMe devices read from /sys/class/nvme. func (fs FS) NVMeClass() (NVMeClass, error) { path := fs.sys.Path(nvmeClassPath) dirs, err := os.ReadDir(path) if err != nil { return nil, fmt.Errorf("failed to list NVMe devices at %q: %w", path, err) } nc := make(NVMeClass, len(dirs)) for _, d := range dirs { device, err := fs.parseNVMeDevice(d.Name()) if err != nil { return nil, err } nc[device.Name] = *device } return nc, nil } // Parse one NVMe device. func (fs FS) parseNVMeDevice(name string) (*NVMeDevice, error) { path := fs.sys.Path(nvmeClassPath, name) device := NVMeDevice{Name: name} for _, f := range [...]string{"firmware_rev", "model", "serial", "state"} { name := filepath.Join(path, f) value, err := util.SysReadFile(name) if err != nil { return nil, fmt.Errorf("failed to read file %q: %w", name, err) } switch f { case "firmware_rev": device.FirmwareRevision = value case "model": device.Model = value case "serial": device.Serial = value case "state": device.State = value } } return &device, nil } golang-github-prometheus-procfs-0.14.0/sysfs/class_nvme_test.go000066400000000000000000000022751461002754700247110ustar00rootroot00000000000000// Copyright 2021 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. //go:build linux // +build linux package sysfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestNVMeClass(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } got, err := fs.NVMeClass() if err != nil { t.Fatal(err) } want := NVMeClass{ "nvme0": NVMeDevice{ Name: "nvme0", FirmwareRevision: "1B2QEXP7", Model: "Samsung SSD 970 PRO 512GB", Serial: "S680HF8N190894I", State: "live", }, } if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected NVMe class (-want +got):\n%s", diff) } } golang-github-prometheus-procfs-0.14.0/sysfs/class_power_supply.go000066400000000000000000000263141461002754700254550ustar00rootroot00000000000000// Copyright 2018 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. //go:build linux // +build linux package sysfs import ( "errors" "fmt" "os" "path/filepath" "github.com/prometheus/procfs/internal/util" ) // PowerSupply contains info from files in /sys/class/power_supply for a // single power supply. type PowerSupply struct { Name string // Power Supply Name Authentic *int64 // /sys/class/power_supply//authentic Calibrate *int64 // /sys/class/power_supply//calibrate Capacity *int64 // /sys/class/power_supply//capacity CapacityAlertMax *int64 // /sys/class/power_supply//capacity_alert_max CapacityAlertMin *int64 // /sys/class/power_supply//capacity_alert_min CapacityLevel string // /sys/class/power_supply//capacity_level ChargeAvg *int64 // /sys/class/power_supply//charge_avg ChargeControlLimit *int64 // /sys/class/power_supply//charge_control_limit ChargeControlLimitMax *int64 // /sys/class/power_supply//charge_control_limit_max ChargeCounter *int64 // /sys/class/power_supply//charge_counter ChargeEmpty *int64 // /sys/class/power_supply//charge_empty ChargeEmptyDesign *int64 // /sys/class/power_supply//charge_empty_design ChargeFull *int64 // /sys/class/power_supply//charge_full ChargeFullDesign *int64 // /sys/class/power_supply//charge_full_design ChargeNow *int64 // /sys/class/power_supply//charge_now ChargeTermCurrent *int64 // /sys/class/power_supply//charge_term_current ChargeType string // /sys/class/power_supply//charge_type ConstantChargeCurrent *int64 // /sys/class/power_supply//constant_charge_current ConstantChargeCurrentMax *int64 // /sys/class/power_supply//constant_charge_current_max ConstantChargeVoltage *int64 // /sys/class/power_supply//constant_charge_voltage ConstantChargeVoltageMax *int64 // /sys/class/power_supply//constant_charge_voltage_max CurrentAvg *int64 // /sys/class/power_supply//current_avg CurrentBoot *int64 // /sys/class/power_supply//current_boot CurrentMax *int64 // /sys/class/power_supply//current_max CurrentNow *int64 // /sys/class/power_supply//current_now CycleCount *int64 // /sys/class/power_supply//cycle_count EnergyAvg *int64 // /sys/class/power_supply//energy_avg EnergyEmpty *int64 // /sys/class/power_supply//energy_empty EnergyEmptyDesign *int64 // /sys/class/power_supply//energy_empty_design EnergyFull *int64 // /sys/class/power_supply//energy_full EnergyFullDesign *int64 // /sys/class/power_supply//energy_full_design EnergyNow *int64 // /sys/class/power_supply//energy_now Health string // /sys/class/power_supply//health InputCurrentLimit *int64 // /sys/class/power_supply//input_current_limit Manufacturer string // /sys/class/power_supply//manufacturer ModelName string // /sys/class/power_supply//model_name Online *int64 // /sys/class/power_supply//online PowerAvg *int64 // /sys/class/power_supply//power_avg PowerNow *int64 // /sys/class/power_supply//power_now PrechargeCurrent *int64 // /sys/class/power_supply//precharge_current Present *int64 // /sys/class/power_supply//present Scope string // /sys/class/power_supply//scope SerialNumber string // /sys/class/power_supply//serial_number Status string // /sys/class/power_supply//status Technology string // /sys/class/power_supply//technology Temp *int64 // /sys/class/power_supply//temp TempAlertMax *int64 // /sys/class/power_supply//temp_alert_max TempAlertMin *int64 // /sys/class/power_supply//temp_alert_min TempAmbient *int64 // /sys/class/power_supply//temp_ambient TempAmbientMax *int64 // /sys/class/power_supply//temp_ambient_max TempAmbientMin *int64 // /sys/class/power_supply//temp_ambient_min TempMax *int64 // /sys/class/power_supply//temp_max TempMin *int64 // /sys/class/power_supply//temp_min TimeToEmptyAvg *int64 // /sys/class/power_supply//time_to_empty_avg TimeToEmptyNow *int64 // /sys/class/power_supply//time_to_empty_now TimeToFullAvg *int64 // /sys/class/power_supply//time_to_full_avg TimeToFullNow *int64 // /sys/class/power_supply//time_to_full_now Type string // /sys/class/power_supply//type UsbType string // /sys/class/power_supply//usb_type VoltageAvg *int64 // /sys/class/power_supply//voltage_avg VoltageBoot *int64 // /sys/class/power_supply//voltage_boot VoltageMax *int64 // /sys/class/power_supply//voltage_max VoltageMaxDesign *int64 // /sys/class/power_supply//voltage_max_design VoltageMin *int64 // /sys/class/power_supply//voltage_min VoltageMinDesign *int64 // /sys/class/power_supply//voltage_min_design VoltageNow *int64 // /sys/class/power_supply//voltage_now VoltageOCV *int64 // /sys/class/power_supply//voltage_ocv } // PowerSupplyClass is a collection of every power supply in // /sys/class/power_supply. // // The map keys are the names of the power supplies. type PowerSupplyClass map[string]PowerSupply // PowerSupplyClass returns info for all power supplies read from // /sys/class/power_supply. func (fs FS) PowerSupplyClass() (PowerSupplyClass, error) { path := fs.sys.Path("class/power_supply") dirs, err := os.ReadDir(path) if err != nil { return nil, err } psc := make(PowerSupplyClass, len(dirs)) for _, d := range dirs { ps, err := parsePowerSupply(filepath.Join(path, d.Name())) if err != nil { return nil, err } ps.Name = d.Name() psc[d.Name()] = *ps } return psc, nil } func parsePowerSupply(path string) (*PowerSupply, error) { files, err := os.ReadDir(path) if err != nil { return nil, err } var ps PowerSupply for _, f := range files { if !f.Type().IsRegular() { continue } name := filepath.Join(path, f.Name()) value, err := util.SysReadFile(name) if err != nil { if os.IsNotExist(err) || err.Error() == "operation not supported" || errors.Is(err, os.ErrInvalid) { continue } return nil, fmt.Errorf("failed to read file %q: %w", name, err) } vp := util.NewValueParser(value) switch f.Name() { case "authentic": ps.Authentic = vp.PInt64() case "calibrate": ps.Calibrate = vp.PInt64() case "capacity": ps.Capacity = vp.PInt64() case "capacity_alert_max": ps.CapacityAlertMax = vp.PInt64() case "capacity_alert_min": ps.CapacityAlertMin = vp.PInt64() case "capacity_level": ps.CapacityLevel = value case "charge_avg": ps.ChargeAvg = vp.PInt64() case "charge_control_limit": ps.ChargeControlLimit = vp.PInt64() case "charge_control_limit_max": ps.ChargeControlLimitMax = vp.PInt64() case "charge_counter": ps.ChargeCounter = vp.PInt64() case "charge_empty": ps.ChargeEmpty = vp.PInt64() case "charge_empty_design": ps.ChargeEmptyDesign = vp.PInt64() case "charge_full": ps.ChargeFull = vp.PInt64() case "charge_full_design": ps.ChargeFullDesign = vp.PInt64() case "charge_now": ps.ChargeNow = vp.PInt64() case "charge_term_current": ps.ChargeTermCurrent = vp.PInt64() case "charge_type": ps.ChargeType = value case "constant_charge_current": ps.ConstantChargeCurrent = vp.PInt64() case "constant_charge_current_max": ps.ConstantChargeCurrentMax = vp.PInt64() case "constant_charge_voltage": ps.ConstantChargeVoltage = vp.PInt64() case "constant_charge_voltage_max": ps.ConstantChargeVoltageMax = vp.PInt64() case "current_avg": ps.CurrentAvg = vp.PInt64() case "current_boot": ps.CurrentBoot = vp.PInt64() case "current_max": ps.CurrentMax = vp.PInt64() case "current_now": ps.CurrentNow = vp.PInt64() case "cycle_count": ps.CycleCount = vp.PInt64() case "energy_avg": ps.EnergyAvg = vp.PInt64() case "energy_empty": ps.EnergyEmpty = vp.PInt64() case "energy_empty_design": ps.EnergyEmptyDesign = vp.PInt64() case "energy_full": ps.EnergyFull = vp.PInt64() case "energy_full_design": ps.EnergyFullDesign = vp.PInt64() case "energy_now": ps.EnergyNow = vp.PInt64() case "health": ps.Health = value case "input_current_limit": ps.InputCurrentLimit = vp.PInt64() case "manufacturer": ps.Manufacturer = value case "model_name": ps.ModelName = value case "online": ps.Online = vp.PInt64() case "power_avg": ps.PowerAvg = vp.PInt64() case "power_now": ps.PowerNow = vp.PInt64() case "precharge_current": ps.PrechargeCurrent = vp.PInt64() case "present": ps.Present = vp.PInt64() case "scope": ps.Scope = value case "serial_number": ps.SerialNumber = value case "status": ps.Status = value case "technology": ps.Technology = value case "temp": ps.Temp = vp.PInt64() case "temp_alert_max": ps.TempAlertMax = vp.PInt64() case "temp_alert_min": ps.TempAlertMin = vp.PInt64() case "temp_ambient": ps.TempAmbient = vp.PInt64() case "temp_ambient_max": ps.TempAmbientMax = vp.PInt64() case "temp_ambient_min": ps.TempAmbientMin = vp.PInt64() case "temp_max": ps.TempMax = vp.PInt64() case "temp_min": ps.TempMin = vp.PInt64() case "time_to_empty_avg": ps.TimeToEmptyAvg = vp.PInt64() case "time_to_empty_now": ps.TimeToEmptyNow = vp.PInt64() case "time_to_full_avg": ps.TimeToFullAvg = vp.PInt64() case "time_to_full_now": ps.TimeToFullNow = vp.PInt64() case "type": ps.Type = value case "usb_type": ps.UsbType = value case "voltage_avg": ps.VoltageAvg = vp.PInt64() case "voltage_boot": ps.VoltageBoot = vp.PInt64() case "voltage_max": ps.VoltageMax = vp.PInt64() case "voltage_max_design": ps.VoltageMaxDesign = vp.PInt64() case "voltage_min": ps.VoltageMin = vp.PInt64() case "voltage_min_design": ps.VoltageMinDesign = vp.PInt64() case "voltage_now": ps.VoltageNow = vp.PInt64() case "voltage_ocv": ps.VoltageOCV = vp.PInt64() } if err := vp.Err(); err != nil { return nil, err } } return &ps, nil } golang-github-prometheus-procfs-0.14.0/sysfs/class_power_supply_test.go000066400000000000000000000041731461002754700265130ustar00rootroot00000000000000// Copyright 2018 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. //go:build linux // +build linux package sysfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestPowerSupplyClass(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatalf("failed to open filesystem: %v", err) } got, err := fs.PowerSupplyClass() if err != nil { t.Fatalf("failed to parse power supply class: %v", err) } var ( acOnline int64 bat0Capacity int64 = 98 bat0CycleCount int64 bat0EnergyFull int64 = 50060000 bat0EnergyFullDesign int64 = 47520000 bat0EnergyNow int64 = 49450000 bat0PowerNow int64 = 4830000 bat0Present int64 = 1 bat0VoltageMinDesign int64 = 10800000 bat0VoltageNow int64 = 12229000 ) want := PowerSupplyClass{ "AC": { Name: "AC", Type: "Mains", Online: &acOnline, }, "BAT0": { Name: "BAT0", Capacity: &bat0Capacity, CapacityLevel: "Normal", CycleCount: &bat0CycleCount, EnergyFull: &bat0EnergyFull, EnergyFullDesign: &bat0EnergyFullDesign, EnergyNow: &bat0EnergyNow, Manufacturer: "LGC", ModelName: "LNV-45N1", PowerNow: &bat0PowerNow, Present: &bat0Present, SerialNumber: "38109", Status: "Discharging", Technology: "Li-ion", Type: "Battery", VoltageMinDesign: &bat0VoltageMinDesign, VoltageNow: &bat0VoltageNow, }, } if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected power supply class (-want +got):\n%s", diff) } } golang-github-prometheus-procfs-0.14.0/sysfs/class_powercap.go000066400000000000000000000071241461002754700245230ustar00rootroot00000000000000// 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. //go:build linux // +build linux package sysfs import ( "fmt" "os" "path/filepath" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) // RaplZone stores the information for one RAPL power zone. type RaplZone struct { Name string // name of RAPL zone from file "name" Index int // index (different value for duplicate names) Path string // filesystem path of RaplZone MaxMicrojoules uint64 // max RAPL microjoule value } // GetRaplZones returns a slice of RaplZones. When RAPL files are not present, // returns nil with error. // - https://www.kernel.org/doc/Documentation/power/powercap/powercap.txt func GetRaplZones(fs FS) ([]RaplZone, error) { raplDir := fs.sys.Path("class/powercap") files, err := os.ReadDir(raplDir) if err != nil { return nil, fmt.Errorf("unable to read class/powercap: %w", err) } var zones []RaplZone // Count name usages to avoid duplicates (label them with an index). countNameUsages := make(map[string]int) // Loop through directory files searching for file "name" from subdirs. for _, f := range files { nameFile := filepath.Join(raplDir, f.Name(), "/name") nameBytes, err := os.ReadFile(nameFile) if err == nil { // Add new rapl zone since name file was found. name := strings.TrimSpace(string(nameBytes)) // get a pair of index and final name index, name := getIndexAndName(countNameUsages, name) maxMicrojouleFilename := filepath.Join(raplDir, f.Name(), "/max_energy_range_uj") maxMicrojoules, err := util.ReadUintFromFile(maxMicrojouleFilename) if err != nil { return nil, err } zone := RaplZone{ Name: name, Index: index, Path: filepath.Join(raplDir, f.Name()), MaxMicrojoules: maxMicrojoules, } zones = append(zones, zone) // Store into map how many times this name has been used. There can // be e.g. multiple "dram" instances without any index postfix. The // count is then used for indexing countNameUsages[name] = index + 1 } } return zones, nil } // GetEnergyMicrojoules returns the current microjoule value from the zone energy counter // https://www.kernel.org/doc/Documentation/power/powercap/powercap.txt func (rz RaplZone) GetEnergyMicrojoules() (uint64, error) { return util.ReadUintFromFile(filepath.Join(rz.Path, "/energy_uj")) } // getIndexAndName returns a pair of (index, name) for a given name and name // counting map. Some RAPL-names have an index at the end, some have duplicates // without an index at the end. When the index is embedded in the name, it is // provided back as an integer, and stripped from the returned name. Usage // count is used when the index value is absent from the name. func getIndexAndName(countNameUsages map[string]int, name string) (int, string) { s := strings.Split(name, "-") if len(s) == 2 { index, err := strconv.Atoi(s[1]) if err == nil { return index, s[0] } } // return count as the index, since name didn't have an index at the end return countNameUsages[name], name } golang-github-prometheus-procfs-0.14.0/sysfs/class_powercap_test.go000066400000000000000000000031741461002754700255630ustar00rootroot00000000000000// 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. //go:build linux // +build linux package sysfs import ( "path/filepath" "testing" ) func TestGetRaplZones(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } zones, err := GetRaplZones(fs) if err != nil || zones == nil { t.Fatal(err) } } func TestNoRaplFiles(t *testing.T) { // use a bad (but existing) fs path fs, err := NewFS(filepath.Join(sysTestFixtures, "class")) if err != nil { t.Fatal(err) } zones, err := GetRaplZones(fs) // expect failure if err == nil || zones != nil { t.Fatal(err) } } func TestNewRaplValues(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } zones, err := GetRaplZones(fs) if err != nil || zones == nil { t.Fatal(err) } if len(zones) != 3 { t.Fatal("wrong number of RAPL values") } microjoules, err := zones[0].GetEnergyMicrojoules() if err != nil { t.Fatal("couldn't read microjoules") } if microjoules != 240422366267 { t.Fatal("wrong microjoule number") } if zones[2].Index != 10 { t.Fatal("wrong index number") } } golang-github-prometheus-procfs-0.14.0/sysfs/class_sas_device.go000066400000000000000000000130701461002754700250050ustar00rootroot00000000000000// Copyright 2022 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. //go:build linux // +build linux package sysfs import ( "os" "path/filepath" "regexp" "github.com/prometheus/procfs/internal/util" ) const ( sasDeviceClassPath = "class/sas_device" sasEndDeviceClassPath = "class/sas_end_device" sasExpanderClassPath = "class/sas_expander" ) type SASDevice struct { Name string // /sys/class/sas_device/ SASAddress string // /sys/class/sas_device//sas_address SASPhys []string // /sys/class/sas_device//device/phy-* SASPorts []string // /sys/class/sas_device//device/ports-* BlockDevices []string // /sys/class/sas_device//device/target*/*/block/* } type SASDeviceClass map[string]*SASDevice var ( sasTargetDeviceRegexp = regexp.MustCompile(`^target[0-9:]+$`) sasTargetSubDeviceRegexp = regexp.MustCompile(`[0-9]+:.*`) ) // sasDeviceClasses reads all of the SAS devices from a specific set // of /sys/class/sas*/ entries. The sas_device, sas_end_device, and // sas_expander classes are all nearly identical and can be handled by the same basic code. func (fs FS) parseSASDeviceClass(dir string) (SASDeviceClass, error) { path := fs.sys.Path(dir) dirs, err := os.ReadDir(path) if err != nil { return nil, err } sdc := make(SASDeviceClass, len(dirs)) for _, d := range dirs { device, err := fs.parseSASDevice(d.Name()) if err != nil { return nil, err } sdc[device.Name] = device } return sdc, nil } // SASDeviceClass parses devices in /sys/class/sas_device. func (fs FS) SASDeviceClass() (SASDeviceClass, error) { return fs.parseSASDeviceClass(sasDeviceClassPath) } // SASEndDeviceClass parses devices in /sys/class/sas_end_device. // This is a subset of sas_device, and excludes expanders. func (fs FS) SASEndDeviceClass() (SASDeviceClass, error) { return fs.parseSASDeviceClass(sasEndDeviceClassPath) } // SASExpanderClass parses devices in /sys/class/sas_expander. // This is a subset of sas_device, but only includes expanders. func (fs FS) SASExpanderClass() (SASDeviceClass, error) { return fs.parseSASDeviceClass(sasExpanderClassPath) } // Parse a single sas_device. This uses /sys/class/sas_device, as // it's a superset of the other two directories so there's no reason // to plumb the path through to here. func (fs FS) parseSASDevice(name string) (*SASDevice, error) { device := SASDevice{Name: name} devicepath := fs.sys.Path(filepath.Join(sasDeviceClassPath, name, "device")) dirs, err := os.ReadDir(devicepath) if err != nil { return nil, err } for _, d := range dirs { if sasPhyDeviceRegexp.MatchString(d.Name()) { device.SASPhys = append(device.SASPhys, d.Name()) } if sasPortDeviceRegexp.MatchString(d.Name()) { device.SASPorts = append(device.SASPorts, d.Name()) } } address := fs.sys.Path(sasDeviceClassPath, name, "sas_address") value, err := util.SysReadFile(address) if err != nil { return nil, err } device.SASAddress = value device.BlockDevices, err = fs.blockSASDeviceBlockDevices(name) if err != nil { return nil, err } return &device, nil } // Identify block devices that map to a specific SAS Device // This info comes from (for example) // /sys/class/sas_device/end_device-11:2/device/target11:0:0/11:0:0:0/block/sdp // // To find that, we have to look in the device directory for target$X // subdirs, then specific subdirs of $X, then read from directory // names in the 'block/' subdirectory under that. This really // shouldn't be this hard. func (fs FS) blockSASDeviceBlockDevices(name string) ([]string, error) { var devices []string devicepath := fs.sys.Path(filepath.Join(sasDeviceClassPath, name, "device")) dirs, err := os.ReadDir(devicepath) if err != nil { return nil, err } for _, d := range dirs { if sasTargetDeviceRegexp.MatchString(d.Name()) { targetdir := d.Name() subtargets, err := os.ReadDir(filepath.Join(devicepath, targetdir)) if err != nil { return nil, err } for _, targetsubdir := range subtargets { if !sasTargetSubDeviceRegexp.MatchString(targetsubdir.Name()) { // need to skip 'power', 'subsys', etc. continue } blocks, err := os.ReadDir(filepath.Join(devicepath, targetdir, targetsubdir.Name(), "block")) if err != nil { if os.IsNotExist(err) { continue } return nil, err } for _, blockdevice := range blocks { devices = append(devices, blockdevice.Name()) } } } } return devices, nil } // GetByName returns the SASDevice with the provided name. func (sdc *SASDeviceClass) GetByName(name string) *SASDevice { return (*sdc)[name] } // GetByPhy finds the SASDevice that contains the provided PHY name. func (sdc *SASDeviceClass) GetByPhy(name string) *SASDevice { for _, d := range *sdc { for _, p := range d.SASPhys { if p == name { return d } } } return nil } // GetByPort finds the SASDevice that contains the provided SAS Port name. func (sdc *SASDeviceClass) GetByPort(name string) *SASDevice { for _, d := range *sdc { for _, p := range d.SASPorts { if p == name { return d } } } return nil } golang-github-prometheus-procfs-0.14.0/sysfs/class_sas_device_test.go000066400000000000000000000122751461002754700260520ustar00rootroot00000000000000// Copyright 2022 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. //go:build linux // +build linux package sysfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestSASDeviceClass(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } got, err := fs.SASDeviceClass() if err != nil { t.Fatal(err) } want := SASDeviceClass{ "end_device-11:0:0": { Name: "end_device-11:0:0", SASAddress: "0x5000ccab02009402", BlockDevices: []string{"sdv"}, }, "end_device-11:0:1": { Name: "end_device-11:0:1", SASAddress: "0x5000cca26128b1f5", BlockDevices: []string{"sdw"}, }, "end_device-11:0:2": { Name: "end_device-11:0:2", SASAddress: "0x5000ccab02009406", BlockDevices: []string{"sdx"}, }, "end_device-11:2": { Name: "end_device-11:2", SASAddress: "0x5000cca0506b5f1d", BlockDevices: []string{"sdp"}, }, "expander-11:0": { Name: "expander-11:0", SASAddress: "0x5000ccab0200947e", SASPhys: []string{ "phy-11:0:10", "phy-11:0:11", "phy-11:0:12", "phy-11:0:13", "phy-11:0:14", "phy-11:0:15", "phy-11:0:2", "phy-11:0:4", "phy-11:0:6", "phy-11:0:7", "phy-11:0:8", "phy-11:0:9", }, SASPorts: []string{ "port-11:0:0", "port-11:0:1", "port-11:0:2", }, }, "expander-11:1": { Name: "expander-11:1", SASAddress: "0x5003048001e8967f", }, } if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASDevice class (-want +got):\n%s", diff) } } func TestSASEndDeviceClass(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } got, err := fs.SASEndDeviceClass() if err != nil { t.Fatal(err) } want := SASDeviceClass{ "end_device-11:0:0": { Name: "end_device-11:0:0", SASAddress: "0x5000ccab02009402", BlockDevices: []string{"sdv"}, }, "end_device-11:0:1": { Name: "end_device-11:0:1", SASAddress: "0x5000cca26128b1f5", BlockDevices: []string{"sdw"}, }, "end_device-11:0:2": { Name: "end_device-11:0:2", SASAddress: "0x5000ccab02009406", BlockDevices: []string{"sdx"}, }, "end_device-11:2": { Name: "end_device-11:2", SASAddress: "0x5000cca0506b5f1d", BlockDevices: []string{"sdp"}, }, } if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASDevice class (-want +got):\n%s", diff) } } func TestSASExpanderClass(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } got, err := fs.SASExpanderClass() if err != nil { t.Fatal(err) } want := SASDeviceClass{ "expander-11:0": { Name: "expander-11:0", SASAddress: "0x5000ccab0200947e", SASPhys: []string{ "phy-11:0:10", "phy-11:0:11", "phy-11:0:12", "phy-11:0:13", "phy-11:0:14", "phy-11:0:15", "phy-11:0:2", "phy-11:0:4", "phy-11:0:6", "phy-11:0:7", "phy-11:0:8", "phy-11:0:9", }, SASPorts: []string{ "port-11:0:0", "port-11:0:1", "port-11:0:2", }, }, "expander-11:1": { Name: "expander-11:1", SASAddress: "0x5003048001e8967f", }, } if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASDevice class (-want +got):\n%s", diff) } } func TestSASDeviceGetByName(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } dc, err := fs.SASDeviceClass() if err != nil { t.Fatal(err) } want := "expander-11:0" got := dc.GetByName("expander-11:0").Name if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASDevice name (-want +got):\n%s", diff) } // Doesn't exist. got2 := dc.GetByName("expander-15") if got2 != nil { t.Fatalf("unexpected GetByName response: got %v want nil", got2) } } func TestSASDeviceGetByPhy(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } dc, err := fs.SASDeviceClass() if err != nil { t.Fatal(err) } want := "expander-11:0" got := dc.GetByPhy("phy-11:0:11").Name if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASDevice class (-want +got):\n%s", diff) } // Doesn't exist. got2 := dc.GetByPhy("phy-12:0") if got2 != nil { t.Fatalf("unexpected GetByPhy response: got %v want nil", got2) } } func TestSASDeviceGetByPort(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } dc, err := fs.SASDeviceClass() if err != nil { t.Fatal(err) } want := "expander-11:0" got := dc.GetByPort("port-11:0:0").Name if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASDevice class (-want +got):\n%s", diff) } // Doesn't exist. got2 := dc.GetByPort("port-12:0") if got2 != nil { t.Fatalf("unexpected GetByPhy response: got %v want nil", got2) } } golang-github-prometheus-procfs-0.14.0/sysfs/class_sas_host.go000066400000000000000000000060751461002754700245320ustar00rootroot00000000000000// Copyright 2021 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. //go:build linux // +build linux package sysfs import ( "os" "path/filepath" "regexp" ) const sasHostClassPath = "class/sas_host" type SASHost struct { Name string // /sys/class/sas_host/ SASPhys []string // /sys/class/sas_host//device/phy-* SASPorts []string // /sys/class/sas_host//device/ports-* } type SASHostClass map[string]*SASHost var ( sasPhyDeviceRegexp = regexp.MustCompile(`^phy-[0-9:]+$`) sasPortDeviceRegexp = regexp.MustCompile(`^port-[0-9:]+$`) ) // SASHostClass parses host[0-9]+ devices in /sys/class/sas_host. // This generally only exists so that it can pull in SAS Port and SAS // PHY entries. // // The sas_host class doesn't collect any obvious statistics. Each // sas_host contains a scsi_host, which seems to collect a couple // minor stats (ioc_reset_count and reply_queue_count), but they're // not worth collecting at this time. There are more useful SAS stats // in the sas_phy class. func (fs FS) SASHostClass() (SASHostClass, error) { path := fs.sys.Path(sasHostClassPath) dirs, err := os.ReadDir(path) if err != nil { return nil, err } shc := make(SASHostClass, len(dirs)) for _, d := range dirs { host, err := fs.parseSASHost(d.Name()) if err != nil { return nil, err } shc[host.Name] = host } return shc, nil } // Parse a single sas_host. func (fs FS) parseSASHost(name string) (*SASHost, error) { //path := fs.sys.Path(sasHostClassPath, name) host := SASHost{Name: name} devicepath := fs.sys.Path(filepath.Join(sasHostClassPath, name, "device")) dirs, err := os.ReadDir(devicepath) if err != nil { return nil, err } for _, d := range dirs { if sasPhyDeviceRegexp.MatchString(d.Name()) { host.SASPhys = append(host.SASPhys, d.Name()) } if sasPortDeviceRegexp.MatchString(d.Name()) { host.SASPorts = append(host.SASPorts, d.Name()) } } return &host, nil } // GetByName returns the SASHost with the provided name. func (shc *SASHostClass) GetByName(hostName string) *SASHost { return (*shc)[hostName] } // GetByPhy finds the SASHost that contains the provided PHY name. func (shc *SASHostClass) GetByPhy(phyName string) *SASHost { for _, h := range *shc { for _, p := range h.SASPhys { if p == phyName { return h } } } return nil } // GetByPort finds the SASHost that contains the provided SAS Port name. func (shc *SASHostClass) GetByPort(portName string) *SASHost { for _, h := range *shc { for _, p := range h.SASPorts { if p == portName { return h } } } return nil } golang-github-prometheus-procfs-0.14.0/sysfs/class_sas_host_test.go000066400000000000000000000053051461002754700255640ustar00rootroot00000000000000// Copyright 2021 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. //go:build linux // +build linux package sysfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestSASHostClass(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } got, err := fs.SASHostClass() if err != nil { t.Fatal(err) } want := SASHostClass{ "host11": &SASHost{ Name: "host11", SASPhys: []string{ "phy-11:10", "phy-11:11", "phy-11:12", "phy-11:13", "phy-11:14", "phy-11:15", "phy-11:7", "phy-11:8", "phy-11:9", }, SASPorts: []string{ "port-11:0", "port-11:1", "port-11:2", }, }, } if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASHost class (-want +got):\n%s", diff) } } func TestSASHostGetByName(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } hc, err := fs.SASHostClass() if err != nil { t.Fatal(err) } want := "host11" got := hc.GetByName("host11").Name if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASHost class (-want +got):\n%s", diff) } // Doesn't exist. got2 := hc.GetByName("host12") if got2 != nil { t.Fatalf("unexpected GetByName response: got %v want nil", got2) } } func TestSASHostGetByPhy(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } hc, err := fs.SASHostClass() if err != nil { t.Fatal(err) } want := "host11" got := hc.GetByPhy("phy-11:11").Name if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASHost class (-want +got):\n%s", diff) } // Doesn't exist. got2 := hc.GetByPhy("phy-12:0") if got2 != nil { t.Fatalf("unexpected GetByPhy response: got %v want nil", got2) } } func TestSASHostGetByPort(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } hc, err := fs.SASHostClass() if err != nil { t.Fatal(err) } want := "host11" got := hc.GetByPort("port-11:0").Name if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASHost class (-want +got):\n%s", diff) } // Doesn't exist. got2 := hc.GetByPort("port-12:0") if got2 != nil { t.Fatalf("unexpected GetByPhy response: got %v want nil", got2) } } golang-github-prometheus-procfs-0.14.0/sysfs/class_sas_phy.go000066400000000000000000000120771461002754700243540ustar00rootroot00000000000000// Copyright 2021 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. //go:build linux // +build linux package sysfs import ( "fmt" "os" "path/filepath" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) const sasPhyClassPath = "class/sas_phy" type SASPhy struct { Name string // /sys/class/sas_phy/ SASAddress string // /sys/class/sas_phy//sas_address SASPort string // /sys/class/sas_phy//device/ports DeviceType string // /sys/class/sas_phy//device_type InitiatorPortProtocols []string // /sys/class/sas_phy//initiator_port_protocols InvalidDwordCount int // /sys/class/sas_phy//invalid_dword_count LossOfDwordSyncCount int // /sys/class/sas_phy//loss_of_dword_sync_count MaximumLinkrate float64 // /sys/class/sas_phy//maximum_linkrate MaximumLinkrateHW float64 // /sys/class/sas_phy//maximum_linkrate_hw MinimumLinkrate float64 // /sys/class/sas_phy//minimum_linkrate MinimumLinkrateHW float64 // /sys/class/sas_phy//minimum_linkrate_hw NegotiatedLinkrate float64 // /sys/class/sas_phy//negotiated_linkrate PhyIdentifier string // /sys/class/sas_phy//phy_identifier PhyResetProblemCount int // /sys/class/sas_phy//phy_reset_problem_count RunningDisparityErrorCount int // /sys/class/sas_phy//running_disparity_error_count TargetPortProtocols []string // /sys/class/sas_phy//target_port_protocols } type SASPhyClass map[string]*SASPhy // SASPhyClass parses entries in /sys/class/sas_phy. func (fs FS) SASPhyClass() (SASPhyClass, error) { path := fs.sys.Path(sasPhyClassPath) dirs, err := os.ReadDir(path) if err != nil { return nil, err } spc := make(SASPhyClass, len(dirs)) for _, d := range dirs { phy, err := fs.parseSASPhy(d.Name()) if err != nil { return nil, err } spc[phy.Name] = phy } return spc, nil } // Parse a single sas_phy. func (fs FS) parseSASPhy(name string) (*SASPhy, error) { phy := SASPhy{Name: name} phypath := fs.sys.Path(filepath.Join(sasPhyClassPath, name)) phydevicepath := filepath.Join(phypath, "device") link, err := os.Readlink(filepath.Join(phydevicepath, "port")) if err == nil { if sasPortDeviceRegexp.MatchString(filepath.Base(link)) { phy.SASPort = filepath.Base(link) } } files, err := os.ReadDir(phypath) if err != nil { return nil, err } for _, f := range files { name := filepath.Join(phypath, f.Name()) fileinfo, _ := os.Stat(name) if fileinfo.Mode().IsRegular() { value, err := util.SysReadFile(name) if err != nil { if os.IsPermission(err) { continue } return nil, fmt.Errorf("failed to read file %q: %w", name, err) } vp := util.NewValueParser(value) switch f.Name() { case "sas_address": phy.SASAddress = value case "device_type": phy.DeviceType = value case "initiator_port_protocols": phy.InitiatorPortProtocols = strings.Split(value, ", ") case "invalid_dword_count": phy.InvalidDwordCount = vp.Int() case "loss_of_dword_sync_count": phy.LossOfDwordSyncCount = vp.Int() case "maximum_linkrate": phy.MaximumLinkrate = parseLinkrate(value) case "maximum_linkrate_hw": phy.MaximumLinkrateHW = parseLinkrate(value) case "minimum_linkrate": phy.MinimumLinkrate = parseLinkrate(value) case "minimum_linkrate_hw": phy.MinimumLinkrateHW = parseLinkrate(value) case "negotiated_linkrate": phy.NegotiatedLinkrate = parseLinkrate(value) case "phy_identifier": phy.PhyIdentifier = value case "phy_reset_problem_count": phy.PhyResetProblemCount = vp.Int() case "running_disparity_error_count": phy.RunningDisparityErrorCount = vp.Int() case "target_port_protocols": phy.TargetPortProtocols = strings.Split(value, ", ") } if err := vp.Err(); err != nil { return nil, err } } } return &phy, nil } // parseLinkRate turns the kernel's SAS linkrate values into floats. // The kernel returns values like "12.0 Gbit". Valid speeds are // currently 1.5, 3.0, 6.0, 12.0, and up. This is a float to cover // the 1.5 Gbps case. A value of 0 is returned if the speed can't be // parsed. func parseLinkrate(value string) float64 { f := strings.Split(value, " ")[0] gb, err := strconv.ParseFloat(f, 64) if err != nil { return 0 } return gb } // GetByName returns the SASPhy with the provided name. func (spc *SASPhyClass) GetByName(name string) *SASPhy { return (*spc)[name] } golang-github-prometheus-procfs-0.14.0/sysfs/class_sas_phy_test.go000066400000000000000000000170021461002754700254040ustar00rootroot00000000000000// Copyright 2021 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. //go:build linux // +build linux package sysfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestSASPhyClass(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } got, err := fs.SASPhyClass() if err != nil { t.Fatal(err) } want := SASPhyClass{ "phy-11:0:2": { Name: "phy-11:0:2", SASAddress: "0x5000ccab0200947e", SASPort: "port-11:0:0", DeviceType: "edge expander", InitiatorPortProtocols: []string{"smp"}, InvalidDwordCount: 18, LossOfDwordSyncCount: 1, MaximumLinkrate: 12, MaximumLinkrateHW: 12, MinimumLinkrate: 1.5, MinimumLinkrateHW: 1.5, NegotiatedLinkrate: 6, PhyIdentifier: "2", RunningDisparityErrorCount: 18, TargetPortProtocols: []string{"smp"}, }, "phy-11:0:4": { Name: "phy-11:0:4", SASAddress: "0x5000ccab0200947e", SASPort: "port-11:0:1", DeviceType: "edge expander", InitiatorPortProtocols: []string{"smp"}, InvalidDwordCount: 1, MaximumLinkrate: 12, MaximumLinkrateHW: 12, MinimumLinkrate: 1.5, MinimumLinkrateHW: 1.5, NegotiatedLinkrate: 12, PhyIdentifier: "4", RunningDisparityErrorCount: 1, TargetPortProtocols: []string{"smp"}, }, "phy-11:0:6": { Name: "phy-11:0:6", SASAddress: "0x5000ccab0200947e", SASPort: "port-11:0:2", DeviceType: "edge expander", InitiatorPortProtocols: []string{"smp"}, InvalidDwordCount: 19, LossOfDwordSyncCount: 1, MaximumLinkrate: 12, MaximumLinkrateHW: 12, MinimumLinkrate: 1.5, MinimumLinkrateHW: 1.5, NegotiatedLinkrate: 6, PhyIdentifier: "6", RunningDisparityErrorCount: 20, TargetPortProtocols: []string{"smp"}, }, "phy-11:10": { Name: "phy-11:10", SASAddress: "0x500062b2047b51c4", SASPort: "port-11:0", DeviceType: "end device", InitiatorPortProtocols: []string{"smp", "stp", "ssp"}, MaximumLinkrate: 12, MaximumLinkrateHW: 12, MinimumLinkrate: 3, MinimumLinkrateHW: 1.5, NegotiatedLinkrate: 12, PhyIdentifier: "10", TargetPortProtocols: []string{"none"}, }, "phy-11:11": { Name: "phy-11:11", SASAddress: "0x500062b2047b51c4", SASPort: "port-11:0", DeviceType: "end device", InitiatorPortProtocols: []string{"smp", "stp", "ssp"}, MaximumLinkrate: 12, MaximumLinkrateHW: 12, MinimumLinkrate: 3, MinimumLinkrateHW: 1.5, NegotiatedLinkrate: 12, PhyIdentifier: "11", TargetPortProtocols: []string{"none"}, }, "phy-11:12": { Name: "phy-11:12", SASAddress: "0x500062b2047b51c4", SASPort: "port-11:1", DeviceType: "end device", InitiatorPortProtocols: []string{"smp", "stp", "ssp"}, MaximumLinkrate: 12, MaximumLinkrateHW: 12, MinimumLinkrate: 3, MinimumLinkrateHW: 1.5, NegotiatedLinkrate: 6, PhyIdentifier: "12", TargetPortProtocols: []string{"none"}, }, "phy-11:13": { Name: "phy-11:13", SASAddress: "0x500062b2047b51c4", SASPort: "port-11:1", DeviceType: "end device", InitiatorPortProtocols: []string{"smp", "stp", "ssp"}, MaximumLinkrate: 12, MaximumLinkrateHW: 12, MinimumLinkrate: 3, MinimumLinkrateHW: 1.5, NegotiatedLinkrate: 6, PhyIdentifier: "13", TargetPortProtocols: []string{"none"}, }, "phy-11:14": { Name: "phy-11:14", SASAddress: "0x500062b2047b51c4", SASPort: "port-11:1", DeviceType: "end device", InitiatorPortProtocols: []string{"smp", "stp", "ssp"}, MaximumLinkrate: 12, MaximumLinkrateHW: 12, MinimumLinkrate: 3, MinimumLinkrateHW: 1.5, NegotiatedLinkrate: 6, PhyIdentifier: "14", TargetPortProtocols: []string{"none"}, }, "phy-11:15": { Name: "phy-11:15", SASAddress: "0x500062b2047b51c4", SASPort: "port-11:1", DeviceType: "end device", InitiatorPortProtocols: []string{"smp", "stp", "ssp"}, MaximumLinkrate: 12, MaximumLinkrateHW: 12, MinimumLinkrate: 3, MinimumLinkrateHW: 1.5, NegotiatedLinkrate: 6, PhyIdentifier: "15", TargetPortProtocols: []string{"none"}, }, "phy-11:7": { Name: "phy-11:7", SASAddress: "0x500062b2047b51c4", SASPort: "port-11:2", DeviceType: "end device", InitiatorPortProtocols: []string{"smp", "stp", "ssp"}, MaximumLinkrate: 12, MaximumLinkrateHW: 12, MinimumLinkrate: 3, MinimumLinkrateHW: 1.5, NegotiatedLinkrate: 12, PhyIdentifier: "7", TargetPortProtocols: []string{"none"}, }, "phy-11:8": { Name: "phy-11:8", SASAddress: "0x500062b2047b51c4", SASPort: "port-11:0", DeviceType: "end device", InitiatorPortProtocols: []string{"smp", "stp", "ssp"}, MaximumLinkrate: 12, MaximumLinkrateHW: 12, MinimumLinkrate: 3, MinimumLinkrateHW: 1.5, NegotiatedLinkrate: 12, PhyIdentifier: "8", TargetPortProtocols: []string{"none"}, }, "phy-11:9": { Name: "phy-11:9", SASAddress: "0x500062b2047b51c4", SASPort: "port-11:0", DeviceType: "end device", InitiatorPortProtocols: []string{"smp", "stp", "ssp"}, MaximumLinkrate: 12, MaximumLinkrateHW: 12, MinimumLinkrate: 3, MinimumLinkrateHW: 1.5, NegotiatedLinkrate: 12, PhyIdentifier: "9", TargetPortProtocols: []string{"none"}, }, } if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASPhy class (-want +got):\n%s", diff) } } func TestSASPhyGetByName(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } pc, err := fs.SASPhyClass() if err != nil { t.Fatal(err) } want := "phy-11:9" got := pc.GetByName("phy-11:9").Name if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASPhy class (-want +got):\n%s", diff) } // Doesn't exist. got2 := pc.GetByName("phy-12:0") if got2 != nil { t.Fatalf("unexpected GetByName response: got %v want nil", got2) } } golang-github-prometheus-procfs-0.14.0/sysfs/class_sas_port.go000066400000000000000000000072171461002754700245400ustar00rootroot00000000000000// Copyright 2021 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. //go:build linux // +build linux package sysfs import ( "os" "path/filepath" "regexp" ) const sasPortClassPath = "class/sas_port" type SASPort struct { Name string // /sys/class/sas_device/ SASPhys []string // /sys/class/sas_device//device/phy-* Expanders []string // /sys/class/sas_port//device/expander-* EndDevices []string // /sys/class/sas_port//device/end_device-* } type SASPortClass map[string]*SASPort var ( sasExpanderDeviceRegexp = regexp.MustCompile(`^expander-[0-9:]+$`) sasEndDeviceRegexp = regexp.MustCompile(`^end_device-[0-9:]+$`) ) // SASPortClass parses ports in /sys/class/sas_port. // // A SAS port in this context is a collection of SAS PHYs operating // together. For example, it's common to have 8-lane SAS cards that // have 2 external connectors, each of which carries 4 SAS lanes over // a SFF-8088 or SFF-8644 connector. While it's possible to split // those 4 lanes into 4 different cables wired directly into // individual drives, it's more common to connect them all to a SAS // expander. This gives you 4x the bandwidth between the expander and // the SAS host, and is represented by a sas-port object which // contains 4 sas-phy objects. func (fs FS) SASPortClass() (SASPortClass, error) { path := fs.sys.Path(sasPortClassPath) dirs, err := os.ReadDir(path) if err != nil { return nil, err } spc := make(SASPortClass, len(dirs)) for _, d := range dirs { port, err := fs.parseSASPort(d.Name()) if err != nil { return nil, err } spc[port.Name] = port } return spc, nil } // Parse a single sas_port. func (fs FS) parseSASPort(name string) (*SASPort, error) { port := SASPort{Name: name} portpath := fs.sys.Path(filepath.Join(sasPortClassPath, name, "device")) dirs, err := os.ReadDir(portpath) if err != nil { return nil, err } for _, d := range dirs { if sasPhyDeviceRegexp.MatchString(d.Name()) { port.SASPhys = append(port.SASPhys, d.Name()) } if sasExpanderDeviceRegexp.MatchString(d.Name()) { port.Expanders = append(port.Expanders, d.Name()) } if sasEndDeviceRegexp.MatchString(d.Name()) { port.EndDevices = append(port.EndDevices, d.Name()) } } return &port, nil } // GetByName returns the SASPort with the provided name. func (spc *SASPortClass) GetByName(name string) *SASPort { return (*spc)[name] } // GetByPhy finds the SASPort that contains the provided PHY name. func (spc *SASPortClass) GetByPhy(name string) *SASPort { for _, d := range *spc { for _, p := range d.SASPhys { if p == name { return d } } } return nil } // GetByExpander finds the SASPort that contains the provided SAS expander name. func (spc *SASPortClass) GetByExpander(name string) *SASPort { for _, d := range *spc { for _, e := range d.Expanders { if e == name { return d } } } return nil } // GetByEndDevice finds the SASPort that contains the provided SAS end device name. func (spc *SASPortClass) GetByEndDevice(name string) *SASPort { for _, d := range *spc { for _, e := range d.EndDevices { if e == name { return d } } } return nil } golang-github-prometheus-procfs-0.14.0/sysfs/class_sas_port_test.go000066400000000000000000000073301461002754700255730ustar00rootroot00000000000000// Copyright 2021 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. //go:build linux // +build linux package sysfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestSASPortClass(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } got, err := fs.SASPortClass() if err != nil { t.Fatal(err) } want := SASPortClass{ "port-11:0": { Name: "port-11:0", SASPhys: []string{"phy-11:10", "phy-11:11", "phy-11:8", "phy-11:9"}, Expanders: []string{"expander-11:0"}, }, "port-11:0:0": { Name: "port-11:0:0", SASPhys: []string{"phy-11:0:2"}, EndDevices: []string{"end_device-11:0:0"}, }, "port-11:0:1": { Name: "port-11:0:1", SASPhys: []string{"phy-11:0:4"}, EndDevices: []string{"end_device-11:0:1"}, }, "port-11:0:2": { Name: "port-11:0:2", SASPhys: []string{"phy-11:0:6"}, EndDevices: []string{"end_device-11:0:2"}, }, "port-11:1": { Name: "port-11:1", SASPhys: []string{"phy-11:12", "phy-11:13", "phy-11:14", "phy-11:15"}, Expanders: []string{"expander-11:1"}, }, } if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASDevice class (-want +got):\n%s", diff) } } func TestSASPortGetByName(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } dc, err := fs.SASPortClass() if err != nil { t.Fatal(err) } want := "port-11:0:0" got := dc.GetByName("port-11:0:0").Name if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASPort name (-want +got):\n%s", diff) } // Doesn't exist. got2 := dc.GetByName("port-15") if got2 != nil { t.Fatalf("unexpected GetByName response: got %v want nil", got2) } } func TestSASPortGetByPhy(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } dc, err := fs.SASPortClass() if err != nil { t.Fatal(err) } want := "port-11:0:2" got := dc.GetByPhy("phy-11:0:6").Name if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASPort class (-want +got):\n%s", diff) } // Doesn't exist. got2 := dc.GetByPhy("phy-12:0") if got2 != nil { t.Fatalf("unexpected GetByPhy response: got %v want nil", got2) } } func TestSASPortGetByExpander(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } dc, err := fs.SASPortClass() if err != nil { t.Fatal(err) } want := "port-11:0" got := dc.GetByExpander("expander-11:0").Name if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASPort class (-want +got):\n%s", diff) } // Doesn't exist. got2 := dc.GetByExpander("expander-12:0") if got2 != nil { t.Fatalf("unexpected GetByPhy response: got %v want nil", got2) } } func TestSASPortGetByEndDevice(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } dc, err := fs.SASPortClass() if err != nil { t.Fatal(err) } want := "port-11:0:2" got := dc.GetByEndDevice("end_device-11:0:2").Name if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SASPort class (-want +got):\n%s", diff) } // Doesn't exist. got2 := dc.GetByEndDevice("end_device-12:0") if got2 != nil { t.Fatalf("unexpected GetByPhy response: got %v want nil", got2) } } golang-github-prometheus-procfs-0.14.0/sysfs/class_scsitape.go000066400000000000000000000074311461002754700245170ustar00rootroot00000000000000// Copyright 2021 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. //go:build linux // +build linux package sysfs import ( "fmt" "os" "path/filepath" "regexp" "github.com/prometheus/procfs/internal/util" ) const scsiTapeClassPath = "class/scsi_tape" type SCSITapeCounters struct { WriteNs uint64 // /sys/class/scsi_tape//stats/write_ns ReadByteCnt uint64 // /sys/class/scsi_tape//stats/read_byte_cnt IoNs uint64 // /sys/class/scsi_tape//stats/io_ns WriteCnt uint64 // /sys/class/scsi_tape//stats/write_cnt ResidCnt uint64 // /sys/class/scsi_tape//stats/resid_cnt ReadNs uint64 // /sys/class/scsi_tape//stats/read_ns InFlight uint64 // /sys/class/scsi_tape//stats/in_flight OtherCnt uint64 // /sys/class/scsi_tape//stats/other_cnt ReadCnt uint64 // /sys/class/scsi_tape//stats/read_cnt WriteByteCnt uint64 // /sys/class/scsi_tape//stats/write_byte_cnt } type SCSITape struct { Name string // /sys/class/scsi_tape/ Counters SCSITapeCounters // /sys/class/scsi_tape//statistics/* } type SCSITapeClass map[string]SCSITape // SCSITapeClass parses st[0-9]+ devices in /sys/class/scsi_tape. func (fs FS) SCSITapeClass() (SCSITapeClass, error) { path := fs.sys.Path(scsiTapeClassPath) dirs, err := os.ReadDir(path) if err != nil { return nil, err } // There are n?st[0-9]+[a-b]? variants depending on device features. // n/2 is probably overestimated but never underestimated stc := make(SCSITapeClass, len(dirs)/2) validDevice := regexp.MustCompile(`^st[0-9]+$`) for _, d := range dirs { if !validDevice.Match([]byte(d.Name())) { continue } tape, err := fs.parseSCSITape(d.Name()) if err != nil { return nil, err } stc[tape.Name] = *tape } return stc, nil } // Parse a single scsi_tape. func (fs FS) parseSCSITape(name string) (*SCSITape, error) { path := fs.sys.Path(scsiTapeClassPath, name) tape := SCSITape{Name: name} counters, err := parseSCSITapeStatistics(path) if err != nil { return nil, err } tape.Counters = *counters return &tape, nil } // parseSCSITapeStatistics parses metrics from a single tape. func parseSCSITapeStatistics(tapePath string) (*SCSITapeCounters, error) { var counters SCSITapeCounters path := filepath.Join(tapePath, "stats") files, err := os.ReadDir(path) if err != nil { return nil, err } for _, f := range files { name := filepath.Join(path, f.Name()) value, err := util.SysReadFile(name) if err != nil { return nil, fmt.Errorf("failed to read file %q: %w", name, err) } vp := util.NewValueParser(value) switch f.Name() { case "in_flight": counters.InFlight = *vp.PUInt64() case "io_ns": counters.IoNs = *vp.PUInt64() case "other_cnt": counters.OtherCnt = *vp.PUInt64() case "read_byte_cnt": counters.ReadByteCnt = *vp.PUInt64() case "read_cnt": counters.ReadCnt = *vp.PUInt64() case "read_ns": counters.ReadNs = *vp.PUInt64() case "resid_cnt": counters.ResidCnt = *vp.PUInt64() case "write_byte_cnt": counters.WriteByteCnt = *vp.PUInt64() case "write_cnt": counters.WriteCnt = *vp.PUInt64() case "write_ns": counters.WriteNs = *vp.PUInt64() } if err := vp.Err(); err != nil { return nil, err } } return &counters, nil } golang-github-prometheus-procfs-0.14.0/sysfs/class_scsitape_test.go000066400000000000000000000025361461002754700255570ustar00rootroot00000000000000// Copyright 2021 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. //go:build linux // +build linux package sysfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestSCSITapeClass(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } got, err := fs.SCSITapeClass() if err != nil { t.Fatal(err) } want := SCSITapeClass{ "st0": SCSITape{ Name: "st0", Counters: SCSITapeCounters{ WriteNs: 5233597394395, ReadByteCnt: 979383912, IoNs: 9247011087720, WriteCnt: 53772916, WriteByteCnt: 1496246784000, ResidCnt: 19, ReadNs: 33788355744, InFlight: 1, OtherCnt: 1409, ReadCnt: 3741, }, }, } if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected SCSITape class (-want +got):\n%s", diff) } } golang-github-prometheus-procfs-0.14.0/sysfs/class_thermal.go000066400000000000000000000061211461002754700243330ustar00rootroot00000000000000// Copyright 2018 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. //go:build linux // +build linux package sysfs import ( "errors" "os" "path/filepath" "strings" "syscall" "github.com/prometheus/procfs/internal/util" ) // ClassThermalZoneStats contains info from files in /sys/class/thermal/thermal_zone // for a single . // https://www.kernel.org/doc/Documentation/thermal/sysfs-api.txt type ClassThermalZoneStats struct { Name string // The name of the zone from the directory structure. Type string // The type of thermal zone. Temp int64 // Temperature in millidegree Celsius. Policy string // One of the various thermal governors used for a particular zone. Mode *bool // Optional: One of the predefined values in [enabled, disabled]. Passive *uint64 // Optional: millidegrees Celsius. (0 for disabled, > 1000 for enabled+value) } // ClassThermalZoneStats returns Thermal Zone metrics for all zones. func (fs FS) ClassThermalZoneStats() ([]ClassThermalZoneStats, error) { zones, err := filepath.Glob(fs.sys.Path("class/thermal/thermal_zone[0-9]*")) if err != nil { return nil, err } stats := make([]ClassThermalZoneStats, 0, len(zones)) for _, zone := range zones { zoneStats, err := parseClassThermalZone(zone) if err != nil { if errors.Is(err, syscall.ENODATA) { continue } return nil, err } zoneStats.Name = strings.TrimPrefix(filepath.Base(zone), "thermal_zone") stats = append(stats, zoneStats) } return stats, nil } func parseClassThermalZone(zone string) (ClassThermalZoneStats, error) { // Required attributes. zoneType, err := util.SysReadFile(filepath.Join(zone, "type")) if err != nil { return ClassThermalZoneStats{}, err } zonePolicy, err := util.SysReadFile(filepath.Join(zone, "policy")) if err != nil { return ClassThermalZoneStats{}, err } zoneTemp, err := util.ReadIntFromFile(filepath.Join(zone, "temp")) if err != nil { return ClassThermalZoneStats{}, err } // Optional attributes. mode, err := util.SysReadFile(filepath.Join(zone, "mode")) if err != nil && !os.IsNotExist(err) && !os.IsPermission(err) { return ClassThermalZoneStats{}, err } zoneMode := util.ParseBool(mode) var zonePassive *uint64 passive, err := util.ReadUintFromFile(filepath.Join(zone, "passive")) if os.IsNotExist(err) || os.IsPermission(err) { zonePassive = nil } else if err != nil { return ClassThermalZoneStats{}, err } else { zonePassive = &passive } return ClassThermalZoneStats{ Type: zoneType, Policy: zonePolicy, Temp: zoneTemp, Mode: zoneMode, Passive: zonePassive, }, nil } golang-github-prometheus-procfs-0.14.0/sysfs/class_thermal_test.go000066400000000000000000000026711461002754700254000ustar00rootroot00000000000000// Copyright 2018 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. //go:build linux // +build linux package sysfs import ( "reflect" "testing" "github.com/prometheus/procfs/internal/util" ) func TestClassThermalZoneStats(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } thermalTest, err := fs.ClassThermalZoneStats() if err != nil { t.Fatal(err) } enabled := util.ParseBool("enabled") passive := uint64(0) classThermalZoneStats := []ClassThermalZoneStats{ { Name: "0", Type: "bcm2835_thermal", Policy: "step_wise", Temp: 49925, Mode: nil, Passive: nil, }, { Name: "1", Type: "acpitz", Policy: "step_wise", Temp: -44000, Mode: enabled, Passive: &passive, }, } if !reflect.DeepEqual(classThermalZoneStats, thermalTest) { t.Errorf("Result not correct: want %v, have %v", classThermalZoneStats, thermalTest) } } golang-github-prometheus-procfs-0.14.0/sysfs/class_watchdog.go000066400000000000000000000073171461002754700245070ustar00rootroot00000000000000// Copyright 2023 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. //go:build linux // +build linux package sysfs import ( "fmt" "os" "path/filepath" "github.com/prometheus/procfs/internal/util" ) const watchdogClassPath = "class/watchdog" // WatchdogStats contains info from files in /sys/class/watchdog for a single watchdog device. // https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-class-watchdog type WatchdogStats struct { Name string Bootstatus *int64 // /sys/class/watchdog//bootstatus Options *string // /sys/class/watchdog//options FwVersion *int64 // /sys/class/watchdog//fw_version Identity *string // /sys/class/watchdog//identity Nowayout *int64 // /sys/class/watchdog//nowayout State *string // /sys/class/watchdog//state Status *string // /sys/class/watchdog//status Timeleft *int64 // /sys/class/watchdog//timeleft Timeout *int64 // /sys/class/watchdog//timeout Pretimeout *int64 // /sys/class/watchdog//pretimeout PretimeoutGovernor *string // /sys/class/watchdog//pretimeout_governor AccessCs0 *int64 // /sys/class/watchdog//access_cs0 } // WatchdogClass is a collection of statistics for every watchdog device in /sys/class/watchdog. // // The map keys are the names of the watchdog devices. type WatchdogClass map[string]WatchdogStats // WatchdogClass returns info for all watchdog devices read from /sys/class/watchdog. func (fs FS) WatchdogClass() (WatchdogClass, error) { path := fs.sys.Path(watchdogClassPath) dirs, err := os.ReadDir(path) if err != nil { return nil, fmt.Errorf("failed to list watchdog devices at %q: %w", path, err) } wds := make(WatchdogClass, len(dirs)) for _, d := range dirs { stats, err := fs.parseWatchdog(d.Name()) if err != nil { return nil, err } wds[stats.Name] = *stats } return wds, nil } func (fs FS) parseWatchdog(wdName string) (*WatchdogStats, error) { path := fs.sys.Path(watchdogClassPath, wdName) wd := WatchdogStats{Name: wdName} for _, f := range [...]string{"bootstatus", "options", "fw_version", "identity", "nowayout", "state", "status", "timeleft", "timeout", "pretimeout", "pretimeout_governor", "access_cs0"} { name := filepath.Join(path, f) value, err := util.SysReadFile(name) if err != nil { if os.IsNotExist(err) { continue } return nil, fmt.Errorf("failed to read file %q: %w", name, err) } vp := util.NewValueParser(value) switch f { case "bootstatus": wd.Bootstatus = vp.PInt64() case "options": wd.Options = &value case "fw_version": wd.FwVersion = vp.PInt64() case "identity": wd.Identity = &value case "nowayout": wd.Nowayout = vp.PInt64() case "state": wd.State = &value case "status": wd.Status = &value case "timeleft": wd.Timeleft = vp.PInt64() case "timeout": wd.Timeout = vp.PInt64() case "pretimeout": wd.Pretimeout = vp.PInt64() case "pretimeout_governor": wd.PretimeoutGovernor = &value case "access_cs0": wd.AccessCs0 = vp.PInt64() } if err := vp.Err(); err != nil { return nil, err } } return &wd, nil } golang-github-prometheus-procfs-0.14.0/sysfs/class_watchdog_test.go000066400000000000000000000035251461002754700255430ustar00rootroot00000000000000// Copyright 2023 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. //go:build linux // +build linux package sysfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestWatchdogClass(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } got, err := fs.WatchdogClass() if err != nil { t.Fatal(err) } var ( bootstatus int64 = 1 fwVersion int64 = 2 nowayout int64 timeleft int64 = 300 timeout int64 = 60 pretimeout int64 = 120 accessCs0 int64 options = "0x8380" identity = "Software Watchdog" state = "active" status = "0x8000" pretimeoutGovernor = "noop" ) want := WatchdogClass{ "watchdog0": { Name: "watchdog0", Bootstatus: &bootstatus, Options: &options, FwVersion: &fwVersion, Identity: &identity, Nowayout: &nowayout, State: &state, Status: &status, Timeleft: &timeleft, Timeout: &timeout, Pretimeout: &pretimeout, PretimeoutGovernor: &pretimeoutGovernor, AccessCs0: &accessCs0, }, "watchdog1": { Name: "watchdog1", }, } if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected watchdog class (-want +got):\n%s", diff) } } golang-github-prometheus-procfs-0.14.0/sysfs/clocksource.go000066400000000000000000000040521461002754700240270ustar00rootroot00000000000000// 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. //go:build linux // +build linux package sysfs import ( "path/filepath" "strings" "github.com/prometheus/procfs/internal/util" ) // ClockSource contains metrics related to the clock source. type ClockSource struct { Name string Available []string Current string } // ClockSources returns clocksource information including current and available clocksources // read from '/sys/devices/system/clocksource'. func (fs FS) ClockSources() ([]ClockSource, error) { clocksourcePaths, err := filepath.Glob(fs.sys.Path("devices/system/clocksource/clocksource[0-9]*")) if err != nil { return nil, err } clocksources := make([]ClockSource, len(clocksourcePaths)) for i, clocksourcePath := range clocksourcePaths { clocksourceName := strings.TrimPrefix(filepath.Base(clocksourcePath), "clocksource") clocksource, err := parseClocksource(clocksourcePath) if err != nil { return nil, err } clocksource.Name = clocksourceName clocksources[i] = *clocksource } return clocksources, nil } func parseClocksource(clocksourcePath string) (*ClockSource, error) { stringFiles := []string{ "available_clocksource", "current_clocksource", } stringOut := make([]string, len(stringFiles)) var err error for i, f := range stringFiles { stringOut[i], err = util.SysReadFile(filepath.Join(clocksourcePath, f)) if err != nil { return &ClockSource{}, err } } return &ClockSource{ Available: strings.Fields(stringOut[0]), Current: stringOut[1], }, nil } golang-github-prometheus-procfs-0.14.0/sysfs/clocksource_test.go000066400000000000000000000021161461002754700250650ustar00rootroot00000000000000// 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. //go:build linux // +build linux package sysfs import ( "reflect" "testing" ) func TestNewClocksource(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } c, err := fs.ClockSources() if err != nil { t.Fatal(err) } clocksources := []ClockSource{ { Name: "0", Available: []string{"tsc", "hpet", "acpi_pm"}, Current: "tsc", }, } if !reflect.DeepEqual(clocksources, c) { t.Errorf("Result not correct: want %v, have %v", clocksources, c) } } golang-github-prometheus-procfs-0.14.0/sysfs/doc.go000066400000000000000000000013561461002754700222640ustar00rootroot00000000000000// Copyright 2017 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. //go:build linux // +build linux // Package sysfs provides functions to retrieve system and kernel metrics // from the pseudo-filesystem sys. package sysfs golang-github-prometheus-procfs-0.14.0/sysfs/fs.go000066400000000000000000000025631461002754700221300ustar00rootroot00000000000000// Copyright 2017 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. //go:build linux // +build linux package sysfs import ( "github.com/prometheus/procfs/internal/fs" ) // FS represents the pseudo-filesystem sys, which provides an interface to // kernel data structures. type FS struct { sys fs.FS } // DefaultMountPoint is the common mount point of the sys filesystem. const DefaultMountPoint = fs.DefaultSysMountPoint // NewDefaultFS returns a new FS mounted under the default mountPoint. It will error // if the mount point can't be read. func NewDefaultFS() (FS, error) { return NewFS(DefaultMountPoint) } // NewFS returns a new FS mounted under the given mountPoint. It will error // if the mount point can't be read. func NewFS(mountPoint string) (FS, error) { fs, err := fs.NewFS(mountPoint) if err != nil { return FS{}, err } return FS{fs}, nil } golang-github-prometheus-procfs-0.14.0/sysfs/fs_test.go000066400000000000000000000020711461002754700231610ustar00rootroot00000000000000// Copyright 2017 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. //go:build linux // +build linux package sysfs import "testing" const ( sysTestFixtures = "testdata/fixtures/sys" ) func TestNewFS(t *testing.T) { if _, err := NewFS("foobar"); err == nil { t.Error("want NewFS to fail for non-existing mount point") } if _, err := NewFS("doc.go"); err == nil { t.Error("want NewFS to fail if mount point is not a directory") } if _, err := NewFS(sysTestFixtures); err != nil { t.Error("want NewFS to succeed if mount point exists") } } golang-github-prometheus-procfs-0.14.0/sysfs/mdraid.go000066400000000000000000000114541461002754700227570ustar00rootroot00000000000000// Copyright 2023 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. //go:build linux // +build linux package sysfs import ( "fmt" "path/filepath" "strings" "github.com/prometheus/procfs/internal/util" ) // Mdraid holds info parsed from relevant files in the /sys/block/md*/md directory. type Mdraid struct { Device string // Kernel device name of array. Level string // mdraid level. ArrayState string // State of the array. MetadataVersion string // mdraid metadata version. Disks uint64 // Number of devices in a fully functional array. Components []MdraidComponent // mdraid component devices. UUID string // UUID of the array. // The following item is only valid for raid0, 4, 5, 6 and 10. ChunkSize uint64 // Chunk size // The following items are only valid for raid1, 4, 5, 6 and 10. DegradedDisks uint64 // Number of degraded disks in the array. SyncAction string // Current sync action. SyncCompleted float64 // Fraction (0-1) representing the completion status of current sync operation. } type MdraidComponent struct { Device string // Kernel device name. State string // Current state of device. } // Mdraids gathers information and statistics about mdraid devices present. Based on upstream // kernel documentation https://docs.kernel.org/admin-guide/md.html. func (fs FS) Mdraids() ([]Mdraid, error) { matches, err := filepath.Glob(fs.sys.Path("block/md*/md")) if err != nil { return nil, err } mdraids := make([]Mdraid, 0) for _, m := range matches { md := Mdraid{Device: filepath.Base(filepath.Dir(m))} path := fs.sys.Path("block", md.Device, "md") if val, err := util.SysReadFile(filepath.Join(path, "level")); err == nil { md.Level = val } else { return mdraids, err } // Array state can be one of: clear, inactive, readonly, read-auto, clean, active, // write-pending, active-idle. if val, err := util.SysReadFile(filepath.Join(path, "array_state")); err == nil { md.ArrayState = val } else { return mdraids, err } if val, err := util.SysReadFile(filepath.Join(path, "metadata_version")); err == nil { md.MetadataVersion = val } else { return mdraids, err } if val, err := util.ReadUintFromFile(filepath.Join(path, "raid_disks")); err == nil { md.Disks = val } else { return mdraids, err } if val, err := util.SysReadFile(filepath.Join(path, "uuid")); err == nil { md.UUID = val } else { return mdraids, err } if devs, err := filepath.Glob(filepath.Join(path, "dev-*")); err == nil { for _, dev := range devs { comp := MdraidComponent{Device: strings.TrimPrefix(filepath.Base(dev), "dev-")} // Component state can be a comma-separated list of: faulty, in_sync, writemostly, // blocked, spare, write_error, want_replacement, replacement. if val, err := util.SysReadFile(filepath.Join(dev, "state")); err == nil { comp.State = val } else { return mdraids, err } md.Components = append(md.Components, comp) } } else { return mdraids, err } switch md.Level { case "raid0", "raid4", "raid5", "raid6", "raid10": if val, err := util.ReadUintFromFile(filepath.Join(path, "chunk_size")); err == nil { md.ChunkSize = val } else { return mdraids, err } } switch md.Level { case "raid1", "raid4", "raid5", "raid6", "raid10": if val, err := util.ReadUintFromFile(filepath.Join(path, "degraded")); err == nil { md.DegradedDisks = val } else { return mdraids, err } // Array sync action can be one of: resync, recover, idle, check, repair. if val, err := util.SysReadFile(filepath.Join(path, "sync_action")); err == nil { md.SyncAction = val } else { return mdraids, err } if val, err := util.SysReadFile(filepath.Join(path, "sync_completed")); err == nil { if val != "none" { var a, b uint64 // File contains two values representing the fraction of number of completed // sectors divided by number of total sectors to process. if _, err := fmt.Sscanf(val, "%d / %d", &a, &b); err == nil { md.SyncCompleted = float64(a) / float64(b) } else { return mdraids, err } } } else { return mdraids, err } } mdraids = append(mdraids, md) } return mdraids, nil } golang-github-prometheus-procfs-0.14.0/sysfs/mdraid_test.go000066400000000000000000000066551461002754700240250ustar00rootroot00000000000000// Copyright 2023 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. //go:build linux // +build linux package sysfs import ( "testing" "github.com/google/go-cmp/cmp" ) func TestMdraidStats(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } got, err := fs.Mdraids() if err != nil { t.Fatal(err) } want := []Mdraid{ { Device: "md0", Level: "raid0", ArrayState: "clean", MetadataVersion: "1.2", Disks: 2, Components: []MdraidComponent{ {Device: "sdg", State: "in_sync"}, {Device: "sdh", State: "in_sync"}, }, UUID: "155f29ff-1716-4107-b362-52307ef86cac", ChunkSize: 524288, }, { Device: "md1", Level: "raid1", ArrayState: "clean", MetadataVersion: "1.2", Disks: 2, Components: []MdraidComponent{ {Device: "sdi", State: "in_sync"}, {Device: "sdj", State: "in_sync"}, }, UUID: "0fbf5f2c-add2-43c2-bd78-a4be3ab709ef", SyncAction: "idle", }, { Device: "md10", Level: "raid10", ArrayState: "clean", MetadataVersion: "1.2", Disks: 4, Components: []MdraidComponent{ {Device: "sdu", State: "in_sync"}, {Device: "sdv", State: "in_sync"}, {Device: "sdw", State: "in_sync"}, {Device: "sdx", State: "in_sync"}, }, UUID: "0c15f7e7-b159-4b1f-a5cd-a79b5c04b6f5", ChunkSize: 524288, SyncAction: "idle", }, { Device: "md4", Level: "raid4", ArrayState: "clean", MetadataVersion: "1.2", Disks: 3, Components: []MdraidComponent{ {Device: "sdk", State: "in_sync"}, {Device: "sdl", State: "in_sync"}, {Device: "sdm", State: "in_sync"}, }, UUID: "67f415d5-2c0c-4b69-8e0d-7e20ef553457", ChunkSize: 524288, SyncAction: "idle", }, { Device: "md5", Level: "raid5", ArrayState: "clean", MetadataVersion: "1.2", Disks: 3, Components: []MdraidComponent{ {Device: "sdaa", State: "spare"}, {Device: "sdn", State: "in_sync"}, {Device: "sdo", State: "in_sync"}, {Device: "sdp", State: "faulty"}, }, UUID: "7615b98d-f2ba-4d99-bee8-6202d8e130b9", ChunkSize: 524288, DegradedDisks: 1, SyncAction: "idle", }, { Device: "md6", Level: "raid6", ArrayState: "active", MetadataVersion: "1.2", Disks: 4, Components: []MdraidComponent{ {Device: "sdq", State: "in_sync"}, {Device: "sdr", State: "in_sync"}, {Device: "sds", State: "in_sync"}, {Device: "sdt", State: "spare"}, }, UUID: "5f529b25-6efd-46e4-99a2-31f6f597be6b", ChunkSize: 524288, DegradedDisks: 1, SyncAction: "recover", SyncCompleted: 0.7500458659491194, }, } if diff := cmp.Diff(want, got); diff != "" { t.Fatalf("unexpected Mdraid (-want +got):\n%s", diff) } } golang-github-prometheus-procfs-0.14.0/sysfs/net_class.go000066400000000000000000000163751461002754700235010ustar00rootroot00000000000000// Copyright 2018 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. //go:build linux // +build linux package sysfs import ( "errors" "fmt" "os" "path/filepath" "syscall" "github.com/prometheus/procfs/internal/util" ) const netclassPath = "class/net" // NetClassIface contains info from files in /sys/class/net/ // for single interface (iface). type NetClassIface struct { Name string // Interface name AddrAssignType *int64 // /sys/class/net//addr_assign_type AddrLen *int64 // /sys/class/net//addr_len Address string // /sys/class/net//address Broadcast string // /sys/class/net//broadcast Carrier *int64 // /sys/class/net//carrier CarrierChanges *int64 // /sys/class/net//carrier_changes CarrierUpCount *int64 // /sys/class/net//carrier_up_count CarrierDownCount *int64 // /sys/class/net//carrier_down_count DevID *int64 // /sys/class/net//dev_id Dormant *int64 // /sys/class/net//dormant Duplex string // /sys/class/net//duplex Flags *int64 // /sys/class/net//flags IfAlias string // /sys/class/net//ifalias IfIndex *int64 // /sys/class/net//ifindex IfLink *int64 // /sys/class/net//iflink LinkMode *int64 // /sys/class/net//link_mode MTU *int64 // /sys/class/net//mtu NameAssignType *int64 // /sys/class/net//name_assign_type NetDevGroup *int64 // /sys/class/net//netdev_group OperState string // /sys/class/net//operstate PhysPortID string // /sys/class/net//phys_port_id PhysPortName string // /sys/class/net//phys_port_name PhysSwitchID string // /sys/class/net//phys_switch_id Speed *int64 // /sys/class/net//speed TxQueueLen *int64 // /sys/class/net//tx_queue_len Type *int64 // /sys/class/net//type } // NetClass is collection of info for every interface (iface) in /sys/class/net. The map keys // are interface (iface) names. type NetClass map[string]NetClassIface // NetClassDevices scans /sys/class/net for devices and returns them as a list of names. func (fs FS) NetClassDevices() ([]string, error) { var res []string path := fs.sys.Path(netclassPath) devices, err := os.ReadDir(path) if err != nil { return res, fmt.Errorf("cannot access dir %q: %w", path, err) } for _, deviceDir := range devices { if deviceDir.Type().IsRegular() { continue } res = append(res, deviceDir.Name()) } return res, nil } // NetClassByIface returns info for a single net interfaces (iface). func (fs FS) NetClassByIface(devicePath string) (*NetClassIface, error) { path := fs.sys.Path(netclassPath) interfaceClass, err := parseNetClassIface(filepath.Join(path, devicePath)) if err != nil { return nil, err } interfaceClass.Name = devicePath return interfaceClass, nil } // NetClass returns info for all net interfaces (iface) read from /sys/class/net/. func (fs FS) NetClass() (NetClass, error) { devices, err := fs.NetClassDevices() if err != nil { return nil, err } path := fs.sys.Path(netclassPath) netClass := NetClass{} for _, devicePath := range devices { interfaceClass, err := parseNetClassIface(filepath.Join(path, devicePath)) if err != nil { return nil, err } interfaceClass.Name = devicePath netClass[devicePath] = *interfaceClass } return netClass, nil } // canIgnoreError returns true if the error is non-fatal and can be ignored. // Some kernels and some devices don't expose specific attributes or return // errors when reading those attributes; we can ignore these errors and the // attribute that caused them. func canIgnoreError(err error) bool { var errno syscall.Errno if os.IsNotExist(err) { return true } else if os.IsPermission(err) { return true } else if err.Error() == "operation not supported" { return true } else if errors.Is(err, os.ErrInvalid) { return true } else if errors.As(err, &errno) && (errno == syscall.EINVAL) { return true } // all other errors are fatal return false } // ParseNetClassAttribute parses a given file in /sys/class/net/ // and sets the value in a given NetClassIface object if the value was readable. // It returns an error if the file cannot be read and the error is fatal. func ParseNetClassAttribute(devicePath, attrName string, interfaceClass *NetClassIface) error { attrPath := filepath.Join(devicePath, attrName) value, err := util.SysReadFile(attrPath) if err != nil { if canIgnoreError(err) { return nil } return fmt.Errorf("failed to read file %q: %w", attrPath, err) } vp := util.NewValueParser(value) switch attrName { case "addr_assign_type": interfaceClass.AddrAssignType = vp.PInt64() case "addr_len": interfaceClass.AddrLen = vp.PInt64() case "address": interfaceClass.Address = value case "broadcast": interfaceClass.Broadcast = value case "carrier": interfaceClass.Carrier = vp.PInt64() case "carrier_changes": interfaceClass.CarrierChanges = vp.PInt64() case "carrier_up_count": interfaceClass.CarrierUpCount = vp.PInt64() case "carrier_down_count": interfaceClass.CarrierDownCount = vp.PInt64() case "dev_id": interfaceClass.DevID = vp.PInt64() case "dormant": interfaceClass.Dormant = vp.PInt64() case "duplex": interfaceClass.Duplex = value case "flags": interfaceClass.Flags = vp.PInt64() case "ifalias": interfaceClass.IfAlias = value case "ifindex": interfaceClass.IfIndex = vp.PInt64() case "iflink": interfaceClass.IfLink = vp.PInt64() case "link_mode": interfaceClass.LinkMode = vp.PInt64() case "mtu": interfaceClass.MTU = vp.PInt64() case "name_assign_type": interfaceClass.NameAssignType = vp.PInt64() case "netdev_group": interfaceClass.NetDevGroup = vp.PInt64() case "operstate": interfaceClass.OperState = value case "phys_port_id": interfaceClass.PhysPortID = value case "phys_port_name": interfaceClass.PhysPortName = value case "phys_switch_id": interfaceClass.PhysSwitchID = value case "speed": interfaceClass.Speed = vp.PInt64() case "tx_queue_len": interfaceClass.TxQueueLen = vp.PInt64() case "type": interfaceClass.Type = vp.PInt64() default: return nil } return nil } // parseNetClassIface scans predefined files in /sys/class/net/ // directory and gets their contents. func parseNetClassIface(devicePath string) (*NetClassIface, error) { interfaceClass := NetClassIface{} files, err := os.ReadDir(devicePath) if err != nil { return nil, err } for _, f := range files { if !f.Type().IsRegular() { continue } if err := ParseNetClassAttribute(devicePath, f.Name(), &interfaceClass); err != nil { return nil, err } } return &interfaceClass, nil } golang-github-prometheus-procfs-0.14.0/sysfs/net_class_test.go000066400000000000000000000062231461002754700245270ustar00rootroot00000000000000// Copyright 2018 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. //go:build linux // +build linux package sysfs import ( "reflect" "testing" ) func TestNewNetClassDevices(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } devices, err := fs.NetClassDevices() if err != nil { t.Fatal(err) } if len(devices) != 1 { t.Errorf("Unexpected number of devices, want %d, have %d", 1, len(devices)) } if devices[0] != "eth0" { t.Errorf("Found unexpected device, want %s, have %s", "eth0", devices[0]) } } func TestNewNetClassDevicesByIface(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } _, err = fs.NetClassByIface("non-existent") if err == nil { t.Fatal("expected error, have none") } device, err := fs.NetClassByIface("eth0") if err != nil { t.Fatal(err) } if device.Name != "eth0" { t.Errorf("Found unexpected device, want %s, have %s", "eth0", device.Name) } } func TestNetClass(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } nc, err := fs.NetClass() if err != nil { t.Fatal(err) } var ( addrAssignType int64 = 3 addrLen int64 = 6 carrier int64 = 1 carrierChanges int64 = 2 carrierDownCount int64 = 1 carrierUpCount int64 = 1 devID int64 = 32 dormant int64 = 1 flags int64 = 4867 ifIndex int64 = 2 ifLink int64 = 2 linkMode int64 = 1 mtu int64 = 1500 nameAssignType int64 = 2 netDevGroup int64 speed int64 = 1000 txQueueLen int64 = 1000 netType int64 = 1 ) netClass := NetClass{ "eth0": { Address: "01:01:01:01:01:01", AddrAssignType: &addrAssignType, AddrLen: &addrLen, Broadcast: "ff:ff:ff:ff:ff:ff", Carrier: &carrier, CarrierChanges: &carrierChanges, CarrierDownCount: &carrierDownCount, CarrierUpCount: &carrierUpCount, DevID: &devID, Dormant: &dormant, Duplex: "full", Flags: &flags, IfAlias: "", IfIndex: &ifIndex, IfLink: &ifLink, LinkMode: &linkMode, MTU: &mtu, Name: "eth0", NameAssignType: &nameAssignType, NetDevGroup: &netDevGroup, OperState: "up", PhysPortID: "", PhysPortName: "", PhysSwitchID: "", Speed: &speed, TxQueueLen: &txQueueLen, Type: &netType, }, } if !reflect.DeepEqual(netClass, nc) { t.Errorf("Result not correct: want %v, have %v", netClass, nc) } } golang-github-prometheus-procfs-0.14.0/sysfs/system_cpu.go000066400000000000000000000217121461002754700237100ustar00rootroot00000000000000// Copyright 2018 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. //go:build linux // +build linux package sysfs import ( "fmt" "os" "path/filepath" "strconv" "strings" "golang.org/x/sync/errgroup" "github.com/prometheus/procfs/internal/util" ) // CPU represents a path to a CPU located in `/sys/devices/system/cpu/cpu[0-9]*`. type CPU string // Number returns the ID number of the given CPU. func (c CPU) Number() string { return strings.TrimPrefix(filepath.Base(string(c)), "cpu") } // CPUTopology contains data located in `/sys/devices/system/cpu/cpu[0-9]*/topology`. type CPUTopology struct { CoreID string CoreSiblingsList string PhysicalPackageID string ThreadSiblingsList string } // CPUThermalThrottle contains data from `/sys/devices/system/cpu/cpu[0-9]*/thermal_throttle`. type CPUThermalThrottle struct { CoreThrottleCount uint64 PackageThrottleCount uint64 } // SystemCPUCpufreqStats contains stats from `/sys/devices/system/cpu/cpu[0-9]*/cpufreq/...`. type SystemCPUCpufreqStats struct { Name string CpuinfoCurrentFrequency *uint64 CpuinfoMinimumFrequency *uint64 CpuinfoMaximumFrequency *uint64 CpuinfoTransitionLatency *uint64 ScalingCurrentFrequency *uint64 ScalingMinimumFrequency *uint64 ScalingMaximumFrequency *uint64 AvailableGovernors string Driver string Governor string RelatedCpus string SetSpeed string } // CPUs returns a slice of all CPUs in `/sys/devices/system/cpu`. func (fs FS) CPUs() ([]CPU, error) { cpuPaths, err := filepath.Glob(fs.sys.Path("devices/system/cpu/cpu[0-9]*")) if err != nil { return nil, err } cpus := make([]CPU, len(cpuPaths)) for i, cpu := range cpuPaths { cpus[i] = CPU(cpu) } return cpus, nil } // Topology gets the topology information for a single CPU from `/sys/devices/system/cpu/cpuN/topology`. func (c CPU) Topology() (*CPUTopology, error) { cpuTopologyPath := filepath.Join(string(c), "topology") if _, err := os.Stat(cpuTopologyPath); err != nil { return nil, err } t, err := parseCPUTopology(cpuTopologyPath) if err != nil { return nil, err } return t, nil } func parseCPUTopology(cpuPath string) (*CPUTopology, error) { t := CPUTopology{} var err error t.CoreID, err = util.SysReadFile(filepath.Join(cpuPath, "core_id")) if err != nil { return nil, err } t.PhysicalPackageID, err = util.SysReadFile(filepath.Join(cpuPath, "physical_package_id")) if err != nil { return nil, err } t.CoreSiblingsList, err = util.SysReadFile(filepath.Join(cpuPath, "core_siblings_list")) if err != nil { return nil, err } t.ThreadSiblingsList, err = util.SysReadFile(filepath.Join(cpuPath, "thread_siblings_list")) if err != nil { return nil, err } return &t, nil } // ThermalThrottle gets the cpu throttle count information for a single CPU from `/sys/devices/system/cpu/cpuN/thermal_throttle`. func (c CPU) ThermalThrottle() (*CPUThermalThrottle, error) { cpuPath := filepath.Join(string(c), "thermal_throttle") if _, err := os.Stat(cpuPath); err != nil { return nil, err } t, err := parseCPUThermalThrottle(cpuPath) if err != nil { return nil, err } return t, nil } func parseCPUThermalThrottle(cpuPath string) (*CPUThermalThrottle, error) { t := CPUThermalThrottle{} var err error t.PackageThrottleCount, err = util.ReadUintFromFile(filepath.Join(cpuPath, "package_throttle_count")) if err != nil { return nil, err } t.CoreThrottleCount, err = util.ReadUintFromFile(filepath.Join(cpuPath, "core_throttle_count")) if err != nil { return nil, err } return &t, nil } func binSearch(elem uint16, elemSlice *[]uint16) bool { if len(*elemSlice) == 0 { return false } if len(*elemSlice) == 1 { return elem == (*elemSlice)[0] } start := 0 end := len(*elemSlice) - 1 var mid int for start <= end { mid = (start + end) / 2 if (*elemSlice)[mid] == elem { return true } else if (*elemSlice)[mid] > elem { end = mid - 1 } else if (*elemSlice)[mid] < elem { start = mid + 1 } } return false } func filterOfflineCPUs(offlineCpus *[]uint16, cpus *[]string) ([]string, error) { var filteredCPUs []string for _, cpu := range *cpus { cpuName := strings.TrimPrefix(filepath.Base(cpu), "cpu") cpuNameUint16, err := strconv.Atoi(cpuName) if err != nil { return nil, err } if !binSearch(uint16(cpuNameUint16), offlineCpus) { filteredCPUs = append(filteredCPUs, cpu) } } return filteredCPUs, nil } // SystemCpufreq returns CPU frequency metrics for all CPUs. func (fs FS) SystemCpufreq() ([]SystemCPUCpufreqStats, error) { var g errgroup.Group cpus, err := filepath.Glob(fs.sys.Path("devices/system/cpu/cpu[0-9]*")) if err != nil { return nil, err } line, err := util.ReadFileNoStat(fs.sys.Path("devices/system/cpu/offline")) if err != nil { return nil, err } if strings.TrimSpace(string(line)) != "" { offlineCPUs, err := parseCPURange(line) if err != nil { return nil, err } if len(offlineCPUs) > 0 { cpus, err = filterOfflineCPUs(&offlineCPUs, &cpus) if err != nil { return nil, err } } } systemCpufreq := make([]SystemCPUCpufreqStats, len(cpus)) for i, cpu := range cpus { cpuName := strings.TrimPrefix(filepath.Base(cpu), "cpu") cpuCpufreqPath := filepath.Join(cpu, "cpufreq") _, err = os.Stat(cpuCpufreqPath) if os.IsNotExist(err) { continue } else if err != nil { return nil, err } // Execute the parsing of each CPU in parallel. // This is done because the kernel intentionally delays access to each CPU by // 50 milliseconds to avoid DDoSing possibly expensive functions. i := i // https://golang.org/doc/faq#closures_and_goroutines g.Go(func() error { cpufreq, err := parseCpufreqCpuinfo(cpuCpufreqPath) if err == nil { cpufreq.Name = cpuName systemCpufreq[i] = *cpufreq } return err }) } if err = g.Wait(); err != nil { return nil, err } if len(systemCpufreq) == 0 { return nil, fmt.Errorf("could not find any cpufreq files: %w", os.ErrNotExist) } return systemCpufreq, nil } func parseCpufreqCpuinfo(cpuPath string) (*SystemCPUCpufreqStats, error) { uintFiles := []string{ "cpuinfo_cur_freq", "cpuinfo_max_freq", "cpuinfo_min_freq", "cpuinfo_transition_latency", "scaling_cur_freq", "scaling_max_freq", "scaling_min_freq", } uintOut := make([]*uint64, len(uintFiles)) for i, f := range uintFiles { v, err := util.ReadUintFromFile(filepath.Join(cpuPath, f)) if err != nil { if os.IsNotExist(err) || os.IsPermission(err) { continue } return &SystemCPUCpufreqStats{}, err } uintOut[i] = &v } stringFiles := []string{ "scaling_available_governors", "scaling_driver", "scaling_governor", "related_cpus", "scaling_setspeed", } stringOut := make([]string, len(stringFiles)) var err error for i, f := range stringFiles { stringOut[i], err = util.SysReadFile(filepath.Join(cpuPath, f)) if err != nil { return &SystemCPUCpufreqStats{}, err } } return &SystemCPUCpufreqStats{ CpuinfoCurrentFrequency: uintOut[0], CpuinfoMaximumFrequency: uintOut[1], CpuinfoMinimumFrequency: uintOut[2], CpuinfoTransitionLatency: uintOut[3], ScalingCurrentFrequency: uintOut[4], ScalingMaximumFrequency: uintOut[5], ScalingMinimumFrequency: uintOut[6], AvailableGovernors: stringOut[0], Driver: stringOut[1], Governor: stringOut[2], RelatedCpus: stringOut[3], SetSpeed: stringOut[4], }, nil } func (fs FS) IsolatedCPUs() ([]uint16, error) { isolcpus, err := os.ReadFile(fs.sys.Path("devices/system/cpu/isolated")) if err != nil { return nil, err } return parseCPURange(isolcpus) } func parseCPURange(data []byte) ([]uint16, error) { var cpusInt = []uint16{} for _, cpu := range strings.Split(strings.TrimRight(string(data), "\n"), ",") { if cpu == "" { continue } if strings.Contains(cpu, "-") { ranges := strings.Split(cpu, "-") if len(ranges) != 2 { return nil, fmt.Errorf("invalid cpu range: %s", cpu) } startRange, err := strconv.Atoi(ranges[0]) if err != nil { return nil, fmt.Errorf("invalid cpu start range: %w", err) } endRange, err := strconv.Atoi(ranges[1]) if err != nil { return nil, fmt.Errorf("invalid cpu end range: %w", err) } for i := startRange; i <= endRange; i++ { cpusInt = append(cpusInt, uint16(i)) } continue } cpuN, err := strconv.Atoi(cpu) if err != nil { return nil, err } cpusInt = append(cpusInt, uint16(cpuN)) } return cpusInt, nil } golang-github-prometheus-procfs-0.14.0/sysfs/system_cpu_test.go000066400000000000000000000142531461002754700247510ustar00rootroot00000000000000// Copyright 2018 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. //go:build linux // +build linux package sysfs import ( "errors" "reflect" "testing" ) func makeUint64(v uint64) *uint64 { return &v } func TestCPUTopology(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } cpus, err := fs.CPUs() if err != nil { t.Fatal(err) } if want, have := 3, len(cpus); want != have { t.Errorf("incorrect number of CPUs, have %v, want %v", want, have) } if want, have := "0", cpus[0].Number(); want != have { t.Errorf("incorrect name, have %v, want %v", want, have) } cpu0Topology, err := cpus[0].Topology() if err != nil { t.Fatal(err) } if want, have := "0", cpu0Topology.CoreID; want != have { t.Errorf("incorrect core ID, have %v, want %v", want, have) } if want, have := "0-7", cpu0Topology.CoreSiblingsList; want != have { t.Errorf("incorrect core siblings list, have %v, want %v", want, have) } cpu1Topology, err := cpus[1].Topology() if err != nil { t.Fatal(err) } if want, have := "0", cpu1Topology.PhysicalPackageID; want != have { t.Errorf("incorrect package ID, have %v, want %v", want, have) } if want, have := "1,5", cpu1Topology.ThreadSiblingsList; want != have { t.Errorf("incorrect thread siblings list, have %v, want %v", want, have) } } func TestCPUThermalThrottle(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } cpus, err := fs.CPUs() if err != nil { t.Fatal(err) } if want, have := 3, len(cpus); want != have { t.Errorf("incorrect number of CPUs, have %v, want %v", want, have) } cpu0Throttle, err := cpus[0].ThermalThrottle() if err != nil { t.Fatal(err) } if want, have := uint64(34818), cpu0Throttle.PackageThrottleCount; want != have { t.Errorf("incorrect package throttle count, have %v, want %v", want, have) } cpu1Throttle, err := cpus[1].ThermalThrottle() if err != nil { t.Fatal(err) } if want, have := uint64(523), cpu1Throttle.CoreThrottleCount; want != have { t.Errorf("incorrect core throttle count, have %v, want %v", want, have) } } func TestSystemCpufreq(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } c, err := fs.SystemCpufreq() if err != nil { t.Fatal(err) } systemCpufreq := []SystemCPUCpufreqStats{ // Has missing `cpuinfo_cur_freq` file. { Name: "0", CpuinfoCurrentFrequency: nil, CpuinfoMinimumFrequency: makeUint64(800000), CpuinfoMaximumFrequency: makeUint64(2400000), CpuinfoTransitionLatency: makeUint64(0), ScalingCurrentFrequency: makeUint64(1219917), ScalingMinimumFrequency: makeUint64(800000), ScalingMaximumFrequency: makeUint64(2400000), AvailableGovernors: "performance powersave", Driver: "intel_pstate", Governor: "powersave", RelatedCpus: "0", SetSpeed: "", }, // Has missing `scaling_cur_freq` file. { Name: "1", CpuinfoCurrentFrequency: makeUint64(1200195), CpuinfoMinimumFrequency: makeUint64(1200000), CpuinfoMaximumFrequency: makeUint64(3300000), CpuinfoTransitionLatency: makeUint64(4294967295), ScalingCurrentFrequency: nil, ScalingMinimumFrequency: makeUint64(1200000), ScalingMaximumFrequency: makeUint64(3300000), AvailableGovernors: "performance powersave", Driver: "intel_pstate", Governor: "powersave", RelatedCpus: "1", SetSpeed: "", }, } if !reflect.DeepEqual(systemCpufreq, c) { t.Errorf("Result not correct: want %v, have %v", systemCpufreq, c) } } func TestIsolatedParsingCPU(t *testing.T) { var testParams = []struct { in []byte res []uint16 err error }{ {[]byte(""), []uint16{}, nil}, {[]byte("1\n"), []uint16{1}, nil}, {[]byte("1"), []uint16{1}, nil}, {[]byte("1,2"), []uint16{1, 2}, nil}, {[]byte("1-2"), []uint16{1, 2}, nil}, {[]byte("1-3"), []uint16{1, 2, 3}, nil}, {[]byte("1,2-4"), []uint16{1, 2, 3, 4}, nil}, {[]byte("1,3-4"), []uint16{1, 3, 4}, nil}, {[]byte("1,3-4,7,20-21"), []uint16{1, 3, 4, 7, 20, 21}, nil}, {[]byte("1,"), []uint16{1}, nil}, {[]byte("1,2-"), nil, errors.New(`invalid cpu end range: strconv.Atoi: parsing "": invalid syntax`)}, {[]byte("1,-3"), nil, errors.New(`invalid cpu start range: strconv.Atoi: parsing "": invalid syntax`)}, } for _, params := range testParams { t.Run("blabla", func(t *testing.T) { res, err := parseCPURange(params.in) if !reflect.DeepEqual(res, params.res) { t.Fatalf("should have %v result: got %v", params.res, res) } if err != nil && params.err != nil && err.Error() != params.err.Error() { t.Fatalf("should have '%v' error: got '%v'", params.err, err) } if (err == nil || params.err == nil) && err != params.err { t.Fatalf("should have %v error: got %v", params.err, err) } }) } } func TestIsolatedCPUs(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } isolated, err := fs.IsolatedCPUs() expected := []uint16{1, 2, 3, 4, 5, 6, 7, 9} if !reflect.DeepEqual(isolated, expected) { t.Errorf("Result not correct: want %v, have %v", expected, isolated) } if err != nil { t.Errorf("Error not correct: want %v, have %v", nil, err) } } func TestBinSearch(t *testing.T) { var testParams = []struct { elem uint16 elems []uint16 res bool }{ {3, []uint16{1, 3, 5, 7, 9}, true}, {4, []uint16{1, 3, 5, 7, 9}, false}, {2, []uint16{}, false}, } for _, param := range testParams { res := binSearch(param.elem, ¶m.elems) if res != param.res { t.Fatalf("Result not correct: want %v, have %v", param.res, res) } } } golang-github-prometheus-procfs-0.14.0/sysfs/testdata/000077500000000000000000000000001461002754700227745ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/sysfs/testdata/fixtures000077700000000000000000000000001461002754700306162../../testdata/fixturesustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/sysfs/vmstat_numa.go000066400000000000000000000153611461002754700240560ustar00rootroot00000000000000// Copyright 2020 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. //go:build linux // +build linux package sysfs import ( "bufio" "bytes" "fmt" "path/filepath" "regexp" "strconv" "strings" "github.com/prometheus/procfs/internal/util" ) var ( nodePattern = "devices/system/node/node[0-9]*" nodeNumberRegexp = regexp.MustCompile(`.*devices/system/node/node([0-9]*)`) ) type VMStat struct { NrFreePages uint64 NrZoneInactiveAnon uint64 NrZoneActiveAnon uint64 NrZoneInactiveFile uint64 NrZoneActiveFile uint64 NrZoneUnevictable uint64 NrZoneWritePending uint64 NrMlock uint64 NrPageTablePages uint64 NrKernelStack uint64 NrBounce uint64 NrZspages uint64 NrFreeCma uint64 NumaHit uint64 NumaMiss uint64 NumaForeign uint64 NumaInterleave uint64 NumaLocal uint64 NumaOther uint64 NrInactiveAnon uint64 NrActiveAnon uint64 NrInactiveFile uint64 NrActiveFile uint64 NrUnevictable uint64 NrSlabReclaimable uint64 NrSlabUnreclaimable uint64 NrIsolatedAnon uint64 NrIsolatedFile uint64 WorkingsetNodes uint64 WorkingsetRefault uint64 WorkingsetActivate uint64 WorkingsetRestore uint64 WorkingsetNodereclaim uint64 NrAnonPages uint64 NrMapped uint64 NrFilePages uint64 NrDirty uint64 NrWriteback uint64 NrWritebackTemp uint64 NrShmem uint64 NrShmemHugepages uint64 NrShmemPmdmapped uint64 NrFileHugepages uint64 NrFilePmdmapped uint64 NrAnonTransparentHugepages uint64 NrVmscanWrite uint64 NrVmscanImmediateReclaim uint64 NrDirtied uint64 NrWritten uint64 NrKernelMiscReclaimable uint64 NrFollPinAcquired uint64 NrFollPinReleased uint64 } func (fs FS) VMStatNUMA() (map[int]VMStat, error) { m := make(map[int]VMStat) nodes, err := filepath.Glob(fs.sys.Path(nodePattern)) if err != nil { return nil, err } for _, node := range nodes { nodeNumbers := nodeNumberRegexp.FindStringSubmatch(node) if len(nodeNumbers) != 2 { continue } nodeNumber, err := strconv.Atoi(nodeNumbers[1]) if err != nil { return nil, err } file, err := util.ReadFileNoStat(filepath.Join(node, "vmstat")) if err != nil { return nil, err } nodeStats, err := parseVMStatNUMA(file) if err != nil { return nil, err } m[nodeNumber] = nodeStats } return m, nil } func parseVMStatNUMA(r []byte) (VMStat, error) { var ( vmStat = VMStat{} scanner = bufio.NewScanner(bytes.NewReader(r)) ) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) if line == "" { continue } parts := strings.Fields(line) if len(parts) != 2 { return vmStat, fmt.Errorf("line scan did not return 2 fields: %s", line) } fv, err := strconv.ParseUint(parts[1], 10, 64) if err != nil { return vmStat, fmt.Errorf("invalid value in vmstat: %w", err) } switch parts[0] { case "nr_free_pages": vmStat.NrFreePages = fv case "nr_zone_inactive_anon": vmStat.NrZoneInactiveAnon = fv case "nr_zone_active_anon": vmStat.NrZoneActiveAnon = fv case "nr_zone_inactive_file": vmStat.NrZoneInactiveFile = fv case "nr_zone_active_file": vmStat.NrZoneActiveFile = fv case "nr_zone_unevictable": vmStat.NrZoneUnevictable = fv case "nr_zone_write_pending": vmStat.NrZoneWritePending = fv case "nr_mlock": vmStat.NrMlock = fv case "nr_page_table_pages": vmStat.NrPageTablePages = fv case "nr_kernel_stack": vmStat.NrKernelStack = fv case "nr_bounce": vmStat.NrBounce = fv case "nr_zspages": vmStat.NrZspages = fv case "nr_free_cma": vmStat.NrFreeCma = fv case "numa_hit": vmStat.NumaHit = fv case "numa_miss": vmStat.NumaMiss = fv case "numa_foreign": vmStat.NumaForeign = fv case "numa_interleave": vmStat.NumaInterleave = fv case "numa_local": vmStat.NumaLocal = fv case "numa_other": vmStat.NumaOther = fv case "nr_inactive_anon": vmStat.NrInactiveAnon = fv case "nr_active_anon": vmStat.NrActiveAnon = fv case "nr_inactive_file": vmStat.NrInactiveFile = fv case "nr_active_file": vmStat.NrActiveFile = fv case "nr_unevictable": vmStat.NrUnevictable = fv case "nr_slab_reclaimable": vmStat.NrSlabReclaimable = fv case "nr_slab_unreclaimable": vmStat.NrSlabUnreclaimable = fv case "nr_isolated_anon": vmStat.NrIsolatedAnon = fv case "nr_isolated_file": vmStat.NrIsolatedFile = fv case "workingset_nodes": vmStat.WorkingsetNodes = fv case "workingset_refault": vmStat.WorkingsetRefault = fv case "workingset_activate": vmStat.WorkingsetActivate = fv case "workingset_restore": vmStat.WorkingsetRestore = fv case "workingset_nodereclaim": vmStat.WorkingsetNodereclaim = fv case "nr_anon_pages": vmStat.NrAnonPages = fv case "nr_mapped": vmStat.NrMapped = fv case "nr_file_pages": vmStat.NrFilePages = fv case "nr_dirty": vmStat.NrDirty = fv case "nr_writeback": vmStat.NrWriteback = fv case "nr_writeback_temp": vmStat.NrWritebackTemp = fv case "nr_shmem": vmStat.NrShmem = fv case "nr_shmem_hugepages": vmStat.NrShmemHugepages = fv case "nr_shmem_pmdmapped": vmStat.NrShmemPmdmapped = fv case "nr_file_hugepages": vmStat.NrFileHugepages = fv case "nr_file_pmdmapped": vmStat.NrFilePmdmapped = fv case "nr_anon_transparent_hugepages": vmStat.NrAnonTransparentHugepages = fv case "nr_vmscan_write": vmStat.NrVmscanWrite = fv case "nr_vmscan_immediate_reclaim": vmStat.NrVmscanImmediateReclaim = fv case "nr_dirtied": vmStat.NrDirtied = fv case "nr_written": vmStat.NrWritten = fv case "nr_kernel_misc_reclaimable": vmStat.NrKernelMiscReclaimable = fv case "nr_foll_pin_acquired": vmStat.NrFollPinAcquired = fv case "nr_foll_pin_released": vmStat.NrFollPinReleased = fv } } return vmStat, scanner.Err() } golang-github-prometheus-procfs-0.14.0/sysfs/vmstat_numa_test.go000066400000000000000000000026131461002754700251110ustar00rootroot00000000000000// Copyright 2020 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. //go:build linux // +build linux package sysfs import ( "testing" ) func TestParseVMStatNUMA(t *testing.T) { fs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(err) } vmstat, err := fs.VMStatNUMA() if err != nil { t.Fatal(err) } if want, got := uint64(1), vmstat[1].NrFreePages; want != got { t.Errorf("want vmstat stat nr_free_pages value %d, got %d", want, got) } if want, got := uint64(5), vmstat[1].NrZoneActiveFile; want != got { t.Errorf("want numa stat nr_zone_active_file %d, got %d", want, got) } if want, got := uint64(7), vmstat[2].NrFreePages; want != got { t.Errorf("want vmstat stat nr_free_pages value %d, got %d", want, got) } if want, got := uint64(11), vmstat[2].NrZoneActiveFile; want != got { t.Errorf("want numa stat nr_zone_active_file %d, got %d", want, got) } } golang-github-prometheus-procfs-0.14.0/sysfs/vulnerability.go000066400000000000000000000066171461002754700244150ustar00rootroot00000000000000// 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. //go:build linux // +build linux package sysfs import ( "os" "path/filepath" "strings" ) const ( notAffected = "not affected" // based on: https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-system-cpu vulnerable = "vulnerable" mitigation = "mitigation" unknown = "unknown" ) const ( VulnerabilityStateNotAffected = iota VulnerabilityStateVulnerable VulnerabilityStateMitigation VulnerabilityStateUnknown ) var ( // VulnerabilityHumanEncoding allows mapping the vulnerability state (encoded as an int) onto a human friendly // string. It can be used by consumers of this library to expose to the user the state of the vulnerability. VulnerabilityHumanEncoding = map[int]string{ VulnerabilityStateNotAffected: notAffected, VulnerabilityStateVulnerable: vulnerable, VulnerabilityStateMitigation: mitigation, VulnerabilityStateUnknown: unknown, } ) // CPUVulnerabilities retrieves a map of vulnerability names to their mitigations. func (fs FS) CPUVulnerabilities() (map[string]*Vulnerability, error) { matchingFilepaths, err := filepath.Glob(fs.sys.Path("devices/system/cpu/vulnerabilities/*")) if err != nil { return nil, err } vulnerabilities := make(map[string]*Vulnerability, len(matchingFilepaths)) for _, path := range matchingFilepaths { filename := filepath.Base(path) rawContent, err := os.ReadFile(path) if err != nil { return nil, err } v, err := parseVulnerability(filename, string(rawContent)) if err != nil { return nil, err } vulnerabilities[filename] = v } return vulnerabilities, nil } // Vulnerability represents a single vulnerability extracted from /sys/devices/system/cpu/vulnerabilities/. type Vulnerability struct { CodeName string State int Mitigation string } func parseVulnerability(name, rawContent string) (*Vulnerability, error) { v := &Vulnerability{CodeName: name} rawContent = strings.TrimSpace(rawContent) rawContentLower := strings.ToLower(rawContent) switch { case strings.HasPrefix(rawContentLower, notAffected): v.State = VulnerabilityStateNotAffected case strings.HasPrefix(rawContentLower, vulnerable): v.State = VulnerabilityStateVulnerable m := strings.Fields(rawContent) if len(m) > 1 { v.Mitigation = strings.Join(m[1:], " ") } case strings.HasPrefix(rawContentLower, mitigation): v.State = VulnerabilityStateMitigation m := strings.Fields(rawContent) if len(m) > 1 { v.Mitigation = strings.Join(m[1:], " ") } case strings.HasPrefix(rawContentLower, unknown): v.State = VulnerabilityStateUnknown m := strings.Fields(rawContent) if len(m) > 1 { v.Mitigation = strings.Join(m[1:], " ") } default: // Output the raw data obtained from the vulnerability, with state // unknown, rather than erroring out v.State = VulnerabilityStateUnknown v.Mitigation = rawContent } return v, nil } golang-github-prometheus-procfs-0.14.0/sysfs/vulnerability_test.go000066400000000000000000000061671461002754700254540ustar00rootroot00000000000000// Copyright 2023 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. //go:build linux // +build linux package sysfs import ( "fmt" "reflect" "testing" ) func TestFS_CPUVulnerabilities(t *testing.T) { sysFs, err := NewFS(sysTestFixtures) if err != nil { t.Fatal(fmt.Errorf("failed to get sysfs FS: %w", err)) } got, err := sysFs.CPUVulnerabilities() if err != nil { t.Fatal(fmt.Errorf("failed to parse sysfs vulnerabilities files: %w", err)) } tests := []struct { name string vulnerabilityName string want *Vulnerability wantErr bool }{ {"Not affected", "tsx_async_abort", &Vulnerability{CodeName: "tsx_async_abort", State: VulnerabilityStateNotAffected, Mitigation: ""}, false}, {"Mitigation simple string", "spec_store_bypass", &Vulnerability{CodeName: "spec_store_bypass", State: VulnerabilityStateMitigation, Mitigation: "Speculative Store Bypass disabled via prctl"}, false}, {"Mitigation special chars", "retbleed", &Vulnerability{CodeName: "retbleed", State: VulnerabilityStateMitigation, Mitigation: "untrained return thunk; SMT enabled with STIBP protection"}, false}, {"Mitigation more special chars", "spectre_v1", &Vulnerability{CodeName: "spectre_v1", State: VulnerabilityStateMitigation, Mitigation: "usercopy/swapgs barriers and __user pointer sanitization"}, false}, {"Mitigation with multiple subsections", "spectre_v2", &Vulnerability{CodeName: "spectre_v2", State: VulnerabilityStateMitigation, Mitigation: "Retpolines, IBPB: conditional, STIBP: always-on, RSB filling, PBRSB-eIBRS: Not affected"}, false}, {"Vulnerable", "mds", &Vulnerability{CodeName: "mds", State: VulnerabilityStateVulnerable, Mitigation: ""}, false}, {"Vulnerable with mitigation available", "mmio_stale_data", &Vulnerability{CodeName: "mmio_stale_data", State: VulnerabilityStateVulnerable, Mitigation: "Clear CPU buffers attempted, no microcode"}, false}, {"Unknown", "srbds", &Vulnerability{CodeName: "srbds", State: VulnerabilityStateUnknown, Mitigation: "Dependent on hypervisor status"}, false}, {"Unknown with unparseable mitigation", "itlb_multihit", &Vulnerability{CodeName: "itlb_multihit", State: VulnerabilityStateUnknown, Mitigation: "KVM: Mitigation: VMX unsupported"}, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { gotVulnerability, ok := got[tt.vulnerabilityName] if !ok && !tt.wantErr { t.Errorf("CPUVulnerabilities() vulnerability %s not found", tt.vulnerabilityName) } if !reflect.DeepEqual(gotVulnerability, tt.want) { t.Errorf("CPUVulnerabilities() gotVulnerability = %v, want %v", gotVulnerability, tt.want) } }) } } golang-github-prometheus-procfs-0.14.0/testdata/000077500000000000000000000000001461002754700216255ustar00rootroot00000000000000golang-github-prometheus-procfs-0.14.0/testdata/fixtures.ttar000066400000000000000000033223061461002754700244030ustar00rootroot00000000000000# Archive created by ttar -c -f testdata/fixtures.ttar -C testdata/ fixtures/ Directory: fixtures Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/26231 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/cmdline Lines: 1 vimNULLBYTEtest.goNULLBYTE+10NULLBYTEEOF Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/comm Lines: 1 vim Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/cwd SymlinkTo: /usr/bin # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/environ Lines: 1 PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binNULLBYTEHOSTNAME=cd24e11f73a5NULLBYTETERM=xtermNULLBYTEGOLANG_VERSION=1.12.5NULLBYTEGOPATH=/goNULLBYTEHOME=/rootNULLBYTEEOF Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/exe SymlinkTo: /usr/bin/vim # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/26231/fd Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/fd/0 SymlinkTo: ../../symlinktargets/abc # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/fd/1 SymlinkTo: ../../symlinktargets/def # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/fd/10 SymlinkTo: ../../symlinktargets/xyz # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/fd/2 SymlinkTo: ../../symlinktargets/ghi # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/fd/3 SymlinkTo: ../../symlinktargets/uvw # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/26231/fdinfo Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/fdinfo/0 Lines: 6 pos: 0 flags: 02004000 mnt_id: 13 inotify wd:3 ino:1 sdev:34 mask:fce ignored_mask:0 fhandle-bytes:c fhandle-type:81 f_handle:000000000100000000000000 inotify wd:2 ino:1300016 sdev:fd00002 mask:fce ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:16003001ed3f022a inotify wd:1 ino:2e0001 sdev:fd00000 mask:fce ignored_mask:0 fhandle-bytes:8 fhandle-type:1 f_handle:01002e00138e7c65 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/fdinfo/1 Lines: 4 pos: 0 flags: 02004002 mnt_id: 13 eventfd-count: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/fdinfo/10 Lines: 3 pos: 0 flags: 02004002 mnt_id: 9 Mode: 400 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/fdinfo/2 Lines: 3 pos: 0 flags: 02004002 mnt_id: 9 Mode: 400 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/fdinfo/3 Lines: 3 pos: 0 flags: 02004002 mnt_id: 9 Mode: 400 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/interrupts Lines: 49 CPU0 CPU1 CPU2 CPU3 0: 49 0 0 0 IO-APIC 2-edge timer 1: 0 0 0 9 IO-APIC 1-edge i8042 4: 0 1443 0 0 IO-APIC 4-edge ttyS0 8: 1 0 0 0 IO-APIC 8-edge rtc0 9: 0 0 0 0 IO-APIC 9-fasteoi acpi 12: 0 0 144 0 IO-APIC 12-edge i8042 22: 0 0 0 5 IO-APIC 22-fasteoi virtio1 24: 0 0 0 0 PCI-MSI 114688-edge virtio5-config 25: 1800 0 0 0 PCI-MSI 114689-edge virtio5-req.0 26: 0 1469 0 0 PCI-MSI 114690-edge virtio5-req.1 27: 0 0 2654 0 PCI-MSI 114691-edge virtio5-req.2 28: 0 0 0 1989 PCI-MSI 114692-edge virtio5-req.3 29: 1362 0 0 934 PCI-MSI 512000-edge ahci[0000:00:1f.2] 30: 0 0 0 0 PCI-MSI 98304-edge xhci_hcd 31: 0 0 0 0 PCI-MSI 98305-edge xhci_hcd 32: 0 0 0 0 PCI-MSI 98306-edge xhci_hcd 33: 0 0 0 0 PCI-MSI 98307-edge xhci_hcd 34: 0 0 0 0 PCI-MSI 98308-edge xhci_hcd 35: 0 0 0 0 PCI-MSI 16384-edge virtio0-config 36: 0 335 37 0 PCI-MSI 16385-edge virtio0-input.0 37: 0 0 0 318 PCI-MSI 16386-edge virtio0-output.0 38: 0 0 0 0 PCI-MSI 49152-edge virtio2-config 39: 1243 178 0 0 PCI-MSI 49153-edge virtio2-control 40: 0 0 0 0 PCI-MSI 49154-edge virtio2-cursor 41: 0 0 0 0 PCI-MSI 65536-edge virtio3-config 42: 0 0 0 0 PCI-MSI 65537-edge virtio3-virtqueues 43: 0 0 0 0 PCI-MSI 81920-edge virtio4-config 44: 0 0 0 0 PCI-MSI 81921-edge virtio4-virtqueues NMI: 0 0 0 0 Non-maskable interrupts LOC: 10196 7429 8542 8229 Local timer interrupts SPU: 0 0 0 0 Spurious interrupts PMI: 0 0 0 0 Performance monitoring interrupts IWI: 0 3 11 6 IRQ work interrupts RTR: 0 0 0 0 APIC ICR read retries RES: 7997 11147 10898 12675 Rescheduling interrupts CAL: 2761 2485 1787 2367 Function call interrupts TLB: 212 137 158 231 TLB shootdowns TRM: 0 0 0 0 Thermal event interrupts THR: 0 0 0 0 Threshold APIC interrupts DFR: 0 0 0 0 Deferred Error APIC interrupts MCE: 0 0 0 0 Machine check exceptions MCP: 1 1 1 1 Machine check polls ERR: 0 MIS: 0 PIN: 0 0 0 0 Posted-interrupt notification event NPI: 0 0 0 0 Nested posted-interrupt event PIW: 0 0 0 0 Posted-interrupt wakeup event Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/io Lines: 7 rchar: 750339 wchar: 818609 syscr: 7405 syscw: 5245 read_bytes: 1024 write_bytes: 2048 cancelled_write_bytes: -1024 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/limits Lines: 17 Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Max file size unlimited unlimited bytes Max data size unlimited unlimited bytes Max stack size 8388608 unlimited bytes Max core file size 0 unlimited bytes Max resident set unlimited unlimited bytes Max processes 62898 62898 processes Max open files 2048 4096 files Max locked memory 18446744073708503040 18446744073708503040 bytes Max address space 8589934592 unlimited bytes Max file locks unlimited unlimited locks Max pending signals 62898 62898 signals Max msgqueue size 819200 819200 bytes Max nice priority 0 0 Max realtime priority 0 0 Max realtime timeout unlimited unlimited us Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/mountstats Lines: 20 device rootfs mounted on / with fstype rootfs device sysfs mounted on /sys with fstype sysfs device proc mounted on /proc with fstype proc device /dev/sda1 mounted on / with fstype ext4 device 192.168.1.1:/srv/test mounted on /mnt/nfs/test with fstype nfs4 statvers=1.1 opts: rw,vers=4.0,rsize=1048576,wsize=1048576,namlen=255,acregmin=3,acregmax=60,acdirmin=30,acdirmax=60,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,mountaddr=192.168.1.1,clientaddr=192.168.1.5,local_lock=none age: 13968 caps: caps=0xfff7,wtmult=512,dtsize=32768,bsize=0,namlen=255 nfsv4: bm0=0xfdffafff,bm1=0xf9be3e,bm2=0x0,acl=0x0,pnfs=not configured sec: flavor=1,pseudoflavor=1 events: 52 226 0 0 1 13 398 0 0 331 0 47 0 0 77 0 0 77 0 0 0 0 0 0 0 0 0 bytes: 1207640230 0 0 0 1210214218 0 295483 0 RPC iostats version: 1.0 p/v: 100003/4 (nfs) xprt: tcp 832 0 1 0 11 6428 6428 0 12154 0 24 26 5726 per-op statistics NULL: 0 0 0 0 0 0 0 0 READ: 1298 1298 0 207680 1210292152 6 79386 79407 WRITE: 0 0 0 0 0 0 0 0 ACCESS: 2927395007 2927394995 0 526931094212 362996810236 18446743919241604546 1667369447 1953587717 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/26231/net Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/net/dev Lines: 4 Inter-| Receive | Transmit face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed lo: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 eth0: 438 5 0 0 0 0 0 0 648 8 0 0 0 0 0 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/net/netstat Lines: 4 TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed EmbryonicRsts PruneCalled RcvPruned OfoPruned OutOfWindowIcmps LockDroppedIcmps ArpFilter TW TWRecycled TWKilled PAWSActive PAWSEstab DelayedACKs DelayedACKLocked DelayedACKLost ListenOverflows ListenDrops TCPHPHits TCPPureAcks TCPHPAcks TCPRenoRecovery TCPSackRecovery TCPSACKReneging TCPSACKReorder TCPRenoReorder TCPTSReorder TCPFullUndo TCPPartialUndo TCPDSACKUndo TCPLossUndo TCPLostRetransmit TCPRenoFailures TCPSackFailures TCPLossFailures TCPFastRetrans TCPSlowStartRetrans TCPTimeouts TCPLossProbes TCPLossProbeRecovery TCPRenoRecoveryFail TCPSackRecoveryFail TCPRcvCollapsed TCPDSACKOldSent TCPDSACKOfoSent TCPDSACKRecv TCPDSACKOfoRecv TCPAbortOnData TCPAbortOnClose TCPAbortOnMemory TCPAbortOnTimeout TCPAbortOnLinger TCPAbortFailed TCPMemoryPressures TCPMemoryPressuresChrono TCPSACKDiscard TCPDSACKIgnoredOld TCPDSACKIgnoredNoUndo TCPSpuriousRTOs TCPMD5NotFound TCPMD5Unexpected TCPMD5Failure TCPSackShifted TCPSackMerged TCPSackShiftFallback TCPBacklogDrop PFMemallocDrop TCPMinTTLDrop TCPDeferAcceptDrop IPReversePathFilter TCPTimeWaitOverflow TCPReqQFullDoCookies TCPReqQFullDrop TCPRetransFail TCPRcvCoalesce TCPRcvQDrop TCPOFOQueue TCPOFODrop TCPOFOMerge TCPChallengeACK TCPSYNChallenge TCPFastOpenActive TCPFastOpenActiveFail TCPFastOpenPassive TCPFastOpenPassiveFail TCPFastOpenListenOverflow TCPFastOpenCookieReqd TCPFastOpenBlackhole TCPSpuriousRtxHostQueues BusyPollRxPackets TCPAutoCorking TCPFromZeroWindowAdv TCPToZeroWindowAdv TCPWantZeroWindowAdv TCPSynRetrans TCPOrigDataSent TCPHystartTrainDetect TCPHystartTrainCwnd TCPHystartDelayDetect TCPHystartDelayCwnd TCPACKSkippedSynRecv TCPACKSkippedPAWS TCPACKSkippedSeq TCPACKSkippedFinWait2 TCPACKSkippedTimeWait TCPACKSkippedChallenge TCPWinProbe TCPKeepAlive TCPMTUPFail TCPMTUPSuccess TCPWqueueTooBig TcpExt: 0 0 0 1 0 0 0 0 0 0 83 0 0 0 3640 287 1 7460 0 0 134193 1335 829 0 4 0 1 0 0 0 0 1 19 0 0 0 0 0 3 0 32 100 4 0 0 0 7460 2421 49 1 62 6 0 23 0 7 0 0 0 0 19 2 0 0 0 0 0 6 0 0 0 0 3 0 0 0 0 92425 65515 0 2421 4 4 0 0 0 0 0 0 0 0 0 10 0 0 0 16 2221 0 0 2 45 0 0 3 0 0 0 0 456 0 0 0 IpExt: InNoRoutes InTruncatedPkts InMcastPkts OutMcastPkts InBcastPkts OutBcastPkts InOctets OutOctets InMcastOctets OutMcastOctets InBcastOctets OutBcastOctets InCsumErrors InNoECTPkts InECT1Pkts InECT0Pkts InCEPkts ReasmOverlaps IpExt: 0 0 208 214 118 111 190585481 7512674 26093 25903 14546 13628 0 134215 0 0 0 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/net/snmp Lines: 12 Ip: Forwarding DefaultTTL InReceives InHdrErrors InAddrErrors ForwDatagrams InUnknownProtos InDiscards InDelivers OutRequests OutDiscards OutNoRoutes ReasmTimeout ReasmReqds ReasmOKs ReasmFails FragOKs FragFails FragCreates Ip: 2 64 594223 0 1 0 0 0 593186 547253 20 231 0 0 0 0 0 0 0 Icmp: InMsgs InErrors InCsumErrors InDestUnreachs InTimeExcds InParmProbs InSrcQuenchs InRedirects InEchos InEchoReps InTimestamps InTimestampReps InAddrMasks InAddrMaskReps OutMsgs OutErrors OutDestUnreachs OutTimeExcds OutParmProbs OutSrcQuenchs OutRedirects OutEchos OutEchoReps OutTimestamps OutTimestampReps OutAddrMasks OutAddrMaskReps Icmp: 45 1 0 45 0 0 0 0 0 0 0 0 0 0 50 0 50 0 0 0 0 0 0 0 0 0 0 IcmpMsg: InType3 OutType3 IcmpMsg: 45 50 Tcp: RtoAlgorithm RtoMin RtoMax MaxConn ActiveOpens PassiveOpens AttemptFails EstabResets CurrEstab InSegs OutSegs RetransSegs InErrs OutRsts InCsumErrors Tcp: 1 200 120000 -1 1103 9 8 51 15 653161 594855 348 98 1038 0 Udp: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors InCsumErrors IgnoredMulti Udp: 10179 50 0 9846 0 0 0 58 UdpLite: InDatagrams NoPorts InErrors OutDatagrams RcvbufErrors SndbufErrors InCsumErrors IgnoredMulti UdpLite: 0 0 0 0 0 0 0 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/net/snmp6 Lines: 92 Ip6InReceives 92166 Ip6InHdrErrors 0 Ip6InTooBigErrors 0 Ip6InNoRoutes 0 Ip6InAddrErrors 0 Ip6InUnknownProtos 0 Ip6InTruncatedPkts 0 Ip6InDiscards 0 Ip6InDelivers 92053 Ip6OutForwDatagrams 0 Ip6OutRequests 57502 Ip6OutDiscards 0 Ip6OutNoRoutes 169 Ip6ReasmTimeout 0 Ip6ReasmReqds 0 Ip6ReasmOKs 0 Ip6ReasmFails 0 Ip6FragOKs 0 Ip6FragFails 0 Ip6FragCreates 0 Ip6InMcastPkts 381 Ip6OutMcastPkts 148 Ip6InOctets 113479132 Ip6OutOctets 9842685 Ip6InMcastOctets 65971 Ip6OutMcastOctets 19394 Ip6InBcastOctets 0 Ip6OutBcastOctets 0 Ip6InNoECTPkts 92166 Ip6InECT1Pkts 0 Ip6InECT0Pkts 0 Ip6InCEPkts 0 Icmp6InMsgs 142 Icmp6InErrors 0 Icmp6OutMsgs 58 Icmp6OutErrors 0 Icmp6InCsumErrors 0 Icmp6InDestUnreachs 2 Icmp6InPktTooBigs 0 Icmp6InTimeExcds 0 Icmp6InParmProblems 0 Icmp6InEchos 0 Icmp6InEchoReplies 0 Icmp6InGroupMembQueries 0 Icmp6InGroupMembResponses 0 Icmp6InGroupMembReductions 0 Icmp6InRouterSolicits 0 Icmp6InRouterAdvertisements 111 Icmp6InNeighborSolicits 26 Icmp6InNeighborAdvertisements 1 Icmp6InRedirects 0 Icmp6InMLDv2Reports 2 Icmp6OutDestUnreachs 0 Icmp6OutPktTooBigs 0 Icmp6OutTimeExcds 0 Icmp6OutParmProblems 0 Icmp6OutEchos 0 Icmp6OutEchoReplies 0 Icmp6OutGroupMembQueries 0 Icmp6OutGroupMembResponses 0 Icmp6OutGroupMembReductions 0 Icmp6OutRouterSolicits 2 Icmp6OutRouterAdvertisements 0 Icmp6OutNeighborSolicits 5 Icmp6OutNeighborAdvertisements 26 Icmp6OutRedirects 0 Icmp6OutMLDv2Reports 25 Icmp6InType1 2 Icmp6InType134 111 Icmp6InType135 26 Icmp6InType136 1 Icmp6InType143 2 Icmp6OutType133 2 Icmp6OutType135 5 Icmp6OutType136 26 Icmp6OutType143 25 Udp6InDatagrams 2016 Udp6NoPorts 0 Udp6InErrors 0 Udp6OutDatagrams 1546 Udp6RcvbufErrors 0 Udp6SndbufErrors 0 Udp6InCsumErrors 0 Udp6IgnoredMulti 12 UdpLite6InDatagrams 0 UdpLite6NoPorts 0 UdpLite6InErrors 0 UdpLite6OutDatagrams 0 UdpLite6RcvbufErrors 0 UdpLite6SndbufErrors 0 UdpLite6InCsumErrors 0 Mode: 644 Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/26231/ns Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/ns/mnt SymlinkTo: mnt:[4026531840] # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/ns/net SymlinkTo: net:[4026531993] # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/root SymlinkTo: / # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/schedstat Lines: 1 411605849 93680043 79 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/smaps Lines: 252 00400000-00cb1000 r-xp 00000000 fd:01 952273 /bin/alertmanager Size: 8900 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Rss: 2952 kB Pss: 2952 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 2952 kB Private_Dirty: 0 kB Referenced: 2864 kB Anonymous: 0 kB LazyFree: 0 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 0 kB SwapPss: 0 kB Locked: 0 kB VmFlags: rd ex mr mw me dw sd 00cb1000-016b0000 r--p 008b1000 fd:01 952273 /bin/alertmanager Size: 10236 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Rss: 6152 kB Pss: 6152 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 6152 kB Private_Dirty: 0 kB Referenced: 5308 kB Anonymous: 0 kB LazyFree: 0 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 0 kB SwapPss: 0 kB Locked: 0 kB VmFlags: rd mr mw me dw sd 016b0000-0171a000 rw-p 012b0000 fd:01 952273 /bin/alertmanager Size: 424 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Rss: 176 kB Pss: 176 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 84 kB Private_Dirty: 92 kB Referenced: 176 kB Anonymous: 92 kB LazyFree: 0 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 12 kB SwapPss: 12 kB Locked: 0 kB VmFlags: rd wr mr mw me dw ac sd 0171a000-0173f000 rw-p 00000000 00:00 0 Size: 148 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Rss: 76 kB Pss: 76 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 76 kB Referenced: 76 kB Anonymous: 76 kB LazyFree: 0 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 0 kB SwapPss: 0 kB Locked: 0 kB VmFlags: rd wr mr mw me ac sd c000000000-c000400000 rw-p 00000000 00:00 0 Size: 4096 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Rss: 2564 kB Pss: 2564 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 20 kB Private_Dirty: 2544 kB Referenced: 2544 kB Anonymous: 2564 kB LazyFree: 0 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 1100 kB SwapPss: 1100 kB Locked: 0 kB VmFlags: rd wr mr mw me ac sd c000400000-c001600000 rw-p 00000000 00:00 0 Size: 18432 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Rss: 16024 kB Pss: 16024 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 5864 kB Private_Dirty: 10160 kB Referenced: 11944 kB Anonymous: 16024 kB LazyFree: 5848 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 440 kB SwapPss: 440 kB Locked: 0 kB VmFlags: rd wr mr mw me ac sd nh c001600000-c004000000 rw-p 00000000 00:00 0 Size: 43008 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Rss: 0 kB Pss: 0 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 0 kB Referenced: 0 kB Anonymous: 0 kB LazyFree: 0 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 0 kB SwapPss: 0 kB Locked: 0 kB VmFlags: rd wr mr mw me ac sd 7f0ab95ca000-7f0abbb7b000 rw-p 00000000 00:00 0 Size: 38596 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Rss: 1992 kB Pss: 1992 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 476 kB Private_Dirty: 1516 kB Referenced: 1828 kB Anonymous: 1992 kB LazyFree: 0 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 384 kB SwapPss: 384 kB Locked: 0 kB VmFlags: rd wr mr mw me ac sd 7ffc07ecf000-7ffc07ef0000 rw-p 00000000 00:00 0 [stack] Size: 132 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Rss: 8 kB Pss: 8 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 8 kB Referenced: 8 kB Anonymous: 8 kB LazyFree: 0 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 4 kB SwapPss: 4 kB Locked: 0 kB VmFlags: rd wr mr mw me gd ac 7ffc07f9e000-7ffc07fa1000 r--p 00000000 00:00 0 [vvar] Size: 12 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Rss: 0 kB Pss: 0 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 0 kB Referenced: 0 kB Anonymous: 0 kB LazyFree: 0 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 0 kB SwapPss: 0 kB Locked: 0 kB VmFlags: rd mr pf io de dd sd 7ffc07fa1000-7ffc07fa3000 r-xp 00000000 00:00 0 [vdso] Size: 8 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Rss: 4 kB Pss: 0 kB Shared_Clean: 4 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 0 kB Referenced: 4 kB Anonymous: 0 kB LazyFree: 0 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 0 kB SwapPss: 0 kB Locked: 0 kB VmFlags: rd ex mr mw me de sd ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] Size: 4 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Rss: 0 kB Pss: 0 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 0 kB Referenced: 0 kB Anonymous: 0 kB LazyFree: 0 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 0 kB SwapPss: 0 kB Locked: 0 kB VmFlags: rd ex Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/smaps_rollup Lines: 17 00400000-ffffffffff601000 ---p 00000000 00:00 0 [rollup] Rss: 29948 kB Pss: 29944 kB Shared_Clean: 4 kB Shared_Dirty: 0 kB Private_Clean: 15548 kB Private_Dirty: 14396 kB Referenced: 24752 kB Anonymous: 20756 kB LazyFree: 5848 kB AnonHugePages: 0 kB ShmemPmdMapped: 0 kB Shared_Hugetlb: 0 kB Private_Hugetlb: 0 kB Swap: 1940 kB SwapPss: 1940 kB Locked: 0 kB Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/stat Lines: 1 26231 (vim) R 5392 7446 5392 34835 7446 4218880 32533 309516 26 82 1677 44 158 99 20 0 1 0 82375 56274944 1981 18446744073709551615 4194304 6294284 140736914091744 140736914087944 139965136429984 0 0 12288 1870679807 0 0 0 17 0 0 0 31 0 0 8391624 8481048 16420864 140736914093252 140736914093279 140736914093279 140736914096107 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/status Lines: 53 Name: prometheus Umask: 0022 State: S (sleeping) Tgid: 26231 Ngid: 0 Pid: 26231 PPid: 1 TracerPid: 0 Uid: 1000 1000 1000 0 Gid: 1001 1001 1001 0 FDSize: 128 Groups: NStgid: 1 NSpid: 1 NSpgid: 1 NSsid: 1 VmPeak: 58472 kB VmSize: 58440 kB VmLck: 0 kB VmPin: 0 kB VmHWM: 8028 kB VmRSS: 6716 kB RssAnon: 2092 kB RssFile: 4624 kB RssShmem: 0 kB VmData: 2580 kB VmStk: 136 kB VmExe: 948 kB VmLib: 6816 kB VmPTE: 128 kB VmPMD: 12 kB VmSwap: 660 kB HugetlbPages: 0 kB Threads: 1 SigQ: 8/63965 SigPnd: 0000000000000000 ShdPnd: 0000000000000000 SigBlk: 7be3c0fe28014a03 SigIgn: 0000000000001000 SigCgt: 00000001800004ec CapInh: 0000000000000000 CapPrm: 0000003fffffffff CapEff: 0000003fffffffff CapBnd: 0000003fffffffff CapAmb: 0000000000000000 Seccomp: 0 Cpus_allowed: ff Cpus_allowed_list: 0-7 Mems_allowed: 00000000,00000001 Mems_allowed_list: 0 voluntary_ctxt_switches: 4742839 nonvoluntary_ctxt_switches: 1727500 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26231/wchan Lines: 1 poll_schedule_timeoutEOF Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/26232 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26232/cmdline Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26232/comm Lines: 1 ata_sff Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26232/cwd SymlinkTo: /does/not/exist # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/26232/fd Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26232/fd/0 SymlinkTo: ../../symlinktargets/abc # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26232/fd/1 SymlinkTo: ../../symlinktargets/def # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26232/fd/2 SymlinkTo: ../../symlinktargets/ghi # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26232/fd/3 SymlinkTo: ../../symlinktargets/uvw # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26232/fd/4 SymlinkTo: ../../symlinktargets/xyz # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26232/limits Lines: 17 Limit Soft Limit Hard Limit Units Max cpu time unlimited unlimited seconds Max file size unlimited unlimited bytes Max data size unlimited unlimited bytes Max stack size 8388608 unlimited bytes Max core file size 0 unlimited bytes Max resident set unlimited unlimited bytes Max processes 29436 29436 processes Max open files 1024 4096 files Max locked memory 65536 65536 bytes Max address space unlimited unlimited bytes Max file locks unlimited unlimited locks Max pending signals 29436 29436 signals Max msgqueue size 819200 819200 bytes Max nice priority 0 0 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 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26232/stat Lines: 1 33 (ata_sff) S 2 0 0 0 -1 69238880 0 0 0 0 0 0 -9223372036854775808 9223372036854775807 0 -20 1 0 5 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 18446744073709551615 0 0 -9223372036854775808 9223372036854775807 0 0 0 0 0 0 0 0 0 0 0 0 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26232/wchan Lines: 1 0EOF Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/26233 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26233/cmdline Lines: 1 com.github.uiautomatorNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTEEOF Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26233/schedstat Lines: 8 ____________________________________ < this is a malformed schedstat file > ------------------------------------ \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || || 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/26235 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26235/status Lines: 51 Name: kube-proxy Umask: 0022 State: S (sleeping) Tgid: 26235 Ngid: 12345 Pid: 26235 PPid: 1234 TracerPid: 0 Uid: 0 0 0 0 Gid: 0 0 0 0 FDSize: 64 Groups: NStgid: 26235 1 NSpid: 26235 1 NSpgid: 26235 1 NSsid: 26235 1 VmPeak: 758200 kB VmSize: 758200 kB VmLck: 0 kB VmPin: 0 kB VmHWM: 61776 kB VmRSS: 42652 kB RssAnon: 24852 kB RssFile: 17800 kB RssShmem: 0 kB VmData: 117136 kB VmStk: 132 kB VmExe: 21568 kB VmLib: 4 kB VmPTE: 264 kB VmSwap: 0 kB HugetlbPages: 0 kB Threads: 51 SigQ: 9/511324 SigPnd: 0000000000000000 ShdPnd: 0000000000000000 SigBlk: 0000000000000000 SigIgn: 0000000000000000 SigCgt: fffffffc7fc1feff CapInh: 0000003fffffffff CapPrm: 0000003fffffffff CapEff: 0000003fffffffff CapBnd: 0000003fffffffff CapAmb: 0000000000000000 Seccomp: 0 Cpus_allowed: ff Cpus_allowed_list: 0-7 Mems_allowed: 00000000,00000001 Mems_allowed_list: 0 voluntary_ctxt_switches: 4742839 nonvoluntary_ctxt_switches: 1727500 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/27079 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/27079/stat Lines: 1 27079 (pthread_load) S 1 27079 1 34816 27079 4194304 113 0 1 0 58125 15 0 0 20 0 5 0 4289574 36282368 138 18446744073709551615 94441498279936 94441498282741 140736878632528 0 0 0 0 0 0 0 0 0 17 2 0 0 0 0 0 94441498291504 94441498292248 94441510707200 140736878639434 140736878639460 140736878639460 140736878641129 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/27079/task Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/27079/task/27079 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/27079/task/27079/stat Lines: 1 27079 (pthread_load) S 1 27079 1 34816 27079 4194304 97 0 1 0 0 0 0 0 20 0 5 0 4289574 36282368 138 18446744073709551615 94441498279936 94441498282741 140736878632528 0 0 0 0 0 0 0 0 0 17 2 0 0 0 0 0 94441498291504 94441498292248 94441510707200 140736878639434 140736878639460 140736878639460 140736878641129 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/27079/task/27080 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/27079/task/27080/stat Lines: 1 27080 (pthread_load) R 1 27079 1 34816 27079 4194368 7 0 0 0 34136 3 0 0 20 0 5 0 4289575 36282368 138 18446744073709551615 94441498279936 94441498282741 140736878632528 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0 0 94441498291504 94441498292248 94441510707200 140736878639434 140736878639460 140736878639460 140736878641129 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/27079/task/27081 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/27079/task/27081/stat Lines: 1 27081 (pthread_load) S 1 27079 1 34816 27079 1077936192 3 0 0 0 13680 4 0 0 20 0 5 0 4289575 36282368 138 18446744073709551615 94441498279936 94441498282741 140736878632528 0 0 0 0 0 0 0 0 0 -1 5 0 0 0 0 0 94441498291504 94441498292248 94441510707200 140736878639434 140736878639460 140736878639460 140736878641129 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/27079/task/27082 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/27079/task/27082/stat Lines: 1 27082 (pthread_load) S 1 27079 1 34816 27079 1077936192 3 0 0 0 6859 3 0 0 20 0 5 0 4289575 36282368 138 18446744073709551615 94441498279936 94441498282741 140736878632528 0 0 0 0 0 0 0 0 0 -1 1 0 0 0 0 0 94441498291504 94441498292248 94441510707200 140736878639434 140736878639460 140736878639460 140736878641129 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/27079/task/27083 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/27079/task/27083/stat Lines: 1 27083 (pthread_load) S 1 27079 1 34816 27079 1077936192 3 0 0 0 3452 4 0 0 20 0 5 0 4289575 36282368 138 18446744073709551615 94441498279936 94441498282741 140736878632528 0 0 0 0 0 0 0 0 0 -1 4 0 0 0 0 0 94441498291504 94441498292248 94441510707200 140736878639434 140736878639460 140736878639460 140736878641129 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/584 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/584/stat Lines: 2 1020 ((a b ) ( c d) ) R 28378 1020 28378 34842 1020 4218880 286 0 0 0 0 0 0 0 20 0 1 0 10839175 10395648 155 18446744073709551615 4194304 4238788 140736466511168 140736466511168 140609271124624 0 0 0 0 0 0 0 17 5 0 0 0 0 0 6336016 6337300 25579520 140736466515030 140736466515061 140736466515061 140736466518002 0 #!/bin/cat /proc/self/stat Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/buddyinfo Lines: 3 Node 0, zone DMA 1 0 1 0 2 1 1 0 1 1 3 Node 0, zone DMA32 759 572 791 475 194 45 12 0 0 0 0 Node 0, zone Normal 4381 1093 185 1530 567 102 4 0 0 0 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/cmdline Lines: 1 BOOT_IMAGE=/vmlinuz-5.11.0-22-generic root=UUID=456a0345-450d-4f7b-b7c9-43e3241d99ad ro quiet splash vt.handoff=7 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/cpuinfo Lines: 216 processor : 0 vendor_id : GenuineIntel cpu family : 6 model : 142 model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz stepping : 10 microcode : 0xb4 cpu MHz : 799.998 cache size : 8192 KB physical id : 0 siblings : 8 core id : 0 cpu cores : 4 apicid : 0 initial apicid : 0 fpu : yes fpu_exception : yes cpuid level : 22 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs bogomips : 4224.00 clflush size : 64 cache_alignment : 64 address sizes : 39 bits physical, 48 bits virtual power management: processor : 1 vendor_id : GenuineIntel cpu family : 6 model : 142 model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz stepping : 10 microcode : 0xb4 cpu MHz : 800.037 cache size : 8192 KB physical id : 0 siblings : 8 core id : 1 cpu cores : 4 apicid : 2 initial apicid : 2 fpu : yes fpu_exception : yes cpuid level : 22 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs bogomips : 4224.00 clflush size : 64 cache_alignment : 64 address sizes : 39 bits physical, 48 bits virtual power management: processor : 2 vendor_id : GenuineIntel cpu family : 6 model : 142 model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz stepping : 10 microcode : 0xb4 cpu MHz : 800.010 cache size : 8192 KB physical id : 0 siblings : 8 core id : 2 cpu cores : 4 apicid : 4 initial apicid : 4 fpu : yes fpu_exception : yes cpuid level : 22 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs bogomips : 4224.00 clflush size : 64 cache_alignment : 64 address sizes : 39 bits physical, 48 bits virtual power management: processor : 3 vendor_id : GenuineIntel cpu family : 6 model : 142 model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz stepping : 10 microcode : 0xb4 cpu MHz : 800.028 cache size : 8192 KB physical id : 0 siblings : 8 core id : 3 cpu cores : 4 apicid : 6 initial apicid : 6 fpu : yes fpu_exception : yes cpuid level : 22 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs bogomips : 4224.00 clflush size : 64 cache_alignment : 64 address sizes : 39 bits physical, 48 bits virtual power management: processor : 4 vendor_id : GenuineIntel cpu family : 6 model : 142 model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz stepping : 10 microcode : 0xb4 cpu MHz : 799.989 cache size : 8192 KB physical id : 0 siblings : 8 core id : 0 cpu cores : 4 apicid : 1 initial apicid : 1 fpu : yes fpu_exception : yes cpuid level : 22 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs bogomips : 4224.00 clflush size : 64 cache_alignment : 64 address sizes : 39 bits physical, 48 bits virtual power management: processor : 5 vendor_id : GenuineIntel cpu family : 6 model : 142 model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz stepping : 10 microcode : 0xb4 cpu MHz : 800.083 cache size : 8192 KB physical id : 0 siblings : 8 core id : 1 cpu cores : 4 apicid : 3 initial apicid : 3 fpu : yes fpu_exception : yes cpuid level : 22 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs bogomips : 4224.00 clflush size : 64 cache_alignment : 64 address sizes : 39 bits physical, 48 bits virtual power management: processor : 6 vendor_id : GenuineIntel cpu family : 6 model : 142 model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz stepping : 10 microcode : 0xb4 cpu MHz : 800.017 cache size : 8192 KB physical id : 0 siblings : 8 core id : 2 cpu cores : 4 apicid : 5 initial apicid : 5 fpu : yes fpu_exception : yes cpuid level : 22 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs bogomips : 4224.00 clflush size : 64 cache_alignment : 64 address sizes : 39 bits physical, 48 bits virtual power management: processor : 7 vendor_id : GenuineIntel cpu family : 6 model : 142 model name : Intel(R) Core(TM) i7-8650U CPU @ 1.90GHz stepping : 10 microcode : 0xb4 cpu MHz : 800.030 cache size : 8192 KB physical id : 0 siblings : 8 core id : 3 cpu cores : 4 apicid : 7 initial apicid : 7 fpu : yes fpu_exception : yes cpuid level : 22 wp : yes flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb invpcid_single pti ssbd ibrs ibpb stibp tpr_shadow vnmi flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 hle avx2 smep bmi2 erms invpcid rtm mpx rdseed adx smap clflushopt intel_pt xsaveopt xsavec xgetbv1 xsaves dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp md_clear flush_l1d bugs : cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs bogomips : 4224.00 clflush size : 64 cache_alignment : 64 address sizes : 39 bits physical, 48 bits virtual power management: Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/crypto Lines: 972 name : ccm(aes) driver : ccm_base(ctr(aes-aesni),cbcmac(aes-aesni)) module : ccm priority : 300 refcnt : 4 selftest : passed internal : no type : aead async : no blocksize : 1 ivsize : 16 maxauthsize : 16 geniv : name : cbcmac(aes) driver : cbcmac(aes-aesni) module : ccm priority : 300 refcnt : 7 selftest : passed internal : no type : shash blocksize : 1 digestsize : 16 name : ecdh driver : ecdh-generic module : ecdh_generic priority : 100 refcnt : 1 selftest : passed internal : no type : kpp async : yes name : ecb(arc4) driver : ecb(arc4)-generic module : arc4 priority : 100 refcnt : 1 selftest : passed internal : no type : skcipher async : no blocksize : 1 min keysize : 1 max keysize : 256 ivsize : 0 chunksize : 1 walksize : 1 name : arc4 driver : arc4-generic module : arc4 priority : 0 refcnt : 3 selftest : passed internal : no type : cipher blocksize : 1 min keysize : 1 max keysize : 256 name : crct10dif driver : crct10dif-pclmul module : crct10dif_pclmul priority : 200 refcnt : 2 selftest : passed internal : no type : shash blocksize : 1 digestsize : 2 name : crc32 driver : crc32-pclmul module : crc32_pclmul priority : 200 refcnt : 1 selftest : passed internal : no type : shash blocksize : 1 digestsize : 4 name : __ghash driver : cryptd(__ghash-pclmulqdqni) module : kernel priority : 50 refcnt : 1 selftest : passed internal : yes type : ahash async : yes blocksize : 16 digestsize : 16 name : ghash driver : ghash-clmulni module : ghash_clmulni_intel priority : 400 refcnt : 1 selftest : passed internal : no type : ahash async : yes blocksize : 16 digestsize : 16 name : __ghash driver : __ghash-pclmulqdqni module : ghash_clmulni_intel priority : 0 refcnt : 1 selftest : passed internal : yes type : shash blocksize : 16 digestsize : 16 name : crc32c driver : crc32c-intel module : crc32c_intel priority : 200 refcnt : 5 selftest : passed internal : no type : shash blocksize : 1 digestsize : 4 name : cbc(aes) driver : cbc(aes-aesni) module : kernel priority : 300 refcnt : 1 selftest : passed internal : no type : skcipher async : no blocksize : 16 min keysize : 16 max keysize : 32 ivsize : 16 chunksize : 16 walksize : 16 name : ctr(aes) driver : ctr(aes-aesni) module : kernel priority : 300 refcnt : 5 selftest : passed internal : no type : skcipher async : no blocksize : 1 min keysize : 16 max keysize : 32 ivsize : 16 chunksize : 16 walksize : 16 name : pkcs1pad(rsa,sha256) driver : pkcs1pad(rsa-generic,sha256) module : kernel priority : 100 refcnt : 1 selftest : passed internal : no type : akcipher name : __xts(aes) driver : cryptd(__xts-aes-aesni) module : kernel priority : 451 refcnt : 1 selftest : passed internal : yes type : skcipher async : yes blocksize : 16 min keysize : 32 max keysize : 64 ivsize : 16 chunksize : 16 walksize : 16 name : xts(aes) driver : xts-aes-aesni module : kernel priority : 401 refcnt : 1 selftest : passed internal : no type : skcipher async : yes blocksize : 16 min keysize : 32 max keysize : 64 ivsize : 16 chunksize : 16 walksize : 16 name : __ctr(aes) driver : cryptd(__ctr-aes-aesni) module : kernel priority : 450 refcnt : 1 selftest : passed internal : yes type : skcipher async : yes blocksize : 1 max keysize : 32 ivsize : 16 chunksize : 16 walksize : 16 name : ctr(aes) driver : ctr-aes-aesni module : kernel priority : 400 refcnt : 1 selftest : passed internal : no type : skcipher async : yes blocksize : 1 min keysize : 16 max keysize : 32 ivsize : 16 chunksize : 16 walksize : 16 name : __cbc(aes) driver : cryptd(__cbc-aes-aesni) module : kernel priority : 450 refcnt : 1 selftest : passed internal : yes type : skcipher async : yes blocksize : 16 min keysize : 16 max keysize : 32 ivsize : 16 chunksize : 16 walksize : 16 name : cbc(aes) driver : cbc-aes-aesni module : kernel priority : 400 refcnt : 1 selftest : passed internal : no type : skcipher async : yes blocksize : 16 min keysize : 16 max keysize : 32 ivsize : 16 chunksize : 16 walksize : 16 name : __ecb(aes) driver : cryptd(__ecb-aes-aesni) module : kernel priority : 450 refcnt : 1 selftest : passed internal : yes type : skcipher async : yes blocksize : 16 min keysize : 16 max keysize : 32 ivsize : 0 chunksize : 16 walksize : 16 name : ecb(aes) driver : ecb-aes-aesni module : kernel priority : 400 refcnt : 1 selftest : passed internal : no type : skcipher async : yes blocksize : 16 min keysize : 16 max keysize : 32 ivsize : 0 chunksize : 16 walksize : 16 name : __generic-gcm-aes-aesni driver : cryptd(__driver-generic-gcm-aes-aesni) module : kernel priority : 50 refcnt : 1 selftest : passed internal : yes type : aead async : yes blocksize : 1 ivsize : 12 maxauthsize : 16 geniv : name : gcm(aes) driver : generic-gcm-aesni module : kernel priority : 400 refcnt : 1 selftest : passed internal : no type : aead async : yes blocksize : 1 ivsize : 12 maxauthsize : 16 geniv : name : __generic-gcm-aes-aesni driver : __driver-generic-gcm-aes-aesni module : kernel priority : 0 refcnt : 1 selftest : passed internal : yes type : aead async : no blocksize : 1 ivsize : 12 maxauthsize : 16 geniv : name : __gcm-aes-aesni driver : cryptd(__driver-gcm-aes-aesni) module : kernel priority : 50 refcnt : 1 selftest : passed internal : yes type : aead async : yes blocksize : 1 ivsize : 8 maxauthsize : 16 geniv : name : rfc4106(gcm(aes)) driver : rfc4106-gcm-aesni module : kernel priority : 400 refcnt : 1 selftest : passed internal : no type : aead async : yes blocksize : 1 ivsize : 8 maxauthsize : 16 geniv : name : __gcm-aes-aesni driver : __driver-gcm-aes-aesni module : kernel priority : 0 refcnt : 1 selftest : passed internal : yes type : aead async : no blocksize : 1 ivsize : 8 maxauthsize : 16 geniv : name : __xts(aes) driver : __xts-aes-aesni module : kernel priority : 401 refcnt : 1 selftest : passed internal : yes type : skcipher async : no blocksize : 16 min keysize : 32 max keysize : 64 ivsize : 16 chunksize : 16 walksize : 16 name : __ctr(aes) driver : __ctr-aes-aesni module : kernel priority : 400 refcnt : 1 selftest : passed internal : yes type : skcipher async : no blocksize : 1 min keysize : 16 max keysize : 32 ivsize : 16 chunksize : 16 walksize : 16 name : __cbc(aes) driver : __cbc-aes-aesni module : kernel priority : 400 refcnt : 1 selftest : passed internal : yes type : skcipher async : no blocksize : 16 min keysize : 16 max keysize : 32 ivsize : 16 chunksize : 16 walksize : 16 name : __ecb(aes) driver : __ecb-aes-aesni module : kernel priority : 400 refcnt : 1 selftest : passed internal : yes type : skcipher async : no blocksize : 16 min keysize : 16 max keysize : 32 ivsize : 0 chunksize : 16 walksize : 16 name : __aes driver : __aes-aesni module : kernel priority : 300 refcnt : 1 selftest : passed internal : yes type : cipher blocksize : 16 min keysize : 16 max keysize : 32 name : aes driver : aes-aesni module : kernel priority : 300 refcnt : 8 selftest : passed internal : no type : cipher blocksize : 16 min keysize : 16 max keysize : 32 name : hmac(sha1) driver : hmac(sha1-generic) module : kernel priority : 100 refcnt : 9 selftest : passed internal : no type : shash blocksize : 64 digestsize : 20 name : ghash driver : ghash-generic module : kernel priority : 100 refcnt : 3 selftest : passed internal : no type : shash blocksize : 16 digestsize : 16 name : jitterentropy_rng driver : jitterentropy_rng module : kernel priority : 100 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_nopr_hmac_sha256 module : kernel priority : 221 refcnt : 2 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_nopr_hmac_sha512 module : kernel priority : 220 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_nopr_hmac_sha384 module : kernel priority : 219 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_nopr_hmac_sha1 module : kernel priority : 218 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_nopr_sha256 module : kernel priority : 217 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_nopr_sha512 module : kernel priority : 216 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_nopr_sha384 module : kernel priority : 215 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_nopr_sha1 module : kernel priority : 214 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_nopr_ctr_aes256 module : kernel priority : 213 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_nopr_ctr_aes192 module : kernel priority : 212 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_nopr_ctr_aes128 module : kernel priority : 211 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : hmac(sha256) driver : hmac(sha256-generic) module : kernel priority : 100 refcnt : 10 selftest : passed internal : no type : shash blocksize : 64 digestsize : 32 name : stdrng driver : drbg_pr_hmac_sha256 module : kernel priority : 210 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_pr_hmac_sha512 module : kernel priority : 209 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_pr_hmac_sha384 module : kernel priority : 208 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_pr_hmac_sha1 module : kernel priority : 207 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_pr_sha256 module : kernel priority : 206 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_pr_sha512 module : kernel priority : 205 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_pr_sha384 module : kernel priority : 204 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_pr_sha1 module : kernel priority : 203 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_pr_ctr_aes256 module : kernel priority : 202 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_pr_ctr_aes192 module : kernel priority : 201 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : stdrng driver : drbg_pr_ctr_aes128 module : kernel priority : 200 refcnt : 1 selftest : passed internal : no type : rng seedsize : 0 name : 842 driver : 842-scomp module : kernel priority : 100 refcnt : 1 selftest : passed internal : no type : scomp name : 842 driver : 842-generic module : kernel priority : 100 refcnt : 1 selftest : passed internal : no type : compression name : lzo-rle driver : lzo-rle-scomp module : kernel priority : 0 refcnt : 1 selftest : passed internal : no type : scomp name : lzo-rle driver : lzo-rle-generic module : kernel priority : 0 refcnt : 1 selftest : passed internal : no type : compression name : lzo driver : lzo-scomp module : kernel priority : 0 refcnt : 1 selftest : passed internal : no type : scomp name : lzo driver : lzo-generic module : kernel priority : 0 refcnt : 9 selftest : passed internal : no type : compression name : crct10dif driver : crct10dif-generic module : kernel priority : 100 refcnt : 1 selftest : passed internal : no type : shash blocksize : 1 digestsize : 2 name : crc32c driver : crc32c-generic module : kernel priority : 100 refcnt : 1 selftest : passed internal : no type : shash blocksize : 1 digestsize : 4 name : zlib-deflate driver : zlib-deflate-scomp module : kernel priority : 0 refcnt : 1 selftest : passed internal : no type : scomp name : deflate driver : deflate-scomp module : kernel priority : 0 refcnt : 1 selftest : passed internal : no type : scomp name : deflate driver : deflate-generic module : kernel priority : 0 refcnt : 1 selftest : passed internal : no type : compression name : aes driver : aes-generic module : kernel priority : 100 refcnt : 1 selftest : passed internal : no type : cipher blocksize : 16 min keysize : 16 max keysize : 32 name : sha224 driver : sha224-generic module : kernel priority : 100 refcnt : 1 selftest : passed internal : no type : shash blocksize : 64 digestsize : 28 name : sha256 driver : sha256-generic module : kernel priority : 100 refcnt : 11 selftest : passed internal : no type : shash blocksize : 64 digestsize : 32 name : sha1 driver : sha1-generic module : kernel priority : 100 refcnt : 11 selftest : passed internal : no type : shash blocksize : 64 digestsize : 20 name : md5 driver : md5-generic module : kernel priority : 0 refcnt : 1 selftest : passed internal : no type : shash blocksize : 64 digestsize : 16 name : ecb(cipher_null) driver : ecb-cipher_null module : kernel priority : 100 refcnt : 1 selftest : passed internal : no type : skcipher async : no blocksize : 1 min keysize : 0 max keysize : 0 ivsize : 0 chunksize : 1 walksize : 1 name : digest_null driver : digest_null-generic module : kernel priority : 0 refcnt : 1 selftest : passed internal : no type : shash blocksize : 1 digestsize : 0 name : compress_null driver : compress_null-generic module : kernel priority : 0 refcnt : 1 selftest : passed internal : no type : compression name : cipher_null driver : cipher_null-generic module : kernel priority : 0 refcnt : 1 selftest : passed internal : no type : cipher blocksize : 1 min keysize : 0 max keysize : 0 name : rsa driver : rsa-generic module : kernel priority : 100 refcnt : 1 selftest : passed internal : no type : akcipher name : dh driver : dh-generic module : kernel priority : 100 refcnt : 1 selftest : passed internal : no type : kpp name : aes driver : aes-asm module : kernel priority : 200 refcnt : 1 selftest : passed internal : no type : cipher blocksize : 16 min keysize : 16 max keysize : 32 Mode: 444 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/diskstats Lines: 52 1 0 ram0 0 0 0 0 0 0 0 0 0 0 0 1 1 ram1 0 0 0 0 0 0 0 0 0 0 0 1 2 ram2 0 0 0 0 0 0 0 0 0 0 0 1 3 ram3 0 0 0 0 0 0 0 0 0 0 0 1 4 ram4 0 0 0 0 0 0 0 0 0 0 0 1 5 ram5 0 0 0 0 0 0 0 0 0 0 0 1 6 ram6 0 0 0 0 0 0 0 0 0 0 0 1 7 ram7 0 0 0 0 0 0 0 0 0 0 0 1 8 ram8 0 0 0 0 0 0 0 0 0 0 0 1 9 ram9 0 0 0 0 0 0 0 0 0 0 0 1 10 ram10 0 0 0 0 0 0 0 0 0 0 0 1 11 ram11 0 0 0 0 0 0 0 0 0 0 0 1 12 ram12 0 0 0 0 0 0 0 0 0 0 0 1 13 ram13 0 0 0 0 0 0 0 0 0 0 0 1 14 ram14 0 0 0 0 0 0 0 0 0 0 0 1 15 ram15 0 0 0 0 0 0 0 0 0 0 0 7 0 loop0 0 0 0 0 0 0 0 0 0 0 0 7 1 loop1 0 0 0 0 0 0 0 0 0 0 0 7 2 loop2 0 0 0 0 0 0 0 0 0 0 0 7 3 loop3 0 0 0 0 0 0 0 0 0 0 0 7 4 loop4 0 0 0 0 0 0 0 0 0 0 0 7 5 loop5 0 0 0 0 0 0 0 0 0 0 0 7 6 loop6 0 0 0 0 0 0 0 0 0 0 0 7 7 loop7 0 0 0 0 0 0 0 0 0 0 0 8 0 sda 25354637 34367663 1003346126 18492372 28444756 11134226 505697032 63877960 0 9653880 82621804 8 1 sda1 250 0 2000 36 0 0 0 0 0 36 36 8 2 sda2 246 0 1968 32 0 0 0 0 0 32 32 8 3 sda3 340 13 2818 52 11 8 152 8 0 56 60 8 4 sda4 25353629 34367650 1003337964 18492232 27448755 11134218 505696880 61593380 0 7576432 80332428 252 0 dm-0 59910002 0 1003337218 46229572 39231014 0 505696880 1158557800 0 11325968 1206301256 252 1 dm-1 388 0 3104 84 74 0 592 0 0 76 84 252 2 dm-2 11571 0 308350 6536 153522 0 5093416 122884 0 65400 129416 252 3 dm-3 3870 0 3870 104 0 0 0 0 0 16 104 252 4 dm-4 392 0 1034 28 38 0 137 16 0 24 44 252 5 dm-5 3729 0 84279 924 98918 0 1151688 104684 0 58848 105632 179 0 mmcblk0 192 3 1560 156 0 0 0 0 0 136 156 179 1 mmcblk0p1 17 3 160 24 0 0 0 0 0 24 24 179 2 mmcblk0p2 95 0 760 68 0 0 0 0 0 68 68 2 0 fd0 2 0 16 80 0 0 0 0 0 80 80 254 0 vda 1775784 15386 32670882 8655768 6038856 20711856 213637440 2069221364 0 41614592 2077872228 254 1 vda1 668 85 5984 956 207 4266 35784 32772 0 8808 33720 254 2 vda2 1774936 15266 32663262 8654692 5991028 20707590 213601656 2069152216 0 41607628 2077801992 11 0 sr0 0 0 0 0 0 0 0 0 0 0 0 259 0 nvme0n1 47114 4 4643973 21650 1078320 43950 39451633 1011053 0 222766 1032546 259 1 nvme0n1p1 1140 0 9370 16 1 0 1 0 0 16 16 259 2 nvme0n1p2 45914 4 4631243 21626 1036885 43950 39451632 919480 0 131580 940970 8 0 sdb 326552 841 9657779 84 41822 2895 1972905 5007 0 60730 67070 68851 0 1925173784 11130 8 1 sdb1 231 3 34466 4 24 23 106 0 0 64 64 0 0 0 0 8 2 sdb2 326310 838 9622281 67 40726 2872 1972799 4924 0 58250 64567 68851 0 1925173784 11130 8 0 sdc 14202 71 579164 21861 2995 1589 180500 40875 0 11628 55200 0 0 0 0 127 182 8 1 sdc1 1027 0 13795 5021 2 0 4096 3 0 690 4579 0 0 0 0 0 0 8 2 sdc2 13126 71 561749 16802 2830 1589 176404 40620 0 10931 50449 0 0 0 0 0 0 Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/fs Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/fs/fscache Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/fs/fscache/stats Lines: 24 FS-Cache statistics Cookies: idx=3 dat=67877 spc=0 Objects: alc=67473 nal=0 avl=67473 ded=388 ChkAux : non=12 ok=33 upd=44 obs=55 Pages : mrk=547164 unc=364577 Acquire: n=67880 nul=98 noc=25 ok=67780 nbf=39 oom=26 Lookups: n=67473 neg=67470 pos=58 crt=67473 tmo=85 Invals : n=14 run=13 Updates: n=7 nul=3 run=8 Relinqs: n=394 nul=1 wcr=2 rtr=3 AttrChg: n=6 ok=5 nbf=4 oom=3 run=2 Allocs : n=20 ok=19 wt=18 nbf=17 int=16 Allocs : ops=15 owt=14 abt=13 Retrvls: n=151959 ok=82823 wt=23467 nod=69136 nbf=15 int=69 oom=43 Retrvls: ops=151959 owt=42747 abt=44 Stores : n=225565 ok=225565 agn=12 nbf=13 oom=14 Stores : ops=69156 run=294721 pgs=225565 rxd=225565 olm=43 VmScan : nos=364512 gon=2 bsy=43 can=12 wt=66 Ops : pend=42753 run=221129 enq=628798 can=11 rej=88 Ops : ini=377538 dfr=27 rel=377538 gc=37 CacheOp: alo=1 luo=2 luc=3 gro=4 CacheOp: inv=5 upo=6 dro=7 pto=8 atc=9 syn=10 CacheOp: rap=11 ras=12 alp=13 als=14 wrp=15 ucp=16 dsp=17 CacheEv: nsp=18 stl=19 rtr=20 cul=21EOF Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/fs/xfs Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/fs/xfs/stat Lines: 23 extent_alloc 92447 97589 92448 93751 abt 0 0 0 0 blk_map 1767055 188820 184891 92447 92448 2140766 0 bmbt 0 0 0 0 dir 185039 92447 92444 136422 trans 706 944304 0 ig 185045 58807 0 126238 0 33637 22 log 2883 113448 9 17360 739 push_ail 945014 0 134260 15483 0 3940 464 159985 0 40 xstrat 92447 0 rw 107739 94045 attr 4 0 0 0 icluster 8677 7849 135802 vnodes 92601 0 0 0 92444 92444 92444 0 buf 2666287 7122 2659202 3599 2 7085 0 10297 7085 abtb2 184941 1277345 13257 13278 0 0 0 0 0 0 0 0 0 0 2746147 abtc2 345295 2416764 172637 172658 0 0 0 0 0 0 0 0 0 0 21406023 bmbt2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ibt2 343004 1358467 0 0 0 0 0 0 0 0 0 0 0 0 0 fibt2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 qm 0 0 0 0 0 0 0 0 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: 60 Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] md3 : active raid6 sda1[8] sdh1[7] sdg1[6] sdf1[5] sde1[11] sdd1[3] sdc1[10] sdb1[9] sdd1[10](S) sdd2[11](S) 5853468288 blocks super 1.2 level 6, 64k chunk, algorithm 2 [8/8] [UUUUUUUU] md127 : active raid1 sdi2[0] sdj2[1] 312319552 blocks [2/2] [UU] md0 : active raid1 sdi1[0] sdj1[1] 248896 blocks [2/2] [UU] md4 : inactive raid1 sda3[0](F) sdb3[1](S) 4883648 blocks [2/2] [UU] md6 : active raid1 sdb2[2](F) sdc[1](S) sda2[0] 195310144 blocks [2/1] [U_] [=>...................] recovery = 8.5% (16775552/195310144) finish=17.0min speed=259783K/sec md8 : active raid1 sdb1[1] sda1[0] sdc[2](S) sde[3](S) 195310144 blocks [2/2] [UU] [=>...................] resync = 8.5% (16775552/195310144) finish=17.0min speed=259783K/sec md201 : active raid1 sda3[0] sdb3[1] 1993728 blocks super 1.2 [2/2] [UU] [=>...................] check = 5.7% (114176/1993728) finish=0.2min speed=114176K/sec md7 : active raid6 sdb1[0] sde1[3] sdd1[2] sdc1[1](F) 7813735424 blocks super 1.2 level 6, 512k chunk, algorithm 2 [4/3] [U_UU] bitmap: 0/30 pages [0KB], 65536KB chunk md9 : active raid1 sdc2[2] sdd2[3] sdb2[1] sda2[0] sde[4](F) sdf[5](F) sdg[6](S) 523968 blocks super 1.2 [4/4] [UUUU] resync=DELAYED md10 : active raid0 sda1[0] sdb1[1] 314159265 blocks 64k chunks md11 : active (auto-read-only) raid1 sdb2[0] sdc2[1] sdc3[2](F) hda[4](S) ssdc2[3](S) 4190208 blocks super 1.2 [2/2] [UU] resync=PENDING md12 : active raid0 sdc2[0] sdd2[1] 3886394368 blocks super 1.2 512k chunks md126 : active raid0 sdb[1] sdc[0] 1855870976 blocks super external:/md127/0 128k chunks md219 : inactive sdb[2](S) sdc[1](S) sda[0](S) 7932 blocks super external:imsm md00 : active raid0 xvdb[0] 4186624 blocks super 1.2 256k chunks md120 : active linear sda1[1] sdb1[0] 2095104 blocks super 1.2 0k rounding md101 : active (read-only) raid0 sdb[2] sdd[1] sdc[0] 322560 blocks super 1.2 512k chunks unused devices: Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/meminfo Lines: 43 MemTotal: 15666184 kB MemFree: 440324 kB Buffers: 1020128 kB Cached: 12007640 kB SwapCached: 0 kB Active: 6761276 kB Inactive: 6532708 kB Active(anon): 267256 kB Inactive(anon): 268 kB Active(file): 6494020 kB Inactive(file): 6532440 kB Unevictable: 0 kB Mlocked: 0 kB SwapTotal: 0 kB SwapFree: 0 kB Dirty: 768 kB Writeback: 0 kB AnonPages: 266216 kB Mapped: 44204 kB Shmem: 1308 kB Slab: 1807264 kB SReclaimable: 1738124 kB SUnreclaim: 69140 kB KernelStack: 1616 kB PageTables: 5288 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 7833092 kB Committed_AS: 530844 kB VmallocTotal: 34359738367 kB VmallocUsed: 36596 kB VmallocChunk: 34359637840 kB Percpu: 26176 kB HardwareCorrupted: 0 kB AnonHugePages: 12288 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB DirectMap4k: 91136 kB DirectMap2M: 16039936 kB Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/net Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/arp Lines: 3 IP address HW type Flags HW address Mask Device 192.168.224.1 0x1 0x2 00:50:56:c0:00:08 * ens33 192.168.224.2 0x1 0x0 00:00:00:00:00:00 * ens33 Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/dev Lines: 6 Inter-| Receive | Transmit face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed vethf345468: 648 8 0 0 0 0 0 0 438 5 0 0 0 0 0 0 lo: 1664039048 1566805 0 0 0 0 0 0 1664039048 1566805 0 0 0 0 0 0 docker0: 2568 38 0 0 0 0 0 0 438 5 0 0 0 0 0 0 eth0: 874354587 1036395 0 0 0 0 0 0 563352563 732147 0 0 0 0 0 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/ip_vs Lines: 21 IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP C0A80016:0CEA wlc -> C0A85216:0CEA Tunnel 100 248 2 -> C0A85318:0CEA Tunnel 100 248 2 -> C0A85315:0CEA Tunnel 100 248 1 TCP C0A80039:0CEA wlc -> C0A85416:0CEA Tunnel 0 0 0 -> C0A85215:0CEA Tunnel 100 1499 0 -> C0A83215:0CEA Tunnel 100 1498 0 TCP C0A80037:0CEA wlc -> C0A8321A:0CEA Tunnel 0 0 0 -> C0A83120:0CEA Tunnel 100 0 0 TCP [2620:0000:0000:0000:0000:0000:0000:0001]:0050 sh -> [2620:0000:0000:0000:0000:0000:0000:0002]:0050 Route 1 0 0 -> [2620:0000:0000:0000:0000:0000:0000:0003]:0050 Route 1 0 0 -> [2620:0000:0000:0000:0000:0000:0000:0004]:0050 Route 1 1 1 FWM 10001000 wlc -> C0A8321A:0CEA Route 0 0 1 -> C0A83215:0CEA Route 0 0 2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/ip_vs_stats Lines: 6 Total Incoming Outgoing Incoming Outgoing Conns Packets Packets Bytes Bytes 16AA370 E33656E5 0 51D8C8883AB3 0 Conns/s Pkts/s Pkts/s Bytes/s Bytes/s 4 1FB3C 0 1282A8F 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/protocols Lines: 14 protocol size sockets memory press maxhdr slab module cl co di ac io in de sh ss gs se re sp bi br ha uh gp em PACKET 1344 2 -1 NI 0 no kernel n n n n n n n n n n n n n n n n n n n PINGv6 1112 0 -1 NI 0 yes kernel y y y n n y n n y y y y n y y y y y n RAWv6 1112 1 -1 NI 0 yes kernel y y y n y y y n y y y y n y y y y n n UDPLITEv6 1216 0 57 NI 0 yes kernel y y y n y y y n y y y y n n n y y y n UDPv6 1216 10 57 NI 0 yes kernel y y y n y y y n y y y y n n n y y y n TCPv6 2144 1937 1225378 no 320 yes kernel y y y y y y y y y y y y y n y y y y y UNIX 1024 120 -1 NI 0 yes kernel n n n n n n n n n n n n n n n n n n n UDP-Lite 1024 0 57 NI 0 yes kernel y y y n y y y n y y y y y n n y y y n PING 904 0 -1 NI 0 yes kernel y y y n n y n n y y y y n y y y y y n RAW 912 0 -1 NI 0 yes kernel y y y n y y y n y y y y n y y y y n n UDP 1024 73 57 NI 0 yes kernel y y y n y y y n y y y y y n n y y y n TCP 1984 93064 1225378 yes 320 yes kernel y y y y y y y y y y y y y n y y y y y NETLINK 1040 16 -1 NI 0 no kernel n n n n n n n n n n n n n n n n n n n Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/net/rpc Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/rpc/nfs Lines: 5 net 18628 0 18628 6 rpc 4329785 0 4338291 proc2 18 2 69 0 0 4410 0 0 0 0 0 0 0 0 0 0 0 99 2 proc3 22 1 4084749 29200 94754 32580 186 47747 7981 8639 0 6356 0 6962 0 7958 0 0 241 4 4 2 39 proc4 61 1 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/rpc/nfsd Lines: 11 rc 0 6 18622 fh 0 0 0 0 0 io 157286400 0 th 8 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 ra 32 0 0 0 0 0 0 0 0 0 0 0 net 18628 0 18628 6 rpc 18628 0 0 0 0 proc2 18 2 69 0 0 4410 0 0 0 0 0 0 0 0 0 0 0 99 2 proc3 22 2 112 0 2719 111 0 0 0 0 0 0 0 0 0 0 0 27 216 0 2 1 0 proc4 2 2 10853 proc4ops 72 0 0 0 1098 2 0 0 0 0 8179 5896 0 0 0 0 5900 0 0 2 0 2 0 9609 0 2 150 1272 0 0 0 1236 0 0 0 0 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/sockstat Lines: 6 sockets: used 1602 TCP: inuse 35 orphan 0 tw 4 alloc 59 mem 22 UDP: inuse 12 mem 62 UDPLITE: inuse 0 RAW: inuse 0 FRAG: inuse 0 memory 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/sockstat6 Lines: 5 TCP6: inuse 17 UDP6: inuse 9 UDPLITE6: inuse 0 RAW6: inuse 1 FRAG6: inuse 0 memory 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/softnet_stat Lines: 5 00358fe3 00006283 00000000 00000000 00000000 00000000 00000000 00000000 00000000 000855fc 00000076 00000000 00000000 00953d1a 00000446 000000b1 00000000 00000000 00000000 00000000 00000000 00000000 008eeb9a 0000002b 000000dc 00000001 00015c73 00020e76 f0000769 00000000 00000000 00000000 00000000 00000000 00000004 00000003 00000002 01663fb2 00000000 000109a4 00000000 00000000 00000000 00000000 00000000 00020e76 00008e78 00000001 00000011 00000000 00000000 00000000 00000000 00000000 00000020 00000010 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/softnet_stat.broken Lines: 1 00015c73 00020e76 F0000769 00000000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/net/stat Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/stat/arp_cache Lines: 3 entries allocs destroys hash_grows lookups hits res_failed rcv_probes_mcast rcv_probes_ucast periodic_gc_runs forced_gc_runs unresolved_discards table_fulls 00000014 00000001 00000002 00000003 00000004 00000005 00000006 00000007 00000008 00000009 0000000a 0000000b 0000000c 00000014 0000000d 0000000e 0000000f 00000010 00000011 00000012 00000013 00000014 00000015 00000016 00000017 00000018 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/stat/ndisc_cache Lines: 3 entries allocs destroys hash_grows lookups hits res_failed rcv_probes_mcast rcv_probes_ucast periodic_gc_runs forced_gc_runs unresolved_discards table_fulls 00000024 000000f0 000000f1 000000f2 000000f3 000000f4 000000f5 000000f6 000000f7 000000f8 000000f9 000000fa 000000fb 00000024 000000fc 000000fd 000000fe 000000ff 00000100 00000101 00000102 00000103 00000104 00000105 00000106 00000107 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/tcp Lines: 4 sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode 0: 0500000A:0016 00000000:0000 0A 00000000:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 1: 00000000:0016 00000000:0000 0A 00000001:00000000 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 2: 00000000:0016 00000000:0000 0A 00000001:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/tcp6 Lines: 3 sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops 1315: 00000000000000000000000000000000:14EB 00000000000000000000000000000000:0000 07 00000000:00000000 00:00000000 00000000 981 0 21040 2 0000000013726323 0 6073: 000080FE00000000FFADE15609667CFE:C781 00000000000000000000000000000000:0000 07 00000000:00000000 00:00000000 00000000 1000 0 11337031 2 00000000b9256fdd 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/tls_stat Lines: 12 TlsCurrTxSw 5 TlsCurrRxSw 5 TlsCurrTxDevice 0 TlsCurrRxDevice 0 TlsTxSw 8711 TlsRxSw 8711 TlsTxDevice 0 TlsRxDevice 0 TlsDecryptError 13 TlsRxDeviceResync 0 TlsDecryptRetry 0 TlsRxNoPadViolation 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/udp Lines: 4 sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode 0: 0500000A:0016 00000000:0000 0A 00000000:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 1: 00000000:0016 00000000:0000 0A 00000001:00000000 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 2: 00000000:0016 00000000:0000 0A 00000001:00000001 00:00000000 00000000 0 0 2740 1 ffff88003d3af3c0 100 0 0 10 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/udp6 Lines: 3 sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode ref pointer drops 1315: 00000000000000000000000000000000:14EB 00000000000000000000000000000000:0000 07 00000000:00000000 00:00000000 00000000 981 0 21040 2 0000000013726323 0 6073: 000080FE00000000FFADE15609667CFE:C781 00000000000000000000000000000000:0000 07 00000000:00000000 00:00000000 00000000 1000 0 11337031 2 00000000b9256fdd 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/udp_broken Lines: 2 sl local_address rem_address st 1: 00000000:0016 00000000:0000 0A Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/unix Lines: 6 Num RefCount Protocol Flags Type St Inode Path 0000000000000000: 00000002 00000000 00010000 0001 01 3442596 /var/run/postgresql/.s.PGSQL.5432 0000000000000000: 0000000a 00000000 00010000 0005 01 10061 /run/udev/control 0000000000000000: 00000007 00000000 00000000 0002 01 12392 /dev/log 0000000000000000: 00000003 00000000 00000000 0001 03 4787297 /var/run/postgresql/.s.PGSQL.5432 0000000000000000: 00000003 00000000 00000000 0001 03 5091797 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/unix_without_inode Lines: 6 Num RefCount Protocol Flags Type St Path 0000000000000000: 00000002 00000000 00010000 0001 01 /var/run/postgresql/.s.PGSQL.5432 0000000000000000: 0000000a 00000000 00010000 0005 01 /run/udev/control 0000000000000000: 00000007 00000000 00000000 0002 01 /dev/log 0000000000000000: 00000003 00000000 00000000 0001 03 /var/run/postgresql/.s.PGSQL.5432 0000000000000000: 00000003 00000000 00000000 0001 03 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/wireless Lines: 4 Inter-| sta-| Quality | Discarded packets | Missed face | tus | link level noise | nwid crypt frag retry misc | beacon wlan0: 0001 2. 3. 4. 5 6 7 8 9 10 wlan1: 0010 9 8. 7. 6 5 4 3 2 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/net/xfrm_stat Lines: 28 XfrmInError 1 XfrmInBufferError 2 XfrmInHdrError 4 XfrmInNoStates 3 XfrmInStateProtoError 40 XfrmInStateModeError 100 XfrmInStateSeqError 6000 XfrmInStateExpired 4 XfrmInStateMismatch 23451 XfrmInStateInvalid 55555 XfrmInTmplMismatch 51 XfrmInNoPols 65432 XfrmInPolBlock 100 XfrmInPolError 10000 XfrmOutError 1000000 XfrmOutBundleGenError 43321 XfrmOutBundleCheckError 555 XfrmOutNoStates 869 XfrmOutStateProtoError 4542 XfrmOutStateModeError 4 XfrmOutStateSeqError 543 XfrmOutStateExpired 565 XfrmOutPolBlock 43456 XfrmOutPolDead 7656 XfrmOutPolError 1454 XfrmFwdHdrError 6654 XfrmOutStateInvalid 28765 XfrmAcquireError 24532 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/pressure Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/pressure/cpu Lines: 1 some avg10=0.10 avg60=2.00 avg300=3.85 total=15 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/pressure/io Lines: 2 some avg10=0.10 avg60=2.00 avg300=3.85 total=15 full avg10=0.20 avg60=3.00 avg300=4.95 total=25 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/pressure/memory Lines: 2 some avg10=0.10 avg60=2.00 avg300=3.85 total=15 full avg10=0.20 avg60=3.00 avg300=4.95 total=25 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/schedstat Lines: 6 version 15 timestamp 15819019232 cpu0 498494191 0 3533438552 2553969831 3853684107 2465731542 2045936778163039 343796328169361 4767485306 domain0 00000000,00000003 212499247 210112015 1861015 1860405436 536440 369895 32599 210079416 25368550 24241256 384652 927363878 807233 6366 1647 24239609 2122447165 1886868564 121112060 2848625533 125678146 241025 1032026 1885836538 2545 12 2533 0 0 0 0 0 0 1387952561 21076581 0 cpu1 518377256 0 4155211005 2778589869 10466382 2867629021 1904686152592476 364107263788241 5145567945 domain0 00000000,00000003 217653037 215526982 1577949 1580427380 557469 393576 28538 215498444 28721913 27662819 371153 870843407 745912 5523 1639 27661180 2331056874 2107732788 111442342 652402556 123615235 196159 1045245 2106687543 2400 3 2397 0 0 0 0 0 0 1437804657 26220076 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/self SymlinkTo: 26231 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/slabinfo Lines: 302 slabinfo - version: 2.1 # name : tunables : slabdata pid_3 375 532 576 28 4 : tunables 0 0 0 : slabdata 19 19 0 pid_2 3 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0 nvidia_p2p_page_cache 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 nvidia_pte_cache 9022 9152 368 22 2 : tunables 0 0 0 : slabdata 416 416 0 nvidia_stack_cache 321 326 12624 2 8 : tunables 0 0 0 : slabdata 163 163 0 kvm_async_pf 0 0 472 34 4 : tunables 0 0 0 : slabdata 0 0 0 kvm_vcpu 0 0 15552 2 8 : tunables 0 0 0 : slabdata 0 0 0 kvm_mmu_page_header 0 0 504 32 4 : tunables 0 0 0 : slabdata 0 0 0 pte_list_desc 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 x86_emulator 0 0 3024 10 8 : tunables 0 0 0 : slabdata 0 0 0 x86_fpu 0 0 4608 7 8 : tunables 0 0 0 : slabdata 0 0 0 iwl_cmd_pool:0000:04:00.0 0 128 512 32 4 : tunables 0 0 0 : slabdata 4 4 0 ext4_groupinfo_4k 3719 3740 480 34 4 : tunables 0 0 0 : slabdata 110 110 0 bio-6 32 75 640 25 4 : tunables 0 0 0 : slabdata 3 3 0 bio-5 16 48 1344 24 8 : tunables 0 0 0 : slabdata 2 2 0 bio-4 17 92 1408 23 8 : tunables 0 0 0 : slabdata 4 4 0 fat_inode_cache 0 0 1056 31 8 : tunables 0 0 0 : slabdata 0 0 0 fat_cache 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 ovl_aio_req 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 ovl_inode 0 0 1000 32 8 : tunables 0 0 0 : slabdata 0 0 0 squashfs_inode_cache 0 0 1088 30 8 : tunables 0 0 0 : slabdata 0 0 0 fuse_request 0 0 472 34 4 : tunables 0 0 0 : slabdata 0 0 0 fuse_inode 0 0 1152 28 8 : tunables 0 0 0 : slabdata 0 0 0 xfs_dqtrx 0 0 864 37 8 : tunables 0 0 0 : slabdata 0 0 0 xfs_dquot 0 0 832 39 8 : tunables 0 0 0 : slabdata 0 0 0 xfs_buf 0 0 768 21 4 : tunables 0 0 0 : slabdata 0 0 0 xfs_bui_item 0 0 544 30 4 : tunables 0 0 0 : slabdata 0 0 0 xfs_bud_item 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 xfs_cui_item 0 0 768 21 4 : tunables 0 0 0 : slabdata 0 0 0 xfs_cud_item 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 xfs_rui_item 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0 xfs_rud_item 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 xfs_icr 0 0 520 31 4 : tunables 0 0 0 : slabdata 0 0 0 xfs_ili 0 0 528 31 4 : tunables 0 0 0 : slabdata 0 0 0 xfs_inode 0 0 1344 24 8 : tunables 0 0 0 : slabdata 0 0 0 xfs_efi_item 0 0 768 21 4 : tunables 0 0 0 : slabdata 0 0 0 xfs_efd_item 0 0 776 21 4 : tunables 0 0 0 : slabdata 0 0 0 xfs_buf_item 0 0 608 26 4 : tunables 0 0 0 : slabdata 0 0 0 xf_trans 0 0 568 28 4 : tunables 0 0 0 : slabdata 0 0 0 xfs_ifork 0 0 376 21 2 : tunables 0 0 0 : slabdata 0 0 0 xfs_da_state 0 0 816 20 4 : tunables 0 0 0 : slabdata 0 0 0 xfs_btree_cur 0 0 560 29 4 : tunables 0 0 0 : slabdata 0 0 0 xfs_bmap_free_item 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 xfs_log_ticket 0 0 520 31 4 : tunables 0 0 0 : slabdata 0 0 0 nfs_direct_cache 0 0 560 29 4 : tunables 0 0 0 : slabdata 0 0 0 nfs_commit_data 4 28 1152 28 8 : tunables 0 0 0 : slabdata 1 1 0 nfs_write_data 32 50 1280 25 8 : tunables 0 0 0 : slabdata 2 2 0 nfs_read_data 0 0 1280 25 8 : tunables 0 0 0 : slabdata 0 0 0 nfs_inode_cache 0 0 1408 23 8 : tunables 0 0 0 : slabdata 0 0 0 nfs_page 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 rpc_inode_cache 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0 rpc_buffers 8 13 2496 13 8 : tunables 0 0 0 : slabdata 1 1 0 rpc_tasks 8 25 640 25 4 : tunables 0 0 0 : slabdata 1 1 0 fscache_cookie_jar 1 35 464 35 4 : tunables 0 0 0 : slabdata 1 1 0 jfs_mp 32 35 464 35 4 : tunables 0 0 0 : slabdata 1 1 0 jfs_ip 0 0 1592 20 8 : tunables 0 0 0 : slabdata 0 0 0 reiser_inode_cache 0 0 1096 29 8 : tunables 0 0 0 : slabdata 0 0 0 btrfs_end_io_wq 0 0 464 35 4 : tunables 0 0 0 : slabdata 0 0 0 btrfs_prelim_ref 0 0 424 38 4 : tunables 0 0 0 : slabdata 0 0 0 btrfs_delayed_extent_op 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 btrfs_delayed_data_ref 0 0 448 36 4 : tunables 0 0 0 : slabdata 0 0 0 btrfs_delayed_tree_ref 0 0 440 37 4 : tunables 0 0 0 : slabdata 0 0 0 btrfs_delayed_ref_head 0 0 480 34 4 : tunables 0 0 0 : slabdata 0 0 0 btrfs_inode_defrag 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 btrfs_delayed_node 0 0 648 25 4 : tunables 0 0 0 : slabdata 0 0 0 btrfs_ordered_extent 0 0 752 21 4 : tunables 0 0 0 : slabdata 0 0 0 btrfs_extent_map 0 0 480 34 4 : tunables 0 0 0 : slabdata 0 0 0 btrfs_extent_state 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 bio-3 35 92 704 23 4 : tunables 0 0 0 : slabdata 4 4 0 btrfs_extent_buffer 0 0 600 27 4 : tunables 0 0 0 : slabdata 0 0 0 btrfs_free_space_bitmap 0 0 12288 2 8 : tunables 0 0 0 : slabdata 0 0 0 btrfs_free_space 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 btrfs_path 0 0 448 36 4 : tunables 0 0 0 : slabdata 0 0 0 btrfs_trans_handle 0 0 440 37 4 : tunables 0 0 0 : slabdata 0 0 0 btrfs_inode 0 0 1496 21 8 : tunables 0 0 0 : slabdata 0 0 0 ext4_inode_cache 84136 84755 1400 23 8 : tunables 0 0 0 : slabdata 3685 3685 0 ext4_free_data 22 80 392 20 2 : tunables 0 0 0 : slabdata 4 4 0 ext4_allocation_context 0 70 464 35 4 : tunables 0 0 0 : slabdata 2 2 0 ext4_prealloc_space 24 74 440 37 4 : tunables 0 0 0 : slabdata 2 2 0 ext4_system_zone 267 273 376 21 2 : tunables 0 0 0 : slabdata 13 13 0 ext4_io_end_vec 0 88 368 22 2 : tunables 0 0 0 : slabdata 4 4 0 ext4_io_end 0 80 400 20 2 : tunables 0 0 0 : slabdata 4 4 0 ext4_bio_post_read_ctx 128 147 384 21 2 : tunables 0 0 0 : slabdata 7 7 0 ext4_pending_reservation 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 ext4_extent_status 79351 79422 376 21 2 : tunables 0 0 0 : slabdata 3782 3782 0 jbd2_transaction_s 44 100 640 25 4 : tunables 0 0 0 : slabdata 4 4 0 jbd2_inode 6785 6840 400 20 2 : tunables 0 0 0 : slabdata 342 342 0 jbd2_journal_handle 0 80 392 20 2 : tunables 0 0 0 : slabdata 4 4 0 jbd2_journal_head 824 1944 448 36 4 : tunables 0 0 0 : slabdata 54 54 0 jbd2_revoke_table_s 4 23 352 23 2 : tunables 0 0 0 : slabdata 1 1 0 jbd2_revoke_record_s 0 156 416 39 4 : tunables 0 0 0 : slabdata 4 4 0 ext2_inode_cache 0 0 1144 28 8 : tunables 0 0 0 : slabdata 0 0 0 mbcache 0 0 392 20 2 : tunables 0 0 0 : slabdata 0 0 0 dm_thin_new_mapping 0 152 424 38 4 : tunables 0 0 0 : slabdata 4 4 0 dm_snap_pending_exception 0 0 464 35 4 : tunables 0 0 0 : slabdata 0 0 0 dm_exception 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 dm_dirty_log_flush_entry 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 dm_bio_prison_cell_v2 0 0 432 37 4 : tunables 0 0 0 : slabdata 0 0 0 dm_bio_prison_cell 0 148 432 37 4 : tunables 0 0 0 : slabdata 4 4 0 kcopyd_job 0 8 3648 8 8 : tunables 0 0 0 : slabdata 1 1 0 io 0 32 512 32 4 : tunables 0 0 0 : slabdata 1 1 0 dm_uevent 0 0 3224 10 8 : tunables 0 0 0 : slabdata 0 0 0 dax_cache 1 28 1152 28 8 : tunables 0 0 0 : slabdata 1 1 0 aic94xx_ascb 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 aic94xx_dma_token 0 0 384 21 2 : tunables 0 0 0 : slabdata 0 0 0 asd_sas_event 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 sas_task 0 0 704 23 4 : tunables 0 0 0 : slabdata 0 0 0 qla2xxx_srbs 0 0 832 39 8 : tunables 0 0 0 : slabdata 0 0 0 sd_ext_cdb 2 22 368 22 2 : tunables 0 0 0 : slabdata 1 1 0 scsi_sense_cache 258 288 512 32 4 : tunables 0 0 0 : slabdata 9 9 0 virtio_scsi_cmd 64 75 640 25 4 : tunables 0 0 0 : slabdata 3 3 0 L2TP/IPv6 0 0 1536 21 8 : tunables 0 0 0 : slabdata 0 0 0 L2TP/IP 0 0 1408 23 8 : tunables 0 0 0 : slabdata 0 0 0 ip6-frags 0 0 520 31 4 : tunables 0 0 0 : slabdata 0 0 0 fib6_nodes 5 32 512 32 4 : tunables 0 0 0 : slabdata 1 1 0 ip6_dst_cache 4 25 640 25 4 : tunables 0 0 0 : slabdata 1 1 0 ip6_mrt_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 PINGv6 0 0 1600 20 8 : tunables 0 0 0 : slabdata 0 0 0 RAWv6 25 40 1600 20 8 : tunables 0 0 0 : slabdata 2 2 0 UDPLITEv6 0 0 1728 18 8 : tunables 0 0 0 : slabdata 0 0 0 UDPv6 3 54 1728 18 8 : tunables 0 0 0 : slabdata 3 3 0 tw_sock_TCPv6 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 request_sock_TCPv6 0 0 632 25 4 : tunables 0 0 0 : slabdata 0 0 0 TCPv6 0 33 2752 11 8 : tunables 0 0 0 : slabdata 3 3 0 uhci_urb_priv 0 0 392 20 2 : tunables 0 0 0 : slabdata 0 0 0 sgpool-128 2 14 4544 7 8 : tunables 0 0 0 : slabdata 2 2 0 sgpool-64 2 13 2496 13 8 : tunables 0 0 0 : slabdata 1 1 0 sgpool-32 2 44 1472 22 8 : tunables 0 0 0 : slabdata 2 2 0 sgpool-16 2 68 960 34 8 : tunables 0 0 0 : slabdata 2 2 0 sgpool-8 2 46 704 23 4 : tunables 0 0 0 : slabdata 2 2 0 btree_node 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 bfq_io_cq 0 0 488 33 4 : tunables 0 0 0 : slabdata 0 0 0 bfq_queue 0 0 848 38 8 : tunables 0 0 0 : slabdata 0 0 0 mqueue_inode_cache 1 24 1344 24 8 : tunables 0 0 0 : slabdata 1 1 0 isofs_inode_cache 0 0 968 33 8 : tunables 0 0 0 : slabdata 0 0 0 io_kiocb 0 0 640 25 4 : tunables 0 0 0 : slabdata 0 0 0 kioctx 0 30 1088 30 8 : tunables 0 0 0 : slabdata 1 1 0 aio_kiocb 0 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0 userfaultfd_ctx_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 fanotify_path_event 0 0 392 20 2 : tunables 0 0 0 : slabdata 0 0 0 fanotify_fid_event 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 fsnotify_mark 0 0 408 20 2 : tunables 0 0 0 : slabdata 0 0 0 dnotify_mark 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 dnotify_struct 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 dio 0 0 1088 30 8 : tunables 0 0 0 : slabdata 0 0 0 bio-2 4 25 640 25 4 : tunables 0 0 0 : slabdata 1 1 0 fasync_cache 0 0 384 21 2 : tunables 0 0 0 : slabdata 0 0 0 audit_tree_mark 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 pid_namespace 30 34 480 34 4 : tunables 0 0 0 : slabdata 1 1 0 posix_timers_cache 0 27 592 27 4 : tunables 0 0 0 : slabdata 1 1 0 iommu_devinfo 24 32 512 32 4 : tunables 0 0 0 : slabdata 1 1 0 iommu_domain 10 10 3264 10 8 : tunables 0 0 0 : slabdata 1 1 0 iommu_iova 8682 8748 448 36 4 : tunables 0 0 0 : slabdata 243 243 0 UNIX 529 814 1472 22 8 : tunables 0 0 0 : slabdata 37 37 0 ip4-frags 0 0 536 30 4 : tunables 0 0 0 : slabdata 0 0 0 ip_mrt_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 UDP-Lite 0 0 1536 21 8 : tunables 0 0 0 : slabdata 0 0 0 tcp_bind_bucket 7 128 512 32 4 : tunables 0 0 0 : slabdata 4 4 0 inet_peer_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 xfrm_dst_cache 0 0 704 23 4 : tunables 0 0 0 : slabdata 0 0 0 xfrm_state 0 0 1152 28 8 : tunables 0 0 0 : slabdata 0 0 0 ip_fib_trie 7 21 384 21 2 : tunables 0 0 0 : slabdata 1 1 0 ip_fib_alias 9 20 392 20 2 : tunables 0 0 0 : slabdata 1 1 0 ip_dst_cache 27 84 576 28 4 : tunables 0 0 0 : slabdata 3 3 0 PING 0 0 1408 23 8 : tunables 0 0 0 : slabdata 0 0 0 RAW 32 46 1408 23 8 : tunables 0 0 0 : slabdata 2 2 0 UDP 11 168 1536 21 8 : tunables 0 0 0 : slabdata 8 8 0 tw_sock_TCP 1 56 576 28 4 : tunables 0 0 0 : slabdata 2 2 0 request_sock_TCP 0 25 632 25 4 : tunables 0 0 0 : slabdata 1 1 0 TCP 10 60 2624 12 8 : tunables 0 0 0 : slabdata 5 5 0 hugetlbfs_inode_cache 2 35 928 35 8 : tunables 0 0 0 : slabdata 1 1 0 dquot 0 0 640 25 4 : tunables 0 0 0 : slabdata 0 0 0 bio-1 32 46 704 23 4 : tunables 0 0 0 : slabdata 2 2 0 eventpoll_pwq 409 600 408 20 2 : tunables 0 0 0 : slabdata 30 30 0 eventpoll_epi 408 672 576 28 4 : tunables 0 0 0 : slabdata 24 24 0 inotify_inode_mark 58 195 416 39 4 : tunables 0 0 0 : slabdata 5 5 0 scsi_data_buffer 0 0 360 22 2 : tunables 0 0 0 : slabdata 0 0 0 bio_crypt_ctx 128 147 376 21 2 : tunables 0 0 0 : slabdata 7 7 0 request_queue 29 39 2408 13 8 : tunables 0 0 0 : slabdata 3 3 0 blkdev_ioc 81 148 440 37 4 : tunables 0 0 0 : slabdata 4 4 0 bio-0 125 200 640 25 4 : tunables 0 0 0 : slabdata 8 8 0 biovec-max 166 196 4544 7 8 : tunables 0 0 0 : slabdata 28 28 0 biovec-128 0 52 2496 13 8 : tunables 0 0 0 : slabdata 4 4 0 biovec-64 0 88 1472 22 8 : tunables 0 0 0 : slabdata 4 4 0 biovec-16 0 92 704 23 4 : tunables 0 0 0 : slabdata 4 4 0 bio_integrity_payload 4 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0 khugepaged_mm_slot 59 180 448 36 4 : tunables 0 0 0 : slabdata 5 5 0 ksm_mm_slot 0 0 384 21 2 : tunables 0 0 0 : slabdata 0 0 0 ksm_stable_node 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 ksm_rmap_item 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 user_namespace 2 37 864 37 8 : tunables 0 0 0 : slabdata 1 1 0 uid_cache 5 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0 dmaengine-unmap-256 1 13 2496 13 8 : tunables 0 0 0 : slabdata 1 1 0 dmaengine-unmap-128 1 22 1472 22 8 : tunables 0 0 0 : slabdata 1 1 0 dmaengine-unmap-16 1 28 576 28 4 : tunables 0 0 0 : slabdata 1 1 0 dmaengine-unmap-2 1 36 448 36 4 : tunables 0 0 0 : slabdata 1 1 0 audit_buffer 0 22 360 22 2 : tunables 0 0 0 : slabdata 1 1 0 sock_inode_cache 663 1170 1216 26 8 : tunables 0 0 0 : slabdata 45 45 0 skbuff_ext_cache 0 0 576 28 4 : tunables 0 0 0 : slabdata 0 0 0 skbuff_fclone_cache 1 72 896 36 8 : tunables 0 0 0 : slabdata 2 2 0 skbuff_head_cache 3 650 640 25 4 : tunables 0 0 0 : slabdata 26 26 0 configfs_dir_cache 7 38 424 38 4 : tunables 0 0 0 : slabdata 1 1 0 file_lock_cache 27 116 552 29 4 : tunables 0 0 0 : slabdata 4 4 0 file_lock_ctx 106 120 392 20 2 : tunables 0 0 0 : slabdata 6 6 0 fsnotify_mark_connector 52 66 368 22 2 : tunables 0 0 0 : slabdata 3 3 0 net_namespace 1 6 5312 6 8 : tunables 0 0 0 : slabdata 1 1 0 task_delay_info 784 1560 416 39 4 : tunables 0 0 0 : slabdata 40 40 0 taskstats 45 92 688 23 4 : tunables 0 0 0 : slabdata 4 4 0 proc_dir_entry 678 682 528 31 4 : tunables 0 0 0 : slabdata 22 22 0 pde_opener 0 189 376 21 2 : tunables 0 0 0 : slabdata 9 9 0 proc_inode_cache 7150 8250 992 33 8 : tunables 0 0 0 : slabdata 250 250 0 seq_file 60 735 456 35 4 : tunables 0 0 0 : slabdata 21 21 0 sigqueue 0 156 416 39 4 : tunables 0 0 0 : slabdata 4 4 0 bdev_cache 36 78 1216 26 8 : tunables 0 0 0 : slabdata 3 3 0 shmem_inode_cache 1599 2208 1016 32 8 : tunables 0 0 0 : slabdata 69 69 0 kernfs_iattrs_cache 1251 1254 424 38 4 : tunables 0 0 0 : slabdata 33 33 0 kernfs_node_cache 52898 52920 464 35 4 : tunables 0 0 0 : slabdata 1512 1512 0 mnt_cache 42 46 704 23 4 : tunables 0 0 0 : slabdata 2 2 0 filp 4314 6371 704 23 4 : tunables 0 0 0 : slabdata 277 277 0 inode_cache 28695 29505 920 35 8 : tunables 0 0 0 : slabdata 843 843 0 dentry 166069 169074 528 31 4 : tunables 0 0 0 : slabdata 5454 5454 0 names_cache 0 35 4544 7 8 : tunables 0 0 0 : slabdata 5 5 0 hashtab_node 0 0 360 22 2 : tunables 0 0 0 : slabdata 0 0 0 ebitmap_node 0 0 400 20 2 : tunables 0 0 0 : slabdata 0 0 0 avtab_extended_perms 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 avtab_node 0 0 360 22 2 : tunables 0 0 0 : slabdata 0 0 0 avc_xperms_data 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 avc_xperms_decision_node 0 0 384 21 2 : tunables 0 0 0 : slabdata 0 0 0 avc_xperms_node 0 0 392 20 2 : tunables 0 0 0 : slabdata 0 0 0 avc_node 37 40 408 20 2 : tunables 0 0 0 : slabdata 2 2 0 iint_cache 0 0 448 36 4 : tunables 0 0 0 : slabdata 0 0 0 lsm_inode_cache 122284 122340 392 20 2 : tunables 0 0 0 : slabdata 6117 6117 0 lsm_file_cache 4266 4485 352 23 2 : tunables 0 0 0 : slabdata 195 195 0 key_jar 8 25 640 25 4 : tunables 0 0 0 : slabdata 1 1 0 buffer_head 255622 257076 440 37 4 : tunables 0 0 0 : slabdata 6948 6948 0 uts_namespace 0 0 776 21 4 : tunables 0 0 0 : slabdata 0 0 0 nsproxy 31 40 408 20 2 : tunables 0 0 0 : slabdata 2 2 0 vm_area_struct 39115 43214 528 31 4 : tunables 0 0 0 : slabdata 1394 1394 0 mm_struct 96 529 1408 23 8 : tunables 0 0 0 : slabdata 23 23 0 fs_cache 102 756 448 36 4 : tunables 0 0 0 : slabdata 21 21 0 files_cache 102 588 1152 28 8 : tunables 0 0 0 : slabdata 21 21 0 signal_cache 266 672 1536 21 8 : tunables 0 0 0 : slabdata 32 32 0 sighand_cache 266 507 2496 13 8 : tunables 0 0 0 : slabdata 39 39 0 task_struct 783 963 10240 3 8 : tunables 0 0 0 : slabdata 321 321 0 cred_jar 364 952 576 28 4 : tunables 0 0 0 : slabdata 34 34 0 anon_vma_chain 63907 67821 416 39 4 : tunables 0 0 0 : slabdata 1739 1739 0 anon_vma 25891 28899 416 39 4 : tunables 0 0 0 : slabdata 741 741 0 pid 408 992 512 32 4 : tunables 0 0 0 : slabdata 31 31 0 Acpi-Operand 6682 6740 408 20 2 : tunables 0 0 0 : slabdata 337 337 0 Acpi-ParseExt 0 39 416 39 4 : tunables 0 0 0 : slabdata 1 1 0 Acpi-Parse 0 80 392 20 2 : tunables 0 0 0 : slabdata 4 4 0 Acpi-State 0 78 416 39 4 : tunables 0 0 0 : slabdata 2 2 0 Acpi-Namespace 3911 3948 384 21 2 : tunables 0 0 0 : slabdata 188 188 0 trace_event_file 2638 2660 424 38 4 : tunables 0 0 0 : slabdata 70 70 0 ftrace_event_field 6592 6594 384 21 2 : tunables 0 0 0 : slabdata 314 314 0 pool_workqueue 41 64 1024 32 8 : tunables 0 0 0 : slabdata 2 2 0 radix_tree_node 21638 24045 912 35 8 : tunables 0 0 0 : slabdata 687 687 0 task_group 48 78 1216 26 8 : tunables 0 0 0 : slabdata 3 3 0 vmap_area 4411 4680 400 20 2 : tunables 0 0 0 : slabdata 234 234 0 dma-kmalloc-8k 0 0 24576 1 8 : tunables 0 0 0 : slabdata 0 0 0 dma-kmalloc-4k 0 0 12288 2 8 : tunables 0 0 0 : slabdata 0 0 0 dma-kmalloc-2k 0 0 6144 5 8 : tunables 0 0 0 : slabdata 0 0 0 dma-kmalloc-1k 0 0 3072 10 8 : tunables 0 0 0 : slabdata 0 0 0 dma-kmalloc-512 0 0 1536 21 8 : tunables 0 0 0 : slabdata 0 0 0 dma-kmalloc-256 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0 dma-kmalloc-128 0 0 640 25 4 : tunables 0 0 0 : slabdata 0 0 0 dma-kmalloc-64 0 0 512 32 4 : tunables 0 0 0 : slabdata 0 0 0 dma-kmalloc-32 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 dma-kmalloc-16 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 dma-kmalloc-8 0 0 344 23 2 : tunables 0 0 0 : slabdata 0 0 0 dma-kmalloc-192 0 0 528 31 4 : tunables 0 0 0 : slabdata 0 0 0 dma-kmalloc-96 0 0 432 37 4 : tunables 0 0 0 : slabdata 0 0 0 kmalloc-rcl-8k 0 0 24576 1 8 : tunables 0 0 0 : slabdata 0 0 0 kmalloc-rcl-4k 0 0 12288 2 8 : tunables 0 0 0 : slabdata 0 0 0 kmalloc-rcl-2k 0 0 6144 5 8 : tunables 0 0 0 : slabdata 0 0 0 kmalloc-rcl-1k 0 0 3072 10 8 : tunables 0 0 0 : slabdata 0 0 0 kmalloc-rcl-512 0 0 1536 21 8 : tunables 0 0 0 : slabdata 0 0 0 kmalloc-rcl-256 0 0 1024 32 8 : tunables 0 0 0 : slabdata 0 0 0 kmalloc-rcl-192 0 0 528 31 4 : tunables 0 0 0 : slabdata 0 0 0 kmalloc-rcl-128 31 75 640 25 4 : tunables 0 0 0 : slabdata 3 3 0 kmalloc-rcl-96 3371 3626 432 37 4 : tunables 0 0 0 : slabdata 98 98 0 kmalloc-rcl-64 2080 2272 512 32 4 : tunables 0 0 0 : slabdata 71 71 0 kmalloc-rcl-32 0 0 416 39 4 : tunables 0 0 0 : slabdata 0 0 0 kmalloc-rcl-16 0 0 368 22 2 : tunables 0 0 0 : slabdata 0 0 0 kmalloc-rcl-8 0 0 344 23 2 : tunables 0 0 0 : slabdata 0 0 0 kmalloc-8k 133 140 24576 1 8 : tunables 0 0 0 : slabdata 140 140 0 kmalloc-4k 403 444 12288 2 8 : tunables 0 0 0 : slabdata 222 222 0 kmalloc-2k 2391 2585 6144 5 8 : tunables 0 0 0 : slabdata 517 517 0 kmalloc-1k 2163 2420 3072 10 8 : tunables 0 0 0 : slabdata 242 242 0 kmalloc-512 2972 3633 1536 21 8 : tunables 0 0 0 : slabdata 173 173 0 kmalloc-256 1841 1856 1024 32 8 : tunables 0 0 0 : slabdata 58 58 0 kmalloc-192 2165 2914 528 31 4 : tunables 0 0 0 : slabdata 94 94 0 kmalloc-128 1137 1175 640 25 4 : tunables 0 0 0 : slabdata 47 47 0 kmalloc-96 1925 2590 432 37 4 : tunables 0 0 0 : slabdata 70 70 0 kmalloc-64 9433 10688 512 32 4 : tunables 0 0 0 : slabdata 334 334 0 kmalloc-32 9098 10062 416 39 4 : tunables 0 0 0 : slabdata 258 258 0 kmalloc-16 10914 10956 368 22 2 : tunables 0 0 0 : slabdata 498 498 0 kmalloc-8 7576 7705 344 23 2 : tunables 0 0 0 : slabdata 335 335 0 kmem_cache_node 904 928 512 32 4 : tunables 0 0 0 : slabdata 29 29 0 kmem_cache 904 936 832 39 8 : tunables 0 0 0 : slabdata 24 24 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/softirqs Lines: 11 CPU0 CPU1 HI: 3 0 TIMER: 2776180 247490 NET_TX: 2419 772 NET_RX: 55919 28694 BLOCK: 174915 262755 IRQ_POLL: 0 0 TASKLET: 209 75 SCHED: 2278692 815209 HRTIMER: 1281 220 RCU: 605871 532783 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/stat Lines: 16 cpu 301854 612 111922 8979004 3552 2 3944 0 0 0 cpu0 44490 19 21045 1087069 220 1 3410 0 0 0 cpu1 47869 23 16474 1110787 591 0 46 0 0 0 cpu2 46504 36 15916 1112321 441 0 326 0 0 0 cpu3 47054 102 15683 1113230 533 0 60 0 0 0 cpu4 28413 25 10776 1140321 217 0 8 0 0 0 cpu5 29271 101 11586 1136270 672 0 30 0 0 0 cpu6 29152 36 10276 1139721 319 0 29 0 0 0 cpu7 29098 268 10164 1139282 555 0 31 0 0 0 intr 73777505 41 9 0 0 0 0 0 0 1 172 0 0 190 0 0 0 312 5772089 0 0 0 0 0 43 0 0 0 0 0 521732 252315 550 18 277 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ctxt 38014093 btime 1418183276 processes 26442 procs_running 2 procs_blocked 1 softirq 5057579 250191 1481983 1647 211099 186066 0 1783454 622196 12499 508444 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/swaps Lines: 2 Filename Type Size Used Priority /dev/dm-2 partition 131068 176 -2 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/symlinktargets Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/symlinktargets/README Lines: 2 This directory contains some empty files that are the symlinks the files in the "fd" directory point to. They are otherwise ignored by the tests Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/symlinktargets/abc Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/symlinktargets/def Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/symlinktargets/ghi Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/symlinktargets/uvw Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/symlinktargets/xyz Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/sys Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/sys/kernel Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/sys/kernel/random Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/kernel/random/entropy_avail Lines: 1 3943 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/kernel/random/poolsize Lines: 1 4096 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/kernel/random/urandom_min_reseed_secs Lines: 1 60 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/kernel/random/write_wakeup_threshold Lines: 1 3072 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/sys/kernel/seccomp Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/kernel/seccomp/actions_avail Lines: 1 kill_process kill_thread trap errno trace log allow Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/proc/sys/vm Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/admin_reserve_kbytes Lines: 1 8192 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/block_dump Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/compact_unevictable_allowed Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/dirty_background_bytes Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/dirty_background_ratio Lines: 1 10 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/dirty_bytes Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/dirty_expire_centisecs Lines: 1 3000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/dirty_ratio Lines: 1 20 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/dirty_writeback_centisecs Lines: 1 500 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/dirtytime_expire_seconds Lines: 1 43200 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/drop_caches Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/extfrag_threshold Lines: 1 500 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/hugetlb_shm_group Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/laptop_mode Lines: 1 5 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/legacy_va_layout Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/lowmem_reserve_ratio Lines: 1 256 256 32 0 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/max_map_count Lines: 1 65530 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/memory_failure_early_kill Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/memory_failure_recovery Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/min_free_kbytes Lines: 1 67584 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/min_slab_ratio Lines: 1 5 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/min_unmapped_ratio Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/mmap_min_addr Lines: 1 65536 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/nr_hugepages Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/nr_hugepages_mempolicy Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/nr_overcommit_hugepages Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/numa_stat Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/numa_zonelist_order Lines: 1 Node Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/oom_dump_tasks Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/oom_kill_allocating_task Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/overcommit_kbytes Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/overcommit_memory Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/overcommit_ratio Lines: 1 50 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/page-cluster Lines: 1 3 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/panic_on_oom Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/percpu_pagelist_fraction Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/stat_interval Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/swappiness Lines: 1 60 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/user_reserve_kbytes Lines: 1 131072 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/vfs_cache_pressure Lines: 1 100 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/watermark_boost_factor Lines: 1 15000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/watermark_scale_factor Lines: 1 10 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/sys/vm/zone_reclaim_mode Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/zoneinfo Lines: 262 Node 0, zone DMA per-node stats nr_inactive_anon 230981 nr_active_anon 547580 nr_inactive_file 316904 nr_active_file 346282 nr_unevictable 115467 nr_slab_reclaimable 131220 nr_slab_unreclaimable 47320 nr_isolated_anon 0 nr_isolated_file 0 workingset_nodes 11627 workingset_refault 466886 workingset_activate 276925 workingset_restore 84055 workingset_nodereclaim 487 nr_anon_pages 795576 nr_mapped 215483 nr_file_pages 761874 nr_dirty 908 nr_writeback 0 nr_writeback_temp 0 nr_shmem 224925 nr_shmem_hugepages 0 nr_shmem_pmdmapped 0 nr_anon_transparent_hugepages 0 nr_unstable 0 nr_vmscan_write 12950 nr_vmscan_immediate_reclaim 3033 nr_dirtied 8007423 nr_written 7752121 nr_kernel_misc_reclaimable 0 pages free 3952 min 33 low 41 high 49 spanned 4095 present 3975 managed 3956 protection: (0, 2877, 7826, 7826, 7826) nr_free_pages 3952 nr_zone_inactive_anon 0 nr_zone_active_anon 0 nr_zone_inactive_file 0 nr_zone_active_file 0 nr_zone_unevictable 0 nr_zone_write_pending 0 nr_mlock 0 nr_page_table_pages 0 nr_kernel_stack 0 nr_bounce 0 nr_zspages 0 nr_free_cma 0 numa_hit 1 numa_miss 0 numa_foreign 0 numa_interleave 0 numa_local 1 numa_other 0 pagesets cpu: 0 count: 0 high: 0 batch: 1 vm stats threshold: 8 cpu: 1 count: 0 high: 0 batch: 1 vm stats threshold: 8 cpu: 2 count: 0 high: 0 batch: 1 vm stats threshold: 8 cpu: 3 count: 0 high: 0 batch: 1 vm stats threshold: 8 cpu: 4 count: 0 high: 0 batch: 1 vm stats threshold: 8 cpu: 5 count: 0 high: 0 batch: 1 vm stats threshold: 8 cpu: 6 count: 0 high: 0 batch: 1 vm stats threshold: 8 cpu: 7 count: 0 high: 0 batch: 1 vm stats threshold: 8 node_unreclaimable: 0 start_pfn: 1 Node 0, zone DMA32 pages free 204252 min 19510 low 21059 high 22608 spanned 1044480 present 759231 managed 742806 protection: (0, 0, 4949, 4949, 4949) nr_free_pages 204252 nr_zone_inactive_anon 118558 nr_zone_active_anon 106598 nr_zone_inactive_file 75475 nr_zone_active_file 70293 nr_zone_unevictable 66195 nr_zone_write_pending 64 nr_mlock 4 nr_page_table_pages 1756 nr_kernel_stack 2208 nr_bounce 0 nr_zspages 0 nr_free_cma 0 numa_hit 113952967 numa_miss 0 numa_foreign 0 numa_interleave 0 numa_local 113952967 numa_other 0 pagesets cpu: 0 count: 345 high: 378 batch: 63 vm stats threshold: 48 cpu: 1 count: 356 high: 378 batch: 63 vm stats threshold: 48 cpu: 2 count: 325 high: 378 batch: 63 vm stats threshold: 48 cpu: 3 count: 346 high: 378 batch: 63 vm stats threshold: 48 cpu: 4 count: 321 high: 378 batch: 63 vm stats threshold: 48 cpu: 5 count: 316 high: 378 batch: 63 vm stats threshold: 48 cpu: 6 count: 373 high: 378 batch: 63 vm stats threshold: 48 cpu: 7 count: 339 high: 378 batch: 63 vm stats threshold: 48 node_unreclaimable: 0 start_pfn: 4096 Node 0, zone Normal pages free 18553 min 11176 low 13842 high 16508 spanned 1308160 present 1308160 managed 1268711 protection: (0, 0, 0, 0, 0) nr_free_pages 18553 nr_zone_inactive_anon 112423 nr_zone_active_anon 440982 nr_zone_inactive_file 241429 nr_zone_active_file 275989 nr_zone_unevictable 49272 nr_zone_write_pending 844 nr_mlock 154 nr_page_table_pages 9750 nr_kernel_stack 15136 nr_bounce 0 nr_zspages 0 nr_free_cma 0 numa_hit 162718019 numa_miss 0 numa_foreign 0 numa_interleave 26812 numa_local 162718019 numa_other 0 pagesets cpu: 0 count: 316 high: 378 batch: 63 vm stats threshold: 56 cpu: 1 count: 366 high: 378 batch: 63 vm stats threshold: 56 cpu: 2 count: 60 high: 378 batch: 63 vm stats threshold: 56 cpu: 3 count: 256 high: 378 batch: 63 vm stats threshold: 56 cpu: 4 count: 253 high: 378 batch: 63 vm stats threshold: 56 cpu: 5 count: 159 high: 378 batch: 63 vm stats threshold: 56 cpu: 6 count: 311 high: 378 batch: 63 vm stats threshold: 56 cpu: 7 count: 264 high: 378 batch: 63 vm stats threshold: 56 node_unreclaimable: 0 start_pfn: 1048576 Node 0, zone Movable pages free 0 min 0 low 0 high 0 spanned 0 present 0 managed 0 protection: (0, 0, 0, 0, 0) Node 0, zone Device pages free 0 min 0 low 0 high 0 spanned 0 present 0 managed 0 protection: (0, 0, 0, 0, 0) Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/dm-0 Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/dm-0/dm Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/dm-0/dm/name Lines: 1 vg0--lv_rootEOF Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/dm-0/dm/rq_based_seq_io_merge_deadline Lines: 1 0EOF Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/dm-0/dm/suspended Lines: 1 0EOF Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/dm-0/dm/use_blk_mq Lines: 1 0EOF Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/dm-0/dm/uuid Lines: 1 LVM-3zSHSR5Nbf4j7g6auAAefWY2CMaX01theZYEvQyecVsm2WtX3iY5q51qq5dWWOq7EOF Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/dm-0/slaves Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/dm-0/slaves/sda Lines: 0 Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/dm-0/stat Lines: 1 6447303 0 710266738 1529043 953216 0 31201176 4557464 0 796160 6088971 Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md0 Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md0/md Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md0/md/array_state Lines: 1 clean Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md0/md/chunk_size Lines: 1 524288 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md0/md/dev-sdg Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md0/md/dev-sdg/state Lines: 1 in_sync Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md0/md/dev-sdh Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md0/md/dev-sdh/state Lines: 1 in_sync Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md0/md/level Lines: 1 raid0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md0/md/metadata_version Lines: 1 1.2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md0/md/raid_disks Lines: 1 2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md0/md/rd0 SymlinkTo: dev-sdg # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md0/md/rd1 SymlinkTo: dev-sdh # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md0/md/uuid Lines: 1 155f29ff-1716-4107-b362-52307ef86cac Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md1 Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md1/md Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md1/md/array_state Lines: 1 clean Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md1/md/chunk_size Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md1/md/degraded Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md1/md/dev-sdi Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md1/md/dev-sdi/state Lines: 1 in_sync Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md1/md/dev-sdj Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md1/md/dev-sdj/state Lines: 1 in_sync Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md1/md/level Lines: 1 raid1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md1/md/metadata_version Lines: 1 1.2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md1/md/raid_disks Lines: 1 2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md1/md/rd0 SymlinkTo: dev-sdi # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md1/md/rd1 SymlinkTo: dev-sdj # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md1/md/sync_action Lines: 1 idle Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md1/md/sync_completed Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md1/md/uuid Lines: 1 0fbf5f2c-add2-43c2-bd78-a4be3ab709ef Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md10 Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md10/md Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/array_state Lines: 1 clean Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/chunk_size Lines: 1 524288 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/degraded Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md10/md/dev-sdu Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/dev-sdu/state Lines: 1 in_sync Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md10/md/dev-sdv Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/dev-sdv/state Lines: 1 in_sync Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md10/md/dev-sdw Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/dev-sdw/state Lines: 1 in_sync Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md10/md/dev-sdx Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/dev-sdx/state Lines: 1 in_sync Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/level Lines: 1 raid10 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/metadata_version Lines: 1 1.2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/raid_disks Lines: 1 4 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/rd0 SymlinkTo: dev-sdu # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/rd1 SymlinkTo: dev-sdv # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/rd2 SymlinkTo: dev-sdw # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/rd3 SymlinkTo: dev-sdx # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/sync_action Lines: 1 idle Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/sync_completed Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md10/md/uuid Lines: 1 0c15f7e7-b159-4b1f-a5cd-a79b5c04b6f5 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md4 Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md4/md Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md4/md/array_state Lines: 1 clean Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md4/md/chunk_size Lines: 1 524288 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md4/md/degraded Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md4/md/dev-sdk Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md4/md/dev-sdk/state Lines: 1 in_sync Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md4/md/dev-sdl Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md4/md/dev-sdl/state Lines: 1 in_sync Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md4/md/dev-sdm Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md4/md/dev-sdm/state Lines: 1 in_sync Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md4/md/level Lines: 1 raid4 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md4/md/metadata_version Lines: 1 1.2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md4/md/raid_disks Lines: 1 3 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md4/md/rd0 SymlinkTo: dev-sdk # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md4/md/rd1 SymlinkTo: dev-sdl # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md4/md/rd2 SymlinkTo: dev-sdm # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md4/md/sync_action Lines: 1 idle Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md4/md/sync_completed Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md4/md/uuid Lines: 1 67f415d5-2c0c-4b69-8e0d-7e20ef553457 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md5 Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md5/md Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md5/md/array_state Lines: 1 clean Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md5/md/chunk_size Lines: 1 524288 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md5/md/degraded Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md5/md/dev-sdaa Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md5/md/dev-sdaa/state Lines: 1 spare Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md5/md/dev-sdn Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md5/md/dev-sdn/state Lines: 1 in_sync Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md5/md/dev-sdo Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md5/md/dev-sdo/state Lines: 1 in_sync Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md5/md/dev-sdp Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md5/md/dev-sdp/state Lines: 1 faulty Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md5/md/level Lines: 1 raid5 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md5/md/metadata_version Lines: 1 1.2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md5/md/raid_disks Lines: 1 3 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md5/md/rd0 SymlinkTo: dev-sdn # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md5/md/rd1 SymlinkTo: dev-sdo # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md5/md/rd2 SymlinkTo: dev-sdp # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md5/md/sync_action Lines: 1 idle Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md5/md/sync_completed Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md5/md/uuid Lines: 1 7615b98d-f2ba-4d99-bee8-6202d8e130b9 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md6 Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md6/md Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/array_state Lines: 1 active Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/chunk_size Lines: 1 524288 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/degraded Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md6/md/dev-sdq Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/dev-sdq/state Lines: 1 in_sync Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md6/md/dev-sdr Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/dev-sdr/state Lines: 1 in_sync Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md6/md/dev-sds Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/dev-sds/state Lines: 1 in_sync Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/md6/md/dev-sdt Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/dev-sdt/state Lines: 1 spare Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/level Lines: 1 raid6 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/metadata_version Lines: 1 1.2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/raid_disks Lines: 1 4 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/rd0 SymlinkTo: dev-sdq # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/rd1 SymlinkTo: dev-sdr # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/rd2 SymlinkTo: dev-sds # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/rd3 SymlinkTo: dev-sdt # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/sync_action Lines: 1 recover Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/sync_completed Lines: 1 1569888 / 2093056 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/md6/md/uuid Lines: 1 5f529b25-6efd-46e4-99a2-31f6f597be6b Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/sda Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/sda/queue Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/add_random Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/chunk_sectors Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/dax Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/discard_granularity Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/discard_max_bytes Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/discard_max_hw_bytes Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/discard_zeroes_data Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/fua Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/hw_sector_size Lines: 1 512 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/io_poll Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/io_poll_delay Lines: 1 -1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/io_timeout Lines: 1 30000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/block/sda/queue/iosched Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/iosched/back_seek_max Lines: 1 16384 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/iosched/back_seek_penalty Lines: 1 2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/iosched/fifo_expire_async Lines: 1 250 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/iosched/fifo_expire_sync Lines: 1 125 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/iosched/low_latency Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/iosched/max_budget Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/iosched/slice_idle Lines: 1 8 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/iosched/slice_idle_us Lines: 1 8000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/iosched/strict_guarantees Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/iosched/timeout_sync Lines: 1 125 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/iostats Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/logical_block_size Lines: 1 512 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/max_discard_segments Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/max_hw_sectors_kb Lines: 1 32767 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/max_integrity_segments Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/max_sectors_kb Lines: 1 1280 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/max_segment_size Lines: 1 65536 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/max_segments Lines: 1 168 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/minimum_io_size Lines: 1 512 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/nomerges Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/nr_requests Lines: 1 64 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/nr_zones Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/optimal_io_size Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/physical_block_size Lines: 1 512 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/read_ahead_kb Lines: 1 128 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/rotational Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/rq_affinity Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/scheduler Lines: 1 mq-deadline kyber [bfq] none Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/wbt_lat_usec Lines: 1 75000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/write_cache Lines: 1 write back Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/write_same_max_bytes Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/write_zeroes_max_bytes Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/queue/zoned Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/block/sda/stat Lines: 1 9652963 396792 759304206 412943 8422549 6731723 286915323 13947418 0 5658367 19174573 1 2 3 12 Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/block Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/block/dm-0 SymlinkTo: ../../devices/virtual/block/dm-0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/block/dm-1 SymlinkTo: ../../devices/virtual/block/dm-1 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/block/dm-2 SymlinkTo: ../../devices/virtual/block/dm-2 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/block/dm-3 SymlinkTo: ../../devices/virtual/block/dm-3 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/block/dm-4 SymlinkTo: ../../devices/virtual/block/dm-4 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/block/dm-5 SymlinkTo: ../../devices/virtual/block/dm-5 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/dmi Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/dmi/id Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/bios_date Lines: 1 04/12/2021 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/bios_release Lines: 1 2.2 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/bios_vendor Lines: 1 Dell Inc. Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/bios_version Lines: 1 2.2.4 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/board_name Lines: 1 07PXPY Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/board_serial Lines: 1 .7N62AI2.GRTCL6944100GP. Mode: 400 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/board_vendor Lines: 1 Dell Inc. Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/board_version Lines: 1 A01 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/chassis_asset_tag Lines: 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/chassis_serial Lines: 1 7N62AI2 Mode: 400 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/chassis_type Lines: 1 23 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/chassis_vendor Lines: 1 Dell Inc. Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/chassis_version Lines: 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/modalias Lines: 1 dmi:bvnDellInc.:bvr2.2.4:bd04/12/2021:br2.2:svnDellInc.:pnPowerEdgeR6515:pvr:rvnDellInc.:rn07PXPY:rvrA01:cvnDellInc.:ct23:cvr: Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/product_family Lines: 1 PowerEdge Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/product_name Lines: 1 PowerEdge R6515 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/product_serial Lines: 1 7N62AI2 Mode: 400 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/product_sku Lines: 1 SKU=NotProvided;ModelName=PowerEdge R6515 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/product_uuid Lines: 1 83340ca8-cb49-4474-8c29-d2088ca84dd9 Mode: 400 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/product_version Lines: 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/sys_vendor Lines: 1 Dell Inc. Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/dmi/id/uevent Lines: 1 MODALIAS=dmi:bvnDellInc.:bvr2.2.4:bd04/12/2021:br2.2:svnDellInc.:pnPowerEdgeR6515:pvr:rvnDellInc.:rn07PXPY:rvrA01:cvnDellInc.:ct23:cvr: Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/drm Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/drm/card0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/drm/card0/device Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/aer_dev_correctable Lines: 9 RxErr 0 BadTLP 0 BadDLLP 0 Rollover 0 Timeout 0 NonFatalErr 0 CorrIntErr 0 HeaderOF 0 TOTAL_ERR_COR 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/aer_dev_fatal Lines: 19 Undefined 0 DLP 0 SDES 0 TLP 0 FCP 0 CmpltTO 0 CmpltAbrt 0 UnxCmplt 0 RxOF 0 MalfTLP 0 ECRC 0 UnsupReq 0 ACSViol 0 UncorrIntErr 0 BlockedTLP 0 AtomicOpBlocked 0 TLPBlockedErr 0 PoisonTLPBlocked 0 TOTAL_ERR_FATAL 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/aer_dev_nonfatal Lines: 19 Undefined 0 DLP 0 SDES 0 TLP 0 FCP 0 CmpltTO 0 CmpltAbrt 0 UnxCmplt 0 RxOF 0 MalfTLP 0 ECRC 0 UnsupReq 0 ACSViol 0 UncorrIntErr 0 BlockedTLP 0 AtomicOpBlocked 0 TLPBlockedErr 0 PoisonTLPBlocked 0 TOTAL_ERR_NONFATAL 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/ari_enabled Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/boot_vga Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/broken_parity_status Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/class Lines: 1 0x030000 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/consistent_dma_mask_bits Lines: 1 44 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/current_link_speed Lines: 1 8.0 GT/s PCIe Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/current_link_width Lines: 1 16 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/d3cold_allowed Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/device Lines: 1 0x687f Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/dma_mask_bits Lines: 1 44 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/driver_override Lines: 1 (null) Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/gpu_busy_percent Lines: 1 4 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/irq Lines: 1 95 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/local_cpulist Lines: 1 0-15 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/local_cpus Lines: 1 0000ffff Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/max_link_speed Lines: 1 8.0 GT/s PCIe Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/max_link_width Lines: 1 16 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/mem_info_gtt_total Lines: 1 8573157376 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/mem_info_gtt_used Lines: 1 144560128 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/mem_info_vis_vram_total Lines: 1 8573157376 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/mem_info_vis_vram_used Lines: 1 1490378752 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/mem_info_vram_total Lines: 1 8573157376 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/mem_info_vram_used Lines: 1 1490378752 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/mem_info_vram_vendor Lines: 1 samsung Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/modalias Lines: 1 pci:v00001002d0000687Fsv00001043sd000004C4bc03sc00i00 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/msi_bus Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/numa_node Lines: 1 -1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/pcie_bw Lines: 1 6641 815 256 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/pcie_replay_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/power_dpm_force_performance_level Lines: 1 manual Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/power_dpm_state Lines: 1 performance Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/power_state Lines: 1 D0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/pp_cur_state Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/pp_dpm_dcefclk Lines: 5 0: 600Mhz * 1: 720Mhz 2: 800Mhz 3: 847Mhz 4: 900Mhz Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/pp_dpm_mclk Lines: 4 0: 167Mhz * 1: 500Mhz 2: 800Mhz 3: 945Mhz Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/pp_dpm_pcie Lines: 2 0: 8.0GT/s, x16 1: 8.0GT/s, x16 * Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/pp_dpm_sclk Lines: 8 0: 852Mhz * 1: 991Mhz 2: 1084Mhz 3: 1138Mhz 4: 1200Mhz 5: 1401Mhz 6: 1536Mhz 7: 1630Mhz Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/pp_dpm_socclk Lines: 8 0: 600Mhz 1: 720Mhz * 2: 800Mhz 3: 847Mhz 4: 900Mhz 5: 960Mhz 6: 1028Mhz 7: 1107Mhz Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/pp_features Lines: 32 Current ppfeatures: 0x0000000019a1ff4f FEATURES BITMASK ENABLEMENT DPM_PREFETCHER 0x0000000000000001 Y GFXCLK_DPM 0x0000000000000002 Y UCLK_DPM 0x0000000000000004 Y SOCCLK_DPM 0x0000000000000008 Y UVD_DPM 0x0000000000000010 N VCE_DPM 0x0000000000000020 N ULV 0x0000000000000040 Y MP0CLK_DPM 0x0000000000000080 N LINK_DPM 0x0000000000000100 Y DCEFCLK_DPM 0x0000000000000200 Y AVFS 0x0000000000000400 Y GFXCLK_DS 0x0000000000000800 Y SOCCLK_DS 0x0000000000001000 Y LCLK_DS 0x0000000000002000 Y PPT 0x0000000000004000 Y TDC 0x0000000000008000 Y THERMAL 0x0000000000010000 Y GFX_PER_CU_CG 0x0000000000020000 N RM 0x0000000000040000 N DCEFCLK_DS 0x0000000000080000 N ACDC 0x0000000000100000 N VR0HOT 0x0000000000200000 Y VR1HOT 0x0000000000400000 N FW_CTF 0x0000000000800000 Y LED_DISPLAY 0x0000000001000000 Y FAN_CONTROL 0x0000000002000000 N FAST_PPT 0x0000000004000000 N DIDT 0x0000000008000000 Y ACG 0x0000000010000000 Y PCC_LIMIT 0x0000000020000000 N Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/pp_force_state Lines: 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/pp_mclk_od Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/pp_num_states Lines: 3 states: 2 0 boot 1 performance Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/pp_od_clk_voltage Lines: 18 OD_SCLK: 0: 852Mhz 800mV 1: 991Mhz 900mV 2: 1084Mhz 950mV 3: 1138Mhz 1000mV 4: 1200Mhz 1050mV 5: 1401Mhz 1100mV 6: 1536Mhz 1150mV 7: 1630Mhz 1200mV OD_MCLK: 0: 167Mhz 800mV 1: 500Mhz 800mV 2: 800Mhz 950mV 3: 945Mhz 1100mV OD_RANGE: SCLK: 852MHz 2400MHz MCLK: 167MHz 1500MHz VDDC: 800mV 1200mV Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/pp_power_profile_mode Lines: 8 NUM MODE_NAME BUSY_SET_POINT FPS USE_RLC_BUSY MIN_ACTIVE_LEVEL 0 BOOTUP_DEFAULT : 70 60 0 0 1 3D_FULL_SCREEN*: 70 60 1 3 2 POWER_SAVING : 90 60 0 0 3 VIDEO : 70 60 0 0 4 VR : 70 90 0 0 5 COMPUTE : 30 60 0 6 6 CUSTOM : 0 0 0 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/pp_sclk_od Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/product_name Lines: 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/product_number Lines: 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/resource Lines: 13 0x0000007c00000000 0x0000007dffffffff 0x000000000014220c 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000007e00000000 0x0000007e0fffffff 0x000000000014220c 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x000000000000d000 0x000000000000d0ff 0x0000000000040101 0x00000000fcd00000 0x00000000fcd7ffff 0x0000000000040200 0x00000000fcd80000 0x00000000fcd9ffff 0x0000000000046200 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/revision Lines: 1 0xc1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/serial_number Lines: 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/subsystem_device Lines: 1 0x04c4 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/subsystem_vendor Lines: 1 0x1043 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/thermal_throttling_logging Lines: 1 0000:09:00.0: thermal throttling logging enabled, with interval 60 seconds Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/uevent Lines: 6 DRIVER=amdgpu PCI_CLASS=30000 PCI_ID=1002:687F PCI_SUBSYS_ID=1043:04C4 PCI_SLOT_NAME=0000:09:00.0 MODALIAS=pci:v00001002d0000687Fsv00001043sd000004C4bc03sc00i00 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/unique_id Lines: 1 0123456789abcdef Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/vbios_version Lines: 1 115-D050PIL-100 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/drm/card0/device/vendor Lines: 1 0x1002 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/fc_host Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/fc_host/host0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/dev_loss_tmo Lines: 1 30 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/fabric_name Lines: 1 0x0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/node_name Lines: 1 0x2000e0071bce95f2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/port_id Lines: 1 0x000002 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/port_name Lines: 1 0x1000e0071bce95f2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/port_state Lines: 1 Online Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/port_type Lines: 1 Point-To-Point (direct nport connection) Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/speed Lines: 1 16 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/fc_host/host0/statistics Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/statistics/dumped_frames Lines: 1 0xffffffffffffffff Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/statistics/error_frames Lines: 1 0x0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/statistics/fcp_packet_aborts Lines: 1 0x13 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/statistics/invalid_crc_count Lines: 1 0x2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/statistics/invalid_tx_word_count Lines: 1 0x8 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/statistics/link_failure_count Lines: 1 0x9 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/statistics/loss_of_signal_count Lines: 1 0x11 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/statistics/loss_of_sync_count Lines: 1 0x10 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/statistics/nos_count Lines: 1 0x12 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/statistics/rx_frames Lines: 1 0x3 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/statistics/rx_words Lines: 1 0x4 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/statistics/seconds_since_last_reset Lines: 1 0x7 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/statistics/tx_frames Lines: 1 0x5 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/statistics/tx_words Lines: 1 0x6 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/supported_classes Lines: 1 Class 3 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/supported_speeds Lines: 1 4 Gbit, 8 Gbit, 16 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host0/symbolic_name Lines: 1 Emulex SN1100E2P FV12.4.270.3 DV12.4.0.0. HN:gotest. OS:Linux Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/fc_host/host1 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host1/port_state Lines: 1 Online Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/fc_host/host1/statistics Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host1/statistics/dumped_frames Lines: 1 0x0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host1/statistics/error_frames Lines: 1 0xffffffffffffffff Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host1/statistics/fcp_packet_aborts Lines: 1 0x130 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host1/statistics/invalid_crc_count Lines: 1 0x20 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host1/statistics/invalid_tx_word_count Lines: 1 0x80 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host1/statistics/link_failure_count Lines: 1 0x90 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host1/statistics/loss_of_signal_count Lines: 1 0x110 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host1/statistics/loss_of_sync_count Lines: 1 0x100 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host1/statistics/nos_count Lines: 1 0x120 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host1/statistics/rx_frames Lines: 1 0x30 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host1/statistics/rx_words Lines: 1 0x40 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host1/statistics/seconds_since_last_reset Lines: 1 0x70 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host1/statistics/tx_frames Lines: 1 0x50 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/fc_host/host1/statistics/tx_words Lines: 1 0x60 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/infiniband Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/infiniband/hfi1_0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/board_id Lines: 1 HPE 100Gb 1-port OP101 QSFP28 x16 PCIe Gen3 with Intel Omni-Path Adapter Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/fw_ver Lines: 1 1.27.0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/infiniband/hfi1_0/ports Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/infiniband/hfi1_0/ports/1 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/VL15_dropped Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/excessive_buffer_overrun_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/link_downed Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/link_error_recovery Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/local_link_integrity_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_rcv_constraint_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_rcv_data Lines: 1 345091702026 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_rcv_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_rcv_packets Lines: 1 638036947 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_rcv_remote_physical_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_rcv_switch_relay_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_xmit_constraint_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_xmit_data Lines: 1 273558326543 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_xmit_discards Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_xmit_packets Lines: 1 568318856 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/port_xmit_wait Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/counters/symbol_error Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/phys_state Lines: 1 5: LinkUp Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/rate Lines: 1 100 Gb/sec (4X EDR) Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/hfi1_0/ports/1/state Lines: 1 4: ACTIVE Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/infiniband/mlx4_0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/board_id Lines: 1 SM_1141000001000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/fw_ver Lines: 1 2.31.5050 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/hca_type Lines: 1 MT4099 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/infiniband/mlx4_0/ports Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/infiniband/mlx4_0/ports/1 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/VL15_dropped Lines: 1 0 Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/excessive_buffer_overrun_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/link_downed Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/link_error_recovery Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/local_link_integrity_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_constraint_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_data Lines: 1 2221223609 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_packets Lines: 1 87169372 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_remote_physical_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_rcv_switch_relay_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_xmit_constraint_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_xmit_data Lines: 1 26509113295 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_xmit_discards Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_xmit_packets Lines: 1 85734114 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/port_xmit_wait Lines: 1 3599 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/counters/symbol_error Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/phys_state Lines: 1 5: LinkUp Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/rate Lines: 1 40 Gb/sec (4X QDR) Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/1/state Lines: 1 4: ACTIVE Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/infiniband/mlx4_0/ports/2 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/VL15_dropped Lines: 1 0 Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/excessive_buffer_overrun_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/link_downed Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/link_error_recovery Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/local_link_integrity_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_constraint_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_data Lines: 1 2460436784 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_packets Lines: 1 89332064 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_remote_physical_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_rcv_switch_relay_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_xmit_constraint_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_xmit_data Lines: 1 26540356890 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_xmit_discards Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_xmit_packets Lines: 1 88622850 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/port_xmit_wait Lines: 1 3846 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/counters/symbol_error Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/phys_state Lines: 1 5: LinkUp Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/rate Lines: 1 40 Gb/sec (4X QDR) Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx4_0/ports/2/state Lines: 1 4: ACTIVE Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/infiniband/mlx5_0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/board_id Lines: 1 SM_2001000001034 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/fw_ver Lines: 1 14.28.2006 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/hca_type Lines: 1 MT4118 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/infiniband/mlx5_0/ports Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/infiniband/mlx5_0/ports/1 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/VL15_dropped Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/excessive_buffer_overrun_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/link_downed Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/link_error_recovery Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/local_link_integrity_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/multicast_rcv_packets Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/multicast_xmit_packets Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_rcv_constraint_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_rcv_data Lines: 1 18126345378 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_rcv_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_rcv_packets Lines: 1 541889824 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_rcv_remote_physical_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_rcv_switch_relay_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_xmit_constraint_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_xmit_data Lines: 1 2880761508848 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_xmit_discards Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_xmit_packets Lines: 1 10907922116 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/port_xmit_wait Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/symbol_error Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/unicast_rcv_packets Lines: 1 541889824 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/counters/unicast_xmit_packets Lines: 1 10907922116 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/duplicate_request Lines: 1 41 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/implied_nak_seq_err Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/lifespan Lines: 1 10 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/local_ack_timeout_err Lines: 1 131 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/out_of_buffer Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/out_of_sequence Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/packet_seq_err Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/req_cqe_error Lines: 1 3481 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/req_cqe_flush_error Lines: 1 80 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/req_remote_access_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/req_remote_invalid_request Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/resp_cqe_error Lines: 1 8109 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/resp_cqe_flush_error Lines: 1 4708 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/resp_local_length_error Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/resp_remote_access_errors Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/rnr_nak_retry_err Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/roce_adp_retrans Lines: 1 99 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/roce_adp_retrans_to Lines: 1 4 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/roce_slow_restart Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/roce_slow_restart_cnps Lines: 1 131 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/roce_slow_restart_trans Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/rx_atomic_requests Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/rx_dct_connect Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/rx_read_requests Lines: 1 175528982 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/hw_counters/rx_write_requests Lines: 1 742114 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/phys_state Lines: 1 4: ACTIVE Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/rate Lines: 1 25 Gb/sec (1X EDR) Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/infiniband/mlx5_0/ports/1/state Lines: 1 4: ACTIVE Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/net Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/net/eth0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/addr_assign_type Lines: 1 3 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/addr_len Lines: 1 6 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/address Lines: 1 01:01:01:01:01:01 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/broadcast Lines: 1 ff:ff:ff:ff:ff:ff Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/carrier Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/carrier_changes Lines: 1 2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/carrier_down_count Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/carrier_up_count Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/dev_id Lines: 1 0x20 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/device SymlinkTo: ../../../devices/pci0000:00/0000:00:1f.6/ # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/dormant Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/duplex Lines: 1 full Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/flags Lines: 1 0x1303 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/ifalias Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/ifindex Lines: 1 2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/iflink Lines: 1 2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/link_mode Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/mtu Lines: 1 1500 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/name_assign_type Lines: 1 2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/netdev_group Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/operstate Lines: 1 up Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/phys_port_id Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/phys_port_name Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/phys_switch_id Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/speed Lines: 1 1000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/tx_queue_len Lines: 1 1000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/net/eth0/type Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/nvme Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/nvme/nvme0 Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/nvme/nvme0/firmware_rev Lines: 1 1B2QEXP7 Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/nvme/nvme0/model Lines: 1 Samsung SSD 970 PRO 512GB Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/nvme/nvme0/serial Lines: 1 S680HF8N190894I Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/nvme/nvme0/state Lines: 1 live Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/power_supply Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/power_supply/AC SymlinkTo: ../../devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/power_supply/BAT0 SymlinkTo: ../../devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/powercap Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/powercap/intel-rapl Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl/enabled Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/powercap/intel-rapl:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_0_max_power_uw Lines: 1 95000000 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_0_name Lines: 1 long_term Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_0_power_limit_uw Lines: 1 4090000000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_0_time_window_us Lines: 1 999424 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_1_max_power_uw Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_1_name Lines: 1 short_term Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_1_power_limit_uw Lines: 1 4090000000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0/constraint_1_time_window_us Lines: 1 2440 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0/enabled Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0/energy_uj Lines: 1 240422366267 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0/max_energy_range_uj Lines: 1 262143328850 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0/name Lines: 1 package-0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/powercap/intel-rapl:0:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0:0/constraint_0_max_power_uw Lines: 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0:0/constraint_0_name Lines: 1 long_term Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0:0/constraint_0_power_limit_uw Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0:0/constraint_0_time_window_us Lines: 1 976 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0:0/enabled Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0:0/energy_uj Lines: 1 118821284256 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0:0/max_energy_range_uj Lines: 1 262143328850 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0:0/name Lines: 1 core Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:0:0/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/powercap/intel-rapl:a Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_max_power_uw Lines: 1 95000000 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_name Lines: 1 long_term Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_power_limit_uw Lines: 1 4090000000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_0_time_window_us Lines: 1 999424 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_max_power_uw Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_name Lines: 1 short_term Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_power_limit_uw Lines: 1 4090000000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:a/constraint_1_time_window_us Lines: 1 2440 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:a/enabled Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:a/energy_uj Lines: 1 240422366267 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:a/max_energy_range_uj Lines: 1 262143328850 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:a/name Lines: 1 package-10 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/powercap/intel-rapl:a/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/sas_device Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_device/end_device-11:0:0 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_device/end_device-11:0:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_device/end_device-11:0:1 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:1/end_device-11:0:1/sas_device/end_device-11:0:1 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_device/end_device-11:0:2 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:2/end_device-11:0:2/sas_device/end_device-11:0:2 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_device/end_device-11:2 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:2/end_device-11:2/sas_device/end_device-11:2 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_device/expander-11:0 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/sas_device/expander-11:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_device/expander-11:1 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:1/expander-11:1/sas_device/expander-11:1 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/sas_end_device Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_end_device/end_device-11:0:0 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_device/end_device-11:0:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_end_device/end_device-11:0:1 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:1/end_device-11:0:1/sas_device/end_device-11:0:1 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_end_device/end_device-11:0:2 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:2/end_device-11:0:2/sas_device/end_device-11:0:2 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_end_device/end_device-11:2 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:2/end_device-11:2/sas_device/end_device-11:2 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/sas_expander Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_expander/expander-11:0 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/sas_expander/expander-11:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_expander/expander-11:1 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:1/expander-11:1/sas_expander/expander-11:1 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/sas_host Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_host/host11 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/sas_host/host11 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/sas_phy Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_phy/phy-11:0:2 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_phy/phy-11:0:4 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_phy/phy-11:0:6 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_phy/phy-11:10 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_phy/phy-11:11 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_phy/phy-11:12 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_phy/phy-11:13 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_phy/phy-11:14 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_phy/phy-11:15 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_phy/phy-11:7 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_phy/phy-11:8 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_phy/phy-11:9 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/sas_port Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_port/port-11:0 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/sas_port/port-11:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_port/port-11:0:0 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/sas_port/port-11:0:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_port/port-11:0:1 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:1/sas_port/port-11:0:1 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_port/port-11:0:2 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:2/sas_port/port-11:0:2 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/sas_port/port-11:1 SymlinkTo: ../../devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:1/sas_port/port-11:1 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/scsi_tape Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/scsi_tape/nst0 SymlinkTo: ../../devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/scsi_tape/nst0a SymlinkTo: ../../devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/scsi_tape/nst0l SymlinkTo: ../../devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/scsi_tape/nst0m SymlinkTo: ../../devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/scsi_tape/st0 SymlinkTo: ../../devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/scsi_tape/st0a SymlinkTo: ../../devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/scsi_tape/st0l SymlinkTo: ../../devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/scsi_tape/st0m SymlinkTo: ../../devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/thermal Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/thermal/cooling_device0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/thermal/cooling_device0/cur_state Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/thermal/cooling_device0/max_state Lines: 1 50 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/thermal/cooling_device0/type Lines: 1 Processor Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/thermal/cooling_device1 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/thermal/cooling_device1/cur_state Lines: 1 -1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/thermal/cooling_device1/max_state Lines: 1 27 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/thermal/cooling_device1/type Lines: 1 intel_powerclamp Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/thermal/thermal_zone0 Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/thermal/thermal_zone0/policy Lines: 1 step_wise Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/thermal/thermal_zone0/temp Lines: 1 49925 Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/thermal/thermal_zone0/type Lines: 1 bcm2835_thermal Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/thermal/thermal_zone1 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/thermal/thermal_zone1/mode Lines: 1 enabled Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/thermal/thermal_zone1/passive Lines: 1 0 Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/thermal/thermal_zone1/policy Lines: 1 step_wise Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/thermal/thermal_zone1/temp Lines: 1 -44000 Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/thermal/thermal_zone1/type Lines: 1 acpitz Mode: 664 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/watchdog Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/watchdog/watchdog0 Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/watchdog/watchdog0/access_cs0 Lines: 1 0EOF Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/watchdog/watchdog0/bootstatus Lines: 1 1EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/watchdog/watchdog0/fw_version Lines: 1 2EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/watchdog/watchdog0/identity Lines: 1 Software WatchdogEOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/watchdog/watchdog0/nowayout Lines: 1 0EOF Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/watchdog/watchdog0/options Lines: 1 0x8380EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/watchdog/watchdog0/pretimeout Lines: 1 120EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/watchdog/watchdog0/pretimeout_governor Lines: 1 noopEOF Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/watchdog/watchdog0/state Lines: 1 activeEOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/watchdog/watchdog0/status Lines: 1 0x8000EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/watchdog/watchdog0/timeleft Lines: 1 300EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/class/watchdog/watchdog0/timeout Lines: 1 60EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/class/watchdog/watchdog1 Mode: 775 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/LNXSYSTM:00 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/device SymlinkTo: ../../../ACPI0003:00 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/online Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/async Lines: 1 disabled Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/autosuspend_delay_ms Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/control Lines: 1 auto Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_active_kids Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_active_time Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_enabled Lines: 1 disabled Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_status Lines: 1 unsupported Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_suspended_time Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/runtime_usage Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup Lines: 1 enabled Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_abort_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_active Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_active_count Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_expire_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_last_time_ms Lines: 1 10598 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_max_time_ms Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_prevent_sleep_time_ms Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/power/wakeup_total_time_ms Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/subsystem SymlinkTo: ../../../../../../../../../class/power_supply # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/type Lines: 1 Mains Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/ACPI0003:00/power_supply/AC/uevent Lines: 2 POWER_SUPPLY_NAME=AC POWER_SUPPLY_ONLINE=0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/alarm Lines: 1 2369000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/capacity Lines: 1 98 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/capacity_level Lines: 1 Normal Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/charge_start_threshold Lines: 1 95 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/charge_stop_threshold Lines: 1 100 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/cycle_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/device SymlinkTo: ../../../PNP0C0A:00 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/energy_full Lines: 1 50060000 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/energy_full_design Lines: 1 47520000 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/energy_now Lines: 1 49450000 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/manufacturer Lines: 1 LGC Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/model_name Lines: 1 LNV-45N1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/async Lines: 1 disabled Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/autosuspend_delay_ms Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/control Lines: 1 auto Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_active_kids Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_active_time Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_enabled Lines: 1 disabled Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_status Lines: 1 unsupported Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_suspended_time Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power/runtime_usage Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/power_now Lines: 1 4830000 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/present Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/serial_number Lines: 1 38109 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/status Lines: 1 Discharging Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/subsystem SymlinkTo: ../../../../../../../../../class/power_supply # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/technology Lines: 1 Li-ion Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/type Lines: 1 Battery Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/uevent Lines: 16 POWER_SUPPLY_NAME=BAT0 POWER_SUPPLY_STATUS=Discharging POWER_SUPPLY_PRESENT=1 POWER_SUPPLY_TECHNOLOGY=Li-ion POWER_SUPPLY_CYCLE_COUNT=0 POWER_SUPPLY_VOLTAGE_MIN_DESIGN=10800000 POWER_SUPPLY_VOLTAGE_NOW=11750000 POWER_SUPPLY_POWER_NOW=5064000 POWER_SUPPLY_ENERGY_FULL_DESIGN=47520000 POWER_SUPPLY_ENERGY_FULL=47390000 POWER_SUPPLY_ENERGY_NOW=40730000 POWER_SUPPLY_CAPACITY=85 POWER_SUPPLY_CAPACITY_LEVEL=Normal POWER_SUPPLY_MODEL_NAME=LNV-45N1 POWER_SUPPLY_MANUFACTURER=LGC POWER_SUPPLY_SERIAL_NUMBER=38109 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/voltage_min_design Lines: 1 10800000 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:00/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/voltage_now Lines: 1 12229000 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/in_flight Lines: 1 1EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/io_ns Lines: 1 9247011087720EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/other_cnt Lines: 1 1409EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/read_byte_cnt Lines: 1 979383912EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/read_cnt Lines: 1 3741EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/read_ns Lines: 1 33788355744EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/resid_cnt Lines: 1 19EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/write_byte_cnt Lines: 1 1496246784000EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/write_cnt Lines: 1 53772916EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0/stats/write_ns Lines: 1 5233597394395EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/in_flight Lines: 1 1EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/io_ns Lines: 1 9247011087720EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/other_cnt Lines: 1 1409EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/read_byte_cnt Lines: 1 979383912EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/read_cnt Lines: 1 3741EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/read_ns Lines: 1 33788355744EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/resid_cnt Lines: 1 19EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/write_byte_cnt Lines: 1 1496246784000EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/write_cnt Lines: 1 53772916EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0a/stats/write_ns Lines: 1 5233597394395EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/in_flight Lines: 1 1EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/io_ns Lines: 1 9247011087720EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/other_cnt Lines: 1 1409EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/read_byte_cnt Lines: 1 979383912EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/read_cnt Lines: 1 3741EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/read_ns Lines: 1 33788355744EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/resid_cnt Lines: 1 19EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/write_byte_cnt Lines: 1 1496246784000EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/write_cnt Lines: 1 53772916EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0l/stats/write_ns Lines: 1 5233597394395EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/in_flight Lines: 1 1EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/io_ns Lines: 1 9247011087720EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/other_cnt Lines: 1 1409EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/read_byte_cnt Lines: 1 979383912EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/read_cnt Lines: 1 3741EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/read_ns Lines: 1 33788355744EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/resid_cnt Lines: 1 19EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/write_byte_cnt Lines: 1 1496246784000EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/write_cnt Lines: 1 53772916EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/nst0m/stats/write_ns Lines: 1 5233597394395EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/in_flight Lines: 1 1EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/io_ns Lines: 1 9247011087720EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/other_cnt Lines: 1 1409EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/read_byte_cnt Lines: 1 979383912EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/read_cnt Lines: 1 3741EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/read_ns Lines: 1 33788355744EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/resid_cnt Lines: 1 19EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/write_byte_cnt Lines: 1 1496246784000EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/write_cnt Lines: 1 53772916EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0/stats/write_ns Lines: 1 5233597394395EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/in_flight Lines: 1 1EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/io_ns Lines: 1 9247011087720EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/other_cnt Lines: 1 1409EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/read_byte_cnt Lines: 1 979383912EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/read_cnt Lines: 1 3741EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/read_ns Lines: 1 33788355744EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/resid_cnt Lines: 1 19EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/write_byte_cnt Lines: 1 1496246784000EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/write_cnt Lines: 1 53772916EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0a/stats/write_ns Lines: 1 5233597394395EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/in_flight Lines: 1 1EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/io_ns Lines: 1 9247011087720EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/other_cnt Lines: 1 1409EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/read_byte_cnt Lines: 1 979383912EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/read_cnt Lines: 1 3741EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/read_ns Lines: 1 33788355744EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/resid_cnt Lines: 1 19EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/write_byte_cnt Lines: 1 1496246784000EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/write_cnt Lines: 1 53772916EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0l/stats/write_ns Lines: 1 5233597394395EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/in_flight Lines: 1 1EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/io_ns Lines: 1 9247011087720EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/other_cnt Lines: 1 1409EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/read_byte_cnt Lines: 1 979383912EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/read_cnt Lines: 1 3741EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/read_ns Lines: 1 33788355744EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/resid_cnt Lines: 1 19EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/write_byte_cnt Lines: 1 1496246784000EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/write_cnt Lines: 1 53772916EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:00.0/host0/port-0:0/end_device-0:0/target0:0:0/0:0:0:0/scsi_tape/st0m/stats/write_ns Lines: 1 5233597394395EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:00:03.0:pcie001 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:00:03.0:pcie001/driver SymlinkTo: ../../../../bus/pci_express/drivers/pcie_pme # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:00:03.0:pcie001/subsystem SymlinkTo: ../../../../bus/pci_express # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:00:03.0:pcie001/uevent Lines: 1 DRIVER=pcie_pme Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:00:03.0:pcie010 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:00:03.0:pcie010/subsystem SymlinkTo: ../../../../bus/pci_express # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:00:03.0:pcie010/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/aer_dev_correctable Lines: 9 RxErr 0 BadTLP 0 BadDLLP 0 Rollover 0 Timeout 0 NonFatalErr 0 CorrIntErr 0 HeaderOF 0 TOTAL_ERR_COR 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/aer_dev_fatal Lines: 19 Undefined 0 DLP 0 SDES 0 TLP 0 FCP 0 CmpltTO 0 CmpltAbrt 0 UnxCmplt 0 RxOF 0 MalfTLP 0 ECRC 0 UnsupReq 0 ACSViol 0 UncorrIntErr 0 BlockedTLP 0 AtomicOpBlocked 0 TLPBlockedErr 0 PoisonTLPBlocked 0 TOTAL_ERR_FATAL 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/aer_dev_nonfatal Lines: 19 Undefined 0 DLP 0 SDES 0 TLP 0 FCP 0 CmpltTO 0 CmpltAbrt 0 UnxCmplt 0 RxOF 0 MalfTLP 0 ECRC 0 UnsupReq 0 ACSViol 0 UncorrIntErr 0 BlockedTLP 0 AtomicOpBlocked 0 TLPBlockedErr 0 PoisonTLPBlocked 0 TOTAL_ERR_NONFATAL 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/ari_enabled Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/broken_parity_status Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/class Lines: 1 0x010700 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/config Lines: 1 NULLBYTE«NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE NULLBYTEøNULLBYTENULLBYTENULLBYTENULLBYTE NULLBYTENULLBYTEøNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE ûÐNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE@0NULLBYTENULLBYTEû@NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE NULLBYTENULLBYTEPNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTEp€NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE°NULLBYTE#€d ) NULLBYTEƒ|CNULLBYTE@NULLBYTEƒNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTEЀNULLBYTE NULLBYTENULLBYTENULLBYTE0NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE‚NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE@NULLBYTE0 FNULLBYTENULLBYTE NULLBYTENULLBYTENULLBYTE`NULLBYTENULLBYTE NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTEA%NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE'NULLBYTE'NULLBYTE'NULLBYTE'NULLBYTE'NULLBYTE'NULLBYTE'NULLBYTE'NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE¯NULLBYTESNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTEA%NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTEA(ÿNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE NULLBYTEA8NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE@NULLBYTENULLBYTENULLBYTEC1NULLBYTEK0NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTECDÿT?NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE NULLBYTEÁ;NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE'NULLBYTEÀNULLBYTEÀNULLBYTEÀNULLBYTEÀNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE@NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTEEOF Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/consistent_dma_mask_bits Lines: 1 63 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/current_link_speed Lines: 1 8.0 GT/s PCIe Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/current_link_width Lines: 1 8 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/d3cold_allowed Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/device Lines: 1 0x00ab Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/dma_mask_bits Lines: 1 63 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/driver SymlinkTo: ../../../../bus/pci/drivers/mpt3sas # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/driver_override Lines: 1 (null) Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/firmware_node SymlinkTo: ../../../LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:a6/device:a7 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/bsg Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/bsg/sas_host11 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/bsg/sas_host11/dev Lines: 1 243:4 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/bsg/sas_host11/device SymlinkTo: ../../../host11 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/bsg/sas_host11/subsystem SymlinkTo: ../../../../../../../class/bsg # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/bsg/sas_host11/uevent Lines: 3 MAJOR=243 MINOR=4 DEVNAME=bsg/sas_host11 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/port SymlinkTo: ../port-11:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/device SymlinkTo: ../../../phy-11:10 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/device_type Lines: 1 end device Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/initiator_port_protocols Lines: 1 smp, stp, ssp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/invalid_dword_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/minimum_linkrate Lines: 1 3.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/negotiated_linkrate Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/phy_identifier Lines: 1 10 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/running_disparity_error_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/sas_address Lines: 1 0x500062b2047b51c4 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/subsystem SymlinkTo: ../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/target_port_protocols Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/sas_phy/phy-11:10/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:10/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/port SymlinkTo: ../port-11:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/device SymlinkTo: ../../../phy-11:11 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/device_type Lines: 1 end device Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/initiator_port_protocols Lines: 1 smp, stp, ssp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/invalid_dword_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/minimum_linkrate Lines: 1 3.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/negotiated_linkrate Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/phy_identifier Lines: 1 11 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/running_disparity_error_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/sas_address Lines: 1 0x500062b2047b51c4 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/subsystem SymlinkTo: ../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/target_port_protocols Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/sas_phy/phy-11:11/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:11/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/port SymlinkTo: ../port-11:1 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/device SymlinkTo: ../../../phy-11:12 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/device_type Lines: 1 end device Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/initiator_port_protocols Lines: 1 smp, stp, ssp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/invalid_dword_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/minimum_linkrate Lines: 1 3.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/negotiated_linkrate Lines: 1 6.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/phy_identifier Lines: 1 12 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/running_disparity_error_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/sas_address Lines: 1 0x500062b2047b51c4 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/subsystem SymlinkTo: ../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/target_port_protocols Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/sas_phy/phy-11:12/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:12/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/port SymlinkTo: ../port-11:1 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/device SymlinkTo: ../../../phy-11:13 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/device_type Lines: 1 end device Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/initiator_port_protocols Lines: 1 smp, stp, ssp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/invalid_dword_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/minimum_linkrate Lines: 1 3.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/negotiated_linkrate Lines: 1 6.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/phy_identifier Lines: 1 13 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/running_disparity_error_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/sas_address Lines: 1 0x500062b2047b51c4 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/subsystem SymlinkTo: ../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/target_port_protocols Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/sas_phy/phy-11:13/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:13/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/port SymlinkTo: ../port-11:1 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/device SymlinkTo: ../../../phy-11:14 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/device_type Lines: 1 end device Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/initiator_port_protocols Lines: 1 smp, stp, ssp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/invalid_dword_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/minimum_linkrate Lines: 1 3.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/negotiated_linkrate Lines: 1 6.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/phy_identifier Lines: 1 14 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/running_disparity_error_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/sas_address Lines: 1 0x500062b2047b51c4 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/subsystem SymlinkTo: ../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/target_port_protocols Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/sas_phy/phy-11:14/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:14/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/port SymlinkTo: ../port-11:1 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/device SymlinkTo: ../../../phy-11:15 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/device_type Lines: 1 end device Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/initiator_port_protocols Lines: 1 smp, stp, ssp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/invalid_dword_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/minimum_linkrate Lines: 1 3.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/negotiated_linkrate Lines: 1 6.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/phy_identifier Lines: 1 15 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/running_disparity_error_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/sas_address Lines: 1 0x500062b2047b51c4 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/subsystem SymlinkTo: ../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/target_port_protocols Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/sas_phy/phy-11:15/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:15/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/port SymlinkTo: ../port-11:2 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/device SymlinkTo: ../../../phy-11:7 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/device_type Lines: 1 end device Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/initiator_port_protocols Lines: 1 smp, stp, ssp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/invalid_dword_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/minimum_linkrate Lines: 1 3.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/negotiated_linkrate Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/phy_identifier Lines: 1 7 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/running_disparity_error_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/sas_address Lines: 1 0x500062b2047b51c4 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/subsystem SymlinkTo: ../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/target_port_protocols Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/sas_phy/phy-11:7/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:7/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/port SymlinkTo: ../port-11:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/device SymlinkTo: ../../../phy-11:8 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/device_type Lines: 1 end device Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/initiator_port_protocols Lines: 1 smp, stp, ssp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/invalid_dword_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/minimum_linkrate Lines: 1 3.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/negotiated_linkrate Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/phy_identifier Lines: 1 8 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/running_disparity_error_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/sas_address Lines: 1 0x500062b2047b51c4 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/subsystem SymlinkTo: ../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/target_port_protocols Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/sas_phy/phy-11:8/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:8/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/port SymlinkTo: ../port-11:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/device SymlinkTo: ../../../phy-11:9 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/device_type Lines: 1 end device Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/initiator_port_protocols Lines: 1 smp, stp, ssp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/invalid_dword_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/minimum_linkrate Lines: 1 3.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/negotiated_linkrate Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/phy_identifier Lines: 1 9 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/running_disparity_error_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/sas_address Lines: 1 0x500062b2047b51c4 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/subsystem SymlinkTo: ../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/target_port_protocols Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/sas_phy/phy-11:9/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/phy-11:9/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/bsg Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/bsg/expander-11:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/bsg/expander-11:0/dev Lines: 1 243:8 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/bsg/expander-11:0/device SymlinkTo: ../../../expander-11:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/bsg/expander-11:0/subsystem SymlinkTo: ../../../../../../../../../class/bsg # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/bsg/expander-11:0/uevent Lines: 3 MAJOR=243 MINOR=8 DEVNAME=bsg/expander-11:0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/port SymlinkTo: ../port-11:0:4 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/device SymlinkTo: ../../../phy-11:0:10 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/device_type Lines: 1 edge expander Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/initiator_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/invalid_dword_count Lines: 1 20 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/loss_of_dword_sync_count Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/minimum_linkrate Lines: 1 1.5 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/negotiated_linkrate Lines: 1 6.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/phy_identifier Lines: 1 10 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/running_disparity_error_count Lines: 1 21 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/sas_address Lines: 1 0x5000ccab0200947e Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/subsystem SymlinkTo: ../../../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/target_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/sas_phy/phy-11:0:10/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:10/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/port SymlinkTo: ../port-11:0:5 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/device SymlinkTo: ../../../phy-11:0:11 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/device_type Lines: 1 edge expander Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/initiator_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/invalid_dword_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/minimum_linkrate Lines: 1 1.5 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/negotiated_linkrate Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/phy_identifier Lines: 1 11 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/running_disparity_error_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/sas_address Lines: 1 0x5000ccab0200947e Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/subsystem SymlinkTo: ../../../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/target_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/sas_phy/phy-11:0:11/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:11/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/port SymlinkTo: ../port-11:0:6 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/device SymlinkTo: ../../../phy-11:0:12 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/device_type Lines: 1 edge expander Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/initiator_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/invalid_dword_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/minimum_linkrate Lines: 1 1.5 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/negotiated_linkrate Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/phy_identifier Lines: 1 12 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/running_disparity_error_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/sas_address Lines: 1 0x5000ccab0200947e Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/subsystem SymlinkTo: ../../../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/target_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/sas_phy/phy-11:0:12/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:12/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/device SymlinkTo: ../../../phy-11:0:13 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/device_type Lines: 1 edge expander Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/initiator_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/invalid_dword_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/minimum_linkrate Lines: 1 1.5 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/negotiated_linkrate Lines: 1 Unknown Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/phy_identifier Lines: 1 13 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/running_disparity_error_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/sas_address Lines: 1 0x5000ccab0200947e Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/subsystem SymlinkTo: ../../../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/target_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/sas_phy/phy-11:0:13/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:13/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/port SymlinkTo: ../port-11:0:7 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/device SymlinkTo: ../../../phy-11:0:14 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/device_type Lines: 1 edge expander Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/initiator_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/invalid_dword_count Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/minimum_linkrate Lines: 1 1.5 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/negotiated_linkrate Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/phy_identifier Lines: 1 14 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/running_disparity_error_count Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/sas_address Lines: 1 0x5000ccab0200947e Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/subsystem SymlinkTo: ../../../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/target_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/sas_phy/phy-11:0:14/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:14/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/port SymlinkTo: ../port-11:0:8 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/device SymlinkTo: ../../../phy-11:0:15 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/device_type Lines: 1 edge expander Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/initiator_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/invalid_dword_count Lines: 1 19 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/loss_of_dword_sync_count Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/minimum_linkrate Lines: 1 1.5 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/negotiated_linkrate Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/phy_identifier Lines: 1 15 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/running_disparity_error_count Lines: 1 18 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/sas_address Lines: 1 0x5000ccab0200947e Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/subsystem SymlinkTo: ../../../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/target_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/sas_phy/phy-11:0:15/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:15/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/port SymlinkTo: ../port-11:0:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/device SymlinkTo: ../../../phy-11:0:2 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/device_type Lines: 1 edge expander Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/initiator_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/invalid_dword_count Lines: 1 18 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/loss_of_dword_sync_count Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/minimum_linkrate Lines: 1 1.5 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/negotiated_linkrate Lines: 1 6.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/phy_identifier Lines: 1 2 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/running_disparity_error_count Lines: 1 18 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/sas_address Lines: 1 0x5000ccab0200947e Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/subsystem SymlinkTo: ../../../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/target_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/sas_phy/phy-11:0:2/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:2/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/port SymlinkTo: ../port-11:0:1 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/device SymlinkTo: ../../../phy-11:0:4 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/device_type Lines: 1 edge expander Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/initiator_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/invalid_dword_count Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/minimum_linkrate Lines: 1 1.5 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/negotiated_linkrate Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/phy_identifier Lines: 1 4 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/running_disparity_error_count Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/sas_address Lines: 1 0x5000ccab0200947e Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/subsystem SymlinkTo: ../../../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/target_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/sas_phy/phy-11:0:4/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:4/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/port SymlinkTo: ../port-11:0:2 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/device SymlinkTo: ../../../phy-11:0:6 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/device_type Lines: 1 edge expander Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/initiator_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/invalid_dword_count Lines: 1 19 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/loss_of_dword_sync_count Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/minimum_linkrate Lines: 1 1.5 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/negotiated_linkrate Lines: 1 6.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/phy_identifier Lines: 1 6 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/running_disparity_error_count Lines: 1 20 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/sas_address Lines: 1 0x5000ccab0200947e Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/subsystem SymlinkTo: ../../../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/target_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/sas_phy/phy-11:0:6/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:6/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/device SymlinkTo: ../../../phy-11:0:7 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/device_type Lines: 1 edge expander Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/initiator_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/invalid_dword_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/minimum_linkrate Lines: 1 1.5 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/negotiated_linkrate Lines: 1 Unknown Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/phy_identifier Lines: 1 7 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/running_disparity_error_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/sas_address Lines: 1 0x5000ccab0200947e Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/subsystem SymlinkTo: ../../../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/target_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/sas_phy/phy-11:0:7/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:7/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/port SymlinkTo: ../port-11:0:3 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/device SymlinkTo: ../../../phy-11:0:8 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/device_type Lines: 1 edge expander Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/initiator_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/invalid_dword_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/minimum_linkrate Lines: 1 1.5 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/negotiated_linkrate Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/phy_identifier Lines: 1 8 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/running_disparity_error_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/sas_address Lines: 1 0x5000ccab0200947e Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/subsystem SymlinkTo: ../../../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/target_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/sas_phy/phy-11:0:8/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:8/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/device SymlinkTo: ../../../phy-11:0:9 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/device_type Lines: 1 edge expander Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/enable Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/initiator_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/invalid_dword_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/loss_of_dword_sync_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/maximum_linkrate Lines: 1 12.0 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/maximum_linkrate_hw Lines: 1 12.0 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/minimum_linkrate Lines: 1 1.5 Gbit Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/minimum_linkrate_hw Lines: 1 1.5 Gbit Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/negotiated_linkrate Lines: 1 Unknown Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/phy_identifier Lines: 1 9 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/phy_reset_problem_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/running_disparity_error_count Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/sas_address Lines: 1 0x5000ccab0200947e Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/subsystem SymlinkTo: ../../../../../../../../../../class/sas_phy # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/target_port_protocols Lines: 1 smp Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/sas_phy/phy-11:0:9/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/phy-11:0:9/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/bsg Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/bsg/end_device-11:0:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/bsg/end_device-11:0:0/dev Lines: 1 243:28 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/bsg/end_device-11:0:0/device SymlinkTo: ../../../end_device-11:0:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/bsg/end_device-11:0:0/subsystem SymlinkTo: ../../../../../../../../../../../class/bsg # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/bsg/end_device-11:0:0/uevent Lines: 3 MAJOR=243 MINOR=28 DEVNAME=bsg/end_device-11:0:0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_device Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_device/end_device-11:0:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_device/end_device-11:0:0/bay_identifier Lines: 1 58 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_device/end_device-11:0:0/device SymlinkTo: ../../../end_device-11:0:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_device/end_device-11:0:0/device_type Lines: 1 end device Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_device/end_device-11:0:0/enclosure_identifier Lines: 1 0x5000ccab020094ff Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_device/end_device-11:0:0/initiator_port_protocols Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_device/end_device-11:0:0/phy_identifier Lines: 1 2 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_device/end_device-11:0:0/sas_address Lines: 1 0x5000ccab02009402 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_device/end_device-11:0:0/scsi_target_id Lines: 1 7 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_device/end_device-11:0:0/subsystem SymlinkTo: ../../../../../../../../../../../class/sas_device # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_device/end_device-11:0:0/target_port_protocols Lines: 1 sata Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_device/end_device-11:0:0/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_end_device Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_end_device/end_device-11:0:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_end_device/end_device-11:0:0/I_T_nexus_loss_timeout Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_end_device/end_device-11:0:0/device SymlinkTo: ../../../end_device-11:0:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_end_device/end_device-11:0:0/initiator_response_timeout Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_end_device/end_device-11:0:0/ready_led_meaning Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_end_device/end_device-11:0:0/subsystem SymlinkTo: ../../../../../../../../../../../class/sas_end_device # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_end_device/end_device-11:0:0/tlr_enabled Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_end_device/end_device-11:0:0/tlr_supported Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/sas_end_device/end_device-11:0:0/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/blacklist Lines: 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/alignment_offset Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/bdi SymlinkTo: ../../../../../../../../../../../../virtual/bdi/65:80 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/capability Lines: 1 40 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/dev Lines: 1 65:80 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/device SymlinkTo: ../../../11:0:7:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/discard_alignment Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/diskseq Lines: 1 30 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/events Lines: 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/events_async Lines: 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/events_poll_msecs Lines: 1 -1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/ext_range Lines: 1 256 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/hidden Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/holders Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/inflight Lines: 1 0 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/range Lines: 1 16 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/removable Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/ro Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/size Lines: 1 15628053168 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/slaves Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/stat Lines: 1 4943710 80 5731521173 123364688 448389 952 7964552 336708 0 44594772 125478500 0 0 0 0 44059 1777103 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/subsystem SymlinkTo: ../../../../../../../../../../../../../class/block # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/block/sdv/uevent Lines: 5 MAJOR=65 MINOR=80 DEVNAME=sdv DEVTYPE=disk DISKSEQ=30 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/bsg Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/bsg/11:0:7:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/bsg/11:0:7:0/dev Lines: 1 243:105 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/bsg/11:0:7:0/device SymlinkTo: ../../../11:0:7:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/bsg/11:0:7:0/subsystem SymlinkTo: ../../../../../../../../../../../../../class/bsg # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/bsg/11:0:7:0/uevent Lines: 3 MAJOR=243 MINOR=105 DEVNAME=bsg/11:0:7:0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/device_blocked Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/device_busy Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/dh_state Lines: 1 detached Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/driver SymlinkTo: ../../../../../../../../../../../bus/scsi/drivers/sd # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/eh_timeout Lines: 1 10 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/evt_capacity_change_reported Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/evt_inquiry_change_reported Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/evt_lun_change_reported Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/evt_media_change Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/evt_mode_parameter_change_reported Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/evt_soft_threshold_reached Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/generic SymlinkTo: scsi_generic/sg23 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/inquiry Lines: 1 NULLBYTENULLBYTEENULLBYTENULLBYTEATA ST8000DM004-2CX10001 ZCT0CQLKNULLBYTENULLBYTENULLBYTE€à`À ý# NULLBYTENULLBYTEEOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/iocounterbits Lines: 1 32 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/iodone_cnt Lines: 1 0x52470f Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/ioerr_cnt Lines: 1 0x261 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/iorequest_cnt Lines: 1 0x524caa Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/modalias Lines: 1 scsi:t-0x00 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/model Lines: 1 ST8000DM004-2CX1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/queue_depth Lines: 1 128 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/queue_ramp_up_period Lines: 1 120000 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/queue_type Lines: 1 simple Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/rev Lines: 1 0001 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/sas_address Lines: 1 0x5000ccab02009402 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/sas_device_handle Lines: 1 0x002d Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/sas_ncq_prio_enable Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/sas_ncq_prio_supported Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_device Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_device/11:0:7:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_device/11:0:7:0/device SymlinkTo: ../../../11:0:7:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_device/11:0:7:0/subsystem SymlinkTo: ../../../../../../../../../../../../../class/scsi_device # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_device/11:0:7:0/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/FUA Lines: 1 1 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/allow_restart Lines: 1 1 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/app_tag_own Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/cache_type Lines: 1 write back Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/device SymlinkTo: ../../../11:0:7:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/manage_start_stop Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/max_medium_access_timeouts Lines: 1 2 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/max_retries Lines: 1 5 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/max_write_same_blocks Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/protection_mode Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/protection_type Lines: 1 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/provisioning_mode Lines: 1 full Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/subsystem SymlinkTo: ../../../../../../../../../../../../../class/scsi_disk # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/thin_provisioning Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/uevent Lines: 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/zeroing_mode Lines: 1 write Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_disk/11:0:7:0/zoned_cap Lines: 1 none Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_generic Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Directory: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_generic/sg23 Mode: 755 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_generic/sg23/dev Lines: 1 21:23 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_generic/sg23/device SymlinkTo: ../../../11:0:7:0 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_generic/sg23/subsystem SymlinkTo: ../../../../../../../../../../../../../class/scsi_generic # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_generic/sg23/uevent Lines: 3 MAJOR=21 MINOR=23 DEVNAME=sg23 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/scsi_level Lines: 1 7 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/state Lines: 1 running Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/subsystem SymlinkTo: ../../../../../../../../../../../bus/scsi # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/timeout Lines: 1 30 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/type Lines: 1 0 Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/uevent Lines: 3 DEVTYPE=scsi_device DRIVER=sd MODALIAS=scsi:t-0x00 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/vendor Lines: 1 ATA Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/vpd_pg0 Lines: 1 NULLBYTENULLBYTENULLBYTE NULLBYTE€ƒ‡‰Š°±²EOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/vpd_pg80 Lines: 1 NULLBYTE€NULLBYTE ZCT0CQLKEOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/vpd_pg83 Lines: 1 NULLBYTEƒNULLBYTE NULLBYTEPNULLBYTEÅNULLBYTE³-œa“NULLBYTEPNULLBYTEÌ«NULLBYTE”NULLBYTENULLBYTENULLBYTENULLBYTEEOF Mode: 444 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/sys/devices/pci0000:00/0000:00:03.0/0000:03:00.0/host11/port-11:0/expander-11:0/port-11:0:0/end_device-11:0:0/target11:0:7/11:0:7:0/vpd_pg89 Lines: 2 NULLBYTE‰8NULLBYTENULLBYTENULLBYTENULLBYTELSI LSI SATL 00084@PNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTEìNULLBYTENULLBYTENULLBYTEZ ÿ?7ÈNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE?NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE CZ0TQCKLNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE0010 TS0800MD00-4C21X88 €NULLBYTE@NULLBYTE/NULLBYTE@NULLBYTENULLBYTENULLBYTEÿ?NULLBYTE?NULLBYTEüûNULLBYTE ÿÿÿNULLBYTENULLBYTENULLBYTENULLBYTExNULLBYTExNULLBYTExNULLBYTExNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE‡NULLBYTEÌNULLBYTEDNULLBYTEðmNULLBYTEk4a}cAi4A¼cA@ññNULLBYTENULLBYTEþÿNULLBYTENULLBYTEÐÐNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE°*£NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE`NULLBYTENULLBYTENULLBYTEPNULLBYTEÅ-³œNULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTEÜ@œ@NULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTENULLBYTE!NULLBYTE°*£°*£ NULLBYTE@NULLBYTENULLBYTEP<