kobako 0.28.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +377 -0
- data/Cargo.lock +181 -154
- data/README.md +99 -459
- data/ROADMAP.md +7 -1
- data/SECURITY.md +1 -1
- data/crates/kobako-runtime/CHANGELOG.md +354 -0
- data/crates/kobako-runtime/Cargo.toml +38 -7
- data/crates/kobako-runtime/README.md +17 -8
- data/crates/kobako-runtime/src/dispatch.rs +9 -1
- data/crates/kobako-runtime/src/endpoint/buffer.rs +192 -0
- data/crates/kobako-runtime/src/endpoint/capture.rs +115 -0
- data/crates/kobako-runtime/src/endpoint/dispatch.rs +253 -0
- data/crates/kobako-runtime/src/endpoint/invoke.rs +194 -0
- data/crates/kobako-runtime/src/endpoint/memory_cap.rs +238 -0
- data/crates/kobako-runtime/src/endpoint.rs +166 -0
- data/crates/kobako-runtime/src/filesystem/bind/fid.rs +82 -0
- data/crates/kobako-runtime/src/filesystem/bind/lookup.rs +236 -0
- data/crates/kobako-runtime/src/filesystem/bind/walk.rs +249 -0
- data/crates/kobako-runtime/src/filesystem/bind.rs +2665 -0
- data/crates/kobako-runtime/src/filesystem/overlay/file.rs +89 -0
- data/crates/kobako-runtime/src/filesystem/overlay/inode.rs +106 -0
- data/crates/kobako-runtime/src/filesystem/overlay/path.rs +285 -0
- data/crates/kobako-runtime/src/filesystem/overlay/stack/copy_up.rs +135 -0
- data/crates/kobako-runtime/src/filesystem/overlay/stack/dir.rs +263 -0
- data/crates/kobako-runtime/src/filesystem/overlay/stack/namei.rs +135 -0
- data/crates/kobako-runtime/src/filesystem/overlay/stack/readdir.rs +57 -0
- data/crates/kobako-runtime/src/filesystem/overlay/stack.rs +301 -0
- data/crates/kobako-runtime/src/filesystem/overlay.rs +3469 -0
- data/crates/kobako-runtime/src/filesystem/path.rs +21 -0
- data/crates/kobako-runtime/src/filesystem/pipe.rs +221 -0
- data/crates/kobako-runtime/src/filesystem/rdir.rs +101 -0
- data/crates/kobako-runtime/src/filesystem/tmpfs/tmpfile.rs +32 -0
- data/crates/kobako-runtime/src/filesystem/tmpfs/whiteout.rs +85 -0
- data/crates/kobako-runtime/src/filesystem/tmpfs/xattr.rs +22 -0
- data/crates/kobako-runtime/src/filesystem/tmpfs.rs +1985 -0
- data/crates/kobako-runtime/src/filesystem/wrap.rs +224 -0
- data/crates/kobako-runtime/src/filesystem.rs +26 -0
- data/crates/kobako-runtime/src/grant.rs +20 -0
- data/crates/kobako-runtime/src/hashtable.rs +44 -0
- data/crates/kobako-runtime/src/lib.rs +16 -1
- data/crates/kobako-runtime/src/locking/seqlock.rs +66 -0
- data/crates/kobako-runtime/src/locking.rs +218 -0
- data/crates/kobako-runtime/src/mount.rs +105 -0
- data/crates/kobako-runtime/src/profile.rs +140 -4
- data/crates/kobako-runtime/src/runtime.rs +12 -0
- data/crates/kobako-runtime/src/sched.rs +210 -0
- data/crates/kobako-runtime/src/security.rs +696 -0
- data/crates/kobako-runtime/src/snapshot.rs +20 -5
- data/crates/kobako-runtime/src/vfs/attr.rs +162 -0
- data/crates/kobako-runtime/src/vfs/cred.rs +334 -0
- data/crates/kobako-runtime/src/vfs/dentry.rs +1412 -0
- data/crates/kobako-runtime/src/vfs/errno.rs +153 -0
- data/crates/kobako-runtime/src/vfs/file.rs +1915 -0
- data/crates/kobako-runtime/src/vfs/inode.rs +429 -0
- data/crates/kobako-runtime/src/vfs/kern_path.rs +217 -0
- data/crates/kobako-runtime/src/vfs/mount.rs +59 -0
- data/crates/kobako-runtime/src/vfs/namei.rs +5708 -0
- data/crates/kobako-runtime/src/vfs/openat2.rs +116 -0
- data/crates/kobako-runtime/src/vfs/path.rs +64 -0
- data/crates/kobako-runtime/src/vfs/readdir.rs +163 -0
- data/crates/kobako-runtime/src/vfs/stat.rs +157 -0
- data/crates/kobako-runtime/src/vfs/super_block.rs +122 -0
- data/crates/kobako-runtime/src/vfs/utimes.rs +289 -0
- data/crates/kobako-runtime/src/vfs.rs +60 -0
- data/crates/kobako-runtime/src/yielder.rs +11 -6
- data/crates/kobako-runtime/tests/linux_baseline/calls.rs +171 -0
- data/crates/kobako-runtime/tests/linux_baseline/concurrent.rs +276 -0
- data/crates/kobako-runtime/tests/linux_baseline/kobako.rs +323 -0
- data/crates/kobako-runtime/tests/linux_baseline/linux-baseline-expected.txt +16 -0
- data/crates/kobako-runtime/tests/linux_baseline/linux.rs +449 -0
- data/crates/kobako-runtime/tests/linux_baseline/main.rs +611 -0
- data/crates/kobako-runtime/tests/linux_baseline/permissions.rs +236 -0
- data/crates/kobako-transport/CHANGELOG.md +23 -0
- data/crates/kobako-transport/Cargo.toml +3 -3
- data/crates/kobako-transport/README.md +6 -5
- data/crates/kobako-transport/src/abi.rs +1 -1
- data/crates/kobako-transport/src/envelope/bytes.rs +33 -25
- data/crates/kobako-transport/src/envelope/call.rs +5 -5
- data/crates/kobako-transport/src/envelope/compile_reply.rs +2 -2
- data/crates/kobako-transport/src/envelope/error_record.rs +3 -3
- data/crates/kobako-transport/src/envelope/fault.rs +4 -3
- data/crates/kobako-transport/src/envelope/outcome.rs +3 -3
- data/crates/kobako-transport/src/envelope/preamble.rs +24 -24
- data/crates/kobako-transport/src/envelope/reply.rs +34 -16
- data/crates/kobako-transport/src/envelope/request.rs +19 -9
- data/crates/kobako-transport/src/envelope/run.rs +1 -1
- data/crates/kobako-transport/src/envelope/unsupported.rs +2 -2
- data/crates/kobako-transport/src/envelope.rs +2 -2
- data/crates/kobako-wasmtime/CHANGELOG.md +265 -0
- data/crates/kobako-wasmtime/Cargo.toml +25 -19
- data/crates/kobako-wasmtime/README.md +13 -7
- data/crates/kobako-wasmtime/src/abi.rs +75 -49
- data/crates/kobako-wasmtime/src/ambient.rs +64 -6
- data/crates/kobako-wasmtime/src/cache.rs +188 -77
- data/crates/kobako-wasmtime/src/config.rs +77 -5
- data/crates/kobako-wasmtime/src/descriptors.rs +200 -0
- data/crates/kobako-wasmtime/src/driver.rs +70 -135
- data/crates/kobako-wasmtime/src/exports.rs +5 -16
- data/crates/kobako-wasmtime/src/guest.rs +38 -0
- data/crates/kobako-wasmtime/src/imports.rs +52 -0
- data/crates/kobako-wasmtime/src/instance_pre.rs +18 -46
- data/crates/kobako-wasmtime/src/invocation.rs +43 -74
- data/crates/kobako-wasmtime/src/lib.rs +5 -4
- data/crates/kobako-wasmtime/src/limiter.rs +6 -230
- data/crates/kobako-wasmtime/src/preview1/differential/mount.rs +632 -0
- data/crates/kobako-wasmtime/src/preview1/differential.rs +486 -0
- data/crates/kobako-wasmtime/src/preview1/errno.rs +135 -0
- data/crates/kobako-wasmtime/src/preview1/fd.rs +1420 -0
- data/crates/kobako-wasmtime/src/preview1/memory.rs +172 -0
- data/crates/kobako-wasmtime/src/preview1/mount_view/wrap.rs +211 -0
- data/crates/kobako-wasmtime/src/preview1/mount_view.rs +3766 -0
- data/crates/kobako-wasmtime/src/preview1/path.rs +302 -0
- data/crates/kobako-wasmtime/src/preview1/poll.rs +381 -0
- data/crates/kobako-wasmtime/src/preview1/sock.rs +13 -0
- data/crates/kobako-wasmtime/src/preview1/testsuite-expected.txt +6 -0
- data/crates/kobako-wasmtime/src/preview1/testsuite.rs +157 -0
- data/crates/kobako-wasmtime/src/preview1.rs +512 -0
- data/crates/kobako-wasmtime/src/trap.rs +45 -25
- data/crates/kobako-wasmtime/src/wasi.rs +333 -0
- data/crates/kobako-wasmtime/tests/integration/compile_posture.rs +43 -0
- data/crates/kobako-wasmtime/tests/integration/guest_file.rs +1085 -0
- data/crates/kobako-wasmtime/tests/integration/main.rs +29 -0
- data/crates/kobako-wasmtime/tests/{preamble_flags.rs → integration/preamble_flags.rs} +4 -3
- data/crates/kobako-wasmtime/tests/{snippet_compile.rs → integration/snippet_compile.rs} +5 -4
- data/crates/kobako-wasmtime/tests/{support → integration/support}/mod.rs +9 -13
- data/crates/kobako-wasmtime/tests/integration/unanswered_call.rs +86 -0
- data/crates/kobako-wasmtime/tests/{unsupported_call.rs → integration/unsupported_call.rs} +2 -1
- data/crates/kobako-wasmtime/witx/typenames.witx +750 -0
- data/crates/kobako-wasmtime/witx/wasi_snapshot_preview1.witx +441 -0
- data/data/kobako.wasm +0 -0
- data/ext/kobako/Cargo.toml +4 -2
- data/ext/kobako/src/runtime/bridge.rs +154 -81
- data/ext/kobako/src/runtime/errors.rs +1 -1
- data/ext/kobako/src/runtime/escape.rs +67 -0
- data/ext/kobako/src/runtime/filesystem/grants.rs +107 -0
- data/ext/kobako/src/runtime/filesystem/ruby.rs +708 -0
- data/ext/kobako/src/runtime/filesystem.rs +208 -0
- data/ext/kobako/src/runtime/gvl.rs +49 -8
- data/ext/kobako/src/runtime/pinned_value.rs +31 -0
- data/ext/kobako/src/runtime/snapshot.rs +127 -0
- data/ext/kobako/src/runtime.rs +125 -199
- data/lib/kobako/catalog/extensions.rb +5 -5
- data/lib/kobako/catalog/flags.rb +2 -14
- data/lib/kobako/catalog/grants.rb +30 -0
- data/lib/kobako/catalog/handles.rb +6 -6
- data/lib/kobako/catalog/mount.rb +19 -0
- data/lib/kobako/catalog/services.rb +13 -2
- data/lib/kobako/catalog/snippets.rb +11 -15
- data/lib/kobako/catalog.rb +11 -0
- data/lib/kobako/codec/decoder.rb +10 -9
- data/lib/kobako/codec/ext_types.rb +4 -6
- data/lib/kobako/codec/handle_walk.rb +4 -6
- data/lib/kobako/codec/nesting.rb +7 -7
- data/lib/kobako/codec/state.rb +19 -3
- data/lib/kobako/codec/utils.rb +1 -1
- data/lib/kobako/codec/value_budget.rb +86 -0
- data/lib/kobako/codec.rb +7 -0
- data/lib/kobako/context.rb +40 -13
- data/lib/kobako/errors.rb +15 -14
- data/lib/kobako/filesystem.rb +69 -0
- data/lib/kobako/payload/arguments.rb +2 -2
- data/lib/kobako/pool.rb +6 -6
- data/lib/kobako/sandbox.rb +55 -27
- data/lib/kobako/sandbox_options.rb +39 -13
- data/lib/kobako/snippet/{binary.rb → bytecode.rb} +2 -2
- data/lib/kobako/snippet/source.rb +1 -1
- data/lib/kobako/snippet.rb +1 -1
- data/lib/kobako/transport/block_failure.rb +35 -0
- data/lib/kobako/transport/dispatcher.rb +33 -29
- data/lib/kobako/transport/exposure.rb +7 -9
- data/lib/kobako/transport/reflection.rb +79 -23
- data/lib/kobako/transport/run.rb +5 -5
- data/lib/kobako/transport/yielder.rb +9 -31
- data/lib/kobako/transport.rb +1 -0
- data/lib/kobako/version.rb +1 -1
- data/lib/kobako.rb +35 -0
- data/release-please-config.json +1 -0
- data/sig/kobako/catalog/extensions.rbs +3 -3
- data/sig/kobako/catalog/flags.rbs +0 -4
- data/sig/kobako/catalog/grants.rbs +13 -0
- data/sig/kobako/catalog/handles.rbs +3 -3
- data/sig/kobako/catalog/mount.rbs +24 -0
- data/sig/kobako/catalog/services.rbs +5 -1
- data/sig/kobako/catalog/snippets.rbs +4 -4
- data/sig/kobako/catalog.rbs +1 -0
- data/sig/kobako/codec/decoder.rbs +1 -1
- data/sig/kobako/codec/handle_walk.rbs +1 -1
- data/sig/kobako/codec/nesting.rbs +2 -2
- data/sig/kobako/codec/state.rbs +7 -1
- data/sig/kobako/codec/utils.rbs +1 -1
- data/sig/kobako/codec/value_budget.rbs +23 -0
- data/sig/kobako/codec.rbs +3 -2
- data/sig/kobako/context.rbs +14 -6
- data/sig/kobako/errors.rbs +4 -4
- data/sig/kobako/filesystem.rbs +93 -0
- data/sig/kobako/guest_yielder.rbs +9 -0
- data/sig/kobako/payload/arguments.rbs +1 -1
- data/sig/kobako/pool.rbs +3 -3
- data/sig/kobako/runtime.rbs +21 -49
- data/sig/kobako/sandbox.rbs +9 -5
- data/sig/kobako/sandbox_options.rbs +25 -3
- data/sig/kobako/snapshot.rbs +20 -0
- data/sig/kobako/snippet/bytecode.rbs +12 -0
- data/sig/kobako/transport/block_failure.rbs +13 -0
- data/sig/kobako/transport/dispatcher.rbs +4 -4
- data/sig/kobako/transport/exposure.rbs +2 -2
- data/sig/kobako/transport/reflection.rbs +14 -1
- data/sig/kobako/transport/run.rbs +3 -3
- data/sig/kobako/transport/yielder.rbs +3 -7
- data/sig/kobako/transport.rbs +3 -3
- metadata +116 -15
- data/crates/kobako-wasmtime/src/capture.rs +0 -96
- data/crates/kobako-wasmtime/src/dispatch.rs +0 -107
- data/crates/kobako-wasmtime/src/guest_mem.rs +0 -265
- data/crates/kobako-wasmtime/src/io.rs +0 -286
- data/sig/kobako/snippet/binary.rbs +0 -12
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
//! What an open asks for, as Linux's `openat2` takes an `open_how`.
|
|
2
|
+
|
|
3
|
+
use super::inode::Mask;
|
|
4
|
+
use super::FilesystemError;
|
|
5
|
+
|
|
6
|
+
/// How to open a path, as Linux's `struct open_how` carries `openat2`'s
|
|
7
|
+
/// flags.
|
|
8
|
+
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
|
9
|
+
#[non_exhaustive]
|
|
10
|
+
pub struct OpenHow {
|
|
11
|
+
pub read: bool,
|
|
12
|
+
pub write: bool,
|
|
13
|
+
/// Create a file where nothing stands, as `O_CREAT` does.
|
|
14
|
+
pub create: bool,
|
|
15
|
+
/// Refuse what already stands there, as `O_EXCL` does.
|
|
16
|
+
pub exclusive: bool,
|
|
17
|
+
/// Empty the file once it is open, as `O_TRUNC` does.
|
|
18
|
+
pub truncate: bool,
|
|
19
|
+
/// Refuse anything but a directory, as `O_DIRECTORY` does.
|
|
20
|
+
pub directory: bool,
|
|
21
|
+
/// Follow a link at the end of the path.
|
|
22
|
+
pub follow: bool,
|
|
23
|
+
/// Land each write at the end, as `O_APPEND` does.
|
|
24
|
+
pub append: bool,
|
|
25
|
+
/// Ask not to wait, as `O_NONBLOCK` does.
|
|
26
|
+
pub nonblock: bool,
|
|
27
|
+
/// Make what each write needs read back durable before it answers, as
|
|
28
|
+
/// `O_DSYNC` does.
|
|
29
|
+
pub dsync: bool,
|
|
30
|
+
/// Make everything each write changed durable before it answers, as
|
|
31
|
+
/// `O_SYNC` does.
|
|
32
|
+
pub sync: bool,
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// What an open was found to ask, as Linux's `struct open_flags` holds what
|
|
36
|
+
/// `build_open_flags` made of an `open_how`, which alone makes one, so what
|
|
37
|
+
/// it asks of the entry always matches the flags. A Filesystem never reads
|
|
38
|
+
/// it: `->atomic_open` and `->open` take the `OpenHow` it was made of, as
|
|
39
|
+
/// Linux hands them `open_flag` and `f_flags`.
|
|
40
|
+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
41
|
+
pub struct OpenFlags {
|
|
42
|
+
open_flag: OpenHow,
|
|
43
|
+
acc_mode: Mask,
|
|
44
|
+
lookup_follow: bool,
|
|
45
|
+
lookup_directory: bool,
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
impl OpenFlags {
|
|
49
|
+
/// The flags the open was made with, as `open_flag` keeps them.
|
|
50
|
+
pub(crate) fn open_flag(&self) -> &OpenHow {
|
|
51
|
+
&self.open_flag
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/// What the open asks of what it opens, as `acc_mode` carries it;
|
|
55
|
+
/// `may_open` adds `MAY_OPEN` when it asks.
|
|
56
|
+
pub(crate) fn acc_mode(&self) -> Mask {
|
|
57
|
+
self.acc_mode
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/// Whether the walk follows a link at the end, as `LOOKUP_FOLLOW` in
|
|
61
|
+
/// `lookup_flags` asks.
|
|
62
|
+
pub(crate) fn lookup_follow(&self) -> bool {
|
|
63
|
+
self.lookup_follow
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/// Whether the walk must end on a directory, as `LOOKUP_DIRECTORY` in
|
|
67
|
+
/// `lookup_flags` asks.
|
|
68
|
+
pub(crate) fn lookup_directory(&self) -> bool {
|
|
69
|
+
self.lookup_directory
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/// Refuse flags no open can mean before any path is looked at, as Linux's
|
|
74
|
+
/// `build_open_flags` refuses `O_DIRECTORY` with `O_CREAT`, and make what the
|
|
75
|
+
/// open asks: `O_CREAT` with `O_EXCL` never follows a link at the end, and
|
|
76
|
+
/// `O_SYNC` carries `O_DSYNC`, as Linux implements it as both. An open asking
|
|
77
|
+
/// neither to read nor to write stands only for its path, as `O_PATH` keeps
|
|
78
|
+
/// only `O_PATH_FLAGS` and asks nothing of the entry. An ABI asks it once,
|
|
79
|
+
/// before it reserves a descriptor, and hands what it made to `do_file_open`,
|
|
80
|
+
/// as `do_sys_openat2` does.
|
|
81
|
+
pub fn build_open_flags(how: &OpenHow) -> Result<OpenFlags, FilesystemError> {
|
|
82
|
+
if !how.read && !how.write {
|
|
83
|
+
return Ok(OpenFlags {
|
|
84
|
+
open_flag: OpenHow {
|
|
85
|
+
directory: how.directory,
|
|
86
|
+
follow: how.follow,
|
|
87
|
+
..OpenHow::default()
|
|
88
|
+
},
|
|
89
|
+
acc_mode: Mask::NONE,
|
|
90
|
+
lookup_follow: how.follow,
|
|
91
|
+
lookup_directory: how.directory,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
if how.directory && how.create {
|
|
95
|
+
return Err(FilesystemError::InvalidInput);
|
|
96
|
+
}
|
|
97
|
+
let mut acc_mode = Mask::NONE;
|
|
98
|
+
if how.read {
|
|
99
|
+
acc_mode = acc_mode | Mask::READ;
|
|
100
|
+
}
|
|
101
|
+
if how.write || how.truncate {
|
|
102
|
+
acc_mode = acc_mode | Mask::WRITE;
|
|
103
|
+
}
|
|
104
|
+
if how.append {
|
|
105
|
+
acc_mode = acc_mode | Mask::APPEND;
|
|
106
|
+
}
|
|
107
|
+
Ok(OpenFlags {
|
|
108
|
+
open_flag: OpenHow {
|
|
109
|
+
dsync: how.dsync || how.sync,
|
|
110
|
+
..*how
|
|
111
|
+
},
|
|
112
|
+
acc_mode,
|
|
113
|
+
lookup_follow: how.follow && !(how.create && how.exclusive),
|
|
114
|
+
lookup_directory: how.directory,
|
|
115
|
+
})
|
|
116
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
//! A name beneath a mount, as Linux's `struct path` pairs a mount with a
|
|
2
|
+
//! dentry.
|
|
3
|
+
|
|
4
|
+
use std::sync::Arc;
|
|
5
|
+
|
|
6
|
+
use super::dentry::Dentry;
|
|
7
|
+
use super::mount::VfsMount;
|
|
8
|
+
use super::FilesystemError;
|
|
9
|
+
|
|
10
|
+
/// Where a walk starts, found once the call has taken its name, as Linux's
|
|
11
|
+
/// `path_init` takes the directory a descriptor names only after the name. A
|
|
12
|
+
/// caller holding a table of descriptors hands how to find it, so a call with
|
|
13
|
+
/// two names answers for the first before it looks at the second's start.
|
|
14
|
+
pub trait Start {
|
|
15
|
+
fn path_init(&self) -> Result<Path, FilesystemError>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
impl Start for Path {
|
|
19
|
+
fn path_init(&self) -> Result<Path, FilesystemError> {
|
|
20
|
+
Ok(self.clone())
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
impl<F: Fn() -> Result<Path, FilesystemError>> Start for F {
|
|
25
|
+
fn path_init(&self) -> Result<Path, FilesystemError> {
|
|
26
|
+
self()
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/// A name beneath a mount, as an open file holds its `f_path`: the mount's
|
|
31
|
+
/// root, or an entry opened beneath it. A walk starts only from a directory.
|
|
32
|
+
#[derive(Clone)]
|
|
33
|
+
pub struct Path {
|
|
34
|
+
mnt: Arc<VfsMount>,
|
|
35
|
+
/// The entry, wherever it moved, and whether it was removed.
|
|
36
|
+
dentry: Arc<Dentry>,
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
impl Path {
|
|
40
|
+
/// The root of `mnt`.
|
|
41
|
+
pub fn root(mnt: &Arc<VfsMount>) -> Self {
|
|
42
|
+
Self {
|
|
43
|
+
dentry: mnt.mnt_root().clone(),
|
|
44
|
+
mnt: mnt.clone(),
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/// This Path standing at `dentry`.
|
|
49
|
+
pub(crate) fn with_dentry(&self, dentry: Arc<Dentry>) -> Self {
|
|
50
|
+
Self {
|
|
51
|
+
mnt: self.mnt.clone(),
|
|
52
|
+
dentry,
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// What the entry is mounted on.
|
|
57
|
+
pub fn mnt(&self) -> &Arc<VfsMount> {
|
|
58
|
+
&self.mnt
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
pub(crate) fn dentry(&self) -> &Arc<Dentry> {
|
|
62
|
+
&self.dentry
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
//! Listing a directory, as Linux's `fs/readdir.c` hands each entry a
|
|
2
|
+
//! Filesystem emits to the actor a listing names, with the helpers `libfs.c`
|
|
3
|
+
//! gives every Filesystem.
|
|
4
|
+
|
|
5
|
+
use std::sync::Arc;
|
|
6
|
+
|
|
7
|
+
use super::cred::Cred;
|
|
8
|
+
use super::dentry::Dentry;
|
|
9
|
+
use super::inode::Identity;
|
|
10
|
+
use super::{FileType, FilesystemError, Kstat, PATH_MAX};
|
|
11
|
+
|
|
12
|
+
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
13
|
+
#[non_exhaustive]
|
|
14
|
+
pub struct DirEntry {
|
|
15
|
+
pub name: String,
|
|
16
|
+
pub file_type: FileType,
|
|
17
|
+
/// The device and inode numbers naming the entry, as `Kstat` reports
|
|
18
|
+
/// them and `dir_emit` hands `d_ino`. An `ino` of zero reports none.
|
|
19
|
+
pub dev: u64,
|
|
20
|
+
pub ino: u64,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
impl DirEntry {
|
|
24
|
+
/// The entry `name` in its directory, naming a `file_type`.
|
|
25
|
+
pub fn new(name: impl Into<String>, file_type: FileType) -> Self {
|
|
26
|
+
Self {
|
|
27
|
+
name: name.into(),
|
|
28
|
+
file_type,
|
|
29
|
+
dev: 0,
|
|
30
|
+
ino: 0,
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// This entry naming `dev` and `ino`, as a stat of it reports them.
|
|
35
|
+
pub fn with_identity(self, dev: u64, ino: u64) -> Self {
|
|
36
|
+
Self { dev, ino, ..self }
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/// One entry a listing hands its actor, as `dir_emit` does.
|
|
41
|
+
#[non_exhaustive]
|
|
42
|
+
pub struct DirEmit<'a> {
|
|
43
|
+
pub name: &'a str,
|
|
44
|
+
pub file_type: FileType,
|
|
45
|
+
/// What the entry is, `None` where its Filesystem names no inode number.
|
|
46
|
+
pub identity: Option<Identity>,
|
|
47
|
+
/// Where the entry stands, as `dir_emit` hands `ctx->pos`, so a listing
|
|
48
|
+
/// from there reaches it first.
|
|
49
|
+
pub offset: u64,
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
impl DirEmit<'_> {
|
|
53
|
+
/// This entry as a list keeps one.
|
|
54
|
+
pub fn to_dir_entry(&self) -> DirEntry {
|
|
55
|
+
let entry = DirEntry::new(self.name, self.file_type);
|
|
56
|
+
match self.identity {
|
|
57
|
+
Some(identity) => {
|
|
58
|
+
let named = identity.onto(Kstat::new(self.file_type, 0));
|
|
59
|
+
entry.with_identity(named.dev, named.ino)
|
|
60
|
+
}
|
|
61
|
+
None => entry,
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/// A listing under way, as Linux's `struct dir_context`: where it stands, who
|
|
67
|
+
/// takes each entry, answering whether to go on, and who the listing is for.
|
|
68
|
+
pub struct DirContext<'a> {
|
|
69
|
+
pub(super) pos: u64,
|
|
70
|
+
actor: &'a mut dyn FnMut(&DirEmit<'_>) -> bool,
|
|
71
|
+
pub(super) cred: Arc<Cred>,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
impl<'a> DirContext<'a> {
|
|
75
|
+
/// A listing from `pos`, each entry going to `actor`. A listing of an open
|
|
76
|
+
/// directory starts where that directory stands instead.
|
|
77
|
+
pub fn new(pos: u64, actor: &'a mut dyn FnMut(&DirEmit<'_>) -> bool) -> Self {
|
|
78
|
+
Self {
|
|
79
|
+
pos,
|
|
80
|
+
actor,
|
|
81
|
+
cred: Cred::new(Vec::new()),
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/// Where the listing stands, as `ctx->pos`.
|
|
86
|
+
pub fn pos(&self) -> u64 {
|
|
87
|
+
self.pos
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/// Who the listing is for, as `file->f_cred`.
|
|
91
|
+
pub fn cred(&self) -> &Arc<Cred> {
|
|
92
|
+
&self.cred
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/// Move the listing to `pos`, as a Filesystem sets `ctx->pos` to where its
|
|
96
|
+
/// next entry stands, or past its last.
|
|
97
|
+
pub fn set_pos(&mut self, pos: u64) {
|
|
98
|
+
self.pos = pos;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/// Hand the actor `entry`, standing where the listing stands, answering
|
|
102
|
+
/// whether to go on, as `dir_emit` does. The Filesystem moves the listing
|
|
103
|
+
/// past what the actor took. The actor judges the name, as `filldir64` asks
|
|
104
|
+
/// `verify_dirent_name`.
|
|
105
|
+
pub fn dir_emit(&mut self, entry: &DirEntry) -> bool {
|
|
106
|
+
let identity = Identity::from_numbers(entry.dev, entry.ino);
|
|
107
|
+
self.emit(&entry.name, entry.file_type, identity)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
fn emit(&mut self, name: &str, file_type: FileType, identity: Option<Identity>) -> bool {
|
|
111
|
+
(self.actor)(&DirEmit {
|
|
112
|
+
name,
|
|
113
|
+
file_type,
|
|
114
|
+
identity,
|
|
115
|
+
offset: self.pos,
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/// The identity the inode `dentry` holds was looked up with, as Linux reads
|
|
121
|
+
/// `i_ino`.
|
|
122
|
+
fn i_ino(dentry: &Dentry) -> Option<Identity> {
|
|
123
|
+
dentry.inode().and_then(|inode| inode.identity())
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/// Hand `ctx` the `.` and `..` it has yet to reach, as Linux's `dir_emit_dots`
|
|
127
|
+
/// does with the inode numbers the dentries hold, `..` naming what stands above
|
|
128
|
+
/// `dentry`, or itself at the root. It asks no Filesystem and answers whether
|
|
129
|
+
/// to go on.
|
|
130
|
+
pub fn dir_emit_dots(dentry: &Dentry, ctx: &mut DirContext<'_>) -> bool {
|
|
131
|
+
if ctx.pos == 0 {
|
|
132
|
+
if !ctx.emit(".", FileType::Dir, i_ino(dentry)) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
ctx.pos = 1;
|
|
136
|
+
}
|
|
137
|
+
if ctx.pos == 1 {
|
|
138
|
+
if !ctx.emit("..", FileType::Dir, i_ino(&dentry.parent())) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
ctx.pos = 2;
|
|
142
|
+
}
|
|
143
|
+
true
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/// What a directory's read answers, as Linux's `generic_read_dir` is every
|
|
147
|
+
/// directory's `f_op->read`.
|
|
148
|
+
pub fn generic_read_dir() -> Result<usize, FilesystemError> {
|
|
149
|
+
Err(FilesystemError::IsADirectory)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/// Refuse a name no directory can hold, as Linux's `verify_dirent_name` refuses
|
|
153
|
+
/// what a Filesystem hands it, so whoever walks a listing is never handed a
|
|
154
|
+
/// path where it was promised one name. A Filesystem that asks about each name
|
|
155
|
+
/// before it lists them asks this first.
|
|
156
|
+
pub fn verify_dirent_name(name: &str) -> Result<(), FilesystemError> {
|
|
157
|
+
if name.is_empty() || name.len() >= PATH_MAX || name.contains('/') {
|
|
158
|
+
return Err(FilesystemError::Other(
|
|
159
|
+
"a Filesystem listed a name no directory can hold".to_string(),
|
|
160
|
+
));
|
|
161
|
+
}
|
|
162
|
+
Ok(())
|
|
163
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
//! Looking at what stands at a path, as Linux's `fstatat` and
|
|
2
|
+
//! `readlinkat` do.
|
|
3
|
+
|
|
4
|
+
use std::sync::atomic::{AtomicU64, Ordering};
|
|
5
|
+
use std::sync::Arc;
|
|
6
|
+
use std::time::SystemTime;
|
|
7
|
+
|
|
8
|
+
use super::cred::Cred;
|
|
9
|
+
use super::namei::{filename_lookup, retry_estale};
|
|
10
|
+
use super::path::Start;
|
|
11
|
+
use super::FilesystemError;
|
|
12
|
+
|
|
13
|
+
/// What a path names, as Linux's file types `FT_*` name each kind.
|
|
14
|
+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
15
|
+
#[non_exhaustive]
|
|
16
|
+
pub enum FileType {
|
|
17
|
+
RegFile,
|
|
18
|
+
Dir,
|
|
19
|
+
/// A link, as only a stat that does not follow it and a listing report one.
|
|
20
|
+
Symlink,
|
|
21
|
+
/// A FIFO a host holds, or a pipe of the runtime's own.
|
|
22
|
+
Fifo,
|
|
23
|
+
Sock,
|
|
24
|
+
Blkdev,
|
|
25
|
+
/// A character device a host holds, or a whiteout, as Linux makes one.
|
|
26
|
+
Chrdev,
|
|
27
|
+
/// What a platform names no kind for.
|
|
28
|
+
Unknown,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// Whether `kind` is a device, a FIFO, or a socket, as Linux's `special_file`
|
|
32
|
+
/// names what an open for writing takes no write access to its mount for.
|
|
33
|
+
pub(crate) fn special_file(kind: FileType) -> bool {
|
|
34
|
+
matches!(
|
|
35
|
+
kind,
|
|
36
|
+
FileType::Chrdev | FileType::Blkdev | FileType::Fifo | FileType::Sock
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/// What a Filesystem reports of an entry, as Linux's `struct kstat`.
|
|
41
|
+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
42
|
+
#[non_exhaustive]
|
|
43
|
+
pub struct Kstat {
|
|
44
|
+
/// What the entry is, as the `S_IFMT` bits of `mode` say; the runtime
|
|
45
|
+
/// keeps no permission bits, so the kind stands alone.
|
|
46
|
+
pub file_type: FileType,
|
|
47
|
+
/// The length in bytes, of a directory what its Filesystem reports.
|
|
48
|
+
pub size: u64,
|
|
49
|
+
/// The device and inode numbers naming what the path holds, as
|
|
50
|
+
/// `st_dev` and `st_ino` do. An `ino` of zero reports none, so such a
|
|
51
|
+
/// directory cannot be told from one made in its place.
|
|
52
|
+
pub dev: u64,
|
|
53
|
+
pub ino: u64,
|
|
54
|
+
/// How many names the entry has, as `st_nlink` counts; one where the
|
|
55
|
+
/// Filesystem keeps no count, as Linux starts every inode.
|
|
56
|
+
pub nlink: u64,
|
|
57
|
+
/// When the entry was last read, written, or changed, as `st_atime`,
|
|
58
|
+
/// `st_mtime`, and `st_ctime` record; `None` where the Filesystem keeps
|
|
59
|
+
/// no such time.
|
|
60
|
+
pub atime: Option<SystemTime>,
|
|
61
|
+
pub mtime: Option<SystemTime>,
|
|
62
|
+
pub ctime: Option<SystemTime>,
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
impl Kstat {
|
|
66
|
+
/// What an entry is and its size, reporting no identity or time.
|
|
67
|
+
pub fn new(file_type: FileType, size: u64) -> Self {
|
|
68
|
+
Self {
|
|
69
|
+
file_type,
|
|
70
|
+
size,
|
|
71
|
+
dev: 0,
|
|
72
|
+
ino: 0,
|
|
73
|
+
nlink: 1,
|
|
74
|
+
atime: None,
|
|
75
|
+
mtime: None,
|
|
76
|
+
ctime: None,
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/// The same, naming `dev` and `ino` as what the path holds.
|
|
81
|
+
pub fn with_identity(self, dev: u64, ino: u64) -> Self {
|
|
82
|
+
Self { dev, ino, ..self }
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/// The same, counting `nlink` names.
|
|
86
|
+
pub fn with_nlink(self, nlink: u64) -> Self {
|
|
87
|
+
Self { nlink, ..self }
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/// The same, recording when the entry was last read, written, and changed.
|
|
91
|
+
pub fn with_times(
|
|
92
|
+
self,
|
|
93
|
+
atime: Option<SystemTime>,
|
|
94
|
+
mtime: Option<SystemTime>,
|
|
95
|
+
ctime: Option<SystemTime>,
|
|
96
|
+
) -> Self {
|
|
97
|
+
Self {
|
|
98
|
+
atime,
|
|
99
|
+
mtime,
|
|
100
|
+
ctime,
|
|
101
|
+
..self
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/// A device number for a Filesystem with none of its own, as each
|
|
106
|
+
/// tmpfs mount takes one: no earlier call returned it, and its top bit,
|
|
107
|
+
/// which no host's `st_dev` sets, keeps it apart from a host's.
|
|
108
|
+
pub fn unique_device() -> u64 {
|
|
109
|
+
static NEXT: AtomicU64 = AtomicU64::new(1);
|
|
110
|
+
(1 << 63) | NEXT.fetch_add(1, Ordering::Relaxed)
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/// What `path` beneath `start` names, as Linux's `vfs_fstatat` answers: a
|
|
115
|
+
/// link at its end followed where `follow` asks, and otherwise reported as
|
|
116
|
+
/// itself unless a trailing `/` asks for the directory it leads to, as
|
|
117
|
+
/// `AT_SYMLINK_NOFOLLOW` leaves one.
|
|
118
|
+
pub fn vfs_fstatat(
|
|
119
|
+
cred: &Arc<Cred>,
|
|
120
|
+
start: &impl Start,
|
|
121
|
+
path: &str,
|
|
122
|
+
follow: bool,
|
|
123
|
+
) -> Result<Kstat, FilesystemError> {
|
|
124
|
+
retry_estale(
|
|
125
|
+
|| filename_lookup(cred, start, path, follow),
|
|
126
|
+
|nd| nd.getattr(),
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/// Where the link at `path` beneath `start` points, as Linux's `do_readlinkat`
|
|
131
|
+
/// asks the security hook only of a link, and answers anything else invalid.
|
|
132
|
+
/// It takes the name with `LOOKUP_EMPTY`, so an empty one names `start`
|
|
133
|
+
/// itself, and anything but a link there is not found. The caller's buffer is
|
|
134
|
+
/// the ABI's to judge, as only its syscall has one.
|
|
135
|
+
pub fn do_readlinkat(
|
|
136
|
+
cred: &Arc<Cred>,
|
|
137
|
+
start: &impl Start,
|
|
138
|
+
path: &str,
|
|
139
|
+
) -> Result<String, FilesystemError> {
|
|
140
|
+
let walk = || match path.is_empty() {
|
|
141
|
+
true => Ok((
|
|
142
|
+
start.path_init()?.dentry().clone(),
|
|
143
|
+
FilesystemError::NotFound,
|
|
144
|
+
)),
|
|
145
|
+
false => Ok((
|
|
146
|
+
filename_lookup(cred, start, path, false)?.path()?,
|
|
147
|
+
FilesystemError::InvalidInput,
|
|
148
|
+
)),
|
|
149
|
+
};
|
|
150
|
+
retry_estale(walk, |(target, refusal)| {
|
|
151
|
+
if target.kind()? != FileType::Symlink {
|
|
152
|
+
return Err(refusal);
|
|
153
|
+
}
|
|
154
|
+
cred.security_inode_readlink(&target)?;
|
|
155
|
+
target.get_link()
|
|
156
|
+
})
|
|
157
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
//! One mounted instance of a Filesystem, as Linux's `super_block` is.
|
|
2
|
+
|
|
3
|
+
use std::sync::Arc;
|
|
4
|
+
|
|
5
|
+
use super::dentry::{Dentries, Dentry, DentryOperations};
|
|
6
|
+
use super::errno::FilesystemError;
|
|
7
|
+
use super::inode::Inode;
|
|
8
|
+
use crate::locking::RwSemaphore;
|
|
9
|
+
|
|
10
|
+
/// What makes an instance of a Filesystem, as Linux's `file_system_type`.
|
|
11
|
+
/// Every lock beneath it waits through the one `Blocking` its process
|
|
12
|
+
/// registers, so a Filesystem says nothing about waiting.
|
|
13
|
+
pub trait FileSystemType: Send + Sync + 'static {
|
|
14
|
+
/// Set up the instance, asked once before any walk, as a driver's
|
|
15
|
+
/// `fill_super` fills in its `super_block`. It makes the root through
|
|
16
|
+
/// `d_make_root` after any `set_default_d_op`, so the root answers through
|
|
17
|
+
/// it too. It also says what every dentry answers through, for a
|
|
18
|
+
/// Filesystem changed outside the runtime, whether nothing beneath it
|
|
19
|
+
/// changes, and whether a name goes once unused. An instance that cannot
|
|
20
|
+
/// stand answers why, and none is made.
|
|
21
|
+
fn fill_super(self: Arc<Self>, sb: &mut SuperBlock) -> Result<(), FilesystemError>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/// One Filesystem instance, with the directories of it a walk reaches. Every
|
|
25
|
+
/// mount of the same instance shares them, as a bind mount shares its super
|
|
26
|
+
/// block, so a directory moved or removed beneath one is moved or removed
|
|
27
|
+
/// beneath every other.
|
|
28
|
+
pub struct SuperBlock {
|
|
29
|
+
/// The root dentry `fill_super` made, as `s_root`.
|
|
30
|
+
root: Option<Arc<Dentry>>,
|
|
31
|
+
dentries: Dentries,
|
|
32
|
+
/// Held by a move between two directories, as Linux's
|
|
33
|
+
/// `s_vfs_rename_mutex`, so no other such move changes which of them
|
|
34
|
+
/// stands beneath the other.
|
|
35
|
+
rename_mutex: Arc<RwSemaphore>,
|
|
36
|
+
/// Whether nothing beneath it changes, however it is mounted, as
|
|
37
|
+
/// `SB_RDONLY` in `s_flags`.
|
|
38
|
+
rdonly: bool,
|
|
39
|
+
/// Whether no dentry stays once nothing holds it, as `DCACHE_DONTCACHE` in
|
|
40
|
+
/// `s_d_flags`.
|
|
41
|
+
dontcache: bool,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
impl SuperBlock {
|
|
45
|
+
/// The instance `fs` makes, set up as its `fill_super` asks, or why it cannot
|
|
46
|
+
/// stand. One whose `fill_super` made no root answers EINVAL.
|
|
47
|
+
pub fn new(fs: Arc<dyn FileSystemType>) -> Result<Arc<Self>, FilesystemError> {
|
|
48
|
+
let mut sb = Self {
|
|
49
|
+
root: None,
|
|
50
|
+
dentries: Dentries::new(None),
|
|
51
|
+
rename_mutex: Arc::default(),
|
|
52
|
+
rdonly: false,
|
|
53
|
+
dontcache: false,
|
|
54
|
+
};
|
|
55
|
+
fs.fill_super(&mut sb)?;
|
|
56
|
+
sb.root.as_ref().ok_or(FilesystemError::InvalidInput)?;
|
|
57
|
+
Ok(Arc::new(sb))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/// Make a root dentry for `root` and set it as this instance's root, as a
|
|
61
|
+
/// driver's `fill_super` sets `s_root` to what `d_make_root` makes.
|
|
62
|
+
pub fn d_make_root(&mut self, root: Arc<Inode>) {
|
|
63
|
+
self.root = Some(self.dentries.make_root(root));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/// This instance's root dentry, which `new` refuses an instance without.
|
|
67
|
+
pub(crate) fn s_root(&self) -> Arc<Dentry> {
|
|
68
|
+
self.root
|
|
69
|
+
.clone()
|
|
70
|
+
.expect("SuperBlock::new refuses an instance with no root")
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/// Have every dentry of this instance made from now on answer through
|
|
74
|
+
/// `ops`, as a driver's `fill_super` calls `set_default_d_op` before
|
|
75
|
+
/// `d_make_root`. Without it the runtime trusts every name it holds, as
|
|
76
|
+
/// nothing changes the Filesystem outside the runtime.
|
|
77
|
+
pub fn set_default_d_op(&mut self, ops: Arc<dyn DentryOperations>) {
|
|
78
|
+
self.dentries.set_ops(ops);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// What every dentry of this instance answers through, as `s_d_op`.
|
|
82
|
+
pub fn d_op(&self) -> Option<&Arc<dyn DentryOperations>> {
|
|
83
|
+
self.dentries.ops()
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/// Refuse every change beneath this instance, as a driver's `fill_super`
|
|
87
|
+
/// sets `SB_RDONLY`. Without it the instance refuses no change, though a
|
|
88
|
+
/// read-only mount of it still does.
|
|
89
|
+
pub fn set_rdonly(&mut self) {
|
|
90
|
+
self.rdonly = true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/// Whether nothing beneath this instance changes, as `sb_rdonly`.
|
|
94
|
+
pub fn rdonly(&self) -> bool {
|
|
95
|
+
self.rdonly
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/// Keep no dentry of this instance once nothing holds it, as a driver with
|
|
99
|
+
/// nothing to gain from a cache sets `DCACHE_DONTCACHE`, as tmpfs does.
|
|
100
|
+
/// Without it a name stays for the next walk, one naming nothing too.
|
|
101
|
+
pub fn set_dontcache(&mut self) {
|
|
102
|
+
self.dontcache = true;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/// Whether no dentry of this instance stays once nothing holds it.
|
|
106
|
+
pub(crate) fn dontcache(&self) -> bool {
|
|
107
|
+
self.dontcache
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
pub(crate) fn rename_mutex(&self) -> &Arc<RwSemaphore> {
|
|
111
|
+
&self.rename_mutex
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/// This instance's root dentry, once `fill_super` made it, as `s_root`.
|
|
115
|
+
pub fn root(&self) -> Option<&Arc<Dentry>> {
|
|
116
|
+
self.root.as_ref()
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
pub(crate) fn dentries(&self) -> &Dentries {
|
|
120
|
+
&self.dentries
|
|
121
|
+
}
|
|
122
|
+
}
|