Skip to main content

Overview

The UsageStat struct contains filesystem usage statistics for a specific path, including total space, used space, free space, and inode information. It works across all supported platforms.

Struct Definition

type UsageStat struct {
    Path              string  `json:"path"`
    Fstype            string  `json:"fstype"`
    Total             uint64  `json:"total"`
    Free              uint64  `json:"free"`
    Used              uint64  `json:"used"`
    UsedPercent       float64 `json:"usedPercent"`
    InodesTotal       uint64  `json:"inodesTotal"`
    InodesUsed        uint64  `json:"inodesUsed"`
    InodesFree        uint64  `json:"inodesFree"`
    InodesUsedPercent float64 `json:"inodesUsedPercent"`
}

Fields

Path

  • Type: string
  • Description: The filesystem path that was queried
  • Example: /home, C:\, /mnt/data
  • Note: This is the path passed to disk.Usage(), not necessarily the actual mount point

Fstype

  • Type: string
  • Description: Filesystem type
  • Examples:
    • Linux: ext4, xfs, btrfs, tmpfs, nfs
    • Windows: NTFS, FAT32, ReFS
    • macOS: apfs, hfs
  • Note: Empty string if the filesystem type cannot be determined

Total

  • Type: uint64
  • Description: Total size of the filesystem in bytes
  • Example: 1000000000000 (1 TB)
  • Note: This is the raw capacity, not accounting for filesystem overhead or reserved space

Free

  • Type: uint64
  • Description: Free space available in bytes
  • Note: On some filesystems (like ext4), this may include space reserved for root that regular users cannot use
  • Use case: Use this for administrative tools that need to know all available space

Used

  • Type: uint64
  • Description: Used space in bytes
  • Calculation: Typically Total - Free, but may vary by platform and filesystem
  • Note: Includes space used by files, directories, and filesystem metadata

UsedPercent

  • Type: float64
  • Description: Percentage of space used (0.0 to 100.0)
  • Calculation: (Used / Total) * 100
  • Example: 67.5 means 67.5% of the filesystem is used
  • Use case: Primary metric for monitoring disk space alerts

InodesTotal

  • Type: uint64
  • Description: Total number of inodes (file/directory entries) available on the filesystem
  • Platform: Unix-like systems (Linux, macOS, BSD)
  • Note: Zero on Windows and filesystems that don’t use inodes
  • Example: 62545920 (typical for a large ext4 filesystem)

InodesUsed

  • Type: uint64
  • Description: Number of inodes currently in use
  • Platform: Unix-like systems
  • Use case: Track how many files/directories exist, independent of their size

InodesFree

  • Type: uint64
  • Description: Number of unused inodes available
  • Platform: Unix-like systems
  • Calculation: InodesTotal - InodesUsed
  • Note: A filesystem can run out of inodes even if there’s free space (many small files)

InodesUsedPercent

  • Type: float64
  • Description: Percentage of inodes used (0.0 to 100.0)
  • Platform: Unix-like systems
  • Calculation: (InodesUsed / InodesTotal) * 100
  • Use case: Alert when approaching inode exhaustion (typically at 90%)

Methods

String

func (d UsageStat) String() string
Returns a JSON string representation of the struct. Example output:
{
  "path": "/",
  "fstype": "ext4",
  "total": 1000000000000,
  "free": 400000000000,
  "used": 600000000000,
  "usedPercent": 60.0,
  "inodesTotal": 62545920,
  "inodesUsed": 5242880,
  "inodesFree": 57303040,
  "inodesUsedPercent": 8.38
}

Usage Function

func Usage(path string) (*UsageStat, error)
func UsageWithContext(ctx context.Context, path string) (*UsageStat, error)
Parameters:
  • path - A filesystem path (e.g., /, /home, C:\) - NOT a device path (e.g., /dev/sda1)
Important: If you have a partition from disk.Partitions(), use the Mountpoint field, not the Device field. Returns:
  • *UsageStat - Pointer to usage statistics struct
  • error - Error if path doesn’t exist or cannot be accessed

Usage Examples

Basic Usage

package main

import (
    "fmt"
    "log"
    
    "github.com/shirou/gopsutil/v4/disk"
)

func main() {
    usage, err := disk.Usage("/")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Path: %s\n", usage.Path)
    fmt.Printf("Filesystem: %s\n", usage.Fstype)
    fmt.Printf("Total: %v GB\n", usage.Total/1024/1024/1024)
    fmt.Printf("Used: %v GB\n", usage.Used/1024/1024/1024)
    fmt.Printf("Free: %v GB\n", usage.Free/1024/1024/1024)
    fmt.Printf("Usage: %.2f%%\n", usage.UsedPercent)
    
    // Inode information (Unix-like systems)
    if usage.InodesTotal > 0 {
        fmt.Printf("\nInodes:\n")
        fmt.Printf("  Total: %v\n", usage.InodesTotal)
        fmt.Printf("  Used: %v\n", usage.InodesUsed)
        fmt.Printf("  Free: %v\n", usage.InodesFree)
        fmt.Printf("  Usage: %.2f%%\n", usage.InodesUsedPercent)
    }
}

Monitoring Multiple Filesystems

package main

import (
    "fmt"
    "log"
    
    "github.com/shirou/gopsutil/v4/disk"
)

func main() {
    // Get all partitions
    partitions, err := disk.Partitions(false)
    if err != nil {
        log.Fatal(err)
    }

    // Check usage for each
    for _, partition := range partitions {
        // IMPORTANT: Use Mountpoint, not Device
        usage, err := disk.Usage(partition.Mountpoint)
        if err != nil {
            log.Printf("Error for %s: %v", partition.Mountpoint, err)
            continue
        }

        fmt.Printf("%s (%s) [%s]:\n", 
            partition.Mountpoint, partition.Device, usage.Fstype)
        fmt.Printf("  Space: %v GB / %v GB (%.2f%% used)\n",
            usage.Used/1024/1024/1024,
            usage.Total/1024/1024/1024,
            usage.UsedPercent)
        
        if usage.InodesTotal > 0 {
            fmt.Printf("  Inodes: %v / %v (%.2f%% used)\n",
                usage.InodesUsed, usage.InodesTotal, usage.InodesUsedPercent)
        }
        fmt.Println()
    }
}

Disk Space Alerts

package main

import (
    "fmt"
    "log"
    
    "github.com/shirou/gopsutil/v4/disk"
)

func checkDiskSpace(path string, thresholds map[string]float64) {
    usage, err := disk.Usage(path)
    if err != nil {
        log.Printf("Error checking %s: %v", path, err)
        return
    }

    // Check space usage
    if usage.UsedPercent >= thresholds["critical"] {
        fmt.Printf("CRITICAL: %s is %.2f%% full\n", path, usage.UsedPercent)
    } else if usage.UsedPercent >= thresholds["warning"] {
        fmt.Printf("WARNING: %s is %.2f%% full\n", path, usage.UsedPercent)
    } else {
        fmt.Printf("OK: %s is %.2f%% full\n", path, usage.UsedPercent)
    }

    // Check inode usage (Unix-like systems)
    if usage.InodesTotal > 0 {
        if usage.InodesUsedPercent >= thresholds["critical"] {
            fmt.Printf("CRITICAL: %s inodes %.2f%% used\n", path, usage.InodesUsedPercent)
        } else if usage.InodesUsedPercent >= thresholds["warning"] {
            fmt.Printf("WARNING: %s inodes %.2f%% used\n", path, usage.InodesUsedPercent)
        }
    }
}

func main() {
    thresholds := map[string]float64{
        "warning":  80.0,
        "critical": 90.0,
    }

    checkDiskSpace("/", thresholds)
    checkDiskSpace("/home", thresholds)
    checkDiskSpace("/var", thresholds)
}

With Context for Timeout

package main

import (
    "context"
    "fmt"
    "log"
    "time"
    
    "github.com/shirou/gopsutil/v4/disk"
)

func main() {
    // Set 2 second timeout
    ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
    defer cancel()

    usage, err := disk.UsageWithContext(ctx, "/mnt/slow-network-mount")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("Usage: %.2f%%\n", usage.UsedPercent)
}

Human-Readable Formatting

package main

import (
    "fmt"
    
    "github.com/shirou/gopsutil/v4/disk"
)

func formatBytes(bytes uint64) string {
    const unit = 1024
    if bytes < unit {
        return fmt.Sprintf("%d B", bytes)
    }
    div, exp := uint64(unit), 0
    for n := bytes / unit; n >= unit; n /= unit {
        div *= unit
        exp++
    }
    return fmt.Sprintf("%.1f %cB", float64(bytes)/float64(div), "KMGTPE"[exp])
}

func main() {
    usage, _ := disk.Usage("/")
    
    fmt.Printf("Total: %s\n", formatBytes(usage.Total))
    fmt.Printf("Used: %s\n", formatBytes(usage.Used))
    fmt.Printf("Free: %s\n", formatBytes(usage.Free))
    fmt.Printf("Usage: %.2f%%\n", usage.UsedPercent)
}

Platform-Specific Behavior

Linux

  • All fields are populated from the statvfs system call
  • Fstype is obtained from /proc/mounts or mount system call
  • Reserved space (typically 5% on ext4) is included in Free but not available to non-root users
  • Inode information is always available (except for pseudo filesystems)

Windows

  • Uses GetDiskFreeSpaceEx API
  • Fstype obtained from GetVolumeInformation
  • Inode fields are always 0 (Windows doesn’t use inodes)
  • Path should be drive letter or UNC path (e.g., C:\, \\server\share)

macOS

  • Uses statvfs system call
  • Fstype determined from mount information
  • Inode information available for most filesystems
  • APFS filesystems have dynamic inode allocation

BSD (FreeBSD, OpenBSD)

  • Uses statvfs system call
  • All fields typically available
  • Some pseudo filesystems may have limited information

Common Pitfalls

Device Path vs Mount Point: Always pass a mount point (filesystem path) to disk.Usage(), not a device path. Use partition.Mountpoint, not partition.Device.Correct:
disk.Usage("/home")  // ✓
disk.Usage("C:\\")    // ✓
Incorrect:
disk.Usage("/dev/sda1")  // ✗ Will fail or give wrong results
Inode Exhaustion: A filesystem can run out of inodes even with free space remaining. This typically happens with millions of small files. Always monitor both UsedPercent and InodesUsedPercent on Unix-like systems.
Reserved Space: On Linux ext2/ext3/ext4 filesystems, typically 5% is reserved for root. The Free field includes this space, but regular users cannot use it. This means a filesystem may show free space but return “disk full” errors to non-root processes.

See Also

Build docs developers (and LLMs) love