Skip to content

Commit dcaf5a0

Browse files
committed
introduce MountedFileSizePolicy
1 parent afe5295 commit dcaf5a0

File tree

12 files changed

+226
-99
lines changed

12 files changed

+226
-99
lines changed

CHANGELOG.md

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# Changelog
22

33

4-
## [v0.10.1]
4+
## [v0.11.0]
55
- Fix mounting on absolute paths
66
- Improved mounted memory size reset logic
7+
- API change: explicit mount file size policy added
8+
- Update dependencies
79

810
## [v0.10.0]
911
- Optimized work with folders
@@ -12,29 +14,29 @@
1214
- Add fast direntry lookup by name
1315

1416
## [v0.9.0]
15-
- switch to ic-stable-structures v0.7
16-
- refactor project structure
17-
- integrate ic-test into project for the integration tests
18-
- update dependencies
17+
- Switch to ic-stable-structures v0.7
18+
- Refactor project structure
19+
- Integrate ic-test into project for the integration tests
20+
- Update dependencies
1921

2022

2123
## [v0.8.1]
22-
- switch to ic-cdk v0.18.3
23-
- switch to pocket-ic v9.0
24-
- update dependencies
24+
- Switch to ic-cdk v0.18.3
25+
- Switch to pocket-ic v9.0
26+
- Update dependencies
2527

2628

2729
## [v0.8.0]
28-
- improved Wasi compliance
29-
- change edition to 2024
30-
- update dependencies
31-
- bug fixes
32-
- faster file look-up
33-
- file read-write access control
34-
- fixed writing in append-mode
35-
- switch to pocket-ic v7.0
36-
- support for '..' in paths
37-
- return '.' and '..' during folder file list
30+
- Improved Wasi compliance
31+
- Change edition to 2024
32+
- Update dependencies
33+
- Bug fixes
34+
- Faster file look-up
35+
- File read-write access control
36+
- Fixed writing in append-mode
37+
- Switch to pocket-ic v7.0
38+
- Support for '..' in paths
39+
- Return '.' and '..' during folder file list
3840

3941

4042
## [v0.7.3]
@@ -98,7 +100,7 @@
98100
## [v0.5.0]
99101
- *API change:* init with memory manager using memory index range rather than first memory index.
100102

101-
[v0.10.1]: https://github.com/wasm-forge/stable-fs/compare/v0.10.0...v0.10.1
103+
[v0.11.0]: https://github.com/wasm-forge/stable-fs/compare/v0.10.0...v0.11.0
102104
[v0.10.0]: https://github.com/wasm-forge/stable-fs/compare/v0.9.0...v0.10.0
103105
[v0.9.0]: https://github.com/wasm-forge/stable-fs/compare/v0.8.1...v0.9.0
104106
[v0.8.1]: https://github.com/wasm-forge/stable-fs/compare/v0.8.0...v0.8.1

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ resolver = "2"
1111
bitflags = "2.9.4"
1212
ciborium = "0.2.2"
1313

14-
ic-cdk = "0.18.7"
14+
ic-cdk = "0.18.5"
1515
ic-stable-structures = "0.7.0"
1616

1717
serde = "1.0.219"

stable-fs/src/fs.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{
1212
},
1313
storage::{
1414
Storage,
15-
types::{DirEntry, DirEntryIndex, FileType, Metadata, Node},
15+
types::{DirEntry, DirEntryIndex, FileType, Metadata, MountedFileSizePolicy, Node},
1616
},
1717
};
1818

@@ -22,7 +22,7 @@ pub use crate::runtime::types::{
2222
};
2323
pub use crate::storage::types::FileSize;
2424

25-
// The main class implementing the API to work with the file system.
25+
/// The main class implementing the API to work with the file system.
2626
pub struct FileSystem {
2727
pub(crate) root_fd: Fd,
2828
pub(crate) fd_table: FdTable,
@@ -185,6 +185,7 @@ impl FileSystem {
185185
&mut self,
186186
filename: &str,
187187
memory: Box<dyn Memory>,
188+
policy: MountedFileSizePolicy,
188189
) -> Result<(), Error> {
189190
let filename = filename.strip_prefix('/').unwrap_or(filename);
190191

@@ -199,7 +200,7 @@ impl FileSystem {
199200

200201
let result = (|| {
201202
let file = self.get_file(fd)?;
202-
self.storage.mount_node(file.node, memory)
203+
self.storage.mount_node(file.node, memory, policy)
203204
})();
204205

205206
let _ = self.close(fd);

stable-fs/src/fs_tests.rs

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ mod tests {
55

66
use crate::fs::FileSystem;
77
use crate::runtime::types::Fd;
8-
use crate::storage::types::Node;
8+
use crate::storage::types::{MountedFileSizePolicy, Node};
99

1010
use ic_stable_structures::memory_manager::{MemoryId, MemoryManager};
1111
use ic_stable_structures::{Memory, VectorMemory};
@@ -815,8 +815,12 @@ mod tests {
815815

816816
let root_fd = fs.root_fd();
817817

818-
fs.mount_memory_file("test.txt", Box::new(memory.clone()))
819-
.unwrap();
818+
fs.mount_memory_file(
819+
"test.txt",
820+
Box::new(memory.clone()),
821+
MountedFileSizePolicy::PreviousOrZero,
822+
)
823+
.unwrap();
820824

821825
let content = "ABCDEFG123";
822826

@@ -836,8 +840,12 @@ mod tests {
836840

837841
let storage = StableStorage::new_with_memory_manager(&memory_manager, 200..210);
838842
let mut fs = FileSystem::new(Box::new(storage)).unwrap();
839-
fs.mount_memory_file("test.txt", Box::new(memory.clone()))
840-
.unwrap();
843+
fs.mount_memory_file(
844+
"test.txt",
845+
Box::new(memory.clone()),
846+
MountedFileSizePolicy::PreviousOrZero,
847+
)
848+
.unwrap();
841849

842850
let root_fd = fs.root_fd();
843851
let content = "ABCDEFG123";
@@ -846,8 +854,12 @@ mod tests {
846854
// imitate canister upgrade (we keep the memory manager but recreate the file system with the same virtual memories)
847855
let storage = StableStorage::new_with_memory_manager(&memory_manager, 200..210);
848856
let mut fs = FileSystem::new(Box::new(storage)).unwrap();
849-
fs.mount_memory_file("test.txt", Box::new(memory.clone()))
850-
.unwrap();
857+
fs.mount_memory_file(
858+
"test.txt",
859+
Box::new(memory.clone()),
860+
MountedFileSizePolicy::PreviousOrZero,
861+
)
862+
.unwrap();
851863
let root_fd = fs.root_fd();
852864

853865
let content = read_text_file(&mut fs, root_fd, "test.txt", 0, 100);
@@ -863,8 +875,12 @@ mod tests {
863875

864876
let root_fd = fs.root_fd();
865877

866-
fs.mount_memory_file("test.txt", Box::new(memory.clone()))
867-
.unwrap();
878+
fs.mount_memory_file(
879+
"test.txt",
880+
Box::new(memory.clone()),
881+
MountedFileSizePolicy::PreviousOrZero,
882+
)
883+
.unwrap();
868884

869885
let res = fs.remove_file(root_fd, "test.txt");
870886

@@ -887,8 +903,12 @@ mod tests {
887903

888904
let file_name = "test.txt";
889905

890-
fs.mount_memory_file(file_name, Box::new(memory1.clone()))
891-
.unwrap();
906+
fs.mount_memory_file(
907+
file_name,
908+
Box::new(memory1.clone()),
909+
MountedFileSizePolicy::PreviousOrZero,
910+
)
911+
.unwrap();
892912

893913
let content = "ABCDEFG123";
894914
let len = content.len();
@@ -921,8 +941,12 @@ mod tests {
921941
fs.unmount_memory_file(file_name).unwrap();
922942

923943
// init new memory into a file
924-
fs.mount_memory_file(file_name, Box::new(memory2.clone()))
925-
.unwrap();
944+
fs.mount_memory_file(
945+
file_name,
946+
Box::new(memory2.clone()),
947+
MountedFileSizePolicy::PreviousOrZero,
948+
)
949+
.unwrap();
926950

927951
fs.init_memory_file(file_name).unwrap();
928952

@@ -947,8 +971,12 @@ mod tests {
947971
let hello_message = "Hello host".to_string();
948972
let hello_message2 = "1234Hello from regular file".to_string();
949973

950-
fs.mount_memory_file(file_name, Box::new(memory.clone()))
951-
.unwrap();
974+
fs.mount_memory_file(
975+
file_name,
976+
Box::new(memory.clone()),
977+
MountedFileSizePolicy::PreviousOrZero,
978+
)
979+
.unwrap();
952980

953981
// write something into a host memory file
954982
write_text_file(&mut fs, dir_fd, file_name, &hello_message, 1).unwrap();
@@ -966,8 +994,12 @@ mod tests {
966994
assert_eq!(str, "".to_string());
967995

968996
// mount again, the old content should recover
969-
fs.mount_memory_file(file_name, Box::new(memory.clone()))
970-
.unwrap();
997+
fs.mount_memory_file(
998+
file_name,
999+
Box::new(memory.clone()),
1000+
MountedFileSizePolicy::PreviousOrZero,
1001+
)
1002+
.unwrap();
9711003
let str = read_text_file(&mut fs, dir_fd, file_name, 0, 1000);
9721004
assert_eq!(str, hello_message);
9731005

@@ -985,8 +1017,12 @@ mod tests {
9851017
assert_eq!(str, hello_message2);
9861018

9871019
// after mounting, we still have the old content
988-
fs.mount_memory_file(file_name, Box::new(memory.clone()))
989-
.unwrap();
1020+
fs.mount_memory_file(
1021+
file_name,
1022+
Box::new(memory.clone()),
1023+
MountedFileSizePolicy::PreviousOrZero,
1024+
)
1025+
.unwrap();
9901026
let str = read_text_file(&mut fs, dir_fd, file_name, 0, 1000);
9911027
assert_eq!(str, hello_message);
9921028

stable-fs/src/storage.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ use ic_stable_structures::Memory;
33
use crate::{
44
error::Error,
55
fs::{ChunkSize, ChunkType},
6-
storage::types::{DirEntry, DirEntryIndex, FileName, FileSize, Metadata, Node},
6+
storage::types::{
7+
DirEntry, DirEntryIndex, FileName, FileSize, Metadata, MountedFileSizePolicy, Node,
8+
},
79
};
810

911
mod allocator;
@@ -28,7 +30,13 @@ pub trait Storage {
2830
fn new_node(&mut self) -> Node;
2931

3032
/// mark node as mounted.
31-
fn mount_node(&mut self, node: Node, memory: Box<dyn Memory>) -> Result<(), Error>;
33+
fn mount_node(
34+
&mut self,
35+
node: Node,
36+
memory: Box<dyn Memory>,
37+
mount_policy: MountedFileSizePolicy,
38+
) -> Result<(), Error>;
39+
3240
/// mark note as not mounted.
3341
fn unmount_node(&mut self, node: Node) -> Result<Box<dyn Memory>, Error>;
3442
/// return true if the node is mounted.

stable-fs/src/storage/dummy.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
error::Error,
33
fs::{ChunkSize, ChunkType},
4-
storage::types::FileName,
4+
storage::types::{FileName, MountedFileSizePolicy},
55
};
66

77
use super::{
@@ -64,6 +64,7 @@ impl Storage for DummyStorage {
6464
&mut self,
6565
_node: Node,
6666
_memory: Box<dyn ic_stable_structures::Memory>,
67+
_policy: MountedFileSizePolicy,
6768
) -> Result<(), Error> {
6869
panic!("Not supported")
6970
}

stable-fs/src/storage/stable.rs

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{collections::HashMap, ops::Range};
22

3-
use crate::storage::types::{FileName, ZEROES};
3+
use crate::storage::types::{FileName, MountedFileSizePolicy, ZEROES};
44
use ic_cdk::stable::WASM_PAGE_SIZE_IN_BYTES;
55
use ic_stable_structures::{
66
BTreeMap, Cell, Memory,
@@ -980,7 +980,12 @@ impl<M: Memory> Storage for StableStorage<M> {
980980
Ok(())
981981
}
982982

983-
fn mount_node(&mut self, node: Node, memory: Box<dyn Memory>) -> Result<(), Error> {
983+
fn mount_node(
984+
&mut self,
985+
node: Node,
986+
memory: Box<dyn Memory>,
987+
policy: MountedFileSizePolicy,
988+
) -> Result<(), Error> {
984989
if self.is_mounted(node) {
985990
return Err(Error::DeviceOrResourceBusy);
986991
}
@@ -991,30 +996,23 @@ impl<M: Memory> Storage for StableStorage<M> {
991996

992997
let memory_size = memory.size();
993998

994-
// activate mount
999+
// activate mount, we use mounted metadata after this line
9951000
self.active_mounts.insert(node, memory);
9961001

997-
if let Ok(old_mounted_meta) = self.get_metadata(node) {
998-
// the connected memory might have a different size from the old memory, we need to decide which size to use...
999-
//
1000-
// Solution:
1001-
// if the new memory size in bytes is smaller than the old mounted metadata file size,
1002-
// we assume this is a new and unknown memory, and reinitialize the metadata size to match the total number of bytes
1003-
// provided in memory
1002+
let old_size = if let Ok(old_mounted_meta) = self.get_metadata(node) {
1003+
let size = old_mounted_meta.size;
1004+
file_meta = old_mounted_meta;
1005+
Some(size)
1006+
} else {
1007+
None
1008+
};
10041009

1005-
if memory_size * WASM_PAGE_SIZE_IN_BYTES < old_mounted_meta.size {
1006-
let mut meta = old_mounted_meta.clone();
1010+
let new_size = policy.get_mounted_file_size(old_size, memory_size);
10071011

1008-
meta.size = memory_size * WASM_PAGE_SIZE_IN_BYTES;
1009-
self.put_metadata(node, &meta)?;
1010-
}
1011-
} else {
1012-
// take a copy of the file meta, set the size to the size of the memory
1013-
file_meta.size = memory_size * WASM_PAGE_SIZE_IN_BYTES;
1012+
file_meta.size = new_size;
10141013

1015-
// update mounted metadata
1016-
self.put_metadata(node, &file_meta)?;
1017-
};
1014+
// update mounted metadata
1015+
self.put_metadata(node, &file_meta)?;
10181016

10191017
Ok(())
10201018
}
@@ -1062,7 +1060,7 @@ impl<M: Memory> Storage for StableStorage<M> {
10621060
remainder -= to_read;
10631061
}
10641062

1065-
self.mount_node(node, memory)?;
1063+
self.mount_node(node, memory, MountedFileSizePolicy::PreviousOrZero)?;
10661064

10671065
self.put_metadata(node, &meta)?;
10681066

@@ -1102,7 +1100,7 @@ impl<M: Memory> Storage for StableStorage<M> {
11021100

11031101
self.put_metadata(node, &meta)?;
11041102

1105-
self.mount_node(node, memory)?;
1103+
self.mount_node(node, memory, MountedFileSizePolicy::PreviousOrZero)?;
11061104

11071105
Ok(())
11081106
}

0 commit comments

Comments
 (0)