@@ -9,6 +9,7 @@ use std::ops::Range;
9
9
use std:: sync:: atomic:: { AtomicU32 , AtomicU64 , Ordering } ;
10
10
use tokio:: time:: Instant ;
11
11
12
+ use crucible_client_types:: ReplacementRequestCheck ;
12
13
use crucible_client_types:: VolumeConstructionRequest ;
13
14
14
15
pub struct RegionExtentInfo {
@@ -779,7 +780,8 @@ impl BlockIO for Volume {
779
780
match result {
780
781
ReplaceResult :: Started
781
782
| ReplaceResult :: StartedAlready
782
- | ReplaceResult :: CompletedAlready => {
783
+ | ReplaceResult :: CompletedAlready
784
+ | ReplaceResult :: VcrMatches => {
783
785
// found the subvolume, so stop!
784
786
return Ok ( result) ;
785
787
}
@@ -1092,16 +1094,26 @@ impl Volume {
1092
1094
original : VolumeConstructionRequest ,
1093
1095
replacement : VolumeConstructionRequest ,
1094
1096
log : & Logger ,
1095
- ) -> Result < ( SocketAddr , SocketAddr ) , CrucibleError > {
1097
+ ) -> Result < ReplacementRequestCheck , CrucibleError > {
1096
1098
match Self :: compare_vcr_for_update ( original, replacement, log) ? {
1097
- Some ( ( o, n) ) => Ok ( ( o , n ) ) ,
1098
- None => crucible_bail ! (
1099
- ReplaceRequestInvalid ,
1100
- "VCR targets are the same"
1101
- ) ,
1099
+ Some ( ( o, n) ) => {
1100
+ Ok ( ReplacementRequestCheck :: Valid { old : o , new : n } )
1101
+ }
1102
+
1103
+ None => Ok ( ReplacementRequestCheck :: ReplacementMatchesOriginal ) ,
1102
1104
}
1103
1105
}
1104
1106
1107
+ /// Given two VolumeConstructionRequests, compare them, and return:
1108
+ ///
1109
+ /// - Ok(Some(old, new)) if there's a single target difference in one of the
1110
+ /// Region variants, and the replacement argument is a valid replacement
1111
+ /// for the original argument
1112
+ ///
1113
+ /// - Ok(None) if there are no differences between them
1114
+ ///
1115
+ /// - Err(e) if there's a difference that means the replacement argument is
1116
+ /// not a valid replacement for the original argument
1105
1117
pub fn compare_vcr_for_update (
1106
1118
original : VolumeConstructionRequest ,
1107
1119
replacement : VolumeConstructionRequest ,
@@ -1408,18 +1420,27 @@ impl Volume {
1408
1420
// Given two VolumeConstructionRequests, compare them to verify they
1409
1421
// only have the proper differences and if the VCRs are valid, submit
1410
1422
// the targets for replacement. A success here means the upstairs has
1411
- // accepted the replacement and the process has started.
1423
+ // accepted the replacement and the process has started, or there's
1424
+ // no work to do because the original and replacement match.
1412
1425
pub async fn target_replace (
1413
1426
& self ,
1414
1427
original : VolumeConstructionRequest ,
1415
1428
replacement : VolumeConstructionRequest ,
1416
1429
) -> Result < ReplaceResult , CrucibleError > {
1417
1430
let ( original_target, new_target) =
1418
- Self :: compare_vcr_for_target_replacement (
1431
+ match Self :: compare_vcr_for_target_replacement (
1419
1432
original,
1420
1433
replacement,
1421
1434
& self . log ,
1422
- ) ?;
1435
+ ) ? {
1436
+ ReplacementRequestCheck :: Valid { old, new } => ( old, new) ,
1437
+
1438
+ ReplacementRequestCheck :: ReplacementMatchesOriginal => {
1439
+ // The replacement VCR they sent is the same the original.
1440
+ // No replacement is required
1441
+ return Ok ( ReplaceResult :: VcrMatches ) ;
1442
+ }
1443
+ } ;
1423
1444
1424
1445
info ! (
1425
1446
self . log,
@@ -1464,6 +1485,15 @@ impl Volume {
1464
1485
Ok ( ReplaceResult :: CompletedAlready )
1465
1486
}
1466
1487
1488
+ Ok ( ReplaceResult :: VcrMatches ) => {
1489
+ info ! (
1490
+ self . log,
1491
+ "No work required for replace for {}" , self . uuid
1492
+ ) ;
1493
+
1494
+ Ok ( ReplaceResult :: VcrMatches )
1495
+ }
1496
+
1467
1497
Err ( e) => {
1468
1498
crucible_bail ! (
1469
1499
ReplaceRequestInvalid ,
@@ -3174,15 +3204,19 @@ mod test {
3174
3204
3175
3205
let log = csl ( ) ;
3176
3206
info ! ( log, "Test replacement of CID {cid}" ) ;
3177
- let ( old_t, new_t) = Volume :: compare_vcr_for_target_replacement (
3178
- original,
3179
- replacement,
3180
- & log,
3181
- ) ?;
3207
+ let ReplacementRequestCheck :: Valid { old, new } =
3208
+ Volume :: compare_vcr_for_target_replacement (
3209
+ original,
3210
+ replacement,
3211
+ & log,
3212
+ ) ?
3213
+ else {
3214
+ panic ! ( "wrong variant returned!" ) ;
3215
+ } ;
3182
3216
3183
- info ! ( log, "replace {old_t } with {new_t }" ) ;
3184
- assert_eq ! ( original_target, old_t ) ;
3185
- assert_eq ! ( new_target, new_t ) ;
3217
+ info ! ( log, "replace {old } with {new }" ) ;
3218
+ assert_eq ! ( original_target, old ) ;
3219
+ assert_eq ! ( new_target, new ) ;
3186
3220
Ok ( ( ) )
3187
3221
}
3188
3222
@@ -3239,15 +3273,19 @@ mod test {
3239
3273
} ;
3240
3274
3241
3275
let log = csl ( ) ;
3242
- let ( old_t, new_t) = Volume :: compare_vcr_for_target_replacement (
3243
- original,
3244
- replacement,
3245
- & log,
3246
- )
3247
- . unwrap ( ) ;
3276
+ let ReplacementRequestCheck :: Valid { old, new } =
3277
+ Volume :: compare_vcr_for_target_replacement (
3278
+ original,
3279
+ replacement,
3280
+ & log,
3281
+ )
3282
+ . unwrap ( )
3283
+ else {
3284
+ panic ! ( "wrong variant returned!" ) ;
3285
+ } ;
3248
3286
3249
- assert_eq ! ( original_target, old_t ) ;
3250
- assert_eq ! ( new_target, new_t ) ;
3287
+ assert_eq ! ( original_target, old ) ;
3288
+ assert_eq ! ( new_target, new ) ;
3251
3289
}
3252
3290
3253
3291
#[ tokio:: test]
@@ -3304,15 +3342,19 @@ mod test {
3304
3342
} ;
3305
3343
3306
3344
let log = csl ( ) ;
3307
- let ( old_t, new_t) = Volume :: compare_vcr_for_target_replacement (
3308
- original,
3309
- replacement,
3310
- & log,
3311
- )
3312
- . unwrap ( ) ;
3345
+ let ReplacementRequestCheck :: Valid { old, new } =
3346
+ Volume :: compare_vcr_for_target_replacement (
3347
+ original,
3348
+ replacement,
3349
+ & log,
3350
+ )
3351
+ . unwrap ( )
3352
+ else {
3353
+ panic ! ( "wrong variant returned!" ) ;
3354
+ } ;
3313
3355
3314
- assert_eq ! ( original_target, old_t ) ;
3315
- assert_eq ! ( new_target, new_t ) ;
3356
+ assert_eq ! ( original_target, old ) ;
3357
+ assert_eq ! ( new_target, new ) ;
3316
3358
}
3317
3359
3318
3360
#[ tokio:: test]
@@ -3392,13 +3434,15 @@ mod test {
3392
3434
3393
3435
let log = csl ( ) ;
3394
3436
3395
- // Replacement should return error.
3396
- assert ! ( Volume :: compare_vcr_for_target_replacement(
3397
- original. clone( ) ,
3398
- replacement. clone( ) ,
3399
- & log,
3400
- )
3401
- . is_err( ) ) ;
3437
+ // Replacement should return ReplacementMatchesOriginal
3438
+ assert ! ( matches!(
3439
+ Volume :: compare_vcr_for_target_replacement(
3440
+ original. clone( ) ,
3441
+ replacement. clone( ) ,
3442
+ & log,
3443
+ ) ,
3444
+ Ok ( ReplacementRequestCheck :: ReplacementMatchesOriginal ) ,
3445
+ ) ) ;
3402
3446
3403
3447
// Migration is valid with these VCRs
3404
3448
Volume :: compare_vcr_for_migration ( original, replacement, & log) . unwrap ( ) ;
@@ -3745,7 +3789,17 @@ mod test {
3745
3789
} ;
3746
3790
3747
3791
let log = csl ( ) ;
3748
- Volume :: compare_vcr_for_target_replacement ( original, replacement, & log)
3792
+ let ReplacementRequestCheck :: Valid { old, new } =
3793
+ Volume :: compare_vcr_for_target_replacement (
3794
+ original,
3795
+ replacement,
3796
+ & log,
3797
+ ) ?
3798
+ else {
3799
+ panic ! ( "wrong variant returned!" ) ;
3800
+ } ;
3801
+
3802
+ Ok ( ( old, new) )
3749
3803
}
3750
3804
3751
3805
#[ tokio:: test]
0 commit comments