[sefs] Make cache size configurable in Occlum.json

This commit is contained in:
Shaowei Song 2023-02-08 14:18:35 +08:00 committed by volcano
parent 5174feae15
commit dbe404f16a
5 changed files with 66 additions and 20 deletions

@ -159,6 +159,7 @@ pub struct ConfigMountOptions {
pub mac: Option<sgx_aes_gcm_128bit_tag_t>, pub mac: Option<sgx_aes_gcm_128bit_tag_t>,
pub layers: Option<Vec<ConfigMount>>, pub layers: Option<Vec<ConfigMount>>,
pub temporary: bool, pub temporary: bool,
pub cache_size: Option<u64>,
} }
impl Config { impl Config {
@ -266,10 +267,16 @@ impl ConfigMountOptions {
} else { } else {
None None
}; };
let cache_size = if input.cache_size.is_some() {
Some(parse_memory_size(input.cache_size.as_ref().unwrap())? as _)
} else {
None
};
Ok(ConfigMountOptions { Ok(ConfigMountOptions {
mac, mac,
layers, layers,
temporary: input.temporary, temporary: input.temporary,
cache_size,
}) })
} }
} }
@ -406,4 +413,6 @@ struct InputConfigMountOptions {
pub layers: Option<Vec<InputConfigMount>>, pub layers: Option<Vec<InputConfigMount>>,
#[serde(default)] #[serde(default)]
pub temporary: bool, pub temporary: bool,
#[serde(default)]
pub cache_size: Option<String>,
} }

@ -212,29 +212,50 @@ fn open_or_create_sefs_according_to(
} }
let source_path = mc.source.as_ref().unwrap(); let source_path = mc.source.as_ref().unwrap();
let root_mac = mc.options.mac; let root_mac = mc.options.mac;
let cache_size = mc.options.cache_size;
let sefs = if !mc.options.temporary { let sefs = if !mc.options.temporary {
if root_mac.is_some() { if root_mac.is_some() {
SEFS::open( SEFS::open(
Box::new(SgxStorage::new(source_path, user_key, &root_mac)), Box::new(SgxStorage::new(
source_path,
user_key,
&root_mac,
cache_size,
)?),
&time::OcclumTimeProvider, &time::OcclumTimeProvider,
&SgxUuidProvider, &SgxUuidProvider,
)? )?
} else if source_path.join("metadata").exists() { } else if source_path.join("metadata").exists() {
SEFS::open( SEFS::open(
Box::new(SgxStorage::new(source_path, user_key, &root_mac)), Box::new(SgxStorage::new(
source_path,
user_key,
&root_mac,
cache_size,
)?),
&time::OcclumTimeProvider, &time::OcclumTimeProvider,
&SgxUuidProvider, &SgxUuidProvider,
)? )?
} else { } else {
SEFS::create( SEFS::create(
Box::new(SgxStorage::new(source_path, user_key, &root_mac)), Box::new(SgxStorage::new(
source_path,
user_key,
&root_mac,
cache_size,
)?),
&time::OcclumTimeProvider, &time::OcclumTimeProvider,
&SgxUuidProvider, &SgxUuidProvider,
)? )?
} }
} else { } else {
SEFS::create( SEFS::create(
Box::new(SgxStorage::new(source_path, user_key, &root_mac)), Box::new(SgxStorage::new(
source_path,
user_key,
&root_mac,
cache_size,
)?),
&time::OcclumTimeProvider, &time::OcclumTimeProvider,
&SgxUuidProvider, &SgxUuidProvider,
)? )?

@ -5,7 +5,3 @@ pub use self::sgx_uuid_provider::SgxUuidProvider;
mod sgx_storage; mod sgx_storage;
mod sgx_uuid_provider; mod sgx_uuid_provider;
// Cache size of underlying SGX-PFS of SEFS
// Default cache size: 0x1000 * 48
const SEFS_CACHE_SIZE: u64 = 0x1000 * 256;

@ -30,6 +30,7 @@ pub struct SgxStorage {
path: PathBuf, path: PathBuf,
encrypt_mode: EncryptMode, encrypt_mode: EncryptMode,
file_cache: Mutex<BTreeMap<u64, LockedFile>>, file_cache: Mutex<BTreeMap<u64, LockedFile>>,
cache_size: Option<u64>,
} }
impl SgxStorage { impl SgxStorage {
@ -37,13 +38,16 @@ impl SgxStorage {
path: impl AsRef<Path>, path: impl AsRef<Path>,
key: &Option<sgx_key_128bit_t>, key: &Option<sgx_key_128bit_t>,
root_mac: &Option<sgx_aes_gcm_128bit_tag_t>, root_mac: &Option<sgx_aes_gcm_128bit_tag_t>,
) -> Self { cache_size: Option<u64>,
) -> Result<Self> {
// assert!(path.as_ref().is_dir()); // assert!(path.as_ref().is_dir());
SgxStorage { Self::check_cache_size(&cache_size)?;
Ok(SgxStorage {
path: path.as_ref().to_path_buf(), path: path.as_ref().to_path_buf(),
encrypt_mode: EncryptMode::new(key, root_mac), encrypt_mode: EncryptMode::new(key, root_mac),
file_cache: Mutex::new(BTreeMap::new()), file_cache: Mutex::new(BTreeMap::new()),
} cache_size,
})
} }
/// Get file by `file_id`. /// Get file by `file_id`.
/// It lookups cache first, if miss, then call `open_fn` to open one, /// It lookups cache first, if miss, then call `open_fn` to open one,
@ -82,6 +86,21 @@ impl SgxStorage {
) -> Result<LockedFile> { ) -> Result<LockedFile> {
open_fn(self) open_fn(self)
} }
fn check_cache_size(cache_size: &Option<u64>) -> Result<()> {
const PAGE_SIZE: u64 = 0x1000;
const DEFAULT_CACHE_SIZE: u64 = 48 * PAGE_SIZE;
if let Some(size) = *cache_size {
if size < DEFAULT_CACHE_SIZE || size % PAGE_SIZE != 0 {
error!(
"invalid cache size: {}, must larger than default size: {} and aligned with page size: {}",
size, DEFAULT_CACHE_SIZE, PAGE_SIZE
);
return_errno!(EINVAL, "invalid cache size");
}
}
Ok(())
}
} }
impl Storage for SgxStorage { impl Storage for SgxStorage {
@ -97,11 +116,9 @@ impl Storage for SgxStorage {
let file = match self.encrypt_mode { let file = match self.encrypt_mode {
EncryptMode::IntegrityOnly(_) => options.open_integrity_only(path)?, EncryptMode::IntegrityOnly(_) => options.open_integrity_only(path)?,
EncryptMode::EncryptWithIntegrity(key, _) | EncryptMode::Encrypt(key) => { EncryptMode::EncryptWithIntegrity(key, _) | EncryptMode::Encrypt(key) => {
options.open_with(path, Some(&key), Some(SEFS_CACHE_SIZE))? options.open_with(path, Some(&key), self.cache_size)?
}
EncryptMode::EncryptAutoKey => {
options.open_with(path, None, Some(SEFS_CACHE_SIZE))?
} }
EncryptMode::EncryptAutoKey => options.open_with(path, None, self.cache_size)?,
}; };
// Check the MAC of the root file against the given root MAC of the storage // Check the MAC of the root file against the given root MAC of the storage
@ -134,11 +151,9 @@ impl Storage for SgxStorage {
let file = match self.encrypt_mode { let file = match self.encrypt_mode {
EncryptMode::IntegrityOnly(_) => options.open_integrity_only(path)?, EncryptMode::IntegrityOnly(_) => options.open_integrity_only(path)?,
EncryptMode::EncryptWithIntegrity(key, _) | EncryptMode::Encrypt(key) => { EncryptMode::EncryptWithIntegrity(key, _) | EncryptMode::Encrypt(key) => {
options.open_with(path, Some(&key), Some(SEFS_CACHE_SIZE))? options.open_with(path, Some(&key), self.cache_size)?
}
EncryptMode::EncryptAutoKey => {
options.open_with(path, None, Some(SEFS_CACHE_SIZE))?
} }
EncryptMode::EncryptAutoKey => options.open_with(path, None, self.cache_size)?,
}; };
Ok(LockedFile(Arc::new(Mutex::new(file)))) Ok(LockedFile(Arc::new(Mutex::new(file))))
})?; })?;

@ -199,7 +199,10 @@ fn main() {
heap_max_size heap_max_size
} else { } else {
// If the user doesn't provide a value, use the max value as heap_max_size. // If the user doesn't provide a value, use the max value as heap_max_size.
std::cmp::max(heap_init_size, parse_memory_size(DEFAULT_CONFIG.kernel_heap_max_size)) std::cmp::max(
heap_init_size,
parse_memory_size(DEFAULT_CONFIG.kernel_heap_max_size),
)
} }
}; };
@ -540,6 +543,8 @@ struct OcclumMountOptions {
pub layers: Option<Vec<OcclumMount>>, pub layers: Option<Vec<OcclumMount>>,
#[serde(default, skip_serializing_if = "is_false")] #[serde(default, skip_serializing_if = "is_false")]
pub temporary: bool, pub temporary: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_size: Option<String>,
} }
#[inline] #[inline]