@@ -16,6 +16,8 @@ use crate::devices::virtio::block::{BlockError, CacheType};
16
16
/// Errors associated with the operations allowed on a drive.
17
17
#[ derive( Debug , thiserror:: Error , displaydoc:: Display ) ]
18
18
pub enum DriveError {
19
+ /// Attempt to add block as a root device while the root device defined as a pmem device
20
+ AddingSecondRootDevice ,
19
21
/// Unable to create the virtio block device: {0}
20
22
CreateBlockDevice ( BlockError ) ,
21
23
/// Cannot create RateLimiter: {0}
@@ -99,7 +101,7 @@ impl BlockBuilder {
99
101
}
100
102
101
103
/// Specifies whether there is a root block device already present in the list.
102
- fn has_root_device ( & self ) -> bool {
104
+ pub fn has_root_device ( & self ) -> bool {
103
105
// If there is a root device, it would be at the top of the list.
104
106
if let Some ( block) = self . devices . front ( ) {
105
107
block. lock ( ) . expect ( "Poisoned lock" ) . root_device ( )
@@ -127,11 +129,19 @@ impl BlockBuilder {
127
129
/// Inserts a `Block` in the block devices list using the specified configuration.
128
130
/// If a block with the same id already exists, it will overwrite it.
129
131
/// Inserting a secondary root block device will fail.
130
- pub fn insert ( & mut self , config : BlockDeviceConfig ) -> Result < ( ) , DriveError > {
132
+ pub fn insert (
133
+ & mut self ,
134
+ config : BlockDeviceConfig ,
135
+ has_pmem_root : bool ,
136
+ ) -> Result < ( ) , DriveError > {
131
137
let position = self . get_index_of_drive_id ( & config. drive_id ) ;
132
138
let has_root_device = self . has_root_device ( ) ;
133
139
let configured_as_root = config. is_root_device ;
134
140
141
+ if configured_as_root && has_pmem_root {
142
+ return Err ( DriveError :: AddingSecondRootDevice ) ;
143
+ }
144
+
135
145
// Don't allow adding a second root block device.
136
146
// If the new device cfg is root and not an update to the existing root, fail fast.
137
147
if configured_as_root && has_root_device && position != Some ( 0 ) {
@@ -234,7 +244,9 @@ mod tests {
234
244
} ;
235
245
236
246
let mut block_devs = BlockBuilder :: new ( ) ;
237
- block_devs. insert ( dummy_block_device. clone ( ) ) . unwrap ( ) ;
247
+ block_devs
248
+ . insert ( dummy_block_device. clone ( ) , false )
249
+ . unwrap ( ) ;
238
250
239
251
assert ! ( !block_devs. has_root_device( ) ) ;
240
252
assert_eq ! ( block_devs. devices. len( ) , 1 ) ;
@@ -266,7 +278,9 @@ mod tests {
266
278
} ;
267
279
268
280
let mut block_devs = BlockBuilder :: new ( ) ;
269
- block_devs. insert ( dummy_block_device. clone ( ) ) . unwrap ( ) ;
281
+ block_devs
282
+ . insert ( dummy_block_device. clone ( ) , false )
283
+ . unwrap ( ) ;
270
284
271
285
assert ! ( block_devs. has_root_device( ) ) ;
272
286
assert_eq ! ( block_devs. devices. len( ) , 1 ) ;
@@ -276,6 +290,36 @@ mod tests {
276
290
assert_eq ! ( block. read_only( ) , dummy_block_device. is_read_only. unwrap( ) ) ;
277
291
}
278
292
293
+ #[ test]
294
+ fn test_add_one_root_block_device_with_pmem_already_as_root ( ) {
295
+ let dummy_file = TempFile :: new ( ) . unwrap ( ) ;
296
+ let dummy_path = dummy_file. as_path ( ) . to_str ( ) . unwrap ( ) . to_string ( ) ;
297
+
298
+ let dummy_block_device = BlockDeviceConfig {
299
+ drive_id : String :: from ( "1" ) ,
300
+ partuuid : None ,
301
+ is_root_device : true ,
302
+ cache_type : CacheType :: Unsafe ,
303
+
304
+ is_read_only : Some ( true ) ,
305
+ path_on_host : Some ( dummy_path) ,
306
+ rate_limiter : None ,
307
+ file_engine_type : None ,
308
+
309
+ socket : None ,
310
+ } ;
311
+
312
+ let mut block_devs = BlockBuilder :: new ( ) ;
313
+ assert ! ( matches!(
314
+ block_devs
315
+ . insert( dummy_block_device. clone( ) , true )
316
+ . unwrap_err( ) ,
317
+ DriveError :: AddingSecondRootDevice ,
318
+ ) ) ;
319
+ assert ! ( !block_devs. has_root_device( ) ) ;
320
+ assert_eq ! ( block_devs. devices. len( ) , 0 ) ;
321
+ }
322
+
279
323
#[ test]
280
324
fn test_add_two_root_block_devs ( ) {
281
325
let dummy_file_1 = TempFile :: new ( ) . unwrap ( ) ;
@@ -311,9 +355,9 @@ mod tests {
311
355
} ;
312
356
313
357
let mut block_devs = BlockBuilder :: new ( ) ;
314
- block_devs. insert ( root_block_device_1) . unwrap ( ) ;
358
+ block_devs. insert ( root_block_device_1, false ) . unwrap ( ) ;
315
359
assert_eq ! (
316
- block_devs. insert( root_block_device_2) . unwrap_err( ) ,
360
+ block_devs. insert( root_block_device_2, false ) . unwrap_err( ) ,
317
361
DriveError :: RootBlockDeviceAlreadyAdded
318
362
) ;
319
363
}
@@ -370,9 +414,9 @@ mod tests {
370
414
} ;
371
415
372
416
let mut block_devs = BlockBuilder :: new ( ) ;
373
- block_devs. insert ( dummy_block_dev_2. clone ( ) ) . unwrap ( ) ;
374
- block_devs. insert ( dummy_block_dev_3. clone ( ) ) . unwrap ( ) ;
375
- block_devs. insert ( root_block_device. clone ( ) ) . unwrap ( ) ;
417
+ block_devs. insert ( dummy_block_dev_2. clone ( ) , false ) . unwrap ( ) ;
418
+ block_devs. insert ( dummy_block_dev_3. clone ( ) , false ) . unwrap ( ) ;
419
+ block_devs. insert ( root_block_device. clone ( ) , false ) . unwrap ( ) ;
376
420
377
421
assert_eq ! ( block_devs. devices. len( ) , 3 ) ;
378
422
@@ -443,9 +487,9 @@ mod tests {
443
487
} ;
444
488
445
489
let mut block_devs = BlockBuilder :: new ( ) ;
446
- block_devs. insert ( dummy_block_dev_2. clone ( ) ) . unwrap ( ) ;
447
- block_devs. insert ( dummy_block_dev_3. clone ( ) ) . unwrap ( ) ;
448
- block_devs. insert ( root_block_device. clone ( ) ) . unwrap ( ) ;
490
+ block_devs. insert ( dummy_block_dev_2. clone ( ) , false ) . unwrap ( ) ;
491
+ block_devs. insert ( dummy_block_dev_3. clone ( ) , false ) . unwrap ( ) ;
492
+ block_devs. insert ( root_block_device. clone ( ) , false ) . unwrap ( ) ;
449
493
450
494
assert_eq ! ( block_devs. devices. len( ) , 3 ) ;
451
495
@@ -503,8 +547,10 @@ mod tests {
503
547
let mut block_devs = BlockBuilder :: new ( ) ;
504
548
505
549
// Add 2 block devices.
506
- block_devs. insert ( root_block_device) . unwrap ( ) ;
507
- block_devs. insert ( dummy_block_device_2. clone ( ) ) . unwrap ( ) ;
550
+ block_devs. insert ( root_block_device, false ) . unwrap ( ) ;
551
+ block_devs
552
+ . insert ( dummy_block_device_2. clone ( ) , false )
553
+ . unwrap ( ) ;
508
554
509
555
// Get index zero.
510
556
assert_eq ! (
@@ -528,7 +574,9 @@ mod tests {
528
574
) ;
529
575
// Update OK.
530
576
dummy_block_device_2. is_read_only = Some ( true ) ;
531
- block_devs. insert ( dummy_block_device_2. clone ( ) ) . unwrap ( ) ;
577
+ block_devs
578
+ . insert ( dummy_block_device_2. clone ( ) , false )
579
+ . unwrap ( ) ;
532
580
533
581
let index = block_devs
534
582
. get_index_of_drive_id ( & dummy_block_device_2. drive_id )
@@ -540,7 +588,7 @@ mod tests {
540
588
let dummy_path_3 = String :: from ( "test_update_3" ) ;
541
589
dummy_block_device_2. path_on_host = Some ( dummy_path_3) ;
542
590
assert ! ( matches!(
543
- block_devs. insert( dummy_block_device_2. clone( ) ) ,
591
+ block_devs. insert( dummy_block_device_2. clone( ) , false ) ,
544
592
Err ( DriveError :: CreateBlockDevice ( BlockError :: VirtioBackend (
545
593
VirtioBlockError :: BackingFile ( _, _)
546
594
) ) )
@@ -550,7 +598,7 @@ mod tests {
550
598
dummy_block_device_2. path_on_host = Some ( dummy_path_2. clone ( ) ) ;
551
599
dummy_block_device_2. is_root_device = true ;
552
600
assert_eq ! (
553
- block_devs. insert( dummy_block_device_2) ,
601
+ block_devs. insert( dummy_block_device_2, false ) ,
554
602
Err ( DriveError :: RootBlockDeviceAlreadyAdded )
555
603
) ;
556
604
@@ -584,9 +632,9 @@ mod tests {
584
632
socket : None ,
585
633
} ;
586
634
587
- block_devs. insert ( root_block_device_old) . unwrap ( ) ;
635
+ block_devs. insert ( root_block_device_old, false ) . unwrap ( ) ;
588
636
let root_block_id = root_block_device_new. drive_id . clone ( ) ;
589
- block_devs. insert ( root_block_device_new) . unwrap ( ) ;
637
+ block_devs. insert ( root_block_device_new, false ) . unwrap ( ) ;
590
638
assert ! ( block_devs. has_root_device( ) ) ;
591
639
// Verify it's been moved to the first position.
592
640
assert_eq ! ( block_devs. devices[ 0 ] . lock( ) . unwrap( ) . id( ) , root_block_id) ;
@@ -611,7 +659,9 @@ mod tests {
611
659
} ;
612
660
613
661
let mut block_devs = BlockBuilder :: new ( ) ;
614
- block_devs. insert ( dummy_block_device. clone ( ) ) . unwrap ( ) ;
662
+ block_devs
663
+ . insert ( dummy_block_device. clone ( ) , false )
664
+ . unwrap ( ) ;
615
665
616
666
let configs = block_devs. configs ( ) ;
617
667
assert_eq ! ( configs. len( ) , 1 ) ;
0 commit comments