Skip to content

Commit 3d262da

Browse files
committed
Decouple diffdisk (misnomer) from basedisk
Fix issue 1706. Now basedisk is immediately renamed/converted to diffdisk (not a diff despite the name) by the VM driver, except when basedisk is an ISO9660 image. Decoupling diffdisk from basedisk will eliminate the overhead of differencing I/O and save some disk space. I cannot remember why I designed the disk to be split into basedisk and diffdisk. Maybe it was to allow `limactl factory-reset` to retain the initial state, although the command was apparently never implemented in that way. Maybe it was to allow multiple instances to share the same basedisk, although it was never implemented in that way, either. Signed-off-by: Akihiro Suda <[email protected]>
1 parent 39c5246 commit 3d262da

File tree

6 files changed

+64
-32
lines changed

6 files changed

+64
-32
lines changed

pkg/driver/qemu/qemu.go

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,8 @@ func minimumQemuVersion() (hardMin, softMin semver.Version) {
8686
return hardMin, softMin
8787
}
8888

89-
// EnsureDisk also ensures the kernel and the initrd.
89+
// EnsureDisk just renames baseDisk to diffDisk, unless baseDisk is an ISO9660 image.
90+
// Note that "diffDisk" is a misnomer, it is actually created as a full disk since Lima v2.0.
9091
func EnsureDisk(ctx context.Context, cfg Config) error {
9192
diffDisk := filepath.Join(cfg.InstanceDir, filenames.DiffDisk)
9293
if _, err := os.Stat(diffDisk); err == nil || !errors.Is(err, os.ErrNotExist) {
@@ -114,10 +115,14 @@ func EnsureDisk(ctx context.Context, cfg Config) error {
114115
if baseDiskInfo.Format == "" {
115116
return fmt.Errorf("failed to inspect the format of %q", baseDisk)
116117
}
117-
args := []string{"create", "-f", "qcow2"}
118118
if !isBaseDiskISO {
119-
args = append(args, "-F", baseDiskInfo.Format, "-b", baseDisk)
119+
// "diffdisk" is a misnomer, it is actually created as a full disk since Lima v2.0.
120+
if err = os.Rename(baseDisk, diffDisk); err != nil {
121+
return err
122+
}
123+
return nil
120124
}
125+
args := []string{"create", "-f", "qcow2"}
121126
args = append(args, diffDisk, strconv.Itoa(int(diskSize)))
122127
cmd := exec.CommandContext(ctx, "qemu-img", args...)
123128
if out, err := cmd.CombinedOutput(); err != nil {
@@ -718,9 +723,15 @@ func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err er
718723
extraDisks = append(extraDisks, dataDisk)
719724
}
720725

721-
isBaseDiskCDROM, err := iso9660util.IsISO9660(baseDisk)
722-
if err != nil {
723-
return "", nil, err
726+
var baseDiskExists, isBaseDiskCDROM bool
727+
if _, err := os.Stat(baseDisk); !errors.Is(err, os.ErrNotExist) {
728+
baseDiskExists = true
729+
}
730+
if baseDiskExists {
731+
isBaseDiskCDROM, err = iso9660util.IsISO9660(baseDisk)
732+
if err != nil {
733+
return "", nil, err
734+
}
724735
}
725736
if isBaseDiskCDROM {
726737
args = appendArgsIfNoConflict(args, "-boot", "order=d,splash-time=0,menu=on")
@@ -730,7 +741,8 @@ func Cmdline(ctx context.Context, cfg Config) (exe string, args []string, err er
730741
}
731742
if diskSize, _ := units.RAMInBytes(*cfg.LimaYAML.Disk); diskSize > 0 {
732743
args = append(args, "-drive", fmt.Sprintf("file=%s,if=virtio,discard=on", diffDisk))
733-
} else if !isBaseDiskCDROM {
744+
} else if baseDiskExists && !isBaseDiskCDROM { // FIXME: How does this happen? Is this even a valid case?
745+
logrus.Errorf("weird configuration, how does this happen?: diskSize /* %d */ <= 0 && baseDiskExists && !isBaseDiskCDROM", diskSize)
734746
baseDiskInfo, err := qemuimgutil.GetInfo(ctx, baseDisk)
735747
if err != nil {
736748
return "", nil, fmt.Errorf("failed to get the information of %q: %w", baseDisk, err)

pkg/driver/vz/disk.go

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import (
1818
"github.com/lima-vm/lima/v2/pkg/limatype/filenames"
1919
)
2020

21+
// EnsureDisk just converts baseDisk (can be qcow2) to diffDisk (raw), unless baseDisk is an ISO9660 image.
22+
// Note that "diffDisk" is a misnomer, it is actually created as a full disk in the case of VZ.
2123
func EnsureDisk(ctx context.Context, inst *limatype.Instance) error {
2224
diffDisk := filepath.Join(inst.Dir, filenames.DiffDisk)
2325
if _, err := os.Stat(diffDisk); err == nil || !errors.Is(err, os.ErrNotExist) {
@@ -33,26 +35,33 @@ func EnsureDisk(ctx context.Context, inst *limatype.Instance) error {
3335
if diskSize == 0 {
3436
return nil
3537
}
36-
isBaseDiskISO, err := iso9660util.IsISO9660(baseDisk)
37-
if err != nil {
38-
return err
39-
}
40-
if isBaseDiskISO {
41-
// Create an empty data volume (sparse)
42-
diffDiskF, err := os.Create(diffDisk)
38+
var isBaseDiskISO bool
39+
if _, err := os.Stat(baseDisk); !errors.Is(err, os.ErrNotExist) {
40+
isBaseDiskISO, err = iso9660util.IsISO9660(baseDisk)
4341
if err != nil {
4442
return err
4543
}
44+
if isBaseDiskISO {
45+
// Create an empty data volume (sparse)
46+
diffDiskF, err := os.Create(diffDisk)
47+
if err != nil {
48+
return err
49+
}
4650

47-
err = diskUtil.MakeSparse(ctx, diffDiskF, 0)
48-
if err != nil {
49-
diffDiskF.Close()
50-
return fmt.Errorf("failed to create sparse diff disk %q: %w", diffDisk, err)
51+
err = diskUtil.MakeSparse(ctx, diffDiskF, 0)
52+
if err != nil {
53+
diffDiskF.Close()
54+
return fmt.Errorf("failed to create sparse diff disk %q: %w", diffDisk, err)
55+
}
56+
return diffDiskF.Close()
5157
}
52-
return diffDiskF.Close()
5358
}
54-
if err = diskUtil.ConvertToRaw(ctx, baseDisk, diffDisk, &diskSize, false); err != nil {
59+
// "diffdisk" is a misnomer, it is actually created as a full disk in the case of VZ.
60+
if err := diskUtil.ConvertToRaw(ctx, baseDisk, diffDisk, &diskSize, false); err != nil {
5561
return fmt.Errorf("failed to convert %q to a raw disk %q: %w", baseDisk, diffDisk, err)
5662
}
57-
return err
63+
if err := os.RemoveAll(baseDisk); err != nil {
64+
return err
65+
}
66+
return nil
5867
}

pkg/driver/vz/vm_darwin.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -463,9 +463,15 @@ func attachDisks(ctx context.Context, inst *limatype.Instance, vmConfig *vz.Virt
463463
baseDiskPath := filepath.Join(inst.Dir, filenames.BaseDisk)
464464
diffDiskPath := filepath.Join(inst.Dir, filenames.DiffDisk)
465465
ciDataPath := filepath.Join(inst.Dir, filenames.CIDataISO)
466-
isBaseDiskCDROM, err := iso9660util.IsISO9660(baseDiskPath)
467-
if err != nil {
468-
return err
466+
var (
467+
isBaseDiskCDROM bool
468+
err error
469+
)
470+
if _, err := os.Stat(baseDiskPath); !errors.Is(err, os.ErrNotExist) {
471+
isBaseDiskCDROM, err = iso9660util.IsISO9660(baseDiskPath)
472+
if err != nil {
473+
return err
474+
}
469475
}
470476
var configurations []vz.StorageDeviceConfiguration
471477

pkg/instance/start.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/lima-vm/lima/v2/pkg/imgutil/proxyimgutil"
2929
"github.com/lima-vm/lima/v2/pkg/limatype"
3030
"github.com/lima-vm/lima/v2/pkg/limatype/filenames"
31+
"github.com/lima-vm/lima/v2/pkg/limayaml"
3132
"github.com/lima-vm/lima/v2/pkg/registry"
3233
"github.com/lima-vm/lima/v2/pkg/store"
3334
"github.com/lima-vm/lima/v2/pkg/usrlocalsharelima"
@@ -65,11 +66,12 @@ func Prepare(ctx context.Context, inst *limatype.Instance, guestAgent string) (*
6566
return nil, err
6667
}
6768

68-
// Check if the instance has been created (the base disk already exists)
69-
baseDisk := filepath.Join(inst.Dir, filenames.BaseDisk)
70-
_, err = os.Stat(baseDisk)
71-
created := err == nil
69+
// Check if the instance has been created
70+
created := limayaml.IsExistingInstanceDir(inst.Dir)
7271

72+
// baseDisk is usually immediately renamed to diffDisk (misnomer) by the VM driver,
73+
// except when baseDisk is an ISO9660 image.
74+
baseDisk := filepath.Join(inst.Dir, filenames.BaseDisk)
7375
kernel := filepath.Join(inst.Dir, filenames.Kernel)
7476
kernelCmdline := filepath.Join(inst.Dir, filenames.KernelCmdline)
7577
initrd := filepath.Join(inst.Dir, filenames.Initrd)

pkg/limatype/filenames/filenames.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ const (
3636
CIDataISO = "cidata.iso"
3737
CIDataISODir = "cidata"
3838
CloudConfig = "cloud-config.yaml"
39-
BaseDisk = "basedisk"
40-
DiffDisk = "diffdisk"
39+
BaseDisk = "basedisk" // usually immediately converted/renamed to diffDisk by the VM driver
40+
DiffDisk = "diffdisk" // misnomer; actually a full disk since Lima v2.0
4141
Kernel = "kernel"
4242
KernelCmdline = "kernel.cmdline"
4343
Initrd = "initrd"

website/content/en/docs/dev/internals.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,11 @@ Ansible:
4444
- `ansible-inventory.yaml`: the Ansible node inventory. See [ansible](#ansible).
4545

4646
disk:
47-
- `basedisk`: the base image
48-
- `diffdisk`: the diff image (QCOW2)
47+
- `basedisk`: the historical base image. Can be missing since Lima v2.0.
48+
- The main `limactl` process prepares this `basedisk`, however, a [VM driver](./drivers.md) may convert and rename `basedisk` to `diffdisk` immediately.
49+
- `diffdisk`: the image, historically a QCOW2 diff from `basedisk`.
50+
- `diffdisk` is a misnomer; it does not necessarily have a reference to `basedisk`.
51+
Notably, when a `basedisk` is an ISO9660 image, or the VM driver does not support differencing, `diffdisk` is an independent image.
4952

5053
kernel:
5154
- `kernel`: the kernel

0 commit comments

Comments
 (0)