Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
R
redoxfs
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
redox-os
redoxfs
Commits
e9a7181e
Commit
e9a7181e
authored
6 years ago
by
Jeremy Soller
Browse files
Options
Downloads
Plain Diff
Merge branch 'master' into 'master'
fmap support See merge request
redox-os/redoxfs!35
parents
a345132e
8c57fd95
No related branches found
Branches containing commit
No related tags found
Tags containing commit
1 merge request
!35
fmap support
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
src/lib.rs
+1
-1
1 addition, 1 deletion
src/lib.rs
src/mount/redox/resource.rs
+105
-4
105 additions, 4 deletions
src/mount/redox/resource.rs
src/mount/redox/scheme.rs
+87
-4
87 additions, 4 deletions
src/mount/redox/scheme.rs
with
193 additions
and
9 deletions
src/lib.rs
+
1
−
1
View file @
e9a7181e
#![crate_name=
"redoxfs"
]
#![crate_type=
"lib"
]
#![deny(warnings)]
//
#![deny(warnings)]
extern
crate
syscall
;
extern
crate
uuid
;
...
...
This diff is collapsed.
Click to expand it.
src/mount/redox/resource.rs
+
105
−
4
View file @
e9a7181e
...
...
@@ -2,12 +2,13 @@ use std::cmp::{min, max};
use
std
::
time
::{
SystemTime
,
UNIX_EPOCH
};
use
syscall
::
data
::
TimeSpec
;
use
syscall
::
error
::{
Error
,
Result
,
EBADF
,
EINVAL
,
EISDIR
,
EPERM
};
use
syscall
::
error
::{
Error
,
Result
,
EBADF
,
EBUSY
,
EINVAL
,
EISDIR
,
EPERM
};
use
syscall
::
flag
::{
O_ACCMODE
,
O_RDONLY
,
O_WRONLY
,
O_RDWR
,
F_GETFL
,
F_SETFL
,
MODE_PERM
};
use
syscall
::{
Stat
,
SEEK_SET
,
SEEK_CUR
,
SEEK_END
};
use
disk
::
Disk
;
use
filesystem
::
FileSystem
;
use
super
::
scheme
::{
Fmaps
,
FmapKey
,
FmapValue
};
pub
trait
Resource
<
D
:
Disk
>
{
fn
block
(
&
self
)
->
u64
;
...
...
@@ -15,12 +16,14 @@ pub trait Resource<D: Disk> {
fn
read
(
&
mut
self
,
buf
:
&
mut
[
u8
],
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
;
fn
write
(
&
mut
self
,
buf
:
&
[
u8
],
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
;
fn
seek
(
&
mut
self
,
offset
:
usize
,
whence
:
usize
,
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
;
fn
fmap
(
&
mut
self
,
offset
:
usize
,
size
:
usize
,
maps
:
&
mut
Fmaps
,
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
;
fn
funmap
(
&
mut
self
,
maps
:
&
mut
Fmaps
,
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
;
fn
fchmod
(
&
mut
self
,
mode
:
u16
,
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
;
fn
fchown
(
&
mut
self
,
uid
:
u32
,
gid
:
u32
,
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
;
fn
fcntl
(
&
mut
self
,
cmd
:
usize
,
arg
:
usize
)
->
Result
<
usize
>
;
fn
path
(
&
self
,
buf
:
&
mut
[
u8
])
->
Result
<
usize
>
;
fn
stat
(
&
self
,
_stat
:
&
mut
Stat
,
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
;
fn
sync
(
&
mut
self
)
->
Result
<
usize
>
;
fn
sync
(
&
mut
self
,
maps
:
&
mut
Fmaps
,
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
;
fn
truncate
(
&
mut
self
,
len
:
usize
,
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
;
fn
utimens
(
&
mut
self
,
times
:
&
[
TimeSpec
],
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
;
}
...
...
@@ -87,6 +90,13 @@ impl<D: Disk> Resource<D> for DirResource {
Ok
(
self
.seek
)
}
fn
fmap
(
&
mut
self
,
_offset
:
usize
,
_size
:
usize
,
_maps
:
&
mut
Fmaps
,
_fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
{
Err
(
Error
::
new
(
EBADF
))
}
fn
funmap
(
&
mut
self
,
_maps
:
&
mut
Fmaps
,
_fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
{
Err
(
Error
::
new
(
EBADF
))
}
fn
fchmod
(
&
mut
self
,
mode
:
u16
,
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
{
let
mut
node
=
fs
.node
(
self
.block
)
?
;
...
...
@@ -158,7 +168,7 @@ impl<D: Disk> Resource<D> for DirResource {
Ok
(
0
)
}
fn
sync
(
&
mut
self
)
->
Result
<
usize
>
{
fn
sync
(
&
mut
self
,
_maps
:
&
mut
Fmaps
,
_fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
{
Err
(
Error
::
new
(
EBADF
))
}
...
...
@@ -177,6 +187,7 @@ pub struct FileResource {
flags
:
usize
,
seek
:
u64
,
uid
:
u32
,
fmap
:
Option
<
(
usize
,
FmapKey
)
>
}
impl
FileResource
{
...
...
@@ -187,8 +198,31 @@ impl FileResource {
flags
:
flags
,
seek
:
seek
,
uid
:
uid
,
fmap
:
None
}
}
fn
sync_fmap
<
D
:
Disk
>
(
&
mut
self
,
maps
:
&
mut
Fmaps
,
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
()
>
{
if
let
Some
((
i
,
key_exact
))
=
self
.fmap
.as_ref
()
{
let
(
_
,
value
)
=
maps
.index
(
*
i
)
.as_mut
()
.expect
(
"mapping dropped while still referenced"
);
// Minimum out of our size and the original file size
let
actual_size
=
value
.actual_size
.min
(
key_exact
.size
);
let
mut
count
=
0
;
while
count
<
actual_size
{
let
mtime
=
SystemTime
::
now
()
.duration_since
(
UNIX_EPOCH
)
.unwrap
();
match
fs
.write_node
(
self
.block
,
key_exact
.offset
as
u64
+
count
as
u64
,
&
value
.buffer
[
count
..
actual_size
],
mtime
.as_secs
(),
mtime
.subsec_nanos
())
?
{
0
=>
{
eprintln!
(
"Fmap failed to write whole buffer, encountered EOF early."
);
break
;
}
n
=>
count
+=
n
,
}
}
}
Ok
(())
}
}
impl
<
D
:
Disk
>
Resource
<
D
>
for
FileResource
{
...
...
@@ -203,6 +237,7 @@ impl<D: Disk> Resource<D> for FileResource {
flags
:
self
.flags
,
seek
:
self
.seek
,
uid
:
self
.uid
,
fmap
:
None
}))
}
...
...
@@ -240,6 +275,71 @@ impl<D: Disk> Resource<D> for FileResource {
Ok
(
self
.seek
as
usize
)
}
fn
fmap
(
&
mut
self
,
offset
:
usize
,
size
:
usize
,
maps
:
&
mut
Fmaps
,
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
{
if
self
.flags
&
O_ACCMODE
==
O_RDWR
{
let
key_exact
=
FmapKey
{
block
:
self
.block
,
offset
,
size
};
let
i
=
match
maps
.find_compatible
(
&
key_exact
)
{
Ok
((
i
,
(
key_existing
,
value
)))
=>
{
value
.refcount
+=
1
;
self
.fmap
=
Some
((
i
,
key_exact
));
return
Ok
(
value
.buffer
.as_ptr
()
as
usize
+
(
key_exact
.offset
-
key_existing
.offset
))
},
Err
(
None
)
=>
{
// This is bad!
// We reached the limit of maps, and we can't reallocate
// because that would invalidate stuff.
// Sorry, nothing personal :(
return
Err
(
Error
::
new
(
EBUSY
))
},
Err
(
Some
(
i
))
=>
{
// Can't do stuff in here because lifetime issues
i
}
};
let
key_round
=
key_exact
.round
();
let
mut
content
=
vec!
[
0
;
key_round
.size
];
let
mut
count
=
0
;
while
count
<
key_round
.size
{
match
fs
.read_node
(
self
.block
,
key_round
.offset
as
u64
+
count
as
u64
,
&
mut
content
[
count
..
])
?
{
0
=>
break
,
n
=>
count
+=
n
}
}
let
value
=
maps
.insert
(
i
,
key_round
,
FmapValue
{
buffer
:
content
,
actual_size
:
count
,
refcount
:
1
});
self
.fmap
=
Some
((
i
,
key_exact
));
Ok
(
value
.buffer
.as_ptr
()
as
usize
+
(
key_exact
.offset
-
key_round
.offset
))
}
else
{
Err
(
Error
::
new
(
EBADF
))
}
}
fn
funmap
(
&
mut
self
,
maps
:
&
mut
Fmaps
,
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
{
self
.sync_fmap
(
maps
,
fs
)
?
;
if
let
Some
((
i
,
_
))
=
self
.fmap
.as_ref
()
{
let
value
=
maps
.index
(
*
i
);
let
clear
=
{
let
(
_
,
value
)
=
value
.as_mut
()
.expect
(
"mapping dropped while still referenced"
);
value
.refcount
-=
1
;
value
.refcount
==
0
};
if
clear
{
*
value
=
None
;
}
}
Ok
(
0
)
}
fn
fchmod
(
&
mut
self
,
mode
:
u16
,
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
{
let
mut
node
=
fs
.node
(
self
.block
)
?
;
...
...
@@ -318,7 +418,8 @@ impl<D: Disk> Resource<D> for FileResource {
Ok
(
0
)
}
fn
sync
(
&
mut
self
)
->
Result
<
usize
>
{
fn
sync
(
&
mut
self
,
maps
:
&
mut
Fmaps
,
fs
:
&
mut
FileSystem
<
D
>
)
->
Result
<
usize
>
{
self
.sync_fmap
(
maps
,
fs
)
?
;
Ok
(
0
)
}
...
...
This diff is collapsed.
Click to expand it.
src/mount/redox/scheme.rs
+
87
−
4
View file @
e9a7181e
use
std
::
cell
::
RefCell
;
use
std
::
collections
::
BTreeMap
;
use
std
::
result
::
Result
as
StdResult
;
use
std
::
str
;
use
std
::
sync
::
atomic
::{
AtomicUsize
,
Ordering
};
use
std
::
time
::{
SystemTime
,
UNIX_EPOCH
};
...
...
@@ -17,11 +18,81 @@ use node::Node;
use
super
::
resource
::{
Resource
,
DirResource
,
FileResource
};
use
super
::
spin
::
Mutex
;
/// The size to round offset/len up to.
/// This ensures more fmaps can share the same memory even with different parameters.
const
PAGE_SIZE
:
usize
=
4096
;
/// The max amount of fmaps that can be held simultaneously.
/// This restriction is here because we can under no circumstances reallocate,
/// that would invalidate previous mappings.
const
FMAP_AMOUNT
:
usize
=
1024
;
#[derive(Clone,
Copy,
Debug,
Eq,
PartialEq)]
pub
struct
FmapKey
{
pub
block
:
u64
,
pub
offset
:
usize
,
pub
size
:
usize
}
impl
FmapKey
{
pub
fn
round
(
&
self
)
->
FmapKey
{
let
remainder
=
self
.size
%
PAGE_SIZE
;
FmapKey
{
block
:
self
.block
,
offset
:
self
.offset
-
self
.offset
%
PAGE_SIZE
,
size
:
if
remainder
==
0
{
self
.size
}
else
{
self
.size
-
remainder
+
PAGE_SIZE
}
}
}
pub
fn
is_compatible
(
&
self
,
other
:
&
FmapKey
)
->
bool
{
self
.block
==
other
.block
&&
self
.offset
<=
other
.offset
&&
self
.offset
+
self
.size
>=
other
.offset
+
other
.size
}
}
#[derive(Clone)]
pub
struct
FmapValue
{
pub
buffer
:
Vec
<
u8
>
,
/// The actual file length. Syncing only writes &buffer[..actual_size].
pub
actual_size
:
usize
,
pub
refcount
:
usize
}
// NOTE: This can NOT reallocate. That would invalidate previous mappings.
pub
struct
Fmaps
(
Vec
<
Option
<
(
FmapKey
,
FmapValue
)
>>
);
impl
Default
for
Fmaps
{
fn
default
()
->
Fmaps
{
Fmaps
(
vec!
[
None
;
FMAP_AMOUNT
])
}
}
impl
Fmaps
{
pub
fn
find_compatible
(
&
mut
self
,
key
:
&
FmapKey
)
->
StdResult
<
(
usize
,
&
mut
(
FmapKey
,
FmapValue
)),
Option
<
usize
>>
{
let
mut
first_empty
=
None
;
for
(
i
,
entry
)
in
self
.0
.iter_mut
()
.enumerate
()
{
match
entry
{
None
if
first_empty
.is_none
()
=>
first_empty
=
Some
(
i
),
Some
(
entry
)
if
entry
.0
.is_compatible
(
key
)
=>
return
Ok
((
i
,
entry
)),
_
=>
()
}
}
Err
(
first_empty
)
}
pub
fn
index
(
&
mut
self
,
index
:
usize
)
->
&
mut
Option
<
(
FmapKey
,
FmapValue
)
>
{
&
mut
self
.0
[
index
]
}
pub
fn
insert
(
&
mut
self
,
index
:
usize
,
key
:
FmapKey
,
value
:
FmapValue
)
->
&
mut
FmapValue
{
let
elem
=
&
mut
self
.0
[
index
];
assert!
(
elem
.is_none
());
*
elem
=
Some
((
key
,
value
));
&
mut
elem
.as_mut
()
.unwrap
()
.1
}
}
pub
struct
FileScheme
<
D
:
Disk
>
{
name
:
String
,
fs
:
RefCell
<
FileSystem
<
D
>>
,
next_id
:
AtomicUsize
,
files
:
Mutex
<
BTreeMap
<
usize
,
Box
<
Resource
<
D
>>>>
files
:
Mutex
<
BTreeMap
<
usize
,
Box
<
Resource
<
D
>>>>
,
fmaps
:
Mutex
<
Fmaps
>
}
impl
<
D
:
Disk
>
FileScheme
<
D
>
{
...
...
@@ -30,7 +101,8 @@ impl<D: Disk> FileScheme<D> {
name
:
name
,
fs
:
RefCell
::
new
(
fs
),
next_id
:
AtomicUsize
::
new
(
1
),
files
:
Mutex
::
new
(
BTreeMap
::
new
())
files
:
Mutex
::
new
(
BTreeMap
::
new
()),
fmaps
:
Mutex
::
new
(
Fmaps
::
default
())
}
}
...
...
@@ -651,7 +723,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
// println!("Fsync {}", id);
let
mut
files
=
self
.files
.lock
();
if
let
Some
(
file
)
=
files
.get_mut
(
&
id
)
{
file
.sync
()
file
.sync
(
&
mut
self
.fmaps
.lock
(),
&
mut
self
.fs
.borrow_mut
()
)
}
else
{
Err
(
Error
::
new
(
EBADF
))
}
...
...
@@ -677,10 +749,21 @@ impl<D: Disk> Scheme for FileScheme<D> {
}
}
fn
fmap
(
&
self
,
id
:
usize
,
offset
:
usize
,
size
:
usize
)
->
Result
<
usize
>
{
// println!("Fmap {}, {}, {}", id, offset, size);
let
mut
files
=
self
.files
.lock
();
if
let
Some
(
file
)
=
files
.get_mut
(
&
id
)
{
file
.fmap
(
offset
,
size
,
&
mut
self
.fmaps
.lock
(),
&
mut
self
.fs
.borrow_mut
())
}
else
{
Err
(
Error
::
new
(
EBADF
))
}
}
fn
close
(
&
self
,
id
:
usize
)
->
Result
<
usize
>
{
// println!("Close {}", id);
let
mut
files
=
self
.files
.lock
();
if
files
.remove
(
&
id
)
.is_some
()
{
if
let
Some
(
mut
file
)
=
files
.remove
(
&
id
)
{
let
_
=
file
.funmap
(
&
mut
self
.fmaps
.lock
(),
&
mut
self
.fs
.borrow_mut
());
Ok
(
0
)
}
else
{
Err
(
Error
::
new
(
EBADF
))
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment