From 0e39475fa92a32f2232c59b1b0026e880ecfcbb6 Mon Sep 17 00:00:00 2001 From: Diwakar Sharma Date: Mon, 18 Mar 2024 18:25:40 +0000 Subject: [PATCH] fix(volume/resize): handle overflow during volume shrink attempt Signed-off-by: Diwakar Sharma --- .../src/bin/core/tests/volume/resize.rs | 29 ++++++++++++++++--- .../agents/src/bin/core/volume/service.rs | 7 ++++- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/control-plane/agents/src/bin/core/tests/volume/resize.rs b/control-plane/agents/src/bin/core/tests/volume/resize.rs index 186fa5a59..847d9b822 100644 --- a/control-plane/agents/src/bin/core/tests/volume/resize.rs +++ b/control-plane/agents/src/bin/core/tests/volume/resize.rs @@ -279,22 +279,38 @@ async fn resize_with_cluster_capacity_limit() { let vol_cli = cluster.grpc_client().volume(); - // resize exceeding the capacity limit + // resize(shrink) within a valid capacity limit + grpc_resize_volume_with_limit( + &vol_cli, + Some(EXPANDED_SIZE), + Some(ReplyErrorKind::NotAcceptable {}), + false, + ) + .await; + // resize(expand) exceeding the capacity limit grpc_resize_volume_with_limit( &vol_cli, Some(EXPANDED_SIZE - CAPACITY_LIMIT_DIFF), Some(ReplyErrorKind::CapacityLimitExceeded {}), + true, ) .await; - // resize within the capacity limit - grpc_resize_volume_with_limit(&vol_cli, Some(EXPANDED_SIZE + CAPACITY_LIMIT_DIFF), None).await; + // resize(expand) within the capacity limit + grpc_resize_volume_with_limit( + &vol_cli, + Some(EXPANDED_SIZE + CAPACITY_LIMIT_DIFF), + None, + true, + ) + .await; // resize a new volume, but reduce the limit set previously. The limit balance // calculations are expected to work based on reduced limit value now. grpc_resize_volume_with_limit( &vol_cli, Some(EXPANDED_SIZE + CAPACITY_LIMIT_DIFF / 2), None, + true, ) .await; } @@ -368,8 +384,13 @@ async fn grpc_resize_volume_with_limit( volume_client: &dyn VolumeOperations, capacity: Option, expected_error: Option, + expand: bool, ) { let vol_uuid = Uuid::new_v4(); + let new_size = match expand { + true => EXPANDED_SIZE, + false => SIZE / 2, + }; let volume = volume_client .create( @@ -389,7 +410,7 @@ async fn grpc_resize_volume_with_limit( .resize( &ResizeVolume { uuid: volume.uuid().clone(), - requested_size: EXPANDED_SIZE, + requested_size: new_size, cluster_capacity_limit: capacity, }, None, diff --git a/control-plane/agents/src/bin/core/volume/service.rs b/control-plane/agents/src/bin/core/volume/service.rs index a704f1d2f..188c05833 100644 --- a/control-plane/agents/src/bin/core/volume/service.rs +++ b/control-plane/agents/src/bin/core/volume/service.rs @@ -608,7 +608,12 @@ impl Service { return volume.resize(&self.registry, request).await; }; - let required = request.requested_size - volume.as_ref().size; + // If requested size is less than volume's current size(attempt to shrink volume), + // then required becomes zero because we won't need to borrow anything from capacity_limit. + let required = request + .requested_size + .checked_sub(volume.as_ref().size) + .unwrap_or_default(); *self.capacity_limit_borrow.write() += required; // If there is a defined system wide capacity limit, ensure we don't breach that. let current = *self.capacity_limit_borrow.read();