Skip to content

Commit 5d1bcd0

Browse files
authored
feat(fs): expose overlayfs API for macOS (#8)
* feat(fs): expose overlayfs API for macOS Add public API for using OverlayFS functionality in libkrun on macOS by exposing the implementation through a new FsImplConfig enum. This allows clients to configure either passthrough or overlayfs filesystem modes. Key changes: - Add FsImplConfig enum to select between Passthrough and Overlayfs modes - Add FsImplShare enum to handle different sharing configurations - Refactor Fs implementation to delegate operations to selected backend - Update Config struct to include layers configuration - Clean up and reorganize filesystem server code - Add comprehensive test coverage for overlayfs operations The implementation maintains the existing passthrough functionality while adding the ability to configure overlayfs mode with multiple read-only layers and a writable top layer. * feat(overlayfs): add special handling for init.krun lookup Add special case handling in the lookup method to return a predefined entry when looking up "init.krun" file. This allows exposing the init binary with specific permissions (755) and size based on the included binary data. * fix(overlayfs): improve init.krun inode handling and documentation - Set init.krun inode ID dynamically using next_inode counter - Reorder init.krun inode check before handle data lookup in read() - Add documentation about default values for config options - Clarify proc_sfd_rawfd usage in sandboxing scenarios - Update comments to specifically reference init.krun * refactor(fs): remove debug println statements from overlayfs
1 parent d79d1d6 commit 5d1bcd0

File tree

15 files changed

+972
-178
lines changed

15 files changed

+972
-178
lines changed

include/libkrun.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,34 @@ int32_t krun_set_vm_config(uint32_t ctx_id, uint8_t num_vcpus, uint32_t ram_mib)
5959
*
6060
* Returns:
6161
* Zero on success or a negative error number on failure.
62+
* Documented errors:
63+
* -EEXIST when a root device is already set
64+
*
65+
* Notes:
66+
* This function is mutually exclusive with krun_set_overlayfs_root.
6267
*/
6368
int32_t krun_set_root(uint32_t ctx_id, const char *root_path);
6469

70+
/**
71+
* Sets up an OverlayFS to be used as root for the microVM. Not available in libkrun-SEV.
72+
*
73+
* Arguments:
74+
* "ctx_id" - the configuration context ID.
75+
* "root_layers" - an array of string pointers to filesystem paths representing
76+
* the layers to be used for the OverlayFS. The array must be
77+
* NULL-terminated and contain at least one layer.
78+
*
79+
* Returns:
80+
* Zero on success or a negative error number on failure.
81+
* Documented errors:
82+
* -EINVAL when no layers are provided
83+
* -EEXIST when a root device is already set
84+
*
85+
* Notes:
86+
* This function is mutually exclusive with krun_set_root.
87+
*/
88+
int32_t krun_set_overlayfs_root(uint32_t ctx_id, const char *const root_layers[]);
89+
6590
/**
6691
* DEPRECATED. Use krun_add_disk instead.
6792
*

src/devices/src/virtio/fs/device.rs

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ use vm_memory::{ByteValued, GuestMemoryMmap};
1515
use super::super::{
1616
ActivateResult, DeviceState, FsError, Queue as VirtQueue, VirtioDevice, VirtioShmRegion,
1717
};
18+
use super::kinds::{FsImplConfig, FsImplShare};
19+
use super::macos::overlayfs;
1820
use super::passthrough;
1921
use super::worker::FsWorker;
2022
use super::ExportTable;
@@ -51,7 +53,7 @@ pub struct Fs {
5153
device_state: DeviceState,
5254
config: VirtioFsConfig,
5355
shm_region: Option<VirtioShmRegion>,
54-
passthrough_cfg: passthrough::Config,
56+
fs_config: FsImplConfig,
5557
worker_thread: Option<JoinHandle<()>>,
5658
worker_stopfd: EventFd,
5759
#[cfg(target_os = "macos")]
@@ -61,7 +63,7 @@ pub struct Fs {
6163
impl Fs {
6264
pub(crate) fn with_queues(
6365
fs_id: String,
64-
shared_dir: String,
66+
fs_share: FsImplShare,
6567
queues: Vec<VirtQueue>,
6668
) -> super::Result<Fs> {
6769
let mut queue_events = Vec::new();
@@ -76,10 +78,15 @@ impl Fs {
7678
let mut config = VirtioFsConfig::default();
7779
config.tag[..tag.len()].copy_from_slice(tag.as_slice());
7880
config.num_request_queues = 1;
79-
80-
let fs_cfg = passthrough::Config {
81-
root_dir: shared_dir,
82-
..Default::default()
81+
let fs_config = match fs_share {
82+
FsImplShare::Passthrough(root_dir) => FsImplConfig::Passthrough(passthrough::Config {
83+
root_dir,
84+
..Default::default()
85+
}),
86+
FsImplShare::Overlayfs(layers) => FsImplConfig::Overlayfs(overlayfs::Config {
87+
layers,
88+
..Default::default()
89+
}),
8390
};
8491

8592
Ok(Fs {
@@ -94,20 +101,20 @@ impl Fs {
94101
device_state: DeviceState::Inactive,
95102
config,
96103
shm_region: None,
97-
passthrough_cfg: fs_cfg,
104+
fs_config,
98105
worker_thread: None,
99106
worker_stopfd: EventFd::new(EFD_NONBLOCK).map_err(FsError::EventFd)?,
100107
#[cfg(target_os = "macos")]
101108
map_sender: None,
102109
})
103110
}
104111

105-
pub fn new(fs_id: String, shared_dir: String) -> super::Result<Fs> {
112+
pub fn new(fs_id: String, fs_share: FsImplShare) -> super::Result<Fs> {
106113
let queues: Vec<VirtQueue> = defs::QUEUE_SIZES
107114
.iter()
108115
.map(|&max_size| VirtQueue::new(max_size))
109116
.collect();
110-
Self::with_queues(fs_id, shared_dir, queues)
117+
Self::with_queues(fs_id, fs_share, queues)
111118
}
112119

113120
pub fn id(&self) -> &str {
@@ -124,11 +131,20 @@ impl Fs {
124131

125132
pub fn set_export_table(&mut self, export_table: ExportTable) -> u64 {
126133
static FS_UNIQUE_ID: AtomicU64 = AtomicU64::new(0);
134+
let fsid = FS_UNIQUE_ID.fetch_add(1, Ordering::Relaxed);
127135

128-
self.passthrough_cfg.export_fsid = FS_UNIQUE_ID.fetch_add(1, Ordering::Relaxed);
129-
self.passthrough_cfg.export_table = Some(export_table);
136+
match &mut self.fs_config {
137+
FsImplConfig::Passthrough(cfg) => {
138+
cfg.export_fsid = fsid;
139+
cfg.export_table = Some(export_table);
140+
}
141+
FsImplConfig::Overlayfs(cfg) => {
142+
cfg.export_fsid = fsid;
143+
cfg.export_table = Some(export_table);
144+
}
145+
}
130146

131-
self.passthrough_cfg.export_fsid
147+
fsid
132148
}
133149

134150
#[cfg(target_os = "macos")]
@@ -215,6 +231,7 @@ impl VirtioDevice for Fs {
215231
.iter()
216232
.map(|e| e.try_clone().unwrap())
217233
.collect();
234+
218235
let worker = FsWorker::new(
219236
self.queues.clone(),
220237
queue_evts,
@@ -224,13 +241,13 @@ impl VirtioDevice for Fs {
224241
self.irq_line,
225242
mem.clone(),
226243
self.shm_region.clone(),
227-
self.passthrough_cfg.clone(),
244+
self.fs_config.clone(),
228245
self.worker_stopfd.try_clone().unwrap(),
229246
#[cfg(target_os = "macos")]
230247
self.map_sender.clone(),
231248
);
232-
self.worker_thread = Some(worker.run());
233249

250+
self.worker_thread = Some(worker.run());
234251
self.device_state = DeviceState::Activated(mem);
235252
Ok(())
236253
}

0 commit comments

Comments
 (0)