@@ -19,19 +19,23 @@ package task
1919import (
2020 "context"
2121 "fmt"
22+ "os"
23+ "path/filepath"
2224 "strings"
2325
2426 "github.com/containerd/containerd/api/types"
2527 "github.com/containerd/errdefs"
2628 "github.com/containerd/log"
2729
30+ "github.com/containerd/nerdbox/internal/erofs"
2831 "github.com/containerd/nerdbox/internal/vm"
2932)
3033
3134type diskOptions struct {
3235 name string
3336 source string
3437 readOnly bool
38+ vmdk bool
3539}
3640
3741// transformMounts does not perform any local mounts but transforms
@@ -44,25 +48,63 @@ func transformMounts(ctx context.Context, vmi vm.Instance, id string, ms []*type
4448 err error
4549 )
4650
51+ log .G (ctx ).Trace ("transformMounts" , ms )
4752 for _ , m := range ms {
4853 switch m .Type {
4954 case "erofs" :
55+
5056 disk := fmt .Sprintf ("disk-%d-%s" , disks , id )
5157 // virtiofs implementation has a limit of 36 characters for the tag
5258 if len (disk ) > 36 {
5359 disk = disk [:36 ]
5460 }
55- addDisks = append (addDisks , diskOptions {
56- name : disk ,
57- source : m .Source ,
58- readOnly : true ,
59- })
61+
62+ var Options []string
63+
64+ devices := []string {m .Source }
65+ for _ , o := range m .Options {
66+ if d , f := strings .CutPrefix (o , "device=" ); f {
67+ devices = append (devices , d )
68+ continue
69+ }
70+ Options = append (Options , o )
71+ }
72+
73+ if len (devices ) > 1 {
74+ // generate VMDK desc for the EROFS flattened fs if it does not exist
75+ mergedfsPath := filepath .Dir (m .Source ) + "/merged_fs.vmdk"
76+ if _ , err := os .Stat (mergedfsPath ); err != nil {
77+ if ! os .IsNotExist (err ) {
78+ log .G (ctx ).Warnf ("failed to stat %v: %v" , mergedfsPath , err )
79+ return nil , errdefs .ErrNotImplemented
80+ }
81+ err = erofs .DumpVMDKDescriptorToFile (mergedfsPath , 0xfffffffe , devices )
82+ if err != nil {
83+ log .G (ctx ).Warnf ("failed to generate %v: %v" , mergedfsPath , err )
84+ return nil , errdefs .ErrNotImplemented
85+ }
86+ }
87+ addDisks = append (addDisks , diskOptions {
88+ name : disk ,
89+ source : mergedfsPath ,
90+ readOnly : true ,
91+ vmdk : true ,
92+ })
93+ } else {
94+ addDisks = append (addDisks , diskOptions {
95+ name : disk ,
96+ source : m .Source ,
97+ readOnly : true ,
98+ vmdk : false ,
99+ })
100+ }
60101 am = append (am , & types.Mount {
61102 Type : "erofs" ,
62103 Source : fmt .Sprintf ("/dev/vd%c" , disks ),
63104 Target : m .Target ,
64- Options : filterOptions (m . Options ),
105+ Options : filterOptions (Options ),
65106 })
107+
66108 disks ++
67109 case "ext4" :
68110 disk := fmt .Sprintf ("disk-%d-%s" , disks , id )
@@ -75,6 +117,7 @@ func transformMounts(ctx context.Context, vmi vm.Instance, id string, ms []*type
75117 name : disk ,
76118 source : m .Source ,
77119 readOnly : false ,
120+ vmdk : false ,
78121 })
79122 am = append (am , & types.Mount {
80123 Type : "ext4" ,
@@ -127,6 +170,10 @@ func transformMounts(ctx context.Context, vmi vm.Instance, id string, ms []*type
127170 if do .readOnly {
128171 opts = append (opts , vm .WithReadOnly ())
129172 }
173+ if do .vmdk {
174+ opts = append (opts , vm .WithVmdk ())
175+ }
176+
130177 if err := vmi .AddDisk (ctx , do .name , do .source , opts ... ); err != nil {
131178 return nil , err
132179 }
0 commit comments