Skip to content

Commit

Permalink
Support nvme devices.
Browse files Browse the repository at this point in the history
  • Loading branch information
bradfitz committed Nov 12, 2020
1 parent 71ed88f commit 602f102
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 12 deletions.
54 changes: 47 additions & 7 deletions fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ import (
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"syscall"

"golang.org/x/sys/unix"
)
Expand Down Expand Up @@ -61,14 +63,20 @@ func (e fsResizer) String() string {
func (e fsResizer) DepResizer() (Resizer, error) {
// TODO: use /proc/devices instead and stat the thing to
// figure out what it is, rather than using its name.
if strings.HasPrefix(e.fs.dev, "/dev/sd") && devEndsInNumber(e.fs.dev) {
return partitionResizer(e.fs.dev), nil
dev := e.fs.dev
if dev == "/dev/root" {
return nil, errors.New("unexpected device /dev/root from statFS")
}
if strings.HasPrefix(e.fs.dev, "/dev/mapper") ||
strings.HasPrefix(filepath.Base(e.fs.dev), "dm-") {
return lvResizer(e.fs.dev), nil
if (strings.HasPrefix(dev, "/dev/sd") || strings.HasPrefix(dev, "/dev/nvme")) &&
devEndsInNumber(dev) {
vlogf("fsResizer.DepResizer: returning partitionResizer(%q)", dev)
return partitionResizer(dev), nil
}
return nil, fmt.Errorf("don't know how to resize block device %q", e.fs.dev)
if strings.HasPrefix(dev, "/dev/mapper") ||
strings.HasPrefix(filepath.Base(dev), "dm-") {
return lvResizer(dev), nil
}
return nil, fmt.Errorf("don't know how to resize block device %q", dev)
}

func (e fsResizer) Resize() error {
Expand Down Expand Up @@ -121,8 +129,40 @@ func statFS(mnt string) (fs fsStat, err error) {
fs.mnt = mnt
fs.dev = f[0]
fs.fstype = f[2]
return fs, nil
if fs.dev == "/dev/root" {
dev, err := findDevRoot()
if err != nil {
return fs, fmt.Errorf("failed to map /dev/root to real device: %v", err)
}
fs.dev = dev
}
return fs, err
}
}
return fs, errors.New("mount point not found")
}

// findDevRoot finds which block device (e.g. "/dev/nvme0n1p1") patches the device number of /dev/root.
func findDevRoot() (string, error) {
fis, err := ioutil.ReadDir("/dev")
if err != nil {
return "", err
}
dev := map[string]uint64{}
for _, fi := range fis {
if fi.Mode()&os.ModeDevice == 0 || fi.Mode()&os.ModeCharDevice != 0 {
continue
}
dev[fi.Name()] = fi.Sys().(*syscall.Stat_t).Rdev
}
wantDevnum, ok := dev["root"]
if !ok {
return "", errors.New("/dev/root not found in /dev")
}
for baseName, devNum := range dev {
if devNum == wantDevnum && baseName != "root" {
return "/dev/" + baseName, nil
}
}
return "", errors.New("no block device in /dev had device number like /dev/root")
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module github.com/google/embiggen-disk

go 1.15

require (
github.com/u-root/u-root v0.0.0-20180806213625-12f9029297cf
golang.org/x/sys v0.0.0-20180727230415-bd9dbc187b6e
Expand Down
7 changes: 7 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ func fatalf(format string, args ...interface{}) {
log.Fatalf(format, args...)
}

func vlogf(format string, args ...interface{}) {
if *verbose {
log.Printf(format, args...)
}
}

func main() {
flag.Parse()
if flag.NArg() != 1 {
Expand All @@ -62,6 +68,7 @@ func main() {

mnt := flag.Arg(0)
e, err := getFileSystemResizer(mnt)
vlogf("getFileSystemResizer(%q) = %#v, %v", mnt, e, err)
if err != nil {
fatalf("error preparing to enlarge %s: %v", mnt, err)
}
Expand Down
20 changes: 15 additions & 5 deletions part.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,17 @@ func diskDev(partDev string) string {
if !strings.HasPrefix(partDev, "/dev/") {
panic("bogus partition dev " + partDev)
}
if !strings.HasPrefix(partDev, "/dev/sd") {
panic("TODO: handle other device types; ask kernel")
if strings.HasPrefix(partDev, "/dev/sd") {
return strings.TrimRight(partDev, "0123456789")
}
return strings.TrimRight(partDev, "0123456789")
if strings.HasPrefix(partDev, "/dev/nvme") {
chopP := regexp.MustCompile(`p\d+$`)
if !chopP.MatchString(partDev) {
panic(fmt.Sprintf("partition %q doesn't look like an nvme partition", partDev))
}
return chopP.ReplaceAllString(partDev, "")
}
panic(fmt.Sprintf("Unsupport device %q; TODO: handle other device types; ask kernel", partDev))
}

func (p partitionResizer) String() string { return fmt.Sprintf("partition %s", string(p)) }
Expand All @@ -67,12 +74,15 @@ func (p partitionResizer) State() (string, error) {
func (p partitionResizer) DepResizer() (Resizer, error) { return nil, nil }

func (p partitionResizer) Resize() error {
vlogf("Resizing partition %q ...", string(p))
partDev := string(p)
diskDev := diskDev(partDev)
vlogf("Getting partition table for %q ...", diskDev)
pt := getPartitionTable(diskDev)
if len(pt.parts) == 0 {
log.Fatalf("device %q has no partitions", diskDev)
}
vlogf("Device %q has %d partitions.", diskDev, len(pt.parts))
var isGPT bool
switch t := pt.Meta("label"); t {
case "dos":
Expand Down Expand Up @@ -127,7 +137,7 @@ func (p partitionResizer) Resize() error {
fmt.Println()
}

size, err := readInt64File("/sys/block/sda/size")
size, err := readInt64File("/sys/block/" + filepath.Base(diskDev) + "/size")
if err != nil {
return err
}
Expand Down Expand Up @@ -329,7 +339,7 @@ func getPartitionTable(dev string) *partitionTable {
pt := new(partitionTable)
out, err := exec.Command("/sbin/sfdisk", "-d", dev).Output()
if err != nil {
log.Fatal(err)
log.Fatalf("running sfdisk -f %s: %v, %s", dev, err, out)
}
lines := strings.Split(string(out), "\n")
var pno int
Expand Down

0 comments on commit 602f102

Please sign in to comment.