Skip to content

Commit 80f373c

Browse files
committed
Add dispatch task, plus a bunch more updates
This commit was originally a sequence of trial-and-error commits that are a bit of a mess. Rather than include them, or trying to turn them retroactively into a separate commit for each of the below, I'm just squashing them into here. The changes in a nutshell: There are now tests that can run under src/test. So far it just checks that the hello world filesystem works. I no longer start an OS thread for each FS operation. There is one thread for the C API, which passes all commands back to a "dispatch task" running on the default scheduler, which in turn starts a new task on the default scheduler for each command. I don't try to turn byte strings I get from FUSE into utf-8. I still use std::path in the public API, and therefore could run into some problems due to rust-lang/rust#7225 but that will be addressed here when the underlying problem in std::path is taken care of. The public API now consists of a FuseMount object whose existence is tied to the mounting of a filesystem via FUSE. There is a Makefile whose main purpose is to allow you to quickly run the tests. Once "rustpkg test" works, it may not be needed anymore.
1 parent 796f9e6 commit 80f373c

File tree

15 files changed

+1003
-304
lines changed

15 files changed

+1003
-304
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ build/
22
lib/
33
bin/
44
.rust
5+
.vagrant

Makefile

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
.PHONY: install test
2+
3+
install: bin/hello_fs
4+
5+
test: bin/test
6+
env RUST_LOG=test=4,rust_fuse=4 ./bin/test
7+
8+
bin/hello_fs: $(shell git ls-files src/rust_fuse src/examples '*.rs')
9+
rm .rust/*.json; rustpkg install examples/hello_fs
10+
11+
bin/test: bin/hello_fs $(shell git ls-files src/test '*.rs')
12+
rustc --test --out-dir bin src/test/test.rs

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ The modules:
2020
* `rust_fuse::ffi` - The actual C headers, translated to rust extern fns. Not meant for direct use.
2121
* `rust_fuse::lowlevel` - This is a "thin" rust wrapper over the FUSE low level C API. The goals:
2222
* Eliminate the need for a user of this library to use unsafe code. That means converting all raw pointers to vectors, borrowed pointers, etc as appropriate.
23+
* Pass only meaningful data to a user of this library. The C API has many places where it will pass you a big struct, then tell you in its documentation that only certain fields are meaningful. We change the data structures in those cases so that you the filesystem implementor gets only real information, not random garbage.
2324
* Use rust's task system to:
2425
* Run each filesystem request in its own task to allow them to run in parallel.
2526
* Guarantee that each "request" call receives an appropriate reply, without having to track it yourself.

src/examples/hello_fs/main.rs

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
extern mod rust_fuse;
2+
3+
use std::libc::{
4+
S_IFDIR,
5+
S_IFREG,
6+
ENOENT,
7+
EACCES,
8+
O_RDONLY,
9+
stat,
10+
off_t,
11+
size_t,
12+
mode_t,
13+
c_int
14+
};
15+
16+
use std::cmp::{min, max};
17+
use rust_fuse::lowlevel::*;
18+
use std::os;
19+
use rust_fuse::stat::stat::arch::default_stat;
20+
use std::c_str::CString;
21+
use std::io::stderr;
22+
use std::default::Default;
23+
24+
static HELLO_STR:&'static str = "Hello rusty world!\n";
25+
static HELLO_FILE_NAME:&'static str = "hello_from_rust";
26+
static INO_ROOT_DIR:fuse_ino_t = 1;
27+
static INO_HELLO_FILE:fuse_ino_t = 2;
28+
fn root_dir_stat() -> stat {
29+
stat{
30+
// 493: octal 755. Rust lacks octal literals
31+
st_mode: (S_IFDIR | 493) as mode_t,
32+
st_nlink: 2,
33+
.. default_stat()
34+
}
35+
}
36+
fn hello_file_stat() -> stat {
37+
stat{
38+
// 292: octal 0444
39+
st_mode: (S_IFREG | 292) as mode_t,
40+
st_nlink: 1,
41+
st_size: HELLO_STR.len() as off_t,
42+
.. default_stat()
43+
}
44+
}
45+
46+
fn cstr_as_bytes_no_term<'a>(cs:&'a CString) -> &'a[u8] {
47+
let ab = cs.as_bytes();
48+
ab.slice_to(max(ab.len()-1,0))
49+
}
50+
51+
fn main() {
52+
if os::args().len() < 2 {
53+
stderr().write_line("Must specify mount point");
54+
os::set_exit_status(1);
55+
return;
56+
}
57+
let ops = ~FuseLowLevelOps{
58+
59+
getattr: Some::<~fn(fuse_ino_t) -> ErrnoResult<AttrReply>>(
60+
|ino: fuse_ino_t| {
61+
let hello_stat = match(ino) {
62+
INO_ROOT_DIR => Some(root_dir_stat()),
63+
INO_HELLO_FILE => Some(hello_file_stat()),
64+
_ => None
65+
};
66+
match hello_stat {
67+
Some(st) => Ok(AttrReply{ attr: st,
68+
attr_timeout: 1.0 }),
69+
None => Err(ENOENT)
70+
}
71+
}),
72+
73+
lookup: Some::<~fn(parent: fuse_ino_t, name: &CString)
74+
-> ErrnoResult<EntryReply>>(
75+
|parent: fuse_ino_t, name:&CString| {
76+
if parent != INO_ROOT_DIR ||
77+
cstr_as_bytes_no_term(name)
78+
!= HELLO_FILE_NAME.as_bytes() {
79+
Err(ENOENT)
80+
} else { Ok(Struct_fuse_entry_param {
81+
ino: INO_HELLO_FILE,
82+
generation: 0,
83+
attr: hello_file_stat(),
84+
attr_timeout: 1.0,
85+
entry_timeout: 1.0
86+
})
87+
}
88+
}),
89+
90+
readdir: Some::<~fn(ino: fuse_ino_t, size: size_t, off: off_t,
91+
fh: u64) -> ErrnoResult<ReaddirReply>>(
92+
|ino:fuse_ino_t, _size: size_t, off: off_t, _fh: u64| {
93+
if ino != INO_ROOT_DIR {
94+
Err(ENOENT)
95+
} else {
96+
let mut entries = ~[
97+
DirEntry{ino: INO_ROOT_DIR,
98+
name: ".".to_c_str(),
99+
mode: root_dir_stat().st_mode,
100+
next_offset: 1},
101+
DirEntry{ino: INO_ROOT_DIR,
102+
name: "..".to_c_str(),
103+
mode: root_dir_stat().st_mode,
104+
next_offset: 2},
105+
DirEntry{
106+
ino: INO_HELLO_FILE,
107+
name: HELLO_FILE_NAME.to_c_str(),
108+
mode: hello_file_stat().st_mode,
109+
next_offset: 3},
110+
];
111+
let num_entries = entries.len();
112+
let start = min(num_entries, off as uint);
113+
entries.reverse();
114+
entries.truncate(num_entries - start);
115+
entries.reverse();
116+
Ok(DirEntries(entries))
117+
}
118+
}),
119+
120+
open: Some::<~fn(ino: fuse_ino_t, flags: c_int)
121+
-> ErrnoResult<OpenReply>>(
122+
|ino: fuse_ino_t, flags: c_int| {
123+
if ino != INO_HELLO_FILE {
124+
Err(ENOENT)
125+
} else if flags & 3 != O_RDONLY {
126+
Err(EACCES)
127+
} else {
128+
Ok(OpenReply{direct_io: false, keep_cache: false,
129+
fh: 0})
130+
}
131+
}),
132+
133+
read: Some::<~fn(ino: fuse_ino_t, size: size_t, off: off_t,
134+
fh: u64) -> ErrnoResult<ReadReply>>(
135+
|ino: fuse_ino_t, size: size_t, off: off_t, _fh: u64| {
136+
if ino != INO_HELLO_FILE {
137+
Err(ENOENT)
138+
} else {
139+
let slice_to_read = HELLO_STR.as_bytes().slice(
140+
off as uint, min(HELLO_STR.len(),size as uint));
141+
Ok(DataBuffer(slice_to_read.into_owned()))
142+
}
143+
}),
144+
145+
..Default::default()
146+
};
147+
148+
let args_u8 = os::args().map(|s| s.as_bytes().into_owned());
149+
FuseMount::new(~FuseMountOptions{args: args_u8,
150+
..Default::default()}, ops).finish();
151+
}

src/hello_fs/main.rs

-123
This file was deleted.

src/rust_fuse/ffi.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ automatically generated by rust-bindgen, with some manual changes needed:
44
* * use a bindgen'd statvfs and statfs
55
* * add Struct_iovec
66
* * add stub Struct_flock
7-
* * add derived Zero impl for Struct_fuse_file_info
7+
* * add derived Default impl for Struct_fuse_file_info
88
* * wrap the type of the function pointers in Option to allow them to be null
99
*/
1010

@@ -47,7 +47,7 @@ pub struct Struct_fuse_args {
4747
}
4848
pub type fuse_opt_proc_t = *u8;
4949

50-
#[deriving(Zero)]
50+
#[deriving(Default)]
5151
pub struct Struct_fuse_file_info {
5252
flags: c_int,
5353
fh_old: c_ulong,
@@ -118,7 +118,6 @@ pub struct Struct_fuse_forget_data {
118118
ino: uint64_t,
119119
nlookup: uint64_t,
120120
}
121-
#[packed]
122121
pub struct Struct_fuse_lowlevel_ops {
123122
init: Option<extern "C" fn(userdata:*mut c_void,
124123
_conn:*Struct_fuse_conn_info)>,

src/rust_fuse/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44

55
pub mod lowlevel;
66
pub mod ffi;
7+
pub mod stat;

0 commit comments

Comments
 (0)