Fallback to using dd
if fallocate
isn't available
This commit is contained in:
parent
a74ea6a9ff
commit
0407f22147
|
@ -8,6 +8,7 @@ import (
|
|||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"emperror.dev/errors"
|
||||
"github.com/pterodactyl/wings/config"
|
||||
|
@ -21,6 +22,9 @@ var (
|
|||
ErrFilesystemExists = errors.Sentinel("vhd: filesystem already exists on disk")
|
||||
)
|
||||
|
||||
var useDdAllocation bool
|
||||
var setDdAllocator sync.Once
|
||||
|
||||
// hasExitCode allows this code to test the response error to see if there is
|
||||
// an exit code available from the command call that can be used to determine if
|
||||
// something went wrong.
|
||||
|
@ -157,7 +161,7 @@ func (d *Disk) Mount(ctx context.Context) error {
|
|||
if st, err := d.fs.Stat(d.mountAt); err != nil && !os.IsNotExist(err) {
|
||||
return errors.Wrap(err, "vhd: failed to stat mount path")
|
||||
} else if os.IsNotExist(err) {
|
||||
if err := d.fs.MkdirAll(d.mountAt, 0600); err != nil {
|
||||
if err := d.fs.MkdirAll(d.mountAt, 0700); err != nil {
|
||||
return errors.Wrap(err, "vhd: failed to create mount path")
|
||||
}
|
||||
} else if !st.IsDir() {
|
||||
|
@ -191,6 +195,19 @@ func (d *Disk) Unmount(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// allocationCmd returns the command to allocate the disk image. This will attempt to
|
||||
// use the fallocate command if available, otherwise it will fall back to dd if the
|
||||
// fallocate command has previously failed.
|
||||
//
|
||||
// We use 1024 as the multiplier for all of the disk space logic within the application.
|
||||
// Passing "K" (/1024) is the same as "KiB" for fallocate, but is different than "KB" (/1000).
|
||||
func (d *Disk) alloc(ctx context.Context) Commander {
|
||||
if useDdAllocation {
|
||||
return d.commander(ctx, "dd", "if=/dev/zero", fmt.Sprintf("of=%s", d.diskPath), fmt.Sprintf("bs=%dk", d.size/1024), "count=1")
|
||||
}
|
||||
return d.commander(ctx, "fallocate", "-l", fmt.Sprintf("%dK", d.size/1024), d.diskPath)
|
||||
}
|
||||
|
||||
// Allocate executes the "fallocate" command on the disk. This will first unmount
|
||||
// the disk from the system before attempting to actually allocate the space. If
|
||||
// this disk already exists on the machine it will be resized accordingly.
|
||||
|
@ -208,17 +225,23 @@ func (d *Disk) Allocate(ctx context.Context) error {
|
|||
return errors.Wrap(err, "vhd: failed to check for existence of root disk")
|
||||
}
|
||||
trim := path.Base(d.diskPath)
|
||||
if err := d.fs.MkdirAll(strings.TrimSuffix(d.diskPath, trim), 0600); err != nil {
|
||||
if err := d.fs.MkdirAll(strings.TrimSuffix(d.diskPath, trim), 0700); err != nil {
|
||||
return errors.Wrap(err, "vhd: failed to create base vhd disk directory")
|
||||
}
|
||||
// We use 1024 as the multiplier for all of the disk space logic within the
|
||||
// application. Passing "K" (/1024) is the same as "KiB" for fallocate, but
|
||||
// is different than "KB" (/1000).
|
||||
cmd := d.commander(ctx, "fallocate", "-l", fmt.Sprintf("%dK", d.size/1024), d.diskPath)
|
||||
cmd := d.alloc(ctx)
|
||||
if _, err := cmd.Output(); err != nil {
|
||||
msg := "vhd: failed to execute fallocate command"
|
||||
msg := "vhd: failed to execute space allocation command"
|
||||
if v, ok := err.(*exec.ExitError); ok {
|
||||
msg = msg + ": " + strings.Trim(string(v.Stderr), ".\n")
|
||||
stderr := strings.Trim(string(v.Stderr), ".\n")
|
||||
if !useDdAllocation && strings.HasSuffix(stderr, "not supported") {
|
||||
// Try again: fallocate is not supported on some filesystems so we'll fall
|
||||
// back to making use of dd for subsequent operations.
|
||||
setDdAllocator.Do(func() {
|
||||
useDdAllocation = true
|
||||
})
|
||||
return d.Allocate(ctx)
|
||||
}
|
||||
msg = msg + ": " + stderr
|
||||
}
|
||||
return errors.Wrap(err, msg)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user