@@ -101,8 +101,6 @@ func networkConfigToNet(nc *types.NetworkConfig) chNet {
101101}
102102
103103func storageConfigToDisk (storageConfig * types.StorageConfig , cpuCount int ) chDisk {
104- noDirectIO := false // use page cache, not direct I/O
105-
106104 d := chDisk {
107105 Path : storageConfig .Path ,
108106 ReadOnly : storageConfig .RO ,
@@ -111,19 +109,22 @@ func storageConfigToDisk(storageConfig *types.StorageConfig, cpuCount int) chDis
111109 QueueSize : defaultDiskQueueSize ,
112110 }
113111
112+ // Writable disks use O_DIRECT to bypass host page cache, avoiding
113+ // fdatasync storms on guest flush. Readonly disks keep page cache
114+ // for shared base image benefit (DirectIO defaults to false).
115+ d .DirectIO = ! storageConfig .RO
116+
114117 switch {
115118 case filepath .Ext (storageConfig .Path ) == ".qcow2" :
116- // cloudimg qcow2 overlay
119+ // cloudimg qcow2 overlay: CH has its own L2/refcount LRU cache.
117120 d .ImageType = "Qcow2"
118121 d .BackingFiles = ! storageConfig .RO
119122 case storageConfig .RO :
120- // OCI EROFS layer: readonly, leverage host page cache
123+ // OCI EROFS layer: readonly, host page cache shared across VMs.
121124 d .ImageType = "Raw"
122- d .DirectIO = & noDirectIO
123125 default :
124- // OCI COW raw: writable, leverage host page cache, sparse
126+ // OCI COW raw: writable sparse disk.
125127 d .ImageType = "Raw"
126- d .DirectIO = & noDirectIO
127128 d .Sparse = true
128129 }
129130
@@ -218,7 +219,7 @@ func diskToCLIArg(d chDisk) string {
218219 var b kvBuilder
219220 b .add ("path=" + d .Path )
220221 b .addIf (d .ReadOnly , "readonly=on" )
221- b .addIf (d .DirectIO != nil && ! * d . DirectIO , "direct=off " )
222+ b .addIf (d .DirectIO , "direct=on " )
222223 b .addIf (d .Sparse , "sparse=on" )
223224 b .addIf (d .ImageType != "" , "image_type=" + strings .ToLower (d .ImageType ))
224225 b .addIf (d .BackingFiles , "backing_files=on" )
0 commit comments