// This test is racy. If an external process consumes space while this // runs, we may see spurious differences between the two statfs() calls. func TestStatFs(t *testing.T) { ts := NewTestCase(t) defer ts.Cleanup() empty := syscall.Statfs_t{} s1 := empty err := syscall.Statfs(ts.orig, &s1) if err != 0 { t.Fatal("statfs orig", err) } s2 := syscall.Statfs_t{} err = syscall.Statfs(ts.mnt, &s2) s1.Type = 0 s2.Type = 0 s1.Fsid = empty.Fsid s2.Fsid = empty.Fsid s1.Spare = empty.Spare s2.Spare = empty.Spare if err != 0 { t.Fatal("statfs mnt", err) } if fmt.Sprintf("%v", s2) != fmt.Sprintf("%v", s1) { t.Error("Mismatch", s1, s2) } }
func TestClientStatVFS(t *testing.T) { if *testServerImpl { t.Skipf("go server does not support FXP_EXTENDED") } sftp, cmd := testClient(t, READWRITE, NO_DELAY) defer cmd.Wait() defer sftp.Close() vfs, err := sftp.StatVFS("/") if err != nil { t.Fatal(err) } // get system stats s := syscall.Statfs_t{} err = syscall.Statfs("/", &s) if err != nil { t.Fatal(err) } // check some stats if vfs.Files != uint64(s.Files) { t.Fatal("fr_size does not match") } if vfs.Bfree != uint64(s.Bfree) { t.Fatal("f_bsize does not match") } if vfs.Favail != uint64(s.Ffree) { t.Fatal("f_namemax does not match") } }
// Mounted checks if the given path is mounted as the fs type func Mounted(fsType FsMagic, mountPath string) (bool, error) { var buf syscall.Statfs_t if err := syscall.Statfs(mountPath, &buf); err != nil { return false, err } return FsMagic(buf.Type) == fsType, nil }
// getSelinuxMountPoint returns the path to the mountpoint of an selinuxfs // filesystem or an empty string if no mountpoint is found. Selinuxfs is // a proc-like pseudo-filesystem that exposes the selinux policy API to // processes. The existence of an selinuxfs mount is used to determine // whether selinux is currently enabled or not. func getSelinuxMountPoint() string { if selinuxfs != "unknown" { return selinuxfs } selinuxfs = "" mounts, err := mount.GetMounts() if err != nil { return selinuxfs } for _, mount := range mounts { if mount.Fstype == "selinuxfs" { selinuxfs = mount.Mountpoint break } } if selinuxfs != "" { var buf syscall.Statfs_t syscall.Statfs(selinuxfs, &buf) if (buf.Flags & stRdOnly) == 1 { selinuxfs = "" } } return selinuxfs }
// New - instantiate new disk func New(diskPath string) (Disk, error) { if diskPath == "" { return Disk{}, iodine.New(InvalidArgument{}, nil) } st, err := os.Stat(diskPath) if err != nil { return Disk{}, iodine.New(err, nil) } if !st.IsDir() { return Disk{}, iodine.New(syscall.ENOTDIR, nil) } s := syscall.Statfs_t{} err = syscall.Statfs(diskPath, &s) if err != nil { return Disk{}, iodine.New(err, nil) } disk := Disk{ lock: &sync.Mutex{}, path: diskPath, fsInfo: make(map[string]string), } if fsType := getFSType(s.Type); fsType != "UNKNOWN" { disk.fsInfo["FSType"] = fsType disk.fsInfo["MountPoint"] = disk.path return disk, nil } return Disk{}, iodine.New(UnsupportedFilesystem{Type: strconv.FormatInt(int64(s.Type), 10)}, map[string]string{"Type": strconv.FormatInt(int64(s.Type), 10)}) }
/* * filesystemDetect returns the filesystem on which * the passed-in path sits */ func filesystemDetect(path string) (string, error) { fs := syscall.Statfs_t{} err := syscall.Statfs(path, &fs) if err != nil { return "", err } switch fs.Type { case filesystemSuperMagicBtrfs: return "btrfs", nil case filesystemSuperMagicZfs: return "zfs", nil case filesystemSuperMagicTmpfs: return "tmpfs", nil case filesystemSuperMagicExt4: return "ext4", nil case filesystemSuperMagicXfs: return "xfs", nil case filesystemSuperMagicNfs: return "nfs", nil default: shared.Debugf("Unknown backing filesystem type: 0x%x", fs.Type) return string(fs.Type), nil } }
// isPathInDMG errors if the path is inside dmg func isPathInDMG(p string) (inDMG bool, bundlePath string, err error) { var stat syscall.Statfs_t err = syscall.Statfs(p, &stat) if err != nil { return } // mntRootFS identifies the root filesystem (http://www.opensource.apple.com/source/xnu/xnu-344.26/bsd/sys/mount.h) const mntRootFS = 0x00004000 if (stat.Flags & mntRootFS) != 0 { // We're on the root filesystem so we're not in a DMG return } bundlePath = bundleDirForPath(p) if bundlePath != "" { // Look for Applications symlink in the same folder as Keybase.app, and if // we find it, we're really likely to be in a mounted dmg appLink := filepath.Join(filepath.Dir(bundlePath), "Applications") fi, ferr := os.Lstat(appLink) if os.IsNotExist(ferr) { return } isLink := (fi.Mode()&os.ModeSymlink != 0) if isLink { inDMG = true return } } return }
func BuildDeviceUsage(_fsSpec, _fsFile, _fsVfstype string) (*DeviceUsage, error) { ret := &DeviceUsage{FsSpec: _fsSpec, FsFile: _fsFile, FsVfstype: _fsVfstype} fs := syscall.Statfs_t{} err := syscall.Statfs(_fsFile, &fs) if err != nil { return nil, err } // blocks used := fs.Blocks - fs.Bfree ret.BlocksAll = uint64(fs.Frsize) * fs.Blocks ret.BlocksUsed = uint64(fs.Frsize) * used ret.BlocksFree = uint64(fs.Frsize) * fs.Bavail if fs.Blocks == 0 { ret.BlocksUsedPercent = 100.0 } else { ret.BlocksUsedPercent = float64(used) * 100.0 / float64(used+fs.Bavail) } ret.BlocksFreePercent = 100.0 - ret.BlocksUsedPercent // inodes ret.InodesAll = fs.Files ret.InodesFree = fs.Ffree ret.InodesUsed = fs.Files - fs.Ffree if fs.Files == 0 { ret.InodesUsedPercent = 100.0 } else { ret.InodesUsedPercent = float64(ret.InodesUsed) * 100.0 / float64(ret.InodesAll) } ret.InodesFreePercent = 100.0 - ret.InodesUsedPercent return ret, nil }
func getImageAndWrite(imageClient *rpc.Client, objectClient *objectclient.ObjectClient, name, dirname string) error { inodesDir := dirname + ".inodes" if err := os.Mkdir(inodesDir, dirPerms); err != nil { return err } defer os.RemoveAll(inodesDir) fs, err := getImage(imageClient, name) if err != nil { return err } var statfs syscall.Statfs_t if err := syscall.Statfs(inodesDir, &statfs); err != nil { return errors.New(fmt.Sprintf("Unable to Statfs: %s %s\n", inodesDir, err)) } if fs.TotalDataBytes > uint64(statfs.Bsize)*statfs.Bfree { return errors.New("image will not fit on file-system") } hashes, inums, lengths := getHashes(fs) err = writeObjects(objectClient, hashes, inums, lengths, inodesDir) if err != nil { return err } if err := writeInodes(fs.InodeTable, inodesDir); err != nil { return err } if err = fs.DirectoryInode.Write(dirname); err != nil { return err } return buildTree(&fs.DirectoryInode, dirname, inodesDir) }
// Expose filesystem fullness. func (c *filesystemCollector) Update(ch chan<- prometheus.Metric) (err error) { mpds, err := mountPointDetails() if err != nil { return err } for _, mpd := range mpds { if c.ignoredMountPointsPattern.MatchString(mpd.mountPoint) { log.Debugf("Ignoring mount point: %s", mpd.mountPoint) continue } buf := new(syscall.Statfs_t) err := syscall.Statfs(mpd.mountPoint, buf) if err != nil { return fmt.Errorf("Statfs on %s returned %s", mpd.mountPoint, err) } c.size.WithLabelValues(mpd.device, mpd.mountPoint, mpd.fsType).Set(float64(buf.Blocks) * float64(buf.Bsize)) c.free.WithLabelValues(mpd.device, mpd.mountPoint, mpd.fsType).Set(float64(buf.Bfree) * float64(buf.Bsize)) c.avail.WithLabelValues(mpd.device, mpd.mountPoint, mpd.fsType).Set(float64(buf.Bavail) * float64(buf.Bsize)) c.files.WithLabelValues(mpd.device, mpd.mountPoint, mpd.fsType).Set(float64(buf.Files)) c.filesFree.WithLabelValues(mpd.device, mpd.mountPoint, mpd.fsType).Set(float64(buf.Ffree)) } c.size.Collect(ch) c.free.Collect(ch) c.avail.Collect(ch) c.files.Collect(ch) c.filesFree.Collect(ch) return err }
func IsNSorErr(nspath string) error { stat := syscall.Statfs_t{} if err := syscall.Statfs(nspath, &stat); err != nil { if os.IsNotExist(err) { err = NSPathNotExistErr{msg: fmt.Sprintf("failed to Statfs %q: %v", nspath, err)} } else { err = fmt.Errorf("failed to Statfs %q: %v", nspath, err) } return err } switch stat.Type { case PROCFS_MAGIC: // Kernel < 3.19 validPathContent := "ns/" validName := strings.Contains(nspath, validPathContent) if !validName { return NSPathNotNSErr{msg: fmt.Sprintf("path %q doesn't contain %q", nspath, validPathContent)} } return nil case NSFS_MAGIC: // Kernel >= 3.19 return nil default: return NSPathNotNSErr{msg: fmt.Sprintf("unknown FS magic on %q: %x", nspath, stat.Type)} } }
func BuildDeviceUsage(arr [3]string) (*DeviceUsageStruct, error) { ret := &DeviceUsageStruct{FsSpec: arr[0], FsFile: arr[1], FsVfstype: arr[2]} fs := syscall.Statfs_t{} err := syscall.Statfs(arr[1], &fs) if err != nil { return nil, err } // blocks used := fs.Blocks - fs.Bfree ret.BlocksAll = uint64(fs.Frsize) * fs.Blocks ret.BlocksUsed = uint64(fs.Frsize) * used ret.BlocksFree = uint64(fs.Frsize) * fs.Bfree if fs.Blocks == 0 { ret.BlocksUsedPercent = 100.0 } else { ret.BlocksUsedPercent = float64(float64(used) * 100.0 / float64(fs.Blocks)) } ret.BlocksFreePercent = 100.0 - ret.BlocksUsedPercent // inodes ret.InodesAll = fs.Files ret.InodesFree = fs.Ffree ret.InodesUsed = fs.Files - fs.Ffree if fs.Files == 0 { ret.InodesUsedPercent = 100.0 } else { ret.InodesUsedPercent = float64(float64(ret.InodesUsed) * 100.0 / float64(ret.InodesAll)) } ret.InodesFreePercent = 100.0 - ret.InodesUsedPercent return ret, nil }
func (t *StatFSTest) Syscall_NonZeroValues() { var err error var stat syscall.Statfs_t // Set up the canned response. canned := fuseops.StatFSOp{ BlockSize: 1 << 15, IoSize: 1 << 16, Blocks: 1<<51 + 3, BlocksFree: 1<<43 + 5, BlocksAvailable: 1<<41 + 7, Inodes: 1<<59 + 11, InodesFree: 1<<58 + 13, } t.fs.SetStatFSResponse(canned) // Stat. err = syscall.Statfs(t.Dir, &stat) AssertEq(nil, err) ExpectEq(canned.BlockSize, stat.Frsize) ExpectEq(canned.IoSize, stat.Bsize) ExpectEq(canned.Blocks, stat.Blocks) ExpectEq(canned.BlocksFree, stat.Bfree) ExpectEq(canned.BlocksAvailable, stat.Bavail) ExpectEq(canned.Inodes, stat.Files) ExpectEq(canned.InodesFree, stat.Ffree) }
func DiskUsage(path string) (disk DiskStatus) { fs := syscall.Statfs_t{} err := syscall.Statfs(path, &fs) if err != nil { return } fmt.Print("", "Type:", fs.Type, "\n", /* Type of filesystem (see below) */ "Bsize:", fs.Bsize, "\n", /* Optimal transfer block size */ "Blocks:", fs.Blocks, "\n", /* Total data blocks in filesystem */ "Bfree:", fs.Bfree, "\n", /* Free blocks in filesystem */ "Bavail:", fs.Bavail, "\n", /* Free blocks available to unprivileged user*/ "Files:", fs.Files, "\n", /* Total file nodes in filesystem */ "Ffree:", fs.Ffree, "\n", /* Free file nodes in filesystem */ //"Fsid:", fs.Bsize, "\n",/* Filesystem ID */ "Namelen:", fs.Namelen, "\n", /* Maximum length of filenames */ "Frsize:", fs.Frsize, "\n", /* Fragment size (since Linux 2.6) */ "Flags:", fs.Flags, "\n", /* Mount flags of filesystem (since Linux 2.6.36) */ //"Spare:", fs.Bsize, "\n", /* Padding bytes reserved for future use */ ) disk.All = fs.Blocks * uint64(fs.Bsize) disk.Free = fs.Bfree * uint64(fs.Bsize) disk.Used = disk.All - disk.Free fmt.Println("", "Total:", disk.All, bytefmt.ByteSize(disk.All), "\n", "Used:", disk.Used, bytefmt.ByteSize(disk.Used), "\n", "Free:", disk.Free, bytefmt.ByteSize(disk.Free)) return }
func (m *DiskSpaceMeasurer) Measure() (float64, error) { var res syscall.Statfs_t if err := syscall.Statfs(m.path, &res); err != nil { return 0, err } return float64(res.Blocks-res.Bavail) * float64(res.Bsize), nil }
func TestClientStatVFS(t *testing.T) { if *testServerImpl { t.Skipf("go server does not support FXP_EXTENDED") } sftp, cmd := testClient(t, READWRITE, NO_DELAY) defer cmd.Wait() defer sftp.Close() vfs, err := sftp.StatVFS("/") if err != nil { t.Fatal(err) } // get system stats s := syscall.Statfs_t{} err = syscall.Statfs("/", &s) if err != nil { t.Fatal(err) } // check some stats if vfs.Frsize != uint64(s.Frsize) { t.Fatalf("fr_size does not match, expected: %v, got: %v", s.Frsize, vfs.Frsize) } if vfs.Bsize != uint64(s.Bsize) { t.Fatalf("f_bsize does not match, expected: %v, got: %v", s.Bsize, vfs.Bsize) } if vfs.Namemax != uint64(s.Namelen) { t.Fatalf("f_namemax does not match, expected: %v, got: %v", s.Namelen, vfs.Namemax) } }
func Usage(path string) (*UsageStat, error) { stat := syscall.Statfs_t{} err := syscall.Statfs(path, &stat) if err != nil { return nil, err } bsize := stat.Bsize ret := &UsageStat{ Path: path, Fstype: getFsType(stat), Total: (uint64(stat.Blocks) * uint64(bsize)), Free: (uint64(stat.Bavail) * uint64(bsize)), InodesTotal: (uint64(stat.Files)), InodesFree: (uint64(stat.Ffree)), } // if could not get InodesTotal, return empty if ret.InodesTotal < ret.InodesFree { return ret, nil } ret.InodesUsed = (ret.InodesTotal - ret.InodesFree) ret.InodesUsedPercent = (float64(ret.InodesUsed) / float64(ret.InodesTotal)) * 100.0 ret.Used = (uint64(stat.Blocks) - uint64(stat.Bfree)) * uint64(bsize) ret.UsedPercent = (float64(ret.Used) / float64(ret.Total)) * 100.0 return ret, nil }
// NewDisk - instantiate new disk func NewDisk(diskPath string, diskOrder int) (Disk, error) { if diskPath == "" || diskOrder < 0 { return nil, iodine.New(InvalidArgument{}, nil) } s := syscall.Statfs_t{} err := syscall.Statfs(diskPath, &s) if err != nil { return nil, iodine.New(err, nil) } st, err := os.Stat(diskPath) if err != nil { return nil, iodine.New(err, nil) } if !st.IsDir() { return nil, iodine.New(syscall.ENOTDIR, nil) } d := disk{ root: diskPath, order: diskOrder, filesystem: make(map[string]string), } if fsType := d.getFSType(s.Type); fsType != "UNKNOWN" { d.filesystem["FSType"] = fsType d.filesystem["MountPoint"] = d.root return d, nil } return nil, iodine.New(UnsupportedFilesystem{ Type: strconv.FormatInt(s.Type, 10), }, map[string]string{"Type": strconv.FormatInt(s.Type, 10)}) }
// Init returns a new BTRFS driver. // An error is returned if BTRFS is not supported. func Init(home string, options []string) (graphdriver.Driver, error) { rootdir := path.Dir(home) var buf syscall.Statfs_t if err := syscall.Statfs(rootdir, &buf); err != nil { return nil, err } if graphdriver.FsMagic(buf.Type) != graphdriver.FsMagicBtrfs { return nil, graphdriver.ErrPrerequisites } if err := os.MkdirAll(home, 0700); err != nil { return nil, err } if err := mount.MakePrivate(home); err != nil { return nil, err } driver := &Driver{ home: home, } return graphdriver.NaiveDiffDriver(driver), nil }
func (t *GcsfuseTest) Statfs() { var err error var stat syscall.Statfs_t // Mount. args := []string{canned.FakeBucketName, t.dir} err = t.runGcsfuse(args) AssertEq(nil, err) defer unmount(t.dir) // Stat the file system. err = syscall.Statfs(t.dir, &stat) AssertEq(nil, err) // The FS should show a reasonable number of bytes available, so that e.g. // the Finder doesn't refuse to copy files into it. AssertNe(0, stat.Frsize) AssertLe(stat.Blocks, math.MaxUint64/uint64(stat.Frsize)) ExpectGe(uint64(stat.Frsize)*stat.Blocks, 1<<50) ExpectEq(stat.Blocks, stat.Bfree) ExpectEq(stat.Bfree, stat.Bavail) // Similarly with inodes. ExpectGe(stat.Files, 1<<40) ExpectEq(stat.Files, stat.Ffree) // The recommended IO size should not be pitiful. ExpectEq(1<<20, stat.Bsize) }
// Init returns a new BTRFS driver. // An error is returned if BTRFS is not supported. func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) { rootdir := path.Dir(home) var buf syscall.Statfs_t if err := syscall.Statfs(rootdir, &buf); err != nil { return nil, err } if graphdriver.FsMagic(buf.Type) != graphdriver.FsMagicBtrfs { return nil, graphdriver.ErrPrerequisites } rootUID, rootGID, err := idtools.GetRootUIDGID(uidMaps, gidMaps) if err != nil { return nil, err } if err := idtools.MkdirAllAs(home, 0700, rootUID, rootGID); err != nil { return nil, err } if err := mount.MakePrivate(home); err != nil { return nil, err } driver := &Driver{ home: home, uidMaps: uidMaps, gidMaps: gidMaps, } return graphdriver.NewNaiveDiffDriver(driver, uidMaps, gidMaps), nil }
func (poller Df) Poll(tick time.Time) { ctx := slog.Context{"poller": poller.Name(), "fn": "Poll", "tick": tick} buf := new(syscall.Statfs_t) for mp := range poller.mountpointChannel() { err := syscall.Statfs(mp, buf) if err != nil { ctx["mountpoint"] = mp LogError(ctx, err, "calling Statfs") poller.measurements <- GaugeMeasurement{tick, poller.Name(), []string{"error"}, 1, Errors} continue } mmp := massageMountPoint(mp) total_bytes := uint64(buf.Bsize) * buf.Blocks user_free_bytes := uint64(buf.Bsize) * buf.Bavail root_free_bytes := uint64(buf.Bsize)*buf.Bfree - user_free_bytes used_bytes := total_bytes - root_free_bytes - user_free_bytes poller.measurements <- GaugeMeasurement{tick, poller.Name(), []string{mmp, "total", "bytes"}, total_bytes, Bytes} poller.measurements <- GaugeMeasurement{tick, poller.Name(), []string{mmp, "root", "free", "bytes"}, root_free_bytes, Bytes} poller.measurements <- GaugeMeasurement{tick, poller.Name(), []string{mmp, "user", "free", "bytes"}, user_free_bytes, Bytes} poller.measurements <- GaugeMeasurement{tick, poller.Name(), []string{mmp, "used", "bytes"}, used_bytes, Bytes} poller.measurements <- GaugeMeasurement{tick, poller.Name(), []string{mmp, "total", "inodes"}, buf.Files, INodes} poller.measurements <- GaugeMeasurement{tick, poller.Name(), []string{mmp, "free", "inodes"}, buf.Ffree, INodes} if poller.percentage { poller.measurements <- FloatGaugeMeasurement{tick, poller.Name(), []string{mmp, "used", "perc"}, 100.0 * float64(used_bytes) / float64(total_bytes), Percent} } } }
func PathDiskFreePercentage(path string) (int, error) { var stat syscall.Statfs_t if err := syscall.Statfs(path, &stat); err != nil { return 0, err } return int(100 * stat.Bavail / stat.Blocks), nil }
func (t *StatFSTest) Syscall_NonZeroValues() { var err error var stat syscall.Statfs_t // Set up the canned response. canned := fuseops.StatFSOp{ BlockSize: 1 << 15, IoSize: 1 << 16, Blocks: 1<<51 + 3, BlocksFree: 1<<43 + 5, BlocksAvailable: 1<<41 + 7, Inodes: 1<<59 + 11, InodesFree: 1<<58 + 13, } t.fs.SetStatFSResponse(canned) // Stat. err = syscall.Statfs(t.Dir, &stat) AssertEq(nil, err) ExpectEq(canned.BlockSize, stat.Bsize) ExpectEq(canned.IoSize, stat.Iosize) ExpectEq(canned.Blocks, stat.Blocks) ExpectEq(canned.BlocksFree, stat.Bfree) ExpectEq(canned.BlocksAvailable, stat.Bavail) ExpectEq(canned.Inodes, stat.Files) ExpectEq(canned.InodesFree, stat.Ffree) ExpectEq("osxfuse", convertName(stat.Fstypename[:])) ExpectEq(t.canonicalDir, convertName(stat.Mntonname[:])) ExpectEq(fsName, convertName(stat.Mntfromname[:])) }
// GetFSMagic returns the filesystem id given the path. func GetFSMagic(rootpath string) (FsMagic, error) { var buf syscall.Statfs_t if err := syscall.Statfs(filepath.Dir(rootpath), &buf); err != nil { return 0, err } return FsMagic(buf.Type), nil }
// Parse an individual line from Linux's /etc/mtab. func (fs *FSUsageSampler) parseLine(line string) (err error) { var dev, mount, fstype, options string var dump, fsck_order uint64 var buf syscall.Statfs_t _, err = fmt.Sscanf(line, "%s %s %s %s %d %d", &dev, &mount, &fstype, &options, &dump, &fsck_order) if err != nil { return } // only report on ext[234] filesystems for now if !strings.HasPrefix(fstype, "ext") { return } if err = syscall.Statfs(mount, &buf); err != nil { return } if buf.Blocks == 0 { return } to1K := uint64(buf.Bsize) / 1024 fs.sink.Write("fs", dev, mount, buf.Blocks*to1K, buf.Bfree*to1K, buf.Bavail*to1K, buf.Files, buf.Ffree) return }
func TestClientStatVFS(t *testing.T) { sftp, cmd := testClient(t, READWRITE, NO_DELAY) defer cmd.Wait() defer sftp.Close() vfs, err := sftp.StatVFS("/") if err != nil { t.Fatal(err) } // get system stats s := syscall.Statfs_t{} err = syscall.Statfs("/", &s) if err != nil { t.Fatal(err) } // check some stats if vfs.Frsize != uint64(s.Frsize) { t.Fatal("fr_size does not match") } if vfs.Bsize != uint64(s.Bsize) { t.Fatal("f_bsize does not match") } if vfs.Namemax != uint64(s.Namelen) { t.Fatal("f_namemax does not match") } if vfs.Bavail != s.Bavail { t.Fatal("f_bavail does not match") } }
func (fs *FS) StatFs(name string) (out *fuse.StatfsOut) { fs.CaseMatchingRetry(name, func(nameAttempt string) bool { // Copied from LoopbackFileSystem.StatFs, as the return code doesn't give // an indication for error reason. s := syscall.Statfs_t{} err := syscall.Statfs(fs.GetPath(name), &s) out = nil if err == nil { out = &fuse.StatfsOut{ raw.Kstatfs{ Blocks: s.Blocks, Bsize: uint32(s.Bsize), Bfree: s.Bfree, Bavail: s.Bavail, Files: s.Files, Ffree: s.Ffree, Frsize: uint32(s.Frsize), NameLen: uint32(s.Namelen), }, } return false } out = nil return os.IsNotExist(err) }) return }
// Expose filesystem fullness. func (c *filesystemCollector) GetStats() (stats []filesystemStats, err error) { mpds, err := mountPointDetails() if err != nil { return nil, err } stats = []filesystemStats{} for _, mpd := range mpds { if c.ignoredMountPointsPattern.MatchString(mpd.mountPoint) { log.Debugf("Ignoring mount point: %s", mpd.mountPoint) continue } buf := new(syscall.Statfs_t) err := syscall.Statfs(mpd.mountPoint, buf) if err != nil { log.Debugf("Statfs on %s returned %s", mpd.mountPoint, err) continue } labelValues := []string{mpd.device, mpd.mountPoint, mpd.fsType} stats = append(stats, filesystemStats{ labelValues: labelValues, size: float64(buf.Blocks) * float64(buf.Bsize), free: float64(buf.Bfree) * float64(buf.Bsize), avail: float64(buf.Bavail) * float64(buf.Bsize), files: float64(buf.Files), filesFree: float64(buf.Ffree), }) } return stats, nil }
func (lc *Collector) Collect(ch chan<- promm.Metric) { // Filesystems for _, fs := range lc.cfg.Filesystems { var stat syscall.Statfs_t if err := syscall.Statfs(fs, &stat); err != nil { log.Printf("Error stating filesystem %q: %v", fs, err) lc.fsStatOps.With(promm.Labels{"mount": fs, "result": "error"}).Inc() continue } lc.fsStatOps.With(promm.Labels{"mount": fs, "result": "ok"}).Inc() mountLabels := promm.Labels{"mount": fs} bs := uint64(stat.Bsize) lc.fsSizeBytes.With(mountLabels).Set(float64(bs * stat.Blocks)) lc.fsFreeBytes.With(mountLabels).Set(float64(bs * stat.Bfree)) lc.fsUnprivFreeBytes.With(mountLabels).Set(float64(bs * stat.Bavail)) lc.fsFiles.With(mountLabels).Set(float64(stat.Files)) lc.fsFilesFree.With(mountLabels).Set(float64(stat.Ffree)) } // Networks if ifaces, err := net.Interfaces(); err != nil { log.Print("Error getting network interfaces: ", err) } else { for _, iface := range ifaces { readIntFileIntoCounter( lc.ifaceTxBytes.With(promm.Labels{"interface": iface.Name}), filepath.Join(netPathSysClassNet, iface.Name, netPathStatsTxBytes)) readIntFileIntoCounter( lc.ifaceRxBytes.With(promm.Labels{"interface": iface.Name}), filepath.Join(netPathSysClassNet, iface.Name, netPathStatsRxBytes)) } } lc.metrics.Collect(ch) }