Skip to content

Commit

Permalink
Merge pull request #1573 from scop/feat/udev-fs-label
Browse files Browse the repository at this point in the history
feat(disk): look for filesystem labels from udev on Linux
  • Loading branch information
shirou authored Dec 31, 2023
2 parents 4870f6f + adaeba0 commit df3c7bd
Showing 1 changed file with 39 additions and 20 deletions.
59 changes: 39 additions & 20 deletions disk/disk_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package disk

import (
"bufio"
"bytes"
"context"
"errors"
"fmt"
Expand Down Expand Up @@ -485,25 +484,35 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
return ret, nil
}

func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
var stat unix.Stat_t
err := unix.Stat(name, &stat)
if err != nil {
return "", err
}
major := unix.Major(uint64(stat.Rdev))
minor := unix.Minor(uint64(stat.Rdev))

// Try to get the serial from udev data
func udevData(ctx context.Context, major uint32, minor uint32, name string) (string, error) {
udevDataPath := common.HostRunWithContext(ctx, fmt.Sprintf("udev/data/b%d:%d", major, minor))
if udevdata, err := os.ReadFile(udevDataPath); err == nil {
scanner := bufio.NewScanner(bytes.NewReader(udevdata))
if f, err := os.Open(udevDataPath); err == nil {
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
values := strings.Split(scanner.Text(), "=")
if len(values) == 2 && values[0] == "E:ID_SERIAL" {
values := strings.SplitN(scanner.Text(), "=", 3)
if len(values) == 2 && values[0] == name {
return values[1], nil
}
}
return "", scanner.Err()
} else if !os.IsNotExist(err) {
return "", err
}
return "", nil
}

func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
var stat unix.Stat_t
if err := unix.Stat(name, &stat); err != nil {
return "", err
}
major := unix.Major(stat.Rdev)
minor := unix.Minor(stat.Rdev)

sserial, _ := udevData(ctx, major, minor, "E:ID_SERIAL")
if sserial != "" {
return sserial, nil
}

// Try to get the serial from sysfs, look at the disk device (minor 0) directly
Expand All @@ -520,16 +529,26 @@ func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
func LabelWithContext(ctx context.Context, name string) (string, error) {
// Try label based on devicemapper name
dmname_filename := common.HostSysWithContext(ctx, fmt.Sprintf("block/%s/dm/name", name))

if !common.PathExists(dmname_filename) {
return "", nil
// Could errors.Join errs with Go >= 1.20
if common.PathExists(dmname_filename) {
dmname, err := os.ReadFile(dmname_filename)
if err == nil {
return strings.TrimSpace(string(dmname)), nil
}
}
// Try udev data
var stat unix.Stat_t
if err := unix.Stat(common.HostDevWithContext(ctx, name), &stat); err != nil {
return "", err
}
major := unix.Major(stat.Rdev)
minor := unix.Minor(stat.Rdev)

dmname, err := os.ReadFile(dmname_filename)
label, err := udevData(ctx, major, minor, "E:ID_FS_LABEL")
if err != nil {
return "", err
}
return strings.TrimSpace(string(dmname)), nil
return label, nil
}

func getFsType(stat unix.Statfs_t) string {
Expand Down

0 comments on commit df3c7bd

Please sign in to comment.