Skip to content

Commit adaeba0

Browse files
committed
feat(disk): look for filesystem labels from udev on Linux
1 parent 4870f6f commit adaeba0

File tree

1 file changed

+39
-20
lines changed

1 file changed

+39
-20
lines changed

disk/disk_linux.go

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package disk
55

66
import (
77
"bufio"
8-
"bytes"
98
"context"
109
"errors"
1110
"fmt"
@@ -485,25 +484,35 @@ func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOC
485484
return ret, nil
486485
}
487486

488-
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
489-
var stat unix.Stat_t
490-
err := unix.Stat(name, &stat)
491-
if err != nil {
492-
return "", err
493-
}
494-
major := unix.Major(uint64(stat.Rdev))
495-
minor := unix.Minor(uint64(stat.Rdev))
496-
497-
// Try to get the serial from udev data
487+
func udevData(ctx context.Context, major uint32, minor uint32, name string) (string, error) {
498488
udevDataPath := common.HostRunWithContext(ctx, fmt.Sprintf("udev/data/b%d:%d", major, minor))
499-
if udevdata, err := os.ReadFile(udevDataPath); err == nil {
500-
scanner := bufio.NewScanner(bytes.NewReader(udevdata))
489+
if f, err := os.Open(udevDataPath); err == nil {
490+
defer f.Close()
491+
scanner := bufio.NewScanner(f)
501492
for scanner.Scan() {
502-
values := strings.Split(scanner.Text(), "=")
503-
if len(values) == 2 && values[0] == "E:ID_SERIAL" {
493+
values := strings.SplitN(scanner.Text(), "=", 3)
494+
if len(values) == 2 && values[0] == name {
504495
return values[1], nil
505496
}
506497
}
498+
return "", scanner.Err()
499+
} else if !os.IsNotExist(err) {
500+
return "", err
501+
}
502+
return "", nil
503+
}
504+
505+
func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
506+
var stat unix.Stat_t
507+
if err := unix.Stat(name, &stat); err != nil {
508+
return "", err
509+
}
510+
major := unix.Major(stat.Rdev)
511+
minor := unix.Minor(stat.Rdev)
512+
513+
sserial, _ := udevData(ctx, major, minor, "E:ID_SERIAL")
514+
if sserial != "" {
515+
return sserial, nil
507516
}
508517

509518
// Try to get the serial from sysfs, look at the disk device (minor 0) directly
@@ -520,16 +529,26 @@ func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
520529
func LabelWithContext(ctx context.Context, name string) (string, error) {
521530
// Try label based on devicemapper name
522531
dmname_filename := common.HostSysWithContext(ctx, fmt.Sprintf("block/%s/dm/name", name))
523-
524-
if !common.PathExists(dmname_filename) {
525-
return "", nil
532+
// Could errors.Join errs with Go >= 1.20
533+
if common.PathExists(dmname_filename) {
534+
dmname, err := os.ReadFile(dmname_filename)
535+
if err == nil {
536+
return strings.TrimSpace(string(dmname)), nil
537+
}
538+
}
539+
// Try udev data
540+
var stat unix.Stat_t
541+
if err := unix.Stat(common.HostDevWithContext(ctx, name), &stat); err != nil {
542+
return "", err
526543
}
544+
major := unix.Major(stat.Rdev)
545+
minor := unix.Minor(stat.Rdev)
527546

528-
dmname, err := os.ReadFile(dmname_filename)
547+
label, err := udevData(ctx, major, minor, "E:ID_FS_LABEL")
529548
if err != nil {
530549
return "", err
531550
}
532-
return strings.TrimSpace(string(dmname)), nil
551+
return label, nil
533552
}
534553

535554
func getFsType(stat unix.Statfs_t) string {

0 commit comments

Comments
 (0)