8
8
use std:: cmp;
9
9
use std:: convert:: From ;
10
10
use std:: fs:: { File , OpenOptions } ;
11
- use std:: io:: { self , Seek , SeekFrom , Write } ;
11
+ use std:: io:: { self , Write } ;
12
12
#[ cfg( target_os = "linux" ) ]
13
13
use std:: os:: linux:: fs:: MetadataExt ;
14
14
#[ cfg( target_os = "macos" ) ]
@@ -19,6 +19,9 @@ use std::sync::atomic::AtomicUsize;
19
19
use std:: sync:: { Arc , Mutex } ;
20
20
use std:: thread:: JoinHandle ;
21
21
22
+ use imago:: file:: File as ImagoFile ;
23
+ use imago:: qcow2:: Qcow2 ;
24
+ use imago:: SyncFormatAccess ;
22
25
use log:: { error, warn} ;
23
26
use utils:: eventfd:: { EventFd , EFD_NONBLOCK } ;
24
27
use virtio_bindings:: {
@@ -51,22 +54,18 @@ pub enum CacheType {
51
54
/// Helper object for setting up all `Block` fields derived from its backing file.
52
55
pub ( crate ) struct DiskProperties {
53
56
cache_type : CacheType ,
54
- pub ( crate ) file : File ,
57
+ pub ( crate ) file : Arc < SyncFormatAccess < ImagoFile > > ,
55
58
nsectors : u64 ,
56
59
image_id : Vec < u8 > ,
57
60
}
58
61
59
62
impl DiskProperties {
60
63
pub fn new (
61
- disk_image_path : String ,
62
- is_disk_read_only : bool ,
64
+ disk_image : Arc < SyncFormatAccess < ImagoFile > > ,
65
+ disk_image_id : Vec < u8 > ,
63
66
cache_type : CacheType ,
64
67
) -> io:: Result < Self > {
65
- let mut disk_image = OpenOptions :: new ( )
66
- . read ( true )
67
- . write ( !is_disk_read_only)
68
- . open ( PathBuf :: from ( & disk_image_path) ) ?;
69
- let disk_size = disk_image. seek ( SeekFrom :: End ( 0 ) ) ?;
68
+ let disk_size = disk_image. size ( ) ;
70
69
71
70
// We only support disk size, which uses the first two words of the configuration space.
72
71
// If the image is not a multiple of the sector size, the tail bits are not exposed.
@@ -81,13 +80,13 @@ impl DiskProperties {
81
80
Ok ( Self {
82
81
cache_type,
83
82
nsectors : disk_size >> SECTOR_SHIFT ,
84
- image_id : Self :: build_disk_image_id ( & disk_image ) ,
83
+ image_id : disk_image_id ,
85
84
file : disk_image,
86
85
} )
87
86
}
88
87
89
- pub fn file_mut ( & mut self ) -> & mut File {
90
- & mut self . file
88
+ pub fn file ( & self ) -> & SyncFormatAccess < ImagoFile > {
89
+ self . file . as_ref ( )
91
90
}
92
91
93
92
pub fn nsectors ( & self ) -> u64 {
@@ -141,7 +140,7 @@ impl Drop for DiskProperties {
141
140
error ! ( "Failed to flush block data on drop." ) ;
142
141
}
143
142
// Sync data out to physical media on host.
144
- if self . file . sync_all ( ) . is_err ( ) {
143
+ if self . file . sync ( ) . is_err ( ) {
145
144
error ! ( "Failed to sync block data on drop." )
146
145
}
147
146
}
@@ -168,8 +167,8 @@ pub struct Block {
168
167
// Host file and properties.
169
168
disk : Option < DiskProperties > ,
170
169
cache_type : CacheType ,
171
- disk_image_path : String ,
172
- is_disk_read_only : bool ,
170
+ disk_image : Arc < SyncFormatAccess < ImagoFile > > ,
171
+ disk_image_id : Vec < u8 > ,
173
172
worker_thread : Option < JoinHandle < ( ) > > ,
174
173
worker_stopfd : EventFd ,
175
174
@@ -206,8 +205,29 @@ impl Block {
206
205
disk_image_format : disk:: ImageType ,
207
206
is_disk_read_only : bool ,
208
207
) -> io:: Result < Block > {
208
+ let disk_image = OpenOptions :: new ( )
209
+ . read ( true )
210
+ . write ( !is_disk_read_only)
211
+ . open ( PathBuf :: from ( & disk_image_path) ) ?;
212
+
213
+ let disk_image_id = DiskProperties :: build_disk_image_id ( & disk_image) ;
214
+
215
+ let disk_image = match disk_image_format {
216
+ disk:: ImageType :: Qcow2 => {
217
+ let mut qcow_disk_image =
218
+ Qcow2 :: < ImagoFile > :: open_path_sync ( disk_image_path, !is_disk_read_only) ?;
219
+ qcow_disk_image. open_implicit_dependencies_sync ( ) ?;
220
+ SyncFormatAccess :: new ( qcow_disk_image) ?
221
+ }
222
+ disk:: ImageType :: Raw => {
223
+ let raw = imago:: raw:: Raw :: open_path_sync ( disk_image_path, !is_disk_read_only) ?;
224
+ SyncFormatAccess :: new ( raw) ?
225
+ }
226
+ } ;
227
+ let disk_image = Arc :: new ( disk_image) ;
228
+
209
229
let disk_properties =
210
- DiskProperties :: new ( disk_image_path . clone ( ) , is_disk_read_only , cache_type) ?;
230
+ DiskProperties :: new ( Arc :: clone ( & disk_image ) , disk_image_id . clone ( ) , cache_type) ?;
211
231
212
232
let mut avail_features = ( 1u64 << VIRTIO_F_VERSION_1 )
213
233
| ( 1u64 << VIRTIO_BLK_F_FLUSH )
@@ -235,8 +255,8 @@ impl Block {
235
255
config,
236
256
disk : Some ( disk_properties) ,
237
257
cache_type,
238
- disk_image_path ,
239
- is_disk_read_only ,
258
+ disk_image ,
259
+ disk_image_id ,
240
260
avail_features,
241
261
acked_features : 0u64 ,
242
262
interrupt_status : Arc :: new ( AtomicUsize :: new ( 0 ) ) ,
@@ -349,8 +369,8 @@ impl VirtioDevice for Block {
349
369
let disk = match self . disk . take ( ) {
350
370
Some ( d) => d,
351
371
None => DiskProperties :: new (
352
- self . disk_image_path . clone ( ) ,
353
- self . is_disk_read_only ,
372
+ Arc :: clone ( & self . disk_image ) ,
373
+ self . disk_image_id . clone ( ) ,
354
374
self . cache_type ,
355
375
)
356
376
. map_err ( |_| ActivateError :: BadActivate ) ?,
0 commit comments