44
55use super :: ByteCount ;
66use crate :: SqlU16 ;
7+ use crate :: impl_enum_type;
78use crate :: schema:: region;
89use crate :: typed_uuid:: DbTypedUuid ;
910use db_macros:: Asset ;
@@ -15,6 +16,19 @@ use omicron_uuid_kinds::VolumeUuid;
1516use serde:: { Deserialize , Serialize } ;
1617use uuid:: Uuid ;
1718
19+ impl_enum_type ! (
20+ #[ derive( SqlType , Debug , QueryId ) ]
21+ #[ diesel( postgres_type( name = "region_reservation_percent" , schema = "public" ) ) ]
22+ pub struct RegionReservationPercentEnum ;
23+
24+ #[ derive( Copy , Clone , Debug , AsExpression , FromSqlRow , Serialize , Deserialize , PartialEq ) ]
25+ #[ diesel( sql_type = RegionReservationPercentEnum ) ]
26+ pub enum RegionReservationPercent ;
27+
28+ // Enum values
29+ TwentyFive => b"25"
30+ ) ;
31+
1832/// Database representation of a Region.
1933///
2034/// A region represents a portion of a Crucible Downstairs dataset
@@ -58,13 +72,13 @@ pub struct Region {
5872
5973 // The Agent will reserve space for Downstairs overhead when creating the
6074 // corresponding ZFS dataset. Nexus has to account for that: store that
61- // reservation factor here as it may change in the future, and it can be
62- // used during Crucible related accounting.
63- reservation_factor : f64 ,
75+ // reservation percent here as it may change in the future, and it can be
76+ // used during Crucible related accounting. This is stored as an enum to
77+ // restrict the values to what the Crucible Agent uses.
78+ reservation_percent : RegionReservationPercent ,
6479}
6580
6681impl Region {
67- #[ allow( clippy:: too_many_arguments) ]
6882 pub fn new (
6983 dataset_id : DatasetUuid ,
7084 volume_id : VolumeUuid ,
@@ -73,7 +87,6 @@ impl Region {
7387 extent_count : u64 ,
7488 port : u16 ,
7589 read_only : bool ,
76- reservation_factor : f64 ,
7790 ) -> Self {
7891 Self {
7992 identity : RegionIdentity :: new ( Uuid :: new_v4 ( ) ) ,
@@ -85,7 +98,10 @@ impl Region {
8598 port : Some ( port. into ( ) ) ,
8699 read_only,
87100 deleting : false ,
88- reservation_factor,
101+ // When the Crucible agent's reservation percentage changes, this
102+ // function should accept that as argument. Until then, it can only
103+ // ever be 25%.
104+ reservation_percent : RegionReservationPercent :: TwentyFive ,
89105 }
90106 }
91107
@@ -122,7 +138,9 @@ impl Region {
122138 self . deleting
123139 }
124140
125- /// The size of the Region without accounting for any overhead
141+ /// The size of the Region without accounting for any overhead. The
142+ /// `allocation_query` function should have validated that this won't
143+ /// overflow.
126144 pub fn requested_size ( & self ) -> u64 {
127145 self . block_size ( ) . to_bytes ( )
128146 * self . blocks_per_extent ( )
@@ -133,6 +151,10 @@ impl Region {
133151 /// which is some factor higher than the requested region size to account
134152 /// for on-disk overhead.
135153 pub fn reserved_size ( & self ) -> u64 {
136- ( self . requested_size ( ) as f64 * self . reservation_factor ) . round ( ) as u64
154+ let overhead = match & self . reservation_percent {
155+ RegionReservationPercent :: TwentyFive => self . requested_size ( ) / 4 ,
156+ } ;
157+
158+ self . requested_size ( ) + overhead
137159 }
138160}
0 commit comments