@@ -66,24 +66,26 @@ impl FileEngineType {
66
66
pub struct DiskProperties {
67
67
pub file_path : String ,
68
68
pub file_engine : FileEngine < PendingRequest > ,
69
+ pub is_disk_read_only : bool ,
69
70
pub nsectors : u64 ,
70
71
pub image_id : [ u8 ; VIRTIO_BLK_ID_BYTES as usize ] ,
71
72
}
72
73
73
74
impl DiskProperties {
74
- pub fn new (
75
- disk_image_path : String ,
76
- is_disk_read_only : bool ,
77
- file_engine_type : FileEngineType ,
78
- ) -> Result < Self , VirtioBlockError > {
79
- let mut disk_image = OpenOptions :: new ( )
75
+ // Helper function that opens the file with the proper access permissions
76
+ fn open_file ( disk_image_path : & str , is_disk_read_only : bool ) -> Result < File , VirtioBlockError > {
77
+ OpenOptions :: new ( )
80
78
. read ( true )
81
79
. write ( !is_disk_read_only)
82
80
. open ( PathBuf :: from ( & disk_image_path) )
83
- . map_err ( |x| VirtioBlockError :: BackingFile ( x, disk_image_path. clone ( ) ) ) ?;
81
+ . map_err ( |x| VirtioBlockError :: BackingFile ( x, disk_image_path. to_string ( ) ) )
82
+ }
83
+
84
+ // Helper function that gets the size of the file
85
+ fn file_size ( disk_image_path : & str , disk_image : & mut File ) -> Result < u64 , VirtioBlockError > {
84
86
let disk_size = disk_image
85
87
. seek ( SeekFrom :: End ( 0 ) )
86
- . map_err ( |x| VirtioBlockError :: BackingFile ( x, disk_image_path. clone ( ) ) ) ?;
88
+ . map_err ( |x| VirtioBlockError :: BackingFile ( x, disk_image_path. to_string ( ) ) ) ?;
87
89
88
90
// We only support disk size, which uses the first two words of the configuration space.
89
91
// If the image is not a multiple of the sector size, the tail bits are not exposed.
@@ -95,17 +97,44 @@ impl DiskProperties {
95
97
) ;
96
98
}
97
99
100
+ Ok ( disk_size)
101
+ }
102
+
103
+ /// Create a new file for the block device using a FileEngine
104
+ pub fn new (
105
+ disk_image_path : String ,
106
+ is_disk_read_only : bool ,
107
+ file_engine_type : FileEngineType ,
108
+ ) -> Result < Self , VirtioBlockError > {
109
+ let mut disk_image = Self :: open_file ( & disk_image_path, is_disk_read_only) ?;
110
+ let disk_size = Self :: file_size ( & disk_image_path, & mut disk_image) ?;
98
111
let image_id = Self :: build_disk_image_id ( & disk_image) ;
99
112
100
113
Ok ( Self {
101
114
file_path : disk_image_path,
102
115
file_engine : FileEngine :: from_file ( disk_image, file_engine_type)
103
116
. map_err ( VirtioBlockError :: FileEngine ) ?,
117
+ is_disk_read_only,
104
118
nsectors : disk_size >> SECTOR_SHIFT ,
105
119
image_id,
106
120
} )
107
121
}
108
122
123
+ /// Update the path to the file backing the block device
124
+ pub fn update ( & mut self , disk_image_path : String ) -> Result < ( ) , VirtioBlockError > {
125
+ let mut disk_image = Self :: open_file ( & disk_image_path, self . is_disk_read_only ) ?;
126
+ let disk_size = Self :: file_size ( & disk_image_path, & mut disk_image) ?;
127
+
128
+ self . image_id = Self :: build_disk_image_id ( & disk_image) ;
129
+ self . file_engine
130
+ . update_file_path ( disk_image)
131
+ . map_err ( VirtioBlockError :: FileEngine ) ?;
132
+ self . nsectors = disk_size >> SECTOR_SHIFT ;
133
+ self . file_path = disk_image_path;
134
+
135
+ Ok ( ( ) )
136
+ }
137
+
109
138
fn build_device_id ( disk_file : & File ) -> Result < String , VirtioBlockError > {
110
139
let blk_metadata = disk_file
111
140
. metadata ( )
@@ -506,9 +535,7 @@ impl VirtioBlock {
506
535
507
536
/// Update the backing file and the config space of the block device.
508
537
pub fn update_disk_image ( & mut self , disk_image_path : String ) -> Result < ( ) , VirtioBlockError > {
509
- let disk_properties =
510
- DiskProperties :: new ( disk_image_path, self . read_only , self . file_engine_type ( ) ) ?;
511
- self . disk = disk_properties;
538
+ self . disk . update ( disk_image_path) ?;
512
539
self . config_space = self . disk . virtio_block_config_space ( ) ;
513
540
514
541
// Kick the driver to pick up the changes.
0 commit comments