Skip to content

Commit 8e1be15

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 <akihiro.suda.cz@hco.ntt.co.jp>
1 parent a43cf63 commit 8e1be15

File tree

6 files changed

+65
-33
lines changed

6 files changed

+65
-33
lines changed

pkg/driver/qemu/qemu.go

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

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

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

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/driverutil/disk.go

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import (
1919
)
2020

2121
// EnsureDisk ensures that the diff disk exists with the specified size and format.
22+
// EnsureDisk usually just converts baseDisk (can be qcow2) to diffDisk (raw), unless baseDisk is an ISO9660 image.
23+
// Note that "diffDisk" is a misnomer, it is actually created as a full disk since Lima v2.1.
2224
func EnsureDisk(ctx context.Context, instDir, diskSize string, diskImageFormat image.Type) error {
2325
diffDisk := filepath.Join(instDir, filenames.DiffDisk)
2426
if _, err := os.Stat(diffDisk); err == nil || !errors.Is(err, os.ErrNotExist) {
@@ -34,28 +36,35 @@ func EnsureDisk(ctx context.Context, instDir, diskSize string, diskImageFormat i
3436
if diskSizeInBytes == 0 {
3537
return nil
3638
}
37-
isBaseDiskISO, err := iso9660util.IsISO9660(baseDisk)
38-
if err != nil {
39-
return err
40-
}
41-
if isBaseDiskISO {
42-
// Create an empty data volume (sparse)
43-
diffDiskF, err := os.Create(diffDisk)
39+
var isBaseDiskISO bool
40+
if _, err := os.Stat(baseDisk); !errors.Is(err, os.ErrNotExist) {
41+
isBaseDiskISO, err = iso9660util.IsISO9660(baseDisk)
4442
if err != nil {
4543
return err
4644
}
45+
if isBaseDiskISO {
46+
// Create an empty data volume (sparse)
47+
diffDiskF, err := os.Create(diffDisk)
48+
if err != nil {
49+
return err
50+
}
4751

48-
err = diskUtil.MakeSparse(ctx, diffDiskF, 0)
49-
if err != nil {
50-
diffDiskF.Close()
51-
return fmt.Errorf("failed to create sparse diff disk %q: %w", diffDisk, err)
52+
err = diskUtil.MakeSparse(ctx, diffDiskF, 0)
53+
if err != nil {
54+
diffDiskF.Close()
55+
return fmt.Errorf("failed to create sparse diff disk %q: %w", diffDisk, err)
56+
}
57+
return diffDiskF.Close()
5258
}
53-
return diffDiskF.Close()
5459
}
60+
// "diffdisk" is a misnomer, it is actually created as a full disk since Lima v2.1.
5561
// Check whether to use ASIF format
5662

57-
if err = diskUtil.Convert(ctx, diskImageFormat, baseDisk, diffDisk, &diskSizeInBytes, false); err != nil {
63+
if err := diskUtil.Convert(ctx, diskImageFormat, baseDisk, diffDisk, &diskSizeInBytes, false); err != nil {
5864
return fmt.Errorf("failed to convert %q to a disk %q: %w", baseDisk, diffDisk, err)
5965
}
60-
return err
66+
if err := os.RemoveAll(baseDisk); err != nil {
67+
return err
68+
}
69+
return nil
6170
}

pkg/instance/start.go

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

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

73+
// baseDisk is usually immediately renamed to diffDisk (misnomer) by the VM driver,
74+
// except when baseDisk is an ISO9660 image.
75+
baseDisk := filepath.Join(inst.Dir, filenames.BaseDisk)
7476
kernel := filepath.Join(inst.Dir, filenames.Kernel)
7577
kernelCmdline := filepath.Join(inst.Dir, filenames.KernelCmdline)
7678
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.1
4141
Kernel = "kernel"
4242
KernelCmdline = "kernel.cmdline"
4343
Initrd = "initrd"

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

Lines changed: 6 additions & 3 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.1.
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
@@ -190,4 +193,4 @@ The volume label is "cidata", as defined by [cloud-init NoCloud](https://docs.cl
190193

191194
![](/images/internals/lima-sequence-diagram.png)
192195

193-
(based on Lima 0.8.3)
196+
(based on Lima 0.8.3)

0 commit comments

Comments
 (0)